Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THistPainter.cxx
Go to the documentation of this file.
1// @(#)root/histpainter:$Id$
2// Author: Rene Brun, Olivier Couet
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <cstdlib>
13#include <cstring>
14#include <cstdio>
15#include <cctype>
16#include <iostream>
17
18#include "TROOT.h"
19#include "TSystem.h"
20#include "THistPainter.h"
21#include "TH2.h"
22#include "TH2Poly.h"
23#include "TH3.h"
24#include "TProfile.h"
25#include "TProfile2D.h"
26#include "THStack.h"
27#include "TF2.h"
28#include "TF3.h"
29#include "TCutG.h"
30#include "TMatrixDBase.h"
31#include "TMatrixFBase.h"
32#include "TVectorD.h"
33#include "TVectorF.h"
34#include "TCanvas.h"
35#include "TPad.h"
36#include "TPaveStats.h"
37#include "TFrame.h"
38#include "TLatex.h"
39#include "TPolyLine.h"
40#include "TPoints.h"
41#include "TStyle.h"
42#include "TGraph.h"
43#include "TMultiGraph.h"
44#include "TPie.h"
45#include "TGaxis.h"
46#include "TColor.h"
48#include "TGraph2D.h"
49#include "TGraph2DPainter.h"
50#include "TGraphDelaunay2D.h"
51#include "TView.h"
52#include "TMath.h"
53#include "TRandom2.h"
54#include "TObjArray.h"
55#include "Hoption.h"
56#include "Hparam.h"
57#include "TPluginManager.h"
58#include "TPaletteAxis.h"
59#include "TCrown.h"
60#include "TArrow.h"
61#include "TVirtualPadEditor.h"
62#include "TVirtualX.h"
63#include "TEnv.h"
64#include "TPoint.h"
65#include "TImage.h"
66#include "TCandle.h"
67#include "strlcpy.h"
68
69/*! \class THistPainter
70 \ingroup Histpainter
71 \brief The histogram painter class. Implements all histograms' drawing's options.
72
73- [Introduction](\ref HP00)
74- [Histograms' plotting options](\ref HP01)
75 - [Options supported for 1D and 2D histograms](\ref HP01a)
76 - [Options supported for 1D histograms](\ref HP01b)
77 - [Options supported for 2D histograms](\ref HP01c)
78 - [Options supported for 3D histograms](\ref HP01d)
79 - [Options supported for histograms' stacks (THStack)](\ref HP01e)
80- [Setting the Style](\ref HP02)
81- [Setting line, fill, marker, and text attributes](\ref HP03)
82- [Setting Tick marks on the histogram axis](\ref HP04)
83- [Giving titles to the X, Y and Z axis](\ref HP05)
84- [The option "SAME"](\ref HP060)
85 - [Limitations](\ref HP060a)
86- [Colors automatically picked in palette](\ref HP061)
87- [Superimposing two histograms with different scales in the same pad](\ref HP06)
88- [Statistics Display](\ref HP07)
89- [Fit Statistics](\ref HP08)
90- [The error bars options](\ref HP09)
91- [The bar chart option](\ref HP100)
92- [The "BAR" and "HBAR" options](\ref HP10)
93- [The SCATter plot option (default for 2D histograms)](\ref HP11)
94- [The ARRow option](\ref HP12)
95- [The BOX option](\ref HP13)
96- [The COLor option](\ref HP14)
97- [The CANDLE and VIOLIN options](\ref HP140)
98 - [The CANDLE option](\ref HP140a)
99 - [The VIOLIN option](\ref HP140b)
100- [The TEXT and TEXTnn Option](\ref HP15)
101- [The CONTour options](\ref HP16)
102 - [The LIST option](\ref HP16a)
103 - [The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options](\ref HP16b)
104- [The LEGO options](\ref HP17)
105- [The "SURFace" options](\ref HP18)
106- [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](\ref HP19)
107- [Base line for bar-charts and lego plots](\ref HP20)
108- [TH2Poly Drawing](\ref HP20a)
109- [The SPEC option](\ref HP21)
110- [Option "Z" : Adding the color palette on the right side of the pad](\ref HP22)
111- [Setting the color palette](\ref HP23)
112- [Drawing a sub-range of a 2-D histogram; the [cutg] option](\ref HP24)
113- [Drawing options for 3D histograms](\ref HP25)
114- [Drawing option for histograms' stacks](\ref HP26)
115- [Drawing of 3D implicit functions](\ref HP27)
116- [Associated functions drawing](\ref HP28)
117- [Drawing using OpenGL](\ref HP29)
118 - [General information: plot types and supported options](\ref HP29a)
119 - [TH3 as color boxes](\ref HP290)
120 - [TH3 as boxes (spheres)](\ref HP29b)
121 - [TH3 as iso-surface(s)](\ref HP29c)
122 - [TF3 (implicit function)](\ref HP29d)
123 - [Parametric surfaces](\ref HP29e)
124 - [Interaction with the plots](\ref HP29f)
125 - [Selectable parts](\ref HP29g)
126 - [Rotation and zooming](\ref HP29h)
127 - [Panning](\ref HP29i)
128 - [Box cut](\ref HP29j)
129 - [Plot specific interactions (dynamic slicing etc.)](\ref HP29k)
130 - [Surface with option "GLSURF"](\ref HP29l)
131 - [TF3](\ref HP29m)
132 - [Box](\ref HP29n)
133 - [Iso](\ref HP29o)
134 - [Parametric plot](\ref HP29p)
135- [Highlight mode for histogram](\ref HP30)
136 - [Highlight mode and user function](\ref HP30a)
137
138
139\anchor HP00
140## Introduction
141
142
143Histograms are drawn via the `THistPainter` class. Each histogram has a
144pointer to its own painter (to be usable in a multithreaded program). When the
145canvas has to be redrawn, the `Paint` function of each objects in the
146pad is called. In case of histograms, `TH1::Paint` invokes directly
147`THistPainter::Paint`.
148
149To draw a histogram `h` it is enough to do:
150
151 h->Draw();
152
153`h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
154be drawn, the `Draw()` method can be invoked with an option. For instance
155to draw a 2D histogram as a lego plot it is enough to do:
156
157 h->Draw("lego");
158
159`THistPainter` offers many options to paint 1D, 2D and 3D histograms.
160
161When the `Draw()` method of a histogram is called for the first time
162(`TH1::Draw`), it creates a `THistPainter` object and saves a
163pointer to this "painter" as a data member of the histogram. The
164`THistPainter` class specializes in the drawing of histograms. It is
165separated from the histogram so that one can have histograms without the
166graphics overhead, for example in a batch program. Each histogram having its own
167painter (rather than a central singleton painter painting all histograms), allows
168two histograms to be drawn in two threads without overwriting the painter's
169values.
170
171When a displayed histogram is filled again, there is no need to call the
172`Draw()` method again; the image will be refreshed the next time the
173pad will be updated.
174
175A pad is updated after one of these three actions:
176
1771. a carriage control on the ROOT command line,
1782. a click inside the pad,
1793. a call to `TPad::Update`.
180
181
182By default a call to `TH1::Draw()` clears the pad of all objects
183before drawing the new image of the histogram. One can use the `SAME`
184option to leave the previous display intact and superimpose the new histogram.
185The same histogram can be drawn with different graphics options in different
186pads.
187
188When a displayed histogram is deleted, its image is automatically removed
189from the pad.
190
191To create a copy of the histogram when drawing it, one can use
192`TH1::DrawClone()`. This will clone the histogram and allow to change
193and delete the original one without affecting the clone.
194
195
196\anchor HP01
197### Histograms' plotting options
198
199
200Most options can be concatenated with or without spaces or commas, for example:
201
202 h->Draw("E1 SAME");
203
204The options are not case sensitive:
205
206 h->Draw("e1 same");
207
208
209The default drawing option can be set with `TH1::SetOption` and retrieve
210using `TH1::GetOption`:
211
212 root [0] h->Draw(); // Draw "h" using the standard histogram representation.
213 root [1] h->Draw("E"); // Draw "h" using error bars
214 root [3] h->SetOption("E"); // Change the default drawing option for "h"
215 root [4] h->Draw(); // Draw "h" using error bars
216 root [5] h->GetOption(); // Retrieve the default drawing option for "h"
217 (const Option_t* 0xa3ff948)"E"
218
219
220\anchor HP01a
221#### Options supported for 1D and 2D histograms
222
223| Option | Description |
224|----------|-------------------------------------------------------------------|
225| "E" | Draw error bars. |
226| "AXIS" | Draw only axis. |
227| "AXIG" | Draw only grid (if the grid is requested). |
228| \anchor OPTHIST "HIST" | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
229| "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
230| "SAME" | Superimpose on previous picture in the same pad. |
231| "SAMES" | Same as "SAME" and draw the statistics box|
232| "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
233| "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
234| "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
235| "LEGO" | Draw a lego plot with hidden line removal. |
236| "LEGO1" | Draw a lego plot with hidden surface removal. |
237| "LEGO2" | Draw a lego plot using colors to show the cell contents When the option "0" is used with any LEGO option, the empty bins are not drawn.|
238| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
239| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
240| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
241| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90). |
242| "X+" | The X-axis is drawn on the top side of the plot. |
243| "Y+" | The Y-axis is drawn on the right side of the plot. |
244| "MIN0" | Set minimum value for the Y axis to 0, equivalent to gStyle->SetHistMinimumZero(). |
245
246\anchor HP01b
247#### Options supported for 1D histograms
248
249| Option | Description |
250|----------|-------------------------------------------------------------------|
251| " " | Default. |
252| "AH" | Draw histogram without axis. "A" can be combined with any drawing option. For instance, "AC" draws the histogram as a smooth Curve without axis.|
253| "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
254| "B" | Bar chart option.|
255| "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
256| "HBAR" | Like option "BAR", but bars are drawn horizontally.|
257| "C" | Draw a smooth Curve through the histogram bins.|
258| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
259| "E1" | Draw error bars with perpendicular lines at the edges.|
260| "E2" | Draw error bars with rectangles.|
261| "E3" | Draw a fill area through the end points of the vertical error bars.|
262| "E4" | Draw a smoothed filled area through the end points of the error bars.|
263| "E5" | Like E3 but ignore the bins with 0 contents.|
264| "E6" | Like E4 but ignore the bins with 0 contents.|
265| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
266| "L" | Draw a line through the bin contents.|
267| "P" | Draw current marker at each bin except empty bins.|
268| "P*" | Draw a star marker at each bin except empty bins.|
269| "P0" | Draw current marker at each bin including empty bins.|
270| "PIE" | Draw histogram as a Pie Chart.|
271| "*H" | Draw histogram with a * at each bin.|
272| "LF2" | Draw histogram like with option "L" but with a fill area. Note that "L" draws also a fill area if the hist fill color is set but the fill area corresponds to the histogram contour.|
273
274
275\anchor HP01c
276#### Options supported for 2D histograms
277
278| Option | Description |
279|--------------|------------------------------------------------------------------|
280| " " | Default (scatter plot).|
281| "ARR" | Arrow mode. Shows gradient between adjacent cells.|
282| "BOX" | A box is drawn for each cell with surface proportional to the content's absolute value. A negative content is marked with a X.|
283| "BOX1" | A button is drawn for each cell with surface proportional to content's absolute value. A sunken button is drawn for negative values a raised one for positive.|
284| "COL" | A box is drawn for each cell with a color scale varying with contents. All the none empty bins are painted. Empty bins are not painted unless some bins have a negative content because in that case the null bins might be not empty. `TProfile2D` histograms are handled differently because, for this type of 2D histograms, it is possible to know if an empty bin has been filled or not. So even if all the bins' contents are positive some empty bins might be painted. And vice versa, if some bins have a negative content some empty bins might be not painted.|
285| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
286| "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
287| "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
288| "Z CJUST" | In combination with colored options "COL","CONT0" etc: Justify labels in the color palette at color boudaries. For more details see `TPaletteAxis`|
289| "CANDLE" | Draw a candle plot along X axis.|
290| "CANDLEX" | Same as "CANDLE".|
291| "CANDLEY" | Draw a candle plot along Y axis.|
292| "CANDLEXn" | Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
293| "CANDLEYn" | Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
294| "VIOLIN" | Draw a violin plot along X axis.|
295| "VIOLINX" | Same as "VIOLIN".|
296| "VIOLINY" | Draw a violin plot along Y axis.|
297| "VIOLINXn" | Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
298| "VIOLINYn" | Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
299| "CONT" | Draw a contour plot (same as CONT0).|
300| "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
301| "CONT1" | Draw a contour plot using line styles to distinguish contours.|
302| "CONT2" | Draw a contour plot using the same line style for all contours.|
303| "CONT3" | Draw a contour plot using fill area colors.|
304| "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
305| "LIST" | Generate a list of TGraph objects for each contour.|
306| "SAME0" | Same as "SAME" but do not use the z-axis range of the first plot. |
307| "SAMES0" | Same as "SAMES" but do not use the z-axis range of the first plot. |
308| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
309| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
310| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
311| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
312| "SURF" | Draw a surface plot with hidden line removal.|
313| "SURF1" | Draw a surface plot with hidden surface removal.|
314| "SURF2" | Draw a surface plot using colors to show the cell contents.|
315| "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
316| "SURF4" | Draw a surface using Gouraud shading.|
317| "SURF5" | Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH or PSR it allows to draw colored contours on a sphere, a cylinder or a in pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.|
318| "AITOFF" | Draw a contour via an AITOFF projection.|
319| "MERCATOR" | Draw a contour via an Mercator projection.|
320| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
321| "PARABOLIC" | Draw a contour via an Parabolic projection.|
322| "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
323| "FB" | With LEGO or SURFACE, suppress the Front-Box.|
324| "BB" | With LEGO or SURFACE, suppress the Back-Box.|
325| "A" | With LEGO or SURFACE, suppress the axis.|
326| "SCAT" | Draw a scatter-plot (default).|
327| "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
328
329
330\anchor HP01d
331#### Options supported for 3D histograms
332
333| Option | Description |
334|----------|-------------------------------------------------------------------|
335| " " | Default (scatter plot).|
336| "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)`.|
337| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
338| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
339| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
340| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
341| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
342| "LEGO" | Same as `BOX`.|
343
344
345\anchor HP01e
346#### Options supported for histograms' stacks (`THStack`)
347
348| Option | Description |
349|------------|-----------------------------------------------------------------|
350| " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
351| "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
352| "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
353| "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.|
354| "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
355| "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
356| "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
357
358
359
360\anchor HP02
361### Setting the Style
362
363
364Histograms use the current style (`gStyle`). When one changes the current
365style and would like to propagate the changes to the histogram,
366`TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
367each histogram is needed.
368
369To force all the histogram to use the current style use:
370
371 gROOT->ForceStyle();
372
373All the histograms read after this call will use the current style.
374
375
376\anchor HP03
377### Setting line, fill, marker, and text attributes
378
379
380The histogram classes inherit from the attribute classes:
381`TAttLine`, `TAttFill` and `TAttMarker`.
382See the description of these classes for the list of options.
383
384
385\anchor HP04
386### Setting Tick marks on the histogram axis
387
388
389The `TPad::SetTicks` method specifies the type of tick marks on the axis.
390If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
391
392 tx = 1; tick marks on top side are drawn (inside)
393 tx = 2; tick marks and labels on top side are drawn
394 ty = 1; tick marks on right side are drawn (inside)
395 ty = 2; tick marks and labels on right side are drawn
396
397By default only the left Y axis and X bottom axis are drawn
398(`tx = ty = 0`)
399
400`TPad::SetTicks(tx,ty)` allows to set these options.
401See also The `TAxis` functions to set specific axis attributes.
402
403In case multiple color filled histograms are drawn on the same pad, the fill
404area may hide the axis tick marks. One can force a redraw of the axis over all
405the histograms by calling:
406
407 gPad->RedrawAxis();
408
409
410\anchor HP05
411### Giving titles to the X, Y and Z axis
412
413
414 h->GetXaxis()->SetTitle("X axis title");
415 h->GetYaxis()->SetTitle("Y axis title");
416
417The histogram title and the axis titles can be any `TLatex` string.
418The titles are part of the persistent histogram.
419
420
421\anchor HP060
422### The option "SAME"
423
424
425By default, when an histogram is drawn, the current pad is cleared before
426drawing. In order to keep the previous drawing and draw on top of it the
427option `SAME` should be use. The histogram drawn with the option
428`SAME` uses the coordinates system available in the current pad.
429
430This option can be used alone or combined with any valid drawing option but
431some combinations must be use with care.
432
433\anchor HP060a
434#### Limitations
435
436- It does not work when combined with the `LEGO` and `SURF` options unless the
437 histogram plotted with the option `SAME` has exactly the same
438 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
439 lego plots [histograms' stacks](\ref HP26) should be used.
440
441
442\anchor HP061
443### Colors automatically picked in palette
444
445\since **ROOT version 6.09/01**
446
447When several histograms are painted in the same canvas thanks to the option "SAME"
448or via a `THStack` it might be useful to have an easy and automatic way to choose
449their color. The simplest way is to pick colors in the current active color
450palette. Palette coloring for histogram is activated thanks to the options `PFC`
451(Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
452When one of these options is given to `TH1::Draw` the histogram get its color
453from the current color palette defined by `gStyle->SetPalette(...)`. The color
454is determined according to the number of objects having palette coloring in
455the current pad.
456
457Begin_Macro(source)
458../../../tutorials/hist/histpalettecolor.C
459End_Macro
460
461Begin_Macro(source)
462../../../tutorials/hist/thstackpalettecolor.C
463End_Macro
464
465Begin_Macro(source)
466../../../tutorials/hist/thstack2palettecolor.C
467End_Macro
468
469\anchor HP06
470### Superimposing two histograms with different scales in the same pad
471
472
473The following example creates two histograms, the second histogram is the bins
474integral of the first one. It shows a procedure to draw the two histograms in
475the same pad and it draws the scale of the second histogram using a new vertical
476axis on the right side. See also the tutorial `transpad.C` for a variant
477of this example.
478
479Begin_Macro(source)
480{
481 auto c1 = new TCanvas("c1","c1",600,400);
482 // create/fill draw h1
483 gStyle->SetOptStat(kFALSE);
484 auto h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
485 Int_t i;
486 for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
487 h1->Draw();
488 c1->Update();
489
490 // create hint1 filled with the bins integral of h1
491 auto hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
492 float sum = 0.f;
493 for (i=1;i<=100;i++) {
494 sum += h1->GetBinContent(i);
495 hint1->SetBinContent(i,sum);
496 }
497
498 // scale hint1 to the pad coordinates
499 float rightmax = 1.1*hint1->GetMaximum();
500 float scale = gPad->GetUymax()/rightmax;
501 hint1->SetLineColor(kRed);
502 hint1->Scale(scale);
503 hint1->Draw("same");
504
505 // draw an axis on the right side
506 auto axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
507 gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
508 axis->SetLineColor(kRed);
509 axis->SetTextColor(kRed);
510 axis->Draw();
511}
512End_Macro
513
514
515\anchor HP07
516### Statistics Display
517
518
519The type of information shown in the histogram statistics box can be selected
520with:
521
522 gStyle->SetOptStat(mode);
523
524The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
525
526 mode = ksiourmen (default = 000001111)
527 k = 1; kurtosis printed
528 k = 2; kurtosis and kurtosis error printed
529 s = 1; skewness printed
530 s = 2; skewness and skewness error printed
531 i = 1; integral of bins printed
532 i = 2; integral of bins with option "width" printed
533 o = 1; number of overflows printed
534 u = 1; number of underflows printed
535 r = 1; standard deviation printed
536 r = 2; standard deviation and standard deviation error printed
537 m = 1; mean value printed
538 m = 2; mean and mean error values printed
539 e = 1; number of entries printed
540 n = 1; name of histogram is printed
541
542For example:
543
544 gStyle->SetOptStat(11);
545
546displays only the name of histogram and the number of entries, whereas:
547
548 gStyle->SetOptStat(1101);
549
550displays the name of histogram, mean value and standard deviation.
551
552<b>WARNING 1:</b> never do:
553
554 gStyle->SetOptStat(0001111);
555
556but instead do:
557
558 gStyle->SetOptStat(1111);
559
560because `0001111` will be taken as an octal number!
561
562<b>WARNING 2:</b> for backward compatibility with older versions
563
564 gStyle->SetOptStat(1);
565
566is taken as:
567
568 gStyle->SetOptStat(1111)
569
570To print only the name of the histogram do:
571
572 gStyle->SetOptStat(1000000001);
573
574<b>NOTE</b> that in case of 2D histograms, when selecting only underflow
575(10000) or overflow (100000), the statistics box will show all combinations
576of underflow/overflows and not just one single number.
577
578The parameter mode can be any combination of the letters `kKsSiIourRmMen`
579
580 k : kurtosis printed
581 K : kurtosis and kurtosis error printed
582 s : skewness printed
583 S : skewness and skewness error printed
584 i : integral of bins printed
585 I : integral of bins with option "width" printed
586 o : number of overflows printed
587 u : number of underflows printed
588 r : standard deviation printed
589 R : standard deviation and standard deviation error printed
590 m : mean value printed
591 M : mean value mean error values printed
592 e : number of entries printed
593 n : name of histogram is printed
594
595For example, to print only name of histogram and number of entries do:
596
597 gStyle->SetOptStat("ne");
598
599To print only the name of the histogram do:
600
601 gStyle->SetOptStat("n");
602
603The default value is:
604
605 gStyle->SetOptStat("nemr");
606
607When a histogram is painted, a `TPaveStats` object is created and added
608to the list of functions of the histogram. If a `TPaveStats` object
609already exists in the histogram list of functions, the existing object is just
610updated with the current histogram parameters.
611
612Once a histogram is painted, the statistics box can be accessed using
613`h->FindObject("stats")`. In the command line it is enough to do:
614
615 Root > h->Draw()
616 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
617
618because after `h->Draw()` the histogram is automatically painted. But
619in a script file the painting should be forced using `gPad->Update()`
620in order to make sure the statistics box is created:
621
622 h->Draw();
623 gPad->Update();
624 TPaveStats *st = (TPaveStats*)h->FindObject("stats");
625
626Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
627
628When a histogram is drawn with the option `SAME`, the statistics box
629is not drawn. To force the statistics box drawing with the option
630`SAME`, the option `SAMES` must be used.
631If the new statistics box hides the previous statistics box, one can change
632its position with these lines (`h` being the pointer to the histogram):
633
634 Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
635 Root > st->SetX1NDC(newx1); //new x start position
636 Root > st->SetX2NDC(newx2); //new x end position
637
638To change the type of information for an histogram with an existing
639`TPaveStats` one should do:
640
641 st->SetOptStat(mode);
642
643Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
644(see above).
645
646One can delete the statistics box for a histogram `TH1* h` with:
647
648 h->SetStats(0)
649
650and activate it again with:
651
652 h->SetStats(1).
653
654Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
655`$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
656
657
658\anchor HP08
659### Fit Statistics
660
661
662The type of information about fit parameters printed in the histogram statistics
663box can be selected via the parameter mode. The parameter mode can be
664`= pcev` (default `= 0111`)
665
666 p = 1; print Probability
667 c = 1; print Chisquare/Number of degrees of freedom
668 e = 1; print errors (if e=1, v must be 1)
669 v = 1; print name/values of parameters
670
671Example:
672
673 gStyle->SetOptFit(1011);
674
675print fit probability, parameter names/values and errors.
676
6771. When `v = 1` is specified, only the non-fixed parameters are shown.
6782. When `v = 2` all parameters are shown.
679
680Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
681to `gStyle->SetOptFit(111)`
682
683
684\anchor HP09
685### The error bars options
686
687
688| Option | Description |
689|----------|-------------------------------------------------------------------|
690| "E" | Default. Shows only the error bars, not a marker.|
691| "E1" | Small lines are drawn at the end of the error bars.|
692| "E2" | Error rectangles are drawn.|
693| "E3" | A filled area is drawn through the end points of the vertical error bars.|
694| "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
695| "E0" | Draw error bars. Markers are drawn for bins with 0 contents. Combined with E1 or E2 it avoids error bars clipping|
696| "E5" | Like E3 but ignore the bins with 0 contents.|
697| "E6" | Like E4 but ignore the bins with 0 contents.|
698| "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
699
700Begin_Macro(source)
701{
702 auto c1 = new TCanvas("c1","c1",600,400);
703 auto he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
704 for (int i=0; i<10000; i++) he->Fill(gRandom->Gaus(0,1));
705 gStyle->SetEndErrorSize(3);
706 gStyle->SetErrorX(1.);
707 he->SetMarkerStyle(20);
708 he->Draw("E1");
709}
710End_Macro
711
712The options "E3" and "E4" draw an error band through the end points of the
713vertical error bars. With "E4" the error band is smoothed. Because of the
714smoothing algorithm used some artefacts may appear at the end of the band
715like in the following example. In such cases "E3" should be used instead
716of "E4".
717
718Begin_Macro(source)
719{
720 auto ce4 = new TCanvas("ce4","ce4",600,400);
721 ce4->Divide(2,1);
722 auto he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
723 Int_t i;
724 for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
725 he4->SetFillColor(kRed);
726 he4->GetXaxis()->SetRange(40,48);
727 ce4->cd(1);
728 he4->Draw("E4");
729 ce4->cd(2);
730 auto he3 = (TH1F*)he4->DrawClone("E3");
731 he3->SetTitle("Distribution drawn option E3");
732}
733End_Macro
734
7352D histograms can be drawn with error bars as shown is the following example:
736
737Begin_Macro(source)
738{
739 auto c2e = new TCanvas("c2e","c2e",600,400);
740 auto h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
741 float px, py;
742 for (Int_t i = 0; i < 25000; i++) {
743 gRandom->Rannor(px,py);
744 h2e->Fill(px,5*py);
745 }
746 h2e->Draw("E");
747}
748End_Macro
749
750
751\anchor HP100
752### The bar chart option
753
754
755The option "B" allows to draw simple vertical bar charts.
756The bar width is controlled with `TH1::SetBarWidth()`,
757and the bar offset within the bin, with `TH1::SetBarOffset()`.
758These two settings are useful to draw several histograms on the
759same plot as shown in the following example:
760
761Begin_Macro(source)
762{
763 int i;
764 const Int_t nx = 8;
765 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
766 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
767 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
768
769 auto cb = new TCanvas("cb","cb",600,400);
770 cb->SetGrid();
771
772 gStyle->SetHistMinimumZero();
773
774 auto h1b = new TH1F("h1b","Option B example",nx,0,nx);
775 h1b->SetFillColor(4);
776 h1b->SetBarWidth(0.4);
777 h1b->SetBarOffset(0.1);
778 h1b->SetStats(0);
779 h1b->SetMinimum(-5);
780 h1b->SetMaximum(5);
781
782 for (i=1; i<=nx; i++) {
783 h1b->SetBinContent(i, d_35_0[i-1]);
784 h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
785 }
786
787 h1b->Draw("b");
788
789 auto h2b = new TH1F("h2b","h2b",nx,0,nx);
790 h2b->SetFillColor(38);
791 h2b->SetBarWidth(0.4);
792 h2b->SetBarOffset(0.5);
793 h2b->SetStats(0);
794 for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
795
796 h2b->Draw("b same");
797}
798End_Macro
799
800
801\anchor HP10
802### The "BAR" and "HBAR" options
803
804
805When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
806bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
807An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
808`hbar2`, `hbar3`, `hbar4` (hbars.C).
809
810- The bar is filled with the histogram fill color.
811- The left side of the bar is drawn with a light fill color.
812- The right side of the bar is drawn with a dark fill color.
813- The percentage of the bar drawn with either the light or dark color is:
814 - 0% for option "(h)bar" or "(h)bar0"
815 - 10% for option "(h)bar1"
816 - 20% for option "(h)bar2"
817 - 30% for option "(h)bar3"
818 - 40% for option "(h)bar4"
819
820When an histogram has errors the option ["HIST"](\ref OPTHIST) together with the `(h)bar` option.
821
822Begin_Macro(source)
823../../../tutorials/hist/hbars.C
824End_Macro
825
826To control the bar width (default is the bin width) `TH1::SetBarWidth()`
827should be used.
828
829To control the bar offset (default is 0) `TH1::SetBarOffset()` should
830be used.
831
832These two parameters are useful when several histograms are plotted using
833the option `SAME`. They allow to plot the histograms next to each other.
834
835
836\anchor HP11
837### The SCATter plot option (default for 2D histograms)
838
839
840For each cell (i,j) a number of points proportional to the cell content is
841drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
842`kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
843If option is of the form `scat=ff`, (eg `scat=1.8`,
844`scat=1e-3`), then `ff` is used as a scale factor to compute the
845number of dots. `scat=1` is the default.
846
847By default the scatter plot is painted with a "dot marker" which not scalable
848(see the `TAttMarker` documentation). To change the marker size, a scalable marker
849type should be used. For instance a circle (marker style 20).
850
851Begin_Macro(source)
852{
853 auto c1 = new TCanvas("c1","c1",600,400);
854 auto hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
855 float px, py;
856 for (Int_t i = 0; i < 25000; i++) {
857 gRandom->Rannor(px,py);
858 hscat->Fill(px,5*py);
859 hscat->Fill(3+0.5*px,2*py-10.);
860 }
861 hscat->Draw("scat=0.5");
862}
863End_Macro
864
865
866\anchor HP12
867### The ARRow option
868
869
870Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
871The orientation of the arrow follows the cell gradient.
872
873Begin_Macro(source)
874{
875 auto c1 = new TCanvas("c1","c1",600,400);
876 auto harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
877 harr->SetLineColor(kRed);
878 float px, py;
879 for (Int_t i = 0; i < 25000; i++) {
880 gRandom->Rannor(px,py);
881 harr->Fill(px,5*py);
882 harr->Fill(3+0.5*px,2*py-10.,0.1);
883 }
884 harr->Draw("ARR");
885}
886End_Macro
887
888\since **ROOT version 6.17/01**
889
890The option `ARR` can be combined with the option `COL` or `COLZ`.
891
892Begin_Macro(source)
893{
894 auto c1 = new TCanvas("c1","c1",600,400);
895 auto harr = new TH2F("harr","Option ARR + COLZ example",20,-4,4,20,-20,20);
896 harr->SetStats(0);
897 float px, py;
898 for (Int_t i = 0; i < 25000; i++) {
899 gRandom->Rannor(px,py);
900 harr->Fill(px,5*py);
901 harr->Fill(3+0.5*px,2*py-10.,0.1);
902 }
903 harr->Draw("ARR COLZ");
904}
905End_Macro
906
907
908\anchor HP13
909### The BOX option
910
911
912For each cell (i,j) a box is drawn. The size (surface) of the box is
913proportional to the absolute value of the cell content.
914The cells with a negative content are drawn with a `X` on top of the box.
915
916Begin_Macro(source)
917{
918 auto c1 = new TCanvas("c1","c1",600,400);
919 auto hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
920 hbox->SetFillColor(42);
921 hbox->Fill(0.5, 0.5, 1.);
922 hbox->Fill(0.5, 1.5, 4.);
923 hbox->Fill(0.5, 2.5, 3.);
924 hbox->Fill(1.5, 0.5, 2.);
925 hbox->Fill(1.5, 1.5, 12.);
926 hbox->Fill(1.5, 2.5, -6.);
927 hbox->Fill(2.5, 0.5, -4.);
928 hbox->Fill(2.5, 1.5, 6.);
929 hbox->Fill(2.5, 2.5, 0.5);
930 hbox->Draw("BOX");
931}
932End_Macro
933
934With option `BOX1` a button is drawn for each cell with surface
935proportional to content's absolute value. A sunken button is drawn for
936negative values a raised one for positive.
937
938Begin_Macro(source)
939{
940 auto c1 = new TCanvas("c1","c1",600,400);
941 auto hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
942 hbox1->SetFillColor(42);
943 hbox1->Fill(0.5, 0.5, 1.);
944 hbox1->Fill(0.5, 1.5, 4.);
945 hbox1->Fill(0.5, 2.5, 3.);
946 hbox1->Fill(1.5, 0.5, 2.);
947 hbox1->Fill(1.5, 1.5, 12.);
948 hbox1->Fill(1.5, 2.5, -6.);
949 hbox1->Fill(2.5, 0.5, -4.);
950 hbox1->Fill(2.5, 1.5, 6.);
951 hbox1->Fill(2.5, 2.5, 0.5);
952 hbox1->Draw("BOX1");
953}
954End_Macro
955
956When the option `SAME` (or "SAMES") is used with the option `BOX`,
957the boxes' sizes are computing taking the previous plots into account. The range
958along the Z axis is imposed by the first plot (the one without option
959`SAME`); therefore the order in which the plots are done is relevant.
960
961Begin_Macro(source)
962{
963 auto c1 = new TCanvas("c1","c1",600,400);
964 auto hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
965 auto hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
966 auto hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
967 auto hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
968 for (Int_t i=0;i<1000;i++) {
969 double x,y;
970 gRandom->Rannor(x,y);
971 if (x>0 && y>0) hb1->Fill(x,y,4);
972 if (x<0 && y<0) hb2->Fill(x,y,3);
973 if (x>0 && y<0) hb3->Fill(x,y,2);
974 if (x<0 && y>0) hb4->Fill(x,y,1);
975 }
976 hb1->SetFillColor(1);
977 hb2->SetFillColor(2);
978 hb3->SetFillColor(3);
979 hb4->SetFillColor(4);
980 hb1->Draw("box");
981 hb2->Draw("box same");
982 hb3->Draw("box same");
983 hb4->Draw("box same");
984}
985End_Macro
986
987\since **ROOT version 6.17/01:**
988
989Sometimes the change of the range of the Z axis is unwanted, in which case, one
990can use `SAME0` (or `SAMES0`) option to opt out of this change.
991
992Begin_Macro(source)
993{
994 auto h2 = new TH2F("h2"," ",10,0,10,10,20,30);
995 auto hf = (TH2F*)h2->Clone("hf");
996 h2->SetBit(TH1::kNoStats);
997 hf->SetBit(TH1::kNoStats);
998 h2->Fill(5,22);
999 h2->Fill(5,23);
1000 h2->Fill(6,22);
1001 h2->Fill(6,23);
1002 hf->Fill(6,23);
1003 hf->Fill(6,23);
1004 hf->Fill(6,23);
1005 hf->Fill(6,23);
1006 hf->Fill(5,23);
1007
1008 auto hf_copy1 = hf->Clone("hf_copy1");
1009 TLatex lt;
1010
1011 auto cx = new TCanvas(); cx->Divide(2,1);
1012
1013 cx->cd(1);
1014 h2->Draw("box");
1015 hf->Draw("text colz same");
1016 lt.DrawLatexNDC(0.3,0.5,"SAME");
1017
1018 cx->cd(2);
1019 h2->Draw("box");
1020 hf_copy1->Draw("text colz same0");
1021 lt.DrawLatexNDC(0.3,0.5,"SAME0");
1022}
1023End_Macro
1024
1025
1026\anchor HP14
1027### The COLor option
1028
1029
1030For each cell (i,j) a box is drawn with a color proportional to the cell
1031content.
1032
1033The color table used is defined in the current style.
1034
1035If the histogram's minimum and maximum are the same (flat histogram), the
1036mapping on colors is not possible, therefore nothing is painted. To paint a
1037flat histogram it is enough to set the histogram minimum
1038(`TH1::SetMinimum()`) different from the bins' content.
1039
1040The default number of color levels used to paint the cells is 20.
1041It can be changed with `TH1::SetContour()` or
1042`TStyle::SetNumberContours()`. The higher this number is, the smoother
1043is the color change between cells.
1044
1045The color palette in TStyle can be modified via `gStyle->SetPalette()`.
1046
1047All the non-empty bins are painted. Empty bins are not painted unless
1048some bins have a negative content because in that case the null bins
1049might be not empty.
1050
1051`TProfile2D` histograms are handled differently because, for this type of 2D
1052histograms, it is possible to know if an empty bin has been filled or not. So even
1053if all the bins' contents are positive some empty bins might be painted. And vice versa,
1054if some bins have a negative content some empty bins might be not painted.
1055
1056Combined with the option `COL`, the option `Z` allows to
1057display the color palette defined by `gStyle->SetPalette()`.
1058
1059In the following example, the histogram has only positive bins; the empty
1060bins (containing 0) are not drawn.
1061
1062Begin_Macro(source)
1063{
1064 auto c1 = new TCanvas("c1","c1",600,400);
1065 auto hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
1066 float px, py;
1067 for (Int_t i = 0; i < 25000; i++) {
1068 gRandom->Rannor(px,py);
1069 hcol1->Fill(px,5*py);
1070 }
1071 hcol1->Draw("COLZ");
1072}
1073End_Macro
1074
1075In the first plot of following example, the histogram has some negative bins;
1076the empty bins (containing 0) are drawn. In some cases one wants to not draw
1077empty bins (containing 0) of histograms having a negative minimum. The option
1078`1`, used to produce the second plot in the following picture, allows to do that.
1079
1080Begin_Macro(source)
1081{
1082 auto c1 = new TCanvas("c1","c1",600,600);
1083 c1->Divide(1,2);
1084 auto hcol23 = new TH2F("hcol23","Option COLZ example ",40,-4,4,40,-20,20);
1085 auto hcol24 = new TH2F("hcol24","Option COLZ1 example ",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 hcol23->Fill(px,5*py);
1090 hcol24->Fill(px,5*py);
1091 }
1092 hcol23->Fill(0.,0.,-200.);
1093 hcol24->Fill(0.,0.,-200.);
1094 c1->cd(1); hcol23->Draw("COLZ");
1095 c1->cd(2); hcol24->Draw("COLZ1");
1096}
1097End_Macro
1098
1099When the maximum of the histogram is set to a smaller value than the real maximum,
1100 the bins having a content between the new maximum and the real maximum are
1101painted with the color corresponding to the new maximum.
1102
1103When the minimum of the histogram is set to a greater value than the real minimum,
1104 the bins having a value between the real minimum and the new minimum are not drawn
1105 unless the option `0` is set.
1106
1107The following example illustrates the option `0` combined with the option `COL`.
1108
1109Begin_Macro(source)
1110{
1111 auto c1 = new TCanvas("c1","c1",600,600);
1112 c1->Divide(1,2);
1113 auto hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1114 auto hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1115 float px, py;
1116 for (Int_t i = 0; i < 25000; i++) {
1117 gRandom->Rannor(px,py);
1118 hcol21->Fill(px,5*py);
1119 hcol22->Fill(px,5*py);
1120 }
1121 hcol21->SetBit(TH1::kNoStats);
1122 hcol22->SetBit(TH1::kNoStats);
1123 c1->cd(1); hcol21->Draw("COLZ");
1124 c1->cd(2); hcol22->Draw("COLZ0");
1125 hcol22->SetMaximum(100);
1126 hcol22->SetMinimum(40);
1127}
1128End_Macro
1129
1130\since **ROOT version 6.09/01:**
1131
1132When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1133are computing taking the previous plots into account. The range along the Z axis
1134is imposed by the first plot (the one without option SAME); therefore the order
1135in which the plots are done is relevant. Same as [in the `BOX` option](\ref HP13), one can use
1136`SAME0` (or `SAMES0`) to opt out of this imposition.
1137
1138Begin_Macro(source)
1139{
1140 auto c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1141 auto h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1142 auto h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1143 auto h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1144 auto h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1145 h1->SetBit(TH1::kNoStats);
1146 for (Int_t i=0;i<5000;i++) {
1147 double x,y;
1148 gRandom->Rannor(x,y);
1149 if(x>0 && y>0) h1->Fill(x,y,4);
1150 if(x<0 && y<0) h2->Fill(x,y,3);
1151 if(x>0 && y<0) h3->Fill(x,y,2);
1152 if(x<0 && y>0) h4->Fill(x,y,1);
1153 }
1154 h1->Draw("colz");
1155 h2->Draw("col same");
1156 h3->Draw("col same");
1157 h4->Draw("col same");
1158}
1159End_Macro
1160
1161The option `COL` can be combined with the option `POL`:
1162
1163Begin_Macro(source)
1164{
1165 auto c1 = new TCanvas("c1","c1",600,400);
1166 auto hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1167 float px, py;
1168 for (Int_t i = 0; i < 25000; i++) {
1169 gRandom->Rannor(px,py);
1170 hcol1->Fill(px,py);
1171 }
1172 hcol1->Draw("COLZPOL");
1173}
1174End_Macro
1175
1176\since **ROOT version 6.07/03:**
1177
1178A second rendering technique is also available with the COL2 and COLZ2 options.
1179
1180These options provide potential performance improvements compared to the standard
1181COL option. The performance comparison of the COL2 to the COL option depends on
1182the histogram and the size of the rendering region in the current pad. In general,
1183a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1184faster with the COL option.
1185
1186However, for larger histograms (approx. more than 100 bins per axis)
1187that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1188For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1189faster with the COL2 option.
1190
1191The COL2 option will also scale its performance based on the size of the
1192pixmap the histogram image is being rendered into. It also is much better optimized for
1193sessions where the user is forwarding X11 windows through an `ssh` connection.
1194
1195For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1196and COLZ options. There is one major difference and that concerns the treatment of
1197bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1198
1199COL2 option renders the histogram as a bitmap. Therefore it cannot be saved in vector
1200graphics file format like PostScript or PDF (an empty image will be generated). It can
1201be saved only in bitmap files like PNG format for instance.
1202
1203
1204\anchor HP140
1205### The CANDLE and VIOLIN options
1206
1207The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1208implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1209the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1210vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1211(1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1212
1213Instead of using the predefined representations, the candle and violin parameters can be
1214changed individually. In that case the option have the following form:
1215
1216 CANDLEX(<option-string>)
1217 CANDLEY(<option-string>)
1218 VIOLINX(<option-string>)
1219 VIOLINY(<option-string>).
1220
1221All zeros at the beginning of `option-string` can be omitted.
1222
1223`option-string` consists eight values, defined as follow:
1224
1225 "CANDLEX(zhpawMmb)"
1226
1227Where:
1228
1229 - `b = 0`; no box drawn
1230 - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1231 makes sense in the very most cases to always draw the box
1232 - `b = 2`; draw a filled box with border
1233
1234 - `m = 0`; no median drawn
1235 - `m = 1`; median is drawn as a line
1236 - `m = 2`; median is drawn with errors (notches)
1237 - `m = 3`; median is drawn as a circle
1238
1239 - `M = 0`; no mean drawn
1240 - `M = 1`; mean is drawn as a dashed line
1241 - `M = 3`; mean is drawn as a circle
1242
1243 - `w = 0`; no whisker drawn
1244 - `w = 1`; whisker is drawn to end of distribution.
1245 - `w = 2`; whisker is drawn to max 1.5*iqr
1246
1247 - `a = 0`; no anchor drawn
1248 - `a = 1`; the anchors are drawn
1249
1250 - `p = 0`; no points drawn
1251 - `p = 1`; only outliers are drawn
1252 - `p = 2`; all datapoints are drawn
1253 - `p = 3`: all datapoints are drawn scattered
1254
1255 - `h = 0`; no histogram is drawn
1256 - `h = 1`; histogram at the left or bottom side is drawn
1257 - `h = 2`; histogram at the right or top side is drawn
1258 - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1259
1260 - `z = 0`; no zero indicator line is drawn
1261 - `z = 1`; zero indicator line is drawn.
1262
1263As one can see all individual options for both candle and violin plots can be accessed by this
1264mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1265meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1266vice versa, if you wish.
1267
1268Using a logarithmic x- or y-axis is possible for candle and violin charts.
1269
1270\since **ROOT version 6.11/01**
1271
1272a logarithmic z-axis is possible, too but will only affect violin charts of course.
1273
1274\anchor HP140a
1275#### The CANDLE option
1276
1277<a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1278a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1279way to describe graphically a data distribution (D) with only five numbers:
1280
1281 1. The minimum value of the distribution D (bottom or left whisker).
1282 2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1283 3. The median (M): 50% of the data points in D are less than M.
1284 4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1285 5. The maximum value of the distribution D (top or right whisker).
1286
1287In this implementation a TH2 is considered as a collection of TH1 along
1288X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1289Each TH1 is represented as one candle.
1290
1291Begin_Macro(source)
1292../../../tutorials/hist/candleplotwhiskers.C
1293End_Macro
1294
1295The candle reduces the information coming from a whole distribution into few values.
1296Independently from the number of entries or the significance of the underlying distribution
1297a candle will always look like a candle. So candle plots should be used carefully in
1298particular with unknown distributions. The definition of a candle is based on
1299__unbinned data__. Here, candles are created from binned data. Because of this, the
1300deviation is connected to the bin width used. The calculation of the quantiles
1301normally done on unbinned data also. Because data are binned, this will
1302only work the best possible way within the resolution of one bin
1303
1304Because of all these facts one should take care that:
1305
1306 - there are enough points per candle
1307 - the bin width is small enough (more bins will increase the maximum
1308 available resolution of the quantiles although there will be some
1309 bins with no entries)
1310 - never make a candle-plot if the underlying distribution is double-distributed
1311 - only create candles of distributions that are more-or-less gaussian (the
1312 MPV should be not too far away from the mean).
1313
1314#### What a candle is made of
1315
1316\since **ROOT version 6.07/05**
1317
1318##### The box
1319The box displays the position of the inter-quantile-range of the underlying
1320distribution. The box contains 25% of the distribution below the median
1321and 25% of the distribution above the median. If the underlying distribution is large
1322enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1323(Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1324the position of the box can be modified by SetBarWidth() and SetBarOffset().
1325The +-25% quantiles are calculated by the GetQuantiles() methods.
1326
1327\since **ROOT version 6.11/01**
1328
1329Using the static function TCandle::SetBoxRange(double) the box definition will be
1330overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1331to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1332The static function will affect all candle-charts in the running program.
1333Default is 0.5.
1334
1335Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1336whole candle) can be influenced. Deactivated, the width is constant (to be set by
1337SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1338amount of data in the corresponding candle, the maximum width can be influenced by
1339SetBarWidth(). The static function will affect all candle-charts in the running program.
1340Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1341supported, yet
1342
1343##### The Median
1344For a sorted list of numbers, the median is the value in the middle of the list.
1345E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1346because it is in the middle of the list. If the number of entries is even the
1347average of the two values in the middle will be used. As histograms are binned
1348data, the situation is a bit more complex. The following example shows this:
1349
1350~~~ {.cpp}
1351void quantiles() {
1352 auto h = new TH1I("h","h",10,0,10);
1353 //h->Fill(3);
1354 //h->Fill(3);
1355 h->Fill(4);
1356 h->Draw();
1357 double p = 0.;
1358 double q = 0.;
1359 h->GetQuantiles(1,&q,&p);
1360
1361 cout << "Median is: " << q << std::endl;
1362}
1363~~~
1364
1365Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1366the example will return a calculated median of 4.5, because that's the bin center
1367of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1368commented out, it will return 3.75, because the algorithm tries to evenly distribute
1369the individual values of a bin with bin content > 0. It means the sorted list
1370would be "3.25, 3.75, 4.5".
1371
1372The consequence is a median of 3.75. This shows how important it is to use a
1373small enough bin-width when using candle-plots on binned data.
1374If the distribution is large enough and gaussian shaped the median will be exactly
1375equal to the mean.
1376The median can be shown as a line or as a circle or not shown at all.
1377
1378In order to show the significance of the median notched candle plots apply a "notch" or
1379narrowing of the box around the median. The significance is defined by
1380\f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1381(where iqr is the size of the box and N is the number of entries of the whole
1382distribution). Candle plots like these are usually called "notched candle plots".
1383
1384In case the significance of the median is greater that the size of the box, the
1385box will have an unnatural shape. Usually it means the chart has not enough data,
1386or that representing this uncertainty is not useful
1387
1388##### The Mean
1389The mean can be drawn as a dashed line or as a circle or not drawn at all.
1390The mean is the arithmetic average of the values in the distribution.
1391It is calculated using GetMean(). Because histograms are
1392binned data, the mean value can differ from a calculation on the raw-data.
1393If the distribution is large enough and gaussian shaped the mean will be
1394exactly the median.
1395
1396##### The Whiskers
1397The whiskers represent the part of the distribution not covered by the box.
1398The upper 25% and the lower 25% of the distribution are located within the whiskers.
1399Two representations are available.
1400
1401 - A simple one (using w=1) defining the lower whisker from the lowest data value
1402 to the bottom of the box, and the upper whisker from the top of the box to the
1403 highest data value. In this representation the whisker-lines are dashed.
1404 - A more complex one having a further restriction. The whiskers are still connected
1405 to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1406 be that the outermost part of the underlying distribution will not be covered
1407 by the whiskers. Usually these missing parts will be represented by the outliers
1408 (see points). Of course the upper and the lower whisker may differ in length.
1409 In this representation the whiskers are drawn as solid lines.
1410
1411\since **ROOT version 6.11/01**
1412
1413Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1414will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1415the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1416that candle. The static function will affect all candle-charts in the running program.
1417Default is 1.
1418
1419If the distribution is large enough and gaussian shaped, the maximum length of
1420the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
14211.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1422(see picture above). In that case 99.3% of the total distribution will be covered
1423by the box and the whiskers, whereas 0.7% are represented by the outliers.
1424
1425##### The Anchors
1426The anchors have no special meaning in terms of statistical calculation. They mark
1427the end of the whiskers and they have the width of the box. Both representation
1428with and without anchors are common.
1429
1430##### The Points
1431Depending on the configuration the points can have different meanings:
1432 - If p=1 the points represent the outliers. If they are shown, it means
1433 some parts of the underlying distribution are not covered by the whiskers.
1434 This can only occur when the whiskers are set to option w=2. Here the whiskers
1435 can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1436 whiskers will be drawn as outliers. The outliers will be represented by crosses.
1437 - If p=2 all points in the distribution will be painted as crosses. This is
1438 useful for small datasets only (up to 10 or 20 points per candle).
1439 The outliers are shown along the candle. Because the underlying distribution
1440 is binned, is frequently occurs that a bin contains more than one value.
1441 Because of this the points will be randomly scattered within their bin along
1442 the candle axis. If the bin content for a bin is exactly 1 (usually
1443 this happens for the outliers) if will be drawn in the middle of the bin along
1444 the candle axis. As the maximum number of points per candle is limited by kNMax/2
1445 on very large datasets scaling will be performed automatically. In that case one
1446 would loose all outliers because they have usually a bin content of 1 (and a
1447 bin content between 0 and 1 after the scaling). Because of this all bin contents
1448 between 0 and 1 - after the scaling - will be forced to be 1.
1449 - As the drawing of all values on large datasets can lead to big amounts of crosses,
1450 one can show all values as a scatter plot instead by choosing p=3. The points will be
1451 drawn as dots and will be scattered within the width of the candle. The color
1452 of the points will be the color of the candle-chart.
1453
1454##### Other Options
1455Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1456with a histogram.
1457
1458#### How to use the candle-plots drawing option
1459
1460There are six predefined candle-plot representations:
1461
1462 - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1463 - "CANDLEX2": Standard candle with better whisker definition + outliers.
1464 It is a good compromise
1465 - "CANDLEX3": Like candle2 but with a mean as a circle.
1466 It is easier to distinguish mean and median
1467 - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1468 (notched candle plots).
1469 For bigger datasets per candle
1470 - "CANDLEX5": Like candle2 but showing all data points.
1471 For very small datasets
1472 - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1473 For huge datasets
1474
1475
1476The following picture shows how the six predefined representations look.
1477
1478Begin_Macro
1479{
1480 auto c1 = new TCanvas("c1","c1",700,800);
1481 c1->Divide(2,3);
1482 gStyle->SetOptStat(kFALSE);
1483
1484 auto hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1485 float px, py;
1486 for (Int_t i = 0; i < 15000; i++) {
1487 gRandom->Rannor(px,py);
1488 hcandle->Fill(px,5*py);
1489 }
1490 hcandle->SetMarkerSize(0.5);
1491
1492 TH2F *h2;
1493 for (Int_t i=1; i<7; i++) {
1494 c1->cd(i);
1495 h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1496 h2->SetTitle(Form("CANDLE%d",i));
1497 }
1498}
1499End_Macro
1500
1501
1502#### Example 1
1503Box and improved whisker, no mean, no median, no anchor no outliers
1504
1505 h1->Draw("CANDLEX(2001)");
1506
1507#### Example 2
1508A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1509
1510 h1->Draw("CANDLEX(112111)");
1511
1512#### Example 3
1513The following example shows how several candle plots can be super-imposed using
1514the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1515Also the color, the line width, the size of the points and so on can be changed by the
1516standard attribute setting methods such as SetLineColor() SetLineWidth().
1517
1518Begin_Macro(source)
1519../../../tutorials/hist/candleplot.C
1520End_Macro
1521
1522\anchor HP140b
1523#### The VIOLIN option
1524
1525<a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1526that also encodes the pdf information at each point.
1527
1528
1529Quartiles and mean are also represented at each point, with a marker
1530and two lines.
1531
1532In this implementation a TH2 is considered as a collection of TH1 along
1533X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1534
1535#### What a violin is made of
1536
1537\since **ROOT version 6.09/02**
1538
1539##### The histogram
1540The histogram is typically drawn to both directions with respect to the middle-line of the
1541corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1542one side (h=1, or h=2).
1543The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1544histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1545be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1546A solid fill style is recommended.
1547
1548\since **ROOT version 6.11/01**
1549
1550Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1551violin can be influenced. Activated, the height of the bins of the individual violins will be
1552scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1553Deactivated, the height of the bin with the maximum content of each individual violin is
1554set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1555in the running program. Default is true. Scaling between multiple violin-charts
1556(using "same" or THStack) is not supported, yet.
1557
1558##### The zero indicator line
1559Typical for violin charts is a line in the background over the whole histogram indicating
1560the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1561will always be the same as the fill-color of the histogram.
1562
1563##### The Mean
1564The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1565
1566##### Whiskers
1567The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1568difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1569the whiskers will be forced to be solid (usually hashed)
1570
1571##### Points
1572The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1573better whisker definition (w=2) and outliers (p=1).
1574
1575##### Other options
1576It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1577including a box-plot.
1578
1579#### How to use the violin-plots drawing option
1580
1581There are two predefined violin-plot representations:
1582 - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1583 zero indicator line)
1584 - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1585
1586A solid fill style is recommended for this plot (as opposed to a hollow or
1587hashed style).
1588
1589Begin_Macro(source)
1590{
1591 auto c1 = new TCanvas("c1","c1",600,400);
1592 Int_t nx(6), ny(40);
1593 double xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1594 auto hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1595 TF1 f1("f1", "gaus", +0,0 +4.0);
1596 double x,y;
1597 for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1598 double xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1599 f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1600 for(Int_t i=0; i<10000; ++i){
1601 x = xc;
1602 y = f1.GetRandom();
1603 hviolin->Fill(x, y);
1604 }
1605 }
1606 hviolin->SetFillColor(kGray);
1607 hviolin->SetMarkerStyle(20);
1608 hviolin->SetMarkerSize(0.5);
1609 hviolin->Draw("VIOLIN");
1610 c1->Update();
1611}
1612End_Macro
1613
1614The next example illustrates a time development of a certain value:
1615
1616Begin_Macro(source)
1617../../../tutorials/hist/candledecay.C
1618End_Macro
1619
1620
1621\anchor HP15
1622### The TEXT and TEXTnn Option
1623
1624
1625For each bin the content is printed. The text attributes are:
1626
1627- text font = current TStyle font (`gStyle->SetTextFont()`).
1628- text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1629 with the option `TEXT` the marker size can be changed with
1630 `h->SetMarkerSize(markersize)`).
1631- text color = marker color.
1632
1633By default the format `g` is used. This format can be redefined
1634by calling `gStyle->SetPaintTextFormat()`.
1635
1636It is also possible to use `TEXTnn` in order to draw the text with
1637the angle `nn` (`0 < nn < 90`).
1638
1639For 2D histograms the text is plotted in the center of each non empty cells.
1640It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`
1641or providing MIN0 draw option. For 1D histogram the text is plotted at a y
1642position equal to the bin content.
1643
1644For 2D histograms when the option "E" (errors) is combined with the option
1645text ("TEXTE"), the error for each bin is also printed.
1646
1647Begin_Macro(source)
1648{
1649 auto c01 = new TCanvas("c01","c01",700,400);
1650 c01->Divide(2,1);
1651 auto htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1652 auto htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1653 float px, py;
1654 for (Int_t i = 0; i < 25000; i++) {
1655 gRandom->Rannor(px,py);
1656 htext1->Fill(px,0.1);
1657 htext2->Fill(px,5*py,0.1);
1658 }
1659 gStyle->SetPaintTextFormat("4.1f m");
1660 htext2->SetMarkerSize(1.8);
1661 c01->cd(1);
1662 htext2->Draw("TEXT45");
1663 c01->cd(2);
1664 htext1->Draw();
1665 htext1->Draw("HIST TEXT0 SAME");
1666}
1667End_Macro
1668
1669\since **ROOT version 6.07/07:**
1670
1671In case several histograms are drawn on top ot each other (using option `SAME`),
1672the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1673text position in each cell, in percentage of the bin width.
1674
1675Begin_Macro(source)
1676{
1677 auto c03 = new TCanvas("c03","c03",700,400);
1678 gStyle->SetOptStat(0);
1679 auto htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1680 auto htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1681 auto htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1682 float px, py;
1683 for (Int_t i = 0; i < 25000; i++) {
1684 gRandom->Rannor(px,py);
1685 htext3->Fill(4*px,20*py,0.1);
1686 htext4->Fill(4*px,20*py,0.5);
1687 htext5->Fill(4*px,20*py,1.0);
1688 }
1689 htext4->SetMarkerSize(1.8);
1690 htext5->SetMarkerSize(1.8);
1691 htext5->SetMarkerColor(kRed);
1692 htext3->Draw("COL");
1693 htext4->SetBarOffset(0.2);
1694 htext4->Draw("TEXT SAME");
1695 htext5->SetBarOffset(-0.2);
1696 htext5->Draw("TEXT SAME");
1697}
1698End_Macro
1699
1700In the case of profile histograms it is possible to print the number
1701of entries instead of the bin content. It is enough to combine the
1702option "E" (for entries) with the option "TEXT".
1703
1704Begin_Macro(source)
1705{
1706 auto c02 = new TCanvas("c02","c02",700,400);
1707 c02->Divide(2,1);
1708 gStyle->SetPaintTextFormat("g");
1709
1710 auto profile = new TProfile("profile","profile",10,0,10);
1711 profile->SetMarkerSize(2.2);
1712 profile->Fill(0.5,1);
1713 profile->Fill(1.5,2);
1714 profile->Fill(2.5,3);
1715 profile->Fill(3.5,4);
1716 profile->Fill(4.5,5);
1717 profile->Fill(5.5,5);
1718 profile->Fill(6.5,4);
1719 profile->Fill(7.5,3);
1720 profile->Fill(8.5,2);
1721 profile->Fill(9.5,1);
1722 c02->cd(1); profile->Draw("HIST TEXT0");
1723 c02->cd(2); profile->Draw("HIST TEXT0E");
1724}
1725End_Macro
1726
1727\anchor HP16
1728### The CONTour options
1729
1730
1731The following contour options are supported:
1732
1733| Option | Description |
1734|----------|-----------------------------------------------------------------------------|
1735| "CONT" | Draw a contour plot (same as CONT0). |
1736| "CONT0" | Draw a contour plot using surface colors to distinguish contours. |
1737| "CONT1" | Draw a contour plot using the line colors to distinguish contours. |
1738| "CONT2" | Draw a contour plot using the line styles (1 to 5) to distinguish contours. |
1739| "CONT3" | Draw a contour plot using the same line style for all contours. |
1740| "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0). |
1741
1742
1743The following example shows a 2D histogram plotted with the option
1744`CONTZ`. The option `CONT` draws a contour plot using surface
1745colors to distinguish contours. Combined with the option `CONT` (or
1746`CONT0`), the option `Z` allows to display the color palette
1747defined by `gStyle->SetPalette()`.
1748
1749Begin_Macro(source)
1750{
1751 auto c1 = new TCanvas("c1","c1",600,400);
1752 auto hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1753 float px, py;
1754 for (Int_t i = 0; i < 25000; i++) {
1755 gRandom->Rannor(px,py);
1756 hcontz->Fill(px-1,5*py);
1757 hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1758 }
1759 hcontz->Draw("CONTZ");
1760}
1761End_Macro
1762
1763The following example shows a 2D histogram plotted with the option
1764`CONT1Z`. The option `CONT1` draws a contour plot using the
1765line colors to distinguish contours. Combined with the option `CONT1`,
1766the option `Z` allows to display the color palette defined by
1767`gStyle->SetPalette()`.
1768
1769Begin_Macro(source)
1770{
1771 auto c1 = new TCanvas("c1","c1",600,400);
1772 auto hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1773 float px, py;
1774 for (Int_t i = 0; i < 25000; i++) {
1775 gRandom->Rannor(px,py);
1776 hcont1->Fill(px-1,5*py);
1777 hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1778 }
1779 hcont1->Draw("CONT1Z");
1780}
1781End_Macro
1782
1783The following example shows a 2D histogram plotted with the option
1784`CONT2`. The option `CONT2` draws a contour plot using the
1785line styles (1 to 5) to distinguish contours.
1786
1787Begin_Macro(source)
1788{
1789 auto c1 = new TCanvas("c1","c1",600,400);
1790 auto hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1791 float px, py;
1792 for (Int_t i = 0; i < 25000; i++) {
1793 gRandom->Rannor(px,py);
1794 hcont2->Fill(px-1,5*py);
1795 hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1796 }
1797 hcont2->Draw("CONT2");
1798}
1799End_Macro
1800
1801The following example shows a 2D histogram plotted with the option
1802`CONT3`. The option `CONT3` draws contour plot using the same line style for
1803all contours.
1804
1805Begin_Macro(source)
1806{
1807 auto c1 = new TCanvas("c1","c1",600,400);
1808 auto hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1809 float px, py;
1810 for (Int_t i = 0; i < 25000; i++) {
1811 gRandom->Rannor(px,py);
1812 hcont3->Fill(px-1,5*py);
1813 hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1814 }
1815 hcont3->SetLineStyle(kDotted);
1816 hcont3->Draw("CONT3");
1817}
1818End_Macro
1819
1820The following example shows a 2D histogram plotted with the option
1821`CONT4`. The option `CONT4` draws a contour plot using surface
1822colors to distinguish contours (`SURF` option at theta = 0). Combined
1823with the option `CONT` (or `CONT0`), the option `Z`
1824allows to display the color palette defined by `gStyle->SetPalette()`.
1825
1826Begin_Macro(source)
1827{
1828 auto c1 = new TCanvas("c1","c1",600,400);
1829 auto hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1830 float px, py;
1831 for (Int_t i = 0; i < 25000; i++) {
1832 gRandom->Rannor(px,py);
1833 hcont4->Fill(px-1,5*py);
1834 hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1835 }
1836 hcont4->Draw("CONT4Z");
1837}
1838End_Macro
1839
1840The default number of contour levels is 20 equidistant levels and can be changed
1841with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1842
1843\anchor HP16a
1844#### The LIST option
1845
1846When option `LIST` is specified together with option
1847`CONT`, the points used to draw the contours are saved in
1848`TGraph` objects:
1849
1850 h->Draw("CONT LIST");
1851 gPad->Update();
1852
1853The contour are saved in `TGraph` objects once the pad is painted.
1854Therefore to use this functionality in a macro, `gPad->Update()`
1855should be performed after the histogram drawing. Once the list is
1856built, the contours are accessible in the following way:
1857
1858 TObjArray *contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
1859 Int_t ncontours = contours->GetSize();
1860 TList *list = (TList*)contours->At(i);
1861
1862Where `i` is a contour number, and list contains a list of
1863`TGraph` objects.
1864For one given contour, more than one disjoint polyline may be generated.
1865The number of TGraphs per contour is given by:
1866
1867 list->GetSize();
1868
1869To access the first graph in the list one should do:
1870
1871 TGraph *gr1 = (TGraph*)list->First();
1872
1873
1874The following example (ContourList.C) shows how to use this functionality.
1875
1876Begin_Macro(source)
1877../../../tutorials/hist/ContourList.C
1878End_Macro
1879
1880\anchor HP16b
1881#### The AITOFF, MERCATOR, SINUSOIDAL and PARABOLIC options
1882
1883The following options select the `CONT4` option and are useful for
1884sky maps or exposure maps (earth.C).
1885
1886| Option | Description |
1887|--------------|---------------------------------------------------------------|
1888| "AITOFF" | Draw a contour via an AITOFF projection.|
1889| "MERCATOR" | Draw a contour via an Mercator projection.|
1890| "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1891| "PARABOLIC" | Draw a contour via an Parabolic projection.|
1892
1893Begin_Macro(source)
1894../../../tutorials/graphics/earth.C
1895End_Macro
1896
1897
1898\anchor HP17
1899### The LEGO options
1900
1901
1902In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1903is proportional to the cell content. The lego aspect is control with the
1904following options:
1905
1906| Option | Description |
1907|----------|-------------------------------------------------------------------|
1908| "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1909| "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1910| "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1911| "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1912| "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1913| "0" | When used with any LEGO option, the empty bins are not drawn.|
1914
1915
1916See the limitations with [the option "SAME"](\ref HP060a).
1917
1918Line attributes can be used in lego plots to change the edges' style.
1919
1920The following example shows a 2D histogram plotted with the option
1921`LEGO`. The option `LEGO` draws a lego plot using the hidden
1922lines removal technique.
1923
1924Begin_Macro(source)
1925{
1926 auto c2 = new TCanvas("c2","c2",600,400);
1927 auto hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1928 float px, py;
1929 for (Int_t i = 0; i < 25000; i++) {
1930 gRandom->Rannor(px,py);
1931 hlego->Fill(px-1,5*py);
1932 hlego->Fill(2+0.5*px,2*py-10.,0.1);
1933 }
1934 hlego->Draw("LEGO");
1935}
1936End_Macro
1937
1938The following example shows a 2D histogram plotted with the option
1939`LEGO1`. The option `LEGO1` draws a lego plot using the
1940hidden surface removal technique. Combined with any `LEGOn` option, the
1941option `0` allows to not drawn the empty bins.
1942
1943Begin_Macro(source)
1944{
1945 auto c2 = new TCanvas("c2","c2",600,400);
1946 auto hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1947 float px, py;
1948 for (Int_t i = 0; i < 25000; i++) {
1949 gRandom->Rannor(px,py);
1950 hlego1->Fill(px-1,5*py);
1951 hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1952 }
1953 hlego1->SetFillColor(kYellow);
1954 hlego1->Draw("LEGO1 0");
1955}
1956End_Macro
1957
1958The following example shows a 2D histogram plotted with the option
1959`LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1960draws a lego plot using the hidden surface removal technique but doesn't draw
1961the border lines of each individual lego-bar. This is very useful for histograms
1962having many bins. With such histograms the option `LEGO1` gives a black
1963image because of the border lines. This option also works with stacked legos.
1964
1965Begin_Macro(source)
1966{
1967 auto c2 = new TCanvas("c2","c2",600,400);
1968 auto hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1969 float px, py;
1970 for (Int_t i = 0; i < 25000; i++) {
1971 gRandom->Rannor(px,py);
1972 hlego3->Fill(px-1,5*py);
1973 hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1974 }
1975 hlego3->SetFillColor(kRed);
1976 hlego3->Draw("LEGO3");
1977}
1978End_Macro
1979
1980The following example shows a 2D histogram plotted with the option
1981`LEGO2`. The option `LEGO2` draws a lego plot using colors to
1982show the cell contents. Combined with the option `LEGO2`, the option
1983`Z` allows to display the color palette defined by
1984`gStyle->SetPalette()`.
1985
1986Begin_Macro(source)
1987{
1988 auto c2 = new TCanvas("c2","c2",600,400);
1989 auto hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1990 float px, py;
1991 for (Int_t i = 0; i < 25000; i++) {
1992 gRandom->Rannor(px,py);
1993 hlego2->Fill(px-1,5*py);
1994 hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1995 }
1996 hlego2->Draw("LEGO2Z");
1997}
1998End_Macro
1999
2000
2001
2002\anchor HP18
2003### The "SURFace" options
2004
2005
2006In a surface plot, cell contents are represented as a mesh.
2007The height of the mesh is proportional to the cell content.
2008
2009| Option | Description |
2010|----------|-------------------------------------------------------------------|
2011| "SURF" | Draw a surface plot using the hidden line removal technique.|
2012| "SURF1" | Draw a surface plot using the hidden surface removal technique.|
2013| "SURF2" | Draw a surface plot using colors to show the cell contents.|
2014| "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
2015| "SURF4" | Draw a surface using the Gouraud shading technique.|
2016| "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a filled contour plot.|
2017| "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.|
2018| "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
2019
2020
2021
2022See the limitations with [the option "SAME"](\ref HP060a).
2023
2024The following example shows a 2D histogram plotted with the option
2025`SURF`. The option `SURF` draws a lego plot using the hidden
2026lines removal technique.
2027
2028Begin_Macro(source)
2029{
2030 auto c2 = new TCanvas("c2","c2",600,400);
2031 auto hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
2032 float px, py;
2033 for (Int_t i = 0; i < 25000; i++) {
2034 gRandom->Rannor(px,py);
2035 hsurf->Fill(px-1,5*py);
2036 hsurf->Fill(2+0.5*px,2*py-10.,0.1);
2037 }
2038 hsurf->Draw("SURF");
2039}
2040End_Macro
2041
2042The following example shows a 2D histogram plotted with the option
2043`SURF1`. The option `SURF1` draws a surface plot using the
2044hidden surface removal technique. Combined with the option `SURF1`,
2045the option `Z` allows to display the color palette defined by
2046`gStyle->SetPalette()`.
2047
2048Begin_Macro(source)
2049{
2050 auto c2 = new TCanvas("c2","c2",600,400);
2051 auto hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
2052 float px, py;
2053 for (Int_t i = 0; i < 25000; i++) {
2054 gRandom->Rannor(px,py);
2055 hsurf1->Fill(px-1,5*py);
2056 hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
2057 }
2058 hsurf1->Draw("SURF1");
2059}
2060End_Macro
2061
2062The following example shows a 2D histogram plotted with the option
2063`SURF2`. The option `SURF2` draws a surface plot using colors
2064to show the cell contents. Combined with the option `SURF2`, the option
2065`Z` allows to display the color palette defined by
2066`gStyle->SetPalette()`.
2067
2068Begin_Macro(source)
2069{
2070 auto c2 = new TCanvas("c2","c2",600,400);
2071 auto hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2072 float px, py;
2073 for (Int_t i = 0; i < 25000; i++) {
2074 gRandom->Rannor(px,py);
2075 hsurf2->Fill(px-1,5*py);
2076 hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2077 }
2078 hsurf2->Draw("SURF2");
2079}
2080End_Macro
2081
2082The following example shows a 2D histogram plotted with the option
2083`SURF3`. The option `SURF3` draws a surface plot using the
2084hidden line removal technique with, in addition, a filled contour view drawn on the
2085top. Combined with the option `SURF3`, the option `Z` allows
2086to display the color palette defined by `gStyle->SetPalette()`.
2087
2088Begin_Macro(source)
2089{
2090 auto c2 = new TCanvas("c2","c2",600,400);
2091 auto hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2092 float px, py;
2093 for (Int_t i = 0; i < 25000; i++) {
2094 gRandom->Rannor(px,py);
2095 hsurf3->Fill(px-1,5*py);
2096 hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2097 }
2098 hsurf3->Draw("SURF3");
2099}
2100End_Macro
2101
2102The following example shows a 2D histogram plotted with the option
2103`SURF4`. The option `SURF4` draws a surface using the Gouraud
2104shading technique.
2105
2106Begin_Macro(source)
2107{
2108 auto c2 = new TCanvas("c2","c2",600,400);
2109 auto hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2110 float px, py;
2111 for (Int_t i = 0; i < 25000; i++) {
2112 gRandom->Rannor(px,py);
2113 hsurf4->Fill(px-1,5*py);
2114 hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2115 }
2116 hsurf4->SetFillColor(kOrange);
2117 hsurf4->Draw("SURF4");
2118}
2119End_Macro
2120
2121The following example shows a 2D histogram plotted with the option
2122`SURF5 CYL`. Combined with the option `SURF5`, the option
2123`Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2124
2125Begin_Macro(source)
2126{
2127 auto c2 = new TCanvas("c2","c2",600,400);
2128 auto hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2129 float px, py;
2130 for (Int_t i = 0; i < 25000; i++) {
2131 gRandom->Rannor(px,py);
2132 hsurf5->Fill(px-1,5*py);
2133 hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2134 }
2135 hsurf5->Draw("SURF5 CYL");
2136}
2137End_Macro
2138
2139The following example shows a 2D histogram plotted with the option
2140`SURF7`. The option `SURF7` draws a surface plot using the
2141hidden surfaces removal technique with, in addition, a line contour view drawn on the
2142top. Combined with the option `SURF7`, the option `Z` allows
2143to display the color palette defined by `gStyle->SetPalette()`.
2144
2145Begin_Macro(source)
2146{
2147 auto c2 = new TCanvas("c2","c2",600,400);
2148 auto hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2149 float px, py;
2150 for (Int_t i = 0; i < 25000; i++) {
2151 gRandom->Rannor(px,py);
2152 hsurf7->Fill(px-1,5*py);
2153 hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2154 }
2155 hsurf7->Draw("SURF7");
2156}
2157End_Macro
2158
2159As shown in the following example, when a contour plot is painted on top of a
2160surface plot using the option `SAME`, the contours appear in 3D on the
2161surface.
2162
2163Begin_Macro(source)
2164{
2165 auto c20=new TCanvas("c20","c20",600,400);
2166 int NBins = 50;
2167 double d = 2;
2168 auto hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2169 for (int bx = 1; bx <= NBins; ++bx) {
2170 for (int by = 1; by <= NBins; ++by) {
2171 double x = hsc->GetXaxis()->GetBinCenter(bx);
2172 double y = hsc->GetYaxis()->GetBinCenter(by);
2173 hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2174 }
2175 }
2176 hsc->Draw("surf2");
2177 hsc->Draw("CONT1 SAME");
2178}
2179End_Macro
2180
2181
2182\anchor HP19
2183### Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2184
2185
2186Legos and surfaces plots are represented by default in Cartesian coordinates.
2187Combined with any `LEGOn` or `SURFn` options the following
2188options allow to draw a lego or a surface in other coordinates systems.
2189
2190| Option | Description |
2191|----------|-------------------------------------------------------------------|
2192| "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2193| "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2194| "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2195| "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2196
2197
2198
2199<b>WARNING:</b> Axis are not drawn with these options.
2200
2201The following example shows the same histogram as a lego plot is the four
2202different coordinates systems.
2203
2204Begin_Macro(source)
2205{
2206 auto c3 = new TCanvas("c3","c3",600,400);
2207 c3->Divide(2,2);
2208 auto hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2209 float px, py;
2210 for (Int_t i = 0; i < 25000; i++) {
2211 gRandom->Rannor(px,py);
2212 hlcc->Fill(px-1,5*py);
2213 hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2214 }
2215 hlcc->SetFillColor(kYellow);
2216 c3->cd(1); hlcc->Draw("LEGO1 CYL");
2217 c3->cd(2); auto hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2218 hlpc->SetTitle("Polar coordinates");
2219 c3->cd(3); auto hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2220 hlsc->SetTitle("Spherical coordinates");
2221 c3->cd(4); auto hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2222 hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2223}
2224End_Macro
2225
2226The following example shows the same histogram as a surface plot is the four different coordinates systems.
2227
2228Begin_Macro(source)
2229{
2230 auto c4 = new TCanvas("c4","c4",600,400);
2231 c4->Divide(2,2);
2232 auto hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2233 float px, py;
2234 for (Int_t i = 0; i < 25000; i++) {
2235 gRandom->Rannor(px,py);
2236 hscc->Fill(px-1,5*py);
2237 hscc->Fill(2+0.5*px,2*py-10.,0.1);
2238 }
2239 c4->cd(1); hscc->Draw("SURF1 CYL");
2240 c4->cd(2); auto hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2241 hspc->SetTitle("Polar coordinates");
2242 c4->cd(3); auto hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2243 hssc->SetTitle("Spherical coordinates");
2244 c4->cd(4); auto hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2245 hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2246}
2247End_Macro
2248
2249
2250\anchor HP20
2251### Base line for bar-charts and lego plots
2252
2253
2254By default the base line used to draw the boxes for bar-charts and lego plots is
2255the histogram minimum. It is possible to force this base line to be 0, using MIN0 draw
2256option or with the command:
2257
2258 gStyle->SetHistMinimumZero();
2259
2260Begin_Macro(source)
2261{
2262 auto c5 = new TCanvas("c5","c5",700,400);
2263 c5->Divide(2,1);
2264 auto hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2265 auto hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2266 Int_t i;
2267 double x,y;
2268 hz1->SetFillColor(kBlue);
2269 hz2->SetFillColor(kBlue);
2270 for (i=0;i<10000;i++) {
2271 x = gRandom->Gaus(0,1);
2272 y = gRandom->Gaus(0,1);
2273 if (x>0) {
2274 hz1->Fill(x,1);
2275 hz2->Fill(x,y,1);
2276 } else {
2277 hz1->Fill(x,-1);
2278 hz2->Fill(x,y,-2);
2279 }
2280 }
2281 c5->cd(1); hz1->Draw("bar2 min0");
2282 c5->cd(2); hz2->Draw("lego1 min0");
2283}
2284End_Macro
2285
2286This option also works for horizontal plots. The example given in the section
2287["The bar chart option"](\ref HP100) appears as follow:
2288
2289Begin_Macro(source)
2290{
2291 int i;
2292 const Int_t nx = 8;
2293 string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2294 float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2295 float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2296
2297 auto cbh = new TCanvas("cbh","cbh",400,600);
2298 cbh->SetGrid();
2299
2300 auto h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2301 h1bh->SetFillColor(4);
2302 h1bh->SetBarWidth(0.4);
2303 h1bh->SetBarOffset(0.1);
2304 h1bh->SetStats(0);
2305 h1bh->SetMinimum(-5);
2306 h1bh->SetMaximum(5);
2307
2308 for (i=1; i<=nx; i++) {
2309 h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2310 h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2311 }
2312
2313 h1bh->Draw("hbar min0");
2314
2315 auto h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2316 h2bh->SetFillColor(38);
2317 h2bh->SetBarWidth(0.4);
2318 h2bh->SetBarOffset(0.5);
2319 h2bh->SetStats(0);
2320 for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2321
2322 h2bh->Draw("hbar min0 same");
2323}
2324End_Macro
2325
2326
2327\anchor HP20a
2328### TH2Poly Drawing
2329
2330
2331The following options are supported:
2332
2333| Option | Description |
2334|----------|-------------------------------------------------------------------|
2335| "SCAT" | Draw a scatter plot (default).|
2336| "COL" | Draw a color plot. All the bins are painted even the empty bins.|
2337| "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2338| "0" | When used with any COL options, the empty bins are not drawn.|
2339| "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2340| "TEXTN" | Draw bin names as text.|
2341| "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90).|
2342| "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2343| "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2344| "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2345
2346
2347
2348`TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2349shapes. The bins are defined as graphs. The following macro is a very simple
2350example showing how to book a TH2Poly and draw it.
2351
2352Begin_Macro(source)
2353{
2354 auto ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2355 auto h2p = new TH2Poly();
2356 h2p->SetName("h2poly_name");
2357 h2p->SetTitle("h2poly_title");
2358 double px1[] = {0, 5, 6};
2359 double py1[] = {0, 0, 5};
2360 double px2[] = {0, -1, -1, 0};
2361 double py2[] = {0, 0, -1, 3};
2362 double px3[] = {4, 3, 0, 1, 2.4};
2363 double py3[] = {4, 3.7, 1, 3.7, 2.5};
2364 h2p->AddBin(3, px1, py1);
2365 h2p->AddBin(4, px2, py2);
2366 h2p->AddBin(5, px3, py3);
2367 h2p->Fill(0.1, 0.01, 3);
2368 h2p->Fill(-0.5, -0.5, 7);
2369 h2p->Fill(-0.7, -0.5, 1);
2370 h2p->Fill(1, 3, 1.5);
2371 double fx[] = {0.1, -0.5, -0.7, 1};
2372 double fy[] = {0.01, -0.5, -0.5, 3};
2373 double fw[] = {3, 1, 1, 1.5};
2374 h2p->FillN(4, fx, fy, fw);
2375 h2p->Draw("col");
2376}
2377End_Macro
2378
2379Rectangular bins are a frequent case. The special version of
2380the `AddBin` method allows to define them more easily like
2381shown in the following example (th2polyBoxes.C).
2382
2383Begin_Macro(source)
2384../../../tutorials/hist/th2polyBoxes.C
2385End_Macro
2386
2387One `TH2Poly` bin can be a list of polygons. Such bins are defined
2388by calling `AddBin` with a `TMultiGraph`. The following example
2389shows a such case:
2390
2391Begin_Macro(source)
2392{
2393 auto ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2394
2395 Int_t i, bin;
2396 const Int_t nx = 48;
2397 const char *states [nx] = {
2398 "alabama", "arizona", "arkansas", "california",
2399 "colorado", "connecticut", "delaware", "florida",
2400 "georgia", "idaho", "illinois", "indiana",
2401 "iowa", "kansas", "kentucky", "louisiana",
2402 "maine", "maryland", "massachusetts", "michigan",
2403 "minnesota", "mississippi", "missouri", "montana",
2404 "nebraska", "nevada", "new_hampshire", "new_jersey",
2405 "new_mexico", "new_york", "north_carolina", "north_dakota",
2406 "ohio", "oklahoma", "oregon", "pennsylvania",
2407 "rhode_island", "south_carolina", "south_dakota", "tennessee",
2408 "texas", "utah", "vermont", "virginia",
2409 "washington", "west_virginia", "wisconsin", "wyoming"
2410 };
2411 Double_t pop[nx] = {
2412 4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2413 9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2414 1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2415 1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2416 11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2417 24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2418 };
2419
2420 Double_t lon1 = -130;
2421 Double_t lon2 = -65;
2422 Double_t lat1 = 24;
2423 Double_t lat2 = 50;
2424 auto p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2425
2426 TFile::SetCacheFileDir(".");
2427 auto f = TFile::Open("http://root.cern.ch/files/usa.root", "CACHEREAD");
2428
2429 TMultiGraph *mg;
2430 TKey *key;
2431 TIter nextkey(gDirectory->GetListOfKeys());
2432 while ((key = (TKey*)nextkey())) {
2433 TObject *obj = key->ReadObj();
2434 if (obj->InheritsFrom("TMultiGraph")) {
2435 mg = (TMultiGraph*)obj;
2436 bin = p->AddBin(mg);
2437 }
2438 }
2439
2440 for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2441
2442 gStyle->SetOptStat(11);
2443 p->Draw("COLZ L");
2444}
2445End_Macro
2446
2447`TH2Poly` histograms can also be plotted using the GL interface using
2448the option "GLLEGO".
2449
2450\since **ROOT version 6.09/01**
2451
2452In some cases it can be useful to not draw the empty bins. the option "0"
2453combined with the option "COL" et COLZ allows to do that.
2454
2455Begin_Macro(source)
2456{
2457 auto chc = new TCanvas("chc","chc",600,400);
2458
2459 auto hc = new TH2Poly();
2460 hc->Honeycomb(0,0,.1,25,25);
2461 hc->SetName("hc");
2462 hc->SetTitle("Option COLZ 0");
2463 TRandom ran;
2464 for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2465 hc->Draw("colz 0");
2466}
2467End_Macro
2468
2469\anchor HP21
2470### The SPEC option
2471
2472
2473This option allows to use the `TSpectrum2Painter` tools. See the full
2474documentation in `TSpectrum2Painter::PaintSpectrum`.
2475
2476
2477\anchor HP22
2478### Option "Z" : Adding the color palette on the right side of the pad
2479
2480
2481When this option is specified, a color palette with an axis indicating the value
2482of the corresponding color is drawn on the right side of the picture. In case,
2483not enough space is left, one can increase the size of the right margin by
2484calling `TPad::SetRightMargin()`. The attributes used to display the
2485palette axis values are taken from the Z axis of the object. For example, to
2486set the labels size on the palette axis do:
2487
2488 hist->GetZaxis()->SetLabelSize().
2489
2490<b>WARNING:</b> The palette axis is always drawn vertically.
2491
2492
2493\anchor HP23
2494### Setting the color palette
2495
2496
2497To change the color palette `TStyle::SetPalette` should be used, eg:
2498
2499 gStyle->SetPalette(ncolors,colors);
2500
2501For example the option `COL` draws a 2D histogram with cells
2502represented by a box filled with a color index which is a function
2503of the cell content.
2504If the cell content is N, the color index used will be the color number
2505in `colors[N]`, etc. If the maximum cell content is greater than
2506`ncolors`, all cell contents are scaled to `ncolors`.
2507
2508If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2509defined. This palette is recommended for pads, labels ...
2510
2511`if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2512Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2513palette.
2514
2515Other pre-defined palettes with 255 colors are available when `colors == 0`.
2516The following value of `ncolors` give access to:
2517
2518
2519 if ncolors = 51 and colors=0, a Deep Sea palette is used.
2520 if ncolors = 52 and colors=0, a Grey Scale palette is used.
2521 if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2522 if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright yellow)
2523 if ncolors = 55 and colors=0, a Rain Bow palette is used.
2524 if ncolors = 56 and colors=0, an inverted Dark Body Radiator palette is used.
2525
2526
2527If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2528
2529The default palette defines:
2530
2531- index 0 to 9 : shades of grey
2532- index 10 to 19 : shades of brown
2533- index 20 to 29 : shades of blue
2534- index 30 to 39 : shades of red
2535- index 40 to 49 : basic colors
2536
2537The color numbers specified in the palette can be viewed by selecting
2538the item `colors` in the `VIEW` menu of the canvas tool bar.
2539The red, green, and blue components of a color can be changed thanks to
2540`TColor::SetRGB()`.
2541
2542\since **ROOT version 6.19/01**
2543
2544As default labels and ticks are drawn by `TGAxis` at equidistant (lin or log)
2545points as controlled by SetNdivisions.
2546If option "CJUST" is given labels and ticks are justified at the
2547color boundaries defined by the contour levels.
2548For more details see `TPaletteAxis`
2549
2550\anchor HP24
2551### Drawing a sub-range of a 2D histogram; the [cutg] option
2552
2553
2554Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2555histogram. One must create a graphical cut (mouse or C++) and specify the name
2556of the cut between `[]` in the `Draw()` option.
2557For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2558
2559 myhist->Draw("surf1 [cutg]");
2560
2561To invert the cut, it is enough to put a `-` in front of its name:
2562
2563 myhist->Draw("surf1 [-cutg]");
2564
2565It is possible to apply several cuts (`,` means logical AND):
2566
2567 myhist->Draw("surf1 [cutg1,cutg2]");
2568
2569Begin_Macro(source)
2570../../../tutorials/fit/fit2a.C
2571End_Macro
2572
2573\anchor HP25
2574### Drawing options for 3D histograms
2575
2576
2577| Option | Description |
2578|----------|-------------------------------------------------------------------|
2579| "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)`|
2580| "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2581| "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2582| "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
2583| "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2584| "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2585
2586Note that instead of `BOX` one can also use `LEGO`.
2587
2588By default, like 2D histograms, 3D histograms are drawn as scatter plots.
2589
2590The following example shows a 3D histogram plotted as a scatter plot.
2591
2592Begin_Macro(source)
2593{
2594 auto c06 = new TCanvas("c06","c06",600,400);
2595 gStyle->SetOptStat(kFALSE);
2596 auto h3scat = new TH3F("h3scat","Option SCAT (default) ",15,-2,2,15,-2,2,15,0,4);
2597 double x, y, z;
2598 for (Int_t i=0;i<10000;i++) {
2599 gRandom->Rannor(x, y);
2600 z = x*x + y*y;
2601 h3scat->Fill(x,y,z);
2602 }
2603 h3scat->Draw();
2604}
2605End_Macro
2606
2607The following example shows a 3D histogram plotted with the option `BOX`.
2608
2609Begin_Macro(source)
2610{
2611 auto c16 = new TCanvas("c16","c16",600,400);
2612 gStyle->SetOptStat(kFALSE);
2613 auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2614 double x, y, z;
2615 for (Int_t i=0;i<10000;i++) {
2616 gRandom->Rannor(x, y);
2617 z = x*x + y*y;
2618 h3box->Fill(x,y,z);
2619 }
2620 h3box->Draw("BOX");
2621}
2622End_Macro
2623
2624The following example shows a 3D histogram plotted with the option `BOX1`.
2625
2626Begin_Macro(source)
2627{
2628 auto c36 = new TCanvas("c36","c36",600,400);
2629 gStyle->SetOptStat(kFALSE);
2630 auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2631 double x, y, z;
2632 for (Int_t i=0;i<10000;i++) {
2633 gRandom->Rannor(x, y);
2634 z = abs(sin(x)/x + cos(y)*y);
2635 h3box->Fill(x,y,z);
2636 }
2637 h3box->SetFillColor(9);
2638 h3box->Draw("BOX1");
2639}
2640End_Macro
2641
2642The following example shows a 3D histogram plotted with the option `BOX2`.
2643
2644Begin_Macro(source)
2645{
2646 auto c56 = new TCanvas("c56","c56",600,400);
2647 gStyle->SetOptStat(kFALSE);
2648 auto h3box = new TH3F("h3box","Option BOX2",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2649 double x, y, z;
2650 for (Int_t i=0;i<10000;i++) {
2651 gRandom->Rannor(x, y);
2652 z = abs(sin(x)/x + cos(y)*y);
2653 h3box->Fill(x,y,z);
2654 }
2655 h3box->Draw("BOX2 Z");
2656}
2657End_Macro
2658
2659The following example shows a 3D histogram plotted with the option `BOX3`.
2660
2661Begin_Macro(source)
2662{
2663 auto c46 = new TCanvas("c46","c46",600,400);
2664 c46->SetFillColor(38);
2665 gStyle->SetOptStat(kFALSE);
2666 auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2667 double x, y, z;
2668 for (Int_t i=0;i<10000;i++) {
2669 gRandom->Rannor(x, y);
2670 z = x*x + y*y;
2671 h3box->Fill(x,y,z);
2672 }
2673 h3box->Draw("BOX3");
2674}
2675End_Macro
2676
2677For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2678to the absolute value of the bin content. The bins with a negative content are
2679drawn with a X on each face of the box as shown in the following example:
2680
2681Begin_Macro(source)
2682{
2683 auto c = new TCanvas("c","c",600,400);
2684 gStyle->SetOptStat(kFALSE);
2685 auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2686 h3box->Fill(0., 2., 2., 10.);
2687 h3box->Fill(2., 2., 2., 5.);
2688 h3box->Fill(2., 2., .5, 2.);
2689 h3box->Fill(2., 2., 3., -1.);
2690 h3box->Fill(3., 2., 2., -10.);
2691 h3box->SetFillColor(8);
2692 h3box->Draw("box1");
2693}
2694End_Macro
2695
2696The following example shows a 3D histogram plotted with the option `ISO`.
2697
2698Begin_Macro(source)
2699{
2700 auto c26 = new TCanvas("c26","c26",600,400);
2701 gStyle->SetOptStat(kFALSE);
2702 auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2703 double x, y, z;
2704 for (Int_t i=0;i<10000;i++) {
2705 gRandom->Rannor(x, y);
2706 z = x*x + y*y;
2707 h3iso->Fill(x,y,z);
2708 }
2709 h3iso->SetFillColor(kCyan);
2710 h3iso->Draw("ISO");
2711}
2712End_Macro
2713
2714
2715\anchor HP26
2716### Drawing option for histograms' stacks
2717
2718
2719Stacks of histograms are managed with the `THStack`. A `THStack`
2720is a collection of `TH1` (or derived) objects. For painting only the
2721`THStack` containing `TH1` only or
2722`THStack` containing `TH2` only will be considered.
2723
2724By default, histograms are shown stacked:
2725
27261. The first histogram is paint.
27272. The sum of the first and second, etc...
2728
2729If the option `NOSTACK` is specified, the histograms are all paint in
2730the same pad as if the option `SAME` had been specified. This allows to
2731compute X and Y scales common to all the histograms, like
2732`TMultiGraph` does for graphs.
2733
2734If the option `PADS` is specified, the current pad/canvas is
2735subdivided into a number of pads equal to the number of histograms and each
2736histogram is paint into a separate pad.
2737
2738The following example shows various types of stacks (hstack.C).
2739
2740Begin_Macro(source)
2741../../../tutorials/hist/hstack.C
2742End_Macro
2743
2744The option `nostackb` allows to draw the histograms next to each
2745other as bar charts:
2746
2747Begin_Macro(source)
2748{
2749 auto cst0 = new TCanvas("cst0","cst0",600,400);
2750 auto hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2751
2752 auto h1 = new TH1F("h1","h1",10,-4,4);
2753 h1->FillRandom("gaus",20000);
2754 h1->SetFillColor(kRed);
2755 hs->Add(h1);
2756
2757 auto h2 = new TH1F("h2","h2",10,-4,4);
2758 h2->FillRandom("gaus",15000);
2759 h2->SetFillColor(kBlue);
2760 hs->Add(h2);
2761
2762 auto h3 = new TH1F("h3","h3",10,-4,4);
2763 h3->FillRandom("gaus",10000);
2764 h3->SetFillColor(kGreen);
2765 hs->Add(h3);
2766
2767 hs->Draw("nostackb");
2768 hs->GetXaxis()->SetNdivisions(-10);
2769 cst0->SetGridx();
2770}
2771End_Macro
2772
2773If at least one of the histograms in the stack has errors, the whole stack is
2774visualized by default with error bars. To visualize it without errors the
2775option `HIST` should be used.
2776
2777Begin_Macro(source)
2778{
2779 auto cst1 = new TCanvas("cst1","cst1",700,400);
2780 cst1->Divide(2,1);
2781
2782 auto hst11 = new TH1F("hst11", "", 20, -10, 10);
2783 hst11->Sumw2();
2784 hst11->FillRandom("gaus", 1000);
2785 hst11->SetFillColor(kViolet);
2786 hst11->SetLineColor(kViolet);
2787
2788 auto hst12 = new TH1F("hst12", "", 20, -10, 10);
2789 hst12->FillRandom("gaus", 500);
2790 hst12->SetFillColor(kBlue);
2791 hst12->SetLineColor(kBlue);
2792
2793 THStack st1("st1", "st1");
2794 st1.Add(hst11);
2795 st1.Add(hst12);
2796
2797 cst1->cd(1); st1.Draw();
2798 cst1->cd(2); st1.Draw("hist");
2799}
2800End_Macro
2801
2802\anchor HP27
2803### Drawing of 3D implicit functions
2804
2805
28063D implicit functions (`TF3`) can be drawn as iso-surfaces.
2807The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2808In the following example the options "FB" and "BB" suppress the
2809"Front Box" and "Back Box" around the plot.
2810
2811Begin_Macro(source)
2812{
2813 auto c2 = new TCanvas("c2","c2",600,400);
2814 auto f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2815 f3->SetClippingBoxOn(0,0,0);
2816 f3->SetFillColor(30);
2817 f3->SetLineColor(15);
2818 f3->Draw("FBBB");
2819}
2820End_Macro
2821
2822
2823\anchor HP28
2824### Associated functions drawing
2825
2826
2827An associated function is created by `TH1::Fit`. More than on fitted
2828function can be associated with one histogram (see `TH1::Fit`).
2829
2830A `TF1` object `f1` can be added to the list of associated
2831functions of an histogram `h` without calling `TH1::Fit`
2832simply doing:
2833
2834 h->GetListOfFunctions()->Add(f1);
2835
2836or
2837
2838 h->GetListOfFunctions()->Add(f1,someoption);
2839
2840To retrieve a function by name from this list, do:
2841
2842 TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2843
2844or
2845
2846 TF1 *f1 = h->GetFunction(name);
2847
2848Associated functions are automatically painted when an histogram is drawn.
2849To avoid the painting of the associated functions the option `HIST`
2850should be added to the list of the options used to paint the histogram.
2851
2852
2853\anchor HP29
2854### Drawing using OpenGL
2855
2856
2857The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2858graphics library. The plotting options start with `GL` keyword.
2859In addition, in order to inform canvases that OpenGL should be used to render
28603D representations, the following option should be set:
2861
2862 gStyle->SetCanvasPreferGL(true);
2863
2864
2865\anchor HP29a
2866#### General information: plot types and supported options
2867
2868The following types of plots are provided:
2869
2870For lego plots the supported options are:
2871
2872| Option | Description |
2873|----------|-------------------------------------------------------------------|
2874| "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2875| "GLLEGO2"| Bins with color levels.|
2876| "GLLEGO3"| Cylindrical bars.|
2877
2878
2879
2880Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2881In polar only Z axis can be logarithmic, in cylindrical only Y.
2882
2883For surface plots (`TF2` and `TH2`) the supported options are:
2884
2885| Option | Description |
2886|-----------|------------------------------------------------------------------|
2887| "GLSURF" | Draw a surface.|
2888| "GLSURF1" | Surface with color levels|
2889| "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2890| "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2891| "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2892
2893
2894
2895The surface painting in cartesian coordinates supports logarithmic scales along
2896X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2897in cylindrical coordinates only the Y axis.
2898
2899Additional options to SURF and LEGO - Coordinate systems:
2900
2901| Option | Description |
2902|----------|-------------------------------------------------------------------|
2903| " " | Default, cartesian coordinates system.|
2904| "POL" | Polar coordinates system.|
2905| "CYL" | Cylindrical coordinates system.|
2906| "SPH" | Spherical coordinates system.|
2907
2908
2909
2910\anchor HP290
2911#### TH3 as color boxes
2912
2913The supported option is:
2914
2915| Option | Description |
2916|----------|-------------------------------------------------------------------|
2917| "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/gl/glvox1.C`.|
2918
2919
2920
2921\anchor HP29b
2922#### TH3 as boxes (spheres)
2923
2924The supported options are:
2925
2926| Option | Description |
2927|----------|-------------------------------------------------------------------|
2928| "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2929| "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2930
2931
2932
2933\anchor HP29c
2934#### TH3 as iso-surface(s)
2935
2936The supported option is:
2937
2938| Option | Description |
2939|----------|-------------------------------------------------------------------|
2940| "GLISO" | TH3 is drawn using iso-surfaces.|
2941
2942
2943
2944\anchor HP29d
2945#### TF3 (implicit function)
2946
2947The supported option is:
2948
2949| Option | Description |
2950|----------|-------------------------------------------------------------------|
2951| "GL" | Draw a TF3.|
2952
2953
2954
2955\anchor HP29e
2956#### Parametric surfaces
2957
2958`$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric
2959equations and visualize the surface.
2960
2961\anchor HP29f
2962#### Interaction with the plots
2963
2964All the interactions are implemented via standard methods
2965`DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2966interactions with the OpenGL plots are possible only when the mouse cursor is
2967in the plot's area (the plot's area is the part of a the pad occupied by
2968gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2969pad interaction is performed.
2970
2971\anchor HP29g
2972#### Selectable parts
2973
2974Different parts of the plot can be selected:
2975
2976- xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2977 if the dynamic slicing by this plane is supported, and it's highlighted in red,
2978 if the dynamic slicing is not supported.
2979- The plot itself:
2980 On surfaces, the selected surface is outlined in red. (TF3 and
2981 ISO are not outlined). On lego plots, the selected bin is
2982 highlighted. The bin number and content are displayed in pad's
2983 status bar. In box plots, the box or sphere is highlighted and
2984 the bin info is displayed in pad's status bar.
2985
2986
2987\anchor HP29h
2988#### Rotation and zooming
2989
2990
2991- Rotation:
2992 When the plot is selected, it can be rotated by pressing and
2993 holding the left mouse button and move the cursor.
2994- Zoom/Unzoom:
2995 Mouse wheel or 'j', 'J', 'k', 'K' keys.
2996
2997
2998\anchor HP29i
2999#### Panning
3000
3001The selected plot can be moved in a pad's area by pressing and
3002holding the left mouse button and the shift key.
3003
3004\anchor HP29j
3005#### Box cut
3006
3007Surface, iso, box, TF3 and parametric painters support box cut by
3008pressing the 'c' or 'C' key when the mouse cursor is in a plot's
3009area. That will display a transparent box, cutting away part of the
3010surface (or boxes) in order to show internal part of plot. This box
3011can be moved inside the plot's area (the full size of the box is
3012equal to the plot's surrounding box) by selecting one of the box
3013cut axes and pressing the left mouse button to move it.
3014
3015\anchor HP29k
3016#### Plot specific interactions (dynamic slicing etc.)
3017
3018Currently, all gl-plots support some form of slicing. When back plane
3019is selected (and if it's highlighted in green) you can press and hold
3020left mouse button and shift key and move this back plane inside
3021plot's area, creating the slice. During this "slicing" plot becomes
3022semi-transparent. To remove all slices (and projected curves for
3023surfaces) double click with left mouse button in a plot's area.
3024
3025\anchor HP29l
3026#### Surface with option "GLSURF"
3027
3028The surface profile is displayed on the slicing plane.
3029The profile projection is drawn on the back plane
3030by pressing `'p'` or `'P'` key.
3031
3032\anchor HP29m
3033#### TF3
3034
3035The contour plot is drawn on the slicing plane. For TF3 the color
3036scheme can be changed by pressing 's' or 'S'.
3037
3038\anchor HP29n
3039#### Box
3040
3041The contour plot corresponding to slice plane position is drawn in real time.
3042
3043\anchor HP29o
3044#### Iso
3045
3046Slicing is similar to "GLBOX" option.
3047
3048\anchor HP29p
3049#### Parametric plot
3050
3051No slicing. Additional keys: 's' or 'S' to change color scheme -
3052about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
3053increase number of polygons ('l' for "level" of details), 'w' or 'W'
3054to show outlines ('w' for "wireframe").
3055
3056\anchor HP30
3057#### Highlight mode for histogram
3058
3059\since **ROOT version 6.15/01**
3060
3061\image html hlHisto3_top.gif "Highlight mode"
3062
3063Highlight mode is implemented for `TH1` (and for `TGraph`) class. When
3064highlight mode is on, mouse movement over the bin will be represented
3065graphically. Bin will be highlighted as "bin box" (presented by box
3066object). Moreover, any highlight (change of bin) emits signal
3067`TCanvas::Highlighted()` which allows the user to react and call their own
3068function. For a better understanding see also the tutorials
3069`$ROOTSYS/tutorials/hist/hlHisto*.C` files.
3070
3071Highlight mode is switched on/off by `TH1::SetHighlight()` function
3072or interactively from `TH1` context menu. `TH1::IsHighlight()` to verify
3073whether the highlight mode enabled or disabled, default it is disabled.
3074
3075~~~ {.cpp}
3076 root [0] .x $ROOTSYS/tutorials/hsimple.C
3077 root [1] hpx->SetHighlight(kTRUE) // or interactively from TH1 context menu
3078 root [2] hpx->IsHighlight()
3079 (bool) true
3080~~~
3081
3082\image html hlsimple_nofun.gif "Highlight mode for histogram"
3083
3084\anchor HP30a
3085#### Highlight mode and user function
3086
3087The user can use (connect) `TCanvas::Highlighted()` signal, which is always
3088emitted if there is a highlight bin and call user function via signal
3089and slot communication mechanism. `TCanvas::Highlighted()` is similar
3090`TCanvas::Picked()`
3091
3092- when selected object (histogram as a whole) is different from previous
3093then emit `Picked()` signal
3094- when selected (highlighted) bin from histogram is different from previous
3095then emit `Highlighted()` signal
3096
3097Any user function (or functions) has to be defined
3098`UserFunction(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)`.
3099In example (see below) has name `PrintInfo()`. All parameters of user
3100function are taken from
3101
3102 void TCanvas::Highlighted(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3103
3104- `pad` is pointer to pad with highlighted histogram
3105- `obj` is pointer to highlighted histogram
3106- `x` is highlighted x bin for 1D histogram
3107- `y` is highlighted y bin for 2D histogram (for 1D histogram not in use)
3108
3109Example how to create a connection from any `TCanvas` object to a user
3110`UserFunction()` slot (see also `TQObject::Connect()` for additional info)
3111
3112 TQObject::Connect("TCanvas", "Highlighted(TVirtualPad*,TObject*,Int_t,Int_t)",
3113 0, 0, "UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3114
3115or use non-static "simplified" function
3116`TCanvas::HighlightConnect(const char *slot)`
3117
3118 c1->HighlightConnect("UserFunction(TVirtualPad*,TObject*,Int_t,Int_t)");
3119
3120NOTE the signal and slot string must have a form
3121"(TVirtualPad*,TObject*,Int_t,Int_t)"
3122
3123 root [0] .x $ROOTSYS/tutorials/hsimple.C
3124 root [1] hpx->SetHighlight(kTRUE)
3125 root [2] .x hlprint.C
3126
3127file `hlprint.C`
3128~~~ {.cpp}
3129void PrintInfo(TVirtualPad *pad, TObject *obj, Int_t x, Int_t y)
3130{
3131 auto h = (TH1F *)obj;
3132 if (!h->IsHighlight()) // after highlight disabled
3133 h->SetTitle("highlight disable");
3134 else
3135 h->SetTitle(TString::Format("bin[%03d] (%5.2f) content %g", x,
3136 h->GetBinCenter(x), h->GetBinContent(x)));
3137 pad->Update();
3138}
3139
3140void hlprint()
3141{
3142 if (!gPad) return;
3143 gPad->GetCanvas()->HighlightConnect("PrintInfo(TVirtualPad*,TObject*,Int_t,Int_t)");
3144}
3145~~~
3146
3147\image html hlsimple.gif "Highlight mode and simple user function"
3148
3149For more complex demo please see for example `$ROOTSYS/tutorials/tree/temperature.C` file.
3150
3151*/
3152
3154
3157
3158const Int_t kNMAX = 2000;
3159
3160const Int_t kMAXCONTOUR = 104;
3162
3163static std::unique_ptr<TBox> gXHighlightBox, gYHighlightBox; // highlight X and Y box
3164
3186
3188
3189////////////////////////////////////////////////////////////////////////////////
3190/// Default constructor.
3191
3193{
3194 fH = nullptr;
3195 fXaxis = nullptr;
3196 fYaxis = nullptr;
3197 fZaxis = nullptr;
3198 fFunctions = nullptr;
3199 fNcuts = 0;
3200 fStack = 0;
3201 fShowProjection = 0;
3202 fShowOption = "";
3203 for (int i=0; i<kMaxCuts; i++) {
3204 fCuts[i] = nullptr;
3205 fCutsOpt[i] = 0;
3206 }
3207 fXHighlightBin = -1;
3208 fYHighlightBin = -1;
3209 fCurrentF3 = nullptr;
3210
3211 gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3212 gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3213 gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3214 gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3215 gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3216 gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3217 gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3218 gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3219 gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3220 gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3221 gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3222 gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3223 gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3224 gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3225 gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3226 gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3227 gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3228 gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3229 gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3230 gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3231 gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3232}
3233
3234////////////////////////////////////////////////////////////////////////////////
3235/// destructor.
3236
3238{
3239}
3240
3241////////////////////////////////////////////////////////////////////////////////
3242/// Compute the distance from the point px,py to a line.
3243///
3244/// Compute the closest distance of approach from point px,py to elements of
3245/// an histogram. The distance is computed in pixels units.
3246///
3247/// Algorithm: Currently, this simple model computes the distance from the mouse
3248/// to the histogram contour only.
3249
3251{
3252
3253 Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3254
3255 const Int_t big = 9999;
3256 const Int_t kMaxDiff = 7;
3257
3258 if (fPie)
3259 return fPie->DistancetoPrimitive(px, py);
3260
3261 Double_t x = gPad->AbsPixeltoX(px);
3262 Double_t x1 = gPad->AbsPixeltoX(px+1);
3263
3264 Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3265 Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3266 Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3267 Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3268 Int_t curdist = big;
3269 Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3270 Bool_t dsame;
3271 TObject *PadPointer = gPad->GetPadPointer();
3272 if (!PadPointer) return 0;
3273 TString doption = PadPointer->GetDrawOption();
3274 Double_t factor = 1;
3275 if (fH->GetNormFactor() != 0) {
3276 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3277 }
3278 // return if point is not in the histogram area
3279
3280 // If a 3D view exists, check distance to axis
3281 TView *view = gPad->GetView();
3282 Int_t d1,d2,d3;
3283 if (view && Hoption.Contour != 14) {
3284 Double_t ratio;
3285 d3 = view->GetDistancetoAxis(3, px, py, ratio);
3286 if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3287 d1 = view->GetDistancetoAxis(1, px, py, ratio);
3288 if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3289 d2 = view->GetDistancetoAxis(2, px, py, ratio);
3290 if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3291 if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3292 goto FUNCTIONS;
3293 }
3294 // check if point is close to an axis
3295 doption.ToLower();
3296 dsame = kFALSE;
3297 if (doption.Contains("same")) dsame = kTRUE;
3298
3299 dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3300 if (doption.Contains("y+")) {
3301 xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3302 if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3303 if (!dsame) {
3304 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3305 else gPad->SetSelected(fXaxis);
3306 return 0;
3307 }
3308 }
3309 } else {
3310 xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3311 if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3312 if (!dsame) {
3313 if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3314 else gPad->SetSelected(fXaxis);
3315 return 0;
3316 }
3317 }
3318 }
3319
3320 dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3321 if (doption.Contains("x+")) {
3322 yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3323 if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3324 if (!dsame) {
3325 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3326 else gPad->SetSelected(fYaxis);
3327 return 0;
3328 }
3329 }
3330 } else {
3331 yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3332 if (yxaxis < puymin) yxaxis = puymin;
3333 if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3334 if (!dsame) {
3335 if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3336 else gPad->SetSelected(fYaxis);
3337 return 0;
3338 }
3339 }
3340 }
3341
3342 if (fH->IsHighlight()) { // only if highlight is enable
3343 if ((px > puxmin) && (py < puymin) && (px < puxmax) && (py > puymax))
3344 HighlightBin(px, py);
3345 }
3346
3347 // if object is 2D or 3D return this object
3348 if (fH->GetDimension() == 2) {
3349 if (fH->InheritsFrom(TH2Poly::Class())) {
3350 TH2Poly *th2 = (TH2Poly*)fH;
3352 gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3353 Double_t pxu = gPad->AbsPixeltoX(px);
3354 Double_t pyu = gPad->AbsPixeltoY(py);
3355 if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3356 curdist = big;
3357 goto FUNCTIONS;
3358 } else {
3359 Int_t bin = th2->FindBin(pxu, pyu);
3360 if (bin>0) curdist = 1;
3361 else curdist = big;
3362 goto FUNCTIONS;
3363 }
3364 }
3365 Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3366 if ( px > puxmin + delta2
3367 && px < puxmax - delta2
3368 && py > puymax + delta2
3369 && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3370 }
3371
3372 // point is inside histogram area. Find channel number
3373 if (gPad->IsVertical()) {
3374 Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3375 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3376 Double_t binval = factor*fH->GetBinContent(bin);
3377 Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3378 if (binval == 0 && pybin < puymin) pybin = 10000;
3379 // special case if more than one bin for the pixel
3380 if (binsup-bin>1) {
3381 Double_t binvalmin, binvalmax;
3382 binvalmin=binval;
3383 binvalmax=binval;
3384 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3385 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3386 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3387 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3388 }
3389 Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3390 Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3391 if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3392 }
3393 if (bin != binsup) { // Mouse on bin border
3394 Double_t binsupval = factor*fH->GetBinContent(binsup);
3395 Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3396 if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3397 }
3398 if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3399 } else {
3400 Double_t y = gPad->AbsPixeltoY(py);
3401 Double_t y1 = gPad->AbsPixeltoY(py+1);
3402 Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3403 Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3404 Double_t binval = factor*fH->GetBinContent(bin);
3405 Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3406 if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3407 // special case if more than one bin for the pixel
3408 if (binsup-bin>1) {
3409 Double_t binvalmin, binvalmax;
3410 binvalmin=binval;
3411 binvalmax=binval;
3412 for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3413 Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3414 if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3415 if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3416 }
3417 Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3418 Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3419 if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3420 }
3421 if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3422 }
3423 // Loop on the list of associated functions and user objects
3424FUNCTIONS:
3425 TObject *f;
3426 TIter next(fFunctions);
3427 while ((f = (TObject*) next())) {
3428 Int_t dist;
3429 if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3430 else dist = f->DistancetoPrimitive(px,py);
3431 if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3432 }
3433 return curdist;
3434}
3435
3436////////////////////////////////////////////////////////////////////////////////
3437/// Display a panel with all histogram drawing options.
3438
3440{
3441
3442 gCurrentHist = fH;
3443 if (!gPad) {
3444 Error("DrawPanel", "need to draw histogram first");
3445 return;
3446 }
3448 editor->Show();
3449 gROOT->ProcessLine(TString::Format("((TCanvas*)0x%zx)->Selected((TVirtualPad*)0x%zx,(TObject*)0x%zx,1)",
3450 (size_t)gPad->GetCanvas(), (size_t)gPad, (size_t)fH).Data());
3451}
3452
3453////////////////////////////////////////////////////////////////////////////////
3454/// Execute the actions corresponding to `event`.
3455///
3456/// This function is called when a histogram is clicked with the locator at
3457/// the pixel position px,py.
3458
3460{
3461
3462 if (!gPad) return;
3463
3464 static Int_t bin, px1, py1, px2, py2, pyold;
3465 static std::unique_ptr<TBox> zoombox;
3466 Double_t zbx1,zbx2,zby1,zby2;
3467
3468 Int_t bin1, bin2;
3469 Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3470 Bool_t opaque = gPad->OpaqueMoving();
3471
3472 if (!gPad->IsEditable()) return;
3473
3474 if (fPie) {
3475 fPie->ExecuteEvent(event, px, py);
3476 return;
3477 }
3478 // come here if we have a lego/surface in the pad
3479 TView *view = gPad->GetView();
3480
3481 if (!fShowProjection && view && !view->TestBit(kCannotRotate)) {
3482 view->ExecuteRotateView(event, px, py);
3483 return;
3484 }
3485
3486 TAxis *xaxis = fH->GetXaxis();
3487 TAxis *yaxis = fH->GetYaxis();
3488 Int_t dimension = fH->GetDimension();
3489
3490 // In case of option SAME the axis must be the ones of the first drawn histogram
3491 TString IsSame = fH->GetDrawOption();
3492 IsSame.ToLower();
3493 if (IsSame.Index("same")>=0) {
3494 TH1 *h1;
3495 TIter next(gPad->GetListOfPrimitives());
3496 while ((h1 = (TH1 *)next())) {
3497 if (!h1->InheritsFrom(TH1::Class())) continue;
3498 xaxis = h1->GetXaxis();
3499 yaxis = h1->GetYaxis();
3500 break;
3501 }
3502 }
3503
3504 Double_t factor = 1;
3505 if (fH->GetNormFactor() != 0) {
3506 factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3507 }
3508
3509 switch (event) {
3510
3511 case kButton1Down:
3512
3513 if (!opaque) gVirtualX->SetLineColor(-1);
3514 fH->TAttLine::Modify();
3515
3516 if (opaque && dimension ==2) {
3517 zbx1 = gPad->AbsPixeltoX(px);
3518 zbx2 = gPad->AbsPixeltoX(px);
3519 zby1 = gPad->AbsPixeltoY(py);
3520 zby2 = gPad->AbsPixeltoY(py);
3521 px1 = px;
3522 py1 = py;
3523 if (gPad->GetLogx()) {
3524 zbx1 = TMath::Power(10,zbx1);
3525 zbx2 = TMath::Power(10,zbx2);
3526 }
3527 if (gPad->GetLogy()) {
3528 zby1 = TMath::Power(10,zby1);
3529 zby2 = TMath::Power(10,zby2);
3530 }
3531 if (zoombox) Error("ExecuteEvent", "Last zoom box was not deleted");
3532 zoombox = std::make_unique<TBox>(zbx1, zby1, zbx2, zby2);
3533 Int_t ci = TColor::GetColor("#7d7dff");
3534 TColor *zoomcolor = gROOT->GetColor(ci);
3535 if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3536 else zoomcolor->SetAlpha(0.5);
3537 zoombox->SetFillColor(ci);
3538 zoombox->Draw();
3539 gPad->Modified();
3540 gPad->Update();
3541 }
3542 // No break !!!
3543
3544 case kMouseMotion:
3545
3546 if (fShowProjection) {ShowProjection3(px,py); break;}
3547
3548 gPad->SetCursor(kPointer);
3549 if (dimension ==1) {
3550 if (Hoption.Bar) {
3551 baroffset = fH->GetBarOffset();
3552 barwidth = fH->GetBarWidth();
3553 } else {
3554 baroffset = 0;
3555 barwidth = 1;
3556 }
3557 x = gPad->AbsPixeltoX(px);
3558 bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3559 binwidth = fXaxis->GetBinWidth(bin);
3560 xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3561 xup = gPad->XtoPad(xlow + barwidth*binwidth);
3562 ylow = gPad->GetUymin();
3563 px1 = gPad->XtoAbsPixel(xlow);
3564 px2 = gPad->XtoAbsPixel(xup);
3565 py1 = gPad->YtoAbsPixel(ylow);
3566 py2 = py;
3567 pyold = py;
3568 if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3569 }
3570
3571 break;
3572
3573 case kButton1Motion:
3574
3575 if (dimension ==1) {
3576 if (gROOT->GetEditHistograms()) {
3577 if (!opaque) {
3578 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3579 py2 += py - pyold;
3580 gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3581 pyold = py;
3582 } else {
3583 py2 += py - pyold;
3584 pyold = py;
3585 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3586 fH->SetBinContent(bin,binval);
3587 gPad->Modified(kTRUE);
3588 }
3589 }
3590 }
3591
3592 if (opaque && dimension ==2) {
3593 if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3594 zbx2 = gPad->AbsPixeltoX(px);
3595 zby2 = gPad->AbsPixeltoY(py);
3596 if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3597 if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3598 if (zoombox) {
3599 zoombox->SetX2(zbx2);
3600 zoombox->SetY2(zby2);
3601 }
3602 gPad->Modified();
3603 gPad->Update();
3604 }
3605 }
3606
3607 break;
3608
3609 case kWheelUp:
3610
3611 if (dimension ==2) {
3612 bin1 = xaxis->GetFirst()+1;
3613 bin2 = xaxis->GetLast()-1;
3614 bin1 = TMath::Max(bin1, 1);
3615 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3616 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3617 bin1 = yaxis->GetFirst()+1;
3618 bin2 = yaxis->GetLast()-1;
3619 bin1 = TMath::Max(bin1, 1);
3620 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3621 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3622 }
3623 gPad->Modified();
3624 gPad->Update();
3625
3626 break;
3627
3628 case kWheelDown:
3629
3630 if (dimension == 2) {
3631 bin1 = xaxis->GetFirst()-1;
3632 bin2 = xaxis->GetLast()+1;
3633 bin1 = TMath::Max(bin1, 1);
3634 bin2 = TMath::Min(bin2, xaxis->GetNbins());
3635 if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3636 bin1 = yaxis->GetFirst()-1;
3637 bin2 = yaxis->GetLast()+1;
3638 bin1 = TMath::Max(bin1, 1);
3639 bin2 = TMath::Min(bin2, yaxis->GetNbins());
3640 if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3641 }
3642 gPad->Modified();
3643 gPad->Update();
3644
3645 break;
3646
3647 case kButton1Up:
3648 if (dimension ==1) {
3649 if (gROOT->GetEditHistograms()) {
3650 binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3651 fH->SetBinContent(bin,binval);
3652 PaintInit(); // recalculate Hparam structure and recalculate range
3653 }
3654
3655 // might resize pad pixmap so should be called before any paint routine
3657 }
3658 if (opaque && dimension ==2) {
3659 if (zoombox) {
3660 Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3661 Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3662 Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3663 Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3664 x1 = TMath::Max(x1,xaxis->GetXmin());
3665 x2 = TMath::Min(x2,xaxis->GetXmax());
3666 y1 = TMath::Max(y1,yaxis->GetXmin());
3667 y2 = TMath::Min(y2,yaxis->GetXmax());
3668 if (x1<x2 && y1<y2) {
3669 xaxis->SetRangeUser(x1, x2);
3670 yaxis->SetRangeUser(y1, y2);
3671 }
3672 zoombox.reset();
3673 }
3674 }
3675 gPad->Modified(kTRUE);
3676 if (opaque) gVirtualX->SetLineColor(-1);
3677
3678 break;
3679
3680 case kButton1Locate:
3681
3682 ExecuteEvent(kButton1Down, px, py);
3683
3684 while (1) {
3685 px = py = 0;
3686 event = gVirtualX->RequestLocator(1, 1, px, py);
3687
3689
3690 if (event != -1) { // button is released
3691 ExecuteEvent(kButton1Up, px, py);
3692 return;
3693 }
3694 }
3695 }
3696}
3697
3698////////////////////////////////////////////////////////////////////////////////
3699/// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3700
3702{
3703 // Check if fH contains a TGraphDelaunay2D
3704 TList *hl = fH->GetListOfFunctions();
3705 TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3706 // try with the old painter
3707 TGraphDelaunay *dtOld = nullptr;
3708 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3709
3710 if (!dt && !dtOld) return nullptr;
3711
3712 gCurrentHist = fH;
3713
3714 if (!fGraph2DPainter)
3715 ((THistPainter*)this)->fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
3716
3717 return fGraph2DPainter->GetContourList(contour);
3718}
3719
3720////////////////////////////////////////////////////////////////////////////////
3721/// Display the histogram info (bin number, contents, integral up to bin
3722/// corresponding to cursor position px,py.
3723
3725{
3726
3727 if (!gPad) return (char*)"";
3728
3729 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3730 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3731 Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3732 TString drawOption = fH->GetDrawOption();
3733 drawOption.ToLower();
3734 Double_t xmin, xmax, uxmin,uxmax;
3735 Double_t ymin, ymax, uymin,uymax;
3736 if (fH->GetDimension() == 2) {
3737 if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3738 uxmin=gPad->GetUxmin();
3739 uxmax=gPad->GetUxmax();
3742 x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3743 uymin=gPad->GetUymin();
3744 uymax=gPad->GetUymax();
3747 y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3748 }
3749 }
3750 Int_t binx,biny,binmin=0,binx1;
3751 if (gPad->IsVertical()) {
3752 binx = fXaxis->FindFixBin(x);
3753 if (drawOption.Index("same") >= 0) {
3754 TH1 *h1;
3755 TIter next(gPad->GetListOfPrimitives());
3756 while ((h1 = (TH1 *)next())) {
3757 if (!h1->InheritsFrom(TH1::Class())) continue;
3758 binmin = h1->GetXaxis()->GetFirst();
3759 break;
3760 }
3761 } else {
3762 binmin = fXaxis->GetFirst();
3763 }
3764 binx1 = fXaxis->FindFixBin(x1);
3765 // special case if more than 1 bin in x per pixel
3766 if (binx1-binx>1 && fH->GetDimension() == 1) {
3767 Double_t binval=fH->GetBinContent(binx);
3768 Int_t binnear=binx;
3769 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3770 Double_t binvaltmp = fH->GetBinContent(ibin);
3771 if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3772 binval=binvaltmp;
3773 binnear=ibin;
3774 }
3775 }
3776 binx = binnear;
3777 }
3778 } else {
3779 x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3780 binx = fXaxis->FindFixBin(y);
3781 if (drawOption.Index("same") >= 0) {
3782 TH1 *h1;
3783 TIter next(gPad->GetListOfPrimitives());
3784 while ((h1 = (TH1 *)next())) {
3785 if (!h1->InheritsFrom(TH1::Class())) continue;
3786 binmin = h1->GetXaxis()->GetFirst();
3787 break;
3788 }
3789 } else {
3790 binmin = fXaxis->GetFirst();
3791 }
3792 binx1 = fXaxis->FindFixBin(x1);
3793 // special case if more than 1 bin in x per pixel
3794 if (binx1-binx>1 && fH->GetDimension() == 1) {
3795 Double_t binval=fH->GetBinContent(binx);
3796 Int_t binnear=binx;
3797 for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3798 Double_t binvaltmp = fH->GetBinContent(ibin);
3799 if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3800 binval=binvaltmp;
3801 binnear=ibin;
3802 }
3803 }
3804 binx = binnear;
3805 }
3806 }
3807 if (fH->GetDimension() == 1) {
3809 TProfile *tp = (TProfile*)fH;
3810 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3811 x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3812 (Int_t) tp->GetBinEntries(binx));
3813 }
3814 else {
3815 Double_t integ = 0;
3816 for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3817 fObjectInfo.Form("(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3818 x,y,binx,fH->GetBinContent(binx),integ);
3819 }
3820 } else if (fH->GetDimension() == 2) {
3821 if (fH->InheritsFrom(TH2Poly::Class())) {
3822 TH2Poly *th2 = (TH2Poly*)fH;
3823 biny = th2->FindBin(x,y);
3824 fObjectInfo.Form("%s (x=%g, y=%g, bin=%d, binc=%g)",
3825 th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3826 }
3827 else if (fH->InheritsFrom(TProfile2D::Class())) {
3828 TProfile2D *tp = (TProfile2D*)fH;
3829 biny = fYaxis->FindFixBin(y);
3830 Int_t bin = fH->GetBin(binx,biny);
3831 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3832 x, y, binx, biny, fH->GetBinContent(bin),
3833 fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3834 } else {
3835 biny = fYaxis->FindFixBin(y);
3836 fObjectInfo.Form("(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3837 x,y,binx,biny,fH->GetBinContent(binx,biny),
3838 fH->GetBinError(binx,biny));
3839 }
3840 } else {
3841 // 3d case: retrieving the x,y,z bin is not yet implemented
3842 // print just the x,y info
3843 fObjectInfo.Form("(x=%g, y=%g)",x,y);
3844 }
3845
3846 return (char *)fObjectInfo.Data();
3847}
3848
3849////////////////////////////////////////////////////////////////////////////////
3850/// Set highlight (enable/disable) mode for fH
3851
3853{
3854 if (fH->IsHighlight()) return;
3855
3856 fXHighlightBin = -1;
3857 fYHighlightBin = -1;
3858 // delete previous highlight box
3859 if (gXHighlightBox) gXHighlightBox.reset();
3860 if (gYHighlightBox) gYHighlightBox.reset();
3861 // emit Highlighted() signal (user can check on disabled)
3862 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3863}
3864
3865////////////////////////////////////////////////////////////////////////////////
3866/// Check on highlight bin
3867
3869{
3870 // call from DistancetoPrimitive (only if highlight is enable)
3871
3872 Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3873 Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3874 Int_t binx = fXaxis->FindFixBin(x);
3875 Int_t biny = fYaxis->FindFixBin(y);
3876 if (!gPad->IsVertical()) binx = fXaxis->FindFixBin(y);
3877
3878 Bool_t changedBin = kFALSE;
3879 if (binx != fXHighlightBin) {
3880 fXHighlightBin = binx;
3881 changedBin = kTRUE;
3882 } else if (fH->GetDimension() == 1) return;
3883 if (biny != fYHighlightBin) {
3884 fYHighlightBin = biny;
3885 changedBin = kTRUE;
3886 }
3887 if (!changedBin) return;
3888
3889 // Info("HighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3890 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3891
3892 // paint highlight bin as box (recursive calls PaintHighlightBin)
3893 gPad->Modified(kTRUE);
3894 gPad->Update();
3895
3896 // emit Highlighted() signal
3897 if (gPad->GetCanvas()) gPad->GetCanvas()->Highlighted(gPad, fH, fXHighlightBin, fYHighlightBin);
3898}
3899
3900////////////////////////////////////////////////////////////////////////////////
3901/// Paint highlight bin as TBox object
3902
3904{
3905 // call from PaintTitle
3906
3907 if (!fH->IsHighlight()) return;
3908
3909 Double_t uxmin = gPad->GetUxmin();
3910 Double_t uxmax = gPad->GetUxmax();
3911 Double_t uymin = gPad->GetUymin();
3912 Double_t uymax = gPad->GetUymax();
3913 if (gPad->GetLogx()) {
3914 uxmin = TMath::Power(10.0, uxmin);
3915 uxmax = TMath::Power(10.0, uxmax);
3916 }
3917 if (gPad->GetLogy()) {
3918 uymin = TMath::Power(10.0, uymin);
3919 uymax = TMath::Power(10.0, uymax);
3920 }
3921
3922 // testing specific possibility (after zoom, draw with "same", log, etc.)
3923 Double_t hcenter;
3924 if (gPad->IsVertical()) {
3926 if ((hcenter < uxmin) || (hcenter > uxmax)) return;
3927 } else {
3929 if ((hcenter < uymin) || (hcenter > uymax)) return;
3930 }
3931 if (fH->GetDimension() == 2) {
3933 if ((hcenter < uymin) || (hcenter > uymax)) return;
3934 }
3935
3936 // paint X highlight bin (for 1D or 2D)
3937 Double_t hbx1, hbx2, hby1, hby2;
3938 if (gPad->IsVertical()) {
3941 hby1 = uymin;
3942 hby2 = uymax;
3943 } else {
3944 hbx1 = uxmin;
3945 hbx2 = uxmax;
3948 }
3949
3950 if (!gXHighlightBox) {
3951 gXHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3952 gXHighlightBox->SetBit(kCannotPick);
3953 gXHighlightBox->SetFillColor(TColor::GetColor("#9797ff"));
3954 if (!TCanvas::SupportAlpha()) gXHighlightBox->SetFillStyle(3001);
3955 else gROOT->GetColor(gXHighlightBox->GetFillColor())->SetAlpha(0.5);
3956 }
3957 gXHighlightBox->SetX1(hbx1);
3958 gXHighlightBox->SetX2(hbx2);
3959 gXHighlightBox->SetY1(hby1);
3960 gXHighlightBox->SetY2(hby2);
3961 gXHighlightBox->Paint();
3962
3963 // Info("PaintHighlightBin", "histo: %p '%s'\txbin: %d, ybin: %d",
3964 // (void *)fH, fH->GetName(), fXHighlightBin, fYHighlightBin);
3965
3966 // paint Y highlight bin (only for 2D)
3967 if (fH->GetDimension() != 2) return;
3968 hbx1 = uxmin;
3969 hbx2 = uxmax;
3972
3973 if (!gYHighlightBox) {
3974 gYHighlightBox = std::make_unique<TBox>(hbx1, hby1, hbx2, hby2);
3975 gYHighlightBox->SetBit(kCannotPick);
3976 gYHighlightBox->SetFillColor(gXHighlightBox->GetFillColor());
3977 gYHighlightBox->SetFillStyle(gXHighlightBox->GetFillStyle());
3978 }
3979 gYHighlightBox->SetX1(hbx1);
3980 gYHighlightBox->SetX2(hbx2);
3981 gYHighlightBox->SetY1(hby1);
3982 gYHighlightBox->SetY2(hby2);
3983 gYHighlightBox->Paint();
3984}
3985
3986////////////////////////////////////////////////////////////////////////////////
3987/// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3988
3990{
3991
3992 for (Int_t i=0;i<fNcuts;i++) {
3995 if (fCutsOpt[i] > 0) {
3996 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3997 } else {
3998 if (fCuts[i]->IsInside(x,y)) return kFALSE;
3999 }
4000 }
4001 return kTRUE;
4002}
4003
4004////////////////////////////////////////////////////////////////////////////////
4005/// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
4006
4008{
4009
4010 for (Int_t i=0;i<fNcuts;i++) {
4011 if (fCutsOpt[i] > 0) {
4012 if (!fCuts[i]->IsInside(x,y)) return kFALSE;
4013 } else {
4014 if (fCuts[i]->IsInside(x,y)) return kFALSE;
4015 }
4016 }
4017 return kTRUE;
4018}
4019
4020////////////////////////////////////////////////////////////////////////////////
4021/// Decode string `choptin` and fill Hoption structure.
4022
4024{
4025
4026 char *l;
4027 char chopt[128];
4028 Int_t nch = strlen(choptin);
4029 strlcpy(chopt,choptin,128);
4030 Int_t hdim = fH->GetDimension();
4031
4039 Hoption.Candle = 0;
4040
4041 // special 2D options
4042 Hoption.List = 0;
4043 Hoption.Zscale = 0;
4044 Hoption.FrontBox = 1;
4045 Hoption.BackBox = 1;
4047
4048 Hoption.Zero = 0;
4049
4051
4052 //check for graphical cuts
4053 MakeCuts(chopt);
4054
4055 for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
4056 if (hdim > 1) Hoption.Scat = 1;
4057 if (!nch) Hoption.Hist = 1;
4058 if (fFunctions->First()) Hoption.Func = 1;
4059 if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
4060
4061 char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
4062 char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
4063 char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
4064 if (l1 || l2 || l3) {
4065 Int_t i = gPad->NextPaletteColor();
4066 if (l1) {memcpy(l1," ",3); fH->SetFillColor(i);}
4067 if (l2) {memcpy(l2," ",3); fH->SetLineColor(i);}
4068 if (l3) {memcpy(l3," ",3); fH->SetMarkerColor(i);}
4069 Hoption.Hist = 1; // Make sure something is drawn in case there is no drawing option specified.
4070 }
4071
4072 l = strstr(chopt,"MIN0");
4073 if (l) {
4074 Hoption.MinimumZero = 1;
4075 memcpy(l," ",4);
4076 }
4077
4078 l = strstr(chopt,"SPEC");
4079 if (l) {
4080 Hoption.Scat = 0;
4081 memcpy(l," ",4);
4082 Int_t bs=0;
4083 l = strstr(chopt,"BF(");
4084 if (l) {
4085 if (sscanf(&l[3],"%d",&bs) > 0) {
4086 Int_t i=0;
4087 while (l[i]!=')') {
4088 l[i] = ' ';
4089 i++;
4090 }
4091 l[i] = ' ';
4092 }
4093 }
4094 Hoption.Spec = TMath::Max(1600,bs);
4095 return 1;
4096 }
4097
4098 l = strstr(chopt,"GL");
4099 if (l) {
4100 memcpy(l," ",2);
4101 }
4102 l = strstr(chopt,"X+");
4103 if (l) {
4104 Hoption.AxisPos = 10;
4105 memcpy(l," ",2);
4106 }
4107 l = strstr(chopt,"Y+");
4108 if (l) {
4109 Hoption.AxisPos += 1;
4110 memcpy(l," ",2);
4111 }
4112 if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
4113 if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
4114
4115 l = strstr(chopt,"SAMES");
4116 if (l) {
4117 if (nch == 5) Hoption.Hist = 1;
4118 Hoption.Same = 2;
4119 memcpy(l," ",5);
4120 if (l[5] == '0') { Hoption.Same += 10; l[5] = ' '; }
4121 }
4122 l = strstr(chopt,"SAME");
4123 if (l) {
4124 if (nch == 4) Hoption.Hist = 1;
4125 Hoption.Same = 1;
4126 memcpy(l," ",4);
4127 if (l[4] == '0') { Hoption.Same += 10; l[4] = ' '; }
4128 }
4129
4130 l = strstr(chopt,"PIE");
4131 if (l) {
4132 Hoption.Pie = 1;
4133 memcpy(l," ",3);
4134 }
4135
4136
4137 l = strstr(chopt,"CANDLE");
4138 if (l) {
4139 TCandle candle;
4140 Hoption.Candle = candle.ParseOption(l);
4141 Hoption.Scat = 0;
4142 }
4143
4144 l = strstr(chopt,"VIOLIN");
4145 if (l) {
4146 TCandle candle;
4147 Hoption.Candle = candle.ParseOption(l);
4148 Hoption.Scat = 0;
4149 }
4150
4151 l = strstr(chopt,"LEGO");
4152 if (l) {
4153 Hoption.Scat = 0;
4154 Hoption.Lego = 1; memcpy(l," ",4);
4155 if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
4156 if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
4157 if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
4158 if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
4159 if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
4160 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4161 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4162 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4163 }
4164
4165 l = strstr(chopt,"SURF");
4166 if (l) {
4167 Hoption.Scat = 0;
4168 Hoption.Surf = 1; memcpy(l," ",4);
4169 if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
4170 if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
4171 if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
4172 if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
4173 if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
4174 if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
4175 if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
4176 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4177 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4178 }
4179
4180 l = strstr(chopt,"TF3");
4181 if (l) {
4182 memcpy(l," ",3);
4183 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4184 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4185 }
4186
4187 l = strstr(chopt,"ISO");
4188 if (l) {
4189 memcpy(l," ",3);
4190 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4191 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4192 }
4193
4194 l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; memcpy(l," ",4);}
4195
4196 l = strstr(chopt,"CONT");
4197 if (l) {
4198 memcpy(l," ",4);
4199 if (hdim>1) {
4200 Hoption.Scat = 0;
4201 Hoption.Contour = 1;
4202 if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
4203 if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
4204 if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
4205 if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
4206 if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
4207 } else {
4208 Hoption.Hist = 1;
4209 }
4210 }
4211 l = strstr(chopt,"HBAR");
4212 if (l) {
4213 Hoption.Hist = 0;
4214 Hoption.Bar = 20; memcpy(l," ",4);
4215 if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
4216 if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
4217 if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
4218 if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
4219 }
4220 l = strstr(chopt,"BAR");
4221 if (l) {
4222 Hoption.Hist = 0;
4223 Hoption.Bar = 10; memcpy(l," ",3);
4224 if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
4225 if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
4226 if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
4227 if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
4228 }
4229
4230 l = strstr(chopt,"ARR" );
4231 if (l) {
4232 memcpy(l," ", 3);
4233 if (hdim>1) {
4234 Hoption.Arrow = 1;
4235 Hoption.Scat = 0;
4236 l = strstr(chopt,"COL"); if (l) { Hoption.Arrow = 2; memcpy(l," ",3); }
4237 l = strstr(chopt,"Z"); if (l) { Hoption.Zscale = 1; memcpy(l," ",1); }
4238 } else {
4239 Hoption.Hist = 1;
4240 }
4241 }
4242 l = strstr(chopt,"BOX" );
4243 if (l) {
4244 memcpy(l," ", 3);
4245 if (hdim>1) {
4246 Hoption.Scat = 0;
4247 Hoption.Box = 1;
4248 if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
4249 if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
4250 if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
4251 } else {
4252 Hoption.Hist = 1;
4253 }
4254 }
4255 l = strstr(chopt,"COLZ");
4256 if (l) {
4257 memcpy(l," ",4);
4258 if (hdim>1) {
4259 Hoption.Color = 1;
4260 Hoption.Scat = 0;
4261 Hoption.Zscale = 1;
4262 if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
4263 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4264 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4265 } else {
4266 Hoption.Hist = 1;
4267 }
4268 }
4269 l = strstr(chopt,"COL" );
4270 if (l) {
4271 memcpy(l," ", 3);
4272 if (hdim>1) {
4273 Hoption.Color = 1;
4274 Hoption.Scat = 0;
4275 if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
4276 l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; memcpy(l," ",1); }
4277 l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; memcpy(l," ",1); }
4278 } else {
4279 Hoption.Hist = 1;
4280 }
4281 }
4282 l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; memcpy(l," ",4); Hoption.Hist = 0; }
4283 l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; memcpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
4284 l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; memcpy(l," ",4); }
4285 l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; memcpy(l," ",4); }
4286 l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; memcpy(l," ",4); }
4287 l = strstr(chopt,"TEXT");
4288 if (l) {
4289 Int_t angle;
4290 if (sscanf(&l[4],"%d",&angle) > 0) {
4291 if (angle < 0) angle=0;
4292 if (angle > 90) angle=90;
4293 Hoption.Text = 1000+angle;
4294 } else {
4295 Hoption.Text = 1;
4296 }
4297 memcpy(l," ", 4);
4298 l = strstr(chopt,"N");
4299 if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
4300 Hoption.Scat = 0;
4301 }
4302 l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; memcpy(l," ",3); }
4303 l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; memcpy(l," ",3); }
4304 l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; memcpy(l," ",3); }
4305 l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; memcpy(l," ",3); }
4306
4307 l = strstr(chopt,"TRI");
4308 if (l) {
4309 Hoption.Scat = 0;
4310 Hoption.Color = 0;
4311 Hoption.Tri = 1; memcpy(l," ",3);
4312 l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; memcpy(l," ",2); }
4313 l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; memcpy(l," ",2); }
4314 l = strstr(chopt,"ERR"); if (l) memcpy(l," ",3);
4315 }
4316
4317 l = strstr(chopt,"AITOFF");
4318 if (l) {
4319 Hoption.Proj = 1; memcpy(l," ",6); //Aitoff projection
4320 }
4321 l = strstr(chopt,"MERCATOR");
4322 if (l) {
4323 Hoption.Proj = 2; memcpy(l," ",8); //Mercator projection
4324 }
4325 l = strstr(chopt,"SINUSOIDAL");
4326 if (l) {
4327 Hoption.Proj = 3; memcpy(l," ",10); //Sinusoidal projection
4328 }
4329 l = strstr(chopt,"PARABOLIC");
4330 if (l) {
4331 Hoption.Proj = 4; memcpy(l," ",9); //Parabolic projection
4332 }
4333 if (Hoption.Proj > 0) {
4334 Hoption.Scat = 0;
4335 Hoption.Contour = 14;
4336 }
4337
4338 if (strstr(chopt,"A")) Hoption.Axis = -1;
4339 if (strstr(chopt,"B")) Hoption.Bar = 1;
4340 if (strstr(chopt,"C") && !strstr(chopt,"CJUST")) { Hoption.Curve =1; Hoption.Hist = -1;}
4341 if (strstr(chopt,"F")) Hoption.Fill =1;
4342 if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4343 if (strstr(chopt,"F2")) Hoption.Fill =2;
4344 if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4345 if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4346 if (strstr(chopt,"Z")) Hoption.Zscale =1;
4347 if (strstr(chopt,"*")) Hoption.Star =1;
4348 if (strstr(chopt,"H")) Hoption.Hist =2;
4349 if (strstr(chopt,"P0")) Hoption.Mark =10;
4350
4351 if (fH->InheritsFrom(TH2Poly::Class())) {
4353 }
4354
4355 if (strstr(chopt,"E")) {
4356 if (hdim == 1) {
4357 Hoption.Error = 1;
4358 if (strstr(chopt,"E1")) Hoption.Error = 11;
4359 if (strstr(chopt,"E2")) Hoption.Error = 12;
4360 if (strstr(chopt,"E3")) Hoption.Error = 13;
4361 if (strstr(chopt,"E4")) Hoption.Error = 14;
4362 if (strstr(chopt,"E5")) Hoption.Error = 15;
4363 if (strstr(chopt,"E6")) Hoption.Error = 16;
4364 if (strstr(chopt,"E0")) Hoption.Error += 40;
4365 if (strstr(chopt,"X0")) {
4366 if (Hoption.Error == 1) Hoption.Error += 20;
4367 Hoption.Error += 10;
4368 }
4370 Hoption.Text += 2000;
4371 Hoption.Error = 0;
4372 }
4373 } else {
4374 if (Hoption.Error == 0) {
4375 Hoption.Error = 100;
4376 Hoption.Scat = 0;
4377 }
4378 if (Hoption.Text) {
4379 Hoption.Text += 2000;
4380 Hoption.Error = 0;
4381 }
4382 }
4383 }
4384
4385 if (Hoption.Surf == 15) {
4387 Hoption.Surf = 13;
4388 Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4389 }
4390 }
4391
4392 // Copy options from current style
4393 Hoption.Logx = gPad->GetLogx();
4394 Hoption.Logy = gPad->GetLogy();
4395 Hoption.Logz = gPad->GetLogz();
4396
4397 // Check options incompatibilities
4398 if (Hoption.Bar == 1) Hoption.Hist = -1;
4399 return 1;
4400}
4401
4402////////////////////////////////////////////////////////////////////////////////
4403/// Decode string `choptin` and fill Graphical cuts structure.
4404
4406{
4407
4408 fNcuts = 0;
4409 char *left = (char*)strchr(choptin,'[');
4410 if (!left) return 0;
4411 char *right = (char*)strchr(choptin,']');
4412 if (!right) return 0;
4413 Int_t nch = right-left;
4414 if (nch < 2) return 0;
4415 char *cuts = left+1;
4416 *right = 0;
4417 char *comma, *minus;
4418 Int_t i;
4419 while (1) {
4420 comma = strchr(cuts,',');
4421 if (comma) *comma = 0;
4422 minus = strchr(cuts,'-');
4423 if (minus) cuts = minus+1;
4424 while (*cuts == ' ') cuts++;
4425 Int_t nc = strlen(cuts);
4426 while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4427 TIter next(gROOT->GetListOfSpecials());
4428 TCutG *cut=0;
4429 TObject *obj;
4430 while ((obj = next())) {
4431 if (!obj->InheritsFrom(TCutG::Class())) continue;
4432 if (strcmp(obj->GetName(),cuts)) continue;
4433 cut = (TCutG*)obj;
4434 break;
4435 }
4436 if (cut) {
4437 fCuts[fNcuts] = cut;
4438 fCutsOpt[fNcuts] = 1;
4439 if (minus) fCutsOpt[fNcuts] = -1;
4440 fNcuts++;
4441 }
4442 if (!comma) break;
4443 cuts = comma+1;
4444 }
4445 for (i=0;i<=nch;i++) left[i] = ' ';
4446 return fNcuts;
4447}
4448
4449////////////////////////////////////////////////////////////////////////////////
4450/// [Control routine to paint any kind of histograms](\ref HP00)
4451
4453{
4454
4455 if (fH->GetBuffer()) fH->BufferEmpty(-1);
4456
4457 //For iOS: put the histogram on the top of stack of pickable objects.
4458 const TPickerStackGuard topPush(fH);
4459
4460 gPad->SetVertical(kTRUE);
4461
4462 TH1 *oldhist = gCurrentHist;
4463 gCurrentHist = fH;
4464 TH1 *hsave = fH;
4465 Double_t minsav = fH->GetMinimumStored();
4466
4467 if (!MakeChopt(option)) return; //check options and fill Hoption structure
4468
4469 // Paint using TSpectrum2Painter
4470 if (Hoption.Spec) {
4471 if (!TableInit()) return;
4472 if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4473 gROOT->ProcessLineFast(TString::Format("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%zx,\"%s\",%d)",
4474 (size_t)fH, option, Hoption.Spec).Data());
4475 return;
4476 }
4477
4478 // Deflate the labels in case of alphanumeric labels
4482
4483 if (Hoption.Pie) {
4484 if (fH->GetDimension() == 1) {
4485 if (!fPie)
4486 fPie = std::make_unique<TPie>(fH);
4487 fPie->Paint(option);
4488 } else {
4489 Error("Paint", "Option PIE is for 1D histograms only");
4490 }
4491 return;
4492 } else {
4493 fPie.reset();
4494 }
4495
4496 fXbuf.resize(kNMAX);
4497 fYbuf.resize(kNMAX);
4498 if (fH->GetDimension() > 2) {
4499 PaintH3(option);
4500 fH->SetMinimum(minsav);
4501 if (Hoption.Func) {
4502 Hoption_t hoptsave = Hoption;
4503 Hparam_t hparsave = Hparam;
4505 SetHistogram(hsave);
4506 Hoption = hoptsave;
4507 Hparam = hparsave;
4508 }
4509 gCurrentHist = oldhist;
4510 fXbuf.clear();
4511 fYbuf.clear();
4512 return;
4513 }
4514 TView *view = gPad->GetView();
4515 if (view) {
4516 if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4517 delete view;
4518 gPad->SetView(nullptr);
4519 }
4520 }
4521 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4522 // In case of 1D histogram, Z axis becomes Y axis.
4523 Int_t logysav=0, logzsav=0;
4524 if (fH->GetDimension() == 1) {
4525 logysav = Hoption.Logy;
4526 logzsav = Hoption.Logz;
4527 Hoption.Logz = 0;
4528 if (Hoption.Logy) {
4529 Hoption.Logz = 1;
4530 Hoption.Logy = 0;
4531 }
4532 }
4534 if (Hoption.Func) {
4535 Hoption_t hoptsave = Hoption;
4536 Hparam_t hparsave = Hparam;
4538 SetHistogram(hsave);
4539 Hoption = hoptsave;
4540 Hparam = hparsave;
4541 }
4542 fH->SetMinimum(minsav);
4543 gCurrentHist = oldhist;
4544 fXbuf.clear();
4545 fYbuf.clear();
4546 if (fH->GetDimension() == 1) {
4547 Hoption.Logy = logysav;
4548 Hoption.Logz = logzsav;
4549 }
4550 return;
4551 }
4552
4553 if (Hoption.Bar >= 20) {
4555 fXbuf.clear();
4556 fYbuf.clear();
4557 return;
4558 }
4559
4560 gPad->RangeAxisChanged(); //emit RangeAxisChanged() signal to sync axes
4561 // fill Hparam structure with histo parameters
4562 if (!PaintInit()) {
4563 fXbuf.clear();
4564 fYbuf.clear();
4565 return;
4566 }
4567
4568 // Picture surround (if new page) and page number (if requested).
4569 // Histogram surround (if not option "Same").
4570 PaintFrame();
4571
4572 // Paint histogram axis only
4573 Bool_t gridx = gPad->GetGridx();
4574 Bool_t gridy = gPad->GetGridy();
4575 if (Hoption.Axis > 0) {
4576 if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4577 else {
4578 if (gridx) gPad->SetGridx(0);
4579 if (gridy) gPad->SetGridy(0);
4581 if (gridx) gPad->SetGridx(1);
4582 if (gridy) gPad->SetGridy(1);
4583 }
4584 if ((Hoption.Same%10) ==1) Hoption.Same += 1;
4585 goto paintstat;
4586 }
4587 if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4588
4589 // test for options BAR or HBAR
4590 if (Hoption.Bar >= 10) {
4592 }
4593
4594 // do not draw histogram if error bars required
4595 if (!Hoption.Error) {
4596 if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4597 }
4598
4599 // test for error bars or option E
4600 if (Hoption.Error) {
4602 if (Hoption.Hist == 2) PaintHist(option);
4603 }
4604
4606
4607 // test for associated function
4608 if (Hoption.Func) {
4609 Hoption_t hoptsave = Hoption;
4610 Hparam_t hparsave = Hparam;
4612 SetHistogram(hsave);
4613 Hoption = hoptsave;
4614 Hparam = hparsave;
4615 }
4616
4617 if (gridx) gPad->SetGridx(0);
4618 if (gridy) gPad->SetGridy(0);
4620 if (gridx) gPad->SetGridx(1);
4621 if (gridy) gPad->SetGridy(1);
4622
4623 PaintTitle(); // Draw histogram title
4624
4625 // Draw box with histogram statistics and/or fit parameters
4626paintstat:
4627 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4628 TIter next(fFunctions);
4629 TObject *obj = 0;
4630 while ((obj = next())) {
4631 if (obj->InheritsFrom(TF1::Class())) break;
4632 obj = 0;
4633 }
4634
4635 //Stat is painted twice (first, it will be in canvas' list of primitives),
4636 //second, it will be here, this is not required on iOS.
4637 //Condition is ALWAYS true on a platform different from iOS.
4638 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4639 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4640 }
4641 fH->SetMinimum(minsav);
4642 gCurrentHist = oldhist;
4643 fXbuf.clear();
4644 fYbuf.clear();
4645}
4646
4647////////////////////////////////////////////////////////////////////////////////
4648/// [Control function to draw a table as an arrow plot](\ref HP12)
4649
4651{
4652 Double_t xk, xstep, yk, ystep;
4653 Double_t dx, dy, x1, x2, y1, y2, xc, yc, dxn, dyn;
4656 Double_t xrg = gPad->GetUxmin();
4657 Double_t yrg = gPad->GetUymin();
4658 Double_t xln = gPad->GetUxmax() - xrg;
4659 Double_t yln = gPad->GetUymax() - yrg;
4660 Double_t cx = (xln/Double_t(ncx))/2.;
4661 Double_t cy = (yln/Double_t(ncy))/2.;
4662 Double_t dn = 1.E-30;
4663
4664 auto arrow = new TArrow();
4665 arrow->SetAngle(30);
4666 arrow->SetFillStyle(1001);
4667 arrow->SetFillColor(fH->GetLineColor());
4668 arrow->SetLineColor(fH->GetLineColor());
4669 arrow->SetLineWidth(fH->GetLineWidth());
4670
4671 // Initialize the levels on the Z axis
4672 Int_t ncolors=0, ndivz=0;
4673 Double_t scale=0.;
4674 if (Hoption.Arrow>1) {
4675 ncolors = gStyle->GetNumberOfColors();
4676 Int_t ndiv = fH->GetContour();
4677 if (ndiv == 0 ) {
4678 ndiv = gStyle->GetNumberContours();
4679 fH->SetContour(ndiv);
4680 }
4681 ndivz = TMath::Abs(ndiv);
4682 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
4683 scale = ndivz/(fH->GetMaximum()-fH->GetMinimum());
4684 }
4685
4686 for (Int_t id=1;id<=2;id++) {
4687 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4688 yk = fYaxis->GetBinLowEdge(j);
4689 ystep = fYaxis->GetBinWidth(j);
4690 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4691 xk = fXaxis->GetBinLowEdge(i);
4692 xstep = fXaxis->GetBinWidth(i);
4693 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4694 if (i == Hparam.xfirst) {
4695 dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4696 } else if (i == Hparam.xlast) {
4697 dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4698 } else {
4699 dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4700 }
4701 if (j == Hparam.yfirst) {
4702 dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4703 } else if (j == Hparam.ylast) {
4704 dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4705 } else {
4706 dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4707 }
4708 if (id == 1) {
4709 dn = TMath::Max(dn, TMath::Abs(dx));
4710 dn = TMath::Max(dn, TMath::Abs(dy));
4711 } else if (id == 2) {
4712 xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4713 dxn = cx*dx/dn;
4714 x1 = xc - dxn;
4715 x2 = xc + dxn;
4716 yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4717 dyn = cy*dy/dn;
4718 y1 = yc - dyn;
4719 y2 = yc + dyn;
4720 if (Hoption.Arrow>1) {
4721 int color = Int_t(0.01+(fH->GetBinContent(i, j)-fH->GetMinimum())*scale);
4722 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
4723 if (theColor > ncolors-1) theColor = ncolors-1;
4724 arrow->SetFillColor(gStyle->GetColorPalette(theColor));
4725 arrow->SetLineColor(gStyle->GetColorPalette(theColor));
4726 }
4727 if (TMath::Abs(x2-x1) > 0. || TMath::Abs(y2-y1) > 0.) {
4728 arrow->PaintArrow(x1, y1, x2, y2, 0.015, "|>");
4729 } else {
4730 arrow->PaintArrow(x1, y1, x2, y2, 0.005, "|>");
4731 }
4732 }
4733 }
4734 }
4735 }
4736
4738}
4739
4740////////////////////////////////////////////////////////////////////////////////
4741/// Draw axis (2D case) of an histogram.
4742///
4743/// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4744/// to draw the grid and the axis separately. In `THistPainter::Paint` this
4745/// feature is used to make sure that the grid is drawn in the background and
4746/// the axis tick marks in the foreground of the pad.
4747
4749{
4750
4751 //On iOS, grid should not be pickable and can not be highlighted.
4752 //Condition is never true on a platform different from iOS.
4753 if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4754 return;
4755
4756 if (Hoption.Axis == -1) return;
4757 if (Hoption.Same && Hoption.Axis <= 0) return;
4758
4759 // Repainting alphanumeric labels axis on a plot done with
4760 // the option HBAR (horizontal) needs some adjustments.
4761 TAxis *xaxis = nullptr;
4762 TAxis *yaxis = nullptr;
4763 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4764 if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4765 TIter next(gPad->GetListOfPrimitives());
4766 TObject *obj;
4767 // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4768 while ((obj = next())) {
4769 if (!obj->InheritsFrom(TH1::Class()) &&
4770 !obj->InheritsFrom(THStack::Class())) continue;
4771 TString opt = obj->GetDrawOption();
4772 opt.ToLower();
4773 // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4774 if (strstr(opt,"hbar")) {
4775 gPad->SetVertical(kFALSE);
4776 xaxis = fXaxis;
4777 yaxis = fYaxis;
4778 if (!strcmp(xaxis->GetName(),"xaxis")) {
4779 fXaxis = yaxis;
4780 fYaxis = xaxis;
4781 }
4782 }
4783 break;
4784 }
4785 }
4786 }
4787
4788 static char chopt[10] = "";
4789 Double_t gridl = 0;
4790 Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4791 Int_t useHparam = 0;
4792 Double_t umin, umax, uminsave, umaxsave;
4793 Short_t xAxisPos = Hoption.AxisPos/10;
4794 Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4795
4796 Double_t axmin = gPad->GetUxmin();
4797 Double_t axmax = gPad->GetUxmax();
4798 Double_t aymin = gPad->GetUymin();
4799 Double_t aymax = gPad->GetUymax();
4800 char *cw = nullptr;
4801 TGaxis axis;
4802
4803 // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4804 // Hparam must be use for the axis limits.
4805 if (Hoption.Contour == 14) useHparam = 1;
4806 if (Hoption.Same) {
4807 TObject *obj;
4808 TIter next(gPad->GetListOfPrimitives());
4809 while ((obj=next())) {
4810 if (strstr(obj->GetDrawOption(),"cont4")) {
4811 useHparam = 1;
4812 break;
4813 }
4814 }
4815 }
4816
4817 // Paint X axis
4818
4819 //To make X-axis selectable on iOS device.
4820 if (gPad->PadInSelectionMode())
4821 gPad->PushSelectableObject(fXaxis);
4822
4823 //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4824 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4825 ndivx = fXaxis->GetNdivisions();
4826 if (ndivx > 1000) {
4827 nx2 = ndivx/100;
4828 nx1 = TMath::Max(1, ndivx%100);
4829 ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4830 }
4831 axis.SetTextAngle(0);
4833
4834 chopt[0] = 0;
4835 strlcat(chopt, "SDH",10);
4836 if (ndivx < 0) strlcat(chopt, "N",10);
4837 if (gPad->GetGridx()) {
4838 gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4839 strlcat(chopt, "W",10);
4840 }
4841
4842 // Define X-Axis limits
4843 if (Hoption.Logx) {
4844 strlcat(chopt, "G",10);
4845 ndiv = TMath::Abs(ndivx);
4846 if (useHparam) {
4847 umin = TMath::Power(10,Hparam.xmin);
4848 umax = TMath::Power(10,Hparam.xmax);
4849 } else {
4850 umin = TMath::Power(10,axmin);
4851 umax = TMath::Power(10,axmax);
4852 }
4853 } else {
4854 ndiv = TMath::Abs(ndivx);
4855 if (useHparam) {
4856 umin = Hparam.xmin;
4857 umax = Hparam.xmax;
4858 } else {
4859 umin = axmin;
4860 umax = axmax;
4861 }
4862 }
4863
4864 // Display axis as time
4865 if (fXaxis->GetTimeDisplay()) {
4866 strlcat(chopt,"t",10);
4867 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4869 }
4870 }
4871
4872 // The main X axis can be on the bottom or on the top of the pad
4873 Double_t xAxisYPos1, xAxisYPos2;
4874 if (xAxisPos == 1) {
4875 // Main X axis top
4876 xAxisYPos1 = aymax;
4877 xAxisYPos2 = aymin;
4878 } else {
4879 // Main X axis bottom
4880 xAxisYPos1 = aymin;
4881 xAxisYPos2 = aymax;
4882 }
4883
4884 // Paint the main X axis (always)
4885 uminsave = umin;
4886 umaxsave = umax;
4887 ndivsave = ndiv;
4888 axis.SetOption(chopt);
4889 if (xAxisPos) {
4890 strlcat(chopt, "-",10);
4891 gridl = -gridl;
4892 }
4893 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4894 axis.SetLabelSize(0.);
4895 axis.SetTitle("");
4896 }
4897 axis.PaintAxis(axmin, xAxisYPos1,
4898 axmax, xAxisYPos1,
4899 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4900
4901 // Paint additional X axis (if needed)
4902 // On iOS, this additional X axis is neither pickable, nor highlighted.
4903 // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4904 if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4905 if (xAxisPos) {
4906 cw=strstr(chopt,"-");
4907 *cw='z';
4908 } else {
4909 strlcat(chopt, "-",10);
4910 }
4911 if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4912 if ((cw=strstr(chopt,"W"))) *cw='z';
4913 axis.SetTitle("");
4914 axis.PaintAxis(axmin, xAxisYPos2,
4915 axmax, xAxisYPos2,
4916 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4917 }
4918 }//End of "if pad in selection mode etc".
4919
4920 // Paint Y axis
4921 //On iOS, Y axis must pushed into the stack of selectable objects.
4922 if (gPad->PadInSelectionMode())
4923 gPad->PushSelectableObject(fYaxis);
4924
4925 //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4926 if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4927 ndivy = fYaxis->GetNdivisions();
4929
4930 chopt[0] = 0;
4931 strlcat(chopt, "SDH",10);
4932 if (ndivy < 0) strlcat(chopt, "N",10);
4933 if (gPad->GetGridy()) {
4934 gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4935 strlcat(chopt, "W",10);
4936 }
4937
4938 // Define Y-Axis limits
4939 if (Hoption.Logy) {
4940 strlcat(chopt, "G",10);
4941 ndiv = TMath::Abs(ndivy);
4942 if (useHparam) {
4943 umin = TMath::Power(10,Hparam.ymin);
4944 umax = TMath::Power(10,Hparam.ymax);
4945 } else {
4946 umin = TMath::Power(10,aymin);
4947 umax = TMath::Power(10,aymax);
4948 }
4949 } else {
4950 ndiv = TMath::Abs(ndivy);
4951 if (useHparam) {
4952 umin = Hparam.ymin;
4953 umax = Hparam.ymax;
4954 } else {
4955 umin = aymin;
4956 umax = aymax;
4957 }
4958 }
4959
4960 // Display axis as time
4961 if (fYaxis->GetTimeDisplay()) {
4962 strlcat(chopt,"t",10);
4963 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4965 }
4966 }
4967
4968 // The main Y axis can be on the left or on the right of the pad
4969 Double_t yAxisXPos1, yAxisXPos2;
4970 if (yAxisPos == 1) {
4971 // Main Y axis left
4972 yAxisXPos1 = axmax;
4973 yAxisXPos2 = axmin;
4974 } else {
4975 // Main Y axis right
4976 yAxisXPos1 = axmin;
4977 yAxisXPos2 = axmax;
4978 }
4979
4980 // Paint the main Y axis (always)
4981 uminsave = umin;
4982 umaxsave = umax;
4983 ndivsave = ndiv;
4984 axis.SetOption(chopt);
4985 if (yAxisPos) {
4986 strlcat(chopt, "+L",10);
4987 gridl = -gridl;
4988 }
4989 if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4990 axis.SetLabelSize(0.);
4991 axis.SetTitle("");
4992 }
4993 axis.PaintAxis(yAxisXPos1, aymin,
4994 yAxisXPos1, aymax,
4995 umin, umax, ndiv, chopt, gridl, drawGridOnly);
4996
4997 // Paint the additional Y axis (if needed)
4998 // Additional checks for pad mode are required on iOS: this "second" axis is
4999 // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
5000 if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
5001 if (gPad->GetTicky() < 2) {
5002 strlcat(chopt, "U",10);
5004 } else {
5005 strlcat(chopt, "+L",10);
5006 }
5007 if ((cw=strstr(chopt,"W"))) *cw='z';
5008 axis.SetTitle("");
5009 axis.PaintAxis(yAxisXPos2, aymin,
5010 yAxisXPos2, aymax,
5011 uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
5012 }
5013 }//End of "if pad is in selection mode etc."
5014
5015 // Reset the axis if they have been inverted in case of option HBAR
5016 if (xaxis) {
5017 fXaxis = xaxis;
5018 fYaxis = yaxis;
5019 }
5020}
5021
5022////////////////////////////////////////////////////////////////////////////////
5023/// [Draw a bar-chart in a normal pad.](\ref HP10)
5024
5026{
5027
5028 Int_t bar = Hoption.Bar - 10;
5029 Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
5032 TBox box;
5033 Int_t hcolor = fH->GetFillColor();
5034 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5035 Int_t hstyle = fH->GetFillStyle();
5036 box.SetFillColor(hcolor);
5037 box.SetFillStyle(hstyle);
5038 box.SetLineStyle(fH->GetLineStyle());
5039 box.SetLineColor(fH->GetLineColor());
5040 box.SetLineWidth(fH->GetLineWidth());
5041 for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
5042 y = fH->GetBinContent(bin);
5043 xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
5044 xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
5045 ymin = gPad->GetUymin();
5046 ymax = gPad->YtoPad(y);
5047 if (ymax < gPad->GetUymin()) continue;
5048 if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
5049 if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
5050 if (Hoption.MinimumZero && ymin < 0)
5051 ymin=TMath::Min(0.,gPad->GetUymax());
5052 w = (xmax-xmin)*width;
5053 xmin += offset*(xmax-xmin);
5054 xmax = xmin + w;
5055 if (bar < 1) {
5056 box.PaintBox(xmin,ymin,xmax,ymax);
5057 } else {
5058 umin = xmin + bar*(xmax-xmin)/10.;
5059 umax = xmax - bar*(xmax-xmin)/10.;
5060 //box.SetFillColor(hcolor+150); //bright
5061 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5062 box.PaintBox(xmin,ymin,umin,ymax);
5063 box.SetFillColor(hcolor);
5064 box.PaintBox(umin,ymin,umax,ymax);
5065 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5066 box.PaintBox(umax,ymin,xmax,ymax);
5067 }
5068 }
5069}
5070
5071////////////////////////////////////////////////////////////////////////////////
5072/// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](\ref HP10)
5073
5075{
5076
5077 gPad->SetVertical(kFALSE);
5078
5079 PaintInitH();
5080
5081 TAxis *xaxis = fXaxis;
5082 TAxis *yaxis = fYaxis;
5083 if (!strcmp(xaxis->GetName(),"xaxis")) {
5084 fXaxis = yaxis;
5085 fYaxis = xaxis;
5086 }
5087
5088 PaintFrame();
5090
5091 Int_t bar = Hoption.Bar - 20;
5092 Double_t xmin,xmax,ymin,ymax,umin,umax,w;
5095 TBox box;
5096 Int_t hcolor = fH->GetFillColor();
5097 if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
5098 Int_t hstyle = fH->GetFillStyle();
5099 box.SetFillColor(hcolor);
5100 box.SetFillStyle(hstyle);
5101 box.SetLineStyle(fH->GetLineStyle());
5102 box.SetLineColor(fH->GetLineColor());
5103 box.SetLineWidth(fH->GetLineWidth());
5104 for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
5105 ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
5106 ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
5107 xmin = gPad->GetUxmin();
5108 xmax = gPad->XtoPad(fH->GetBinContent(bin));
5109 if (xmax < gPad->GetUxmin()) continue;
5110 if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
5111 if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
5112 if (Hoption.MinimumZero && xmin < 0)
5113 xmin=TMath::Min(0.,gPad->GetUxmax());
5114 w = (ymax-ymin)*width;
5115 ymin += offset*(ymax-ymin);
5116 ymax = ymin + w;
5117 if (bar < 1) {
5118 box.PaintBox(xmin,ymin,xmax,ymax);
5119 } else {
5120 umin = ymin + bar*(ymax-ymin)/10.;
5121 umax = ymax - bar*(ymax-ymin)/10.;
5122 box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
5123 box.PaintBox(xmin,ymin,xmax,umin);
5124 box.SetFillColor(hcolor);
5125 box.PaintBox(xmin,umin,xmax,umax);
5126 box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
5127 box.PaintBox(xmin,umax,xmax,ymax);
5128 }
5129 }
5130
5131 PaintTitle();
5132
5133 // Draw box with histogram statistics and/or fit parameters
5134 if ((Hoption.Same%10) != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
5135 TIter next(fFunctions);
5136 TObject *obj = nullptr;
5137 while ((obj = next())) {
5138 if (obj->InheritsFrom(TF1::Class())) break;
5139 obj = nullptr;
5140 }
5141 PaintStat(gStyle->GetOptStat(),(TF1*)obj);
5142 }
5143
5144 fXaxis = xaxis;
5145 fYaxis = yaxis;
5146}
5147
5148////////////////////////////////////////////////////////////////////////////////
5149/// [Control function to draw a 2D histogram as a box plot](\ref HP13)
5150
5152{
5153
5154 Style_t fillsav = fH->GetFillStyle();
5155 Style_t colsav = fH->GetFillColor();
5156 if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
5157 if (Hoption.Box == 11) fH->SetFillStyle(1001);
5158 fH->TAttLine::Modify();
5159 fH->TAttFill::Modify();
5160
5161 Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
5162 Double_t ux1 = gPad->PixeltoX(1);
5163 Double_t ux0 = gPad->PixeltoX(0);
5164 Double_t uy1 = gPad->PixeltoY(1);
5165 Double_t uy0 = gPad->PixeltoY(0);
5166 Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
5167 Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
5168
5169 Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
5172 Double_t zminlin = zmin, zmaxlin = zmax;
5173
5174 // In case of option SAME, zmin and zmax values are taken from the
5175 // first plotted 2D histogram.
5176 if (Hoption.Same > 0 && Hoption.Same < 10) {
5177 TH2 *h2;
5178 TIter next(gPad->GetListOfPrimitives());
5179 while ((h2 = (TH2 *)next())) {
5180 if (!h2->InheritsFrom(TH2::Class())) continue;
5181 zmin = TMath::Max(h2->GetMinimum(), 0.);
5182 zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
5183 TMath::Abs(h2->GetMinimum()));
5184 zminlin = zmin;
5185 zmaxlin = zmax;
5186 if (Hoption.Logz) {
5187 if (zmin <= 0) {
5188 zmin = TMath::Log10(zmax*0.001);
5189 } else {
5190 zmin = TMath::Log10(zmin);
5191 }
5192 zmax = TMath::Log10(zmax);
5193 }
5194 break;
5195 }
5196 } else {
5197 if (Hoption.Logz) {
5198 if (zmin > 0) {
5199 zmin = TMath::Log10(zmin);
5200 zmax = TMath::Log10(zmax);
5201 } else {
5202 return;
5203 }
5204 }
5205 }
5206
5207 Double_t zratio, dz = zmax - zmin;
5208 Bool_t kZminNeg = kFALSE;
5209 if (fH->GetMinimum()<0) kZminNeg = kTRUE;
5210 Bool_t kZNeg = kFALSE;
5211
5212 // Define the dark and light colors the "button style" boxes.
5213 Color_t color = fH->GetFillColor();
5214 Color_t light=0, dark=0;
5215 if (Hoption.Box == 11) {
5216 light = TColor::GetColorBright(color);
5217 dark = TColor::GetColorDark(color);
5218 }
5219
5220 // Loop over all the bins and draw the boxes
5221 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5222 yk = fYaxis->GetBinLowEdge(j);
5223 ystep = fYaxis->GetBinWidth(j);
5224 ycent = 0.5*ystep;
5225 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5226 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5227 xk = fXaxis->GetBinLowEdge(i);
5228 xstep = fXaxis->GetBinWidth(i);
5229 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5230 xcent = 0.5*xstep;
5231 z = Hparam.factor*fH->GetBinContent(bin);
5232 kZNeg = kFALSE;
5233
5234 if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
5235 if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
5236 if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with negative bins.
5237
5238 if (z < 0) {
5239 if (Hoption.Logz) continue;
5240 z = -z;
5241 kZNeg = kTRUE;
5242 }
5243 if (Hoption.Logz) {
5244 if (z != 0) z = TMath::Log10(z);
5245 else z = zmin;
5246 }
5247
5248 if (dz == 0) continue;
5249 zratio = TMath::Sqrt((z-zmin)/dz);
5250 if (zratio == 0) continue;
5251
5252 xup = xcent*zratio + xk + xcent;
5253 xlow = 2*(xk + xcent) - xup;
5254 if (xup-xlow < dxmin) xup = xlow+dxmin;
5255 if (Hoption.Logx) {
5256 if (xup > 0) xup = TMath::Log10(xup);
5257 else continue;
5258 if (xlow > 0) xlow = TMath::Log10(xlow);
5259 else continue;
5260 }
5261
5262 yup = ycent*zratio + yk + ycent;
5263 ylow = 2*(yk + ycent) - yup;
5264 if (yup-ylow < dymin) yup = ylow+dymin;
5265 if (Hoption.Logy) {
5266 if (yup > 0) yup = TMath::Log10(yup);
5267 else continue;
5268 if (ylow > 0) ylow = TMath::Log10(ylow);
5269 else continue;
5270 }
5271
5272 xlow = TMath::Max(xlow, gPad->GetUxmin());
5273 ylow = TMath::Max(ylow, gPad->GetUymin());
5274 xup = TMath::Min(xup , gPad->GetUxmax());
5275 yup = TMath::Min(yup , gPad->GetUymax());
5276
5277 if (xlow >= xup) continue;
5278 if (ylow >= yup) continue;
5279
5280 if (Hoption.Box == 1) {
5281 fH->SetFillColor(color);
5282 fH->TAttFill::Modify();
5283 gPad->PaintBox(xlow, ylow, xup, yup);
5284 if (kZNeg) {
5285 gPad->PaintLine(xlow, ylow, xup, yup);
5286 gPad->PaintLine(xlow, yup, xup, ylow);
5287 }
5288 } else if (Hoption.Box == 11) {
5289 // Draw the center of the box
5290 fH->SetFillColor(color);
5291 fH->TAttFill::Modify();
5292 gPad->PaintBox(xlow, ylow, xup, yup);
5293
5294 // Draw top&left part of the box
5295 Double_t x[7], y[7];
5296 Double_t bwidth = 0.1;
5297 x[0] = xlow; y[0] = ylow;
5298 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5299 x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
5300 x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
5301 x[4] = xup; y[4] = yup;
5302 x[5] = xlow; y[5] = yup;
5303 x[6] = xlow; y[6] = ylow;
5304 if (kZNeg) fH->SetFillColor(dark);
5305 else fH->SetFillColor(light);
5306 fH->TAttFill::Modify();
5307 gPad->PaintFillArea(7, x, y);
5308
5309 // Draw bottom&right part of the box
5310 x[0] = xlow; y[0] = ylow;
5311 x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
5312 x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
5313 x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
5314 x[4] = xup; y[4] = yup;
5315 x[5] = xup; y[5] = ylow;
5316 x[6] = xlow; y[6] = ylow;
5317 if (kZNeg) fH->SetFillColor(light);
5318 else fH->SetFillColor(dark);
5319 fH->TAttFill::Modify();
5320 gPad->PaintFillArea(7, x, y);
5321 }
5322 }
5323 }
5324
5326 fH->SetFillStyle(fillsav);
5327 fH->SetFillColor(colsav);
5328 fH->TAttFill::Modify();
5329}
5330
5331
5332
5333////////////////////////////////////////////////////////////////////////////////
5334/// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](\ref HP14)
5335
5337{
5338 TH1D *hproj = nullptr;
5339 TH2D *h2 = (TH2D*)fH;
5340
5341 TCandle myCandle;
5343 myCandle.SetMarkerColor(fH->GetLineColor());
5344 myCandle.SetLineColor(fH->GetLineColor());
5345 myCandle.SetLineWidth(fH->GetLineWidth());
5346 myCandle.SetFillColor(fH->GetFillColor());
5347 myCandle.SetFillStyle(fH->GetFillStyle());
5348 myCandle.SetMarkerSize(fH->GetMarkerSize());
5349 myCandle.SetMarkerStyle(fH->GetMarkerStyle());
5351
5352 Bool_t swapXY = myCandle.IsHorizontal();
5353 const Double_t standardCandleWidth = 0.66;
5354 const Double_t standardHistoWidth = 0.8;
5355
5356 double allMaxContent = 0, allMaxIntegral = 0;
5357 if (myCandle.IsViolinScaled())
5358 allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
5359
5360 if (!swapXY) { // Vertical candle
5361 //Determining the slice with the maximum integral - if necessary
5362 if (myCandle.IsCandleScaled())
5363 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5364 hproj = h2->ProjectionY("_px", i, i);
5365 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5366 }
5367 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
5368 Double_t binPosX = fXaxis->GetBinLowEdge(i);
5369 Double_t binWidth = fXaxis->GetBinWidth(i);
5370 hproj = h2->ProjectionY("_px", i, i);
5371 if (hproj->GetEntries() != 0) {
5372 Double_t candleWidth = fH->GetBarWidth();
5373 Double_t offset = fH->GetBarOffset()*binWidth;
5374 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5375 double myIntegral = hproj->Integral();
5376 Double_t histoWidth = candleWidth;
5377 if (candleWidth > 0.999 && candleWidth < 1.001) {
5378 candleWidth = standardCandleWidth;
5379 histoWidth = standardHistoWidth;
5380 }
5381 if (Hoption.Logz && myMaxContent > 0) {
5382 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5383 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5384 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5385 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5386 histoWidth *= myMaxContent/allMaxContent;
5387 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5388 candleWidth *= myIntegral/allMaxIntegral;
5389
5390 myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5391 myCandle.SetCandleWidth(candleWidth*binWidth);
5392 myCandle.SetHistoWidth(histoWidth*binWidth);
5393 myCandle.SetHistogram(hproj);
5394 myCandle.Paint();
5395 }
5396 }
5397 } else { // Horizontal candle
5398 //Determining the slice with the maximum integral - if necessary
5399 if (myCandle.IsCandleScaled())
5400 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5401 hproj = h2->ProjectionX("_py", i, i);
5402 if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5403 }
5404 for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5405 Double_t binPosY = fYaxis->GetBinLowEdge(i);
5406 Double_t binWidth = fYaxis->GetBinWidth(i);
5407 hproj = h2->ProjectionX("_py", i, i);
5408 if (hproj->GetEntries() != 0) {
5409 Double_t candleWidth = fH->GetBarWidth();
5410 Double_t offset = fH->GetBarOffset()*binWidth;
5411 double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5412 double myIntegral = hproj->Integral();
5413 Double_t histoWidth = candleWidth;
5414 if (candleWidth > 0.999 && candleWidth < 1.001) {
5415 candleWidth = standardCandleWidth;
5416 histoWidth = standardHistoWidth;
5417 }
5418 if (Hoption.Logz && myMaxContent > 0) {
5419 histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5420 if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0)
5421 histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5422 } else if (myCandle.IsViolinScaled() && (allMaxContent > 0))
5423 histoWidth *= myMaxContent/allMaxContent;
5424 if (myCandle.IsCandleScaled() && (allMaxIntegral > 0))
5425 candleWidth *= myIntegral/allMaxIntegral;
5426
5427 myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5428 myCandle.SetCandleWidth(candleWidth*binWidth);
5429 myCandle.SetHistoWidth(histoWidth*binWidth);
5430 myCandle.SetHistogram(hproj);
5431 myCandle.Paint();
5432 }
5433 }
5434 }
5435 delete hproj;
5436}
5437
5438
5439
5440////////////////////////////////////////////////////////////////////////////////
5441/// Returns the rendering regions for an axis to use in the COL2 option
5442///
5443/// The algorithm analyses the size of the axis compared to the size of
5444/// the rendering region. It figures out the boundaries to use for each color
5445/// of the rendering region. Only one axis is computed here.
5446///
5447/// This allows for a single computation of the boundaries before iterating
5448/// through all of the bins.
5449///
5450/// \param pAxis the axis to consider
5451/// \param nPixels the number of pixels to render axis into
5452/// \param isLog whether the axis is log scale
5453
5454std::vector<THistRenderingRegion>
5456{
5457 std::vector<THistRenderingRegion> regions;
5458
5459 enum STRATEGY { Bins, Pixels } strategy;
5460
5461 Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5462
5463 if (nBins >= nPixels) {
5464 // more bins than pixels... we should loop over pixels and sample
5465 strategy = Pixels;
5466 } else {
5467 // fewer bins than pixels... we should loop over bins
5468 strategy = Bins;
5469 }
5470
5471 if (isLog) {
5472
5473 Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5474 Int_t binOffset=0;
5475 while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5476 binOffset++;
5477 xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5478 }
5479 if (xMin <= 0) {
5480 // this should cause an error if we have
5481 return regions;
5482 }
5483 Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5484
5485 if (strategy == Bins) {
5486 // logarithmic plot. we find the pixel for the bin
5487 // pixel = eta * log10(V) - alpha
5488 // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5489 // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5490 // and V is axis value
5491 Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5492 Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5493
5494 for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5495
5496 // linear plot. we simply need to find the appropriate bin
5497 // for the
5498 Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5499 Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5500 Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5501 Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5502 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5503 std::make_pair(bin, bin+1)};
5504 regions.push_back(region);
5505 }
5506
5507 } else {
5508
5509 // loop over pixels
5510
5511 Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5512
5513 for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5514 // linear plot
5515 Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5516 Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5517 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5518 std::make_pair(binLow, binHigh)};
5519 regions.push_back(region);
5520 }
5521 }
5522 } else {
5523 // standard linear plot
5524
5525 if (strategy == Bins) {
5526 // loop over bins
5527 for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5528
5529 // linear plot. we simply need to find the appropriate bin
5530 // for the
5531 Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5532 Int_t xPx1 = xPx0 + nPixels/nBins;
5533
5534 // make sure we don't compute beyond our bounds
5535 if (xPx1>= nPixels) xPx1 = nPixels-1;
5536
5537 THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5538 std::make_pair(bin, bin+1)};
5539 regions.push_back(region);
5540 }
5541 } else {
5542 // loop over pixels
5543 for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5544 // linear plot
5545 Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5546 Int_t binHigh = binLow + nBins/nPixels;
5547 THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5548 std::make_pair(binLow, binHigh)};
5549 regions.push_back(region);
5550 }
5551 }
5552 }
5553
5554 return regions;
5555}
5556
5557////////////////////////////////////////////////////////////////////////////////
5558/// [Rendering scheme for the COL2 and COLZ2 options] (\ref HP14)
5559
5561{
5562
5563 if (Hoption.System != kCARTESIAN) {
5564 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5565 "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5566 PaintColorLevels(nullptr);
5567 return;
5568 }
5569
5570 Double_t z;
5571
5572 // Use existing max or min values. If either is already set
5573 // the appropriate value to use.
5574 Double_t zmin = fH->GetMinimumStored();
5575 Double_t zmax = fH->GetMaximumStored();
5576 Double_t originalZMin = zmin;
5577 Double_t originalZMax = zmax;
5578 if ((zmin == -1111) && (zmax == -1111)) {
5579 fH->GetMinimumAndMaximum(zmin, zmax);
5580 fH->SetMinimum(zmin);
5581 fH->SetMaximum(zmax);
5582 } else if (zmin == -1111) {
5583 zmin = fH->GetMinimum();
5584 fH->SetMinimum(zmin);
5585 } else if (zmax == -1111) {
5586 zmax = fH->GetMaximum();
5587 fH->SetMaximum(zmax);
5588 }
5589
5590 Double_t dz = zmax - zmin;
5591 if (dz <= 0) { // Histogram filled with a constant value
5592 zmax += 0.1*TMath::Abs(zmax);
5593 zmin -= 0.1*TMath::Abs(zmin);
5594 dz = zmax - zmin;
5595 }
5596
5597 if (Hoption.Logz) {
5598 if (zmin > 0) {
5599 zmin = TMath::Log10(zmin);
5600 zmax = TMath::Log10(zmax);
5601 dz = zmax - zmin;
5602 } else {
5603 Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5604 "Cannot plot logz because bin content is less than 0.");
5605 return;
5606 }
5607 }
5608
5609 // Initialize the levels on the Z axis
5610 Int_t ndiv = fH->GetContour();
5611 if (ndiv == 0 ) {
5612 ndiv = gStyle->GetNumberContours();
5613 fH->SetContour(ndiv);
5614 }
5615 std::vector<Double_t> colorBounds(ndiv);
5616 std::vector<Double_t> contours(ndiv, 0);
5617 if (!fH->TestBit(TH1::kUserContour)) {
5618 fH->SetContour(ndiv);
5619 } else {
5620 fH->GetContour(contours.data());
5621 }
5622
5623 Double_t step = 1.0/ndiv;
5624 for (Int_t i=0; i<ndiv; ++i) {
5625 colorBounds[i] = step*i;
5626 }
5627
5628 auto pFrame = gPad->GetFrame();
5629 Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5630 Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5631 Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5632 Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5633 Int_t nXPixels = px1-px0;
5634 Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5635
5636 std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5637
5638 auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5639 auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5640 if (xRegions.size() == 0 || yRegions.size() == 0) {
5641 Error("THistPainter::PaintColorLevelFast(Option_t*)",
5642 "Encountered error while computing rendering regions.");
5643 return;
5644 }
5645
5646 Bool_t minExists = kFALSE;
5647 Bool_t maxExists = kFALSE;
5648 Double_t minValue = 1.;
5649 Double_t maxValue = 0.;
5650 for (auto& yRegion : yRegions) {
5651 for (auto& xRegion : xRegions ) {
5652
5653 const auto& xBinRange = xRegion.fBinRange;
5654 const auto& yBinRange = yRegion.fBinRange;
5655
5656 // sample the range
5657 z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5658
5659 if (Hoption.Logz) {
5660 if (z > 0) z = TMath::Log10(z);
5661 else z = zmin;
5662 }
5663
5664 // obey the user's max and min values if they were set
5665 if (z > zmax) z = zmax;
5666 if (z < zmin) z = zmin;
5667
5669 // contours are absolute values
5670 auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5671 z = colorBounds[index];
5672 } else {
5673 Int_t index = 0;
5674 if (dz != 0) {
5675 index = 0.001 + ((z - zmin)/dz)*ndiv;
5676 }
5677
5678 if (index == static_cast<Int_t>(colorBounds.size())) {
5679 index--;
5680 }
5681
5682 // Do a little bookkeeping to use later for getting libAfterImage to produce
5683 // the correct colors
5684 if (index == 0) {
5685 minExists = kTRUE;
5686 } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5687 maxExists = kTRUE;
5688 }
5689
5690 z = colorBounds[index];
5691
5692 if (z < minValue) {
5693 minValue = z;
5694 }
5695 if (z > maxValue) {
5696 maxValue = z;
5697 }
5698 }
5699
5700 // fill in the actual pixels
5701 const auto& xPixelRange = xRegion.fPixelRange;
5702 const auto& yPixelRange = yRegion.fPixelRange;
5703 for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5704 for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5705 Int_t pixel = yPx*nXPixels + xPx;
5706 buffer[pixel] = z;
5707 }
5708 }
5709 } // end px loop
5710 } // end py loop
5711
5712 // This is a bit of a hack to ensure that we span the entire color range and
5713 // don't screw up the colors for a sparse histogram. No one will notice that I set a
5714 // single pixel on the edge of the image to a different color. This is even more
5715 // true because the chosen pixels will be covered by the axis.
5716 if (minValue != maxValue) {
5717 if ( !minExists) {
5718 buffer.front() = 0;
5719 }
5720
5721 if ( !maxExists) {
5722 buffer[buffer.size()-nXPixels] = 0.95;
5723 }
5724 }
5725
5726 // Generate the TImage
5728 TImage* pImage = TImage::Create();
5730 pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5731 delete pPalette;
5732
5733 Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5734 pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5735 delete pImage;
5736
5738
5739 // Reset the maximum and minimum values to their original values
5740 // when this function was called. If we don't do this, an initial
5741 // value of -1111 will be replaced with the true max or min values.
5742 fH->SetMinimum(originalZMin);
5743 fH->SetMaximum(originalZMax);
5744}
5745
5746////////////////////////////////////////////////////////////////////////////////
5747/// [Control function to draw a 2D histogram as a color plot.](\ref HP14)
5748
5750{
5751 Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5752
5753 Double_t zmin = fH->GetMinimum();
5754 Double_t zmax = fH->GetMaximum();
5755
5756 Double_t dz = zmax - zmin;
5757 if (dz <= 0) { // Histogram filled with a constant value
5758 zmax += 0.1*TMath::Abs(zmax);
5759 zmin -= 0.1*TMath::Abs(zmin);
5760 dz = zmax - zmin;
5761 }
5762
5763 // In case of option SAME, zmin and zmax values are taken from the
5764 // first plotted 2D histogram.
5765 if (Hoption.Same > 0 && Hoption.Same < 10) {
5766 TH2 *h2;
5767 TIter next(gPad->GetListOfPrimitives());
5768 while ((h2 = (TH2 *)next())) {
5769 if (!h2->InheritsFrom(TH2::Class())) continue;
5770 zmin = h2->GetMinimum();
5771 zmax = h2->GetMaximum();
5772 fH->SetMinimum(zmin);
5773 fH->SetMaximum(zmax);
5774 if (Hoption.Logz) {
5775 if (zmin <= 0) {
5776 zmin = TMath::Log10(zmax*0.001);
5777 } else {
5778 zmin = TMath::Log10(zmin);
5779 }
5780 zmax = TMath::Log10(zmax);
5781 }
5782 dz = zmax - zmin;
5783 break;
5784 }
5785 } else {
5786 if (Hoption.Logz) {
5787 if (zmin > 0) {
5788 zmin = TMath::Log10(zmin);
5789 zmax = TMath::Log10(zmax);
5790 dz = zmax - zmin;
5791 } else {
5792 return;
5793 }
5794 }
5795 }
5796
5797 Style_t fillsav = fH->GetFillStyle();
5798 Style_t colsav = fH->GetFillColor();
5799 fH->SetFillStyle(1001);
5800 fH->TAttFill::Modify();
5801
5802 // Initialize the levels on the Z axis
5803 Int_t ncolors = gStyle->GetNumberOfColors();
5804 Int_t ndiv = fH->GetContour();
5805 if (ndiv == 0 ) {
5806 ndiv = gStyle->GetNumberContours();
5807 fH->SetContour(ndiv);
5808 }
5809 Int_t ndivz = TMath::Abs(ndiv);
5810 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
5811 Double_t scale = (dz ? ndivz / dz : 1.0);
5812
5813 Int_t color;
5814 TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5815 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5816 yk = fYaxis->GetBinLowEdge(j);
5817 ystep = fYaxis->GetBinWidth(j);
5818 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5819 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5820 xk = fXaxis->GetBinLowEdge(i);
5821 xstep = fXaxis->GetBinWidth(i);
5822 if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
5823 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5824 z = fH->GetBinContent(bin);
5825 // if fH is a profile histogram do not draw empty bins
5826 if (prof2d) {
5827 const Double_t binEntries = prof2d->GetBinEntries(bin);
5828 if (binEntries == 0)
5829 continue;
5830 } else {
5831 // don't draw the empty bins for non-profile histograms
5832 // with positive content
5833 if (z == 0) {
5834 if (zmin >= 0 || Hoption.Logz) continue;
5835 if (Hoption.Color == 2) continue;
5836 }
5837 }
5838
5839 if (Hoption.Logz) {
5840 if (z > 0) z = TMath::Log10(z);
5841 else z = zmin;
5842 }
5843 if (z < zmin && !Hoption.Zero) continue;
5844 xup = xk + xstep;
5845 xlow = xk;
5846 if (Hoption.Logx) {
5847 if (xup > 0) xup = TMath::Log10(xup);
5848 else continue;
5849 if (xlow > 0) xlow = TMath::Log10(xlow);
5850 else continue;
5851 }
5852 yup = yk + ystep;
5853 ylow = yk;
5854 if (Hoption.System != kPOLAR) {
5855 if (Hoption.Logy) {
5856 if (yup > 0) yup = TMath::Log10(yup);
5857 else continue;
5858 if (ylow > 0) ylow = TMath::Log10(ylow);
5859 else continue;
5860 }
5861 if (xup < gPad->GetUxmin()) continue;
5862 if (yup < gPad->GetUymin()) continue;
5863 if (xlow > gPad->GetUxmax()) continue;
5864 if (ylow > gPad->GetUymax()) continue;
5865 if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5866 if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5867 if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5868 if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5869 }
5870
5872 zc = fH->GetContourLevelPad(0);
5873 if (z < zc) continue;
5874 color = -1;
5875 for (Int_t k=0; k<ndiv; k++) {
5876 zc = fH->GetContourLevelPad(k);
5877 if (z < zc) {
5878 continue;
5879 } else {
5880 color++;
5881 }
5882 }
5883 } else {
5884 color = Int_t(0.01+(z-zmin)*scale);
5885 }
5886
5887 Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5888 if (theColor > ncolors-1) theColor = ncolors-1;
5890 fH->TAttFill::Modify();
5891 if (Hoption.System != kPOLAR) {
5892 gPad->PaintBox(xlow, ylow, xup, yup);
5893 } else {
5894 TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
5895 crown.SetFillColor(gStyle->GetColorPalette(theColor));
5896 crown.SetLineColor(fH->GetLineColor());
5897 crown.SetLineWidth(fH->GetLineWidth());
5898 crown.SetLineStyle(fH->GetLineStyle());
5899 crown.Paint();
5900 }
5901 }
5902 }
5903
5905
5906 fH->SetFillStyle(fillsav);
5907 fH->SetFillColor(colsav);
5908 fH->TAttFill::Modify();
5909
5910}
5911
5912////////////////////////////////////////////////////////////////////////////////
5913/// [Control function to draw a 2D histogram as a contour plot.](\ref HP16)
5914
5916{
5917
5918 Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5919 Int_t itars, mode, ir[4];
5920 Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5921
5922 if (Hoption.Contour == 14) {
5923 Hoption.Surf = 12;
5924 Hoption.Axis = 1;
5925 thesave = gPad->GetTheta();
5926 phisave = gPad->GetPhi();
5927 gPad->SetPhi(0.);
5928 gPad->SetTheta(90.);
5930 gPad->SetPhi(phisave);
5931 gPad->SetTheta(thesave);
5932 TView *view = gPad->GetView();
5933 if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5934 PaintAxis();
5935 return;
5936 }
5937
5938 if (Hoption.Same) {
5939 // If the contour is painted on a 3d plot, the contour lines are
5940 // paint in 3d too.
5941 TObject *obj;
5942 TIter next(gPad->GetListOfPrimitives());
5943 while ((obj=next())) {
5944 if (strstr(obj->GetDrawOption(),"surf") ||
5945 strstr(obj->GetDrawOption(),"lego") ||
5946 strstr(obj->GetDrawOption(),"tri")) {
5947 Hoption.Surf = 16;
5949 return;
5950 }
5951 }
5952 }
5953
5954 if (Hoption.Contour == 15) {
5955 TGraphDelaunay2D *dt = nullptr;
5956 TGraphDelaunay *dtOld = nullptr;
5957 TList *hl = fH->GetListOfFunctions();
5958 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5959 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5960 if (!dt && !dtOld) return;
5961 if (!fGraph2DPainter)
5962 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
5963 fGraph2DPainter->Paint(option);
5964 return;
5965 }
5966
5967 gPad->SetBit(TGraph::kClipFrame);
5968
5969 std::vector<Double_t> levels(2*kMAXCONTOUR);
5970 std::vector<Double_t> xarr(2*kMAXCONTOUR);
5971 std::vector<Double_t> yarr(2*kMAXCONTOUR);
5972 std::vector<Int_t> itarr(2*kMAXCONTOUR);
5973
5974 Int_t npmax = 0;
5975 for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
5976
5977 ncontour = fH->GetContour();
5978 if (ncontour == 0) {
5979 ncontour = gStyle->GetNumberContours();
5980 fH->SetContour(ncontour);
5981 }
5982 if (ncontour > kMAXCONTOUR) {
5983 Warning("PaintContour", "maximum number of contours is %d, asked for %d",
5984 kMAXCONTOUR, ncontour);
5985 ncontour = kMAXCONTOUR-1;
5986 }
5987 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ncontour);
5988
5989 for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
5990 Int_t linesav = fH->GetLineStyle();
5991 Int_t colorsav = fH->GetLineColor();
5992 Int_t fillsav = fH->GetFillColor();
5993 if (Hoption.Contour == 13) {
5994 fH->TAttLine::Modify();
5995 }
5996
5997 std::vector<std::unique_ptr<TPolyLine>> polys;
5998 TObjArray *contours = nullptr;
5999 TList *list = nullptr;
6000 TGraph *graph = nullptr;
6001 std::vector<Int_t> np;
6002 if (Hoption.Contour == 1) {
6003 np.resize(ncontour);
6004 for (i=0;i<ncontour;i++)
6005 np[i] = 0;
6006 for (i=0;i<ncontour;i++)
6007 polys.emplace_back(std::make_unique<TPolyLine>(100));
6008 if (Hoption.List == 1) {
6009 contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
6010 if (contours) {
6011 gROOT->GetListOfSpecials()->Remove(contours);
6012 count = contours->GetSize();
6013 for (i=0;i<count;i++) {
6014 list = (TList*)contours->At(i);
6015 if (list) list->Delete();
6016 }
6017 contours->Delete();
6018 delete contours;
6019 }
6020 contours = new TObjArray(ncontour);
6021 contours->SetName("contours");
6022 gROOT->GetListOfSpecials()->Add(contours);
6023 for (i=0;i<ncontour;i++) {
6024 list = new TList();
6025 contours->Add(list);
6026 }
6027 }
6028 }
6029 Int_t theColor;
6030 Int_t ncolors = gStyle->GetNumberOfColors();
6031 Int_t ndivz = TMath::Abs(ncontour);
6032
6033 Int_t k,ipoly;
6034 for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
6035 y[0] = fYaxis->GetBinCenter(j);
6036 y[1] = y[0];
6037 y[2] = fYaxis->GetBinCenter(j+1);
6038 y[3] = y[2];
6039 for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
6040 zc[0] = fH->GetBinContent(i, j);
6041 zc[1] = fH->GetBinContent(i+1, j);
6042 zc[2] = fH->GetBinContent(i+1, j+1);
6043 zc[3] = fH->GetBinContent(i, j+1);
6044 if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
6045 if (Hoption.Logz) {
6046 if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
6047 else zc[0] = Hparam.zmin;
6048 if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
6049 else zc[1] = Hparam.zmin;
6050 if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
6051 else zc[2] = Hparam.zmin;
6052 if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
6053 else zc[3] = Hparam.zmin;
6054 }
6055 for (k=0;k<4;k++) {
6056 ir[k] = TMath::BinarySearch(ncontour, levels.data(), zc[k]);
6057 }
6058 if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
6059 x[0] = fXaxis->GetBinCenter(i);
6060 x[3] = x[0];
6061 x[1] = fXaxis->GetBinCenter(i+1);
6062 x[2] = x[1];
6063 if (zc[0] <= zc[1]) n = 0; else n = 1;
6064 if (zc[2] <= zc[3]) m = 2; else m = 3;
6065 if (zc[n] > zc[m]) n = m;
6066 n++;
6067 lj=1;
6068 for (ix=1;ix<=4;ix++) {
6069 m = n%4 + 1;
6070 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6071 ir[m-1],x[m-1],y[m-1], xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6072 lj += 2*ljfill;
6073 n = m;
6074 }
6075
6076 if (zc[0] <= zc[1]) n = 0; else n = 1;
6077 if (zc[2] <= zc[3]) m = 2; else m = 3;
6078 if (zc[n] > zc[m]) n = m;
6079 n++;
6080 lj=2;
6081 for (ix=1;ix<=4;ix++) {
6082 if (n == 1) m = 4;
6083 else m = n-1;
6084 ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
6085 ir[m-1],x[m-1],y[m-1],xarr.data()+lj-1,yarr.data()+lj-1,itarr.data()+lj-1, levels.data());
6086 lj += 2*ljfill;
6087 n = m;
6088 }
6089
6090 // Re-order endpoints
6091
6092 count = 0;
6093 for (ix=1; ix<=lj-5; ix +=2) {
6094 //count = 0;
6095 while (itarr[ix-1] != itarr[ix]) {
6096 xsave = xarr[ix];
6097 ysave = yarr[ix];
6098 itars = itarr[ix];
6099 for (jx=ix; jx<=lj-5; jx +=2) {
6100 xarr[jx] = xarr[jx+2];
6101 yarr[jx] = yarr[jx+2];
6102 itarr[jx] = itarr[jx+2];
6103 }
6104 xarr[lj-3] = xsave;
6105 yarr[lj-3] = ysave;
6106 itarr[lj-3] = itars;
6107 if (count > 100) break;
6108 count++;
6109 }
6110 }
6111
6112 if (count > 100) continue;
6113 for (ix=1; ix<=lj-2; ix +=2) {
6114 theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
6115 icol = gStyle->GetColorPalette(theColor);
6116 if (Hoption.Contour == 11) {
6117 fH->SetLineColor(icol);
6118 }
6119 if (Hoption.Contour == 12) {
6120 mode = icol%5;
6121 if (mode == 0) mode = 5;
6123 }
6124 if (Hoption.Contour != 1) {
6125 fH->TAttLine::Modify();
6126 gPad->PaintPolyLine(2,xarr.data()+ix-1,yarr.data()+ix-1);
6127 continue;
6128 }
6129
6130 ipoly = itarr[ix-1];
6131 if (ipoly >=0 && ipoly <ncontour) {
6132 polys[ipoly]->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
6133 polys[ipoly]->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
6134 np[ipoly] += 2;
6135 if (npmax < np[ipoly]) npmax = np[ipoly];
6136 }
6137 }
6138 } // end of if (ir[0]
6139 } //end of for (i
6140 } //end of for (j
6141
6143 std::vector<Double_t> xp, yp;
6144 Int_t nadd,iminus,iplus;
6145 Int_t istart;
6146 Int_t first = ncontour;
6147 std::vector<Int_t> polysort;
6148 Int_t contListNb;
6149 if (Hoption.Contour != 1) goto theEND;
6150
6151 //The 2 points line generated above are now sorted/merged to generate
6152 //a list of consecutive points.
6153 // If the option "List" has been specified, the list of points is saved
6154 // in the form of TGraph objects in the ROOT list of special objects.
6155 xmin = gPad->GetUxmin();
6156 ymin = gPad->GetUymin();
6157 xp.resize(2*npmax);
6158 yp.resize(2*npmax);
6159 polysort.resize(ncontour);
6160 //find first positive contour
6161 for (ipoly=0;ipoly<ncontour;ipoly++) {
6162 if (levels[ipoly] >= 0) {first = ipoly; break;}
6163 }
6164 //store negative contours from 0 to minimum, then all positive contours
6165 k = 0;
6166 for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
6167 for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
6168 // we can now draw sorted contours
6169 contListNb = 0;
6170 fH->SetFillStyle(1001);
6171 for (k=0;k<ncontour;k++) {
6172 ipoly = polysort[k];
6173 if (np[ipoly] == 0) continue;
6174 if (Hoption.List) list = (TList*)contours->At(contListNb);
6175 contListNb++;
6176 Double_t *xx = polys[ipoly]->GetX();
6177 Double_t *yy = polys[ipoly]->GetY();
6178 istart = 0;
6179 while (1) {
6180 iminus = npmax;
6181 iplus = iminus+1;
6182 xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
6183 xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
6184 xx[istart] = xmin; yy[istart] = ymin;
6185 xx[istart+1] = xmin; yy[istart+1] = ymin;
6186 while (1) {
6187 nadd = 0;
6188 for (i=2;i<np[ipoly];i+=2) {
6189 if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
6190 iplus++;
6191 xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
6192 xx[i] = xmin; yy[i] = ymin;
6193 xx[i+1] = xmin; yy[i+1] = ymin;
6194 nadd++;
6195 }
6196 if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
6197 iminus--;
6198 xp[iminus] = xx[i]; yp[iminus] = yy[i];
6199 xx[i] = xmin; yy[i] = ymin;
6200 xx[i+1] = xmin; yy[i+1] = ymin;
6201 nadd++;
6202 }
6203 }
6204 if (nadd == 0) break;
6205 }
6206 theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
6207 icol = gStyle->GetColorPalette(theColor);
6208 if (ndivz > 1) fH->SetFillColor(icol);
6209 fH->TAttFill::Modify();
6210 gPad->PaintFillArea(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6211 if (Hoption.List) {
6212 graph = new TGraph(iplus-iminus+1,xp.data()+iminus,yp.data()+iminus);
6213 graph->SetFillColor(icol);
6214 graph->SetLineWidth(fH->GetLineWidth());
6215 list->Add(graph);
6216 }
6217 //check if more points are left
6218 istart = 0;
6219 for (i=2;i<np[ipoly];i+=2) {
6220 if (xx[i] != xmin && yy[i] != ymin) {
6221 istart = i;
6222 break;
6223 }
6224 }
6225 if (istart == 0) break;
6226 }
6227 }
6228
6229theEND:
6230 gPad->ResetBit(TGraph::kClipFrame);
6232 fH->SetLineStyle(linesav);
6233 fH->SetLineColor(colorsav);
6234 fH->SetFillColor(fillsav);
6235}
6236
6237////////////////////////////////////////////////////////////////////////////////
6238/// Fill the matrix `xarr` and `yarr` for Contour Plot.
6239
6241 Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
6242 Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
6243{
6244
6245 Bool_t vert;
6246 Double_t tlen, tdif, elev, diff, pdif, xlen;
6247 Int_t n, i, icount;
6248
6249 if (x1 == x2) {
6250 vert = kTRUE;
6251 tlen = y2 - y1;
6252 } else {
6253 vert = kFALSE;
6254 tlen = x2 - x1;
6255 }
6256
6257 n = icont1 +1;
6258 tdif = elev2 - elev1;
6259 i = 0;
6260 icount = 0;
6261 while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
6262 //elev = fH->GetContourLevel(n);
6263 elev = levels[n];
6264 diff = elev - elev1;
6265 pdif = diff/tdif;
6266 xlen = tlen*pdif;
6267 if (vert) {
6268 if (Hoption.Logx)
6269 xarr[i] = TMath::Log10(x1);
6270 else
6271 xarr[i] = x1;
6272 if (Hoption.Logy)
6273 yarr[i] = TMath::Log10(y1 + xlen);
6274 else
6275 yarr[i] = y1 + xlen;
6276 } else {
6277 if (Hoption.Logx)
6278 xarr[i] = TMath::Log10(x1 + xlen);
6279 else
6280 xarr[i] = x1 + xlen;
6281 if (Hoption.Logy)
6282 yarr[i] = TMath::Log10(y1);
6283 else
6284 yarr[i] = y1;
6285 }
6286 itarr[i] = n;
6287 icount++;
6288 i +=2;
6289 n++;
6290 }
6291 return icount;
6292}
6293
6294////////////////////////////////////////////////////////////////////////////////
6295/// [Draw 1D histograms error bars.](\ref HP09)
6296
6298{
6299
6300 // On iOS, we do not highlight histogram, if it's not picked at the moment
6301 // (but part of histogram (axis or pavestat) was picked, that's why this code
6302 // is called at all. This conditional statement never executes on non-iOS platform.
6303 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
6304
6305 const Int_t kBASEMARKER=8;
6306 Double_t xp, yp, ex1, ex2, ey1, ey2;
6307 Double_t delta;
6308 Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbasex, sbasey;
6309 Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
6311 Double_t logxmin = 0;
6312 Double_t logymin = 0;
6313 Double_t offset = 0.;
6314 Double_t width = 0.;
6315 Int_t i, k, npoints, first, last, fixbin;
6316 Int_t if1 = 0;
6317 Int_t if2 = 0;
6318 Int_t drawmarker, errormarker;
6319 Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
6320 static Float_t cxx[30] = {1.0,1.0,0.5,0.5,1.0,1.0,0.5,0.6,1.0,0.5,0.5,1.0,0.5,0.6,1.0,1.0,1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0};
6321 static Float_t cyy[30] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.5,0.5,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0,0.0,1.0,1.0,1.0,1.0,0.5,0.5,0.5,1.0};
6322
6323 std::vector<Double_t> xline, yline;
6324 option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
6325 if (Hoption.Error >= 40) {Hoption.Error -=40; option0 = 1;}
6326 if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
6327 if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
6328 if (Hoption.Error == 11) option1 = 1;
6329 if (Hoption.Error == 12) option2 = 1;
6330 if (Hoption.Error == 13) option3 = 1;
6331 if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
6332 if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
6333 if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
6334 if (option2+option3 == 0) optionE = 1;
6335 if (Hoption.Error == 0) optionE = 0;
6336 if (fXaxis->GetXbins()->fN) fixbin = 0;
6337 else fixbin = 1;
6338
6339 offset = fH->GetBarOffset();
6340 width = fH->GetBarWidth();
6341
6343 if (optionEX0) {
6344 xerror = 0;
6345 } else {
6346 xerror = gStyle->GetErrorX();
6347 }
6348 symbolsize = fH->GetMarkerSize();
6349 if (errormarker == 1) symbolsize = 0.01;
6350 sbasex = sbasey = symbolsize*kBASEMARKER;
6351 if (errormarker >= 20 && errormarker <= 49) {
6352 sbasex *= cxx[errormarker-20];
6353 sbasey *= cyy[errormarker-20];
6354 }
6355 // set the graphics attributes
6356
6357 fH->TAttLine::Modify();
6358 fH->TAttFill::Modify();
6359 fH->TAttMarker::Modify();
6360
6361 // set the first and last bin
6362
6363 Double_t factor = Hparam.factor;
6365 last = Hparam.xlast;
6366 npoints = last - first +1;
6367 xmin = gPad->GetUxmin();
6368 xmax = gPad->GetUxmax();
6369 ymin = gPad->GetUymin();
6370 ymax = gPad->GetUymax();
6371
6372
6373 if (option3) {
6374 xline.resize(2*npoints);
6375 yline.resize(2*npoints);
6376 if ((npoints > 0) && (xline.empty() || yline.empty())) {
6377 Error("PaintErrors", "too many points, out of memory");
6378 return;
6379 }
6380 if1 = 1;
6381 if2 = 2*npoints;
6382 }
6383
6384 // compute the offset of the error bars due to the symbol size
6385 s2x = gPad->PixeltoX(Int_t(0.5*sbasex)) - gPad->PixeltoX(0);
6386 s2y =-gPad->PixeltoY(Int_t(0.5*sbasey)) + gPad->PixeltoY(0);
6387
6388 // compute size of the lines at the end of the error bars
6389 Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6390 bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6391 bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6392
6393
6394 if (fixbin) {
6395 if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6396 else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6397 } else {
6398 delta = fH->GetBinWidth(first);
6399 xp = fH->GetBinLowEdge(first) + 0.5*delta;
6400 }
6401
6402 // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6403 if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6404 if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6405
6406 // ---------------------- Loop over the points---------------------
6407 for (k=first; k<=last; k++) {
6408
6409 // get the data
6410 // xp = X position of the current point
6411 // yp = Y position of the current point
6412 // ex1 = Low X error
6413 // ex2 = Up X error
6414 // ey1 = Low Y error
6415 // ey2 = Up Y error
6416 // (xi,yi) = Error bars coordinates
6417
6418 // apply offset on errors for bar histograms
6419 Double_t xminTmp = gPad->XtoPad(fXaxis->GetBinLowEdge(k));
6420 Double_t xmaxTmp = gPad->XtoPad(fXaxis->GetBinUpEdge(k));
6421 if (Hoption.Logx) {
6422 xminTmp = TMath::Power(10, xminTmp);
6423 xmaxTmp = TMath::Power(10, xmaxTmp);
6424 }
6425 Double_t w = (xmaxTmp-xminTmp)*width;
6426 xminTmp += offset*(xmaxTmp-xminTmp);
6427 xmaxTmp = xminTmp + w;
6428 xp = (xminTmp+xmaxTmp)/2.;
6429
6430 if (Hoption.Logx) {
6431 if (xp <= 0) goto L30;
6432 if (xp < logxmin) goto L30;
6433 if (xp > TMath::Power(10,xmax)) break;
6434 } else {
6435 if (xp < xmin) goto L30;
6436 if (xp > xmax) break;
6437 }
6438 yp = factor*fH->GetBinContent(k);
6439 if (optionI0 && yp==0) goto L30;
6440 if (fixbin) {
6441 ex1 = xerror*Hparam.xbinsize;
6442 } else {
6443 delta = fH->GetBinWidth(k);
6444 ex1 = xerror*delta;
6445 }
6446 if (fH->GetBinErrorOption() == TH1::kNormal) {
6447 ey1 = factor*fH->GetBinError(k);
6448 ey2 = ey1;
6449 } else {
6450 ey1 = factor*fH->GetBinErrorLow(k);
6451 ey2 = factor*fH->GetBinErrorUp(k);
6452 }
6453 ex2 = ex1;
6454
6455 xi4 = xp;
6456 xi3 = xp;
6457 xi2 = xp + ex2;
6458 xi1 = xp - ex1;
6459
6460 yi1 = yp;
6461 yi2 = yp;
6462 yi3 = yp - ey1;
6463 yi4 = yp + ey2;
6464
6465 // take the LOG if necessary
6466 if (Hoption.Logx) {
6467 xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6468 xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6469 xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6470 xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6471 }
6472 if (Hoption.Logy) {
6473 yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6474 yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6475 yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6476 yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6477 }
6478
6479 // test if error bars are not outside the limits
6480 // otherwise they are truncated
6481
6482 xi1 = TMath::Max(xi1,xmin);
6483 xi2 = TMath::Min(xi2,xmax);
6484 yi3 = TMath::Max(yi3,ymin);
6485 yi4 = TMath::Min(yi4,ymax);
6486
6487 // test if the marker is on the frame limits. If "Yes", the
6488 // marker will not be drawn and the error bars will be readjusted.
6489
6490 drawmarker = kTRUE;
6491 if (!option0 && !option3) {
6492 if (Hoption.Logy && yp < logymin) goto L30;
6493 if (yi1 < ymin || yi1 > ymax) goto L30;
6494 if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6495 }
6496 if (!symbolsize || !errormarker) drawmarker = kFALSE;
6497
6498 // draw the error rectangles
6499 if (option2) {
6500 if (yi3 >= ymax) goto L30;
6501 if (yi4 <= ymin) goto L30;
6502 gPad->PaintBox(xi1,yi3,xi2,yi4);
6503 }
6504
6505 // keep points for fill area drawing
6506 if (option3) {
6507 xline[if1-1] = xi3;
6508 xline[if2-1] = xi3;
6509 yline[if1-1] = yi4;
6510 yline[if2-1] = yi3;
6511 if1++;
6512 if2--;
6513 }
6514
6515 // draw the error bars
6516 if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6517 if (optionE && drawmarker) {
6518 if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6519 if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6520 // don't duplicate the horizontal line
6521 if (Hoption.Hist != 2) {
6522 if (yi1<ymax && yi1>ymin) {
6523 if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6524 if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6525 }
6526 }
6527 }
6528 if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6529 if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6530 if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6531 // don't duplicate the horizontal line
6532 if (Hoption.Hist != 2) {
6533 if (yi1<ymax && yi1>ymin) {
6534 if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6535 if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6536 }
6537 }
6538 }
6539
6540 // draw line at the end of the error bars
6541
6542 if (option1 && drawmarker) {
6543
6544 if (yi3 < yi1-s2y && yi3 < ymax && yi3 > ymin) gPad->PaintLine(xi3 - bxsize, yi3 , xi3 + bxsize, yi3);
6545 if (yi4 > yi1+s2y && yi4 < ymax && yi4 > ymin) gPad->PaintLine(xi3 - bxsize, yi4 , xi3 + bxsize, yi4);
6546 if (yi1 <= ymax && yi1 >= ymin) {
6547 if (xi1 < xi3-s2x) gPad->PaintLine(xi1 , yi1 - bysize, xi1 , yi1 + bysize);
6548 if (xi2 > xi3+s2x) gPad->PaintLine(xi2 , yi1 - bysize, xi2 , yi1 + bysize);
6549 }
6550 }
6551
6552 // draw the marker
6553
6554 if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6555
6556L30:
6557 if (fixbin) xp += Hparam.xbinsize;
6558 else {
6559 if (k < last) {
6560 delta = fH->GetBinWidth(k+1);
6561 xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6562 }
6563 }
6564 } //end of for loop
6565
6566 // draw the filled area
6567
6568 if (option3) {
6569 TGraph graph;
6570 graph.SetLineStyle(fH->GetLineStyle());
6571 graph.SetLineColor(fH->GetLineColor());
6572 graph.SetLineWidth(fH->GetLineWidth());
6573 graph.SetFillStyle(fH->GetFillStyle());
6574 graph.SetFillColor(fH->GetFillColor());
6575 Int_t logx = gPad->GetLogx();
6576 Int_t logy = gPad->GetLogy();
6577 gPad->SetLogx(0);
6578 gPad->SetLogy(0);
6579
6580 // In some cases the number of points in the fill area is smaller than
6581 // 2*npoints. In such cases the array xline and yline must be arranged
6582 // before being plotted. The next loop does that.
6583 if (if2 > npoints) {
6584 for (i=1; i<if1; i++) {
6585 xline[if1-2+i] = xline[if2-1+i];
6586 yline[if1-2+i] = yline[if2-1+i];
6587 }
6588 npoints = if1-1;
6589 }
6590 if (option4) graph.PaintGraph(2*npoints,xline.data(),yline.data(),"FC");
6591 else graph.PaintGraph(2*npoints,xline.data(),yline.data(),"F");
6592 gPad->SetLogx(logx);
6593 gPad->SetLogy(logy);
6594 }
6595}
6596
6597////////////////////////////////////////////////////////////////////////////////
6598/// Draw 2D histograms errors.
6599
6601{
6602
6603 fH->TAttMarker::Modify();
6604 fH->TAttLine::Modify();
6605
6606 // Define the 3D view
6607 fXbuf[0] = Hparam.xmin;
6608 fYbuf[0] = Hparam.xmax;
6609 fXbuf[1] = Hparam.ymin;
6610 fYbuf[1] = Hparam.ymax;
6611 fXbuf[2] = Hparam.zmin;
6612 fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6613 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
6614 TView *view = gPad ? gPad->GetView() : nullptr;
6615 if (!view) {
6616 Error("Paint2DErrors", "no TView in current pad");
6617 return;
6618 }
6619 Double_t thedeg = 90 - gPad->GetTheta();
6620 Double_t phideg = -90 - gPad->GetPhi();
6621 Double_t psideg = view->GetPsi();
6622 Int_t irep;
6623 view->SetView(phideg, thedeg, psideg, irep);
6624
6625 // Set color/style for back box
6626 fLego->SetFillStyle(gPad->GetFrameFillStyle());
6627 fLego->SetFillColor(gPad->GetFrameFillColor());
6628 fLego->TAttFill::Modify();
6629 Int_t backcolor = gPad->GetFrameFillColor();
6630 if (Hoption.System != kCARTESIAN) backcolor = 0;
6631 view->PadRange(backcolor);
6632 fLego->SetFillStyle(fH->GetFillStyle());
6633 fLego->SetFillColor(fH->GetFillColor());
6634 fLego->TAttFill::Modify();
6635
6636 // Paint the Back Box if needed
6637 if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6638 fLego->InitMoveScreen(-1.1,1.1);
6639 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
6641 fLego->BackBox(90);
6642 }
6643
6644 // Paint the Errors
6645 Double_t x, ex, x1, x2;
6646 Double_t y, ey, y1, y2;
6647 Double_t z, ez1, ez2, z1, z2;
6648 Double_t temp1[3],temp2[3];
6649 Double_t xyerror;
6650 if (Hoption.Error == 110) {
6651 xyerror = 0;
6652 } else {
6653 xyerror = gStyle->GetErrorX();
6654 }
6655
6656 Double_t xk, xstep, yk, ystep;
6657 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6658 y = fYaxis->GetBinCenter(j);
6659 ey = fYaxis->GetBinWidth(j)*xyerror;
6660 y1 = y-ey;
6661 y2 = y+ey;
6662 if (Hoption.Logy) {
6663 if (y > 0) y = TMath::Log10(y);
6664 else continue;
6665 if (y1 > 0) y1 = TMath::Log10(y1);
6666 else y1 = Hparam.ymin;
6667 if (y2 > 0) y2 = TMath::Log10(y2);
6668 else y2 = Hparam.ymin;
6669 }
6670 yk = fYaxis->GetBinLowEdge(j);
6671 ystep = fYaxis->GetBinWidth(j);
6672 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6673 xk = fXaxis->GetBinLowEdge(i);
6674 xstep = fXaxis->GetBinWidth(i);
6675 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6676 Int_t bin = fH->GetBin(i,j);
6677 x = fXaxis->GetBinCenter(i);
6678 ex = fXaxis->GetBinWidth(i)*xyerror;
6679 x1 = x-ex;
6680 x2 = x+ex;
6681 if (Hoption.Logx) {
6682 if (x > 0) x = TMath::Log10(x);
6683 else continue;
6684 if (x1 > 0) x1 = TMath::Log10(x1);
6685 else x1 = Hparam.xmin;
6686 if (x2 > 0) x2 = TMath::Log10(x2);
6687 else x2 = Hparam.xmin;
6688 }
6689 z = fH->GetBinContent(bin);
6690 if (fH->GetBinErrorOption() == TH1::kNormal) {
6691 ez1 = fH->GetBinError(bin);
6692 ez2 = ez1;
6693 }
6694 else {
6695 ez1 = fH->GetBinErrorLow(bin);
6696 ez2 = fH->GetBinErrorUp(bin);
6697 }
6698 z1 = z - ez1;
6699 z2 = z + ez2;
6700 if (Hoption.Logz) {
6701 if (z > 0) z = TMath::Log10(z);
6702 else z = Hparam.zmin;
6703 if (z1 > 0) z1 = TMath::Log10(z1);
6704 else z1 = Hparam.zmin;
6705 if (z2 > 0) z2 = TMath::Log10(z2);
6706 else z2 = Hparam.zmin;
6707
6708 }
6709 if (z <= Hparam.zmin) continue;
6710 if (z > Hparam.zmax) z = Hparam.zmax;
6711
6712 temp1[0] = x1;
6713 temp1[1] = y;
6714 temp1[2] = z;
6715 temp2[0] = x2;
6716 temp2[1] = y;
6717 temp2[2] = z;
6718 gPad->PaintLine3D(temp1, temp2);
6719 temp1[0] = x;
6720 temp1[1] = y1;
6721 temp1[2] = z;
6722 temp2[0] = x;
6723 temp2[1] = y2;
6724 temp2[2] = z;
6725 gPad->PaintLine3D(temp1, temp2);
6726 temp1[0] = x;
6727 temp1[1] = y;
6728 temp1[2] = z1;
6729 temp2[0] = x;
6730 temp2[1] = y;
6731 temp2[2] = z2;
6732 gPad->PaintLine3D(temp1, temp2);
6733 temp1[0] = x;
6734 temp1[1] = y;
6735 temp1[2] = z;
6736 view->WCtoNDC(temp1, &temp2[0]);
6737 gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6738 }
6739 }
6740
6741 // Paint the Front Box if needed
6742 if (Hoption.FrontBox) {
6743 fLego->InitMoveScreen(-1.1,1.1);
6745 fLego->FrontBox(90);
6746 }
6747
6748 // Paint the Axis if needed
6749 if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6750 TGaxis axis;
6751 PaintLegoAxis(&axis, 90);
6752 }
6753
6754 fLego.reset();
6755}
6756
6757////////////////////////////////////////////////////////////////////////////////
6758/// Calculate range and clear pad (canvas).
6759
6761{
6762
6763 if (Hoption.Same) return;
6764
6766
6767 if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6768 Hoption.Contour == 14 || Hoption.Error >= 100) {
6769 TObject *frame = gPad->FindObject("TFrame");
6770 if (frame) gPad->GetListOfPrimitives()->Remove(frame);
6771 return;
6772 }
6773
6774 //The next statement is always executed on non-iOS platform,
6775 //on iOS depends on pad mode.
6776 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6777 gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6778}
6779
6780////////////////////////////////////////////////////////////////////////////////
6781/// [Paint functions associated to an histogram.](\ref HP28")
6782
6784{
6785 auto lnk = fFunctions->FirstLink();
6786
6787 while (lnk) {
6788 auto obj = lnk->GetObject();
6789 TVirtualPad::TContext ctxt(true);
6790 if (obj->InheritsFrom(TF2::Class())) {
6791 if (!obj->TestBit(TF2::kNotDraw)) {
6792 if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6793 TF2 *f2 = (TF2*)obj;
6794 f2->SetMinimum(fH->GetMinimum());
6795 f2->SetMaximum(fH->GetMaximum());
6796 f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6797 f2->Paint("surf same");
6798 } else {
6799 obj->Paint("cont3 same");
6800 }
6801 }
6802 } else if (obj->InheritsFrom(TF1::Class())) {
6803 if (!obj->TestBit(TF1::kNotDraw)) obj->Paint("lsame");
6804 } else {
6805 //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6806 gPad->PushSelectableObject(obj);
6807
6808 //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6809 //and picked object.
6810 if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6811 obj->Paint(lnk->GetOption());
6812 }
6813 lnk = lnk->Next();
6814 }
6815}
6816
6817////////////////////////////////////////////////////////////////////////////////
6818/// [Control routine to draw 1D histograms](\ref HP01b)
6819
6821{
6822
6823 //On iOS: do not highlight hist, if part of it was selected.
6824 //Never executes on non-iOS platform.
6825 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6826 return;
6827
6828 static char chopth[17];
6829
6830 Int_t htype, oldhtype;
6831 Int_t i, j, first, last, nbins, fixbin;
6832 Double_t c1, yb;
6833 yb = 0;
6834
6835 strlcpy(chopth, " ",17);
6836
6839 Double_t baroffset = fH->GetBarOffset();
6840 Double_t barwidth = fH->GetBarWidth();
6841 Double_t baroffsetsave = gStyle->GetBarOffset();
6842 Double_t barwidthsave = gStyle->GetBarWidth();
6843 gStyle->SetBarOffset(baroffset);
6844 gStyle->SetBarWidth(barwidth);
6845
6846 // Create "LIFE" structure to keep current histogram status
6847
6849 last = Hparam.xlast;
6850 nbins = last - first + 1;
6851
6852 std::vector<Double_t> keepx, keepy;
6853 if (fXaxis->GetXbins()->fN) fixbin = 0;
6854 else fixbin = 1;
6855 if (fixbin) keepx.resize(2);
6856 else keepx.resize(nbins+1);
6857 keepy.resize(nbins);
6858 Double_t logymin = 0;
6859 if (Hoption.Logy) logymin = TMath::Power(10,ymin);
6860
6861 // Loop on histogram bins
6862
6863 for (j=first; j<=last;j++) {
6865 if (TMath::Abs(ymax-ymin) > 0) {
6866 if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
6867 else yb = c1;
6868 }
6869 if (!Hoption.Line) {
6870 yb = TMath::Max(yb, ymin);
6871 yb = TMath::Min(yb, ymax);
6872 }
6873 keepy[j-first] = yb;
6874 }
6875
6876 // Draw histogram according to value of FillStyle and FillColor
6877
6878 if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6879 else {
6880 for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6881 keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6882 }
6883
6884 // Prepare Fill area (systematic with option "Bar").
6885
6886 oldhtype = fH->GetFillStyle();
6887 htype = oldhtype;
6888 if (Hoption.Bar) {
6889 if (htype == 0 || htype == 1000) htype = 1001;
6890 }
6891
6892 Width_t lw = (Width_t)fH->GetLineWidth();
6893
6894 // Code option for GrapHist
6895
6896 if (Hoption.Line) chopth[0] = 'L';
6897 if (Hoption.Star) chopth[1] = '*';
6898 if (Hoption.Mark) chopth[2] = 'P';
6899 if (Hoption.Mark == 10) chopth[3] = '0';
6901 if (Hoption.Curve) chopth[3] = 'C';
6902 if (Hoption.Hist > 0) chopth[4] = 'H';
6903 else if (Hoption.Bar) chopth[5] = 'B';
6904 if (Hoption.Logy) chopth[6] = '1';
6905 if (fH->GetFillColor() && htype) {
6906 if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6907 chopth[7] = 'F';
6908 }
6909 }
6910 }
6911 if (!fixbin && strlen(chopth)) {
6912 chopth[8] = 'N';
6913 }
6914
6915 if (Hoption.Fill == 2) chopth[13] = '2';
6916
6917 // Option LOGX
6918
6919 if (Hoption.Logx) {
6920 chopth[9] = 'G';
6921 chopth[10] = 'X';
6922 if (fixbin) {
6923 keepx[0] = TMath::Power(10,keepx[0]);
6924 keepx[1] = TMath::Power(10,keepx[1]);
6925 }
6926 }
6927
6928 if (Hoption.Off) {
6929 chopth[11] = ']';
6930 chopth[12] = '[';
6931 }
6932
6933 // Draw the histogram
6934
6935 TGraph graph;
6936 graph.SetLineWidth(lw);
6937 graph.SetLineStyle(fH->GetLineStyle());
6938 graph.SetLineColor(fH->GetLineColor());
6939 graph.SetFillStyle(htype);
6940 graph.SetFillColor(fH->GetFillColor());
6941 graph.SetMarkerStyle(fH->GetMarkerStyle());
6942 graph.SetMarkerSize(fH->GetMarkerSize());
6943 graph.SetMarkerColor(fH->GetMarkerColor());
6944 if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
6945
6946 graph.PaintGrapHist(nbins, keepx.data(), keepy.data() ,chopth);
6947
6948 gStyle->SetBarOffset(baroffsetsave);
6949 gStyle->SetBarWidth(barwidthsave);
6950
6951 htype=oldhtype;
6952}
6953
6954////////////////////////////////////////////////////////////////////////////////
6955/// [Control function to draw a 3D histograms.](\ref HP01d)
6956
6958{
6959
6960 TString cmd;
6961 TString opt = option;
6962 opt.ToLower();
6963 Int_t irep;
6964
6965 if (fCurrentF3) {
6966 PaintTF3();
6967 return;
6968 } else if (Hoption.Box || Hoption.Lego) {
6969 if (Hoption.Box == 11 || Hoption.Lego == 11) {
6970 PaintH3Box(1);
6971 } else if (Hoption.Box == 12 || Hoption.Lego == 12) {
6972 PaintH3Box(2);
6973 } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
6974 PaintH3Box(3);
6975 } else {
6977 }
6978 return;
6979 } else if (strstr(opt,"iso")) {
6980 PaintH3Iso();
6981 return;
6982 } else if (strstr(opt,"tf3")) {
6983 PaintTF3();
6984 return;
6985 } else {
6986 cmd.Form("TPolyMarker3D::PaintH3((TH1 *)0x%zx,\"%s\");",(size_t)fH,option);
6987 }
6988
6989 if (strstr(opt,"fb")) Hoption.FrontBox = 0;
6990 if (strstr(opt,"bb")) Hoption.BackBox = 0;
6991
6992 TView *view = gPad ? gPad->GetView() : nullptr;
6993 if (!view) return;
6994 Double_t thedeg = 90 - gPad->GetTheta();
6995 Double_t phideg = -90 - gPad->GetPhi();
6996 Double_t psideg = view->GetPsi();
6997 view->SetView(phideg, thedeg, psideg, irep);
6998
6999 // Paint the data
7000 gROOT->ProcessLine(cmd.Data());
7001
7002 if (Hoption.Same) return;
7003
7004 // Draw axis
7005 view->SetOutlineToCube();
7006 TSeqCollection *ol = view->GetOutline();
7007 if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
7009
7010 if (!Hoption.Axis && !Hoption.Same) {
7011 TGaxis axis;
7012 PaintLegoAxis(&axis, 90);
7013 }
7014
7015 // Draw palette. In case of 4D plot with TTree::Draw() the palette should
7016 // be painted with the option colz.
7017 if (fH->GetDrawOption() && strstr(opt,"colz")) {
7018 Int_t ndiv = fH->GetContour();
7019 if (ndiv == 0 ) {
7020 ndiv = gStyle->GetNumberContours();
7021 fH->SetContour(ndiv);
7022 }
7023 PaintPalette();
7024 }
7025
7026 // Draw title
7027 PaintTitle();
7028
7029 //Draw stats and fit results
7030 TF1 *fit = nullptr;
7031 TIter next(fFunctions);
7032 while (auto obj = next()) {
7033 if (obj->InheritsFrom(TF1::Class())) {
7034 fit = (TF1*)obj;
7035 break;
7036 }
7037 }
7038 if ((Hoption.Same%10) != 1) {
7039 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
7041 }
7042 }
7043
7044}
7045
7046////////////////////////////////////////////////////////////////////////////////
7047/// Compute histogram parameters used by the drawing routines.
7048
7050{
7051
7052 if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
7053
7054 Int_t i;
7055 static const char *where = "PaintInit";
7056 Double_t yMARGIN = gStyle->GetHistTopMargin();
7057 Int_t maximum = 0;
7058 Int_t minimum = 0;
7059 if (fH->GetMaximumStored() != -1111) maximum = 1;
7060 if (fH->GetMinimumStored() != -1111) minimum = 1;
7061
7062 // Compute X axis parameters
7063
7064 Int_t last = fXaxis->GetLast();
7068 Hparam.xlast = last;
7072
7073 // if log scale in X, replace xmin,max by the log
7074 if (Hoption.Logx) {
7075 if (Hparam.xmax<=0) {
7076 Error(where, "cannot set X axis to log scale");
7077 return 0;
7078 }
7079 if (Hparam.xlowedge <=0 ) {
7080 if (Hoption.Same) {
7081 TH1* h1 = nullptr;
7082 TObject *obj;
7083 TIter next(gPad->GetListOfPrimitives());
7084 while ((obj = (TObject *)next())) {
7085 if (obj->InheritsFrom(TH1::Class())) { h1 = (TH1*)(obj) ; break; }
7086 if (obj->InheritsFrom(THStack::Class())) { h1 = ((THStack*)(obj))->GetHistogram() ; break; }
7087 if (obj->InheritsFrom(TGraph::Class())) { h1 = ((TGraph*)(obj))->GetHistogram() ; break; }
7088 if (obj->InheritsFrom(TMultiGraph::Class())) { h1 = ((TMultiGraph*)(obj))->GetHistogram(); break; }
7089 if (obj->InheritsFrom(TGraph2D::Class())) { h1 = ((TGraph2D*)(obj))->GetHistogram(); break; }
7090 if (obj->InheritsFrom(TF1::Class())) { h1 = ((TF1*)(obj))->GetHistogram(); break; }
7091 }
7092 if (h1) {
7094 } else {
7095 Error(where, "undefined user's coordinates. Cannot use option SAME");
7096 return 0;
7097 }
7098 } else {
7099 for (i=first; i<=last; i++) {
7100 Double_t binLow = fXaxis->GetBinLowEdge(i);
7101 if (binLow>0) {
7102 Hparam.xlowedge = binLow;
7103 break;
7104 }
7105 if (binLow == 0 && fH->GetBinContent(i) !=0) {
7106 Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
7107 break;
7108 }
7109 }
7110 if (Hparam.xlowedge<=0) {
7111 Error(where, "cannot set X axis to log scale");
7112 return 0;
7113 }
7114 }
7116 }
7121 if (Hparam.xlast > last) Hparam.xlast = last;
7123 }
7124
7125 // Compute Y axis parameters
7126 Double_t bigp = TMath::Power(10,32);
7127 Double_t ymax = -bigp;
7128 Double_t ymin = bigp;
7129 Double_t c1, e1;
7130 Double_t xv[1];
7131 Double_t fval;
7132 TObject *f;
7133 TF1 *f1;
7134 Double_t allchan = 0;
7135 Int_t nonNullErrors = 0;
7136 TIter next(fFunctions);
7137 for (i=first; i<=last;i++) {
7138 c1 = fH->GetBinContent(i);
7140 if (Hoption.Logy) {
7141 if (c1 > 0) ymin = TMath::Min(ymin,c1);
7142 } else {
7144 }
7145 if (Hoption.Error) {
7147 e1 = fH->GetBinError(i);
7148 else
7149 e1 = fH->GetBinErrorUp(i);
7150 if (e1 > 0) nonNullErrors++;
7151 ymax = TMath::Max(ymax,c1+e1);
7153 e1 = fH->GetBinErrorLow(i);
7154
7155 if (Hoption.Logy) {
7156 if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
7157 } else {
7158 ymin = TMath::Min(ymin,c1-e1);
7159 }
7160 }
7161 if (Hoption.Func) {
7162 xv[0] = fXaxis->GetBinCenter(i);
7163 while ((f = (TObject*) next())) {
7164 if (f->IsA() == TF1::Class()) {
7165 f1 = (TF1*)f;
7166 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7167 fval = f1->Eval(xv[0],0,0);
7168 if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
7169 ymax = TMath::Max(ymax,fval);
7170 if (Hoption.Logy) {
7171 if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
7172 }
7173 }
7174 }
7175 next.Reset();
7176 }
7177 allchan += c1;
7178 }
7179 if (!nonNullErrors) {
7180 if (Hoption.Error) {
7181 if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
7182 Hoption.Error=0;
7183 }
7184 }
7185
7186
7187 // Take into account maximum , minimum
7188
7189 if (Hoption.Logy && ymin <= 0) {
7190 if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
7191 else ymin = 0.001*ymax;
7192 }
7193
7194 Double_t xm = ymin;
7195 if (maximum) ymax = fH->GetMaximumStored();
7196 if (minimum) xm = fH->GetMinimumStored();
7197 if (Hoption.Logy && xm < 0) {
7198 Error(where, "log scale requested with a negative argument (%f)", xm);
7199 return 0;
7200 } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
7201 ymin = 0.01;
7202 ymax = 10.;
7203 } else {
7204 ymin = xm;
7205 }
7206
7207 if (ymin >= ymax) {
7208 if (Hoption.Logy) {
7209 if (ymax > 0) ymin = 0.001*ymax;
7210 else {
7211 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
7212 return 0;
7213 }
7214 }
7215 else {
7216 if (ymin > 0) {
7217 ymin = 0;
7218 ymax *= 2;
7219 } else if (ymin < 0) {
7220 ymax = 0;
7221 ymin *= 2;
7222 } else {
7223 ymin = 0;
7224 ymax = 1;
7225 }
7226 }
7227 }
7228
7229 // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
7230 if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
7231 ymin = ymin*(1-1E-14);
7232 ymax = ymax*(1+1E-14);
7233 }
7234
7235 // take into account normalization factor
7236 Hparam.allchan = allchan;
7237 Double_t factor = allchan;
7238 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7239 if (allchan) factor /= allchan;
7240 if (factor == 0) factor = 1;
7241 Hparam.factor = factor;
7242 ymax = factor*ymax;
7243 ymin = factor*ymin;
7244 //just in case the norm factor is negative
7245 // this may happen with a positive norm factor and a negative integral !
7246 if (ymax < ymin) {
7247 Double_t temp = ymax;
7248 ymax = ymin;
7249 ymin = temp;
7250 }
7251
7252 // For log scales, histogram coordinates are LOG10(ymin) and
7253 // LOG10(ymax). Final adjustment (if not option "Same"
7254 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7255 // Maximum and Minimum are not defined.
7256 if (Hoption.Logy) {
7257 if (ymin <=0 || ymax <=0) {
7258 Error(where, "Cannot set Y axis to log scale");
7259 return 0;
7260 }
7262 if (!minimum) ymin += TMath::Log10(0.5);
7264 if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
7265 if (!Hoption.Same) {
7266 Hparam.ymin = ymin;
7267 Hparam.ymax = ymax;
7268 }
7269 return 1;
7270 }
7271
7272 // final adjustment of ymin for linear scale.
7273 // if minimum is not set , then ymin is set to zero if >0
7274 // or to ymin - margin if <0.
7275 if (!minimum) {
7276 if (Hoption.MinimumZero) {
7277 if (ymin >= 0) ymin = 0;
7278 else ymin -= yMARGIN*(ymax-ymin);
7279 } else {
7280 Double_t dymin = yMARGIN*(ymax-ymin);
7281 if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
7282 else ymin -= dymin;
7283 }
7284 }
7285
7286 // final adjustment of YMAXI for linear scale (if not option "Same"):
7287 // decrease histogram height to MAX% of allowed height if HMAXIM
7288 // has not been called.
7289 if (!maximum) {
7290 ymax += yMARGIN*(ymax-ymin);
7291 }
7292
7293 Hparam.ymin = ymin;
7294 Hparam.ymax = ymax;
7295 return 1;
7296}
7297
7298////////////////////////////////////////////////////////////////////////////////
7299/// Compute histogram parameters used by the drawing routines for a rotated pad.
7300
7302{
7303
7304 static const char *where = "PaintInitH";
7305 Double_t yMARGIN = gStyle->GetHistTopMargin();
7306 Int_t maximum = 0;
7307 Int_t minimum = 0;
7308 if (fH->GetMaximumStored() != -1111) maximum = 1;
7309 if (fH->GetMinimumStored() != -1111) minimum = 1;
7310
7311 // Compute X axis parameters
7312
7313 Int_t last = fXaxis->GetLast();
7317 Hparam.xlast = last;
7321
7322 // if log scale in Y, replace ymin,max by the log
7323 if (Hoption.Logy) {
7324 if (Hparam.xlowedge <=0 ) {
7327 }
7328 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
7329 Error(where, "cannot set Y axis to log scale");
7330 return 0;
7331 }
7336 if (Hparam.xlast > last) Hparam.xlast = last;
7337 }
7338
7339 // Compute Y axis parameters
7340 Double_t bigp = TMath::Power(10,32);
7341 Double_t xmax = -bigp;
7342 Double_t xmin = bigp;
7343 Double_t c1, e1;
7344 Double_t xv[1];
7345 Double_t fval;
7346 Int_t i;
7347 TObject *f;
7348 TF1 *f1;
7349 Double_t allchan = 0;
7350 TIter next(fFunctions);
7351 for (i=first; i<=last;i++) {
7352 c1 = fH->GetBinContent(i);
7355 if (Hoption.Error) {
7356 e1 = fH->GetBinError(i);
7357 xmax = TMath::Max(xmax,c1+e1);
7358 xmin = TMath::Min(xmin,c1-e1);
7359 }
7360 if (Hoption.Func) {
7361 xv[0] = fXaxis->GetBinCenter(i);
7362 while ((f = (TObject*) next())) {
7363 if (f->IsA() == TF1::Class()) {
7364 f1 = (TF1*)f;
7365 if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
7366 fval = f1->Eval(xv[0],0,0);
7367 xmax = TMath::Max(xmax,fval);
7368 if (Hoption.Logy) {
7369 if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
7370 }
7371 }
7372 }
7373 next.Reset();
7374 }
7375 allchan += c1;
7376 }
7377
7378 // Take into account maximum , minimum
7379
7380 if (Hoption.Logx && xmin <= 0) {
7381 if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
7382 else xmin = 0.001*xmax;
7383 }
7384 Double_t xm = xmin;
7385 if (maximum) xmax = fH->GetMaximumStored();
7386 if (minimum) xm = fH->GetMinimumStored();
7387 if (Hoption.Logx && xm <= 0) {
7388 Error(where, "log scale requested with zero or negative argument (%f)", xm);
7389 return 0;
7390 }
7391 else xmin = xm;
7392 if (xmin >= xmax) {
7393 if (Hoption.Logx) {
7394 if (xmax > 0) xmin = 0.001*xmax;
7395 else {
7396 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
7397 return 0;
7398 }
7399 }
7400 else {
7401 if (xmin > 0) {
7402 xmin = 0;
7403 xmax *= 2;
7404 } else if (xmin < 0) {
7405 xmax = 0;
7406 xmin *= 2;
7407 } else {
7408 xmin = -1;
7409 xmax = 1;
7410 }
7411 }
7412 }
7413
7414 // take into account normalization factor
7415 Hparam.allchan = allchan;
7416 Double_t factor = allchan;
7417 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7418 if (allchan) factor /= allchan;
7419 if (factor == 0) factor = 1;
7420 Hparam.factor = factor;
7421 xmax = factor*xmax;
7422 xmin = factor*xmin;
7423
7424 // For log scales, histogram coordinates are LOG10(ymin) and
7425 // LOG10(ymax). Final adjustment (if not option "Same"
7426 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7427 // Maximum and Minimum are not defined.
7428 if (Hoption.Logx) {
7429 if (xmin <=0 || xmax <=0) {
7430 Error(where, "Cannot set Y axis to log scale");
7431 return 0;
7432 }
7434 if (!minimum) xmin += TMath::Log10(0.5);
7436 if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7437 if (!Hoption.Same) {
7438 Hparam.xmin = xmin;
7439 Hparam.xmax = xmax;
7440 }
7441 return 1;
7442 }
7443
7444 // final adjustment of ymin for linear scale.
7445 // if minimum is not set , then ymin is set to zero if >0
7446 // or to ymin - margin if <0.
7447 if (!minimum) {
7448 if (xmin >= 0) xmin = 0;
7449 else xmin -= yMARGIN*(xmax-xmin);
7450 }
7451
7452 // final adjustment of YMAXI for linear scale (if not option "Same"):
7453 // decrease histogram height to MAX% of allowed height if HMAXIM
7454 // has not been called.
7455 if (!maximum) {
7456 xmax += yMARGIN*(xmax-xmin);
7457 }
7458 Hparam.xmin = xmin;
7459 Hparam.xmax = xmax;
7460 return 1;
7461}
7462
7463////////////////////////////////////////////////////////////////////////////////
7464/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7465
7467{
7468 // Predefined box structure
7469 Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7470 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7471 Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7472 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7473
7474 // Define dimensions of world space
7475 TAxis *xaxis = fH->GetXaxis();
7476 TAxis *yaxis = fH->GetYaxis();
7477 TAxis *zaxis = fH->GetZaxis();
7478
7479 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7480 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7481 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7482 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7483 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7484 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7485
7486 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7487
7488 // Set view
7489 TView *view = gPad ? gPad->GetView() : nullptr;
7490 if (!view) {
7491 Error("PaintH3", "no TView in current pad");
7492 return;
7493 }
7494 Double_t thedeg = 90 - gPad->GetTheta();
7495 Double_t phideg = -90 - gPad->GetPhi();
7496 Double_t psideg = view->GetPsi();
7497 Int_t irep;
7498 view->SetView(phideg, thedeg, psideg, irep);
7499
7500 Int_t backcolor = gPad->GetFrameFillColor();
7501 view->PadRange(backcolor);
7502
7503 // Draw back surfaces of frame box
7504 fLego->InitMoveScreen(-1.1,1.1);
7505 if (Hoption.BackBox) {
7506 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7508 fLego->BackBox(90);
7509 }
7510
7512
7513 // Define order of drawing
7514 Double_t *tnorm = view->GetTnorm();
7515 if (!tnorm) return;
7516 Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7517 Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7518 Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7519 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7520 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7521 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7522 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7523 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7524 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7525
7526 // Set graphic attributes (colour, style, etc.)
7527 Style_t fillsav = fH->GetFillStyle();
7528 Style_t colsav = fH->GetFillColor();
7529 Style_t coldark = TColor::GetColorDark(colsav);
7530 Style_t colbright = TColor::GetColorBright(colsav);
7531
7532 fH->SetFillStyle(1001);
7533 fH->TAttFill::Modify();
7534 fH->TAttLine::Modify();
7535 Int_t ncolors = gStyle->GetNumberOfColors();
7536 Int_t theColor;
7537
7538 // Create bin boxes and draw
7542
7543 Double_t pmin[3], pmax[3], sxyz[8][3];
7544 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7545 pmin[0] = xaxis->GetBinLowEdge(ix);
7546 pmax[0] = xaxis->GetBinUpEdge(ix);
7547 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7548 pmin[1] = yaxis->GetBinLowEdge(iy);
7549 pmax[1] = yaxis->GetBinUpEdge(iy);
7550 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7551 pmin[2] = zaxis->GetBinLowEdge(iz);
7552 pmax[2] = zaxis->GetBinUpEdge(iz);
7553 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7554 Bool_t neg = kFALSE;
7555 Int_t n = 5;
7556 if (w<0) {
7557 w = -w;
7558 neg = kTRUE;
7559 }
7560 if (w < wmin) continue;
7561 if (w > wmax) w = wmax;
7562 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7563 if (scale == 0) continue;
7564 for (Int_t i=0; i<3; ++i) {
7565 Double_t c = (pmax[i] + pmin[i])*0.5;
7566 Double_t d = (pmax[i] - pmin[i])*scale;
7567 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7568 sxyz[k][i] = wxyz[k][i]*d + c;
7569 }
7570 }
7571 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7572 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7573 }
7574 Double_t x[8], y[8]; // draw bin box faces
7575 for (Int_t k=0; k<6; ++k) {
7576 for (Int_t i=0; i<4; ++i) {
7577 Int_t iv = iface[k][i];
7578 x[i] = sxyz[iv][0];
7579 y[i] = sxyz[iv][1];
7580 }
7581 x[4] = x[0] ; y[4] = y[0];
7582 if (neg) {
7583 x[5] = x[2] ; y[5] = y[2];
7584 x[6] = x[3] ; y[6] = y[3];
7585 x[7] = x[1] ; y[7] = y[1];
7586 n = 8;
7587 } else {
7588 n = 5;
7589 }
7590 Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7591 if (z <= 0.) continue;
7592 if (iopt == 2) {
7593 theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7595 } else {
7596 if (k == 3 || k == 5) {
7597 fH->SetFillColor(coldark);
7598 } else if (k == 0 || k == 1) {
7599 fH->SetFillColor(colbright);
7600 } else {
7601 fH->SetFillColor(colsav);
7602 }
7603 }
7604 fH->TAttFill::Modify();
7605 gPad->PaintFillArea(4, x, y);
7606 if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7607 }
7608 }
7609 }
7610 }
7611
7612 // Draw front surfaces of frame box
7613 if (Hoption.FrontBox) fLego->FrontBox(90);
7614
7615 // Draw axis and title
7616 if (!Hoption.Axis && !Hoption.Same) {
7617 TGaxis axis;
7618 PaintLegoAxis(&axis, 90);
7619 }
7620 PaintTitle();
7621
7622 // Draw palette. if needed.
7623 if (Hoption.Zscale) {
7624 Int_t ndiv = fH->GetContour();
7625 if (ndiv == 0 ) {
7626 ndiv = gStyle->GetNumberContours();
7627 fH->SetContour(ndiv);
7628 }
7629 PaintPalette();
7630 }
7631
7632 fLego.reset();
7633
7634 fH->SetFillStyle(fillsav);
7635 fH->SetFillColor(colsav);
7636 fH->TAttFill::Modify();
7637}
7638
7639////////////////////////////////////////////////////////////////////////////////
7640/// [Control function to draw a 3D histogram with boxes.](\ref HP25)
7641
7643{
7644 // Predefined box structure
7645 Double_t wxyz[8][3] = {
7646 {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7647 {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7648 };
7649 Int_t iface[6][4] = {
7650 {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7651 {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7652 };
7653 Double_t normal[6][3] = {
7654 {0,0,-1}, {0,0,1}, // Z-, Z+
7655 {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7656 };
7657
7658 // Define dimensions of world space
7659 TAxis *xaxis = fH->GetXaxis();
7660 TAxis *yaxis = fH->GetYaxis();
7661 TAxis *zaxis = fH->GetZaxis();
7662
7663 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7664 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7665 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7666 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7667 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7668 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7669
7670 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7671
7672 // Set view
7673 TView *view = gPad ? gPad->GetView() : nullptr;
7674 if (!view) {
7675 Error("PaintH3", "no TView in current pad");
7676 return;
7677 }
7678 Double_t thedeg = 90 - gPad->GetTheta();
7679 Double_t phideg = -90 - gPad->GetPhi();
7680 Double_t psideg = view->GetPsi();
7681 Int_t irep;
7682 view->SetView(phideg, thedeg, psideg, irep);
7683
7684 Int_t backcolor = gPad->GetFrameFillColor();
7685 view->PadRange(backcolor);
7686
7687 // Draw front surfaces of frame box
7688 if (Hoption.FrontBox) {
7689 fLego->InitMoveScreen(-1.1,1.1);
7691 }
7692
7693 // Initialize hidden line removal algorithm "raster screen"
7694 fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7695
7696 // Define order of drawing
7697 Double_t *tnorm = view->GetTnorm();
7698 if (!tnorm) return;
7699 Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7700 Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7701 Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7702 Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7703 Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7704 Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7705 Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7706 Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7707 Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7708
7709 // Set line attributes (colour, style, etc.)
7710 fH->TAttLine::Modify();
7711
7712 // Create bin boxes and draw
7713 const Int_t NTMAX = 100;
7714 Double_t tt[NTMAX][2];
7718 Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7719 for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7720 pmin[0] = xaxis->GetBinLowEdge(ix);
7721 pmax[0] = xaxis->GetBinUpEdge(ix);
7722 for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7723 pmin[1] = yaxis->GetBinLowEdge(iy);
7724 pmax[1] = yaxis->GetBinUpEdge(iy);
7725 for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7726 pmin[2] = zaxis->GetBinLowEdge(iz);
7727 pmax[2] = zaxis->GetBinUpEdge(iz);
7728 Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7729 Bool_t neg = kFALSE;
7730 if (w<0) {
7731 w = -w;
7732 neg = kTRUE;
7733 }
7734 if (w < wmin) continue;
7735 if (w > wmax) w = wmax;
7736 Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7737 if (scale == 0) continue;
7738 for (Int_t i=0; i<3; ++i) {
7739 Double_t c = (pmax[i] + pmin[i])*0.5;
7740 Double_t d = (pmax[i] - pmin[i])*scale;
7741 for (Int_t k=0; k<8; ++k) { // set bin box vertices
7742 sxyz[k][i] = wxyz[k][i]*d + c;
7743 }
7744 }
7745 for (Int_t k=0; k<8; ++k) { // transform to normalized space
7746 view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7747 }
7748 for (Int_t k=0; k<6; ++k) { // draw box faces
7749 Double_t zn;
7750 view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7751 if (zn <= 0) continue;
7752 for (Int_t i=0; i<4; ++i) {
7753 Int_t ip = iface[k][i];
7754 pp[i][0] = sxyz[ip][0];
7755 pp[i][1] = sxyz[ip][1];
7756 }
7757 for (Int_t i=0; i<4; ++i) {
7758 Int_t i1 = i;
7759 Int_t i2 = (i == 3) ? 0 : i + 1;
7760 Int_t nt;
7761 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7762 Double_t xdel = pp[i2][0] - pp[i1][0];
7763 Double_t ydel = pp[i2][1] - pp[i1][1];
7764 Double_t x[2], y[2];
7765 for (Int_t it = 0; it < nt; ++it) {
7766 x[0] = pp[i1][0] + xdel*tt[it][0];
7767 y[0] = pp[i1][1] + ydel*tt[it][0];
7768 x[1] = pp[i1][0] + xdel*tt[it][1];
7769 y[1] = pp[i1][1] + ydel*tt[it][1];
7770 gPad->PaintPolyLine(2, x, y);
7771 }
7772 }
7773 if (neg) {
7774 Int_t i1 = 0;
7775 Int_t i2 = 2;
7776 Int_t nt;
7777 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7778 Double_t xdel = pp[i2][0] - pp[i1][0];
7779 Double_t ydel = pp[i2][1] - pp[i1][1];
7780 Double_t x[2], y[2];
7781 for (Int_t it = 0; it < nt; ++it) {
7782 x[0] = pp[i1][0] + xdel*tt[it][0];
7783 y[0] = pp[i1][1] + ydel*tt[it][0];
7784 x[1] = pp[i1][0] + xdel*tt[it][1];
7785 y[1] = pp[i1][1] + ydel*tt[it][1];
7786 gPad->PaintPolyLine(2, x, y);
7787 }
7788 i1 = 1;
7789 i2 = 3;
7790 fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7791 xdel = pp[i2][0] - pp[i1][0];
7792 ydel = pp[i2][1] - pp[i1][1];
7793 for (Int_t it = 0; it < nt; ++it) {
7794 x[0] = pp[i1][0] + xdel*tt[it][0];
7795 y[0] = pp[i1][1] + ydel*tt[it][0];
7796 x[1] = pp[i1][0] + xdel*tt[it][1];
7797 y[1] = pp[i1][1] + ydel*tt[it][1];
7798 gPad->PaintPolyLine(2, x, y);
7799 }
7800 }
7801 fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7802 }
7803 }
7804 }
7805 }
7806
7807 // Draw frame box
7808 if (Hoption.BackBox) {
7809 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7811 fLego->BackBox(90);
7812 }
7813
7814 if (Hoption.FrontBox) fLego->FrontBox(90);
7815
7816 // Draw axis and title
7817 if (!Hoption.Axis && !Hoption.Same) {
7818 TGaxis axis;
7819 PaintLegoAxis(&axis, 90);
7820 }
7821 PaintTitle();
7822
7823 fLego.reset();
7824}
7825
7826////////////////////////////////////////////////////////////////////////////////
7827/// [Control function to draw a 3D histogram with Iso Surfaces.](\ref HP25)
7828
7830{
7831
7832 const Double_t ydiff = 1;
7833 const Double_t yligh1 = 10;
7834 const Double_t qa = 0.15;
7835 const Double_t qd = 0.15;
7836 const Double_t qs = 0.8;
7837 Double_t fmin, fmax;
7838 Int_t i, irep;
7839 Int_t nbcol = 28;
7840 Int_t icol1 = 201;
7841 Int_t ic1 = icol1;
7842 Int_t ic2 = ic1+nbcol;
7843 Int_t ic3 = ic2+nbcol;
7844
7845 TAxis *xaxis = fH->GetXaxis();
7846 TAxis *yaxis = fH->GetYaxis();
7847 TAxis *zaxis = fH->GetZaxis();
7848
7849 Int_t nx = fH->GetNbinsX();
7850 Int_t ny = fH->GetNbinsY();
7851 Int_t nz = fH->GetNbinsZ();
7852
7853 std::vector<Double_t> x(nx);
7854 std::vector<Double_t> y(ny);
7855 std::vector<Double_t> z(nz);
7856
7857 for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7858 for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7859 for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7860
7861 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7862 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7863 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7864 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7865 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7866 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7867
7868 Double_t s[3];
7869 s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7870 s[1] = 0.5*s[0];
7871 s[2] = 1.5*s[0];
7872
7873 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
7874
7875 TView *view = gPad ? gPad->GetView() : nullptr;
7876 if (!view) {
7877 Error("PaintH3Iso", "no TView in current pad");
7878 return;
7879 }
7880 Double_t thedeg = 90 - gPad->GetTheta();
7881 Double_t phideg = -90 - gPad->GetPhi();
7882 Double_t psideg = view->GetPsi();
7883 view->SetView(phideg, thedeg, psideg, irep);
7884
7885 Int_t backcolor = gPad->GetFrameFillColor();
7886 if (Hoption.System != kCARTESIAN) backcolor = 0;
7887 view->PadRange(backcolor);
7888
7889 Double_t dcol = 0.5/Double_t(nbcol);
7890 TColor *colref = gROOT->GetColor(fH->GetFillColor());
7891 if (!colref) {
7892 return;
7893 }
7894 Float_t r, g, b, hue, light, satur;
7895 colref->GetRGB(r,g,b);
7896 TColor::RGBtoHLS(r,g,b,hue,light,satur);
7897 TColor *acol;
7898 for (Int_t col=0;col<nbcol;col++) {
7899 acol = gROOT->GetColor(col+icol1);
7900 TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7901 if (acol) acol->SetRGB(r, g, b);
7902 }
7903
7904 fLego->InitMoveScreen(-1.1,1.1);
7905
7906 if (Hoption.BackBox) {
7907 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
7909 fLego->BackBox(90);
7910 }
7911
7912 fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7913 fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7914 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7915 fmin = ydiff*qa;
7916 fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7917 fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7918
7919 fLego->IsoSurface(1, s, nx, ny, nz, x.data(), y.data(), z.data(), "BF");
7920
7921 if (Hoption.FrontBox) {
7922 fLego->InitMoveScreen(-1.1,1.1);
7924 fLego->FrontBox(90);
7925 }
7926 if (!Hoption.Axis && !Hoption.Same) {
7927 TGaxis axis;
7928 PaintLegoAxis(&axis, 90);
7929 }
7930
7931 PaintTitle();
7932
7933 fLego.reset();
7934}
7935
7936////////////////////////////////////////////////////////////////////////////////
7937/// [Control function to draw a 2D histogram as a lego plot.](\ref HP17)
7938
7940{
7941
7942 Int_t raster = 1;
7943 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
7944 Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
7945 Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
7946 Double_t zmin = Hparam.zmin;
7947 Double_t zmax = Hparam.zmax;
7948 Double_t xlab1 = Hparam.xmin;
7949 Double_t xlab2 = Hparam.xmax;
7950 Double_t ylab1 = Hparam.ymin;
7951 Double_t ylab2 = Hparam.ymax;
7952 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
7953 Double_t deltaz = TMath::Abs(zmin);
7954 if (deltaz == 0) deltaz = 1;
7955 if (zmin >= zmax) {
7956 zmin -= 0.5*deltaz;
7957 zmax += 0.5*deltaz;
7958 }
7959 Double_t z1c = zmin;
7960 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
7961
7962 // Compute the lego limits and instantiate a lego object
7963 fXbuf[0] = -1;
7964 fYbuf[0] = 1;
7965 fXbuf[1] = -1;
7966 fYbuf[1] = 1;
7967 if (Hoption.System == kPOLAR) {
7968 fXbuf[2] = z1c;
7969 fYbuf[2] = z2c;
7970 } else if (Hoption.System == kCYLINDRICAL) {
7971 if (Hoption.Logy) {
7972 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
7973 else fXbuf[2] = 0;
7974 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
7975 else fYbuf[2] = 0;
7976 } else {
7977 fXbuf[2] = ylab1;
7978 fYbuf[2] = ylab2;
7979 }
7980 z1c = 0; z2c = 1;
7981 } else if (Hoption.System == kSPHERICAL) {
7982 fXbuf[2] = -1;
7983 fYbuf[2] = 1;
7984 z1c = 0; z2c = 1;
7985 } else if (Hoption.System == kRAPIDITY) {
7986 fXbuf[2] = -1/TMath::Tan(dangle);
7987 fYbuf[2] = 1/TMath::Tan(dangle);
7988 } else {
7989 fXbuf[0] = xlab1;
7990 fYbuf[0] = xlab2;
7991 fXbuf[1] = ylab1;
7992 fYbuf[1] = ylab2;
7993 fXbuf[2] = z1c;
7994 fYbuf[2] = z2c;
7995 raster = 0;
7996 }
7997
7998 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
7999
8000 Int_t nids = -1;
8001 TH1 * hid = NULL;
8002 Color_t colormain = -1, colordark = -1;
8003 Bool_t drawShadowsInLego1 = kTRUE;
8004
8005 // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
8006 if (Hoption.Lego == 13) {
8007 Hoption.Lego = 11;
8008 fLego->SetMesh(0);
8009 }
8010 // LEGO4 is like LEGO1 except no shadows are drawn.
8011 if (Hoption.Lego == 14) {
8012 Hoption.Lego = 11;
8013 drawShadowsInLego1 = kFALSE;
8014 }
8015
8016 // Initialize the levels on the Z axis
8017 Int_t ndiv = fH->GetContour();
8018 if (ndiv == 0 ) {
8019 ndiv = gStyle->GetNumberContours();
8020 fH->SetContour(ndiv);
8021 }
8022 Int_t ndivz = TMath::Abs(ndiv);
8023 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
8024
8025 // Initialize colors
8026 if (!fStack) {
8027 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
8028 } else {
8029 for (Int_t id=0;id<=fStack->GetSize();id++) {
8030 hid = (TH1*)fStack->At((id==0)?id:id-1);
8031 fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
8032 }
8033 }
8034
8035 if (Hoption.Lego == 11) {
8036 nids = 1;
8037 if (fStack) nids = fStack->GetSize();
8038 hid = fH;
8039 for (Int_t id=0;id<=nids;id++) {
8040 if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
8041 colormain = hid->GetFillColor();
8042 if (colormain == 1) colormain = 17; //avoid drawing with black
8043 if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
8044 else colordark = colormain;
8045 fLego->SetColorMain(colormain,id);
8046 fLego->SetColorDark(colordark,id);
8047 if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
8048 if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
8049 }
8050 }
8051
8052 // Now ready to draw the lego plot
8053 Int_t irep = 0;
8054
8055 TView *view = gPad ? gPad->GetView() : nullptr;
8056 if (!view) {
8057 Error("PaintLego", "no TView in current pad");
8058 return;
8059 }
8060
8061 Double_t thedeg = 90 - gPad->GetTheta();
8062 Double_t phideg = -90 - gPad->GetPhi();
8063 Double_t psideg = view->GetPsi();
8064 view->SetView(phideg, thedeg, psideg, irep);
8065
8066 fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
8067 fLego->SetFillStyle(fH->GetFillStyle());
8068
8069 // Set color/style for back box
8070 fLego->SetFillStyle(gPad->GetFrameFillStyle());
8071 fLego->SetFillColor(gPad->GetFrameFillColor());
8072 fLego->TAttFill::Modify();
8073
8074 Int_t backcolor = gPad->GetFrameFillColor();
8075 if (Hoption.System != kCARTESIAN) backcolor = 0;
8076 view->PadRange(backcolor);
8077
8078 fLego->SetFillStyle(fH->GetFillStyle());
8079 fLego->SetFillColor(fH->GetFillColor());
8080 fLego->TAttFill::Modify();
8081
8082 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
8083
8084 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8085 else fLego->InitMoveScreen(-1.1,1.1);
8086
8087 if (Hoption.Lego == 19) {
8089 if (Hoption.BackBox) fLego->BackBox(90);
8090 if (Hoption.FrontBox) fLego->FrontBox(90);
8091 if (!Hoption.Axis) { TGaxis axis; PaintLegoAxis(&axis, 90); }
8092 return;
8093 }
8094
8095 if (Hoption.Lego == 11 || Hoption.Lego == 12) {
8098 fLego->BackBox(90);
8099 }
8100 }
8101
8102 if (Hoption.Lego == 12) DefineColorLevels(ndivz);
8103
8104 fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
8106 if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
8107 if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8108 if (Hoption.System == kPOLAR) {
8109 if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
8110 if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
8111 if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
8112 } else if (Hoption.System == kCYLINDRICAL) {
8113 if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
8114 if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
8115 if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
8116 } else if (Hoption.System == kSPHERICAL) {
8117 if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
8118 if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
8119 if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
8120 } else if (Hoption.System == kRAPIDITY) {
8121 if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
8122 if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
8123 if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
8124 } else {
8125 if (Hoption.Lego == 1) {
8127 fLego->LegoCartesian(90,nx,ny,"FB");}
8128 if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
8129 if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
8130 }
8131
8132 if (Hoption.Lego == 1 || Hoption.Lego == 11) {
8135 fLego->BackBox(90);
8136 }
8137 }
8138 if (Hoption.System == kCARTESIAN) {
8139 fLego->InitMoveScreen(-1.1,1.1);
8141 if (Hoption.FrontBox) fLego->FrontBox(90);
8142 }
8143 if (!Hoption.Axis && !Hoption.Same) {
8144 TGaxis axis;
8145 PaintLegoAxis(&axis, 90);
8146 }
8148 fLego.reset();
8149}
8150
8151////////////////////////////////////////////////////////////////////////////////
8152/// Draw the axis for legos and surface plots.
8153
8155{
8156
8157 static Double_t epsil = 0.001;
8158
8159 Double_t cosa, sina;
8160 Double_t bmin, bmax;
8161 Double_t r[24] /* was [3][8] */;
8162 Int_t ndivx, ndivy, ndivz, i;
8163 Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
8164 static char chopax[8], chopay[8], chopaz[8];
8165 Int_t ix1, ix2, iy1, iy2, iz1, iz2;
8166 Double_t rad;
8167
8168 TView *view = gPad ? gPad->GetView() : nullptr;
8169 if (!view) {
8170 Error("PaintLegoAxis", "no TView in current pad");
8171 return;
8172 }
8173
8174 // In polar coordinates, draw a short line going from the external circle
8175 // corresponding to r = 1 up to r = 1.1
8176 if (Hoption.System == kPOLAR) {
8177 r[0] = 1;
8178 r[1] = 0;
8179 r[2] = 0;
8180 view->WCtoNDC(r, x1);
8181 r[0] = 1.1;
8182 r[1] = 0;
8183 r[2] = 0;
8184 view->WCtoNDC(r, x2);
8185 gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
8186 return;
8187 }
8188
8189 if (Hoption.System != kCARTESIAN) return;
8190
8191 rad = TMath::ATan(1.) * 4. /180.;
8192 cosa = TMath::Cos(ang*rad);
8193 sina = TMath::Sin(ang*rad);
8194
8195 view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
8196 for (i = 1; i <= 8; ++i) {
8197 r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
8198 r[i*3 - 2] = av[i*3 - 2]*sina;
8199 r[i*3 - 1] = av[i*3 - 1];
8200 }
8201
8202 view->WCtoNDC(&r[ix1*3 - 3], x1);
8203 view->WCtoNDC(&r[ix2*3 - 3], x2);
8204 view->WCtoNDC(&r[iy1*3 - 3], y1);
8205 view->WCtoNDC(&r[iy2*3 - 3], y2);
8206 view->WCtoNDC(&r[iz1*3 - 3], z1);
8207 view->WCtoNDC(&r[iz2*3 - 3], z2);
8208
8209 view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
8210
8211 Double_t *rmin = view->GetRmin();
8212 Double_t *rmax = view->GetRmax();
8213 if (!rmin || !rmax) return;
8214
8215 // Initialize the axis options
8216 if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
8217 else strlcpy(chopax, "SDH=-",8);
8218 if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
8219 else strlcpy(chopay, "SDH=-",8);
8220 if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
8221 else strlcpy(chopaz, "SDH=-",8);
8222
8223 // Option LOG is required ?
8224 if (Hoption.Logx) strlcat(chopax,"G",8);
8225 if (Hoption.Logy) strlcat(chopay,"G",8);
8226 if (Hoption.Logz) strlcat(chopaz,"G",8);
8227
8228 // Initialize the number of divisions. If the
8229 // number of divisions is negative, option 'N' is required.
8230 ndivx = fXaxis->GetNdivisions();
8231 ndivy = fYaxis->GetNdivisions();
8232 ndivz = fZaxis->GetNdivisions();
8233 if (ndivx < 0) {
8234 ndivx = TMath::Abs(ndivx);
8235 strlcat(chopax, "N",8);
8236 }
8237 if (ndivy < 0) {
8238 ndivy = TMath::Abs(ndivy);
8239 strlcat(chopay, "N",8);
8240 }
8241 if (ndivz < 0) {
8242 ndivz = TMath::Abs(ndivz);
8243 strlcat(chopaz, "N",8);
8244 }
8245
8246 // Set Axis attributes.
8247 // The variable SCALE rescales the VSIZ
8248 // in order to have the same label size for all angles.
8249
8250 axis->SetLineWidth(1);
8251
8252 // X axis drawing
8253 if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
8256 if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
8257 bmin = TMath::Power(10, rmin[0]);
8258 bmax = TMath::Power(10, rmax[0]);
8259 } else {
8260 bmin = rmin[0];
8261 bmax = rmax[0];
8262 }
8263 // Option time display is required ?
8264 if (fXaxis->GetTimeDisplay()) {
8265 strlcat(chopax,"t",8);
8266 if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
8267 axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
8268 } else {
8270 }
8271 }
8272 axis->SetOption(chopax);
8273 axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
8274 }
8275
8276 // Y axis drawing
8277 if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
8280 if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
8281
8282 if (fH->GetDimension() < 2) {
8283 strlcpy(chopay, "V=+UN",8);
8284 ndivy = 0;
8285 }
8286 if (TMath::Abs(y1[0] - y2[0]) < epsil) {
8287 y2[0] = y1[0];
8288 }
8289 if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
8290 bmin = TMath::Power(10, rmin[1]);
8291 bmax = TMath::Power(10, rmax[1]);
8292 } else {
8293 bmin = rmin[1];
8294 bmax = rmax[1];
8295 }
8296 // Option time display is required ?
8297 if (fYaxis->GetTimeDisplay()) {
8298 strlcat(chopay,"t",8);
8299 if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
8300 axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
8301 } else {
8303 }
8304 }
8305 axis->SetOption(chopay);
8306 axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
8307 }
8308
8309 // Z axis drawing
8310 if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
8312 if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
8313 bmin = TMath::Power(10, rmin[2]);
8314 bmax = TMath::Power(10, rmax[2]);
8315 } else {
8316 bmin = rmin[2];
8317 bmax = rmax[2];
8318 }
8319 // Option time display is required ?
8320 if (fZaxis->GetTimeDisplay()) {
8321 strlcat(chopaz,"t",8);
8322 if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
8323 axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
8324 } else {
8326 }
8327 }
8328 axis->SetOption(chopaz);
8329 axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
8330 }
8331
8332 //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
8333}
8334
8335////////////////////////////////////////////////////////////////////////////////
8336/// [Paint the color palette on the right side of the pad.](\ref HP22)
8337
8339{
8340 TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
8341 TView *view = gPad ? gPad->GetView() : nullptr;
8342 if (palette) {
8343 if (view) {
8344 if (!palette->TestBit(TPaletteAxis::kHasView)) {
8345 fFunctions->Remove(palette);
8346 delete palette; palette = nullptr;
8347 }
8348 } else {
8349 if (palette->TestBit(TPaletteAxis::kHasView)) {
8350 fFunctions->Remove(palette);
8351 delete palette; palette = nullptr;
8352 }
8353 }
8354 // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
8355 if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
8356 }
8357
8358 if (!palette) {
8359 Double_t xup = gPad->GetUxmax();
8360 Double_t x2 = gPad->PadtoX(gPad->GetX2());
8361 Double_t ymin = gPad->PadtoY(gPad->GetUymin());
8362 Double_t ymax = gPad->PadtoY(gPad->GetUymax());
8363 Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
8364 Double_t xmin = gPad->PadtoX(xup +0.1*xr);
8365 Double_t xmax = gPad->PadtoX(xup + xr);
8366 if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
8367 palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
8368 fFunctions->AddFirst(palette);
8369 palette->Paint();
8370 }
8371}
8372
8373////////////////////////////////////////////////////////////////////////////////
8374/// [Control function to draw a 2D histogram as a scatter plot.](\ref HP11)
8375
8377{
8378
8379 fH->TAttMarker::Modify();
8380
8381 Int_t k, marker;
8382 Double_t dz, z, xk,xstep, yk, ystep;
8383 Double_t scale = 1;
8384 Bool_t ltest = kFALSE;
8385 Double_t zmax = fH->GetMaximum();
8386 Double_t zmin = fH->GetMinimum();
8387 if (zmin == 0 && zmax == 0) return;
8388 if (zmin == zmax) {
8389 zmax += 0.1*TMath::Abs(zmax);
8390 zmin -= 0.1*TMath::Abs(zmin);
8391 }
8393 if (Hoption.Logz) {
8394 if (zmin > 0) zmin = TMath::Log10(zmin);
8395 else zmin = 0;
8396 if (zmax > 0) zmax = TMath::Log10(zmax);
8397 else zmax = 0;
8398 if (zmin == 0 && zmax == 0) return;
8399 dz = zmax - zmin;
8400 scale = 100/dz;
8401 if (ncells > 10000) scale /= 5;
8402 ltest = kTRUE;
8403 } else {
8404 dz = zmax - zmin;
8405 if (dz >= kNMAX || zmax < 1) {
8406 scale = (kNMAX-1)/dz;
8407 if (ncells > 10000) scale /= 5;
8408 ltest = kTRUE;
8409 }
8410 }
8411 if (fH->GetMinimumStored() == -1111) {
8412 Double_t yMARGIN = gStyle->GetHistTopMargin();
8413 if (Hoption.MinimumZero) {
8414 if (zmin >= 0) zmin = 0;
8415 else zmin -= yMARGIN*(zmax-zmin);
8416 } else {
8417 Double_t dzmin = yMARGIN*(zmax-zmin);
8418 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8419 else zmin -= dzmin;
8420 }
8421 }
8422
8423 TString opt = option;
8424 opt.ToLower();
8425 if (opt.Contains("scat=")) {
8426 char optscat[100];
8427 strlcpy(optscat,opt.Data(),100);
8428 char *oscat = strstr(optscat,"scat=");
8429 char *blank = strstr(oscat," "); if (blank) *blank = 0;
8430 sscanf(oscat+5,"%lg",&scale);
8431 }
8432 // use an independent instance of a random generator
8433 // instead of gRandom to avoid conflicts and
8434 // to get same random numbers when drawing the same histogram
8435 TRandom2 random;
8436 marker=0;
8437 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8438 yk = fYaxis->GetBinLowEdge(j);
8439 ystep = fYaxis->GetBinWidth(j);
8440 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8441 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8442 xk = fXaxis->GetBinLowEdge(i);
8443 xstep = fXaxis->GetBinWidth(i);
8444 if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8445 z = fH->GetBinContent(bin);
8446 if (z < zmin) z = zmin;
8447 if (z > zmax) z = zmax;
8448 if (Hoption.Logz) {
8449 if (z > 0) z = TMath::Log10(z) - zmin;
8450 } else {
8451 z -= zmin;
8452 }
8453 if (z <= 0) continue;
8454 k = Int_t(z*scale);
8455 if (ltest) k++;
8456 if (k > 0) {
8457 for (Int_t loop=0; loop<k; loop++) {
8458 if (k+marker >= kNMAX) {
8459 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8460 marker=0;
8461 }
8462 fXbuf[marker] = (random.Rndm()*xstep) + xk;
8463 fYbuf[marker] = (random.Rndm()*ystep) + yk;
8464 if (Hoption.Logx) {
8465 if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8466 else break;
8467 }
8468 if (Hoption.Logy) {
8469 if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8470 else break;
8471 }
8472 if (fXbuf[marker] < gPad->GetUxmin()) break;
8473 if (fYbuf[marker] < gPad->GetUymin()) break;
8474 if (fXbuf[marker] > gPad->GetUxmax()) break;
8475 if (fYbuf[marker] > gPad->GetUymax()) break;
8476 marker++;
8477 }
8478 }
8479 }
8480 }
8481 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
8482
8484}
8485
8486////////////////////////////////////////////////////////////////////////////////
8487/// Static function to paint special objects like vectors and matrices.
8488/// This function is called via `gROOT->ProcessLine` to paint these objects
8489/// without having a direct dependency of the graphics or histogramming
8490/// system.
8491
8493{
8494
8495 if (!obj) return;
8498
8499 if (obj->InheritsFrom(TMatrixFBase::Class())) {
8500 // case TMatrixF
8501 TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8502 R__TMatrixFBase->SetBit(kCanDelete);
8503 R__TMatrixFBase->Draw(option);
8504
8505 } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8506 // case TMatrixD
8507 TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8508 R__TMatrixDBase->SetBit(kCanDelete);
8509 R__TMatrixDBase->Draw(option);
8510
8511 } else if (obj->InheritsFrom(TVectorF::Class())) {
8512 //case TVectorF
8513 TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8514 R__TVectorF->SetBit(kCanDelete);
8515 R__TVectorF->Draw(option);
8516
8517 } else if (obj->InheritsFrom(TVectorD::Class())) {
8518 //case TVectorD
8519 TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8520 R__TVectorD->SetBit(kCanDelete);
8521 R__TVectorD->Draw(option);
8522 }
8523
8524 TH1::AddDirectory(status);
8525}
8526
8527////////////////////////////////////////////////////////////////////////////////
8528/// [Draw the statistics box for 1D and profile histograms.](\ref HP07)
8529
8531{
8532 TString tt, tf;
8533 Int_t dofit;
8534 TPaveStats *stats = nullptr;
8535 TIter next(fFunctions);
8536 while (auto obj = next()) {
8537 if (obj->InheritsFrom(TPaveStats::Class())) {
8538 stats = (TPaveStats*)obj;
8539 break;
8540 }
8541 }
8542
8543 if (stats && dostat) {
8544 dofit = stats->GetOptFit();
8545 dostat = stats->GetOptStat();
8546 } else {
8547 dofit = gStyle->GetOptFit();
8548 }
8549 if (!dofit) fit = 0;
8550 if (dofit == 1) dofit = 111;
8551 if (dostat == 1) dostat = 1111;
8552 Int_t print_name = dostat%10;
8553 Int_t print_entries = (dostat/10)%10;
8554 Int_t print_mean = (dostat/100)%10;
8555 Int_t print_stddev = (dostat/1000)%10;
8556 Int_t print_under = (dostat/10000)%10;
8557 Int_t print_over = (dostat/100000)%10;
8558 Int_t print_integral= (dostat/1000000)%10;
8559 Int_t print_skew = (dostat/10000000)%10;
8560 Int_t print_kurt = (dostat/100000000)%10;
8561 Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8562 print_under + print_over + print_integral +
8563 print_skew + print_kurt;
8564 Int_t print_fval = dofit%10;
8565 Int_t print_ferrors = (dofit/10)%10;
8566 Int_t print_fchi2 = (dofit/100)%10;
8567 Int_t print_fprob = (dofit/1000)%10;
8568 Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8569 if (fit) {
8570 if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8571 else nlinesf += fit->GetNpar();
8572 }
8573 if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8574
8575 // Pavetext with statistics
8576 Bool_t done = kFALSE;
8577 if (!dostat && !fit) {
8578 if (stats) { fFunctions->Remove(stats); delete stats;}
8579 return;
8580 }
8581 Double_t statw = gStyle->GetStatW();
8582 if (fit) statw = 1.8*gStyle->GetStatW();
8583 Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8584 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8585 stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8586 }
8587 if (stats) {
8588 stats->Clear();
8589 done = kTRUE;
8590 } else {
8591 stats = new TPaveStats(
8592 gStyle->GetStatX()-statw,
8593 gStyle->GetStatY()-stath,
8594 gStyle->GetStatX(),
8595 gStyle->GetStatY(),"brNDC");
8596
8597 stats->SetParent(fH);
8598 stats->SetOptFit(dofit);
8599 stats->SetOptStat(dostat);
8600 stats->SetFillColor(gStyle->GetStatColor());
8601 stats->SetFillStyle(gStyle->GetStatStyle());
8603 stats->SetTextFont(gStyle->GetStatFont());
8604 if (gStyle->GetStatFont()%10 > 2)
8606 stats->SetFitFormat(gStyle->GetFitFormat());
8608 stats->SetName("stats");
8609
8611 stats->SetTextAlign(12);
8612 stats->SetBit(kCanDelete);
8613 stats->SetBit(kMustCleanup);
8614 }
8615 if (print_name) stats->AddText(fH->GetName());
8616 if (print_entries) {
8617 if (fH->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8618 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8619 stats->AddText(tt.Data());
8620 }
8621 if (print_mean) {
8622 if (print_mean == 1) {
8623 tf.Form("%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8624 tt.Form(tf.Data(),fH->GetMean(1));
8625 } else {
8626 tf.Form("%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8627 ,"%",stats->GetStatFormat());
8628 tt.Form(tf.Data(),fH->GetMean(1),fH->GetMeanError(1));
8629 }
8630 stats->AddText(tt.Data());
8632 if (print_mean == 1) {
8633 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8634 tt.Form(tf.Data(),fH->GetMean(2));
8635 } else {
8636 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8637 ,"%",stats->GetStatFormat());
8638 tt.Form(tf.Data(),fH->GetMean(2),fH->GetMeanError(2));
8639 }
8640 stats->AddText(tt.Data());
8641 }
8642 }
8643 if (print_stddev) {
8644 if (print_stddev == 1) {
8645 tf.Form("%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8646 tt.Form(tf.Data(),fH->GetStdDev(1));
8647 } else {
8648 tf.Form("%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8649 ,"%",stats->GetStatFormat());
8650 tt.Form(tf.Data(),fH->GetStdDev(1),fH->GetStdDevError(1));
8651 }
8652 stats->AddText(tt.Data());
8654 if (print_stddev == 1) {
8655 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8656 tt.Form(tf.Data(),fH->GetStdDev(2));
8657 } else {
8658 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8659 ,"%",stats->GetStatFormat());
8660 tt.Form(tf.Data(),fH->GetStdDev(2),fH->GetStdDevError(2));
8661 }
8662 stats->AddText(tt.Data());
8663 }
8664 }
8665 if (print_under) {
8666 tf.Form("%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8667 tt.Form(tf.Data(),fH->GetBinContent(0));
8668 stats->AddText(tt.Data());
8669 }
8670 if (print_over) {
8671 tf.Form("%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8672 tt.Form(tf.Data(),fH->GetBinContent(fXaxis->GetNbins()+1));
8673 stats->AddText(tt.Data());
8674 }
8675 if (print_integral) {
8676 if (print_integral == 1) {
8677 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8678 tt.Form(tf.Data(),fH->Integral());
8679 } else {
8680 tf.Form("%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8681 tt.Form(tf.Data(),fH->Integral("width"));
8682 }
8683 stats->AddText(tt.Data());
8684 }
8685 if (print_skew) {
8686 if (print_skew == 1) {
8687 tf.Form("%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8688 tt.Form(tf.Data(),fH->GetSkewness(1));
8689 } else {
8690 tf.Form("%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8691 ,"%",stats->GetStatFormat());
8692 tt.Form(tf.Data(),fH->GetSkewness(1),fH->GetSkewness(11));
8693 }
8694 stats->AddText(tt.Data());
8695 }
8696 if (print_kurt) {
8697 if (print_kurt == 1) {
8698 tf.Form("%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8699 tt.Form(tf.Data(),fH->GetKurtosis(1));
8700 } else {
8701 tf.Form("%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8702 ,"%",stats->GetStatFormat());
8703 tt.Form(tf.Data(),fH->GetKurtosis(1),fH->GetKurtosis(11));
8704 }
8705 stats->AddText(tt.Data());
8706 }
8707
8708 // Draw Fit parameters
8709 if (fit) {
8710 Int_t ndf = fit->GetNDF();
8711 tf.Form("#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8712 tt.Form(tf.Data(),(Float_t)fit->GetChisquare());
8713 if (print_fchi2) stats->AddText(tt.Data());
8714 if (print_fprob) {
8715 tf.Form("Prob = %s%s","%",stats->GetFitFormat());
8716 tt.Form(tf.Data(),(Float_t)TMath::Prob(fit->GetChisquare(),ndf));
8717 stats->AddText(tt.Data());
8718 }
8719 if (print_fval || print_ferrors) {
8720 Double_t parmin,parmax;
8721 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8722 fit->GetParLimits(ipar,parmin,parmax);
8723 if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8724 if (print_ferrors) {
8725 tf.Form("%-8s = %s%s #pm %s ", fit->GetParName(ipar), "%",stats->GetFitFormat(),
8726 GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8727 tt.Form(tf.Data(),(Float_t)fit->GetParameter(ipar)
8728 ,(Float_t)fit->GetParError(ipar));
8729 } else {
8730 tf.Form("%-8s = %s%s ",fit->GetParName(ipar), "%",stats->GetFitFormat());
8731 tt.Form(tf.Data(),(Float_t)fit->GetParameter(ipar));
8732 }
8733 stats->AddText(tt.Data());
8734 }
8735 }
8736 }
8737
8738 if (!done) fFunctions->Add(stats);
8739 stats->Paint();
8740}
8741
8742////////////////////////////////////////////////////////////////////////////////
8743/// [Draw the statistics box for 2D histograms.](\ref HP07)
8744
8746{
8747
8748 if (fH->GetDimension() != 2) return;
8749 TH2 *h2 = (TH2*)fH;
8750
8751 TString tt, tf;
8752 Int_t dofit;
8753 TPaveStats *stats = nullptr;
8754 TIter next(fFunctions);
8755 while (auto obj = next()) {
8756 if (obj->InheritsFrom(TPaveStats::Class())) {
8757 stats = (TPaveStats*)obj;
8758 break;
8759 }
8760 }
8761 if (stats && dostat) {
8762 dofit = stats->GetOptFit();
8763 dostat = stats->GetOptStat();
8764 } else {
8765 dofit = gStyle->GetOptFit();
8766 }
8767 if (dostat == 1) dostat = 1111;
8768 Int_t print_name = dostat%10;
8769 Int_t print_entries = (dostat/10)%10;
8770 Int_t print_mean = (dostat/100)%10;
8771 Int_t print_stddev = (dostat/1000)%10;
8772 Int_t print_under = (dostat/10000)%10;
8773 Int_t print_over = (dostat/100000)%10;
8774 Int_t print_integral= (dostat/1000000)%10;
8775 Int_t print_skew = (dostat/10000000)%10;
8776 Int_t print_kurt = (dostat/100000000)%10;
8777 Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8778 if (print_under || print_over) nlines += 3;
8779
8780 // Pavetext with statistics
8781 if (!gStyle->GetOptFit()) fit = 0;
8782 Bool_t done = kFALSE;
8783 if (!dostat && !fit) {
8784 if (stats) { fFunctions->Remove(stats); delete stats;}
8785 return;
8786 }
8787 Double_t statw = gStyle->GetStatW();
8788 if (fit) statw = 1.8*gStyle->GetStatW();
8789 Double_t stath = nlines*gStyle->GetStatFontSize();
8790 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8791 stath = 0.25*nlines*gStyle->GetStatH();
8792 }
8793 if (fit) stath += gStyle->GetStatH();
8794 if (stats) {
8795 stats->Clear();
8796 done = kTRUE;
8797 } else {
8798 stats = new TPaveStats(
8799 gStyle->GetStatX()-statw,
8800 gStyle->GetStatY()-stath,
8801 gStyle->GetStatX(),
8802 gStyle->GetStatY(),"brNDC");
8803
8804 stats->SetParent(fH);
8805 stats->SetOptFit(dofit);
8806 stats->SetOptStat(dostat);
8807 stats->SetFillColor(gStyle->GetStatColor());
8808 stats->SetFillStyle(gStyle->GetStatStyle());
8810 stats->SetName("stats");
8811
8813 stats->SetTextAlign(12);
8814 stats->SetTextFont(gStyle->GetStatFont());
8815 if (gStyle->GetStatFont()%10 > 2)
8817 stats->SetFitFormat(gStyle->GetFitFormat());
8819 stats->SetBit(kCanDelete);
8820 stats->SetBit(kMustCleanup);
8821 }
8822 if (print_name) stats->AddText(h2->GetName());
8823 if (print_entries) {
8824 if (h2->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8825 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8826 stats->AddText(tt.Data());
8827 }
8828 if (print_mean) {
8829 if (print_mean == 1) {
8830 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8831 tt.Form(tf.Data(),h2->GetMean(1));
8832 stats->AddText(tt.Data());
8833 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8834 tt.Form(tf.Data(),h2->GetMean(2));
8835 stats->AddText(tt.Data());
8836 } else {
8837 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8838 ,"%",stats->GetStatFormat());
8839 tt.Form(tf.Data(),h2->GetMean(1),h2->GetMeanError(1));
8840 stats->AddText(tt.Data());
8841 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8842 ,"%",stats->GetStatFormat());
8843 tt.Form(tf.Data(),h2->GetMean(2),h2->GetMeanError(2));
8844 stats->AddText(tt.Data());
8845 }
8846 }
8847 if (print_stddev) {
8848 if (print_stddev == 1) {
8849 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8850 tt.Form(tf.Data(),h2->GetStdDev(1));
8851 stats->AddText(tt.Data());
8852 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8853 tt.Form(tf.Data(),h2->GetStdDev(2));
8854 stats->AddText(tt.Data());
8855 } else {
8856 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8857 ,"%",stats->GetStatFormat());
8858 tt.Form(tf.Data(),h2->GetStdDev(1),h2->GetStdDevError(1));
8859 stats->AddText(tt.Data());
8860 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8861 ,"%",stats->GetStatFormat());
8862 tt.Form(tf.Data(),h2->GetStdDev(2),h2->GetStdDevError(2));
8863 stats->AddText(tt.Data());
8864 }
8865 }
8866 if (print_integral) {
8867 tf.Form("%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8868 tt.Form(tf.Data(),fH->Integral());
8869 stats->AddText(tt.Data());
8870 }
8871 if (print_skew) {
8872 if (print_skew == 1) {
8873 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8874 tt.Form(tf.Data(),h2->GetSkewness(1));
8875 stats->AddText(tt.Data());
8876 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8877 tt.Form(tf.Data(),h2->GetSkewness(2));
8878 stats->AddText(tt.Data());
8879 } else {
8880 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8881 ,"%",stats->GetStatFormat());
8882 tt.Form(tf.Data(),h2->GetSkewness(1),h2->GetSkewness(11));
8883 stats->AddText(tt.Data());
8884 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8885 ,"%",stats->GetStatFormat());
8886 tt.Form(tf.Data(),h2->GetSkewness(2),h2->GetSkewness(12));
8887 stats->AddText(tt.Data());
8888 }
8889 }
8890 if (print_kurt) {
8891 if (print_kurt == 1) {
8892 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8893 tt.Form(tf.Data(),h2->GetKurtosis(1));
8894 stats->AddText(tt.Data());
8895 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8896 tt.Form(tf.Data(),h2->GetKurtosis(2));
8897 stats->AddText(tt.Data());
8898 } else {
8899 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8900 ,"%",stats->GetStatFormat());
8901 tt.Form(tf.Data(),h2->GetKurtosis(1),h2->GetKurtosis(11));
8902 stats->AddText(tt.Data());
8903 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8904 ,"%",stats->GetStatFormat());
8905 tt.Form(tf.Data(),h2->GetKurtosis(2),h2->GetKurtosis(12));
8906 stats->AddText(tt.Data());
8907 }
8908 }
8909 if (print_under || print_over) {
8910 //get 3*3 under/overflows for 2d hist
8911 Double_t unov[9];
8912
8913 Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8914 Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8915 Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
8916 Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
8917 Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
8918 Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
8919
8920 unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
8921 unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
8922 unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
8923 unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
8924 unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
8925 unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
8926 unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
8927 unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
8928 unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
8929
8930 tt.Form("%g|%g|%g\n", unov[0], unov[1], unov[2]);
8931 stats->AddText(tt.Data());
8932 tt.Form("%g|%g|%g\n", unov[3], unov[4], unov[5]);
8933 stats->AddText(tt.Data());
8934 tt.Form("%g|%g|%g\n", unov[6], unov[7], unov[8]);
8935 stats->AddText(tt.Data());
8936 }
8937
8938 // Draw Fit parameters
8939 if (fit) {
8940 Int_t ndf = fit->GetNDF();
8941 tt.Form("#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
8942 stats->AddText(tt.Data());
8943 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8944 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
8945 ,(Float_t)fit->GetParameter(ipar)
8946 ,(Float_t)fit->GetParError(ipar));
8947 stats->AddText(tt.Data());
8948 }
8949 }
8950
8951 if (!done) fFunctions->Add(stats);
8952 stats->Paint();
8953}
8954
8955////////////////////////////////////////////////////////////////////////////////
8956/// [Draw the statistics box for 3D histograms.](\ref HP07)
8957
8959{
8960
8961 if (fH->GetDimension() != 3) return;
8962 TH3 *h3 = (TH3*)fH;
8963
8964 TString tt, tf;
8965 Int_t dofit;
8966 TPaveStats *stats = nullptr;
8967 TIter next(fFunctions);
8968 while (auto obj = next()) {
8969 if (obj->InheritsFrom(TPaveStats::Class())) {
8970 stats = (TPaveStats*)obj;
8971 break;
8972 }
8973 }
8974 if (stats && dostat) {
8975 dofit = stats->GetOptFit();
8976 dostat = stats->GetOptStat();
8977 } else {
8978 dofit = gStyle->GetOptFit();
8979 }
8980 if (dostat == 1) dostat = 1111;
8981 Int_t print_name = dostat%10;
8982 Int_t print_entries = (dostat/10)%10;
8983 Int_t print_mean = (dostat/100)%10;
8984 Int_t print_stddev = (dostat/1000)%10;
8985 Int_t print_under = (dostat/10000)%10;
8986 Int_t print_over = (dostat/100000)%10;
8987 Int_t print_integral= (dostat/1000000)%10;
8988 Int_t print_skew = (dostat/10000000)%10;
8989 Int_t print_kurt = (dostat/100000000)%10;
8990 Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
8991 if (print_under || print_over) nlines += 3;
8992
8993 // Pavetext with statistics
8994 if (!gStyle->GetOptFit()) fit = 0;
8995 Bool_t done = kFALSE;
8996 if (!dostat && !fit) {
8997 if (stats) { fFunctions->Remove(stats); delete stats;}
8998 return;
8999 }
9000 Double_t statw = gStyle->GetStatW();
9001 if (fit) statw = 1.8*gStyle->GetStatW();
9002 Double_t stath = nlines*gStyle->GetStatFontSize();
9003 if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
9004 stath = 0.25*nlines*gStyle->GetStatH();
9005 }
9006 if (fit) stath += gStyle->GetStatH();
9007 if (stats) {
9008 stats->Clear();
9009 done = kTRUE;
9010 } else {
9011 stats = new TPaveStats(
9012 gStyle->GetStatX()-statw,
9013 gStyle->GetStatY()-stath,
9014 gStyle->GetStatX(),
9015 gStyle->GetStatY(),"brNDC");
9016
9017 stats->SetParent(fH);
9018 stats->SetOptFit(dofit);
9019 stats->SetOptStat(dostat);
9020 stats->SetFillColor(gStyle->GetStatColor());
9021 stats->SetFillStyle(gStyle->GetStatStyle());
9023 stats->SetName("stats");
9024
9026 stats->SetTextAlign(12);
9027 stats->SetTextFont(gStyle->GetStatFont());
9028 stats->SetFitFormat(gStyle->GetFitFormat());
9030 stats->SetBit(kCanDelete);
9031 stats->SetBit(kMustCleanup);
9032 }
9033 if (print_name) stats->AddText(h3->GetName());
9034 if (print_entries) {
9035 if (h3->GetEntries() < 1e7) tt.Form("%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
9036 else tt.Form("%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
9037 stats->AddText(tt.Data());
9038 }
9039 if (print_mean) {
9040 if (print_mean == 1) {
9041 tf.Form("%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
9042 tt.Form(tf.Data(),h3->GetMean(1));
9043 stats->AddText(tt.Data());
9044 tf.Form("%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
9045 tt.Form(tf.Data(),h3->GetMean(2));
9046 stats->AddText(tt.Data());
9047 tf.Form("%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
9048 tt.Form(tf.Data(),h3->GetMean(3));
9049 stats->AddText(tt.Data());
9050 } else {
9051 tf.Form("%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
9052 ,"%",stats->GetStatFormat());
9053 tt.Form(tf.Data(),h3->GetMean(1),h3->GetMeanError(1));
9054 stats->AddText(tt.Data());
9055 tf.Form("%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
9056 ,"%",stats->GetStatFormat());
9057 tt.Form(tf.Data(),h3->GetMean(2),h3->GetMeanError(2));
9058 stats->AddText(tt.Data());
9059 tf.Form("%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
9060 ,"%",stats->GetStatFormat());
9061 tt.Form(tf.Data(),h3->GetMean(3),h3->GetMeanError(3));
9062 stats->AddText(tt.Data());
9063 }
9064 }
9065 if (print_stddev) {
9066 if (print_stddev == 1) {
9067 tf.Form("%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
9068 tt.Form(tf.Data(),h3->GetStdDev(1));
9069 stats->AddText(tt.Data());
9070 tf.Form("%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
9071 tt.Form(tf.Data(),h3->GetStdDev(2));
9072 stats->AddText(tt.Data());
9073 tf.Form("%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
9074 tt.Form(tf.Data(),h3->GetStdDev(3));
9075 stats->AddText(tt.Data());
9076 } else {
9077 tf.Form("%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
9078 ,"%",stats->GetStatFormat());
9079 tt.Form(tf.Data(),h3->GetStdDev(1),h3->GetStdDevError(1));
9080 stats->AddText(tt.Data());
9081 tf.Form("%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
9082 ,"%",stats->GetStatFormat());
9083 tt.Form(tf.Data(),h3->GetStdDev(2),h3->GetStdDevError(2));
9084 stats->AddText(tt.Data());
9085 tf.Form("%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
9086 ,"%",stats->GetStatFormat());
9087 tt.Form(tf.Data(),h3->GetStdDev(3),h3->GetStdDevError(3));
9088 stats->AddText(tt.Data());
9089 }
9090 }
9091 if (print_integral) {
9092 tt.Form("%s = %6.4g",gStringIntegral.Data(),h3->Integral());
9093 stats->AddText(tt.Data());
9094 }
9095 if (print_skew) {
9096 if (print_skew == 1) {
9097 tf.Form("%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
9098 tt.Form(tf.Data(),h3->GetSkewness(1));
9099 stats->AddText(tt.Data());
9100 tf.Form("%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
9101 tt.Form(tf.Data(),h3->GetSkewness(2));
9102 stats->AddText(tt.Data());
9103 tf.Form("%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
9104 tt.Form(tf.Data(),h3->GetSkewness(3));
9105 stats->AddText(tt.Data());
9106 } else {
9107 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
9108 ,"%",stats->GetStatFormat());
9109 tt.Form(tf.Data(),h3->GetSkewness(1),h3->GetSkewness(11));
9110 stats->AddText(tt.Data());
9111 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
9112 ,"%",stats->GetStatFormat());
9113 tt.Form(tf.Data(),h3->GetSkewness(2),h3->GetSkewness(12));
9114 stats->AddText(tt.Data());
9115 tf.Form("%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
9116 ,"%",stats->GetStatFormat());
9117 tt.Form(tf.Data(),h3->GetSkewness(3),h3->GetSkewness(13));
9118 stats->AddText(tt.Data());
9119 }
9120 }
9121 if (print_kurt) {
9122 if (print_kurt == 1) {
9123 tf.Form("%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
9124 tt.Form(tf.Data(),h3->GetKurtosis(1));
9125 stats->AddText(tt.Data());
9126 tf.Form("%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
9127 tt.Form(tf.Data(),h3->GetKurtosis(2));
9128 stats->AddText(tt.Data());
9129 tf.Form("%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
9130 tt.Form(tf.Data(),h3->GetKurtosis(3));
9131 stats->AddText(tt.Data());
9132 } else {
9133 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
9134 ,"%",stats->GetStatFormat());
9135 tt.Form(tf.Data(),h3->GetKurtosis(1),h3->GetKurtosis(11));
9136 stats->AddText(tt.Data());
9137 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
9138 ,"%",stats->GetStatFormat());
9139 tt.Form(tf.Data(),h3->GetKurtosis(2),h3->GetKurtosis(12));
9140 stats->AddText(tt.Data());
9141 tf.Form("%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
9142 ,"%",stats->GetStatFormat());
9143 tt.Form(tf.Data(),h3->GetKurtosis(3),h3->GetKurtosis(13));
9144 stats->AddText(tt.Data());
9145 }
9146 }
9147 if (print_under || print_over) {
9148 // no underflow - overflow printing for a 3D histogram
9149 // one would need a 3D table
9150 }
9151
9152 // Draw Fit parameters
9153 if (fit) {
9154 Int_t ndf = fit->GetNDF();
9155 tt.Form("#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
9156 stats->AddText(tt.Data());
9157 for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
9158 tt.Form("%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
9159 ,(Float_t)fit->GetParameter(ipar)
9160 ,(Float_t)fit->GetParError(ipar));
9161 stats->AddText(tt.Data());
9162 }
9163 }
9164
9165 if (!done) fFunctions->Add(stats);
9166 stats->Paint();
9167}
9168
9169////////////////////////////////////////////////////////////////////////////////
9170/// [Control function to draw a 2D histogram as a surface plot.](\ref HP18)
9171
9173{
9174
9175 const Double_t ydiff = 1;
9176 const Double_t yligh1 = 10;
9177 const Double_t qa = 0.15;
9178 const Double_t qd = 0.15;
9179 const Double_t qs = 0.8;
9180 Double_t fmin, fmax;
9181 Int_t raster = 0;
9182 Int_t irep = 0;
9183
9184 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9187 Double_t zmin = Hparam.zmin;
9188 Double_t zmax = Hparam.zmax;
9189 Double_t xlab1 = Hparam.xmin;
9190 Double_t xlab2 = Hparam.xmax;
9191 Double_t ylab1 = Hparam.ymin;
9192 Double_t ylab2 = Hparam.ymax;
9193 Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
9194 Double_t deltaz = TMath::Abs(zmin);
9195 if (deltaz == 0) deltaz = 1;
9196 if (zmin >= zmax) {
9197 zmin -= 0.5*deltaz;
9198 zmax += 0.5*deltaz;
9199 }
9200 Double_t z1c = zmin;
9201 Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
9202 // Compute the lego limits and instantiate a lego object
9203 fXbuf[0] = -1;
9204 fYbuf[0] = 1;
9205 fXbuf[1] = -1;
9206 fYbuf[1] = 1;
9207 if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
9208 if (Hoption.System == kPOLAR) {
9209 fXbuf[2] = z1c;
9210 fYbuf[2] = z2c;
9211 } else if (Hoption.System == kCYLINDRICAL) {
9212 if (Hoption.Logy) {
9213 if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
9214 else fXbuf[2] = 0;
9215 if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
9216 else fYbuf[2] = 0;
9217 } else {
9218 fXbuf[2] = ylab1;
9219 fYbuf[2] = ylab2;
9220 }
9221 z1c = 0; z2c = 1;
9222 } else if (Hoption.System == kSPHERICAL) {
9223 fXbuf[2] = -1;
9224 fYbuf[2] = 1;
9225 z1c = 0; z2c = 1;
9226 } else if (Hoption.System == kRAPIDITY) {
9227 fXbuf[2] = -1/TMath::Tan(dangle);
9228 fYbuf[2] = 1/TMath::Tan(dangle);
9229 } else {
9230 fXbuf[0] = xlab1;
9231 fYbuf[0] = xlab2;
9232 fXbuf[1] = ylab1;
9233 fYbuf[1] = ylab2;
9234 fXbuf[2] = z1c;
9235 fYbuf[2] = z2c;
9236 }
9237
9238 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data(), Hoption.System);
9239 fLego->SetEdgeAtt(fH->GetLineColor(),fH->GetLineStyle(),fH->GetLineWidth(),0);
9240 fLego->SetFillColor(fH->GetFillColor());
9241
9242 // Initialize the levels on the Z axis
9243 Int_t ndiv = fH->GetContour();
9244 if (ndiv == 0 ) {
9245 ndiv = gStyle->GetNumberContours();
9246 fH->SetContour(ndiv);
9247 }
9248 Int_t ndivz = TMath::Abs(ndiv);
9249 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9250
9251 if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
9252 if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
9253
9254 // Close the surface in case of non cartesian coordinates.
9255
9256 if (Hoption.System != kCARTESIAN) {nx++; ny++;}
9257
9258 // Now ready to draw the surface plot
9259
9260 TView *view = gPad ? gPad->GetView() : nullptr;
9261 if (!view) {
9262 Error("PaintSurface", "no TView in current pad");
9263 return;
9264 }
9265
9266 Double_t thedeg = 90 - gPad->GetTheta();
9267 Double_t phideg = -90 - gPad->GetPhi();
9268 Double_t psideg = view->GetPsi();
9269 view->SetView(phideg, thedeg, psideg, irep);
9270
9271 // Set color/style for back box
9272 if (Hoption.Same) {
9273 fLego->SetFillStyle(0);
9274 fLego->SetFillColor(1);
9275 } else {
9276 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9277 fLego->SetFillColor(gPad->GetFrameFillColor());
9278 }
9279 fLego->TAttFill::Modify();
9280
9281 Int_t backcolor = gPad->GetFrameFillColor();
9282 if (Hoption.System != kCARTESIAN) backcolor = 0;
9283 view->PadRange(backcolor);
9284
9285 fLego->SetFillStyle(fH->GetFillStyle());
9286 fLego->SetFillColor(fH->GetFillColor());
9287 fLego->TAttFill::Modify();
9288
9289 // Draw the filled contour on top
9290 Int_t icol1 = fH->GetFillColor();
9291
9292 Int_t hoption35 = Hoption.Surf;
9293 if (Hoption.Surf == 13 || Hoption.Surf == 15) {
9294 DefineColorLevels(ndivz);
9295 Hoption.Surf = 23;
9296 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9298 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9299 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9300 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9301 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9302 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9303 Hoption.Surf = hoption35;
9304 fLego->SetMesh(1);
9305 }
9306
9307 if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
9308 else fLego->InitMoveScreen(-1.1,1.1);
9309
9310 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
9311 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9314 fLego->BackBox(90);
9315 }
9316 }
9317
9318 // Gouraud Shading surface
9319 if (Hoption.Surf == 14) {
9320 // Set light sources
9321 fLego->LightSource(0, ydiff, 0,0,0,irep);
9322 fLego->LightSource(1, yligh1 ,1,1,1,irep);
9323 fLego->SurfaceProperty(qa, qd, qs, 1, irep);
9324 fmin = ydiff*qa;
9325 fmax = fmin + (yligh1+0.1)*(qd+qs);
9326 Int_t nbcol = 28;
9327 icol1 = 201;
9328 Double_t dcol = 0.5/Double_t(nbcol);
9329 TColor *colref = gROOT->GetColor(fH->GetFillColor());
9330 if (!colref) return;
9331 Float_t r,g,b,hue,light,satur;
9332 colref->GetRGB(r,g,b);
9333 TColor::RGBtoHLS(r,g,b,hue,light,satur);
9334 TColor *acol;
9335 for (Int_t col=0;col<nbcol;col++) {
9336 acol = gROOT->GetColor(col+icol1);
9337 TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
9338 if (acol) acol->SetRGB(r,g,b);
9339 }
9340 fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
9341 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
9343 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
9344 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9345 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9346 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9347 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
9348 } else if (Hoption.Surf == 15) {
9349 // The surface is not drawn in this case.
9350 } else {
9351 // Draw the surface
9352 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
9353 DefineColorLevels(ndivz);
9354 } else {
9355 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9356 }
9357 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9358 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
9359 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
9360 if (Hoption.System == kPOLAR) {
9361 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
9362 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
9363 } else if (Hoption.System == kCYLINDRICAL) {
9364 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9365 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
9366 } else if (Hoption.System == kSPHERICAL) {
9367 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9368 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
9369 } else if (Hoption.System == kRAPIDITY) {
9370 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9371 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
9372 } else {
9373 if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9374 if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
9375 if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9376 if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9377 }
9378 }
9379
9380 // Paint the line contour on top for option SURF7
9381 if (Hoption.Surf == 17) {
9382 fLego->InitMoveScreen(-1.1,1.1);
9383 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9384 Hoption.Surf = 23;
9385 fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
9387 if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9388 if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9389 if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9390 if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9391 if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9392 }
9393
9394 if ((!Hoption.Same) &&
9395 (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9398 fLego->BackBox(90);
9399 }
9400 }
9401 if (Hoption.System == kCARTESIAN) {
9402 fLego->InitMoveScreen(-1.1,1.1);
9404 if (Hoption.FrontBox) fLego->FrontBox(90);
9405 }
9406 if (!Hoption.Axis && !Hoption.Same) {
9407 TGaxis axis;
9408 PaintLegoAxis(&axis, 90);
9409 }
9410
9412
9413 fLego.reset();
9414}
9415
9416////////////////////////////////////////////////////////////////////////////////
9417/// Control function to draw a table using Delaunay triangles.
9418
9420{
9421
9422 TGraphDelaunay2D *dt = nullptr;
9423 TGraphDelaunay *dtOld = nullptr;
9424
9425 // Check if fH contains a TGraphDelaunay2D
9426 TList *hl = fH->GetListOfFunctions();
9427 dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9428 if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9429 if (!dt && !dtOld) return;
9430
9431 // If needed, create a TGraph2DPainter
9432 if (!fGraph2DPainter)
9433 fGraph2DPainter = dt ? std::make_unique<TGraph2DPainter>(dt) : std::make_unique<TGraph2DPainter>(dtOld);
9434
9435 // Define the 3D view
9436 if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9437 if (Hoption.Same) {
9438 TView *viewsame = gPad ? gPad->GetView() : nullptr;
9439 if (!viewsame) {
9440 Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9441 return;
9442 }
9443 Double_t *rmin = viewsame->GetRmin();
9444 Double_t *rmax = viewsame->GetRmax();
9445 if (!rmin || !rmax) return;
9446 fXbuf[0] = rmin[0];
9447 fYbuf[0] = rmax[0];
9448 fXbuf[1] = rmin[1];
9449 fYbuf[1] = rmax[1];
9450 fXbuf[2] = rmin[2];
9451 fYbuf[2] = rmax[2];
9452 } else {
9453 fXbuf[0] = Hparam.xmin;
9454 fYbuf[0] = Hparam.xmax;
9455 fXbuf[1] = Hparam.ymin;
9456 fYbuf[1] = Hparam.ymax;
9457 fXbuf[2] = Hparam.zmin;
9458 fYbuf[2] = Hparam.zmax;
9459 }
9460
9461 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
9462 TView *view = gPad ? gPad->GetView() : nullptr;
9463 if (!view) {
9464 Error("PaintTriangles", "no TView in current pad");
9465 return;
9466 }
9467 Double_t thedeg = 90 - gPad->GetTheta();
9468 Double_t phideg = -90 - gPad->GetPhi();
9469 Double_t psideg = view->GetPsi();
9470 Int_t irep;
9471 view->SetView(phideg, thedeg, psideg, irep);
9472
9473 // Set color/style for back box
9474 fLego->SetFillStyle(gPad->GetFrameFillStyle());
9475 fLego->SetFillColor(gPad->GetFrameFillColor());
9476 fLego->TAttFill::Modify();
9477 Int_t backcolor = gPad->GetFrameFillColor();
9478 if (Hoption.System != kCARTESIAN) backcolor = 0;
9479 view->PadRange(backcolor);
9480 fLego->SetFillStyle(fH->GetFillStyle());
9481 fLego->SetFillColor(fH->GetFillColor());
9482 fLego->TAttFill::Modify();
9483
9484 // Paint the Back Box if needed
9485 if (Hoption.BackBox && !Hoption.Same) {
9486 fLego->InitMoveScreen(-1.1,1.1);
9487 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
9489 fLego->BackBox(90);
9490 }
9491
9492 // Paint the triangles
9493 fGraph2DPainter->Paint(option);
9494
9495 // Paint the Front Box if needed
9496 if (Hoption.FrontBox) {
9497 fLego->InitMoveScreen(-1.1,1.1);
9499 fLego->FrontBox(90);
9500 }
9501
9502 // Paint the Axis if needed
9503 if (!Hoption.Axis && !Hoption.Same) {
9504 TGaxis axis;
9505 PaintLegoAxis(&axis, 90);
9506 }
9507
9509
9510 fLego.reset();
9511}
9512
9513////////////////////////////////////////////////////////////////////////////////
9514/// Define the color levels used to paint legos, surfaces etc..
9515
9517{
9518
9519 Int_t i, irep;
9520
9521 // Initialize the color levels
9522 if (ndivz >= 100) {
9523 Warning("PaintSurface", "too many color levels, %d >= 100, reset to 99", ndivz);
9524 ndivz = 99;
9525 }
9526 std::vector<Double_t> funlevel(ndivz+1);
9527 std::vector<Int_t> colorlevel(ndivz+1);
9528 Int_t theColor;
9529 Int_t ncolors = gStyle->GetNumberOfColors();
9530 for (i = 0; i < ndivz; ++i) {
9531 funlevel[i] = fH->GetContourLevelPad(i);
9532 theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9533 colorlevel[i] = gStyle->GetColorPalette(theColor);
9534 }
9535 colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9536 fLego->ColorFunction(ndivz, funlevel.data(), colorlevel.data(), irep);
9537}
9538
9539////////////////////////////////////////////////////////////////////////////////
9540/// [Control function to draw 2D/3D histograms (tables).](\ref HP01c)
9541
9543{
9544
9545 // Fill Hparam structure with histo parameters
9546 if (!TableInit()) return;
9547
9548 // Draw histogram frame
9549 PaintFrame();
9550
9551 // If palette option not specified, delete a possible existing palette
9552 if (!Hoption.Zscale) {
9553 TObject *palette = fFunctions->FindObject("palette");
9554 if (palette) { fFunctions->Remove(palette); delete palette;}
9555 }
9556
9557 // Do not draw the histogram. Only the attached functions will be drawn.
9558 if (Hoption.Func == 2) {
9559 if (Hoption.Zscale) {
9560 Int_t ndiv = fH->GetContour();
9561 if (ndiv == 0 ) {
9562 ndiv = gStyle->GetNumberContours();
9563 fH->SetContour(ndiv);
9564 }
9565 PaintPalette();
9566 }
9567
9568 // Draw the histogram according to the option
9569 } else {
9570 if (fH->InheritsFrom(TH2Poly::Class()) && Hoption.Axis<=0) {
9571 if (Hoption.Fill) PaintTH2PolyBins("f");
9575 if (Hoption.Line) PaintTH2PolyBins("l");
9576 if (Hoption.Mark) PaintTH2PolyBins("P");
9577 } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9581 if (Hoption.Color) {
9584 }
9587 if (Hoption.Error >= 100) Paint2DErrors(option);
9589 }
9593 }
9594
9595 // Draw histogram title
9596 PaintTitle();
9597
9598 // Draw the axes
9599 if (!Hoption.Lego && !Hoption.Surf &&
9600 !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9601
9602 TF1 *fit = nullptr;
9603 TIter next(fFunctions);
9604 while (auto obj = next()) {
9605 if (obj->InheritsFrom(TF1::Class())) {
9606 fit = (TF1*)obj;
9607 break;
9608 }
9609 }
9610 if ((Hoption.Same%10) != 1) {
9611 if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9612 if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9613 //ALWAYS executed on non-iOS platform.
9614 //On iOS, depends on mode.
9616 }
9617 }
9618 }
9619}
9620
9621////////////////////////////////////////////////////////////////////////////////
9622/// Control function to draw a TH2Poly bins' contours.
9623///
9624/// - option = "F" draw the bins as filled areas.
9625/// - option = "L" draw the bins as line.
9626/// - option = "P" draw the bins as markers.
9627
9629{
9630
9631 //Do not highlight the histogram, if its part was picked.
9632 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9633
9634 TString opt = option;
9635 opt.ToLower();
9636 Bool_t line = kFALSE;
9637 Bool_t fill = kFALSE;
9638 Bool_t mark = kFALSE;
9639 if (opt.Contains("l")) line = kTRUE;
9640 if (opt.Contains("f")) fill = kTRUE;
9641 if (opt.Contains("p")) mark = kTRUE;
9642
9643 TH2PolyBin *b;
9644 Double_t z;
9645
9646 TIter next(((TH2Poly*)fH)->GetBins());
9647 TObject *obj, *poly;
9648
9649 while ((obj=next())) {
9650 b = (TH2PolyBin*)obj;
9651 z = b->GetContent();
9652 if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9653 poly = b->GetPolygon();
9654
9655 // Paint the TGraph bins.
9656 if (poly->IsA() == TGraph::Class()) {
9657 TGraph *g = (TGraph*)poly;
9658 g->TAttLine::Modify();
9659 g->TAttMarker::Modify();
9660 g->TAttFill::Modify();
9661 if (line) {
9662 Int_t fs = g->GetFillStyle();
9663 Int_t fc = g->GetFillColor();
9664 g->SetFillStyle(0);
9665 g->SetFillColor(g->GetLineColor());
9666 g->Paint("F");
9667 g->SetFillStyle(fs);
9668 g->SetFillColor(fc);
9669 }
9670 if (fill) g->Paint("F");
9671 if (mark) g->Paint("P");
9672 }
9673
9674 // Paint the TMultiGraph bins.
9675 if (poly->IsA() == TMultiGraph::Class()) {
9676 TMultiGraph *mg = (TMultiGraph*)poly;
9677 TList *gl = mg->GetListOfGraphs();
9678 if (!gl) return;
9679 TGraph *g;
9680 TIter nextg(gl);
9681 while ((g = (TGraph*) nextg())) {
9682 g->TAttLine::Modify();
9683 g->TAttMarker::Modify();
9684 g->TAttFill::Modify();
9685 if (line) {
9686 Int_t fs = g->GetFillStyle();
9687 Int_t fc = g->GetFillColor();
9688 g->SetFillStyle(0);
9689 g->SetFillColor(g->GetLineColor());
9690 g->Paint("F");
9691 g->SetFillStyle(fs);
9692 g->SetFillColor(fc);
9693 }
9694 if (fill) g->Paint("F");
9695 if (mark) g->Paint("P");
9696 }
9697 }
9698 }
9699}
9700
9701////////////////////////////////////////////////////////////////////////////////
9702/// [Control function to draw a TH2Poly as a color plot.](\ref HP20a)
9703
9705{
9706
9707 //Do not highlight the histogram, if its part was picked.
9708 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9709 return;
9710
9711 Int_t ncolors, color, theColor;
9712 Double_t z, zc;
9713 Double_t zmin = fH->GetMinimum();
9714 Double_t zmax = fH->GetMaximum();
9715 if (Hoption.Logz) {
9716 if (zmax > 0) {
9717 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9718 zmin = TMath::Log10(zmin);
9719 zmax = TMath::Log10(zmax);
9720 } else {
9721 return;
9722 }
9723 }
9724 Double_t dz = zmax - zmin;
9725
9726 // Initialize the levels on the Z axis
9727 ncolors = gStyle->GetNumberOfColors();
9728 Int_t ndiv = fH->GetContour();
9729 if (ndiv == 0 ) {
9730 ndiv = gStyle->GetNumberContours();
9731 fH->SetContour(ndiv);
9732 }
9733 Int_t ndivz = TMath::Abs(ndiv);
9734 if (!fH->TestBit(TH1::kUserContour)) fH->SetContour(ndiv);
9735 Double_t scale = ndivz/dz;
9736
9737 TIter next(((TH2Poly*)fH)->GetBins());
9738
9739 while (auto obj = next()) {
9740 TH2PolyBin *b = (TH2PolyBin*)obj;
9741 TObject *poly = b->GetPolygon();
9742
9743 z = b->GetContent();
9744 if (z==0 && Hoption.Zero) continue;
9745 if (Hoption.Logz) {
9746 if (z > 0) z = TMath::Log10(z);
9747 else z = zmin;
9748 }
9749 if (z < zmin) continue;
9750
9751 // Define the bin color.
9753 zc = fH->GetContourLevelPad(0);
9754 if (z < zc) continue;
9755 color = -1;
9756 for (Int_t k=0; k<ndiv; k++) {
9757 zc = fH->GetContourLevelPad(k);
9758 if (z < zc) {
9759 continue;
9760 } else {
9761 color++;
9762 }
9763 }
9764 } else {
9765 color = Int_t(0.01+(z-zmin)*scale);
9766 }
9767 theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9768 if (theColor > ncolors-1) theColor = ncolors-1;
9769
9770 // Paint the TGraph bins.
9771 if (poly->IsA() == TGraph::Class()) {
9772 TGraph *g = (TGraph*)poly;
9773 g->SetFillColor(gStyle->GetColorPalette(theColor));
9774 g->TAttFill::Modify();
9775 g->Paint("F");
9776 }
9777
9778 // Paint the TMultiGraph bins.
9779 if (poly->IsA() == TMultiGraph::Class()) {
9780 TMultiGraph *mg = (TMultiGraph*)poly;
9781 TList *gl = mg->GetListOfGraphs();
9782 if (!gl) return;
9783 TGraph *g;
9784 TIter nextg(gl);
9785 while ((g = (TGraph*) nextg())) {
9786 g->SetFillColor(gStyle->GetColorPalette(theColor));
9787 g->TAttFill::Modify();
9788 g->Paint("F");
9789 }
9790 }
9791 }
9793}
9794
9795////////////////////////////////////////////////////////////////////////////////
9796/// [Control function to draw a TH2Poly as a scatter plot.](\ref HP20a)
9797
9799{
9800
9801 //Do not highlight the histogram, if its part was selected.
9802 if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9803 return;
9804
9805 Int_t k, loop, marker=0;
9806 Double_t z, xk,xstep, yk, ystep, xp, yp;
9807 Double_t scale = 1;
9808 Double_t zmin = fH->GetMinimum();
9809 Double_t zmax = fH->GetMaximum();
9810 if (Hoption.Logz) {
9811 if (zmax > 0) {
9812 if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9813 zmin = TMath::Log10(zmin);
9814 zmax = TMath::Log10(zmax);
9815 } else {
9816 return;
9817 }
9818 }
9819 Double_t dz = zmax - zmin;
9820 scale = (kNMAX-1)/dz;
9821
9822
9823 // use an independent instance of a random generator
9824 // instead of gRandom to avoid conflicts and
9825 // to get same random numbers when drawing the same histogram
9826 TRandom2 random;
9827
9828 TH2PolyBin *b;
9829
9830 TIter next(((TH2Poly*)fH)->GetBins());
9831 TObject *obj, *poly;
9832
9833 Double_t maxarea = 0, a;
9834 while ((obj=next())) {
9835 b = (TH2PolyBin*)obj;
9836 a = b->GetArea();
9837 if (a>maxarea) maxarea = a;
9838 }
9839
9840 next.Reset();
9841
9842 while ((obj=next())) {
9843 b = (TH2PolyBin*)obj;
9844 poly = b->GetPolygon();
9845 z = b->GetContent();
9846 if (z < zmin) z = zmin;
9847 if (z > zmax) z = zmax;
9848 if (Hoption.Logz) {
9849 if (z > 0) z = TMath::Log10(z) - zmin;
9850 } else {
9851 z -= zmin;
9852 }
9853 k = Int_t((z*scale)*(b->GetArea()/maxarea));
9854 xk = b->GetXMin();
9855 yk = b->GetYMin();
9856 xstep = b->GetXMax()-xk;
9857 ystep = b->GetYMax()-yk;
9858
9859 // Paint the TGraph bins.
9860 if (poly->IsA() == TGraph::Class()) {
9861 TGraph *g = (TGraph*)poly;
9862 if (k <= 0 || z <= 0) continue;
9863 loop = 0;
9864 while (loop<k) {
9865 if (k+marker >= kNMAX) {
9866 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9867 marker=0;
9868 }
9869 xp = (random.Rndm()*xstep) + xk;
9870 yp = (random.Rndm()*ystep) + yk;
9871 if (g->IsInside(xp,yp)) {
9872 fXbuf[marker] = xp;
9873 fYbuf[marker] = yp;
9874 marker++;
9875 loop++;
9876 }
9877 }
9878 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9879 }
9880
9881 // Paint the TMultiGraph bins.
9882 if (poly->IsA() == TMultiGraph::Class()) {
9883 TMultiGraph *mg = (TMultiGraph*)poly;
9884 TList *gl = mg->GetListOfGraphs();
9885 if (!gl) return;
9886 if (k <= 0 || z <= 0) continue;
9887 loop = 0;
9888 while (loop<k) {
9889 if (k+marker >= kNMAX) {
9890 gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9891 marker=0;
9892 }
9893 xp = (random.Rndm()*xstep) + xk;
9894 yp = (random.Rndm()*ystep) + yk;
9895 if (mg->IsInside(xp,yp)) {
9896 fXbuf[marker] = xp;
9897 fYbuf[marker] = yp;
9898 marker++;
9899 loop++;
9900 }
9901 }
9902 if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf.data(), fYbuf.data());
9903 }
9904 }
9905 PaintTH2PolyBins("l");
9906}
9907
9908////////////////////////////////////////////////////////////////////////////////
9909/// [Control function to draw a TH2Poly as a text plot.](\ref HP20a)
9910
9912{
9913
9914 TLatex text;
9915 text.SetTextFont(gStyle->GetTextFont());
9916 text.SetTextColor(fH->GetMarkerColor());
9917 text.SetTextSize(0.02*fH->GetMarkerSize());
9918
9919 Double_t x, y, z, e, angle = 0;
9920 TString tt, tf;
9921 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
9922 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9923 Int_t opt = (Int_t)Hoption.Text/1000;
9924
9925 text.SetTextAlign(22);
9926 if (Hoption.Text == 1) angle = 0;
9927 text.SetTextAngle(angle);
9928 text.TAttText::Modify();
9929
9930 TH2PolyBin *b;
9931
9932 TIter next(((TH2Poly*)fH)->GetBins());
9933 TObject *obj, *p;
9934
9935 while ((obj=next())) {
9936 b = (TH2PolyBin*)obj;
9937 p = b->GetPolygon();
9938 x = (b->GetXMin()+b->GetXMax())/2;
9939 if (Hoption.Logx) {
9940 if (x > 0) x = TMath::Log10(x);
9941 else continue;
9942 }
9943 y = (b->GetYMin()+b->GetYMax())/2;
9944 if (Hoption.Logy) {
9945 if (y > 0) y = TMath::Log10(y);
9946 else continue;
9947 }
9948 z = b->GetContent();
9949 if (z < fH->GetMinimum() || (z == 0 && !Hoption.MinimumZero)) continue;
9950 if (opt==2) {
9951 e = fH->GetBinError(b->GetBinNumber());
9952 tf.Form("#splitline{%s%s}{#pm %s%s}",
9954 "%",gStyle->GetPaintTextFormat());
9955 tt.Form(tf.Data(),z,e);
9956 } else {
9957 tt.Form(tf.Data(),z);
9958 }
9959 if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
9960 else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),tt.Data());
9961 }
9962
9963 PaintTH2PolyBins("l");
9964}
9965
9966////////////////////////////////////////////////////////////////////////////////
9967/// [Control function to draw a 1D/2D histograms with the bin values.](\ref HP15)
9968
9970{
9971
9972 TLatex text;
9973 text.SetTextFont(gStyle->GetTextFont());
9974 text.SetTextColor(fH->GetMarkerColor());
9975 text.SetTextSize(0.02*fH->GetMarkerSize());
9976
9977 Double_t x, y, z, e, angle = 0;
9978 TString tt, tf;
9979 tf.Form("%s%s","%",gStyle->GetPaintTextFormat());
9980 if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9981
9982 // 1D histograms
9983 if (fH->GetDimension() == 1) {
9984 Bool_t getentries = kFALSE;
9985 Double_t yt;
9986 TProfile *hp = (TProfile*)fH;
9987 if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
9988 Hoption.Text = Hoption.Text-2000;
9989 getentries = kTRUE;
9990 }
9991 if (Hoption.Text == 1) angle = 90;
9992 text.SetTextAlign(11);
9993 if (angle == 90) text.SetTextAlign(12);
9994 if (angle == 0) text.SetTextAlign(21);
9995 text.TAttText::Modify();
9996 Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
9997 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
9998 if (Hoption.Bar) {
9999 x = fH->GetXaxis()->GetBinLowEdge(i)+
10000 fH->GetXaxis()->GetBinWidth(i)*
10001 (fH->GetBarOffset()+0.5*fH->GetBarWidth());
10002 } else {
10003 x = fH->GetXaxis()->GetBinCenter(i);
10004 }
10005 y = fH->GetBinContent(i);
10006 yt = y;
10007 if (Hoption.MinimumZero && y<0) y = 0;
10008 if (getentries) yt = hp->GetBinEntries(i);
10009 if (yt == 0.) continue;
10010 tt.Form(tf.Data(),yt);
10011 if (Hoption.Logx) {
10012 if (x > 0) x = TMath::Log10(x);
10013 else continue;
10014 }
10015 if (Hoption.Logy) {
10016 if (y > 0) y = TMath::Log10(y);
10017 else continue;
10018 }
10019 if (y >= gPad->GetY2()) continue;
10020 if (y <= gPad->GetY1()) continue;
10021 text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),tt.Data());
10022 }
10023
10024 // 2D histograms
10025 } else {
10026 text.SetTextAlign(22);
10027 if (Hoption.Text == 1) angle = 0;
10028 text.SetTextAngle(angle);
10029 text.TAttText::Modify();
10030 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10031 y = fYaxis->GetBinCenter(j);
10032 if (Hoption.Logy) {
10033 if (y > 0) y = TMath::Log10(y);
10034 else continue;
10035 }
10036 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10037 Int_t bin = j*(fXaxis->GetNbins()+2) + i;
10038 x = fXaxis->GetBinCenter(i);
10039 if (Hoption.Logx) {
10040 if (x > 0) x = TMath::Log10(x);
10041 else continue;
10042 }
10043 if (!IsInside(x,y)) continue;
10044 z = fH->GetBinContent(bin);
10045 if (z < Hparam.zmin || (z == 0 && !Hoption.MinimumZero)) continue;
10046 if (Hoption.Text>2000) {
10047 e = fH->GetBinError(bin);
10048 tf.Form("#splitline{%s%s}{#pm %s%s}",
10050 "%",gStyle->GetPaintTextFormat());
10051 tt.Form(tf.Data(),z,e);
10052 } else {
10053 tt.Form(tf.Data(),z);
10054 }
10055 text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
10056 angle,0.02*fH->GetMarkerSize(),tt.Data());
10057 }
10058 }
10059 }
10060}
10061
10062////////////////////////////////////////////////////////////////////////////////
10063/// [Control function to draw a 3D implicit functions.](\ref HP27)
10064
10066{
10067
10068 Int_t irep;
10069
10070 TAxis *xaxis = fH->GetXaxis();
10071 TAxis *yaxis = fH->GetYaxis();
10072 TAxis *zaxis = fH->GetZaxis();
10073
10074 fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
10075 fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
10076 fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
10077 fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
10078 fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
10079 fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
10080
10081 fLego = std::make_unique<TPainter3dAlgorithms>(fXbuf.data(), fYbuf.data());
10082
10083 TView *view = gPad ? gPad->GetView() : nullptr;
10084 if (!view) {
10085 Error("PaintTF3", "no TView in current pad");
10086 return;
10087 }
10088 Double_t thedeg = 90 - gPad->GetTheta();
10089 Double_t phideg = -90 - gPad->GetPhi();
10090 Double_t psideg = view->GetPsi();
10091 view->SetView(phideg, thedeg, psideg, irep);
10092
10093 fLego->InitMoveScreen(-1.1,1.1);
10094
10095 if (Hoption.BackBox) {
10096 fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
10098 fLego->BackBox(90);
10099 }
10100
10102
10103 fLego->ImplicitFunction(fCurrentF3, fXbuf.data(), fYbuf.data(), fH->GetNbinsX(),
10104 fH->GetNbinsY(),
10105 fH->GetNbinsZ(), "BF");
10106
10107 if (Hoption.FrontBox) {
10108 fLego->InitMoveScreen(-1.1,1.1);
10110 fLego->FrontBox(90);
10111 }
10112 if (!Hoption.Axis && !Hoption.Same) {
10113 TGaxis axis;
10114 PaintLegoAxis(&axis, 90);
10115 }
10116
10117 PaintTitle();
10118
10119 fLego.reset();
10120}
10121
10122/////////////////////////////////////////////////////////////new TGaxis///////////////////
10123/// Draw the histogram title
10124///
10125/// The title is drawn according to the title alignment returned by
10126/// `GetTitleAlign()`. It is a 2 digits integer): hv
10127///
10128/// where `h` is the horizontal alignment and `v` is the
10129/// vertical alignment.
10130///
10131/// - `h` can get the values 1 2 3 for left, center, and right
10132/// - `v` can get the values 1 2 3 for bottom, middle and top
10133///
10134/// for instance the default alignment is: 13 (left top)
10135
10137{
10138 // probably best place for calls PaintHighlightBin
10139 // calls after paint histo (1D or 2D) and before paint title and stats
10140 if (!gPad->GetView()) PaintHighlightBin();
10141
10142 if (Hoption.Same) return;
10143 if (fH->TestBit(TH1::kNoTitle)) return;
10144 Int_t nt = strlen(fH->GetTitle());
10145 TPaveText *title = nullptr;
10146 TObject *obj;
10147 TIter next(gPad->GetListOfPrimitives());
10148 while ((obj = next())) {
10149 if (!obj->InheritsFrom(TPaveText::Class())) continue;
10150 title = (TPaveText*)obj;
10151 if (strcmp(title->GetName(),"title")) {title = nullptr; continue;}
10152 break;
10153 }
10154 if (nt == 0 || gStyle->GetOptTitle() <= 0) {
10155 if (title) delete title;
10156 return;
10157 }
10158 Double_t ht = gStyle->GetTitleH();
10159 Double_t wt = gStyle->GetTitleW();
10160
10161 if (ht <= 0) {
10162 if (gStyle->GetTitleFont("")%10 == 3) {
10163 Double_t hw = TMath::Max((Double_t)gPad->XtoPixel(gPad->GetX2()),
10164 (Double_t)gPad->YtoPixel(gPad->GetY1()));
10165 ht = 1.1*(gStyle->GetTitleSize("")/hw);
10166 } else {
10167 ht = 1.1*gStyle->GetTitleFontSize();
10168 }
10169 }
10170 if (ht <= 0) ht = 0.05;
10171 if (wt <= 0) {
10172 TLatex l;
10173 l.SetTextSize(ht);
10174 l.SetTitle(fH->GetTitle());
10175 // adjustment in case the title has several lines (#splitline)
10176 ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
10177 Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
10178 wt = TMath::Min(0.7, 0.02+wndc);
10179 }
10180 if (title) {
10181 TText *t0 = (TText*)title->GetLine(0);
10182 if (t0) {
10183 if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
10184 t0->SetTitle(fH->GetTitle());
10185 if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
10186 }
10187 return;
10188 }
10189
10190 Int_t talh = gStyle->GetTitleAlign()/10;
10191 if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
10192 Int_t talv = gStyle->GetTitleAlign()%10;
10193 if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
10195 xpos = gStyle->GetTitleX();
10196 ypos = gStyle->GetTitleY();
10197 if (talh == 2) xpos = xpos-wt/2.;
10198 if (talh == 3) xpos = xpos-wt;
10199 if (talv == 2) ypos = ypos+ht/2.;
10200 if (talv == 1) ypos = ypos+ht;
10201
10202 TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
10203
10204 // box with the histogram title
10206 ptitle->SetFillStyle(gStyle->GetTitleStyle());
10207 ptitle->SetName("title");
10210 ptitle->SetTextFont(gStyle->GetTitleFont(""));
10211 if (gStyle->GetTitleFont("")%10 > 2)
10213 ptitle->AddText(fH->GetTitle());
10214 ptitle->SetBit(kCanDelete);
10215 ptitle->Draw();
10216 ptitle->Paint();
10217
10218 if(!gPad->IsEditable()) delete ptitle;
10219}
10220
10221////////////////////////////////////////////////////////////////////////////////
10222/// Process message `mess`.
10223
10224void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
10225{
10226 if (!strcmp(mess,"SetF3")) {
10227 fCurrentF3 = (TF3 *)obj;
10228 }
10229}
10230
10231////////////////////////////////////////////////////////////////////////////////
10232/// Static function.
10233///
10234/// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
10235/// This procedure can be used to create an all-sky map in Galactic
10236/// coordinates with an equal-area Aitoff projection. Output map
10237/// coordinates are zero longitude centered.
10238/// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
10239///
10240/// source: GMT
10241///
10242/// code from Ernst-Jan Buis
10243
10245{
10246
10247 Double_t x, y;
10248
10249 Double_t alpha2 = (l/2)*TMath::DegToRad();
10250 Double_t delta = b*TMath::DegToRad();
10251 Double_t r2 = TMath::Sqrt(2.);
10252 Double_t f = 2*r2/TMath::Pi();
10253 Double_t cdec = TMath::Cos(delta);
10254 Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
10255 x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
10256 y = TMath::Sin(delta)*r2/denom;
10257 x *= TMath::RadToDeg()/f;
10258 y *= TMath::RadToDeg()/f;
10259 // x *= -1.; // for a skymap swap left<->right
10260 Al = x;
10261 Ab = y;
10262
10263 return 0;
10264}
10265
10266////////////////////////////////////////////////////////////////////////////////
10267/// Static function
10268///
10269/// Probably the most famous of the various map projections, the Mercator projection
10270/// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
10271/// with no distortion along the equator.
10272/// The Mercator projection has been used extensively for world maps in which the distortion towards
10273/// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
10274/// Greenland is larger than South America. In reality, the latter is about eight times the size of
10275/// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
10276/// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
10277/// code from Ernst-Jan Buis
10278
10280{
10281
10282 Al = l;
10284 Ab = TMath::Log(aid);
10285 return 0;
10286}
10287
10288////////////////////////////////////////////////////////////////////////////////
10289/// Static function code from Ernst-Jan Buis
10290
10292{
10293
10294 Al = l*cos(b*TMath::DegToRad());
10295 Ab = b;
10296 return 0;
10297}
10298
10299////////////////////////////////////////////////////////////////////////////////
10300/// Static function code from Ernst-Jan Buis
10301
10303{
10304
10305 Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
10306 Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
10307 return 0;
10308}
10309
10310////////////////////////////////////////////////////////////////////////////////
10311/// Recompute the histogram range following graphics operations.
10312
10314{
10315
10316 if (Hoption.Same) return;
10317
10318 // Compute x,y range
10323
10324 Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
10325 if (Hoption.Proj ==1) {
10326 // TODO : check x range not lower than -180 and not higher than 180
10331
10332 if (xmin > xmin_aid) xmin = xmin_aid;
10333 if (ymin > ymin_aid) ymin = ymin_aid;
10334 if (xmax < xmax_aid) xmax = xmax_aid;
10335 if (ymax < ymax_aid) ymax = ymax_aid;
10336 if (Hparam.ymin<0 && Hparam.ymax>0) {
10337 // there is an 'equator', check its range in the plot..
10338 THistPainter::ProjectAitoff2xy(Hparam.xmin*0.9999, 0, xmin_aid, ymin_aid);
10339 THistPainter::ProjectAitoff2xy(Hparam.xmax*0.9999, 0, xmax_aid, ymin_aid);
10340 if (xmin >xmin_aid) xmin = xmin_aid;
10341 if (xmax <xmax_aid) xmax = xmax_aid;
10342 }
10343 if (Hparam.xmin<0 && Hparam.xmax>0) {
10344 THistPainter::ProjectAitoff2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
10345 THistPainter::ProjectAitoff2xy(0, Hparam.ymax, xmax_aid, ymax_aid);
10346 if (ymin >ymin_aid) ymin = ymin_aid;
10347 if (ymax <ymax_aid) ymax = ymax_aid;
10348 }
10349 } else if ( Hoption.Proj ==2) {
10350 if (Hparam.ymin <= -90 || Hparam.ymax >=90) {
10351 Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
10352 Hoption.Proj = 0;
10353 } else {
10356 }
10357 } else if (Hoption.Proj == 3) {
10362
10363 if (xmin > xmin_aid) xmin = xmin_aid;
10364 if (ymin > ymin_aid) ymin = ymin_aid;
10365 if (xmax < xmax_aid) xmax = xmax_aid;
10366 if (ymax < ymax_aid) ymax = ymax_aid;
10367 if (Hparam.ymin<0 && Hparam.ymax>0) {
10368 THistPainter::ProjectSinusoidal2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
10369 THistPainter::ProjectSinusoidal2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
10370 if (xmin >xmin_aid) xmin = xmin_aid;
10371 if (xmax <xmax_aid) xmax = xmax_aid;
10372 }
10373 if (Hparam.xmin<0 && Hparam.xmax>0) {
10374 THistPainter::ProjectSinusoidal2xy(0,Hparam.ymin, xmin_aid, ymin_aid);
10375 THistPainter::ProjectSinusoidal2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
10376 if (ymin >ymin_aid) ymin = ymin_aid;
10377 if (ymax <ymax_aid) ymax = ymax_aid;
10378 }
10379 } else if (Hoption.Proj == 4) {
10384
10385 if (xmin > xmin_aid) xmin = xmin_aid;
10386 if (ymin > ymin_aid) ymin = ymin_aid;
10387 if (xmax < xmax_aid) xmax = xmax_aid;
10388 if (ymax < ymax_aid) ymax = ymax_aid;
10389 if (Hparam.ymin<0 && Hparam.ymax>0) {
10390 THistPainter::ProjectParabolic2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
10391 THistPainter::ProjectParabolic2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
10392 if (xmin >xmin_aid) xmin = xmin_aid;
10393 if (xmax <xmax_aid) xmax = xmax_aid;
10394 }
10395 if (Hparam.xmin<0 && Hparam.xmax>0) {
10396 THistPainter::ProjectParabolic2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
10397 THistPainter::ProjectParabolic2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
10398 if (ymin >ymin_aid) ymin = ymin_aid;
10399 if (ymax <ymax_aid) ymax = ymax_aid;
10400 }
10401 }
10402 Hparam.xmin= xmin;
10403 Hparam.xmax= xmax;
10404 Hparam.ymin= ymin;
10405 Hparam.ymax= ymax;
10406
10407 Double_t dx = xmax-xmin;
10408 Double_t dy = ymax-ymin;
10409 Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10410 Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10411
10412 // Range() could change the size of the pad pixmap and therefore should
10413 // be called before the other paint routines
10414 gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10415 ymin - dyr*gPad->GetBottomMargin(),
10416 xmax + dxr*gPad->GetRightMargin(),
10417 ymax + dyr*gPad->GetTopMargin());
10418 gPad->RangeAxis(xmin, ymin, xmax, ymax);
10419}
10420
10421////////////////////////////////////////////////////////////////////////////////
10422/// Set current histogram to `h`
10423
10425{
10426
10427 if (h == 0) return;
10428 fH = h;
10429 fXaxis = h->GetXaxis();
10430 fYaxis = h->GetYaxis();
10431 fZaxis = h->GetZaxis();
10433}
10434
10435////////////////////////////////////////////////////////////////////////////////
10436/// Initialize various options to draw 2D histograms.
10437
10439{
10440
10441 static const char *where = "TableInit";
10442
10443 Int_t first, last;
10444 Double_t yMARGIN= gStyle->GetHistTopMargin();
10445 Double_t zmin, zmax;
10446 Int_t maximum = 0;
10447 Int_t minimum = 0;
10448 if (fH->GetMaximumStored() != -1111) maximum = 1;
10449 if (fH->GetMinimumStored() != -1111) minimum = 1;
10450
10451 // ----------------- Compute X axis parameters
10452 first = fXaxis->GetFirst();
10453 last = fXaxis->GetLast();
10454 Hparam.xlast = last;
10460
10461 // if log scale in X, replace xmin,max by the log
10462 if (Hoption.Logx) {
10463 // find the first edge of a bin that is > 0
10464 if (Hparam.xlowedge <=0 ) {
10467 }
10468 if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10469 Error(where, "cannot set X axis to log scale");
10470 return 0;
10471 }
10475 if (Hparam.xlast > last) Hparam.xlast = last;
10478 }
10479
10480 // ----------------- Compute Y axis parameters
10481 first = fYaxis->GetFirst();
10482 last = fYaxis->GetLast();
10483 Hparam.ylast = last;
10487 if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10490
10491 // if log scale in Y, replace ymin,max by the log
10492 if (Hoption.Logy) {
10493 if (Hparam.ylowedge <=0 ) {
10496 }
10497 if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10498 Error(where, "cannot set Y axis to log scale");
10499 return 0;
10500 }
10504 if (Hparam.ylast > last) Hparam.ylast = last;
10507 }
10508
10509
10510 // ----------------- Compute Z axis parameters
10511 Double_t bigp = TMath::Power(10,32);
10512 zmax = -bigp;
10513 zmin = bigp;
10514 Double_t c1, e1;
10515 Double_t allchan = 0;
10516 for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10517 for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10518 c1 = fH->GetBinContent(i,j);
10519 zmax = TMath::Max(zmax,c1);
10520 if (Hoption.Error) {
10521 e1 = fH->GetBinError(i,j);
10522 zmax = TMath::Max(zmax,c1+e1);
10523 }
10524 zmin = TMath::Min(zmin,c1);
10525 allchan += c1;
10526 }
10527 }
10528
10529 // Take into account maximum , minimum
10530
10531 if (maximum) zmax = fH->GetMaximumStored();
10532 if (minimum) zmin = fH->GetMinimumStored();
10533 if (Hoption.Logz && zmax < 0) {
10534 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10535 return 0;
10536 } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10537 zmin = 0.01;
10538 zmax = 10.;
10539 }
10540 if (zmin >= zmax) {
10541 if (Hoption.Logz) {
10542 if (zmax > 0) zmin = 0.001*zmax;
10543 else {
10544 if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10545 return 0;
10546 }
10547 }
10548 }
10549
10550 // take into account normalization factor
10551 Hparam.allchan = allchan;
10552 Double_t factor = allchan;
10553 if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10554 if (allchan) factor /= allchan;
10555 if (factor == 0) factor = 1;
10556 Hparam.factor = factor;
10557 zmax = factor*zmax;
10558 zmin = factor*zmin;
10559 c1 = zmax;
10560 if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10561
10562 // For log scales, histogram coordinates are log10(ymin) and
10563 // log10(ymax). Final adjustment (if not option "Same")
10564 // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10565 // Maximum and Minimum are not defined.
10566 if (Hoption.Logz) {
10567 if (zmin <= 0) {
10568 zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10569 fH->SetMinimum(zmin);
10570 }
10571 zmin = TMath::Log10(zmin);
10572 if (!minimum) zmin += TMath::Log10(0.5);
10573 zmax = TMath::Log10(zmax);
10574 if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10575 goto LZMIN;
10576 }
10577
10578 // final adjustment of YMAXI for linear scale (if not option "Same"):
10579 // decrease histogram height to MAX% of allowed height if HMAXIM
10580 // has not been called.
10581 // MAX% is the value in percent which has been set in HPLSET
10582 // (default is 90%).
10583 if (!maximum) {
10584 zmax += yMARGIN*(zmax-zmin);
10585 }
10586
10587 // final adjustment of ymin for linear scale.
10588 // if minimum is not set , then ymin is set to zero if >0
10589 // or to ymin - yMARGIN if <0.
10590 if (!minimum) {
10591 if (Hoption.MinimumZero) {
10592 if (zmin >= 0) zmin = 0;
10593 else zmin -= yMARGIN*(zmax-zmin);
10594 } else {
10595 Double_t dzmin = yMARGIN*(zmax-zmin);
10596 if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10597 else zmin -= dzmin;
10598 }
10599 }
10600
10601LZMIN:
10602 Hparam.zmin = zmin;
10603 Hparam.zmax = zmax;
10604
10605 // Set bar offset and width
10608
10609 return 1;
10610}
10611
10612////////////////////////////////////////////////////////////////////////////////
10613/// This function returns the best format to print the error value (e)
10614/// knowing the parameter value (v) and the format (f) used to print it.
10615
10617{
10618
10619 static TString ef;
10620 TString tf, tv;
10621
10622 // print v with the format f in tv.
10623 tf.Form("%s%s","%",f);
10624 tv.Form(tf.Data(),v);
10625
10626 // Analyse tv.
10627 int ie = tv.Index("e");
10628 int iE = tv.Index("E");
10629 int id = tv.Index(".");
10630
10631 // v has been printed with the exponent notation.
10632 // There is 2 cases, the exponent is positive or negative
10633 if (ie >= 0 || iE >= 0) {
10634 if (tv.Index("+") >= 0) {
10635 if (e < 1) {
10636 ef.Form("%s.1f","%");
10637 } else {
10638 if (ie >= 0) {
10639 ef.Form("%s.%de","%",ie-id-1);
10640 } else {
10641 ef.Form("%s.%dE","%",iE-id-1);
10642 }
10643 }
10644 } else {
10645 if (ie >= 0) {
10646 ef.Form("%s.%de","%",ie-id-1);
10647 } else {
10648 ef.Form("%s.%dE","%",iE-id-1);
10649 }
10650 }
10651
10652 // There is not '.' in tv. e will be printed with one decimal digit.
10653 } else if (id < 0) {
10654 ef.Form("%s.1f","%");
10655
10656 // There is a '.' in tv and no exponent notation. e's decimal part will
10657 // have the same number of digits as v's one.
10658 } else {
10659 ef.Form("%s.%df","%",tv.Length()-id-1);
10660 }
10661
10662 return ef.Data();
10663}
10664
10665////////////////////////////////////////////////////////////////////////////////
10666/// Set projection.
10667
10669{
10670
10671 if (fShowProjection) return;
10672 TString opt = option;
10673 opt.ToLower();
10674 Int_t projection = 0;
10675 if (opt.Contains("x")) projection = 1;
10676 if (opt.Contains("y")) projection = 2;
10677 if (opt.Contains("z")) projection = 3;
10678 if (opt.Contains("xy")) projection = 4;
10679 if (opt.Contains("yx")) projection = 5;
10680 if (opt.Contains("xz")) projection = 6;
10681 if (opt.Contains("zx")) projection = 7;
10682 if (opt.Contains("yz")) projection = 8;
10683 if (opt.Contains("zy")) projection = 9;
10684 if (projection < 4) fShowOption = option+1;
10685 else fShowOption = option+2;
10686 fShowProjection = projection+100*nbins;
10687 gROOT->MakeDefCanvas();
10688 gPad->SetName(TString::Format("c_%zx_projection_%d", (size_t)fH, fShowProjection).Data());
10689 gPad->SetGrid();
10690}
10691
10692////////////////////////////////////////////////////////////////////////////////
10693/// Show projection onto X.
10694
10696{
10697
10698 Int_t nbins = (Int_t)fShowProjection/100;
10699 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10700 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10701
10702 // Erase old position and draw a line at current position
10703 static int pyold1 = 0;
10704 static int pyold2 = 0;
10705 float uxmin = gPad->GetUxmin();
10706 float uxmax = gPad->GetUxmax();
10707 int pxmin = gPad->XtoAbsPixel(uxmin);
10708 int pxmax = gPad->XtoAbsPixel(uxmax);
10709 Float_t upy = gPad->AbsPixeltoY(py);
10710 Float_t y = gPad->PadtoY(upy);
10711 Int_t biny1 = fH->GetYaxis()->FindBin(y);
10712 Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10713 Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10714 Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10715
10716 if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10717 gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10718 pyold1 = py1;
10719 pyold2 = py2;
10720
10721 // Create or set the new canvas proj x
10722 TVirtualPad::TContext ctxt(true);
10723 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
10724 (size_t)fH, fShowProjection).Data());
10725 if (c) {
10726 c->Clear();
10727 } else {
10728 fShowProjection = 0;
10729 pyold1 = 0;
10730 pyold2 = 0;
10731 return;
10732 }
10733 c->cd();
10734 c->SetLogy(ctxt.GetSaved()->GetLogz());
10735 c->SetLogx(ctxt.GetSaved()->GetLogx());
10736
10737 // Draw slice corresponding to mouse position
10738 TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10739 TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10740 if (hp) {
10741 hp->SetFillColor(38);
10742 // apply a patch from Oliver Freyermuth to set the title in the projection
10743 // using the range of the projected Y values
10744 if (biny1 == biny2) {
10745 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10746 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10747 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10748 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10749 if (fH->GetYaxis()->GetLabels() != NULL) {
10750 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10751 } else {
10752 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10753 }
10754 } else {
10755 Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10756 Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10757 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10758 // biny1 is used here to get equal precision no matter how large the binrange is,
10759 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10760 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10761 if (fH->GetYaxis()->GetLabels() != NULL) {
10762 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)));
10763 } else {
10764 hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10765 }
10766 }
10767 hp->SetXTitle(fH->GetXaxis()->GetTitle());
10768 hp->SetYTitle("Number of Entries");
10769 hp->Draw();
10770 c->Update();
10771 }
10772}
10773
10774////////////////////////////////////////////////////////////////////////////////
10775/// Show projection onto Y.
10776
10778{
10779
10780 Int_t nbins = (Int_t)fShowProjection/100;
10781 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10782 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10783
10784 // Erase old position and draw a line at current position
10785 static int pxold1 = 0;
10786 static int pxold2 = 0;
10787 float uymin = gPad->GetUymin();
10788 float uymax = gPad->GetUymax();
10789 int pymin = gPad->YtoAbsPixel(uymin);
10790 int pymax = gPad->YtoAbsPixel(uymax);
10791 Float_t upx = gPad->AbsPixeltoX(px);
10792 Float_t x = gPad->PadtoX(upx);
10793 Int_t binx1 = fH->GetXaxis()->FindBin(x);
10794 Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10795 Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10796 Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10797
10798 if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10799 gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10800 pxold1 = px1;
10801 pxold2 = px2;
10802
10803 // Create or set the new canvas proj y
10804 TVirtualPad::TContext ctxt(true);
10805
10806 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
10807 (size_t)fH, fShowProjection).Data());
10808 if (c) {
10809 c->Clear();
10810 } else {
10811 fShowProjection = 0;
10812 pxold1 = 0;
10813 pxold2 = 0;
10814 return;
10815 }
10816 c->cd();
10817 c->SetLogy(ctxt.GetSaved()->GetLogz());
10818 c->SetLogx(ctxt.GetSaved()->GetLogy());
10819
10820 // Draw slice corresponding to mouse position
10821 TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10822 TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10823 if (hp) {
10824 hp->SetFillColor(38);
10825 // apply a patch from Oliver Freyermuth to set the title in the projection
10826 // using the range of the projected X values
10827 if (binx1 == binx2) {
10828 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10829 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10830 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10831 Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10832 if (fH->GetXaxis()->GetLabels() != NULL) {
10833 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10834 } else {
10835 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10836 }
10837 } else {
10838 Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10839 Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
10840 // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10841 // binx1 is used here to get equal precision no matter how large the binrange is,
10842 // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10843 Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
10844 if (fH->GetXaxis()->GetLabels() != NULL) {
10845 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)));
10846 } else {
10847 hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
10848 }
10849 }
10850 hp->SetXTitle(fH->GetYaxis()->GetTitle());
10851 hp->SetYTitle("Number of Entries");
10852 hp->Draw();
10853 c->Update();
10854 }
10855}
10856
10857////////////////////////////////////////////////////////////////////////////////
10858/// Show projection (specified by `fShowProjection`) of a `TH3`.
10859/// The drawing option for the projection is in `fShowOption`.
10860///
10861/// First implementation; R.Brun
10862///
10863/// Full implementation: Tim Tran (timtran@jlab.org) April 2006
10864
10866{
10867
10868 Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
10869 if (fH->GetDimension() < 3) {
10870 if (fShowProjection%100 == 1) {ShowProjectionX(px,py); return;}
10871 if (fShowProjection%100 == 2) {ShowProjectionY(px,py); return;}
10872 }
10873
10874 gPad->SetDoubleBuffer(0); // turn off double buffer mode
10875 gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10876
10877 // Erase old position and draw a line at current position
10878 TView *view = gPad->GetView();
10879 if (!view) return;
10880 TH3 *h3 = (TH3*)fH;
10881 TAxis *xaxis = h3->GetXaxis();
10882 TAxis *yaxis = h3->GetYaxis();
10883 TAxis *zaxis = h3->GetZaxis();
10884 Double_t u[3],xx[3];
10885
10886 static TPoint line1[2];//store end points of a line, initialised 0 by default
10887 static TPoint line2[2];// second line when slice thickness > 1 bin thickness
10888 static TPoint line3[2];
10889 static TPoint line4[2];
10890 static TPoint endface1[5];
10891 static TPoint endface2[5];
10892 static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
10893 static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
10894
10895 Double_t uxmin = gPad->GetUxmin();
10896 Double_t uxmax = gPad->GetUxmax();
10897 Double_t uymin = gPad->GetUymin();
10898 Double_t uymax = gPad->GetUymax();
10899
10900 int pxmin = gPad->XtoAbsPixel(uxmin);
10901 int pxmax = gPad->XtoAbsPixel(uxmax);
10902 if (pxmin==pxmax) return;
10903 int pymin = gPad->YtoAbsPixel(uymin);
10904 int pymax = gPad->YtoAbsPixel(uymax);
10905 if (pymin==pymax) return;
10906 Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
10907 Double_t cy = (pymax-pymin)/(uymax-uymin);
10908 TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(TString::Format("c_%zx_projection_%d",
10909 (size_t)fH, fShowProjection).Data());
10910 if (!c) {
10911 fShowProjection = 0;
10912 return;
10913 }
10914
10915 TVirtualPad::TContext ctxt(true);
10916
10917 switch ((Int_t)fShowProjection%100) {
10918 case 1:
10919 // "x"
10920 {
10921 Int_t firstY = yaxis->GetFirst();
10922 Int_t lastY = yaxis->GetLast();
10923 Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
10924 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
10925 yaxis->SetRange(biny,biny2);
10926 Int_t firstZ = zaxis->GetFirst();
10927 Int_t lastZ = zaxis->GetLast();
10928 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
10929 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10930 zaxis->SetRange(binz,binz2);
10931 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
10932 if (nbins>1 && line1[0].GetX()) {
10933 gVirtualX->DrawPolyLine(2,line2);
10934 gVirtualX->DrawPolyLine(2,line3);
10935 gVirtualX->DrawPolyLine(2,line4);
10936 gVirtualX->DrawPolyLine(5,endface1);
10937 gVirtualX->DrawPolyLine(5,endface2);
10938 }
10939 xx[0] = xaxis->GetXmin();
10940 xx[2] = zaxis->GetBinCenter(binz);
10941 xx[1] = yaxis->GetBinCenter(biny);
10942 view->WCtoNDC(xx,u);
10943 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10944 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10945 xx[0] = xaxis->GetXmax();
10946 view->WCtoNDC(xx,u);
10947 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10948 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10949 gVirtualX->DrawPolyLine(2,line1);
10950 if (nbins>1) {
10951 xx[0] = xaxis->GetXmin();
10952 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10953 xx[1] = yaxis->GetBinCenter(biny);
10954 view->WCtoNDC(xx,u);
10955 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10956 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10957 xx[0] = xaxis->GetXmax();
10958 view->WCtoNDC(xx,u);
10959 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10960 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10961
10962 xx[0] = xaxis->GetXmin();
10963 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10964 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10965 view->WCtoNDC(xx,u);
10966 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10967 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10968 xx[0] = xaxis->GetXmax();
10969 view->WCtoNDC(xx,u);
10970 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10971 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10972
10973 xx[0] = xaxis->GetXmin();
10974 xx[2] = zaxis->GetBinCenter(binz);
10975 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10976 view->WCtoNDC(xx,u);
10977 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10978 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10979 xx[0] = xaxis->GetXmax();
10980 view->WCtoNDC(xx,u);
10981 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10982 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10983
10984 endface1[0].SetX(line1[0].GetX());
10985 endface1[0].SetY(line1[0].GetY());
10986 endface1[1].SetX(line2[0].GetX());
10987 endface1[1].SetY(line2[0].GetY());
10988 endface1[2].SetX(line3[0].GetX());
10989 endface1[2].SetY(line3[0].GetY());
10990 endface1[3].SetX(line4[0].GetX());
10991 endface1[3].SetY(line4[0].GetY());
10992 endface1[4].SetX(line1[0].GetX());
10993 endface1[4].SetY(line1[0].GetY());
10994
10995 endface2[0].SetX(line1[1].GetX());
10996 endface2[0].SetY(line1[1].GetY());
10997 endface2[1].SetX(line2[1].GetX());
10998 endface2[1].SetY(line2[1].GetY());
10999 endface2[2].SetX(line3[1].GetX());
11000 endface2[2].SetY(line3[1].GetY());
11001 endface2[3].SetX(line4[1].GetX());
11002 endface2[3].SetY(line4[1].GetY());
11003 endface2[4].SetX(line1[1].GetX());
11004 endface2[4].SetY(line1[1].GetY());
11005
11006 gVirtualX->DrawPolyLine(2,line2);
11007 gVirtualX->DrawPolyLine(2,line3);
11008 gVirtualX->DrawPolyLine(2,line4);
11009 gVirtualX->DrawPolyLine(5,endface1);
11010 gVirtualX->DrawPolyLine(5,endface2);
11011 }
11012 c->Clear();
11013 c->cd();
11014 TH1 *hp = h3->Project3D("x");
11015 yaxis->SetRange(firstY,lastY);
11016 zaxis->SetRange(firstZ,lastZ);
11017 if (hp) {
11018 hp->SetFillColor(38);
11019 if (nbins == 1)
11020 hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
11021 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11022 else {
11023 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),
11024 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11025 }
11026 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11027 hp->SetYTitle("Number of Entries");
11028 hp->Draw(fShowOption.Data());
11029 }
11030 }
11031 break;
11032
11033 case 2:
11034 // "y"
11035 {
11036 Int_t firstX = xaxis->GetFirst();
11037 Int_t lastX = xaxis->GetLast();
11038 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11039 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11040 xaxis->SetRange(binx,binx2);
11041 Int_t firstZ = zaxis->GetFirst();
11042 Int_t lastZ = zaxis->GetLast();
11043 Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
11044 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11045 zaxis->SetRange(binz,binz2);
11046 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11047 if (nbins>1 && line1[0].GetX()) {
11048 gVirtualX->DrawPolyLine(2,line2);
11049 gVirtualX->DrawPolyLine(2,line3);
11050 gVirtualX->DrawPolyLine(2,line4);
11051 gVirtualX->DrawPolyLine(5,endface1);
11052 gVirtualX->DrawPolyLine(5,endface2);
11053 }
11054 xx[0]=xaxis->GetBinCenter(binx);
11055 xx[2] = zaxis->GetBinCenter(binz);
11056 xx[1] = yaxis->GetXmin();
11057 view->WCtoNDC(xx,u);
11058 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11059 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11060 xx[1] = yaxis->GetXmax();
11061 view->WCtoNDC(xx,u);
11062 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11063 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11064 gVirtualX->DrawPolyLine(2,line1);
11065 if (nbins>1) {
11066 xx[1] = yaxis->GetXmin();
11067 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11068 xx[0] = xaxis->GetBinCenter(binx);
11069 view->WCtoNDC(xx,u);
11070 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11071 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11072 xx[1] = yaxis->GetXmax();
11073 view->WCtoNDC(xx,u);
11074 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11075 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11076
11077 xx[1] = yaxis->GetXmin();
11078 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11079 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11080 view->WCtoNDC(xx,u);
11081 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11082 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11083 xx[1] = yaxis->GetXmax();
11084 view->WCtoNDC(xx,u);
11085 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11086 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11087
11088 xx[1] = yaxis->GetXmin();
11089 xx[2] = zaxis->GetBinCenter(binz);
11090 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11091 view->WCtoNDC(xx,u);
11092 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11093 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11094 xx[1] = yaxis->GetXmax();
11095 view->WCtoNDC(xx,u);
11096 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11097 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11098
11099 endface1[0].SetX(line1[0].GetX());
11100 endface1[0].SetY(line1[0].GetY());
11101 endface1[1].SetX(line2[0].GetX());
11102 endface1[1].SetY(line2[0].GetY());
11103 endface1[2].SetX(line3[0].GetX());
11104 endface1[2].SetY(line3[0].GetY());
11105 endface1[3].SetX(line4[0].GetX());
11106 endface1[3].SetY(line4[0].GetY());
11107 endface1[4].SetX(line1[0].GetX());
11108 endface1[4].SetY(line1[0].GetY());
11109
11110 endface2[0].SetX(line1[1].GetX());
11111 endface2[0].SetY(line1[1].GetY());
11112 endface2[1].SetX(line2[1].GetX());
11113 endface2[1].SetY(line2[1].GetY());
11114 endface2[2].SetX(line3[1].GetX());
11115 endface2[2].SetY(line3[1].GetY());
11116 endface2[3].SetX(line4[1].GetX());
11117 endface2[3].SetY(line4[1].GetY());
11118 endface2[4].SetX(line1[1].GetX());
11119 endface2[4].SetY(line1[1].GetY());
11120
11121 gVirtualX->DrawPolyLine(2,line2);
11122 gVirtualX->DrawPolyLine(2,line3);
11123 gVirtualX->DrawPolyLine(2,line4);
11124 gVirtualX->DrawPolyLine(5,endface1);
11125 gVirtualX->DrawPolyLine(5,endface2);
11126 }
11127 c->Clear();
11128 c->cd();
11129 TH1 *hp = h3->Project3D("y");
11130 xaxis->SetRange(firstX,lastX);
11131 zaxis->SetRange(firstZ,lastZ);
11132 if (hp) {
11133 hp->SetFillColor(38);
11134 if (nbins == 1)
11135 hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11136 binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
11137 else
11138 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),
11139 binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
11140 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11141 hp->SetYTitle("Number of Entries");
11142 hp->Draw(fShowOption.Data());
11143 }
11144 }
11145 break;
11146
11147 case 3:
11148 // "z"
11149 {
11150 Int_t firstX = xaxis->GetFirst();
11151 Int_t lastX = xaxis->GetLast();
11152 Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
11153 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11154 xaxis->SetRange(binx,binx2);
11155 Int_t firstY = yaxis->GetFirst();
11156 Int_t lastY = yaxis->GetLast();
11157 Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
11158 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11159 yaxis->SetRange(biny,biny2);
11160 if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
11161 if (nbins>1 && line1[0].GetX()) {
11162 gVirtualX->DrawPolyLine(2,line2);
11163 gVirtualX->DrawPolyLine(2,line3);
11164 gVirtualX->DrawPolyLine(2,line4);
11165 gVirtualX->DrawPolyLine(5,endface1);
11166 gVirtualX->DrawPolyLine(5,endface2);
11167 }
11168 xx[0] = xaxis->GetBinCenter(binx);
11169 xx[1] = yaxis->GetBinCenter(biny);
11170 xx[2] = zaxis->GetXmin();
11171 view->WCtoNDC(xx,u);
11172 line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11173 line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11174 xx[2] = zaxis->GetXmax();
11175 view->WCtoNDC(xx,u);
11176 line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11177 line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11178 gVirtualX->DrawPolyLine(2,line1);
11179 if (nbins>1) {
11180 xx[2] = zaxis->GetXmin();
11181 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11182 xx[0] = xaxis->GetBinCenter(binx);
11183 view->WCtoNDC(xx,u);
11184 line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11185 line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11186 xx[2] = zaxis->GetXmax();
11187 view->WCtoNDC(xx,u);
11188 line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11189 line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11190
11191 xx[2] = zaxis->GetXmin();
11192 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11193 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11194 view->WCtoNDC(xx,u);
11195 line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11196 line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11197 xx[2] = zaxis->GetXmax();
11198 view->WCtoNDC(xx,u);
11199 line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11200 line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11201
11202 xx[2] = zaxis->GetXmin();
11203 xx[1] = yaxis->GetBinCenter(biny);
11204 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11205 view->WCtoNDC(xx,u);
11206 line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11207 line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11208 xx[2] = zaxis->GetXmax();
11209 view->WCtoNDC(xx,u);
11210 line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11211 line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11212
11213 endface1[0].SetX(line1[0].GetX());
11214 endface1[0].SetY(line1[0].GetY());
11215 endface1[1].SetX(line2[0].GetX());
11216 endface1[1].SetY(line2[0].GetY());
11217 endface1[2].SetX(line3[0].GetX());
11218 endface1[2].SetY(line3[0].GetY());
11219 endface1[3].SetX(line4[0].GetX());
11220 endface1[3].SetY(line4[0].GetY());
11221 endface1[4].SetX(line1[0].GetX());
11222 endface1[4].SetY(line1[0].GetY());
11223
11224 endface2[0].SetX(line1[1].GetX());
11225 endface2[0].SetY(line1[1].GetY());
11226 endface2[1].SetX(line2[1].GetX());
11227 endface2[1].SetY(line2[1].GetY());
11228 endface2[2].SetX(line3[1].GetX());
11229 endface2[2].SetY(line3[1].GetY());
11230 endface2[3].SetX(line4[1].GetX());
11231 endface2[3].SetY(line4[1].GetY());
11232 endface2[4].SetX(line1[1].GetX());
11233 endface2[4].SetY(line1[1].GetY());
11234
11235 gVirtualX->DrawPolyLine(2,line2);
11236 gVirtualX->DrawPolyLine(2,line3);
11237 gVirtualX->DrawPolyLine(2,line4);
11238 gVirtualX->DrawPolyLine(5,endface1);
11239 gVirtualX->DrawPolyLine(5,endface2);
11240 }
11241 c->Clear();
11242 c->cd();
11243 TH1 *hp = h3->Project3D("z");
11244 xaxis->SetRange(firstX,lastX);
11245 yaxis->SetRange(firstY,lastY);
11246 if (hp) {
11247 hp->SetFillColor(38);
11248 if (nbins == 1)
11249 hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
11250 biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
11251 else
11252 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),
11253 biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
11254 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11255 hp->SetYTitle("Number of Entries");
11256 hp->Draw(fShowOption.Data());
11257 }
11258 }
11259 break;
11260
11261 case 4:
11262 // "xy"
11263 {
11264 Int_t first = zaxis->GetFirst();
11265 Int_t last = zaxis->GetLast();
11266 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11267 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11268 zaxis->SetRange(binz,binz2);
11269 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11270 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11271 xx[0] = xaxis->GetXmin();
11272 xx[1] = yaxis->GetXmax();
11273 xx[2] = zaxis->GetBinCenter(binz);
11274 view->WCtoNDC(xx,u);
11275 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11276 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11277 rect1[4].SetX(rect1[0].GetX());
11278 rect1[4].SetY(rect1[0].GetY());
11279 xx[0] = xaxis->GetXmax();
11280 view->WCtoNDC(xx,u);
11281 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11282 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11283 xx[1] = yaxis->GetXmin();
11284 view->WCtoNDC(xx,u);
11285 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11286 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11287 xx[0] = xaxis->GetXmin();
11288 view->WCtoNDC(xx,u);
11289 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11290 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11291 gVirtualX->DrawPolyLine(5,rect1);
11292 if (nbins>1) {
11293 xx[0] = xaxis->GetXmin();
11294 xx[1] = yaxis->GetXmax();
11295 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11296 view->WCtoNDC(xx,u);
11297 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11298 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11299 rect2[4].SetX(rect2[0].GetX());
11300 rect2[4].SetY(rect2[0].GetY());
11301 xx[0] = xaxis->GetXmax();
11302 view->WCtoNDC(xx,u);
11303 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11304 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11305 xx[1] = yaxis->GetXmin();
11306 view->WCtoNDC(xx,u);
11307 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11308 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11309 xx[0] = xaxis->GetXmin();
11310 view->WCtoNDC(xx,u);
11311 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11312 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11313 gVirtualX->DrawPolyLine(5,rect2);
11314 }
11315
11316 c->Clear();
11317 c->cd();
11318 TH2 *hp = (TH2*)h3->Project3D("xy");
11319 zaxis->SetRange(first,last);
11320 if (hp) {
11321 hp->SetFillColor(38);
11322 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11323 else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11324 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11325 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11326 hp->SetZTitle("Number of Entries");
11327 hp->Draw(fShowOption.Data());
11328 }
11329 }
11330 break;
11331
11332 case 5:
11333 // "yx"
11334 {
11335 Int_t first = zaxis->GetFirst();
11336 Int_t last = zaxis->GetLast();
11337 Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11338 Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
11339 zaxis->SetRange(binz,binz2);
11340 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11341 if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11342 xx[0] = xaxis->GetXmin();
11343 xx[1] = yaxis->GetXmax();
11344 xx[2] = zaxis->GetBinCenter(binz);
11345 view->WCtoNDC(xx,u);
11346 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11347 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11348 rect1[4].SetX(rect1[0].GetX());
11349 rect1[4].SetY(rect1[0].GetY());
11350 xx[0] = xaxis->GetXmax();
11351 view->WCtoNDC(xx,u);
11352 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11353 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11354 xx[1] = yaxis->GetXmin();
11355 view->WCtoNDC(xx,u);
11356 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11357 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11358 xx[0] = xaxis->GetXmin();
11359 view->WCtoNDC(xx,u);
11360 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11361 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11362 gVirtualX->DrawPolyLine(5,rect1);
11363 if (nbins>1) {
11364 xx[0] = xaxis->GetXmin();
11365 xx[1] = yaxis->GetXmax();
11366 xx[2] = zaxis->GetBinCenter(binz+nbins-1);
11367 view->WCtoNDC(xx,u);
11368 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11369 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11370 rect2[4].SetX(rect2[0].GetX());
11371 rect2[4].SetY(rect2[0].GetY());
11372 xx[0] = xaxis->GetXmax();
11373 view->WCtoNDC(xx,u);
11374 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11375 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11376 xx[1] = yaxis->GetXmin();
11377 view->WCtoNDC(xx,u);
11378 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11379 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11380 xx[0] = xaxis->GetXmin();
11381 view->WCtoNDC(xx,u);
11382 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11383 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11384 gVirtualX->DrawPolyLine(5,rect2);
11385 }
11386 c->Clear();
11387 c->cd();
11388 TH2 *hp = (TH2*)h3->Project3D("yx");
11389 zaxis->SetRange(first,last);
11390 if (hp) {
11391 hp->SetFillColor(38);
11392 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11393 else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11394 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11395 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11396 hp->SetZTitle("Number of Entries");
11397 hp->Draw(fShowOption.Data());
11398 }
11399 }
11400 break;
11401
11402 case 6:
11403 // "xz"
11404 {
11405 Int_t first = yaxis->GetFirst();
11406 Int_t last = yaxis->GetLast();
11407 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11408 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11409 yaxis->SetRange(biny,biny2);
11410 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11411 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11412 xx[0] = xaxis->GetXmin();
11413 xx[2] = zaxis->GetXmax();
11414 xx[1] = yaxis->GetBinCenter(biny);
11415 view->WCtoNDC(xx,u);
11416 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11417 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11418 rect1[4].SetX(rect1[0].GetX());
11419 rect1[4].SetY(rect1[0].GetY());
11420 xx[0] = xaxis->GetXmax();
11421 view->WCtoNDC(xx,u);
11422 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11423 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11424 xx[2] = zaxis->GetXmin();
11425 view->WCtoNDC(xx,u);
11426 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11427 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11428 xx[0] = xaxis->GetXmin();
11429 view->WCtoNDC(xx,u);
11430 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11431 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11432 gVirtualX->DrawPolyLine(5,rect1);
11433 if (nbins>1) {
11434 xx[0] = xaxis->GetXmin();
11435 xx[2] = zaxis->GetXmax();
11436 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11437 view->WCtoNDC(xx,u);
11438 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11439 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11440 rect2[4].SetX(rect2[0].GetX());
11441 rect2[4].SetY(rect2[0].GetY());
11442 xx[0] = xaxis->GetXmax();
11443 view->WCtoNDC(xx,u);
11444 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11445 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11446 xx[2] = zaxis->GetXmin();
11447 view->WCtoNDC(xx,u);
11448 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11449 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11450 xx[0] = xaxis->GetXmin();
11451 view->WCtoNDC(xx,u);
11452 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11453 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11454 gVirtualX->DrawPolyLine(5,rect2);
11455 }
11456 c->Clear();
11457 c->cd();
11458 TH2 *hp = (TH2*)h3->Project3D("xz");
11459 yaxis->SetRange(first,last);
11460 if (hp) {
11461 hp->SetFillColor(38);
11462 if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11463 else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11464 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11465 hp->SetYTitle(fH->GetXaxis()->GetTitle());
11466 hp->SetZTitle("Number of Entries");
11467 hp->Draw(fShowOption.Data());
11468 }
11469 }
11470 break;
11471
11472 case 7:
11473 // "zx"
11474 {
11475 Int_t first = yaxis->GetFirst();
11476 Int_t last = yaxis->GetLast();
11477 Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11478 Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11479 yaxis->SetRange(biny,biny2);
11480 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11481 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11482 xx[0] = xaxis->GetXmin();
11483 xx[2] = zaxis->GetXmax();
11484 xx[1] = yaxis->GetBinCenter(biny);
11485 view->WCtoNDC(xx,u);
11486 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11487 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11488 rect1[4].SetX(rect1[0].GetX());
11489 rect1[4].SetY(rect1[0].GetY());
11490 xx[0] = xaxis->GetXmax();
11491 view->WCtoNDC(xx,u);
11492 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11493 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11494 xx[2] = zaxis->GetXmin();
11495 view->WCtoNDC(xx,u);
11496 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11497 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11498 xx[0] = xaxis->GetXmin();
11499 view->WCtoNDC(xx,u);
11500 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11501 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11502 gVirtualX->DrawPolyLine(5,rect1);
11503 if (nbins>1) {
11504 xx[0] = xaxis->GetXmin();
11505 xx[2] = zaxis->GetXmax();
11506 xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11507 view->WCtoNDC(xx,u);
11508 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11509 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11510 rect2[4].SetX(rect2[0].GetX());
11511 rect2[4].SetY(rect2[0].GetY());
11512 xx[0] = xaxis->GetXmax();
11513 view->WCtoNDC(xx,u);
11514 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11515 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11516 xx[2] = zaxis->GetXmin();
11517 view->WCtoNDC(xx,u);
11518 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11519 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11520 xx[0] = xaxis->GetXmin();
11521 view->WCtoNDC(xx,u);
11522 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11523 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11524 gVirtualX->DrawPolyLine(5,rect2);
11525 }
11526 c->Clear();
11527 c->cd();
11528 TH2 *hp = (TH2*)h3->Project3D("zx");
11529 yaxis->SetRange(first,last);
11530 if (hp) {
11531 hp->SetFillColor(38);
11532 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11533 else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11534 hp->SetXTitle(fH->GetXaxis()->GetTitle());
11535 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11536 hp->SetZTitle("Number of Entries");
11537 hp->Draw(fShowOption.Data());
11538 }
11539 }
11540 break;
11541
11542 case 8:
11543 // "yz"
11544 {
11545 Int_t first = xaxis->GetFirst();
11546 Int_t last = xaxis->GetLast();
11547 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11548 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11549 xaxis->SetRange(binx,binx2);
11550 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11551 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11552 xx[2] = zaxis->GetXmin();
11553 xx[1] = yaxis->GetXmax();
11554 xx[0] = xaxis->GetBinCenter(binx);
11555 view->WCtoNDC(xx,u);
11556 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11557 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11558 rect1[4].SetX(rect1[0].GetX());
11559 rect1[4].SetY(rect1[0].GetY());
11560 xx[2] = zaxis->GetXmax();
11561 view->WCtoNDC(xx,u);
11562 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11563 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11564 xx[1] = yaxis->GetXmin();
11565 view->WCtoNDC(xx,u);
11566 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11567 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11568 xx[2] = zaxis->GetXmin();
11569 view->WCtoNDC(xx,u);
11570 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11571 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11572 gVirtualX->DrawPolyLine(5,rect1);
11573 if (nbins>1) {
11574 xx[2] = zaxis->GetXmin();
11575 xx[1] = yaxis->GetXmax();
11576 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11577 view->WCtoNDC(xx,u);
11578 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11579 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11580 rect2[4].SetX(rect2[0].GetX());
11581 rect2[4].SetY(rect2[0].GetY());
11582 xx[2] = zaxis->GetXmax();
11583 view->WCtoNDC(xx,u);
11584 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11585 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11586 xx[1] = yaxis->GetXmin();
11587 view->WCtoNDC(xx,u);
11588 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11589 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11590 xx[2] = zaxis->GetXmin();
11591 view->WCtoNDC(xx,u);
11592 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11593 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11594 gVirtualX->DrawPolyLine(5,rect2);
11595 }
11596 c->Clear();
11597 c->cd();
11598 TH2 *hp = (TH2*)h3->Project3D("yz");
11599 xaxis->SetRange(first,last);
11600 if (hp) {
11601 hp->SetFillColor(38);
11602 if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11603 else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11604 hp->SetXTitle(fH->GetZaxis()->GetTitle());
11605 hp->SetYTitle(fH->GetYaxis()->GetTitle());
11606 hp->SetZTitle("Number of Entries");
11607 hp->Draw(fShowOption.Data());
11608 }
11609 }
11610 break;
11611
11612 case 9:
11613 // "zy"
11614 {
11615 Int_t first = xaxis->GetFirst();
11616 Int_t last = xaxis->GetLast();
11617 Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11618 Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11619 xaxis->SetRange(binx,binx2);
11620 if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11621 if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11622 xx[2] = zaxis->GetXmin();
11623 xx[1] = yaxis->GetXmax();
11624 xx[0] = xaxis->GetBinCenter(binx);
11625 view->WCtoNDC(xx,u);
11626 rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11627 rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11628 rect1[4].SetX(rect1[0].GetX());
11629 rect1[4].SetY(rect1[0].GetY());
11630 xx[2] = zaxis->GetXmax();
11631 view->WCtoNDC(xx,u);
11632 rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11633 rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11634 xx[1] = yaxis->GetXmin();
11635 view->WCtoNDC(xx,u);
11636 rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11637 rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11638 xx[2] = zaxis->GetXmin();
11639 view->WCtoNDC(xx,u);
11640 rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11641 rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11642 gVirtualX->DrawPolyLine(5,rect1);
11643 if (nbins>1) {
11644 xx[2] = zaxis->GetXmin();
11645 xx[1] = yaxis->GetXmax();
11646 xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11647 view->WCtoNDC(xx,u);
11648 rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11649 rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11650 rect2[4].SetX(rect2[0].GetX());
11651 rect2[4].SetY(rect2[0].GetY());
11652 xx[2] = zaxis->GetXmax();
11653 view->WCtoNDC(xx,u);
11654 rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11655 rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11656 xx[1] = yaxis->GetXmin();
11657 view->WCtoNDC(xx,u);
11658 rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11659 rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11660 xx[2] = zaxis->GetXmin();
11661 view->WCtoNDC(xx,u);
11662 rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11663 rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11664 gVirtualX->DrawPolyLine(5,rect2);
11665 }
11666 c->Clear();
11667 c->cd();
11668 TH2 *hp = (TH2*)h3->Project3D("zy");
11669 xaxis->SetRange(first,last);
11670 if (hp) {
11671 hp->SetFillColor(38);
11672 if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11673 else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11674 hp->SetXTitle(fH->GetYaxis()->GetTitle());
11675 hp->SetYTitle(fH->GetZaxis()->GetTitle());
11676 hp->SetZTitle("Number of Entries");
11677 hp->Draw(fShowOption.Data());
11678 }
11679 }
11680 break;
11681 }
11682 c->Update();
11683}
@ kMouseMotion
Definition Buttons.h:23
@ kWheelUp
Definition Buttons.h:18
@ kButton1Motion
Definition Buttons.h:20
@ kButton1Up
Definition Buttons.h:19
@ kWheelDown
Definition Buttons.h:18
@ kButton1Down
Definition Buttons.h:17
@ kButton1Locate
Definition Buttons.h:22
@ kArrowVer
Definition GuiTypes.h:374
@ kPointer
Definition GuiTypes.h:375
Handle_t Window_t
Window handle.
Definition GuiTypes.h:29
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
RooFitResult * fit(const char *options)
RooPlot * contour(RooRealVar &var1, RooRealVar &var2, double n1=1, double n2=2, double n3=0.0, double n4=0.0, double n5=0.0, double n6=0.0)
short Style_t
Definition RtypesCore.h:89
int Int_t
Definition RtypesCore.h:45
short Color_t
Definition RtypesCore.h:92
unsigned int UInt_t
Definition RtypesCore.h:46
short Width_t
Definition RtypesCore.h:91
float Float_t
Definition RtypesCore.h:57
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
double Double_t
Definition RtypesCore.h:59
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define BIT(n)
Definition Rtypes.h:85
#define ClassImp(name)
Definition Rtypes.h:377
@ kBlack
Definition Rtypes.h:65
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void pixel
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmin
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize wid
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint angle
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void xpos
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char backcolor
Option_t Option_t TPoint TPoint const char y2
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void ypos
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize fs
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t wmax
Option_t Option_t TPoint TPoint const char text
Option_t Option_t TPoint TPoint const char y1
R__EXTERN TH1 * gCurrentHist
R__EXTERN Hoption_t Hoption
float xmin
int ncx
float ymin
int ncy
float xmax
float ymax
static TString gStringStdDevZ
static TString gStringStdDevX
static TString gStringIntegralBinWidth
const UInt_t kCannotRotate
static TString gStringStdDev
const Int_t kNMAX
Hparam_t Hparam
const Int_t kMAXCONTOUR
static TString gStringOverflow
static TString gStringUnderflow
static TString gStringSkewnessY
static TString gStringMean
static TString gStringKurtosis
Hoption_t Hoption
static TString gStringMeanX
static TString gStringEntries
static TString gStringIntegral
static TString gStringKurtosisY
static TString gStringStdDevY
static TString gStringMeanY
static TString gStringSkewnessX
static TString gStringKurtosisX
static std::unique_ptr< TBox > gXHighlightBox
static std::unique_ptr< TBox > gYHighlightBox
static TString gStringSkewnessZ
TH1 * gCurrentHist
static TString gStringMeanZ
static TString gStringSkewness
static TString gStringKurtosisZ
const Int_t kMaxCuts
const Int_t kCYLINDRICAL
const Int_t kSPHERICAL
const Int_t kRAPIDITY
#define gROOT
Definition TROOT.h:405
R__EXTERN TStyle * gStyle
Definition TStyle.h:414
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
const Int_t kCARTESIAN
Definition TView3D.cxx:33
const Int_t kPOLAR
Definition TView3D.cxx:34
#define gPad
#define gVirtualX
Definition TVirtualX.h:338
polygon * polys
Definition X3DBuffer.c:24
Int_t fN
Definition TArray.h:38
Draw all kinds of Arrows.
Definition TArrow.h:29
virtual Int_t GetNdivisions() const
Definition TAttAxis.h:36
virtual Float_t GetLabelOffset() const
Definition TAttAxis.h:40
virtual Float_t GetLabelSize() const
Definition TAttAxis.h:41
virtual Float_t GetTickLength() const
Definition TAttAxis.h:45
virtual Float_t GetTitleOffset() const
Definition TAttAxis.h:43
virtual Color_t GetFillColor() const
Return the fill area color.
Definition TAttFill.h:30
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition TAttFill.h:31
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition TAttFill.h:39
virtual void SetImageQuality(EImageQuality lquality)
Definition TAttImage.h:99
virtual Color_t GetLineColor() const
Return the line color.
Definition TAttLine.h:33
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition TAttLine.h:42
virtual Width_t GetLineWidth() const
Return the line width.
Definition TAttLine.h:35
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition TAttLine.h:43
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition TAttLine.h:40
virtual Style_t GetLineStyle() const
Return the line style.
Definition TAttLine.h:34
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition TAttMarker.h:32
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition TAttMarker.h:38
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition TAttMarker.h:31
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition TAttMarker.h:33
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition TAttMarker.h:40
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition TAttMarker.h:45
static Style_t GetMarkerStyleBase(Style_t style)
Internal helper function that returns the corresponding marker style with line width 1 for the given ...
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition TAttText.h:42
virtual Font_t GetTextFont() const
Return the text font.
Definition TAttText.h:35
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition TAttText.h:43
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition TAttText.h:44
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition TAttText.h:46
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition TAttText.h:47
Class to manage histogram axis.
Definition TAxis.h:30
virtual Bool_t GetTimeDisplay() const
Definition TAxis.h:127
Bool_t IsAlphanumeric() const
Definition TAxis.h:84
const char * GetTitle() const override
Returns title of object.
Definition TAxis.h:130
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition TAxis.cxx:478
Bool_t CanExtend() const
Definition TAxis.h:82
const TArrayD * GetXbins() const
Definition TAxis.h:131
Double_t GetXmax() const
Definition TAxis.h:135
const char * GetBinLabel(Int_t bin) const
Return label for bin.
Definition TAxis.cxx:440
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:293
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition TAxis.cxx:518
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition TAxis.cxx:419
const char * ChooseTimeFormat(Double_t axislength=0)
Choose a reasonable time format from the coordinates in the active pad and the number of divisions in...
Definition TAxis.cxx:132
Int_t GetLast() const
Return last bin on the axis i.e.
Definition TAxis.cxx:469
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition TAxis.cxx:599
Double_t GetXmin() const
Definition TAxis.h:134
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:978
virtual const char * GetTimeFormat() const
Definition TAxis.h:128
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis using bin numbers.
Definition TAxis.cxx:952
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
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:662
Bool_t IsViolinScaled()
Definition TCandle.cxx:190
Bool_t IsHorizontal()
Definition TCandle.h:117
int ParseOption(char *optin)
Parsing of the option-string.
Definition TCandle.cxx:244
void SetOption(CandleOption opt)
Definition TCandle.h:122
void SetHistogram(TH1D *proj)
Definition TCandle.h:128
Bool_t IsCandleScaled()
Definition TCandle.cxx:185
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:2455
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition TClass.cxx:2968
void SetName(const char *name)
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
void Paint(Option_t *option="") override
Paint all objects in this collection.
The color creation and management class.
Definition TColor.h:19
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its associated colors.
Definition TColor.cxx:1759
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition TColor.h:79
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition TColor.h:52
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb",...
Definition TColor.cxx:1823
static Int_t GetColorBright(Int_t color)
Static function: Returns the bright color number corresponding to n If the TColor object does not exi...
Definition TColor.cxx:1970
static Int_t GetColorDark(Int_t color)
Static function: Returns the dark color number corresponding to n If the TColor object does not exist...
Definition TColor.cxx:2002
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition TColor.h:74
virtual void SetAlpha(Float_t a)
Definition TColor.h:68
To draw a Crown.
Definition TCrown.h:19
void Paint(Option_t *option="") override
Paint this crown with its current attributes.
Definition TCrown.cxx:179
Graphical cut class.
Definition TCutG.h:20
static TClass * Class()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
1-Dim function class
Definition TF1.h:213
virtual Double_t GetXmax() const
Definition TF1.h:561
static TClass * Class()
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn,...
Definition TF1.cxx:3392
virtual Double_t GetMaximumStored() const
Definition TF1.h:478
@ 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:3405
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:1440
virtual Double_t GetXmin() const
Definition TF1.h:557
A 2-Dim function with parameters.
Definition TF2.h:29
void Paint(Option_t *option="") override
Paint this 2-D function with its current attributes.
Definition TF2.cxx:744
void SetRange(Double_t xmin, Double_t xmax) override
Initialize the upper and lower bounds to draw the function.
Definition TF2.h:148
static TClass * Class()
A 3-Dim function with parameters.
Definition TF3.h:28
The axis painter class.
Definition TGaxis.h:23
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition TGaxis.cxx:2861
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:1013
void SetTitleOffset(Float_t titleoffset=1)
Definition TGaxis.h:127
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition TGaxis.cxx:2834
void SetLabelOffset(Float_t labeloffset)
Definition TGaxis.h:109
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition TGaxis.cxx:961
void SetTickSize(Float_t ticksize)
Definition TGaxis.h:121
void SetLabelSize(Float_t labelsize)
Definition TGaxis.h:110
void SetOption(Option_t *option="")
To set axis options.
Definition TGaxis.cxx:2826
Graphics object made of three arrays X, Y and Z with the same number of points each.
Definition TGraph2D.h:41
static TClass * Class()
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
static TClass * Class()
@ kClipFrame
Clip to the frame boundary.
Definition TGraph.h:74
1-D histogram with a double per channel (see TH1 documentation)}
Definition TH1.h:620
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:577
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:58
TAxis * GetZaxis()
Definition TH1.h:324
void SetTitle(const char *title) override
Change (i.e.
Definition TH1.cxx:6700
virtual EBinErrorOpt GetBinErrorOption() const
Definition TH1.h:271
virtual Float_t GetBarWidth() const
Definition TH1.h:255
virtual Double_t GetMinimumStored() const
Definition TH1.h:291
virtual Float_t GetBarOffset() const
Definition TH1.h:254
static TClass * Class()
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition TH1.cxx:7517
virtual Int_t GetNbinsY() const
Definition TH1.h:296
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition TH1.cxx:8929
virtual Int_t GetNbinsZ() const
Definition TH1.h:297
virtual Double_t GetNormFactor() const
Definition TH1.h:299
virtual Double_t GetMean(Int_t axis=1) const
For axis = 1,2 or 3 returns the mean value of the histogram along X,Y or Z axis.
Definition TH1.cxx:7445
virtual Double_t GetSkewness(Int_t axis=1) const
Definition TH1.cxx:7581
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition TH1.cxx:8306
virtual void SetXTitle(const char *title)
Definition TH1.h:415
virtual Int_t GetDimension() const
Definition TH1.h:281
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1267
@ kNoTitle
Don't draw the histogram title.
Definition TH1.h:168
@ kUserContour
User specified contour levels.
Definition TH1.h:164
@ kNoStats
Don't draw stats box.
Definition TH1.h:163
TAxis * GetXaxis()
Definition TH1.h:322
virtual Int_t GetBin(Int_t binx, Int_t biny=0, Int_t binz=0) const
Return Global bin number corresponding to binx,y,z.
Definition TH1.cxx:4925
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:8411
virtual Int_t GetNbinsX() const
Definition TH1.h:295
virtual void SetMaximum(Double_t maximum=-1111)
Definition TH1.h:400
TAxis * GetYaxis()
Definition TH1.h:323
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition TH1.cxx:8945
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3060
virtual void SetMinimum(Double_t minimum=-1111)
Definition TH1.h:401
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition TH1.cxx:7851
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:9088
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition TH1.cxx:9018
virtual Double_t GetEntries() const
Return the current number of entries.
Definition TH1.cxx:4419
virtual void SetZTitle(const char *title)
Definition TH1.h:417
TList * GetListOfFunctions() const
Definition TH1.h:242
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition TH1.cxx:7485
virtual Double_t GetMaximumStored() const
Definition TH1.h:287
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition TH1.cxx:8597
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition TH1.cxx:8443
@ 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:5025
virtual Int_t GetContour(Double_t *levels=nullptr)
Return contour values into array levels if pointer levels is non zero.
Definition TH1.cxx:8277
const Double_t * GetBuffer() const
Definition TH1.h:237
virtual Bool_t IsHighlight() const
Definition TH1.h:336
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition TH1.cxx:9029
virtual void SetContour(Int_t nlevels, const Double_t *levels=nullptr)
Set the number and values of contour levels.
Definition TH1.cxx:8349
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition TH1.cxx:8976
virtual void SetYTitle(const char *title)
Definition TH1.h:416
virtual Int_t GetSumw2N() const
Definition TH1.h:313
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition TH1.cxx:7565
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:8501
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition TH1.cxx:7827
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition TH1.cxx:735
virtual void LabelsDeflate(Option_t *axis="X")
Reduce the number of bins for the axis passed in the option to the number of bins having a label.
Definition TH1.cxx:5209
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition TH1.cxx:1387
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition TH1.cxx:7654
2-D histogram with a double per channel (see TH1 documentation)}
Definition TH2.h:300
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:257
Helper class to represent a bin in the TH2Poly histogram.
Definition TH2Poly.h:25
2D Histogram with Polygonal Bins
Definition TH2Poly.h:66
static TClass * Class()
Service class for 2-D histogram classes.
Definition TH2.h:30
TH1D * ProjectionY(const char *name="_py", Int_t firstxbin=0, Int_t lastxbin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along Y.
Definition TH2.cxx:2414
TH1D * ProjectionX(const char *name="_px", Int_t firstybin=0, Int_t lastybin=-1, Option_t *option="") const
Project a 2-D histogram into a 1-D histogram along X.
Definition TH2.cxx:2374
Double_t GetBinContent(Int_t binx, Int_t biny) const override
Definition TH2.h:89
static TClass * Class()
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH2.cxx:1270
The 3-D histogram classes derived from the 1-D histogram classes.
Definition TH3.h:31
static TClass * Class()
virtual TH1 * Project3D(Option_t *option="x") const
Project a 3-d histogram into 1 or 2-d histograms depending on the option parameter,...
Definition TH3.cxx:2363
Double_t Integral(Option_t *option="") const override
Return integral of bin contents.
Definition TH3.cxx:1348
The Histogram stack class.
Definition THStack.h:38
static TClass * Class()
The histogram painter class.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
void Paint(Option_t *option="") override
Control routine to paint any kind of histograms
TAxis * fYaxis
Pointer to Y axis.
std::unique_ptr< TPainter3dAlgorithms > fLego
Pointer to a TPainter3dAlgorithms object.
std::vector< Double_t > fXbuf
X buffer coordinates.
Int_t fXHighlightBin
X highlight bin.
TF3 * fCurrentF3
Current TF3 function.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
~THistPainter() override
destructor.
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
Int_t DistancetoPrimitive(Int_t px, Int_t py) override
Compute the distance from the point px,py to a line.
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintColorLevelsFast(Option_t *option)
[Rendering scheme for the COL2 and COLZ2 options] (HP14)
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
Int_t fYHighlightBin
Y highlight bin.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
Int_t fNcuts
Number of graphical cuts.
TString fShowOption
Option to draw the projection.
virtual void PaintHighlightBin(Option_t *option="")
Paint highlight bin as TBox object.
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins' contours.
virtual Int_t PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1, Double_t elev2, Int_t icont2, Double_t x2, Double_t y2, Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
Fill the matrix xarr and yarr for Contour Plot.
Int_t fShowProjection
True if a projection must be drawn.
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
virtual void HighlightBin(Int_t px, Int_t py)
Check on highlight bin.
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
Int_t MakeCuts(char *cutsopt) override
Decode string choptin and fill Graphical cuts structure.
TList * fFunctions
Pointer to histogram list of functions.
void DrawPanel() override
Display a panel with all histogram drawing options.
std::unique_ptr< TPie > fPie
Pointer to a TPie in case of option PIE.
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintTitle()
new TGaxis/////////////////// Draw the histogram title
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
virtual std::vector< THistRenderingRegion > ComputeRenderingRegions(TAxis *pAxis, Int_t nPixels, bool isLog)
Returns the rendering regions for an axis to use in the COL2 option.
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
TAxis * fXaxis
Pointer to X axis.
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
void PaintStat(Int_t dostat, TF1 *fit) override
Draw the statistics box for 1D and profile histograms.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
std::unique_ptr< TGraph2DPainter > fGraph2DPainter
Pointer to a TGraph2DPainter object.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
TList * fStack
Pointer to stack of histograms (if any)
THistPainter()
Default constructor.
TH1 * fH
Pointer to histogram to paint.
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
TAxis * fZaxis
Pointer to Z axis.
void SetHistogram(TH1 *h) override
Set current histogram to h
virtual void PaintFunction(Option_t *option)
[Paint functions associated to an histogram.](HP28")
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
char * GetObjectInfo(Int_t px, Int_t py) const override
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
TList * GetContourList(Double_t contour) const override
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
void ProcessMessage(const char *mess, const TObject *obj) override
Process message mess.
void SetShowProjection(const char *option, Int_t nbins) override
Set projection.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
static const char * GetBestFormat(Double_t v, Double_t e, const char *f)
This function returns the best format to print the error value (e) knowing the parameter value (v) an...
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
TCutG * fCuts[kMaxCuts]
Pointers to graphical cuts.
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
void ExecuteEvent(Int_t event, Int_t px, Int_t py) override
Execute the actions corresponding to event.
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Int_t fCutsOpt[kMaxCuts]
Sign of each cut.
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
std::vector< Double_t > fYbuf
Y buffer coordinates.
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
void SetHighlight() override
Set highlight (enable/disable) mode for fH.
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
TString fObjectInfo
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Bool_t IsInside(Int_t x, Int_t y) override
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
A class to define a conversion from pixel values to pixel color.
Definition TAttImage.h:33
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
An abstract interface to image processing library.
Definition TImage.h:29
static TImage * Create()
Create an image.
Definition TImage.cxx:35
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=nullptr)
Definition TImage.h:116
virtual void PaintImage(Drawable_t, Int_t, Int_t, Int_t=0, Int_t=0, UInt_t=0, UInt_t=0, Option_t *="")
Definition TImage.h:243
void Reset()
To draw Mathematical Formula.
Definition TLatex.h:18
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:578
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
TObject * First() const override
Return the first object in the list. Returns 0 when list is empty.
Definition TList.cxx:659
virtual TObjLink * FirstLink() const
Definition TList.h:102
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:470
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:100
TMatrixTBase.
static TClass * Class()
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition TMultiGraph.h:34
TList * GetListOfGraphs() const
Definition TMultiGraph.h:68
static TClass * Class()
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
Returns title of object.
Definition TNamed.h:48
An array of TObjects.
Definition TObjArray.h:31
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
void Add(TObject *obj) override
Definition TObjArray.h:68
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Clear(Option_t *="")
Definition TObject.h:119
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition TObject.cxx:423
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:956
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition TObject.cxx:403
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:774
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:525
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
virtual TClass * IsA() const
Definition TObject.h:245
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition TObject.cxx:601
@ kCannotPick
if object in a pad cannot be picked
Definition TObject.h:67
@ kCanDelete
if object in a list can be deleted
Definition TObject.h:62
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition TObject.h:64
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondence with function levels)
The palette painting class.
void Paint(Option_t *option="") override
Paint the palette.
void SetHistogram(TH1 *h)
TH1 * GetHistogram()
The histogram statistics painter class.
Definition TPaveStats.h:18
Int_t GetOptStat() const
Return the stat option.
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
void SetOptStat(Int_t stat=1)
Set the stat option.
virtual const char * GetFitFormat() const
Definition TPaveStats.h:35
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Int_t GetOptFit() const
Return the fit option.
void SetParent(TObject *obj) override
Definition TPaveStats.h:52
void SetOptFit(Int_t fit=1)
Set the fit option.
virtual const char * GetStatFormat() const
Definition TPaveStats.h:36
void Paint(Option_t *option="") override
Paint the pave stat.
static TClass * Class()
A Pave (see TPave) with text, lines or/and boxes inside.
Definition TPaveText.h:21
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
static TClass * Class()
void Clear(Option_t *option="") override
Clear all lines in this pavetext.
void Draw(Option_t *option="") override
Draw this pavetext with its current attributes.
void Paint(Option_t *option="") override
Paint this pavetext with its current attributes.
virtual TText * GetLine(Int_t number) const
Get Pointer to line number in this pavetext.
const char * GetName() const override
Returns name of object.
Definition TPave.h:56
virtual void SetName(const char *name="")
Definition TPave.h:75
virtual void SetBorderSize(Int_t bordersize=4)
Definition TPave.h:73
Double_t GetX1NDC() const
Definition TPave.h:59
virtual void SetX2NDC(Double_t x2)
Definition TPave.h:79
void SetX(SCoord_t x)
Definition TPoint.h:48
void SetY(SCoord_t y)
Definition TPoint.h:49
Profile2D histograms are used to display the mean value of Z and its error for each cell in X,...
Definition TProfile2D.h:27
static TClass * Class()
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Profile Histogram.
Definition TProfile.h:32
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition TProfile.cxx:834
static TClass * Class()
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition TRandom2.h:27
Double_t Rndm() override
TausWorth generator from L'Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition TRandom2.cxx:56
Sequenceable collection abstract base class.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
void ToLower()
Change string to lower-case.
Definition TString.cxx:1170
const char * Data() const
Definition TString.h:380
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2356
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2334
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
Int_t GetOptStat() const
Definition TStyle.h:237
Color_t GetStatTextColor() const
Definition TStyle.h:250
Float_t GetTitleX() const
Definition TStyle.h:272
Int_t GetOptTitle() const
Definition TStyle.h:238
Float_t GetStatFontSize() const
Definition TStyle.h:253
Float_t GetBarOffset() const
Definition TStyle.h:175
Float_t GetStatX() const
Definition TStyle.h:256
Float_t GetTitleSize(Option_t *axis="X") const
Return title size.
Definition TStyle.cxx:1189
Float_t GetTitleY() const
Definition TStyle.h:273
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition TStyle.cxx:1165
Bool_t GetHistMinimumZero() const
Definition TStyle.h:229
Float_t GetStatY() const
Definition TStyle.h:257
Color_t GetTitleFillColor() const
Definition TStyle.h:263
Style_t GetTitleStyle() const
Definition TStyle.h:265
Color_t GetStatColor() const
Definition TStyle.h:249
Float_t GetBarWidth() const
Definition TStyle.h:176
Float_t GetStatH() const
Definition TStyle.h:259
Width_t GetTitleBorderSize() const
Definition TStyle.h:267
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition TStyle.cxx:1057
Float_t GetErrorX() const
Definition TStyle.h:179
Double_t GetHistTopMargin() const
Definition TStyle.h:230
void SetBarOffset(Float_t baroff=0.5)
Definition TStyle.h:320
Float_t GetEndErrorSize() const
Definition TStyle.h:178
Width_t GetStatBorderSize() const
Definition TStyle.h:251
Int_t GetTitleAlign()
Definition TStyle.h:262
Color_t GetTitleTextColor() const
Definition TStyle.h:264
void SetBarWidth(Float_t barwidth=0.5)
Definition TStyle.h:321
Float_t GetTitleH() const
Definition TStyle.h:275
Style_t GetStatStyle() const
Definition TStyle.h:254
Float_t GetStatW() const
Definition TStyle.h:258
const char * GetFitFormat() const
Definition TStyle.h:192
const char * GetStatFormat() const
Definition TStyle.h:255
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition TStyle.cxx:1123
Int_t GetOptFit() const
Definition TStyle.h:236
Int_t GetNumberContours() const
Definition TStyle.h:233
const char * GetPaintTextFormat() const
Definition TStyle.h:242
Style_t GetStatFont() const
Definition TStyle.h:252
Float_t GetTitleFontSize() const
Definition TStyle.h:266
Float_t GetTitleW() const
Definition TStyle.h:274
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1858
Base class for several text objects.
Definition TText.h:22
TVectorT.
Definition TVectorT.h:27
static TClass * Class()
See TView3D.
Definition TView.h:25
virtual Double_t GetPsi()=0
virtual Double_t * GetRmax()=0
virtual void SetAxisNDC(const Double_t *x1, const Double_t *x2, const Double_t *y1, const Double_t *y2, const Double_t *z1, const Double_t *z2)=0
virtual Double_t * GetRmin()=0
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual void SetOutlineToCube()=0
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
virtual Double_t * GetTnorm()=0
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
virtual TSeqCollection * GetOutline()=0
virtual void PadRange(Int_t rback)=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
Abstract base class used by ROOT graphics editor.
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
virtual void Show()
small helper class to store/restore gPad context in TPad methods
Definition TVirtualPad.h:61
auto GetSaved() const
Definition TVirtualPad.h:69
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
TLine * line
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition fillpatterns.C:1
Double_t y[n]
Definition legend1.C:17
return c1
Definition legend1.C:41
Double_t x[n]
Definition legend1.C:17
Double_t ey[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition TMath.h:691
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:250
Double_t Prob(Double_t chi2, Int_t ndf)
Computation of the probability for a certain Chi-squared (chi2) and number of degrees of freedom (ndf...
Definition TMath.cxx:637
Double_t ATan(Double_t)
Returns the principal value of the arc tangent of x, expressed in radians.
Definition TMath.h:638
constexpr Double_t PiOver2()
Definition TMath.h:51
Double_t Log(Double_t x)
Returns the natural logarithm of x.
Definition TMath.h:754
constexpr Double_t DegToRad()
Conversion from degree to radian: .
Definition TMath.h:79
Double_t Sqrt(Double_t x)
Returns the square root of x.
Definition TMath.h:660
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:719
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:198
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Definition TMath.h:592
constexpr Double_t Pi()
Definition TMath.h:37
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Comparing floating points.
Definition TMath.h:425
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Definition TMath.h:586
Double_t Tan(Double_t)
Returns the tangent of an angle of x radians.
Definition TMath.h:598
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Binary search in an array of n values to locate value.
Definition TMathBase.h:347
constexpr Double_t RadToDeg()
Conversion from radian to degree: .
Definition TMath.h:72
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:760
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:123
Definition first.py:1
Definition graph.py:1
Histograms' drawing options structure.
Definition Hoption.h:24
int Curve
"C" A smooth Curve is drawn.
Definition Hoption.h:32
int Proj
"AITOFF", "MERCATOR", "SINUSOIDAL" and "PARABOLIC" projections for 2d plots.
Definition Hoption.h:59
int Axis
"A" Axis are not drawn around the graph.
Definition Hoption.h:30
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition Hoption.h:41
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition Hoption.h:48
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition Hoption.h:50
int Color
"COL" Draw 2D plot with Colored boxes.
Definition Hoption.h:43
int AxisPos
"X+" and "Y+" Axis position
Definition Hoption.h:60
int List
"LIST" Generate the TObjArray "contours". To be used with option "CONT"
Definition Hoption.h:58
int Logx
log scale in X. Also set by histogram option
Definition Hoption.h:70
int Zscale
"Z" Display the color palette.
Definition Hoption.h:55
int MinimumZero
"MIN0" or gStyle->GetHistMinimumZero()
Definition Hoption.h:63
int Contour
"CONTn" Draw 2D plot as a Contour plot (0 <= n <= 5).
Definition Hoption.h:44
int Off
"][" The first and last vertical lines are not drawn.
Definition Hoption.h:35
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition Hoption.h:45
long Candle
"CANDLE" and "VIOLIN" Draw a 2D histogram as candle/box plot or violin plot.
Definition Hoption.h:53
int Spec
"SPEC" TSpectrum graphics
Definition Hoption.h:61
int FrontBox
"FB" Suppress the front box for the 3D plots.
Definition Hoption.h:56
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition Hoption.h:52
int Star
"*" With option "P", a * is plotted at each point.
Definition Hoption.h:39
int Zero
"0" if selected with any LEGO option the empty bins are not drawn.
Definition Hoption.h:62
int Logz
log scale in Z. Also set by histogram option
Definition Hoption.h:72
int Tri
"TRI" Draw TGraph2D with Delaunay triangles.
Definition Hoption.h:51
int BackBox
"BB" Suppress the back box for the 3D plots.
Definition Hoption.h:57
int Mark
"P" The current Marker is drawn at each point.
Definition Hoption.h:37
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition Hoption.h:40
int Line
"L" A simple polyline through every point is drawn.
Definition Hoption.h:36
int Same
"SAME" Histogram is plotted in the current pad.
Definition Hoption.h:38
int Lego
"LEGO" and "LEGOn" Draw as a Lego plot(1 <= n <= 4).
Definition Hoption.h:47
int Bar
"B", "BAR" and "HBAR" A Bar chart is drawn at each point.
Definition Hoption.h:31
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition Hoption.h:34
int Hist
"HIST" Draw only the histogram.
Definition Hoption.h:46
int Surf
"SURF" and "SURFn" Draw as a Surface ((1 <= n <= 4).
Definition Hoption.h:49
int Logy
log scale in Y. Also set by histogram option
Definition Hoption.h:71
int System
"POL", "CYL", "SPH" and "PSR" Type of coordinate system for 3D plots.
Definition Hoption.h:54
int Error
"En" Draw Errors with current marker type and size (0 <= n <=6).
Definition Hoption.h:33
Histogram parameters structure.
Definition Hparam.h:27
Double_t baroffset
Offset of bin for bars or legos [0,1].
Definition Hparam.h:42
Double_t ylowedge
Low edge of axis.
Definition Hparam.h:33
Double_t xmin
Minimum value along X.
Definition Hparam.h:30
Int_t ylast
Last bin number along Y.
Definition Hparam.h:47
Int_t xfirst
First bin number along X.
Definition Hparam.h:44
Double_t zmin
Minimum value along Z.
Definition Hparam.h:38
Double_t xbinsize
Bin size in case of equidistant bins.
Definition Hparam.h:28
Double_t ymin
Minimum value along y.
Definition Hparam.h:34
Double_t allchan
Integrated sum of contents.
Definition Hparam.h:41
Double_t xlowedge
Low edge of axis.
Definition Hparam.h:29
Double_t ymax
Maximum value along y.
Definition Hparam.h:35
Double_t factor
Multiplication factor (normalization)
Definition Hparam.h:40
Int_t xlast
Last bin number along X.
Definition Hparam.h:45
Double_t ybinsize
Bin size in case of equidistant bins.
Definition Hparam.h:32
Double_t barwidth
Width of bin for bars and legos [0,1].
Definition Hparam.h:43
Double_t zmax
Maximum value along Z.
Definition Hparam.h:39
Double_t xmax
Maximum value along X.
Definition Hparam.h:31
Int_t yfirst
First bin number along Y.
Definition Hparam.h:46
auto * th2
Definition textalign.C:18
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4
auto * tt
Definition textangle.C:16
#define mark(osub)
Definition triangle.c:1207