Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#include "Hoption.h"
56#include "Hparam.h"
57#include "TPluginManager.h"
58#include "TPaletteAxis.h"
59#include "TCrown.h"
60#include "TArrow.h"
61#include "TVirtualPadEditor.h"
62#include "TVirtualX.h"
63#include "TEnv.h"
64#include "TPoint.h"
65#include "TImage.h"
66#include "TCandle.h"
67#include "strlcpy.h"
68
69/*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72
73- [Introduction](\ref HP00)
74- [Histograms' plotting options](\ref HP01)
75 - [Options supported for 1D and 2D histograms](\ref HP01a)
76 - [Options supported for 1D histograms](\ref HP01b)
77 - [Options supported for 2D histograms](\ref HP01c)
78 - [Options supported for 3D histograms](\ref HP01d)
79 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
80- [Setting the Style](\ref HP02)
81- [Setting line, fill, marker, and text attributes](\ref HP03)
82- [Setting Tick marks on the histogram axis](\ref HP04)
83- [Giving titles to the X, Y and Z axis](\ref HP05)
84- [The option SAME](\ref HP060)
85 - [Limitations](\ref HP060a)
86- [Colors automatically picked in palette](\ref HP061)
87- [Superimposing two histograms with different scales in the same pad](\ref HP06)
88- [Statistics Display](\ref HP07)
89- [Fit Statistics](\ref HP08)
90- [The error bars options](\ref HP09)
91- [The bar chart option](\ref HP100)
92- [The BAR and HBAR options](\ref HP10)
93- [The SCATter plot option (legacy draw option)](\ref HP11)
94- [The ARRow option](\ref HP12)
95- [The BOX option](\ref HP13)
96- [The COLor option (default for 2D and 3D histograms)](\ref HP14)
97- [The CANDLE and VIOLIN options](\ref HP140)
98 - [The CANDLE option](\ref HP140a)
99 - [The VIOLIN option](\ref HP140b)
100- [The TEXT and TEXTnn Option](\ref HP15)
101- [The CONTour options](\ref HP16)
102 - [The LIST option](\ref HP16a)
103 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
104- [The LEGO options](\ref HP17)
105- [The SURFace options](\ref HP18)
106- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
107- [Base line for bar-charts and lego plots](\ref HP20)
108- [TH2Poly Drawing](\ref HP20a)
109- [The SPEC option](\ref HP21)
110- [Option Z : Adding the color palette on the right side of the pad](\ref HP22)
111- [Setting the color palette](\ref HP23)
112- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
113- [Drawing options for 3D histograms](\ref HP25)
114- [Drawing option for histograms' stacks](\ref HP26)
115- [Drawing of 3D implicit functions](\ref HP27)
116- [Associated functions drawing](\ref HP28)
117- [Drawing using OpenGL](\ref HP29)
118 - [General information: plot types and supported options](\ref HP29a)
119 - [TH3 as color boxes](\ref HP290)
120 - [TH3 as boxes (spheres)](\ref HP29b)
121 - [TH3 as iso-surface(s)](\ref HP29c)
122 - [TF3 (implicit function)](\ref HP29d)
123 - [Parametric surfaces](\ref HP29e)
124 - [Interaction with the plots](\ref HP29f)
125 - [Selectable parts](\ref HP29g)
126 - [Rotation and zooming](\ref HP29h)
127 - [Panning](\ref HP29i)
128 - [Box cut](\ref HP29j)
129 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
130 - [Surface with option GLSURF](\ref HP29l)
131 - [TF3](\ref HP29m)
132 - [Box](\ref HP29n)
133 - [Iso](\ref HP29o)
134 - [Parametric plot](\ref HP29p)
135- [Highlight mode for histogram](\ref HP30)
136 - [Highlight mode and user function](\ref HP30a)
137
138
139\anchor HP00
140## Introduction
141
142
143Histograms are drawn via the `THistPainter` class. Each histogram has a
144pointer to its own painter (to be usable in a multithreaded program). When the
145canvas has to be redrawn, the `Paint` function of each objects in the
146pad is called. In case of histograms, `TH1::Paint` invokes directly
147`THistPainter::Paint`.
148
149To draw a histogram `h` it is enough to do:
150
151 h->Draw();
152
153`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
154be drawn, the `Draw()` method can be invoked with an option. For instance
155to draw a 2D histogram as a lego plot it is enough to do:
156
157 h->Draw("lego");
158
159`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
160
161When the `Draw()` method of a histogram is called for the first time
162(`TH1::Draw`), it creates a `THistPainter` object and saves a
163pointer to this "painter" as a data member of the histogram. The
164`THistPainter` class specializes in the drawing of histograms. It is
165separated from the histogram so that one can have histograms without the
166graphics overhead, for example in a batch program. Each histogram having its own
167painter (rather than a central singleton painter painting all histograms), allows
168two histograms to be drawn in two threads without overwriting the painter's
169values.
170
171When a displayed histogram is filled again, there is no need to call the
172`Draw()` method again; the image will be refreshed the next time the
173pad will be updated.
174
175A pad is updated after one of these three actions:
176
1771. a carriage control on the ROOT command line,
1782. a click inside the pad,
1793. a call to `TPad::Update`.
180
181
182By default a call to `TH1::Draw()` clears the pad of all objects
183before drawing the new image of the histogram. One can use the `SAME`
184option to leave the previous display intact and superimpose the new histogram.
185The same histogram can be drawn with different graphics options in different
186pads.
187
188When a displayed histogram is deleted, its image is automatically removed
189from the pad.
190
191To create a copy of the histogram when drawing it, one can use
192`TH1::DrawClone()`. This will clone the histogram and allow to change
193and delete the original one without affecting the clone.
194
195
196\anchor HP01
197### Histograms' plotting options
198
199
200Most options can be concatenated with or without spaces or commas, for example:
201
202 h->Draw("E1 SAME");
203
204The options are not case sensitive:
205
206 h->Draw("e1 same");
207
208
209The default drawing option can be set with `TH1::SetOption` and retrieve
210using `TH1::GetOption`:
211
212 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
213 root [1] h->Draw("E"); // Draw "h" using error bars
214 root [3] h->SetOption("E"); // Change the default drawing option for "h"
215 root [4] h->Draw(); // Draw "h" using error bars
216 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
217 (const Option_t* 0xa3ff948)"E"
218
219
220\anchor HP01a
221#### Options supported for 1D and 2D histograms
222
223| Option | Description |
224|----------|-------------------------------------------------------------------|
225| "E" | Draw error bars. |
226| "AXIS" | Draw only axis. |
227| "AXIG" | Draw only grid (if the grid is requested). |
228| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
229| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
230| "SAME" | Superimpose on previous picture in the same pad. |
231| "SAMES" | Same as "SAME" and draw the statistics box|
232| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
233| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
234| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
235| "LEGO" | Draw a lego plot with hidden line removal. |
236| "LEGO1" | Draw a lego plot with hidden surface removal. |
237| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
238| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
239| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
240| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
241| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90). |
242| "X+" | The X-axis is drawn on the top side of the plot. |
243| "Y+" | The Y-axis is drawn on the right side of the plot. |
244| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
245
246
247\anchor HP01b
248#### Options supported for 1D histograms
249
250| Option | Description |
251|----------|-------------------------------------------------------------------|
252| " " | Default. |
253| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
254| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
255| "B" | Bar chart option.|
256| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
257| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
258| "C" | Draw a smooth Curve through the histogram bins.|
259| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
260| "E1" | Draw error bars with perpendicular lines at the edges.|
261| "E2" | Draw error bars with rectangles.|
262| "E3" | Draw a fill area through the end points of the vertical error bars.|
263| "E4" | Draw a smoothed filled area through the end points of the error bars.|
264| "E5" | Like E3 but ignore the bins with 0 contents.|
265| "E6" | Like E4 but ignore the bins with 0 contents.|
266| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
267| "L" | Draw a line through the bin contents.|
268| "P" | Draw current marker at each bin except empty bins.|
269| "P*" | Draw a star marker at each bin except empty bins.|
270| "P0" | Draw current marker at each bin including empty bins.|
271| "PIE" | Draw histogram as a Pie Chart.|
272| "*H" | Draw histogram with a * at each bin.|
273| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
274
275
276
277\anchor HP01c
278#### Options supported for 2D histograms
279
280| Option | Description |
281|--------------|------------------------------------------------------------------|
282| " " | Default (color plot).|
283| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
284| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X. |
285| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
286| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins (bins with content and error equal to 0) are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted (default).|
287| "COL1" | Same as "COL" but in case of histogram with negative content the empty bins are not drawn.
288| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
289| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
290| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
291| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boundaries. For more details see `TPaletteAxis`|
292| "CANDLE" | Draw a candle plot along X axis.|
293| "CANDLEX" | Same as "CANDLE".|
294| "CANDLEY" | Draw a candle plot along Y axis.|
295| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
296| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
297| "VIOLIN" | Draw a violin plot along X axis.|
298| "VIOLINX" | Same as "VIOLIN".|
299| "VIOLINY" | Draw a violin plot along Y axis.|
300| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
301| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
302| "CONT" | Draw a contour plot (same as CONT0).|
303| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
304| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
305| "CONT2" | Draw a contour plot using the same line style for all contours.|
306| "CONT3" | Draw a contour plot using fill area colors.|
307| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
308| "LIST" | Generate a list of TGraph objects for each contour.|
309| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
310| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
311| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
312| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
313| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
314| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
315| "SURF" | Draw a surface plot with hidden line removal.|
316| "SURF1" | Draw a surface plot with hidden surface removal.|
317| "SURF2" | Draw a surface plot using colors to show the cell contents.|
318| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
319| "SURF4" | Draw a surface using Gouraud shading.|
320| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
321| "AITOFF" | Draw a contour via an AITOFF projection.|
322| "MERCATOR" | Draw a contour via an Mercator projection.|
323| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
324| "PARABOLIC" | Draw a contour via an Parabolic projection.|
325| "MOLLWEIDE" | Draw a contour via an Mollweide projection.|
326| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
327| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
328| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
329| "A" | With LEGO or SURFACE, suppress the axis.|
330| "SCAT" | Draw a scatter-plot (legacy draw option).|
331| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
332
333
334
335\anchor HP01d
336#### Options supported for 3D histograms
337
338| Option | Description |
339|----------|-------------------------------------------------------------------|
340| " " | Default (color plot).|
341| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`.|
342| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
343| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
344| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
345| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
346| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
347| "LEGO" | Same as `BOX`.|
348
349\anchor HP01e
350#### Options supported for histograms' stacks (`THStack`)
351
352| Option | Description |
353|------------|-----------------------------------------------------------------|
354| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
355| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
356| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
357| "PADS" | The current pad/canvas is subdivided into a number of pads equal to the number of histograms in the stack and each histogram is paint into a separate pad.|
358| "PADSn" | Like PADS but the current pad/canvas is subdivided into a `n` columns, automatically calculating the number of rows.|
359| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
360| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
361| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
362
363
364
365\anchor HP02
366### Setting the Style
367
368
369Histograms use the current style (`gStyle`). When one changes the current
370style and would like to propagate the changes to the histogram,
371`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
372each histogram is needed.
373
374To force all the histogram to use the current style use:
375
376 gROOT->ForceStyle();
377
378All the histograms read after this call will use the current style.
379
380
381\anchor HP03
382### Setting line, fill, marker, and text attributes
383
384
385The histogram classes inherit from the attribute classes:
386`TAttLine`, `TAttFill` and `TAttMarker`.
387See the description of these classes for the list of options.
388
389
390\anchor HP04
391### Setting Tick marks on the histogram axis
392
393
394The `TPad::SetTicks` method specifies the type of tick marks on the axis.
395If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
396
397 tx = 1; tick marks on top side are drawn (inside)
398 tx = 2; tick marks and labels on top side are drawn
399 ty = 1; tick marks on right side are drawn (inside)
400 ty = 2; tick marks and labels on right side are drawn
401
402By default only the left Y axis and X bottom axis are drawn
403(`tx = ty = 0`)
404
405`TPad::SetTicks(tx,ty)` allows to set these options.
406See also The `TAxis` functions to set specific axis attributes.
407
408In case multiple color filled histograms are drawn on the same pad, the fill
409area may hide the axis tick marks. One can force a redraw of the axis over all
410the histograms by calling:
411
412 gPad->RedrawAxis();
413
414
415\anchor HP05
416### Giving titles to the X, Y and Z axis
417
418
419 h->GetXaxis()->SetTitle("X axis title");
420 h->GetYaxis()->SetTitle("Y axis title");
421
422The histogram title and the axis titles can be any `TLatex` string.
423The titles are part of the persistent histogram.
424
425
426\anchor HP060
427### The option "SAME"
428
429
430By default, when an histogram is drawn, the current pad is cleared before
431drawing. In order to keep the previous drawing and draw on top of it the
432option `SAME` should be use. The histogram drawn with the option
433`SAME` uses the coordinates system available in the current pad.
434
435This option can be used alone or combined with any valid drawing option but
436some combinations must be use with care.
437
438\anchor HP060a
439#### Limitations
440
441- It does not work when combined with the `LEGO` and `SURF` options unless the
442 histogram plotted with the option `SAME` has exactly the same
443 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
444 lego plots [histograms' stacks](\ref HP26) should be used.
445
446
447\anchor HP061
448### Colors automatically picked in palette
449
450\since **ROOT version 6.09/01**
451
452When several histograms are painted in the same canvas thanks to the option "SAME"
453or via a `THStack` it might be useful to have an easy and automatic way to choose
454their color. The simplest way is to pick colors in the current active color
455palette. Palette coloring for histogram is activated thanks to the options `PFC`
456(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
457When one of these options is given to `TH1::Draw` the histogram get its color
458from the current color palette defined by `gStyle->SetPalette(...)`. The color
459is determined according to the number of objects having palette coloring in
460the current pad.
461
462Begin_Macro(source)
463../../../tutorials/hist/hist005_TH1_palettecolor.C
464End_Macro
465
466Begin_Macro(source)
467../../../tutorials/hist/hist027_THStack_palette_color.C
468End_Macro
469
470Begin_Macro(source)
471../../../tutorials/hist/hist025_THStack_2d_palette_color.C
472End_Macro
473
474\anchor HP06
475### Superimposing two histograms with different scales in the same pad
476
477
478The following example creates two histograms, the second histogram is the bins
479integral of the first one. It shows a procedure to draw the two histograms in
480the same pad and it draws the scale of the second histogram using a new vertical
481axis on the right side. See also the tutorial `transpad.C` for a variant
482of this example.
483
484Begin_Macro(source)
485{
486 auto c1 = new TCanvas("c1","c1",600,400);
487 // create/fill draw h1
488 gStyle->SetOptStat(kFALSE);
489 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
490 Int_t i;
491 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
492 h1->Draw();
493 c1->Update();
494
495 // create hint1 filled with the bins integral of h1
496 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
497 float sum = 0.f;
498 for (i=1;i<=100;i++) {
499 sum += h1->GetBinContent(i);
500 hint1->SetBinContent(i,sum);
501 }
502
503 // scale hint1 to the pad coordinates
504 float rightmax = 1.1*hint1->GetMaximum();
505 float scale = gPad->GetUymax()/rightmax;
506 hint1->SetLineColor(kRed);
507 hint1->Scale(scale);
508 hint1->Draw("same");
509
510 // draw an axis on the right side
511 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
512 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
513 axis->SetLineColor(kRed);
514 axis->SetTextColor(kRed);
515 axis->Draw();
516}
517End_Macro
518
519
520\anchor HP07
521### Statistics Display
522
523
524The type of information shown in the histogram statistics box can be selected
525with:
526
527 gStyle->SetOptStat(mode);
528
529The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
530
531 mode = ksiourmen (default = 000001111)
532 k = 1; kurtosis printed
533 k = 2; kurtosis and kurtosis error printed
534 s = 1; skewness printed
535 s = 2; skewness and skewness error printed
536 i = 1; integral of bins printed
537 i = 2; integral of bins with option "width" printed
538 o = 1; number of overflows printed
539 u = 1; number of underflows printed
540 r = 1; standard deviation printed
541 r = 2; standard deviation and standard deviation error printed
542 m = 1; mean value printed
543 m = 2; mean and mean error values printed
544 e = 1; number of entries printed
545 n = 1; name of histogram is printed
546
547For example:
548
549 gStyle->SetOptStat(11);
550
551displays only the name of histogram and the number of entries, whereas:
552
553 gStyle->SetOptStat(1101);
554
555displays the name of histogram, mean value and standard deviation.
556
557<b>WARNING 1:</b> never do:
558
559 gStyle->SetOptStat(0001111);
560
561but instead do:
562
563 gStyle->SetOptStat(1111);
564
565because `0001111` will be taken as an octal number!
566
567<b>WARNING 2:</b> for backward compatibility with older versions
568
569 gStyle->SetOptStat(1);
570
571is taken as:
572
573 gStyle->SetOptStat(1111)
574
575To print only the name of the histogram do:
576
577 gStyle->SetOptStat(1000000001);
578
579<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
580(10000) or overflow (100000), the statistics box will show all combinations
581of underflow/overflows and not just one single number.
582
583The parameter mode can be any combination of the letters `kKsSiIourRmMen`
584
585 k : kurtosis printed
586 K : kurtosis and kurtosis error printed
587 s : skewness printed
588 S : skewness and skewness error printed
589 i : integral of bins printed
590 I : integral of bins with option "width" printed
591 o : number of overflows printed
592 u : number of underflows printed
593 r : standard deviation printed
594 R : standard deviation and standard deviation error printed
595 m : mean value printed
596 M : mean value mean error values printed
597 e : number of entries printed
598 n : name of histogram is printed
599
600For example, to print only name of histogram and number of entries do:
601
602 gStyle->SetOptStat("ne");
603
604To print only the name of the histogram do:
605
606 gStyle->SetOptStat("n");
607
608The default value is:
609
610 gStyle->SetOptStat("nemr");
611
612When a histogram is painted, a `TPaveStats` object is created and added
613to the list of functions of the histogram. If a `TPaveStats` object
614already exists in the histogram list of functions, the existing object is just
615updated with the current histogram parameters.
616
617Once a histogram is painted, the statistics box can be accessed using
618`h->FindObject("stats")`. In the command line it is enough to do:
619
620 Root > h->Draw()
621 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
622
623because after `h->Draw()` the histogram is automatically painted. But
624in a script file the painting should be forced using `gPad->Update()`
625in order to make sure the statistics box is created:
626
627 h->Draw();
628 gPad->Update();
629 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
630
631Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
632
633When a histogram is drawn with the option `SAME`, the statistics box
634is not drawn. To force the statistics box drawing with the option
635`SAME`, the option `SAMES` must be used.
636If the new statistics box hides the previous statistics box, one can change
637its position with these lines (`h` being the pointer to the histogram):
638
639 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
640 Root > st->SetX1NDC(newx1); //new x start position
641 Root > st->SetX2NDC(newx2); //new x end position
642
643To change the type of information for an histogram with an existing
644`TPaveStats` one should do:
645
646 st->SetOptStat(mode);
647
648Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
649(see above).
650
651One can delete the statistics box for a histogram `TH1* h` with:
652
653 h->SetStats(0)
654
655and activate it again with:
656
657 h->SetStats(1).
658
659Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
660`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
661
662
663\anchor HP08
664### Fit Statistics
665
666
667The type of information about fit parameters printed in the histogram statistics
668box can be selected via the parameter mode. The parameter mode can be
669`= pcev` (default `= 0111`)
670
671 p = 1; print Probability
672 c = 1; print Chisquare/Number of degrees of freedom
673 e = 1; print errors (if e=1, v must be 1)
674 v = 1; print name/values of parameters
675
676Example:
677
678 gStyle->SetOptFit(1011);
679
680print fit probability, parameter names/values and errors.
681
6821. When `v = 1` is specified, only the non-fixed parameters are shown.
6832. When `v = 2` all parameters are shown.
684
685Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
686to `gStyle->SetOptFit(111)`
687
688
689\anchor HP09
690### The error bars options
691
692
693| Option | Description |
694|----------|-------------------------------------------------------------------|
695| "E" | Default. Shows only the error bars, not a marker.|
696| "E1" | Small lines are drawn at the end of the error bars.|
697| "E2" | Error rectangles are drawn.|
698| "E3" | A filled area is drawn through the end points of the vertical error bars.|
699| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
700| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
701| "E5" | Like E3 but ignore the bins with 0 contents.|
702| "E6" | Like E4 but ignore the bins with 0 contents.|
703| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
704
705Begin_Macro(source)
706{
707 auto c1 = new TCanvas("c1","c1",600,400);
708 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
709 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
710 gStyle->SetEndErrorSize(3);
711 gStyle->SetErrorX(1.);
712 he->SetMarkerStyle(20);
713 he->Draw("E1");
714}
715End_Macro
716
717The options "E3" and "E4" draw an error band through the end points of the
718vertical error bars. With "E4" the error band is smoothed. Because of the
719smoothing algorithm used some artefacts may appear at the end of the band
720like in the following example. In such cases "E3" should be used instead
721of "E4".
722
723Begin_Macro(source)
724{
725 auto ce4 = new TCanvas("ce4","ce4",600,400);
726 ce4->Divide(2,1);
727 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
728 Int_t i;
729 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
730 he4->SetFillColor(kRed);
731 he4->GetXaxis()->SetRange(40,48);
732 ce4->cd(1);
733 he4->Draw("E4");
734 ce4->cd(2);
735 auto he3 = (TH1F*)he4->DrawClone("E3");
736 he3->SetTitle("Distribution drawn option E3");
737}
738End_Macro
739
7402D histograms can be drawn with error bars as shown is the following example:
741
742Begin_Macro(source)
743{
744 auto c2e = new TCanvas("c2e","c2e",600,400);
745 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
746 float px, py;
747 for (Int_t i = 0; i < 25000; i++) {
748 gRandom->Rannor(px,py);
749 h2e->Fill(px,5*py);
750 }
751 h2e->Draw("E");
752}
753End_Macro
754
755
756\anchor HP100
757### The bar chart option
758
759
760The option "B" allows to draw simple vertical bar charts.
761The bar width is controlled with `TH1::SetBarWidth()`,
762and the bar offset within the bin, with `TH1::SetBarOffset()`.
763These two settings are useful to draw several histograms on the
764same plot as shown in the following example:
765
766Begin_Macro(source)
767{
768 int i;
769 const Int_t nx = 8;
770 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
771 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
772 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
773
774 auto cb = new TCanvas("cb","cb",600,400);
775 cb->SetGrid();
776
777 gStyle->SetHistMinimumZero();
778
779 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
780 h1b->SetFillColor(4);
781 h1b->SetBarWidth(0.4);
782 h1b->SetBarOffset(0.1);
783 h1b->SetStats(0);
784 h1b->SetMinimum(-5);
785 h1b->SetMaximum(5);
786
787 for (i=1; i<=nx; i++) {
788 h1b->SetBinContent(i, d_35_0[i-1]);
789 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
790 }
791
792 h1b->Draw("b");
793
794 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
795 h2b->SetFillColor(38);
796 h2b->SetBarWidth(0.4);
797 h2b->SetBarOffset(0.5);
798 h2b->SetStats(0);
799 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
800
801 h2b->Draw("b same");
802}
803End_Macro
804
805
806\anchor HP10
807### The "BAR" and "HBAR" options
808
809
810When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
811bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
812An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
813`hbar2`, `hbar3`, `hbar4` (hist006_TH1_bar_charts.C).
814
815- The bar is filled with the histogram fill color.
816- The left side of the bar is drawn with a light fill color.
817- The right side of the bar is drawn with a dark fill color.
818- The percentage of the bar drawn with either the light or dark color is:
819 - 0% for option "(h)bar" or "(h)bar0"
820 - 10% for option "(h)bar1"
821 - 20% for option "(h)bar2"
822 - 30% for option "(h)bar3"
823 - 40% for option "(h)bar4"
824
825When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
826
827Begin_Macro(source)
828../../../tutorials/hist/hist006_TH1_bar_charts.C
829End_Macro
830
831To control the bar width (default is the bin width) `TH1::SetBarWidth()`
832should be used.
833
834To control the bar offset (default is 0) `TH1::SetBarOffset()` should
835be used.
836
837These two parameters are useful when several histograms are plotted using
838the option `SAME`. They allow to plot the histograms next to each other.
839
840
841\anchor HP11
842### The SCATter plot option (legacy draw option)
843
844\attention
845Use of option `SCAT` has been deprecated. It was the default drawing option for 2D and
8463D histograms. The new default option is `COL` (heat-map).
847
848
849For each cell (i,j) a number of points proportional to the cell content is
850drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
851`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
852If option is of the form `scat=ff`, (eg `scat=1.8`,
853`scat=1e-3`), then `ff` is used as a scale factor to compute the
854number of dots. `scat=1` is the default.
855
856By default the scatter plot is painted with a "dot marker" which not scalable
857(see the `TAttMarker` documentation). To change the marker size, a scalable marker
858type should be used. For instance a circle (marker style 20).
859
860Begin_Macro(source)
861{
862 auto c1 = new TCanvas("c1","c1",600,400);
863 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
864 float px, py;
865 for (Int_t i = 0; i < 25000; i++) {
866 gRandom->Rannor(px,py);
867 hscat->Fill(px,5*py);
868 hscat->Fill(3+0.5*px,2*py-10.);
869 }
870 hscat->Draw("scat=0.5"); // This a legacy draw option. Please consider using TScatter
871}
872End_Macro
873
874
875\anchor HP12
876### The ARRow option
877
878
879Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
880The orientation of the arrow follows the cell gradient.
881
882Begin_Macro(source)
883{
884 auto c1 = new TCanvas("c1","c1",600,400);
885 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
886 harr->SetLineColor(kRed);
887 float px, py;
888 for (Int_t i = 0; i < 25000; i++) {
889 gRandom->Rannor(px,py);
890 harr->Fill(px,5*py);
891 harr->Fill(3+0.5*px,2*py-10.,0.1);
892 }
893 harr->Draw("ARR");
894}
895End_Macro
896
897\since **ROOT version 6.17/01**
898
899The option `ARR` can be combined with the option `COL` or `COLZ`.
900
901Begin_Macro(source)
902{
903 auto c1 = new TCanvas("c1","c1",600,400);
904 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
905 harr->SetStats(0);
906 float px, py;
907 for (Int_t i = 0; i < 25000; i++) {
908 gRandom->Rannor(px,py);
909 harr->Fill(px,5*py);
910 harr->Fill(3+0.5*px,2*py-10.,0.1);
911 }
912 harr->Draw("ARR COLZ");
913}
914End_Macro
915
916
917\anchor HP13
918### The BOX option
919
920
921For each cell (i,j) a box is drawn. The size (surface) of the box is
922proportional to the absolute value of the cell content.
923The cells with a negative content are drawn with a `X` on top of the box.
924
925Begin_Macro(source)
926{
927 auto c1 = new TCanvas("c1","c1",600,400);
928 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
929 hbox->SetFillColor(42);
930 hbox->Fill(0.5, 0.5, 1.);
931 hbox->Fill(0.5, 1.5, 4.);
932 hbox->Fill(0.5, 2.5, 3.);
933 hbox->Fill(1.5, 0.5, 2.);
934 hbox->Fill(1.5, 1.5, 12.);
935 hbox->Fill(1.5, 2.5, -6.);
936 hbox->Fill(2.5, 0.5, -4.);
937 hbox->Fill(2.5, 1.5, 6.);
938 hbox->Fill(2.5, 2.5, 0.5);
939 hbox->Draw("BOX");
940}
941End_Macro
942
943With option `BOX1` a button is drawn for each cell with surface
944proportional to content's absolute value. A sunken button is drawn for
945negative values a raised one for positive.
946
947Begin_Macro(source)
948{
949 auto c1 = new TCanvas("c1","c1",600,400);
950 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
951 hbox1->SetFillColor(42);
952 hbox1->Fill(0.5, 0.5, 1.);
953 hbox1->Fill(0.5, 1.5, 4.);
954 hbox1->Fill(0.5, 2.5, 3.);
955 hbox1->Fill(1.5, 0.5, 2.);
956 hbox1->Fill(1.5, 1.5, 12.);
957 hbox1->Fill(1.5, 2.5, -6.);
958 hbox1->Fill(2.5, 0.5, -4.);
959 hbox1->Fill(2.5, 1.5, 6.);
960 hbox1->Fill(2.5, 2.5, 0.5);
961 hbox1->Draw("BOX1");
962}
963End_Macro
964
965When the option `SAME` (or "SAMES") is used with the option `BOX`,
966the boxes' sizes are computed taking the previous plots into account. The range
967along the Z axis is imposed by the first plot (the one without option
968`SAME`); therefore the order in which the plots are done is relevant.
969
970Begin_Macro(source)
971{
972 auto c1 = new TCanvas("c1","c1",600,400);
973 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
974 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
975 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
976 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
977 for (Int_t i=0;i<1000;i++) {
978 double x,y;
979 gRandom->Rannor(x,y);
980 if (x>0 && y>0) hb1->Fill(x,y,4);
981 if (x<0 && y<0) hb2->Fill(x,y,3);
982 if (x>0 && y<0) hb3->Fill(x,y,2);
983 if (x<0 && y>0) hb4->Fill(x,y,1);
984 }
985 hb1->SetFillColor(1);
986 hb2->SetFillColor(2);
987 hb3->SetFillColor(3);
988 hb4->SetFillColor(4);
989 hb1->Draw("box");
990 hb2->Draw("box same");
991 hb3->Draw("box same");
992 hb4->Draw("box same");
993}
994End_Macro
995
996\since **ROOT version 6.17/01:**
997
998Sometimes the change of the range of the Z axis is unwanted, in which case, one
999can use `SAME0` (or `SAMES0`) option to opt out of this change.
1000
1001Begin_Macro(source)
1002{
1003 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
1004 auto hf = (TH2F*)h2->Clone("hf");
1005 h2->SetBit(TH1::kNoStats);
1006 hf->SetBit(TH1::kNoStats);
1007 h2->Fill(5,22);
1008 h2->Fill(5,23);
1009 h2->Fill(6,22);
1010 h2->Fill(6,23);
1011 hf->Fill(6,23);
1012 hf->Fill(6,23);
1013 hf->Fill(6,23);
1014 hf->Fill(6,23);
1015 hf->Fill(5,23);
1016
1017 auto hf_copy1 = hf->Clone("hf_copy1");
1018 TLatex lt;
1019
1020 auto cx = new TCanvas(); cx->Divide(2,1);
1021
1022 cx->cd(1);
1023 h2->Draw("box");
1024 hf->Draw("text colz same");
1025 lt.DrawLatexNDC(0.3,0.5,"SAME");
1026
1027 cx->cd(2);
1028 h2->Draw("box");
1029 hf_copy1->Draw("text colz same0");
1030 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1031}
1032End_Macro
1033
1034
1035\anchor HP14
1036### The COLor option (default for 2D histograms)
1037
1038The magnitude of individual cell (i,j) is represented as a color picked in the current color palette.
1039This data visualization technique is often called a heat map (or heat-map).
1040
1041The color table used is defined in the current style.
1042
1043If the histogram's minimum and maximum are the same (flat histogram), the
1044mapping on colors is not possible, therefore nothing is painted. To paint a
1045flat histogram it is enough to set the histogram minimum
1046(`TH1::SetMinimum()`) different from the bins' content.
1047
1048The default number of color levels used to paint the cells is 20.
1049It can be changed with `TH1::SetContour()` or
1050`TStyle::SetNumberContours()`. The higher this number is, the smoother
1051is the color change between cells.
1052
1053The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1054
1055All the non-empty bins are painted. Empty bins (bins with content and error equal to 0) are
1056not painted unless some bins have a negative content because in that case the null bins
1057might be not empty.
1058
1059`TProfile2D` histograms are handled differently because, for this type of 2D
1060histograms, it is possible to know if an empty bin has been filled or not. So even
1061if all the bins' contents are positive some empty bins might be painted. And vice versa,
1062if some bins have a negative content some empty bins might be not painted.
1063
1064Combined with the option `COL`, the option `Z` allows to
1065display the color palette defined by `gStyle->SetPalette()`.
1066
1067In the following example, the histogram has only positive bins; the empty
1068bins (containing 0) are not drawn.
1069
1070Begin_Macro(source)
1071{
1072 auto c1 = new TCanvas("c1","c1",600,400);
1073 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1074 float px, py;
1075 for (Int_t i = 0; i < 25000; i++) {
1076 gRandom->Rannor(px,py);
1077 hcol1->Fill(px,5*py);
1078 }
1079 hcol1->Draw("COLZ");
1080}
1081End_Macro
1082
1083In the first plot of following example, the histogram has some negative bins;
1084the empty bins (containing 0) are drawn. In some cases one wants to not draw
1085empty bins (containing 0) of histograms having a negative minimum. The option
1086`1`, used to produce the second plot in the following picture, allows to do that.
1087
1088Begin_Macro(source)
1089{
1090 auto c1 = new TCanvas("c1","c1",600,600);
1091 c1->Divide(1,2);
1092 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1093 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1094 float px, py;
1095 for (Int_t i = 0; i < 25000; i++) {
1096 gRandom->Rannor(px,py);
1097 hcol23->Fill(px,5*py);
1098 hcol24->Fill(px,5*py);
1099 }
1100 hcol23->Fill(0.,0.,-200.);
1101 hcol24->Fill(0.,0.,-200.);
1102 c1->cd(1); hcol23->Draw("COLZ");
1103 c1->cd(2); hcol24->Draw("COLZ1");
1104}
1105End_Macro
1106
1107When the maximum of the histogram is set to a smaller value than the real maximum,
1108 the bins having a content between the new maximum and the real maximum are
1109painted with the color corresponding to the new maximum.
1110
1111When the minimum of the histogram is set to a greater value than the real minimum,
1112 the bins having a value between the real minimum and the new minimum are not drawn
1113 unless the option `0` is set.
1114In other words, option `COLZ0` forces the painting of bins with content < set minimum with
1115 a color corresponding to the set minimum. In contrast, option `COLZ` would not draw values
1116 smaller than the specified minimum. Note that both `COLZ` and `COLZ0` still do not draw
1117 empty bins, ie bins with `content == error == 0`, if the set min is not negative.
1118(Note that option `COLZ0` for TH2Poly has a different behavior than for TH2.)
1119
1120The following example illustrates the option `0` combined with the option `COL`.
1121
1122Begin_Macro(source)
1123{
1124 auto c1 = new TCanvas("c1","c1",600,600);
1125 c1->Divide(1,2);
1126 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1127 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1128 float px, py;
1129 for (Int_t i = 0; i < 25000; i++) {
1130 gRandom->Rannor(px,py);
1131 hcol21->Fill(px,5*py);
1132 hcol22->Fill(px,5*py);
1133 }
1134 hcol21->SetBit(TH1::kNoStats);
1135 hcol22->SetBit(TH1::kNoStats);
1136 c1->cd(1); hcol21->Draw("COLZ");
1137 c1->cd(2); hcol22->Draw("COLZ0");
1138 hcol21->SetMaximum(100);
1139 hcol21->SetMinimum(40);
1140 hcol22->SetMaximum(100);
1141 hcol22->SetMinimum(40);
1142}
1143End_Macro
1144
1145Note that the behavior of `COLZ` is not symmetric: it does not draw values below the specified minimum,
1146but does draw values above the specified maximum by clipping them to the maximum color. In contrast, `COLZ0`
1147clips color on both lower and upper sides. Both `COLZ0` and `COLZ` exclude drawing empty bins (`content == error == 0`),
1148if the set minimum is not negative.
1149
1150\since **ROOT version 6.09/01:**
1151
1152When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1153are computed taking the previous plots into account. The range along the Z axis
1154is imposed by the first plot (the one without option SAME); therefore the order
1155in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1156`SAME0` (or `SAMES0`) to opt out of this imposition.
1157
1158Begin_Macro(source)
1159{
1160 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1161 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1162 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1163 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1164 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1165 h1->SetBit(TH1::kNoStats);
1166 for (Int_t i=0;i<5000;i++) {
1167 double x,y;
1168 gRandom->Rannor(x,y);
1169 if(x>0 && y>0) h1->Fill(x,y,4);
1170 if(x<0 && y<0) h2->Fill(x,y,3);
1171 if(x>0 && y<0) h3->Fill(x,y,2);
1172 if(x<0 && y>0) h4->Fill(x,y,1);
1173 }
1174 h1->Draw("colz");
1175 h2->Draw("col same");
1176 h3->Draw("col same");
1177 h4->Draw("col same");
1178}
1179End_Macro
1180
1181The option `COL` can be combined with the option `POL`:
1182
1183Begin_Macro(source)
1184{
1185 auto c1 = new TCanvas("c1","c1",600,400);
1186 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1187 float px, py;
1188 for (Int_t i = 0; i < 25000; i++) {
1189 gRandom->Rannor(px,py);
1190 hcol1->Fill(px,py);
1191 }
1192 hcol1->Draw("COLZPOL");
1193}
1194End_Macro
1195
1196\since **ROOT version 6.07/03:**
1197
1198A second rendering technique is also available with the COL2 and COLZ2 options.
1199
1200These options provide potential performance improvements compared to the standard
1201COL option. The performance comparison of the COL2 to the COL option depends on
1202the histogram and the size of the rendering region in the current pad. In general,
1203a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1204faster with the COL option.
1205
1206However, for larger histograms (approx. more than 100 bins per axis)
1207that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1208For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1209faster with the COL2 option.
1210
1211The COL2 option will also scale its performance based on the size of the
1212pixmap the histogram image is being rendered into. It also is much better optimized for
1213sessions where the user is forwarding X11 windows through an `ssh` connection.
1214
1215For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1216and COLZ options. There is one major difference and that concerns the treatment of
1217bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1218
1219COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1220graphics file format like PostScript or PDF (an empty image will be generated). It can
1221be saved only in bitmap files like PNG format for instance.
1222
1223
1224\anchor HP140
1225### The CANDLE and VIOLIN options
1226
1227The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1228implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1229the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1230vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1231(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1232
1233Instead of using the predefined representations, the candle and violin parameters can be
1234changed individually. In that case the option have the following form:
1235
1236 CANDLEX(<option-string>)
1237 CANDLEY(<option-string>)
1238 VIOLINX(<option-string>)
1239 VIOLINY(<option-string>).
1240
1241All zeros at the beginning of `option-string` can be omitted.
1242
1243`option-string` consists eight values, defined as follow:
1244
1245 "CANDLEX(zhpawMmb)"
1246
1247Where:
1248
1249 - `b = 0`; no box drawn
1250 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1251 makes sense in the very most cases to always draw the box
1252 - `b = 2`; draw a filled box with border
1253
1254 - `m = 0`; no median drawn
1255 - `m = 1`; median is drawn as a line
1256 - `m = 2`; median is drawn with errors (notches)
1257 - `m = 3`; median is drawn as a circle
1258
1259 - `M = 0`; no mean drawn
1260 - `M = 1`; mean is drawn as a dashed line
1261 - `M = 3`; mean is drawn as a circle
1262
1263 - `w = 0`; no whisker drawn
1264 - `w = 1`; whisker is drawn to end of distribution.
1265 - `w = 2`; whisker is drawn to max 1.5*iqr
1266
1267 - `a = 0`; no anchor drawn
1268 - `a = 1`; the anchors are drawn
1269
1270 - `p = 0`; no points drawn
1271 - `p = 1`; only outliers are drawn
1272 - `p = 2`; all datapoints are drawn
1273 - `p = 3`: all datapoints are drawn scattered
1274
1275 - `h = 0`; no histogram is drawn
1276 - `h = 1`; histogram at the left or bottom side is drawn
1277 - `h = 2`; histogram at the right or top side is drawn
1278 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1279
1280 - `z = 0`; no zero indicator line is drawn
1281 - `z = 1`; zero indicator line is drawn.
1282
1283As one can see all individual options for both candle and violin plots can be accessed by this
1284mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1285meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1286vice versa, if you wish.
1287
1288Using a logarithmic x- or y-axis is possible for candle and violin charts.
1289
1290\since **ROOT version 6.11/01**
1291
1292a logarithmic z-axis is possible, too but will only affect violin charts of course.
1293
1294\anchor HP140a
1295#### The CANDLE option
1296
1297<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1298a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1299way to describe graphically a data distribution (D) with only five numbers:
1300
1301 1. The minimum value of the distribution D (bottom or left whisker).
1302 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1303 3. The median (M): 50% of the data points in D are less than M.
1304 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1305 5. The maximum value of the distribution D (top or right whisker).
1306
1307In this implementation a TH2 is considered as a collection of TH1 along
1308X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1309Each TH1 is represented as one candle.
1310
1311Begin_Macro(source)
1312../../../tutorials/hist/hist052_Graphics_candle_plot_whiskers.C
1313End_Macro
1314
1315The candle reduces the information coming from a whole distribution into few values.
1316Independently from the number of entries or the significance of the underlying distribution
1317a candle will always look like a candle. So candle plots should be used carefully in
1318particular with unknown distributions. The definition of a candle is based on
1319__unbinned data__. Here, candles are created from binned data. Because of this, the
1320deviation is connected to the bin width used. The calculation of the quantiles
1321normally done on unbinned data also. Because data are binned, this will
1322only work the best possible way within the resolution of one bin
1323
1324Because of all these facts one should take care that:
1325
1326 - there are enough points per candle
1327 - the bin width is small enough (more bins will increase the maximum
1328 available resolution of the quantiles although there will be some
1329 bins with no entries)
1330 - never make a candle-plot if the underlying distribution is double-distributed
1331 - only create candles of distributions that are more-or-less gaussian (the
1332 MPV should be not too far away from the mean).
1333
1334#### What a candle is made of
1335
1336\since **ROOT version 6.07/05**
1337
1338##### The box
1339The box displays the position of the inter-quantile-range of the underlying
1340distribution. The box contains 25% of the distribution below the median
1341and 25% of the distribution above the median. If the underlying distribution is large
1342enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1343(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1344the position of the box can be modified by SetBarWidth() and SetBarOffset().
1345The +-25% quantiles are calculated by the GetQuantiles() methods.
1346
1347\since **ROOT version 6.11/01**
1348
1349Using the static function TCandle::SetBoxRange(double) the box definition will be
1350overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1351to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1352The static function will affect all candle-charts in the running program.
1353Default is 0.5.
1354
1355Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1356whole candle) can be influenced. Deactivated, the width is constant (to be set by
1357SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1358amount of data in the corresponding candle, the maximum width can be influenced by
1359SetBarWidth(). The static function will affect all candle-charts in the running program.
1360Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1361supported, yet
1362
1363##### The Median
1364For a sorted list of numbers, the median is the value in the middle of the list.
1365E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1366because it is in the middle of the list. If the number of entries is even the
1367average of the two values in the middle will be used. As histograms are binned
1368data, the situation is a bit more complex. The following example shows this:
1369
1370~~~ {.cpp}
1371void quantiles() {
1372 auto h = new TH1I("h","h",10,0,10);
1373 //h->Fill(3);
1374 //h->Fill(3);
1375 h->Fill(4);
1376 h->Draw();
1377 double p = 0.;
1378 double q = 0.;
1379 h->GetQuantiles(1,&q,&p);
1380
1381 cout << "Median is: " << q << std::endl;
1382}
1383~~~
1384
1385Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1386the example will return a calculated median of 4.5, because that's the bin center
1387of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1388commented out, it will return 3.75, because the algorithm tries to evenly distribute
1389the individual values of a bin with bin content > 0. It means the sorted list
1390would be "3.25, 3.75, 4.5".
1391
1392The consequence is a median of 3.75. This shows how important it is to use a
1393small enough bin-width when using candle-plots on binned data.
1394If the distribution is large enough and gaussian shaped the median will be exactly
1395equal to the mean.
1396The median can be shown as a line or as a circle or not shown at all.
1397
1398In order to show the significance of the median notched candle plots apply a "notch" or
1399narrowing of the box around the median. The significance is defined by
1400\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1401(where iqr is the size of the box and N is the number of entries of the whole
1402distribution). Candle plots like these are usually called "notched candle plots".
1403
1404In case the significance of the median is greater that the size of the box, the
1405box will have an unnatural shape. Usually it means the chart has not enough data,
1406or that representing this uncertainty is not useful
1407
1408##### The Mean
1409The mean can be drawn as a dashed line or as a circle or not drawn at all.
1410The mean is the arithmetic average of the values in the distribution.
1411It is calculated using GetMean(). Because histograms are
1412binned data, the mean value can differ from a calculation on the raw-data.
1413If the distribution is large enough and gaussian shaped the mean will be
1414exactly the median.
1415
1416##### The Whiskers
1417The whiskers represent the part of the distribution not covered by the box.
1418The upper 25% and the lower 25% of the distribution are located within the whiskers.
1419Two representations are available.
1420
1421 - A simple one (using w=1) defining the lower whisker from the lowest data value
1422 to the bottom of the box, and the upper whisker from the top of the box to the
1423 highest data value. In this representation the whisker-lines are dashed.
1424 - A more complex one having a further restriction. The whiskers are still connected
1425 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1426 be that the outermost part of the underlying distribution will not be covered
1427 by the whiskers. Usually these missing parts will be represented by the outliers
1428 (see points). Of course the upper and the lower whisker may differ in length.
1429 In this representation the whiskers are drawn as solid lines.
1430
1431\since **ROOT version 6.11/01**
1432
1433Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1434will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1435the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1436that candle. The static function will affect all candle-charts in the running program.
1437Default is 1.
1438
1439If the distribution is large enough and gaussian shaped, the maximum length of
1440the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14411.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1442(see picture above). In that case 99.3% of the total distribution will be covered
1443by the box and the whiskers, whereas 0.7% are represented by the outliers.
1444
1445##### The Anchors
1446The anchors have no special meaning in terms of statistical calculation. They mark
1447the end of the whiskers and they have the width of the box. Both representation
1448with and without anchors are common.
1449
1450##### The Points
1451Depending on the configuration the points can have different meanings:
1452 - If p=1 the points represent the outliers. If they are shown, it means
1453 some parts of the underlying distribution are not covered by the whiskers.
1454 This can only occur when the whiskers are set to option w=2. Here the whiskers
1455 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1456 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1457 - If p=2 all points in the distribution will be painted as crosses. This is
1458 useful for small datasets only (up to 10 or 20 points per candle).
1459 The outliers are shown along the candle. Because the underlying distribution
1460 is binned, is frequently occurs that a bin contains more than one value.
1461 Because of this the points will be randomly scattered within their bin along
1462 the candle axis. If the bin content for a bin is exactly 1 (usually
1463 this happens for the outliers) if will be drawn in the middle of the bin along
1464 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1465 on very large datasets scaling will be performed automatically. In that case one
1466 would loose all outliers because they have usually a bin content of 1 (and a
1467 bin content between 0 and 1 after the scaling). Because of this all bin contents
1468 between 0 and 1 - after the scaling - will be forced to be 1.
1469 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1470 one can show all values as a scatter plot instead by choosing p=3. The points will be
1471 drawn as dots and will be scattered within the width of the candle. The color
1472 of the points will be the color of the candle-chart.
1473
1474##### Other Options
1475Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1476with a histogram.
1477
1478#### How to use the candle-plots drawing option
1479
1480There are six predefined candle-plot representations:
1481
1482 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1483 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1484 It is a good compromise
1485 - "CANDLEX3": Like candle2 but with a mean as a circle.
1486 It is easier to distinguish mean and median
1487 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1488 (notched candle plots).
1489 For bigger datasets per candle
1490 - "CANDLEX5": Like candle2 but showing all data points.
1491 For very small datasets
1492 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1493 For huge datasets
1494
1495
1496The following picture shows how the six predefined representations look.
1497
1498Begin_Macro
1499{
1500 auto c1 = new TCanvas("c1","c1",700,800);
1501 c1->Divide(2,3);
1502 gStyle->SetOptStat(kFALSE);
1503
1504 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1505 float px, py;
1506 for (Int_t i = 0; i < 15000; i++) {
1507 gRandom->Rannor(px,py);
1508 hcandle->Fill(px,5*py);
1509 }
1510 hcandle->SetMarkerSize(0.5);
1511
1512 TH2F *h2;
1513 for (Int_t i=1; i<7; i++) {
1514 c1->cd(i);
1515 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1516 h2->SetTitle(Form("CANDLE%d",i));
1517 }
1518}
1519End_Macro
1520
1521
1522#### Example 1
1523Box and improved whisker, no mean, no median, no anchor no outliers
1524
1525 h1->Draw("CANDLEX(2001)");
1526
1527#### Example 2
1528A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1529
1530 h1->Draw("CANDLEX(112111)");
1531
1532#### Example 3
1533The following example shows how several candle plots can be super-imposed using
1534the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1535Also the color, the line width, the size of the points and so on can be changed by the
1536standard attribute setting methods such as SetLineColor() SetLineWidth().
1537
1538Begin_Macro(source)
1539../../../tutorials/hist/hist049_Graphics_candle_plot.C
1540End_Macro
1541
1542\anchor HP140b
1543#### The VIOLIN option
1544
1545<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1546that also encodes the pdf information at each point.
1547
1548
1549Quartiles and mean are also represented at each point, with a marker
1550and two lines.
1551
1552In this implementation a TH2 is considered as a collection of TH1 along
1553X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1554
1555#### What a violin is made of
1556
1557\since **ROOT version 6.09/02**
1558
1559##### The histogram
1560The histogram is typically drawn to both directions with respect to the middle-line of the
1561corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1562one side (h=1, or h=2).
1563The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1564histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1565be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1566A solid fill style is recommended.
1567
1568\since **ROOT version 6.11/01**
1569
1570Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1571violin can be influenced. Activated, the height of the bins of the individual violins will be
1572scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1573Deactivated, the height of the bin with the maximum content of each individual violin is
1574set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1575in the running program. Default is true. Scaling between multiple violin-charts
1576(using "same" or THStack) is not supported, yet.
1577
1578##### The zero indicator line
1579Typical for violin charts is a line in the background over the whole histogram indicating
1580the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1581will always be the same as the fill-color of the histogram.
1582
1583##### The Mean
1584The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1585
1586##### Whiskers
1587The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1588difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1589the whiskers will be forced to be solid (usually hashed)
1590
1591##### Points
1592The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1593better whisker definition (w=2) and outliers (p=1).
1594
1595##### Other options
1596It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1597including a box-plot.
1598
1599#### How to use the violin-plots drawing option
1600
1601There are two predefined violin-plot representations:
1602 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1603 zero indicator line)
1604 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1605
1606A solid fill style is recommended for this plot (as opposed to a hollow or
1607hashed style).
1608
1609Begin_Macro(source)
1610{
1611 auto c1 = new TCanvas("c1","c1",600,400);
1612 Int_t nx(6), ny(40);
1613 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1614 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1615 TF1 f1("f1", "gaus", +0,0 +4.0);
1616 double x,y;
1617 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1618 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1619 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1620 for(Int_t i=0; i<10000; ++i){
1621 x = xc;
1622 y = f1.GetRandom();
1623 hviolin->Fill(x, y);
1624 }
1625 }
1626 hviolin->SetFillColor(kGray);
1627 hviolin->SetMarkerStyle(20);
1628 hviolin->SetMarkerSize(0.5);
1629 hviolin->Draw("VIOLIN");
1630 c1->Update();
1631}
1632End_Macro
1633
1634The next example illustrates a time development of a certain value:
1635
1636Begin_Macro(source)
1637../../../tutorials/hist/hist047_Graphics_candle_decay.C
1638End_Macro
1639
1640
1641\anchor HP15
1642### The TEXT and TEXTnn Option
1643
1644
1645For each bin the content is printed. The text attributes are:
1646
1647- text font = current TStyle font (`gStyle->SetTextFont()`).
1648- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1649 with the option `TEXT` the marker size can be changed with
1650 `h->SetMarkerSize(markersize)`).
1651- text color = marker color.
1652
1653By default the format `g` is used. This format can be redefined
1654by calling `gStyle->SetPaintTextFormat()`.
1655
1656It is also possible to use `TEXTnn` in order to draw the text with
1657the angle `nn` (`0 < nn <= 90`).
1658
1659For 2D histograms the text is plotted in the center of each non empty cells.
1660It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1661or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1662position equal to the bin content.
1663
1664For 2D histograms when the option "E" (errors) is combined with the option
1665text ("TEXTE"), the error for each bin is also printed.
1666
1667Begin_Macro(source)
1668{
1669 auto c01 = new TCanvas("c01","c01",700,400);
1670 c01->Divide(2,1);
1671 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1672 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1673 float px, py;
1674 for (Int_t i = 0; i < 25000; i++) {
1675 gRandom->Rannor(px,py);
1676 htext1->Fill(px,0.1);
1677 htext2->Fill(px,5*py,0.1);
1678 }
1679 gStyle->SetPaintTextFormat("4.1f m");
1680 htext2->SetMarkerSize(1.8);
1681 c01->cd(1);
1682 htext2->Draw("TEXT45");
1683 c01->cd(2);
1684 htext1->Draw();
1685 htext1->Draw("HIST TEXT0 SAME");
1686}
1687End_Macro
1688
1689\since **ROOT version 6.07/07:**
1690
1691In case several histograms are drawn on top ot each other (using option `SAME`),
1692the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1693text position in each cell, in percentage of the bin width.
1694
1695Begin_Macro(source)
1696{
1697 auto c03 = new TCanvas("c03","c03",700,400);
1698 gStyle->SetOptStat(0);
1699 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1700 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1701 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1702 float px, py;
1703 for (Int_t i = 0; i < 25000; i++) {
1704 gRandom->Rannor(px,py);
1705 htext3->Fill(4*px,20*py,0.1);
1706 htext4->Fill(4*px,20*py,0.5);
1707 htext5->Fill(4*px,20*py,1.0);
1708 }
1709 htext4->SetMarkerSize(1.8);
1710 htext5->SetMarkerSize(1.8);
1711 htext5->SetMarkerColor(kRed);
1712 htext4->SetBarOffset(0.2);
1713 htext5->SetBarOffset(-0.2);
1714 htext3->Draw("COL");
1715 htext4->Draw("TEXT SAME");
1716 htext5->Draw("TEXT SAME");
1717}
1718End_Macro
1719
1720In the case of profile histograms it is possible to print the number
1721of entries instead of the bin content. It is enough to combine the
1722option "E" (for entries) with the option "TEXT".
1723
1724Begin_Macro(source)
1725{
1726 auto c02 = new TCanvas("c02","c02",700,400);
1727 c02->Divide(2,1);
1728 gStyle->SetPaintTextFormat("g");
1729
1730 auto profile = new TProfile("profile","profile",10,0,10);
1731 profile->SetMarkerSize(2.2);
1732 profile->Fill(0.5,1);
1733 profile->Fill(1.5,2);
1734 profile->Fill(2.5,3);
1735 profile->Fill(3.5,4);
1736 profile->Fill(4.5,5);
1737 profile->Fill(5.5,5);
1738 profile->Fill(6.5,4);
1739 profile->Fill(7.5,3);
1740 profile->Fill(8.5,2);
1741 profile->Fill(9.5,1);
1742 c02->cd(1); profile->Draw("HIST TEXT0");
1743 c02->cd(2); profile->Draw("HIST TEXT0E");
1744}
1745End_Macro
1746
1747\anchor HP16
1748### The CONTour options
1749
1750
1751The following contour options are supported:
1752
1753| Option | Description |
1754|----------|-----------------------------------------------------------------------------|
1755| "CONT" | Draw a contour plot (same as CONT0). |
1756| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1757| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1758| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1759| "CONT3" | Draw a contour plot using the same line style for all contours. |
1760| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1761
1762
1763The following example shows a 2D histogram plotted with the option
1764`CONTZ`. The option `CONT` draws a contour plot using surface
1765colors to distinguish contours. Combined with the option `CONT` (or
1766`CONT0`), the option `Z` allows to display the color palette
1767defined by `gStyle->SetPalette()`.
1768
1769Begin_Macro(source)
1770{
1771 auto c1 = new TCanvas("c1","c1",600,400);
1772 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1773 float px, py;
1774 for (Int_t i = 0; i < 25000; i++) {
1775 gRandom->Rannor(px,py);
1776 hcontz->Fill(px-1,5*py);
1777 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1778 }
1779 hcontz->Draw("CONTZ");
1780}
1781End_Macro
1782
1783The following example shows a 2D histogram plotted with the option
1784`CONT1Z`. The option `CONT1` draws a contour plot using the
1785line colors to distinguish contours. Combined with the option `CONT1`,
1786the option `Z` allows to display the color palette defined by
1787`gStyle->SetPalette()`.
1788
1789Begin_Macro(source)
1790{
1791 auto c1 = new TCanvas("c1","c1",600,400);
1792 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1793 float px, py;
1794 for (Int_t i = 0; i < 25000; i++) {
1795 gRandom->Rannor(px,py);
1796 hcont1->Fill(px-1,5*py);
1797 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1798 }
1799 hcont1->Draw("CONT1Z");
1800}
1801End_Macro
1802
1803The following example shows a 2D histogram plotted with the option
1804`CONT2`. The option `CONT2` draws a contour plot using the
1805line styles (1 to 5) to distinguish contours.
1806
1807Begin_Macro(source)
1808{
1809 auto c1 = new TCanvas("c1","c1",600,400);
1810 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1811 float px, py;
1812 for (Int_t i = 0; i < 25000; i++) {
1813 gRandom->Rannor(px,py);
1814 hcont2->Fill(px-1,5*py);
1815 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1816 }
1817 hcont2->Draw("CONT2");
1818}
1819End_Macro
1820
1821The following example shows a 2D histogram plotted with the option
1822`CONT3`. The option `CONT3` draws contour plot using the same line style for
1823all contours.
1824
1825Begin_Macro(source)
1826{
1827 auto c1 = new TCanvas("c1","c1",600,400);
1828 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1829 float px, py;
1830 for (Int_t i = 0; i < 25000; i++) {
1831 gRandom->Rannor(px,py);
1832 hcont3->Fill(px-1,5*py);
1833 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1834 }
1835 hcont3->SetLineStyle(kDotted);
1836 hcont3->Draw("CONT3");
1837}
1838End_Macro
1839
1840The following example shows a 2D histogram plotted with the option
1841`CONT4`. The option `CONT4` draws a contour plot using surface
1842colors to distinguish contours (`SURF` option at theta = 0). Combined
1843with the option `CONT` (or `CONT0`), the option `Z`
1844allows to display the color palette defined by `gStyle->SetPalette()`.
1845
1846Begin_Macro(source)
1847{
1848 auto c1 = new TCanvas("c1","c1",600,400);
1849 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1850 float px, py;
1851 for (Int_t i = 0; i < 25000; i++) {
1852 gRandom->Rannor(px,py);
1853 hcont4->Fill(px-1,5*py);
1854 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1855 }
1856 hcont4->Draw("CONT4Z");
1857}
1858End_Macro
1859
1860The default number of contour levels is 20 equidistant levels and can be changed
1861with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1862
1863\anchor HP16a
1864#### The LIST option
1865
1866When option `LIST` is specified together with option
1867`CONT`, the points used to draw the contours are saved in
1868`TGraph` objects:
1869
1870 h->Draw("CONT LIST");
1871 gPad->Update();
1872
1873The contour are saved in `TGraph` objects once the pad is painted.
1874Therefore to use this functionality in a macro, `gPad->Update()`
1875should be performed after the histogram drawing. Once the list is
1876built, the contours are accessible in the following way:
1877
1878 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1879 Int_t ncontours = contours->GetSize();
1880 TList *list = (TList*)contours->At(i);
1881
1882Where `i` is a contour number, and list contains a list of
1883`TGraph` objects.
1884For one given contour, more than one disjoint polyline may be generated.
1885The number of TGraphs per contour is given by:
1886
1887 list->GetSize();
1888
1889To access the first graph in the list one should do:
1890
1891 TGraph *gr1 = (TGraph*)list->First();
1892
1893
1894The following example (hist102_TH2_contour_list.C) shows how to use this functionality.
1895
1896Begin_Macro(source)
1897../../../tutorials/hist/hist102_TH2_contour_list.C
1898End_Macro
1899
1900\anchor HP16b
1901#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1902
1903The following options select the `CONT4` option and are useful for
1904sky maps or exposure maps (earth.C).
1905
1906| Option | Description |
1907|--------------|---------------------------------------------------------------|
1908| "AITOFF" | Draw a contour via an AITOFF projection.|
1909| "MERCATOR" | Draw a contour via an Mercator projection.|
1910| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1911| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1912
1913Begin_Macro(source)
1914../../../tutorials/visualisation/graphics/earth.C
1915End_Macro
1916
1917
1918\anchor HP17
1919### The LEGO options
1920
1921
1922In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1923is proportional to the cell content. The lego aspect is control with the
1924following options:
1925
1926| Option | Description |
1927|----------|-------------------------------------------------------------------|
1928| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1929| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1930| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1931| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1932| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1933| "0" | When used with any LEGO option, the empty bins are not drawn.|
1934
1935
1936See the limitations with [the option "SAME"](\ref HP060a).
1937
1938Line attributes can be used in lego plots to change the edges' style.
1939
1940The following example shows a 2D histogram plotted with the option
1941`LEGO`. The option `LEGO` draws a lego plot using the hidden
1942lines removal technique.
1943
1944Begin_Macro(source)
1945{
1946 auto c2 = new TCanvas("c2","c2",600,400);
1947 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1948 float px, py;
1949 for (Int_t i = 0; i < 25000; i++) {
1950 gRandom->Rannor(px,py);
1951 hlego->Fill(px-1,5*py);
1952 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1953 }
1954 hlego->Draw("LEGO");
1955}
1956End_Macro
1957
1958The following example shows a 2D histogram plotted with the option
1959`LEGO1`. The option `LEGO1` draws a lego plot using the
1960hidden surface removal technique. Combined with any `LEGOn` option, the
1961option `0` allows to not drawn the empty bins.
1962
1963Begin_Macro(source)
1964{
1965 auto c2 = new TCanvas("c2","c2",600,400);
1966 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1967 float px, py;
1968 for (Int_t i = 0; i < 25000; i++) {
1969 gRandom->Rannor(px,py);
1970 hlego1->Fill(px-1,5*py);
1971 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1972 }
1973 hlego1->SetFillColor(kYellow);
1974 hlego1->Draw("LEGO1 0");
1975}
1976End_Macro
1977
1978The following example shows a 2D histogram plotted with the option
1979`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1980draws a lego plot using the hidden surface removal technique but doesn't draw
1981the border lines of each individual lego-bar. This is very useful for histograms
1982having many bins. With such histograms the option `LEGO1` gives a black
1983image because of the border lines. This option also works with stacked legos.
1984
1985Begin_Macro(source)
1986{
1987 auto c2 = new TCanvas("c2","c2",600,400);
1988 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1989 float px, py;
1990 for (Int_t i = 0; i < 25000; i++) {
1991 gRandom->Rannor(px,py);
1992 hlego3->Fill(px-1,5*py);
1993 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1994 }
1995 hlego3->SetFillColor(kRed);
1996 hlego3->Draw("LEGO3");
1997}
1998End_Macro
1999
2000The following example shows a 2D histogram plotted with the option
2001`LEGO2`. The option `LEGO2` draws a lego plot using colors to
2002show the cell contents. Combined with the option `LEGO2`, the option
2003`Z` allows to display the color palette defined by
2004`gStyle->SetPalette()`.
2005
2006Begin_Macro(source)
2007{
2008 auto c2 = new TCanvas("c2","c2",600,400);
2009 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
2010 float px, py;
2011 for (Int_t i = 0; i < 25000; i++) {
2012 gRandom->Rannor(px,py);
2013 hlego2->Fill(px-1,5*py);
2014 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
2015 }
2016 hlego2->Draw("LEGO2Z");
2017}
2018End_Macro
2019
2020
2021
2022\anchor HP18
2023### The "SURFace" options
2024
2025
2026In a surface plot, cell contents are represented as a mesh.
2027The height of the mesh is proportional to the cell content.
2028
2029| Option | Description |
2030|----------|-------------------------------------------------------------------|
2031| "SURF" | Draw a surface plot using the hidden line removal technique.|
2032| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2033| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2034| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2035| "SURF4" | Draw a surface using the Gouraud shading technique.|
2036| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2037| "SURF6" | This option should not be used directly. It is used internally when the CONT is used with option the option SAME on a 3D plot.|
2038| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2039
2040
2041
2042See the limitations with [the option "SAME"](\ref HP060a).
2043
2044The following example shows a 2D histogram plotted with the option
2045`SURF`. The option `SURF` draws a lego plot using the hidden
2046lines removal technique.
2047
2048Begin_Macro(source)
2049{
2050 auto c2 = new TCanvas("c2","c2",600,400);
2051 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2052 float px, py;
2053 for (Int_t i = 0; i < 25000; i++) {
2054 gRandom->Rannor(px,py);
2055 hsurf->Fill(px-1,5*py);
2056 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2057 }
2058 hsurf->Draw("SURF");
2059}
2060End_Macro
2061
2062The following example shows a 2D histogram plotted with the option
2063`SURF1`. The option `SURF1` draws a surface plot using the
2064hidden surface removal technique. Combined with the option `SURF1`,
2065the option `Z` allows to display the color palette defined by
2066`gStyle->SetPalette()`.
2067
2068Begin_Macro(source)
2069{
2070 auto c2 = new TCanvas("c2","c2",600,400);
2071 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2072 float px, py;
2073 for (Int_t i = 0; i < 25000; i++) {
2074 gRandom->Rannor(px,py);
2075 hsurf1->Fill(px-1,5*py);
2076 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2077 }
2078 hsurf1->Draw("SURF1");
2079}
2080End_Macro
2081
2082The following example shows a 2D histogram plotted with the option
2083`SURF2`. The option `SURF2` draws a surface plot using colors
2084to show the cell contents. Combined with the option `SURF2`, the option
2085`Z` allows to display the color palette defined by
2086`gStyle->SetPalette()`.
2087
2088Begin_Macro(source)
2089{
2090 auto c2 = new TCanvas("c2","c2",600,400);
2091 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2092 float px, py;
2093 for (Int_t i = 0; i < 25000; i++) {
2094 gRandom->Rannor(px,py);
2095 hsurf2->Fill(px-1,5*py);
2096 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2097 }
2098 hsurf2->Draw("SURF2");
2099}
2100End_Macro
2101
2102The following example shows a 2D histogram plotted with the option
2103`SURF3`. The option `SURF3` draws a surface plot using the
2104hidden line removal technique with, in addition, a filled contour view drawn on the
2105top. Combined with the option `SURF3`, the option `Z` allows
2106to display the color palette defined by `gStyle->SetPalette()`.
2107
2108Begin_Macro(source)
2109{
2110 auto c2 = new TCanvas("c2","c2",600,400);
2111 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2112 float px, py;
2113 for (Int_t i = 0; i < 25000; i++) {
2114 gRandom->Rannor(px,py);
2115 hsurf3->Fill(px-1,5*py);
2116 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2117 }
2118 hsurf3->Draw("SURF3");
2119}
2120End_Macro
2121
2122The following example shows a 2D histogram plotted with the option
2123`SURF4`. The option `SURF4` draws a surface using the Gouraud
2124shading technique.
2125
2126Begin_Macro(source)
2127{
2128 auto c2 = new TCanvas("c2","c2",600,400);
2129 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2130 float px, py;
2131 for (Int_t i = 0; i < 25000; i++) {
2132 gRandom->Rannor(px,py);
2133 hsurf4->Fill(px-1,5*py);
2134 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2135 }
2136 hsurf4->SetFillColor(kOrange);
2137 hsurf4->Draw("SURF4");
2138}
2139End_Macro
2140
2141The following example shows a 2D histogram plotted with the option
2142`SURF5 CYL`. Combined with the option `SURF5`, the option
2143`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2144
2145Begin_Macro(source)
2146{
2147 auto c2 = new TCanvas("c2","c2",600,400);
2148 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2149 float px, py;
2150 for (Int_t i = 0; i < 25000; i++) {
2151 gRandom->Rannor(px,py);
2152 hsurf5->Fill(px-1,5*py);
2153 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2154 }
2155 hsurf5->Draw("SURF5 CYL");
2156}
2157End_Macro
2158
2159The following example shows a 2D histogram plotted with the option
2160`SURF7`. The option `SURF7` draws a surface plot using the
2161hidden surfaces removal technique with, in addition, a line contour view drawn on the
2162top. Combined with the option `SURF7`, the option `Z` allows
2163to display the color palette defined by `gStyle->SetPalette()`.
2164
2165Begin_Macro(source)
2166{
2167 auto c2 = new TCanvas("c2","c2",600,400);
2168 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2169 float px, py;
2170 for (Int_t i = 0; i < 25000; i++) {
2171 gRandom->Rannor(px,py);
2172 hsurf7->Fill(px-1,5*py);
2173 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2174 }
2175 hsurf7->Draw("SURF7");
2176}
2177End_Macro
2178
2179As shown in the following example, when a contour plot is painted on top of a
2180surface plot using the option `SAME`, the contours appear in 3D on the
2181surface.
2182
2183Begin_Macro(source)
2184{
2185 auto c20=new TCanvas("c20","c20",600,400);
2186 int NBins = 50;
2187 double d = 2;
2188 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2189 for (int bx = 1; bx <= NBins; ++bx) {
2190 for (int by = 1; by <= NBins; ++by) {
2191 double x = hsc->GetXaxis()->GetBinCenter(bx);
2192 double y = hsc->GetYaxis()->GetBinCenter(by);
2193 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2194 }
2195 }
2196 hsc->Draw("surf2");
2197 hsc->Draw("CONT1 SAME");
2198}
2199End_Macro
2200
2201
2202\anchor HP19
2203### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2204
2205
2206Legos and surfaces plots are represented by default in Cartesian coordinates.
2207Combined with any `LEGOn` or `SURFn` options the following
2208options allow to draw a lego or a surface in other coordinates systems.
2209
2210| Option | Description |
2211|----------|-------------------------------------------------------------------|
2212| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2213| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2214| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2215| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2216
2217
2218
2219<b>WARNING:</b> Axis are not drawn with these options.
2220
2221The following example shows the same histogram as a lego plot is the four
2222different coordinates systems.
2223
2224Begin_Macro(source)
2225{
2226 auto c3 = new TCanvas("c3","c3",600,400);
2227 c3->Divide(2,2);
2228 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2229 float px, py;
2230 for (Int_t i = 0; i < 25000; i++) {
2231 gRandom->Rannor(px,py);
2232 hlcc->Fill(px-1,5*py);
2233 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2234 }
2235 hlcc->SetFillColor(kYellow);
2236 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2237 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2238 hlpc->SetTitle("Polar coordinates");
2239 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2240 hlsc->SetTitle("Spherical coordinates");
2241 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2242 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2243}
2244End_Macro
2245
2246The following example shows the same histogram as a surface plot is the four different coordinates systems.
2247
2248Begin_Macro(source)
2249{
2250 auto c4 = new TCanvas("c4","c4",600,400);
2251 c4->Divide(2,2);
2252 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2253 float px, py;
2254 for (Int_t i = 0; i < 25000; i++) {
2255 gRandom->Rannor(px,py);
2256 hscc->Fill(px-1,5*py);
2257 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2258 }
2259 c4->cd(1); hscc->Draw("SURF1 CYL");
2260 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2261 hspc->SetTitle("Polar coordinates");
2262 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2263 hssc->SetTitle("Spherical coordinates");
2264 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2265 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2266}
2267End_Macro
2268
2269
2270\anchor HP20
2271### Base line for bar-charts and lego plots
2272
2273
2274By default the base line used to draw the boxes for bar-charts and lego plots is
2275the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2276option or with the command:
2277
2278 gStyle->SetHistMinimumZero();
2279
2280Begin_Macro(source)
2281{
2282 auto c5 = new TCanvas("c5","c5",700,400);
2283 c5->Divide(2,1);
2284 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2285 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2286 Int_t i;
2287 double x,y;
2288 hz1->SetFillColor(kBlue);
2289 hz2->SetFillColor(kBlue);
2290 for (i=0;i<10000;i++) {
2291 x = gRandom->Gaus(0,1);
2292 y = gRandom->Gaus(0,1);
2293 if (x>0) {
2294 hz1->Fill(x,1);
2295 hz2->Fill(x,y,1);
2296 } else {
2297 hz1->Fill(x,-1);
2298 hz2->Fill(x,y,-2);
2299 }
2300 }
2301 c5->cd(1); hz1->Draw("bar2 min0");
2302 c5->cd(2); hz2->Draw("lego1 min0");
2303}
2304End_Macro
2305
2306This option also works for horizontal plots. The example given in the section
2307["The bar chart option"](\ref HP100) appears as follow:
2308
2309Begin_Macro(source)
2310{
2311 int i;
2312 const Int_t nx = 8;
2313 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2314 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2315 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2316
2317 auto cbh = new TCanvas("cbh","cbh",400,600);
2318 cbh->SetGrid();
2319
2320 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2321 h1bh->SetFillColor(4);
2322 h1bh->SetBarWidth(0.4);
2323 h1bh->SetBarOffset(0.1);
2324 h1bh->SetStats(0);
2325 h1bh->SetMinimum(-5);
2326 h1bh->SetMaximum(5);
2327
2328 for (i=1; i<=nx; i++) {
2329 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2330 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2331 }
2332
2333 h1bh->Draw("hbar min0");
2334
2335 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2336 h2bh->SetFillColor(38);
2337 h2bh->SetBarWidth(0.4);
2338 h2bh->SetBarOffset(0.5);
2339 h2bh->SetStats(0);
2340 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2341
2342 h2bh->Draw("hbar min0 same");
2343}
2344End_Macro
2345
2346
2347\anchor HP20a
2348### TH2Poly Drawing
2349
2350
2351The following options are supported:
2352
2353| Option | Description |
2354|----------|-------------------------------------------------------------------|
2355| "SCAT" | Draw a scatter plot (legacy draw option).|
2356| "COL" | Draw a color plot. All the bins are painted even the empty bins (default).|
2357| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2358| "0" | When used with any COL options, the empty bins are not drawn.|
2359| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2360| "TEXTN" | Draw bin names as text.|
2361| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn <= 90).|
2362| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2363| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2364| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2365
2366
2367
2368`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2369shapes. The bins are defined as graphs. The following macro is a very simple
2370example showing how to book a TH2Poly and draw it.
2371
2372Begin_Macro(source)
2373{
2374 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2375 auto h2p = new TH2Poly();
2376 h2p->SetName("h2poly_name");
2377 h2p->SetTitle("h2poly_title");
2378 double px1[] = {0, 5, 6};
2379 double py1[] = {0, 0, 5};
2380 double px2[] = {0, -1, -1, 0};
2381 double py2[] = {0, 0, -1, 3};
2382 double px3[] = {4, 3, 0, 1, 2.4};
2383 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2384 h2p->AddBin(3, px1, py1);
2385 h2p->AddBin(4, px2, py2);
2386 h2p->AddBin(5, px3, py3);
2387 h2p->Fill(0.1, 0.01, 3);
2388 h2p->Fill(-0.5, -0.5, 7);
2389 h2p->Fill(-0.7, -0.5, 1);
2390 h2p->Fill(1, 3, 1.5);
2391 double fx[] = {0.1, -0.5, -0.7, 1};
2392 double fy[] = {0.01, -0.5, -0.5, 3};
2393 double fw[] = {3, 1, 1, 1.5};
2394 h2p->FillN(4, fx, fy, fw);
2395 h2p->Draw("col");
2396}
2397End_Macro
2398
2399Rectangular bins are a frequent case. The special version of
2400the `AddBin` method allows to define them more easily like
2401shown in the following example (hist037_TH2Poly_boxes.C).
2402
2403Begin_Macro(source)
2404../../../tutorials/hist/hist037_TH2Poly_boxes.C
2405End_Macro
2406
2407One `TH2Poly` bin can be a list of polygons. Such bins are defined
2408by calling `AddBin` with a `TMultiGraph`. The following example
2409shows a such case:
2410
2411Begin_Macro(source)
2412{
2413 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2414
2415 Int_t i, bin;
2416 const Int_t nx = 48;
2417 const char *states [nx] = {
2418 "alabama", "arizona", "arkansas", "california",
2419 "colorado", "connecticut", "delaware", "florida",
2420 "georgia", "idaho", "illinois", "indiana",
2421 "iowa", "kansas", "kentucky", "louisiana",
2422 "maine", "maryland", "massachusetts", "michigan",
2423 "minnesota", "mississippi", "missouri", "montana",
2424 "nebraska", "nevada", "new_hampshire", "new_jersey",
2425 "new_mexico", "new_york", "north_carolina", "north_dakota",
2426 "ohio", "oklahoma", "oregon", "pennsylvania",
2427 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2428 "texas", "utah", "vermont", "virginia",
2429 "washington", "west_virginia", "wisconsin", "wyoming"
2430 };
2431 Double_t pop[nx] = {
2432 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2433 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2434 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2435 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2436 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2437 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2438 };
2439
2440 Double_t lon1 = -130;
2441 Double_t lon2 = -65;
2442 Double_t lat1 = 24;
2443 Double_t lat2 = 50;
2444 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2445
2446 TFile::SetCacheFileDir(".");
2447 auto f = TFile::Open("http://root.cern/files/usa.root", "CACHEREAD");
2448
2449 TMultiGraph *mg;
2450 TKey *key;
2451 TIter nextkey(gDirectory->GetListOfKeys());
2452 while ((key = (TKey*)nextkey())) {
2453 TObject *obj = key->ReadObj();
2454 if (obj->InheritsFrom("TMultiGraph")) {
2455 mg = (TMultiGraph*)obj;
2456 bin = p->AddBin(mg);
2457 }
2458 }
2459
2460 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2461
2462 gStyle->SetOptStat(11);
2463 p->Draw("COLZ L");
2464}
2465End_Macro
2466
2467`TH2Poly` histograms can also be plotted using the GL interface using
2468the option "GLLEGO".
2469
2470\since **ROOT version 6.09/01**
2471
2472In some cases it can be useful to not draw the empty bins. the option "0"
2473combined with the option "COL" and "COLZ" allows to do that.
2474
2475Begin_Macro(source)
2476{
2477 auto chc = new TCanvas("chc","chc",600,400);
2478
2479 auto hc = new TH2Poly();
2480 hc->Honeycomb(0,0,.1,25,25);
2481 hc->SetName("hc");
2482 hc->SetTitle("Option COLZ 0");
2483 TRandom ran;
2484 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2485 hc->Draw("colz 0");
2486}
2487End_Macro
2488
2489\anchor HP21
2490### The SPEC option
2491
2492
2493This option allows to use the `TSpectrum2Painter` tools. See the full
2494documentation in `TSpectrum2Painter::PaintSpectrum`.
2495
2496
2497\anchor HP22
2498### Option "Z" : Adding the color palette on the right side of the pad
2499
2500
2501When this option is specified, a color palette with an axis indicating the value
2502of the corresponding color is drawn on the right side of the picture. In case,
2503not enough space is left, one can increase the size of the right margin by
2504calling `TPad::SetRightMargin()`. The attributes used to display the
2505palette axis values are taken from the Z axis of the object. For example, to
2506set the labels size on the palette axis do:
2507
2508 hist->GetZaxis()->SetLabelSize().
2509
2510<b>WARNING:</b> The palette axis is always drawn vertically.
2511
2512
2513\anchor HP23
2514### Setting the color palette
2515
2516
2517To change the color palette `TStyle::SetPalette` should be used, eg:
2518
2519 gStyle->SetPalette(ncolors,colors);
2520
2521For example the option `COL` draws a 2D histogram with cells
2522represented by a box filled with a color index which is a function
2523of the cell content.
2524If the cell content is N, the color index used will be the color number
2525in `colors[N]`, etc. If the maximum cell content is greater than
2526`ncolors`, all cell contents are scaled to `ncolors`.
2527
2528If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2529defined. This palette is recommended for pads, labels ...
2530
2531`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2532Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2533palette.
2534
2535Other pre-defined palettes with 255 colors are available when `colors == 0`.
2536The following value of `ncolors` give access to:
2537
2538
2539 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2540 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2541 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2542 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright
2543yellow) if ncolors = 55 and colors=0, a Rain Bow palette is used. if ncolors = 56 and colors=0, an inverted Dark Body
2544Radiator palette is used.
2545
2546
2547If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2548
2549The default palette defines:
2550
2551- index 0 to 9 : shades of grey
2552- index 10 to 19 : shades of brown
2553- index 20 to 29 : shades of blue
2554- index 30 to 39 : shades of red
2555- index 40 to 49 : basic colors
2556
2557The color numbers specified in the palette can be viewed by selecting
2558the item `colors` in the `VIEW` menu of the canvas tool bar.
2559The red, green, and blue components of a color can be changed thanks to
2560`TColor::SetRGB()`.
2561
2562\since **ROOT version 6.19/01**
2563
2564As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2565points as controlled by SetNdivisions.
2566If option "CJUST" is given labels and ticks are justified at the
2567color boundaries defined by the contour levels.
2568For more details see `TPaletteAxis`
2569
2570\anchor HP24
2571### Drawing a sub-range of a 2D histogram; the [cutg] option
2572
2573
2574Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2575histogram. One must create a graphical cut (mouse or C++) and specify the name
2576of the cut between `[]` in the `Draw()` option.
2577For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2578
2579 myhist->Draw("surf1 [cutg]");
2580
2581To invert the cut, it is enough to put a `-` in front of its name:
2582
2583 myhist->Draw("surf1 [-cutg]");
2584
2585It is possible to apply several cuts (`,` means logical AND):
2586
2587 myhist->Draw("surf1 [cutg1,cutg2]");
2588
2589Begin_Macro(source)
2590../../../tutorials/fit/fit2a.C
2591End_Macro
2592
2593\anchor HP25
2594### Drawing options for 3D histograms
2595
2596
2597| Option | Description |
2598|----------|-------------------------------------------------------------------|
2599| "SCAT" | Draw a scatter plot (legacy draw option).|
2600| "ISO" | Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one surface at the value computed as follow: `SumOfWeights/(NbinsX*NbinsY*NbinsZ)`|
2601| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2602| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2603| "BOX2" | Same as "COL". The boxes' colors are picked in the current palette according to the bins' contents (default)|
2604| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2605| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2606
2607Note that instead of `BOX` one can also use `LEGO`.
2608
2609By default, 3D histograms are drawn as a colored box plots.
2610
2611The following example shows a 3D histogram plotted as a scatter plot.
2612
2613Begin_Macro(source)
2614{
2615 auto c06 = new TCanvas("c06","c06",600,400);
2616 gStyle->SetOptStat(kFALSE);
2617 auto h3scat = new TH3F("h3scat","Option SCAT",15,-2,2,15,-2,2,15,0,4);
2618 double x, y, z;
2619 for (Int_t i=0;i<10000;i++) {
2620 gRandom->Rannor(x, y);
2621 z = x*x + y*y;
2622 h3scat->Fill(x,y,z);
2623 }
2624 h3scat->Draw("SCAT"); // This a legacy draw option
2625}
2626End_Macro
2627
2628The following example shows a 3D histogram plotted with the option `BOX`.
2629
2630Begin_Macro(source)
2631{
2632 auto c16 = new TCanvas("c16","c16",600,400);
2633 gStyle->SetOptStat(kFALSE);
2634 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2635 double x, y, z;
2636 for (Int_t i=0;i<10000;i++) {
2637 gRandom->Rannor(x, y);
2638 z = x*x + y*y;
2639 h3box->Fill(x,y,z);
2640 }
2641 h3box->Draw("BOX");
2642}
2643End_Macro
2644
2645The following example shows a 3D histogram plotted with the option `BOX1`.
2646
2647Begin_Macro(source)
2648{
2649 auto c36 = new TCanvas("c36","c36",600,400);
2650 gStyle->SetOptStat(kFALSE);
2651 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2652 double x, y, z;
2653 for (Int_t i=0;i<10000;i++) {
2654 gRandom->Rannor(x, y);
2655 z = abs(sin(x)/x + cos(y)*y);
2656 h3box->Fill(x,y,z);
2657 }
2658 h3box->SetFillColor(9);
2659 h3box->Draw("BOX1");
2660}
2661End_Macro
2662
2663The following example shows a 3D histogram plotted with the option `BOX2`.
2664
2665Begin_Macro(source)
2666{
2667 auto c56 = new TCanvas("c56","c56",600,400);
2668 gStyle->SetOptStat(kFALSE);
2669 auto h3box = new TH3F("h3box","Option BOX2 (default)",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2670 double x, y, z;
2671 for (Int_t i=0;i<10000;i++) {
2672 gRandom->Rannor(x, y);
2673 z = abs(sin(x)/x + cos(y)*y);
2674 h3box->Fill(x,y,z);
2675 }
2676 h3box->Draw("BOX2 Z");
2677}
2678End_Macro
2679
2680The following example shows a 3D histogram plotted with the option `BOX3`.
2681
2682Begin_Macro(source)
2683{
2684 auto c46 = new TCanvas("c46","c46",600,400);
2685 c46->SetFillColor(38);
2686 gStyle->SetOptStat(kFALSE);
2687 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2688 double x, y, z;
2689 for (Int_t i=0;i<10000;i++) {
2690 gRandom->Rannor(x, y);
2691 z = x*x + y*y;
2692 h3box->Fill(x,y,z);
2693 }
2694 h3box->Draw("BOX3");
2695}
2696End_Macro
2697
2698For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2699to the absolute value of the bin content. The bins with a negative content are
2700drawn with a X on each face of the box as shown in the following example:
2701
2702Begin_Macro(source)
2703{
2704 auto c = new TCanvas("c","c",600,400);
2705 gStyle->SetOptStat(kFALSE);
2706 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2707 h3box->Fill(0., 2., 2., 10.);
2708 h3box->Fill(2., 2., 2., 5.);
2709 h3box->Fill(2., 2., .5, 2.);
2710 h3box->Fill(2., 2., 3., -1.);
2711 h3box->Fill(3., 2., 2., -10.);
2712 h3box->SetFillColor(8);
2713 h3box->Draw("box1");
2714}
2715End_Macro
2716
2717The following example shows a 3D histogram plotted with the option `ISO`.
2718
2719Begin_Macro(source)
2720{
2721 auto c26 = new TCanvas("c26","c26",600,400);
2722 gStyle->SetOptStat(kFALSE);
2723 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2724 double x, y, z;
2725 for (Int_t i=0;i<10000;i++) {
2726 gRandom->Rannor(x, y);
2727 z = x*x + y*y;
2728 h3iso->Fill(x,y,z);
2729 }
2730 h3iso->SetFillColor(kCyan);
2731 h3iso->Draw("ISO");
2732}
2733End_Macro
2734
2735
2736\anchor HP26
2737### Drawing option for histograms' stacks
2738
2739
2740Stacks of histograms are managed with the `THStack`. A `THStack`
2741is a collection of `TH1` (or derived) objects. For painting only the
2742`THStack` containing `TH1` only or
2743`THStack` containing `TH2` only will be considered.
2744
2745By default, histograms are shown stacked:
2746
27471. The first histogram is paint.
27482. The sum of the first and second, etc...
2749
2750If the option `NOSTACK` is specified, the histograms are all paint in
2751the same pad as if the option `SAME` had been specified. This allows to
2752compute X and Y scales common to all the histograms, like
2753`TMultiGraph` does for graphs.
2754
2755If the option `PADS` is specified, the current pad/canvas is subdivided into
2756a number of pads equal to the number of histograms and each histogram is paint
2757into a separate pad. With `PADSn`, the current pad/canvas is subdivided into
2758`n` columns, automatically calculating the number of rows.
2759
2760The following example shows various types of stacks (hist023_THStack_simple.C).
2761
2762Begin_Macro(source)
2763../../../tutorials/hist/hist023_THStack_simple.C
2764End_Macro
2765
2766The option `nostackb` allows to draw the histograms next to each
2767other as bar charts:
2768
2769Begin_Macro(source)
2770{
2771 auto cst0 = new TCanvas("cst0","cst0",600,400);
2772 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2773
2774 auto h1 = new TH1F("h1","h1",10,-4,4);
2775 h1->FillRandom("gaus",20000);
2776 h1->SetFillColor(kRed);
2777 hs->Add(h1);
2778
2779 auto h2 = new TH1F("h2","h2",10,-4,4);
2780 h2->FillRandom("gaus",15000);
2781 h2->SetFillColor(kBlue);
2782 hs->Add(h2);
2783
2784 auto h3 = new TH1F("h3","h3",10,-4,4);
2785 h3->FillRandom("gaus",10000);
2786 h3->SetFillColor(kGreen);
2787 hs->Add(h3);
2788
2789 hs->Draw("nostackb");
2790 hs->GetXaxis()->SetNdivisions(-10);
2791 cst0->SetGridx();
2792}
2793End_Macro
2794
2795If at least one of the histograms in the stack has errors, the whole stack is
2796visualized by default with error bars. To visualize it without errors the
2797option `HIST` should be used.
2798
2799Begin_Macro(source)
2800{
2801 auto cst1 = new TCanvas("cst1","cst1",700,400);
2802 cst1->Divide(2,1);
2803
2804 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2805 hst11->Sumw2();
2806 hst11->FillRandom("gaus", 1000);
2807 hst11->SetFillColor(kViolet);
2808 hst11->SetLineColor(kViolet);
2809
2810 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2811 hst12->FillRandom("gaus", 500);
2812 hst12->SetFillColor(kBlue);
2813 hst12->SetLineColor(kBlue);
2814
2815 THStack st1("st1", "st1");
2816 st1.Add(hst11);
2817 st1.Add(hst12);
2818
2819 cst1->cd(1); st1.Draw();
2820 cst1->cd(2); st1.Draw("hist");
2821}
2822End_Macro
2823
2824\anchor HP27
2825### Drawing of 3D implicit functions
2826
2827
28283D implicit functions (`TF3`) can be drawn as iso-surfaces.
2829The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2830In the following example the options "FB" and "BB" suppress the
2831"Front Box" and "Back Box" around the plot.
2832
2833Begin_Macro(source)
2834{
2835 auto c2 = new TCanvas("c2","c2",600,400);
2836 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2837 f3->SetClippingBoxOn(0,0,0);
2838 f3->SetFillColor(30);
2839 f3->SetLineColor(15);
2840 f3->Draw("FBBB");
2841}
2842End_Macro
2843
2844
2845\anchor HP28
2846### Associated functions drawing
2847
2848
2849An associated function is created by `TH1::Fit`. More than on fitted
2850function can be associated with one histogram (see `TH1::Fit`).
2851
2852A `TF1` object `f1` can be added to the list of associated
2853functions of an histogram `h` without calling `TH1::Fit`
2854simply doing:
2855
2856 h->GetListOfFunctions()->Add(f1);
2857
2858or
2859
2860 h->GetListOfFunctions()->Add(f1,someoption);
2861
2862To retrieve a function by name from this list, do:
2863
2864 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2865
2866or
2867
2868 TF1 *f1 = h->GetFunction(name);
2869
2870Associated functions are automatically painted when an histogram is drawn.
2871To avoid the painting of the associated functions the option `HIST`
2872should be added to the list of the options used to paint the histogram.
2873
2874
2875\anchor HP29
2876### Drawing using OpenGL
2877
2878
2879The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2880graphics library. The plotting options start with `GL` keyword.
2881In addition, in order to inform canvases that OpenGL should be used to render
28823D representations, the following option should be set:
2883
2884 gStyle->SetCanvasPreferGL(true);
2885
2886
2887\anchor HP29a
2888#### General information: plot types and supported options
2889
2890The following types of plots are provided:
2891
2892For lego plots the supported options are:
2893
2894| Option | Description |
2895|----------|-------------------------------------------------------------------|
2896| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2897| "GLLEGO2"| Bins with color levels.|
2898| "GLLEGO3"| Cylindrical bars.|
2899
2900
2901
2902Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2903In polar only Z axis can be logarithmic, in cylindrical only Y.
2904
2905For surface plots (`TF2` and `TH2`) the supported options are:
2906
2907| Option | Description |
2908|-----------|------------------------------------------------------------------|
2909| "GLSURF" | Draw a surface.|
2910| "GLSURF1" | Surface with color levels|
2911| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2912| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2913| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2914
2915
2916
2917The surface painting in cartesian coordinates supports logarithmic scales along
2918X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2919in cylindrical coordinates only the Y axis.
2920
2921Additional options to SURF and LEGO - Coordinate systems:
2922
2923| Option | Description |
2924|----------|-------------------------------------------------------------------|
2925| " " | Default, cartesian coordinates system.|
2926| "POL" | Polar coordinates system.|
2927| "CYL" | Cylindrical coordinates system.|
2928| "SPH" | Spherical coordinates system.|
2929
2930
2931
2932\anchor HP290
2933#### TH3 as color boxes
2934
2935The supported option is:
2936
2937| Option | Description |
2938|----------|-------------------------------------------------------------------|
2939| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See glvox1.C .|
2940
2941
2942
2943\anchor HP29b
2944#### TH3 as boxes (spheres)
2945
2946The supported options are:
2947
2948| Option | Description |
2949|----------|-------------------------------------------------------------------|
2950| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2951| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2952
2953
2954
2955\anchor HP29c
2956#### TH3 as iso-surface(s)
2957
2958The supported option is:
2959
2960| Option | Description |
2961|----------|-------------------------------------------------------------------|
2962| "GLISO" | TH3 is drawn using iso-surfaces.|
2963
2964
2965
2966\anchor HP29d
2967#### TF3 (implicit function)
2968
2969The supported option is:
2970
2971| Option | Description |
2972|----------|-------------------------------------------------------------------|
2973| "GL" | Draw a TF3.|
2974
2975
2976
2977\anchor HP29e
2978#### Parametric surfaces
2979
2980glparametric.C shows how to create parametric equations and visualize the surface.
2981
2982\anchor HP29f
2983#### Interaction with the plots
2984
2985All the interactions are implemented via standard methods
2986`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2987interactions with the OpenGL plots are possible only when the mouse cursor is
2988in the plot's area (the plot's area is the part of a the pad occupied by
2989gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2990pad interaction is performed.
2991
2992\anchor HP29g
2993#### Selectable parts
2994
2995Different parts of the plot can be selected:
2996
2997- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2998 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2999 if the dynamic slicing is not supported.
3000- The plot itself:
3001 On surfaces, the selected surface is outlined in red. (TF3 and
3002 ISO are not outlined). On lego plots, the selected bin is
3003 highlighted. The bin number and content are displayed in pad's
3004 status bar. In box plots, the box or sphere is highlighted and
3005 the bin info is displayed in pad's status bar.
3006
3007
3008\anchor HP29h
3009#### Rotation and zooming
3010
3011
3012- Rotation:
3013 When the plot is selected, it can be rotated by pressing and
3014 holding the left mouse button and move the cursor.
3015- Zoom/Unzoom:
3016 Mouse wheel or 'j', 'J', 'k', 'K' keys.
3017
3018
3019\anchor HP29i
3020#### Panning
3021
3022The selected plot can be moved in a pad's area by pressing and
3023holding the left mouse button and the shift key.
3024
3025\anchor HP29j
3026#### Box cut
3027
3028Surface, iso, box, TF3 and parametric painters support box cut by
3029pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3030area. That will display a transparent box, cutting away part of the
3031surface (or boxes) in order to show internal part of plot. This box
3032can be moved inside the plot's area (the full size of the box is
3033equal to the plot's surrounding box) by selecting one of the box
3034cut axes and pressing the left mouse button to move it.
3035
3036\anchor HP29k
3037#### Plot specific interactions (dynamic slicing etc.)
3038
3039Currently, all gl-plots support some form of slicing. When back plane
3040is selected (and if it's highlighted in green) you can press and hold
3041left mouse button and shift key and move this back plane inside
3042plot's area, creating the slice. During this "slicing" plot becomes
3043semi-transparent. To remove all slices (and projected curves for
3044surfaces) double click with left mouse button in a plot's area.
3045
3046\anchor HP29l
3047#### Surface with option "GLSURF"
3048
3049The surface profile is displayed on the slicing plane.
3050The profile projection is drawn on the back plane
3051by pressing `'p'` or `'P'` key.
3052
3053\anchor HP29m
3054#### TF3
3055
3056The contour plot is drawn on the slicing plane. For TF3 the color
3057scheme can be changed by pressing 's' or 'S'.
3058
3059\anchor HP29n
3060#### Box
3061
3062The contour plot corresponding to slice plane position is drawn in real time.
3063
3064\anchor HP29o
3065#### Iso
3066
3067Slicing is similar to "GLBOX" option.
3068
3069\anchor HP29p
3070#### Parametric plot
3071
3072No slicing. Additional keys: 's' or 'S' to change color scheme -
3073about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3074increase number of polygons ('l' for "level" of details), 'w' or 'W'
3075to show outlines ('w' for "wireframe").
3076
3077\anchor HP30
3078#### Highlight mode for histogram
3079
3080\since **ROOT version 6.15/01**
3081
3082\image html hlHisto3_top.gif "Highlight mode"
3083
3084Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3085highlight mode is on, mouse movement over the bin will be represented
3086graphically. Bin will be highlighted as "bin box" (presented by box
3087object). Moreover, any highlight (change of bin) emits signal
3088`TCanvas::Highlighted()` which allows the user to react and call their own
3089function. For a better understanding see also the tutorial `hist043` to `hist046`
3090located in `$ROOTSYS/tutorials/hist/`.
3091
3092Highlight mode is switched on/off by `TH1::SetHighlight()` function
3093or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3094whether the highlight mode enabled or disabled, default it is disabled.
3095
3096~~~ {.cpp}
3097 root [0] .x $ROOTSYS/tutorials/hsimple.C
3098 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3099 root [2] hpx->IsHighlight()
3100 (bool) true
3101~~~
3102
3103\image html hlsimple_nofun.gif "Highlight mode for histogram"
3104
3105\anchor HP30a
3106#### Highlight mode and user function
3107
3108The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3109emitted if there is a highlight bin and call user function via signal
3110and slot communication mechanism. `TCanvas::Highlighted()` is similar
3111`TCanvas::Picked()`
3112
3113- when selected object (histogram as a whole) is different from previous
3114then emit `Picked()` signal
3115- when selected (highlighted) bin from histogram is different from previous
3116then emit `Highlighted()` signal
3117
3118Any user function (or functions) has to be defined
3119`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3120In example (see below) has name `PrintInfo()`. All parameters of user
3121function are taken from
3122
3123 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3124
3125- `pad` is pointer to pad with highlighted histogram
3126- `obj` is pointer to highlighted histogram
3127- `x` is highlighted x bin for 1D histogram
3128- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3129
3130Example how to create a connection from any `TCanvas` object to a user
3131`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3132
3133 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3134 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3135
3136or use non-static "simplified" function
3137`TCanvas::HighlightConnect(const char *slot)`
3138
3139 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3140
3141NOTE the signal and slot string must have a form
3142"(TVirtualPad*,TObject*,Int_t,Int_t)"
3143
3144 root [0] .x $ROOTSYS/tutorials/hsimple.C
3145 root [1] hpx->SetHighlight(kTRUE)
3146 root [2] .x hlprint.C
3147
3148file `hlprint.C`
3149~~~ {.cpp}
3150void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3151{
3152 auto h = (TH1F *)obj;
3153 if (!h->IsHighlight()) // after highlight disabled
3154 h->SetTitle("highlight disable");
3155 else
3156 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3157 h->GetBinCenter(x), h->GetBinContent(x)));
3158 pad->Update();
3159}
3160
3161void hlprint()
3162{
3163 if (!gPad) return;
3164 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3165}
3166~~~
3167
3168\image html hlsimple.gif "Highlight mode and simple user function"
3169
3170For more complex demo please see for example tree200_temperature.C file.
3171
3172*/
3173
3175
3178
3179const Int_t kNMAX = 2000;
3180
3181const Int_t kMAXCONTOUR = 104;
3183
3184static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3185
3207
3208
3209////////////////////////////////////////////////////////////////////////////////
3210/// Default constructor.
3211
3213{
3214 fH = nullptr;
3215 fXaxis = nullptr;
3216 fYaxis = nullptr;
3217 fZaxis = nullptr;
3218 fFunctions = nullptr;
3219 fNcuts = 0;
3220 fStack = nullptr;
3221 fShowProjection = 0;
3222 fShowProjection2 = 0;
3223 fShowOption = "";
3224 for (int i=0; i<kMaxCuts; i++) {
3225 fCuts[i] = nullptr;
3226 fCutsOpt[i] = 0;
3227 }
3228 fXHighlightBin = -1;
3229 fYHighlightBin = -1;
3230 fCurrentF3 = nullptr;
3231
3232 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3233 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3234 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3235 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3236 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3237 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3238 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3239 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3240 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3241 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3242 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3243 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3244 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3245 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3246 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3247 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3248 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3249 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3250 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3251 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3252 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3253}
3254
3255////////////////////////////////////////////////////////////////////////////////
3256/// destructor.
3257
3261
3262////////////////////////////////////////////////////////////////////////////////
3263/// Compute the distance from the point px,py to a line.
3264///
3265/// Compute the closest distance of approach from point px,py to elements of
3266/// an histogram. The distance is computed in pixels units.
3267///
3268/// Algorithm: Currently, this simple model computes the distance from the mouse
3269/// to the histogram contour only.
3270
3272{
3273
3274 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3275
3276 const Int_t big = 9999;
3277 const Int_t kMaxDiff = 7;
3278
3279 if (fPie)
3280 return fPie->DistancetoPrimitive(px, py);
3281
3282 Double_t x = gPad->AbsPixeltoX(px);
3283 Double_t x1 = gPad->AbsPixeltoX(px+1);
3284
3285 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3286 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3287 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3288 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3289 Int_t curdist = big;
3291 Bool_t dsame;
3292 TObject *PadPointer = gPad->GetPadPointer();
3293 if (!PadPointer) return 0;
3294 TString doption = PadPointer->GetDrawOption();
3295 Double_t factor = 1;
3296 if (fH->GetNormFactor() != 0) {
3297 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3298 }
3299 // return if point is not in the histogram area
3300
3301 // If a 3D view exists, check distance to axis
3302 TView *view = gPad->GetView();
3303 Int_t d1,d2,d3;
3304 if (view && Hoption.Contour != 14) {
3305 Double_t ratio;
3306 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3307 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3308 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3309 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3310 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3311 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3312 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3313 goto FUNCTIONS;
3314 }
3315 // check if point is close to an axis
3316 doption.ToLower();
3317 dsame = kFALSE;
3318 if (doption.Contains("same")) dsame = kTRUE;
3319
3321 if (doption.Contains("y+")) {
3323 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3324 if (!dsame) {
3325 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3326 else gPad->SetSelected(fXaxis);
3327 return 0;
3328 }
3329 }
3330 } else {
3332 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3333 if (!dsame) {
3334 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3335 else gPad->SetSelected(fXaxis);
3336 return 0;
3337 }
3338 }
3339 }
3340
3342 if (doption.Contains("x+")) {
3344 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3345 if (!dsame) {
3346 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3347 else gPad->SetSelected(fYaxis);
3348 return 0;
3349 }
3350 }
3351 } else {
3353 if (yxaxis < puymin) yxaxis = puymin;
3355 if (!dsame) {
3356 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3357 else gPad->SetSelected(fYaxis);
3358 return 0;
3359 }
3360 }
3361 }
3362
3363 if (fH->IsHighlight()) { // only if highlight is enable
3364 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3365 HighlightBin(px, py);
3366 }
3367
3368 // if object is 2D or 3D return this object
3369 if (fH->GetDimension() == 2) {
3370 if (fH->InheritsFrom(TH2Poly::Class())) {
3371 TH2Poly *th2 = (TH2Poly*)fH;
3373 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3374 Double_t pxu = gPad->AbsPixeltoX(px);
3375 Double_t pyu = gPad->AbsPixeltoY(py);
3376 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3377 curdist = big;
3378 goto FUNCTIONS;
3379 } else {
3380 Int_t bin = th2->FindBin(pxu, pyu);
3381 if (bin>0) curdist = 1;
3382 else curdist = big;
3383 goto FUNCTIONS;
3384 }
3385 }
3386 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3387 if ( px > puxmin + delta2
3388 && px < puxmax - delta2
3389 && py > puymax + delta2
3390 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3391 }
3392
3393 // point is inside histogram area. Find channel number
3394 if (gPad->IsVertical()) {
3395 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3396 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3397 Double_t binval = factor*fH->GetBinContent(bin);
3398 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3399 if (binval == 0 && pybin < puymin) pybin = 10000;
3400 // special case if more than one bin for the pixel
3401 if (binsup-bin>1) {
3405 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3409 }
3410 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3411 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3413 }
3414 if (bin != binsup) { // Mouse on bin border
3416 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3417 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3418 }
3419 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3420 } else {
3421 Double_t y = gPad->AbsPixeltoY(py);
3422 Double_t y1 = gPad->AbsPixeltoY(py+1);
3423 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3424 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3425 Double_t binval = factor*fH->GetBinContent(bin);
3426 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3427 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3428 // special case if more than one bin for the pixel
3429 if (binsup-bin>1) {
3433 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3437 }
3438 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3439 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3441 }
3442 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3443 }
3444 // Loop on the list of associated functions and user objects
3445FUNCTIONS:
3446 TObject *f;
3447 TIter next(fFunctions);
3448 while ((f = (TObject*) next())) {
3449 Int_t dist;
3450 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3451 else dist = f->DistancetoPrimitive(px,py);
3452 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3453 }
3454 return curdist;
3455}
3456
3457////////////////////////////////////////////////////////////////////////////////
3458/// Display a panel with all histogram drawing options.
3459
3461{
3462
3463 gCurrentHist = fH;
3464 if (!gPad) {
3465 Error("DrawPanel", "need to draw histogram first");
3466 return;
3467 }
3469 editor->Show();
3470 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3471 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3472}
3473
3474////////////////////////////////////////////////////////////////////////////////
3475/// Execute the actions corresponding to `event`.
3476///
3477/// This function is called when a histogram is clicked with the locator at
3478/// the pixel position px,py.
3479
3481{
3482
3483 if (!gPad) return;
3484
3485 static Int_t bin, px1, py1, px2, py2, pyold;
3486 static std::unique_ptr<TBox> zoombox;
3488
3489 Int_t bin1, bin2;
3490 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3491 Bool_t opaque = gPad->OpaqueMoving();
3492
3493 if (!gPad->IsEditable()) return;
3494
3495 if (fPie) {
3496 fPie->ExecuteEvent(event, px, py);
3497 return;
3498 }
3499 // come here if we have a lego/surface in the pad
3500 TView *view = gPad->GetView();
3501
3502 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3503 view->ExecuteRotateView(event, px, py);
3504 return;
3505 }
3506
3507 TAxis *xaxis = fH->GetXaxis();
3508 TAxis *yaxis = fH->GetYaxis();
3509 Int_t dimension = fH->GetDimension();
3510
3511 // In case of option SAME the axis must be the ones of the first drawn histogram
3512 TString IsSame = fH->GetDrawOption();
3513 IsSame.ToLower();
3514 if (IsSame.Index("same")>=0) {
3515 TH1 *h1;
3516 TIter next(gPad->GetListOfPrimitives());
3517 while ((h1 = (TH1 *)next())) {
3518 if (!h1->InheritsFrom(TH1::Class())) continue;
3519 xaxis = h1->GetXaxis();
3520 yaxis = h1->GetYaxis();
3521 break;
3522 }
3523 }
3524
3525 Double_t factor = 1;
3526 if (fH->GetNormFactor() != 0) {
3527 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3528 }
3529
3530 switch (event) {
3531
3532 case kButton1Down:
3533
3534 if (!opaque) gVirtualX->SetLineColor(-1);
3535 fH->TAttLine::Modify();
3536
3537 if (opaque && dimension ==2) {
3538 zbx1 = gPad->AbsPixeltoX(px);
3539 zbx2 = gPad->AbsPixeltoX(px);
3540 zby1 = gPad->AbsPixeltoY(py);
3541 zby2 = gPad->AbsPixeltoY(py);
3542 px1 = px;
3543 py1 = py;
3544 if (gPad->GetLogx()) {
3545 zbx1 = TMath::Power(10,zbx1);
3546 zbx2 = TMath::Power(10,zbx2);
3547 }
3548 if (gPad->GetLogy()) {
3549 zby1 = TMath::Power(10,zby1);
3550 zby2 = TMath::Power(10,zby2);
3551 }
3552 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3553 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3554 Int_t ci = TColor::GetColor("#7d7dff");
3555 TColor *zoomcolor = gROOT->GetColor(ci);
3556 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3557 else zoomcolor->SetAlpha(0.5);
3558 zoombox->SetFillColor(ci);
3559 zoombox->Draw();
3560 gPad->Modified();
3561 gPad->Update();
3562 }
3563 // No break !!!
3564
3565 case kMouseMotion:
3566
3567 if (fShowProjection) {ShowProjection3(px,py); break;}
3568
3569 gPad->SetCursor(kPointer);
3570 if (dimension ==1) {
3571 if (Hoption.Bar) {
3572 baroffset = fH->GetBarOffset();
3573 barwidth = fH->GetBarWidth();
3574 } else {
3575 baroffset = 0;
3576 barwidth = 1;
3577 }
3578 x = gPad->AbsPixeltoX(px);
3579 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3580 binwidth = fXaxis->GetBinWidth(bin);
3581 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3582 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3583 ylow = gPad->GetUymin();
3584 px1 = gPad->XtoAbsPixel(xlow);
3585 px2 = gPad->XtoAbsPixel(xup);
3586 py1 = gPad->YtoAbsPixel(ylow);
3587 py2 = py;
3588 pyold = py;
3589 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3590 }
3591
3592 break;
3593
3594 case kButton1Motion:
3595
3596 if (dimension ==1) {
3597 if (gROOT->GetEditHistograms()) {
3598 if (!opaque) {
3599 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3600 py2 += py - pyold;
3601 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3602 pyold = py;
3603 } else {
3604 py2 += py - pyold;
3605 pyold = py;
3606 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3607 fH->SetBinContent(bin,binval);
3608 gPad->Modified(kTRUE);
3609 }
3610 }
3611 }
3612
3613 if (opaque && dimension ==2) {
3614 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3615 zbx2 = gPad->AbsPixeltoX(px);
3616 zby2 = gPad->AbsPixeltoY(py);
3617 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3618 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3619 if (zoombox) {
3620 zoombox->SetX2(zbx2);
3621 zoombox->SetY2(zby2);
3622 }
3623 gPad->Modified();
3624 gPad->Update();
3625 }
3626 }
3627
3628 break;
3629
3630 case kWheelUp:
3631
3632 if (dimension ==2) {
3633 bin1 = xaxis->GetFirst()+1;
3634 bin2 = xaxis->GetLast()-1;
3635 bin1 = TMath::Max(bin1, 1);
3636 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3637 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3638 bin1 = yaxis->GetFirst()+1;
3639 bin2 = yaxis->GetLast()-1;
3640 bin1 = TMath::Max(bin1, 1);
3641 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3642 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3643 }
3644 gPad->Modified();
3645 gPad->Update();
3646
3647 break;
3648
3649 case kWheelDown:
3650
3651 if (dimension == 2) {
3652 bin1 = xaxis->GetFirst()-1;
3653 bin2 = xaxis->GetLast()+1;
3654 bin1 = TMath::Max(bin1, 1);
3655 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3656 const bool resetXaxisRange = bin1 == 1 && xaxis->GetFirst() == 1 && bin2 == xaxis->GetNbins() && xaxis->GetLast() == xaxis->GetNbins();
3657 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3658 if (resetXaxisRange) xaxis->ResetBit(TAxis::kAxisRange);
3659 bin1 = yaxis->GetFirst()-1;
3660 bin2 = yaxis->GetLast()+1;
3661 bin1 = TMath::Max(bin1, 1);
3662 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3663 const bool resetYaxisRange = bin1 == 1 && yaxis->GetFirst() == 1 && bin2 == yaxis->GetNbins() && yaxis->GetLast() == yaxis->GetNbins();
3664 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3665 if (resetYaxisRange) yaxis->ResetBit(TAxis::kAxisRange);
3666 }
3667 gPad->Modified();
3668 gPad->Update();
3669
3670 break;
3671
3672 case kButton1Up:
3673 if (dimension ==1) {
3674 if (gROOT->GetEditHistograms()) {
3675 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3676 fH->SetBinContent(bin,binval);
3677 PaintInit(); // recalculate Hparam structure and recalculate range
3678 }
3679
3680 // might resize pad pixmap so should be called before any paint routine
3682 }
3683 if (opaque && dimension ==2) {
3684 if (zoombox) {
3685 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3686 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3687 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3688 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3689 x1 = TMath::Max(x1,xaxis->GetXmin());
3690 x2 = TMath::Min(x2,xaxis->GetXmax());
3691 y1 = TMath::Max(y1,yaxis->GetXmin());
3692 y2 = TMath::Min(y2,yaxis->GetXmax());
3693 if (x1<x2 && y1<y2) {
3694 xaxis->SetRangeUser(x1, x2);
3695 yaxis->SetRangeUser(y1, y2);
3696 }
3697 zoombox.reset();
3698 }
3699 }
3700 gPad->Modified(kTRUE);
3701 if (opaque) gVirtualX->SetLineColor(-1);
3702
3703 break;
3704
3705 case kButton1Locate:
3706
3707 ExecuteEvent(kButton1Down, px, py);
3708
3709 while (true) {
3710 px = py = 0;
3711 event = gVirtualX->RequestLocator(1, 1, px, py);
3712
3714
3715 if (event != -1) { // button is released
3716 ExecuteEvent(kButton1Up, px, py);
3717 return;
3718 }
3719 }
3720 }
3721}
3722
3723////////////////////////////////////////////////////////////////////////////////
3724/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3725
3727{
3728 // Check if fH contains a TGraphDelaunay2D
3730 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3731 // try with the old painter
3732 TGraphDelaunay *dtOld = nullptr;
3733 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3734
3735 if (!dt && !dtOld) return nullptr;
3736
3737 gCurrentHist = fH;
3738
3739 if (!fGraph2DPainter)
3740 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3741
3742 return fGraph2DPainter->GetContourList(contour);
3743}
3744
3745////////////////////////////////////////////////////////////////////////////////
3746/// Display the histogram info (bin number, contents, integral up to bin
3747/// corresponding to cursor position px,py.
3748
3750{
3751
3752 if (!gPad) return (char*)"";
3753
3754 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3755 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3756 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3758 drawOption.ToLower();
3761 if (fH->GetDimension() == 2) {
3762 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3763 uxmin=gPad->GetUxmin();
3764 uxmax=gPad->GetUxmax();
3767 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3768 uymin=gPad->GetUymin();
3769 uymax=gPad->GetUymax();
3772 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3773 }
3774 }
3776 if (gPad->IsVertical()) {
3777 binx = fXaxis->FindFixBin(x);
3778 if (drawOption.Index("same") >= 0) {
3779 TH1 *h1;
3780 TIter next(gPad->GetListOfPrimitives());
3781 while ((h1 = (TH1 *)next())) {
3782 if (!h1->InheritsFrom(TH1::Class())) continue;
3783 binmin = h1->GetXaxis()->GetFirst();
3784 break;
3785 }
3786 } else {
3787 binmin = fXaxis->GetFirst();
3788 }
3790 // special case if more than 1 bin in x per pixel
3791 if (binx1-binx>1 && fH->GetDimension() == 1) {
3794 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3798 binnear=ibin;
3799 }
3800 }
3801 binx = binnear;
3802 }
3803 } else {
3804 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3805 binx = fXaxis->FindFixBin(y);
3806 if (drawOption.Index("same") >= 0) {
3807 TH1 *h1;
3808 TIter next(gPad->GetListOfPrimitives());
3809 while ((h1 = (TH1 *)next())) {
3810 if (!h1->InheritsFrom(TH1::Class())) continue;
3811 binmin = h1->GetXaxis()->GetFirst();
3812 break;
3813 }
3814 } else {
3815 binmin = fXaxis->GetFirst();
3816 }
3818 // special case if more than 1 bin in x per pixel
3819 if (binx1-binx>1 && fH->GetDimension() == 1) {
3822 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3826 binnear=ibin;
3827 }
3828 }
3829 binx = binnear;
3830 }
3831 }
3832 if (fH->GetDimension() == 1) {
3834 TProfile *tp = (TProfile*)fH;
3835 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3837 (Int_t) tp->GetBinEntries(binx));
3838 }
3839 else {
3840 Double_t integ = 0;
3841 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3842 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3844 }
3845 } else if (fH->GetDimension() == 2) {
3846 if (fH->InheritsFrom(TH2Poly::Class())) {
3847 TH2Poly *th2 = (TH2Poly*)fH;
3848 biny = th2->FindBin(x,y);
3849 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3850 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3851 }
3852 else if (fH->InheritsFrom(TProfile2D::Class())) {
3854 biny = fYaxis->FindFixBin(y);
3855 Int_t bin = fH->GetBin(binx,biny);
3856 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3857 x, y, binx, biny, fH->GetBinContent(bin),
3858 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3859 } else {
3860 biny = fYaxis->FindFixBin(y);
3861 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3864 }
3865 } else {
3866 // 3d case: retrieving the x,y,z bin is not yet implemented
3867 // print just the x,y info
3868 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3869 }
3870
3871 return (char *)fObjectInfo.Data();
3872}
3873
3874////////////////////////////////////////////////////////////////////////////////
3875/// Set highlight (enable/disable) mode for fH
3876
3878{
3879 if (fH->IsHighlight()) return;
3880
3881 fXHighlightBin = -1;
3882 fYHighlightBin = -1;
3883 // delete previous highlight box
3884 if (gXHighlightBox) gXHighlightBox.reset();
3885 if (gYHighlightBox) gYHighlightBox.reset();
3886 // emit Highlighted() signal (user can check on disabled)
3887 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3888}
3889
3890////////////////////////////////////////////////////////////////////////////////
3891/// Check on highlight bin
3892
3894{
3895 // call from DistancetoPrimitive (only if highlight is enable)
3896
3897 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3898 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3901 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3902
3904 if (binx != fXHighlightBin) {
3906 changedBin = kTRUE;
3907 } else if (fH->GetDimension() == 1) return;
3908 if (biny != fYHighlightBin) {
3910 changedBin = kTRUE;
3911 }
3912 if (!changedBin) return;
3913
3914 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3915 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3916
3917 // paint highlight bin as box (recursive calls PaintHighlightBin)
3918 gPad->Modified(kTRUE);
3919 gPad->Update();
3920
3921 // emit Highlighted() signal
3922 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3923}
3924
3925////////////////////////////////////////////////////////////////////////////////
3926/// Paint highlight bin as TBox object
3927
3929{
3930 // call from PaintTitle
3931
3932 if (!fH->IsHighlight()) return;
3933
3934 Double_t uxmin = gPad->GetUxmin();
3935 Double_t uxmax = gPad->GetUxmax();
3936 Double_t uymin = gPad->GetUymin();
3937 Double_t uymax = gPad->GetUymax();
3938 if (gPad->GetLogx()) {
3939 uxmin = TMath::Power(10.0, uxmin);
3940 uxmax = TMath::Power(10.0, uxmax);
3941 }
3942 if (gPad->GetLogy()) {
3943 uymin = TMath::Power(10.0, uymin);
3944 uymax = TMath::Power(10.0, uymax);
3945 }
3946
3947 // testing specific possibility (after zoom, draw with "same", log, etc.)
3949 if (gPad->IsVertical()) {
3951 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3952 } else {
3954 if ((hcenter < uymin) || (hcenter > uymax)) return;
3955 }
3956 if (fH->GetDimension() == 2) {
3958 if ((hcenter < uymin) || (hcenter > uymax)) return;
3959 }
3960
3961 // paint X highlight bin (for 1D or 2D)
3963 if (gPad->IsVertical()) {
3966 hby1 = uymin;
3967 hby2 = uymax;
3968 } else {
3969 hbx1 = uxmin;
3970 hbx2 = uxmax;
3973 }
3974
3975 if (!gXHighlightBox) {
3976 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3977 gXHighlightBox->SetBit(kCannotPick);
3978 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3979 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3980 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3981 }
3982 gXHighlightBox->SetX1(hbx1);
3983 gXHighlightBox->SetX2(hbx2);
3984 gXHighlightBox->SetY1(hby1);
3985 gXHighlightBox->SetY2(hby2);
3986 gXHighlightBox->Paint();
3987
3988 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3989 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3990
3991 // paint Y highlight bin (only for 2D)
3992 if (fH->GetDimension() != 2) return;
3993 hbx1 = uxmin;
3994 hbx2 = uxmax;
3997
3998 if (!gYHighlightBox) {
3999 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
4000 gYHighlightBox->SetBit(kCannotPick);
4001 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
4002 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
4003 }
4004 gYHighlightBox->SetX1(hbx1);
4005 gYHighlightBox->SetX2(hbx2);
4006 gYHighlightBox->SetY1(hby1);
4007 gYHighlightBox->SetY2(hby2);
4008 gYHighlightBox->Paint();
4009}
4010
4011////////////////////////////////////////////////////////////////////////////////
4012/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
4013
4015{
4016
4017 for (Int_t i=0;i<fNcuts;i++) {
4020 if (fCutsOpt[i] > 0) {
4021 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4022 } else {
4023 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4024 }
4025 }
4026 return kTRUE;
4027}
4028
4029////////////////////////////////////////////////////////////////////////////////
4030/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4031
4033{
4034
4035 for (Int_t i=0;i<fNcuts;i++) {
4036 if (fCutsOpt[i] > 0) {
4037 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4038 } else {
4039 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4040 }
4041 }
4042 return kTRUE;
4043}
4044
4045////////////////////////////////////////////////////////////////////////////////
4046/// Decode string `choptin` and fill Hoption structure.
4047
4049{
4050
4051 char *l;
4052 char chopt[128];
4054 strlcpy(chopt,choptin,128);
4057
4065 Hoption.Candle = 0;
4066
4067 // special 2D options
4068 Hoption.List = 0;
4069 Hoption.Zscale = 0;
4070 Hoption.FrontBox = 1;
4071 Hoption.BackBox = 1;
4073
4074 Hoption.Zero = 0;
4075
4077
4078 //check for graphical cuts
4079 MakeCuts(chopt);
4080
4081 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4082 if (hdim > 1) Hoption.Color = 1; // Default drawing option for 2D and 3D histograms
4083 if (!nch) Hoption.Hist = 1;
4084 if (fFunctions->First()) Hoption.Func = 1;
4085 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4086
4087 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4088 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4089 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4090 if (l1 || l2 || l3) {
4091 Int_t i = gPad->NextPaletteColor();
4092 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4093 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4094 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4095 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4096 }
4097
4098 l = strstr(chopt,"MIN0");
4099 if (l) {
4100 Hoption.MinimumZero = 1;
4101 memcpy(l," ",4);
4102 }
4103
4104 l = strstr(chopt,"SPEC");
4105 if (l) {
4106 Hoption.Color = 0;
4107 memcpy(l," ",4);
4108 Int_t bs=0;
4109 l = strstr(chopt,"BF(");
4110 if (l) {
4111 if (sscanf(&l[3],"%d",&bs) > 0) {
4112 Int_t i=0;
4113 while (l[i]!=')') {
4114 l[i] = ' ';
4115 i++;
4116 }
4117 l[i] = ' ';
4118 }
4119 }
4120 Hoption.Spec = TMath::Max(1600,bs);
4121 return 1;
4122 }
4123
4124 l = strstr(chopt,"GL");
4125 if (l) {
4126 memcpy(l," ",2);
4127 }
4128 l = strstr(chopt,"X+");
4129 if (l) {
4130 Hoption.AxisPos = 10;
4131 memcpy(l," ",2);
4132 }
4133 l = strstr(chopt,"Y+");
4134 if (l) {
4135 Hoption.AxisPos += 1;
4136 memcpy(l," ",2);
4137 }
4138 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4139 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4140
4141 l = strstr(chopt,"SAMES");
4142 if (l) {
4143 if (nch == 5) Hoption.Hist = 1;
4144 Hoption.Same = 2;
4145 memcpy(l," ",5);
4146 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4147 }
4148 l = strstr(chopt,"SAME");
4149 if (l) {
4150 if (nch == 4) Hoption.Hist = 1;
4151 Hoption.Same = 1;
4152 memcpy(l," ",4);
4153 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4154 }
4155
4156 l = strstr(chopt,"SCAT");
4157 if (l) {
4158 Warning("MakeChopt","option SCAT is deprecated.");
4159 Hoption.Scat = 1;
4160 memcpy(l," ",4);
4161 Hoption.Color = 0;
4162 }
4163
4164 l = strstr(chopt,"PIE");
4165 if (l) {
4166 Hoption.Pie = 1;
4167 memcpy(l," ",3);
4168 }
4169
4170
4171 l = strstr(chopt,"CANDLE");
4172 if (l) {
4174 Hoption.Candle = candle.ParseOption(l);
4175 Hoption.Color = 0;
4176 }
4177
4178 l = strstr(chopt,"VIOLIN");
4179 if (l) {
4181 Hoption.Candle = candle.ParseOption(l);
4182 Hoption.Color = 0;
4183 }
4184
4185 l = strstr(chopt,"LEGO");
4186 if (l) {
4187 Hoption.Color = 0;
4188 Hoption.Lego = 1; memcpy(l," ",4);
4189 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4190 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4191 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4192 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4193 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4194 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4195 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4196 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4197 }
4198
4199 l = strstr(chopt,"SURF");
4200 if (l) {
4201 Hoption.Color = 0;
4202 Hoption.Surf = 1; memcpy(l," ",4);
4203 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4204 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4205 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4206 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4207 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4208 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4209 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4210 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4211 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4212 }
4213
4214 l = strstr(chopt,"TF3");
4215 if (l) {
4216 memcpy(l," ",3);
4217 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4218 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4219 }
4220
4221 l = strstr(chopt,"ISO");
4222 if (l) {
4223 memcpy(l," ",3);
4224 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4225 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4226 Hoption.Color = 0;
4227 }
4228
4229 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4230
4231 l = strstr(chopt,"CONT");
4232 if (l) {
4233 memcpy(l," ",4);
4234 if (hdim>1) {
4235 Hoption.Color = 0;
4236 Hoption.Contour = 1;
4237 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4238 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4239 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4240 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4241 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4242 } else {
4243 Hoption.Hist = 1;
4244 }
4245 }
4246 l = strstr(chopt,"HBAR");
4247 if (l) {
4248 Hoption.Hist = 0;
4249 Hoption.Bar = 20; memcpy(l," ",4);
4250 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4251 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4252 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4253 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4254 }
4255 l = strstr(chopt,"BAR");
4256 if (l) {
4257 Hoption.Hist = 0;
4258 Hoption.Bar = 10; memcpy(l," ",3);
4259 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4260 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4261 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4262 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4263 }
4264
4265 l = strstr(chopt,"ARR" );
4266 if (l) {
4267 memcpy(l," ", 3);
4268 if (hdim>1) {
4269 Hoption.Arrow = 1;
4270 Hoption.Color = 0;
4271 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4272 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4273 } else {
4274 Hoption.Hist = 1;
4275 }
4276 }
4277 l = strstr(chopt,"BOX" );
4278 if (l) {
4279 memcpy(l," ", 3);
4280 if (hdim>1) {
4281 Hoption.Color = 0;
4282 Hoption.Box = 1;
4283 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4284 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4285 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4286 } else {
4287 Hoption.Hist = 1;
4288 }
4289 }
4290 l = strstr(chopt,"TEXT");
4291 if (l) {
4292 Int_t angle;
4293 if (sscanf(&l[4],"%d",&angle) > 0) {
4294 if (angle < 0) angle=0;
4295 if (angle > 90) angle=90;
4296 Hoption.Text = 1000+angle;
4297 } else {
4298 Hoption.Text = 1;
4299 }
4300 memcpy(l," ", 4);
4301 l = strstr(chopt,"N");
4302 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text = 3000 + (Hoption.Text != 1 ? Hoption.Text : 0);
4303 Hoption.Color = 0;
4304 }
4305 l = strstr(chopt,"COLZ");
4306 if (l) {
4307 memcpy(l," ",4);
4308 if (hdim > 1) {
4310 Hoption.Color = 1;
4311 Hoption.Zscale = 1;
4312 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4313 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4314 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4315 } else {
4316 Hoption.Hist = 1;
4317 }
4318 }
4319 l = strstr(chopt,"COL" );
4320 if (l) {
4321 memcpy(l," ", 3);
4322 if (hdim > 1) {
4324 Hoption.Color = 1;
4325 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4326 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4327 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4328 } else {
4329 Hoption.Hist = 1;
4330 }
4331 }
4332 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4333 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4334 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4335 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4336 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4337 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4338 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4339 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4340 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4341
4342 l = strstr(chopt,"TRI");
4343 if (l) {
4344 if (!explicitColor) Hoption.Color = 0;
4345 Hoption.Tri = 1; memcpy(l," ",3);
4346 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4347 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4348 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4349 }
4350
4351 l = strstr(chopt,"AITOFF");
4352 if (l) {
4353 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4354 }
4355 l = strstr(chopt,"MERCATOR");
4356 if (l) {
4357 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4358 }
4359 l = strstr(chopt,"SINUSOIDAL");
4360 if (l) {
4361 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4362 }
4363 l = strstr(chopt,"PARABOLIC");
4364 if (l) {
4365 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4366 }
4367 l = strstr(chopt,"MOLLWEIDE");
4368 if (l) {
4369 Hoption.Proj = 5; memcpy(l," ",9); //Mollweide projection
4370 }
4371 if (Hoption.Proj > 0) {
4372 if (!explicitColor) Hoption.Color = 0;
4373 Hoption.Contour = 14;
4374 }
4375
4376 if (strstr(chopt,"A")) Hoption.Axis = -1;
4377 if (strstr(chopt,"B")) Hoption.Bar = 1;
4378 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4379 if (strstr(chopt,"F")) Hoption.Fill =1;
4380 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4381 if (strstr(chopt,"F2")) Hoption.Fill =2;
4382 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4383 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4384 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4385 if (strstr(chopt,"*")) Hoption.Star =1;
4386 if (strstr(chopt,"H")) Hoption.Hist =2;
4387 if (strstr(chopt,"P0")) Hoption.Mark =10;
4388
4389 if (fH->InheritsFrom(TH2Poly::Class())) {
4391 }
4392
4393 if (strstr(chopt,"E")) {
4394 if (hdim == 1) {
4395 Hoption.Error = 1;
4396 if (strstr(chopt,"E1")) Hoption.Error = 11;
4397 if (strstr(chopt,"E2")) Hoption.Error = 12;
4398 if (strstr(chopt,"E3")) Hoption.Error = 13;
4399 if (strstr(chopt,"E4")) Hoption.Error = 14;
4400 if (strstr(chopt,"E5")) Hoption.Error = 15;
4401 if (strstr(chopt,"E6")) Hoption.Error = 16;
4402 if (strstr(chopt,"E0")) Hoption.Error += 40;
4403 if (strstr(chopt,"X0")) {
4404 if (Hoption.Error == 1) Hoption.Error += 20;
4405 Hoption.Error += 10;
4406 }
4408 Hoption.Text += 2000;
4409 Hoption.Error = 0;
4410 }
4411 } else {
4412 if (Hoption.Error == 0) {
4413 Hoption.Error = 100;
4414 if (!explicitColor) Hoption.Color = 0;
4415 }
4416 if (Hoption.Text) {
4417 Hoption.Text += 2000;
4418 Hoption.Error = 0;
4419 }
4420 }
4421 }
4422
4423 if (Hoption.Surf == 15) {
4425 Hoption.Surf = 13;
4426 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4427 }
4428 }
4429
4430 // Copy options from current style
4431 Hoption.Logx = gPad->GetLogx();
4432 Hoption.Logy = gPad->GetLogy();
4433 Hoption.Logz = gPad->GetLogz();
4434
4435 // Check options incompatibilities
4436 if (Hoption.Bar == 1) Hoption.Hist = -1;
4437 return 1;
4438}
4439
4440////////////////////////////////////////////////////////////////////////////////
4441/// Decode string `choptin` and fill Graphical cuts structure.
4442
4444{
4445
4446 fNcuts = 0;
4447 char *left = (char*)strchr(choptin,'[');
4448 if (!left) return 0;
4449 char *right = (char*)strchr(choptin,']');
4450 if (!right) return 0;
4451 Int_t nch = right-left;
4452 if (nch < 2) return 0;
4453 char *cuts = left+1;
4454 *right = 0;
4455 char *comma, *minus;
4456 Int_t i;
4457 while (true) {
4458 comma = strchr(cuts,',');
4459 if (comma) *comma = 0;
4460 minus = strchr(cuts,'-');
4461 if (minus) cuts = minus+1;
4462 while (*cuts == ' ') cuts++;
4463 Int_t nc = strlen(cuts);
4464 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4465 TIter next(gROOT->GetListOfSpecials());
4466 TCutG *cut=nullptr;
4467 TObject *obj;
4468 while ((obj = next())) {
4469 if (!obj->InheritsFrom(TCutG::Class())) continue;
4470 if (strcmp(obj->GetName(),cuts)) continue;
4471 cut = (TCutG*)obj;
4472 break;
4473 }
4474 if (cut) {
4475 fCuts[fNcuts] = cut;
4476 fCutsOpt[fNcuts] = 1;
4477 if (minus) fCutsOpt[fNcuts] = -1;
4478 fNcuts++;
4479 }
4480 if (!comma) break;
4481 cuts = comma+1;
4482 }
4483 for (i=0;i<=nch;i++) left[i] = ' ';
4484 return fNcuts;
4485}
4486
4487////////////////////////////////////////////////////////////////////////////////
4488/// [Control routine to paint any kind of histograms](\ref HP00)
4489
4491{
4492
4493 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4494
4495 //For iOS: put the histogram on the top of stack of pickable objects.
4497
4498 gPad->SetVertical(kTRUE);
4499
4501 gCurrentHist = fH;
4502 TH1 *hsave = fH;
4504
4505 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4506
4507 // Paint using TSpectrum2Painter
4508 if (Hoption.Spec) {
4509 if (!TableInit()) return;
4510 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4511 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4512 (size_t)fH, option, Hoption.Spec).Data());
4513 return;
4514 }
4515
4516 // Deflate the labels in case of alphanumeric labels
4520
4521 if (Hoption.Pie) {
4522 if (fH->GetDimension() == 1) {
4523 if (!fPie)
4524 fPie = std::make_unique<TPie>(fH);
4525 fPie->Paint(option);
4526 } else {
4527 Error("Paint", "Option PIE is for 1D histograms only");
4528 }
4529 return;
4530 } else {
4531 fPie.reset();
4532 }
4533
4534 fXbuf.resize(kNMAX);
4535 fYbuf.resize(kNMAX);
4536 if (fH->GetDimension() > 2) {
4537 PaintH3(option);
4539 if (Hoption.Func) {
4544 Hoption = hoptsave;
4545 Hparam = hparsave;
4546 }
4548 fXbuf.clear();
4549 fYbuf.clear();
4550 return;
4551 }
4552 TView *view = gPad->GetView();
4553 if (view) {
4554 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4555 delete view;
4556 gPad->SetView(nullptr);
4557 }
4558 }
4559 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4560 // In case of 1D histogram, Z axis becomes Y axis.
4561 Int_t logysav=0, logzsav=0;
4562 if (fH->GetDimension() == 1) {
4565 Hoption.Logz = 0;
4566 if (Hoption.Logy) {
4567 Hoption.Logz = 1;
4568 Hoption.Logy = 0;
4569 }
4570 }
4572 if (Hoption.Func) {
4577 Hoption = hoptsave;
4578 Hparam = hparsave;
4579 }
4582 fXbuf.clear();
4583 fYbuf.clear();
4584 if (fH->GetDimension() == 1) {
4587 }
4588 return;
4589 }
4590
4591 if (Hoption.Bar >= 20) {
4593 fXbuf.clear();
4594 fYbuf.clear();
4595 return;
4596 }
4597
4598 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4599 // fill Hparam structure with histo parameters
4600 if (!PaintInit()) {
4601 fXbuf.clear();
4602 fYbuf.clear();
4603 return;
4604 }
4605
4606 // Picture surround (if new page) and page number (if requested).
4607 // Histogram surround (if not option "Same").
4608 PaintFrame();
4609
4610 // Paint histogram axis only
4611 Bool_t gridx = gPad->GetGridx();
4612 Bool_t gridy = gPad->GetGridy();
4613 if (Hoption.Axis > 0) {
4614 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4615 else {
4616 if (gridx) gPad->SetGridx(0);
4617 if (gridy) gPad->SetGridy(0);
4619 if (gridx) gPad->SetGridx(1);
4620 if (gridy) gPad->SetGridy(1);
4621 }
4622 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4623 goto paintstat;
4624 }
4625 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4626
4627 // test for options BAR or HBAR
4628 if (Hoption.Bar >= 10) {
4630 }
4631
4632 // do not draw histogram if error bars required
4633 if (!Hoption.Error) {
4634 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4635 }
4636
4637 // test for error bars or option E
4638 if (Hoption.Error) {
4640 if (Hoption.Hist == 2) PaintHist(option);
4641 }
4642
4644
4645 // test for associated function
4646 if (Hoption.Func) {
4651 Hoption = hoptsave;
4652 Hparam = hparsave;
4653 }
4654
4655 if (gridx) gPad->SetGridx(0);
4656 if (gridy) gPad->SetGridy(0);
4658 if (gridx) gPad->SetGridx(1);
4659 if (gridy) gPad->SetGridy(1);
4660
4661 PaintTitle(); // Draw histogram title
4662
4663 // Draw box with histogram statistics and/or fit parameters
4664paintstat:
4665 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4666 TIter next(fFunctions);
4667 TObject *obj = nullptr;
4668 while ((obj = next())) {
4669 if (obj->InheritsFrom(TF1::Class())) break;
4670 obj = nullptr;
4671 }
4672
4673 //Stat is painted twice (first, it will be in canvas' list of primitives),
4674 //second, it will be here, this is not required on iOS.
4675 //Condition is ALWAYS true on a platform different from iOS.
4676 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4677 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4678 }
4681 fXbuf.clear();
4682 fYbuf.clear();
4683}
4684
4685////////////////////////////////////////////////////////////////////////////////
4686/// [Control function to draw a table as an arrow plot](\ref HP12)
4687
4689{
4691 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4694 Double_t xrg = gPad->GetUxmin();
4695 Double_t yrg = gPad->GetUymin();
4696 Double_t xln = gPad->GetUxmax() - xrg;
4697 Double_t yln = gPad->GetUymax() - yrg;
4698 Double_t cx = (xln/Double_t(ncx))/2.;
4699 Double_t cy = (yln/Double_t(ncy))/2.;
4700 Double_t dn = 1.E-30;
4701
4702 auto arrow = new TArrow();
4703 arrow->SetAngle(30);
4704 arrow->SetFillStyle(1001);
4705 arrow->SetFillColor(fH->GetLineColor());
4706 arrow->SetLineColor(fH->GetLineColor());
4707 arrow->SetLineWidth(fH->GetLineWidth());
4708
4709 // Initialize the levels on the Z axis
4710 Int_t ncolors=0, ndivz=0;
4711 Double_t scale=0.;
4712 if (Hoption.Arrow>1) {
4713 ncolors = gStyle->GetNumberOfColors();
4714 Int_t ndiv = fH->GetContour();
4715 if (ndiv == 0 ) {
4716 ndiv = gStyle->GetNumberContours();
4717 fH->SetContour(ndiv);
4718 }
4719 ndivz = TMath::Abs(ndiv);
4720 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4722 }
4723
4724 for (Int_t id=1;id<=2;id++) {
4725 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4728 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4729 xk = fXaxis->GetBinLowEdge(i);
4730 xstep = fXaxis->GetBinWidth(i);
4731 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4732 if (i == Hparam.xfirst) {
4733 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4734 } else if (i == Hparam.xlast) {
4735 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4736 } else {
4737 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4738 }
4739 if (j == Hparam.yfirst) {
4740 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4741 } else if (j == Hparam.ylast) {
4742 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4743 } else {
4744 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4745 }
4746 if (id == 1) {
4749 } else if (id == 2) {
4750 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4751 dxn = cx*dx/dn;
4752 x1 = xc - dxn;
4753 x2 = xc + dxn;
4754 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4755 dyn = cy*dy/dn;
4756 y1 = yc - dyn;
4757 y2 = yc + dyn;
4758 if (Hoption.Arrow>1) {
4759 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4760 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4761 if (theColor > ncolors-1) theColor = ncolors-1;
4762 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4763 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4764 }
4765 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4766 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4767 } else {
4768 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4769 }
4770 }
4771 }
4772 }
4773 }
4774
4776}
4777
4778////////////////////////////////////////////////////////////////////////////////
4779/// Draw axis (2D case) of an histogram.
4780///
4781/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4782/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4783/// feature is used to make sure that the grid is drawn in the background and
4784/// the axis tick marks in the foreground of the pad.
4785
4787{
4788
4789 //On iOS, grid should not be pickable and can not be highlighted.
4790 //Condition is never true on a platform different from iOS.
4791 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4792 return;
4793
4794 if (Hoption.Axis == -1) return;
4795 if (Hoption.Same && Hoption.Axis <= 0) return;
4796
4797 // Repainting alphanumeric labels axis on a plot done with
4798 // the option HBAR (horizontal) needs some adjustments.
4799 TAxis *xaxis = nullptr;
4800 TAxis *yaxis = nullptr;
4801 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4802 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4803 TIter next(gPad->GetListOfPrimitives());
4804 TObject *obj;
4805 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4806 while ((obj = next())) {
4807 if (!obj->InheritsFrom(TH1::Class()) &&
4808 !obj->InheritsFrom(THStack::Class())) continue;
4809 TString opt = obj->GetDrawOption();
4810 opt.ToLower();
4811 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4812 if (strstr(opt,"hbar")) {
4813 gPad->SetVertical(kFALSE);
4814 xaxis = fXaxis;
4815 yaxis = fYaxis;
4816 if (!strcmp(xaxis->GetName(),"xaxis")) {
4817 fXaxis = yaxis;
4818 fYaxis = xaxis;
4819 }
4820 }
4821 break;
4822 }
4823 }
4824 }
4825
4826 static char chopt[10] = "";
4827 Double_t gridl = 0;
4828 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4829 Int_t useHparam = 0;
4833
4834 Double_t axmin = gPad->GetUxmin();
4835 Double_t axmax = gPad->GetUxmax();
4836 Double_t aymin = gPad->GetUymin();
4837 Double_t aymax = gPad->GetUymax();
4838 char *cw = nullptr;
4839 TGaxis axis;
4840
4841 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4842 // Hparam must be use for the axis limits.
4843 if (Hoption.Contour == 14) useHparam = 1;
4844 if (Hoption.Same) {
4845 TObject *obj;
4846 TIter next(gPad->GetListOfPrimitives());
4847 while ((obj=next())) {
4848 if (strstr(obj->GetDrawOption(),"cont4")) {
4849 useHparam = 1;
4850 break;
4851 }
4852 }
4853 }
4854
4855 // Paint X axis
4856
4857 //To make X-axis selectable on iOS device.
4858 if (gPad->PadInSelectionMode())
4859 gPad->PushSelectableObject(fXaxis);
4860
4861 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4862 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4864 if (ndivx > 1000) {
4865 nx2 = ndivx/100;
4866 nx1 = TMath::Max(1, ndivx%100);
4867 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4868 }
4869 axis.SetTextAngle(0);
4871
4872 chopt[0] = 0;
4873 strlcat(chopt, "SDH",10);
4874 if (ndivx < 0) strlcat(chopt, "N",10);
4875 if (gPad->GetGridx()) {
4876 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4877 strlcat(chopt, "W",10);
4878 }
4879
4880 // Define X-Axis limits
4881 if (Hoption.Logx) {
4882 strlcat(chopt, "G",10);
4883 ndiv = TMath::Abs(ndivx);
4884 if (useHparam) {
4887 } else {
4888 umin = TMath::Power(10,axmin);
4889 umax = TMath::Power(10,axmax);
4890 }
4891 } else {
4892 ndiv = TMath::Abs(ndivx);
4893 if (useHparam) {
4894 umin = Hparam.xmin;
4895 umax = Hparam.xmax;
4896 } else {
4897 umin = axmin;
4898 umax = axmax;
4899 }
4900 }
4901
4902 // Display axis as time
4903 if (fXaxis->GetTimeDisplay()) {
4904 strlcat(chopt,"t",10);
4905 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4907 }
4908 }
4909
4910 // The main X axis can be on the bottom or on the top of the pad
4912 if (xAxisPos == 1) {
4913 // Main X axis top
4914 xAxisYPos1 = aymax;
4915 xAxisYPos2 = aymin;
4916 } else {
4917 // Main X axis bottom
4918 xAxisYPos1 = aymin;
4919 xAxisYPos2 = aymax;
4920 }
4921
4922 // Paint the main X axis (always)
4923 uminsave = umin;
4924 umaxsave = umax;
4925 ndivsave = ndiv;
4926 axis.SetOption(chopt);
4927 if (xAxisPos) {
4928 strlcat(chopt, "-",10);
4929 gridl = -gridl;
4930 }
4931 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4932 axis.SetLabelSize(0.);
4933 axis.SetTitle("");
4934 }
4937 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4938
4939 // Paint additional X axis (if needed)
4940 // On iOS, this additional X axis is neither pickable, nor highlighted.
4941 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4942 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4943 if (xAxisPos) {
4944 cw=strstr(chopt,"-");
4945 *cw='z';
4946 } else {
4947 strlcat(chopt, "-",10);
4948 }
4949 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4950 if ((cw=strstr(chopt,"W"))) *cw='z';
4951 axis.SetTitle("");
4955 }
4956 }//End of "if pad in selection mode etc".
4957
4958 // Paint Y axis
4959 //On iOS, Y axis must pushed into the stack of selectable objects.
4960 if (gPad->PadInSelectionMode())
4961 gPad->PushSelectableObject(fYaxis);
4962
4963 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4964 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4967
4968 chopt[0] = 0;
4969 strlcat(chopt, "SDH",10);
4970 if (ndivy < 0) strlcat(chopt, "N",10);
4971 if (gPad->GetGridy()) {
4972 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4973 strlcat(chopt, "W",10);
4974 }
4975
4976 // Define Y-Axis limits
4977 if (Hoption.Logy) {
4978 strlcat(chopt, "G",10);
4979 ndiv = TMath::Abs(ndivy);
4980 if (useHparam) {
4983 } else {
4984 umin = TMath::Power(10,aymin);
4985 umax = TMath::Power(10,aymax);
4986 }
4987 } else {
4988 ndiv = TMath::Abs(ndivy);
4989 if (useHparam) {
4990 umin = Hparam.ymin;
4991 umax = Hparam.ymax;
4992 } else {
4993 umin = aymin;
4994 umax = aymax;
4995 }
4996 }
4997
4998 // Display axis as time
4999 if (fYaxis->GetTimeDisplay()) {
5000 strlcat(chopt,"t",10);
5001 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
5003 }
5004 }
5005
5006 // The main Y axis can be on the left or on the right of the pad
5008 if (yAxisPos == 1) {
5009 // Main Y axis left
5010 yAxisXPos1 = axmax;
5011 yAxisXPos2 = axmin;
5012 } else {
5013 // Main Y axis right
5014 yAxisXPos1 = axmin;
5015 yAxisXPos2 = axmax;
5016 }
5017
5018 // Paint the main Y axis (always)
5019 uminsave = umin;
5020 umaxsave = umax;
5021 ndivsave = ndiv;
5022 axis.SetOption(chopt);
5023 if (yAxisPos) {
5024 strlcat(chopt, "+L",10);
5025 gridl = -gridl;
5026 }
5027 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
5028 axis.SetLabelSize(0.);
5029 axis.SetTitle("");
5030 }
5033 umin, umax, ndiv, chopt, gridl, drawGridOnly);
5034
5035 // Paint the additional Y axis (if needed)
5036 // Additional checks for pad mode are required on iOS: this "second" axis is
5037 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5038 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5039 if (gPad->GetTicky() < 2) {
5040 strlcat(chopt, "U",10);
5042 } else {
5043 strlcat(chopt, "+L",10);
5044 }
5045 if ((cw=strstr(chopt,"W"))) *cw='z';
5046 axis.SetTitle("");
5050 }
5051 }//End of "if pad is in selection mode etc."
5052
5053 // Reset the axis if they have been inverted in case of option HBAR
5054 if (xaxis) {
5055 fXaxis = xaxis;
5056 fYaxis = yaxis;
5057 }
5058}
5059
5060////////////////////////////////////////////////////////////////////////////////
5061/// [Draw a bar-chart in a normal pad.](\ref HP10)
5062
5064{
5065
5066 Int_t bar = Hoption.Bar - 10;
5070 TBox box;
5072 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5074 box.SetFillColor(hcolor);
5075 box.SetFillStyle(hstyle);
5076 box.SetLineStyle(fH->GetLineStyle());
5077 box.SetLineColor(fH->GetLineColor());
5078 box.SetLineWidth(fH->GetLineWidth());
5079 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5080 y = fH->GetBinContent(bin);
5081 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5082 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5083 ymin = gPad->GetUymin();
5084 ymax = gPad->YtoPad(y);
5085 if (ymax < gPad->GetUymin()) continue;
5086 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5087 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5088 if (Hoption.MinimumZero && ymin < 0)
5089 ymin=TMath::Min(0.,gPad->GetUymax());
5090 w = (xmax-xmin)*width;
5091 xmin += offset*(xmax-xmin);
5092 xmax = xmin + w;
5093 if (bar < 1) {
5094 box.PaintBox(xmin,ymin,xmax,ymax);
5095 } else {
5096 umin = xmin + bar*(xmax-xmin)/10.;
5097 umax = xmax - bar*(xmax-xmin)/10.;
5098 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5099 box.PaintBox(xmin,ymin,umin,ymax);
5100 box.SetFillColor(hcolor);
5101 box.PaintBox(umin,ymin,umax,ymax);
5102 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5103 box.PaintBox(umax,ymin,xmax,ymax);
5104 }
5105 }
5106}
5107
5108////////////////////////////////////////////////////////////////////////////////
5109/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5110
5112{
5113
5114 gPad->SetVertical(kFALSE);
5115
5116 PaintInitH();
5117
5118 TAxis *xaxis = fXaxis;
5119 TAxis *yaxis = fYaxis;
5120 if (!strcmp(xaxis->GetName(),"xaxis")) {
5121 fXaxis = yaxis;
5122 fYaxis = xaxis;
5123 }
5124
5125 PaintFrame();
5127
5128 Int_t bar = Hoption.Bar - 20;
5132 TBox box;
5134 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5136 box.SetFillColor(hcolor);
5137 box.SetFillStyle(hstyle);
5138 box.SetLineStyle(fH->GetLineStyle());
5139 box.SetLineColor(fH->GetLineColor());
5140 box.SetLineWidth(fH->GetLineWidth());
5141 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5142 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5143 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5144 xmin = gPad->GetUxmin();
5145 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5146 if (xmax < gPad->GetUxmin()) continue;
5147 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5148 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5149 if (Hoption.MinimumZero && xmin < 0)
5150 xmin=TMath::Min(0.,gPad->GetUxmax());
5151 w = (ymax-ymin)*width;
5152 ymin += offset*(ymax-ymin);
5153 ymax = ymin + w;
5154 if (bar < 1) {
5155 box.PaintBox(xmin,ymin,xmax,ymax);
5156 } else {
5157 umin = ymin + bar*(ymax-ymin)/10.;
5158 umax = ymax - bar*(ymax-ymin)/10.;
5159 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5160 box.PaintBox(xmin,ymin,xmax,umin);
5161 box.SetFillColor(hcolor);
5162 box.PaintBox(xmin,umin,xmax,umax);
5163 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5164 box.PaintBox(xmin,umax,xmax,ymax);
5165 }
5166 }
5167
5168 PaintTitle();
5169
5170 // Draw box with histogram statistics and/or fit parameters
5171 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5172 TIter next(fFunctions);
5173 TObject *obj = nullptr;
5174 while ((obj = next())) {
5175 if (obj->InheritsFrom(TF1::Class())) break;
5176 obj = nullptr;
5177 }
5178 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5179 }
5180
5181 fXaxis = xaxis;
5182 fYaxis = yaxis;
5183}
5184
5185////////////////////////////////////////////////////////////////////////////////
5186/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5187
5189{
5190
5193 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5194 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5195 fH->TAttLine::Modify();
5196 fH->TAttFill::Modify();
5197
5198 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5199 Double_t ux1 = gPad->PixeltoX(1);
5200 Double_t ux0 = gPad->PixeltoX(0);
5201 Double_t uy1 = gPad->PixeltoY(1);
5202 Double_t uy0 = gPad->PixeltoY(0);
5203 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5204 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5205
5206 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5209 Double_t zminlin = zmin, zmaxlin = zmax;
5210
5211 // In case of option SAME, zmin and zmax values are taken from the
5212 // first plotted 2D histogram.
5213 if (Hoption.Same > 0 && Hoption.Same < 10) {
5214 TH2 *h2;
5215 TIter next(gPad->GetListOfPrimitives());
5216 while ((h2 = (TH2 *)next())) {
5217 if (!h2->InheritsFrom(TH2::Class())) continue;
5218 zmin = TMath::Max(h2->GetMinimum(), 0.);
5219 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5220 TMath::Abs(h2->GetMinimum()));
5221 zminlin = zmin;
5222 zmaxlin = zmax;
5223 if (Hoption.Logz) {
5224 if (zmin <= 0) {
5225 zmin = TMath::Log10(zmax*0.001);
5226 } else {
5227 zmin = TMath::Log10(zmin);
5228 }
5229 zmax = TMath::Log10(zmax);
5230 }
5231 break;
5232 }
5233 } else {
5234 if (Hoption.Logz) {
5235 if (zmin > 0) {
5236 zmin = TMath::Log10(zmin);
5237 zmax = TMath::Log10(zmax);
5238 } else {
5239 return;
5240 }
5241 }
5242 }
5243
5244 Double_t zratio, dz = zmax - zmin;
5246 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5248
5249 // Define the dark and light colors the "button style" boxes.
5250 Color_t color = fH->GetFillColor();
5251 Color_t light=0, dark=0;
5252 if (Hoption.Box == 11) {
5254 dark = TColor::GetColorDark(color);
5255 }
5256
5257 // Loop over all the bins and draw the boxes
5258 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5261 ycent = 0.5*ystep;
5262 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5263 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5264 xk = fXaxis->GetBinLowEdge(i);
5265 xstep = fXaxis->GetBinWidth(i);
5266 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5267 xcent = 0.5*xstep;
5268 z = Hparam.factor*fH->GetBinContent(bin);
5269 kZNeg = kFALSE;
5270
5271 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5272 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5273 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5274
5275 if (z < 0) {
5276 if (Hoption.Logz) continue;
5277 z = -z;
5278 kZNeg = kTRUE;
5279 }
5280 if (Hoption.Logz) {
5281 if (z != 0) z = TMath::Log10(z);
5282 else z = zmin;
5283 }
5284
5285 if (dz == 0) continue;
5286 zratio = TMath::Sqrt((z-zmin)/dz);
5287 if (zratio == 0) continue;
5288
5289 xup = xcent*zratio + xk + xcent;
5290 xlow = 2*(xk + xcent) - xup;
5291 if (xup-xlow < dxmin) xup = xlow+dxmin;
5292 if (Hoption.Logx) {
5293 if (xup > 0) xup = TMath::Log10(xup);
5294 else continue;
5295 if (xlow > 0) xlow = TMath::Log10(xlow);
5296 else continue;
5297 }
5298
5299 yup = ycent*zratio + yk + ycent;
5300 ylow = 2*(yk + ycent) - yup;
5301 if (yup-ylow < dymin) yup = ylow+dymin;
5302 if (Hoption.Logy) {
5303 if (yup > 0) yup = TMath::Log10(yup);
5304 else continue;
5305 if (ylow > 0) ylow = TMath::Log10(ylow);
5306 else continue;
5307 }
5308
5309 xlow = TMath::Max(xlow, gPad->GetUxmin());
5310 ylow = TMath::Max(ylow, gPad->GetUymin());
5311 xup = TMath::Min(xup , gPad->GetUxmax());
5312 yup = TMath::Min(yup , gPad->GetUymax());
5313
5314 if (xlow >= xup) continue;
5315 if (ylow >= yup) continue;
5316
5317 if (Hoption.Box == 1) {
5318 fH->SetFillColor(color);
5319 fH->TAttFill::Modify();
5320 gPad->PaintBox(xlow, ylow, xup, yup);
5321 if (kZNeg) {
5322 gPad->PaintLine(xlow, ylow, xup, yup);
5323 gPad->PaintLine(xlow, yup, xup, ylow);
5324 }
5325 } else if (Hoption.Box == 11) {
5326 // Draw the center of the box
5327 fH->SetFillColor(color);
5328 fH->TAttFill::Modify();
5329 gPad->PaintBox(xlow, ylow, xup, yup);
5330
5331 // Draw top&left part of the box
5332 Double_t x[7], y[7];
5333 Double_t bwidth = 0.1;
5334 x[0] = xlow; y[0] = ylow;
5335 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5336 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5337 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5338 x[4] = xup; y[4] = yup;
5339 x[5] = xlow; y[5] = yup;
5340 x[6] = xlow; y[6] = ylow;
5341 if (kZNeg) fH->SetFillColor(dark);
5342 else fH->SetFillColor(light);
5343 fH->TAttFill::Modify();
5344 gPad->PaintFillArea(7, x, y);
5345
5346 // Draw bottom&right part of the box
5347 x[0] = xlow; y[0] = ylow;
5348 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5349 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5350 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5351 x[4] = xup; y[4] = yup;
5352 x[5] = xup; y[5] = ylow;
5353 x[6] = xlow; y[6] = ylow;
5354 if (kZNeg) fH->SetFillColor(light);
5355 else fH->SetFillColor(dark);
5356 fH->TAttFill::Modify();
5357 gPad->PaintFillArea(7, x, y);
5358 }
5359 }
5360 }
5361
5365 fH->TAttFill::Modify();
5366}
5367
5368
5369
5370////////////////////////////////////////////////////////////////////////////////
5371/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5372
5374{
5375 TH1D *hproj = nullptr;
5376 TH2D *h2 = (TH2D*)fH;
5377
5380 myCandle.SetMarkerColor(fH->GetLineColor());
5381 myCandle.SetLineColor(fH->GetLineColor());
5382 myCandle.SetLineWidth(fH->GetLineWidth());
5383 myCandle.SetFillColor(fH->GetFillColor());
5384 myCandle.SetFillStyle(fH->GetFillStyle());
5385 myCandle.SetMarkerSize(fH->GetMarkerSize());
5386 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5388
5389 Bool_t swapXY = myCandle.IsHorizontal();
5390 const Double_t standardCandleWidth = 0.66;
5391 const Double_t standardHistoWidth = 0.8;
5392
5393 double allMaxContent = 0, allMaxIntegral = 0;
5394 if (myCandle.IsViolinScaled())
5395 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5396
5397 if (!swapXY) { // Vertical candle
5398 //Determining the slice with the maximum integral - if necessary
5399 if (myCandle.IsCandleScaled())
5400 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5401 hproj = h2->ProjectionY("_px", i, i);
5402 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5403 }
5404 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5406 Double_t binWidth = fXaxis->GetBinWidth(i);
5407 hproj = h2->ProjectionY("_px", i, i);
5408 if (hproj->GetEntries() != 0) {
5410 Double_t offset = fH->GetBarOffset()*binWidth;
5411 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5412 double myIntegral = hproj->Integral();
5414 if (candleWidth > 0.999 && candleWidth < 1.001) {
5417 }
5418 if (Hoption.Logz && myMaxContent > 0) {
5420 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5422 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5424 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5426
5427 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5428 myCandle.SetCandleWidth(candleWidth*binWidth);
5429 myCandle.SetHistoWidth(histoWidth*binWidth);
5430 myCandle.SetHistogram(hproj);
5431 myCandle.Paint();
5432 }
5433 }
5434 } else { // Horizontal candle
5435 //Determining the slice with the maximum integral - if necessary
5436 if (myCandle.IsCandleScaled())
5437 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5438 hproj = h2->ProjectionX("_py", i, i);
5439 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5440 }
5441 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5443 Double_t binWidth = fYaxis->GetBinWidth(i);
5444 hproj = h2->ProjectionX("_py", i, i);
5445 if (hproj->GetEntries() != 0) {
5447 Double_t offset = fH->GetBarOffset()*binWidth;
5448 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5449 double myIntegral = hproj->Integral();
5451 if (candleWidth > 0.999 && candleWidth < 1.001) {
5454 }
5455 if (Hoption.Logz && myMaxContent > 0) {
5457 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5459 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5461 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5463
5464 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5465 myCandle.SetCandleWidth(candleWidth*binWidth);
5466 myCandle.SetHistoWidth(histoWidth*binWidth);
5467 myCandle.SetHistogram(hproj);
5468 myCandle.Paint();
5469 }
5470 }
5471 }
5472 delete hproj;
5473}
5474
5475
5476
5477////////////////////////////////////////////////////////////////////////////////
5478/// Returns the rendering regions for an axis to use in the COL2 option
5479///
5480/// The algorithm analyses the size of the axis compared to the size of
5481/// the rendering region. It figures out the boundaries to use for each color
5482/// of the rendering region. Only one axis is computed here.
5483///
5484/// This allows for a single computation of the boundaries before iterating
5485/// through all of the bins.
5486///
5487/// \param pAxis the axis to consider
5488/// \param nPixels the number of pixels to render axis into
5489/// \param isLog whether the axis is log scale
5490
5491std::vector<THistRenderingRegion>
5493{
5494 std::vector<THistRenderingRegion> regions;
5495
5496 enum STRATEGY { Bins, Pixels } strategy;
5497
5498 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5499
5500 if (nBins >= nPixels) {
5501 // more bins than pixels... we should loop over pixels and sample
5502 strategy = Pixels;
5503 } else {
5504 // fewer bins than pixels... we should loop over bins
5505 strategy = Bins;
5506 }
5507
5508 if (isLog) {
5509
5510 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5511 Int_t binOffset=0;
5512 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5513 binOffset++;
5514 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5515 }
5516 if (xMin <= 0) {
5517 // this should cause an error if we have
5518 return regions;
5519 }
5520 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5521
5522 if (strategy == Bins) {
5523 // logarithmic plot. we find the pixel for the bin
5524 // pixel = eta * log10(V) - alpha
5525 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5526 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5527 // and V is axis value
5529 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5530
5531 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5532
5533 // linear plot. we simply need to find the appropriate bin
5534 // for the
5535 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5536 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5539 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5540 std::make_pair(bin, bin+1)};
5541 regions.push_back(region);
5542 }
5543
5544 } else {
5545
5546 // loop over pixels
5547
5549
5550 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5551 // linear plot
5552 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5553 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5554 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5555 std::make_pair(binLow, binHigh)};
5556 regions.push_back(region);
5557 }
5558 }
5559 } else {
5560 // standard linear plot
5561
5562 if (strategy == Bins) {
5563 // loop over bins
5564 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5565
5566 // linear plot. we simply need to find the appropriate bin
5567 // for the
5568 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5569 Int_t xPx1 = xPx0 + nPixels/nBins;
5570
5571 // make sure we don't compute beyond our bounds
5572 if (xPx1>= nPixels) xPx1 = nPixels-1;
5573
5574 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5575 std::make_pair(bin, bin+1)};
5576 regions.push_back(region);
5577 }
5578 } else {
5579 // loop over pixels
5581 // linear plot
5582 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5583 Int_t binHigh = binLow + nBins/nPixels;
5584 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5585 std::make_pair(binLow, binHigh)};
5586 regions.push_back(region);
5587 }
5588 }
5589 }
5590
5591 return regions;
5592}
5593
5594////////////////////////////////////////////////////////////////////////////////
5595/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5596
5598{
5599
5600 if (Hoption.System != kCARTESIAN) {
5601 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5602 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5603 PaintColorLevels(nullptr);
5604 return;
5605 }
5606
5607 Double_t z;
5608
5609 // Use existing max or min values. If either is already set
5610 // the appropriate value to use.
5611 Double_t zmin = fH->GetMinimumStored();
5612 Double_t zmax = fH->GetMaximumStored();
5613 Double_t originalZMin = zmin;
5614 Double_t originalZMax = zmax;
5615 if ((zmin == -1111) && (zmax == -1111)) {
5616 fH->GetMinimumAndMaximum(zmin, zmax);
5617 fH->SetMinimum(zmin);
5618 fH->SetMaximum(zmax);
5619 } else if (zmin == -1111) {
5620 zmin = fH->GetMinimum();
5621 fH->SetMinimum(zmin);
5622 } else if (zmax == -1111) {
5623 zmax = fH->GetMaximum();
5624 fH->SetMaximum(zmax);
5625 }
5626
5627 Double_t dz = zmax - zmin;
5628 if (dz <= 0) { // Histogram filled with a constant value
5629 zmax += 0.1*TMath::Abs(zmax);
5630 zmin -= 0.1*TMath::Abs(zmin);
5631 dz = zmax - zmin;
5632 }
5633
5634 if (Hoption.Logz) {
5635 if (zmin > 0) {
5636 zmin = TMath::Log10(zmin);
5637 zmax = TMath::Log10(zmax);
5638 dz = zmax - zmin;
5639 } else {
5640 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5641 "Cannot plot logz because bin content is less than 0.");
5642 return;
5643 }
5644 }
5645
5646 // Initialize the levels on the Z axis
5647 Int_t ndiv = fH->GetContour();
5648 if (ndiv == 0 ) {
5649 ndiv = gStyle->GetNumberContours();
5650 fH->SetContour(ndiv);
5651 }
5652 std::vector<Double_t> colorBounds(ndiv);
5653 std::vector<Double_t> contours(ndiv, 0);
5654 if (!fH->TestBit(TH1::kUserContour)) {
5655 fH->SetContour(ndiv);
5656 } else {
5657 fH->GetContour(contours.data());
5658 }
5659
5660 Double_t step = 1.0/ndiv;
5661 for (Int_t i=0; i<ndiv; ++i) {
5662 colorBounds[i] = step*i;
5663 }
5664
5665 auto pFrame = gPad->GetFrame();
5666 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5667 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5668 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5669 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5670 Int_t nXPixels = px1-px0;
5671 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5672
5673 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5674
5677 if (xRegions.empty() || yRegions.empty()) {
5678 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5679 "Encountered error while computing rendering regions.");
5680 return;
5681 }
5682
5685 Double_t minValue = 1.;
5686 Double_t maxValue = 0.;
5687 for (auto& yRegion : yRegions) {
5688 for (auto& xRegion : xRegions ) {
5689
5690 const auto& xBinRange = xRegion.fBinRange;
5691 const auto& yBinRange = yRegion.fBinRange;
5692
5693 // sample the range
5694 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5695
5696 if (Hoption.Logz) {
5697 if (z > 0) z = TMath::Log10(z);
5698 else z = zmin;
5699 }
5700
5701 // obey the user's max and min values if they were set
5702 if (z > zmax) z = zmax;
5703 if (z < zmin) z = zmin;
5704
5706 // contours are absolute values
5707 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5708 z = colorBounds[index];
5709 } else {
5710 Int_t index = 0;
5711 if (dz != 0) {
5712 index = 0.001 + ((z - zmin)/dz)*ndiv;
5713 }
5714
5715 if (index == static_cast<Int_t>(colorBounds.size())) {
5716 index--;
5717 }
5718
5719 // Do a little bookkeeping to use later for getting libAfterImage to produce
5720 // the correct colors
5721 if (index == 0) {
5722 minExists = kTRUE;
5723 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5724 maxExists = kTRUE;
5725 }
5726
5727 z = colorBounds[index];
5728
5729 if (z < minValue) {
5730 minValue = z;
5731 }
5732 if (z > maxValue) {
5733 maxValue = z;
5734 }
5735 }
5736
5737 // fill in the actual pixels
5738 const auto& xPixelRange = xRegion.fPixelRange;
5739 const auto& yPixelRange = yRegion.fPixelRange;
5740 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5741 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5743 buffer[pixel] = z;
5744 }
5745 }
5746 } // end px loop
5747 } // end py loop
5748
5749 // This is a bit of a hack to ensure that we span the entire color range and
5750 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5751 // single pixel on the edge of the image to a different color. This is even more
5752 // true because the chosen pixels will be covered by the axis.
5753 if (minValue != maxValue) {
5754 if ( !minExists) {
5755 buffer.front() = 0;
5756 }
5757
5758 if ( !maxExists) {
5759 buffer[buffer.size()-nXPixels] = 0.95;
5760 }
5761 }
5762
5763 // Generate the TImage
5766 pImage->SetImageQuality(TAttImage::kImgBest);
5767 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5768 delete pPalette;
5769
5770 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5771 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5772 delete pImage;
5773
5775
5776 // Reset the maximum and minimum values to their original values
5777 // when this function was called. If we don't do this, an initial
5778 // value of -1111 will be replaced with the true max or min values.
5781}
5782
5783////////////////////////////////////////////////////////////////////////////////
5784/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5785
5787{
5788 Double_t z, e, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5789
5790 Double_t zmin = fH->GetMinimum();
5791 Double_t zmax = fH->GetMaximum();
5792
5793 Double_t dz = zmax - zmin;
5794 if (dz <= 0) { // Histogram filled with a constant value
5795 zmax += 0.1*TMath::Abs(zmax);
5796 zmin -= 0.1*TMath::Abs(zmin);
5797 dz = zmax - zmin;
5798 }
5799
5800 // In case of option SAME, zmin and zmax values are taken from the
5801 // first plotted 2D histogram.
5802 if (Hoption.Same > 0 && Hoption.Same < 10) {
5803 TH2 *h2;
5804 TIter next(gPad->GetListOfPrimitives());
5805 while ((h2 = (TH2 *)next())) {
5806 if (!h2->InheritsFrom(TH2::Class())) continue;
5807 zmin = h2->GetMinimum();
5808 zmax = h2->GetMaximum();
5809 fH->SetMinimum(zmin);
5810 fH->SetMaximum(zmax);
5811 if (Hoption.Logz) {
5812 if (zmin <= 0) {
5813 zmin = TMath::Log10(zmax*0.001);
5814 } else {
5815 zmin = TMath::Log10(zmin);
5816 }
5817 zmax = TMath::Log10(zmax);
5818 }
5819 dz = zmax - zmin;
5820 break;
5821 }
5822 } else {
5823 if (Hoption.Logz) {
5824 if (zmin > 0) {
5825 zmin = TMath::Log10(zmin);
5826 zmax = TMath::Log10(zmax);
5827 dz = zmax - zmin;
5828 } else {
5829 return;
5830 }
5831 }
5832 }
5833
5836 fH->SetFillStyle(1001);
5837 fH->TAttFill::Modify();
5838
5839 // Initialize the levels on the Z axis
5840 Int_t ncolors = gStyle->GetNumberOfColors();
5841 Int_t ndiv = fH->GetContour();
5842 if (ndiv == 0 ) {
5843 ndiv = gStyle->GetNumberContours();
5844 fH->SetContour(ndiv);
5845 }
5846 Int_t ndivz = TMath::Abs(ndiv);
5847 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5848 Double_t scale = (dz ? ndivz / dz : 1.0);
5849
5850 Int_t color;
5851 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5852 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5855 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5856 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5857 xk = fXaxis->GetBinLowEdge(i);
5858 xstep = fXaxis->GetBinWidth(i);
5859 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5860 z = fH->GetBinContent(bin);
5861 e = fH->GetBinError(bin);
5862 // if fH is a profile histogram do not draw empty bins
5863 if (prof2d) {
5864 const Double_t binEntries = prof2d->GetBinEntries(bin);
5865 if (binEntries == 0)
5866 continue;
5867 } else {
5868 // don't draw the empty bins for non-profile histograms
5869 // with positive content
5870 if (z == 0 && e == 0) {
5871 if (zmin >= 0 || Hoption.Logz) continue;
5872 if (Hoption.Color == 2) continue;
5873 }
5874 }
5875
5876 if (Hoption.Logz) {
5877 if (z > 0) z = TMath::Log10(z);
5878 else z = zmin;
5879 }
5880 if (z < zmin && !Hoption.Zero) continue;
5881 xup = xk + xstep;
5882 xlow = xk;
5883 if (Hoption.Logx) {
5884 if (xup > 0) xup = TMath::Log10(xup);
5885 else continue;
5886 if (xlow > 0) xlow = TMath::Log10(xlow);
5887 else continue;
5888 }
5889 yup = yk + ystep;
5890 ylow = yk;
5891 if (Hoption.Logy) {
5892 if (yup > 0) yup = TMath::Log10(yup);
5893 else continue;
5894 if (ylow > 0) ylow = TMath::Log10(ylow);
5895 else continue;
5896 }
5897 if (xup < gPad->GetUxmin()) continue;
5898 if (yup < gPad->GetUymin()) continue;
5899 if (xlow > gPad->GetUxmax()) continue;
5900 if (ylow > gPad->GetUymax()) continue;
5901 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5902 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5903 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5904 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5905
5907 zc = fH->GetContourLevelPad(0);
5908 if (z < zc) continue;
5909 color = -1;
5910 for (Int_t k=0; k<ndiv; k++) {
5911 zc = fH->GetContourLevelPad(k);
5912 if (z < zc) {
5913 continue;
5914 } else {
5915 color++;
5916 }
5917 }
5918 } else {
5919 color = Hoption.Zero ? Int_t(0.01+(std::max(z, zmin)-zmin)*scale) : Int_t(0.01+(z-zmin)*scale);
5920 }
5921
5922 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5923 if (theColor > ncolors-1) theColor = ncolors-1;
5925 if (Hoption.System != kPOLAR) {
5927 fH->TAttFill::Modify();
5928 gPad->PaintBox(xlow, ylow, xup, yup);
5929 } else {
5930 Double_t midx = (gPad->GetUxmin() + gPad->GetUxmax()) / 2,
5931 midy = (gPad->GetUymin() + gPad->GetUymax()) / 2,
5932 a1 = (xlow - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5933 a2 = (xup - gPad->GetUxmin()) / (gPad->GetUxmax() - gPad->GetUxmin()) * 360,
5934 rx = gPad->GetUxmax() - gPad->GetUxmin(),
5935 ry = gPad->GetUymax() - gPad->GetUymin(),
5936 r1 = (ylow - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2,
5937 r2 = (yup - gPad->GetUymin()) / (gPad->GetUymax() - gPad->GetUymin()) * rx / 2;
5938
5939 TCrown crown(midx, midy, r1, r2, a1, a2);
5940 crown.SetYXRatio(rx > 0 ? ry / rx : 1);
5941 crown.SetFillColor(fillColor);
5942 crown.SetLineColor(fH->GetLineColor());
5943 crown.SetLineWidth(fH->GetLineWidth());
5944 crown.SetLineStyle(fH->GetLineStyle());
5945 crown.Paint();
5946 }
5947 }
5948 }
5949
5951
5954 fH->TAttFill::Modify();
5955
5956}
5957
5958////////////////////////////////////////////////////////////////////////////////
5959/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5960
5962{
5963
5964 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5965 Int_t itars, mode, ir[4];
5966 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5967
5968 if (Hoption.Contour == 14) {
5969 Hoption.Surf = 12;
5970 Hoption.Axis = 1;
5971 thesave = gPad->GetTheta();
5972 phisave = gPad->GetPhi();
5973 gPad->SetPhi(0.);
5974 gPad->SetTheta(90.);
5976 gPad->SetPhi(phisave);
5977 gPad->SetTheta(thesave);
5978 TView *view = gPad->GetView();
5979 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5980 PaintAxis();
5981 return;
5982 }
5983
5984 if (Hoption.Same) {
5985 // If the contour is painted on a 3d plot, the contour lines are
5986 // paint in 3d too.
5987 TObject *obj;
5988 TIter next(gPad->GetListOfPrimitives());
5989 while ((obj=next())) {
5990 if (strstr(obj->GetDrawOption(),"surf") ||
5991 strstr(obj->GetDrawOption(),"lego") ||
5992 strstr(obj->GetDrawOption(),"tri")) {
5993 Hoption.Surf = 16;
5995 return;
5996 }
5997 }
5998 }
5999
6000 if (Hoption.Contour == 15) {
6001 TGraphDelaunay2D *dt = nullptr;
6002 TGraphDelaunay *dtOld = nullptr;
6004 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
6005 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
6006 if (!dt && !dtOld) return;
6007 if (!fGraph2DPainter)
6008 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
6009 fGraph2DPainter->Paint(option);
6010 return;
6011 }
6012
6013 gPad->SetBit(TGraph::kClipFrame);
6014
6015 std::vector<Double_t> levels(2*kMAXCONTOUR);
6016 std::vector<Double_t> xarr(2*kMAXCONTOUR);
6017 std::vector<Double_t> yarr(2*kMAXCONTOUR);
6018 std::vector<Int_t> itarr(2*kMAXCONTOUR);
6019
6020 Int_t npmax = 0;
6021 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
6022
6023 ncontour = fH->GetContour();
6024 if (ncontour == 0) {
6027 }
6028 if (ncontour > kMAXCONTOUR) {
6029 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
6032 }
6034
6035 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
6039 if (Hoption.Contour == 13) {
6040 fH->TAttLine::Modify();
6041 }
6042
6043 std::vector<std::unique_ptr<TPolyLine>> polys;
6044 TObjArray *contours = nullptr;
6045 TList *list = nullptr;
6046 TGraph *graph = nullptr;
6047 std::vector<Int_t> np;
6048 if (Hoption.Contour == 1 || (Hoption.List && (Hoption.Contour == 11 || Hoption.Contour == 12 || Hoption.Contour == 13))) {
6049 np.resize(ncontour);
6050 for (i=0;i<ncontour;i++)
6051 np[i] = 0;
6052 for (i=0;i<ncontour;i++)
6053 polys.emplace_back(std::make_unique<TPolyLine>(100));
6054 if (Hoption.List == 1) {
6055 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6056 if (contours) {
6057 gROOT->GetListOfSpecials()->Remove(contours);
6058 count = contours->GetSize();
6059 for (i=0;i<count;i++) {
6060 list = (TList*)contours->At(i);
6061 if (list) list->Delete();
6062 }
6063 contours->Delete();
6064 delete contours;
6065 }
6067 contours->SetName("contours");
6068 gROOT->GetListOfSpecials()->Add(contours);
6069 for (i=0;i<ncontour;i++) {
6070 list = new TList();
6071 contours->Add(list);
6072 }
6073 }
6074 }
6076 Int_t ncolors = gStyle->GetNumberOfColors();
6078
6079 Int_t k,ipoly;
6080 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6081 y[0] = fYaxis->GetBinCenter(j);
6082 y[1] = y[0];
6083 y[2] = fYaxis->GetBinCenter(j+1);
6084 y[3] = y[2];
6085 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6086 zc[0] = fH->GetBinContent(i, j);
6087 zc[1] = fH->GetBinContent(i+1, j);
6088 zc[2] = fH->GetBinContent(i+1, j+1);
6089 zc[3] = fH->GetBinContent(i, j+1);
6090 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6091 if (Hoption.Logz) {
6092 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6093 else zc[0] = Hparam.zmin;
6094 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6095 else zc[1] = Hparam.zmin;
6096 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6097 else zc[2] = Hparam.zmin;
6098 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6099 else zc[3] = Hparam.zmin;
6100 }
6101 for (k=0;k<4;k++) {
6102 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6103 }
6104 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6105 x[0] = fXaxis->GetBinCenter(i);
6106 x[3] = x[0];
6107 x[1] = fXaxis->GetBinCenter(i+1);
6108 x[2] = x[1];
6109 if (zc[0] <= zc[1]) n = 0; else n = 1;
6110 if (zc[2] <= zc[3]) m = 2; else m = 3;
6111 if (zc[n] > zc[m]) n = m;
6112 n++;
6113 lj=1;
6114 for (ix=1;ix<=4;ix++) {
6115 m = n%4 + 1;
6116 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6117 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6118 lj += 2*ljfill;
6119 n = m;
6120 }
6121
6122 if (zc[0] <= zc[1]) n = 0; else n = 1;
6123 if (zc[2] <= zc[3]) m = 2; else m = 3;
6124 if (zc[n] > zc[m]) n = m;
6125 n++;
6126 lj=2;
6127 for (ix=1;ix<=4;ix++) {
6128 if (n == 1) m = 4;
6129 else m = n-1;
6130 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6131 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6132 lj += 2*ljfill;
6133 n = m;
6134 }
6135
6136 // Re-order endpoints
6137
6138 count = 0;
6139 for (ix=1; ix<=lj-5; ix +=2) {
6140 //count = 0;
6141 while (itarr[ix-1] != itarr[ix]) {
6142 xsave = xarr[ix];
6143 ysave = yarr[ix];
6144 itars = itarr[ix];
6145 for (jx=ix; jx<=lj-5; jx +=2) {
6146 xarr[jx] = xarr[jx+2];
6147 yarr[jx] = yarr[jx+2];
6148 itarr[jx] = itarr[jx+2];
6149 }
6150 xarr[lj-3] = xsave;
6151 yarr[lj-3] = ysave;
6152 itarr[lj-3] = itars;
6153 if (count > 100) break;
6154 count++;
6155 }
6156 }
6157
6158 if (count > 100) continue;
6159 for (ix=1; ix<=lj-2; ix +=2) {
6160 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6162 if (Hoption.Contour == 11) {
6164 }
6165 if (Hoption.Contour == 12) {
6166 mode = icol%5;
6167 if (mode == 0) mode = 5;
6169 }
6170 if (Hoption.Contour != 1) {
6171 fH->TAttLine::Modify();
6172 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6173 if ((Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13) || !Hoption.List)
6174 continue;
6175 }
6176
6177 ipoly = itarr[ix-1];
6178 if (ipoly >=0 && ipoly <ncontour) {
6179 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6180 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6181 np[ipoly] += 2;
6182 if (npmax < np[ipoly]) npmax = np[ipoly];
6183 }
6184 }
6185 } // end of if (ir[0]
6186 } //end of for (i
6187 } //end of for (j
6188
6190 std::vector<Double_t> xp, yp;
6192 Int_t istart;
6193 Int_t first = ncontour;
6194 std::vector<Int_t> polysort;
6196 if (Hoption.Contour != 1) {
6197 if (!Hoption.List || (Hoption.Contour != 11 && Hoption.Contour != 12 && Hoption.Contour != 13))
6198 goto theEND;
6199 }
6200
6201 //The 2 points line generated above are now sorted/merged to generate
6202 //a list of consecutive points.
6203 // If the option "List" has been specified, the list of points is saved
6204 // in the form of TGraph objects in the ROOT list of special objects.
6205 xmin = gPad->GetUxmin();
6206 ymin = gPad->GetUymin();
6207 xp.resize(2*npmax);
6208 yp.resize(2*npmax);
6209 polysort.resize(ncontour);
6210 //find first positive contour
6211 for (ipoly=0;ipoly<ncontour;ipoly++) {
6212 if (levels[ipoly] >= 0) {first = ipoly; break;}
6213 }
6214 //store negative contours from 0 to minimum, then all positive contours
6215 k = 0;
6216 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6217 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6218 // if Contour==1 we can now draw sorted contours, otherwise (11,12,13) just store
6219 contListNb = 0;
6220 if (Hoption.Contour == 1) fH->SetFillStyle(1001);
6221 for (k=0;k<ncontour;k++) {
6222 ipoly = polysort[k];
6223 if (Hoption.List) list = (TList*)contours->At(contListNb);
6224 contListNb++;
6225 if (np[ipoly] == 0)
6226 continue;
6227 Double_t *xx = polys[ipoly]->GetX();
6228 Double_t *yy = polys[ipoly]->GetY();
6229 istart = 0;
6230 while (true) {
6231 iminus = npmax;
6232 iplus = iminus+1;
6233 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6234 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6235 xx[istart] = xmin; yy[istart] = ymin;
6236 xx[istart+1] = xmin; yy[istart+1] = ymin;
6237 while (true) {
6238 nadd = 0;
6239 for (i=2;i<np[ipoly];i+=2) {
6240 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6241 iplus++;
6242 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6243 xx[i] = xmin; yy[i] = ymin;
6244 xx[i+1] = xmin; yy[i+1] = ymin;
6245 nadd++;
6246 }
6247 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6248 iminus--;
6249 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6250 xx[i] = xmin; yy[i] = ymin;
6251 xx[i+1] = xmin; yy[i+1] = ymin;
6252 nadd++;
6253 }
6254 }
6255 if (nadd == 0) break;
6256 }
6257 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6259 if (Hoption.Contour == 1) {
6260 if (ndivz > 1) fH->SetFillColor(icol);
6261 fH->TAttFill::Modify();
6262 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6263 }
6264 if (Hoption.List) {
6265 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6266 if (Hoption.Contour == 1)
6267 graph->SetFillColor(icol);
6268 else if (Hoption.Contour == 11)
6269 graph->SetLineColor(icol);
6270 else if (Hoption.Contour == 12) {
6271 mode = icol%5;
6272 if (mode == 0) mode = 5;
6273 graph->SetLineStyle(mode);
6274 }
6275 graph->SetLineWidth(fH->GetLineWidth());
6276 list->Add(graph);
6277 }
6278 //check if more points are left
6279 istart = 0;
6280 for (i=2;i<np[ipoly];i+=2) {
6281 if (xx[i] != xmin && yy[i] != ymin) {
6282 istart = i;
6283 break;
6284 }
6285 }
6286 if (istart == 0) break;
6287 }
6288 }
6289
6290theEND:
6291 gPad->ResetBit(TGraph::kClipFrame);
6296}
6297
6298////////////////////////////////////////////////////////////////////////////////
6299/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6300
6304{
6305
6306 Bool_t vert;
6308 Int_t n, i, icount;
6309
6310 if (x1 == x2) {
6311 vert = kTRUE;
6312 tlen = y2 - y1;
6313 } else {
6314 vert = kFALSE;
6315 tlen = x2 - x1;
6316 }
6317
6318 n = icont1 +1;
6319 tdif = elev2 - elev1;
6320 i = 0;
6321 icount = 0;
6322 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6323 //elev = fH->GetContourLevel(n);
6324 elev = levels[n];
6325 diff = elev - elev1;
6326 pdif = diff/tdif;
6327 xlen = tlen*pdif;
6328 if (vert) {
6329 if (Hoption.Logx)
6330 xarr[i] = TMath::Log10(x1);
6331 else
6332 xarr[i] = x1;
6333 if (Hoption.Logy)
6334 yarr[i] = TMath::Log10(y1 + xlen);
6335 else
6336 yarr[i] = y1 + xlen;
6337 } else {
6338 if (Hoption.Logx)
6339 xarr[i] = TMath::Log10(x1 + xlen);
6340 else
6341 xarr[i] = x1 + xlen;
6342 if (Hoption.Logy)
6343 yarr[i] = TMath::Log10(y1);
6344 else
6345 yarr[i] = y1;
6346 }
6347 itarr[i] = n;
6348 icount++;
6349 i +=2;
6350 n++;
6351 }
6352 return icount;
6353}
6354
6355////////////////////////////////////////////////////////////////////////////////
6356/// [Draw 1D histograms error bars.](\ref HP09)
6357
6359{
6360
6361 // On iOS, we do not highlight histogram, if it's not picked at the moment
6362 // (but part of histogram (axis or pavestat) was picked, that's why this code
6363 // is called at all. This conditional statement never executes on non-iOS platform.
6364 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6365
6366 const Int_t kBASEMARKER=8;
6367 Double_t xp, yp, ex1, ex2, ey1, ey2;
6368 Double_t delta;
6370 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6372 Double_t logxmin = 0;
6373 Double_t logymin = 0;
6374 Double_t offset = 0.;
6375 Double_t width = 0.;
6376 Int_t i, k, npoints, first, last, fixbin;
6377 Int_t if1 = 0;
6378 Int_t if2 = 0;
6382 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};
6383 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};
6384
6385 std::vector<Double_t> xline, yline, xsegm, ysegm, xmarker, ymarker;
6387 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6388 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6389 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6390 if (Hoption.Error == 11) option1 = 1;
6391 if (Hoption.Error == 12) option2 = 1;
6392 if (Hoption.Error == 13) option3 = 1;
6393 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6394 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6395 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6396 if (option2+option3 == 0) optionE = 1;
6397 if (Hoption.Error == 0) optionE = 0;
6398 if (fXaxis->GetXbins()->fN) fixbin = 0;
6399 else fixbin = 1;
6400
6401 offset = fH->GetBarOffset();
6402 width = fH->GetBarWidth();
6403
6405 if (optionEX0) {
6406 xerror = 0;
6407 } else {
6408 xerror = gStyle->GetErrorX();
6409 }
6411 if (errormarker == 1) symbolsize = 0.01;
6413 if (errormarker >= 20 && errormarker <= 49) {
6414 sbasex *= cxx[errormarker-20];
6415 sbasey *= cyy[errormarker-20];
6416 }
6417 // set the graphics attributes
6418
6419 fH->TAttLine::Modify();
6420 fH->TAttFill::Modify();
6421 fH->TAttMarker::Modify();
6422
6423 // set the first and last bin
6424
6425 Double_t factor = Hparam.factor;
6426 first = Hparam.xfirst;
6427 last = Hparam.xlast;
6428 npoints = last - first +1;
6429 xmin = gPad->GetUxmin();
6430 xmax = gPad->GetUxmax();
6431 ymin = gPad->GetUymin();
6432 ymax = gPad->GetUymax();
6433
6434 xsegm.reserve(1024);
6435 ysegm.reserve(1024);
6436 if (!xsegm.capacity() || !ysegm.capacity()) {
6437 Error("PaintErrors", "out of memory for lines painting");
6438 return;
6439 }
6440
6441 auto flush_segmentes = [&]() {
6442 if (xsegm.size() > 0) {
6443 gPad->PaintSegments(xsegm.size()/2, xsegm.data(), ysegm.data());
6444 xsegm.clear();
6445 ysegm.clear();
6446 }
6447 };
6448
6450 xsegm.emplace_back(x1);
6451 xsegm.emplace_back(x2);
6452 ysegm.emplace_back(y1);
6453 ysegm.emplace_back(y2);
6454 if (xsegm.size() == xsegm.capacity())
6456 };
6457
6458 auto flush_markers = [&]() {
6459 if (xmarker.size() > 0) {
6460 gPad->PaintPolyMarker(xmarker.size(), xmarker.data(), ymarker.data());
6461 xmarker.clear();
6462 ymarker.clear();
6463 }
6464 };
6465
6466 auto add_marker = [&](Double_t x, Double_t y) {
6467 if (xmarker.capacity() == 0) {
6468 xmarker.reserve(256);
6469 ymarker.reserve(256);
6470 }
6471
6472 xmarker.emplace_back(x);
6473 ymarker.emplace_back(y);
6474 if (xmarker.size() == xmarker.capacity()) {
6476 flush_markers();
6477 }
6478 };
6479
6480
6481 if (option3) {
6482 xline.resize(2*npoints);
6483 yline.resize(2*npoints);
6484 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6485 Error("PaintErrors", "too many points, out of memory");
6486 return;
6487 }
6488 if1 = 1;
6489 if2 = 2*npoints;
6490 }
6491
6492 // compute the offset of the error bars due to the symbol size
6493 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6494 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6495
6496 // compute size of the lines at the end of the error bars
6498 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6499 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6500
6501
6502 if (fixbin) {
6504 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6505 } else {
6506 delta = fH->GetBinWidth(first);
6507 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6508 }
6509
6510 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6513
6514 // ---------------------- Loop over the points---------------------
6515 for (k=first; k<=last; k++) {
6516
6517 // get the data
6518 // xp = X position of the current point
6519 // yp = Y position of the current point
6520 // ex1 = Low X error
6521 // ex2 = Up X error
6522 // ey1 = Low Y error
6523 // ey2 = Up Y error
6524 // (xi,yi) = Error bars coordinates
6525
6526 // apply offset on errors for bar histograms
6527 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6528 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6529 if (Hoption.Logx) {
6532 }
6535 xmaxTmp = xminTmp + w;
6536 xp = (xminTmp+xmaxTmp)/2.;
6537
6538 if (Hoption.Logx) {
6539 if (xp <= 0) goto L30;
6540 if (xp < logxmin) goto L30;
6541 if (xp > TMath::Power(10,xmax)) break;
6542 } else {
6543 if (xp < xmin) goto L30;
6544 if (xp > xmax) break;
6545 }
6546 yp = factor*fH->GetBinContent(k);
6547 if (optionI0 && yp==0) goto L30;
6548 if (fixbin) {
6550 } else {
6551 delta = fH->GetBinWidth(k);
6552 ex1 = xerror*delta;
6553 }
6554 if (fH->GetBinErrorOption() == TH1::kNormal) {
6555 ey1 = factor*fH->GetBinError(k);
6556 ey2 = ey1;
6557 } else {
6558 ey1 = factor*fH->GetBinErrorLow(k);
6559 ey2 = factor*fH->GetBinErrorUp(k);
6560 }
6561 ex2 = ex1;
6562
6563 xi4 = xp;
6564 xi3 = xp;
6565 xi2 = xp + ex2;
6566 xi1 = xp - ex1;
6567
6568 yi1 = yp;
6569 yi2 = yp;
6570 yi3 = yp - ey1;
6571 yi4 = yp + ey2;
6572
6573 // take the LOG if necessary
6574 if (Hoption.Logx) {
6579 }
6580 if (Hoption.Logy) {
6585 }
6586
6587 // test if error bars are not outside the limits
6588 // otherwise they are truncated
6589
6594
6595 // test if the marker is on the frame limits. If "Yes", the
6596 // marker will not be drawn and the error bars will be readjusted.
6597
6598 drawmarker = kTRUE;
6599 if (!option0 && !option3) {
6600 if (Hoption.Logy && yp < logymin) goto L30;
6601 if (yi1 < ymin || yi1 > ymax) goto L30;
6602 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6603 }
6605
6606 // draw the error rectangles
6607 if (option2) {
6608 if ((yi3 >= ymax) || (yi4 <= ymin))
6609 goto L30;
6610 gPad->PaintBox(xi1,yi3,xi2,yi4);
6611 }
6612
6613 // keep points for fill area drawing
6614 if (option3) {
6615 xline[if1-1] = xi3;
6616 xline[if2-1] = xi3;
6617 yline[if1-1] = yi4;
6618 yline[if2-1] = yi3;
6619 if1++;
6620 if2--;
6621 }
6622
6623 // draw the error bars
6624 if (Hoption.Logy && yp < logymin)
6626 if (optionE && drawmarker) {
6627 if ((yi3 < yi1 - s2y) && (yi3 < ymax))
6629 if ((yi1 + s2y < yi4) && (yi4 > ymin))
6631 // don't duplicate the horizontal line
6632 if (Hoption.Hist != 2) {
6634 if (xi1 < xi3 - s2x)
6636 if (xi3 + s2x < xi2)
6638 }
6639 }
6640 }
6641 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6642 if ((yi3 < yi1) && (yi3 < ymax))
6644 if ((yi1 < yi4) && (yi4 > ymin))
6646 // don't duplicate the horizontal line
6647 if (Hoption.Hist != 2) {
6649 if (xi1 < xi3)
6651 if (xi3 < xi2)
6653 }
6654 }
6655 }
6656
6657 // draw line at the end of the error bars
6658
6659 if (option1 && drawmarker) {
6660
6666 if (xi1 < xi3-s2x)
6668 if (xi2 > xi3+s2x)
6670 }
6671 }
6672
6673 // draw the marker
6674
6675 if (drawmarker)
6676 add_marker(xi3, yi1);
6677
6678L30:
6679 if (fixbin) xp += Hparam.xbinsize;
6680 else {
6681 if (k < last) {
6682 delta = fH->GetBinWidth(k+1);
6683 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6684 }
6685 }
6686 } //end of for loop
6687
6689
6690 flush_markers();
6691
6692
6693 // draw the filled area
6694
6695 if (option3) {
6696 TGraph graph;
6697 graph.SetLineStyle(fH->GetLineStyle());
6698 graph.SetLineColor(fH->GetLineColor());
6699 graph.SetLineWidth(fH->GetLineWidth());
6700 graph.SetFillStyle(fH->GetFillStyle());
6701 graph.SetFillColor(fH->GetFillColor());
6702 Int_t logx = gPad->GetLogx();
6703 Int_t logy = gPad->GetLogy();
6704 gPad->SetLogx(0);
6705 gPad->SetLogy(0);
6706
6707 // In some cases the number of points in the fill area is smaller than
6708 // 2*npoints. In such cases the array xline and yline must be arranged
6709 // before being plotted. The next loop does that.
6710 if (if2 > npoints) {
6711 for (i=1; i<if1; i++) {
6712 xline[if1-2+i] = xline[if2-1+i];
6713 yline[if1-2+i] = yline[if2-1+i];
6714 }
6715 npoints = if1-1;
6716 }
6717 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6718 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6719 gPad->SetLogx(logx);
6720 gPad->SetLogy(logy);
6721 }
6722}
6723
6724////////////////////////////////////////////////////////////////////////////////
6725/// Draw 2D histograms errors.
6726
6728{
6729
6730 fH->TAttMarker::Modify();
6731 fH->TAttLine::Modify();
6732
6733 // Define the 3D view
6734 fXbuf[0] = Hparam.xmin;
6735 fYbuf[0] = Hparam.xmax;
6736 fXbuf[1] = Hparam.ymin;
6737 fYbuf[1] = Hparam.ymax;
6738 fXbuf[2] = Hparam.zmin;
6739 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6740 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6741 TView *view = gPad ? gPad->GetView() : nullptr;
6742 if (!view) {
6743 Error("Paint2DErrors", "no TView in current pad");
6744 return;
6745 }
6746 Double_t thedeg = 90 - gPad->GetTheta();
6747 Double_t phideg = -90 - gPad->GetPhi();
6748 Double_t psideg = view->GetPsi();
6749 Int_t irep;
6750 view->SetView(phideg, thedeg, psideg, irep);
6751
6752 // Set color/style for back box
6753 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6754 fLego->SetFillColor(gPad->GetFrameFillColor());
6755 fLego->TAttFill::Modify();
6756 Int_t backcolor = gPad->GetFrameFillColor();
6757 if (Hoption.System != kCARTESIAN) backcolor = 0;
6758 view->PadRange(backcolor);
6759 fLego->SetFillStyle(fH->GetFillStyle());
6760 fLego->SetFillColor(fH->GetFillColor());
6761 fLego->TAttFill::Modify();
6762
6763 // Paint the Back Box if needed
6764 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6765 fLego->InitMoveScreen(-1.1,1.1);
6766 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6768 fLego->BackBox(90);
6769 }
6770
6771 // Paint the Errors
6772 Double_t x, ex, x1, x2;
6773 Double_t y, ey, y1, y2;
6774 Double_t z, ez1, ez2, z1, z2;
6775 Double_t temp1[3],temp2[3];
6777 if (Hoption.Error == 110) {
6778 xyerror = 0;
6779 } else {
6781 }
6782
6784 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6785 y = fYaxis->GetBinCenter(j);
6787 y1 = y-ey;
6788 y2 = y+ey;
6789 if (Hoption.Logy) {
6790 if (y > 0) y = TMath::Log10(y);
6791 else continue;
6792 if (y1 > 0) y1 = TMath::Log10(y1);
6793 else y1 = Hparam.ymin;
6794 if (y2 > 0) y2 = TMath::Log10(y2);
6795 else y2 = Hparam.ymin;
6796 }
6799 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6800 xk = fXaxis->GetBinLowEdge(i);
6801 xstep = fXaxis->GetBinWidth(i);
6802 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6803 Int_t bin = fH->GetBin(i,j);
6804 x = fXaxis->GetBinCenter(i);
6806 x1 = x-ex;
6807 x2 = x+ex;
6808 if (Hoption.Logx) {
6809 if (x > 0) x = TMath::Log10(x);
6810 else continue;
6811 if (x1 > 0) x1 = TMath::Log10(x1);
6812 else x1 = Hparam.xmin;
6813 if (x2 > 0) x2 = TMath::Log10(x2);
6814 else x2 = Hparam.xmin;
6815 }
6816 z = fH->GetBinContent(bin);
6817 if (fH->GetBinErrorOption() == TH1::kNormal) {
6818 ez1 = fH->GetBinError(bin);
6819 ez2 = ez1;
6820 }
6821 else {
6822 ez1 = fH->GetBinErrorLow(bin);
6823 ez2 = fH->GetBinErrorUp(bin);
6824 }
6825 z1 = z - ez1;
6826 z2 = z + ez2;
6827 if (Hoption.Logz) {
6828 if (z > 0) z = TMath::Log10(z);
6829 else z = Hparam.zmin;
6830 if (z1 > 0) z1 = TMath::Log10(z1);
6831 else z1 = Hparam.zmin;
6832 if (z2 > 0) z2 = TMath::Log10(z2);
6833 else z2 = Hparam.zmin;
6834
6835 }
6836 if (z <= Hparam.zmin) continue;
6837 if (z > Hparam.zmax) z = Hparam.zmax;
6838
6839 temp1[0] = x1;
6840 temp1[1] = y;
6841 temp1[2] = z;
6842 temp2[0] = x2;
6843 temp2[1] = y;
6844 temp2[2] = z;
6845 gPad->PaintLine3D(temp1, temp2);
6846 temp1[0] = x;
6847 temp1[1] = y1;
6848 temp1[2] = z;
6849 temp2[0] = x;
6850 temp2[1] = y2;
6851 temp2[2] = z;
6852 gPad->PaintLine3D(temp1, temp2);
6853 temp1[0] = x;
6854 temp1[1] = y;
6855 temp1[2] = z1;
6856 temp2[0] = x;
6857 temp2[1] = y;
6858 temp2[2] = z2;
6859 gPad->PaintLine3D(temp1, temp2);
6860 temp1[0] = x;
6861 temp1[1] = y;
6862 temp1[2] = z;
6863 view->WCtoNDC(temp1, &temp2[0]);
6864 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6865 }
6866 }
6867
6868 // Paint the Front Box if needed
6869 if (Hoption.FrontBox) {
6870 fLego->InitMoveScreen(-1.1,1.1);
6872 fLego->FrontBox(90);
6873 }
6874
6875 // Paint the Axis if needed
6876 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6877 TGaxis axis;
6878 PaintLegoAxis(&axis, 90);
6879 }
6880
6881 fLego.reset();
6882}
6883
6884////////////////////////////////////////////////////////////////////////////////
6885/// Calculate range and clear pad (canvas).
6886
6888{
6889
6890 if (Hoption.Same) return;
6891
6893
6894 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6895 Hoption.Contour == 14 || Hoption.Error >= 100) {
6896 TObject *frame = gPad->FindObject("TFrame");
6897 if (frame) gPad->Remove(frame);
6898 return;
6899 }
6900
6901 //The next statement is always executed on non-iOS platform,
6902 //on iOS depends on pad mode.
6903 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6904 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6905}
6906
6907////////////////////////////////////////////////////////////////////////////////
6908/// [Paint functions associated to an histogram.](\ref HP28")
6909
6911{
6912 auto lnk = fFunctions->FirstLink();
6913
6914 while (lnk) {
6915 auto obj = lnk->GetObject();
6917 if (obj->InheritsFrom(TF2::Class())) {
6918 if (!obj->TestBit(TF2::kNotDraw)) {
6919 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6920 TF2 *f2 = (TF2*)obj;
6921 f2->SetMinimum(fH->GetMinimum());
6922 f2->SetMaximum(fH->GetMaximum());
6923 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6924 f2->Paint("surf same");
6925 } else {
6926 obj->Paint("cont3 same");
6927 }
6928 }
6929 } else if (obj->InheritsFrom(TF1::Class())) {
6930 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6931 } else {
6932 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6933 gPad->PushSelectableObject(obj);
6934
6935 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6936 //and picked object.
6937 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6938 obj->Paint(lnk->GetOption());
6939 }
6940 lnk = lnk->Next();
6941 }
6942}
6943
6944////////////////////////////////////////////////////////////////////////////////
6945/// [Control routine to draw 1D histograms](\ref HP01b)
6946
6948{
6949
6950 //On iOS: do not highlight hist, if part of it was selected.
6951 //Never executes on non-iOS platform.
6952 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6953 return;
6954
6955 static char chopth[17];
6956
6958 Int_t i, j, first, last, nbins, fixbin;
6959 Double_t c1, yb;
6960 yb = 0;
6961
6962 strlcpy(chopth, " ",17);
6963
6966 Double_t baroffset = fH->GetBarOffset();
6967 Double_t barwidth = fH->GetBarWidth();
6970 gStyle->SetBarOffset(baroffset);
6971 gStyle->SetBarWidth(barwidth);
6972
6973 // Create "LIFE" structure to keep current histogram status
6974
6975 first = Hparam.xfirst;
6976 last = Hparam.xlast;
6977 nbins = last - first + 1;
6978
6979 std::vector<Double_t> keepx, keepy;
6980 if (fXaxis->GetXbins()->fN) fixbin = 0;
6981 else fixbin = 1;
6982 if (fixbin) keepx.resize(2);
6983 else keepx.resize(nbins+1);
6984 keepy.resize(nbins);
6985 Double_t logymin = 0;
6987
6988 // Loop on histogram bins
6989
6990 for (j=first; j<=last;j++) {
6992 if (TMath::Abs(ymax-ymin) > 0) {
6994 else yb = c1;
6995 }
6996 if (!Hoption.Line) {
6997 yb = TMath::Max(yb, ymin);
6998 yb = TMath::Min(yb, ymax);
6999 }
7000 keepy[j-first] = yb;
7001 }
7002
7003 // Draw histogram according to value of FillStyle and FillColor
7004
7005 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
7006 else {
7007 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
7008 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
7009 }
7010
7011 // Prepare Fill area (systematic with option "Bar").
7012
7014 htype = oldhtype;
7015 if (Hoption.Bar) {
7016 if (htype == 0 || htype == 1000) htype = 1001;
7017 }
7018
7020
7021 // Code option for GrapHist
7022
7023 if (Hoption.Line) chopth[0] = 'L';
7024 if (Hoption.Star) chopth[1] = '*';
7025 if (Hoption.Mark) chopth[2] = 'P';
7026 if (Hoption.Mark == 10) chopth[3] = '0';
7028 if (Hoption.Curve) chopth[3] = 'C';
7029 if (Hoption.Hist > 0) chopth[4] = 'H';
7030 else if (Hoption.Bar) chopth[5] = 'B';
7031 if (Hoption.Logy) chopth[6] = '1';
7032 if (fH->GetFillColor() && htype) {
7033 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
7034 chopth[7] = 'F';
7035 }
7036 }
7037 }
7038 if (!fixbin && strlen(chopth)) {
7039 chopth[8] = 'N';
7040 }
7041
7042 if (Hoption.Fill == 2) chopth[13] = '2';
7043
7044 // Option LOGX
7045
7046 if (Hoption.Logx) {
7047 chopth[9] = 'G';
7048 chopth[10] = 'X';
7049 if (fixbin) {
7050 keepx[0] = TMath::Power(10,keepx[0]);
7051 keepx[1] = TMath::Power(10,keepx[1]);
7052 }
7053 }
7054
7055 if (Hoption.Off) {
7056 chopth[11] = ']';
7057 chopth[12] = '[';
7058 }
7059
7060 // Draw the histogram
7061
7062 TGraph graph;
7063 graph.SetLineWidth(lw);
7064 graph.SetLineStyle(fH->GetLineStyle());
7065 graph.SetLineColor(fH->GetLineColor());
7066 graph.SetFillStyle(htype);
7067 graph.SetFillColor(fH->GetFillColor());
7069 graph.SetMarkerSize(fH->GetMarkerSize());
7072
7073 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
7074
7077
7079}
7080
7081////////////////////////////////////////////////////////////////////////////////
7082/// [Control function to draw a 3D histograms.](\ref HP01d)
7083
7085{
7086
7087 TString cmd;
7088 TString opt = option;
7089 opt.ToLower();
7090 Int_t irep;
7091 Float_t NEntries = fH->GetEntries();
7092
7093 if (fCurrentF3 || strstr(opt,"tf3")) {
7094 PaintTF3();
7095 return;
7096 }
7097
7098 if (NEntries > 0) {
7099 if (Hoption.Box || Hoption.Lego || Hoption.Color) {
7100 if (Hoption.Box == 11 || Hoption.Lego == 11) {
7101 PaintH3Box(1);
7102 } else if (Hoption.Box == 12 || Hoption.Lego == 12 || Hoption.Color == 1) {
7103 PaintH3Box(2);
7104 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
7105 PaintH3Box(3);
7106 } else {
7108 }
7109 return;
7110 }
7111
7112 if (strstr(opt,"iso")) {
7113 PaintH3Iso();
7114 return;
7115 }
7116 }
7117
7118 TView *view = gPad ? gPad->GetView() : nullptr;
7119 if (!view) return;
7120
7121 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
7122 if (strstr(opt,"bb")) Hoption.BackBox = 0;
7123
7124 Double_t thedeg = 90 - gPad->GetTheta();
7125 Double_t phideg = -90 - gPad->GetPhi();
7126 Double_t psideg = view->GetPsi();
7127 view->SetView(phideg, thedeg, psideg, irep);
7128
7129 if(NEntries > 0) { // Paint as 3D scatter plot
7130 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
7131 gROOT->ProcessLine(cmd.Data());
7132 } else {
7133 TAxis* xAxis = fH->GetXaxis();
7134 TAxis* yAxis = fH->GetYaxis();
7135 TAxis* zAxis = fH->GetZaxis();
7136 Double_t xmin = xAxis->GetXmin();
7137 Double_t xmax = xAxis->GetXmax();
7138 Double_t ymin = yAxis->GetXmin();
7139 Double_t ymax = yAxis->GetXmax();
7140 Double_t zmin = zAxis->GetXmin();
7141 Double_t zmax = zAxis->GetXmax();
7142 view->SetRange(xmin, ymin, zmin, xmax, ymax, zmax); // Set the axis limits (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax)
7143 }
7144
7145 if (Hoption.Same) return;
7146
7147 // Draw axis
7148 view->SetOutlineToCube();
7149 TSeqCollection *ol = view->GetOutline();
7150 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7152
7153 if (!Hoption.Axis && !Hoption.Same) {
7154 TGaxis axis;
7155 PaintLegoAxis(&axis, 90);
7156 }
7157
7158 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7159 // be painted with the option colz.
7160 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7161 Int_t ndiv = fH->GetContour();
7162 if (ndiv == 0 ) {
7163 ndiv = gStyle->GetNumberContours();
7164 fH->SetContour(ndiv);
7165 }
7166 PaintPalette();
7167 }
7168
7169 // Draw title
7170 PaintTitle();
7171
7172 //Draw stats and fit results
7173 TF1 *fit = nullptr;
7174 TIter next(fFunctions);
7175 while (auto obj = next()) {
7176 if (obj->InheritsFrom(TF1::Class())) {
7177 fit = (TF1*)obj;
7178 break;
7179 }
7180 }
7181 if ((Hoption.Same%10) != 1) {
7182 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7184 }
7185 }
7186
7187}
7188
7189////////////////////////////////////////////////////////////////////////////////
7190/// Compute histogram parameters used by the drawing routines.
7191
7193{
7194
7195 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7196
7197 Int_t i;
7198 static const char *where = "PaintInit";
7200 Int_t maximum = 0;
7201 Int_t minimum = 0;
7202 if (fH->GetMaximumStored() != -1111) maximum = 1;
7203 if (fH->GetMinimumStored() != -1111) minimum = 1;
7204
7205 // Compute X axis parameters
7206
7207 Int_t last = fXaxis->GetLast();
7208 Int_t first = fXaxis->GetFirst();
7211 Hparam.xlast = last;
7212 Hparam.xfirst = first;
7215
7216 // if log scale in X, replace xmin,max by the log
7217 if (Hoption.Logx) {
7218 if (Hparam.xmax<=0) {
7219 Error(where, "cannot set X axis to log scale");
7220 return 0;
7221 }
7222 if (Hparam.xlowedge <=0 ) {
7223 if (Hoption.Same) {
7224 TH1* h1 = nullptr;
7225 TObject *obj;
7226 TIter next(gPad->GetListOfPrimitives());
7227 while ((obj = (TObject *)next())) {
7228 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7229 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7230 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7231 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7232 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7233 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7234 }
7235 if (h1) {
7237 } else {
7238 Error(where, "undefined user's coordinates. Cannot use option SAME");
7239 return 0;
7240 }
7241 } else {
7242 for (i=first; i<=last; i++) {
7243 Double_t binLow = fXaxis->GetBinLowEdge(i);
7244 if (binLow>0) {
7245 Hparam.xlowedge = binLow;
7246 break;
7247 }
7248 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7249 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7250 break;
7251 }
7252 }
7253 if (Hparam.xlowedge<=0) {
7254 Error(where, "cannot set X axis to log scale");
7255 return 0;
7256 }
7257 }
7259 }
7264 if (Hparam.xlast > last) Hparam.xlast = last;
7265 if (Hparam.xfirst < first) Hparam.xfirst = first;
7266 }
7267
7268 // Compute Y axis parameters
7269 Double_t bigp = TMath::Power(10,32);
7270 Double_t ymax = -bigp;
7271 Double_t ymin = bigp;
7272 Double_t c1, e1;
7273 Double_t xv[1];
7274 Double_t fval;
7275 TObject *f;
7276 TF1 *f1;
7277 Double_t allchan = 0;
7278 Int_t nonNullErrors = 0;
7279 TIter next(fFunctions);
7280 for (i=first; i<=last;i++) {
7281 c1 = fH->GetBinContent(i);
7283 if (Hoption.Logy) {
7284 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7285 } else {
7287 }
7288 if (Hoption.Error) {
7290 e1 = fH->GetBinError(i);
7291 else
7292 e1 = fH->GetBinErrorUp(i);
7293 if (e1 > 0) nonNullErrors++;
7296 e1 = fH->GetBinErrorLow(i);
7297
7298 if (Hoption.Logy) {
7299 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7300 } else {
7302 }
7303 }
7304 if (Hoption.Func) {
7305 xv[0] = fXaxis->GetBinCenter(i);
7306 while ((f = (TObject*) next())) {
7307 if (f->IsA() == TF1::Class()) {
7308 f1 = (TF1*)f;
7309 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7310 fval = f1->Eval(xv[0],0,0);
7311 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7313 if (Hoption.Logy) {
7314 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7315 }
7316 }
7317 }
7318 next.Reset();
7319 }
7320 allchan += c1;
7321 }
7322 if (!nonNullErrors) {
7323 if (Hoption.Error) {
7324 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7325 Hoption.Error=0;
7326 }
7327 }
7328
7329
7330 // Take into account maximum , minimum
7331
7332 if (Hoption.Logy && ymin <= 0) {
7333 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7334 else ymin = 0.001*ymax;
7335 }
7336
7337 Double_t xm = ymin;
7338 if (maximum) ymax = fH->GetMaximumStored();
7339 if (minimum) xm = fH->GetMinimumStored();
7340 if (Hoption.Logy && xm < 0) {
7341 Error(where, "log scale requested with a negative argument (%f)", xm);
7342 return 0;
7343 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7344 ymin = 0.01;
7345 ymax = 10.;
7346 } else {
7347 ymin = xm;
7348 }
7349
7350 if (ymin >= ymax) {
7351 if (Hoption.Logy) {
7352 if (ymax > 0) ymin = 0.001*ymax;
7353 else {
7354 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7355 return 0;
7356 }
7357 }
7358 else {
7359 if (ymin > 0) {
7360 ymin = 0;
7361 ymax *= 2;
7362 } else if (ymin < 0) {
7363 ymax = 0;
7364 ymin *= 2;
7365 } else {
7366 ymin = 0;
7367 ymax = 1;
7368 }
7369 }
7370 }
7371
7372 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7373 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7374 ymin = ymin*(1-1E-14);
7375 ymax = ymax*(1+1E-14);
7376 }
7377
7378 // take into account normalization factor
7379 Hparam.allchan = allchan;
7380 Double_t factor = allchan;
7381 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7382 if (allchan) factor /= allchan;
7383 if (factor == 0) factor = 1;
7384 Hparam.factor = factor;
7385 ymax = factor*ymax;
7386 ymin = factor*ymin;
7387 //just in case the norm factor is negative
7388 // this may happen with a positive norm factor and a negative integral !
7389 if (ymax < ymin) {
7390 Double_t temp = ymax;
7391 ymax = ymin;
7392 ymin = temp;
7393 }
7394
7395 // For log scales, histogram coordinates are LOG10(ymin) and
7396 // LOG10(ymax). Final adjustment (if not option "Same"
7397 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7398 // Maximum and Minimum are not defined.
7399 if (Hoption.Logy) {
7400 if (ymin <=0 || ymax <=0) {
7401 Error(where, "Cannot set Y axis to log scale");
7402 return 0;
7403 }
7405 if (!minimum) ymin += TMath::Log10(0.5);
7407 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7408 if (!Hoption.Same) {
7409 Hparam.ymin = ymin;
7410 Hparam.ymax = ymax;
7411 }
7412 return 1;
7413 }
7414
7415 // final adjustment of ymin for linear scale.
7416 // if minimum is not set , then ymin is set to zero if >0
7417 // or to ymin - margin if <0.
7418 if (!minimum) {
7419 if (Hoption.MinimumZero) {
7420 if (ymin >= 0) ymin = 0;
7421 else ymin -= yMARGIN*(ymax-ymin);
7422 } else {
7424 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7425 else ymin -= dymin;
7426 }
7427 }
7428
7429 // final adjustment of YMAXI for linear scale (if not option "Same"):
7430 // decrease histogram height to MAX% of allowed height if HMAXIM
7431 // has not been called.
7432 if (!maximum) {
7433 ymax += yMARGIN*(ymax-ymin);
7434 }
7435
7436 Hparam.ymin = ymin;
7437 Hparam.ymax = ymax;
7438 return 1;
7439}
7440
7441////////////////////////////////////////////////////////////////////////////////
7442/// Compute histogram parameters used by the drawing routines for a rotated pad.
7443
7445{
7446
7447 static const char *where = "PaintInitH";
7449 Int_t maximum = 0;
7450 Int_t minimum = 0;
7451 if (fH->GetMaximumStored() != -1111) maximum = 1;
7452 if (fH->GetMinimumStored() != -1111) minimum = 1;
7453
7454 // Compute X axis parameters
7455
7456 Int_t last = fXaxis->GetLast();
7457 Int_t first = fXaxis->GetFirst();
7460 Hparam.xlast = last;
7461 Hparam.xfirst = first;
7464
7465 // if log scale in Y, replace ymin,max by the log
7466 if (Hoption.Logy) {
7467 if (Hparam.xlowedge <=0 ) {
7470 }
7471 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7472 Error(where, "cannot set Y axis to log scale");
7473 return 0;
7474 }
7479 if (Hparam.xlast > last) Hparam.xlast = last;
7480 }
7481
7482 // Compute Y axis parameters
7483 Double_t bigp = TMath::Power(10,32);
7484 Double_t xmax = -bigp;
7485 Double_t xmin = bigp;
7486 Double_t c1, e1;
7487 Double_t xv[1];
7488 Double_t fval;
7489 Int_t i;
7490 TObject *f;
7491 TF1 *f1;
7492 Double_t allchan = 0;
7493 TIter next(fFunctions);
7494 for (i=first; i<=last;i++) {
7495 c1 = fH->GetBinContent(i);
7498 if (Hoption.Error) {
7499 e1 = fH->GetBinError(i);
7502 }
7503 if (Hoption.Func) {
7504 xv[0] = fXaxis->GetBinCenter(i);
7505 while ((f = (TObject*) next())) {
7506 if (f->IsA() == TF1::Class()) {
7507 f1 = (TF1*)f;
7508 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7509 fval = f1->Eval(xv[0],0,0);
7511 if (Hoption.Logy) {
7512 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7513 }
7514 }
7515 }
7516 next.Reset();
7517 }
7518 allchan += c1;
7519 }
7520
7521 // Take into account maximum , minimum
7522
7523 if (Hoption.Logx && xmin <= 0) {
7524 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7525 else xmin = 0.001*xmax;
7526 }
7527 Double_t xm = xmin;
7528 if (maximum) xmax = fH->GetMaximumStored();
7529 if (minimum) xm = fH->GetMinimumStored();
7530 if (Hoption.Logx && xm <= 0) {
7531 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7532 return 0;
7533 }
7534 else xmin = xm;
7535 if (xmin >= xmax) {
7536 if (Hoption.Logx) {
7537 if (xmax > 0) xmin = 0.001*xmax;
7538 else {
7539 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7540 return 0;
7541 }
7542 }
7543 else {
7544 if (xmin > 0) {
7545 xmin = 0;
7546 xmax *= 2;
7547 } else if (xmin < 0) {
7548 xmax = 0;
7549 xmin *= 2;
7550 } else {
7551 xmin = 0;
7552 xmax = 1;
7553 }
7554 }
7555 }
7556
7557 // take into account normalization factor
7558 Hparam.allchan = allchan;
7559 Double_t factor = allchan;
7560 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7561 if (allchan) factor /= allchan;
7562 if (factor == 0) factor = 1;
7563 Hparam.factor = factor;
7564 xmax = factor*xmax;
7565 xmin = factor*xmin;
7566
7567 // For log scales, histogram coordinates are LOG10(ymin) and
7568 // LOG10(ymax). Final adjustment (if not option "Same"
7569 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7570 // Maximum and Minimum are not defined.
7571 if (Hoption.Logx) {
7572 if (xmin <=0 || xmax <=0) {
7573 Error(where, "Cannot set Y axis to log scale");
7574 return 0;
7575 }
7577 if (!minimum) xmin += TMath::Log10(0.5);
7579 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7580 if (!Hoption.Same) {
7581 Hparam.xmin = xmin;
7582 Hparam.xmax = xmax;
7583 }
7584 return 1;
7585 }
7586
7587 // final adjustment of ymin for linear scale.
7588 // if minimum is not set , then ymin is set to zero if >0
7589 // or to ymin - margin if <0.
7590 if (!minimum) {
7591 if (xmin >= 0) xmin = 0;
7592 else xmin -= yMARGIN*(xmax-xmin);
7593 }
7594
7595 // final adjustment of YMAXI for linear scale (if not option "Same"):
7596 // decrease histogram height to MAX% of allowed height if HMAXIM
7597 // has not been called.
7598 if (!maximum) {
7599 xmax += yMARGIN*(xmax-xmin);
7600 }
7601 Hparam.xmin = xmin;
7602 Hparam.xmax = xmax;
7603 return 1;
7604}
7605
7606////////////////////////////////////////////////////////////////////////////////
7607/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7608
7610{
7611 // Predefined box structure
7612 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7613 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7614 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7615 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7616
7617 // Define dimensions of world space
7618 TAxis *xaxis = fH->GetXaxis();
7619 TAxis *yaxis = fH->GetYaxis();
7620 TAxis *zaxis = fH->GetZaxis();
7621
7622 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7623 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7624 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7625 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7626 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7627 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7628
7629 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7630
7631 // Set view
7632 TView *view = gPad ? gPad->GetView() : nullptr;
7633 if (!view) {
7634 Error("PaintH3", "no TView in current pad");
7635 return;
7636 }
7637 Double_t thedeg = 90 - gPad->GetTheta();
7638 Double_t phideg = -90 - gPad->GetPhi();
7639 Double_t psideg = view->GetPsi();
7640 Int_t irep;
7641 view->SetView(phideg, thedeg, psideg, irep);
7642
7643 Int_t backcolor = gPad->GetFrameFillColor();
7644 view->PadRange(backcolor);
7645
7646 // Draw back surfaces of frame box
7647 fLego->InitMoveScreen(-1.1,1.1);
7648 if (Hoption.BackBox) {
7649 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7651 fLego->BackBox(90);
7652 }
7653
7655
7656 // Define order of drawing
7657 Double_t *tnorm = view->GetTnorm();
7658 if (!tnorm) return;
7659 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7660 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7661 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7662 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7663 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7664 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7665 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7666 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7667 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7668
7669 // Set graphic attributes (colour, style, etc.)
7674
7675 fH->SetFillStyle(1001);
7676 fH->TAttFill::Modify();
7677 fH->TAttLine::Modify();
7678 Int_t ncolors = gStyle->GetNumberOfColors();
7680
7681 // Create bin boxes and draw
7685
7686 Double_t pmin[3], pmax[3], sxyz[8][3];
7687 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7688 pmin[0] = xaxis->GetBinLowEdge(ix);
7689 pmax[0] = xaxis->GetBinUpEdge(ix);
7690 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7691 pmin[1] = yaxis->GetBinLowEdge(iy);
7692 pmax[1] = yaxis->GetBinUpEdge(iy);
7693 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7694 pmin[2] = zaxis->GetBinLowEdge(iz);
7695 pmax[2] = zaxis->GetBinUpEdge(iz);
7696 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7697 Bool_t neg = kFALSE;
7698 Int_t n = 5;
7699 if (w<0) {
7700 w = -w;
7701 neg = kTRUE;
7702 }
7703 if (w < wmin) continue;
7704 if (w > wmax) w = wmax;
7705 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7706 if (scale == 0) continue;
7707 for (Int_t i=0; i<3; ++i) {
7708 Double_t c = (pmax[i] + pmin[i])*0.5;
7709 Double_t d = (pmax[i] - pmin[i])*scale;
7710 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7711 sxyz[k][i] = wxyz[k][i]*d + c;
7712 }
7713 }
7714 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7715 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7716 }
7717 Double_t x[8], y[8]; // draw bin box faces
7718 for (Int_t k=0; k<6; ++k) {
7719 for (Int_t i=0; i<4; ++i) {
7720 Int_t iv = iface[k][i];
7721 x[i] = sxyz[iv][0];
7722 y[i] = sxyz[iv][1];
7723 }
7724 x[4] = x[0] ; y[4] = y[0];
7725 if (neg) {
7726 x[5] = x[2] ; y[5] = y[2];
7727 x[6] = x[3] ; y[6] = y[3];
7728 x[7] = x[1] ; y[7] = y[1];
7729 n = 8;
7730 } else {
7731 n = 5;
7732 }
7733 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7734 if (z <= 0.) continue;
7735 if (iopt == 2) {
7736 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7738 } else {
7739 if (k == 3 || k == 5) {
7741 } else if (k == 0 || k == 1) {
7743 } else {
7745 }
7746 }
7747 fH->TAttFill::Modify();
7748 gPad->PaintFillArea(4, x, y);
7749 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7750 }
7751 }
7752 }
7753 }
7754
7755 // Draw front surfaces of frame box
7756 if (Hoption.FrontBox) fLego->FrontBox(90);
7757
7758 // Draw axis and title
7759 if (!Hoption.Axis && !Hoption.Same) {
7760 TGaxis axis;
7761 PaintLegoAxis(&axis, 90);
7762 }
7763 PaintTitle();
7764
7765 // Draw palette. if needed.
7766 if (Hoption.Zscale) {
7767 Int_t ndiv = fH->GetContour();
7768 if (ndiv == 0 ) {
7769 ndiv = gStyle->GetNumberContours();
7770 fH->SetContour(ndiv);
7771 }
7772 PaintPalette();
7773 }
7774
7775 //Draw stats and fit results
7776 TF1 *fit = nullptr;
7777 TIter next(fFunctions);
7778 while (auto obj = next()) {
7779 if (obj->InheritsFrom(TF1::Class())) {
7780 fit = (TF1*)obj;
7781 break;
7782 }
7783 }
7784 if ((Hoption.Same%10) != 1) {
7785 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7787 }
7788 }
7789
7790 fLego.reset();
7791
7794 fH->TAttFill::Modify();
7795}
7796
7797////////////////////////////////////////////////////////////////////////////////
7798/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7799
7801{
7802 // Predefined box structure
7803 Double_t wxyz[8][3] = {
7804 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7805 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7806 };
7807 Int_t iface[6][4] = {
7808 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7809 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7810 };
7811 Double_t normal[6][3] = {
7812 {0,0,-1}, {0,0,1}, // Z-, Z+
7813 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7814 };
7815
7816 // Define dimensions of world space
7817 TAxis *xaxis = fH->GetXaxis();
7818 TAxis *yaxis = fH->GetYaxis();
7819 TAxis *zaxis = fH->GetZaxis();
7820
7821 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7822 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7823 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7824 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7825 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7826 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7827
7828 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7829
7830 // Set view
7831 TView *view = gPad ? gPad->GetView() : nullptr;
7832 if (!view) {
7833 Error("PaintH3", "no TView in current pad");
7834 return;
7835 }
7836 Double_t thedeg = 90 - gPad->GetTheta();
7837 Double_t phideg = -90 - gPad->GetPhi();
7838 Double_t psideg = view->GetPsi();
7839 Int_t irep;
7840 view->SetView(phideg, thedeg, psideg, irep);
7841
7842 Int_t backcolor = gPad->GetFrameFillColor();
7843 view->PadRange(backcolor);
7844
7845 // Draw front surfaces of frame box
7846 if (Hoption.FrontBox) {
7847 fLego->InitMoveScreen(-1.1,1.1);
7849 }
7850
7851 // Initialize hidden line removal algorithm "raster screen"
7852 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7853
7854 // Define order of drawing
7855 Double_t *tnorm = view->GetTnorm();
7856 if (!tnorm) return;
7857 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7858 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7859 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7860 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7861 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7862 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7863 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7864 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7865 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7866
7867 // Set line attributes (colour, style, etc.)
7868 fH->TAttLine::Modify();
7869
7870 // Create bin boxes and draw
7871 const Int_t NTMAX = 100;
7872 Double_t tt[NTMAX][2];
7876 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7877 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7878 pmin[0] = xaxis->GetBinLowEdge(ix);
7879 pmax[0] = xaxis->GetBinUpEdge(ix);
7880 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7881 pmin[1] = yaxis->GetBinLowEdge(iy);
7882 pmax[1] = yaxis->GetBinUpEdge(iy);
7883 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7884 pmin[2] = zaxis->GetBinLowEdge(iz);
7885 pmax[2] = zaxis->GetBinUpEdge(iz);
7886 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7887 Bool_t neg = kFALSE;
7888 if (w<0) {
7889 w = -w;
7890 neg = kTRUE;
7891 }
7892 if (w < wmin) continue;
7893 if (w > wmax) w = wmax;
7894 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7895 if (scale == 0) continue;
7896 for (Int_t i=0; i<3; ++i) {
7897 Double_t c = (pmax[i] + pmin[i])*0.5;
7898 Double_t d = (pmax[i] - pmin[i])*scale;
7899 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7900 sxyz[k][i] = wxyz[k][i]*d + c;
7901 }
7902 }
7903 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7904 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7905 }
7906 for (Int_t k=0; k<6; ++k) { // draw box faces
7907 Double_t zn;
7908 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7909 if (zn <= 0) continue;
7910 for (Int_t i=0; i<4; ++i) {
7911 Int_t ip = iface[k][i];
7912 pp[i][0] = sxyz[ip][0];
7913 pp[i][1] = sxyz[ip][1];
7914 }
7915 for (Int_t i=0; i<4; ++i) {
7916 Int_t i1 = i;
7917 Int_t i2 = (i == 3) ? 0 : i + 1;
7918 Int_t nt;
7919 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7920 Double_t xdel = pp[i2][0] - pp[i1][0];
7921 Double_t ydel = pp[i2][1] - pp[i1][1];
7922 Double_t x[2], y[2];
7923 for (Int_t it = 0; it < nt; ++it) {
7924 x[0] = pp[i1][0] + xdel*tt[it][0];
7925 y[0] = pp[i1][1] + ydel*tt[it][0];
7926 x[1] = pp[i1][0] + xdel*tt[it][1];
7927 y[1] = pp[i1][1] + ydel*tt[it][1];
7928 gPad->PaintPolyLine(2, x, y);
7929 }
7930 }
7931 if (neg) {
7932 Int_t i1 = 0;
7933 Int_t i2 = 2;
7934 Int_t nt;
7935 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7936 Double_t xdel = pp[i2][0] - pp[i1][0];
7937 Double_t ydel = pp[i2][1] - pp[i1][1];
7938 Double_t x[2], y[2];
7939 for (Int_t it = 0; it < nt; ++it) {
7940 x[0] = pp[i1][0] + xdel*tt[it][0];
7941 y[0] = pp[i1][1] + ydel*tt[it][0];
7942 x[1] = pp[i1][0] + xdel*tt[it][1];
7943 y[1] = pp[i1][1] + ydel*tt[it][1];
7944 gPad->PaintPolyLine(2, x, y);
7945 }
7946 i1 = 1;
7947 i2 = 3;
7948 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7949 xdel = pp[i2][0] - pp[i1][0];
7950 ydel = pp[i2][1] - pp[i1][1];
7951 for (Int_t it = 0; it < nt; ++it) {
7952 x[0] = pp[i1][0] + xdel*tt[it][0];
7953 y[0] = pp[i1][1] + ydel*tt[it][0];
7954 x[1] = pp[i1][0] + xdel*tt[it][1];
7955 y[1] = pp[i1][1] + ydel*tt[it][1];
7956 gPad->PaintPolyLine(2, x, y);
7957 }
7958 }
7959 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7960 }
7961 }
7962 }
7963 }
7964
7965 // Draw frame box
7966 if (Hoption.BackBox) {
7967 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7969 fLego->BackBox(90);
7970 }
7971
7972 if (Hoption.FrontBox) fLego->FrontBox(90);
7973
7974 // Draw axis and title
7975 if (!Hoption.Axis && !Hoption.Same) {
7976 TGaxis axis;
7977 PaintLegoAxis(&axis, 90);
7978 }
7979 PaintTitle();
7980
7981 //Draw stats and fit results
7982 TF1 *fit = nullptr;
7983 TIter next(fFunctions);
7984 while (auto obj = next()) {
7985 if (obj->InheritsFrom(TF1::Class())) {
7986 fit = (TF1*)obj;
7987 break;
7988 }
7989 }
7990 if ((Hoption.Same%10) != 1) {
7991 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7993 }
7994 }
7995
7996 fLego.reset();
7997}
7998
7999////////////////////////////////////////////////////////////////////////////////
8000/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
8001
8003{
8004
8005 const Double_t ydiff = 1;
8006 const Double_t yligh1 = 10;
8007 const Double_t qa = 0.15;
8008 const Double_t qd = 0.15;
8009 const Double_t qs = 0.8;
8011 Int_t i, irep;
8012 Int_t nbcol = 28;
8013 Int_t icol1 = 201;
8014 Int_t ic1 = icol1;
8015 Int_t ic2 = ic1+nbcol;
8016 Int_t ic3 = ic2+nbcol;
8017
8018 TAxis *xaxis = fH->GetXaxis();
8019 TAxis *yaxis = fH->GetYaxis();
8020 TAxis *zaxis = fH->GetZaxis();
8021
8022 Int_t nx = fH->GetNbinsX();
8023 Int_t ny = fH->GetNbinsY();
8024 Int_t nz = fH->GetNbinsZ();
8025
8026 std::vector<Double_t> x(nx);
8027 std::vector<Double_t> y(ny);
8028 std::vector<Double_t> z(nz);
8029
8030 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
8031 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
8032 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
8033
8034 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
8035 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
8036 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
8037 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
8038 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
8039 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
8040
8041 Double_t s[3];
8042 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
8043 s[1] = 0.5*s[0];
8044 s[2] = 1.5*s[0];
8045
8046 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
8047
8048 TView *view = gPad ? gPad->GetView() : nullptr;
8049 if (!view) {
8050 Error("PaintH3Iso", "no TView in current pad");
8051 return;
8052 }
8053 Double_t thedeg = 90 - gPad->GetTheta();
8054 Double_t phideg = -90 - gPad->GetPhi();
8055 Double_t psideg = view->GetPsi();
8056 view->SetView(phideg, thedeg, psideg, irep);
8057
8058 Int_t backcolor = gPad->GetFrameFillColor();
8059 if (Hoption.System != kCARTESIAN) backcolor = 0;
8060 view->PadRange(backcolor);
8061
8062 Double_t dcol = 0.5/Double_t(nbcol);
8063 TColor *colref = gROOT->GetColor(fH->GetFillColor());
8064 if (!colref) {
8065 return;
8066 }
8067 Float_t r, g, b, hue, light, satur;
8068 colref->GetRGB(r,g,b);
8070 TColor *acol;
8071 for (Int_t col=0;col<nbcol;col++) {
8072 acol = gROOT->GetColor(col+icol1);
8073 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
8074 if (acol) acol->SetRGB(r, g, b);
8075 }
8076
8077 fLego->InitMoveScreen(-1.1,1.1);
8078
8079 if (Hoption.BackBox) {
8080 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8082 fLego->BackBox(90);
8083 }
8084
8085 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
8086 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
8087 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8088 fmin = ydiff*qa;
8089 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
8090 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
8091
8092 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
8093
8094 if (Hoption.FrontBox) {
8095 fLego->InitMoveScreen(-1.1,1.1);
8097 fLego->FrontBox(90);
8098 }
8099 if (!Hoption.Axis && !Hoption.Same) {
8100 TGaxis axis;
8101 PaintLegoAxis(&axis, 90);
8102 }
8103
8104 PaintTitle();
8105
8106 //Draw stats and fit results
8107 TF1 *fit = nullptr;
8108 TIter next(fFunctions);
8109 while (auto obj = next()) {
8110 if (obj->InheritsFrom(TF1::Class())) {
8111 fit = (TF1*)obj;
8112 break;
8113 }
8114 }
8115 if ((Hoption.Same%10) != 1) {
8116 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
8118 }
8119 }
8120
8121 fLego.reset();
8122}
8123
8124////////////////////////////////////////////////////////////////////////////////
8125/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
8126
8128{
8129
8130 Int_t raster = 1;
8131 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8132 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
8133 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
8134 Double_t zmin = Hparam.zmin;
8135 Double_t zmax = Hparam.zmax;
8140 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8141 Double_t deltaz = TMath::Abs(zmin);
8142 if (deltaz == 0) deltaz = 1;
8143 if (zmin >= zmax) {
8144 zmin -= 0.5*deltaz;
8145 zmax += 0.5*deltaz;
8146 }
8147 Double_t z1c = zmin;
8148 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8149
8150 // Compute the lego limits and instantiate a lego object
8151 fXbuf[0] = -1;
8152 fYbuf[0] = 1;
8153 fXbuf[1] = -1;
8154 fYbuf[1] = 1;
8155 if (Hoption.System == kPOLAR) {
8156 fXbuf[2] = z1c;
8157 fYbuf[2] = z2c;
8158 } else if (Hoption.System == kCYLINDRICAL) {
8159 if (Hoption.Logy) {
8160 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8161 else fXbuf[2] = 0;
8162 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8163 else fYbuf[2] = 0;
8164 } else {
8165 fXbuf[2] = ylab1;
8166 fYbuf[2] = ylab2;
8167 }
8168 z1c = 0; z2c = 1;
8169 } else if (Hoption.System == kSPHERICAL) {
8170 fXbuf[2] = -1;
8171 fYbuf[2] = 1;
8172 z1c = 0; z2c = 1;
8173 } else if (Hoption.System == kRAPIDITY) {
8174 fXbuf[2] = -1/TMath::Tan(dangle);
8175 fYbuf[2] = 1/TMath::Tan(dangle);
8176 } else {
8177 fXbuf[0] = xlab1;
8178 fYbuf[0] = xlab2;
8179 fXbuf[1] = ylab1;
8180 fYbuf[1] = ylab2;
8181 fXbuf[2] = z1c;
8182 fYbuf[2] = z2c;
8183 raster = 0;
8184 }
8185
8186 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
8187
8188 Int_t nids = -1;
8189 TH1 * hid = nullptr;
8190 Color_t colormain = -1, colordark = -1;
8192
8193 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8194 if (Hoption.Lego == 13) {
8195 Hoption.Lego = 11;
8196 fLego->SetMesh(0);
8197 }
8198 // LEGO4 is like LEGO1 except no shadows are drawn.
8199 if (Hoption.Lego == 14) {
8200 Hoption.Lego = 11;
8202 }
8203
8204 // Initialize the levels on the Z axis
8205 Int_t ndiv = fH->GetContour();
8206 if (ndiv == 0 ) {
8207 ndiv = gStyle->GetNumberContours();
8208 fH->SetContour(ndiv);
8209 }
8210 Int_t ndivz = TMath::Abs(ndiv);
8211 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8212
8213 // Initialize colors
8214 if (!fStack) {
8215 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8216 } else {
8217 for (Int_t id=0;id<=fStack->GetSize();id++) {
8218 hid = (TH1*)fStack->At((id==0)?id:id-1);
8219 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8220 }
8221 }
8222
8223 if (Hoption.Lego == 11) {
8224 nids = 1;
8225 if (fStack) nids = fStack->GetSize();
8226 hid = fH;
8227 for (Int_t id=0;id<=nids;id++) {
8228 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8229 colormain = hid->GetFillColor();
8230 if (colormain == 1) colormain = 17; //avoid drawing with black
8232 else colordark = colormain;
8233 fLego->SetColorMain(colormain,id);
8234 fLego->SetColorDark(colordark,id);
8235 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8236 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8237 }
8238 }
8239
8240 // Now ready to draw the lego plot
8241 Int_t irep = 0;
8242
8243 TView *view = gPad ? gPad->GetView() : nullptr;
8244 if (!view) {
8245 Error("PaintLego", "no TView in current pad");
8246 return;
8247 }
8248
8249 Double_t thedeg = 90 - gPad->GetTheta();
8250 Double_t phideg = -90 - gPad->GetPhi();
8251 Double_t psideg = view->GetPsi();
8252 view->SetView(phideg, thedeg, psideg, irep);
8253
8254 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8255 fLego->SetFillStyle(fH->GetFillStyle());
8256
8257 // Set color/style for back box
8258 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8259 fLego->SetFillColor(gPad->GetFrameFillColor());
8260 fLego->TAttFill::Modify();
8261
8262 Int_t backcolor = gPad->GetFrameFillColor();
8263 if (Hoption.System != kCARTESIAN) backcolor = 0;
8264 view->PadRange(backcolor);
8265
8266 fLego->SetFillStyle(fH->GetFillStyle());
8267 fLego->SetFillColor(fH->GetFillColor());
8268 fLego->TAttFill::Modify();
8269
8270 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8271
8272 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8273 else fLego->InitMoveScreen(-1.1,1.1);
8274
8275 if (Hoption.Lego == 19) {
8277 if (Hoption.BackBox) fLego->BackBox(90);
8278 if (Hoption.FrontBox) fLego->FrontBox(90);
8279 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8280 return;
8281 }
8282
8283 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8286 fLego->BackBox(90);
8287 }
8288 }
8289
8290 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8291
8292 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8294 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8295 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8296 if (Hoption.System == kPOLAR) {
8297 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8298 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8299 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8300 } else if (Hoption.System == kCYLINDRICAL) {
8301 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8302 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8303 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8304 } else if (Hoption.System == kSPHERICAL) {
8305 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8306 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8307 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8308 } else if (Hoption.System == kRAPIDITY) {
8309 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8310 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8311 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8312 } else {
8313 if (Hoption.Lego == 1) {
8315 fLego->LegoCartesian(90,nx,ny,"FB");}
8316 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8317 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8318 }
8319
8320 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8323 fLego->BackBox(90);
8324 }
8325 }
8326 if (Hoption.System == kCARTESIAN) {
8327 fLego->InitMoveScreen(-1.1,1.1);
8329 if (Hoption.FrontBox) fLego->FrontBox(90);
8330 }
8331 if (!Hoption.Axis && !Hoption.Same) {
8332 TGaxis axis;
8333 PaintLegoAxis(&axis, 90);
8334 }
8336 fLego.reset();
8337}
8338
8339////////////////////////////////////////////////////////////////////////////////
8340/// Draw the axis for legos and surface plots.
8341
8343{
8344
8345 static Double_t epsil = 0.001;
8346
8349 Double_t r[24] /* was [3][8] */;
8350 Int_t ndivx, ndivy, ndivz, i;
8351 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8352 static char chopax[8], chopay[8], chopaz[8];
8353 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8354 Double_t rad;
8355
8356 TView *view = gPad ? gPad->GetView() : nullptr;
8357 if (!view) {
8358 Error("PaintLegoAxis", "no TView in current pad");
8359 return;
8360 }
8361
8362 // In polar coordinates, draw a short line going from the external circle
8363 // corresponding to r = 1 up to r = 1.1
8364 if (Hoption.System == kPOLAR) {
8365 r[0] = 1;
8366 r[1] = 0;
8367 r[2] = 0;
8368 view->WCtoNDC(r, x1);
8369 r[0] = 1.1;
8370 r[1] = 0;
8371 r[2] = 0;
8372 view->WCtoNDC(r, x2);
8373 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8374 return;
8375 }
8376
8377 if (Hoption.System != kCARTESIAN) return;
8378
8379 rad = TMath::ATan(1.) * 4. /180.;
8380 cosa = TMath::Cos(ang*rad);
8381 sina = TMath::Sin(ang*rad);
8382
8383 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8384 for (i = 1; i <= 8; ++i) {
8385 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8386 r[i*3 - 2] = av[i*3 - 2]*sina;
8387 r[i*3 - 1] = av[i*3 - 1];
8388 }
8389
8390 view->WCtoNDC(&r[ix1*3 - 3], x1);
8391 view->WCtoNDC(&r[ix2*3 - 3], x2);
8392 view->WCtoNDC(&r[iy1*3 - 3], y1);
8393 view->WCtoNDC(&r[iy2*3 - 3], y2);
8394 view->WCtoNDC(&r[iz1*3 - 3], z1);
8395 view->WCtoNDC(&r[iz2*3 - 3], z2);
8396
8397 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8398
8399 Double_t *rmin = view->GetRmin();
8400 Double_t *rmax = view->GetRmax();
8401 if (!rmin || !rmax) return;
8402
8403 // Initialize the axis options
8404 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8405 else strlcpy(chopax, "SDH=-",8);
8406 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8407 else strlcpy(chopay, "SDH=-",8);
8408 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8409 else strlcpy(chopaz, "SDH=-",8);
8410
8411 // Option LOG is required ?
8412 if (Hoption.Logx) strlcat(chopax,"G",8);
8413 if (Hoption.Logy) strlcat(chopay,"G",8);
8414 if (Hoption.Logz) strlcat(chopaz,"G",8);
8415
8416 // Initialize the number of divisions. If the
8417 // number of divisions is negative, option 'N' is required.
8421 if (ndivx < 0) {
8423 strlcat(chopax, "N",8);
8424 }
8425 if (ndivy < 0) {
8427 strlcat(chopay, "N",8);
8428 }
8429 if (ndivz < 0) {
8431 strlcat(chopaz, "N",8);
8432 }
8433
8434 // Set Axis attributes.
8435 // The variable SCALE rescales the VSIZ
8436 // in order to have the same label size for all angles.
8437
8438 axis->SetLineWidth(1);
8439
8440 // X axis drawing
8441 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8444 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8445 bmin = TMath::Power(10, rmin[0]);
8446 bmax = TMath::Power(10, rmax[0]);
8447 } else {
8448 bmin = rmin[0];
8449 bmax = rmax[0];
8450 }
8451 // Option time display is required ?
8452 if (fXaxis->GetTimeDisplay()) {
8453 strlcat(chopax,"t",8);
8454 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8456 } else {
8458 }
8459 }
8460 axis->SetOption(chopax);
8461 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8462 }
8463
8464 // Y axis drawing
8465 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8468 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8469
8470 if (fH->GetDimension() < 2) {
8471 strlcpy(chopay, "V=+UN",8);
8472 ndivy = 0;
8473 }
8474 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8475 y2[0] = y1[0];
8476 }
8477 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8478 bmin = TMath::Power(10, rmin[1]);
8479 bmax = TMath::Power(10, rmax[1]);
8480 } else {
8481 bmin = rmin[1];
8482 bmax = rmax[1];
8483 }
8484 // Option time display is required ?
8485 if (fYaxis->GetTimeDisplay()) {
8486 strlcat(chopay,"t",8);
8487 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8489 } else {
8491 }
8492 }
8493 axis->SetOption(chopay);
8494 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8495 }
8496
8497 // Z axis drawing
8498 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8500 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8501 bmin = TMath::Power(10, rmin[2]);
8502 bmax = TMath::Power(10, rmax[2]);
8503 } else {
8504 bmin = rmin[2];
8505 bmax = rmax[2];
8506 }
8507 // Option time display is required ?
8508 if (fZaxis->GetTimeDisplay()) {
8509 strlcat(chopaz,"t",8);
8510 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8512 } else {
8514 }
8515 }
8516 axis->SetOption(chopaz);
8518 if (ztit.Index(";")>0) {
8519 ztit.Remove(ztit.Index(";"),ztit.Length());
8520 axis->SetTitle(ztit.Data());
8521 }
8522 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8523 }
8524
8525 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8526}
8527
8528////////////////////////////////////////////////////////////////////////////////
8529/// [Paint the color palette on the right side of the pad.](\ref HP22)
8530
8532{
8534 TView *view = gPad ? gPad->GetView() : nullptr;
8535 if (palette) {
8536 if (view) {
8537 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8539 delete palette; palette = nullptr;
8540 }
8541 } else {
8542 if (palette->TestBit(TPaletteAxis::kHasView)) {
8544 delete palette; palette = nullptr;
8545 }
8546 }
8547 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8548 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8549 }
8550
8551 if (!palette) {
8552 Double_t xup = gPad->GetUxmax();
8553 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8554 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8555 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8556 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8557 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8558 Double_t xmax = gPad->PadtoX(xup + xr);
8559 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8562 palette->Paint();
8563 }
8564}
8565
8566////////////////////////////////////////////////////////////////////////////////
8567/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8568
8570{
8571
8572 fH->TAttMarker::Modify();
8573
8574 Int_t k, marker;
8575 Double_t dz, z, xk,xstep, yk, ystep;
8576 Double_t scale = 1;
8578 Double_t zmax = fH->GetMaximum();
8579 Double_t zmin = fH->GetMinimum();
8580 if (zmin == 0 && zmax == 0) return;
8581 if (zmin == zmax) {
8582 zmax += 0.1*TMath::Abs(zmax);
8583 zmin -= 0.1*TMath::Abs(zmin);
8584 }
8586 if (Hoption.Logz) {
8587 if (zmin > 0) zmin = TMath::Log10(zmin);
8588 else zmin = 0;
8589 if (zmax > 0) zmax = TMath::Log10(zmax);
8590 else zmax = 0;
8591 if (zmin == 0 && zmax == 0) return;
8592 dz = zmax - zmin;
8593 scale = 100/dz;
8594 if (ncells > 10000) scale /= 5;
8595 ltest = kTRUE;
8596 } else {
8597 dz = zmax - zmin;
8598 if (dz >= kNMAX || zmax < 1) {
8599 scale = (kNMAX-1)/dz;
8600 if (ncells > 10000) scale /= 5;
8601 ltest = kTRUE;
8602 }
8603 }
8604 if (fH->GetMinimumStored() == -1111) {
8606 if (Hoption.MinimumZero) {
8607 if (zmin >= 0) zmin = 0;
8608 else zmin -= yMARGIN*(zmax-zmin);
8609 } else {
8610 Double_t dzmin = yMARGIN*(zmax-zmin);
8611 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8612 else zmin -= dzmin;
8613 }
8614 }
8615
8616 TString opt = option;
8617 opt.ToLower();
8618 if (opt.Contains("scat=")) {
8619 char optscat[100];
8620 strlcpy(optscat,opt.Data(),100);
8621 char *oscat = strstr(optscat,"scat=");
8622 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8623 sscanf(oscat+5,"%lg",&scale);
8624 }
8625 // use an independent instance of a random generator
8626 // instead of gRandom to avoid conflicts and
8627 // to get same random numbers when drawing the same histogram
8629 marker=0;
8630 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8633 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8634 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8635 xk = fXaxis->GetBinLowEdge(i);
8636 xstep = fXaxis->GetBinWidth(i);
8637 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8638 z = fH->GetBinContent(bin);
8639 if (z < zmin) z = zmin;
8640 if (z > zmax) z = zmax;
8641 if (Hoption.Logz) {
8642 if (z > 0) z = TMath::Log10(z) - zmin;
8643 } else {
8644 z -= zmin;
8645 }
8646 if (z <= 0) continue;
8647 k = Int_t(z*scale);
8648 if (ltest) k++;
8649 if (k > 0) {
8650 for (Int_t loop=0; loop<k; loop++) {
8651 if (k+marker >= kNMAX) {
8652 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8653 marker=0;
8654 }
8655 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8656 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8657 if (Hoption.Logx) {
8658 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8659 else break;
8660 }
8661 if (Hoption.Logy) {
8662 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8663 else break;
8664 }
8665 if (fXbuf[marker] < gPad->GetUxmin()) break;
8666 if (fYbuf[marker] < gPad->GetUymin()) break;
8667 if (fXbuf[marker] > gPad->GetUxmax()) break;
8668 if (fYbuf[marker] > gPad->GetUymax()) break;
8669 marker++;
8670 }
8671 }
8672 }
8673 }
8674 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8675
8677}
8678
8679////////////////////////////////////////////////////////////////////////////////
8680/// Static function to paint special objects like vectors and matrices.
8681/// This function is called via `gROOT->ProcessLine` to paint these objects
8682/// without having a direct dependency of the graphics or histogramming
8683/// system.
8684
8686{
8687
8688 if (!obj) return;
8689 TDirectory::TContext ctx{nullptr}; // No self-registration to directories
8690
8691 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8692 // case TMatrixF
8693 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8694 R__TMatrixFBase->SetBit(kCanDelete);
8695 R__TMatrixFBase->Draw(option);
8696
8697 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8698 // case TMatrixD
8699 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8700 R__TMatrixDBase->SetBit(kCanDelete);
8701 R__TMatrixDBase->Draw(option);
8702
8703 } else if (obj->InheritsFrom(TVectorF::Class())) {
8704 //case TVectorF
8705 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8706 R__TVectorF->SetBit(kCanDelete);
8707 R__TVectorF->Draw(option);
8708
8709 } else if (obj->InheritsFrom(TVectorD::Class())) {
8710 //case TVectorD
8711 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8712 R__TVectorD->SetBit(kCanDelete);
8713 R__TVectorD->Draw(option);
8714 }
8715}
8716
8717////////////////////////////////////////////////////////////////////////////////
8718/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8719
8721{
8722 TString tt, tf;
8723 Int_t dofit;
8724 TPaveStats *stats = nullptr;
8725 TIter next(fFunctions);
8726 while (auto obj = next()) {
8727 if (obj->InheritsFrom(TPaveStats::Class())) {
8728 stats = (TPaveStats*)obj;
8729 break;
8730 }
8731 }
8732
8733 if (stats && dostat) {
8734 dofit = stats->GetOptFit();
8735 dostat = stats->GetOptStat();
8736 } else {
8737 dofit = gStyle->GetOptFit();
8738 }
8739 if (!dofit) fit = nullptr;
8740 if (dofit == 1) dofit = 111;
8741 if (dostat == 1) dostat = 1111;
8742 Int_t print_name = dostat%10;
8743 Int_t print_entries = (dostat/10)%10;
8744 Int_t print_mean = (dostat/100)%10;
8745 Int_t print_stddev = (dostat/1000)%10;
8746 Int_t print_under = (dostat/10000)%10;
8747 Int_t print_over = (dostat/100000)%10;
8748 Int_t print_integral= (dostat/1000000)%10;
8749 Int_t print_skew = (dostat/10000000)%10;
8750 Int_t print_kurt = (dostat/100000000)%10;
8754 Int_t print_fval = dofit%10;
8755 Int_t print_ferrors = (dofit/10)%10;
8756 Int_t print_fchi2 = (dofit/100)%10;
8757 Int_t print_fprob = (dofit/1000)%10;
8759 if (fit) {
8760 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8761 else nlinesf += fit->GetNpar();
8762 }
8764
8765 // Pavetext with statistics
8766 Bool_t done = kFALSE;
8767 if (!dostat && !fit) {
8768 if (stats) { fFunctions->Remove(stats); delete stats;}
8769 return;
8770 }
8772 if (fit) statw = 1.8*gStyle->GetStatW();
8774 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8775 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8776 }
8777 if (stats) {
8778 stats->Clear();
8779 done = kTRUE;
8780 } else {
8781 stats = new TPaveStats(
8784 gStyle->GetStatX(),
8785 gStyle->GetStatY(),"brNDC");
8786
8787 stats->SetParent(fH);
8788 stats->SetOptFit(dofit);
8789 stats->SetOptStat(dostat);
8790 stats->SetFillColor(gStyle->GetStatColor());
8791 stats->SetFillStyle(gStyle->GetStatStyle());
8793 stats->SetTextFont(gStyle->GetStatFont());
8794 if (gStyle->GetStatFont()%10 > 2)
8796 stats->SetFitFormat(gStyle->GetFitFormat());
8798 stats->SetName("stats");
8799
8801 stats->SetTextAlign(12);
8802 stats->SetBit(kCanDelete);
8803 stats->SetBit(kMustCleanup);
8804 }
8805 if (print_name) stats->AddText(fH->GetName());
8806 if (print_entries) {
8807 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8808 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8809 stats->AddText(tt.Data());
8810 }
8811 if (print_mean) {
8812 if (print_mean == 1) {
8813 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8814 tt.Form(tf.Data(),fH->GetMean(1));
8815 } else {
8816 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8817 ,"%",stats->GetStatFormat());
8818 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8819 }
8820 stats->AddText(tt.Data());
8822 if (print_mean == 1) {
8823 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8824 tt.Form(tf.Data(),fH->GetMean(2));
8825 } else {
8826 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8827 ,"%",stats->GetStatFormat());
8828 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8829 }
8830 stats->AddText(tt.Data());
8831 }
8832 }
8833 if (print_stddev) {
8834 if (print_stddev == 1) {
8835 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8836 tt.Form(tf.Data(),fH->GetStdDev(1));
8837 } else {
8838 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8839 ,"%",stats->GetStatFormat());
8840 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8841 }
8842 stats->AddText(tt.Data());
8844 if (print_stddev == 1) {
8845 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8846 tt.Form(tf.Data(),fH->GetStdDev(2));
8847 } else {
8848 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8849 ,"%",stats->GetStatFormat());
8850 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8851 }
8852 stats->AddText(tt.Data());
8853 }
8854 }
8855 if (print_under) {
8856 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8857 tt.Form(tf.Data(),fH->GetBinContent(0));
8858 stats->AddText(tt.Data());
8859 }
8860 if (print_over) {
8861 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8862 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8863 stats->AddText(tt.Data());
8864 }
8865 if (print_integral) {
8866 if (print_integral == 1) {
8867 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8868 tt.Form(tf.Data(),fH->Integral());
8869 } else {
8870 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8871 tt.Form(tf.Data(),fH->Integral("width"));
8872 }
8873 stats->AddText(tt.Data());
8874 }
8875 if (print_skew) {
8876 if (print_skew == 1) {
8877 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8878 tt.Form(tf.Data(),fH->GetSkewness(1));
8879 } else {
8880 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8881 ,"%",stats->GetStatFormat());
8882 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8883 }
8884 stats->AddText(tt.Data());
8885 }
8886 if (print_kurt) {
8887 if (print_kurt == 1) {
8888 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8889 tt.Form(tf.Data(),fH->GetKurtosis(1));
8890 } else {
8891 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8892 ,"%",stats->GetStatFormat());
8893 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8894 }
8895 stats->AddText(tt.Data());
8896 }
8897
8898 // Draw Fit parameters
8899 if (fit) {
8900 Int_t ndf = fit->GetNDF();
8901 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8902 tt.Form(tf.Data(),fit->GetChisquare());
8903 if (print_fchi2) stats->AddText(tt.Data());
8904 if (print_fprob) {
8905 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8906 tt.Form(tf.Data(),TMath::Prob(fit->GetChisquare(),ndf));
8907 stats->AddText(tt.Data());
8908 }
8909 if (print_fval || print_ferrors) {
8911 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8912 fit->GetParLimits(ipar,parmin,parmax);
8914 if (print_ferrors) {
8915 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8916 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8917 tt.Form(tf.Data(),fit->GetParameter(ipar)
8918 ,fit->GetParError(ipar));
8919 } else {
8920 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8921 tt.Form(tf.Data(),fit->GetParameter(ipar));
8922 }
8923 stats->AddText(tt.Data());
8924 }
8925 }
8926 }
8927
8928 if (!done) fFunctions->Add(stats);
8929 stats->Paint(stats->GetOption());
8930}
8931
8932////////////////////////////////////////////////////////////////////////////////
8933/// [Draw the statistics box for 2D histograms.](\ref HP07)
8934
8936{
8937
8938 if (fH->GetDimension() != 2) return;
8939 TH2 *h2 = (TH2*)fH;
8940
8941 TString tt, tf;
8942 Int_t dofit;
8943 TPaveStats *stats = nullptr;
8944 TIter next(fFunctions);
8945 while (auto obj = next()) {
8946 if (obj->InheritsFrom(TPaveStats::Class())) {
8947 stats = (TPaveStats*)obj;
8948 break;
8949 }
8950 }
8951 if (stats && dostat) {
8952 dofit = stats->GetOptFit();
8953 dostat = stats->GetOptStat();
8954 } else {
8955 dofit = gStyle->GetOptFit();
8956 }
8957 if (dostat == 1) dostat = 1111;
8958 Int_t print_name = dostat%10;
8959 Int_t print_entries = (dostat/10)%10;
8960 Int_t print_mean = (dostat/100)%10;
8961 Int_t print_stddev = (dostat/1000)%10;
8962 Int_t print_under = (dostat/10000)%10;
8963 Int_t print_over = (dostat/100000)%10;
8964 Int_t print_integral= (dostat/1000000)%10;
8965 Int_t print_skew = (dostat/10000000)%10;
8966 Int_t print_kurt = (dostat/100000000)%10;
8968 if (print_under || print_over) nlines += 3;
8969
8970 // Pavetext with statistics
8971 if (!gStyle->GetOptFit()) fit = nullptr;
8972 Bool_t done = kFALSE;
8973 if (!dostat && !fit) {
8974 if (stats) { fFunctions->Remove(stats); delete stats;}
8975 return;
8976 }
8978 if (fit) statw = 1.8*gStyle->GetStatW();
8980 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8981 stath = 0.25*nlines*gStyle->GetStatH();
8982 }
8983 if (fit) stath += gStyle->GetStatH();
8984 if (stats) {
8985 stats->Clear();
8986 done = kTRUE;
8987 } else {
8988 stats = new TPaveStats(
8991 gStyle->GetStatX(),
8992 gStyle->GetStatY(),"brNDC");
8993
8994 stats->SetParent(fH);
8995 stats->SetOptFit(dofit);
8996 stats->SetOptStat(dostat);
8997 stats->SetFillColor(gStyle->GetStatColor());
8998 stats->SetFillStyle(gStyle->GetStatStyle());
9000 stats->SetName("stats");
9001
9003 stats->SetTextAlign(12);
9004 stats->SetTextFont(gStyle->GetStatFont());
9005 if (gStyle->GetStatFont()%10 > 2)
9007 stats->SetFitFormat(gStyle->GetFitFormat());
9009 stats->SetBit(kCanDelete);
9010 stats->SetBit(kMustCleanup);
9011 }
9012 if (print_name) stats->AddText(h2->GetName());
9013 if (print_entries) {
9014 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
9015 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
9016 stats->AddText(tt.Data());
9017 }
9018 if (print_mean) {
9019 if (print_mean == 1) {
9020 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9021 tt.Form(tf.Data(),h2->GetMean(1));
9022 stats->AddText(tt.Data());
9023 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9024 tt.Form(tf.Data(),h2->GetMean(2));
9025 stats->AddText(tt.Data());
9026 } else {
9027 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9028 ,"%",stats->GetStatFormat());
9029 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
9030 stats->AddText(tt.Data());
9031 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9032 ,"%",stats->GetStatFormat());
9033 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
9034 stats->AddText(tt.Data());
9035 }
9036 }
9037 if (print_stddev) {
9038 if (print_stddev == 1) {
9039 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9040 tt.Form(tf.Data(),h2->GetStdDev(1));
9041 stats->AddText(tt.Data());
9042 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9043 tt.Form(tf.Data(),h2->GetStdDev(2));
9044 stats->AddText(tt.Data());
9045 } else {
9046 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9047 ,"%",stats->GetStatFormat());
9048 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
9049 stats->AddText(tt.Data());
9050 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9051 ,"%",stats->GetStatFormat());
9052 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
9053 stats->AddText(tt.Data());
9054 }
9055 }
9056 if (print_integral) {
9057 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
9058 tt.Form(tf.Data(),fH->Integral());
9059 stats->AddText(tt.Data());
9060 }
9061 if (print_skew) {
9062 if (print_skew == 1) {
9063 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9064 tt.Form(tf.Data(),h2->GetSkewness(1));
9065 stats->AddText(tt.Data());
9066 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9067 tt.Form(tf.Data(),h2->GetSkewness(2));
9068 stats->AddText(tt.Data());
9069 } else {
9070 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9071 ,"%",stats->GetStatFormat());
9072 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
9073 stats->AddText(tt.Data());
9074 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9075 ,"%",stats->GetStatFormat());
9076 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
9077 stats->AddText(tt.Data());
9078 }
9079 }
9080 if (print_kurt) {
9081 if (print_kurt == 1) {
9082 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9083 tt.Form(tf.Data(),h2->GetKurtosis(1));
9084 stats->AddText(tt.Data());
9085 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9086 tt.Form(tf.Data(),h2->GetKurtosis(2));
9087 stats->AddText(tt.Data());
9088 } else {
9089 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9090 ,"%",stats->GetStatFormat());
9091 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
9092 stats->AddText(tt.Data());
9093 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9094 ,"%",stats->GetStatFormat());
9095 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
9096 stats->AddText(tt.Data());
9097 }
9098 }
9099 if (print_under || print_over) {
9100 //get 3*3 under/overflows for 2d hist
9101 Double_t unov[9];
9102
9103 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
9104 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
9105 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
9106 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
9107 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
9108 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
9109
9110 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
9111 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
9112 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
9113 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
9114 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
9115 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
9116 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
9117 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
9118 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
9119
9120 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
9121 stats->AddText(tt.Data());
9122 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
9123 stats->AddText(tt.Data());
9124 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
9125 stats->AddText(tt.Data());
9126 }
9127
9128 // Draw Fit parameters
9129 if (fit) {
9130 Int_t ndf = fit->GetNDF();
9131 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9132 stats->AddText(tt.Data());
9133 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9134 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9135 ,fit->GetParameter(ipar)
9136 ,fit->GetParError(ipar));
9137 stats->AddText(tt.Data());
9138 }
9139 }
9140
9141 if (!done) fFunctions->Add(stats);
9142 stats->Paint(stats->GetOption());
9143}
9144
9145////////////////////////////////////////////////////////////////////////////////
9146/// [Draw the statistics box for 3D histograms.](\ref HP07)
9147
9149{
9150
9151 if (fH->GetDimension() != 3) return;
9152 TH3 *h3 = (TH3*)fH;
9153
9154 TString tt, tf;
9155 Int_t dofit;
9156 TPaveStats *stats = nullptr;
9157 TIter next(fFunctions);
9158 while (auto obj = next()) {
9159 if (obj->InheritsFrom(TPaveStats::Class())) {
9160 stats = (TPaveStats*)obj;
9161 break;
9162 }
9163 }
9164 if (stats && dostat) {
9165 dofit = stats->GetOptFit();
9166 dostat = stats->GetOptStat();
9167 } else {
9168 dofit = gStyle->GetOptFit();
9169 }
9170 if (dostat == 1) dostat = 1111;
9171 Int_t print_name = dostat%10;
9172 Int_t print_entries = (dostat/10)%10;
9173 Int_t print_mean = (dostat/100)%10;
9174 Int_t print_stddev = (dostat/1000)%10;
9175 Int_t print_under = (dostat/10000)%10;
9176 Int_t print_over = (dostat/100000)%10;
9177 Int_t print_integral= (dostat/1000000)%10;
9178 Int_t print_skew = (dostat/10000000)%10;
9179 Int_t print_kurt = (dostat/100000000)%10;
9181 if (print_under || print_over) nlines += 3;
9182
9183 // Pavetext with statistics
9184 if (!gStyle->GetOptFit()) fit = nullptr;
9185 Bool_t done = kFALSE;
9186 if (!dostat && !fit) {
9187 if (stats) { fFunctions->Remove(stats); delete stats;}
9188 return;
9189 }
9191 if (fit) statw = 1.8*gStyle->GetStatW();
9193 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9194 stath = 0.25*nlines*gStyle->GetStatH();
9195 }
9196 if (fit) stath += gStyle->GetStatH();
9197 if (stats) {
9198 stats->Clear();
9199 done = kTRUE;
9200 } else {
9201 stats = new TPaveStats(
9204 gStyle->GetStatX(),
9205 gStyle->GetStatY(),"brNDC");
9206
9207 stats->SetParent(fH);
9208 stats->SetOptFit(dofit);
9209 stats->SetOptStat(dostat);
9210 stats->SetFillColor(gStyle->GetStatColor());
9211 stats->SetFillStyle(gStyle->GetStatStyle());
9213 stats->SetName("stats");
9214
9216 stats->SetTextAlign(12);
9217 stats->SetTextFont(gStyle->GetStatFont());
9218 stats->SetFitFormat(gStyle->GetFitFormat());
9220 stats->SetBit(kCanDelete);
9221 stats->SetBit(kMustCleanup);
9222 }
9223 if (print_name) stats->AddText(h3->GetName());
9224 if (print_entries) {
9225 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9226 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9227 stats->AddText(tt.Data());
9228 }
9229 if (print_mean) {
9230 if (print_mean == 1) {
9231 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9232 tt.Form(tf.Data(),h3->GetMean(1));
9233 stats->AddText(tt.Data());
9234 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9235 tt.Form(tf.Data(),h3->GetMean(2));
9236 stats->AddText(tt.Data());
9237 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9238 tt.Form(tf.Data(),h3->GetMean(3));
9239 stats->AddText(tt.Data());
9240 } else {
9241 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9242 ,"%",stats->GetStatFormat());
9243 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9244 stats->AddText(tt.Data());
9245 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9246 ,"%",stats->GetStatFormat());
9247 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9248 stats->AddText(tt.Data());
9249 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9250 ,"%",stats->GetStatFormat());
9251 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9252 stats->AddText(tt.Data());
9253 }
9254 }
9255 if (print_stddev) {
9256 if (print_stddev == 1) {
9257 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9258 tt.Form(tf.Data(),h3->GetStdDev(1));
9259 stats->AddText(tt.Data());
9260 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9261 tt.Form(tf.Data(),h3->GetStdDev(2));
9262 stats->AddText(tt.Data());
9263 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9264 tt.Form(tf.Data(),h3->GetStdDev(3));
9265 stats->AddText(tt.Data());
9266 } else {
9267 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9268 ,"%",stats->GetStatFormat());
9269 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9270 stats->AddText(tt.Data());
9271 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9272 ,"%",stats->GetStatFormat());
9273 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9274 stats->AddText(tt.Data());
9275 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9276 ,"%",stats->GetStatFormat());
9277 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9278 stats->AddText(tt.Data());
9279 }
9280 }
9281 if (print_integral) {
9282 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9283 stats->AddText(tt.Data());
9284 }
9285 if (print_skew) {
9286 if (print_skew == 1) {
9287 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9288 tt.Form(tf.Data(),h3->GetSkewness(1));
9289 stats->AddText(tt.Data());
9290 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9291 tt.Form(tf.Data(),h3->GetSkewness(2));
9292 stats->AddText(tt.Data());
9293 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9294 tt.Form(tf.Data(),h3->GetSkewness(3));
9295 stats->AddText(tt.Data());
9296 } else {
9297 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9298 ,"%",stats->GetStatFormat());
9299 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9300 stats->AddText(tt.Data());
9301 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9302 ,"%",stats->GetStatFormat());
9303 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9304 stats->AddText(tt.Data());
9305 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9306 ,"%",stats->GetStatFormat());
9307 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9308 stats->AddText(tt.Data());
9309 }
9310 }
9311 if (print_kurt) {
9312 if (print_kurt == 1) {
9313 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9314 tt.Form(tf.Data(),h3->GetKurtosis(1));
9315 stats->AddText(tt.Data());
9316 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9317 tt.Form(tf.Data(),h3->GetKurtosis(2));
9318 stats->AddText(tt.Data());
9319 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9320 tt.Form(tf.Data(),h3->GetKurtosis(3));
9321 stats->AddText(tt.Data());
9322 } else {
9323 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9324 ,"%",stats->GetStatFormat());
9325 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9326 stats->AddText(tt.Data());
9327 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9328 ,"%",stats->GetStatFormat());
9329 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9330 stats->AddText(tt.Data());
9331 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9332 ,"%",stats->GetStatFormat());
9333 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9334 stats->AddText(tt.Data());
9335 }
9336 }
9337 if (print_under || print_over) {
9338 // no underflow - overflow printing for a 3D histogram
9339 // one would need a 3D table
9340 }
9341
9342 // Draw Fit parameters
9343 if (fit) {
9344 Int_t ndf = fit->GetNDF();
9345 tt.Form("#chi^{2} / ndf = %6.4g / %d",fit->GetChisquare(),ndf);
9346 stats->AddText(tt.Data());
9347 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9348 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9349 ,fit->GetParameter(ipar)
9350 ,fit->GetParError(ipar));
9351 stats->AddText(tt.Data());
9352 }
9353 }
9354
9355 if (!done) fFunctions->Add(stats);
9356 stats->Paint(stats->GetOption());
9357}
9358
9359////////////////////////////////////////////////////////////////////////////////
9360/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9361
9363{
9364
9365 const Double_t ydiff = 1;
9366 const Double_t yligh1 = 10;
9367 const Double_t qa = 0.15;
9368 const Double_t qd = 0.15;
9369 const Double_t qs = 0.8;
9371 Int_t raster = 0;
9372 Int_t irep = 0;
9373
9374 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9377 Double_t zmin = Hparam.zmin;
9378 Double_t zmax = Hparam.zmax;
9383 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9384 Double_t deltaz = TMath::Abs(zmin);
9385 if (deltaz == 0) deltaz = 1;
9386 if (zmin >= zmax) {
9387 zmin -= 0.5*deltaz;
9388 zmax += 0.5*deltaz;
9389 }
9390 Double_t z1c = zmin;
9391 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9392 // Compute the lego limits and instantiate a lego object
9393 fXbuf[0] = -1;
9394 fYbuf[0] = 1;
9395 fXbuf[1] = -1;
9396 fYbuf[1] = 1;
9397 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9398 if (Hoption.System == kPOLAR) {
9399 fXbuf[2] = z1c;
9400 fYbuf[2] = z2c;
9401 } else if (Hoption.System == kCYLINDRICAL) {
9402 if (Hoption.Logy) {
9403 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9404 else fXbuf[2] = 0;
9405 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9406 else fYbuf[2] = 0;
9407 } else {
9408 fXbuf[2] = ylab1;
9409 fYbuf[2] = ylab2;
9410 }
9411 z1c = 0; z2c = 1;
9412 } else if (Hoption.System == kSPHERICAL) {
9413 fXbuf[2] = -1;
9414 fYbuf[2] = 1;
9415 z1c = 0; z2c = 1;
9416 } else if (Hoption.System == kRAPIDITY) {
9417 fXbuf[2] = -1/TMath::Tan(dangle);
9418 fYbuf[2] = 1/TMath::Tan(dangle);
9419 } else {
9420 fXbuf[0] = xlab1;
9421 fYbuf[0] = xlab2;
9422 fXbuf[1] = ylab1;
9423 fYbuf[1] = ylab2;
9424 fXbuf[2] = z1c;
9425 fYbuf[2] = z2c;
9426 }
9427
9428 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9429 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9430 fLego->SetFillColor(fH->GetFillColor());
9431
9432 // Initialize the levels on the Z axis
9433 Int_t ndiv = fH->GetContour();
9434 if (ndiv == 0 ) {
9435 ndiv = gStyle->GetNumberContours();
9436 fH->SetContour(ndiv);
9437 }
9438 Int_t ndivz = TMath::Abs(ndiv);
9439 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9440
9441 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9442 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9443
9444 // Close the surface in case of non cartesian coordinates.
9445
9446 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9447
9448 // Now ready to draw the surface plot
9449
9450 TView *view = gPad ? gPad->GetView() : nullptr;
9451 if (!view) {
9452 Error("PaintSurface", "no TView in current pad");
9453 return;
9454 }
9455
9456 Double_t thedeg = 90 - gPad->GetTheta();
9457 Double_t phideg = -90 - gPad->GetPhi();
9458 Double_t psideg = view->GetPsi();
9459 view->SetView(phideg, thedeg, psideg, irep);
9460
9461 // Set color/style for back box
9462 if (Hoption.Same) {
9463 fLego->SetFillStyle(0);
9464 fLego->SetFillColor(1);
9465 } else {
9466 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9467 fLego->SetFillColor(gPad->GetFrameFillColor());
9468 }
9469 fLego->TAttFill::Modify();
9470
9471 Int_t backcolor = gPad->GetFrameFillColor();
9472 if (Hoption.System != kCARTESIAN) backcolor = 0;
9473 view->PadRange(backcolor);
9474
9475 fLego->SetFillStyle(fH->GetFillStyle());
9476 fLego->SetFillColor(fH->GetFillColor());
9477 fLego->TAttFill::Modify();
9478
9479 // Draw the filled contour on top
9481
9483 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9485 Hoption.Surf = 23;
9486 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9488 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9489 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9490 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9491 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9492 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9494 fLego->SetMesh(1);
9495 }
9496
9497 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9498 else fLego->InitMoveScreen(-1.1,1.1);
9499
9500 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9501 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9504 fLego->BackBox(90);
9505 }
9506 }
9507
9508 // Gouraud Shading surface
9509 if (Hoption.Surf == 14) {
9510 // Set light sources
9511 fLego->LightSource(0, ydiff, 0,0,0,irep);
9512 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9513 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9514 fmin = ydiff*qa;
9515 fmax = fmin + (yligh1+0.1)*(qd+qs);
9516 Int_t nbcol = 28;
9517 icol1 = 201;
9518 Double_t dcol = 0.5/Double_t(nbcol);
9519 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9520 if (!colref) return;
9522 colref->GetRGB(r,g,b);
9524 TColor *acol;
9525 for (Int_t col=0;col<nbcol;col++) {
9526 acol = gROOT->GetColor(col+icol1);
9527 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9528 if (acol) acol->SetRGB(r,g,b);
9529 }
9530 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9531 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9533 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9534 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9535 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9536 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9537 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9538 } else if (Hoption.Surf == 15) {
9539 // The surface is not drawn in this case.
9540 } else {
9541 // Draw the surface
9542 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9544 } else {
9545 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9546 }
9547 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9548 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9549 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9550 if (Hoption.System == kPOLAR) {
9551 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9552 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9553 } else if (Hoption.System == kCYLINDRICAL) {
9554 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9555 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9556 } else if (Hoption.System == kSPHERICAL) {
9557 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9558 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9559 } else if (Hoption.System == kRAPIDITY) {
9560 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9561 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9562 } else {
9563 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9564 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9565 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9566 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9567 }
9568 }
9569
9570 // Paint the line contour on top for option SURF7
9571 if (Hoption.Surf == 17) {
9572 fLego->InitMoveScreen(-1.1,1.1);
9573 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9574 Hoption.Surf = 23;
9575 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9577 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9578 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9579 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9580 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9581 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9582 }
9583
9584 if ((!Hoption.Same) &&
9585 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9588 fLego->BackBox(90);
9589 }
9590 }
9591 if (Hoption.System == kCARTESIAN) {
9592 fLego->InitMoveScreen(-1.1,1.1);
9594 if (Hoption.FrontBox) fLego->FrontBox(90);
9595 }
9596 if (!Hoption.Axis && !Hoption.Same) {
9597 TGaxis axis;
9598 PaintLegoAxis(&axis, 90);
9599 }
9600
9602
9603 fLego.reset();
9604}
9605
9606////////////////////////////////////////////////////////////////////////////////
9607/// Control function to draw a table using Delaunay triangles.
9608
9610{
9611
9612 TGraphDelaunay2D *dt = nullptr;
9613 TGraphDelaunay *dtOld = nullptr;
9614
9615 // Check if fH contains a TGraphDelaunay2D
9617 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9618 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9619 if (!dt && !dtOld) return;
9620
9621 // If needed, create a TGraph2DPainter
9622 if (!fGraph2DPainter)
9623 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9624
9625 // Define the 3D view
9626 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9627 if (Hoption.Same) {
9628 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9629 if (!viewsame) {
9630 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9631 return;
9632 }
9633 Double_t *rmin = viewsame->GetRmin();
9634 Double_t *rmax = viewsame->GetRmax();
9635 if (!rmin || !rmax) return;
9636 fXbuf[0] = rmin[0];
9637 fYbuf[0] = rmax[0];
9638 fXbuf[1] = rmin[1];
9639 fYbuf[1] = rmax[1];
9640 fXbuf[2] = rmin[2];
9641 fYbuf[2] = rmax[2];
9642 fH->SetMaximum(rmax[2]);
9643 fH->SetMinimum(rmin[2]);
9644 fH->GetXaxis()->SetRangeUser(rmin[0],rmax[0]);
9645 fH->GetYaxis()->SetRangeUser(rmin[1],rmax[1]);
9646 } else {
9647 fXbuf[0] = Hparam.xmin;
9648 fYbuf[0] = Hparam.xmax;
9649 fXbuf[1] = Hparam.ymin;
9650 fYbuf[1] = Hparam.ymax;
9651 fXbuf[2] = Hparam.zmin;
9652 fYbuf[2] = Hparam.zmax;
9653 }
9654
9655 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9656 TView *view = gPad ? gPad->GetView() : nullptr;
9657 if (!view) {
9658 Error("PaintTriangles", "no TView in current pad");
9659 return;
9660 }
9661 Double_t thedeg = 90 - gPad->GetTheta();
9662 Double_t phideg = -90 - gPad->GetPhi();
9663 Double_t psideg = view->GetPsi();
9664 Int_t irep;
9665 view->SetView(phideg, thedeg, psideg, irep);
9666
9667 // Set color/style for back box
9668 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9669 fLego->SetFillColor(gPad->GetFrameFillColor());
9670 fLego->TAttFill::Modify();
9671 Int_t backcolor = gPad->GetFrameFillColor();
9672 if (Hoption.System != kCARTESIAN) backcolor = 0;
9673 view->PadRange(backcolor);
9674 fLego->SetFillStyle(fH->GetFillStyle());
9675 fLego->SetFillColor(fH->GetFillColor());
9676 fLego->TAttFill::Modify();
9677
9678 // Paint the Back Box if needed
9679 if (Hoption.BackBox && !Hoption.Same) {
9680 fLego->InitMoveScreen(-1.1,1.1);
9681 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9683 fLego->BackBox(90);
9684 }
9685
9686 // Paint the triangles
9687 fGraph2DPainter->Paint(option);
9688
9689 // Paint the Front Box if needed
9690 if (Hoption.FrontBox) {
9691 fLego->InitMoveScreen(-1.1,1.1);
9693 fLego->FrontBox(90);
9694 }
9695
9696 // Paint the Axis if needed
9697 if (!Hoption.Axis && !Hoption.Same) {
9698 TGaxis axis;
9699 PaintLegoAxis(&axis, 90);
9700 }
9701
9703
9704 fLego.reset();
9705}
9706
9707////////////////////////////////////////////////////////////////////////////////
9708/// Define the color levels used to paint legos, surfaces etc..
9709
9711{
9712
9713 Int_t i, irep;
9714
9715 // Initialize the color levels
9716 if (ndivz >= 100) {
9717 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9718 ndivz = 99;
9719 }
9720 std::vector<Double_t> funlevel(ndivz+1);
9721 std::vector<Int_t> colorlevel(ndivz+1);
9723 Int_t ncolors = gStyle->GetNumberOfColors();
9724 for (i = 0; i < ndivz; ++i) {
9726 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9728 }
9729 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9730 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9731}
9732
9733////////////////////////////////////////////////////////////////////////////////
9734/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9735
9737{
9738
9739 // Fill Hparam structure with histo parameters
9740 if (!TableInit()) return;
9741
9742 // Draw histogram frame
9743 PaintFrame();
9744
9745 // If palette option not specified, delete a possible existing palette
9746 if (!Hoption.Zscale) {
9747 TObject *palette = fFunctions->FindObject("palette");
9748 if (palette) { fFunctions->Remove(palette); delete palette;}
9749 }
9750
9751 // Do not draw the histogram. Only the attached functions will be drawn.
9752 if (Hoption.Func == 2) {
9753 if (Hoption.Zscale) {
9754 Int_t ndiv = fH->GetContour();
9755 if (ndiv == 0 ) {
9756 ndiv = gStyle->GetNumberContours();
9757 fH->SetContour(ndiv);
9758 }
9759 PaintPalette();
9760 }
9761
9762 // Draw the histogram according to the option
9763 } else {
9764 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9765 if (Hoption.Fill) PaintTH2PolyBins("f");
9769 if (Hoption.Line) PaintTH2PolyBins("l");
9770 if (Hoption.Mark) PaintTH2PolyBins("P");
9771 } else if (Hoption.Axis<=0) {
9775 if (Hoption.Color) {
9778 }
9781 if (Hoption.Error >= 100) Paint2DErrors(option);
9783 }
9787 }
9788
9789 // Draw histogram title
9790 PaintTitle();
9791
9792 // Draw the axes
9793 if (!Hoption.Lego && !Hoption.Surf &&
9794 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9795
9796 TF1 *fit = nullptr;
9797 TIter next(fFunctions);
9798 while (auto obj = next()) {
9799 if (obj->InheritsFrom(TF1::Class())) {
9800 fit = (TF1*)obj;
9801 break;
9802 }
9803 }
9804 if ((Hoption.Same%10) != 1) {
9805 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9806 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9807 //ALWAYS executed on non-iOS platform.
9808 //On iOS, depends on mode.
9810 }
9811 }
9812 }
9813}
9814
9815////////////////////////////////////////////////////////////////////////////////
9816/// Control function to draw a TH2Poly bins' contours.
9817///
9818/// - option = "F" draw the bins as filled areas.
9819/// - option = "L" draw the bins as line.
9820/// - option = "P" draw the bins as markers.
9821
9823{
9824
9825 //Do not highlight the histogram, if its part was picked.
9826 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9827
9828 TString opt = option;
9829 opt.ToLower();
9830 Bool_t line = kFALSE;
9831 Bool_t fill = kFALSE;
9832 Bool_t mark = kFALSE;
9833 if (opt.Contains("l")) line = kTRUE;
9834 if (opt.Contains("f")) fill = kTRUE;
9835 if (opt.Contains("p")) mark = kTRUE;
9836
9837 TH2PolyBin *b;
9838 Double_t z;
9839
9840 TIter next(((TH2Poly*)fH)->GetBins());
9841 TObject *obj, *poly;
9842
9843 while ((obj=next())) {
9844 b = (TH2PolyBin*)obj;
9845 z = b->GetContent();
9846 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9847 poly = b->GetPolygon();
9848
9849 // Paint the TGraph bins.
9850 if (poly->IsA() == TGraph::Class()) {
9851 TGraph *g = (TGraph*)poly;
9852 g->TAttLine::Modify();
9853 g->TAttMarker::Modify();
9854 g->TAttFill::Modify();
9855 if (line) {
9856 Int_t fs = g->GetFillStyle();
9858 g->SetFillStyle(0);
9860 g->Paint("F");
9862 g->SetFillStyle(fs);
9863 }
9864 if (fill) g->Paint("F");
9865 if (mark) g->Paint("P");
9866 }
9867
9868 // Paint the TMultiGraph bins.
9869 if (poly->IsA() == TMultiGraph::Class()) {
9871 TList *gl = mg->GetListOfGraphs();
9872 if (!gl) return;
9873 TGraph *g;
9874 TIter nextg(gl);
9875 while ((g = (TGraph*) nextg())) {
9876 g->TAttLine::Modify();
9877 g->TAttMarker::Modify();
9878 g->TAttFill::Modify();
9879 if (line) {
9880 Int_t fs = g->GetFillStyle();
9882 g->SetFillStyle(0);
9884 g->Paint("F");
9886 g->SetFillStyle(fs);
9887 }
9888 if (fill) g->Paint("F");
9889 if (mark) g->Paint("P");
9890 }
9891 }
9892 }
9893}
9894
9895////////////////////////////////////////////////////////////////////////////////
9896/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9897
9899{
9900
9901 //Do not highlight the histogram, if its part was picked.
9902 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9903 return;
9904
9905 Int_t ncolors, color, theColor;
9906 Double_t z, zc;
9907 Double_t zmin = fH->GetMinimum();
9908 Double_t zmax = fH->GetMaximum();
9909 if (Hoption.Logz) {
9910 if (zmax > 0) {
9911 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9912 zmin = TMath::Log10(zmin);
9913 zmax = TMath::Log10(zmax);
9914 } else {
9915 return;
9916 }
9917 }
9918 Double_t dz = zmax - zmin;
9919
9920 // Initialize the levels on the Z axis
9921 ncolors = gStyle->GetNumberOfColors();
9922 Int_t ndiv = fH->GetContour();
9923 if (ndiv == 0 ) {
9924 ndiv = gStyle->GetNumberContours();
9925 fH->SetContour(ndiv);
9926 }
9927 Int_t ndivz = TMath::Abs(ndiv);
9928 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9930
9931 TIter next(((TH2Poly*)fH)->GetBins());
9932
9933 while (auto obj = next()) {
9934 TH2PolyBin *b = (TH2PolyBin*)obj;
9935 TObject *poly = b->GetPolygon();
9936
9937 z = b->GetContent();
9938 if (z==0 && Hoption.Zero) continue;
9939 if (Hoption.Logz) {
9940 if (z > 0) z = TMath::Log10(z);
9941 else z = zmin;
9942 }
9943 if (z < zmin) continue;
9944
9945 // Define the bin color.
9947 zc = fH->GetContourLevelPad(0);
9948 if (z < zc) continue;
9949 color = -1;
9950 for (Int_t k=0; k<ndiv; k++) {
9951 zc = fH->GetContourLevelPad(k);
9952 if (z < zc) {
9953 continue;
9954 } else {
9955 color++;
9956 }
9957 }
9958 } else {
9959 color = Int_t(0.01+(z-zmin)*scale);
9960 }
9961 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9962 if (theColor > ncolors-1) theColor = ncolors-1;
9963
9965
9966 // Paint the TGraph bins.
9967 if (poly->IsA() == TGraph::Class()) {
9968 TGraph *g = (TGraph*)poly;
9969 auto origin = g->GetFillColor();
9970 g->SetFillColor(rootColor);
9971 g->TAttFill::Modify();
9972 g->Paint("F");
9973 g->SetFillColor(origin);
9974 }
9975
9976 // Paint the TMultiGraph bins.
9977 if (poly->IsA() == TMultiGraph::Class()) {
9980 while (auto g = (TGraph*) nextg()) {
9981 auto origin = g->GetFillColor();
9982 g->SetFillColor(rootColor);
9983 g->TAttFill::Modify();
9984 g->Paint("F");
9985 g->SetFillColor(origin);
9986 }
9987 }
9988 }
9990}
9991
9992////////////////////////////////////////////////////////////////////////////////
9993/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9994
9996{
9997
9998 //Do not highlight the histogram, if its part was selected.
9999 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
10000 return;
10001
10002 Int_t k, loop, marker=0;
10003 Double_t z, xk,xstep, yk, ystep, xp, yp;
10004 Double_t scale = 1;
10005 Double_t zmin = fH->GetMinimum();
10006 Double_t zmax = fH->GetMaximum();
10007 if (Hoption.Logz) {
10008 if (zmax > 0) {
10009 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10010 zmin = TMath::Log10(zmin);
10011 zmax = TMath::Log10(zmax);
10012 } else {
10013 return;
10014 }
10015 }
10016 Double_t dz = zmax - zmin;
10017 scale = (kNMAX-1)/dz;
10018
10019
10020 // use an independent instance of a random generator
10021 // instead of gRandom to avoid conflicts and
10022 // to get same random numbers when drawing the same histogram
10024
10025 TH2PolyBin *b;
10026
10027 TIter next(((TH2Poly*)fH)->GetBins());
10028 TObject *obj, *poly;
10029
10030 Double_t maxarea = 0, a;
10031 while ((obj=next())) {
10032 b = (TH2PolyBin*)obj;
10033 a = b->GetArea();
10034 if (a>maxarea) maxarea = a;
10035 }
10036
10037 next.Reset();
10038
10039 while ((obj=next())) {
10040 b = (TH2PolyBin*)obj;
10041 poly = b->GetPolygon();
10042 z = b->GetContent();
10043 if (z < zmin) z = zmin;
10044 if (z > zmax) z = zmax;
10045 if (Hoption.Logz) {
10046 if (z > 0) z = TMath::Log10(z) - zmin;
10047 } else {
10048 z -= zmin;
10049 }
10050 k = Int_t((z*scale)*(b->GetArea()/maxarea));
10051 xk = b->GetXMin();
10052 yk = b->GetYMin();
10053 xstep = b->GetXMax()-xk;
10054 ystep = b->GetYMax()-yk;
10055
10056 // Paint the TGraph bins.
10057 if (poly->IsA() == TGraph::Class()) {
10058 TGraph *g = (TGraph*)poly;
10059 if (k <= 0 || z <= 0) continue;
10060 loop = 0;
10061 while (loop<k) {
10062 if (k+marker >= kNMAX) {
10063 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10064 marker=0;
10065 }
10066 xp = (random.Rndm()*xstep) + xk;
10067 yp = (random.Rndm()*ystep) + yk;
10068 if (g->IsInside(xp,yp)) {
10069 fXbuf[marker] = xp;
10070 fYbuf[marker] = yp;
10071 marker++;
10072 loop++;
10073 }
10074 }
10075 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10076 }
10077
10078 // Paint the TMultiGraph bins.
10079 if (poly->IsA() == TMultiGraph::Class()) {
10081 TList *gl = mg->GetListOfGraphs();
10082 if (!gl) return;
10083 if (k <= 0 || z <= 0) continue;
10084 loop = 0;
10085 while (loop<k) {
10086 if (k+marker >= kNMAX) {
10087 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10088 marker=0;
10089 }
10090 xp = (random.Rndm()*xstep) + xk;
10091 yp = (random.Rndm()*ystep) + yk;
10092 if (mg->IsInside(xp,yp)) {
10093 fXbuf[marker] = xp;
10094 fYbuf[marker] = yp;
10095 marker++;
10096 loop++;
10097 }
10098 }
10099 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
10100 }
10101 }
10102 PaintTH2PolyBins("l");
10103}
10104
10105////////////////////////////////////////////////////////////////////////////////
10106/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
10107
10109{
10110
10111 TLatex text;
10112 text.SetTextFont(gStyle->GetTextFont());
10113 text.SetTextColor(fH->GetMarkerColor());
10114 text.SetTextSize(0.02*fH->GetMarkerSize());
10115
10116 Double_t x, y, z, e, angle = 0;
10117 TString tt, tf;
10118 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10119 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10120 Int_t opt = (Int_t)Hoption.Text/1000;
10121
10122 text.SetTextAlign(22);
10123 if (Hoption.Text == 1) angle = 0;
10124 text.SetTextAngle(angle);
10125 text.TAttText::Modify();
10126
10127 TH2PolyBin *b;
10128
10129 TIter next(((TH2Poly*)fH)->GetBins());
10130 TObject *obj, *p;
10131
10132 while ((obj=next())) {
10133 b = (TH2PolyBin*)obj;
10134 p = b->GetPolygon();
10135 x = (b->GetXMin()+b->GetXMax())/2;
10136 if (Hoption.Logx) {
10137 if (x > 0) x = TMath::Log10(x);
10138 else continue;
10139 }
10140 y = (b->GetYMin()+b->GetYMax())/2;
10141 if (Hoption.Logy) {
10142 if (y > 0) y = TMath::Log10(y);
10143 else continue;
10144 }
10145 z = b->GetContent();
10146 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
10147 if (opt==2) {
10148 e = fH->GetBinError(b->GetBinNumber());
10149 tf.Form("#splitline{%s%s}{#pm %s%s}",
10151 "%",gStyle->GetPaintTextFormat());
10152 tt.Form(tf.Data(),z,e);
10153 } else {
10154 tt.Form(tf.Data(),z);
10155 }
10156 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
10157 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
10158 }
10159
10160 PaintTH2PolyBins("l");
10161}
10162
10163////////////////////////////////////////////////////////////////////////////////
10164/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
10165
10167{
10168
10169 TLatex text;
10170 text.SetTextFont(((int)gStyle->GetTextFont()/10)*10+2); // font precision must be 2
10171 text.SetTextColor(fH->GetMarkerColor());
10172 text.SetTextSize(0.02*fH->GetMarkerSize());
10173
10174 Double_t x, y, z, e, angle = 0;
10175 TString tt, tf;
10176 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
10177 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
10178
10179 // 1D histograms
10180 if (fH->GetDimension() == 1) {
10182 Double_t yt;
10183 TProfile *hp = (TProfile*)fH;
10184 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
10185 Hoption.Text = Hoption.Text-2000;
10186 getentries = kTRUE;
10187 }
10188 if (Hoption.Text == 1) angle = 90;
10189 text.SetTextAlign(11);
10190 if (angle == 90) text.SetTextAlign(12);
10191 if (angle == 0) text.SetTextAlign(21);
10192 text.TAttText::Modify();
10193 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
10194 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10195 if (Hoption.Bar) {
10196 x = fH->GetXaxis()->GetBinLowEdge(i)+
10197 fH->GetXaxis()->GetBinWidth(i)*
10198 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10199 } else {
10200 x = fH->GetXaxis()->GetBinCenter(i);
10201 }
10202 y = fH->GetBinContent(i);
10203 yt = y;
10204 if (Hoption.MinimumZero && y<0) y = 0;
10205 if (getentries) yt = hp->GetBinEntries(i);
10206 if (yt == 0.) continue;
10207 tt.Form(tf.Data(),yt);
10208 if (Hoption.Logx) {
10209 if (x > 0) x = TMath::Log10(x);
10210 else continue;
10211 }
10212 if (Hoption.Logy) {
10213 if (y > 0) y = TMath::Log10(y);
10214 else continue;
10215 }
10216 if (y >= gPad->GetY2()) continue;
10217 if (y <= gPad->GetY1()) continue;
10218 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10219 }
10220
10221 // 2D histograms
10222 } else {
10223 Double_t zmin = Hparam.zmin;
10224 if (Hoption.Logz) zmin = TMath::Power(10,Hparam.zmin);
10225
10226 text.SetTextAlign(22);
10227 if (Hoption.Text == 1) angle = 0;
10228 text.SetTextAngle(angle);
10229 text.TAttText::Modify();
10230 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10231 y = fYaxis->GetBinCenter(j);
10232 if (Hoption.Logy) {
10233 if (y > 0) y = TMath::Log10(y);
10234 else continue;
10235 }
10236 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10237 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10238 x = fXaxis->GetBinCenter(i);
10239 if (Hoption.Logx) {
10240 if (x > 0) x = TMath::Log10(x);
10241 else continue;
10242 }
10243 if (!IsInside(x,y)) continue;
10244 z = fH->GetBinContent(bin);
10245 if (z < zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10246 if (Hoption.Text>2000) {
10247 e = fH->GetBinError(bin);
10248 tf.Form("#splitline{%s%s}{#pm %s%s}",
10250 "%",gStyle->GetPaintTextFormat());
10251 tt.Form(tf.Data(),z,e);
10252 } else {
10253 tt.Form(tf.Data(),z);
10254 }
10255 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10256 angle,0.02*fH->GetMarkerSize(),tt.Data());
10257 }
10258 }
10259 }
10260}
10261
10262////////////////////////////////////////////////////////////////////////////////
10263/// [Control function to draw a 3D implicit functions.](\ref HP27)
10264
10266{
10267
10268 Int_t irep;
10269
10270 TAxis *xaxis = fH->GetXaxis();
10271 TAxis *yaxis = fH->GetYaxis();
10272 TAxis *zaxis = fH->GetZaxis();
10273
10274 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10275 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10276 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10277 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10278 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10279 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10280
10281 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10282
10283 TView *view = gPad ? gPad->GetView() : nullptr;
10284 if (!view) {
10285 Error("PaintTF3", "no TView in current pad");
10286 return;
10287 }
10288 Double_t thedeg = 90 - gPad->GetTheta();
10289 Double_t phideg = -90 - gPad->GetPhi();
10290 Double_t psideg = view->GetPsi();
10291 view->SetView(phideg, thedeg, psideg, irep);
10292
10293 fLego->InitMoveScreen(-1.1,1.1);
10294
10295 if (Hoption.BackBox) {
10296 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10298 fLego->BackBox(90);
10299 }
10300
10302
10303 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10304 fH->GetNbinsY(),
10305 fH->GetNbinsZ(), "BF");
10306
10307 if (Hoption.FrontBox) {
10308 fLego->InitMoveScreen(-1.1,1.1);
10310 fLego->FrontBox(90);
10311 }
10312 if (!Hoption.Axis && !Hoption.Same) {
10313 TGaxis axis;
10314 PaintLegoAxis(&axis, 90);
10315 }
10316
10317 PaintTitle();
10318
10319 fLego.reset();
10320}
10321
10322/////////////////////////////////////////////////////////////new TGaxis///////////////////
10323/// Draw the histogram title
10324///
10325/// The title is drawn according to the title alignment returned by
10326/// `GetTitleAlign()`. It is a 2 digits integer): hv
10327///
10328/// where `h` is the horizontal alignment and `v` is the
10329/// vertical alignment.
10330///
10331/// - `h` can get the values 1 2 3 for left, center, and right
10332/// - `v` can get the values 1 2 3 for bottom, middle and top
10333///
10334/// for instance the default alignment is: 13 (left top)
10335
10337{
10338 // probably best place for calls PaintHighlightBin
10339 // calls after paint histo (1D or 2D) and before paint title and stats
10340 if (!gPad->GetView()) PaintHighlightBin();
10341
10342 if (Hoption.Same) return;
10343 if (fH->TestBit(TH1::kNoTitle)) return;
10344 Int_t nt = strlen(fH->GetTitle());
10345 TPaveText *title = nullptr;
10346 TObject *obj;
10347 TIter next(gPad->GetListOfPrimitives());
10348 while ((obj = next())) {
10349 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10350 title = (TPaveText*)obj;
10351 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10352 break;
10353 }
10354 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10355 if (title) delete title;
10356 return;
10357 }
10360
10361 if (ht <= 0) {
10362 if (gStyle->GetTitleFont("")%10 == 3) {
10363 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10364 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10365 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10366 } else {
10367 ht = 1.1*gStyle->GetTitleFontSize();
10368 }
10369 }
10370 if (ht <= 0) ht = 0.05;
10371 if (wt <= 0) {
10372 TLatex l;
10373 l.SetTextSize(ht);
10374 l.SetTitle(fH->GetTitle());
10375 // adjustment in case the title has several lines (#splitline)
10376 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10377 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10378 wt = TMath::Min(0.7, 0.02+wndc);
10379 }
10380 if (title) {
10381 TText *t0 = (TText*)title->GetLine(0);
10382 if (t0) {
10383 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10384 t0->SetTitle(fH->GetTitle());
10385 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10386 }
10387 return;
10388 }
10389
10391 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10393 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10395 xpos = gStyle->GetTitleX();
10396 ypos = gStyle->GetTitleY();
10397 if (talh == 2) xpos = xpos-wt/2.;
10398 if (talh == 3) xpos = xpos-wt;
10399 if (talv == 2) ypos = ypos+ht/2.;
10400 if (talv == 1) ypos = ypos+ht;
10401
10402 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10403
10404 // box with the histogram title
10405 ptitle->SetFillColor(gStyle->GetTitleFillColor());
10406 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10407 ptitle->SetName("title");
10408 ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
10409 ptitle->SetTextColor(gStyle->GetTitleTextColor());
10410 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10411 if (gStyle->GetTitleFont("")%10 > 2)
10412 ptitle->SetTextSize(gStyle->GetTitleFontSize());
10413 ptitle->AddText(fH->GetTitle());
10414 ptitle->SetBit(kCanDelete);
10415 ptitle->Draw();
10416 ptitle->Paint("blNDC");
10417
10418 if(!gPad->IsEditable()) delete ptitle;
10419}
10420
10421////////////////////////////////////////////////////////////////////////////////
10422/// Process message `mess`.
10423
10424void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10425{
10426 if (!strcmp(mess,"SetF3")) {
10427 fCurrentF3 = (TF3 *)obj;
10428 }
10429}
10430
10431////////////////////////////////////////////////////////////////////////////////
10432/// Static function.
10433///
10434/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10435/// This procedure can be used to create an all-sky map in Galactic
10436/// coordinates with an equal-area Aitoff projection. Output map
10437/// coordinates are zero longitude centered.
10438/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10439///
10440/// source: GMT
10441///
10442/// code from Ernst-Jan Buis
10443
10445{
10446
10447 Double_t x, y;
10448
10450 Double_t delta = b*TMath::DegToRad();
10451 Double_t r2 = TMath::Sqrt(2.);
10452 Double_t f = 2*r2/TMath::Pi();
10453 Double_t cdec = TMath::Cos(delta);
10456 y = TMath::Sin(delta)*r2/denom;
10457 x *= TMath::RadToDeg()/f;
10458 y *= TMath::RadToDeg()/f;
10459 // x *= -1.; // for a skymap swap left<->right
10460 Al = x;
10461 Ab = y;
10462
10463 return 0;
10464}
10465
10466////////////////////////////////////////////////////////////////////////////////
10467/// Static function
10468///
10469/// Probably the most famous of the various map projections, the Mercator projection
10470/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10471/// with no distortion along the equator.
10472/// The Mercator projection has been used extensively for world maps in which the distortion towards
10473/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10474/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10475/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10476/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10477/// code from Ernst-Jan Buis
10478
10480{
10481
10482 Al = l;
10484 Ab = TMath::Log(aid);
10485 return 0;
10486}
10487
10488////////////////////////////////////////////////////////////////////////////////
10489/// Static function code for sinusoidal projection
10490/// from Ernst-Jan Buis
10491/// Source https://en.wikipedia.org/wiki/Sinusoidal_projection
10492
10494{
10495
10496 Al = l*cos(b*TMath::DegToRad());
10497 Ab = b;
10498 return 0;
10499}
10500
10501////////////////////////////////////////////////////////////////////////////////
10502/// Static function code for parabolic projection
10503/// from Ernst-Jan Buis
10504
10506{
10507
10508 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10509 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10510 return 0;
10511}
10512
10513////////////////////////////////////////////////////////////////////////////////
10514/// Static function.
10515///
10516/// Convert Right Ascension, Declination to X,Y using an MOLLWEIDE projection.
10517/// This procedure can be used to create an all-sky map in Galactic
10518/// coordinates with an equal-area Mollweide projection. Output map
10519/// coordinates are zero longitude centered.
10520/// It is also known as the Babinet projection, homalographic projection, homolographic projection, and elliptical projection.
10521/// Source: https://en.wikipedia.org/wiki/Mollweide_projection
10522///
10523/// code from Marco Meyer-Conde
10524
10526{
10527
10528 Double_t theta0 = b * TMath::DegToRad(), theta = theta0;
10529
10530 for (int i = 0; i < 100; i++) {
10531 Double_t num = 2 * theta + TMath::Sin(2 * theta) - TMath::Pi() * TMath::Sin(theta0);
10532 Double_t den = 4 * TMath::Power(TMath::Cos(theta), 2);
10533
10534 if (den < 1e-20) {
10535 theta = theta0;
10536 break;
10537 }
10538
10539 theta -= num / den;
10540
10541 if (TMath::Abs(num / den) < 1e-4) break;
10542 }
10543
10544 Al = l * TMath::Cos(theta);
10545 Ab = 90 * TMath::Sin(theta);
10546
10547 return 0;
10548}
10549
10550////////////////////////////////////////////////////////////////////////////////
10551/// Recompute the histogram range following graphics operations.
10552
10554{
10555
10556 if (Hoption.Same) return;
10557
10558 // Compute x,y range
10560 xmax = Hparam.xmax,
10561 ymin = Hparam.ymin,
10562 ymax = Hparam.ymax,
10563 xscale = 1;
10564
10565 std::function<Int_t(Double_t,Double_t,Double_t&,Double_t&)> func;
10566
10567 if (Hoption.Proj == 1) {
10568 func = ProjectAitoff2xy;
10569 xscale = 0.9999;
10570 } else if (Hoption.Proj == 2) {
10571 if (Hparam.ymin <= -90 || Hparam.ymax >= 90) {
10572 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10573 Hoption.Proj = 0;
10574 } else {
10577 }
10578 } else if (Hoption.Proj == 3) {
10579 func = ProjectSinusoidal2xy;
10580 } else if (Hoption.Proj == 4) {
10581 func = ProjectParabolic2xy;
10582 } else if (Hoption.Proj == 5) {
10583 func = ProjectMollweide2xy;
10584 }
10585
10586 if (func) {
10588
10592 func(Hparam.xmax, Hparam.ymin, xmax, ymin);
10593
10594 if (xmin > xmin_aid) xmin = xmin_aid;
10595 if (ymin > ymin_aid) ymin = ymin_aid;
10596 if (xmax < xmax_aid) xmax = xmax_aid;
10597 if (ymax < ymax_aid) ymax = ymax_aid;
10598 if (Hparam.ymin < 0 && Hparam.ymax > 0) {
10599 // there is an 'equator', check its range in the plot..
10600 func(Hparam.xmin*xscale, 0, xmin_aid, ymin_aid);
10601 func(Hparam.xmax*xscale, 0, xmax_aid, ymin_aid);
10602 if (xmin > xmin_aid) xmin = xmin_aid;
10603 if (xmax < xmax_aid) xmax = xmax_aid;
10604 }
10605 if (Hparam.xmin < 0 && Hparam.xmax > 0) {
10606 func(0, Hparam.ymin, xmin_aid, ymin_aid);
10607 func(0, Hparam.ymax, xmax_aid, ymax_aid);
10608 if (ymin > ymin_aid) ymin = ymin_aid;
10609 if (ymax < ymax_aid) ymax = ymax_aid;
10610 }
10611 }
10612
10613 Hparam.xmin = xmin;
10614 Hparam.xmax = xmax;
10615 Hparam.ymin = ymin;
10616 Hparam.ymax = ymax;
10617
10618 Double_t dx = xmax-xmin;
10619 Double_t dy = ymax-ymin;
10620 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10621 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10622
10623 // Range() could change the size of the pad pixmap and therefore should
10624 // be called before the other paint routines
10625 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10626 ymin - dyr*gPad->GetBottomMargin(),
10627 xmax + dxr*gPad->GetRightMargin(),
10628 ymax + dyr*gPad->GetTopMargin());
10629 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10630}
10631
10632////////////////////////////////////////////////////////////////////////////////
10633/// Set current histogram to `h`
10634
10636{
10637
10638 if (h == nullptr) return;
10639 fH = h;
10640 fXaxis = h->GetXaxis();
10641 fYaxis = h->GetYaxis();
10642 fZaxis = h->GetZaxis();
10644}
10645
10646////////////////////////////////////////////////////////////////////////////////
10647/// Initialize various options to draw 2D histograms.
10648
10650{
10651
10652 static const char *where = "TableInit";
10653
10654 Int_t first, last;
10656 Double_t zmin, zmax;
10657 Int_t maximum = 0;
10658 Int_t minimum = 0;
10659 if (fH->GetMaximumStored() != -1111) maximum = 1;
10660 if (fH->GetMinimumStored() != -1111) minimum = 1;
10661
10662 // ----------------- Compute X axis parameters
10663 first = fXaxis->GetFirst();
10664 last = fXaxis->GetLast();
10665 Hparam.xlast = last;
10666 Hparam.xfirst = first;
10671
10672 // if log scale in X, replace xmin,max by the log
10673 if (Hoption.Logx) {
10674 // find the first edge of a bin that is > 0
10675 if (Hparam.xlowedge <=0 ) {
10678 }
10679 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10680 Error(where, "cannot set X axis to log scale");
10681 return 0;
10682 }
10684 if (Hparam.xfirst < first) Hparam.xfirst = first;
10686 if (Hparam.xlast > last) Hparam.xlast = last;
10689 }
10690
10691 // ----------------- Compute Y axis parameters
10692 first = fYaxis->GetFirst();
10693 last = fYaxis->GetLast();
10694 Hparam.ylast = last;
10695 Hparam.yfirst = first;
10698 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10701
10702 // if log scale in Y, replace ymin,max by the log
10703 if (Hoption.Logy) {
10704 if (Hparam.ylowedge <=0 ) {
10707 }
10708 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10709 Error(where, "cannot set Y axis to log scale");
10710 return 0;
10711 }
10713 if (Hparam.yfirst < first) Hparam.yfirst = first;
10715 if (Hparam.ylast > last) Hparam.ylast = last;
10718 }
10719
10720
10721 // ----------------- Compute Z axis parameters
10722 Double_t bigp = TMath::Power(10,32);
10723 zmax = -bigp;
10724 zmin = bigp;
10725 Double_t c1, e1;
10726 Double_t allchan = 0;
10727 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10728 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10729 c1 = fH->GetBinContent(i,j);
10730 zmax = TMath::Max(zmax,c1);
10731 if (Hoption.Error) {
10732 e1 = fH->GetBinError(i,j);
10733 zmax = TMath::Max(zmax,c1+e1);
10734 }
10735 zmin = TMath::Min(zmin,c1);
10736 allchan += c1;
10737 }
10738 }
10739
10740 // Take into account maximum , minimum
10741
10742 if (maximum) zmax = fH->GetMaximumStored();
10743 if (minimum) zmin = fH->GetMinimumStored();
10744 if (Hoption.Logz && zmax < 0) {
10745 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10746 return 0;
10747 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10748 zmin = 0.01;
10749 zmax = 10.;
10750 }
10751 if (zmin >= zmax) {
10752 if (Hoption.Logz) {
10753 if (zmax > 0) zmin = 0.001*zmax;
10754 else {
10755 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10756 return 0;
10757 }
10758 }
10759 }
10760
10761 // take into account normalization factor
10762 Hparam.allchan = allchan;
10763 Double_t factor = allchan;
10764 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10765 if (allchan) factor /= allchan;
10766 if (factor == 0) factor = 1;
10767 Hparam.factor = factor;
10768 zmax = factor*zmax;
10769 zmin = factor*zmin;
10770 c1 = zmax;
10771 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10772
10773 // For log scales, histogram coordinates are log10(ymin) and
10774 // log10(ymax). Final adjustment (if not option "Same")
10775 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10776 // Maximum and Minimum are not defined.
10777 if (Hoption.Logz) {
10778 if (zmin <= 0) {
10779 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10780 fH->SetMinimum(zmin);
10781 }
10782 zmin = TMath::Log10(zmin);
10783 if (!minimum) zmin += TMath::Log10(0.5);
10784 zmax = TMath::Log10(zmax);
10785 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10786 goto LZMIN;
10787 }
10788
10789 // final adjustment of YMAXI for linear scale (if not option "Same"):
10790 // decrease histogram height to MAX% of allowed height if HMAXIM
10791 // has not been called.
10792 // MAX% is the value in percent which has been set in HPLSET
10793 // (default is 90%).
10794 if (!maximum) {
10795 zmax += yMARGIN*(zmax-zmin);
10796 }
10797
10798 // final adjustment of ymin for linear scale.
10799 // if minimum is not set , then ymin is set to zero if >0
10800 // or to ymin - yMARGIN if <0.
10801 if (!minimum) {
10802 if (Hoption.MinimumZero) {
10803 if (zmin >= 0) zmin = 0;
10804 else zmin -= yMARGIN*(zmax-zmin);
10805 } else {
10806 Double_t dzmin = yMARGIN*(zmax-zmin);
10807 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10808 else zmin -= dzmin;
10809 }
10810 }
10811
10812LZMIN:
10813 Hparam.zmin = zmin;
10814 Hparam.zmax = zmax;
10815
10816 // Set bar offset and width
10819
10820 return 1;
10821}
10822
10823////////////////////////////////////////////////////////////////////////////////
10824/// This function returns the best format to print the error value (e)
10825/// knowing the parameter value (v) and the format (f) used to print it.
10826
10828{
10829
10830 static TString ef;
10831 TString tf, tv;
10832
10833 // print v with the format f in tv.
10834 tf.Form("%s%s","%",f);
10835 tv.Form(tf.Data(),v);
10836
10837 // Analyse tv.
10838 int ie = tv.Index("e");
10839 int iE = tv.Index("E");
10840 int id = tv.Index(".");
10841
10842 // v has been printed with the exponent notation.
10843 // There is 2 cases, the exponent is positive or negative
10844 if (ie >= 0 || iE >= 0) {
10845 if (tv.Index("+") >= 0) {
10846 if (e < 1) {
10847 ef.Form("%s.1f","%");
10848 } else {
10849 if (ie >= 0) {
10850 ef.Form("%s.%de","%",ie-id-1);
10851 } else {
10852 ef.Form("%s.%dE","%",iE-id-1);
10853 }
10854 }
10855 } else {
10856 if (ie >= 0) {
10857 ef.Form("%s.%de","%",ie-id-1);
10858 } else {
10859 ef.Form("%s.%dE","%",iE-id-1);
10860 }
10861 }
10862
10863 // There is not '.' in tv. e will be printed with one decimal digit.
10864 } else if (id < 0) {
10865 ef.Form("%s.1f","%");
10866
10867 // There is a '.' in tv and no exponent notation. e's decimal part will
10868 // have the same number of digits as v's one.
10869 } else {
10870 ef.Form("%s.%df","%",tv.Length()-id-1);
10871 }
10872
10873 return ef.Data();
10874}
10875
10876////////////////////////////////////////////////////////////////////////////////
10877/// Set projection.
10878
10880{
10881 if (fShowProjection2) {
10882 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10883 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10884 if (c2) c2->Close();
10885 fShowProjection2 = 0;
10886 }
10887 if (fShowProjection) {
10888 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10889 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10890 if (c1) c1->Close();
10891 fShowProjection = 0;
10892 }
10893
10894 if (nbins <= 0) return;
10895
10896 TString opt = option;
10897 opt.ToLower();
10898 Int_t projection = 0;
10899 if (opt.Contains("x")) projection = 1;
10900 if (opt.Contains("y")) projection = 2;
10901 if (opt.Contains("z")) projection = 3;
10902 if (opt.Contains("xy")) projection = 4;
10903 if (opt.Contains("yx")) projection = 5;
10904 if (opt.Contains("xz")) projection = 6;
10905 if (opt.Contains("zx")) projection = 7;
10906 if (opt.Contains("yz")) projection = 8;
10907 if (opt.Contains("zy")) projection = 9;
10908 if (projection < 4) fShowOption = option+1;
10909 else fShowOption = option+2;
10910 fShowProjection = projection+100*nbins;
10911 fShowProjection2 = 0;
10912 gROOT->MakeDefCanvas();
10913 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10914 gPad->SetGrid();
10915}
10916
10918{
10919 if (fShowProjection2) {
10920 auto name2 = TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2);
10921 auto c2 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name2.Data()));
10922 if (c2) c2->Close();
10923 fShowProjection2 = 0;
10924 }
10925 if (fShowProjection) {
10926 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10927 auto c1 = static_cast<TVirtualPad *>(gROOT->GetListOfCanvases()->FindObject(name1.Data()));
10928 if (c1) c1->Close();
10929 fShowProjection = 0;
10930 }
10931
10932 if ((nbinsX <= 0) || (nbinsY <= 0)) return;
10933
10934
10935 TString opt = option;
10936 opt.ToLower();
10937 Int_t projection = 0;
10938 if (opt.Contains("x")) projection = 1;
10939 if (opt.Contains("y")) projection = 2;
10940 if (opt.Contains("z")) projection = 3;
10941 if (opt.Contains("xy")) projection = 4;
10942 if (opt.Contains("yx")) projection = 5;
10943 if (opt.Contains("xz")) projection = 6;
10944 if (opt.Contains("zx")) projection = 7;
10945 if (opt.Contains("yz")) projection = 8;
10946 if (opt.Contains("zy")) projection = 9;
10947 if (projection < 4) fShowOption = option+1;
10948 else fShowOption = option+2;
10951 gROOT->MakeDefCanvas();
10952 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10953 gPad->SetGrid();
10954 gROOT->MakeDefCanvas();
10955 gPad->SetName(TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2).Data());
10956 gPad->SetGrid();
10957}
10958
10959
10960////////////////////////////////////////////////////////////////////////////////
10961/// Show projection onto X.
10962
10964{
10965
10966 Int_t nbins = (Int_t)fShowProjection/100;
10967 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10968 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10969
10970 // Erase old position and draw a line at current position
10971 static int pyold1 = 0;
10972 static int pyold2 = 0;
10973 float uxmin = gPad->GetUxmin();
10974 float uxmax = gPad->GetUxmax();
10975 int pxmin = gPad->XtoAbsPixel(uxmin);
10976 int pxmax = gPad->XtoAbsPixel(uxmax);
10977 Float_t upy = gPad->AbsPixeltoY(py);
10978 Float_t y = gPad->PadtoY(upy);
10979 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10980 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10981 Int_t py1 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinLowEdge(biny1)) : fH->GetYaxis()->GetBinLowEdge(biny1));
10982 Int_t py2 = gPad->YtoAbsPixel(gPad->GetLogy() ? TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny2)) : fH->GetYaxis()->GetBinUpEdge(biny2));
10983
10985 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10986 pyold1 = py1;
10987 pyold2 = py2;
10988
10989 // Create or set the new canvas proj x
10991 auto name1 = TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
10992 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name1.Data());
10993 if (c) {
10994 c->Clear();
10995 } else {
10996 fShowProjection = 0;
10997 fShowProjection2 = 0;
10998 pyold1 = 0;
10999 pyold2 = 0;
11000 return;
11001 }
11002 c->cd();
11003 c->SetLogy(ctxt.GetSaved()->GetLogz());
11004 c->SetLogx(ctxt.GetSaved()->GetLogx());
11005
11006 // Draw slice corresponding to mouse position
11007 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
11008 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
11009 if (hp) {
11010 hp->SetFillColor(38);
11011 // apply a patch from Oliver Freyermuth to set the title in the projection
11012 // using the range of the projected Y values
11013 if (biny1 == biny2) {
11016 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11018 if (fH->GetYaxis()->GetLabels() != nullptr) {
11019 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
11020 } else {
11021 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
11022 }
11023 } else {
11026 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11027 // biny1 is used here to get equal precision no matter how large the binrange is,
11028 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11030 if (fH->GetYaxis()->GetLabels() != nullptr) {
11031 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)));
11032 } else {
11033 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
11034 }
11035 }
11036 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11037 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11038 hp->Draw();
11039 c->Update();
11040 }
11041}
11042
11043////////////////////////////////////////////////////////////////////////////////
11044/// Show projection onto Y.
11045
11047{
11048
11049 Int_t nbins = (Int_t)fShowProjection/100;
11050 if (fShowProjection2)
11051 nbins = (Int_t)fShowProjection2/100;
11052 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11053 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11054
11055 // Erase old position and draw a line at current position
11056 static int pxold1 = 0;
11057 static int pxold2 = 0;
11058 float uymin = gPad->GetUymin();
11059 float uymax = gPad->GetUymax();
11060 int pymin = gPad->YtoAbsPixel(uymin);
11061 int pymax = gPad->YtoAbsPixel(uymax);
11062 Float_t upx = gPad->AbsPixeltoX(px);
11063 Float_t x = gPad->PadtoX(upx);
11064 Int_t binx1 = fH->GetXaxis()->FindBin(x);
11065 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
11066 Int_t px1 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinLowEdge(binx1)) : fH->GetXaxis()->GetBinLowEdge(binx1));
11067 Int_t px2 = gPad->XtoAbsPixel(gPad->GetLogx() ? TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx2)) : fH->GetXaxis()->GetBinUpEdge(binx2));
11068
11070 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
11071 pxold1 = px1;
11072 pxold2 = px2;
11073
11074 // Create or set the new canvas proj y
11076
11077 TString name2 = fShowProjection2 ? TString::Format("c_%zx_projection2_%d", (size_t)fH, fShowProjection2)
11078 : TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection);
11079
11080 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(name2.Data());
11081 if (c) {
11082 c->Clear();
11083 } else {
11084 fShowProjection = 0;
11085 fShowProjection2 = 0;
11086 pxold1 = 0;
11087 pxold2 = 0;
11088 return;
11089 }
11090 c->cd();
11091 c->SetLogy(ctxt.GetSaved()->GetLogz());
11092 c->SetLogx(ctxt.GetSaved()->GetLogy());
11093
11094 // Draw slice corresponding to mouse position
11095 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
11096 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
11097 if (hp) {
11098 hp->SetFillColor(38);
11099 // apply a patch from Oliver Freyermuth to set the title in the projection
11100 // using the range of the projected X values
11101 if (binx1 == binx2) {
11104 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11106 if (fH->GetXaxis()->GetLabels() != nullptr) {
11107 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
11108 } else {
11109 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
11110 }
11111 } else {
11114 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
11115 // binx1 is used here to get equal precision no matter how large the binrange is,
11116 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
11118 if (fH->GetXaxis()->GetLabels() != nullptr) {
11119 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)));
11120 } else {
11121 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
11122 }
11123 }
11124 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11125 hp->SetYTitle(((TH2*)fH)->GetZaxis()->GetTitle() ? ((TH2*)fH)->GetZaxis()->GetTitle() : "Number of Entries");
11126 hp->Draw(fShowProjection2 ? "hbar" : "");
11127 c->Update();
11128 }
11129}
11130
11131////////////////////////////////////////////////////////////////////////////////
11132/// Show projection (specified by `fShowProjection`) of a `TH3`.
11133/// The drawing option for the projection is in `fShowOption`.
11134///
11135/// First implementation; R.Brun
11136///
11137/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
11138
11140{
11141
11142 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
11143 if (fH->GetDimension() < 3) {
11144 if (fShowProjection2 % 100 == 1) {
11145 ShowProjectionY(px, py);
11146 }
11147 if (fShowProjection % 100 == 1) {
11148 ShowProjectionX(px, py);
11149 return;
11150 }
11151 if (fShowProjection % 100 == 2) {
11152 ShowProjectionY(px, py);
11153 return;
11154 }
11155 }
11156
11157 gPad->SetDoubleBuffer(0); // turn off double buffer mode
11158 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
11159
11160 // Erase old position and draw a line at current position
11161 TView *view = gPad->GetView();
11162 if (!view) return;
11163 TH3 *h3 = (TH3*)fH;
11164 TAxis *xaxis = h3->GetXaxis();
11165 TAxis *yaxis = h3->GetYaxis();
11166 TAxis *zaxis = h3->GetZaxis();
11167 Double_t u[3],xx[3];
11168
11169 static TPoint line1[2];//store end points of a line, initialised 0 by default
11170 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
11171 static TPoint line3[2];
11172 static TPoint line4[2];
11173 static TPoint endface1[5];
11174 static TPoint endface2[5];
11175 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
11176 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
11177
11178 Double_t uxmin = gPad->GetUxmin();
11179 Double_t uxmax = gPad->GetUxmax();
11180 Double_t uymin = gPad->GetUymin();
11181 Double_t uymax = gPad->GetUymax();
11182
11183 int pxmin = gPad->XtoAbsPixel(uxmin);
11184 int pxmax = gPad->XtoAbsPixel(uxmax);
11185 if (pxmin==pxmax) return;
11186 int pymin = gPad->YtoAbsPixel(uymin);
11187 int pymax = gPad->YtoAbsPixel(uymax);
11188 if (pymin==pymax) return;
11191 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
11192 (size_t)fH, fShowProjection).Data());
11193 if (!c) {
11194 fShowProjection = 0;
11195 return;
11196 }
11197
11199
11200 switch ((Int_t)fShowProjection%100) {
11201 case 1:
11202 // "x"
11203 {
11204 Int_t firstY = yaxis->GetFirst();
11205 Int_t lastY = yaxis->GetLast();
11207 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11208 yaxis->SetRange(biny,biny2);
11209 Int_t firstZ = zaxis->GetFirst();
11210 Int_t lastZ = zaxis->GetLast();
11212 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11213 zaxis->SetRange(binz,binz2);
11214 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11215 if (nbins>1 && line1[0].GetX()) {
11216 gVirtualX->DrawPolyLine(2,line2);
11217 gVirtualX->DrawPolyLine(2,line3);
11218 gVirtualX->DrawPolyLine(2,line4);
11219 gVirtualX->DrawPolyLine(5,endface1);
11220 gVirtualX->DrawPolyLine(5,endface2);
11221 }
11222 xx[0] = xaxis->GetXmin();
11223 xx[2] = zaxis->GetBinCenter(binz);
11224 xx[1] = yaxis->GetBinCenter(biny);
11225 view->WCtoNDC(xx,u);
11226 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11227 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11228 xx[0] = xaxis->GetXmax();
11229 view->WCtoNDC(xx,u);
11230 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11231 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11232 gVirtualX->DrawPolyLine(2,line1);
11233 if (nbins>1) {
11234 xx[0] = xaxis->GetXmin();
11235 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11236 xx[1] = yaxis->GetBinCenter(biny);
11237 view->WCtoNDC(xx,u);
11238 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11239 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11240 xx[0] = xaxis->GetXmax();
11241 view->WCtoNDC(xx,u);
11242 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11243 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11244
11245 xx[0] = xaxis->GetXmin();
11246 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11247 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11248 view->WCtoNDC(xx,u);
11249 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11250 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11251 xx[0] = xaxis->GetXmax();
11252 view->WCtoNDC(xx,u);
11253 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11254 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11255
11256 xx[0] = xaxis->GetXmin();
11257 xx[2] = zaxis->GetBinCenter(binz);
11258 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11259 view->WCtoNDC(xx,u);
11260 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11261 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11262 xx[0] = xaxis->GetXmax();
11263 view->WCtoNDC(xx,u);
11264 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11265 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11266
11267 endface1[0].SetX(line1[0].GetX());
11268 endface1[0].SetY(line1[0].GetY());
11269 endface1[1].SetX(line2[0].GetX());
11270 endface1[1].SetY(line2[0].GetY());
11271 endface1[2].SetX(line3[0].GetX());
11272 endface1[2].SetY(line3[0].GetY());
11273 endface1[3].SetX(line4[0].GetX());
11274 endface1[3].SetY(line4[0].GetY());
11275 endface1[4].SetX(line1[0].GetX());
11276 endface1[4].SetY(line1[0].GetY());
11277
11278 endface2[0].SetX(line1[1].GetX());
11279 endface2[0].SetY(line1[1].GetY());
11280 endface2[1].SetX(line2[1].GetX());
11281 endface2[1].SetY(line2[1].GetY());
11282 endface2[2].SetX(line3[1].GetX());
11283 endface2[2].SetY(line3[1].GetY());
11284 endface2[3].SetX(line4[1].GetX());
11285 endface2[3].SetY(line4[1].GetY());
11286 endface2[4].SetX(line1[1].GetX());
11287 endface2[4].SetY(line1[1].GetY());
11288
11289 gVirtualX->DrawPolyLine(2,line2);
11290 gVirtualX->DrawPolyLine(2,line3);
11291 gVirtualX->DrawPolyLine(2,line4);
11292 gVirtualX->DrawPolyLine(5,endface1);
11293 gVirtualX->DrawPolyLine(5,endface2);
11294 }
11295 c->Clear();
11296 c->cd();
11297 TH1 *hp = h3->Project3D("x");
11298 yaxis->SetRange(firstY,lastY);
11299 zaxis->SetRange(firstZ,lastZ);
11300 if (hp) {
11301 hp->SetFillColor(38);
11302 if (nbins == 1)
11303 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11304 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11305 else {
11306 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),
11307 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11308 }
11309 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11310 hp->SetYTitle("Number of Entries");
11311 hp->Draw(fShowOption.Data());
11312 }
11313 }
11314 break;
11315
11316 case 2:
11317 // "y"
11318 {
11319 Int_t firstX = xaxis->GetFirst();
11320 Int_t lastX = xaxis->GetLast();
11322 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11323 xaxis->SetRange(binx,binx2);
11324 Int_t firstZ = zaxis->GetFirst();
11325 Int_t lastZ = zaxis->GetLast();
11327 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11328 zaxis->SetRange(binz,binz2);
11329 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11330 if (nbins>1 && line1[0].GetX()) {
11331 gVirtualX->DrawPolyLine(2,line2);
11332 gVirtualX->DrawPolyLine(2,line3);
11333 gVirtualX->DrawPolyLine(2,line4);
11334 gVirtualX->DrawPolyLine(5,endface1);
11335 gVirtualX->DrawPolyLine(5,endface2);
11336 }
11337 xx[0]=xaxis->GetBinCenter(binx);
11338 xx[2] = zaxis->GetBinCenter(binz);
11339 xx[1] = yaxis->GetXmin();
11340 view->WCtoNDC(xx,u);
11341 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11342 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11343 xx[1] = yaxis->GetXmax();
11344 view->WCtoNDC(xx,u);
11345 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11346 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11347 gVirtualX->DrawPolyLine(2,line1);
11348 if (nbins>1) {
11349 xx[1] = yaxis->GetXmin();
11350 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11351 xx[0] = xaxis->GetBinCenter(binx);
11352 view->WCtoNDC(xx,u);
11353 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11354 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11355 xx[1] = yaxis->GetXmax();
11356 view->WCtoNDC(xx,u);
11357 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11358 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11359
11360 xx[1] = yaxis->GetXmin();
11361 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11362 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11363 view->WCtoNDC(xx,u);
11364 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11365 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11366 xx[1] = yaxis->GetXmax();
11367 view->WCtoNDC(xx,u);
11368 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11369 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11370
11371 xx[1] = yaxis->GetXmin();
11372 xx[2] = zaxis->GetBinCenter(binz);
11373 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11374 view->WCtoNDC(xx,u);
11375 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11376 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11377 xx[1] = yaxis->GetXmax();
11378 view->WCtoNDC(xx,u);
11379 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11380 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11381
11382 endface1[0].SetX(line1[0].GetX());
11383 endface1[0].SetY(line1[0].GetY());
11384 endface1[1].SetX(line2[0].GetX());
11385 endface1[1].SetY(line2[0].GetY());
11386 endface1[2].SetX(line3[0].GetX());
11387 endface1[2].SetY(line3[0].GetY());
11388 endface1[3].SetX(line4[0].GetX());
11389 endface1[3].SetY(line4[0].GetY());
11390 endface1[4].SetX(line1[0].GetX());
11391 endface1[4].SetY(line1[0].GetY());
11392
11393 endface2[0].SetX(line1[1].GetX());
11394 endface2[0].SetY(line1[1].GetY());
11395 endface2[1].SetX(line2[1].GetX());
11396 endface2[1].SetY(line2[1].GetY());
11397 endface2[2].SetX(line3[1].GetX());
11398 endface2[2].SetY(line3[1].GetY());
11399 endface2[3].SetX(line4[1].GetX());
11400 endface2[3].SetY(line4[1].GetY());
11401 endface2[4].SetX(line1[1].GetX());
11402 endface2[4].SetY(line1[1].GetY());
11403
11404 gVirtualX->DrawPolyLine(2,line2);
11405 gVirtualX->DrawPolyLine(2,line3);
11406 gVirtualX->DrawPolyLine(2,line4);
11407 gVirtualX->DrawPolyLine(5,endface1);
11408 gVirtualX->DrawPolyLine(5,endface2);
11409 }
11410 c->Clear();
11411 c->cd();
11412 TH1 *hp = h3->Project3D("y");
11413 xaxis->SetRange(firstX,lastX);
11414 zaxis->SetRange(firstZ,lastZ);
11415 if (hp) {
11416 hp->SetFillColor(38);
11417 if (nbins == 1)
11418 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11419 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11420 else
11421 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),
11422 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11423 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11424 hp->SetYTitle("Number of Entries");
11425 hp->Draw(fShowOption.Data());
11426 }
11427 }
11428 break;
11429
11430 case 3:
11431 // "z"
11432 {
11433 Int_t firstX = xaxis->GetFirst();
11434 Int_t lastX = xaxis->GetLast();
11436 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11437 xaxis->SetRange(binx,binx2);
11438 Int_t firstY = yaxis->GetFirst();
11439 Int_t lastY = yaxis->GetLast();
11441 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11442 yaxis->SetRange(biny,biny2);
11443 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11444 if (nbins>1 && line1[0].GetX()) {
11445 gVirtualX->DrawPolyLine(2,line2);
11446 gVirtualX->DrawPolyLine(2,line3);
11447 gVirtualX->DrawPolyLine(2,line4);
11448 gVirtualX->DrawPolyLine(5,endface1);
11449 gVirtualX->DrawPolyLine(5,endface2);
11450 }
11451 xx[0] = xaxis->GetBinCenter(binx);
11452 xx[1] = yaxis->GetBinCenter(biny);
11453 xx[2] = zaxis->GetXmin();
11454 view->WCtoNDC(xx,u);
11455 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11456 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11457 xx[2] = zaxis->GetXmax();
11458 view->WCtoNDC(xx,u);
11459 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11460 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11461 gVirtualX->DrawPolyLine(2,line1);
11462 if (nbins>1) {
11463 xx[2] = zaxis->GetXmin();
11464 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11465 xx[0] = xaxis->GetBinCenter(binx);
11466 view->WCtoNDC(xx,u);
11467 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11468 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11469 xx[2] = zaxis->GetXmax();
11470 view->WCtoNDC(xx,u);
11471 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11472 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11473
11474 xx[2] = zaxis->GetXmin();
11475 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11476 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11477 view->WCtoNDC(xx,u);
11478 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11479 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11480 xx[2] = zaxis->GetXmax();
11481 view->WCtoNDC(xx,u);
11482 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11483 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11484
11485 xx[2] = zaxis->GetXmin();
11486 xx[1] = yaxis->GetBinCenter(biny);
11487 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11488 view->WCtoNDC(xx,u);
11489 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11490 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11491 xx[2] = zaxis->GetXmax();
11492 view->WCtoNDC(xx,u);
11493 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11494 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11495
11496 endface1[0].SetX(line1[0].GetX());
11497 endface1[0].SetY(line1[0].GetY());
11498 endface1[1].SetX(line2[0].GetX());
11499 endface1[1].SetY(line2[0].GetY());
11500 endface1[2].SetX(line3[0].GetX());
11501 endface1[2].SetY(line3[0].GetY());
11502 endface1[3].SetX(line4[0].GetX());
11503 endface1[3].SetY(line4[0].GetY());
11504 endface1[4].SetX(line1[0].GetX());
11505 endface1[4].SetY(line1[0].GetY());
11506
11507 endface2[0].SetX(line1[1].GetX());
11508 endface2[0].SetY(line1[1].GetY());
11509 endface2[1].SetX(line2[1].GetX());
11510 endface2[1].SetY(line2[1].GetY());
11511 endface2[2].SetX(line3[1].GetX());
11512 endface2[2].SetY(line3[1].GetY());
11513 endface2[3].SetX(line4[1].GetX());
11514 endface2[3].SetY(line4[1].GetY());
11515 endface2[4].SetX(line1[1].GetX());
11516 endface2[4].SetY(line1[1].GetY());
11517
11518 gVirtualX->DrawPolyLine(2,line2);
11519 gVirtualX->DrawPolyLine(2,line3);
11520 gVirtualX->DrawPolyLine(2,line4);
11521 gVirtualX->DrawPolyLine(5,endface1);
11522 gVirtualX->DrawPolyLine(5,endface2);
11523 }
11524 c->Clear();
11525 c->cd();
11526 TH1 *hp = h3->Project3D("z");
11527 xaxis->SetRange(firstX,lastX);
11528 yaxis->SetRange(firstY,lastY);
11529 if (hp) {
11530 hp->SetFillColor(38);
11531 if (nbins == 1)
11532 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11533 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11534 else
11535 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),
11536 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11537 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11538 hp->SetYTitle("Number of Entries");
11539 hp->Draw(fShowOption.Data());
11540 }
11541 }
11542 break;
11543
11544 case 4:
11545 // "xy"
11546 {
11547 Int_t first = zaxis->GetFirst();
11548 Int_t last = zaxis->GetLast();
11549 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11550 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11551 zaxis->SetRange(binz,binz2);
11552 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11553 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11554 xx[0] = xaxis->GetXmin();
11555 xx[1] = yaxis->GetXmax();
11556 xx[2] = zaxis->GetBinCenter(binz);
11557 view->WCtoNDC(xx,u);
11558 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11559 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11560 rect1[4].SetX(rect1[0].GetX());
11561 rect1[4].SetY(rect1[0].GetY());
11562 xx[0] = xaxis->GetXmax();
11563 view->WCtoNDC(xx,u);
11564 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11565 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11566 xx[1] = yaxis->GetXmin();
11567 view->WCtoNDC(xx,u);
11568 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11569 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11570 xx[0] = xaxis->GetXmin();
11571 view->WCtoNDC(xx,u);
11572 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11573 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11574 gVirtualX->DrawPolyLine(5,rect1);
11575 if (nbins>1) {
11576 xx[0] = xaxis->GetXmin();
11577 xx[1] = yaxis->GetXmax();
11578 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11579 view->WCtoNDC(xx,u);
11580 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11581 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11582 rect2[4].SetX(rect2[0].GetX());
11583 rect2[4].SetY(rect2[0].GetY());
11584 xx[0] = xaxis->GetXmax();
11585 view->WCtoNDC(xx,u);
11586 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11587 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11588 xx[1] = yaxis->GetXmin();
11589 view->WCtoNDC(xx,u);
11590 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11591 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11592 xx[0] = xaxis->GetXmin();
11593 view->WCtoNDC(xx,u);
11594 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11595 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11596 gVirtualX->DrawPolyLine(5,rect2);
11597 }
11598
11599 c->Clear();
11600 c->cd();
11601 TH2 *hp = (TH2*)h3->Project3D("xy");
11602 zaxis->SetRange(first,last);
11603 if (hp) {
11604 hp->SetFillColor(38);
11605 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11606 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11607 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11608 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11609 hp->SetZTitle("Number of Entries");
11610 hp->Draw(fShowOption.Data());
11611 }
11612 }
11613 break;
11614
11615 case 5:
11616 // "yx"
11617 {
11618 Int_t first = zaxis->GetFirst();
11619 Int_t last = zaxis->GetLast();
11620 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11621 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11622 zaxis->SetRange(binz,binz2);
11623 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11624 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11625 xx[0] = xaxis->GetXmin();
11626 xx[1] = yaxis->GetXmax();
11627 xx[2] = zaxis->GetBinCenter(binz);
11628 view->WCtoNDC(xx,u);
11629 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11630 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11631 rect1[4].SetX(rect1[0].GetX());
11632 rect1[4].SetY(rect1[0].GetY());
11633 xx[0] = xaxis->GetXmax();
11634 view->WCtoNDC(xx,u);
11635 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11636 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11637 xx[1] = yaxis->GetXmin();
11638 view->WCtoNDC(xx,u);
11639 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11640 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11641 xx[0] = xaxis->GetXmin();
11642 view->WCtoNDC(xx,u);
11643 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11644 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11645 gVirtualX->DrawPolyLine(5,rect1);
11646 if (nbins>1) {
11647 xx[0] = xaxis->GetXmin();
11648 xx[1] = yaxis->GetXmax();
11649 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11650 view->WCtoNDC(xx,u);
11651 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11652 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11653 rect2[4].SetX(rect2[0].GetX());
11654 rect2[4].SetY(rect2[0].GetY());
11655 xx[0] = xaxis->GetXmax();
11656 view->WCtoNDC(xx,u);
11657 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11658 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11659 xx[1] = yaxis->GetXmin();
11660 view->WCtoNDC(xx,u);
11661 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11662 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11663 xx[0] = xaxis->GetXmin();
11664 view->WCtoNDC(xx,u);
11665 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11666 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11667 gVirtualX->DrawPolyLine(5,rect2);
11668 }
11669 c->Clear();
11670 c->cd();
11671 TH2 *hp = (TH2*)h3->Project3D("yx");
11672 zaxis->SetRange(first,last);
11673 if (hp) {
11674 hp->SetFillColor(38);
11675 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11676 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11677 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11678 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11679 hp->SetZTitle("Number of Entries");
11680 hp->Draw(fShowOption.Data());
11681 }
11682 }
11683 break;
11684
11685 case 6:
11686 // "xz"
11687 {
11688 Int_t first = yaxis->GetFirst();
11689 Int_t last = yaxis->GetLast();
11690 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11691 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11692 yaxis->SetRange(biny,biny2);
11693 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11694 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11695 xx[0] = xaxis->GetXmin();
11696 xx[2] = zaxis->GetXmax();
11697 xx[1] = yaxis->GetBinCenter(biny);
11698 view->WCtoNDC(xx,u);
11699 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11700 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11701 rect1[4].SetX(rect1[0].GetX());
11702 rect1[4].SetY(rect1[0].GetY());
11703 xx[0] = xaxis->GetXmax();
11704 view->WCtoNDC(xx,u);
11705 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11706 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11707 xx[2] = zaxis->GetXmin();
11708 view->WCtoNDC(xx,u);
11709 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11710 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11711 xx[0] = xaxis->GetXmin();
11712 view->WCtoNDC(xx,u);
11713 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11714 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11715 gVirtualX->DrawPolyLine(5,rect1);
11716 if (nbins>1) {
11717 xx[0] = xaxis->GetXmin();
11718 xx[2] = zaxis->GetXmax();
11719 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11720 view->WCtoNDC(xx,u);
11721 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11722 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11723 rect2[4].SetX(rect2[0].GetX());
11724 rect2[4].SetY(rect2[0].GetY());
11725 xx[0] = xaxis->GetXmax();
11726 view->WCtoNDC(xx,u);
11727 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11728 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11729 xx[2] = zaxis->GetXmin();
11730 view->WCtoNDC(xx,u);
11731 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11732 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11733 xx[0] = xaxis->GetXmin();
11734 view->WCtoNDC(xx,u);
11735 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11736 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11737 gVirtualX->DrawPolyLine(5,rect2);
11738 }
11739 c->Clear();
11740 c->cd();
11741 TH2 *hp = (TH2*)h3->Project3D("xz");
11742 yaxis->SetRange(first,last);
11743 if (hp) {
11744 hp->SetFillColor(38);
11745 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11746 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11747 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11748 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11749 hp->SetZTitle("Number of Entries");
11750 hp->Draw(fShowOption.Data());
11751 }
11752 }
11753 break;
11754
11755 case 7:
11756 // "zx"
11757 {
11758 Int_t first = yaxis->GetFirst();
11759 Int_t last = yaxis->GetLast();
11760 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11761 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11762 yaxis->SetRange(biny,biny2);
11763 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11764 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11765 xx[0] = xaxis->GetXmin();
11766 xx[2] = zaxis->GetXmax();
11767 xx[1] = yaxis->GetBinCenter(biny);
11768 view->WCtoNDC(xx,u);
11769 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11770 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11771 rect1[4].SetX(rect1[0].GetX());
11772 rect1[4].SetY(rect1[0].GetY());
11773 xx[0] = xaxis->GetXmax();
11774 view->WCtoNDC(xx,u);
11775 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11776 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11777 xx[2] = zaxis->GetXmin();
11778 view->WCtoNDC(xx,u);
11779 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11780 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11781 xx[0] = xaxis->GetXmin();
11782 view->WCtoNDC(xx,u);
11783 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11784 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11785 gVirtualX->DrawPolyLine(5,rect1);
11786 if (nbins>1) {
11787 xx[0] = xaxis->GetXmin();
11788 xx[2] = zaxis->GetXmax();
11789 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11790 view->WCtoNDC(xx,u);
11791 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11792 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11793 rect2[4].SetX(rect2[0].GetX());
11794 rect2[4].SetY(rect2[0].GetY());
11795 xx[0] = xaxis->GetXmax();
11796 view->WCtoNDC(xx,u);
11797 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11798 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11799 xx[2] = zaxis->GetXmin();
11800 view->WCtoNDC(xx,u);
11801 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11802 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11803 xx[0] = xaxis->GetXmin();
11804 view->WCtoNDC(xx,u);
11805 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11806 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11807 gVirtualX->DrawPolyLine(5,rect2);
11808 }
11809 c->Clear();
11810 c->cd();
11811 TH2 *hp = (TH2*)h3->Project3D("zx");
11812 yaxis->SetRange(first,last);
11813 if (hp) {
11814 hp->SetFillColor(38);
11815 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11816 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11817 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11818 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11819 hp->SetZTitle("Number of Entries");
11820 hp->Draw(fShowOption.Data());
11821 }
11822 }
11823 break;
11824
11825 case 8:
11826 // "yz"
11827 {
11828 Int_t first = xaxis->GetFirst();
11829 Int_t last = xaxis->GetLast();
11830 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11831 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11832 xaxis->SetRange(binx,binx2);
11833 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11834 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11835 xx[2] = zaxis->GetXmin();
11836 xx[1] = yaxis->GetXmax();
11837 xx[0] = xaxis->GetBinCenter(binx);
11838 view->WCtoNDC(xx,u);
11839 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11840 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11841 rect1[4].SetX(rect1[0].GetX());
11842 rect1[4].SetY(rect1[0].GetY());
11843 xx[2] = zaxis->GetXmax();
11844 view->WCtoNDC(xx,u);
11845 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11846 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11847 xx[1] = yaxis->GetXmin();
11848 view->WCtoNDC(xx,u);
11849 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11850 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11851 xx[2] = zaxis->GetXmin();
11852 view->WCtoNDC(xx,u);
11853 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11854 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11855 gVirtualX->DrawPolyLine(5,rect1);
11856 if (nbins>1) {
11857 xx[2] = zaxis->GetXmin();
11858 xx[1] = yaxis->GetXmax();
11859 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11860 view->WCtoNDC(xx,u);
11861 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11862 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11863 rect2[4].SetX(rect2[0].GetX());
11864 rect2[4].SetY(rect2[0].GetY());
11865 xx[2] = zaxis->GetXmax();
11866 view->WCtoNDC(xx,u);
11867 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11868 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11869 xx[1] = yaxis->GetXmin();
11870 view->WCtoNDC(xx,u);
11871 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11872 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11873 xx[2] = zaxis->GetXmin();
11874 view->WCtoNDC(xx,u);
11875 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11876 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11877 gVirtualX->DrawPolyLine(5,rect2);
11878 }
11879 c->Clear();
11880 c->cd();
11881 TH2 *hp = (TH2*)h3->Project3D("yz");
11882 xaxis->SetRange(first,last);
11883 if (hp) {
11884 hp->SetFillColor(38);
11885 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11886 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11887 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11888 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11889 hp->SetZTitle("Number of Entries");
11890 hp->Draw(fShowOption.Data());
11891 }
11892 }
11893 break;
11894
11895 case 9:
11896 // "zy"
11897 {
11898 Int_t first = xaxis->GetFirst();
11899 Int_t last = xaxis->GetLast();
11900 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11901 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11902 xaxis->SetRange(binx,binx2);
11903 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11904 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11905 xx[2] = zaxis->GetXmin();
11906 xx[1] = yaxis->GetXmax();
11907 xx[0] = xaxis->GetBinCenter(binx);
11908 view->WCtoNDC(xx,u);
11909 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11910 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11911 rect1[4].SetX(rect1[0].GetX());
11912 rect1[4].SetY(rect1[0].GetY());
11913 xx[2] = zaxis->GetXmax();
11914 view->WCtoNDC(xx,u);
11915 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11916 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11917 xx[1] = yaxis->GetXmin();
11918 view->WCtoNDC(xx,u);
11919 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11920 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11921 xx[2] = zaxis->GetXmin();
11922 view->WCtoNDC(xx,u);
11923 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11924 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11925 gVirtualX->DrawPolyLine(5,rect1);
11926 if (nbins>1) {
11927 xx[2] = zaxis->GetXmin();
11928 xx[1] = yaxis->GetXmax();
11929 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11930 view->WCtoNDC(xx,u);
11931 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11932 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11933 rect2[4].SetX(rect2[0].GetX());
11934 rect2[4].SetY(rect2[0].GetY());
11935 xx[2] = zaxis->GetXmax();
11936 view->WCtoNDC(xx,u);
11937 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11938 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11939 xx[1] = yaxis->GetXmin();
11940 view->WCtoNDC(xx,u);
11941 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11942 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11943 xx[2] = zaxis->GetXmin();
11944 view->WCtoNDC(xx,u);
11945 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11946 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11947 gVirtualX->DrawPolyLine(5,rect2);
11948 }
11949 c->Clear();
11950 c->cd();
11951 TH2 *hp = (TH2*)h3->Project3D("zy");
11952 xaxis->SetRange(first,last);
11953 if (hp) {
11954 hp->SetFillColor(38);
11955 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11956 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11957 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11958 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11959 hp->SetZTitle("Number of Entries");
11960 hp->Draw(fShowOption.Data());
11961 }
11962 }
11963 break;
11964 }
11965 c->Update();
11966}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
short Style_t
Style number (short)
Definition RtypesCore.h:96
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
short Color_t
Color number (short)
Definition RtypesCore.h:99
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Width_t
Line width (short)
Definition RtypesCore.h:98
float Float_t
Float 4 bytes (float)
Definition RtypesCore.h:71
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
#define BIT(n)
Definition Rtypes.h:91
@ kBlack
Definition Rtypes.h:66
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:414
R__EXTERN TStyle * gStyle
Definition TStyle.h:442
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
const Int_t kCARTESIAN
Definition TView3D.cxx:32
const Int_t kPOLAR
Definition TView3D.cxx:33
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
polygon * polys
Definition X3DBuffer.c:24
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:37
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:41
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:42
virtual Float_t GetTickLength() const
Definition TAttAxis.h:46
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:44
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:31
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:32
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:38
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:40
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:35
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:44
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:37
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:45
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:42
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:36
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:33
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:39
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:32
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:34
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:41
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:46
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:44
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:37
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:45
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:46
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:48
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:49
Class to manage histogram axis.
Definition TAxis.h:32
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:133
Bool_t IsAlphanumeric() const
Definition TAxis.h:90
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:137
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:482
Bool_t CanExtend() const
Definition TAxis.h:88
const TArrayD * GetXbins() const
Definition TAxis.h:138
Double_t GetXmax() const
Definition TAxis.h:142
@ kAxisRange
Definition TAxis.h:66
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:444
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:522
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x
Definition TAxis.cxx:422
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:127
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:473
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:604
Double_t GetXmin() const
Definition TAxis.h:141
Int_t GetNbins() const
Definition TAxis.h:127
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates, that is,...
Definition TAxis.cxx:1090
virtual const char * GetTimeFormat() const
Definition TAxis.h:134
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:546
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:532
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:462
THashList * GetLabels() const
Definition TAxis.h:123
Create a Box.
Definition TBox.h:22
The candle plot painter class.
Definition TCandle.h:27
CandleOption
Definition TCandle.h:30
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2473
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2973
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:22
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:83
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1926
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:2095
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2138
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:78
To draw a Crown.
Definition TCrown.h:19
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:503
1-Dim function class
Definition TF1.h:182
virtual Double_t GetXmax() const
Definition TF1.h:525
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition TF1.cxx:1939
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition TF1.cxx:1990
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition TF1.cxx:1980
static TClass * Class()
Double_t GetChisquare() const
Return the Chisquare after fitting. See ROOT::Fit::FitResult::Chi2()
Definition TF1.h:409
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3449
virtual Double_t GetMaximumStored() const
Definition TF1.h:438
virtual Int_t GetNpar() const
Definition TF1.h:446
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition TF1.cxx:1950
@ kNotDraw
Definition TF1.h:297
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3462
virtual const char * GetParName(Int_t ipar) const
Definition TF1.h:494
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition TF1.cxx:1446
virtual Double_t GetXmin() const
Definition TF1.h:521
virtual Double_t GetParameter(Int_t ipar) const
Definition TF1.h:477
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:805
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:133
static TClass * Class()
TF3 defines a 3D Function with Parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:26
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2954
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition TGaxis.cxx:1007
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:130
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2927
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:108
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:954
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:124
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:109
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2919
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:75
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition TGraph.cxx:2016
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition TGraph.cxx:2025
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
1-D histogram with a float per channel (see TH1 documentation)
Definition TH1.h:878
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
TAxis * GetZaxis()
Definition TH1.h:573
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:517
virtual Float_t GetBarWidth() const
Definition TH1.h:501
virtual Double_t GetMinimumStored() const
Definition TH1.h:537
virtual Float_t GetBarOffset() const
Definition TH1.h:500
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7699
virtual Int_t GetNbinsY() const
Definition TH1.h:542
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:9176
virtual Int_t GetNbinsZ() const
Definition TH1.h:543
virtual Double_t GetNormFactor() const
Definition TH1.h:545
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7627
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7763
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8552
virtual Int_t GetDimension() const
Definition TH1.h:527
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:408
@ kUserContour
User specified contour levels.
Definition TH1.h:404
@ kNoStats
Don't draw stats box.
Definition TH1.h:403
TAxis * GetXaxis()
Definition TH1.h:571
virtual Double_t GetSumOfWeights() const
Return the sum of weights across all bins excluding under/overflows.
Definition TH1.h:559
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:5020
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:8661
virtual Int_t GetNbinsX() const
Definition TH1.h:541
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:652
TAxis * GetYaxis()
Definition TH1.h:572
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:9192
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:653
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:8053
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:9335
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9265
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4457
TList * GetListOfFunctions() const
Definition TH1.h:488
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7667
virtual Double_t GetMaximumStored() const
Definition TH1.h:533
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8847
@ kNormal
Errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:115
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5122
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8523
const Double_t * GetBuffer() const
Definition TH1.h:483
virtual Bool_t IsHighlight() const
Definition TH1.h:585
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9276
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8599
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:9223
virtual Int_t GetSumw2N() const
Definition TH1.h:562
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7747
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:8751
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:5306
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1409
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7836
2-D histogram with a double per channel (see TH1 documentation)
Definition TH2.h:400
2-D histogram with a float per channel (see TH1 documentation)
Definition TH2.h:345
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
static TClass * Class()
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:45
static TClass * Class()
The Histogram stack class.
Definition THStack.h:40
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for sinusoidal projection from Ernst-Jan Buis Source https://en....
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
Int_t fShowProjection2
True if a second projection must be drawn (when calling SetShowProjectionXY on a TH2)
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectMollweide2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
void SetShowProjectionXY(const char *option, Int_t nbinsY, Int_t nbinsX) override
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code for parabolic projection from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:34
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:20
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:708
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:789
virtual TObjLink * FirstLink() const
Definition TList.h:107
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:487
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:67
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:50
An array of TObjects.
Definition TObjArray.h:31
Mother of all ROOT objects.
Definition TObject.h:42
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:458
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:204
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:442
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1075
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:422
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:882
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:544
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1089
virtual const char * GetTitle() const
Returns title of object.
Definition TObject.cxx:502
void ResetBit(UInt_t f)
Definition TObject.h:203
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:75
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:70
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:72
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:53
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:58
virtual void SetName(const char *name="")
Definition TPave.h:81
virtual void SetBorderSize(Int_t bordersize=4)
Sets the border size of the TPave box and shadow.
Definition TPave.h:79
Option_t * GetOption() const override
Definition TPave.h:59
Double_t GetX1NDC() const
Definition TPave.h:61
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:85
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
Profile Histogram.
Definition TProfile.h:32
static TClass * Class()
Random number generator class based on the maximally equidistributed combined Tausworthe generator by...
Definition TRandom2.h:27
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:138
void ToLower()
Change string to lower-case.
Definition TString.cxx:1189
const char * Data() const
Definition TString.h:384
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2384
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2362
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:641
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:660
Int_t GetOptStat() const
Definition TStyle.h:247
Color_t GetStatTextColor() const
Definition TStyle.h:260
Float_t GetTitleX() const
Definition TStyle.h:282
Int_t GetOptTitle() const
Definition TStyle.h:248
Float_t GetStatFontSize() const
Definition TStyle.h:263
Float_t GetBarOffset() const
Definition TStyle.h:184
Float_t GetStatX() const
Definition TStyle.h:266
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1241
Float_t GetTitleY() const
Definition TStyle.h:283
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1217
Bool_t GetHistMinimumZero() const
Definition TStyle.h:239
Float_t GetStatY() const
Definition TStyle.h:267
Color_t GetTitleFillColor() const
Definition TStyle.h:273
Style_t GetTitleStyle() const
Definition TStyle.h:275
Color_t GetStatColor() const
Definition TStyle.h:259
Float_t GetBarWidth() const
Definition TStyle.h:185
void SetDrawBorder(Int_t drawborder=1)
Definition TStyle.h:346
Float_t GetStatH() const
Definition TStyle.h:269
Width_t GetTitleBorderSize() const
Definition TStyle.h:277
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1102
Float_t GetErrorX() const
Definition TStyle.h:188
Double_t GetHistTopMargin() const
Definition TStyle.h:240
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:339
Float_t GetEndErrorSize() const
Definition TStyle.h:187
Int_t GetDrawBorder() const
Definition TStyle.h:186
Width_t GetStatBorderSize() const
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:274
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:340
Float_t GetTitleH() const
Definition TStyle.h:285
Style_t GetStatStyle() const
Definition TStyle.h:264
Float_t GetStatW() const
Definition TStyle.h:268
const char * GetFitFormat() const
Definition TStyle.h:201
const char * GetStatFormat() const
Definition TStyle.h:265
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1176
Int_t GetOptFit() const
Definition TStyle.h:246
Int_t GetNumberContours() const
Definition TStyle.h:243
const char * GetPaintTextFormat() const
Definition TStyle.h:252
Style_t GetStatFont() const
Definition TStyle.h:262
Float_t GetTitleFontSize() const
Definition TStyle.h:276
Int_t GetTitleAlign() const
Definition TStyle.h:272
Float_t GetTitleW() const
Definition TStyle.h:284
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1868
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:29
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void SetRange(const Double_t *min, const Double_t *max)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
return c2
Definition legend2.C:14
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:704
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:249
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:651
constexpr Double_t PiOver2()
Definition TMath.h:54
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:767
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:82
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:673
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:197
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:605
constexpr Double_t Pi()
Definition TMath.h:40
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:429
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:599
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:611
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:329
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:75
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:122
Histograms' drawing options structure.
Definition Hoption.h:24
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:32
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:59
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:30
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:41
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:48
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:50
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:43
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:60
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:58
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:70
int Zscale
"Z" Display the color palette.
Definition Hoption.h:55
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:63
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:44
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:35
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:45
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:53
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:61
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:56
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:52
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:39
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:62
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:72
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:51
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:57
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:37
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:40
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:36
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:38
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:47
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:31
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:34
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:46
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:49
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:71
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:54
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:33
Histogram parameters structure.
Definition Hparam.h:27
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:42
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:33
Double_t xmin
Minimum value along X.
Definition Hparam.h:30
Int_t ylast
Last bin number along Y.
Definition Hparam.h:47
Int_t xfirst
First bin number along X.
Definition Hparam.h:44
Double_t zmin
Minimum value along Z.
Definition Hparam.h:38
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:28
Double_t ymin
Minimum value along y.
Definition Hparam.h:34
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:41
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:29
Double_t ymax
Maximum value along y.
Definition Hparam.h:35
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:40
Int_t xlast
Last bin number along X.
Definition Hparam.h:45
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:43
Double_t zmax
Maximum value along Z.
Definition Hparam.h:39
Double_t xmax
Maximum value along X.
Definition Hparam.h:31
Int_t yfirst
First bin number along Y.
Definition Hparam.h:46
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16