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 "TGraph2DPainter.h"
49#include "TGraphDelaunay2D.h"
50#include "TView.h"
51#include "TMath.h"
52#include "TRandom2.h"
53#include "TObjArray.h"
54#include "Hoption.h"
55#include "Hparam.h"
56#include "TPluginManager.h"
57#include "TPaletteAxis.h"
58#include "TCrown.h"
59#include "TArrow.h"
60#include "TVirtualPadEditor.h"
61#include "TVirtualX.h"
62#include "TEnv.h"
63#include "TPoint.h"
64#include "TImage.h"
65#include "TCandle.h"
66#include "strlcpy.h"
67
68/*! \class THistPainter
69\ingroup Histpainter
70\brief The histogram painter class. Implements all histograms' drawing's options.
71
72- [Introduction](#HP00)
73- [Histograms' plotting options](#HP01)
74 - [Options supported for 1D and 2D histograms](#HP01a)
75 - [Options supported for 1D histograms](#HP01b)
76 - [Options supported for 2D histograms](#HP01c)
77 - [Options supported for 3D histograms](#HP01d)
78 - [Options supported for histograms' stacks (THStack)](#HP01e)
79- [Setting the Style](#HP02)
80- [Setting line, fill, marker, and text attributes](#HP03)
81- [Setting Tick marks on the histogram axis](#HP04)
82- [Giving titles to the X, Y and Z axis](#HP05)
83- [The option "SAME"](#HP060)
84 - [Limitations](#HP060a)
85- [Colors automatically picked in palette](#HP061)
86- [Superimposing two histograms with different scales in the same pad](#HP06)
87- [Statistics Display](#HP07)
88- [Fit Statistics](#HP08)
89- [The error bars options](#HP09)
90- [The bar chart option](#HP100)
91- [The "BAR" and "HBAR" options](#HP10)
92- [The SCATter plot option (default for 2D histograms)](#HP11)
93- [The ARRow option](#HP12)
94- [The BOX option](#HP13)
95- [The COLor option](#HP14)
96- [The CANDLE and VIOLIN options](#HP140)
97 - [The CANDLE option](#HP140a)
98 - [The VIOLIN option](#HP140b)
99- [The TEXT and TEXTnn Option](#HP15)
100- [The CONTour options](#HP16)
101 - [The LIST option](#HP16a)
102 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](#HP16b)
103- [The LEGO options](#HP17)
104- [The "SURFace" options](#HP18)
105- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](#HP19)
106- [Base line for bar-charts and lego plots](#HP20)
107- [TH2Poly Drawing](#HP20a)
108- [The SPEC option](#HP21)
109- [Option "Z" : Adding the color palette on the right side of the pad](#HP22)
110- [Setting the color palette](#HP23)
111- [Drawing a sub-range of a 2-D histogram; the [cutg] option](#HP24)
112- [Drawing options for 3D histograms](#HP25)
113- [Drawing option for histograms' stacks](#HP26)
114- [Drawing of 3D implicit functions](#HP27)
115- [Associated functions drawing](#HP28)
116- [Drawing using OpenGL](#HP29)
117 - [General information: plot types and supported options](#HP29a)
118 - [TH3 as color boxes](#HP290)
119 - [TH3 as boxes (spheres)](#HP29b)
120 - [TH3 as iso-surface(s)](#HP29c)
121 - [TF3 (implicit function)](#HP29d)
122 - [Parametric surfaces](#HP29e)
123 - [Interaction with the plots](#HP29f)
124 - [Selectable parts](#HP29g)
125 - [Rotation and zooming](#HP29h)
126 - [Panning](#HP29i)
127 - [Box cut](#HP29j)
128 - [Plot specific interactions (dynamic slicing etc.)](#HP29k)
129 - [Surface with option "GLSURF"](#HP29l)
130 - [TF3](#HP29m)
131 - [Box](#HP29n)
132 - [Iso](#HP29o)
133 - [Parametric plot](#HP29p)
134- [Highlight mode for histogram](#HP30)
135 - [Highlight mode and user function](#HP30a)
136
137
138## <a name="HP00"></a> Introduction
139
140
141Histograms are drawn via the `THistPainter` class. Each histogram has a
142pointer to its own painter (to be usable in a multithreaded program). When the
143canvas has to be redrawn, the `Paint` function of each objects in the
144pad is called. In case of histograms, `TH1::Paint` invokes directly
145`THistPainter::Paint`.
146
147To draw a histogram `h` it is enough to do:
148
149 h->Draw();
150
151`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
152be drawn, the `Draw()` method can be invoked with an option. For instance
153to draw a 2D histogram as a lego plot it is enough to do:
154
155 h->Draw("lego");
156
157`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
158
159When the `Draw()` method of a histogram is called for the first time
160(`TH1::Draw`), it creates a `THistPainter` object and saves a
161pointer to this "painter" as a data member of the histogram. The
162`THistPainter` class specializes in the drawing of histograms. It is
163separated from the histogram so that one can have histograms without the
164graphics overhead, for example in a batch program. Each histogram having its own
165painter (rather than a central singleton painter painting all histograms), allows
166two histograms to be drawn in two threads without overwriting the painter's
167values.
168
169When a displayed histogram is filled again, there is no need to call the
170`Draw()` method again; the image will be refreshed the next time the
171pad will be updated.
172
173A pad is updated after one of these three actions:
174
1751. a carriage control on the ROOT command line,
1762. a click inside the pad,
1773. a call to `TPad::Update`.
178
179
180By default a call to `TH1::Draw()` clears the pad of all objects
181before drawing the new image of the histogram. One can use the `SAME`
182option to leave the previous display intact and superimpose the new histogram.
183The same histogram can be drawn with different graphics options in different
184pads.
185
186When a displayed histogram is deleted, its image is automatically removed
187from the pad.
188
189To create a copy of the histogram when drawing it, one can use
190`TH1::DrawClone()`. This will clone the histogram and allow to change
191and delete the original one without affecting the clone.
192
193
194### <a name="HP01"></a> Histograms' plotting options
195
196
197Most options can be concatenated with or without spaces or commas, for example:
198
199 h->Draw("E1 SAME");
200
201The options are not case sensitive:
202
203 h->Draw("e1 same");
204
205
206The default drawing option can be set with `TH1::SetOption` and retrieve
207using `TH1::GetOption`:
208
209 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
210 root [1] h->Draw("E"); // Draw "h" using error bars
211 root [3] h->SetOption("E"); // Change the default drawing option for "h"
212 root [4] h->Draw(); // Draw "h" using error bars
213 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
214 (const Option_t* 0xa3ff948)"E"
215
216
217#### <a name="HP01a"></a> Options supported for 1D and 2D histograms
218
219| Option | Description |
220|----------|-------------------------------------------------------------------|
221| "E" | Draw error bars. |
222| "AXIS" | Draw only axis. |
223| "AXIG" | Draw only grid (if the grid is requested). |
224| <a name="OPTHIST">"HIST"</a> | 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). |
225| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
226| "SAME" | Superimpose on previous picture in the same pad. |
227| "SAMES" | Same as "SAME" and draw the statistics box|
228| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
229| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
230| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
231| "LEGO" | Draw a lego plot with hidden line removal. |
232| "LEGO1" | Draw a lego plot with hidden surface removal. |
233| "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.|
234| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
235| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
236| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
237| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90). |
238| "X+" | The X-axis is drawn on the top side of the plot. |
239| "Y+" | The Y-axis is drawn on the right side of the plot. |
240| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
241
242#### <a name="HP01b"></a> Options supported for 1D histograms
243
244| Option | Description |
245|----------|-------------------------------------------------------------------|
246| " " | Default. |
247| "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.|
248| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
249| "B" | Bar chart option.|
250| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
251| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
252| "C" | Draw a smooth Curve through the histogram bins.|
253| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
254| "E1" | Draw error bars with perpendicular lines at the edges.|
255| "E2" | Draw error bars with rectangles.|
256| "E3" | Draw a fill area through the end points of the vertical error bars.|
257| "E4" | Draw a smoothed filled area through the end points of the error bars.|
258| "E5" | Like E3 but ignore the bins with 0 contents.|
259| "E6" | Like E4 but ignore the bins with 0 contents.|
260| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
261| "L" | Draw a line through the bin contents.|
262| "P" | Draw current marker at each bin except empty bins.|
263| "P0" | Draw current marker at each bin including empty bins.|
264| "PIE" | Draw histogram as a Pie Chart.|
265| "*H" | Draw histogram with a * at each bin.|
266| "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.|
267
268
269#### <a name="HP01c"></a> Options supported for 2D histograms
270
271| Option | Description |
272|-----------|------------------------------------------------------------------|
273| " " | Default (scatter plot).|
274| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
275| "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.|
276| "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.|
277| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted.|
278| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
279| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
280| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
281| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boudaries. For more details see `TPaletteAxis`|
282| "CANDLE" | Draw a candle plot along X axis.|
283| "CANDLEX" | Same as "CANDLE".|
284| "CANDLEY" | Draw a candle plot along Y axis.|
285| "CANDLEXn"| Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
286| "CANDLEYn"| Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
287| "VIOLIN" | Draw a violin plot along X axis.|
288| "VIOLINX" | Same as "VIOLIN".|
289| "VIOLINY" | Draw a violin plot along Y axis.|
290| "VIOLINXn"| Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
291| "VIOLINYn"| Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
292| "CONT" | Draw a contour plot (same as CONT0).|
293| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
294| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
295| "CONT2" | Draw a contour plot using the same line style for all contours.|
296| "CONT3" | Draw a contour plot using fill area colors.|
297| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
298| "CONT5" | (TGraph2D only) Draw a contour plot using Delaunay triangles.|
299| "LIST" | Generate a list of TGraph objects for each contour.|
300| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
301| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
302| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
303| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
304| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
305| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
306| "SURF" | Draw a surface plot with hidden line removal.|
307| "SURF1" | Draw a surface plot with hidden surface removal.|
308| "SURF2" | Draw a surface plot using colors to show the cell contents.|
309| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
310| "SURF4" | Draw a surface using Gouraud shading.|
311| "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.|
312| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
313| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
314| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
315| "A" | With LEGO or SURFACE, suppress the axis.|
316| "SCAT" | Draw a scatter-plot (default).|
317| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
318
319
320#### <a name="HP01d"></a> Options supported for 3D histograms
321
322| Option | Description |
323|----------|-------------------------------------------------------------------|
324| " " | Default (scatter plot).|
325| "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)`.|
326| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
327| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
328| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
329| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
330| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
331| "LEGO" | Same as `BOX`.|
332
333
334#### <a name="HP01e"></a> Options supported for histograms' stacks (`THStack`)
335
336| Option | Description |
337|------------|-----------------------------------------------------------------|
338| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
339| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
340| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
341| "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.|
342| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
343| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
344| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
345
346
347
348### <a name="HP02"></a> Setting the Style
349
350
351Histograms use the current style (`gStyle`). When one changes the current
352style and would like to propagate the changes to the histogram,
353`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
354each histogram is needed.
355
356To force all the histogram to use the current style use:
357
358 gROOT->ForceStyle();
359
360All the histograms read after this call will use the current style.
361
362
363### <a name="HP03"></a> Setting line, fill, marker, and text attributes
364
365
366The histogram classes inherit from the attribute classes:
367`TAttLine`, `TAttFill` and `TAttMarker`.
368See the description of these classes for the list of options.
369
370
371### <a name="HP04"></a> Setting Tick marks on the histogram axis
372
373
374The `TPad::SetTicks` method specifies the type of tick marks on the axis.
375If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
376
377 tx = 1; tick marks on top side are drawn (inside)
378 tx = 2; tick marks and labels on top side are drawn
379 ty = 1; tick marks on right side are drawn (inside)
380 ty = 2; tick marks and labels on right side are drawn
381
382By default only the left Y axis and X bottom axis are drawn
383(`tx = ty = 0`)
384
385`TPad::SetTicks(tx,ty)` allows to set these options.
386See also The `TAxis` functions to set specific axis attributes.
387
388In case multiple color filled histograms are drawn on the same pad, the fill
389area may hide the axis tick marks. One can force a redraw of the axis over all
390the histograms by calling:
391
392 gPad->RedrawAxis();
393
394
395### <a name="HP05"></a> Giving titles to the X, Y and Z axis
396
397
398 h->GetXaxis()->SetTitle("X axis title");
399 h->GetYaxis()->SetTitle("Y axis title");
400
401The histogram title and the axis titles can be any `TLatex` string.
402The titles are part of the persistent histogram.
403
404
405### <a name="HP060"></a> The option "SAME"
406
407
408By default, when an histogram is drawn, the current pad is cleared before
409drawing. In order to keep the previous drawing and draw on top of it the
410option `SAME` should be use. The histogram drawn with the option
411`SAME` uses the coordinates system available in the current pad.
412
413This option can be used alone or combined with any valid drawing option but
414some combinations must be use with care.
415
416#### <a name="HP060a"></a> Limitations
417
418- It does not work when combined with the `LEGO` and `SURF` options unless the
419 histogram plotted with the option `SAME` has exactly the same
420 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
421 lego plots [histograms' stacks](#HP26) should be used.
422
423
424### <a name="HP061"></a> Colors automatically picked in palette
425
426\since **ROOT version 6.09/01**
427
428When several histograms are painted in the same canvas thanks to the option "SAME"
429or via a `THStack` it might be useful to have an easy and automatic way to choose
430their color. The simplest way is to pick colors in the current active color
431palette. Palette coloring for histogram is activated thanks to the options `PFC`
432(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
433When one of these options is given to `TH1::Draw` the histogram get its color
434from the current color palette defined by `gStyle->SetPalette(…)`. The color
435is determined according to the number of objects having palette coloring in
436the current pad.
437
438Begin_Macro(source)
439../../../tutorials/hist/histpalettecolor.C
440End_Macro
441
442Begin_Macro(source)
443../../../tutorials/hist/thstackpalettecolor.C
444End_Macro
445
446Begin_Macro(source)
447../../../tutorials/hist/thstack2palettecolor.C
448End_Macro
449
450### <a name="HP06"></a> Superimposing two histograms with different scales in the same pad
451
452
453The following example creates two histograms, the second histogram is the bins
454integral of the first one. It shows a procedure to draw the two histograms in
455the same pad and it draws the scale of the second histogram using a new vertical
456axis on the right side. See also the tutorial `transpad.C` for a variant
457of this example.
458
459Begin_Macro(source)
460{
461 auto c1 = new TCanvas("c1","c1",600,400);
462 // create/fill draw h1
463 gStyle->SetOptStat(kFALSE);
464 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
465 Int_t i;
466 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
467 h1->Draw();
468 c1->Update();
469
470 // create hint1 filled with the bins integral of h1
471 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
472 float sum = 0.f;
473 for (i=1;i<=100;i++) {
474 sum += h1->GetBinContent(i);
475 hint1->SetBinContent(i,sum);
476 }
477
478 // scale hint1 to the pad coordinates
479 float rightmax = 1.1*hint1->GetMaximum();
480 float scale = gPad->GetUymax()/rightmax;
481 hint1->SetLineColor(kRed);
482 hint1->Scale(scale);
483 hint1->Draw("same");
484
485 // draw an axis on the right side
486 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
487 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
488 axis->SetLineColor(kRed);
489 axis->SetTextColor(kRed);
490 axis->Draw();
491}
492End_Macro
493
494
495### <a name="HP07"></a> Statistics Display
496
497
498The type of information shown in the histogram statistics box can be selected
499with:
500
501 gStyle->SetOptStat(mode);
502
503The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
504
505 mode = ksiourmen (default = 000001111)
506 k = 1; kurtosis printed
507 k = 2; kurtosis and kurtosis error printed
508 s = 1; skewness printed
509 s = 2; skewness and skewness error printed
510 i = 1; integral of bins printed
511 i = 2; integral of bins with option "width" printed
512 o = 1; number of overflows printed
513 u = 1; number of underflows printed
514 r = 1; standard deviation printed
515 r = 2; standard deviation and standard deviation error printed
516 m = 1; mean value printed
517 m = 2; mean and mean error values printed
518 e = 1; number of entries printed
519 n = 1; name of histogram is printed
520
521For example:
522
523 gStyle->SetOptStat(11);
524
525displays only the name of histogram and the number of entries, whereas:
526
527 gStyle->SetOptStat(1101);
528
529displays the name of histogram, mean value and standard deviation.
530
531<b>WARNING 1:</b> never do:
532
533 gStyle->SetOptStat(0001111);
534
535but instead do:
536
537 gStyle->SetOptStat(1111);
538
539because `0001111` will be taken as an octal number!
540
541<b>WARNING 2:</b> for backward compatibility with older versions
542
543 gStyle->SetOptStat(1);
544
545is taken as:
546
547 gStyle->SetOptStat(1111)
548
549To print only the name of the histogram do:
550
551 gStyle->SetOptStat(1000000001);
552
553<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
554(10000) or overflow (100000), the statistics box will show all combinations
555of underflow/overflows and not just one single number.
556
557The parameter mode can be any combination of the letters `kKsSiIourRmMen`
558
559 k : kurtosis printed
560 K : kurtosis and kurtosis error printed
561 s : skewness printed
562 S : skewness and skewness error printed
563 i : integral of bins printed
564 I : integral of bins with option "width" printed
565 o : number of overflows printed
566 u : number of underflows printed
567 r : standard deviation printed
568 R : standard deviation and standard deviation error printed
569 m : mean value printed
570 M : mean value mean error values printed
571 e : number of entries printed
572 n : name of histogram is printed
573
574For example, to print only name of histogram and number of entries do:
575
576 gStyle->SetOptStat("ne");
577
578To print only the name of the histogram do:
579
580 gStyle->SetOptStat("n");
581
582The default value is:
583
584 gStyle->SetOptStat("nemr");
585
586When a histogram is painted, a `TPaveStats` object is created and added
587to the list of functions of the histogram. If a `TPaveStats` object
588already exists in the histogram list of functions, the existing object is just
589updated with the current histogram parameters.
590
591Once a histogram is painted, the statistics box can be accessed using
592`h->FindObject("stats")`. In the command line it is enough to do:
593
594 Root > h->Draw()
595 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
596
597because after `h->Draw()` the histogram is automatically painted. But
598in a script file the painting should be forced using `gPad->Update()`
599in order to make sure the statistics box is created:
600
601 h->Draw();
602 gPad->Update();
603 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
604
605Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
606
607When a histogram is drawn with the option `SAME`, the statistics box
608is not drawn. To force the statistics box drawing with the option
609`SAME`, the option `SAMES` must be used.
610If the new statistics box hides the previous statistics box, one can change
611its position with these lines (`h` being the pointer to the histogram):
612
613 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
614 Root > st->SetX1NDC(newx1); //new x start position
615 Root > st->SetX2NDC(newx2); //new x end position
616
617To change the type of information for an histogram with an existing
618`TPaveStats` one should do:
619
620 st->SetOptStat(mode);
621
622Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
623(see above).
624
625One can delete the statistics box for a histogram `TH1* h` with:
626
627 h->SetStats(0)
628
629and activate it again with:
630
631 h->SetStats(1).
632
633Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
634`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
635
636
637### <a name="HP08"></a> Fit Statistics
638
639
640The type of information about fit parameters printed in the histogram statistics
641box can be selected via the parameter mode. The parameter mode can be
642`= pcev` (default `= 0111`)
643
644 p = 1; print Probability
645 c = 1; print Chisquare/Number of degrees of freedom
646 e = 1; print errors (if e=1, v must be 1)
647 v = 1; print name/values of parameters
648
649Example:
650
651 gStyle->SetOptFit(1011);
652
653print fit probability, parameter names/values and errors.
654
6551. When `v = 1` is specified, only the non-fixed parameters are shown.
6562. When `v = 2` all parameters are shown.
657
658Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
659to `gStyle->SetOptFit(111)`
660
661
662### <a name="HP09"></a> The error bars options
663
664
665| Option | Description |
666|----------|-------------------------------------------------------------------|
667| "E" | Default. Shows only the error bars, not a marker.|
668| "E1" | Small lines are drawn at the end of the error bars.|
669| "E2" | Error rectangles are drawn.|
670| "E3" | A filled area is drawn through the end points of the vertical error bars.|
671| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
672| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
673| "E5" | Like E3 but ignore the bins with 0 contents.|
674| "E6" | Like E4 but ignore the bins with 0 contents.|
675| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
676
677Begin_Macro(source)
678{
679 auto c1 = new TCanvas("c1","c1",600,400);
680 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
681 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
682 gStyle->SetEndErrorSize(3);
683 gStyle->SetErrorX(1.);
684 he->SetMarkerStyle(20);
685 he->Draw("E1");
686}
687End_Macro
688
689The options "E3" and "E4" draw an error band through the end points of the
690vertical error bars. With "E4" the error band is smoothed. Because of the
691smoothing algorithm used some artefacts may appear at the end of the band
692like in the following example. In such cases "E3" should be used instead
693of "E4".
694
695Begin_Macro(source)
696{
697 auto ce4 = new TCanvas("ce4","ce4",600,400);
698 ce4->Divide(2,1);
699 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
700 Int_t i;
701 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
702 he4->SetFillColor(kRed);
703 he4->GetXaxis()->SetRange(40,48);
704 ce4->cd(1);
705 he4->Draw("E4");
706 ce4->cd(2);
707 auto he3 = (TH1F*)he4->DrawClone("E3");
708 he3->SetTitle("Distribution drawn option E3");
709}
710End_Macro
711
7122D histograms can be drawn with error bars as shown is the following example:
713
714Begin_Macro(source)
715{
716 auto c2e = new TCanvas("c2e","c2e",600,400);
717 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
718 float px, py;
719 for (Int_t i = 0; i < 25000; i++) {
720 gRandom->Rannor(px,py);
721 h2e->Fill(px,5*py);
722 }
723 h2e->Draw("E");
724}
725End_Macro
726
727
728### <a name="HP100"></a> The bar chart option
729
730
731The option "B" allows to draw simple vertical bar charts.
732The bar width is controlled with `TH1::SetBarWidth()`,
733and the bar offset within the bin, with `TH1::SetBarOffset()`.
734These two settings are useful to draw several histograms on the
735same plot as shown in the following example:
736
737Begin_Macro(source)
738{
739 int i;
740 const Int_t nx = 8;
741 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
742 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
743 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
744
745 auto cb = new TCanvas("cb","cb",600,400);
746 cb->SetGrid();
747
748 gStyle->SetHistMinimumZero();
749
750 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
751 h1b->SetFillColor(4);
752 h1b->SetBarWidth(0.4);
753 h1b->SetBarOffset(0.1);
754 h1b->SetStats(0);
755 h1b->SetMinimum(-5);
756 h1b->SetMaximum(5);
757
758 for (i=1; i<=nx; i++) {
759 h1b->SetBinContent(i, d_35_0[i-1]);
760 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
761 }
762
763 h1b->Draw("b");
764
765 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
766 h2b->SetFillColor(38);
767 h2b->SetBarWidth(0.4);
768 h2b->SetBarOffset(0.5);
769 h2b->SetStats(0);
770 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
771
772 h2b->Draw("b same");
773}
774End_Macro
775
776
777### <a name="HP10"></a> The "BAR" and "HBAR" options
778
779
780When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
781bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
782An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
783`hbar2`, `hbar3`, `hbar4` (hbars.C).
784
785- The bar is filled with the histogram fill color.
786- The left side of the bar is drawn with a light fill color.
787- The right side of the bar is drawn with a dark fill color.
788- The percentage of the bar drawn with either the light or dark color is:
789 - 0% for option "(h)bar" or "(h)bar0"
790 - 10% for option "(h)bar1"
791 - 20% for option "(h)bar2"
792 - 30% for option "(h)bar3"
793 - 40% for option "(h)bar4"
794
795When an histogram has errors the option ["HIST"](#OPTHIST) together with the `(h)bar` option.
796
797Begin_Macro(source)
798../../../tutorials/hist/hbars.C
799End_Macro
800
801To control the bar width (default is the bin width) `TH1::SetBarWidth()`
802should be used.
803
804To control the bar offset (default is 0) `TH1::SetBarOffset()` should
805be used.
806
807These two parameters are useful when several histograms are plotted using
808the option `SAME`. They allow to plot the histograms next to each other.
809
810
811### <a name="HP11"></a> The SCATter plot option (default for 2D histograms)
812
813
814For each cell (i,j) a number of points proportional to the cell content is
815drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
816`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
817If option is of the form `scat=ff`, (eg `scat=1.8`,
818`scat=1e-3`), then `ff` is used as a scale factor to compute the
819number of dots. `scat=1` is the default.
820
821By default the scatter plot is painted with a "dot marker" which not scalable
822(see the `TAttMarker` documentation). To change the marker size, a scalable marker
823type should be used. For instance a circle (marker style 20).
824
825Begin_Macro(source)
826{
827 auto c1 = new TCanvas("c1","c1",600,400);
828 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
829 float px, py;
830 for (Int_t i = 0; i < 25000; i++) {
831 gRandom->Rannor(px,py);
832 hscat->Fill(px,5*py);
833 hscat->Fill(3+0.5*px,2*py-10.);
834 }
835 hscat->Draw("scat=0.5");
836}
837End_Macro
838
839
840### <a name="HP12"></a> The ARRow option
841
842
843Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
844The orientation of the arrow follows the cell gradient.
845
846Begin_Macro(source)
847{
848 auto c1 = new TCanvas("c1","c1",600,400);
849 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
850 harr->SetLineColor(kRed);
851 float px, py;
852 for (Int_t i = 0; i < 25000; i++) {
853 gRandom->Rannor(px,py);
854 harr->Fill(px,5*py);
855 harr->Fill(3+0.5*px,2*py-10.,0.1);
856 }
857 harr->Draw("ARR");
858}
859End_Macro
860
861\since **ROOT version 6.17/01**
862
863The option `ARR` can be combined with the option `COL` or `COLZ`.
864
865Begin_Macro(source)
866{
867 auto c1 = new TCanvas("c1","c1",600,400);
868 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
869 harr->SetStats(0);
870 float px, py;
871 for (Int_t i = 0; i < 25000; i++) {
872 gRandom->Rannor(px,py);
873 harr->Fill(px,5*py);
874 harr->Fill(3+0.5*px,2*py-10.,0.1);
875 }
876 harr->Draw("ARR COLZ");
877}
878End_Macro
879
880
881### <a name="HP13"></a> The BOX option
882
883
884For each cell (i,j) a box is drawn. The size (surface) of the box is
885proportional to the absolute value of the cell content.
886The cells with a negative content are drawn with a `X` on top of the box.
887
888Begin_Macro(source)
889{
890 auto c1 = new TCanvas("c1","c1",600,400);
891 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
892 hbox->SetFillColor(42);
893 hbox->Fill(0.5, 0.5, 1.);
894 hbox->Fill(0.5, 1.5, 4.);
895 hbox->Fill(0.5, 2.5, 3.);
896 hbox->Fill(1.5, 0.5, 2.);
897 hbox->Fill(1.5, 1.5, 12.);
898 hbox->Fill(1.5, 2.5, -6.);
899 hbox->Fill(2.5, 0.5, -4.);
900 hbox->Fill(2.5, 1.5, 6.);
901 hbox->Fill(2.5, 2.5, 0.5);
902 hbox->Draw("BOX");
903}
904End_Macro
905
906With option `BOX1` a button is drawn for each cell with surface
907proportional to content's absolute value. A sunken button is drawn for
908negative values a raised one for positive.
909
910Begin_Macro(source)
911{
912 auto c1 = new TCanvas("c1","c1",600,400);
913 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
914 hbox1->SetFillColor(42);
915 hbox1->Fill(0.5, 0.5, 1.);
916 hbox1->Fill(0.5, 1.5, 4.);
917 hbox1->Fill(0.5, 2.5, 3.);
918 hbox1->Fill(1.5, 0.5, 2.);
919 hbox1->Fill(1.5, 1.5, 12.);
920 hbox1->Fill(1.5, 2.5, -6.);
921 hbox1->Fill(2.5, 0.5, -4.);
922 hbox1->Fill(2.5, 1.5, 6.);
923 hbox1->Fill(2.5, 2.5, 0.5);
924 hbox1->Draw("BOX1");
925}
926End_Macro
927
928When the option `SAME` (or "SAMES") is used with the option `BOX`,
929the boxes' sizes are computing taking the previous plots into account. The range
930along the Z axis is imposed by the first plot (the one without option
931`SAME`); therefore the order in which the plots are done is relevant.
932
933Begin_Macro(source)
934{
935 auto c1 = new TCanvas("c1","c1",600,400);
936 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
937 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
938 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
939 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
940 for (Int_t i=0;i<1000;i++) {
941 double x,y;
942 gRandom->Rannor(x,y);
943 if (x>0 && y>0) hb1->Fill(x,y,4);
944 if (x<0 && y<0) hb2->Fill(x,y,3);
945 if (x>0 && y<0) hb3->Fill(x,y,2);
946 if (x<0 && y>0) hb4->Fill(x,y,1);
947 }
948 hb1->SetFillColor(1);
949 hb2->SetFillColor(2);
950 hb3->SetFillColor(3);
951 hb4->SetFillColor(4);
952 hb1->Draw("box");
953 hb2->Draw("box same");
954 hb3->Draw("box same");
955 hb4->Draw("box same");
956}
957End_Macro
958
959\since **ROOT version 6.17/01:**
960
961Sometimes the change of the range of the Z axis is unwanted, in which case, one
962can use `SAME0` (or `SAMES0`) option to opt out of this change.
963
964Begin_Macro(source)
965{
966 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
967 auto hf = (TH2F*)h2->Clone("hf");
968 h2->SetBit(TH1::kNoStats);
969 hf->SetBit(TH1::kNoStats);
970 h2->Fill(5,22);
971 h2->Fill(5,23);
972 h2->Fill(6,22);
973 h2->Fill(6,23);
974 hf->Fill(6,23);
975 hf->Fill(6,23);
976 hf->Fill(6,23);
977 hf->Fill(6,23);
978 hf->Fill(5,23);
979
980 auto hf_copy1 = hf->Clone("hf_copy1");
981 auto lt = new TLatex();
982
983 auto cx = new TCanvas(); cx->Divide(2,1);
984
985 cx->cd(1);
986 h2->Draw("box");
987 hf->Draw("text colz same");
988 lt->DrawLatexNDC(0.3,0.5,"SAME");
989
990 cx->cd(2);
991 h2->Draw("box");
992 hf_copy1->Draw("text colz same0");
993 lt->DrawLatexNDC(0.3,0.5,"SAME0");
994}
995End_Macro
996
997
998### <a name="HP14"></a> The COLor option
999
1000
1001For each cell (i,j) a box is drawn with a color proportional to the cell
1002content.
1003
1004The color table used is defined in the current style.
1005
1006If the histogram's minimum and maximum are the same (flat histogram), the
1007mapping on colors is not possible, therefore nothing is painted. To paint a
1008flat histogram it is enough to set the histogram minimum
1009(`TH1::SetMinimum()`) different from the bins' content.
1010
1011The default number of color levels used to paint the cells is 20.
1012It can be changed with `TH1::SetContour()` or
1013`TStyle::SetNumberContours()`. The higher this number is, the smoother
1014is the color change between cells.
1015
1016The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1017
1018All the non-empty bins are painted. Empty bins are not painted unless
1019some bins have a negative content because in that case the null bins
1020might be not empty.
1021
1022`TProfile2D` histograms are handled differently because, for this type of 2D
1023histograms, it is possible to know if an empty bin has been filled or not. So even
1024if all the bins' contents are positive some empty bins might be painted. And vice versa,
1025if some bins have a negative content some empty bins might be not painted.
1026
1027Combined with the option `COL`, the option `Z` allows to
1028display the color palette defined by `gStyle->SetPalette()`.
1029
1030In the following example, the histogram has only positive bins; the empty
1031bins (containing 0) are not drawn.
1032
1033Begin_Macro(source)
1034{
1035 auto c1 = new TCanvas("c1","c1",600,400);
1036 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1037 float px, py;
1038 for (Int_t i = 0; i < 25000; i++) {
1039 gRandom->Rannor(px,py);
1040 hcol1->Fill(px,5*py);
1041 }
1042 hcol1->Draw("COLZ");
1043}
1044End_Macro
1045
1046In the first plot of following example, the histogram has some negative bins;
1047the empty bins (containing 0) are drawn. In some cases one wants to not draw
1048empty bins (containing 0) of histograms having a negative minimum. The option
1049`1`, used to produce the second plot in the following picture, allows to do that.
1050
1051Begin_Macro(source)
1052{
1053 auto c1 = new TCanvas("c1","c1",600,600);
1054 c1->Divide(1,2);
1055 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1056 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",40,-4,4,40,-20,20);
1057 float px, py;
1058 for (Int_t i = 0; i < 25000; i++) {
1059 gRandom->Rannor(px,py);
1060 hcol23->Fill(px,5*py);
1061 hcol24->Fill(px,5*py);
1062 }
1063 hcol23->Fill(0.,0.,-200.);
1064 hcol24->Fill(0.,0.,-200.);
1065 c1->cd(1); hcol23->Draw("COLZ");
1066 c1->cd(2); hcol24->Draw("COLZ1");
1067}
1068End_Macro
1069
1070When the maximum of the histogram is set to a smaller value than the real maximum,
1071 the bins having a content between the new maximum and the real maximum are
1072painted with the color corresponding to the new maximum.
1073
1074When the minimum of the histogram is set to a greater value than the real minimum,
1075 the bins having a value between the real minimum and the new minimum are not drawn
1076 unless the option `0` is set.
1077
1078The following example illustrates the option `0` combined with the option `COL`.
1079
1080Begin_Macro(source)
1081{
1082 auto c1 = new TCanvas("c1","c1",600,600);
1083 c1->Divide(1,2);
1084 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1085 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1086 float px, py;
1087 for (Int_t i = 0; i < 25000; i++) {
1088 gRandom->Rannor(px,py);
1089 hcol21->Fill(px,5*py);
1090 hcol22->Fill(px,5*py);
1091 }
1092 hcol21->SetBit(TH1::kNoStats);
1093 hcol22->SetBit(TH1::kNoStats);
1094 c1->cd(1); hcol21->Draw("COLZ");
1095 c1->cd(2); hcol22->Draw("COLZ0");
1096 hcol22->SetMaximum(100);
1097 hcol22->SetMinimum(40);
1098}
1099End_Macro
1100
1101\since **ROOT version 6.09/01:**
1102
1103When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1104are computing taking the previous plots into account. The range along the Z axis
1105is imposed by the first plot (the one without option SAME); therefore the order
1106in which the plots are done is relevant. Same as [in the `BOX` option](#HP13), one can use
1107`SAME0` (or `SAMES0`) to opt out of this imposition.
1108
1109Begin_Macro(source)
1110{
1111 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1112 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1113 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1114 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1115 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1116 h1->SetBit(TH1::kNoStats);
1117 for (Int_t i=0;i<5000;i++) {
1118 double x,y;
1119 gRandom->Rannor(x,y);
1120 if(x>0 && y>0) h1->Fill(x,y,4);
1121 if(x<0 && y<0) h2->Fill(x,y,3);
1122 if(x>0 && y<0) h3->Fill(x,y,2);
1123 if(x<0 && y>0) h4->Fill(x,y,1);
1124 }
1125 h1->Draw("colz");
1126 h2->Draw("col same");
1127 h3->Draw("col same");
1128 h4->Draw("col same");
1129}
1130End_Macro
1131
1132The option `COL` can be combined with the option `POL`:
1133
1134Begin_Macro(source)
1135{
1136 auto c1 = new TCanvas("c1","c1",600,400);
1137 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1138 float px, py;
1139 for (Int_t i = 0; i < 25000; i++) {
1140 gRandom->Rannor(px,py);
1141 hcol1->Fill(px,py);
1142 }
1143 hcol1->Draw("COLZPOL");
1144}
1145End_Macro
1146
1147\since **ROOT version 6.07/03:**
1148
1149A second rendering technique is also available with the COL2 and COLZ2 options.
1150
1151These options provide potential performance improvements compared to the standard
1152COL option. The performance comparison of the COL2 to the COL option depends on
1153the histogram and the size of the rendering region in the current pad. In general,
1154a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1155faster with the COL option.
1156
1157However, for larger histograms (approx. more than 100 bins per axis)
1158that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1159For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1160faster with the COL2 option.
1161
1162The COL2 option will also scale its performance based on the size of the
1163pixmap the histogram image is being rendered into. It also is much better optimized for
1164sessions where the user is forwarding X11 windows through an `ssh` connection.
1165
1166For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1167and COLZ options. There is one major difference and that concerns the treatment of
1168bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1169
1170COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1171graphics file format like PostScript or PDF (an empty image will be generated). It can
1172be saved only in bitmap files like PNG format for instance.
1173
1174
1175### <a name="HP140"></a> The CANDLE and VIOLIN options
1176
1177The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1178implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1179the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1180vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1181(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1182
1183Instead of using the predefined representations, the candle and violin parameters can be
1184changed individually. In that case the option have the following form:
1185
1186 CANDLEX(<option-string>)
1187 CANDLEY(<option-string>)
1188 VIOLINX(<option-string>)
1189 VIOLINY(<option-string>).
1190
1191All zeros at the beginning of `option-string` can be omitted.
1192
1193`option-string` consists eight values, defined as follow:
1194
1195 "CANDLEX(zhpawMmb)"
1196
1197Where:
1198
1199 - `b = 0`; no box drawn
1200 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1201 makes sense in the very most cases to always draw the box
1202 - `b = 2`; draw a filled box with border
1203
1204 - `m = 0`; no median drawn
1205 - `m = 1`; median is drawn as a line
1206 - `m = 2`; median is drawn with errors (notches)
1207 - `m = 3`; median is drawn as a circle
1208
1209 - `M = 0`; no mean drawn
1210 - `M = 1`; mean is drawn as a dashed line
1211 - `M = 3`; mean is drawn as a circle
1212
1213 - `w = 0`; no whisker drawn
1214 - `w = 1`; whisker is drawn to end of distribution.
1215 - `w = 2`; whisker is drawn to max 1.5*iqr
1216
1217 - `a = 0`; no anchor drawn
1218 - `a = 1`; the anchors are drawn
1219
1220 - `p = 0`; no points drawn
1221 - `p = 1`; only outliers are drawn
1222 - `p = 2`; all datapoints are drawn
1223 - `p = 3`: all datapoints are drawn scattered
1224
1225 - `h = 0`; no histogram is drawn
1226 - `h = 1`; histogram at the left or bottom side is drawn
1227 - `h = 2`; histogram at the right or top side is drawn
1228 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1229
1230 - `z = 0`; no zero indicator line is drawn
1231 - `z = 1`; zero indicator line is drawn.
1232
1233As one can see all individual options for both candle and violin plots can be accessed by this
1234mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1235meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1236vice versa, if you wish.
1237
1238Using a logarithmic x- or y-axis is possible for candle and violin charts.
1239
1240\since **ROOT version 6.11/01**
1241
1242a logarithmic z-axis is possible, too but will only affect violin charts of course.
1243
1244#### <a name="HP140a"></a> The CANDLE option
1245
1246<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1247a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1248way to describe graphically a data distribution (D) with only five numbers:
1249
1250 1. The minimum value of the distribution D (bottom or left whisker).
1251 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1252 3. The median (M): 50% of the data points in D are less than M.
1253 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1254 5. The maximum value of the distribution D (top or right whisker).
1255
1256In this implementation a TH2 is considered as a collection of TH1 along
1257X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1258Each TH1 is represented as one candle.
1259
1260Begin_Macro(source)
1261../../../tutorials/hist/candleplotwhiskers.C
1262End_Macro
1263
1264The candle reduces the information coming from a whole distribution into few values.
1265Independently from the number of entries or the significance of the underlying distribution
1266a candle will always look like a candle. So candle plots should be used carefully in
1267particular with unknown distributions. The definition of a candle is based on
1268__unbinned data__. Here, candles are created from binned data. Because of this, the
1269deviation is connected to the bin width used. The calculation of the quantiles
1270normally done on unbinned data also. Because data are binned, this will
1271only work the best possible way within the resolution of one bin
1272
1273Because of all these facts one should take care that:
1274
1275 - there are enough points per candle
1276 - the bin width is small enough (more bins will increase the maximum
1277 available resolution of the quantiles although there will be some
1278 bins with no entries)
1279 - never make a candle-plot if the underlying distribution is double-distributed
1280 - only create candles of distributions that are more-or-less gaussian (the
1281 MPV should be not too far away from the mean).
1282
1283#### What a candle is made of
1284
1285\since **ROOT version 6.07/05**
1286
1287##### The box
1288The box displays the position of the inter-quantile-range of the underlying
1289distribution. The box contains 25% of the distribution below the median
1290and 25% of the distribution above the median. If the underlying distribution is large
1291enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1292(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1293the position of the box can be modified by SetBarWidth() and SetBarOffset().
1294The +-25% quantiles are calculated by the GetQuantiles() methods.
1295
1296\since **ROOT version 6.11/01**
1297
1298Using the static function TCandle::SetBoxRange(double) the box definition will be
1299overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1300to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1301The static function will affect all candle-charts in the running program.
1302Default is 0.5.
1303
1304Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1305whole candle) can be influenced. Deactivated, the width is constant (to be set by
1306SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1307amount of data in the corresponding candle, the maximum width can be influenced by
1308SetBarWidth(). The static function will affect all candle-charts in the running program.
1309Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1310supported, yet
1311
1312##### The Median
1313For a sorted list of numbers, the median is the value in the middle of the list.
1314E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1315because it is in the middle of the list. If the number of entries is even the
1316average of the two values in the middle will be used. As histograms are binned
1317data, the situation is a bit more complex. The following example shows this:
1318
1319~~~ {.cpp}
1320void quantiles() {
1321 auto h = new TH1I("h","h",10,0,10);
1322 //h->Fill(3);
1323 //h->Fill(3);
1324 h->Fill(4);
1325 h->Draw();
1326 double p = 0.;
1327 double q = 0.;
1328 h->GetQuantiles(1,&q,&p);
1329
1330 cout << "Median is: " << q << std::endl;
1331}
1332~~~
1333
1334Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1335the example will return a calculated median of 4.5, because that's the bin center
1336of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1337commented out, it will return 3.75, because the algorithm tries to evenly distribute
1338the individual values of a bin with bin content > 0. It means the sorted list
1339would be "3.25, 3.75, 4.5".
1340
1341The consequence is a median of 3.75. This shows how important it is to use a
1342small enough bin-width when using candle-plots on binned data.
1343If the distribution is large enough and gaussian shaped the median will be exactly
1344equal to the mean.
1345The median can be shown as a line or as a circle or not shown at all.
1346
1347In order to show the significance of the median notched candle plots apply a "notch" or
1348narrowing of the box around the median. The significance is defined by
1349\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1350(where iqr is the size of the box and N is the number of entries of the whole
1351distribution). Candle plots like these are usually called "notched candle plots".
1352
1353In case the significance of the median is greater that the size of the box, the
1354box will have an unnatural shape. Usually it means the chart has not enough data,
1355or that representing this uncertainty is not useful
1356
1357##### The Mean
1358The mean can be drawn as a dashed line or as a circle or not drawn at all.
1359The mean is the arithmetic average of the values in the distribution.
1360It is calculated using GetMean(). Because histograms are
1361binned data, the mean value can differ from a calculation on the raw-data.
1362If the distribution is large enough and gaussian shaped the mean will be
1363exactly the median.
1364
1365##### The Whiskers
1366The whiskers represent the part of the distribution not covered by the box.
1367The upper 25% and the lower 25% of the distribution are located within the whiskers.
1368Two representations are available.
1369
1370 - A simple one (using w=1) defining the lower whisker from the lowest data value
1371 to the bottom of the box, and the upper whisker from the top of the box to the
1372 highest data value. In this representation the whisker-lines are dashed.
1373 - A more complex one having a further restriction. The whiskers are still connected
1374 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1375 be that the outermost part of the underlying distribution will not be covered
1376 by the whiskers. Usually these missing parts will be represented by the outliers
1377 (see points). Of course the upper and the lower whisker may differ in length.
1378 In this representation the whiskers are drawn as solid lines.
1379
1380\since **ROOT version 6.11/01**
1381
1382Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1383will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1384the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1385that candle. The static function will affect all candle-charts in the running program.
1386Default is 1.
1387
1388If the distribution is large enough and gaussian shaped, the maximum length of
1389the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
13901.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1391(see picture above). In that case 99.3% of the total distribution will be covered
1392by the box and the whiskers, whereas 0.7% are represented by the outliers.
1393
1394##### The Anchors
1395The anchors have no special meaning in terms of statistical calculation. They mark
1396the end of the whiskers and they have the width of the box. Both representation
1397with and without anchors are common.
1398
1399##### The Points
1400Depending on the configuration the points can have different meanings:
1401 - If p=1 the points represent the outliers. If they are shown, it means
1402 some parts of the underlying distribution are not covered by the whiskers.
1403 This can only occur when the whiskers are set to option w=2. Here the whiskers
1404 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1405 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1406 - If p=2 all points in the distribution will be painted as crosses. This is
1407 useful for small datasets only (up to 10 or 20 points per candle).
1408 The outliers are shown along the candle. Because the underlying distribution
1409 is binned, is frequently occurs that a bin contains more than one value.
1410 Because of this the points will be randomly scattered within their bin along
1411 the candle axis. If the bin content for a bin is exactly 1 (usually
1412 this happens for the outliers) if will be drawn in the middle of the bin along
1413 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1414 on very large datasets scaling will be performed automatically. In that case one
1415 would loose all outliers because they have usually a bin content of 1 (and a
1416 bin content between 0 and 1 after the scaling). Because of this all bin contents
1417 between 0 and 1 - after the scaling - will be forced to be 1.
1418 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1419 one can show all values as a scatter plot instead by choosing p=3. The points will be
1420 drawn as dots and will be scattered within the width of the candle. The color
1421 of the points will be the color of the candle-chart.
1422
1423##### Other Options
1424Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1425with a histogram.
1426
1427#### How to use the candle-plots drawing option
1428
1429There are six predefined candle-plot representations:
1430
1431 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1432 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1433 It is a good compromise
1434 - "CANDLEX3": Like candle2 but with a mean as a circle.
1435 It is easier to distinguish mean and median
1436 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1437 (notched candle plots).
1438 For bigger datasets per candle
1439 - "CANDLEX5": Like candle2 but showing all data points.
1440 For very small datasets
1441 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1442 For huge datasets
1443
1444
1445The following picture shows how the six predefined representations look.
1446
1447Begin_Macro
1448{
1449 auto c1 = new TCanvas("c1","c1",700,800);
1450 c1->Divide(2,3);
1451 gStyle->SetOptStat(kFALSE);
1452
1453 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1454 float px, py;
1455 for (Int_t i = 0; i < 15000; i++) {
1456 gRandom->Rannor(px,py);
1457 hcandle->Fill(px,5*py);
1458 }
1459 hcandle->SetMarkerSize(0.5);
1460
1461 TH2F *h2;
1462 for (Int_t i=1; i<7; i++) {
1463 c1->cd(i);
1464 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1465 h2->SetTitle(Form("CANDLE%d",i));
1466 }
1467}
1468End_Macro
1469
1470
1471#### Example 1
1472Box and improved whisker, no mean, no median, no anchor no outliers
1473
1474 h1->Draw("CANDLEX(2001)");
1475
1476#### Example 2
1477A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1478
1479 h1->Draw("CANDLEX(112111)");
1480
1481#### Example 3
1482The following example shows how several candle plots can be super-imposed using
1483the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1484Also the color, the line width, the size of the points and so on can be changed by the
1485standard attribute setting methods such as SetLineColor() SetLineWidth().
1486
1487Begin_Macro(source)
1488../../../tutorials/hist/candleplot.C
1489End_Macro
1490
1491#### <a name="HP140b"></a> The VIOLIN option
1492
1493<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1494that also encodes the pdf information at each point.
1495
1496
1497Quartiles and mean are also represented at each point, with a marker
1498and two lines.
1499
1500In this implementation a TH2 is considered as a collection of TH1 along
1501X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1502
1503#### What a violin is made of
1504
1505\since **ROOT version 6.09/02**
1506
1507##### The histogram
1508The histogram is typically drawn to both directions with respect to the middle-line of the
1509corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1510one side (h=1, or h=2).
1511The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1512histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1513be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1514A solid fill style is recommended.
1515
1516\since **ROOT version 6.11/01**
1517
1518Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1519violin can be influenced. Activated, the height of the bins of the individual violins will be
1520scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1521Deactivated, the height of the bin with the maximum content of each individual violin is
1522set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1523in the running program. Default is true. Scaling between multiple violin-charts
1524(using "same" or THStack) is not supported, yet.
1525
1526##### The zero indicator line
1527Typical for violin charts is a line in the background over the whole histogram indicating
1528the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1529will always be the same as the fill-color of the histogram.
1530
1531##### The Mean
1532The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1533
1534##### Whiskers
1535The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1536difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1537the whiskers will be forced to be solid (usually hashed)
1538
1539##### Points
1540The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1541better whisker definition (w=2) and outliers (p=1).
1542
1543##### Other options
1544It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1545including a box-plot.
1546
1547#### How to use the violin-plots drawing option
1548
1549There are two predefined violin-plot representations:
1550 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1551 zero indicator line)
1552 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1553
1554A solid fill style is recommended for this plot (as opposed to a hollow or
1555hashed style).
1556
1557Begin_Macro(source)
1558{
1559 auto c1 = new TCanvas("c1","c1",600,400);
1560 Int_t nx(6), ny(40);
1561 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1562 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1563 TF1 f1("f1", "gaus", +0,0 +4.0);
1564 double x,y;
1565 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1566 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1567 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1568 for(Int_t i=0; i<10000; ++i){
1569 x = xc;
1570 y = f1.GetRandom();
1571 hviolin->Fill(x, y);
1572 }
1573 }
1574 hviolin->SetFillColor(kGray);
1575 hviolin->SetMarkerStyle(20);
1576 hviolin->SetMarkerSize(0.5);
1577 hviolin->Draw("VIOLIN");
1578 c1->Update();
1579}
1580End_Macro
1581
1582The next example illustrates a time development of a certain value:
1583
1584Begin_Macro(source)
1585../../../tutorials/hist/candledecay.C
1586End_Macro
1587
1588
1589### <a name="HP15"></a> The TEXT and TEXTnn Option
1590
1591
1592For each bin the content is printed. The text attributes are:
1593
1594- text font = current TStyle font (`gStyle->SetTextFont()`).
1595- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1596 with the option `TEXT` the marker size can be changed with
1597 `h->SetMarkerSize(markersize)`).
1598- text color = marker color.
1599
1600By default the format `g` is used. This format can be redefined
1601by calling `gStyle->SetPaintTextFormat()`.
1602
1603It is also possible to use `TEXTnn` in order to draw the text with
1604the angle `nn` (`0 < nn < 90`).
1605
1606For 2D histograms the text is plotted in the center of each non empty cells.
1607It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1608or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1609position equal to the bin content.
1610
1611For 2D histograms when the option "E" (errors) is combined with the option
1612text ("TEXTE"), the error for each bin is also printed.
1613
1614Begin_Macro(source)
1615{
1616 auto c01 = new TCanvas("c01","c01",700,400);
1617 c01->Divide(2,1);
1618 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1619 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1620 float px, py;
1621 for (Int_t i = 0; i < 25000; i++) {
1622 gRandom->Rannor(px,py);
1623 htext1->Fill(px,0.1);
1624 htext2->Fill(px,5*py,0.1);
1625 }
1626 gStyle->SetPaintTextFormat("4.1f m");
1627 htext2->SetMarkerSize(1.8);
1628 c01->cd(1);
1629 htext2->Draw("TEXT45");
1630 c01->cd(2);
1631 htext1->Draw();
1632 htext1->Draw("HIST TEXT0 SAME");
1633}
1634End_Macro
1635
1636\since **ROOT version 6.07/07:**
1637
1638In case several histograms are drawn on top ot each other (using option `SAME`),
1639the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1640text position in each cell, in percentage of the bin width.
1641
1642Begin_Macro(source)
1643{
1644 auto c03 = new TCanvas("c03","c03",700,400);
1645 gStyle->SetOptStat(0);
1646 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1647 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1648 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1649 float px, py;
1650 for (Int_t i = 0; i < 25000; i++) {
1651 gRandom->Rannor(px,py);
1652 htext3->Fill(4*px,20*py,0.1);
1653 htext4->Fill(4*px,20*py,0.5);
1654 htext5->Fill(4*px,20*py,1.0);
1655 }
1656 htext4->SetMarkerSize(1.8);
1657 htext5->SetMarkerSize(1.8);
1658 htext5->SetMarkerColor(kRed);
1659 htext3->Draw("COL");
1660 htext4->SetBarOffset(0.2);
1661 htext4->Draw("TEXT SAME");
1662 htext5->SetBarOffset(-0.2);
1663 htext5->Draw("TEXT SAME");
1664}
1665End_Macro
1666
1667In the case of profile histograms it is possible to print the number
1668of entries instead of the bin content. It is enough to combine the
1669option "E" (for entries) with the option "TEXT".
1670
1671Begin_Macro(source)
1672{
1673 auto c02 = new TCanvas("c02","c02",700,400);
1674 c02->Divide(2,1);
1675 gStyle->SetPaintTextFormat("g");
1676
1677 auto profile = new TProfile("profile","profile",10,0,10);
1678 profile->SetMarkerSize(2.2);
1679 profile->Fill(0.5,1);
1680 profile->Fill(1.5,2);
1681 profile->Fill(2.5,3);
1682 profile->Fill(3.5,4);
1683 profile->Fill(4.5,5);
1684 profile->Fill(5.5,5);
1685 profile->Fill(6.5,4);
1686 profile->Fill(7.5,3);
1687 profile->Fill(8.5,2);
1688 profile->Fill(9.5,1);
1689 c02->cd(1); profile->Draw("HIST TEXT0");
1690 c02->cd(2); profile->Draw("HIST TEXT0E");
1691}
1692End_Macro
1693
1694### <a name="HP16"></a> The CONTour options
1695
1696
1697The following contour options are supported:
1698
1699| Option | Description |
1700|----------|-----------------------------------------------------------------------------|
1701| "CONT" | Draw a contour plot (same as CONT0). |
1702| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1703| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1704| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1705| "CONT3" | Draw a contour plot using the same line style for all contours. |
1706| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1707| "CONT5" | Draw a contour plot using Delaunay triangles. |
1708
1709
1710
1711The following example shows a 2D histogram plotted with the option
1712`CONTZ`. The option `CONT` draws a contour plot using surface
1713colors to distinguish contours. Combined with the option `CONT` (or
1714`CONT0`), the option `Z` allows to display the color palette
1715defined by `gStyle->SetPalette()`.
1716
1717Begin_Macro(source)
1718{
1719 auto c1 = new TCanvas("c1","c1",600,400);
1720 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1721 float px, py;
1722 for (Int_t i = 0; i < 25000; i++) {
1723 gRandom->Rannor(px,py);
1724 hcontz->Fill(px-1,5*py);
1725 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1726 }
1727 hcontz->Draw("CONTZ");
1728}
1729End_Macro
1730
1731The following example shows a 2D histogram plotted with the option
1732`CONT1Z`. The option `CONT1` draws a contour plot using the
1733line colors to distinguish contours. Combined with the option `CONT1`,
1734the option `Z` allows to display the color palette defined by
1735`gStyle->SetPalette()`.
1736
1737Begin_Macro(source)
1738{
1739 auto c1 = new TCanvas("c1","c1",600,400);
1740 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1741 float px, py;
1742 for (Int_t i = 0; i < 25000; i++) {
1743 gRandom->Rannor(px,py);
1744 hcont1->Fill(px-1,5*py);
1745 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1746 }
1747 hcont1->Draw("CONT1Z");
1748}
1749End_Macro
1750
1751The following example shows a 2D histogram plotted with the option
1752`CONT2`. The option `CONT2` draws a contour plot using the
1753line styles (1 to 5) to distinguish contours.
1754
1755Begin_Macro(source)
1756{
1757 auto c1 = new TCanvas("c1","c1",600,400);
1758 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1759 float px, py;
1760 for (Int_t i = 0; i < 25000; i++) {
1761 gRandom->Rannor(px,py);
1762 hcont2->Fill(px-1,5*py);
1763 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1764 }
1765 hcont2->Draw("CONT2");
1766}
1767End_Macro
1768
1769The following example shows a 2D histogram plotted with the option
1770`CONT3`. The option `CONT3` draws contour plot using the same line style for
1771all contours.
1772
1773Begin_Macro(source)
1774{
1775 auto c1 = new TCanvas("c1","c1",600,400);
1776 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1777 float px, py;
1778 for (Int_t i = 0; i < 25000; i++) {
1779 gRandom->Rannor(px,py);
1780 hcont3->Fill(px-1,5*py);
1781 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1782 }
1783 hcont3->SetLineStyle(kDotted);
1784 hcont3->Draw("CONT3");
1785}
1786End_Macro
1787
1788The following example shows a 2D histogram plotted with the option
1789`CONT4`. The option `CONT4` draws a contour plot using surface
1790colors to distinguish contours (`SURF` option at theta = 0). Combined
1791with the option `CONT` (or `CONT0`), the option `Z`
1792allows to display the color palette defined by `gStyle->SetPalette()`.
1793
1794Begin_Macro(source)
1795{
1796 auto c1 = new TCanvas("c1","c1",600,400);
1797 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1798 float px, py;
1799 for (Int_t i = 0; i < 25000; i++) {
1800 gRandom->Rannor(px,py);
1801 hcont4->Fill(px-1,5*py);
1802 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1803 }
1804 hcont4->Draw("CONT4Z");
1805}
1806End_Macro
1807
1808The default number of contour levels is 20 equidistant levels and can be changed
1809with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1810
1811#### <a name="HP16a"></a> The LIST option
1812
1813When option `LIST` is specified together with option
1814`CONT`, the points used to draw the contours are saved in
1815`TGraph` objects:
1816
1817 h->Draw("CONT LIST");
1818 gPad->Update();
1819
1820The contour are saved in `TGraph` objects once the pad is painted.
1821Therefore to use this functionality in a macro, `gPad->Update()`
1822should be performed after the histogram drawing. Once the list is
1823built, the contours are accessible in the following way:
1824
1825 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1826 Int_t ncontours = contours->GetSize();
1827 TList *list = (TList*)contours->At(i);
1828
1829Where `i` is a contour number, and list contains a list of
1830`TGraph` objects.
1831For one given contour, more than one disjoint polyline may be generated.
1832The number of TGraphs per contour is given by:
1833
1834 list->GetSize();
1835
1836To access the first graph in the list one should do:
1837
1838 TGraph *gr1 = (TGraph*)list->First();
1839
1840
1841The following example (ContourList.C) shows how to use this functionality.
1842
1843Begin_Macro(source)
1844../../../tutorials/hist/ContourList.C
1845End_Macro
1846
1847#### <a name="HP16b"></a> The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1848
1849The following options select the `CONT4` option and are useful for
1850sky maps or exposure maps (earth.C).
1851
1852| Option | Description |
1853|--------------|---------------------------------------------------------------|
1854| "AITOFF" | Draw a contour via an AITOFF projection.|
1855| "MERCATOR" | Draw a contour via an Mercator projection.|
1856| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1857| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1858
1859Begin_Macro(source)
1860../../../tutorials/graphics/earth.C
1861End_Macro
1862
1863
1864### <a name="HP17"></a> The LEGO options
1865
1866
1867In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1868is proportional to the cell content. The lego aspect is control with the
1869following options:
1870
1871| Option | Description |
1872|----------|-------------------------------------------------------------------|
1873| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1874| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1875| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1876| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1877| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1878| "0" | When used with any LEGO option, the empty bins are not drawn.|
1879
1880
1881See the limitations with [the option "SAME"](#HP060a).
1882
1883Line attributes can be used in lego plots to change the edges' style.
1884
1885The following example shows a 2D histogram plotted with the option
1886`LEGO`. The option `LEGO` draws a lego plot using the hidden
1887lines removal technique.
1888
1889Begin_Macro(source)
1890{
1891 auto c2 = new TCanvas("c2","c2",600,400);
1892 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1893 float px, py;
1894 for (Int_t i = 0; i < 25000; i++) {
1895 gRandom->Rannor(px,py);
1896 hlego->Fill(px-1,5*py);
1897 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1898 }
1899 hlego->Draw("LEGO");
1900}
1901End_Macro
1902
1903The following example shows a 2D histogram plotted with the option
1904`LEGO1`. The option `LEGO1` draws a lego plot using the
1905hidden surface removal technique. Combined with any `LEGOn` option, the
1906option `0` allows to not drawn the empty bins.
1907
1908Begin_Macro(source)
1909{
1910 auto c2 = new TCanvas("c2","c2",600,400);
1911 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1912 float px, py;
1913 for (Int_t i = 0; i < 25000; i++) {
1914 gRandom->Rannor(px,py);
1915 hlego1->Fill(px-1,5*py);
1916 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1917 }
1918 hlego1->SetFillColor(kYellow);
1919 hlego1->Draw("LEGO1 0");
1920}
1921End_Macro
1922
1923The following example shows a 2D histogram plotted with the option
1924`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1925draws a lego plot using the hidden surface removal technique but doesn't draw
1926the border lines of each individual lego-bar. This is very useful for histograms
1927having many bins. With such histograms the option `LEGO1` gives a black
1928image because of the border lines. This option also works with stacked legos.
1929
1930Begin_Macro(source)
1931{
1932 auto c2 = new TCanvas("c2","c2",600,400);
1933 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1934 float px, py;
1935 for (Int_t i = 0; i < 25000; i++) {
1936 gRandom->Rannor(px,py);
1937 hlego3->Fill(px-1,5*py);
1938 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1939 }
1940 hlego3->SetFillColor(kRed);
1941 hlego3->Draw("LEGO3");
1942}
1943End_Macro
1944
1945The following example shows a 2D histogram plotted with the option
1946`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1947show the cell contents. Combined with the option `LEGO2`, the option
1948`Z` allows to display the color palette defined by
1949`gStyle->SetPalette()`.
1950
1951Begin_Macro(source)
1952{
1953 auto c2 = new TCanvas("c2","c2",600,400);
1954 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1955 float px, py;
1956 for (Int_t i = 0; i < 25000; i++) {
1957 gRandom->Rannor(px,py);
1958 hlego2->Fill(px-1,5*py);
1959 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1960 }
1961 hlego2->Draw("LEGO2Z");
1962}
1963End_Macro
1964
1965
1966
1967### <a name="HP18"></a> The "SURFace" options
1968
1969
1970In a surface plot, cell contents are represented as a mesh.
1971The height of the mesh is proportional to the cell content.
1972
1973| Option | Description |
1974|----------|-------------------------------------------------------------------|
1975| "SURF" | Draw a surface plot using the hidden line removal technique.|
1976| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
1977| "SURF2" | Draw a surface plot using colors to show the cell contents.|
1978| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
1979| "SURF4" | Draw a surface using the Gouraud shading technique.|
1980| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a a filled contour plot.|
1981| "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.|
1982| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
1983
1984
1985
1986See the limitations with [the option "SAME"](#HP060a).
1987
1988The following example shows a 2D histogram plotted with the option
1989`SURF`. The option `SURF` draws a lego plot using the hidden
1990lines removal technique.
1991
1992Begin_Macro(source)
1993{
1994 auto c2 = new TCanvas("c2","c2",600,400);
1995 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
1996 float px, py;
1997 for (Int_t i = 0; i < 25000; i++) {
1998 gRandom->Rannor(px,py);
1999 hsurf->Fill(px-1,5*py);
2000 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2001 }
2002 hsurf->Draw("SURF");
2003}
2004End_Macro
2005
2006The following example shows a 2D histogram plotted with the option
2007`SURF1`. The option `SURF1` draws a surface plot using the
2008hidden surface removal technique. Combined with the option `SURF1`,
2009the option `Z` allows to display the color palette defined by
2010`gStyle->SetPalette()`.
2011
2012Begin_Macro(source)
2013{
2014 auto c2 = new TCanvas("c2","c2",600,400);
2015 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2016 float px, py;
2017 for (Int_t i = 0; i < 25000; i++) {
2018 gRandom->Rannor(px,py);
2019 hsurf1->Fill(px-1,5*py);
2020 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2021 }
2022 hsurf1->Draw("SURF1");
2023}
2024End_Macro
2025
2026The following example shows a 2D histogram plotted with the option
2027`SURF2`. The option `SURF2` draws a surface plot using colors
2028to show the cell contents. Combined with the option `SURF2`, the option
2029`Z` allows to display the color palette defined by
2030`gStyle->SetPalette()`.
2031
2032Begin_Macro(source)
2033{
2034 auto c2 = new TCanvas("c2","c2",600,400);
2035 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2036 float px, py;
2037 for (Int_t i = 0; i < 25000; i++) {
2038 gRandom->Rannor(px,py);
2039 hsurf2->Fill(px-1,5*py);
2040 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2041 }
2042 hsurf2->Draw("SURF2");
2043}
2044End_Macro
2045
2046The following example shows a 2D histogram plotted with the option
2047`SURF3`. The option `SURF3` draws a surface plot using the
2048hidden line removal technique with, in addition, a filled contour view drawn on the
2049top. Combined with the option `SURF3`, the option `Z` allows
2050to display the color palette defined by `gStyle->SetPalette()`.
2051
2052Begin_Macro(source)
2053{
2054 auto c2 = new TCanvas("c2","c2",600,400);
2055 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2056 float px, py;
2057 for (Int_t i = 0; i < 25000; i++) {
2058 gRandom->Rannor(px,py);
2059 hsurf3->Fill(px-1,5*py);
2060 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2061 }
2062 hsurf3->Draw("SURF3");
2063}
2064End_Macro
2065
2066The following example shows a 2D histogram plotted with the option
2067`SURF4`. The option `SURF4` draws a surface using the Gouraud
2068shading technique.
2069
2070Begin_Macro(source)
2071{
2072 auto c2 = new TCanvas("c2","c2",600,400);
2073 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2074 float px, py;
2075 for (Int_t i = 0; i < 25000; i++) {
2076 gRandom->Rannor(px,py);
2077 hsurf4->Fill(px-1,5*py);
2078 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2079 }
2080 hsurf4->SetFillColor(kOrange);
2081 hsurf4->Draw("SURF4");
2082}
2083End_Macro
2084
2085The following example shows a 2D histogram plotted with the option
2086`SURF5 CYL`. Combined with the option `SURF5`, the option
2087`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2088
2089Begin_Macro(source)
2090{
2091 auto c2 = new TCanvas("c2","c2",600,400);
2092 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2093 float px, py;
2094 for (Int_t i = 0; i < 25000; i++) {
2095 gRandom->Rannor(px,py);
2096 hsurf5->Fill(px-1,5*py);
2097 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2098 }
2099 hsurf5->Draw("SURF5 CYL");
2100}
2101End_Macro
2102
2103The following example shows a 2D histogram plotted with the option
2104`SURF7`. The option `SURF7` draws a surface plot using the
2105hidden surfaces removal technique with, in addition, a line contour view drawn on the
2106top. Combined with the option `SURF7`, the option `Z` allows
2107to display the color palette defined by `gStyle->SetPalette()`.
2108
2109Begin_Macro(source)
2110{
2111 auto c2 = new TCanvas("c2","c2",600,400);
2112 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2113 float px, py;
2114 for (Int_t i = 0; i < 25000; i++) {
2115 gRandom->Rannor(px,py);
2116 hsurf7->Fill(px-1,5*py);
2117 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2118 }
2119 hsurf7->Draw("SURF7");
2120}
2121End_Macro
2122
2123As shown in the following example, when a contour plot is painted on top of a
2124surface plot using the option `SAME`, the contours appear in 3D on the
2125surface.
2126
2127Begin_Macro(source)
2128{
2129 auto c20=new TCanvas("c20","c20",600,400);
2130 int NBins = 50;
2131 double d = 2;
2132 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2133 for (int bx = 1; bx <= NBins; ++bx) {
2134 for (int by = 1; by <= NBins; ++by) {
2135 double x = hsc->GetXaxis()->GetBinCenter(bx);
2136 double y = hsc->GetYaxis()->GetBinCenter(by);
2137 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2138 }
2139 }
2140 hsc->Draw("surf2");
2141 hsc->Draw("CONT1 SAME");
2142}
2143End_Macro
2144
2145
2146### <a name="HP19"></a> Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2147
2148
2149Legos and surfaces plots are represented by default in Cartesian coordinates.
2150Combined with any `LEGOn` or `SURFn` options the following
2151options allow to draw a lego or a surface in other coordinates systems.
2152
2153| Option | Description |
2154|----------|-------------------------------------------------------------------|
2155| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2156| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2157| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2158| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2159
2160
2161
2162<b>WARNING:</b> Axis are not drawn with these options.
2163
2164The following example shows the same histogram as a lego plot is the four
2165different coordinates systems.
2166
2167Begin_Macro(source)
2168{
2169 auto c3 = new TCanvas("c3","c3",600,400);
2170 c3->Divide(2,2);
2171 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2172 float px, py;
2173 for (Int_t i = 0; i < 25000; i++) {
2174 gRandom->Rannor(px,py);
2175 hlcc->Fill(px-1,5*py);
2176 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2177 }
2178 hlcc->SetFillColor(kYellow);
2179 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2180 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2181 hlpc->SetTitle("Polar coordinates");
2182 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2183 hlsc->SetTitle("Spherical coordinates");
2184 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2185 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2186}
2187End_Macro
2188
2189The following example shows the same histogram as a surface plot is the four different coordinates systems.
2190
2191Begin_Macro(source)
2192{
2193 auto c4 = new TCanvas("c4","c4",600,400);
2194 c4->Divide(2,2);
2195 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2196 float px, py;
2197 for (Int_t i = 0; i < 25000; i++) {
2198 gRandom->Rannor(px,py);
2199 hscc->Fill(px-1,5*py);
2200 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2201 }
2202 c4->cd(1); hscc->Draw("SURF1 CYL");
2203 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2204 hspc->SetTitle("Polar coordinates");
2205 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2206 hssc->SetTitle("Spherical coordinates");
2207 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2208 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2209}
2210End_Macro
2211
2212
2213### <a name="HP20"></a> Base line for bar-charts and lego plots
2214
2215
2216By default the base line used to draw the boxes for bar-charts and lego plots is
2217the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2218option or with the command:
2219
2220 gStyle->SetHistMinimumZero();
2221
2222Begin_Macro(source)
2223{
2224 auto c5 = new TCanvas("c5","c5",700,400);
2225 c5->Divide(2,1);
2226 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2227 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2228 Int_t i;
2229 double x,y;
2230 hz1->SetFillColor(kBlue);
2231 hz2->SetFillColor(kBlue);
2232 for (i=0;i<10000;i++) {
2233 x = gRandom->Gaus(0,1);
2234 y = gRandom->Gaus(0,1);
2235 if (x>0) {
2236 hz1->Fill(x,1);
2237 hz2->Fill(x,y,1);
2238 } else {
2239 hz1->Fill(x,-1);
2240 hz2->Fill(x,y,-2);
2241 }
2242 }
2243 c5->cd(1); hz1->Draw("bar2 min0");
2244 c5->cd(2); hz2->Draw("lego1 min0");
2245}
2246End_Macro
2247
2248This option also works for horizontal plots. The example given in the section
2249["The bar chart option"](#HP100) appears as follow:
2250
2251Begin_Macro(source)
2252{
2253 int i;
2254 const Int_t nx = 8;
2255 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2256 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2257 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2258
2259 auto cbh = new TCanvas("cbh","cbh",400,600);
2260 cbh->SetGrid();
2261
2262 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2263 h1bh->SetFillColor(4);
2264 h1bh->SetBarWidth(0.4);
2265 h1bh->SetBarOffset(0.1);
2266 h1bh->SetStats(0);
2267 h1bh->SetMinimum(-5);
2268 h1bh->SetMaximum(5);
2269
2270 for (i=1; i<=nx; i++) {
2271 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2272 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2273 }
2274
2275 h1bh->Draw("hbar min0");
2276
2277 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2278 h2bh->SetFillColor(38);
2279 h2bh->SetBarWidth(0.4);
2280 h2bh->SetBarOffset(0.5);
2281 h2bh->SetStats(0);
2282 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2283
2284 h2bh->Draw("hbar min0 same");
2285}
2286End_Macro
2287
2288
2289### <a name="HP20a"></a> TH2Poly Drawing
2290
2291
2292The following options are supported:
2293
2294| Option | Description |
2295|----------|-------------------------------------------------------------------|
2296| "SCAT" | Draw a scatter plot (default).|
2297| "COL" | Draw a color plot. All the bins are painted even the empty bins.|
2298| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2299| "0" | When used with any COL options, the empty bins are not drawn.|
2300| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2301| "TEXTN" | Draw bin names as text.|
2302| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90).|
2303| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2304| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2305| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2306
2307
2308
2309`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2310shapes. The bins are defined as graphs. The following macro is a very simple
2311example showing how to book a TH2Poly and draw it.
2312
2313Begin_Macro(source)
2314{
2315 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2316 auto h2p = new TH2Poly();
2317 h2p->SetName("h2poly_name");
2318 h2p->SetTitle("h2poly_title");
2319 double px1[] = {0, 5, 6};
2320 double py1[] = {0, 0, 5};
2321 double px2[] = {0, -1, -1, 0};
2322 double py2[] = {0, 0, -1, 3};
2323 double px3[] = {4, 3, 0, 1, 2.4};
2324 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2325 h2p->AddBin(3, px1, py1);
2326 h2p->AddBin(4, px2, py2);
2327 h2p->AddBin(5, px3, py3);
2328 h2p->Fill(0.1, 0.01, 3);
2329 h2p->Fill(-0.5, -0.5, 7);
2330 h2p->Fill(-0.7, -0.5, 1);
2331 h2p->Fill(1, 3, 1.5);
2332 double fx[] = {0.1, -0.5, -0.7, 1};
2333 double fy[] = {0.01, -0.5, -0.5, 3};
2334 double fw[] = {3, 1, 1, 1.5};
2335 h2p->FillN(4, fx, fy, fw);
2336 h2p->Draw("col");
2337}
2338End_Macro
2339
2340Rectangular bins are a frequent case. The special version of
2341the `AddBin` method allows to define them more easily like
2342shown in the following example (th2polyBoxes.C).
2343
2344Begin_Macro(source)
2345../../../tutorials/hist/th2polyBoxes.C
2346End_Macro
2347
2348One `TH2Poly` bin can be a list of polygons. Such bins are defined
2349by calling `AddBin` with a `TMultiGraph`. The following example
2350shows a such case:
2351
2352Begin_Macro(source)
2353{
2354 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2355
2356 Int_t i, bin;
2357 const Int_t nx = 48;
2358 const char *states [nx] = {
2359 "alabama", "arizona", "arkansas", "california",
2360 "colorado", "connecticut", "delaware", "florida",
2361 "georgia", "idaho", "illinois", "indiana",
2362 "iowa", "kansas", "kentucky", "louisiana",
2363 "maine", "maryland", "massachusetts", "michigan",
2364 "minnesota", "mississippi", "missouri", "montana",
2365 "nebraska", "nevada", "new_hampshire", "new_jersey",
2366 "new_mexico", "new_york", "north_carolina", "north_dakota",
2367 "ohio", "oklahoma", "oregon", "pennsylvania",
2368 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2369 "texas", "utah", "vermont", "virginia",
2370 "washington", "west_virginia", "wisconsin", "wyoming"
2371 };
2372 Double_t pop[nx] = {
2373 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2374 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2375 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2376 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2377 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2378 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2379 };
2380
2381 Double_t lon1 = -130;
2382 Double_t lon2 = -65;
2383 Double_t lat1 = 24;
2384 Double_t lat2 = 50;
2385 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2386
2387 TFile::SetCacheFileDir(".");
2388 auto f = TFile::Open("http://root.cern.ch/files/usa.root", "CACHEREAD");
2389
2390 TMultiGraph *mg;
2391 TKey *key;
2392 TIter nextkey(gDirectory->GetListOfKeys());
2393 while ((key = (TKey*)nextkey())) {
2394 TObject *obj = key->ReadObj();
2395 if (obj->InheritsFrom("TMultiGraph")) {
2396 mg = (TMultiGraph*)obj;
2397 bin = p->AddBin(mg);
2398 }
2399 }
2400
2401 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2402
2403 gStyle->SetOptStat(11);
2404 p->Draw("COLZ L");
2405}
2406End_Macro
2407
2408`TH2Poly` histograms can also be plotted using the GL interface using
2409the option "GLLEGO".
2410
2411\since **ROOT version 6.09/01**
2412
2413In some cases it can be useful to not draw the empty bins. the option "0"
2414combined with the option "COL" et COLZ allows to do that.
2415
2416Begin_Macro(source)
2417{
2418 auto chc = new TCanvas("chc","chc",600,400);
2419
2420 auto hc = new TH2Poly();
2421 hc->Honeycomb(0,0,.1,25,25);
2422 hc->SetName("hc");
2423 hc->SetTitle("Option COLZ 0");
2424 TRandom ran;
2425 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2426 hc->Draw("colz 0");
2427}
2428End_Macro
2429
2430### <a name="HP21"></a> The SPEC option
2431
2432
2433This option allows to use the `TSpectrum2Painter` tools. See the full
2434documentation in `TSpectrum2Painter::PaintSpectrum`.
2435
2436
2437### <a name="HP22"></a> Option "Z" : Adding the color palette on the right side of the pad
2438
2439
2440When this option is specified, a color palette with an axis indicating the value
2441of the corresponding color is drawn on the right side of the picture. In case,
2442not enough space is left, one can increase the size of the right margin by
2443calling `TPad::SetRightMargin()`. The attributes used to display the
2444palette axis values are taken from the Z axis of the object. For example, to
2445set the labels size on the palette axis do:
2446
2447 hist->GetZaxis()->SetLabelSize().
2448
2449<b>WARNING:</b> The palette axis is always drawn vertically.
2450
2451
2452### <a name="HP23"></a> Setting the color palette
2453
2454
2455To change the color palette `TStyle::SetPalette` should be used, eg:
2456
2457 gStyle->SetPalette(ncolors,colors);
2458
2459For example the option `COL` draws a 2D histogram with cells
2460represented by a box filled with a color index which is a function
2461of the cell content.
2462If the cell content is N, the color index used will be the color number
2463in `colors[N]`, etc. If the maximum cell content is greater than
2464`ncolors`, all cell contents are scaled to `ncolors`.
2465
2466If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2467defined. This palette is recommended for pads, labels ...
2468
2469`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2470Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2471palette.
2472
2473Other pre-defined palettes with 255 colors are available when `colors == 0`.
2474The following value of `ncolors` give access to:
2475
2476
2477 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2478 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2479 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2480 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright yellow)
2481 if ncolors = 55 and colors=0, a Rain Bow palette is used.
2482 if ncolors = 56 and colors=0, an inverted Dark Body Radiator palette is used.
2483
2484
2485If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2486
2487The default palette defines:
2488
2489- index 0 to 9 : shades of grey
2490- index 10 to 19 : shades of brown
2491- index 20 to 29 : shades of blue
2492- index 30 to 39 : shades of red
2493- index 40 to 49 : basic colors
2494
2495The color numbers specified in the palette can be viewed by selecting
2496the item `colors` in the `VIEW` menu of the canvas tool bar.
2497The red, green, and blue components of a color can be changed thanks to
2498`TColor::SetRGB()`.
2499
2500\since **ROOT version 6.19/01**
2501
2502As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2503points as controlled by SetNdivisions.
2504If option "CJUST" is given labels and ticks are justified at the
2505color boundaries defined by the contour levels.
2506For more details see `TPaletteAxis`
2507
2508### <a name="HP24"></a> Drawing a sub-range of a 2D histogram; the [cutg] option
2509
2510
2511Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2512histogram. One must create a graphical cut (mouse or C++) and specify the name
2513of the cut between `[]` in the `Draw()` option.
2514For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2515
2516 myhist->Draw("surf1 [cutg]");
2517
2518To invert the cut, it is enough to put a `-` in front of its name:
2519
2520 myhist->Draw("surf1 [-cutg]");
2521
2522It is possible to apply several cuts (`,` means logical AND):
2523
2524 myhist->Draw("surf1 [cutg1,cutg2]");
2525
2526Begin_Macro(source)
2527../../../tutorials/fit/fit2a.C
2528End_Macro
2529
2530### <a name="HP25"></a> Drawing options for 3D histograms
2531
2532
2533| Option | Description |
2534|----------|-------------------------------------------------------------------|
2535| "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)`|
2536| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2537| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2538| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
2539| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2540| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2541
2542Note that instead of `BOX` one can also use `LEGO`.
2543
2544By default, like 2D histograms, 3D histograms are drawn as scatter plots.
2545
2546The following example shows a 3D histogram plotted as a scatter plot.
2547
2548Begin_Macro(source)
2549{
2550 auto c06 = new TCanvas("c06","c06",600,400);
2551 gStyle->SetOptStat(kFALSE);
2552 auto h3scat = new TH3F("h3scat","Option SCAT (default) ",15,-2,2,15,-2,2,15,0,4);
2553 double x, y, z;
2554 for (Int_t i=0;i<10000;i++) {
2555 gRandom->Rannor(x, y);
2556 z = x*x + y*y;
2557 h3scat->Fill(x,y,z);
2558 }
2559 h3scat->Draw();
2560}
2561End_Macro
2562
2563The following example shows a 3D histogram plotted with the option `BOX`.
2564
2565Begin_Macro(source)
2566{
2567 auto c16 = new TCanvas("c16","c16",600,400);
2568 gStyle->SetOptStat(kFALSE);
2569 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2570 double x, y, z;
2571 for (Int_t i=0;i<10000;i++) {
2572 gRandom->Rannor(x, y);
2573 z = x*x + y*y;
2574 h3box->Fill(x,y,z);
2575 }
2576 h3box->Draw("BOX");
2577}
2578End_Macro
2579
2580The following example shows a 3D histogram plotted with the option `BOX1`.
2581
2582Begin_Macro(source)
2583{
2584 auto c36 = new TCanvas("c36","c36",600,400);
2585 gStyle->SetOptStat(kFALSE);
2586 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2587 double x, y, z;
2588 for (Int_t i=0;i<10000;i++) {
2589 gRandom->Rannor(x, y);
2590 z = abs(sin(x)/x + cos(y)*y);
2591 h3box->Fill(x,y,z);
2592 }
2593 h3box->SetFillColor(9);
2594 h3box->Draw("BOX1");
2595}
2596End_Macro
2597
2598The following example shows a 3D histogram plotted with the option `BOX2`.
2599
2600Begin_Macro(source)
2601{
2602 auto c56 = new TCanvas("c56","c56",600,400);
2603 gStyle->SetOptStat(kFALSE);
2604 auto h3box = new TH3F("h3box","Option BOX2",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2605 double x, y, z;
2606 for (Int_t i=0;i<10000;i++) {
2607 gRandom->Rannor(x, y);
2608 z = abs(sin(x)/x + cos(y)*y);
2609 h3box->Fill(x,y,z);
2610 }
2611 h3box->Draw("BOX2 Z");
2612}
2613End_Macro
2614
2615The following example shows a 3D histogram plotted with the option `BOX3`.
2616
2617Begin_Macro(source)
2618{
2619 auto c46 = new TCanvas("c46","c46",600,400);
2620 c46->SetFillColor(38);
2621 gStyle->SetOptStat(kFALSE);
2622 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2623 double x, y, z;
2624 for (Int_t i=0;i<10000;i++) {
2625 gRandom->Rannor(x, y);
2626 z = x*x + y*y;
2627 h3box->Fill(x,y,z);
2628 }
2629 h3box->Draw("BOX3");
2630}
2631End_Macro
2632
2633For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2634to the absolute value of the bin content. The bins with a negative content are
2635drawn with a X on each face of the box as shown in the following example:
2636
2637Begin_Macro(source)
2638{
2639 auto c = new TCanvas("c","c",600,400);
2640 gStyle->SetOptStat(kFALSE);
2641 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2642 h3box->Fill(0., 2., 2., 10.);
2643 h3box->Fill(2., 2., 2., 5.);
2644 h3box->Fill(2., 2., .5, 2.);
2645 h3box->Fill(2., 2., 3., -1.);
2646 h3box->Fill(3., 2., 2., -10.);
2647 h3box->SetFillColor(8);
2648 h3box->Draw("box1");
2649}
2650End_Macro
2651
2652The following example shows a 3D histogram plotted with the option `ISO`.
2653
2654Begin_Macro(source)
2655{
2656 auto c26 = new TCanvas("c26","c26",600,400);
2657 gStyle->SetOptStat(kFALSE);
2658 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2659 double x, y, z;
2660 for (Int_t i=0;i<10000;i++) {
2661 gRandom->Rannor(x, y);
2662 z = x*x + y*y;
2663 h3iso->Fill(x,y,z);
2664 }
2665 h3iso->SetFillColor(kCyan);
2666 h3iso->Draw("ISO");
2667}
2668End_Macro
2669
2670
2671### <a name="HP26"></a> Drawing option for histograms' stacks
2672
2673
2674Stacks of histograms are managed with the `THStack`. A `THStack`
2675is a collection of `TH1` (or derived) objects. For painting only the
2676`THStack` containing `TH1` only or
2677`THStack` containing `TH2` only will be considered.
2678
2679By default, histograms are shown stacked:
2680
26811. The first histogram is paint.
26822. The the sum of the first and second, etc...
2683
2684If the option `NOSTACK` is specified, the histograms are all paint in
2685the same pad as if the option `SAME` had been specified. This allows to
2686compute X and Y scales common to all the histograms, like
2687`TMultiGraph` does for graphs.
2688
2689If the option `PADS` is specified, the current pad/canvas is
2690subdivided into a number of pads equal to the number of histograms and each
2691histogram is paint into a separate pad.
2692
2693The following example shows various types of stacks (hstack.C).
2694
2695Begin_Macro(source)
2696../../../tutorials/hist/hstack.C
2697End_Macro
2698
2699The option `nostackb` allows to draw the histograms next to each
2700other as bar charts:
2701
2702Begin_Macro(source)
2703{
2704 auto cst0 = new TCanvas("cst0","cst0",600,400);
2705 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2706
2707 auto h1 = new TH1F("h1","h1",10,-4,4);
2708 h1->FillRandom("gaus",20000);
2709 h1->SetFillColor(kRed);
2710 hs->Add(h1);
2711
2712 auto h2 = new TH1F("h2","h2",10,-4,4);
2713 h2->FillRandom("gaus",15000);
2714 h2->SetFillColor(kBlue);
2715 hs->Add(h2);
2716
2717 auto h3 = new TH1F("h3","h3",10,-4,4);
2718 h3->FillRandom("gaus",10000);
2719 h3->SetFillColor(kGreen);
2720 hs->Add(h3);
2721
2722 hs->Draw("nostackb");
2723 hs->GetXaxis()->SetNdivisions(-10);
2724 cst0->SetGridx();
2725}
2726End_Macro
2727
2728If at least one of the histograms in the stack has errors, the whole stack is
2729visualized by default with error bars. To visualize it without errors the
2730option `HIST` should be used.
2731
2732Begin_Macro(source)
2733{
2734 auto cst1 = new TCanvas("cst1","cst1",700,400);
2735 cst1->Divide(2,1);
2736
2737 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2738 hst11->Sumw2();
2739 hst11->FillRandom("gaus", 1000);
2740 hst11->SetFillColor(kViolet);
2741 hst11->SetLineColor(kViolet);
2742
2743 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2744 hst12->FillRandom("gaus", 500);
2745 hst12->SetFillColor(kBlue);
2746 hst12->SetLineColor(kBlue);
2747
2748 THStack st1("st1", "st1");
2749 st1.Add(hst11);
2750 st1.Add(hst12);
2751
2752 cst1->cd(1); st1.Draw();
2753 cst1->cd(2); st1.Draw("hist");
2754}
2755End_Macro
2756
2757### <a name="HP27"></a> Drawing of 3D implicit functions
2758
2759
27603D implicit functions (`TF3`) can be drawn as iso-surfaces.
2761The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2762In the following example the options "FB" and "BB" suppress the
2763"Front Box" and "Back Box" around the plot.
2764
2765Begin_Macro(source)
2766{
2767 auto c2 = new TCanvas("c2","c2",600,400);
2768 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2769 f3->SetClippingBoxOn(0,0,0);
2770 f3->SetFillColor(30);
2771 f3->SetLineColor(15);
2772 f3->Draw("FBBB");
2773}
2774End_Macro
2775
2776
2777### <a name="HP28"></a> Associated functions drawing
2778
2779
2780An associated function is created by `TH1::Fit`. More than on fitted
2781function can be associated with one histogram (see `TH1::Fit`).
2782
2783A `TF1` object `f1` can be added to the list of associated
2784functions of an histogram `h` without calling `TH1::Fit`
2785simply doing:
2786
2787 h->GetListOfFunctions()->Add(f1);
2788
2789or
2790
2791 h->GetListOfFunctions()->Add(f1,someoption);
2792
2793To retrieve a function by name from this list, do:
2794
2795 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2796
2797or
2798
2799 TF1 *f1 = h->GetFunction(name);
2800
2801Associated functions are automatically painted when an histogram is drawn.
2802To avoid the painting of the associated functions the option `HIST`
2803should be added to the list of the options used to paint the histogram.
2804
2805
2806### <a name="HP29"></a> Drawing using OpenGL
2807
2808
2809The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2810graphics library. The plotting options start with `GL` keyword.
2811In addition, in order to inform canvases that OpenGL should be used to render
28123D representations, the following option should be set:
2813
2814 gStyle->SetCanvasPreferGL(true);
2815
2816
2817#### <a name="HP29a"></a> General information: plot types and supported options
2818
2819The following types of plots are provided:
2820
2821For lego plots the supported options are:
2822
2823| Option | Description |
2824|----------|-------------------------------------------------------------------|
2825| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2826| "GLLEGO2"| Bins with color levels.|
2827| "GLLEGO3"| Cylindrical bars.|
2828
2829
2830
2831Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2832In polar only Z axis can be logarithmic, in cylindrical only Y.
2833
2834For surface plots (`TF2` and `TH2`) the supported options are:
2835
2836| Option | Description |
2837|-----------|------------------------------------------------------------------|
2838| "GLSURF" | Draw a surface.|
2839| "GLSURF1" | Surface with color levels|
2840| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2841| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2842| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2843
2844
2845
2846The surface painting in cartesian coordinates supports logarithmic scales along
2847X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2848in cylindrical coordinates only the Y axis.
2849
2850Additional options to SURF and LEGO - Coordinate systems:
2851
2852| Option | Description |
2853|----------|-------------------------------------------------------------------|
2854| " " | Default, cartesian coordinates system.|
2855| "POL" | Polar coordinates system.|
2856| "CYL" | Cylindrical coordinates system.|
2857| "SPH" | Spherical coordinates system.|
2858
2859
2860
2861#### <a name="HP290"></a> TH3 as color boxes
2862
2863The supported option is:
2864
2865| Option | Description |
2866|----------|-------------------------------------------------------------------|
2867| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/gl/glvox1.C`.|
2868
2869
2870
2871#### <a name="HP29b"></a> TH3 as boxes (spheres)
2872
2873The supported options are:
2874
2875| Option | Description |
2876|----------|-------------------------------------------------------------------|
2877| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2878| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2879
2880
2881
2882#### <a name="HP29c"></a> TH3 as iso-surface(s)
2883
2884The supported option is:
2885
2886| Option | Description |
2887|----------|-------------------------------------------------------------------|
2888| "GLISO" | TH3 is drawn using iso-surfaces.|
2889
2890
2891
2892#### <a name="HP29d"></a> TF3 (implicit function)
2893
2894The supported option is:
2895
2896| Option | Description |
2897|----------|-------------------------------------------------------------------|
2898| "GL" | Draw a TF3.|
2899
2900
2901
2902#### <a name="HP29e"></a> Parametric surfaces
2903
2904`$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric
2905equations and visualize the surface.
2906
2907#### <a name="HP29f"></a> Interaction with the plots
2908
2909All the interactions are implemented via standard methods
2910`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2911interactions with the OpenGL plots are possible only when the mouse cursor is
2912in the plot's area (the plot's area is the part of a the pad occupied by
2913gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2914pad interaction is performed.
2915
2916#### <a name="HP29g"></a> Selectable parts
2917
2918Different parts of the plot can be selected:
2919
2920- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2921 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2922 if the dynamic slicing is not supported.
2923- The plot itself:
2924 On surfaces, the selected surface is outlined in red. (TF3 and
2925 ISO are not outlined). On lego plots, the selected bin is
2926 highlighted. The bin number and content are displayed in pad's
2927 status bar. In box plots, the box or sphere is highlighted and
2928 the bin info is displayed in pad's status bar.
2929
2930
2931#### <a name="HP29h"></a> Rotation and zooming
2932
2933
2934- Rotation:
2935 When the plot is selected, it can be rotated by pressing and
2936 holding the left mouse button and move the cursor.
2937- Zoom/Unzoom:
2938 Mouse wheel or 'j', 'J', 'k', 'K' keys.
2939
2940
2941#### <a name="HP29i"></a> Panning
2942
2943The selected plot can be moved in a pad's area by pressing and
2944holding the left mouse button and the shift key.
2945
2946#### <a name="HP29j"></a> Box cut
2947
2948Surface, iso, box, TF3 and parametric painters support box cut by
2949pressing the 'c' or 'C' key when the mouse cursor is in a plot's
2950area. That will display a transparent box, cutting away part of the
2951surface (or boxes) in order to show internal part of plot. This box
2952can be moved inside the plot's area (the full size of the box is
2953equal to the plot's surrounding box) by selecting one of the box
2954cut axes and pressing the left mouse button to move it.
2955
2956#### <a name="HP29k"></a> Plot specific interactions (dynamic slicing etc.)
2957
2958Currently, all gl-plots support some form of slicing. When back plane
2959is selected (and if it's highlighted in green) you can press and hold
2960left mouse button and shift key and move this back plane inside
2961plot's area, creating the slice. During this "slicing" plot becomes
2962semi-transparent. To remove all slices (and projected curves for
2963surfaces) double click with left mouse button in a plot's area.
2964
2965#### <a name="HP29l"></a> Surface with option "GLSURF"
2966
2967The surface profile is displayed on the slicing plane.
2968The profile projection is drawn on the back plane
2969by pressing `'p'` or `'P'` key.
2970
2971#### <a name="HP29m"></a> TF3
2972
2973The contour plot is drawn on the slicing plane. For TF3 the color
2974scheme can be changed by pressing 's' or 'S'.
2975
2976#### <a name="HP29n"></a> Box
2977
2978The contour plot corresponding to slice plane position is drawn in real time.
2979
2980#### <a name="HP29o"></a> Iso
2981
2982Slicing is similar to "GLBOX" option.
2983
2984#### <a name="HP29p"></a> Parametric plot
2985
2986No slicing. Additional keys: 's' or 'S' to change color scheme -
2987about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
2988increase number of polygons ('l' for "level" of details), 'w' or 'W'
2989to show outlines ('w' for "wireframe").
2990
2991#### <a name="HP30"></a> Highlight mode for histogram
2992
2993\since **ROOT version 6.15/01**
2994
2995\image html hlHisto3_top.gif "Highlight mode"
2996
2997Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
2998highlight mode is on, mouse movement over the bin will be represented
2999graphically. Bin will be highlighted as "bin box" (presented by box
3000object). Moreover, any highlight (change of bin) emits signal
3001`TCanvas::Highlighted()` which allows the user to react and call their own
3002function. For a better understanding see also the tutorials
3003`$ROOTSYS/tutorials/hist/hlHisto*.C` files.
3004
3005Highlight mode is switched on/off by `TH1::SetHighlight()` function
3006or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3007whether the highlight mode enabled or disabled, default it is disabled.
3008
3009~~~ {.cpp}
3010 root [0] .x $ROOTSYS/tutorials/hsimple.C
3011 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3012 root [2] hpx->IsHighlight()
3013 (bool) true
3014~~~
3015
3016\image html hlsimple_nofun.gif "Highlight mode for histogram"
3017
3018#### <a name="HP30a"></a> Highlight mode and user function
3019
3020The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3021emitted if there is a highlight bin and call user function via signal
3022and slot communication mechanism. `TCanvas::Highlighted()` is similar
3023`TCanvas::Picked()`
3024
3025- when selected object (histogram as a whole) is different from previous
3026then emit `Picked()` signal
3027- when selected (highlighted) bin from histogram is different from previous
3028then emit `Highlighted()` signal
3029
3030Any user function (or functions) has to be defined
3031`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3032In example (see below) has name `PrintInfo()`. All parameters of user
3033function are taken from
3034
3035 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3036
3037- `pad` is pointer to pad with highlighted histogram
3038- `obj` is pointer to highlighted histogram
3039- `x` is highlighted x bin for 1D histogram
3040- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3041
3042Example how to create a connection from any `TCanvas` object to a user
3043`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3044
3045 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3046 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3047
3048or use non-static "simplified" function
3049`TCanvas::HighlightConnect(const char *slot)`
3050
3051 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3052
3053NOTE the signal and slot string must have a form
3054"(TVirtualPad*,TObject*,Int_t,Int_t)"
3055
3056 root [0] .x $ROOTSYS/tutorials/hsimple.C
3057 root [1] hpx->SetHighlight(kTRUE)
3058 root [2] .x hlprint.C
3059
3060file `hlprint.C`
3061~~~ {.cpp}
3062void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3063{
3064 auto h = (TH1F *)obj;
3065 if (!h->IsHighlight()) // after highlight disabled
3066 h->SetTitle("highlight disable");
3067 else
3068 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3069 h->GetBinCenter(x), h->GetBinContent(x)));
3070 pad->Update();
3071}
3072
3073void hlprint()
3074{
3075 if (!gPad) return;
3076 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3077}
3078~~~
3079
3080\image html hlsimple.gif "Highlight mode and simple user function"
3081
3082For more complex demo please see for example `$ROOTSYS/tutorials/tree/temperature.C` file.
3083
3084*/
3085
3087
3090
3091const Int_t kNMAX = 2000;
3092
3093const Int_t kMAXCONTOUR = 104;
3095
3096static TBox *gXHighlightBox = 0; // highlight X box
3097static TBox *gYHighlightBox = 0; // highlight Y box
3098
3120
3122
3123////////////////////////////////////////////////////////////////////////////////
3124/// Default constructor.
3125
3127{
3128
3129 fH = 0;
3130 fXaxis = 0;
3131 fYaxis = 0;
3132 fZaxis = 0;
3133 fFunctions = 0;
3134 fXbuf = 0;
3135 fYbuf = 0;
3136 fNcuts = 0;
3137 fStack = 0;
3138 fLego = 0;
3139 fPie = 0;
3140 fGraph2DPainter = 0;
3141 fShowProjection = 0;
3142 fShowOption = "";
3143 for (int i=0; i<kMaxCuts; i++) {
3144 fCuts[i] = 0;
3145 fCutsOpt[i] = 0;
3146 }
3147 fXHighlightBin = -1;
3148 fYHighlightBin = -1;
3149 fCurrentF3 = nullptr;
3150
3151 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3152 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3153 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3154 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3155 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3156 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3157 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3158 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3159 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3160 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3161 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3162 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3163 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3164 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3165 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3166 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3167 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3168 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3169 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3170 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3171 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3172}
3173
3174////////////////////////////////////////////////////////////////////////////////
3175/// Default destructor.
3176
3178{
3179 if (fPie) delete fPie;
3180}
3181
3182////////////////////////////////////////////////////////////////////////////////
3183/// Compute the distance from the point px,py to a line.
3184///
3185/// Compute the closest distance of approach from point px,py to elements of
3186/// an histogram. The distance is computed in pixels units.
3187///
3188/// Algorithm: Currently, this simple model computes the distance from the mouse
3189/// to the histogram contour only.
3190
3192{
3193
3194 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3195
3196 const Int_t big = 9999;
3197 const Int_t kMaxDiff = 7;
3198
3199 if (fPie) return fPie->DistancetoPrimitive(px, py);
3200
3201 Double_t x = gPad->AbsPixeltoX(px);
3202 Double_t x1 = gPad->AbsPixeltoX(px+1);
3203
3204 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3205 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3206 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3207 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3208 Int_t curdist = big;
3209 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3210 Bool_t dsame;
3211 TObject *PadPointer = gPad->GetPadPointer();
3212 if (!PadPointer) return 0;
3213 TString doption = PadPointer->GetDrawOption();
3214 Double_t factor = 1;
3215 if (fH->GetNormFactor() != 0) {
3216 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3217 }
3218 // return if point is not in the histogram area
3219
3220 // If a 3D view exists, check distance to axis
3221 TView *view = gPad->GetView();
3222 Int_t d1,d2,d3;
3223 if (view && Hoption.Contour != 14) {
3224 Double_t ratio;
3225 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3226 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3227 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3228 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3229 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3230 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3231 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3232 goto FUNCTIONS;
3233 }
3234 // check if point is close to an axis
3235 doption.ToLower();
3236 dsame = kFALSE;
3237 if (doption.Contains("same")) dsame = kTRUE;
3238
3239 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3240 if (doption.Contains("y+")) {
3241 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3242 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3243 if (!dsame) {
3244 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3245 else gPad->SetSelected(fXaxis);
3246 return 0;
3247 }
3248 }
3249 } else {
3250 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3251 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3252 if (!dsame) {
3253 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3254 else gPad->SetSelected(fXaxis);
3255 return 0;
3256 }
3257 }
3258 }
3259
3260 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3261 if (doption.Contains("x+")) {
3262 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3263 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3264 if (!dsame) {
3265 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3266 else gPad->SetSelected(fYaxis);
3267 return 0;
3268 }
3269 }
3270 } else {
3271 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3272 if (yxaxis < puymin) yxaxis = puymin;
3273 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3274 if (!dsame) {
3275 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3276 else gPad->SetSelected(fYaxis);
3277 return 0;
3278 }
3279 }
3280 }
3281
3282 if (fH->IsHighlight()) { // only if highlight is enable
3283 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3284 HighlightBin(px, py);
3285 }
3286
3287 // if object is 2D or 3D return this object
3288 if (fH->GetDimension() == 2) {
3289 if (fH->InheritsFrom(TH2Poly::Class())) {
3290 TH2Poly *th2 = (TH2Poly*)fH;
3292 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3293 Double_t pxu = gPad->AbsPixeltoX(px);
3294 Double_t pyu = gPad->AbsPixeltoY(py);
3295 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3296 curdist = big;
3297 goto FUNCTIONS;
3298 } else {
3299 Int_t bin = th2->FindBin(pxu, pyu);
3300 if (bin>0) curdist = 1;
3301 else curdist = big;
3302 goto FUNCTIONS;
3303 }
3304 }
3305 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3306 if ( px > puxmin + delta2
3307 && px < puxmax - delta2
3308 && py > puymax + delta2
3309 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3310 }
3311
3312 // point is inside histogram area. Find channel number
3313 if (gPad->IsVertical()) {
3314 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3315 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3316 Double_t binval = factor*fH->GetBinContent(bin);
3317 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3318 if (binval == 0 && pybin < puymin) pybin = 10000;
3319 // special case if more than one bin for the pixel
3320 if (binsup-bin>1) {
3321 Double_t binvalmin, binvalmax;
3322 binvalmin=binval;
3323 binvalmax=binval;
3324 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3325 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3326 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3327 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3328 }
3329 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3330 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3331 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3332 }
3333 if (bin != binsup) { // Mouse on bin border
3334 Double_t binsupval = factor*fH->GetBinContent(binsup);
3335 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3336 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3337 }
3338 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3339 } else {
3340 Double_t y = gPad->AbsPixeltoY(py);
3341 Double_t y1 = gPad->AbsPixeltoY(py+1);
3342 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3343 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3344 Double_t binval = factor*fH->GetBinContent(bin);
3345 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3346 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3347 // special case if more than one bin for the pixel
3348 if (binsup-bin>1) {
3349 Double_t binvalmin, binvalmax;
3350 binvalmin=binval;
3351 binvalmax=binval;
3352 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3353 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3354 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3355 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3356 }
3357 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3358 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3359 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3360 }
3361 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3362 }
3363 // Loop on the list of associated functions and user objects
3364FUNCTIONS:
3365 TObject *f;
3366 TIter next(fFunctions);
3367 while ((f = (TObject*) next())) {
3368 Int_t dist;
3369 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3370 else dist = f->DistancetoPrimitive(px,py);
3371 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3372 }
3373 return curdist;
3374}
3375
3376////////////////////////////////////////////////////////////////////////////////
3377/// Display a panel with all histogram drawing options.
3378
3380{
3381
3382 gCurrentHist = fH;
3383 if (!gPad) {
3384 Error("DrawPanel", "need to draw histogram first");
3385 return;
3386 }
3388 editor->Show();
3389 gROOT->ProcessLine(Form("((TCanvas*)0x%lx)->Selected((TVirtualPad*)0x%lx,(TObject*)0x%lx,1)",
3390 (ULong_t)gPad->GetCanvas(), (ULong_t)gPad, (ULong_t)fH));
3391}
3392
3393////////////////////////////////////////////////////////////////////////////////
3394/// Execute the actions corresponding to `event`.
3395///
3396/// This function is called when a histogram is clicked with the locator at
3397/// the pixel position px,py.
3398
3400{
3401
3402 if (!gPad) return;
3403
3404 static Int_t bin, px1, py1, px2, py2, pyold;
3405 static TBox *zoombox;
3406 Double_t zbx1,zbx2,zby1,zby2;
3407
3408 Int_t bin1, bin2;
3409 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3410 Bool_t opaque = gPad->OpaqueMoving();
3411
3412 if (!gPad->IsEditable()) return;
3413
3414 if (fPie) {
3415 fPie->ExecuteEvent(event, px, py);
3416 return;
3417 }
3418 // come here if we have a lego/surface in the pad
3419 TView *view = gPad->GetView();
3420
3421 if (!fShowProjection && view && view->TestBit(kCannotRotate) == 0) {
3422 view->ExecuteRotateView(event, px, py);
3423 return;
3424 }
3425
3426 TAxis *xaxis = fH->GetXaxis();
3427 TAxis *yaxis = fH->GetYaxis();
3428 Int_t dimension = fH->GetDimension();
3429
3430 // In case of option SAME the axis must be the ones of the first drawn histogram
3431 TString IsSame = fH->GetDrawOption();
3432 IsSame.ToLower();
3433 if (IsSame.Index("same")>=0) {
3434 TH1 *h1;
3435 TIter next(gPad->GetListOfPrimitives());
3436 while ((h1 = (TH1 *)next())) {
3437 if (!h1->InheritsFrom(TH1::Class())) continue;
3438 xaxis = h1->GetXaxis();
3439 yaxis = h1->GetYaxis();
3440 break;
3441 }
3442 }
3443
3444 Double_t factor = 1;
3445 if (fH->GetNormFactor() != 0) {
3446 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3447 }
3448
3449 switch (event) {
3450
3451 case kButton1Down:
3452
3453 if (!opaque) gVirtualX->SetLineColor(-1);
3454 fH->TAttLine::Modify();
3455
3456 if (opaque && dimension ==2) {
3457 zbx1 = gPad->AbsPixeltoX(px);
3458 zbx2 = gPad->AbsPixeltoX(px);
3459 zby1 = gPad->AbsPixeltoY(py);
3460 zby2 = gPad->AbsPixeltoY(py);
3461 px1 = px;
3462 py1 = py;
3463 if (gPad->GetLogx()) {
3464 zbx1 = TMath::Power(10,zbx1);
3465 zbx2 = TMath::Power(10,zbx2);
3466 }
3467 if (gPad->GetLogy()) {
3468 zby1 = TMath::Power(10,zby1);
3469 zby2 = TMath::Power(10,zby2);
3470 }
3471 zoombox = new TBox(zbx1, zby1, zbx2, zby2);
3472 Int_t ci = TColor::GetColor("#7d7dff");
3473 TColor *zoomcolor = gROOT->GetColor(ci);
3474 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3475 else zoomcolor->SetAlpha(0.5);
3476 zoombox->SetFillColor(ci);
3477 zoombox->Draw();
3478 gPad->Modified();
3479 gPad->Update();
3480 }
3481 // No break !!!
3482
3483 case kMouseMotion:
3484
3485 if (fShowProjection) {ShowProjection3(px,py); break;}
3486
3487 gPad->SetCursor(kPointer);
3488 if (dimension ==1) {
3489 if (Hoption.Bar) {
3490 baroffset = fH->GetBarOffset();
3491 barwidth = fH->GetBarWidth();
3492 } else {
3493 baroffset = 0;
3494 barwidth = 1;
3495 }
3496 x = gPad->AbsPixeltoX(px);
3497 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3498 binwidth = fXaxis->GetBinWidth(bin);
3499 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3500 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3501 ylow = gPad->GetUymin();
3502 px1 = gPad->XtoAbsPixel(xlow);
3503 px2 = gPad->XtoAbsPixel(xup);
3504 py1 = gPad->YtoAbsPixel(ylow);
3505 py2 = py;
3506 pyold = py;
3507 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3508 }
3509
3510 break;
3511
3512 case kButton1Motion:
3513
3514 if (dimension ==1) {
3515 if (gROOT->GetEditHistograms()) {
3516 if (!opaque) {
3517 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3518 py2 += py - pyold;
3519 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3520 pyold = py;
3521 } else {
3522 py2 += py - pyold;
3523 pyold = py;
3524 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3525 fH->SetBinContent(bin,binval);
3526 gPad->Modified(kTRUE);
3527 }
3528 }
3529 }
3530
3531 if (opaque && dimension ==2) {
3532 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3533 zbx2 = gPad->AbsPixeltoX(px);
3534 zby2 = gPad->AbsPixeltoY(py);
3535 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3536 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3537 zoombox->SetX2(zbx2);
3538 zoombox->SetY2(zby2);
3539 gPad->Modified();
3540 gPad->Update();
3541 }
3542 }
3543
3544 break;
3545
3546 case kWheelUp:
3547
3548 if (dimension ==2) {
3549 bin1 = xaxis->GetFirst()+1;
3550 bin2 = xaxis->GetLast()-1;
3551 bin1 = TMath::Max(bin1, 1);
3552 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3553 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3554 bin1 = yaxis->GetFirst()+1;
3555 bin2 = yaxis->GetLast()-1;
3556 bin1 = TMath::Max(bin1, 1);
3557 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3558 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3559 }
3560 gPad->Modified();
3561 gPad->Update();
3562
3563 break;
3564
3565 case kWheelDown:
3566
3567 if (dimension == 2) {
3568 bin1 = xaxis->GetFirst()-1;
3569 bin2 = xaxis->GetLast()+1;
3570 bin1 = TMath::Max(bin1, 1);
3571 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3572 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3573 bin1 = yaxis->GetFirst()-1;
3574 bin2 = yaxis->GetLast()+1;
3575 bin1 = TMath::Max(bin1, 1);
3576 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3577 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3578 }
3579 gPad->Modified();
3580 gPad->Update();
3581
3582 break;
3583
3584 case kButton1Up:
3585 if (dimension ==1) {
3586 if (gROOT->GetEditHistograms()) {
3587 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3588 fH->SetBinContent(bin,binval);
3589 PaintInit(); // recalculate Hparam structure and recalculate range
3590 }
3591
3592 // might resize pad pixmap so should be called before any paint routine
3594 }
3595 if (opaque && dimension ==2) {
3596 if (zoombox) {
3597 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3598 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3599 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3600 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3601 x1 = TMath::Max(x1,xaxis->GetXmin());
3602 x2 = TMath::Min(x2,xaxis->GetXmax());
3603 y1 = TMath::Max(y1,yaxis->GetXmin());
3604 y2 = TMath::Min(y2,yaxis->GetXmax());
3605 if (x1<x2 && y1<y2) {
3606 xaxis->SetRangeUser(x1, x2);
3607 yaxis->SetRangeUser(y1, y2);
3608 }
3609 zoombox->Delete();
3610 zoombox = 0;
3611 }
3612 }
3613 gPad->Modified(kTRUE);
3614 if (opaque) gVirtualX->SetLineColor(-1);
3615
3616 break;
3617
3618 case kButton1Locate:
3619
3620 ExecuteEvent(kButton1Down, px, py);
3621
3622 while (1) {
3623 px = py = 0;
3624 event = gVirtualX->RequestLocator(1, 1, px, py);
3625
3627
3628 if (event != -1) { // button is released
3629 ExecuteEvent(kButton1Up, px, py);
3630 return;
3631 }
3632 }
3633 }
3634}
3635
3636////////////////////////////////////////////////////////////////////////////////
3637/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3638
3640{
3641
3642
3643
3644 // Check if fH contains a TGraphDelaunay2D
3645 TList *hl = fH->GetListOfFunctions();
3646 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3647 // try with the old painter
3648 TGraphDelaunay *dtOld = nullptr;
3649 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3650
3651 if (!dt && !dtOld) return nullptr;
3652
3653 gCurrentHist = fH;
3654
3655 if (!fGraph2DPainter) {
3656 if (dt) ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dt);
3657 else ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dtOld);
3658 }
3659
3660 return fGraph2DPainter->GetContourList(contour);
3661}
3662
3663////////////////////////////////////////////////////////////////////////////////
3664/// Display the histogram info (bin number, contents, integral up to bin
3665/// corresponding to cursor position px,py.
3666
3668{
3669
3670 if (!gPad) return (char*)"";
3671
3672 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3673 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3674 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3675 TString drawOption = fH->GetDrawOption();
3676 drawOption.ToLower();
3677 Double_t xmin, xmax, uxmin,uxmax;
3678 Double_t ymin, ymax, uymin,uymax;
3679 if (fH->GetDimension() == 2) {
3680 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3681 uxmin=gPad->GetUxmin();
3682 uxmax=gPad->GetUxmax();
3685 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3686 uymin=gPad->GetUymin();
3687 uymax=gPad->GetUymax();
3690 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3691 }
3692 }
3693 Int_t binx,biny,binmin=0,binx1;
3694 if (gPad->IsVertical()) {
3695 binx = fXaxis->FindFixBin(x);
3696 if (drawOption.Index("same") >= 0) {
3697 TH1 *h1;
3698 TIter next(gPad->GetListOfPrimitives());
3699 while ((h1 = (TH1 *)next())) {
3700 if (!h1->InheritsFrom(TH1::Class())) continue;
3701 binmin = h1->GetXaxis()->GetFirst();
3702 break;
3703 }
3704 } else {
3705 binmin = fXaxis->GetFirst();
3706 }
3707 binx1 = fXaxis->FindFixBin(x1);
3708 // special case if more than 1 bin in x per pixel
3709 if (binx1-binx>1 && fH->GetDimension() == 1) {
3710 Double_t binval=fH->GetBinContent(binx);
3711 Int_t binnear=binx;
3712 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3713 Double_t binvaltmp = fH->GetBinContent(ibin);
3714 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3715 binval=binvaltmp;
3716 binnear=ibin;
3717 }
3718 }
3719 binx = binnear;
3720 }
3721 } else {
3722 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3723 binx = fXaxis->FindFixBin(y);
3724 if (drawOption.Index("same") >= 0) {
3725 TH1 *h1;
3726 TIter next(gPad->GetListOfPrimitives());
3727 while ((h1 = (TH1 *)next())) {
3728 if (!h1->InheritsFrom(TH1::Class())) continue;
3729 binmin = h1->GetXaxis()->GetFirst();
3730 break;
3731 }
3732 } else {
3733 binmin = fXaxis->GetFirst();
3734 }
3735 binx1 = fXaxis->FindFixBin(x1);
3736 // special case if more than 1 bin in x per pixel
3737 if (binx1-binx>1 && fH->GetDimension() == 1) {
3738 Double_t binval=fH->GetBinContent(binx);
3739 Int_t binnear=binx;
3740 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3741 Double_t binvaltmp = fH->GetBinContent(ibin);
3742 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3743 binval=binvaltmp;
3744 binnear=ibin;
3745 }
3746 }
3747 binx = binnear;
3748 }
3749 }
3750 if (fH->GetDimension() == 1) {
3751 if (fH->InheritsFrom(TProfile::Class())) {
3752 TProfile *tp = (TProfile*)fH;
3753 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3754 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3755 (Int_t) tp->GetBinEntries(binx));
3756 }
3757 else {
3758 Double_t integ = 0;
3759 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3760 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3761 x,y,binx,fH->GetBinContent(binx),integ);
3762 }
3763 } else if (fH->GetDimension() == 2) {
3764 if (fH->InheritsFrom(TH2Poly::Class())) {
3765 TH2Poly *th2 = (TH2Poly*)fH;
3766 biny = th2->FindBin(x,y);
3767 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3768 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3769 }
3770 else if (fH->InheritsFrom(TProfile2D::Class())) {
3771 TProfile2D *tp = (TProfile2D*)fH;
3772 biny = fYaxis->FindFixBin(y);
3773 Int_t bin = fH->GetBin(binx,biny);
3774 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3775 x, y, binx, biny, fH->GetBinContent(bin),
3776 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3777 } else {
3778 biny = fYaxis->FindFixBin(y);
3779 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3780 x,y,binx,biny,fH->GetBinContent(binx,biny),
3781 fH->GetBinError(binx,biny));
3782 }
3783 } else {
3784 // 3d case: retrieving the x,y,z bin is not yet implemented
3785 // print just the x,y info
3786 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3787 }
3788
3789 return (char *)fObjectInfo.Data();
3790}
3791
3792////////////////////////////////////////////////////////////////////////////////
3793/// Set highlight (enable/disable) mode for fH
3794
3796{
3797 if (fH->IsHighlight()) return;
3798
3799 fXHighlightBin = -1;
3800 fYHighlightBin = -1;
3801 // delete previous highlight box
3804 // emit Highlighted() signal (user can check on disabled)
3805 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3806}
3807
3808////////////////////////////////////////////////////////////////////////////////
3809/// Check on highlight bin
3810
3812{
3813 // call from DistancetoPrimitive (only if highlight is enable)
3814
3815 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3816 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3817 Int_t binx = fXaxis->FindFixBin(x);
3818 Int_t biny = fYaxis->FindFixBin(y);
3819 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3820
3821 Bool_t changedBin = kFALSE;
3822 if (binx != fXHighlightBin) {
3823 fXHighlightBin = binx;
3824 changedBin = kTRUE;
3825 } else if (fH->GetDimension() == 1) return;
3826 if (biny != fYHighlightBin) {
3827 fYHighlightBin = biny;
3828 changedBin = kTRUE;
3829 }
3830 if (!changedBin) return;
3831
3832 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3833 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3834
3835 // paint highlight bin as box (recursive calls PaintHighlightBin)
3836 gPad->Modified(kTRUE);
3837 gPad->Update();
3838
3839 // emit Highlighted() signal
3840 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3841}
3842
3843////////////////////////////////////////////////////////////////////////////////
3844/// Paint highlight bin as TBox object
3845
3847{
3848 // call from PaintTitle
3849
3850 if (!fH->IsHighlight()) return;
3851
3852 Double_t uxmin = gPad->GetUxmin();
3853 Double_t uxmax = gPad->GetUxmax();
3854 Double_t uymin = gPad->GetUymin();
3855 Double_t uymax = gPad->GetUymax();
3856 if (gPad->GetLogx()) {
3857 uxmin = TMath::Power(10.0, uxmin);
3858 uxmax = TMath::Power(10.0, uxmax);
3859 }
3860 if (gPad->GetLogy()) {
3861 uymin = TMath::Power(10.0, uymin);
3862 uymax = TMath::Power(10.0, uymax);
3863 }
3864
3865 // testing specific possibility (after zoom, draw with "same", log, etc.)
3866 Double_t hcenter;
3867 if (gPad->IsVertical()) {
3869 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3870 } else {
3872 if ((hcenter < uymin) || (hcenter > uymax)) return;
3873 }
3874 if (fH->GetDimension() == 2) {
3876 if ((hcenter < uymin) || (hcenter > uymax)) return;
3877 }
3878
3879 // paint X highlight bin (for 1D or 2D)
3880 Double_t hbx1, hbx2, hby1, hby2;
3881 if (gPad->IsVertical()) {
3884 hby1 = uymin;
3885 hby2 = uymax;
3886 } else {
3887 hbx1 = uxmin;
3888 hbx2 = uxmax;
3891 }
3892
3893 if (!gXHighlightBox) {
3894 gXHighlightBox = new TBox(hbx1, hby1, hbx2, hby2);
3898 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3899 }
3900 gXHighlightBox->SetX1(hbx1);
3901 gXHighlightBox->SetX2(hbx2);
3902 gXHighlightBox->SetY1(hby1);
3903 gXHighlightBox->SetY2(hby2);
3905
3906 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3907 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3908
3909 // paint Y highlight bin (only for 2D)
3910 if (fH->GetDimension() != 2) return;
3911 hbx1 = uxmin;
3912 hbx2 = uxmax;
3915
3916 if (!gYHighlightBox) {
3917 gYHighlightBox = new TBox(hbx1, hby1, hbx2, hby2);
3921 }
3922 gYHighlightBox->SetX1(hbx1);
3923 gYHighlightBox->SetX2(hbx2);
3924 gYHighlightBox->SetY1(hby1);
3925 gYHighlightBox->SetY2(hby2);
3927}
3928
3929////////////////////////////////////////////////////////////////////////////////
3930/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3931
3933{
3934
3935 for (Int_t i=0;i<fNcuts;i++) {
3938 if (fCutsOpt[i] > 0) {
3939 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3940 } else {
3941 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3942 }
3943 }
3944 return kTRUE;
3945}
3946
3947////////////////////////////////////////////////////////////////////////////////
3948/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
3949
3951{
3952
3953 for (Int_t i=0;i<fNcuts;i++) {
3954 if (fCutsOpt[i] > 0) {
3955 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3956 } else {
3957 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3958 }
3959 }
3960 return kTRUE;
3961}
3962
3963////////////////////////////////////////////////////////////////////////////////
3964/// Decode string `choptin` and fill Hoption structure.
3965
3967{
3968
3969 char *l;
3970 char chopt[128];
3971 Int_t nch = strlen(choptin);
3972 strlcpy(chopt,choptin,128);
3973 Int_t hdim = fH->GetDimension();
3974
3983
3984 // special 2D options
3985 Hoption.List = 0;
3986 Hoption.Zscale = 0;
3987 Hoption.FrontBox = 1;
3988 Hoption.BackBox = 1;
3990
3991 Hoption.Zero = 0;
3992
3994
3995 //check for graphical cuts
3996 MakeCuts(chopt);
3997
3998 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
3999 if (hdim > 1) Hoption.Scat = 1;
4000 if (!nch) Hoption.Hist = 1;
4001 if (fFunctions->First()) Hoption.Func = 1;
4002 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4003
4004 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4005 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4006 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4007 if (l1 || l2 || l3) {
4008 Int_t i = gPad->NextPaletteColor();
4009 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4010 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4011 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4012 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4013 }
4014
4015 l = strstr(chopt,"MIN0");
4016 if (l) {
4017 Hoption.MinimumZero = 1;
4018 memcpy(l," ",4);
4019 }
4020
4021 l = strstr(chopt,"SPEC");
4022 if (l) {
4023 Hoption.Scat = 0;
4024 memcpy(l," ",4);
4025 Int_t bs=0;
4026 l = strstr(chopt,"BF(");
4027 if (l) {
4028 if (sscanf(&l[3],"%d",&bs) > 0) {
4029 Int_t i=0;
4030 while (l[i]!=')') {
4031 l[i] = ' ';
4032 i++;
4033 }
4034 l[i] = ' ';
4035 }
4036 }
4037 Hoption.Spec = TMath::Max(1600,bs);
4038 return 1;
4039 }
4040
4041 l = strstr(chopt,"GL");
4042 if (l) {
4043 memcpy(l," ",2);
4044 }
4045 l = strstr(chopt,"X+");
4046 if (l) {
4047 Hoption.AxisPos = 10;
4048 memcpy(l," ",2);
4049 }
4050 l = strstr(chopt,"Y+");
4051 if (l) {
4052 Hoption.AxisPos += 1;
4053 memcpy(l," ",2);
4054 }
4055 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4056 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4057
4058 l = strstr(chopt,"SAMES");
4059 if (l) {
4060 if (nch == 5) Hoption.Hist = 1;
4061 Hoption.Same = 2;
4062 memcpy(l," ",5);
4063 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4064 }
4065 l = strstr(chopt,"SAME");
4066 if (l) {
4067 if (nch == 4) Hoption.Hist = 1;
4068 Hoption.Same = 1;
4069 memcpy(l," ",4);
4070 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4071 }
4072
4073 l = strstr(chopt,"PIE");
4074 if (l) {
4075 Hoption.Pie = 1;
4076 memcpy(l," ",3);
4077 }
4078
4079
4080 l = strstr(chopt,"CANDLE");
4081 if (l) {
4082 TCandle candle;
4083 Hoption.Candle = candle.ParseOption(l);
4084 Hoption.Scat = 0;
4085 }
4086
4087 l = strstr(chopt,"VIOLIN");
4088 if (l) {
4089 TCandle candle;
4090 Hoption.Candle = candle.ParseOption(l);
4091 Hoption.Scat = 0;
4092 }
4093
4094 l = strstr(chopt,"LEGO");
4095 if (l) {
4096 Hoption.Scat = 0;
4097 Hoption.Lego = 1; memcpy(l," ",4);
4098 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4099 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4100 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4101 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4102 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4103 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4104 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4105 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4106 }
4107
4108 l = strstr(chopt,"SURF");
4109 if (l) {
4110 Hoption.Scat = 0;
4111 Hoption.Surf = 1; memcpy(l," ",4);
4112 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4113 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4114 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4115 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4116 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4117 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4118 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4119 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4120 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4121 }
4122
4123 l = strstr(chopt,"TF3");
4124 if (l) {
4125 memcpy(l," ",3);
4126 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4127 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4128 }
4129
4130 l = strstr(chopt,"ISO");
4131 if (l) {
4132 memcpy(l," ",3);
4133 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4134 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4135 }
4136
4137 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4138
4139 l = strstr(chopt,"CONT");
4140 if (l) {
4141 memcpy(l," ",4);
4142 if (hdim>1) {
4143 Hoption.Scat = 0;
4144 Hoption.Contour = 1;
4145 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4146 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4147 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4148 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4149 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4150 } else {
4151 Hoption.Hist = 1;
4152 }
4153 }
4154 l = strstr(chopt,"HBAR");
4155 if (l) {
4156 Hoption.Hist = 0;
4157 Hoption.Bar = 20; memcpy(l," ",4);
4158 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4159 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4160 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4161 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4162 }
4163 l = strstr(chopt,"BAR");
4164 if (l) {
4165 Hoption.Hist = 0;
4166 Hoption.Bar = 10; memcpy(l," ",3);
4167 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4168 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4169 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4170 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4171 }
4172
4173 l = strstr(chopt,"ARR" );
4174 if (l) {
4175 memcpy(l," ", 3);
4176 if (hdim>1) {
4177 Hoption.Arrow = 1;
4178 Hoption.Scat = 0;
4179 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4180 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4181 } else {
4182 Hoption.Hist = 1;
4183 }
4184 }
4185 l = strstr(chopt,"BOX" );
4186 if (l) {
4187 memcpy(l," ", 3);
4188 if (hdim>1) {
4189 Hoption.Scat = 0;
4190 Hoption.Box = 1;
4191 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4192 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4193 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4194 } else {
4195 Hoption.Hist = 1;
4196 }
4197 }
4198 l = strstr(chopt,"COLZ");
4199 if (l) {
4200 memcpy(l," ",4);
4201 if (hdim>1) {
4202 Hoption.Color = 1;
4203 Hoption.Scat = 0;
4204 Hoption.Zscale = 1;
4205 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4206 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4207 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4208 } else {
4209 Hoption.Hist = 1;
4210 }
4211 }
4212 l = strstr(chopt,"COL" );
4213 if (l) {
4214 memcpy(l," ", 3);
4215 if (hdim>1) {
4216 Hoption.Color = 1;
4217 Hoption.Scat = 0;
4218 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4219 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4220 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4221 } else {
4222 Hoption.Hist = 1;
4223 }
4224 }
4225 l = strstr(chopt,"CHAR"); if (l) { Hoption.Char = 1; memcpy(l," ",4); Hoption.Scat = 0; }
4226 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4227 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4228 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4229 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4230 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4231 l = strstr(chopt,"TEXT");
4232 if (l) {
4233 Int_t angle;
4234 if (sscanf(&l[4],"%d",&angle) > 0) {
4235 if (angle < 0) angle=0;
4236 if (angle > 90) angle=90;
4237 Hoption.Text = 1000+angle;
4238 } else {
4239 Hoption.Text = 1;
4240 }
4241 memcpy(l," ", 4);
4242 l = strstr(chopt,"N");
4243 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
4244 Hoption.Scat = 0;
4245 }
4246 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4247 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4248 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4249 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4250
4251 l = strstr(chopt,"TRI");
4252 if (l) {
4253 Hoption.Scat = 0;
4254 Hoption.Color = 0;
4255 Hoption.Tri = 1; memcpy(l," ",3);
4256 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4257 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4258 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4259 }
4260
4261 l = strstr(chopt,"AITOFF");
4262 if (l) {
4263 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4264 }
4265 l = strstr(chopt,"MERCATOR");
4266 if (l) {
4267 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4268 }
4269 l = strstr(chopt,"SINUSOIDAL");
4270 if (l) {
4271 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4272 }
4273 l = strstr(chopt,"PARABOLIC");
4274 if (l) {
4275 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4276 }
4277 if (Hoption.Proj > 0) {
4278 Hoption.Scat = 0;
4279 Hoption.Contour = 14;
4280 }
4281
4282 if (strstr(chopt,"A")) Hoption.Axis = -1;
4283 if (strstr(chopt,"B")) Hoption.Bar = 1;
4284 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4285 if (strstr(chopt,"F")) Hoption.Fill =1;
4286 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4287 if (strstr(chopt,"F2")) Hoption.Fill =2;
4288 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4289 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4290 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4291 if (strstr(chopt,"*")) Hoption.Star =1;
4292 if (strstr(chopt,"H")) Hoption.Hist =2;
4293 if (strstr(chopt,"P0")) Hoption.Mark =10;
4294
4295 if (fH->InheritsFrom(TH2Poly::Class())) {
4297 }
4298
4299 if (strstr(chopt,"E")) {
4300 if (hdim == 1) {
4301 Hoption.Error = 1;
4302 if (strstr(chopt,"E1")) Hoption.Error = 11;
4303 if (strstr(chopt,"E2")) Hoption.Error = 12;
4304 if (strstr(chopt,"E3")) Hoption.Error = 13;
4305 if (strstr(chopt,"E4")) Hoption.Error = 14;
4306 if (strstr(chopt,"E5")) Hoption.Error = 15;
4307 if (strstr(chopt,"E6")) Hoption.Error = 16;
4308 if (strstr(chopt,"E0")) Hoption.Error += 40;
4309 if (strstr(chopt,"X0")) {
4310 if (Hoption.Error == 1) Hoption.Error += 20;
4311 Hoption.Error += 10;
4312 }
4313 if (Hoption.Text && fH->InheritsFrom(TProfile::Class())) {
4314 Hoption.Text += 2000;
4315 Hoption.Error = 0;
4316 }
4317 } else {
4318 if (Hoption.Error == 0) {
4319 Hoption.Error = 100;
4320 Hoption.Scat = 0;
4321 }
4322 if (Hoption.Text) {
4323 Hoption.Text += 2000;
4324 Hoption.Error = 0;
4325 }
4326 }
4327 }
4328
4329 if (Hoption.Surf == 15) {
4331 Hoption.Surf = 13;
4332 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4333 }
4334 }
4335
4336 // Copy options from current style
4337 Hoption.Logx = gPad->GetLogx();
4338 Hoption.Logy = gPad->GetLogy();
4339 Hoption.Logz = gPad->GetLogz();
4340
4341 // Check options incompatibilities
4342 if (Hoption.Bar == 1) Hoption.Hist = -1;
4343 return 1;
4344}
4345
4346////////////////////////////////////////////////////////////////////////////////
4347/// Decode string `choptin` and fill Graphical cuts structure.
4348
4350{
4351
4352 fNcuts = 0;
4353 char *left = (char*)strchr(choptin,'[');
4354 if (!left) return 0;
4355 char *right = (char*)strchr(choptin,']');
4356 if (!right) return 0;
4357 Int_t nch = right-left;
4358 if (nch < 2) return 0;
4359 char *cuts = left+1;
4360 *right = 0;
4361 char *comma, *minus;
4362 Int_t i;
4363 while (1) {
4364 comma = strchr(cuts,',');
4365 if (comma) *comma = 0;
4366 minus = strchr(cuts,'-');
4367 if (minus) cuts = minus+1;
4368 while (*cuts == ' ') cuts++;
4369 Int_t nc = strlen(cuts);
4370 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4371 TIter next(gROOT->GetListOfSpecials());
4372 TCutG *cut=0;
4373 TObject *obj;
4374 while ((obj = next())) {
4375 if (!obj->InheritsFrom(TCutG::Class())) continue;
4376 if (strcmp(obj->GetName(),cuts)) continue;
4377 cut = (TCutG*)obj;
4378 break;
4379 }
4380 if (cut) {
4381 fCuts[fNcuts] = cut;
4382 fCutsOpt[fNcuts] = 1;
4383 if (minus) fCutsOpt[fNcuts] = -1;
4384 fNcuts++;
4385 }
4386 if (!comma) break;
4387 cuts = comma+1;
4388 }
4389 for (i=0;i<=nch;i++) left[i] = ' ';
4390 return fNcuts;
4391}
4392
4393////////////////////////////////////////////////////////////////////////////////
4394/// [Control routine to paint any kind of histograms](#HP00)
4395
4397{
4398
4399 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4400
4401 //For iOS: put the histogram on the top of stack of pickable objects.
4402 const TPickerStackGuard topPush(fH);
4403
4404 gPad->SetVertical(kTRUE);
4405
4406 TH1 *oldhist = gCurrentHist;
4407 gCurrentHist = fH;
4408 TH1 *hsave = fH;
4409 Double_t minsav = fH->GetMinimumStored();
4410
4411 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4412
4413 // Paint using TSpectrum2Painter
4414 if (Hoption.Spec) {
4415 if (!TableInit()) return;
4416 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4417 gROOT->ProcessLineFast(Form("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%lx,\"%s\",%d)",
4418 (ULong_t)fH, option, Hoption.Spec));
4419 return;
4420 }
4421
4422 if (Hoption.Pie) {
4423 if (fH->GetDimension() == 1) {
4424 if (!fPie) fPie = new TPie(fH);
4425 fPie->Paint(option);
4426 } else {
4427 Error("Paint", "Option PIE is for 1D histograms only");
4428 }
4429 return;
4430 } else {
4431 if (fPie) delete fPie;
4432 fPie = 0;
4433 }
4434
4435 fXbuf = new Double_t[kNMAX];
4436 fYbuf = new Double_t[kNMAX];
4437 if (fH->GetDimension() > 2) {
4438 PaintH3(option);
4439 fH->SetMinimum(minsav);
4440 if (Hoption.Func) {
4441 Hoption_t hoptsave = Hoption;
4442 Hparam_t hparsave = Hparam;
4443 PaintFunction(option);
4444 SetHistogram(hsave);
4445 Hoption = hoptsave;
4446 Hparam = hparsave;
4447 }
4448 gCurrentHist = oldhist;
4449 delete [] fXbuf; delete [] fYbuf;
4450 return;
4451 }
4452 TView *view = gPad->GetView();
4453 if (view) {
4454 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4455 delete view;
4456 gPad->SetView(0);
4457 }
4458 }
4459 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4460 // In case of 1D histogram, Z axis becomes Y axis.
4461 Int_t logysav=0, logzsav=0;
4462 if (fH->GetDimension() == 1) {
4463 logysav = Hoption.Logy;
4464 logzsav = Hoption.Logz;
4465 Hoption.Logz = 0;
4466 if (Hoption.Logy) {
4467 Hoption.Logz = 1;
4468 Hoption.Logy = 0;
4469 }
4470 }
4471 PaintTable(option);
4472 if (Hoption.Func) {
4473 Hoption_t hoptsave = Hoption;
4474 Hparam_t hparsave = Hparam;
4475 PaintFunction(option);
4476 SetHistogram(hsave);
4477 Hoption = hoptsave;
4478 Hparam = hparsave;
4479 }
4480 fH->SetMinimum(minsav);
4481 gCurrentHist = oldhist;
4482 delete [] fXbuf; delete [] fYbuf;
4483 if (fH->GetDimension() == 1) {
4484 Hoption.Logy = logysav;
4485 Hoption.Logz = logzsav;
4486 }
4487 return;
4488 }
4489
4490 if (Hoption.Bar >= 20) {
4491 PaintBarH(option);
4492 delete [] fXbuf; delete [] fYbuf;
4493 return;
4494 }
4495
4496 // fill Hparam structure with histo parameters
4497 if (!PaintInit()) {
4498 delete [] fXbuf; delete [] fYbuf;
4499 return;
4500 }
4501
4502 // Picture surround (if new page) and page number (if requested).
4503 // Histogram surround (if not option "Same").
4504 PaintFrame();
4505
4506 // Paint histogram axis only
4507 Bool_t gridx = gPad->GetGridx();
4508 Bool_t gridy = gPad->GetGridy();
4509 if (Hoption.Axis > 0) {
4510 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4511 else {
4512 if (gridx) gPad->SetGridx(0);
4513 if (gridy) gPad->SetGridy(0);
4515 if (gridx) gPad->SetGridx(1);
4516 if (gridy) gPad->SetGridy(1);
4517 }
4518 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4519 goto paintstat;
4520 }
4521 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4522
4523 // test for options BAR or HBAR
4524 if (Hoption.Bar >= 10) {
4525 PaintBar(option);
4526 }
4527
4528 // do not draw histogram if error bars required
4529 if (!Hoption.Error) {
4530 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4531 }
4532
4533 // test for error bars or option E
4534 if (Hoption.Error) {
4535 PaintErrors(option);
4536 if (Hoption.Hist == 2) PaintHist(option);
4537 }
4538
4539 if (Hoption.Text) PaintText(option);
4540
4541 // test for associated function
4542 if (Hoption.Func) {
4543 Hoption_t hoptsave = Hoption;
4544 Hparam_t hparsave = Hparam;
4545 PaintFunction(option);
4546 SetHistogram(hsave);
4547 Hoption = hoptsave;
4548 Hparam = hparsave;
4549 }
4550
4551 if (gridx) gPad->SetGridx(0);
4552 if (gridy) gPad->SetGridy(0);
4554 if (gridx) gPad->SetGridx(1);
4555 if (gridy) gPad->SetGridy(1);
4556
4557 PaintTitle(); // Draw histogram title
4558
4559 // Draw box with histogram statistics and/or fit parameters
4560paintstat:
4561 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4562 TIter next(fFunctions);
4563 TObject *obj = 0;
4564 while ((obj = next())) {
4565 if (obj->InheritsFrom(TF1::Class())) break;
4566 obj = 0;
4567 }
4568
4569 //Stat is painted twice (first, it will be in canvas' list of primitives),
4570 //second, it will be here, this is not required on iOS.
4571 //Condition is ALWAYS true on a platform different from iOS.
4572 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4573 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4574 }
4575 fH->SetMinimum(minsav);
4576 gCurrentHist = oldhist;
4577 delete [] fXbuf; fXbuf = 0;
4578 delete [] fYbuf; fYbuf = 0;
4579
4580}
4581
4582////////////////////////////////////////////////////////////////////////////////
4583/// [Control function to draw a table as an arrow plot](#HP12)
4584
4586{
4587 Double_t xk, xstep, yk, ystep;
4588 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4591 Double_t xrg = gPad->GetUxmin();
4592 Double_t yrg = gPad->GetUymin();
4593 Double_t xln = gPad->GetUxmax() - xrg;
4594 Double_t yln = gPad->GetUymax() - yrg;
4595 Double_t cx = (xln/Double_t(ncx) -0.03)/2;
4596 Double_t cy = (yln/Double_t(ncy) -0.03)/2;
4597 Double_t dn = 1.E-30;
4598
4599 auto arrow = new TArrow();
4600 arrow->SetAngle(30);
4601 arrow->SetFillStyle(1001);
4602 arrow->SetFillColor(fH->GetLineColor());
4603 arrow->SetLineColor(fH->GetLineColor());
4604 arrow->SetLineWidth(fH->GetLineWidth());
4605
4606 // Initialize the levels on the Z axis
4607 Int_t ncolors=0, ndivz=0;
4608 Double_t scale=0.;
4609 if (Hoption.Arrow>1) {
4610 ncolors = gStyle->GetNumberOfColors();
4611 Int_t ndiv = fH->GetContour();
4612 if (ndiv == 0 ) {
4613 ndiv = gStyle->GetNumberContours();
4614 fH->SetContour(ndiv);
4615 }
4616 ndivz = TMath::Abs(ndiv);
4617 if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
4618 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4619 }
4620
4621 for (Int_t id=1;id<=2;id++) {
4622 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4623 yk = fYaxis->GetBinLowEdge(j);
4624 ystep = fYaxis->GetBinWidth(j);
4625 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4626 xk = fXaxis->GetBinLowEdge(i);
4627 xstep = fXaxis->GetBinWidth(i);
4628 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4629 if (i == Hparam.xfirst) {
4630 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4631 } else if (i == Hparam.xlast) {
4632 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4633 } else {
4634 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4635 }
4636 if (j == Hparam.yfirst) {
4637 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4638 } else if (j == Hparam.ylast) {
4639 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4640 } else {
4641 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4642 }
4643 if (id == 1) {
4644 dn = TMath::Max(dn, TMath::Abs(dx));
4645 dn = TMath::Max(dn, TMath::Abs(dy));
4646 } else if (id == 2) {
4647 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4648 dxn = cx*dx/dn;
4649 x1 = xc - dxn;
4650 x2 = xc + dxn;
4651 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4652 dyn = cy*dy/dn;
4653 y1 = yc - dyn;
4654 y2 = yc + dyn;
4655 if (Hoption.Arrow>1) {
4656 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4657 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4658 if (theColor > ncolors-1) theColor = ncolors-1;
4659 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4660 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4661 }
4662 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4663 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4664 } else {
4665 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4666 }
4667 }
4668 }
4669 }
4670 }
4671
4673}
4674
4675////////////////////////////////////////////////////////////////////////////////
4676/// Draw axis (2D case) of an histogram.
4677///
4678/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4679/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4680/// feature is used to make sure that the grid is drawn in the background and
4681/// the axis tick marks in the foreground of the pad.
4682
4684{
4685
4686 //On iOS, grid should not be pickable and can not be highlighted.
4687 //Condition is never true on a platform different from iOS.
4688 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4689 return;
4690
4691 if (Hoption.Axis == -1) return;
4692 if (Hoption.Same && Hoption.Axis <= 0) return;
4693
4694 // Repainting alphanumeric labels axis on a plot done with
4695 // the option HBAR (horizontal) needs some adjustments.
4696 TAxis *xaxis = 0;
4697 TAxis *yaxis = 0;
4698 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4699 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4700 TIter next(gPad->GetListOfPrimitives());
4701 TObject *obj;
4702 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4703 while ((obj = next())) {
4704 if (!obj->InheritsFrom(TH1::Class()) &&
4705 !obj->InheritsFrom(THStack::Class())) continue;
4706 TString opt = obj->GetDrawOption();
4707 opt.ToLower();
4708 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4709 if (strstr(opt,"hbar")) {
4710 gPad->SetVertical(kFALSE);
4711 xaxis = fXaxis;
4712 yaxis = fYaxis;
4713 if (!strcmp(xaxis->GetName(),"xaxis")) {
4714 fXaxis = yaxis;
4715 fYaxis = xaxis;
4716 }
4717 }
4718 break;
4719 }
4720 }
4721 }
4722
4723 static char chopt[10] = "";
4724 Double_t gridl = 0;
4725 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4726 Int_t useHparam = 0;
4727 Double_t umin, umax, uminsave, umaxsave;
4728 Short_t xAxisPos = Hoption.AxisPos/10;
4729 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4730
4731 Double_t axmin = gPad->GetUxmin();
4732 Double_t axmax = gPad->GetUxmax();
4733 Double_t aymin = gPad->GetUymin();
4734 Double_t aymax = gPad->GetUymax();
4735 char *cw = 0;
4736 TGaxis axis;
4737
4738 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4739 // Hparam must be use for the axis limits.
4740 if (Hoption.Contour == 14) useHparam = 1;
4741 if (Hoption.Same) {
4742 TObject *obj;
4743 TIter next(gPad->GetListOfPrimitives());
4744 while ((obj=next())) {
4745 if (strstr(obj->GetDrawOption(),"cont4")) {
4746 useHparam = 1;
4747 break;
4748 }
4749 }
4750 }
4751
4752 // Paint X axis
4753
4754 //To make X-axis selectable on iOS device.
4755 if (gPad->PadInSelectionMode())
4756 gPad->PushSelectableObject(fXaxis);
4757
4758 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4759 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4760 ndivx = fXaxis->GetNdivisions();
4761 if (ndivx > 1000) {
4762 nx2 = ndivx/100;
4763 nx1 = TMath::Max(1, ndivx%100);
4764 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4765 }
4766 axis.SetTextAngle(0);
4768
4769 chopt[0] = 0;
4770 strlcat(chopt, "SDH",10);
4771 if (ndivx < 0) strlcat(chopt, "N",10);
4772 if (gPad->GetGridx()) {
4773 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4774 strlcat(chopt, "W",10);
4775 }
4776
4777 // Define X-Axis limits
4778 if (Hoption.Logx) {
4779 strlcat(chopt, "G",10);
4780 ndiv = TMath::Abs(ndivx);
4781 if (useHparam) {
4782 umin = TMath::Power(10,Hparam.xmin);
4783 umax = TMath::Power(10,Hparam.xmax);
4784 } else {
4785 umin = TMath::Power(10,axmin);
4786 umax = TMath::Power(10,axmax);
4787 }
4788 } else {
4789 ndiv = TMath::Abs(ndivx);
4790 if (useHparam) {
4791 umin = Hparam.xmin;
4792 umax = Hparam.xmax;
4793 } else {
4794 umin = axmin;
4795 umax = axmax;
4796 }
4797 }
4798
4799 // Display axis as time
4800 if (fXaxis->GetTimeDisplay()) {
4801 strlcat(chopt,"t",10);
4802 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4804 }
4805 }
4806
4807 // The main X axis can be on the bottom or on the top of the pad
4808 Double_t xAxisYPos1, xAxisYPos2;
4809 if (xAxisPos == 1) {
4810 // Main X axis top
4811 xAxisYPos1 = aymax;
4812 xAxisYPos2 = aymin;
4813 } else {
4814 // Main X axis bottom
4815 xAxisYPos1 = aymin;
4816 xAxisYPos2 = aymax;
4817 }
4818
4819 // Paint the main X axis (always)
4820 uminsave = umin;
4821 umaxsave = umax;
4822 ndivsave = ndiv;
4823 axis.SetOption(chopt);
4824 if (xAxisPos) {
4825 strlcat(chopt, "-",10);
4826 gridl = -gridl;
4827 }
4828 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4829 axis.SetLabelSize(0.);
4830 axis.SetTitle("");
4831 }
4832 axis.PaintAxis(axmin, xAxisYPos1,
4833 axmax, xAxisYPos1,
4834 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4835
4836 // Paint additional X axis (if needed)
4837 // On iOS, this additional X axis is neither pickable, nor highlighted.
4838 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4839 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4840 if (xAxisPos) {
4841 cw=strstr(chopt,"-");
4842 *cw='z';
4843 } else {
4844 strlcat(chopt, "-",10);
4845 }
4846 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4847 if ((cw=strstr(chopt,"W"))) *cw='z';
4848 axis.SetTitle("");
4849 axis.PaintAxis(axmin, xAxisYPos2,
4850 axmax, xAxisYPos2,
4851 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4852 }
4853 }//End of "if pad in selection mode etc".
4854
4855 // Paint Y axis
4856 //On iOS, Y axis must pushed into the stack of selectable objects.
4857 if (gPad->PadInSelectionMode())
4858 gPad->PushSelectableObject(fYaxis);
4859
4860 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4861 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4862 ndivy = fYaxis->GetNdivisions();
4864
4865 chopt[0] = 0;
4866 strlcat(chopt, "SDH",10);
4867 if (ndivy < 0) strlcat(chopt, "N",10);
4868 if (gPad->GetGridy()) {
4869 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4870 strlcat(chopt, "W",10);
4871 }
4872
4873 // Define Y-Axis limits
4874 if (Hoption.Logy) {
4875 strlcat(chopt, "G",10);
4876 ndiv = TMath::Abs(ndivy);
4877 if (useHparam) {
4878 umin = TMath::Power(10,Hparam.ymin);
4879 umax = TMath::Power(10,Hparam.ymax);
4880 } else {
4881 umin = TMath::Power(10,aymin);
4882 umax = TMath::Power(10,aymax);
4883 }
4884 } else {
4885 ndiv = TMath::Abs(ndivy);
4886 if (useHparam) {
4887 umin = Hparam.ymin;
4888 umax = Hparam.ymax;
4889 } else {
4890 umin = aymin;
4891 umax = aymax;
4892 }
4893 }
4894
4895 // Display axis as time
4896 if (fYaxis->GetTimeDisplay()) {
4897 strlcat(chopt,"t",10);
4898 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4900 }
4901 }
4902
4903 // The main Y axis can be on the left or on the right of the pad
4904 Double_t yAxisXPos1, yAxisXPos2;
4905 if (yAxisPos == 1) {
4906 // Main Y axis left
4907 yAxisXPos1 = axmax;
4908 yAxisXPos2 = axmin;
4909 } else {
4910 // Main Y axis right
4911 yAxisXPos1 = axmin;
4912 yAxisXPos2 = axmax;
4913 }
4914
4915 // Paint the main Y axis (always)
4916 uminsave = umin;
4917 umaxsave = umax;
4918 ndivsave = ndiv;
4919 axis.SetOption(chopt);
4920 if (yAxisPos) {
4921 strlcat(chopt, "+L",10);
4922 gridl = -gridl;
4923 }
4924 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4925 axis.SetLabelSize(0.);
4926 axis.SetTitle("");
4927 }
4928 axis.PaintAxis(yAxisXPos1, aymin,
4929 yAxisXPos1, aymax,
4930 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4931
4932 // Paint the additional Y axis (if needed)
4933 // Additional checks for pad mode are required on iOS: this "second" axis is
4934 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
4935 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4936 if (gPad->GetTicky() < 2) {
4937 strlcat(chopt, "U",10);
4939 } else {
4940 strlcat(chopt, "+L",10);
4941 }
4942 if ((cw=strstr(chopt,"W"))) *cw='z';
4943 axis.SetTitle("");
4944 axis.PaintAxis(yAxisXPos2, aymin,
4945 yAxisXPos2, aymax,
4946 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4947 }
4948 }//End of "if pad is in selection mode etc."
4949
4950 // Reset the axis if they have been inverted in case of option HBAR
4951 if (xaxis) {
4952 fXaxis = xaxis;
4953 fYaxis = yaxis;
4954 }
4955}
4956
4957////////////////////////////////////////////////////////////////////////////////
4958/// [Draw a bar-chart in a normal pad.](#HP10)
4959
4961{
4962
4963 Int_t bar = Hoption.Bar - 10;
4964 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
4965 Double_t offset = fH->GetBarOffset();
4967 TBox box;
4968 Int_t hcolor = fH->GetFillColor();
4969 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
4970 Int_t hstyle = fH->GetFillStyle();
4971 box.SetFillColor(hcolor);
4972 box.SetFillStyle(hstyle);
4973 box.SetLineStyle(fH->GetLineStyle());
4974 box.SetLineColor(fH->GetLineColor());
4975 box.SetLineWidth(fH->GetLineWidth());
4976 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
4977 y = fH->GetBinContent(bin);
4978 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
4979 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
4980 ymin = gPad->GetUymin();
4981 ymax = gPad->YtoPad(y);
4982 if (ymax < gPad->GetUymin()) continue;
4983 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
4984 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
4985 if (Hoption.MinimumZero && ymin < 0)
4986 ymin=TMath::Min(0.,gPad->GetUymax());
4987 w = (xmax-xmin)*width;
4988 xmin += offset*(xmax-xmin);
4989 xmax = xmin + w;
4990 if (bar < 1) {
4991 box.PaintBox(xmin,ymin,xmax,ymax);
4992 } else {
4993 umin = xmin + bar*(xmax-xmin)/10.;
4994 umax = xmax - bar*(xmax-xmin)/10.;
4995 //box.SetFillColor(hcolor+150); //bright
4996 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
4997 box.PaintBox(xmin,ymin,umin,ymax);
4998 box.SetFillColor(hcolor);
4999 box.PaintBox(umin,ymin,umax,ymax);
5000 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5001 box.PaintBox(umax,ymin,xmax,ymax);
5002 }
5003 }
5004}
5005
5006////////////////////////////////////////////////////////////////////////////////
5007/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](#HP10)
5008
5010{
5011
5012 gPad->SetVertical(kFALSE);
5013
5014 PaintInitH();
5015
5016 TAxis *xaxis = fXaxis;
5017 TAxis *yaxis = fYaxis;
5018 if (!strcmp(xaxis->GetName(),"xaxis")) {
5019 fXaxis = yaxis;
5020 fYaxis = xaxis;
5021 }
5022
5023 PaintFrame();
5025
5026 Int_t bar = Hoption.Bar - 20;
5027 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5028 Double_t offset = fH->GetBarOffset();
5030 TBox box;
5031 Int_t hcolor = fH->GetFillColor();
5032 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5033 Int_t hstyle = fH->GetFillStyle();
5034 box.SetFillColor(hcolor);
5035 box.SetFillStyle(hstyle);
5036 box.SetLineStyle(fH->GetLineStyle());
5037 box.SetLineColor(fH->GetLineColor());
5038 box.SetLineWidth(fH->GetLineWidth());
5039 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5040 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5041 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5042 xmin = gPad->GetUxmin();
5043 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5044 if (xmax < gPad->GetUxmin()) continue;
5045 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5046 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5047 if (Hoption.MinimumZero && xmin < 0)
5048 xmin=TMath::Min(0.,gPad->GetUxmax());
5049 w = (ymax-ymin)*width;
5050 ymin += offset*(ymax-ymin);
5051 ymax = ymin + w;
5052 if (bar < 1) {
5053 box.PaintBox(xmin,ymin,xmax,ymax);
5054 } else {
5055 umin = ymin + bar*(ymax-ymin)/10.;
5056 umax = ymax - bar*(ymax-ymin)/10.;
5057 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5058 box.PaintBox(xmin,ymin,xmax,umin);
5059 box.SetFillColor(hcolor);
5060 box.PaintBox(xmin,umin,xmax,umax);
5061 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5062 box.PaintBox(xmin,umax,xmax,ymax);
5063 }
5064 }
5065
5066 PaintTitle();
5067
5068 // Draw box with histogram statistics and/or fit parameters
5069 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5070 TIter next(fFunctions);
5071 TObject *obj = 0;
5072 while ((obj = next())) {
5073 if (obj->InheritsFrom(TF1::Class())) break;
5074 obj = 0;
5075 }
5076 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5077 }
5078
5079 fXaxis = xaxis;
5080 fYaxis = yaxis;
5081}
5082
5083////////////////////////////////////////////////////////////////////////////////
5084/// [Control function to draw a 2D histogram as a box plot](#HP13)
5085
5087{
5088
5089 Style_t fillsav = fH->GetFillStyle();
5090 Style_t colsav = fH->GetFillColor();
5091 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5092 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5093 fH->TAttLine::Modify();
5094 fH->TAttFill::Modify();
5095
5096 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5097 Double_t ux1 = gPad->PixeltoX(1);
5098 Double_t ux0 = gPad->PixeltoX(0);
5099 Double_t uy1 = gPad->PixeltoY(1);
5100 Double_t uy0 = gPad->PixeltoY(0);
5101 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5102 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5103
5104 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5107 Double_t zminlin = zmin, zmaxlin = zmax;
5108
5109 // In case of option SAME, zmin and zmax values are taken from the
5110 // first plotted 2D histogram.
5111 if (Hoption.Same > 0 && Hoption.Same < 10) {
5112 TH2 *h2;
5113 TIter next(gPad->GetListOfPrimitives());
5114 while ((h2 = (TH2 *)next())) {
5115 if (!h2->InheritsFrom(TH2::Class())) continue;
5116 zmin = TMath::Max(h2->GetMinimum(), 0.);
5117 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5118 TMath::Abs(h2->GetMinimum()));
5119 zminlin = zmin;
5120 zmaxlin = zmax;
5121 if (Hoption.Logz) {
5122 if (zmin <= 0) {
5123 zmin = TMath::Log10(zmax*0.001);
5124 } else {
5125 zmin = TMath::Log10(zmin);
5126 }
5127 zmax = TMath::Log10(zmax);
5128 }
5129 break;
5130 }
5131 } else {
5132 if (Hoption.Logz) {
5133 if (zmin > 0) {
5134 zmin = TMath::Log10(zmin);
5135 zmax = TMath::Log10(zmax);
5136 } else {
5137 return;
5138 }
5139 }
5140 }
5141
5142 Double_t zratio, dz = zmax - zmin;
5143 Bool_t kZminNeg = kFALSE;
5144 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5145 Bool_t kZNeg = kFALSE;
5146
5147 // Define the dark and light colors the "button style" boxes.
5148 Color_t color = fH->GetFillColor();
5149 Color_t light=0, dark=0;
5150 if (Hoption.Box == 11) {
5151 light = TColor::GetColorBright(color);
5152 dark = TColor::GetColorDark(color);
5153 }
5154
5155 // Loop over all the bins and draw the boxes
5156 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5157 yk = fYaxis->GetBinLowEdge(j);
5158 ystep = fYaxis->GetBinWidth(j);
5159 ycent = 0.5*ystep;
5160 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5161 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5162 xk = fXaxis->GetBinLowEdge(i);
5163 xstep = fXaxis->GetBinWidth(i);
5164 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5165 xcent = 0.5*xstep;
5166 z = Hparam.factor*fH->GetBinContent(bin);
5167 kZNeg = kFALSE;
5168
5169 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5170 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5171 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with netgative bins.
5172
5173 if (z < 0) {
5174 if (Hoption.Logz) continue;
5175 z = -z;
5176 kZNeg = kTRUE;
5177 }
5178 if (Hoption.Logz) {
5179 if (z != 0) z = TMath::Log10(z);
5180 else z = zmin;
5181 }
5182
5183 if (dz == 0) continue;
5184 zratio = TMath::Sqrt((z-zmin)/dz);
5185 if (zratio == 0) continue;
5186
5187 xup = xcent*zratio + xk + xcent;
5188 xlow = 2*(xk + xcent) - xup;
5189 if (xup-xlow < dxmin) xup = xlow+dxmin;
5190 if (Hoption.Logx) {
5191 if (xup > 0) xup = TMath::Log10(xup);
5192 else continue;
5193 if (xlow > 0) xlow = TMath::Log10(xlow);
5194 else continue;
5195 }
5196
5197 yup = ycent*zratio + yk + ycent;
5198 ylow = 2*(yk + ycent) - yup;
5199 if (yup-ylow < dymin) yup = ylow+dymin;
5200 if (Hoption.Logy) {
5201 if (yup > 0) yup = TMath::Log10(yup);
5202 else continue;
5203 if (ylow > 0) ylow = TMath::Log10(ylow);
5204 else continue;
5205 }
5206
5207 xlow = TMath::Max(xlow, gPad->GetUxmin());
5208 ylow = TMath::Max(ylow, gPad->GetUymin());
5209 xup = TMath::Min(xup , gPad->GetUxmax());
5210 yup = TMath::Min(yup , gPad->GetUymax());
5211
5212 if (xlow >= xup) continue;
5213 if (ylow >= yup) continue;
5214
5215 if (Hoption.Box == 1) {
5216 fH->SetFillColor(color);
5217 fH->TAttFill::Modify();
5218 gPad->PaintBox(xlow, ylow, xup, yup);
5219 if (kZNeg) {
5220 gPad->PaintLine(xlow, ylow, xup, yup);
5221 gPad->PaintLine(xlow, yup, xup, ylow);
5222 }
5223 } else if (Hoption.Box == 11) {
5224 // Draw the center of the box
5225 fH->SetFillColor(color);
5226 fH->TAttFill::Modify();
5227 gPad->PaintBox(xlow, ylow, xup, yup);
5228
5229 // Draw top&left part of the box
5230 Double_t x[7], y[7];
5231 Double_t bwidth = 0.1;
5232 x[0] = xlow; y[0] = ylow;
5233 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5234 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5235 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5236 x[4] = xup; y[4] = yup;
5237 x[5] = xlow; y[5] = yup;
5238 x[6] = xlow; y[6] = ylow;
5239 if (kZNeg) fH->SetFillColor(dark);
5240 else fH->SetFillColor(light);
5241 fH->TAttFill::Modify();
5242 gPad->PaintFillArea(7, x, y);
5243
5244 // Draw bottom&right part of the box
5245 x[0] = xlow; y[0] = ylow;
5246 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5247 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5248 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5249 x[4] = xup; y[4] = yup;
5250 x[5] = xup; y[5] = ylow;
5251 x[6] = xlow; y[6] = ylow;
5252 if (kZNeg) fH->SetFillColor(light);
5253 else fH->SetFillColor(dark);
5254 fH->TAttFill::Modify();
5255 gPad->PaintFillArea(7, x, y);
5256 }
5257 }
5258 }
5259
5261 fH->SetFillStyle(fillsav);
5262 fH->SetFillColor(colsav);
5263 fH->TAttFill::Modify();
5264}
5265
5266
5267
5268////////////////////////////////////////////////////////////////////////////////
5269/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](#HP14)
5270
5272{
5273 TH1D *hproj;
5274 TH2D *h2 = (TH2D*)fH;
5275
5276 TCandle myCandle;
5278 myCandle.SetMarkerColor(fH->GetLineColor());
5279 myCandle.SetLineColor(fH->GetLineColor());
5280 myCandle.SetLineWidth(fH->GetLineWidth());
5281 myCandle.SetFillColor(fH->GetFillColor());
5282 myCandle.SetFillStyle(fH->GetFillStyle());
5283 myCandle.SetMarkerSize(fH->GetMarkerSize());
5284 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5286
5287 Bool_t swapXY = myCandle.IsHorizontal();
5288 const Double_t standardCandleWidth = 0.66;
5289 const Double_t standardHistoWidth = 0.8;
5290
5291 double allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5292 double allMaxIntegral = 0;
5293
5294 if (!swapXY) { // Vertical candle
5295 //Determining the slice with the maximum content
5296 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5297 hproj = h2->ProjectionY("_px", i, i);
5298 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5299 }
5300 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5301 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5302 Double_t binWidth = fXaxis->GetBinWidth(i);
5303 hproj = h2->ProjectionY("_px", i, i);
5304 if (hproj->GetEntries() !=0) {
5305 Double_t candleWidth = fH->GetBarWidth();
5306 Double_t offset = fH->GetBarOffset()*binWidth;
5307 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5308 double myIntegral = hproj->Integral();
5309 Double_t histoWidth = candleWidth;
5310 if (candleWidth > 0.999 && candleWidth < 1.001) {
5311 candleWidth = standardCandleWidth;
5312 histoWidth = standardHistoWidth;
5313 }
5314 if (Hoption.Logz && myMaxContent > 0) {
5315 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5316 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0) histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5317 } else if (myCandle.IsViolinScaled()) histoWidth *= myMaxContent/allMaxContent;
5318 if (myCandle.IsCandleScaled()) candleWidth *= myIntegral/allMaxIntegral;
5319
5320 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5321 myCandle.SetCandleWidth(candleWidth*binWidth);
5322 myCandle.SetHistoWidth(histoWidth*binWidth);
5323 myCandle.SetHistogram(hproj);
5324 myCandle.Paint();
5325 }
5326 }
5327 } else { // Horizontal candle
5328 //Determining the slice with the maximum content
5329 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5330 hproj = h2->ProjectionX("_py", i, i);
5331 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5332 }
5333 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5334 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5335 Double_t binWidth = fYaxis->GetBinWidth(i);
5336 hproj = h2->ProjectionX("_py", i, i);
5337 if (hproj->GetEntries() !=0) {
5338 Double_t candleWidth = fH->GetBarWidth();
5339 Double_t offset = fH->GetBarOffset()*binWidth;
5340 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5341 double myIntegral = hproj->Integral();
5342 Double_t histoWidth = candleWidth;
5343 if (candleWidth > 0.999 && candleWidth < 1.001) {
5344 candleWidth = standardCandleWidth;
5345 histoWidth = standardHistoWidth;
5346 }
5347 if (Hoption.Logz && myMaxContent > 0) {
5348 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5349 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0) histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5350 } else if (myCandle.IsViolinScaled()) histoWidth *= myMaxContent/allMaxContent;
5351 if (myCandle.IsCandleScaled()) candleWidth *= myIntegral/allMaxIntegral;
5352
5353 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5354 myCandle.SetCandleWidth(candleWidth*binWidth);
5355 myCandle.SetHistoWidth(histoWidth*binWidth);
5356 myCandle.SetHistogram(hproj);
5357 myCandle.Paint();
5358 }
5359 }
5360 }
5361}
5362
5363
5364
5365////////////////////////////////////////////////////////////////////////////////
5366/// Returns the rendering regions for an axis to use in the COL2 option
5367///
5368/// The algorithm analyses the size of the axis compared to the size of
5369/// the rendering region. It figures out the boundaries to use for each color
5370/// of the rendering region. Only one axis is computed here.
5371///
5372/// This allows for a single computation of the boundaries before iterating
5373/// through all of the bins.
5374///
5375/// \param pAxis the axis to consider
5376/// \param nPixels the number of pixels to render axis into
5377/// \param isLog whether the axis is log scale
5378
5379std::vector<THistRenderingRegion>
5381{
5382 std::vector<THistRenderingRegion> regions;
5383
5384 enum STRATEGY { Bins, Pixels } strategy;
5385
5386 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5387
5388 if (nBins >= nPixels) {
5389 // more bins than pixels... we should loop over pixels and sample
5390 strategy = Pixels;
5391 } else {
5392 // fewer bins than pixels... we should loop over bins
5393 strategy = Bins;
5394 }
5395
5396 if (isLog) {
5397
5398 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5399 Int_t binOffset=0;
5400 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5401 binOffset++;
5402 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5403 }
5404 if (xMin <= 0) {
5405 // this should cause an error if we have
5406 return regions;
5407 }
5408 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5409
5410 if (strategy == Bins) {
5411 // logarithmic plot. we find the pixel for the bin
5412 // pixel = eta * log10(V) - alpha
5413 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5414 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5415 // and V is axis value
5416 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5417 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5418
5419 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5420
5421 // linear plot. we simply need to find the appropriate bin
5422 // for the
5423 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5424 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5425 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5426 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5427 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5428 std::make_pair(bin, bin+1)};
5429 regions.push_back(region);
5430 }
5431
5432 } else {
5433
5434 // loop over pixels
5435
5436 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5437
5438 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5439 // linear plot
5440 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5441 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5442 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5443 std::make_pair(binLow, binHigh)};
5444 regions.push_back(region);
5445 }
5446 }
5447 } else {
5448 // standard linear plot
5449
5450 if (strategy == Bins) {
5451 // loop over bins
5452 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5453
5454 // linear plot. we simply need to find the appropriate bin
5455 // for the
5456 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5457 Int_t xPx1 = xPx0 + nPixels/nBins;
5458
5459 // make sure we don't compute beyond our bounds
5460 if (xPx1>= nPixels) xPx1 = nPixels-1;
5461
5462 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5463 std::make_pair(bin, bin+1)};
5464 regions.push_back(region);
5465 }
5466 } else {
5467 // loop over pixels
5468 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5469 // linear plot
5470 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5471 Int_t binHigh = binLow + nBins/nPixels;
5472 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5473 std::make_pair(binLow, binHigh)};
5474 regions.push_back(region);
5475 }
5476 }
5477 }
5478
5479 return regions;
5480}
5481
5482////////////////////////////////////////////////////////////////////////////////
5483/// [Rendering scheme for the COL2 and COLZ2 options] (#HP14)
5484
5486{
5487
5488 if (Hoption.System != kCARTESIAN) {
5489 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5490 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5491 PaintColorLevels(nullptr);
5492 return;
5493 }
5494
5495 Double_t z;
5496
5497 // Use existing max or min values. If either is already set
5498 // the appropriate value to use.
5499 Double_t zmin = fH->GetMinimumStored();
5500 Double_t zmax = fH->GetMaximumStored();
5501 Double_t originalZMin = zmin;
5502 Double_t originalZMax = zmax;
5503 if ((zmin == -1111) && (zmax == -1111)) {
5504 fH->GetMinimumAndMaximum(zmin, zmax);
5505 fH->SetMinimum(zmin);
5506 fH->SetMaximum(zmax);
5507 } else if (zmin == -1111) {
5508 zmin = fH->GetMinimum();
5509 fH->SetMinimum(zmin);
5510 } else if (zmax == -1111) {
5511 zmax = fH->GetMaximum();
5512 fH->SetMaximum(zmax);
5513 }
5514
5515 Double_t dz = zmax - zmin;
5516 if (dz <= 0) { // Histogram filled with a constant value
5517 zmax += 0.1*TMath::Abs(zmax);
5518 zmin -= 0.1*TMath::Abs(zmin);
5519 dz = zmax - zmin;
5520 }
5521
5522 if (Hoption.Logz) {
5523 if (zmin > 0) {
5524 zmin = TMath::Log10(zmin);
5525 zmax = TMath::Log10(zmax);
5526 dz = zmax - zmin;
5527 } else {
5528 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5529 "Cannot plot logz because bin content is less than 0.");
5530 return;
5531 }
5532 }
5533
5534 // Initialize the levels on the Z axis
5535 Int_t ndiv = fH->GetContour();
5536 if (ndiv == 0 ) {
5537 ndiv = gStyle->GetNumberContours();
5538 fH->SetContour(ndiv);
5539 }
5540 std::vector<Double_t> colorBounds(ndiv);
5541 std::vector<Double_t> contours(ndiv, 0);
5542 if (fH->TestBit(TH1::kUserContour) == 0) {
5543 fH->SetContour(ndiv);
5544 } else {
5545 fH->GetContour(contours.data());
5546 }
5547
5548 Double_t step = 1.0/ndiv;
5549 for (Int_t i=0; i<ndiv; ++i) {
5550 colorBounds[i] = step*i;
5551 }
5552
5553 auto pFrame = gPad->GetFrame();
5554 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5555 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5556 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5557 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5558 Int_t nXPixels = px1-px0;
5559 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5560
5561 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5562
5563 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5564 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5565 if (xRegions.size() == 0 || yRegions.size() == 0) {
5566 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5567 "Encountered error while computing rendering regions.");
5568 return;
5569 }
5570
5571 Bool_t minExists = kFALSE;
5572 Bool_t maxExists = kFALSE;
5573 Double_t minValue = 1.;
5574 Double_t maxValue = 0.;
5575 for (auto& yRegion : yRegions) {
5576 for (auto& xRegion : xRegions ) {
5577
5578 const auto& xBinRange = xRegion.fBinRange;
5579 const auto& yBinRange = yRegion.fBinRange;
5580
5581 // sample the range
5582 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5583
5584 if (Hoption.Logz) {
5585 if (z > 0) z = TMath::Log10(z);
5586 else z = zmin;
5587 }
5588
5589 // obey the user's max and min values if they were set
5590 if (z > zmax) z = zmax;
5591 if (z < zmin) z = zmin;
5592
5593 if (fH->TestBit(TH1::kUserContour) == 1) {
5594 // contours are absolute values
5595 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5596 z = colorBounds[index];
5597 } else {
5598 Int_t index = 0;
5599 if (dz != 0) {
5600 index = 0.001 + ((z - zmin)/dz)*ndiv;
5601 }
5602
5603 if (index == static_cast<Int_t>(colorBounds.size())) {
5604 index--;
5605 }
5606
5607 // Do a little bookkeeping to use later for getting libAfterImage to produce
5608 // the correct colors
5609 if (index == 0) {
5610 minExists = kTRUE;
5611 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5612 maxExists = kTRUE;
5613 }
5614
5615 z = colorBounds[index];
5616
5617 if (z < minValue) {
5618 minValue = z;
5619 }
5620 if (z > maxValue) {
5621 maxValue = z;
5622 }
5623 }
5624
5625 // fill in the actual pixels
5626 const auto& xPixelRange = xRegion.fPixelRange;
5627 const auto& yPixelRange = yRegion.fPixelRange;
5628 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5629 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5630 Int_t pixel = yPx*nXPixels + xPx;
5631 buffer[pixel] = z;
5632 }
5633 }
5634 } // end px loop
5635 } // end py loop
5636
5637 // This is a bit of a hack to ensure that we span the entire color range and
5638 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5639 // single pixel on the edge of the image to a different color. This is even more
5640 // true because the chosen pixels will be covered by the axis.
5641 if (minValue != maxValue) {
5642 if ( !minExists) {
5643 buffer.front() = 0;
5644 }
5645
5646 if ( !maxExists) {
5647 buffer[buffer.size()-nXPixels] = 0.95;
5648 }
5649 }
5650
5651 // Generate the TImage
5653 TImage* pImage = TImage::Create();
5655 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5656 delete pPalette;
5657
5658 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5659 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5660 delete pImage;
5661
5663
5664 // Reset the maximum and minimum values to their original values
5665 // when this function was called. If we don't do this, an initial
5666 // value of -1111 will be replaced with the true max or min values.
5667 fH->SetMinimum(originalZMin);
5668 fH->SetMaximum(originalZMax);
5669}
5670
5671////////////////////////////////////////////////////////////////////////////////
5672/// [Control function to draw a 2D histogram as a color plot.](#HP14)
5673
5675{
5676 Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5677
5678 Double_t zmin = fH->GetMinimum();
5679 Double_t zmax = fH->GetMaximum();
5680
5681 Double_t dz = zmax - zmin;
5682 if (dz <= 0) { // Histogram filled with a constant value
5683 zmax += 0.1*TMath::Abs(zmax);
5684 zmin -= 0.1*TMath::Abs(zmin);
5685 dz = zmax - zmin;
5686 }
5687
5688 // In case of option SAME, zmin and zmax values are taken from the
5689 // first plotted 2D histogram.
5690 if (Hoption.Same > 0 && Hoption.Same < 10) {
5691 TH2 *h2;
5692 TIter next(gPad->GetListOfPrimitives());
5693 while ((h2 = (TH2 *)next())) {
5694 if (!h2->InheritsFrom(TH2::Class())) continue;
5695 zmin = h2->GetMinimum();
5696 zmax = h2->GetMaximum();
5697 fH->SetMinimum(zmin);
5698 fH->SetMaximum(zmax);
5699 if (Hoption.Logz) {
5700 if (zmin <= 0) {
5701 zmin = TMath::Log10(zmax*0.001);
5702 } else {
5703 zmin = TMath::Log10(zmin);
5704 }
5705 zmax = TMath::Log10(zmax);
5706 }
5707 dz = zmax - zmin;
5708 break;
5709 }
5710 } else {
5711 if (Hoption.Logz) {
5712 if (zmin > 0) {
5713 zmin = TMath::Log10(zmin);
5714 zmax = TMath::Log10(zmax);
5715 dz = zmax - zmin;
5716 } else {
5717 return;
5718 }
5719 }
5720 }
5721
5722 Style_t fillsav = fH->GetFillStyle();
5723 Style_t colsav = fH->GetFillColor();
5724 fH->SetFillStyle(1001);
5725 fH->TAttFill::Modify();
5726
5727 // Initialize the levels on the Z axis
5728 Int_t ncolors = gStyle->GetNumberOfColors();
5729 Int_t ndiv = fH->GetContour();
5730 if (ndiv == 0 ) {
5731 ndiv = gStyle->GetNumberContours();
5732 fH->SetContour(ndiv);
5733 }
5734 Int_t ndivz = TMath::Abs(ndiv);
5735 if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
5736 Double_t scale = (dz ? ndivz / dz : 1.0);
5737
5738 Int_t color;
5739 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5740 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5741 yk = fYaxis->GetBinLowEdge(j);
5742 ystep = fYaxis->GetBinWidth(j);
5743 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5744 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5745 xk = fXaxis->GetBinLowEdge(i);
5746 xstep = fXaxis->GetBinWidth(i);
5747 if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
5748 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5749 z = fH->GetBinContent(bin);
5750 // if fH is a profile histogram do not draw empty bins
5751 if (prof2d) {
5752 const Double_t binEntries = prof2d->GetBinEntries(bin);
5753 if (binEntries == 0)
5754 continue;
5755 } else {
5756 // don't draw the empty bins for non-profile histograms
5757 // with positive content
5758 if (z == 0) {
5759 if (zmin >= 0 || Hoption.Logz) continue;
5760 if (Hoption.Color == 2) continue;
5761 }
5762 }
5763
5764 if (Hoption.Logz) {
5765 if (z > 0) z = TMath::Log10(z);
5766 else z = zmin;
5767 }
5768 if (z < zmin && !Hoption.Zero) continue;
5769 xup = xk + xstep;
5770 xlow = xk;
5771 if (Hoption.Logx) {
5772 if (xup > 0) xup = TMath::Log10(xup);
5773 else continue;
5774 if (xlow > 0) xlow = TMath::Log10(xlow);
5775 else continue;
5776 }
5777 yup = yk + ystep;
5778 ylow = yk;
5779 if (Hoption.System != kPOLAR) {
5780 if (Hoption.Logy) {
5781 if (yup > 0) yup = TMath::Log10(yup);
5782 else continue;
5783 if (ylow > 0) ylow = TMath::Log10(ylow);
5784 else continue;
5785 }
5786 if (xup < gPad->GetUxmin()) continue;
5787 if (yup < gPad->GetUymin()) continue;
5788 if (xlow > gPad->GetUxmax()) continue;
5789 if (ylow > gPad->GetUymax()) continue;
5790 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5791 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5792 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5793 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5794 }
5795
5797 zc = fH->GetContourLevelPad(0);
5798 if (z < zc) continue;
5799 color = -1;
5800 for (Int_t k=0; k<ndiv; k++) {
5801 zc = fH->GetContourLevelPad(k);
5802 if (z < zc) {
5803 continue;
5804 } else {
5805 color++;
5806 }
5807 }
5808 } else {
5809 color = Int_t(0.01+(z-zmin)*scale);
5810 }
5811
5812 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5813 if (theColor > ncolors-1) theColor = ncolors-1;
5815 fH->TAttFill::Modify();
5816 if (Hoption.System != kPOLAR) {
5817 gPad->PaintBox(xlow, ylow, xup, yup);
5818 } else {
5819 TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
5820 crown.SetFillColor(gStyle->GetColorPalette(theColor));
5821 crown.Paint();
5822 }
5823 }
5824 }
5825
5827
5828 fH->SetFillStyle(fillsav);
5829 fH->SetFillColor(colsav);
5830 fH->TAttFill::Modify();
5831
5832}
5833
5834////////////////////////////////////////////////////////////////////////////////
5835/// [Control function to draw a 2D histogram as a contour plot.](#HP16)
5836
5838{
5839
5840 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5841 Int_t itars, mode, ir[4];
5842 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5843
5844 if (Hoption.Contour == 14) {
5845 Hoption.Surf = 12;
5846 Hoption.Axis = 1;
5847 thesave = gPad->GetTheta();
5848 phisave = gPad->GetPhi();
5849 gPad->SetPhi(0.);
5850 gPad->SetTheta(90.);
5851 PaintSurface(option);
5852 gPad->SetPhi(phisave);
5853 gPad->SetTheta(thesave);
5854 TView *view = gPad->GetView();
5855 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5856 PaintAxis();
5857 return;
5858 }
5859
5860 if (Hoption.Same) {
5861 // If the contour is painted on a 3d plot, the contour lines are
5862 // paint in 3d too.
5863 TObject *obj;
5864 TIter next(gPad->GetListOfPrimitives());
5865 while ((obj=next())) {
5866 if (strstr(obj->GetDrawOption(),"surf") ||
5867 strstr(obj->GetDrawOption(),"lego") ||
5868 strstr(obj->GetDrawOption(),"tri")) {
5869 Hoption.Surf = 16;
5870 PaintSurface(option);
5871 return;
5872 }
5873 }
5874 }
5875
5876 if (Hoption.Contour == 15) {
5877 TGraphDelaunay2D *dt = nullptr;
5878 TGraphDelaunay *dtOld = nullptr;
5879 TList *hl = fH->GetListOfFunctions();
5880 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5881 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5882 if (!dt && !dtOld) return;
5883 if (!fGraph2DPainter) {
5884 if (dt) fGraph2DPainter = new TGraph2DPainter(dt);
5885 else fGraph2DPainter = new TGraph2DPainter(dtOld);
5886 }
5887 fGraph2DPainter->Paint(option);
5888 return;
5889 }
5890
5891 gPad->SetBit(TGraph::kClipFrame);
5892
5893 Double_t *levels = new Double_t[2*kMAXCONTOUR];
5894 Double_t *xarr = new Double_t[2*kMAXCONTOUR];
5895 Double_t *yarr = new Double_t[2*kMAXCONTOUR];
5896 Int_t *itarr = new Int_t[2*kMAXCONTOUR];
5897
5898 Int_t npmax = 0;
5899 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
5900
5901 ncontour = fH->GetContour();
5902 if (ncontour == 0) {
5903 ncontour = gStyle->GetNumberContours();
5904 fH->SetContour(ncontour);
5905 }
5906 if (ncontour > kMAXCONTOUR) {
5907 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
5908 kMAXCONTOUR, ncontour);
5909 ncontour = kMAXCONTOUR-1;
5910 }
5911 if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ncontour);
5912
5913 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
5914 Int_t linesav = fH->GetLineStyle();
5915 Int_t colorsav = fH->GetLineColor();
5916 Int_t fillsav = fH->GetFillColor();
5917 if (Hoption.Contour == 13) {
5918 fH->TAttLine::Modify();
5919 }
5920
5921 TPolyLine **polys = 0;
5922 TPolyLine *poly=0;
5923 TObjArray *contours = 0;
5924 TList *list = 0;
5925 TGraph *graph = 0;
5926 Int_t *np = 0;
5927 if (Hoption.Contour == 1) {
5928 np = new Int_t[ncontour];
5929 for (i=0;i<ncontour;i++) np[i] = 0;
5930 polys = new TPolyLine*[ncontour];
5931 for (i=0;i<ncontour;i++) {
5932 polys[i] = new TPolyLine(100);
5933 }
5934 if (Hoption.List == 1) {
5935 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
5936 if (contours) {
5937 gROOT->GetListOfSpecials()->Remove(contours);
5938 count = contours->GetSize();
5939 for (i=0;i<count;i++) {
5940 list = (TList*)contours->At(i);
5941 if (list) list->Delete();
5942 }
5943 }
5944 contours = new TObjArray(ncontour);
5945 contours->SetName("contours");
5946 gROOT->GetListOfSpecials()->Add(contours);
5947 for (i=0;i<ncontour;i++) {
5948 list = new TList();
5949 contours->Add(list);
5950 }
5951 }
5952 }
5953 Int_t theColor;
5954 Int_t ncolors = gStyle->GetNumberOfColors();
5955 Int_t ndivz = TMath::Abs(ncontour);
5956
5957 Int_t k,ipoly;
5958 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
5959 y[0] = fYaxis->GetBinCenter(j);
5960 y[1] = y[0];
5961 y[2] = fYaxis->GetBinCenter(j+1);
5962 y[3] = y[2];
5963 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
5964 zc[0] = fH->GetBinContent(i, j);
5965 zc[1] = fH->GetBinContent(i+1, j);
5966 zc[2] = fH->GetBinContent(i+1, j+1);
5967 zc[3] = fH->GetBinContent(i, j+1);
5968 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
5969 if (Hoption.Logz) {
5970 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
5971 else zc[0] = Hparam.zmin;
5972 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
5973 else zc[1] = Hparam.zmin;
5974 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
5975 else zc[2] = Hparam.zmin;
5976 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
5977 else zc[3] = Hparam.zmin;
5978 }
5979 for (k=0;k<4;k++) {
5980 ir[k] = TMath::BinarySearch(ncontour,levels,zc[k]);
5981 }
5982 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
5983 x[0] = fXaxis->GetBinCenter(i);
5984 x[3] = x[0];
5985 x[1] = fXaxis->GetBinCenter(i+1);
5986 x[2] = x[1];
5987 if (zc[0] <= zc[1]) n = 0; else n = 1;
5988 if (zc[2] <= zc[3]) m = 2; else m = 3;
5989 if (zc[n] > zc[m]) n = m;
5990 n++;
5991 lj=1;
5992 for (ix=1;ix<=4;ix++) {
5993 m = n%4 + 1;
5994 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
5995 ir[m-1],x[m-1],y[m-1],&xarr[lj-1],&yarr[lj-1],&itarr[lj-1], levels);
5996 lj += 2*ljfill;
5997 n = m;
5998 }
5999
6000 if (zc[0] <= zc[1]) n = 0; else n = 1;
6001 if (zc[2] <= zc[3]) m = 2; else m = 3;
6002 if (zc[n] > zc[m]) n = m;
6003 n++;
6004 lj=2;
6005 for (ix=1;ix<=4;ix++) {
6006 if (n == 1) m = 4;
6007 else m = n-1;
6008 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6009 ir[m-1],x[m-1],y[m-1],&xarr[lj-1],&yarr[lj-1],&itarr[lj-1], levels);
6010 lj += 2*ljfill;
6011 n = m;
6012 }
6013
6014 // Re-order endpoints
6015
6016 count = 0;
6017 for (ix=1; ix<=lj-5; ix +=2) {
6018 //count = 0;
6019 while (itarr[ix-1] != itarr[ix]) {
6020 xsave = xarr[ix];
6021 ysave = yarr[ix];
6022 itars = itarr[ix];
6023 for (jx=ix; jx<=lj-5; jx +=2) {
6024 xarr[jx] = xarr[jx+2];
6025 yarr[jx] = yarr[jx+2];
6026 itarr[jx] = itarr[jx+2];
6027 }
6028 xarr[lj-3] = xsave;
6029 yarr[lj-3] = ysave;
6030 itarr[lj-3] = itars;
6031 if (count > 100) break;
6032 count++;
6033 }
6034 }
6035
6036 if (count > 100) continue;
6037 for (ix=1; ix<=lj-2; ix +=2) {
6038 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6039 icol = gStyle->GetColorPalette(theColor);
6040 if (Hoption.Contour == 11) {
6041 fH->SetLineColor(icol);
6042 }
6043 if (Hoption.Contour == 12) {
6044 mode = icol%5;
6045 if (mode == 0) mode = 5;
6046 fH->SetLineStyle(mode);
6047 }
6048 if (Hoption.Contour != 1) {
6049 fH->TAttLine::Modify();
6050 gPad->PaintPolyLine(2,&xarr[ix-1],&yarr[ix-1]);
6051 continue;
6052 }
6053
6054 ipoly = itarr[ix-1];
6055 if (ipoly >=0 && ipoly <ncontour) {
6056 poly = polys[ipoly];
6057 poly->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6058 poly->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6059 np[ipoly] += 2;
6060 if (npmax < np[ipoly]) npmax = np[ipoly];
6061 }
6062 }
6063 } // end of if (ir[0]
6064 } //end of for (i
6065 } //end of for (j
6066
6068 Double_t *xp, *yp;
6069 Int_t nadd,iminus,iplus;
6070 Double_t *xx, *yy;
6071 Int_t istart;
6072 Int_t first = ncontour;
6073 Int_t *polysort = 0;
6074 Int_t contListNb;
6075 if (Hoption.Contour != 1) goto theEND;
6076
6077 //The 2 points line generated above are now sorted/merged to generate
6078 //a list of consecutive points.
6079 // If the option "List" has been specified, the list of points is saved
6080 // in the form of TGraph objects in the ROOT list of special objects.
6081 xmin = gPad->GetUxmin();
6082 ymin = gPad->GetUymin();
6083 xp = new Double_t[2*npmax];
6084 yp = new Double_t[2*npmax];
6085 polysort = new Int_t[ncontour];
6086 //find first positive contour
6087 for (ipoly=0;ipoly<ncontour;ipoly++) {
6088 if (levels[ipoly] >= 0) {first = ipoly; break;}
6089 }
6090 //store negative contours from 0 to minimum, then all positive contours
6091 k = 0;
6092 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6093 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6094 // we can now draw sorted contours
6095 contListNb = 0;
6096 fH->SetFillStyle(1001);
6097 for (k=0;k<ncontour;k++) {
6098 ipoly = polysort[k];
6099 if (np[ipoly] == 0) continue;
6100 if (Hoption.List) list = (TList*)contours->At(contListNb);
6101 contListNb++;
6102 poly = polys[ipoly];
6103 xx = poly->GetX();
6104 yy = poly->GetY();
6105 istart = 0;
6106 while (1) {
6107 iminus = npmax;
6108 iplus = iminus+1;
6109 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6110 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6111 xx[istart] = xmin; yy[istart] = ymin;
6112 xx[istart+1] = xmin; yy[istart+1] = ymin;
6113 while (1) {
6114 nadd = 0;
6115 for (i=2;i<np[ipoly];i+=2) {
6116 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6117 iplus++;
6118 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6119 xx[i] = xmin; yy[i] = ymin;
6120 xx[i+1] = xmin; yy[i+1] = ymin;
6121 nadd++;
6122 }
6123 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6124 iminus--;
6125 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6126 xx[i] = xmin; yy[i] = ymin;
6127 xx[i+1] = xmin; yy[i+1] = ymin;
6128 nadd++;
6129 }
6130 }
6131 if (nadd == 0) break;
6132 }
6133 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6134 icol = gStyle->GetColorPalette(theColor);
6135 if (ndivz > 1) fH->SetFillColor(icol);
6136 fH->TAttFill::Modify();
6137 gPad->PaintFillArea(iplus-iminus+1,&xp[iminus],&yp[iminus]);
6138 if (Hoption.List) {
6139 graph = new TGraph(iplus-iminus+1,&xp[iminus],&yp[iminus]);
6140 graph->SetFillColor(icol);
6141 graph->SetLineWidth(fH->GetLineWidth());
6142 list->Add(graph);
6143 }
6144 //check if more points are left
6145 istart = 0;
6146 for (i=2;i<np[ipoly];i+=2) {
6147 if (xx[i] != xmin && yy[i] != ymin) {
6148 istart = i;
6149 break;
6150 }
6151 }
6152 if (istart == 0) break;
6153 }
6154 }
6155
6156 for (i=0;i<ncontour;i++) delete polys[i];
6157 delete [] polys;
6158 delete [] xp;
6159 delete [] yp;
6160 delete [] polysort;
6161
6162theEND:
6163 gPad->ResetBit(TGraph::kClipFrame);
6165 fH->SetLineStyle(linesav);
6166 fH->SetLineColor(colorsav);
6167 fH->SetFillColor(fillsav);
6168 if (np) delete [] np;
6169 delete [] xarr;
6170 delete [] yarr;
6171 delete [] itarr;
6172 delete [] levels;
6173}
6174
6175////////////////////////////////////////////////////////////////////////////////
6176/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6177
6179 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6180 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6181{
6182
6183 Bool_t vert;
6184 Double_t tlen, tdif, elev, diff, pdif, xlen;
6185 Int_t n, i, icount;
6186
6187 if (x1 == x2) {
6188 vert = kTRUE;
6189 tlen = y2 - y1;
6190 } else {
6191 vert = kFALSE;
6192 tlen = x2 - x1;
6193 }
6194
6195 n = icont1 +1;
6196 tdif = elev2 - elev1;
6197 i = 0;
6198 icount = 0;
6199 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6200 //elev = fH->GetContourLevel(n);
6201 elev = levels[n];
6202 diff = elev - elev1;
6203 pdif = diff/tdif;
6204 xlen = tlen*pdif;
6205 if (vert) {
6206 if (Hoption.Logx)
6207 xarr[i] = TMath::Log10(x1);
6208 else
6209 xarr[i] = x1;
6210 if (Hoption.Logy)
6211 yarr[i] = TMath::Log10(y1 + xlen);
6212 else
6213 yarr[i] = y1 + xlen;
6214 } else {
6215 if (Hoption.Logx)
6216 xarr[i] = TMath::Log10(x1 + xlen);
6217 else
6218 xarr[i] = x1 + xlen;
6219 if (Hoption.Logy)
6220 yarr[i] = TMath::Log10(y1);
6221 else
6222 yarr[i] = y1;
6223 }
6224 itarr[i] = n;
6225 icount++;
6226 i +=2;
6227 n++;
6228 }
6229 return icount;
6230}
6231
6232////////////////////////////////////////////////////////////////////////////////
6233/// [Draw 1D histograms error bars.](#HP09)
6234
6236{
6237
6238 // On iOS, we do not highlight histogram, if it's not picked at the moment
6239 // (but part of histogram (axis or pavestat) was picked, that's why this code
6240 // is called at all. This conditional statement never executes on non-iOS platform.
6241 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6242
6243 const Int_t kBASEMARKER=8;
6244 Double_t xp, yp, ex1, ex2, ey1, ey2;
6245 Double_t delta;
6246 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbase;
6247 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6249 Double_t logxmin = 0;
6250 Double_t logymin = 0;
6251 Double_t offset = 0.;
6252 Double_t width = 0.;
6253 Int_t i, k, npoints, first, last, fixbin;
6254 Int_t if1 = 0;
6255 Int_t if2 = 0;
6256 Int_t drawmarker, errormarker;
6257 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6258
6259 Double_t *xline = 0;
6260 Double_t *yline = 0;
6261 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6262 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6263 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6264 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6265 if (Hoption.Error == 11) option1 = 1;
6266 if (Hoption.Error == 12) option2 = 1;
6267 if (Hoption.Error == 13) option3 = 1;
6268 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6269 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6270 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6271 if (option2+option3 == 0) optionE = 1;
6272 if (Hoption.Error == 0) optionE = 0;
6273 if (fXaxis->GetXbins()->fN) fixbin = 0;
6274 else fixbin = 1;
6275
6276 offset = fH->GetBarOffset();
6277 width = fH->GetBarWidth();
6278
6279 errormarker = fH->GetMarkerStyle();
6280 if (optionEX0) {
6281 xerror = 0;
6282 } else {
6283 xerror = gStyle->GetErrorX();
6284 }
6285 symbolsize = fH->GetMarkerSize();
6286 if (errormarker == 1) symbolsize = 0.01;
6287 sbase = symbolsize*kBASEMARKER;
6288 // set the graphics attributes
6289
6290 fH->TAttLine::Modify();
6291 fH->TAttFill::Modify();
6292 fH->TAttMarker::Modify();
6293
6294 // set the first and last bin
6295
6296 Double_t factor = Hparam.factor;
6298 last = Hparam.xlast;
6299 npoints = last - first +1;
6300 xmin = gPad->GetUxmin();
6301 xmax = gPad->GetUxmax();
6302 ymin = gPad->GetUymin();
6303 ymax = gPad->GetUymax();
6304
6305
6306 if (option3) {
6307 xline = new Double_t[2*npoints];
6308 yline = new Double_t[2*npoints];
6309 if (!xline || !yline) {
6310 Error("PaintErrors", "too many points, out of memory");
6311 return;
6312 }
6313 if1 = 1;
6314 if2 = 2*npoints;
6315 }
6316
6317 // compute the offset of the error bars due to the symbol size
6318 s2x = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
6319 s2y =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
6320
6321 // compute size of the lines at the end of the error bars
6322 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6323 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6324 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6325
6326
6327 if (fixbin) {
6328 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6329 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6330 } else {
6331 delta = fH->GetBinWidth(first);
6332 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6333 }
6334
6335 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6336 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6337 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6338
6339 // ---------------------- Loop over the points---------------------
6340 for (k=first; k<=last; k++) {
6341
6342 // get the data
6343 // xp = X position of the current point
6344 // yp = Y position of the current point
6345 // ex1 = Low X error
6346 // ex2 = Up X error
6347 // ey1 = Low Y error
6348 // ey2 = Up Y error
6349 // (xi,yi) = Error bars coordinates
6350
6351 // apply offset on errors for bar histograms
6352 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6353 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6354 if (Hoption.Logx) {
6355 xminTmp = TMath::Power(10, xminTmp);
6356 xmaxTmp = TMath::Power(10, xmaxTmp);
6357 }
6358 Double_t w = (xmaxTmp-xminTmp)*width;
6359 xminTmp += offset*(xmaxTmp-xminTmp);
6360 xmaxTmp = xminTmp + w;
6361 xp = (xminTmp+xmaxTmp)/2.;
6362
6363 if (Hoption.Logx) {
6364 if (xp <= 0) goto L30;
6365 if (xp < logxmin) goto L30;
6366 if (xp > TMath::Power(10,xmax)) break;
6367 } else {
6368 if (xp < xmin) goto L30;
6369 if (xp > xmax) break;
6370 }
6371 yp = factor*fH->GetBinContent(k);
6372 if (optionI0 && yp==0) goto L30;
6373 if (fixbin) {
6374 ex1 = xerror*Hparam.xbinsize;
6375 } else {
6376 delta = fH->GetBinWidth(k);
6377 ex1 = xerror*delta;
6378 }
6379 if (fH->GetBinErrorOption() == TH1::kNormal) {
6380 ey1 = factor*fH->GetBinError(k);
6381 ey2 = ey1;
6382 } else {
6383 ey1 = factor*fH->GetBinErrorLow(k);
6384 ey2 = factor*fH->GetBinErrorUp(k);
6385 }
6386 ex2 = ex1;
6387
6388 xi4 = xp;
6389 xi3 = xp;
6390 xi2 = xp + ex2;
6391 xi1 = xp - ex1;
6392
6393 yi1 = yp;
6394 yi2 = yp;
6395 yi3 = yp - ey1;
6396 yi4 = yp + ey2;
6397
6398 // take the LOG if necessary
6399 if (Hoption.Logx) {
6400 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6401 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6402 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6403 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6404 }
6405 if (Hoption.Logy) {
6406 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6407 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6408 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6409 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6410 }
6411
6412 // test if error bars are not outside the limits
6413 // otherwise they are truncated
6414
6415 xi1 = TMath::Max(xi1,xmin);
6416 xi2 = TMath::Min(xi2,xmax);
6417 yi3 = TMath::Max(yi3,ymin);
6418 yi4 = TMath::Min(yi4,ymax);
6419
6420 // test if the marker is on the frame limits. If "Yes", the
6421 // marker will not be drawn and the error bars will be readjusted.
6422
6423 drawmarker = kTRUE;
6424 if (!option0 && !option3) {
6425 if (Hoption.Logy && yp < logymin) goto L30;
6426 if (yi1 < ymin || yi1 > ymax) goto L30;
6427 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6428 }
6429 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6430
6431 // draw the error rectangles
6432 if (option2) {
6433 if (yi3 >= ymax) goto L30;
6434 if (yi4 <= ymin) goto L30;
6435 gPad->PaintBox(xi1,yi3,xi2,yi4);
6436 }
6437
6438 // keep points for fill area drawing
6439 if (option3) {
6440 xline[if1-1] = xi3;
6441 xline[if2-1] = xi3;
6442 yline[if1-1] = yi4;
6443 yline[if2-1] = yi3;
6444 if1++;
6445 if2--;
6446 }
6447
6448 // draw the error bars
6449 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6450 if (optionE && drawmarker) {
6451 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6452 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6453 // don't duplicate the horizontal line
6454 if (Hoption.Hist != 2) {
6455 if (yi1<ymax && yi1>ymin) {
6456 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6457 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6458 }
6459 }
6460 }
6461 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6462 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6463 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6464 // don't duplicate the horizontal line
6465 if (Hoption.Hist != 2) {
6466 if (yi1<ymax && yi1>ymin) {
6467 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6468 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6469 }
6470 }
6471 }
6472
6473 // draw line at the end of the error bars
6474
6475 if (option1 && drawmarker) {
6476
6477 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6478 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6479 if (yi1 <= ymax && yi1 >= ymin) {
6480 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6481 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6482 }
6483 }
6484
6485 // draw the marker
6486
6487 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6488
6489L30:
6490 if (fixbin) xp += Hparam.xbinsize;
6491 else {
6492 if (k < last) {
6493 delta = fH->GetBinWidth(k+1);
6494 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6495 }
6496 }
6497 } //end of for loop
6498
6499 // draw the filled area
6500
6501 if (option3) {
6502 TGraph graph;
6503 graph.SetLineStyle(fH->GetLineStyle());
6504 graph.SetLineColor(fH->GetLineColor());
6505 graph.SetLineWidth(fH->GetLineWidth());
6506 graph.SetFillStyle(fH->GetFillStyle());
6507 graph.SetFillColor(fH->GetFillColor());
6508 Int_t logx = gPad->GetLogx();
6509 Int_t logy = gPad->GetLogy();
6510 gPad->SetLogx(0);
6511 gPad->SetLogy(0);
6512
6513 // In some cases the number of points in the fill area is smaller than
6514 // 2*npoints. In such cases the array xline and yline must be arranged
6515 // before being plotted. The next loop does that.
6516 if (if2 > npoints) {
6517 for (i=1; i<if1; i++) {
6518 xline[if1-2+i] = xline[if2-1+i];
6519 yline[if1-2+i] = yline[if2-1+i];
6520 }
6521 npoints = if1-1;
6522 }
6523 if (option4) graph.PaintGraph(2*npoints,xline,yline,"FC");
6524 else graph.PaintGraph(2*npoints,xline,yline,"F");
6525 gPad->SetLogx(logx);
6526 gPad->SetLogy(logy);
6527 delete [] xline;
6528 delete [] yline;
6529 }
6530}
6531
6532////////////////////////////////////////////////////////////////////////////////
6533/// Draw 2D histograms errors.
6534
6536{
6537
6538 fH->TAttMarker::Modify();
6539 fH->TAttLine::Modify();
6540
6541 // Define the 3D view
6542 fXbuf[0] = Hparam.xmin;
6543 fYbuf[0] = Hparam.xmax;
6544 fXbuf[1] = Hparam.ymin;
6545 fYbuf[1] = Hparam.ymax;
6546 fXbuf[2] = Hparam.zmin;
6547 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6549 TView *view = gPad->GetView();
6550 if (!view) {
6551 Error("Paint2DErrors", "no TView in current pad");
6552 return;
6553 }
6554 Double_t thedeg = 90 - gPad->GetTheta();
6555 Double_t phideg = -90 - gPad->GetPhi();
6556 Double_t psideg = view->GetPsi();
6557 Int_t irep;
6558 view->SetView(phideg, thedeg, psideg, irep);
6559
6560 // Set color/style for back box
6561 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6562 fLego->SetFillColor(gPad->GetFrameFillColor());
6563 fLego->TAttFill::Modify();
6564 Int_t backcolor = gPad->GetFrameFillColor();
6565 if (Hoption.System != kCARTESIAN) backcolor = 0;
6566 view->PadRange(backcolor);
6569 fLego->TAttFill::Modify();
6570
6571 // Paint the Back Box if needed
6572 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6573 fLego->InitMoveScreen(-1.1,1.1);
6576 fLego->BackBox(90);
6577 }
6578
6579 // Paint the Errors
6580 Double_t x, ex, x1, x2;
6581 Double_t y, ey, y1, y2;
6582 Double_t z, ez1, ez2, z1, z2;
6583 Double_t temp1[3],temp2[3];
6584 Double_t xyerror;
6585 if (Hoption.Error == 110) {
6586 xyerror = 0;
6587 } else {
6588 xyerror = gStyle->GetErrorX();
6589 }
6590
6591 Double_t xk, xstep, yk, ystep;
6592 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6593 y = fYaxis->GetBinCenter(j);
6594 ey = fYaxis->GetBinWidth(j)*xyerror;
6595 y1 = y-ey;
6596 y2 = y+ey;
6597 if (Hoption.Logy) {
6598 if (y > 0) y = TMath::Log10(y);
6599 else continue;
6600 if (y1 > 0) y1 = TMath::Log10(y1);
6601 else y1 = Hparam.ymin;
6602 if (y2 > 0) y2 = TMath::Log10(y2);
6603 else y2 = Hparam.ymin;
6604 }
6605 yk = fYaxis->GetBinLowEdge(j);
6606 ystep = fYaxis->GetBinWidth(j);
6607 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6608 xk = fXaxis->GetBinLowEdge(i);
6609 xstep = fXaxis->GetBinWidth(i);
6610 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6611 Int_t bin = fH->GetBin(i,j);
6612 x = fXaxis->GetBinCenter(i);
6613 ex = fXaxis->GetBinWidth(i)*xyerror;
6614 x1 = x-ex;
6615 x2 = x+ex;
6616 if (Hoption.Logx) {
6617 if (x > 0) x = TMath::Log10(x);
6618 else continue;
6619 if (x1 > 0) x1 = TMath::Log10(x1);
6620 else x1 = Hparam.xmin;
6621 if (x2 > 0) x2 = TMath::Log10(x2);
6622 else x2 = Hparam.xmin;
6623 }
6624 z = fH->GetBinContent(bin);
6625 if (fH->GetBinErrorOption() == TH1::kNormal) {
6626 ez1 = fH->GetBinError(bin);
6627 ez2 = ez1;
6628 }
6629 else {
6630 ez1 = fH->GetBinErrorLow(bin);
6631 ez2 = fH->GetBinErrorUp(bin);
6632 }
6633 z1 = z - ez1;
6634 z2 = z + ez2;
6635 if (Hoption.Logz) {
6636 if (z > 0) z = TMath::Log10(z);
6637 else z = Hparam.zmin;
6638 if (z1 > 0) z1 = TMath::Log10(z1);
6639 else z1 = Hparam.zmin;
6640 if (z2 > 0) z2 = TMath::Log10(z2);
6641 else z2 = Hparam.zmin;
6642
6643 }
6644 if (z <= Hparam.zmin) continue;
6645 if (z > Hparam.zmax) z = Hparam.zmax;
6646
6647 temp1[0] = x1;
6648 temp1[1] = y;
6649 temp1[2] = z;
6650 temp2[0] = x2;
6651 temp2[1] = y;
6652 temp2[2] = z;
6653 gPad->PaintLine3D(temp1, temp2);
6654 temp1[0] = x;
6655 temp1[1] = y1;
6656 temp1[2] = z;
6657 temp2[0] = x;
6658 temp2[1] = y2;
6659 temp2[2] = z;
6660 gPad->PaintLine3D(temp1, temp2);
6661 temp1[0] = x;
6662 temp1[1] = y;
6663 temp1[2] = z1;
6664 temp2[0] = x;
6665 temp2[1] = y;
6666 temp2[2] = z2;
6667 gPad->PaintLine3D(temp1, temp2);
6668 temp1[0] = x;
6669 temp1[1] = y;
6670 temp1[2] = z;
6671 view->WCtoNDC(temp1, &temp2[0]);
6672 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6673 }
6674 }
6675
6676 // Paint the Front Box if needed
6677 if (Hoption.FrontBox) {
6678 fLego->InitMoveScreen(-1.1,1.1);
6680 fLego->FrontBox(90);
6681 }
6682
6683 // Paint the Axis if needed
6684 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6685 TGaxis *axis = new TGaxis();
6686 PaintLegoAxis(axis, 90);
6687 delete axis;
6688 }
6689
6690 delete fLego; fLego = 0;
6691}
6692
6693////////////////////////////////////////////////////////////////////////////////
6694/// Calculate range and clear pad (canvas).
6695
6697{
6698
6699 if (Hoption.Same) return;
6700
6702
6703 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6704 Hoption.Contour == 14 || Hoption.Error >= 100) {
6705 TObject *frame = gPad->FindObject("TFrame");
6706 if (frame) gPad->GetListOfPrimitives()->Remove(frame);
6707 return;
6708 }
6709
6710 //The next statement is always executed on non-iOS platform,
6711 //on iOS depends on pad mode.
6712 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6713 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6714}
6715
6716////////////////////////////////////////////////////////////////////////////////
6717/// [Paint functions associated to an histogram.](#HP28")
6718
6720{
6721
6723 TObject *obj;
6724
6725 while (lnk) {
6726 obj = lnk->GetObject();
6727 TVirtualPad *padsave = gPad;
6728 if (obj->InheritsFrom(TF2::Class())) {
6729 if (obj->TestBit(TF2::kNotDraw) == 0) {
6730 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6731 TF2 *f2 = (TF2*)obj;
6732 f2->SetMinimum(fH->GetMinimum());
6733 f2->SetMaximum(fH->GetMaximum());
6734 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6735 f2->Paint("surf same");
6736 } else {
6737 obj->Paint("cont3 same");
6738 }
6739 }
6740 } else if (obj->InheritsFrom(TF1::Class())) {
6741 if (obj->TestBit(TF1::kNotDraw) == 0) obj->Paint("lsame");
6742 } else {
6743 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6744 gPad->PushSelectableObject(obj);
6745
6746 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6747 //and picked object.
6748 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6749 obj->Paint(lnk->GetOption());
6750 }
6751 lnk = (TObjOptLink*)lnk->Next();
6752 padsave->cd();
6753 }
6754}
6755
6756////////////////////////////////////////////////////////////////////////////////
6757/// [Control routine to draw 1D histograms](#HP01b)
6758
6760{
6761
6762 //On iOS: do not highlight hist, if part of it was selected.
6763 //Never executes on non-iOS platform.
6764 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6765 return;
6766
6767 static char chopth[17];
6768
6769 Int_t htype, oldhtype;
6770 Int_t i, j, first, last, nbins, fixbin;
6771 Double_t c1, yb;
6772 yb = 0;
6773
6774 strlcpy(chopth, " ",17);
6775
6778 Double_t baroffset = fH->GetBarOffset();
6779 Double_t barwidth = fH->GetBarWidth();
6780 Double_t baroffsetsave = gStyle->GetBarOffset();
6781 Double_t barwidthsave = gStyle->GetBarWidth();
6782 gStyle->SetBarOffset(baroffset);
6783 gStyle->SetBarWidth(barwidth);
6784
6785 // Create "LIFE" structure to keep current histogram status
6786
6788 last = Hparam.xlast;
6789 nbins = last - first + 1;
6790
6791 Double_t *keepx = 0;
6792 Double_t *keepy = 0;
6793 if (fXaxis->GetXbins()->fN) fixbin = 0;
6794 else fixbin = 1;
6795 if (fixbin) keepx = new Double_t[2];
6796 else keepx = new Double_t[nbins+1];
6797 keepy = new Double_t[nbins];
6798 Double_t logymin = 0;
6799 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
6800
6801 // Loop on histogram bins
6802
6803 for (j=first; j<=last;j++) {
6805 if (TMath::Abs(ymax-ymin) > 0) {
6806 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
6807 else yb = c1;
6808 }
6809 if (!Hoption.Line) {
6810 yb = TMath::Max(yb, ymin);
6811 yb = TMath::Min(yb, ymax);
6812 }
6813 keepy[j-first] = yb;
6814 }
6815
6816 // Draw histogram according to value of FillStyle and FillColor
6817
6818 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6819 else {
6820 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6821 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6822 }
6823
6824 // Prepare Fill area (systematic with option "Bar").
6825
6826 oldhtype = fH->GetFillStyle();
6827 htype = oldhtype;
6828 if (Hoption.Bar) {
6829 if (htype == 0 || htype == 1000) htype = 1001;
6830 }
6831
6832 Width_t lw = (Width_t)fH->GetLineWidth();
6833
6834 // Code option for GrapHist
6835
6836 if (Hoption.Line) chopth[0] = 'L';
6837 if (Hoption.Star) chopth[1] = '*';
6838 if (Hoption.Mark) chopth[2] = 'P';
6839 if (Hoption.Mark == 10) chopth[3] = '0';
6841 if (Hoption.Curve) chopth[3] = 'C';
6842 if (Hoption.Hist > 0) chopth[4] = 'H';
6843 else if (Hoption.Bar) chopth[5] = 'B';
6844 if (fH->GetFillColor() && htype) {
6845 if (Hoption.Logy) {
6846 chopth[6] = '1';
6847 }
6848 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6849 chopth[7] = 'F';
6850 }
6851 }
6852 }
6853 if (!fixbin && strlen(chopth)) {
6854 chopth[8] = 'N';
6855 }
6856
6857 if (Hoption.Fill == 2) chopth[13] = '2';
6858
6859 // Option LOGX
6860
6861 if (Hoption.Logx) {
6862 chopth[9] = 'G';
6863 chopth[10] = 'X';
6864 if (fixbin) {
6865 keepx[0] = TMath::Power(10,keepx[0]);
6866 keepx[1] = TMath::Power(10,keepx[1]);
6867 }
6868 }
6869
6870 if (Hoption.Off) {
6871 chopth[11] = ']';
6872 chopth[12] = '[';
6873 }
6874
6875 // Draw the histogram
6876
6877 TGraph graph;
6878 graph.SetLineWidth(lw);
6879 graph.SetLineStyle(fH->GetLineStyle());
6880 graph.SetLineColor(fH->GetLineColor());
6881 graph.SetFillStyle(htype);
6882 graph.SetFillColor(fH->GetFillColor());
6883 graph.SetMarkerStyle(fH->GetMarkerStyle());
6884 graph.SetMarkerSize(fH->GetMarkerSize());
6885 graph.SetMarkerColor(fH->GetMarkerColor());
6886 if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
6887
6888 graph.PaintGrapHist(nbins, keepx, keepy ,chopth);
6889
6890 delete [] keepx;
6891 delete [] keepy;
6892 gStyle->SetBarOffset(baroffsetsave);
6893 gStyle->SetBarWidth(barwidthsave);
6894
6895 htype=oldhtype;
6896}
6897
6898////////////////////////////////////////////////////////////////////////////////
6899/// [Control function to draw a 3D histograms.](#HP01d)
6900
6902{
6903
6904 char *cmd;
6905 TString opt = option;
6906 opt.ToLower();
6907 Int_t irep;
6908
6909 if (fCurrentF3) {
6910 PaintTF3();
6911 return;
6912 } else if (Hoption.Box || Hoption.Lego) {
6913 if (Hoption.Box == 11 || Hoption.Lego == 11) {
6914 PaintH3Box(1);
6915 } else if (Hoption.Box == 12 || Hoption.Lego == 12) {
6916 PaintH3Box(2);
6917 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
6918 PaintH3Box(3);
6919 } else {
6921 }
6922 return;
6923 } else if (strstr(opt,"iso")) {
6924 PaintH3Iso();
6925 return;
6926 } else if (strstr(opt,"tf3")) {
6927 PaintTF3();
6928 return;
6929 } else {
6930 cmd = Form("TPolyMarker3D::PaintH3((TH1 *)0x%lx,\"%s\");",(Long_t)fH,option);
6931 }
6932
6933 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
6934 if (strstr(opt,"bb")) Hoption.BackBox = 0;
6935
6936 TView *view = gPad->GetView();
6937 if (!view) return;
6938 Double_t thedeg = 90 - gPad->GetTheta();
6939 Double_t phideg = -90 - gPad->GetPhi();
6940 Double_t psideg = view->GetPsi();
6941 view->SetView(phideg, thedeg, psideg, irep);
6942
6943 // Paint the data
6944 gROOT->ProcessLine(cmd);
6945
6946 if (Hoption.Same) return;
6947
6948 // Draw axis
6949 view->SetOutlineToCube();
6950 TSeqCollection *ol = view->GetOutline();
6951 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
6953 TGaxis *axis = new TGaxis();
6954 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
6955 delete axis;
6956
6957 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
6958 // be painted with the option colz.
6959 if (fH->GetDrawOption() && strstr(opt,"colz")) {
6960 Int_t ndiv = fH->GetContour();
6961 if (ndiv == 0 ) {
6962 ndiv = gStyle->GetNumberContours();
6963 fH->SetContour(ndiv);
6964 }
6965 PaintPalette();
6966 }
6967
6968 // Draw title
6969 PaintTitle();
6970
6971 //Draw stats and fit results
6972 TF1 *fit = 0;
6973 TIter next(fFunctions);
6974 TObject *obj;
6975 while ((obj = next())) {
6976 if (obj->InheritsFrom(TF1::Class())) {
6977 fit = (TF1*)obj;
6978 break;
6979 }
6980 }
6981 if ((Hoption.Same%10) != 1) {
6982 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
6984 }
6985 }
6986
6987}
6988
6989////////////////////////////////////////////////////////////////////////////////
6990/// Compute histogram parameters used by the drawing routines.
6991
6993{
6994
6995 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
6996
6997 Int_t i;
6998 static const char *where = "PaintInit";
6999 Double_t yMARGIN = gStyle->GetHistTopMargin();
7000 Int_t maximum = 0;
7001 Int_t minimum = 0;
7002 if (fH->GetMaximumStored() != -1111) maximum = 1;
7003 if (fH->GetMinimumStored() != -1111) minimum = 1;
7004
7005 // Compute X axis parameters
7006
7007 Int_t last = fXaxis->GetLast();
7011 Hparam.xlast = last;
7015
7016 // if log scale in X, replace xmin,max by the log
7017 if (Hoption.Logx) {
7018 if (Hparam.xmax<=0) {
7019 Error(where, "cannot set X axis to log scale");
7020 return 0;
7021 }
7022 if (Hparam.xlowedge <=0 ) {
7023 if (Hoption.Same) {
7024 Hparam.xlowedge = TMath::Power(10, gPad->GetUxmin());
7025 } else {
7026 for (i=first; i<=last; i++) {
7027 Double_t binLow = fXaxis->GetBinLowEdge(i);
7028 if (binLow>0) {
7029 Hparam.xlowedge = binLow;
7030 break;
7031 }
7032 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7033 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7034 break;
7035 }
7036 }
7037 if (Hparam.xlowedge<=0) {
7038 Error(where, "cannot set X axis to log scale");
7039 return 0;
7040 }
7041 }
7043 }
7048 if (Hparam.xlast > last) Hparam.xlast = last;
7050 }
7051
7052 // Compute Y axis parameters
7053 Double_t bigp = TMath::Power(10,32);
7054 Double_t ymax = -bigp;
7055 Double_t ymin = bigp;
7056 Double_t c1, e1;
7057 Double_t xv[1];
7058 Double_t fval;
7059 TObject *f;
7060 TF1 *f1;
7061 Double_t allchan = 0;
7062 Int_t nonNullErrors = 0;
7063 TIter next(fFunctions);
7064 for (i=first; i<=last;i++) {
7065 c1 = fH->GetBinContent(i);
7067 if (Hoption.Logy) {
7068 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7069 } else {
7071 }
7072 if (Hoption.Error) {
7074 e1 = fH->GetBinError(i);
7075 else
7076 e1 = fH->GetBinErrorUp(i);
7077 if (e1 > 0) nonNullErrors++;
7078 ymax = TMath::Max(ymax,c1+e1);
7080 e1 = fH->GetBinErrorLow(i);
7081
7082 if (Hoption.Logy) {
7083 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7084 } else {
7085 ymin = TMath::Min(ymin,c1-e1);
7086 }
7087 }
7088 if (Hoption.Func) {
7089 xv[0] = fXaxis->GetBinCenter(i);
7090 while ((f = (TObject*) next())) {
7091 if (f->IsA() == TF1::Class()) {
7092 f1 = (TF1*)f;
7093 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7094 fval = f1->Eval(xv[0],0,0);
7095 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7096 ymax = TMath::Max(ymax,fval);
7097 if (Hoption.Logy) {
7098 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7099 }
7100 }
7101 }
7102 next.Reset();
7103 }
7104 allchan += c1;
7105 }
7106 if (!nonNullErrors) {
7107 if (Hoption.Error) {
7108 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7109 Hoption.Error=0;
7110 }
7111 }
7112
7113
7114 // Take into account maximum , minimum
7115
7116 if (Hoption.Logy && ymin <= 0) {
7117 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7118 else ymin = 0.001*ymax;
7119 }
7120
7121 Double_t xm = ymin;
7122 if (maximum) ymax = fH->GetMaximumStored();
7123 if (minimum) xm = fH->GetMinimumStored();
7124 if (Hoption.Logy && xm < 0) {
7125 Error(where, "log scale requested with a negative argument (%f)", xm);
7126 return 0;
7127 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7128 ymin = 0.01;
7129 ymax = 10.;
7130 } else {
7131 ymin = xm;
7132 }
7133
7134 if (ymin >= ymax) {
7135 if (Hoption.Logy) {
7136 if (ymax > 0) ymin = 0.001*ymax;
7137 else {
7138 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7139 return 0;
7140 }
7141 }
7142 else {
7143 if (ymin > 0) {
7144 ymin = 0;
7145 ymax *= 2;
7146 } else if (ymin < 0) {
7147 ymax = 0;
7148 ymin *= 2;
7149 } else {
7150 ymin = 0;
7151 ymax = 1;
7152 }
7153 }
7154 }
7155
7156 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7157 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7158 ymin = ymin*(1-1E-14);
7159 ymax = ymax*(1+1E-14);
7160 }
7161
7162 // take into account normalization factor
7163 Hparam.allchan = allchan;
7164 Double_t factor = allchan;
7165 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7166 if (allchan) factor /= allchan;
7167 if (factor == 0) factor = 1;
7168 Hparam.factor = factor;
7169 ymax = factor*ymax;
7170 ymin = factor*ymin;
7171 //just in case the norm factor is negative
7172 // this may happen with a positive norm factor and a negative integral !
7173 if (ymax < ymin) {
7174 Double_t temp = ymax;
7175 ymax = ymin;
7176 ymin = temp;
7177 }
7178
7179 // For log scales, histogram coordinates are LOG10(ymin) and
7180 // LOG10(ymax). Final adjustment (if not option "Same"
7181 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7182 // Maximum and Minimum are not defined.
7183 if (Hoption.Logy) {
7184 if (ymin <=0 || ymax <=0) {
7185 Error(where, "Cannot set Y axis to log scale");
7186 return 0;
7187 }
7189 if (!minimum) ymin += TMath::Log10(0.5);
7191 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7192 if (!Hoption.Same) {
7193 Hparam.ymin = ymin;
7194 Hparam.ymax = ymax;
7195 }
7196 return 1;
7197 }
7198
7199 // final adjustment of ymin for linear scale.
7200 // if minimum is not set , then ymin is set to zero if >0
7201 // or to ymin - margin if <0.
7202 if (!minimum) {
7203 if (Hoption.MinimumZero) {
7204 if (ymin >= 0) ymin = 0;
7205 else ymin -= yMARGIN*(ymax-ymin);
7206 } else {
7207 Double_t dymin = yMARGIN*(ymax-ymin);
7208 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7209 else ymin -= dymin;
7210 }
7211 }
7212
7213 // final adjustment of YMAXI for linear scale (if not option "Same"):
7214 // decrease histogram height to MAX% of allowed height if HMAXIM
7215 // has not been called.
7216 if (!maximum) {
7217 ymax += yMARGIN*(ymax-ymin);
7218 }
7219
7220 Hparam.ymin = ymin;
7221 Hparam.ymax = ymax;
7222 return 1;
7223}
7224
7225////////////////////////////////////////////////////////////////////////////////
7226/// Compute histogram parameters used by the drawing routines for a rotated pad.
7227
7229{
7230
7231 static const char *where = "PaintInitH";
7232 Double_t yMARGIN = gStyle->GetHistTopMargin();
7233 Int_t maximum = 0;
7234 Int_t minimum = 0;
7235 if (fH->GetMaximumStored() != -1111) maximum = 1;
7236 if (fH->GetMinimumStored() != -1111) minimum = 1;
7237
7238 // Compute X axis parameters
7239
7240 Int_t last = fXaxis->GetLast();
7244 Hparam.xlast = last;
7248
7249 // if log scale in Y, replace ymin,max by the log
7250 if (Hoption.Logy) {
7251 if (Hparam.xlowedge <=0 ) {
7254 }
7255 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7256 Error(where, "cannot set Y axis to log scale");
7257 return 0;
7258 }
7263 if (Hparam.xlast > last) Hparam.xlast = last;
7264 }
7265
7266 // Compute Y axis parameters
7267 Double_t bigp = TMath::Power(10,32);
7268 Double_t xmax = -bigp;
7269 Double_t xmin = bigp;
7270 Double_t c1, e1;
7271 Double_t xv[1];
7272 Double_t fval;
7273 Int_t i;
7274 TObject *f;
7275 TF1 *f1;
7276 Double_t allchan = 0;
7277 TIter next(fFunctions);
7278 for (i=first; i<=last;i++) {
7279 c1 = fH->GetBinContent(i);
7282 if (Hoption.Error) {
7283 e1 = fH->GetBinError(i);
7284 xmax = TMath::Max(xmax,c1+e1);
7285 xmin = TMath::Min(xmin,c1-e1);
7286 }
7287 if (Hoption.Func) {
7288 xv[0] = fXaxis->GetBinCenter(i);
7289 while ((f = (TObject*) next())) {
7290 if (f->IsA() == TF1::Class()) {
7291 f1 = (TF1*)f;
7292 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7293 fval = f1->Eval(xv[0],0,0);
7294 xmax = TMath::Max(xmax,fval);
7295 if (Hoption.Logy) {
7296 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7297 }
7298 }
7299 }
7300 next.Reset();
7301 }
7302 allchan += c1;
7303 }
7304
7305 // Take into account maximum , minimum
7306
7307 if (Hoption.Logx && xmin <= 0) {
7308 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7309 else xmin = 0.001*xmax;
7310 }
7311 Double_t xm = xmin;
7312 if (maximum) xmax = fH->GetMaximumStored();
7313 if (minimum) xm = fH->GetMinimumStored();
7314 if (Hoption.Logx && xm <= 0) {
7315 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7316 return 0;
7317 }
7318 else xmin = xm;
7319 if (xmin >= xmax) {
7320 if (Hoption.Logx) {
7321 if (xmax > 0) xmin = 0.001*xmax;
7322 else {
7323 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7324 return 0;
7325 }
7326 }
7327 else {
7328 if (xmin > 0) {
7329 xmin = 0;
7330 xmax *= 2;
7331 } else if (xmin < 0) {
7332 xmax = 0;
7333 xmin *= 2;
7334 } else {
7335 xmin = -1;
7336 xmax = 1;
7337 }
7338 }
7339 }
7340
7341 // take into account normalization factor
7342 Hparam.allchan = allchan;
7343 Double_t factor = allchan;
7344 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7345 if (allchan) factor /= allchan;
7346 if (factor == 0) factor = 1;
7347 Hparam.factor = factor;
7348 xmax = factor*xmax;
7349 xmin = factor*xmin;
7350
7351 // For log scales, histogram coordinates are LOG10(ymin) and
7352 // LOG10(ymax). Final adjustment (if not option "Same"
7353 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7354 // Maximum and Minimum are not defined.
7355 if (Hoption.Logx) {
7356 if (xmin <=0 || xmax <=0) {
7357 Error(where, "Cannot set Y axis to log scale");
7358 return 0;
7359 }
7361 if (!minimum) xmin += TMath::Log10(0.5);
7363 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7364 if (!Hoption.Same) {
7365 Hparam.xmin = xmin;
7366 Hparam.xmax = xmax;
7367 }
7368 return 1;
7369 }
7370
7371 // final adjustment of ymin for linear scale.
7372 // if minimum is not set , then ymin is set to zero if >0
7373 // or to ymin - margin if <0.
7374 if (!minimum) {
7375 if (xmin >= 0) xmin = 0;
7376 else xmin -= yMARGIN*(xmax-xmin);
7377 }
7378
7379 // final adjustment of YMAXI for linear scale (if not option "Same"):
7380 // decrease histogram height to MAX% of allowed height if HMAXIM
7381 // has not been called.
7382 if (!maximum) {
7383 xmax += yMARGIN*(xmax-xmin);
7384 }
7385 Hparam.xmin = xmin;
7386 Hparam.xmax = xmax;
7387 return 1;
7388}
7389
7390////////////////////////////////////////////////////////////////////////////////
7391/// [Control function to draw a 3D histogram with boxes.](#HP25)
7392
7394{
7395 // Predefined box structure
7396 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7397 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7398 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7399 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7400
7401 // Define dimensions of world space
7402 TGaxis *axis = new TGaxis();
7403 TAxis *xaxis = fH->GetXaxis();
7404 TAxis *yaxis = fH->GetYaxis();
7405 TAxis *zaxis = fH->GetZaxis();
7406
7407 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7408 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7409 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7410 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7411 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7412 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7413
7415
7416 // Set view
7417 TView *view = gPad->GetView();
7418 if (!view) {
7419 Error("PaintH3", "no TView in current pad");
7420 return;
7421 }
7422 Double_t thedeg = 90 - gPad->GetTheta();
7423 Double_t phideg = -90 - gPad->GetPhi();
7424 Double_t psideg = view->GetPsi();
7425 Int_t irep;
7426 view->SetView(phideg, thedeg, psideg, irep);
7427
7428 Int_t backcolor = gPad->GetFrameFillColor();
7429 view->PadRange(backcolor);
7430
7431 // Draw back surfaces of frame box
7432 fLego->InitMoveScreen(-1.1,1.1);
7433 if (Hoption.BackBox) {
7436 fLego->BackBox(90);
7437 }
7438
7440
7441 // Define order of drawing
7442 Double_t *tnorm = view->GetTnorm();
7443 if (!tnorm) return;
7444 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7445 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7446 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7447 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7448 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7449 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7450 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7451 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7452 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7453
7454 // Set graphic attributes (colour, style, etc.)
7455 Style_t fillsav = fH->GetFillStyle();
7456 Style_t colsav = fH->GetFillColor();
7457 Style_t coldark = TColor::GetColorDark(colsav);
7458 Style_t colbright = TColor::GetColorBright(colsav);
7459
7460 fH->SetFillStyle(1001);
7461 fH->TAttFill::Modify();
7462 fH->TAttLine::Modify();
7463 Int_t ncolors = gStyle->GetNumberOfColors();
7464 Int_t theColor;
7465
7466 // Create bin boxes and draw
7467 Double_t wmin = TMath::Max(fH->GetMinimum(),0.);
7470
7471 Double_t pmin[3], pmax[3], sxyz[8][3];
7472 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7473 pmin[0] = xaxis->GetBinLowEdge(ix);
7474 pmax[0] = xaxis->GetBinUpEdge(ix);
7475 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7476 pmin[1] = yaxis->GetBinLowEdge(iy);
7477 pmax[1] = yaxis->GetBinUpEdge(iy);
7478 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7479 pmin[2] = zaxis->GetBinLowEdge(iz);
7480 pmax[2] = zaxis->GetBinUpEdge(iz);
7481 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7482 Bool_t neg = kFALSE;
7483 Int_t n = 5;
7484 if (w<0) {
7485 w = -w;
7486 neg = kTRUE;
7487 }
7488 if (w < wmin) continue;
7489 if (w > wmax) w = wmax;
7490 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7491 if (scale == 0) continue;
7492 for (Int_t i=0; i<3; ++i) {
7493 Double_t c = (pmax[i] + pmin[i])*0.5;
7494 Double_t d = (pmax[i] - pmin[i])*scale;
7495 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7496 sxyz[k][i] = wxyz[k][i]*d + c;
7497 }
7498 }
7499 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7500 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7501 }
7502 Double_t x[8], y[8]; // draw bin box faces
7503 for (Int_t k=0; k<6; ++k) {
7504 for (Int_t i=0; i<4; ++i) {
7505 Int_t iv = iface[k][i];
7506 x[i] = sxyz[iv][0];
7507 y[i] = sxyz[iv][1];
7508 }
7509 x[4] = x[0] ; y[4] = y[0];
7510 if (neg) {
7511 x[5] = x[2] ; y[5] = y[2];
7512 x[6] = x[3] ; y[6] = y[3];
7513 x[7] = x[1] ; y[7] = y[1];
7514 n = 8;
7515 } else {
7516 n = 5;
7517 }
7518 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7519 if (z <= 0.) continue;
7520 if (iopt == 2) {
7521 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7523 } else {
7524 if (k == 3 || k == 5) {
7525 fH->SetFillColor(coldark);
7526 } else if (k == 0 || k == 1) {
7527 fH->SetFillColor(colbright);
7528 } else {
7529 fH->SetFillColor(colsav);
7530 }
7531 }
7532 fH->TAttFill::Modify();
7533 gPad->PaintFillArea(4, x, y);
7534 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7535 }
7536 }
7537 }
7538 }
7539
7540 // Draw front surfaces of frame box
7541 if (Hoption.FrontBox) fLego->FrontBox(90);
7542
7543 // Draw axis and title
7544 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7545 PaintTitle();
7546
7547 // Draw palette. if needed.
7548 if (Hoption.Zscale) {
7549 Int_t ndiv = fH->GetContour();
7550 if (ndiv == 0 ) {
7551 ndiv = gStyle->GetNumberContours();
7552 fH->SetContour(ndiv);
7553 }
7554 PaintPalette();
7555 }
7556
7557 delete axis;
7558 delete fLego; fLego = 0;
7559
7560 fH->SetFillStyle(fillsav);
7561 fH->SetFillColor(colsav);
7562 fH->TAttFill::Modify();
7563}
7564
7565////////////////////////////////////////////////////////////////////////////////
7566/// [Control function to draw a 3D histogram with boxes.](#HP25)
7567
7569{
7570 // Predefined box structure
7571 Double_t wxyz[8][3] = {
7572 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7573 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7574 };
7575 Int_t iface[6][4] = {
7576 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7577 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7578 };
7579 Double_t normal[6][3] = {
7580 {0,0,-1}, {0,0,1}, // Z-, Z+
7581 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7582 };
7583
7584 // Define dimensions of world space
7585 TGaxis *axis = new TGaxis();
7586 TAxis *xaxis = fH->GetXaxis();
7587 TAxis *yaxis = fH->GetYaxis();
7588 TAxis *zaxis = fH->GetZaxis();
7589
7590 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7591 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7592 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7593 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7594 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7595 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7596
7598
7599 // Set view
7600 TView *view = gPad->GetView();
7601 if (!view) {
7602 Error("PaintH3", "no TView in current pad");
7603 return;
7604 }
7605 Double_t thedeg = 90 - gPad->GetTheta();
7606 Double_t phideg = -90 - gPad->GetPhi();
7607 Double_t psideg = view->GetPsi();
7608 Int_t irep;
7609 view->SetView(phideg, thedeg, psideg, irep);
7610
7611 Int_t backcolor = gPad->GetFrameFillColor();
7612 view->PadRange(backcolor);
7613
7614 // Draw front surfaces of frame box
7615 if (Hoption.FrontBox) {
7616 fLego->InitMoveScreen(-1.1,1.1);
7618 }
7619
7620 // Initialize hidden line removal algorithm "raster screen"
7621 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7622
7623 // Define order of drawing
7624 Double_t *tnorm = view->GetTnorm();
7625 if (!tnorm) return;
7626 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7627 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7628 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7629 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7630 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7631 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7632 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7633 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7634 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7635
7636 // Set line attributes (colour, style, etc.)
7637 fH->TAttLine::Modify();
7638
7639 // Create bin boxes and draw
7640 const Int_t NTMAX = 100;
7641 Double_t tt[NTMAX][2];
7642 Double_t wmin = TMath::Max(fH->GetMinimum(),0.);
7645 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7646 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7647 pmin[0] = xaxis->GetBinLowEdge(ix);
7648 pmax[0] = xaxis->GetBinUpEdge(ix);
7649 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7650 pmin[1] = yaxis->GetBinLowEdge(iy);
7651 pmax[1] = yaxis->GetBinUpEdge(iy);
7652 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7653 pmin[2] = zaxis->GetBinLowEdge(iz);
7654 pmax[2] = zaxis->GetBinUpEdge(iz);
7655 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7656 Bool_t neg = kFALSE;
7657 if (w<0) {
7658 w = -w;
7659 neg = kTRUE;
7660 }
7661 if (w < wmin) continue;
7662 if (w > wmax) w = wmax;
7663 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7664 if (scale == 0) continue;
7665 for (Int_t i=0; i<3; ++i) {
7666 Double_t c = (pmax[i] + pmin[i])*0.5;
7667 Double_t d = (pmax[i] - pmin[i])*scale;
7668 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7669 sxyz[k][i] = wxyz[k][i]*d + c;
7670 }
7671 }
7672 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7673 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7674 }
7675 for (Int_t k=0; k<6; ++k) { // draw box faces
7676 Double_t zn;
7677 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7678 if (zn <= 0) continue;
7679 for (Int_t i=0; i<4; ++i) {
7680 Int_t ip = iface[k][i];
7681 pp[i][0] = sxyz[ip][0];
7682 pp[i][1] = sxyz[ip][1];
7683 }
7684 for (Int_t i=0; i<4; ++i) {
7685 Int_t i1 = i;
7686 Int_t i2 = (i == 3) ? 0 : i + 1;
7687 Int_t nt;
7688 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7689 Double_t xdel = pp[i2][0] - pp[i1][0];
7690 Double_t ydel = pp[i2][1] - pp[i1][1];
7691 Double_t x[2], y[2];
7692 for (Int_t it = 0; it < nt; ++it) {
7693 x[0] = pp[i1][0] + xdel*tt[it][0];
7694 y[0] = pp[i1][1] + ydel*tt[it][0];
7695 x[1] = pp[i1][0] + xdel*tt[it][1];
7696 y[1] = pp[i1][1] + ydel*tt[it][1];
7697 gPad->PaintPolyLine(2, x, y);
7698 }
7699 }
7700 if (neg) {
7701 Int_t i1 = 0;
7702 Int_t i2 = 2;
7703 Int_t nt;
7704 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7705 Double_t xdel = pp[i2][0] - pp[i1][0];
7706 Double_t ydel = pp[i2][1] - pp[i1][1];
7707 Double_t x[2], y[2];
7708 for (Int_t it = 0; it < nt; ++it) {
7709 x[0] = pp[i1][0] + xdel*tt[it][0];
7710 y[0] = pp[i1][1] + ydel*tt[it][0];
7711 x[1] = pp[i1][0] + xdel*tt[it][1];
7712 y[1] = pp[i1][1] + ydel*tt[it][1];
7713 gPad->PaintPolyLine(2, x, y);
7714 }
7715 i1 = 1;
7716 i2 = 3;
7717 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7718 xdel = pp[i2][0] - pp[i1][0];
7719 ydel = pp[i2][1] - pp[i1][1];
7720 for (Int_t it = 0; it < nt; ++it) {
7721 x[0] = pp[i1][0] + xdel*tt[it][0];
7722 y[0] = pp[i1][1] + ydel*tt[it][0];
7723 x[1] = pp[i1][0] + xdel*tt[it][1];
7724 y[1] = pp[i1][1] + ydel*tt[it][1];
7725 gPad->PaintPolyLine(2, x, y);
7726 }
7727 }
7728 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7729 }
7730 }
7731 }
7732 }
7733
7734 // Draw frame box
7735 if (Hoption.BackBox) {
7738 fLego->BackBox(90);
7739 }
7740
7741 if (Hoption.FrontBox) fLego->FrontBox(90);
7742
7743 // Draw axis and title
7744 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7745 PaintTitle();
7746
7747 delete axis;
7748 delete fLego; fLego = 0;
7749}
7750
7751////////////////////////////////////////////////////////////////////////////////
7752/// [Control function to draw a 3D histogram with Iso Surfaces.](#HP25)
7753
7755{
7756
7757 const Double_t ydiff = 1;
7758 const Double_t yligh1 = 10;
7759 const Double_t qa = 0.15;
7760 const Double_t qd = 0.15;
7761 const Double_t qs = 0.8;
7762 Double_t fmin, fmax;
7763 Int_t i, irep;
7764 Int_t nbcol = 28;
7765 Int_t icol1 = 201;
7766 Int_t ic1 = icol1;
7767 Int_t ic2 = ic1+nbcol;
7768 Int_t ic3 = ic2+nbcol;
7769
7770 TGaxis *axis = new TGaxis();
7771 TAxis *xaxis = fH->GetXaxis();
7772 TAxis *yaxis = fH->GetYaxis();
7773 TAxis *zaxis = fH->GetZaxis();
7774
7775 Int_t nx = fH->GetNbinsX();
7776 Int_t ny = fH->GetNbinsY();
7777 Int_t nz = fH->GetNbinsZ();
7778
7779 Double_t *x = new Double_t[nx];
7780 Double_t *y = new Double_t[ny];
7781 Double_t *z = new Double_t[nz];
7782
7783 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7784 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7785 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7786
7787 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7788 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7789 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7790 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7791 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7792 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7793
7794 Double_t s[3];
7795 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7796 s[1] = 0.5*s[0];
7797 s[2] = 1.5*s[0];
7798
7800
7801 TView *view = gPad->GetView();
7802 if (!view) {
7803 Error("PaintH3Iso", "no TView in current pad");
7804 delete [] x;
7805 delete [] y;
7806 delete [] z;
7807 return;
7808 }
7809 Double_t thedeg = 90 - gPad->GetTheta();
7810 Double_t phideg = -90 - gPad->GetPhi();
7811 Double_t psideg = view->GetPsi();
7812 view->SetView(phideg, thedeg, psideg, irep);
7813
7814 Int_t backcolor = gPad->GetFrameFillColor();
7815 if (Hoption.System != kCARTESIAN) backcolor = 0;
7816 view->PadRange(backcolor);
7817
7818 Double_t dcol = 0.5/Double_t(nbcol);
7819 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7820 if (!colref) {
7821 delete [] x;
7822 delete [] y;
7823 delete [] z;
7824 return;
7825 }
7826 Float_t r, g, b, hue, light, satur;
7827 colref->GetRGB(r,g,b);
7828 TColor::RGBtoHLS(r,g,b,hue,light,satur);
7829 TColor *acol;
7830 for (Int_t col=0;col<nbcol;col++) {
7831 acol = gROOT->GetColor(col+icol1);
7832 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7833 if (acol) acol->SetRGB(r, g, b);
7834 }
7835
7836 fLego->InitMoveScreen(-1.1,1.1);
7837
7838 if (Hoption.BackBox) {
7841 fLego->BackBox(90);
7842 }
7843
7844 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7845 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7846 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7847 fmin = ydiff*qa;
7848 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7849 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7850
7851 fLego->IsoSurface(1, s, nx, ny, nz, x, y, z, "BF");
7852
7853 if (Hoption.FrontBox) {
7854 fLego->InitMoveScreen(-1.1,1.1);
7856 fLego->FrontBox(90);
7857 }
7858 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7859
7860 PaintTitle();
7861
7862 delete axis;
7863 delete fLego; fLego = 0;
7864 delete [] x;
7865 delete [] y;
7866 delete [] z;
7867}
7868
7869////////////////////////////////////////////////////////////////////////////////
7870/// [Control function to draw a 2D histogram as a lego plot.](#HP17)
7871
7873{
7874
7875 Int_t raster = 1;
7876 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
7877 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
7878 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
7879 Double_t zmin = Hparam.zmin;
7880 Double_t zmax = Hparam.zmax;
7881 Double_t xlab1 = Hparam.xmin;
7882 Double_t xlab2 = Hparam.xmax;
7883 Double_t ylab1 = Hparam.ymin;
7884 Double_t ylab2 = Hparam.ymax;
7885 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
7886 Double_t deltaz = TMath::Abs(zmin);
7887 if (deltaz == 0) deltaz = 1;
7888 if (zmin >= zmax) {
7889 zmin -= 0.5*deltaz;
7890 zmax += 0.5*deltaz;
7891 }
7892 Double_t z1c = zmin;
7893 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
7894
7895 // Compute the lego limits and instantiate a lego object
7896 fXbuf[0] = -1;
7897 fYbuf[0] = 1;
7898 fXbuf[1] = -1;
7899 fYbuf[1] = 1;
7900 if (Hoption.System == kPOLAR) {
7901 fXbuf[2] = z1c;
7902 fYbuf[2] = z2c;
7903 } else if (Hoption.System == kCYLINDRICAL) {
7904 if (Hoption.Logy) {
7905 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
7906 else fXbuf[2] = 0;
7907 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
7908 else fYbuf[2] = 0;
7909 } else {
7910 fXbuf[2] = ylab1;
7911 fYbuf[2] = ylab2;
7912 }
7913 z1c = 0; z2c = 1;
7914 } else if (Hoption.System == kSPHERICAL) {
7915 fXbuf[2] = -1;
7916 fYbuf[2] = 1;
7917 z1c = 0; z2c = 1;
7918 } else if (Hoption.System == kRAPIDITY) {
7919 fXbuf[2] = -1/TMath::Tan(dangle);
7920 fYbuf[2] = 1/TMath::Tan(dangle);
7921 } else {
7922 fXbuf[0] = xlab1;
7923 fYbuf[0] = xlab2;
7924 fXbuf[1] = ylab1;
7925 fYbuf[1] = ylab2;
7926 fXbuf[2] = z1c;
7927 fYbuf[2] = z2c;
7928 raster = 0;
7929 }
7930
7932
7933 Int_t nids = -1;
7934 TH1 * hid = NULL;
7935 Color_t colormain = -1, colordark = -1;
7936 Bool_t drawShadowsInLego1 = kTRUE;
7937
7938 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
7939 if (Hoption.Lego == 13) {
7940 Hoption.Lego = 11;
7941 fLego->SetMesh(0);
7942 }
7943 // LEGO4 is like LEGO1 except no shadows are drawn.
7944 if (Hoption.Lego == 14) {
7945 Hoption.Lego = 11;
7946 drawShadowsInLego1 = kFALSE;
7947 }
7948
7949 // Create axis object
7950
7951 TGaxis *axis = new TGaxis();
7952
7953 // Initialize the levels on the Z axis
7954 Int_t ndiv = fH->GetContour();
7955 if (ndiv == 0 ) {
7956 ndiv = gStyle->GetNumberContours();
7957 fH->SetContour(ndiv);
7958 }
7959 Int_t ndivz = TMath::Abs(ndiv);
7960 if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
7961
7962 // Initialize colors
7963 if (!fStack) {
7965 } else {
7966 for (Int_t id=0;id<=fStack->GetSize();id++) {
7967 hid = (TH1*)fStack->At((id==0)?id:id-1);
7969 }
7970 }
7971
7972 if (Hoption.Lego == 11) {
7973 nids = 1;
7974 if (fStack) nids = fStack->GetSize();
7975 hid = fH;
7976 for (Int_t id=0;id<=nids;id++) {
7977 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
7978 colormain = hid->GetFillColor();
7979 if (colormain == 1) colormain = 17; //avoid drawing with black
7980 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
7981 else colordark = colormain;
7982 fLego->SetColorMain(colormain,id);
7983 fLego->SetColorDark(colordark,id);
7984 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
7985 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
7986 }
7987 }
7988
7989 // Now ready to draw the lego plot
7990 Int_t irep = 0;
7991
7992 TView *view = gPad->GetView();
7993 if (!view) {
7994 Error("PaintLego", "no TView in current pad");
7995 return;
7996 }
7997
7998 Double_t thedeg = 90 - gPad->GetTheta();
7999 Double_t phideg = -90 - gPad->GetPhi();
8000 Double_t psideg = view->GetPsi();
8001 view->SetView(phideg, thedeg, psideg, irep);
8002
8003 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8005
8006 // Set color/style for back box
8007 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8008 fLego->SetFillColor(gPad->GetFrameFillColor());
8009 fLego->TAttFill::Modify();
8010
8011 Int_t backcolor = gPad->GetFrameFillColor();
8012 if (Hoption.System != kCARTESIAN) backcolor = 0;
8013 view->PadRange(backcolor);
8014
8017 fLego->TAttFill::Modify();
8018
8020
8021 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8022 else fLego->InitMoveScreen(-1.1,1.1);
8023
8024 if (Hoption.Lego == 19) {
8026 if (Hoption.BackBox) fLego->BackBox(90);
8027 if (Hoption.FrontBox) fLego->FrontBox(90);
8028 if (!Hoption.Axis) PaintLegoAxis(axis, 90);
8029 return;
8030 }
8031
8032 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8035 fLego->BackBox(90);
8036 }
8037 }
8038
8039 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8040
8045 if (Hoption.System == kPOLAR) {
8046 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8047 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8048 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8049 } else if (Hoption.System == kCYLINDRICAL) {
8050 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8051 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8052 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8053 } else if (Hoption.System == kSPHERICAL) {
8054 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8055 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8056 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8057 } else if (Hoption.System == kRAPIDITY) {
8058 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8059 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8060 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8061 } else {
8062 if (Hoption.Lego == 1) {
8064 fLego->LegoCartesian(90,nx,ny,"FB");}
8065 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8066 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8067 }
8068
8069 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8072 fLego->BackBox(90);
8073 }
8074 }
8075 if (Hoption.System == kCARTESIAN) {
8076 fLego->InitMoveScreen(-1.1,1.1);
8078 if (Hoption.FrontBox) fLego->FrontBox(90);
8079 }
8080 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
8082 delete axis;
8083 delete fLego; fLego = 0;
8084}
8085
8086////////////////////////////////////////////////////////////////////////////////
8087/// Draw the axis for legos and surface plots.
8088
8090{
8091
8092 static Double_t epsil = 0.001;
8093
8094 Double_t cosa, sina;
8095 Double_t bmin, bmax;
8096 Double_t r[24] /* was [3][8] */;
8097 Int_t ndivx, ndivy, ndivz, i;
8098 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8099 static char chopax[8], chopay[8], chopaz[8];
8100 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8101 Double_t rad;
8102
8103 TView *view = gPad->GetView();
8104 if (!view) {
8105 Error("PaintLegoAxis", "no TView in current pad");
8106 return;
8107 }
8108
8109 // In polar coordinates, draw a short line going from the external circle
8110 // corresponding to r = 1 up to r = 1.1
8111 if (Hoption.System == kPOLAR) {
8112 r[0] = 1;
8113 r[1] = 0;
8114 r[2] = 0;
8115 view->WCtoNDC(r, x1);
8116 r[0] = 1.1;
8117 r[1] = 0;
8118 r[2] = 0;
8119 view->WCtoNDC(r, x2);
8120 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8121 return;
8122 }
8123
8124 if (Hoption.System != kCARTESIAN) return;
8125
8126 rad = TMath::ATan(1.) * 4. /180.;
8127 cosa = TMath::Cos(ang*rad);
8128 sina = TMath::Sin(ang*rad);
8129
8130 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8131 for (i = 1; i <= 8; ++i) {
8132 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8133 r[i*3 - 2] = av[i*3 - 2]*sina;
8134 r[i*3 - 1] = av[i*3 - 1];
8135 }
8136
8137 view->WCtoNDC(&r[ix1*3 - 3], x1);
8138 view->WCtoNDC(&r[ix2*3 - 3], x2);
8139 view->WCtoNDC(&r[iy1*3 - 3], y1);
8140 view->WCtoNDC(&r[iy2*3 - 3], y2);
8141 view->WCtoNDC(&r[iz1*3 - 3], z1);
8142 view->WCtoNDC(&r[iz2*3 - 3], z2);
8143
8144 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8145
8146 Double_t *rmin = view->GetRmin();
8147 Double_t *rmax = view->GetRmax();
8148 if (!rmin || !rmax) return;
8149
8150 // Initialize the axis options
8151 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8152 else strlcpy(chopax, "SDH=-",8);
8153 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8154 else strlcpy(chopay, "SDH=-",8);
8155 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8156 else strlcpy(chopaz, "SDH=-",8);
8157
8158 // Option LOG is required ?
8159 if (Hoption.Logx) strlcat(chopax,"G",8);
8160 if (Hoption.Logy) strlcat(chopay,"G",8);
8161 if (Hoption.Logz) strlcat(chopaz,"G",8);
8162
8163 // Initialize the number of divisions. If the
8164 // number of divisions is negative, option 'N' is required.
8165 ndivx = fXaxis->GetNdivisions();
8166 ndivy = fYaxis->GetNdivisions();
8167 ndivz = fZaxis->GetNdivisions();
8168 if (ndivx < 0) {
8169 ndivx = TMath::Abs(ndivx);
8170 strlcat(chopax, "N",8);
8171 }
8172 if (ndivy < 0) {
8173 ndivy = TMath::Abs(ndivy);
8174 strlcat(chopay, "N",8);
8175 }
8176 if (ndivz < 0) {
8177 ndivz = TMath::Abs(ndivz);
8178 strlcat(chopaz, "N",8);
8179 }
8180
8181 // Set Axis attributes.
8182 // The variable SCALE rescales the VSIZ
8183 // in order to have the same label size for all angles.
8184
8185 axis->SetLineWidth(1);
8186
8187 // X axis drawing
8188 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8191 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8192 bmin = TMath::Power(10, rmin[0]);
8193 bmax = TMath::Power(10, rmax[0]);
8194 } else {
8195 bmin = rmin[0];
8196 bmax = rmax[0];
8197 }
8198 // Option time display is required ?
8199 if (fXaxis->GetTimeDisplay()) {
8200 strlcat(chopax,"t",8);
8201 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8202 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8203 } else {
8205 }
8206 }
8207 axis->SetOption(chopax);
8208 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8209 }
8210
8211 // Y axis drawing
8212 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8215 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8216
8217 if (fH->GetDimension() < 2) {
8218 strlcpy(chopay, "V=+UN",8);
8219 ndivy = 0;
8220 }
8221 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8222 y2[0] = y1[0];
8223 }
8224 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8225 bmin = TMath::Power(10, rmin[1]);
8226 bmax = TMath::Power(10, rmax[1]);
8227 } else {
8228 bmin = rmin[1];
8229 bmax = rmax[1];
8230 }
8231 // Option time display is required ?
8232 if (fYaxis->GetTimeDisplay()) {
8233 strlcat(chopay,"t",8);
8234 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8235 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8236 } else {
8238 }
8239 }
8240 axis->SetOption(chopay);
8241 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8242 }
8243
8244 // Z axis drawing
8245 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8247 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8248 bmin = TMath::Power(10, rmin[2]);
8249 bmax = TMath::Power(10, rmax[2]);
8250 } else {
8251 bmin = rmin[2];
8252 bmax = rmax[2];
8253 }
8254 // Option time display is required ?
8255 if (fZaxis->GetTimeDisplay()) {
8256 strlcat(chopaz,"t",8);
8257 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8258 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8259 } else {
8261 }
8262 }
8263 axis->SetOption(chopaz);
8264 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8265 }
8266
8267 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8268}
8269
8270////////////////////////////////////////////////////////////////////////////////
8271/// [Paint the color palette on the right side of the pad.](#HP22)
8272
8274{
8275
8276 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8277 TView *view = gPad->GetView();
8278 if (palette) {
8279 if (view) {
8280 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8281 fFunctions->Remove(palette);
8282 delete palette; palette = 0;
8283 }
8284 } else {
8285 if (palette->TestBit(TPaletteAxis::kHasView)) {
8286 fFunctions->Remove(palette);
8287 delete palette; palette = 0;
8288 }
8289 }
8290 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8291 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8292 }
8293
8294 if (!palette) {
8295 Double_t xup = gPad->GetUxmax();
8296 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8297 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8298 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8299 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8300 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8301 Double_t xmax = gPad->PadtoX(xup + xr);
8302 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8303 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8304 fFunctions->AddFirst(palette);
8305 palette->Paint();
8306 }
8307}
8308
8309////////////////////////////////////////////////////////////////////////////////
8310/// [Control function to draw a 2D histogram as a scatter plot.](#HP11)
8311
8313{
8314
8315 fH->TAttMarker::Modify();
8316
8317 Int_t k, marker;
8318 Double_t dz, z, xk,xstep, yk, ystep;
8319 Double_t scale = 1;
8320 Bool_t ltest = kFALSE;
8321 Double_t zmax = fH->GetMaximum();
8322 Double_t zmin = fH->GetMinimum();
8323 if (zmin == 0 && zmax == 0) return;
8324 if (zmin == zmax) {
8325 zmax += 0.1*TMath::Abs(zmax);
8326 zmin -= 0.1*TMath::Abs(zmin);
8327 }
8329 if (Hoption.Logz) {
8330 if (zmin > 0) zmin = TMath::Log10(zmin);
8331 else zmin = 0;
8332 if (zmax > 0) zmax = TMath::Log10(zmax);
8333 else zmax = 0;
8334 if (zmin == 0 && zmax == 0) return;
8335 dz = zmax - zmin;
8336 scale = 100/dz;
8337 if (ncells > 10000) scale /= 5;
8338 ltest = kTRUE;
8339 } else {
8340 dz = zmax - zmin;
8341 if (dz >= kNMAX || zmax < 1) {
8342 scale = (kNMAX-1)/dz;
8343 if (ncells > 10000) scale /= 5;
8344 ltest = kTRUE;
8345 }
8346 }
8347 if (fH->GetMinimumStored() == -1111) {
8348 Double_t yMARGIN = gStyle->GetHistTopMargin();
8349 if (Hoption.MinimumZero) {
8350 if (zmin >= 0) zmin = 0;
8351 else zmin -= yMARGIN*(zmax-zmin);
8352 } else {
8353 Double_t dzmin = yMARGIN*(zmax-zmin);
8354 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8355 else zmin -= dzmin;
8356 }
8357 }
8358
8359 TString opt = option;
8360 opt.ToLower();
8361 if (opt.Contains("scat=")) {
8362 char optscat[100];
8363 strlcpy(optscat,opt.Data(),100);
8364 char *oscat = strstr(optscat,"scat=");
8365 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8366 sscanf(oscat+5,"%lg",&scale);
8367 }
8368 // use an independent instance of a random generator
8369 // instead of gRandom to avoid conflicts and
8370 // to get same random numbers when drawing the same histogram
8371 TRandom2 random;
8372 marker=0;
8373 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8374 yk = fYaxis->GetBinLowEdge(j);
8375 ystep = fYaxis->GetBinWidth(j);
8376 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8377 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8378 xk = fXaxis->GetBinLowEdge(i);
8379 xstep = fXaxis->GetBinWidth(i);
8380 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8381 z = fH->GetBinContent(bin);
8382 if (z < zmin) z = zmin;
8383 if (z > zmax) z = zmax;
8384 if (Hoption.Logz) {
8385 if (z > 0) z = TMath::Log10(z) - zmin;
8386 } else {
8387 z -= zmin;
8388 }
8389 if (z <= 0) continue;
8390 k = Int_t(z*scale);
8391 if (ltest) k++;
8392 if (k > 0) {
8393 for (Int_t loop=0; loop<k; loop++) {
8394 if (k+marker >= kNMAX) {
8395 gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
8396 marker=0;
8397 }
8398 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8399 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8400 if (Hoption.Logx) {
8401 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8402 else break;
8403 }
8404 if (Hoption.Logy) {
8405 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8406 else break;
8407 }
8408 if (fXbuf[marker] < gPad->GetUxmin()) break;
8409 if (fYbuf[marker] < gPad->GetUymin()) break;
8410 if (fXbuf[marker] > gPad->GetUxmax()) break;
8411 if (fYbuf[marker] > gPad->GetUymax()) break;
8412 marker++;
8413 }
8414 }
8415 }
8416 }
8417 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
8418
8420}
8421
8422////////////////////////////////////////////////////////////////////////////////
8423/// Static function to paint special objects like vectors and matrices.
8424/// This function is called via `gROOT->ProcessLine` to paint these objects
8425/// without having a direct dependency of the graphics or histogramming
8426/// system.
8427
8429{
8430
8431 if (!obj) return;
8434
8435 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8436 // case TMatrixF
8437 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8438 R__TMatrixFBase->SetBit(kCanDelete);
8439 R__TMatrixFBase->Draw(option);
8440
8441 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8442 // case TMatrixD
8443 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8444 R__TMatrixDBase->SetBit(kCanDelete);
8445 R__TMatrixDBase->Draw(option);
8446
8447 } else if (obj->InheritsFrom(TVectorF::Class())) {
8448 //case TVectorF
8449 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8450 R__TVectorF->SetBit(kCanDelete);
8451 R__TVectorF->Draw(option);
8452
8453 } else if (obj->InheritsFrom(TVectorD::Class())) {
8454 //case TVectorD
8455 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8456 R__TVectorD->SetBit(kCanDelete);
8457 R__TVectorD->Draw(option);
8458 }
8459
8460 TH1::AddDirectory(status);
8461}
8462
8463////////////////////////////////////////////////////////////////////////////////
8464/// [Draw the statistics box for 1D and profile histograms.](#HP07)
8465
8467{
8468
8469 TString tt, tf;
8470 Int_t dofit;
8471 TPaveStats *stats = 0;
8472 TIter next(fFunctions);
8473 TObject *obj;
8474 while ((obj = next())) {
8475 if (obj->InheritsFrom(TPaveStats::Class())) {
8476 stats = (TPaveStats*)obj;
8477 break;
8478 }
8479 }
8480
8481 if (stats && dostat) {
8482 dofit = stats->GetOptFit();
8483 dostat = stats->GetOptStat();
8484 } else {
8485 dofit = gStyle->GetOptFit();
8486 }
8487 if (!dofit) fit = 0;
8488 if (dofit == 1) dofit = 111;
8489 if (dostat == 1) dostat = 1111;
8490 Int_t print_name = dostat%10;
8491 Int_t print_entries = (dostat/10)%10;
8492 Int_t print_mean = (dostat/100)%10;
8493 Int_t print_stddev = (dostat/1000)%10;
8494 Int_t print_under = (dostat/10000)%10;
8495 Int_t print_over = (dostat/100000)%10;
8496 Int_t print_integral= (dostat/1000000)%10;
8497 Int_t print_skew = (dostat/10000000)%10;
8498 Int_t print_kurt = (dostat/100000000)%10;
8499 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8500 print_under + print_over + print_integral +
8501 print_skew + print_kurt;
8502 Int_t print_fval = dofit%10;
8503 Int_t print_ferrors = (dofit/10)%10;
8504 Int_t print_fchi2 = (dofit/100)%10;
8505 Int_t print_fprob = (dofit/1000)%10;
8506 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8507 if (fit) {
8508 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8509 else nlinesf += fit->GetNpar();
8510 }
8511 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8512
8513 // Pavetext with statistics
8514 Bool_t done = kFALSE;
8515 if (!dostat && !fit) {
8516 if (stats) { fFunctions->Remove(stats); delete stats;}
8517 return;
8518 }
8519 Double_t statw = gStyle->GetStatW();
8520 if (fit) statw = 1.8*gStyle->GetStatW();
8521 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8522 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8523 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8524 }
8525 if (stats) {
8526 stats->Clear();
8527 done = kTRUE;
8528 } else {
8529 stats = new TPaveStats(
8530 gStyle->GetStatX()-statw,
8531 gStyle->GetStatY()-stath,
8532 gStyle->GetStatX(),
8533 gStyle->GetStatY(),"brNDC");
8534
8535 stats->SetParent(fH);
8536 stats->SetOptFit(dofit);
8537 stats->SetOptStat(dostat);
8538 stats->SetFillColor(gStyle->GetStatColor());
8539 stats->SetFillStyle(gStyle->GetStatStyle());
8541 stats->SetTextFont(gStyle->GetStatFont());
8542 if (gStyle->GetStatFont()%10 > 2)
8544 stats->SetFitFormat(gStyle->GetFitFormat());
8546 stats->SetName("stats");
8547
8549 stats->SetTextAlign(12);
8550 stats->SetBit(kCanDelete);
8551 stats->SetBit(kMustCleanup);
8552 }
8553 if (print_name) stats->AddText(fH->GetName());
8554 if (print_entries) {
8555 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8556 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8557 stats->AddText(tt.Data());
8558 }
8559 if (print_mean) {
8560 if (print_mean == 1) {
8561 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8562 tt.Form(tf.Data(),fH->GetMean(1));
8563 } else {
8564 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8565 ,"%",stats->GetStatFormat());
8566 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8567 }
8568 stats->AddText(tt.Data());
8569 if (fH->InheritsFrom(TProfile::Class())) {
8570 if (print_mean == 1) {
8571 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8572 tt.Form(tf.Data(),fH->GetMean(2));
8573 } else {
8574 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8575 ,"%",stats->GetStatFormat());
8576 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8577 }
8578 stats->AddText(tt.Data());
8579 }
8580 }
8581 if (print_stddev) {
8582 if (print_stddev == 1) {
8583 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8584 tt.Form(tf.Data(),fH->GetStdDev(1));
8585 } else {
8586 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8587 ,"%",stats->GetStatFormat());
8588 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8589 }
8590 stats->AddText(tt.Data());
8591 if (fH->InheritsFrom(TProfile::Class())) {
8592 if (print_stddev == 1) {
8593 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8594 tt.Form(tf.Data(),fH->GetStdDev(2));
8595 } else {
8596 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8597 ,"%",stats->GetStatFormat());
8598 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8599 }
8600 stats->AddText(tt.Data());
8601 }
8602 }
8603 if (print_under) {
8604 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8605 tt.Form(tf.Data(),fH->GetBinContent(0));
8606 stats->AddText(tt.Data());
8607 }
8608 if (print_over) {
8609 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8610 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8611 stats->AddText(tt.Data());
8612 }
8613 if (print_integral) {
8614 if (print_integral == 1) {
8615 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8616 tt.Form(tf.Data(),fH->Integral());
8617 } else {
8618 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8619 tt.Form(tf.Data(),fH->Integral("width"));
8620 }
8621 stats->AddText(tt.Data());
8622 }
8623 if (print_skew) {
8624 if (print_skew == 1) {
8625 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8626 tt.Form(tf.Data(),fH->GetSkewness(1));
8627 } else {
8628 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8629 ,"%",stats->GetStatFormat());
8630 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8631 }
8632 stats->AddText(tt.Data());
8633 }
8634 if (print_kurt) {
8635 if (print_kurt == 1) {
8636 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8637 tt.Form(tf.Data(),fH->GetKurtosis(1));
8638 } else {
8639 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8640 ,"%",stats->GetStatFormat());
8641 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8642 }
8643 stats->AddText(tt.Data());
8644 }
8645
8646 // Draw Fit parameters
8647 if (fit) {
8648 Int_t ndf = fit->GetNDF();
8649 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8650 tt.Form(tf.Data(),(Float_t)fit->GetChisquare());
8651 if (print_fchi2) stats->AddText(tt.Data());
8652 if (print_fprob) {
8653 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8654 tt.Form(tf.Data(),(Float_t)TMath::Prob(fit->GetChisquare(),ndf));
8655 stats->AddText(tt.Data());
8656 }
8657 if (print_fval || print_ferrors) {
8658 Double_t parmin,parmax;
8659 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8660 fit->GetParLimits(ipar,parmin,parmax);
8661 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8662 if (print_ferrors) {
8663 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8664 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8665 tt.Form(tf.Data(),(Float_t)fit->GetParameter(ipar)
8666 ,(Float_t)fit->GetParError(ipar));
8667 } else {
8668 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8669 tt.Form(tf.Data(),(Float_t)fit->GetParameter(ipar));
8670 }
8671 stats->AddText(tt.Data());
8672 }
8673 }
8674 }
8675
8676 if (!done) fFunctions->Add(stats);
8677 stats->Paint();
8678}
8679
8680////////////////////////////////////////////////////////////////////////////////
8681/// [Draw the statistics box for 2D histograms.](#HP07)
8682
8684{
8685
8686 if (fH->GetDimension() != 2) return;
8687 TH2 *h2 = (TH2*)fH;
8688
8689 TString tt, tf;
8690 Int_t dofit;
8691 TPaveStats *stats = 0;
8692 TIter next(fFunctions);
8693 TObject *obj;
8694 while ((obj = next())) {
8695 if (obj->InheritsFrom(TPaveStats::Class())) {
8696 stats = (TPaveStats*)obj;
8697 break;
8698 }
8699 }
8700 if (stats && dostat) {
8701 dofit = stats->GetOptFit();
8702 dostat = stats->GetOptStat();
8703 } else {
8704 dofit = gStyle->GetOptFit();
8705 }
8706 if (dostat == 1) dostat = 1111;
8707 Int_t print_name = dostat%10;
8708 Int_t print_entries = (dostat/10)%10;
8709 Int_t print_mean = (dostat/100)%10;
8710 Int_t print_stddev = (dostat/1000)%10;
8711 Int_t print_under = (dostat/10000)%10;
8712 Int_t print_over = (dostat/100000)%10;
8713 Int_t print_integral= (dostat/1000000)%10;
8714 Int_t print_skew = (dostat/10000000)%10;
8715 Int_t print_kurt = (dostat/100000000)%10;
8716 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8717 if (print_under || print_over) nlines += 3;
8718
8719 // Pavetext with statistics
8720 if (!gStyle->GetOptFit()) fit = 0;
8721 Bool_t done = kFALSE;
8722 if (!dostat && !fit) {
8723 if (stats) { fFunctions->Remove(stats); delete stats;}
8724 return;
8725 }
8726 Double_t statw = gStyle->GetStatW();
8727 if (fit) statw = 1.8*gStyle->GetStatW();
8728 Double_t stath = nlines*gStyle->GetStatFontSize();
8729 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8730 stath = 0.25*nlines*gStyle->GetStatH();
8731 }
8732 if (fit) stath += gStyle->GetStatH();
8733 if (stats) {
8734 stats->Clear();
8735 done = kTRUE;
8736 } else {
8737 stats = new TPaveStats(
8738 gStyle->GetStatX()-statw,
8739 gStyle->GetStatY()-stath,
8740 gStyle->GetStatX(),
8741 gStyle->GetStatY(),"brNDC");
8742
8743 stats->SetParent(fH);
8744 stats->SetOptFit(dofit);
8745 stats->SetOptStat(dostat);
8746 stats->SetFillColor(gStyle->GetStatColor());
8747 stats->SetFillStyle(gStyle->GetStatStyle());
8749 stats->SetName("stats");
8750
8752 stats->SetTextAlign(12);
8753 stats->SetTextFont(gStyle->GetStatFont());
8754 if (gStyle->GetStatFont()%10 > 2)
8756 stats->SetFitFormat(gStyle->GetFitFormat());
8758 stats->SetBit(kCanDelete);
8759 stats->SetBit(kMustCleanup);
8760 }
8761 if (print_name) stats->AddText(h2->GetName());
8762 if (print_entries) {
8763 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8764 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8765 stats->AddText(tt.Data());
8766 }
8767 if (print_mean) {
8768 if (print_mean == 1) {
8769 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8770 tt.Form(tf.Data(),h2->GetMean(1));
8771 stats->AddText(tt.Data());
8772 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8773 tt.Form(tf.Data(),h2->GetMean(2));
8774 stats->AddText(tt.Data());
8775 } else {
8776 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8777 ,"%",stats->GetStatFormat());
8778 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8779 stats->AddText(tt.Data());
8780 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8781 ,"%",stats->GetStatFormat());
8782 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8783 stats->AddText(tt.Data());
8784 }
8785 }
8786 if (print_stddev) {
8787 if (print_stddev == 1) {
8788 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8789 tt.Form(tf.Data(),h2->GetStdDev(1));
8790 stats->AddText(tt.Data());
8791 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8792 tt.Form(tf.Data(),h2->GetStdDev(2));
8793 stats->AddText(tt.Data());
8794 } else {
8795 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8796 ,"%",stats->GetStatFormat());
8797 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8798 stats->AddText(tt.Data());
8799 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8800 ,"%",stats->GetStatFormat());
8801 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8802 stats->AddText(tt.Data());
8803 }
8804 }
8805 if (print_integral) {
8806 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8807 tt.Form(tf.Data(),fH->Integral());
8808 stats->AddText(tt.Data());
8809 }
8810 if (print_skew) {
8811 if (print_skew == 1) {
8812 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8813 tt.Form(tf.Data(),h2->GetSkewness(1));
8814 stats->AddText(tt.Data());
8815 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8816 tt.Form(tf.Data(),h2->GetSkewness(2));
8817 stats->AddText(tt.Data());
8818 } else {
8819 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8820 ,"%",stats->GetStatFormat());
8821 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8822 stats->AddText(tt.Data());
8823 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8824 ,"%",stats->GetStatFormat());
8825 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8826 stats->AddText(tt.Data());
8827 }
8828 }
8829 if (print_kurt) {
8830 if (print_kurt == 1) {
8831 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8832 tt.Form(tf.Data(),h2->GetKurtosis(1));
8833 stats->AddText(tt.Data());
8834 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8835 tt.Form(tf.Data(),h2->GetKurtosis(2));
8836 stats->AddText(tt.Data());
8837 } else {
8838 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8839 ,"%",stats->GetStatFormat());
8840 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
8841 stats->AddText(tt.Data());
8842 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8843 ,"%",stats->GetStatFormat());
8844 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
8845 stats->AddText(tt.Data());
8846 }
8847 }
8848 if (print_under || print_over) {
8849 //get 3*3 under/overflows for 2d hist
8850 Double_t unov[9];
8851
8852 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8853 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8854 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
8855 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
8856 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
8857 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
8858
8859 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
8860 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
8861 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
8862 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
8863 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
8864 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
8865 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
8866 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
8867 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
8868
8869 tt.Form(" %7d|%7d|%7d\n", (Int_t)unov[0], (Int_t)unov[1], (Int_t)unov[2]);
8870 stats->AddText(tt.Data());
8871 if (TMath::Abs(unov[4]) < 1.e7)
8872 tt.Form(" %7d|%7d|%7d\n", (Int_t)unov[3], (Int_t)unov[4], (Int_t)unov[5]);
8873 else
8874 tt.Form(" %7d|%14.7g|%7d\n", (Int_t)unov[3], (Float_t)unov[4], (Int_t)unov[5]);
8875 stats->AddText(tt.Data());
8876 tt.Form(" %7d|%7d|%7d\n", (Int_t)unov[6], (Int_t)unov[7], (Int_t)unov[8]);
8877 stats->AddText(tt.Data());
8878 }
8879
8880 // Draw Fit parameters
8881 if (fit) {
8882 Int_t ndf = fit->GetNDF();
8883 tt.Form("#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
8884 stats->AddText(tt.Data());
8885 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8886 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
8887 ,(Float_t)fit->GetParameter(ipar)
8888 ,(Float_t)fit->GetParError(ipar));
8889 stats->AddText(tt.Data());
8890 }
8891 }
8892
8893 if (!done) fFunctions->Add(stats);
8894 stats->Paint();
8895}
8896
8897////////////////////////////////////////////////////////////////////////////////
8898/// [Draw the statistics box for 3D histograms.](#HP07)
8899
8901{
8902
8903 if (fH->GetDimension() != 3) return;
8904 TH3 *h3 = (TH3*)fH;
8905
8906 TString tt, tf;
8907 Int_t dofit;
8908 TPaveStats *stats = 0;
8909 TIter next(fFunctions);
8910 TObject *obj;
8911 while ((obj = next())) {
8912 if (obj->InheritsFrom(TPaveStats::Class())) {
8913 stats = (TPaveStats*)obj;
8914 break;
8915 }
8916 }
8917 if (stats && dostat) {
8918 dofit = stats->GetOptFit();
8919 dostat = stats->GetOptStat();
8920 } else {
8921 dofit = gStyle->GetOptFit();
8922 }
8923 if (dostat == 1) dostat = 1111;
8924 Int_t print_name = dostat%10;
8925 Int_t print_entries = (dostat/10)%10;
8926 Int_t print_mean = (dostat/100)%10;
8927 Int_t print_stddev = (dostat/1000)%10;
8928 Int_t print_under = (dostat/10000)%10;
8929 Int_t print_over = (dostat/100000)%10;
8930 Int_t print_integral= (dostat/1000000)%10;
8931 Int_t print_skew = (dostat/10000000)%10;
8932 Int_t print_kurt = (dostat/100000000)%10;
8933 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
8934 if (print_under || print_over) nlines += 3;
8935
8936 // Pavetext with statistics
8937 if (!gStyle->GetOptFit()) fit = 0;
8938 Bool_t done = kFALSE;
8939 if (!dostat && !fit) {
8940 if (stats) { fFunctions->Remove(stats); delete stats;}
8941 return;
8942 }
8943 Double_t statw = gStyle->GetStatW();
8944 if (fit) statw = 1.8*gStyle->GetStatW();
8945 Double_t stath = nlines*gStyle->GetStatFontSize();
8946 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8947 stath = 0.25*nlines*gStyle->GetStatH();
8948 }
8949 if (fit) stath += gStyle->GetStatH();
8950 if (stats) {
8951 stats->Clear();
8952 done = kTRUE;
8953 } else {
8954 stats = new TPaveStats(
8955 gStyle->GetStatX()-statw,
8956 gStyle->GetStatY()-stath,
8957 gStyle->GetStatX(),
8958 gStyle->GetStatY(),"brNDC");
8959
8960 stats->SetParent(fH);
8961 stats->SetOptFit(dofit);
8962 stats->SetOptStat(dostat);
8963 stats->SetFillColor(gStyle->GetStatColor());
8964 stats->SetFillStyle(gStyle->GetStatStyle());
8966 stats->SetName("stats");
8967
8969 stats->SetTextAlign(12);
8970 stats->SetTextFont(gStyle->GetStatFont());
8971 stats->SetFitFormat(gStyle->GetFitFormat());
8973 stats->SetBit(kCanDelete);
8974 stats->SetBit(kMustCleanup);
8975 }
8976 if (print_name) stats->AddText(h3->GetName());
8977 if (print_entries) {
8978 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
8979 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
8980 stats->AddText(tt.Data());
8981 }
8982 if (print_mean) {
8983 if (print_mean == 1) {
8984 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8985 tt.Form(tf.Data(),h3->GetMean(1));
8986 stats->AddText(tt.Data());
8987 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8988 tt.Form(tf.Data(),h3->GetMean(2));
8989 stats->AddText(tt.Data());
8990 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
8991 tt.Form(tf.Data(),h3->GetMean(3));
8992 stats->AddText(tt.Data());
8993 } else {
8994 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8995 ,"%",stats->GetStatFormat());
8996 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
8997 stats->AddText(tt.Data());
8998 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8999 ,"%",stats->GetStatFormat());
9000 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9001 stats->AddText(tt.Data());
9002 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9003 ,"%",stats->GetStatFormat());
9004 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9005 stats->AddText(tt.Data());
9006 }
9007 }
9008 if (print_stddev) {
9009 if (print_stddev == 1) {
9010 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9011 tt.Form(tf.Data(),h3->GetStdDev(1));
9012 stats->AddText(tt.Data());
9013 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9014 tt.Form(tf.Data(),h3->GetStdDev(2));
9015 stats->AddText(tt.Data());
9016 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9017 tt.Form(tf.Data(),h3->GetStdDev(3));
9018 stats->AddText(tt.Data());
9019 } else {
9020 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9021 ,"%",stats->GetStatFormat());
9022 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9023 stats->AddText(tt.Data());
9024 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9025 ,"%",stats->GetStatFormat());
9026 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9027 stats->AddText(tt.Data());
9028 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9029 ,"%",stats->GetStatFormat());
9030 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9031 stats->AddText(tt.Data());
9032 }
9033 }
9034 if (print_integral) {
9035 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9036 stats->AddText(tt.Data());
9037 }
9038 if (print_skew) {
9039 if (print_skew == 1) {
9040 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9041 tt.Form(tf.Data(),h3->GetSkewness(1));
9042 stats->AddText(tt.Data());
9043 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9044 tt.Form(tf.Data(),h3->GetSkewness(2));
9045 stats->AddText(tt.Data());
9046 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9047 tt.Form(tf.Data(),h3->GetSkewness(3));
9048 stats->AddText(tt.Data());
9049 } else {
9050 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9051 ,"%",stats->GetStatFormat());
9052 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9053 stats->AddText(tt.Data());
9054 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9055 ,"%",stats->GetStatFormat());
9056 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9057 stats->AddText(tt.Data());
9058 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9059 ,"%",stats->GetStatFormat());
9060 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9061 stats->AddText(tt.Data());
9062 }
9063 }
9064 if (print_kurt) {
9065 if (print_kurt == 1) {
9066 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9067 tt.Form(tf.Data(),h3->GetKurtosis(1));
9068 stats->AddText(tt.Data());
9069 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9070 tt.Form(tf.Data(),h3->GetKurtosis(2));
9071 stats->AddText(tt.Data());
9072 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9073 tt.Form(tf.Data(),h3->GetKurtosis(3));
9074 stats->AddText(tt.Data());
9075 } else {
9076 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9077 ,"%",stats->GetStatFormat());
9078 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9079 stats->AddText(tt.Data());
9080 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9081 ,"%",stats->GetStatFormat());
9082 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9083 stats->AddText(tt.Data());
9084 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9085 ,"%",stats->GetStatFormat());
9086 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9087 stats->AddText(tt.Data());
9088 }
9089 }
9090 if (print_under || print_over) {
9091 // no underflow - overflow printing for a 3D histogram
9092 // one would need a 3D table
9093 }
9094
9095 // Draw Fit parameters
9096 if (fit) {
9097 Int_t ndf = fit->GetNDF();
9098 tt.Form("#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
9099 stats->AddText(tt.Data());
9100 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9101 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9102 ,(Float_t)fit->GetParameter(ipar)
9103 ,(Float_t)fit->GetParError(ipar));
9104 stats->AddText(tt.Data());
9105 }
9106 }
9107
9108 if (!done) fFunctions->Add(stats);
9109 stats->Paint();
9110}
9111
9112////////////////////////////////////////////////////////////////////////////////
9113/// [Control function to draw a 2D histogram as a surface plot.](#HP18)
9114
9116{
9117
9118 const Double_t ydiff = 1;
9119 const Double_t yligh1 = 10;
9120 const Double_t qa = 0.15;
9121 const Double_t qd = 0.15;
9122 const Double_t qs = 0.8;
9123 Double_t fmin, fmax;
9124 Int_t raster = 0;
9125 Int_t irep = 0;
9126
9127 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9130 Double_t zmin = Hparam.zmin;
9131 Double_t zmax = Hparam.zmax;
9132 Double_t xlab1 = Hparam.xmin;
9133 Double_t xlab2 = Hparam.xmax;
9134 Double_t ylab1 = Hparam.ymin;
9135 Double_t ylab2 = Hparam.ymax;
9136 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9137 Double_t deltaz = TMath::Abs(zmin);
9138 if (deltaz == 0) deltaz = 1;
9139 if (zmin >= zmax) {
9140 zmin -= 0.5*deltaz;
9141 zmax += 0.5*deltaz;
9142 }
9143 Double_t z1c = zmin;
9144 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9145 // Compute the lego limits and instantiate a lego object
9146 fXbuf[0] = -1;
9147 fYbuf[0] = 1;
9148 fXbuf[1] = -1;
9149 fYbuf[1] = 1;
9150 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9151 if (Hoption.System == kPOLAR) {
9152 fXbuf[2] = z1c;
9153 fYbuf[2] = z2c;
9154 } else if (Hoption.System == kCYLINDRICAL) {
9155 if (Hoption.Logy) {
9156 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9157 else fXbuf[2] = 0;
9158 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9159 else fYbuf[2] = 0;
9160 } else {
9161 fXbuf[2] = ylab1;
9162 fYbuf[2] = ylab2;
9163 }
9164 z1c = 0; z2c = 1;
9165 } else if (Hoption.System == kSPHERICAL) {
9166 fXbuf[2] = -1;
9167 fYbuf[2] = 1;
9168 z1c = 0; z2c = 1;
9169 } else if (Hoption.System == kRAPIDITY) {
9170 fXbuf[2] = -1/TMath::Tan(dangle);
9171 fYbuf[2] = 1/TMath::Tan(dangle);
9172 } else {
9173 fXbuf[0] = xlab1;
9174 fYbuf[0] = xlab2;
9175 fXbuf[1] = ylab1;
9176 fYbuf[1] = ylab2;
9177 fXbuf[2] = z1c;
9178 fYbuf[2] = z2c;
9179 }
9180
9184
9185 // Create axis object
9186
9187 TGaxis *axis = new TGaxis();
9188
9189 // Initialize the levels on the Z axis
9190 Int_t ndiv = fH->GetContour();
9191 if (ndiv == 0 ) {
9192 ndiv = gStyle->GetNumberContours();
9193 fH->SetContour(ndiv);
9194 }
9195 Int_t ndivz = TMath::Abs(ndiv);
9196 if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
9197
9198 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9199 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9200
9201 // Close the surface in case of non cartesian coordinates.
9202
9203 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9204
9205 // Now ready to draw the surface plot
9206
9207 TView *view = gPad->GetView();
9208 if (!view) {
9209 Error("PaintSurface", "no TView in current pad");
9210 return;
9211 }
9212
9213 Double_t thedeg = 90 - gPad->GetTheta();
9214 Double_t phideg = -90 - gPad->GetPhi();
9215 Double_t psideg = view->GetPsi();
9216 view->SetView(phideg, thedeg, psideg, irep);
9217
9218 // Set color/style for back box
9219 if (Hoption.Same) {
9220 fLego->SetFillStyle(0);
9221 fLego->SetFillColor(1);
9222 } else {
9223 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9224 fLego->SetFillColor(gPad->GetFrameFillColor());
9225 }
9226 fLego->TAttFill::Modify();
9227
9228 Int_t backcolor = gPad->GetFrameFillColor();
9229 if (Hoption.System != kCARTESIAN) backcolor = 0;
9230 view->PadRange(backcolor);
9231
9234 fLego->TAttFill::Modify();
9235
9236 // Draw the filled contour on top
9237 Int_t icol1 = fH->GetFillColor();
9238
9239 Int_t hoption35 = Hoption.Surf;
9240 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9241 DefineColorLevels(ndivz);
9242 Hoption.Surf = 23;
9245 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9246 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9247 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9248 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9249 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9250 Hoption.Surf = hoption35;
9251 fLego->SetMesh(1);
9252 }
9253
9254 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9255 else fLego->InitMoveScreen(-1.1,1.1);
9256
9257 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9261 fLego->BackBox(90);
9262 }
9263 }
9264
9265 // Gouraud Shading surface
9266 if (Hoption.Surf == 14) {
9267 // Set light sources
9268 fLego->LightSource(0, ydiff, 0,0,0,irep);
9269 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9270 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9271 fmin = ydiff*qa;
9272 fmax = fmin + (yligh1+0.1)*(qd+qs);
9273 Int_t nbcol = 28;
9274 icol1 = 201;
9275 Double_t dcol = 0.5/Double_t(nbcol);
9276 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9277 if (!colref) return;
9278 Float_t r,g,b,hue,light,satur;
9279 colref->GetRGB(r,g,b);
9280 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9281 TColor *acol;
9282 for (Int_t col=0;col<nbcol;col++) {
9283 acol = gROOT->GetColor(col+icol1);
9284 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9285 if (acol) acol->SetRGB(r,g,b);
9286 }
9287 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9290 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9291 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9292 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9293 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9294 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9295 } else if (Hoption.Surf == 15) {
9296 // The surface is not drawn in this case.
9297 } else {
9298 // Draw the surface
9299 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9300 DefineColorLevels(ndivz);
9301 } else {
9303 }
9307 if (Hoption.System == kPOLAR) {
9308 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9309 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9310 } else if (Hoption.System == kCYLINDRICAL) {
9311 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9312 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9313 } else if (Hoption.System == kSPHERICAL) {
9314 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9315 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9316 } else if (Hoption.System == kRAPIDITY) {
9317 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9318 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9319 } else {
9322 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9323 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9324 }
9325 }
9326
9327 // Paint the line contour on top for option SURF7
9328 if (Hoption.Surf == 17) {
9329 fLego->InitMoveScreen(-1.1,1.1);
9331 Hoption.Surf = 23;
9334 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9335 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9336 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9337 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9338 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9339 }
9340
9341 if ((!Hoption.Same) &&
9342 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9345 fLego->BackBox(90);
9346 }
9347 }
9348 if (Hoption.System == kCARTESIAN) {
9349 fLego->InitMoveScreen(-1.1,1.1);
9351 if (Hoption.FrontBox) fLego->FrontBox(90);
9352 }
9353 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
9354
9356
9357 delete axis;
9358 delete fLego; fLego = 0;
9359}
9360
9361////////////////////////////////////////////////////////////////////////////////
9362/// Control function to draw a table using Delaunay triangles.
9363
9365{
9366
9367 TGraphDelaunay2D *dt = nullptr;
9368 TGraphDelaunay *dtOld = nullptr;
9369
9370 // Check if fH contains a TGraphDelaunay2D
9371 TList *hl = fH->GetListOfFunctions();
9372 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9373 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9374 if (!dt && !dtOld) return;
9375
9376 // If needed, create a TGraph2DPainter
9377 if (!fGraph2DPainter) {
9378 if (dt) fGraph2DPainter = new TGraph2DPainter(dt);
9379 else fGraph2DPainter = new TGraph2DPainter(dtOld);
9380 }
9381
9382 // Define the 3D view
9383 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9384 if (Hoption.Same) {
9385 TView *viewsame = gPad->GetView();
9386 if (!viewsame) {
9387 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9388 return;
9389 }
9390 Double_t *rmin = viewsame->GetRmin();
9391 Double_t *rmax = viewsame->GetRmax();
9392 if (!rmin || !rmax) return;
9393 fXbuf[0] = rmin[0];
9394 fYbuf[0] = rmax[0];
9395 fXbuf[1] = rmin[1];
9396 fYbuf[1] = rmax[1];
9397 fXbuf[2] = rmin[2];
9398 fYbuf[2] = rmax[2];
9399 } else {
9400 fXbuf[0] = Hparam.xmin;
9401 fYbuf[0] = Hparam.xmax;
9402 fXbuf[1] = Hparam.ymin;
9403 fYbuf[1] = Hparam.ymax;
9404 fXbuf[2] = Hparam.zmin;
9405 fYbuf[2] = Hparam.zmax;
9406 }
9407
9409 TView *view = gPad->GetView();
9410 if (!view) {
9411 Error("PaintTriangles", "no TView in current pad");
9412 return;
9413 }
9414 Double_t thedeg = 90 - gPad->GetTheta();
9415 Double_t phideg = -90 - gPad->GetPhi();
9416 Double_t psideg = view->GetPsi();
9417 Int_t irep;
9418 view->SetView(phideg, thedeg, psideg, irep);
9419
9420 // Set color/style for back box
9421 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9422 fLego->SetFillColor(gPad->GetFrameFillColor());
9423 fLego->TAttFill::Modify();
9424 Int_t backcolor = gPad->GetFrameFillColor();
9425 if (Hoption.System != kCARTESIAN) backcolor = 0;
9426 view->PadRange(backcolor);
9429 fLego->TAttFill::Modify();
9430
9431 // Paint the Back Box if needed
9432 if (Hoption.BackBox && !Hoption.Same) {
9433 fLego->InitMoveScreen(-1.1,1.1);
9436 fLego->BackBox(90);
9437 }
9438
9439 // Paint the triangles
9440 fGraph2DPainter->Paint(option);
9441
9442 // Paint the Front Box if needed
9443 if (Hoption.FrontBox) {
9444 fLego->InitMoveScreen(-1.1,1.1);
9446 fLego->FrontBox(90);
9447 }
9448
9449 // Paint the Axis if needed
9450 if (!Hoption.Axis && !Hoption.Same) {
9451 TGaxis *axis = new TGaxis();
9452 PaintLegoAxis(axis, 90);
9453 delete axis;
9454 }
9455
9457
9458 delete fLego; fLego = 0;
9459}
9460
9461////////////////////////////////////////////////////////////////////////////////
9462/// Define the color levels used to paint legos, surfaces etc..
9463
9465{
9466
9467 Int_t i, irep;
9468
9469 // Initialize the color levels
9470 if (ndivz >= 100) {
9471 Warning("PaintSurface", "too many color levels, %d, reset to 8", ndivz);
9472 ndivz = 8;
9473 }
9474 Double_t *funlevel = new Double_t[ndivz+1];
9475 Int_t *colorlevel = new Int_t[ndivz+1];
9476 Int_t theColor;
9477 Int_t ncolors = gStyle->GetNumberOfColors();
9478 for (i = 0; i < ndivz; ++i) {
9479 funlevel[i] = fH->GetContourLevelPad(i);
9480 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9481 colorlevel[i] = gStyle->GetColorPalette(theColor);
9482 }
9483 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9484 fLego->ColorFunction(ndivz, funlevel, colorlevel, irep);
9485 delete [] colorlevel;
9486 delete [] funlevel;
9487}
9488
9489////////////////////////////////////////////////////////////////////////////////
9490/// [Control function to draw 2D/3D histograms (tables).](#HP01c)
9491
9493{
9494
9495 // Fill Hparam structure with histo parameters
9496 if (!TableInit()) return;
9497
9498 // Draw histogram frame
9499 PaintFrame();
9500
9501 // If palette option not specified, delete a possible existing palette
9502 if (!Hoption.Zscale) {
9503 TObject *palette = fFunctions->FindObject("palette");
9504 if (palette) { fFunctions->Remove(palette); delete palette;}
9505 }
9506
9507 // Do not draw the histogram. Only the attached functions will be drawn.
9508 if (Hoption.Func == 2) {
9509 if (Hoption.Zscale) {
9510 Int_t ndiv = fH->GetContour();
9511 if (ndiv == 0 ) {
9512 ndiv = gStyle->GetNumberContours();
9513 fH->SetContour(ndiv);
9514 }
9515 PaintPalette();
9516 }
9517
9518 // Draw the histogram according to the option
9519 } else {
9520 if (fH->InheritsFrom(TH2Poly::Class())) {
9521 if (Hoption.Fill) PaintTH2PolyBins("f");
9524 if (Hoption.Text) PaintTH2PolyText(option);
9525 if (Hoption.Line) PaintTH2PolyBins("l");
9526 if (Hoption.Mark) PaintTH2PolyBins("P");
9527 } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9528 if (Hoption.Scat) PaintScatterPlot(option);
9529 if (Hoption.Arrow) PaintArrows(option);
9530 if (Hoption.Box) PaintBoxes(option);
9531 if (Hoption.Color) {
9532 if (Hoption.Color == 3) PaintColorLevelsFast(option);
9533 else PaintColorLevels(option);
9534 }
9535 if (Hoption.Contour) PaintContour(option);
9536 if (Hoption.Text) PaintText(option);
9537 if (Hoption.Error >= 100) Paint2DErrors(option);
9538 if (Hoption.Candle) PaintCandlePlot(option);
9539 }
9540 if (Hoption.Lego) PaintLego(option);
9541 if (Hoption.Surf && !Hoption.Contour) PaintSurface(option);
9542 if (Hoption.Tri) PaintTriangles(option);
9543 }
9544
9545 // Draw histogram title
9546 PaintTitle();
9547
9548 // Draw the axes
9549 if (!Hoption.Lego && !Hoption.Surf &&
9550 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9551
9552 TF1 *fit = 0;
9553 TIter next(fFunctions);
9554 TObject *obj;
9555 while ((obj = next())) {
9556 if (obj->InheritsFrom(TF1::Class())) {
9557 fit = (TF1*)obj;
9558 break;
9559 }
9560 }
9561 if ((Hoption.Same%10) != 1) {
9562 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9563 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9564 //ALWAYS executed on non-iOS platform.
9565 //On iOS, depends on mode.
9567 }
9568 }
9569 }
9570}
9571
9572////////////////////////////////////////////////////////////////////////////////
9573/// Control function to draw a TH2Poly bins' contours.
9574///
9575/// - option = "F" draw the bins as filled areas.
9576/// - option = "L" draw the bins as line.
9577/// - option = "P" draw the bins as markers.
9578
9580{
9581
9582 //Do not highlight the histogram, if its part was picked.
9583 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9584
9585 TString opt = option;
9586 opt.ToLower();
9587 Bool_t line = kFALSE;
9588 Bool_t fill = kFALSE;
9589 Bool_t mark = kFALSE;
9590 if (opt.Contains("l")) line = kTRUE;
9591 if (opt.Contains("f")) fill = kTRUE;
9592 if (opt.Contains("p")) mark = kTRUE;
9593
9594 TH2PolyBin *b;
9595 Double_t z;
9596
9597 TIter next(((TH2Poly*)fH)->GetBins());
9598 TObject *obj, *poly;
9599
9600 while ((obj=next())) {
9601 b = (TH2PolyBin*)obj;
9602 z = b->GetContent();
9603 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9604 poly = b->GetPolygon();
9605
9606 // Paint the TGraph bins.
9607 if (poly->IsA() == TGraph::Class()) {
9608 TGraph *g = (TGraph*)poly;
9609 g->TAttLine::Modify();
9610 g->TAttMarker::Modify();
9611 g->TAttFill::Modify();
9612 if (line) {
9613 Int_t fs = g->GetFillStyle();
9614 Int_t fc = g->GetFillColor();
9615 g->SetFillStyle(0);
9616 g->SetFillColor(g->GetLineColor());
9617 g->Paint("F");
9618 g->SetFillStyle(fs);
9619 g->SetFillColor(fc);
9620 }
9621 if (fill) g->Paint("F");
9622 if (mark) g->Paint("P");
9623 }
9624
9625 // Paint the TMultiGraph bins.
9626 if (poly->IsA() == TMultiGraph::Class()) {
9627 TMultiGraph *mg = (TMultiGraph*)poly;
9628 TList *gl = mg->GetListOfGraphs();
9629 if (!gl) return;
9630 TGraph *g;
9631 TIter nextg(gl);
9632 while ((g = (TGraph*) nextg())) {
9633 g->TAttLine::Modify();
9634 g->TAttMarker::Modify();
9635 g->TAttFill::Modify();
9636 if (line) {
9637 Int_t fs = g->GetFillStyle();
9638 Int_t fc = g->GetFillColor();
9639 g->SetFillStyle(0);
9640 g->SetFillColor(g->GetLineColor());
9641 g->Paint("F");
9642 g->SetFillStyle(fs);
9643 g->SetFillColor(fc);
9644 }
9645 if (fill) g->Paint("F");
9646 if (mark) g->Paint("P");
9647 }
9648 }
9649 }
9650}
9651
9652////////////////////////////////////////////////////////////////////////////////
9653/// [Control function to draw a TH2Poly as a color plot.](#HP20a)
9654
9656{
9657
9658 //Do not highlight the histogram, if its part was picked.
9659 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9660 return;
9661
9662 Int_t ncolors, color, theColor;
9663 Double_t z, zc;
9664 Double_t zmin = fH->GetMinimum();
9665 Double_t zmax = fH->GetMaximum();
9666 if (Hoption.Logz) {
9667 if (zmax > 0) {
9668 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9669 zmin = TMath::Log10(zmin);
9670 zmax = TMath::Log10(zmax);
9671 } else {
9672 return;
9673 }
9674 }
9675 Double_t dz = zmax - zmin;
9676
9677 // Initialize the levels on the Z axis
9678 ncolors = gStyle->GetNumberOfColors();
9679 Int_t ndiv = fH->GetContour();
9680 if (ndiv == 0 ) {
9681 ndiv = gStyle->GetNumberContours();
9682 fH->SetContour(ndiv);
9683 }
9684 Int_t ndivz = TMath::Abs(ndiv);
9685 if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
9686 Double_t scale = ndivz/dz;
9687
9688 TH2PolyBin *b;
9689
9690 TIter next(((TH2Poly*)fH)->GetBins());
9691 TObject *obj, *poly;
9692
9693 while ((obj=next())) {
9694 b = (TH2PolyBin*)obj;
9695 poly = b->GetPolygon();
9696
9697 z = b->GetContent();
9698 if (z==0 && Hoption.Zero) continue;
9699 if (Hoption.Logz) {
9700 if (z > 0) z = TMath::Log10(z);
9701 else z = zmin;
9702 }
9703 if (z < zmin) continue;
9704
9705 // Define the bin color.
9707 zc = fH->GetContourLevelPad(0);
9708 if (z < zc) continue;
9709 color = -1;
9710 for (Int_t k=0; k<ndiv; k++) {
9711 zc = fH->GetContourLevelPad(k);
9712 if (z < zc) {
9713 continue;
9714 } else {
9715 color++;
9716 }
9717 }
9718 } else {
9719 color = Int_t(0.01+(z-zmin)*scale);
9720 }
9721 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9722 if (theColor > ncolors-1) theColor = ncolors-1;
9723
9724 // Paint the TGraph bins.
9725 if (poly->IsA() == TGraph::Class()) {
9726 TGraph *g = (TGraph*)poly;
9727 g->SetFillColor(gStyle->GetColorPalette(theColor));
9728 g->TAttFill::Modify();
9729 g->Paint("F");
9730 }
9731
9732 // Paint the TMultiGraph bins.
9733 if (poly->IsA() == TMultiGraph::Class()) {
9734 TMultiGraph *mg = (TMultiGraph*)poly;
9735 TList *gl = mg->GetListOfGraphs();
9736 if (!gl) return;
9737 TGraph *g;
9738 TIter nextg(gl);
9739 while ((g = (TGraph*) nextg())) {
9740 g->SetFillColor(gStyle->GetColorPalette(theColor));
9741 g->TAttFill::Modify();
9742 g->Paint("F");
9743 }
9744 }
9745 }
9747}
9748
9749////////////////////////////////////////////////////////////////////////////////
9750/// [Control function to draw a TH2Poly as a scatter plot.](#HP20a)
9751
9753{
9754
9755 //Do not highlight the histogram, if its part was selected.
9756 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9757 return;
9758
9759 Int_t k, loop, marker=0;
9760 Double_t z, xk,xstep, yk, ystep, xp, yp;
9761 Double_t scale = 1;
9762 Double_t zmin = fH->GetMinimum();
9763 Double_t zmax = fH->GetMaximum();
9764 if (Hoption.Logz) {
9765 if (zmax > 0) {
9766 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9767 zmin = TMath::Log10(zmin);
9768 zmax = TMath::Log10(zmax);
9769 } else {
9770 return;
9771 }
9772 }
9773 Double_t dz = zmax - zmin;
9774 scale = (kNMAX-1)/dz;
9775
9776
9777 // use an independent instance of a random generator
9778 // instead of gRandom to avoid conflicts and
9779 // to get same random numbers when drawing the same histogram
9780 TRandom2 random;
9781
9782 TH2PolyBin *b;
9783
9784 TIter next(((TH2Poly*)fH)->GetBins());
9785 TObject *obj, *poly;
9786
9787 Double_t maxarea = 0, a;
9788 while ((obj=next())) {
9789 b = (TH2PolyBin*)obj;
9790 a = b->GetArea();
9791 if (a>maxarea) maxarea = a;
9792 }
9793
9794 next.Reset();
9795
9796 while ((obj=next())) {
9797 b = (TH2PolyBin*)obj;
9798 poly = b->GetPolygon();
9799 z = b->GetContent();
9800 if (z < zmin) z = zmin;
9801 if (z > zmax) z = zmax;
9802 if (Hoption.Logz) {
9803 if (z > 0) z = TMath::Log10(z) - zmin;
9804 } else {
9805 z -= zmin;
9806 }
9807 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9808 xk = b->GetXMin();
9809 yk = b->GetYMin();
9810 xstep = b->GetXMax()-xk;
9811 ystep = b->GetYMax()-yk;
9812
9813 // Paint the TGraph bins.
9814 if (poly->IsA() == TGraph::Class()) {
9815 TGraph *g = (TGraph*)poly;
9816 if (k <= 0 || z <= 0) continue;
9817 loop = 0;
9818 while (loop<k) {
9819 if (k+marker >= kNMAX) {
9820 gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9821 marker=0;
9822 }
9823 xp = (random.Rndm()*xstep) + xk;
9824 yp = (random.Rndm()*ystep) + yk;
9825 if (g->IsInside(xp,yp)) {
9826 fXbuf[marker] = xp;
9827 fYbuf[marker] = yp;
9828 marker++;
9829 loop++;
9830 }
9831 }
9832 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9833 }
9834
9835 // Paint the TMultiGraph bins.
9836 if (poly->IsA() == TMultiGraph::Class()) {
9837 TMultiGraph *mg = (TMultiGraph*)poly;
9838 TList *gl = mg->GetListOfGraphs();
9839 if (!gl) return;
9840 if (k <= 0 || z <= 0) continue;
9841 loop = 0;
9842 while (loop<k) {
9843 if (k+marker >= kNMAX) {
9844 gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9845 marker=0;
9846 }
9847 xp = (random.Rndm()*xstep) + xk;
9848 yp = (random.Rndm()*ystep) + yk;
9849 if (mg->IsInside(xp,yp)) {
9850 fXbuf[marker] = xp;
9851 fYbuf[marker] = yp;
9852 marker++;
9853 loop++;
9854 }
9855 }
9856 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9857 }
9858 }
9859 PaintTH2PolyBins("l");
9860}
9861
9862////////////////////////////////////////////////////////////////////////////////
9863/// [Control function to draw a TH2Poly as a text plot.](#HP20a)
9864
9866{
9867
9868 TLatex text;
9872
9873 Double_t x, y, z, e, angle = 0;
9874 TString tt, tf;
9875 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
9876 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9877 Int_t opt = (Int_t)Hoption.Text/1000;
9878
9879 text.SetTextAlign(22);
9880 if (Hoption.Text == 1) angle = 0;
9881 text.SetTextAngle(angle);
9882 text.TAttText::Modify();
9883
9884 TH2PolyBin *b;
9885
9886 TIter next(((TH2Poly*)fH)->GetBins());
9887 TObject *obj, *p;
9888
9889 while ((obj=next())) {
9890 b = (TH2PolyBin*)obj;
9891 p = b->GetPolygon();
9892 x = (b->GetXMin()+b->GetXMax())/2;
9893 if (Hoption.Logx) {
9894 if (x > 0) x = TMath::Log10(x);
9895 else continue;
9896 }
9897 y = (b->GetYMin()+b->GetYMax())/2;
9898 if (Hoption.Logy) {
9899 if (y > 0) y = TMath::Log10(y);
9900 else continue;
9901 }
9902 z = b->GetContent();
9903 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
9904 if (opt==2) {
9905 e = fH->GetBinError(b->GetBinNumber());
9906 tf.Form("#splitline{%s%s}{#pm %s%s}",
9908 "%",gStyle->GetPaintTextFormat());
9909 tt.Form(tf.Data(),z,e);
9910 } else {
9911 tt.Form(tf.Data(),z);
9912 }
9913 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
9914 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
9915 }
9916
9917 PaintTH2PolyBins("l");
9918}
9919
9920////////////////////////////////////////////////////////////////////////////////
9921/// [Control function to draw a 1D/2D histograms with the bin values.](#HP15)
9922
9924{
9925
9926 TLatex text;
9930
9931 Double_t x, y, z, e, angle = 0;
9932 TString tt, tf;
9933 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
9934 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9935
9936 // 1D histograms
9937 if (fH->GetDimension() == 1) {
9938 Bool_t getentries = kFALSE;
9939 Double_t yt;
9940 TProfile *hp = (TProfile*)fH;
9941 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
9942 Hoption.Text = Hoption.Text-2000;
9943 getentries = kTRUE;
9944 }
9945 if (Hoption.Text == 1) angle = 90;
9946 text.SetTextAlign(11);
9947 if (angle == 90) text.SetTextAlign(12);
9948 if (angle == 0) text.SetTextAlign(21);
9949 text.TAttText::Modify();
9950 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
9951 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
9952 if (Hoption.Bar) {
9953 x = fH->GetXaxis()->GetBinLowEdge(i)+
9954 fH->GetXaxis()->GetBinWidth(i)*
9955 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
9956 } else {
9957 x = fH->GetXaxis()->GetBinCenter(i);
9958 }
9959 y = fH->GetBinContent(i);
9960 yt = y;
9961 if (Hoption.MinimumZero && y<0) y = 0;
9962 if (getentries) yt = hp->GetBinEntries(i);
9963 if (yt == 0.) continue;
9964 tt.Form(tf.Data(),yt);
9965 if (Hoption.Logx) {
9966 if (x > 0) x = TMath::Log10(x);
9967 else continue;
9968 }
9969 if (Hoption.Logy) {
9970 if (y > 0) y = TMath::Log10(y);
9971 else continue;
9972 }
9973 if (y >= gPad->GetY2()) continue;
9974 if (y <= gPad->GetY1()) continue;
9975 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
9976 }
9977
9978 // 2D histograms
9979 } else {
9980 text.SetTextAlign(22);
9981 if (Hoption.Text == 1) angle = 0;
9982 text.SetTextAngle(angle);
9983 text.TAttText::Modify();
9984 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
9985 y = fYaxis->GetBinCenter(j);
9986 if (Hoption.Logy) {
9987 if (y > 0) y = TMath::Log10(y);
9988 else continue;
9989 }
9990 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
9991 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
9992 x = fXaxis->GetBinCenter(i);
9993 if (Hoption.Logx) {
9994 if (x > 0) x = TMath::Log10(x);
9995 else continue;
9996 }
9997 if (!IsInside(x,y)) continue;
9998 z = fH->GetBinContent(bin);
9999 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10000 if (Hoption.Text>2000) {
10001 e = fH->GetBinError(bin);
10002 tf.Form("#splitline{%s%s}{#pm %s%s}",
10004 "%",gStyle->GetPaintTextFormat());
10005 tt.Form(tf.Data(),z,e);
10006 } else {
10007 tt.Form(tf.Data(),z);
10008 }
10009 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10010 angle,0.02*fH->GetMarkerSize(),tt.Data());
10011 }
10012 }
10013 }
10014}
10015
10016////////////////////////////////////////////////////////////////////////////////
10017/// [Control function to draw a 3D implicit functions.](#HP27)
10018
10020{
10021
10022 Int_t irep;
10023
10024 TGaxis *axis = new TGaxis();
10025 TAxis *xaxis = fH->GetXaxis();
10026 TAxis *yaxis = fH->GetYaxis();
10027 TAxis *zaxis = fH->GetZaxis();
10028
10029 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10030 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10031 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10032 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10033 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10034 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10035
10037
10038 TView *view = gPad->GetView();
10039 if (!view) {
10040 Error("PaintTF3", "no TView in current pad");
10041 return;
10042 }
10043 Double_t thedeg = 90 - gPad->GetTheta();
10044 Double_t phideg = -90 - gPad->GetPhi();
10045 Double_t psideg = view->GetPsi();
10046 view->SetView(phideg, thedeg, psideg, irep);
10047
10048 fLego->InitMoveScreen(-1.1,1.1);
10049
10050 if (Hoption.BackBox) {
10053 fLego->BackBox(90);
10054 }
10055
10057
10059 fH->GetNbinsY(),
10060 fH->GetNbinsZ(), "BF");
10061
10062 if (Hoption.FrontBox) {
10063 fLego->InitMoveScreen(-1.1,1.1);
10065 fLego->FrontBox(90);
10066 }
10067 if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
10068
10069 PaintTitle();
10070
10071 delete axis;
10072 delete fLego; fLego = 0;
10073}
10074
10075////////////////////////////////////////////////////////////////////////////////
10076/// Draw the histogram title
10077///
10078/// The title is drawn according to the title alignment returned by
10079/// `GetTitleAlign()`. It is a 2 digits integer): hv
10080///
10081/// where `h` is the horizontal alignment and `v` is the
10082/// vertical alignment.
10083///
10084/// - `h` can get the values 1 2 3 for left, center, and right
10085/// - `v` can get the values 1 2 3 for bottom, middle and top
10086///
10087/// for instance the default alignment is: 13 (left top)
10088
10090{
10091 // probably best place for calls PaintHighlightBin
10092 // calls after paint histo (1D or 2D) and before paint title and stats
10093 if (!gPad->GetView()) PaintHighlightBin();
10094
10095 if (Hoption.Same) return;
10096 if (fH->TestBit(TH1::kNoTitle)) return;
10097 Int_t nt = strlen(fH->GetTitle());
10098 TPaveText *title = 0;
10099 TObject *obj;
10100 TIter next(gPad->GetListOfPrimitives());
10101 while ((obj = next())) {
10102 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10103 title = (TPaveText*)obj;
10104 if (strcmp(title->GetName(),"title")) {title = 0; continue;}
10105 break;
10106 }
10107 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10108 if (title) delete title;
10109 return;
10110 }
10111 Double_t ht = gStyle->GetTitleH();
10112 Double_t wt = gStyle->GetTitleW();
10113
10114 if (ht <= 0) {
10115 if (gStyle->GetTitleFont("")%10 == 3) {
10116 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10117 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10118 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10119 } else {
10120 ht = 1.1*gStyle->GetTitleFontSize();
10121 }
10122 }
10123 if (ht <= 0) ht = 0.05;
10124 if (wt <= 0) {
10125 TLatex l;
10126 l.SetTextSize(ht);
10127 l.SetTitle(fH->GetTitle());
10128 // adjustment in case the title has several lines (#splitline)
10129 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10130 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10131 wt = TMath::Min(0.7, 0.02+wndc);
10132 }
10133 if (title) {
10134 TText *t0 = (TText*)title->GetLine(0);
10135 if (t0) {
10136 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10137 t0->SetTitle(fH->GetTitle());
10138 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10139 }
10140 return;
10141 }
10142
10143 Int_t talh = gStyle->GetTitleAlign()/10;
10144 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10145 Int_t talv = gStyle->GetTitleAlign()%10;
10146 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10147 Double_t xpos, ypos;
10148 xpos = gStyle->GetTitleX();
10149 ypos = gStyle->GetTitleY();
10150 if (talh == 2) xpos = xpos-wt/2.;
10151 if (talh == 3) xpos = xpos-wt;
10152 if (talv == 2) ypos = ypos+ht/2.;
10153 if (talv == 1) ypos = ypos+ht;
10154
10155 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10156
10157 // box with the histogram title
10159 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10160 ptitle->SetName("title");
10163 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10164 if (gStyle->GetTitleFont("")%10 > 2)
10166 ptitle->AddText(fH->GetTitle());
10167 ptitle->SetBit(kCanDelete);
10168 ptitle->Draw();
10169 ptitle->Paint();
10170
10171 if(!gPad->IsEditable()) delete ptitle;
10172}
10173
10174////////////////////////////////////////////////////////////////////////////////
10175/// Process message `mess`.
10176
10177void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10178{
10179 if (!strcmp(mess,"SetF3")) {
10180 fCurrentF3 = (TF3 *)obj;
10181 }
10182}
10183
10184////////////////////////////////////////////////////////////////////////////////
10185/// Static function.
10186///
10187/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10188/// This procedure can be used to create an all-sky map in Galactic
10189/// coordinates with an equal-area Aitoff projection. Output map
10190/// coordinates are zero longitude centered.
10191/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10192///
10193/// source: GMT
10194///
10195/// code from Ernst-Jan Buis
10196
10198{
10199
10200 Double_t x, y;
10201
10202 Double_t alpha2 = (l/2)*TMath::DegToRad();
10203 Double_t delta = b*TMath::DegToRad();
10204 Double_t r2 = TMath::Sqrt(2.);
10205 Double_t f = 2*r2/TMath::Pi();
10206 Double_t cdec = TMath::Cos(delta);
10207 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10208 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10209 y = TMath::Sin(delta)*r2/denom;
10210 x *= TMath::RadToDeg()/f;
10211 y *= TMath::RadToDeg()/f;
10212 // x *= -1.; // for a skymap swap left<->right
10213 Al = x;
10214 Ab = y;
10215
10216 return 0;
10217}
10218
10219////////////////////////////////////////////////////////////////////////////////
10220/// Static function
10221///
10222/// Probably the most famous of the various map projections, the Mercator projection
10223/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10224/// with no distortion along the equator.
10225/// The Mercator projection has been used extensively for world maps in which the distortion towards
10226/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10227/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10228/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10229/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10230/// code from Ernst-Jan Buis
10231
10233{
10234
10235 Al = l;
10237 Ab = TMath::Log(aid);
10238 return 0;
10239}
10240
10241////////////////////////////////////////////////////////////////////////////////
10242/// Static function code from Ernst-Jan Buis
10243
10245{
10246
10247 Al = l*cos(b*TMath::DegToRad());
10248 Ab = b;
10249 return 0;
10250}
10251
10252////////////////////////////////////////////////////////////////////////////////
10253/// Static function code from Ernst-Jan Buis
10254
10256{
10257
10258 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10259 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10260 return 0;
10261}
10262
10263////////////////////////////////////////////////////////////////////////////////
10264/// Recompute the histogram range following graphics operations.
10265
10267{
10268
10269 if (Hoption.Same) return;
10270
10271 // Compute x,y range
10276
10277 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10278 if (Hoption.Proj ==1) {
10279 // TODO : check x range not lower than -180 and not higher than 180
10284
10285 if (xmin > xmin_aid) xmin = xmin_aid;
10286 if (ymin > ymin_aid) ymin = ymin_aid;
10287 if (xmax < xmax_aid) xmax = xmax_aid;
10288 if (ymax < ymax_aid) ymax = ymax_aid;
10289 if (Hparam.ymin<0 && Hparam.ymax>0) {
10290 // there is an 'equator', check its range in the plot..
10291 THistPainter::ProjectAitoff2xy(Hparam.xmin*0.9999, 0, xmin_aid, ymin_aid);
10292 THistPainter::ProjectAitoff2xy(Hparam.xmax*0.9999, 0, xmax_aid, ymin_aid);
10293 if (xmin >xmin_aid) xmin = xmin_aid;
10294 if (xmax <xmax_aid) xmax = xmax_aid;
10295 }
10296 if (Hparam.xmin<0 && Hparam.xmax>0) {
10297 THistPainter::ProjectAitoff2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
10298 THistPainter::ProjectAitoff2xy(0, Hparam.ymax, xmax_aid, ymax_aid);
10299 if (ymin >ymin_aid) ymin = ymin_aid;
10300 if (ymax <ymax_aid) ymax = ymax_aid;
10301 }
10302 } else if ( Hoption.Proj ==2) {
10303 if (Hparam.ymin <= -90 || Hparam.ymax >=90) {
10304 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10305 Hoption.Proj = 0;
10306 } else {
10309 }
10310 } else if (Hoption.Proj == 3) {
10315
10316 if (xmin > xmin_aid) xmin = xmin_aid;
10317 if (ymin > ymin_aid) ymin = ymin_aid;
10318 if (xmax < xmax_aid) xmax = xmax_aid;
10319 if (ymax < ymax_aid) ymax = ymax_aid;
10320 if (Hparam.ymin<0 && Hparam.ymax>0) {
10321 THistPainter::ProjectSinusoidal2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
10322 THistPainter::ProjectSinusoidal2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
10323 if (xmin >xmin_aid) xmin = xmin_aid;
10324 if (xmax <xmax_aid) xmax = xmax_aid;
10325 }
10326 if (Hparam.xmin<0 && Hparam.xmax>0) {
10327 THistPainter::ProjectSinusoidal2xy(0,Hparam.ymin, xmin_aid, ymin_aid);
10328 THistPainter::ProjectSinusoidal2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
10329 if (ymin >ymin_aid) ymin = ymin_aid;
10330 if (ymax <ymax_aid) ymax = ymax_aid;
10331 }
10332 } else if (Hoption.Proj == 4) {
10337
10338 if (xmin > xmin_aid) xmin = xmin_aid;
10339 if (ymin > ymin_aid) ymin = ymin_aid;
10340 if (xmax < xmax_aid) xmax = xmax_aid;
10341 if (ymax < ymax_aid) ymax = ymax_aid;
10342 if (Hparam.ymin<0 && Hparam.ymax>0) {
10343 THistPainter::ProjectParabolic2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
10344 THistPainter::ProjectParabolic2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
10345 if (xmin >xmin_aid) xmin = xmin_aid;
10346 if (xmax <xmax_aid) xmax = xmax_aid;
10347 }
10348 if (Hparam.xmin<0 && Hparam.xmax>0) {
10349 THistPainter::ProjectParabolic2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
10350 THistPainter::ProjectParabolic2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
10351 if (ymin >ymin_aid) ymin = ymin_aid;
10352 if (ymax <ymax_aid) ymax = ymax_aid;
10353 }
10354 }
10355 Hparam.xmin= xmin;
10356 Hparam.xmax= xmax;
10357 Hparam.ymin= ymin;
10358 Hparam.ymax= ymax;
10359
10360 Double_t dx = xmax-xmin;
10361 Double_t dy = ymax-ymin;
10362 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10363 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10364
10365 // Range() could change the size of the pad pixmap and therefore should
10366 // be called before the other paint routines
10367 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10368 ymin - dyr*gPad->GetBottomMargin(),
10369 xmax + dxr*gPad->GetRightMargin(),
10370 ymax + dyr*gPad->GetTopMargin());
10371 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10372}
10373
10374////////////////////////////////////////////////////////////////////////////////
10375/// Set current histogram to `h`
10376
10378{
10379
10380 if (h == 0) return;
10381 fH = h;
10382 fXaxis = h->GetXaxis();
10383 fYaxis = h->GetYaxis();
10384 fZaxis = h->GetZaxis();
10386}
10387
10388////////////////////////////////////////////////////////////////////////////////
10389/// Initialize various options to draw 2D histograms.
10390
10392{
10393
10394 static const char *where = "TableInit";
10395
10396 Int_t first, last;
10397 Double_t yMARGIN= gStyle->GetHistTopMargin();
10398 Double_t zmin, zmax;
10399 Int_t maximum = 0;
10400 Int_t minimum = 0;
10401 if (fH->GetMaximumStored() != -1111) maximum = 1;
10402 if (fH->GetMinimumStored() != -1111) minimum = 1;
10403
10404 // ----------------- Compute X axis parameters
10405 first = fXaxis->GetFirst();
10406 last = fXaxis->GetLast();
10407 Hparam.xlast = last;
10413
10414 // if log scale in X, replace xmin,max by the log
10415 if (Hoption.Logx) {
10416 // find the first edge of a bin that is > 0
10417 if (Hparam.xlowedge <=0 ) {
10420 }
10421 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10422 Error(where, "cannot set X axis to log scale");
10423 return 0;
10424 }
10428 if (Hparam.xlast > last) Hparam.xlast = last;
10431 }
10432
10433 // ----------------- Compute Y axis parameters
10434 first = fYaxis->GetFirst();
10435 last = fYaxis->GetLast();
10436 Hparam.ylast = last;
10440 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10443
10444 // if log scale in Y, replace ymin,max by the log
10445 if (Hoption.Logy) {
10446 if (Hparam.ylowedge <=0 ) {
10449 }
10450 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10451 Error(where, "cannot set Y axis to log scale");
10452 return 0;
10453 }
10457 if (Hparam.ylast > last) Hparam.ylast = last;
10460 }
10461
10462
10463 // ----------------- Compute Z axis parameters
10464 Double_t bigp = TMath::Power(10,32);
10465 zmax = -bigp;
10466 zmin = bigp;
10467 Double_t c1, e1;
10468 Double_t allchan = 0;
10469 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10470 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10471 c1 = fH->GetBinContent(i,j);
10472 zmax = TMath::Max(zmax,c1);
10473 if (Hoption.Error) {
10474 e1 = fH->GetBinError(i,j);
10475 zmax = TMath::Max(zmax,c1+e1);
10476 }
10477 zmin = TMath::Min(zmin,c1);
10478 allchan += c1;
10479 }
10480 }
10481
10482 // Take into account maximum , minimum
10483
10484 if (maximum) zmax = fH->GetMaximumStored();
10485 if (minimum) zmin = fH->GetMinimumStored();
10486 if (Hoption.Logz && zmax < 0) {
10487 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10488 return 0;
10489 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10490 zmin = 0.01;
10491 zmax = 10.;
10492 }
10493 if (zmin >= zmax) {
10494 if (Hoption.Logz) {
10495 if (zmax > 0) zmin = 0.001*zmax;
10496 else {
10497 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10498 return 0;
10499 }
10500 }
10501 }
10502
10503 // take into account normalization factor
10504 Hparam.allchan = allchan;
10505 Double_t factor = allchan;
10506 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10507 if (allchan) factor /= allchan;
10508 if (factor == 0) factor = 1;
10509 Hparam.factor = factor;
10510 zmax = factor*zmax;
10511 zmin = factor*zmin;
10512 c1 = zmax;
10513 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10514
10515 // For log scales, histogram coordinates are log10(ymin) and
10516 // log10(ymax). Final adjustment (if not option "Same")
10517 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10518 // Maximum and Minimum are not defined.
10519 if (Hoption.Logz) {
10520 if (zmin <= 0) {
10521 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10522 fH->SetMinimum(zmin);
10523 }
10524 zmin = TMath::Log10(zmin);
10525 if (!minimum) zmin += TMath::Log10(0.5);
10526 zmax = TMath::Log10(zmax);
10527 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10528 goto LZMIN;
10529 }
10530
10531 // final adjustment of YMAXI for linear scale (if not option "Same"):
10532 // decrease histogram height to MAX% of allowed height if HMAXIM
10533 // has not been called.
10534 // MAX% is the value in percent which has been set in HPLSET
10535 // (default is 90%).
10536 if (!maximum) {
10537 zmax += yMARGIN*(zmax-zmin);
10538 }
10539
10540 // final adjustment of ymin for linear scale.
10541 // if minimum is not set , then ymin is set to zero if >0
10542 // or to ymin - yMARGIN if <0.
10543 if (!minimum) {
10544 if (Hoption.MinimumZero) {
10545 if (zmin >= 0) zmin = 0;
10546 else zmin -= yMARGIN*(zmax-zmin);
10547 } else {
10548 Double_t dzmin = yMARGIN*(zmax-zmin);
10549 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10550 else zmin -= dzmin;
10551 }
10552 }
10553
10554LZMIN:
10555 Hparam.zmin = zmin;
10556 Hparam.zmax = zmax;
10557
10558 // Set bar offset and width
10561
10562 return 1;
10563}
10564
10565////////////////////////////////////////////////////////////////////////////////
10566/// This function returns the best format to print the error value (e)
10567/// knowing the parameter value (v) and the format (f) used to print it.
10568
10570{
10571
10572 static TString ef;
10573 TString tf, tv;
10574
10575 // print v with the format f in tv.
10576 tf.Form("%s%s","%",f);
10577 tv.Form(tf.Data(),v);
10578
10579 // Analyse tv.
10580 int ie = tv.Index("e");
10581 int iE = tv.Index("E");
10582 int id = tv.Index(".");
10583
10584 // v has been printed with the exponent notation.
10585 // There is 2 cases, the exponent is positive or negative
10586 if (ie >= 0 || iE >= 0) {
10587 if (tv.Index("+") >= 0) {
10588 if (e < 1) {
10589 ef.Form("%s.1f","%");
10590 } else {
10591 if (ie >= 0) {
10592 ef.Form("%s.%de","%",ie-id-1);
10593 } else {
10594 ef.Form("%s.%dE","%",iE-id-1);
10595 }
10596 }
10597 } else {
10598 if (ie >= 0) {
10599 ef.Form("%s.%de","%",ie-id-1);
10600 } else {
10601 ef.Form("%s.%dE","%",iE-id-1);
10602 }
10603 }
10604
10605 // There is not '.' in tv. e will be printed with one decimal digit.
10606 } else if (id < 0) {
10607 ef.Form("%s.1f","%");
10608
10609 // There is a '.' in tv and no exponent notation. e's decimal part will
10610 // have the same number of digits as v's one.
10611 } else {
10612 ef.Form("%s.%df","%",tv.Length()-id-1);
10613 }
10614
10615 return ef.Data();
10616}
10617
10618////////////////////////////////////////////////////////////////////////////////
10619/// Set projection.
10620
10621void THistPainter::SetShowProjection(const char *option,Int_t nbins)
10622{
10623
10624 if (fShowProjection) return;
10625 TString opt = option;
10626 opt.ToLower();
10627 Int_t projection = 0;
10628 if (opt.Contains("x")) projection = 1;
10629 if (opt.Contains("y")) projection = 2;
10630 if (opt.Contains("z")) projection = 3;
10631 if (opt.Contains("xy")) projection = 4;
10632 if (opt.Contains("yx")) projection = 5;
10633 if (opt.Contains("xz")) projection = 6;
10634 if (opt.Contains("zx")) projection = 7;
10635 if (opt.Contains("yz")) projection = 8;
10636 if (opt.Contains("zy")) projection = 9;
10637 if (projection < 4) fShowOption = option+1;
10638 else fShowOption = option+2;
10639 fShowProjection = projection+100*nbins;
10640 gROOT->MakeDefCanvas();
10641 gPad->SetName(Form("c_%lx_projection_%d", (ULong_t)fH, fShowProjection));
10642 gPad->SetGrid();
10643}
10644
10645////////////////////////////////////////////////////////////////////////////////
10646/// Show projection onto X.
10647
10649{
10650
10651 Int_t nbins = (Int_t)fShowProjection/100;
10652 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10653 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10654
10655 // Erase old position and draw a line at current position
10656 static int pyold1 = 0;
10657 static int pyold2 = 0;
10658 float uxmin = gPad->GetUxmin();
10659 float uxmax = gPad->GetUxmax();
10660 int pxmin = gPad->XtoAbsPixel(uxmin);
10661 int pxmax = gPad->XtoAbsPixel(uxmax);
10662 Float_t upy = gPad->AbsPixeltoY(py);
10663 Float_t y = gPad->PadtoY(upy);
10664 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10665 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10666 Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10667 Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10668
10669 if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10670 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10671 pyold1 = py1;
10672 pyold2 = py2;
10673
10674 // Create or set the new canvas proj x
10675 TVirtualPad *padsav = gPad;
10676 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
10678 if (c) {
10679 c->Clear();
10680 } else {
10681 fShowProjection = 0;
10682 pyold1 = 0;
10683 pyold2 = 0;
10684 return;
10685 }
10686 c->cd();
10687 c->SetLogy(padsav->GetLogz());
10688 c->SetLogx(padsav->GetLogx());
10689
10690 // Draw slice corresponding to mouse position
10691 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10692 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10693 if (hp) {
10694 hp->SetFillColor(38);
10695 // apply a patch from Oliver Freyermuth to set the title in the projection
10696 // using the range of the projected Y values
10697 if (biny1 == biny2) {
10698 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10699 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10700 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10701 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10702 if (fH->GetYaxis()->GetLabels() != NULL) {
10703 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10704 } else {
10705 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10706 }
10707 } else {
10708 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10709 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10710 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10711 // biny1 is used here to get equal precision no matter how large the binrange is,
10712 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10713 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10714 if (fH->GetYaxis()->GetLabels() != NULL) {
10715 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)));
10716 } else {
10717 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10718 }
10719 }
10720 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10721 hp->SetYTitle("Number of Entries");
10722 hp->Draw();
10723 c->Update();
10724 padsav->cd();
10725 }
10726}
10727
10728////////////////////////////////////////////////////////////////////////////////
10729/// Show projection onto Y.
10730
10732{
10733
10734 Int_t nbins = (Int_t)fShowProjection/100;
10735 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10736 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10737
10738 // Erase old position and draw a line at current position
10739 static int pxold1 = 0;
10740 static int pxold2 = 0;
10741 float uymin = gPad->GetUymin();
10742 float uymax = gPad->GetUymax();
10743 int pymin = gPad->YtoAbsPixel(uymin);
10744 int pymax = gPad->YtoAbsPixel(uymax);
10745 Float_t upx = gPad->AbsPixeltoX(px);
10746 Float_t x = gPad->PadtoX(upx);
10747 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10748 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10749 Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10750 Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10751
10752 if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10753 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10754 pxold1 = px1;
10755 pxold2 = px2;
10756
10757 // Create or set the new canvas proj y
10758 TVirtualPad *padsav = gPad;
10759 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
10761 if (c) {
10762 c->Clear();
10763 } else {
10764 fShowProjection = 0;
10765 pxold1 = 0;
10766 pxold2 = 0;
10767 return;
10768 }
10769 c->cd();
10770 c->SetLogy(padsav->GetLogz());
10771 c->SetLogx(padsav->GetLogy());
10772
10773 // Draw slice corresponding to mouse position
10774 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10775 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10776 if (hp) {
10777 hp->SetFillColor(38);
10778 // apply a patch from Oliver Freyermuth to set the title in the projection
10779 // using the range of the projected X values
10780 if (binx1 == binx2) {
10781 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10782 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10783 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10784 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10785 if (fH->GetXaxis()->GetLabels() != NULL) {
10786 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10787 } else {
10788 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10789 }
10790 } else {
10791 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10792 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
10793 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10794 // binx1 is used here to get equal precision no matter how large the binrange is,
10795 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10796 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
10797 if (fH->GetXaxis()->GetLabels() != NULL) {
10798 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)));
10799 } else {
10800 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
10801 }
10802 }
10803 hp->SetXTitle(fH->GetYaxis()->GetTitle());
10804 hp->SetYTitle("Number of Entries");
10805 hp->Draw();
10806 c->Update();
10807 padsav->cd();
10808 }
10809}
10810
10811////////////////////////////////////////////////////////////////////////////////
10812/// Show projection (specified by `fShowProjection`) of a `TH3`.
10813/// The drawing option for the projection is in `fShowOption`.
10814///
10815/// First implementation; R.Brun
10816///
10817/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
10818
10820{
10821
10822 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
10823 if (fH->GetDimension() < 3) {
10824 if (fShowProjection%100 == 1) {ShowProjectionX(px,py); return;}
10825 if (fShowProjection%100 == 2) {ShowProjectionY(px,py); return;}
10826 }
10827
10828 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10829 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10830
10831 // Erase old position and draw a line at current position
10832 TView *view = gPad->GetView();
10833 if (!view) return;
10834 TH3 *h3 = (TH3*)fH;
10835 TAxis *xaxis = h3->GetXaxis();
10836 TAxis *yaxis = h3->GetYaxis();
10837 TAxis *zaxis = h3->GetZaxis();
10838 Double_t u[3],xx[3];
10839
10840 static TPoint line1[2];//store end points of a line, initialised 0 by default
10841 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
10842 static TPoint line3[2];
10843 static TPoint line4[2];
10844 static TPoint endface1[5];
10845 static TPoint endface2[5];
10846 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
10847 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
10848
10849 Double_t uxmin = gPad->GetUxmin();
10850 Double_t uxmax = gPad->GetUxmax();
10851 Double_t uymin = gPad->GetUymin();
10852 Double_t uymax = gPad->GetUymax();
10853
10854 int pxmin = gPad->XtoAbsPixel(uxmin);
10855 int pxmax = gPad->XtoAbsPixel(uxmax);
10856 if (pxmin==pxmax) return;
10857 int pymin = gPad->YtoAbsPixel(uymin);
10858 int pymax = gPad->YtoAbsPixel(uymax);
10859 if (pymin==pymax) return;
10860 Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
10861 Double_t cy = (pymax-pymin)/(uymax-uymin);
10862 TVirtualPad *padsav = gPad;
10863 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
10865 if (!c) {
10866 fShowProjection = 0;
10867 return;
10868 }
10869
10870 switch ((Int_t)fShowProjection%100) {
10871 case 1:
10872 // "x"
10873 {
10874 Int_t firstY = yaxis->GetFirst();
10875 Int_t lastY = yaxis->GetLast();
10876 Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
10877 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
10878 yaxis->SetRange(biny,biny2);
10879 Int_t firstZ = zaxis->GetFirst();
10880 Int_t lastZ = zaxis->GetLast();
10881 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
10882 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10883 zaxis->SetRange(binz,binz2);
10884 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
10885 if (nbins>1 && line1[0].GetX()) {
10886 gVirtualX->DrawPolyLine(2,line2);
10887 gVirtualX->DrawPolyLine(2,line3);
10888 gVirtualX->DrawPolyLine(2,line4);
10889 gVirtualX->DrawPolyLine(5,endface1);
10890 gVirtualX->DrawPolyLine(5,endface2);
10891 }
10892 xx[0] = xaxis->GetXmin();
10893 xx[2] = zaxis->GetBinCenter(binz);
10894 xx[1] = yaxis->GetBinCenter(biny);
10895 view->WCtoNDC(xx,u);
10896 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10897 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10898 xx[0] = xaxis->GetXmax();
10899 view->WCtoNDC(xx,u);
10900 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10901 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10902 gVirtualX->DrawPolyLine(2,line1);
10903 if (nbins>1) {
10904 xx[0] = xaxis->GetXmin();
10905 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10906 xx[1] = yaxis->GetBinCenter(biny);
10907 view->WCtoNDC(xx,u);
10908 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10909 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10910 xx[0] = xaxis->GetXmax();
10911 view->WCtoNDC(xx,u);
10912 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10913 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10914
10915 xx[0] = xaxis->GetXmin();
10916 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10917 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10918 view->WCtoNDC(xx,u);
10919 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10920 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10921 xx[0] = xaxis->GetXmax();
10922 view->WCtoNDC(xx,u);
10923 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10924 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10925
10926 xx[0] = xaxis->GetXmin();
10927 xx[2] = zaxis->GetBinCenter(binz);
10928 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10929 view->WCtoNDC(xx,u);
10930 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10931 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10932 xx[0] = xaxis->GetXmax();
10933 view->WCtoNDC(xx,u);
10934 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10935 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10936
10937 endface1[0].SetX(line1[0].GetX());
10938 endface1[0].SetY(line1[0].GetY());
10939 endface1[1].SetX(line2[0].GetX());
10940 endface1[1].SetY(line2[0].GetY());
10941 endface1[2].SetX(line3[0].GetX());
10942 endface1[2].SetY(line3[0].GetY());
10943 endface1[3].SetX(line4[0].GetX());
10944 endface1[3].SetY(line4[0].GetY());
10945 endface1[4].SetX(line1[0].GetX());
10946 endface1[4].SetY(line1[0].GetY());
10947
10948 endface2[0].SetX(line1[1].GetX());
10949 endface2[0].SetY(line1[1].GetY());
10950 endface2[1].SetX(line2[1].GetX());
10951 endface2[1].SetY(line2[1].GetY());
10952 endface2[2].SetX(line3[1].GetX());
10953 endface2[2].SetY(line3[1].GetY());
10954 endface2[3].SetX(line4[1].GetX());
10955 endface2[3].SetY(line4[1].GetY());
10956 endface2[4].SetX(line1[1].GetX());
10957 endface2[4].SetY(line1[1].GetY());
10958
10959 gVirtualX->DrawPolyLine(2,line2);
10960 gVirtualX->DrawPolyLine(2,line3);
10961 gVirtualX->DrawPolyLine(2,line4);
10962 gVirtualX->DrawPolyLine(5,endface1);
10963 gVirtualX->DrawPolyLine(5,endface2);
10964 }
10965 c->Clear();
10966 c->cd();
10967 TH1 *hp = h3->Project3D("x");
10968 yaxis->SetRange(firstY,lastY);
10969 zaxis->SetRange(firstZ,lastZ);
10970 if (hp) {
10971 hp->SetFillColor(38);
10972 if (nbins == 1)
10973 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
10974 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
10975 else {
10976 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),
10977 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
10978 }
10979 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10980 hp->SetYTitle("Number of Entries");
10981 hp->Draw(fShowOption.Data());
10982 }
10983 }
10984 break;
10985
10986 case 2:
10987 // "y"
10988 {
10989 Int_t firstX = xaxis->GetFirst();
10990 Int_t lastX = xaxis->GetLast();
10991 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
10992 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
10993 xaxis->SetRange(binx,binx2);
10994 Int_t firstZ = zaxis->GetFirst();
10995 Int_t lastZ = zaxis->GetLast();
10996 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
10997 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10998 zaxis->SetRange(binz,binz2);
10999 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11000 if (nbins>1 && line1[0].GetX()) {
11001 gVirtualX->DrawPolyLine(2,line2);
11002 gVirtualX->DrawPolyLine(2,line3);
11003 gVirtualX->DrawPolyLine(2,line4);
11004 gVirtualX->DrawPolyLine(5,endface1);
11005 gVirtualX->DrawPolyLine(5,endface2);
11006 }
11007 xx[0]=xaxis->GetBinCenter(binx);
11008 xx[2] = zaxis->GetBinCenter(binz);
11009 xx[1] = yaxis->GetXmin();
11010 view->WCtoNDC(xx,u);
11011 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11012 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11013 xx[1] = yaxis->GetXmax();
11014 view->WCtoNDC(xx,u);
11015 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11016 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11017 gVirtualX->DrawPolyLine(2,line1);
11018 if (nbins>1) {
11019 xx[1] = yaxis->GetXmin();
11020 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11021 xx[0] = xaxis->GetBinCenter(binx);
11022 view->WCtoNDC(xx,u);
11023 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11024 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11025 xx[1] = yaxis->GetXmax();
11026 view->WCtoNDC(xx,u);
11027 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11028 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11029
11030 xx[1] = yaxis->GetXmin();
11031 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11032 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11033 view->WCtoNDC(xx,u);
11034 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11035 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11036 xx[1] = yaxis->GetXmax();
11037 view->WCtoNDC(xx,u);
11038 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11039 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11040
11041 xx[1] = yaxis->GetXmin();
11042 xx[2] = zaxis->GetBinCenter(binz);
11043 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11044 view->WCtoNDC(xx,u);
11045 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11046 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11047 xx[1] = yaxis->GetXmax();
11048 view->WCtoNDC(xx,u);
11049 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11050 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11051
11052 endface1[0].SetX(line1[0].GetX());
11053 endface1[0].SetY(line1[0].GetY());
11054 endface1[1].SetX(line2[0].GetX());
11055 endface1[1].SetY(line2[0].GetY());
11056 endface1[2].SetX(line3[0].GetX());
11057 endface1[2].SetY(line3[0].GetY());
11058 endface1[3].SetX(line4[0].GetX());
11059 endface1[3].SetY(line4[0].GetY());
11060 endface1[4].SetX(line1[0].GetX());
11061 endface1[4].SetY(line1[0].GetY());
11062
11063 endface2[0].SetX(line1[1].GetX());
11064 endface2[0].SetY(line1[1].GetY());
11065 endface2[1].SetX(line2[1].GetX());
11066 endface2[1].SetY(line2[1].GetY());
11067 endface2[2].SetX(line3[1].GetX());
11068 endface2[2].SetY(line3[1].GetY());
11069 endface2[3].SetX(line4[1].GetX());
11070 endface2[3].SetY(line4[1].GetY());
11071 endface2[4].SetX(line1[1].GetX());
11072 endface2[4].SetY(line1[1].GetY());
11073
11074 gVirtualX->DrawPolyLine(2,line2);
11075 gVirtualX->DrawPolyLine(2,line3);
11076 gVirtualX->DrawPolyLine(2,line4);
11077 gVirtualX->DrawPolyLine(5,endface1);
11078 gVirtualX->DrawPolyLine(5,endface2);
11079 }
11080 c->Clear();
11081 c->cd();
11082 TH1 *hp = h3->Project3D("y");
11083 xaxis->SetRange(firstX,lastX);
11084 zaxis->SetRange(firstZ,lastZ);
11085 if (hp) {
11086 hp->SetFillColor(38);
11087 if (nbins == 1)
11088 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11089 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11090 else
11091 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),
11092 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11093 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11094 hp->SetYTitle("Number of Entries");
11095 hp->Draw(fShowOption.Data());
11096 }
11097 }
11098 break;
11099
11100 case 3:
11101 // "z"
11102 {
11103 Int_t firstX = xaxis->GetFirst();
11104 Int_t lastX = xaxis->GetLast();
11105 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11106 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11107 xaxis->SetRange(binx,binx2);
11108 Int_t firstY = yaxis->GetFirst();
11109 Int_t lastY = yaxis->GetLast();
11110 Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
11111 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11112 yaxis->SetRange(biny,biny2);
11113 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11114 if (nbins>1 && line1[0].GetX()) {
11115 gVirtualX->DrawPolyLine(2,line2);
11116 gVirtualX->DrawPolyLine(2,line3);
11117 gVirtualX->DrawPolyLine(2,line4);
11118 gVirtualX->DrawPolyLine(5,endface1);
11119 gVirtualX->DrawPolyLine(5,endface2);
11120 }
11121 xx[0] = xaxis->GetBinCenter(binx);
11122 xx[1] = yaxis->GetBinCenter(biny);
11123 xx[2] = zaxis->GetXmin();
11124 view->WCtoNDC(xx,u);
11125 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11126 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11127 xx[2] = zaxis->GetXmax();
11128 view->WCtoNDC(xx,u);
11129 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11130 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11131 gVirtualX->DrawPolyLine(2,line1);
11132 if (nbins>1) {
11133 xx[2] = zaxis->GetXmin();
11134 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11135 xx[0] = xaxis->GetBinCenter(binx);
11136 view->WCtoNDC(xx,u);
11137 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11138 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11139 xx[2] = zaxis->GetXmax();
11140 view->WCtoNDC(xx,u);
11141 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11142 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11143
11144 xx[2] = zaxis->GetXmin();
11145 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11146 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11147 view->WCtoNDC(xx,u);
11148 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11149 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11150 xx[2] = zaxis->GetXmax();
11151 view->WCtoNDC(xx,u);
11152 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11153 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11154
11155 xx[2] = zaxis->GetXmin();
11156 xx[1] = yaxis->GetBinCenter(biny);
11157 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11158 view->WCtoNDC(xx,u);
11159 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11160 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11161 xx[2] = zaxis->GetXmax();
11162 view->WCtoNDC(xx,u);
11163 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11164 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11165
11166 endface1[0].SetX(line1[0].GetX());
11167 endface1[0].SetY(line1[0].GetY());
11168 endface1[1].SetX(line2[0].GetX());
11169 endface1[1].SetY(line2[0].GetY());
11170 endface1[2].SetX(line3[0].GetX());
11171 endface1[2].SetY(line3[0].GetY());
11172 endface1[3].SetX(line4[0].GetX());
11173 endface1[3].SetY(line4[0].GetY());
11174 endface1[4].SetX(line1[0].GetX());
11175 endface1[4].SetY(line1[0].GetY());
11176
11177 endface2[0].SetX(line1[1].GetX());
11178 endface2[0].SetY(line1[1].GetY());
11179 endface2[1].SetX(line2[1].GetX());
11180 endface2[1].SetY(line2[1].GetY());
11181 endface2[2].SetX(line3[1].GetX());
11182 endface2[2].SetY(line3[1].GetY());
11183 endface2[3].SetX(line4[1].GetX());
11184 endface2[3].SetY(line4[1].GetY());
11185 endface2[4].SetX(line1[1].GetX());
11186 endface2[4].SetY(line1[1].GetY());
11187
11188 gVirtualX->DrawPolyLine(2,line2);
11189 gVirtualX->DrawPolyLine(2,line3);
11190 gVirtualX->DrawPolyLine(2,line4);
11191 gVirtualX->DrawPolyLine(5,endface1);
11192 gVirtualX->DrawPolyLine(5,endface2);
11193 }
11194 c->Clear();
11195 c->cd();
11196 TH1 *hp = h3->Project3D("z");
11197 xaxis->SetRange(firstX,lastX);
11198 yaxis->SetRange(firstY,lastY);
11199 if (hp) {
11200 hp->SetFillColor(38);
11201 if (nbins == 1)
11202 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11203 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11204 else
11205 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),
11206 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11207 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11208 hp->SetYTitle("Number of Entries");
11209 hp->Draw(fShowOption.Data());
11210 }
11211 }
11212 break;
11213
11214 case 4:
11215 // "xy"
11216 {
11217 Int_t first = zaxis->GetFirst();
11218 Int_t last = zaxis->GetLast();
11219 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11220 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11221 zaxis->SetRange(binz,binz2);
11222 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11223 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11224 xx[0] = xaxis->GetXmin();
11225 xx[1] = yaxis->GetXmax();
11226 xx[2] = zaxis->GetBinCenter(binz);
11227 view->WCtoNDC(xx,u);
11228 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11229 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11230 rect1[4].SetX(rect1[0].GetX());
11231 rect1[4].SetY(rect1[0].GetY());
11232 xx[0] = xaxis->GetXmax();
11233 view->WCtoNDC(xx,u);
11234 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11235 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11236 xx[1] = yaxis->GetXmin();
11237 view->WCtoNDC(xx,u);
11238 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11239 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11240 xx[0] = xaxis->GetXmin();
11241 view->WCtoNDC(xx,u);
11242 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11243 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11244 gVirtualX->DrawPolyLine(5,rect1);
11245 if (nbins>1) {
11246 xx[0] = xaxis->GetXmin();
11247 xx[1] = yaxis->GetXmax();
11248 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11249 view->WCtoNDC(xx,u);
11250 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11251 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11252 rect2[4].SetX(rect2[0].GetX());
11253 rect2[4].SetY(rect2[0].GetY());
11254 xx[0] = xaxis->GetXmax();
11255 view->WCtoNDC(xx,u);
11256 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11257 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11258 xx[1] = yaxis->GetXmin();
11259 view->WCtoNDC(xx,u);
11260 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11261 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11262 xx[0] = xaxis->GetXmin();
11263 view->WCtoNDC(xx,u);
11264 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11265 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11266 gVirtualX->DrawPolyLine(5,rect2);
11267 }
11268
11269 c->Clear();
11270 c->cd();
11271 TH2 *hp = (TH2*)h3->Project3D("xy");
11272 zaxis->SetRange(first,last);
11273 if (hp) {
11274 hp->SetFillColor(38);
11275 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11276 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11277 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11278 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11279 hp->SetZTitle("Number of Entries");
11280 hp->Draw(fShowOption.Data());
11281 }
11282 }
11283 break;
11284
11285 case 5:
11286 // "yx"
11287 {
11288 Int_t first = zaxis->GetFirst();
11289 Int_t last = zaxis->GetLast();
11290 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11291 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11292 zaxis->SetRange(binz,binz2);
11293 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11294 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11295 xx[0] = xaxis->GetXmin();
11296 xx[1] = yaxis->GetXmax();
11297 xx[2] = zaxis->GetBinCenter(binz);
11298 view->WCtoNDC(xx,u);
11299 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11300 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11301 rect1[4].SetX(rect1[0].GetX());
11302 rect1[4].SetY(rect1[0].GetY());
11303 xx[0] = xaxis->GetXmax();
11304 view->WCtoNDC(xx,u);
11305 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11306 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11307 xx[1] = yaxis->GetXmin();
11308 view->WCtoNDC(xx,u);
11309 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11310 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11311 xx[0] = xaxis->GetXmin();
11312 view->WCtoNDC(xx,u);
11313 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11314 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11315 gVirtualX->DrawPolyLine(5,rect1);
11316 if (nbins>1) {
11317 xx[0] = xaxis->GetXmin();
11318 xx[1] = yaxis->GetXmax();
11319 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11320 view->WCtoNDC(xx,u);
11321 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11322 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11323 rect2[4].SetX(rect2[0].GetX());
11324 rect2[4].SetY(rect2[0].GetY());
11325 xx[0] = xaxis->GetXmax();
11326 view->WCtoNDC(xx,u);
11327 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11328 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11329 xx[1] = yaxis->GetXmin();
11330 view->WCtoNDC(xx,u);
11331 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11332 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11333 xx[0] = xaxis->GetXmin();
11334 view->WCtoNDC(xx,u);
11335 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11336 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11337 gVirtualX->DrawPolyLine(5,rect2);
11338 }
11339 c->Clear();
11340 c->cd();
11341 TH2 *hp = (TH2*)h3->Project3D("yx");
11342 zaxis->SetRange(first,last);
11343 if (hp) {
11344 hp->SetFillColor(38);
11345 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11346 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11347 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11348 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11349 hp->SetZTitle("Number of Entries");
11350 hp->Draw(fShowOption.Data());
11351 }
11352 }
11353 break;
11354
11355 case 6:
11356 // "xz"
11357 {
11358 Int_t first = yaxis->GetFirst();
11359 Int_t last = yaxis->GetLast();
11360 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11361 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11362 yaxis->SetRange(biny,biny2);
11363 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11364 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11365 xx[0] = xaxis->GetXmin();
11366 xx[2] = zaxis->GetXmax();
11367 xx[1] = yaxis->GetBinCenter(biny);
11368 view->WCtoNDC(xx,u);
11369 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11370 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11371 rect1[4].SetX(rect1[0].GetX());
11372 rect1[4].SetY(rect1[0].GetY());
11373 xx[0] = xaxis->GetXmax();
11374 view->WCtoNDC(xx,u);
11375 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11376 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11377 xx[2] = zaxis->GetXmin();
11378 view->WCtoNDC(xx,u);
11379 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11380 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11381 xx[0] = xaxis->GetXmin();
11382 view->WCtoNDC(xx,u);
11383 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11384 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11385 gVirtualX->DrawPolyLine(5,rect1);
11386 if (nbins>1) {
11387 xx[0] = xaxis->GetXmin();
11388 xx[2] = zaxis->GetXmax();
11389 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11390 view->WCtoNDC(xx,u);
11391 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11392 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11393 rect2[4].SetX(rect2[0].GetX());
11394 rect2[4].SetY(rect2[0].GetY());
11395 xx[0] = xaxis->GetXmax();
11396 view->WCtoNDC(xx,u);
11397 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11398 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11399 xx[2] = zaxis->GetXmin();
11400 view->WCtoNDC(xx,u);
11401 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11402 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11403 xx[0] = xaxis->GetXmin();
11404 view->WCtoNDC(xx,u);
11405 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11406 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11407 gVirtualX->DrawPolyLine(5,rect2);
11408 }
11409 c->Clear();
11410 c->cd();
11411 TH2 *hp = (TH2*)h3->Project3D("xz");
11412 yaxis->SetRange(first,last);
11413 if (hp) {
11414 hp->SetFillColor(38);
11415 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11416 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11417 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11418 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11419 hp->SetZTitle("Number of Entries");
11420 hp->Draw(fShowOption.Data());
11421 }
11422 }
11423 break;
11424
11425 case 7:
11426 // "zx"
11427 {
11428 Int_t first = yaxis->GetFirst();
11429 Int_t last = yaxis->GetLast();
11430 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11431 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11432 yaxis->SetRange(biny,biny2);
11433 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11434 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11435 xx[0] = xaxis->GetXmin();
11436 xx[2] = zaxis->GetXmax();
11437 xx[1] = yaxis->GetBinCenter(biny);
11438 view->WCtoNDC(xx,u);
11439 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11440 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11441 rect1[4].SetX(rect1[0].GetX());
11442 rect1[4].SetY(rect1[0].GetY());
11443 xx[0] = xaxis->GetXmax();
11444 view->WCtoNDC(xx,u);
11445 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11446 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11447 xx[2] = zaxis->GetXmin();
11448 view->WCtoNDC(xx,u);
11449 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11450 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11451 xx[0] = xaxis->GetXmin();
11452 view->WCtoNDC(xx,u);
11453 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11454 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11455 gVirtualX->DrawPolyLine(5,rect1);
11456 if (nbins>1) {
11457 xx[0] = xaxis->GetXmin();
11458 xx[2] = zaxis->GetXmax();
11459 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11460 view->WCtoNDC(xx,u);
11461 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11462 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11463 rect2[4].SetX(rect2[0].GetX());
11464 rect2[4].SetY(rect2[0].GetY());
11465 xx[0] = xaxis->GetXmax();
11466 view->WCtoNDC(xx,u);
11467 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11468 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11469 xx[2] = zaxis->GetXmin();
11470 view->WCtoNDC(xx,u);
11471 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11472 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11473 xx[0] = xaxis->GetXmin();
11474 view->WCtoNDC(xx,u);
11475 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11476 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11477 gVirtualX->DrawPolyLine(5,rect2);
11478 }
11479 c->Clear();
11480 c->cd();
11481 TH2 *hp = (TH2*)h3->Project3D("zx");
11482 yaxis->SetRange(first,last);
11483 if (hp) {
11484 hp->SetFillColor(38);
11485 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11486 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11487 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11488 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11489 hp->SetZTitle("Number of Entries");
11490 hp->Draw(fShowOption.Data());
11491 }
11492 }
11493 break;
11494
11495 case 8:
11496 // "yz"
11497 {
11498 Int_t first = xaxis->GetFirst();
11499 Int_t last = xaxis->GetLast();
11500 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11501 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11502 xaxis->SetRange(binx,binx2);
11503 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11504 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11505 xx[2] = zaxis->GetXmin();
11506 xx[1] = yaxis->GetXmax();
11507 xx[0] = xaxis->GetBinCenter(binx);
11508 view->WCtoNDC(xx,u);
11509 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11510 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11511 rect1[4].SetX(rect1[0].GetX());
11512 rect1[4].SetY(rect1[0].GetY());
11513 xx[2] = zaxis->GetXmax();
11514 view->WCtoNDC(xx,u);
11515 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11516 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11517 xx[1] = yaxis->GetXmin();
11518 view->WCtoNDC(xx,u);
11519 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11520 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11521 xx[2] = zaxis->GetXmin();
11522 view->WCtoNDC(xx,u);
11523 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11524 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11525 gVirtualX->DrawPolyLine(5,rect1);
11526 if (nbins>1) {
11527 xx[2] = zaxis->GetXmin();
11528 xx[1] = yaxis->GetXmax();
11529 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11530 view->WCtoNDC(xx,u);
11531 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11532 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11533 rect2[4].SetX(rect2[0].GetX());
11534 rect2[4].SetY(rect2[0].GetY());
11535 xx[2] = zaxis->GetXmax();
11536 view->WCtoNDC(xx,u);
11537 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11538 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11539 xx[1] = yaxis->GetXmin();
11540 view->WCtoNDC(xx,u);
11541 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11542 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11543 xx[2] = zaxis->GetXmin();
11544 view->WCtoNDC(xx,u);
11545 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11546 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11547 gVirtualX->DrawPolyLine(5,rect2);
11548 }
11549 c->Clear();
11550 c->cd();
11551 TH2 *hp = (TH2*)h3->Project3D("yz");
11552 xaxis->SetRange(first,last);
11553 if (hp) {
11554 hp->SetFillColor(38);
11555 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11556 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11557 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11558 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11559 hp->SetZTitle("Number of Entries");
11560 hp->Draw(fShowOption.Data());
11561 }
11562 }
11563 break;
11564
11565 case 9:
11566 // "zy"
11567 {
11568 Int_t first = xaxis->GetFirst();
11569 Int_t last = xaxis->GetLast();
11570 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11571 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11572 xaxis->SetRange(binx,binx2);
11573 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11574 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11575 xx[2] = zaxis->GetXmin();
11576 xx[1] = yaxis->GetXmax();
11577 xx[0] = xaxis->GetBinCenter(binx);
11578 view->WCtoNDC(xx,u);
11579 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11580 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11581 rect1[4].SetX(rect1[0].GetX());
11582 rect1[4].SetY(rect1[0].GetY());
11583 xx[2] = zaxis->GetXmax();
11584 view->WCtoNDC(xx,u);
11585 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11586 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11587 xx[1] = yaxis->GetXmin();
11588 view->WCtoNDC(xx,u);
11589 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11590 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11591 xx[2] = zaxis->GetXmin();
11592 view->WCtoNDC(xx,u);
11593 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11594 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11595 gVirtualX->DrawPolyLine(5,rect1);
11596 if (nbins>1) {
11597 xx[2] = zaxis->GetXmin();
11598 xx[1] = yaxis->GetXmax();
11599 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11600 view->WCtoNDC(xx,u);
11601 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11602 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11603 rect2[4].SetX(rect2[0].GetX());
11604 rect2[4].SetY(rect2[0].GetY());
11605 xx[2] = zaxis->GetXmax();
11606 view->WCtoNDC(xx,u);
11607 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11608 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11609 xx[1] = yaxis->GetXmin();
11610 view->WCtoNDC(xx,u);
11611 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11612 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11613 xx[2] = zaxis->GetXmin();
11614 view->WCtoNDC(xx,u);
11615 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11616 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11617 gVirtualX->DrawPolyLine(5,rect2);
11618 }
11619 c->Clear();
11620 c->cd();
11621 TH2 *hp = (TH2*)h3->Project3D("zy");
11622 xaxis->SetRange(first,last);
11623 if (hp) {
11624 hp->SetFillColor(38);
11625 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11626 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11627 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11628 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11629 hp->SetZTitle("Number of Entries");
11630 hp->Draw(fShowOption.Data());
11631 }
11632 }
11633 break;
11634 }
11635 c->Update();
11636 padsav->cd();
11637}
@ 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
ROOT::R::TRInterface & r
Definition Object.C:4
#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
static const double x2[5]
static const double x1[5]
int Int_t
Definition RtypesCore.h:45
unsigned int UInt_t
Definition RtypesCore.h:46
const Bool_t kFALSE
Definition RtypesCore.h:92
unsigned long ULong_t
Definition RtypesCore.h:55
long Long_t
Definition RtypesCore.h:54
short Width_t
Definition RtypesCore.h:82
short Short_t
Definition RtypesCore.h:39
double Double_t
Definition RtypesCore.h:59
short Color_t
Definition RtypesCore.h:83
short Style_t
Definition RtypesCore.h:80
float Float_t
Definition RtypesCore.h:57
const Bool_t kTRUE
Definition RtypesCore.h:91
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:85
#define ClassImp(name)
Definition Rtypes.h:364
@ kBlack
Definition Rtypes.h:65
include TDocParser_001 C image html pict1_TDocParser_001 png width
R__EXTERN TEnv * gEnv
Definition TEnv.h:171
XFontStruct * id
Definition TGX11.cxx:109
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TBox * gYHighlightBox
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 TBox * gXHighlightBox
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 TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
double cos(double)
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:406
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition TStyle.h:412
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
polygon * polys
Definition X3DBuffer.c:24
static struct mg_connection * fc(struct mg_context *ctx)
Definition civetweb.c:3728
Int_t fN
Definition TArray.h:38
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:36
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:40
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:41
virtual Float_t GetTickLength() const
Definition TAttAxis.h:45
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:43
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
virtual void SetImageQuality(EImageQuality lquality)
Definition TAttImage.h:99
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:41
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:41
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:35
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:42
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:43
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:45
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:46
Class to manage histogram axis.
Definition TAxis.h:30
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:126
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
const TArrayD * GetXbins() const
Definition TAxis.h:130
Double_t GetXmax() const
Definition TAxis.h:134
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:518
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:419
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:126
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:469
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:571
Double_t GetXmin() const
Definition TAxis.h:133
Int_t GetNbins() const
Definition TAxis.h:121
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:946
virtual const char * GetTimeFormat() const
Definition TAxis.h:127
const char * GetTitle() const
Returns title of object.
Definition TAxis.h:129
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:920
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition TAxis.cxx:540
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition TAxis.cxx:528
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition TAxis.cxx:458
THashList * GetLabels() const
Definition TAxis.h:117
Create a Box.
Definition TBox.h:22
Double_t GetX1() const
Definition TBox.h:50
virtual void SetY2(Double_t y2)
Definition TBox.h:64
Double_t GetX2() const
Definition TBox.h:51
Double_t GetY1() const
Definition TBox.h:52
virtual void SetX1(Double_t x1)
Definition TBox.h:61
Double_t GetY2() const
Definition TBox.h:53
virtual void Draw(Option_t *option="")
Draw this box with its current attributes.
Definition TBox.cxx:195
virtual void SetX2(Double_t x2)
Definition TBox.h:62
virtual void SetY1(Double_t y1)
Definition TBox.h:63
virtual void Paint(Option_t *option="")
Paint this box with its current attributes.
Definition TBox.cxx:669
The candle plot painter class.
Definition TCandle.h:26
void SetLog(int x, int y, int z)
Definition TCandle.h:123
CandleOption
Definition TCandle.h:29
void SetHistoWidth(const Double_t width)
Definition TCandle.h:127
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition TCandle.cxx:675
Bool_t IsViolinScaled()
Definition TCandle.cxx:191
Bool_t IsHorizontal()
Definition TCandle.h:117
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:245
void SetOption(CandleOption opt)
Definition TCandle.h:122
void SetHistogram(TH1D *proj)
Definition TCandle.h:128
Bool_t IsCandleScaled()
Definition TCandle.cxx:186
void SetCandleWidth(const Double_t width)
Definition TCandle.h:126
void SetAxisPosition(const Double_t candlePos)
Definition TCandle.h:124
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition TCanvas.cxx:2491
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:2957
void SetName(const char *name)
virtual void Paint(Option_t *option="")
Paint all objects in this collection.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
The color creation and management class.
Definition TColor.h:19
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its associated colors.
Definition TColor.cxx:1705
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:78
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:51
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:1769
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:1916
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:1948
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:73
virtual void SetAlpha(Float_t a)
Definition TColor.h:67
To draw a Crown.
Definition TCrown.h:19
virtual void Paint(Option_t *option="")
Paint this crown with its current attributes.
Definition TCrown.cxx:181
Graphical cut class.
Definition TCutG.h:20
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:213
virtual Double_t GetXmax() const
Definition TF1.h:556
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:3407
virtual Double_t GetMaximumStored() const
Definition TF1.h:473
@ kNotDraw
Definition TF1.h:326
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:3420
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:1434
virtual Double_t GetXmin() const
Definition TF1.h:552
A 2-Dim function with parameters.
Definition TF2.h:29
virtual void Paint(Option_t *option="")
Paint this 2-D function with its current attributes.
Definition TF2.cxx:726
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:150
A 3-Dim function with parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:23
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2734
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:954
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:124
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2707
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:106
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:904
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:118
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:107
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2699
The TGraphDelaunay painting class.
void Paint(Option_t *option)
Paint a TGraphDelaunay according to the value of "option":
TList * GetContourList(Double_t contour)
Returns the X and Y graphs building a contour.
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
@ kClipFrame
clip to the frame boundary
Definition TGraph.h:70
1-D histogram with a double per channel (see TH1 documentation)}
Definition TH1.h:618
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:575
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
virtual void SetTitle(const char *title)
See GetStatOverflows for more information.
Definition TH1.cxx:6678
TAxis * GetZaxis()
Definition TH1.h:322
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:272
virtual Float_t GetBarWidth() const
Definition TH1.h:256
virtual Double_t GetMinimumStored() const
Definition TH1.h:292
virtual Float_t GetBarOffset() const
Definition TH1.h:255
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7500
virtual Int_t GetNbinsY() const
Definition TH1.h:297
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:8903
virtual Int_t GetNbinsZ() const
Definition TH1.h:298
virtual Double_t GetNormFactor() const
Definition TH1.h:300
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:7428
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7564
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8288
virtual void SetXTitle(const char *title)
Definition TH1.h:413
virtual Int_t GetDimension() const
Definition TH1.h:282
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1282
@ kNoTitle
don't draw the histogram title
Definition TH1.h:169
@ kUserContour
user specified contour levels
Definition TH1.h:165
@ kNoStats
don't draw stats box
Definition TH1.h:164
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition TH1.h:320
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:4893
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:8390
virtual Int_t GetNbinsX() const
Definition TH1.h:296
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:398
TAxis * GetYaxis()
Definition TH1.h:321
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:8919
virtual void SetContour(Int_t nlevels, const Double_t *levels=0)
Set the number and values of contour levels.
Definition TH1.cxx:8331
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:399
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7834
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:9062
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:8992
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4386
virtual void SetZTitle(const char *title)
Definition TH1.h:415
TList * GetListOfFunctions() const
Definition TH1.h:243
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7468
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition TH1.cxx:3073
virtual Double_t GetMaximumStored() const
Definition TH1.h:288
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8571
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8420
@ kNormal
errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition TH1.h:64
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:4993
const Double_t * GetBuffer() const
Definition TH1.h:238
virtual Bool_t IsHighlight() const
Definition TH1.h:334
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9003
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:8950
virtual void SetYTitle(const char *title)
Definition TH1.h:414
virtual Int_t GetSumw2N() const
Definition TH1.h:314
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7548
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:8475
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7810
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:750
virtual Int_t GetContour(Double_t *levels=0)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8259
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1402
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7637
2-D histogram with a double per channel (see TH1 documentation)}
Definition TH2.h:292
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:251
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
Service class for 2-Dim histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y.
Definition TH2.cxx:2367
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X.
Definition TH2.cxx:2327
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH2.cxx:1215
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH2.h:88
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH3.cxx:1299
virtual TH1 * Project3D(Option_t *option="x") const
Project a 3-d histogram into 1 or 2-d histograms depending on the option parameter,...
Definition TH3.cxx:2313
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
virtual Bool_t IsInside(Int_t x, Int_t y)
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
TAxis * fYaxis
Double_t * fXbuf
Int_t fXHighlightBin
virtual void DrawPanel()
Display a panel with all histogram drawing options.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
virtual void SetHistogram(TH1 *h)
Set current histogram to h
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual void PaintStat(Int_t dostat, TF1 *fit)
Draw the statistics box for 1D and profile histograms.
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 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.
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
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.
virtual ~THistPainter()
Default destructor.
virtual char * GetObjectInfo(Int_t px, Int_t py) const
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
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.
TString fShowOption
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
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.
TList * fFunctions
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
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.
virtual void ProcessMessage(const char *mess, const TObject *obj)
Process message mess.
Double_t * fYbuf
TAxis * fXaxis
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.
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute the distance from the point px,py to a line.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
TPainter3dAlgorithms * fLego
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
TGraph2DPainter * fGraph2DPainter
THistPainter()
Default constructor.
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
virtual void Paint(Option_t *option="")
Control routine to paint any kind of histograms
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.
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute the actions corresponding to event.
virtual void SetShowProjection(const char *option, Int_t nbins)
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
virtual void SetHighlight()
Set highlight (enable/disable) mode for fH.
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]
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
virtual TList * GetContourList(Double_t contour) const
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
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]
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
virtual Int_t MakeCuts(char *cutsopt)
Decode string choptin and fill Graphical cuts structure.
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.
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
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=0)
Definition TImage.h:116
static TImage * Create()
Create an image.
Definition TImage.cxx:35
virtual void PaintImage(Drawable_t, Int_t, Int_t, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0, Option_t *="")
Definition TImage.h:243
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
A doubly linked list.
Definition TList.h:44
virtual void Add(TObject *obj)
Definition TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition TList.cxx:822
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition TList.cxx:100
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition TList.cxx:578
virtual TObjLink * FirstLink() const
Definition TList.h:108
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:659
TMatrixTBase.
TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:36
TList * GetListOfGraphs() const
Definition TMultiGraph.h:70
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
virtual const char * GetTitle() const
Returns title of object.
Definition TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
An array of TObjects.
Definition TObjArray.h:37
void Add(TObject *obj)
Definition TObjArray.h:74
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
TObject * At(Int_t idx) const
Definition TObjArray.h:166
Mother of all ROOT objects.
Definition TObject.h:37
virtual void Clear(Option_t *="")
Definition TObject.h:115
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:359
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:187
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:343
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:879
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:323
virtual void Delete(Option_t *option="")
Delete this object.
Definition TObject.cxx:171
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:696
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:445
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:893
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:521
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:63
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:58
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:60
The Legos and Surfaces painter class.
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 SetDrawFace(DrawFaceFunc_t pointer)
Store pointer to current algorithm to draw faces.
void SetIsoSurfaceParameters(Double_t fmin, Double_t fmax, Int_t ncolor, Int_t ic1, Int_t ic2, Int_t ic3)
void IsoSurface(Int_t ns, Double_t *s, Int_t nx, Int_t ny, Int_t nz, Double_t *x, Double_t *y, Double_t *z, const char *chopt)
Draw set of iso-surfaces for a scalar function defined on a grid.
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 SetLegoFunction(LegoFunc_t pointer)
Store pointer to current lego function.
void SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in cylindrical coordinates.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots in cylindrical coordinates.
void FillPolygonBorder(Int_t nn, Double_t *xy)
Fill a polygon including border ("RASTER SCREEN")
void LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots spheric coordinates.
void SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
Draw surface in cartesian coordinate system.
void SurfaceProperty(Double_t qqa, Double_t qqd, Double_t qqs, Int_t nnqs, Int_t &irep)
Set surface property coefficients.
void InitMoveScreen(Double_t xmin, Double_t xmax)
Initialize "MOVING SCREEN" method.
void FindVisibleLine(Double_t *p1, Double_t *p2, Int_t ntmax, Int_t &nt, Double_t *t)
Find visible part of a line ("RASTER SCREEN")
void LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
Draw stack of lego-plots in cartesian coordinates.
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 LightSource(Int_t nl, Double_t yl, Double_t xscr, Double_t yscr, Double_t zscr, Int_t &irep)
Set light source.
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 SetSurfaceFunction(SurfaceFunc_t pointer)
Store pointer to current surface function.
void SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in polar coordinates.
void SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in spheric coordinates.
void BackBox(Double_t ang)
Draw back surfaces of surrounding box.
void ColorFunction(Int_t nl, Double_t *fl, Int_t *icl, Int_t &irep)
Set correspondence between function and color levels.
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 LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots in polar coordinates.
void SetEdgeAtt(Color_t color=1, Style_t style=1, Width_t width=1, Int_t n=0)
void SetMesh(Int_t mesh=1)
void InitRaster(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Int_t nx, Int_t ny)
Initialize hidden lines removal algorithm (RASTER SCREEN)
void DefineGridLevels(Int_t ndivz)
Define the grid levels drawn in the background of surface and lego plots.
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 SetColorMain(Color_t color, Int_t n=0)
Store color for stack number n.
void Spectrum(Int_t nl, Double_t fmin, Double_t fmax, Int_t ic, Int_t idc, Int_t &irep)
Set Spectrum.
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 FrontBox(Double_t ang)
Draw front surfaces of surrounding box & axes.
void SetColorDark(Color_t color, Int_t n=0)
Store dark color for stack number n.
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)
void ImplicitFunction(TF3 *f3, Double_t *rmin, Double_t *rmax, Int_t nx, Int_t ny, Int_t nz, const char *chopt)
Draw implicit function FUN(X,Y,Z) = 0 in cartesian coordinates using hidden surface removal algorithm...
The palette painting class.
void SetHistogram(TH1 *h)
virtual void Paint(Option_t *option="")
Paint the palette.
TH1 * GetHistogram()
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual void SetParent(TObject *obj)
Definition TPaveStats.h:52
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.
virtual void Paint(Option_t *option="")
Paint the pave stat.
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
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.
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
virtual void Paint(Option_t *option="")
Paint this pavetext with its current attributes.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
virtual void Clear(Option_t *option="")
Clear all lines in this pavetext.
virtual void SetName(const char *name="")
Definition TPave.h:75
Option_t * GetName() const
Returns name of object.
Definition TPave.h:56
virtual void SetBorderSize(Int_t bordersize=4)
Definition TPave.h:73
Double_t GetX1NDC() const
Definition TPave.h:59
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:79
Draw a Pie Chart,.
Definition TPie.h:23
virtual void Paint(Option_t *)
Paint a Pie chart in a canvas.
Definition TPie.cxx:804
virtual void ExecuteEvent(Int_t, Int_t, Int_t)
Execute the mouse events.
Definition TPie.cxx:395
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Evaluate the distance to the chart in gPad.
Definition TPie.cxx:170
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Defined by an array on N points in a 2-D space.
Definition TPolyLine.h:23
Double_t * GetX() const
Definition TPolyLine.h:54
virtual void SetPoint(Int_t point, Double_t x, Double_t y)
Set point number n to (x, y) If n is greater than the current size, the arrays are automatically exte...
Double_t * GetY() const
Definition TPolyLine.h:55
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Profile Histogram.
Definition TProfile.h:32
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition TProfile.cxx:833
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
virtual Double_t Rndm()
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:56
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:136
Ssiz_t Length() const
Definition TString.h:410
void ToLower()
Change string to lower-case.
Definition TString.cxx:1145
const char * Data() const
Definition TString.h:369
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:2331
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2309
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:639
Int_t GetOptStat() const
Definition TStyle.h:236
Color_t GetStatTextColor() const
Definition TStyle.h:249
Float_t GetTitleX() const
Definition TStyle.h:271
Int_t GetOptTitle() const
Definition TStyle.h:237
Float_t GetStatFontSize() const
Definition TStyle.h:252
Float_t GetBarOffset() const
Definition TStyle.h:174
Float_t GetStatX() const
Definition TStyle.h:255
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1188
Float_t GetTitleY() const
Definition TStyle.h:272
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1164
Bool_t GetHistMinimumZero() const
Definition TStyle.h:228
Float_t GetStatY() const
Definition TStyle.h:256
Color_t GetTitleFillColor() const
Definition TStyle.h:262
Style_t GetTitleStyle() const
Definition TStyle.h:264
Color_t GetStatColor() const
Definition TStyle.h:248
Float_t GetBarWidth() const
Definition TStyle.h:175
Float_t GetStatH() const
Definition TStyle.h:258
Width_t GetTitleBorderSize() const
Definition TStyle.h:266
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1056
Float_t GetErrorX() const
Definition TStyle.h:178
Double_t GetHistTopMargin() const
Definition TStyle.h:229
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:319
Float_t GetEndErrorSize() const
Definition TStyle.h:177
Width_t GetStatBorderSize() const
Definition TStyle.h:250
Int_t GetTitleAlign()
Definition TStyle.h:261
Color_t GetTitleTextColor() const
Definition TStyle.h:263
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:320
Float_t GetTitleH() const
Definition TStyle.h:274
Style_t GetStatStyle() const
Definition TStyle.h:253
Float_t GetStatW() const
Definition TStyle.h:257
const char * GetFitFormat() const
Definition TStyle.h:191
const char * GetStatFormat() const
Definition TStyle.h:254
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1122
Int_t GetOptFit() const
Definition TStyle.h:235
Int_t GetNumberContours() const
Definition TStyle.h:232
const char * GetPaintTextFormat() const
Definition TStyle.h:241
Style_t GetStatFont() const
Definition TStyle.h:251
Float_t GetTitleFontSize() const
Definition TStyle.h:265
Float_t GetTitleW() const
Definition TStyle.h:273
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1853
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:27
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 FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
virtual void Show()
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
virtual Int_t GetLogz() const =0
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual Int_t GetLogy() const =0
virtual Int_t GetLogx() const =0
TText * text
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
return c1
Definition legend1.C:41
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ey[n]
Definition legend1.C:17
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:713
Short_t Max(Short_t a, Short_t b)
Definition TMathBase.h:212
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:614
Double_t ATan(Double_t)
Definition TMath.h:675
constexpr Double_t PiOver2()
Definition TMath.h:51
Double_t Log(Double_t x)
Definition TMath.h:760
constexpr Double_t DegToRad()
Conversion from degree to radian:
Definition TMath.h:81
Double_t Sqrt(Double_t x)
Definition TMath.h:691
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition TMath.h:735
Short_t Min(Short_t a, Short_t b)
Definition TMathBase.h:180
Double_t Cos(Double_t)
Definition TMath.h:643
constexpr Double_t Pi()
Definition TMath.h:37
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Definition TMath.h:430
Double_t Sin(Double_t)
Definition TMath.h:639
Double_t Tan(Double_t)
Definition TMath.h:647
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition TMathBase.h:278
constexpr Double_t RadToDeg()
Conversion from radian to degree:
Definition TMath.h:73
Double_t Log10(Double_t x)
Definition TMath.h:764
Short_t Abs(Short_t d)
Definition TMathBase.h:120
Definition first.py:1
Definition graph.py:1
Histogram option structure.
Definition Hoption.h:24
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:29
int Proj
1: Aitoff, 2: Mercator, 3: Sinusoidal, 4: Parabolic
Definition Hoption.h:58
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:27
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:40
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:47
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:49
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:42
int AxisPos
Axis position.
Definition Hoption.h:59
int List
= 1 to generate the TObjArray "contours"
Definition Hoption.h:57
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:67
int Zscale
"Z" to display the Z scale (color palette)
Definition Hoption.h:54
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:62
int Contour
"CONT" Draw 2D plot as a Contour plot.
Definition Hoption.h:43
int Off
"][" With H option, the first and last vertical lines are not drawn.
Definition Hoption.h:32
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:44
long Candle
"CANDLE" Draw a 2D histogram as candle/box plot or violin plot (also with "VIOLIN").
Definition Hoption.h:52
int Spec
TSpectrum graphics.
Definition Hoption.h:60
int FrontBox
= 0 to suppress the front box
Definition Hoption.h:55
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:51
int Char
"CHAR" Draw 2D plot with a character set.
Definition Hoption.h:41
int Star
"*" A * is plotted at each point
Definition Hoption.h:38
int Zero
if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:61
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:69
int Tri
"TRI" Draw 2D plot with Delaunay triangles.
Definition Hoption.h:50
int BackBox
= 0 to suppress the back box
Definition Hoption.h:56
int Mark
"P" The current Marker is drawn at each point
Definition Hoption.h:35
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:39
int Line
"L" A simple polyline beetwen every point is drawn.
Definition Hoption.h:34
int Same
"S" Histogram is plotted in the current PAD.
Definition Hoption.h:36
int Lego
"LEGO" Draw as a Lego plot(LEGO,Lego=1, LEGO1,Lego1=11, LEGO2,Lego=12).
Definition Hoption.h:46
int Bar
"B" A Bar chart is drawn at each point.
Definition Hoption.h:28
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:31
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:45
int Surf
"SURF" Draw as a Surface (SURF,Surf=1, SURF1,Surf=11, SURF2,Surf=12)
Definition Hoption.h:48
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:68
int System
type of coordinate system(1=car,2=pol,3=cyl,4=sph,5=psr)
Definition Hoption.h:53
int Error
"E" Draw Errors with current marker type and size.
Definition Hoption.h:30
Histogram parameters structure.
Definition Hparam.h:26
Double_t baroffset
offset of bin for bars or legos [0,1]
Definition Hparam.h:41
Double_t ylowedge
low edge of axis
Definition Hparam.h:32
Double_t xmin
minimum value along X
Definition Hparam.h:29
Int_t ylast
last bin number along Y
Definition Hparam.h:46
Int_t xfirst
first bin number along X
Definition Hparam.h:43
Double_t zmin
minimum value along Z
Definition Hparam.h:37
Double_t xbinsize
bin size in case of equidistant bins
Definition Hparam.h:27
Double_t ymin
minimum value along y
Definition Hparam.h:33
Double_t allchan
integrated sum of contents
Definition Hparam.h:40
Double_t xlowedge
low edge of axis
Definition Hparam.h:28
Double_t ymax
maximum value along y
Definition Hparam.h:34
Double_t factor
multiplication factor (normalization)
Definition Hparam.h:39
Int_t xlast
last bin number along X
Definition Hparam.h:44
Double_t ybinsize
bin size in case of equidistant bins
Definition Hparam.h:31
Double_t barwidth
width of bin for bars and legos [0,1]
Definition Hparam.h:42
Double_t zmax
maximum value along Z
Definition Hparam.h:38
Double_t xmax
maximum value along X
Definition Hparam.h:30
Int_t yfirst
first bin number along Y
Definition Hparam.h:45
auto * th2
Definition textalign.C:17
auto * m
Definition textangle.C:8
auto * tt
Definition textangle.C:16
auto * l
Definition textangle.C:4
#define mark(osub)
Definition triangle.c:1206