Logo ROOT   6.12/07
Reference Guide
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 <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 
17 #include "Riostream.h"
18 #include "TROOT.h"
19 #include "TClass.h"
20 #include "TSystem.h"
21 #include "THistPainter.h"
22 #include "TH2.h"
23 #include "TH2Poly.h"
24 #include "TH3.h"
25 #include "TProfile.h"
26 #include "TProfile2D.h"
27 #include "THStack.h"
28 #include "TF2.h"
29 #include "TF3.h"
30 #include "TCutG.h"
31 #include "TMatrixDBase.h"
32 #include "TMatrixFBase.h"
33 #include "TVectorD.h"
34 #include "TVectorF.h"
35 #include "TCanvas.h"
36 #include "TPad.h"
37 #include "TPaveStats.h"
38 #include "TFrame.h"
39 #include "TLatex.h"
40 #include "TLine.h"
41 #include "TPolyLine.h"
42 #include "TPoints.h"
43 #include "TStyle.h"
44 #include "TGraph.h"
45 #include "TMultiGraph.h"
46 #include "TPie.h"
47 #include "TGaxis.h"
48 #include "TColor.h"
49 #include "TPainter3dAlgorithms.h"
50 #include "TGraph2DPainter.h"
51 #include "TGraphDelaunay2D.h"
52 #include "TView.h"
53 #include "TMath.h"
54 #include "TRandom2.h"
55 #include "TObjArray.h"
56 #include "TVectorD.h"
57 #include "Hoption.h"
58 #include "Hparam.h"
59 #include "TPluginManager.h"
60 #include "TPaletteAxis.h"
61 #include "TCrown.h"
62 #include "TVirtualPadEditor.h"
63 #include "TEnv.h"
64 #include "TPoint.h"
65 #include "TImage.h"
66 #include "TCandle.h"
67 
68 /*! \class THistPainter
69 \ingroup Histpainter
70 \brief The histogram painter class. Implements all histograms' drawing's options.
71 
72 - [Introduction](#HP00)
73 - [Histograms' plotting options](#HP01)
74  - [Options supported for 1D and 2D histograms](#HP01a)
75  - [Options supported for 1D histograms](#HP01b)
76  - [Options supported for 2D histograms](#HP01c)
77  - [Options supported for 3D histograms](#HP01d)
78  - [Options supported for histograms' stacks (THStack)](#HP01e)
79 - [Setting the Style](#HP02)
80 - [Setting line, fill, marker, and text attributes](#HP03)
81 - [Setting Tick marks on the histogram axis](#HP04)
82 - [Giving titles to the X, Y and Z axis](#HP05)
83 - [The option "SAME"](#HP060)
84  - [Limitations](#HP060a)
85 - [Colors automatically picked in palette](#HP061)
86 - [Superimposing two histograms with different scales in the same pad](#HP06)
87 - [Statistics Display](#HP07)
88 - [Fit Statistics](#HP08)
89 - [The error bars options](#HP09)
90 - [The bar chart option](#HP100)
91 - [The "BAR" and "HBAR" options](#HP10)
92 - [The SCATter plot option (default for 2D histograms)](#HP11)
93 - [The ARRow option](#HP12)
94 - [The BOX option](#HP13)
95 - [The COLor option](#HP14)
96 - [The CANDLE and VIOLIN options](#HP140)
97  - [The CANDLE option](#HP140a)
98  - [The VIOLIN option](#HP140b)
99 - [The TEXT and TEXTnn Option](#HP15)
100 - [The CONTour options](#HP16)
101  - [The LIST option](#HP16a)
102 - [The LEGO options](#HP17)
103 - [The "SURFace" options](#HP18)
104 - [Cylindrical, Polar, Spherical and PseudoRapidity/Phi options](#HP19)
105 - [Base line for bar-charts and lego plots](#HP20)
106 - [TH2Poly Drawing](#HP20a)
107 - [The SPEC option](#HP21)
108 - [Option "Z" : Adding the color palette on the right side of the pad](#HP22)
109 - [Setting the color palette](#HP23)
110 - [Drawing a sub-range of a 2-D histogram; the [cutg] option](#HP24)
111 - [Drawing options for 3D histograms](#HP25)
112 - [Drawing option for histograms' stacks](#HP26)
113 - [Drawing of 3D implicit functions](#HP27)
114 - [Associated functions drawing](#HP28)
115 - [Drawing using OpenGL](#HP29)
116  - [General information: plot types and supported options](#HP29a)
117  - [TH3 as color boxes](#HP290)
118  - [TH3 as boxes (spheres)](#HP29b)
119  - [TH3 as iso-surface(s)](#HP29c)
120  - [TF3 (implicit function)](#HP29d)
121  - [Parametric surfaces](#HP29e)
122  - [Interaction with the plots](#HP29f)
123  - [Selectable parts](#HP29g)
124  - [Rotation and zooming](#HP29h)
125  - [Panning](#HP29i)
126  - [Box cut](#HP29j)
127  - [Plot specific interactions (dynamic slicing etc.)](#HP29k)
128  - [Surface with option "GLSURF"](#HP29l)
129  - [TF3](#HP29m)
130  - [Box](#HP29n)
131  - [Iso](#HP29o)
132  - [Parametric plot](#HP29p)
133 
134 
135 ## <a name="HP00"></a> Introduction
136 
137 
138 Histograms are drawn via the `THistPainter` class. Each histogram has a
139 pointer to its own painter (to be usable in a multithreaded program). When the
140 canvas has to be redrawn, the `Paint` function of each objects in the
141 pad is called. In case of histograms, `TH1::Paint` invokes directly
142 `THistPainter::Paint`.
143 
144 To draw a histogram `h` it is enough to do:
145 
146  h->Draw();
147 
148 `h` can be of any kind: 1D, 2D or 3D. To choose how the histogram will
149 be drawn, the `Draw()` method can be invoked with an option. For instance
150 to draw a 2D histogram as a lego plot it is enough to do:
151 
152  h->Draw("lego");
153 
154 `THistPainter` offers many options to paint 1D, 2D and 3D histograms.
155 
156 When the `Draw()` method of a histogram is called for the first time
157 (`TH1::Draw`), it creates a `THistPainter` object and saves a
158 pointer to this "painter" as a data member of the histogram. The
159 `THistPainter` class specializes in the drawing of histograms. It is
160 separated from the histogram so that one can have histograms without the
161 graphics overhead, for example in a batch program. Each histogram having its own
162 painter (rather than a central singleton painter painting all histograms), allows
163 two histograms to be drawn in two threads without overwriting the painter's
164 values.
165 
166 When a displayed histogram is filled again, there is no need to call the
167 `Draw()` method again; the image will be refreshed the next time the
168 pad will be updated.
169 
170 A pad is updated after one of these three actions:
171 
172 1. a carriage control on the ROOT command line,
173 2. a click inside the pad,
174 3. a call to `TPad::Update`.
175 
176 
177 By default a call to `TH1::Draw()` clears the pad of all objects
178 before drawing the new image of the histogram. One can use the `SAME`
179 option to leave the previous display intact and superimpose the new histogram.
180 The same histogram can be drawn with different graphics options in different
181 pads.
182 
183 When a displayed histogram is deleted, its image is automatically removed
184 from the pad.
185 
186 To create a copy of the histogram when drawing it, one can use
187 `TH1::DrawClone()`. This will clone the histogram and allow to change
188 and delete the original one without affecting the clone.
189 
190 
191 ### <a name="HP01"></a> Histograms' plotting options
192 
193 
194 Most options can be concatenated with or without spaces or commas, for example:
195 
196  h->Draw("E1 SAME");
197 
198 The options are not case sensitive:
199 
200  h->Draw("e1 same");
201 
202 
203 The default drawing option can be set with `TH1::SetOption` and retrieve
204 using `TH1::GetOption`:
205 
206  root [0] h->Draw(); // Draw "h" using the standard histogram representation.
207  root [1] h->Draw("E"); // Draw "h" using error bars
208  root [3] h->SetOption("E"); // Change the default drawing option for "h"
209  root [4] h->Draw(); // Draw "h" using error bars
210  root [5] h->GetOption(); // Retrieve the default drawing option for "h"
211  (const Option_t* 0xa3ff948)"E"
212 
213 
214 #### <a name="HP01a"></a> Options supported for 1D and 2D histograms
215 
216 | Option | Description |
217 |----------|-------------------------------------------------------------------|
218 | "E" | Draw error bars. |
219 | "AXIS" | Draw only axis. |
220 | "AXIG" | Draw only grid (if the grid is requested). |
221 | <a name="OPTHIST">"HIST"</a> | When an histogram has errors it is visualized by default with error bars. To visualize it without errors use the option "HIST" together with the required option (eg "hist same c"). The "HIST" option can also be used to plot only the histogram and not the associated function(s). |
222 | "FUNC" | When an histogram has a fitted function, this option allows to draw the fit result only. |
223 | "SAME" | Superimpose on previous picture in the same pad. |
224 | "PFC" | Palette Fill Color: histogram's fill color is taken in the current palette. |
225 | "PLC" | Palette Line Color: histogram's line color is taken in the current palette. |
226 | "PMC" | Palette Marker Color: histogram's marker color is taken in the current palette. |
227 | "LEGO" | Draw a lego plot with hidden line removal. |
228 | "LEGO1" | Draw a lego plot with hidden surface removal. |
229 | "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.|
230 | "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
231 | "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
232 | "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
233 | "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90). |
234 | "X+" | The X-axis is drawn on the top side of the plot. |
235 | "Y+" | The Y-axis is drawn on the right side of the plot. |
236 
237 #### <a name="HP01b"></a> Options supported for 1D histograms
238 
239 | Option | Description |
240 |----------|-------------------------------------------------------------------|
241 | " " | Default. |
242 | "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.|
243 | "][" | When this option is selected the first and last vertical lines of the histogram are not drawn.|
244 | "B" | Bar chart option.|
245 | "BAR" | Like option "B", but bars can be drawn with a 3D effect.|
246 | "HBAR" | Like option "BAR", but bars are drawn horizontally.|
247 | "C" | Draw a smooth Curve through the histogram bins.|
248 | "E0" | Draw error bars. Markers are drawn for bins with 0 contents.|
249 | "E1" | Draw error bars with perpendicular lines at the edges.|
250 | "E2" | Draw error bars with rectangles.|
251 | "E3" | Draw a fill area through the end points of the vertical error bars.|
252 | "E4" | Draw a smoothed filled area through the end points of the error bars.|
253 | "E5" | Like E3 but ignore the bins with 0 contents.|
254 | "E6" | Like E4 but ignore the bins with 0 contents.|
255 | "X0" | When used with one of the "E" option, it suppress the error bar along X as `gStyle->SetErrorX(0)` would do.|
256 | "L" | Draw a line through the bin contents.|
257 | "P" | Draw current marker at each bin except empty bins.|
258 | "P0" | Draw current marker at each bin including empty bins.|
259 | "PIE" | Draw histogram as a Pie Chart.|
260 | "*H" | Draw histogram with a * at each bin.|
261 | "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.|
262 
263 
264 #### <a name="HP01c"></a> Options supported for 2D histograms
265 
266 | Option | Description |
267 |-----------|------------------------------------------------------------------|
268 | " " | Default (scatter plot).|
269 | "ARR" | Arrow mode. Shows gradient between adjacent cells.|
270 | "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.|
271 | "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.|
272 | "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.|
273 | "COLZ" | Same as "COL". In addition the color palette is also drawn.|
274 | "COL2" | Alternative rendering algorithm to "COL". Can significantly improve rendering performance for large, non-sparse 2-D histograms.|
275 | "COLZ2" | Same as "COL2". In addition the color palette is also drawn.|
276 | "CANDLE" | Draw a candle plot along X axis.|
277 | "CANDLEX" | Same as "CANDLE".|
278 | "CANDLEY" | Draw a candle plot along Y axis.|
279 | "CANDLEXn"| Draw a candle plot along X axis. Different candle-styles with n from 1 to 6.|
280 | "CANDLEYn"| Draw a candle plot along Y axis. Different candle-styles with n from 1 to 6.|
281 | "VIOLIN" | Draw a violin plot along X axis.|
282 | "VIOLINX" | Same as "VIOLIN".|
283 | "VIOLINY" | Draw a violin plot along Y axis.|
284 | "VIOLINXn"| Draw a violin plot along X axis. Different violin-styles with n being 1 or 2.|
285 | "VIOLINYn"| Draw a violin plot along Y axis. Different violin-styles with n being 1 or 2.|
286 | "CONT" | Draw a contour plot (same as CONT0).|
287 | "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
288 | "CONT1" | Draw a contour plot using line styles to distinguish contours.|
289 | "CONT2" | Draw a contour plot using the same line style for all contours.|
290 | "CONT3" | Draw a contour plot using fill area colors.|
291 | "CONT4" | Draw a contour plot using surface colors (SURF option at theta = 0).|
292 | "CONT5" | (TGraph2D only) Draw a contour plot using Delaunay triangles.|
293 | "LIST" | Generate a list of TGraph objects for each contour.|
294 | "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
295 | "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
296 | "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
297 | "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
298 | "SURF" | Draw a surface plot with hidden line removal.|
299 | "SURF1" | Draw a surface plot with hidden surface removal.|
300 | "SURF2" | Draw a surface plot using colors to show the cell contents.|
301 | "SURF3" | Same as SURF with in addition a contour view drawn on the top.|
302 | "SURF4" | Draw a surface using Gouraud shading.|
303 | "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.|
304 | "LEGO9" | Draw the 3D axis only. Mainly needed for internal use |
305 | "FB" | With LEGO or SURFACE, suppress the Front-Box.|
306 | "BB" | With LEGO or SURFACE, suppress the Back-Box.|
307 | "A" | With LEGO or SURFACE, suppress the axis.|
308 | "SCAT" | Draw a scatter-plot (default).|
309 | "[cutg]" | Draw only the sub-range selected by the TCutG named "cutg".|
310 
311 
312 #### <a name="HP01d"></a> Options supported for 3D histograms
313 
314 | Option | Description |
315 |----------|-------------------------------------------------------------------|
316 | " " | Default (scatter plot).|
317 | "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)`.|
318 | "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
319 | "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
320 | "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
321 | "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
322 | "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
323 | "LEGO" | Same as `BOX`.|
324 
325 
326 #### <a name="HP01e"></a> Options supported for histograms' stacks (`THStack`)
327 
328 | Option | Description |
329 |------------|-----------------------------------------------------------------|
330 | " " | Default, the histograms are drawn on top of each other (as lego plots for 2D histograms).|
331 | "NOSTACK" | Histograms in the stack are all paint in the same pad as if the option `SAME` had been specified.|
332 | "NOSTACKB" | Histograms are drawn next to each other as bar charts.|
333 | "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.|
334 | "PFC" | Palette Fill Color: stack's fill color is taken in the current palette. |
335 | "PLC" | Palette Line Color: stack's line color is taken in the current palette. |
336 | "PMC" | Palette Marker Color: stack's marker color is taken in the current palette. |
337 
338 
339 
340 ### <a name="HP02"></a> Setting the Style
341 
342 
343 Histograms use the current style (`gStyle`). When one changes the current
344 style and would like to propagate the changes to the histogram,
345 `TH1::UseCurrentStyle` should be called. Call `UseCurrentStyle` on
346 each histogram is needed.
347 
348 To force all the histogram to use the current style use:
349 
350  gROOT->ForceStyle();
351 
352 All the histograms read after this call will use the current style.
353 
354 
355 ### <a name="HP03"></a> Setting line, fill, marker, and text attributes
356 
357 
358 The histogram classes inherit from the attribute classes:
359 `TAttLine`, `TAttFill` and `TAttMarker`.
360 See the description of these classes for the list of options.
361 
362 
363 ### <a name="HP04"></a> Setting Tick marks on the histogram axis
364 
365 
366 The `TPad::SetTicks` method specifies the type of tick marks on the axis.
367 If ` tx = gPad->GetTickx()` and `ty = gPad->GetTicky()` then:
368 
369  tx = 1; tick marks on top side are drawn (inside)
370  tx = 2; tick marks and labels on top side are drawn
371  ty = 1; tick marks on right side are drawn (inside)
372  ty = 2; tick marks and labels on right side are drawn
373 
374 By default only the left Y axis and X bottom axis are drawn
375 (`tx = ty = 0`)
376 
377 `TPad::SetTicks(tx,ty)` allows to set these options.
378 See also The `TAxis` functions to set specific axis attributes.
379 
380 In case multiple color filled histograms are drawn on the same pad, the fill
381 area may hide the axis tick marks. One can force a redraw of the axis over all
382 the histograms by calling:
383 
384  gPad->RedrawAxis();
385 
386 
387 ### <a name="HP05"></a> Giving titles to the X, Y and Z axis
388 
389 
390  h->GetXaxis()->SetTitle("X axis title");
391  h->GetYaxis()->SetTitle("Y axis title");
392 
393 The histogram title and the axis titles can be any `TLatex` string.
394 The titles are part of the persistent histogram.
395 
396 
397 ### <a name="HP060"></a> The option "SAME"
398 
399 
400 By default, when an histogram is drawn, the current pad is cleared before
401 drawing. In order to keep the previous drawing and draw on top of it the
402 option `SAME` should be use. The histogram drawn with the option
403 `SAME` uses the coordinates system available in the current pad.
404 
405 This option can be used alone or combined with any valid drawing option but
406 some combinations must be use with care.
407 
408 #### <a name="HP060a"></a> Limitations
409 
410 - It does not work when combined with the `LEGO` and `SURF` options unless the
411  histogram plotted with the option `SAME` has exactly the same
412  ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
413  lego plots [histograms' stacks](#HP26) should be used.</li>
414 
415 
416 ### <a name="HP061"></a> Colors automatically picked in palette
417 
418 \since **ROOT version 6.09/01**
419 
420 When several histograms are painted in the same canvas thanks to the option "SAME"
421 or via a `THStack` it might be useful to have an easy and automatic way to choose
422 their color. The simplest way is to pick colors in the current active color
423 palette. Palette coloring for histogram is activated thanks to the options `PFC`
424 (Palette Fill Color), `PLC` (Palette Line Color) and `PMC` (Palette Marker Color).
425 When one of these options is given to `TH1::Draw` the histogram get its color
426 from the current color palette defined by `gStyle->SetPalette(…)`. The color
427 is determined according to the number of objects having palette coloring in
428 the current pad.
429 
430 Begin_Macro(source)
431 ../../../tutorials/hist/histpalettecolor.C
432 End_Macro
433 
434 Begin_Macro(source)
435 ../../../tutorials/hist/thstackpalettecolor.C
436 End_Macro
437 
438 Begin_Macro(source)
439 ../../../tutorials/hist/thstack2palettecolor.C
440 End_Macro
441 
442 ### <a name="HP06"></a> Superimposing two histograms with different scales in the same pad
443 
444 
445 The following example creates two histograms, the second histogram is the bins
446 integral of the first one. It shows a procedure to draw the two histograms in
447 the same pad and it draws the scale of the second histogram using a new vertical
448 axis on the right side. See also the tutorial `transpad.C` for a variant
449 of this example.
450 
451 Begin_Macro(source)
452 {
453  TCanvas *c1 = new TCanvas("c1","c1",600,400);
454  // create/fill draw h1
455  gStyle->SetOptStat(kFALSE);
456  TH1F *h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
457  Int_t i;
458  for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
459  h1->Draw();
460  c1->Update();
461 
462  // create hint1 filled with the bins integral of h1
463  TH1F *hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
464  Float_t sum = 0;
465  for (i=1;i<=100;i++) {
466  sum += h1->GetBinContent(i);
467  hint1->SetBinContent(i,sum);
468  }
469 
470  // scale hint1 to the pad coordinates
471  Float_t rightmax = 1.1*hint1->GetMaximum();
472  Float_t scale = gPad->GetUymax()/rightmax;
473  hint1->SetLineColor(kRed);
474  hint1->Scale(scale);
475  hint1->Draw("same");
476 
477  // draw an axis on the right side
478  TGaxis *axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
479  gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
480  axis->SetLineColor(kRed);
481  axis->SetTextColor(kRed);
482  axis->Draw();
483  return c1;
484 }
485 End_Macro
486 
487 
488 ### <a name="HP07"></a> Statistics Display
489 
490 
491 The type of information shown in the histogram statistics box can be selected
492 with:
493 
494  gStyle->SetOptStat(mode);
495 
496 The `mode` has up to nine digits that can be set to on (1 or 2), off (0).
497 
498  mode = ksiourmen (default = 000001111)
499  k = 1; kurtosis printed
500  k = 2; kurtosis and kurtosis error printed
501  s = 1; skewness printed
502  s = 2; skewness and skewness error printed
503  i = 1; integral of bins printed
504  i = 2; integral of bins with option "width" printed
505  o = 1; number of overflows printed
506  u = 1; number of underflows printed
507  r = 1; standard deviation printed
508  r = 2; standard deviation and standard deviation error printed
509  m = 1; mean value printed
510  m = 2; mean and mean error values printed
511  e = 1; number of entries printed
512  n = 1; name of histogram is printed
513 
514 For example:
515 
516  gStyle->SetOptStat(11);
517 
518 displays only the name of histogram and the number of entries, whereas:
519 
520  gStyle->SetOptStat(1101);
521 
522 displays the name of histogram, mean value and standard deviation.
523 
524 <b>WARNING 1:</b> never do:
525 
526  gStyle->SetOptStat(0001111);
527 
528 but instead do:
529 
530  gStyle->SetOptStat(1111);
531 
532 because `0001111` will be taken as an octal number!
533 
534 <b>WARNING 2:</b> for backward compatibility with older versions
535 
536  gStyle->SetOptStat(1);
537 
538 is taken as:
539 
540  gStyle->SetOptStat(1111)
541 
542 To print only the name of the histogram do:
543 
544  gStyle->SetOptStat(1000000001);
545 
546 <b>NOTE</b> that in case of 2D histograms, when selecting only underflow
547 (10000) or overflow (100000), the statistics box will show all combinations
548 of underflow/overflows and not just one single number.
549 
550 The parameter mode can be any combination of the letters `kKsSiIourRmMen`
551 
552  k : kurtosis printed
553  K : kurtosis and kurtosis error printed
554  s : skewness printed
555  S : skewness and skewness error printed
556  i : integral of bins printed
557  I : integral of bins with option "width" printed
558  o : number of overflows printed
559  u : number of underflows printed
560  r : standard deviation printed
561  R : standard deviation and standard deviation error printed
562  m : mean value printed
563  M : mean value mean error values printed
564  e : number of entries printed
565  n : name of histogram is printed
566 
567 For example, to print only name of histogram and number of entries do:
568 
569  gStyle->SetOptStat("ne");
570 
571 To print only the name of the histogram do:
572 
573  gStyle->SetOptStat("n");
574 
575 The default value is:
576 
577  gStyle->SetOptStat("nemr");
578 
579 When a histogram is painted, a `TPaveStats` object is created and added
580 to the list of functions of the histogram. If a `TPaveStats` object
581 already exists in the histogram list of functions, the existing object is just
582 updated with the current histogram parameters.
583 
584 Once a histogram is painted, the statistics box can be accessed using
585 `h->FindObject("stats")`. In the command line it is enough to do:
586 
587  Root > h->Draw()
588  Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
589 
590 because after `h->Draw()` the histogram is automatically painted. But
591 in a script file the painting should be forced using `gPad->Update()`
592 in order to make sure the statistics box is created:
593 
594  h->Draw();
595  gPad->Update();
596  TPaveStats *st = (TPaveStats*)h->FindObject("stats");
597 
598 Without `gPad->Update()` the line `h->FindObject("stats")` returns a null pointer.
599 
600 When a histogram is drawn with the option `SAME`, the statistics box
601 is not drawn. To force the statistics box drawing with the option
602 `SAME`, the option `SAMES` must be used.
603 If the new statistics box hides the previous statistics box, one can change
604 its position with these lines (`h` being the pointer to the histogram):
605 
606  Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
607  Root > st->SetX1NDC(newx1); //new x start position
608  Root > st->SetX2NDC(newx2); //new x end position
609 
610 To change the type of information for an histogram with an existing
611 `TPaveStats` one should do:
612 
613  st->SetOptStat(mode);
614 
615 Where `mode` has the same meaning than when calling `gStyle->SetOptStat(mode)`
616 (see above).
617 
618 One can delete the statistics box for a histogram `TH1* h` with:
619 
620  h->SetStats(0)
621 
622 and activate it again with:
623 
624  h->SetStats(1).
625 
626 Labels used in the statistics box ("Mean", "Std Dev", ...) can be changed from
627 `$ROOTSYS/etc/system.rootrc` or `.rootrc` (look for the string `Hist.Stats.`).
628 
629 
630 ### <a name="HP08"></a> Fit Statistics
631 
632 
633 The type of information about fit parameters printed in the histogram statistics
634 box can be selected via the parameter mode. The parameter mode can be
635 `= pcev` (default `= 0111`)
636 
637  p = 1; print Probability
638  c = 1; print Chisquare/Number of degrees of freedom
639  e = 1; print errors (if e=1, v must be 1)
640  v = 1; print name/values of parameters
641 
642 Example:
643 
644  gStyle->SetOptFit(1011);
645 
646 print fit probability, parameter names/values and errors.
647 
648 1. When `v" = 1` is specified, only the non-fixed parameters are shown.
649 2. When `v" = 2` all parameters are shown.
650 
651 Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
652 to `gStyle->SetOptFit(111)`
653 
654 
655 ### <a name="HP09"></a> The error bars options
656 
657 
658 | Option | Description |
659 |----------|-------------------------------------------------------------------|
660 | "E" | Default. Shows only the error bars, not a marker.|
661 | "E1" | Small lines are drawn at the end of the error bars.|
662 | "E2" | Error rectangles are drawn.|
663 | "E3" | A filled area is drawn through the end points of the vertical error bars.|
664 | "E4" | A smoothed filled area is drawn through the end points of the vertical error bars.|
665 | "E0" | Draw also bins with null contents.|
666 
667 Begin_Macro(source)
668 {
669  TCanvas *c1 = new TCanvas("c1","c1",600,400);
670  TH1F *he = new TH1F("he","Distribution drawn with error bars (option E1) ",100,-3,3);
671  Int_t i;
672  for (i=0;i<10000;i++) he->Fill(gRandom->Gaus(0,1));
673  gStyle->SetEndErrorSize(3);
674  gStyle->SetErrorX(1.);
675  he->SetMarkerStyle(20);
676  he->Draw("E1");
677  return c1;
678 }
679 End_Macro
680 
681 The options "E3" and "E4" draw an error band through the end points of the
682 vertical error bars. With "E4" the error band is smoothed. Because of the
683 smoothing algorithm used some artefacts may appear at the end of the band
684 like in the following example. In such cases "E3" should be used instead
685 of "E4".
686 
687 Begin_Macro(source)
688 {
689  TCanvas *ce4 = new TCanvas("ce4","ce4",600,400);
690  ce4->Divide(2,1);
691  TH1F *he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
692  Int_t i;
693  for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
694  he4->SetFillColor(kRed);
695  he4->GetXaxis()->SetRange(40,48);
696  ce4->cd(1);
697  he4->Draw("E4");
698  ce4->cd(2);
699  TH1F *he3 = (TH1F*)he4->DrawClone("E3");
700  he3->SetTitle("Distribution drawn option E3");
701  return ce4;
702 }
703 End_Macro
704 
705 2D histograms can be drawn with error bars as shown is the following example:
706 
707 Begin_Macro(source)
708 {
709  TCanvas *c2e = new TCanvas("c2e","c2e",600,400);
710  TH2F *h2e = new TH2F("h2e","TH2 drawn with option E",40,-4,4,40,-20,20);
711  Float_t px, py;
712  for (Int_t i = 0; i < 25000; i++) {
713  gRandom->Rannor(px,py);
714  h2e->Fill(px,5*py);
715  }
716  h2e->Draw("E");
717  return c2e;
718 }
719 End_Macro
720 
721 
722 ### <a name="HP100"></a> The bar chart option
723 
724 
725 The option "B" allows to draw simple vertical bar charts.
726 The bar width is controlled with `TH1::SetBarWidth()`,
727 and the bar offset within the bin, with `TH1::SetBarOffset()`.
728 These two settings are useful to draw several histograms on the
729 same plot as shown in the following example:
730 
731 Begin_Macro(source)
732 {
733  int i;
734  const Int_t nx = 8;
735  string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
736  float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
737  float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
738 
739  TCanvas *cb = new TCanvas("cb","cb",600,400);
740  cb->SetGrid();
741 
742  gStyle->SetHistMinimumZero();
743 
744  TH1F *h1b = new TH1F("h1b","Option B example",nx,0,nx);
745  h1b->SetFillColor(4);
746  h1b->SetBarWidth(0.4);
747  h1b->SetBarOffset(0.1);
748  h1b->SetStats(0);
749  h1b->SetMinimum(-5);
750  h1b->SetMaximum(5);
751 
752  for (i=1; i<=nx; i++) {
753  h1b->SetBinContent(i, d_35_0[i-1]);
754  h1b->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
755  }
756 
757  h1b->Draw("b");
758 
759  TH1F *h2b = new TH1F("h2b","h2b",nx,0,nx);
760  h2b->SetFillColor(38);
761  h2b->SetBarWidth(0.4);
762  h2b->SetBarOffset(0.5);
763  h2b->SetStats(0);
764  for (i=1;i<=nx;i++) h2b->SetBinContent(i, d_35_1[i-1]);
765 
766  h2b->Draw("b same");
767 
768  return cb;
769 }
770 End_Macro
771 
772 
773 ### <a name="HP10"></a> The "BAR" and "HBAR" options
774 
775 
776 When the option `bar` or `hbar` is specified, a bar chart is drawn. A vertical
777 bar-chart is drawn with the options `bar`, `bar0`, `bar1`, `bar2`, `bar3`, `bar4`.
778 An horizontal bar-chart is drawn with the options `hbar`, `hbar0`, `hbar1`,
779 `hbar2`, `hbar3`, `hbar4` (hbars.C).
780 
781 - The bar is filled with the histogram fill color.
782 - The left side of the bar is drawn with a light fill color.
783 - The right side of the bar is drawn with a dark fill color.
784 - The percentage of the bar drawn with either the light or dark color is:
785  - 0% for option "(h)bar" or "(h)bar0"
786  - 10% for option "(h)bar1"
787  - 20% for option "(h)bar2"
788  - 30% for option "(h)bar3"
789  - 40% for option "(h)bar4"
790 
791 When an histogram has errors the option ["HIST"](#OPTHIST) together with the `(h)bar` option.
792 
793 Begin_Macro(source)
794 ../../../tutorials/hist/hbars.C
795 End_Macro
796 
797 To control the bar width (default is the bin width) `TH1::SetBarWidth()`
798 should be used.
799 
800 To control the bar offset (default is 0) `TH1::SetBarOffset()` should
801 be used.
802 
803 These two parameters are useful when several histograms are plotted using
804 the option `SAME`. They allow to plot the histograms next to each other.
805 
806 
807 ### <a name="HP11"></a> The SCATter plot option (default for 2D histograms)
808 
809 
810 For each cell (i,j) a number of points proportional to the cell content is
811 drawn. A maximum of `kNMAX` points per cell is drawn. If the maximum is above
812 `kNMAX` contents are normalized to `kNMAX` (`kNMAX=2000`).
813 If option is of the form `scat=ff`, (eg `scat=1.8`,
814 `scat=1e-3`), then `ff` is used as a scale factor to compute the
815 number of dots. `scat=1` is the default.
816 
817 By default the scatter plot is painted with a "dot marker" which not scalable
818 (see the `TAttMarker` documentation). To change the marker size, a scalable marker
819 type should be used. For instance a circle (marker style 20).
820 
821 Begin_Macro(source)
822 {
823  TCanvas *c1 = new TCanvas("c1","c1",600,400);
824  TH2F *hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms) ",40,-4,4,40,-20,20);
825  Float_t px, py;
826  for (Int_t i = 0; i < 25000; i++) {
827  gRandom->Rannor(px,py);
828  hscat->Fill(px,5*py);
829  hscat->Fill(3+0.5*px,2*py-10.);
830  }
831  hscat->Draw("scat=0.5");
832  return c1;
833 }
834 End_Macro
835 
836 
837 ### <a name="HP12"></a> The ARRow option
838 
839 
840 Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
841 The orientation of the arrow follows the cell gradient.
842 
843 Begin_Macro(source)
844 {
845  TCanvas *c1 = new TCanvas("c1","c1",600,400);
846  TH2F *harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
847  Float_t px, py;
848  for (Int_t i = 0; i < 25000; i++) {
849  gRandom->Rannor(px,py);
850  harr->Fill(px,5*py);
851  harr->Fill(3+0.5*px,2*py-10.,0.1);
852  }
853  harr->Draw("ARR");
854  return c1;
855 }
856 End_Macro
857 
858 
859 ### <a name="HP13"></a> The BOX option
860 
861 
862 For each cell (i,j) a box is drawn. The size (surface) of the box is
863 proportional to the absolute value of the cell content.
864 The cells with a negative content are drawn with a `X` on top of the box.
865 
866 Begin_Macro(source)
867 {
868  TCanvas *c1 = new TCanvas("c1","c1",600,400);
869  hbox = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
870  hbox->SetFillColor(42);
871  hbox->Fill(0.5, 0.5, 1.);
872  hbox->Fill(0.5, 1.5, 4.);
873  hbox->Fill(0.5, 2.5, 3.);
874  hbox->Fill(1.5, 0.5, 2.);
875  hbox->Fill(1.5, 1.5, 12.);
876  hbox->Fill(1.5, 2.5, -6.);
877  hbox->Fill(2.5, 0.5, -4.);
878  hbox->Fill(2.5, 1.5, 6.);
879  hbox->Fill(2.5, 2.5, 0.5);
880  hbox->Draw("BOX");
881  return c1;
882 }
883 End_Macro
884 
885 With option `BOX1` a button is drawn for each cell with surface
886 proportional to content's absolute value. A sunken button is drawn for
887 negative values a raised one for positive.
888 
889 Begin_Macro(source)
890 {
891  TCanvas *c1 = new TCanvas("c1","c1",600,400);
892  hbox1 = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
893  hbox1->SetFillColor(42);
894  hbox1->Fill(0.5, 0.5, 1.);
895  hbox1->Fill(0.5, 1.5, 4.);
896  hbox1->Fill(0.5, 2.5, 3.);
897  hbox1->Fill(1.5, 0.5, 2.);
898  hbox1->Fill(1.5, 1.5, 12.);
899  hbox1->Fill(1.5, 2.5, -6.);
900  hbox1->Fill(2.5, 0.5, -4.);
901  hbox1->Fill(2.5, 1.5, 6.);
902  hbox1->Fill(2.5, 2.5, 0.5);
903  hbox1->Draw("BOX1");
904  return c1;
905 }
906 End_Macro
907 
908 When the option `SAME` (or "SAMES") is used with the option `BOX`,
909 the boxes' sizes are computing taking the previous plots into account. The range
910 along the Z axis is imposed by the first plot (the one without option
911 `SAME`); therefore the order in which the plots are done is relevant.
912 
913 Begin_Macro(source)
914 {
915  TCanvas *c1 = new TCanvas("c1","c1",600,400);
916  TH2F *hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
917  TH2F *hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
918  TH2F *hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
919  TH2F *hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
920  for (Int_t i=0;i<1000;i++) {
921  double x,y;
922  gRandom->Rannor(x,y);
923  if (x>0 && y>0) hb1->Fill(x,y,4);
924  if (x<0 && y<0) hb2->Fill(x,y,3);
925  if (x>0 && y<0) hb3->Fill(x,y,2);
926  if (x<0 && y>0) hb4->Fill(x,y,1);
927  }
928  hb1->SetFillColor(1);
929  hb2->SetFillColor(2);
930  hb3->SetFillColor(3);
931  hb4->SetFillColor(4);
932  hb1->Draw("box");
933  hb2->Draw("box same");
934  hb3->Draw("box same");
935  hb4->Draw("box same");
936  return c1;
937 }
938 End_Macro
939 
940 
941 ### <a name="HP14"></a> The COLor option
942 
943 
944 For each cell (i,j) a box is drawn with a color proportional to the cell
945 content.
946 
947 The color table used is defined in the current style.
948 
949 If the histogram's minimum and maximum are the same (flat histogram), the
950 mapping on colors is not possible, therefore nothing is painted. To paint a
951 flat histogram it is enough to set the histogram minimum
952 (`TH1::SetMinimum()`) different from the bins' content.
953 
954 The default number of color levels used to paint the cells is 20.
955 It can be changed with `TH1::SetContour()` or
956 `TStyle::SetNumberContours()`. The higher this number is, the smoother
957 is the color change between cells.
958 
959 The color palette in TStyle can be modified via `gStyle->SetPalette()`.
960 
961 All the non-empty bins are painted. Empty bins are not painted unless
962 some bins have a negative content because in that case the null bins
963 might be not empty.
964 
965 `TProfile2D` histograms are handled differently because, for this type of 2D
966 histograms, it is possible to know if an empty bin has been filled or not. So even
967 if all the bins' contents are positive some empty bins might be painted. And vice versa,
968 if some bins have a negative content some empty bins might be not painted.
969 
970 Combined with the option `COL`, the option `Z` allows to
971 display the color palette defined by `gStyle->SetPalette()`.
972 
973 In the following example, the histogram has only positive bins; the empty
974 bins (containing 0) are not drawn.
975 
976 Begin_Macro(source)
977 {
978  TCanvas *c1 = new TCanvas("c1","c1",600,400);
979  TH2F *hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
980  Float_t px, py;
981  for (Int_t i = 0; i < 25000; i++) {
982  gRandom->Rannor(px,py);
983  hcol1->Fill(px,5*py);
984  }
985  gStyle->SetPalette(kBird);
986  hcol1->Draw("COLZ");
987  return c1;
988 }
989 End_Macro
990 
991 In the first plot of following example, the histogram has some negative bins;
992 the empty bins (containing 0) are drawn. In some cases one wants to not draw
993 empty bins (containing 0) of histograms having a negative minimum. The option
994 `1`, used to produce the second plot in the following picture, allows to do that.
995 
996 Begin_Macro(source)
997 {
998  TCanvas *c1 = new TCanvas("c1","c1",600,600);
999  c1->Divide(1,2);
1000  TH2F *hcol23 = new TH2F("hcol2","Option COLZ example ",40,-4,4,40,-20,20);
1001  TH2F *hcol24 = new TH2F("hcol2","Option COLZ1 example ",40,-4,4,40,-20,20);
1002  Float_t px, py;
1003  for (Int_t i = 0; i < 25000; i++) {
1004  gRandom->Rannor(px,py);
1005  hcol23->Fill(px,5*py);
1006  hcol24->Fill(px,5*py);
1007  }
1008  hcol23->Fill(0.,0.,-200.);
1009  hcol24->Fill(0.,0.,-200.);
1010  gStyle->SetPalette(kBird);
1011  c1->cd(1); hcol23->Draw("COLZ");
1012  c1->cd(2); hcol24->Draw("COLZ1");
1013  return c1;
1014 }
1015 End_Macro
1016 
1017 When the maximum of the histogram is set to a smaller value than the real maximum,
1018  the bins having a content between the new maximum and the real maximum are
1019 painted with the color corresponding to the new maximum.
1020 
1021 When the minimum of the histogram is set to a greater value than the real minimum,
1022  the bins having a value between the real minimum and the new minimum are not drawn
1023  unless the option `0` is set.
1024 
1025 The following example illustrates the option `0` combined with the option `COL`.
1026 
1027 Begin_Macro(source)
1028 {
1029  TCanvas *c1 = new TCanvas("c1","c1",600,600);
1030  c1->Divide(1,2);
1031  TH2F *hcol21 = new TH2F("hcol21","Option COLZ",40,-4,4,40,-20,20);
1032  TH2F *hcol22 = new TH2F("hcol22","Option COLZ0",40,-4,4,40,-20,20);
1033  Float_t px, py;
1034  for (Int_t i = 0; i < 25000; i++) {
1035  gRandom->Rannor(px,py);
1036  hcol21->Fill(px,5*py);
1037  hcol22->Fill(px,5*py);
1038  }
1039  hcol21->SetBit(TH1::kNoStats);
1040  hcol22->SetBit(TH1::kNoStats);
1041  gStyle->SetPalette(kBird);
1042  c1->cd(1); hcol21->Draw("COLZ");
1043  c1->cd(2); hcol22->Draw("COLZ0");
1044  hcol22->SetMaximum(100);
1045  hcol22->SetMinimum(40);
1046  return c1;
1047 }
1048 End_Macro
1049 
1050 \since **ROOT version 6.09/01:**
1051 
1052 When the option SAME (or "SAMES") is used with the option COL, the boxes' color
1053 are computing taking the previous plots into account. The range along the Z axis
1054 is imposed by the first plot (the one without option SAME); therefore the order
1055 in which the plots are done is relevant.
1056 
1057 Begin_Macro(source)
1058 {
1059  c = new TCanvas("c","Example of col plots with option SAME",200,10,700,500);
1060  TH2F *h1 = new TH2F("h1","h1",40,-3,3,40,-3,3);
1061  TH2F *h2 = new TH2F("h2","h2",40,-3,3,40,-3,3);
1062  TH2F *h3 = new TH2F("h3","h3",40,-3,3,40,-3,3);
1063  TH2F *h4 = new TH2F("h4","h4",40,-3,3,40,-3,3);
1064  h1->SetBit(TH1::kNoStats);
1065  for (Int_t i=0;i<5000;i++) {
1066  double x,y;
1067  gRandom->Rannor(x,y);
1068  if(x>0 && y>0) h1->Fill(x,y,4);
1069  if(x<0 && y<0) h2->Fill(x,y,3);
1070  if(x>0 && y<0) h3->Fill(x,y,2);
1071  if(x<0 && y>0) h4->Fill(x,y,1);
1072  }
1073  h1->Draw("colz");
1074  h2->Draw("col same");
1075  h3->Draw("col same");
1076  h4->Draw("col same");
1077 }
1078 End_Macro
1079 
1080 The option `COL` can be combined with the option `POL`:
1081 
1082 Begin_Macro(source)
1083 {
1084  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1085  TH2F *hcol1 = new TH2F("hcol1","Option COLor combined with POL",40,-4,4,40,-4,4);
1086  Float_t px, py;
1087  for (Int_t i = 0; i < 25000; i++) {
1088  gRandom->Rannor(px,py);
1089  hcol1->Fill(px,py);
1090  }
1091  gStyle->SetPalette(kBird);
1092  hcol1->Draw("COLZPOL");
1093  return c1;
1094 }
1095 End_Macro
1096 
1097 \since **ROOT version 6.07/03:**
1098 
1099 A second rendering technique is also available with the COL2 and COLZ2 options.
1100 
1101 These options provide potential performance improvements compared to the standard
1102 COL option. The performance comparison of the COL2 to the COL option depends on
1103 the histogram and the size of the rendering region in the current pad. In general,
1104 a small (approx. less than 100 bins per axis), sparsely populated TH2 will render
1105 faster with the COL option.
1106 
1107 However, for larger histograms (approx. more than 100 bins per axis)
1108 that are not sparse, the COL2 option will provide up to 20 times performance improvements.
1109 For example, a 1000x1000 bin TH2 that is not sparse will render an order of magnitude
1110 faster with the COL2 option.
1111 
1112 The COL2 option will also scale its performance based on the size of the
1113 pixmap the histogram image is being rendered into. It also is much better optimized for
1114 sessions where the user is forwarding X11 windows through an `ssh` connection.
1115 
1116 For the most part, the COL2 and COLZ2 options are a drop in replacement to the COL
1117 and COLZ options. There is one major difference and that concerns the treatment of
1118 bins with zero content. The COL2 and COLZ2 options color these bins the color of zero.
1119 
1120 
1121 ### <a name="HP140"></a> The CANDLE and VIOLIN options
1122 
1123 The mechanism behind Candle plots and Violin plots is very similar. Because of this they are
1124 implemented in the same class TCandle. The keywords CANDLE or VIOLIN will initiate the drawing of
1125 the corresponding plots. Followed by the keyword the user can select a plot direction (X or V for
1126 vertical projections, or Y or H for horizontal projections) and/or predefined definitions
1127 (1-6 for candles, 1-2 for violins). The order doesn't matter. Default is X and 1.
1128 
1129 Instead of using the predefined representations, the candle and violin parameters can be
1130 changed individually. In that case the option have the following form:
1131 
1132  CANDLEX(<option-string>)
1133  CANDLEY(<option-string>)
1134  VIOLINX(<option-string>)
1135  VIOLINY(<option-string>).
1136 
1137 All zeros at the beginning of `option-string` can be omitted.
1138 
1139 `option-string` consists eight values, defined as follow:
1140 
1141  "CANDLEX(zhpawMmb)"
1142 
1143 Where:
1144 
1145  - `b = 0`; no box drawn
1146  - `b = 1`; the box is drawn. As the candle-plot is also called a box-plot it
1147  makes sense in the very most cases to always draw the box
1148  - `b = 2`; draw a filled box with border
1149 
1150  - `m = 0`; no median drawn
1151  - `m = 1`; median is drawn as a line
1152  - `m = 2`; median is drawn with errors (notches)
1153  - `m = 3`; median is drawn as a circle
1154 
1155  - `M = 0`; no mean drawn
1156  - `M = 1`; mean is drawn as a dashed line
1157  - `M = 3`; mean is drawn as a circle
1158 
1159  - `w = 0`; no whisker drawn
1160  - `w = 1`; whisker is drawn to end of distribution.
1161  - `w = 2`; whisker is drawn to max 1.5*iqr
1162 
1163  - `a = 0`; no anchor drawn
1164  - `a = 1`; the anchors are drawn
1165 
1166  - `p = 0`; no points drawn
1167  - `p = 1`; only outliers are drawn
1168  - `p = 2`; all datapoints are drawn
1169  - `p = 3`: all datapoints are drawn scattered
1170 
1171  - `h = 0`; no histogram is drawn
1172  - `h = 1`; histogram at the left or bottom side is drawn
1173  - `h = 2`; histogram at the right or top side is drawn
1174  - `h = 3`; histogram at left and right or top and bottom (violin-style) is drawn
1175 
1176  - `z = 0`; no zero indicator line is drawn
1177  - `z = 1`; zero indicator line is drawn.
1178 
1179 As one can see all individual options for both candle and violin plots can be accessed by this
1180 mechanism. In deed the keywords CANDLE(<option-string>) and VIOLIN(<option-string>) have the same
1181 meaning. So you can parametrise an option-string for a candle plot and use the keywords VIOLIN and
1182 vice versa, if you wish.
1183 
1184 Using a logarithmic x- or y-axis is possible for candle and violin charts.
1185 
1186 \since **ROOT version 6.11/01**
1187 
1188 a logarithmic z-axis is possible, too but will only affect violin charts of course.
1189 
1190 #### <a name="HP140a"></a> The CANDLE option
1191 
1192 <a href="http://en.wikipedia.org/wiki/Box_plot">A Candle plot</a> (also known as
1193 a "box plot" or "whisker plot") was invented in 1977 by John Tukey. It is a convenient
1194 way to describe graphically a data distribution (D) with only five numbers:
1195 
1196  1. The minimum value of the distribution D (bottom or left whisker).
1197  2. The lower quartile (Q1): 25% of the data points in D are less than Q1 (bottom of the box).
1198  3. The median (M): 50% of the data points in D are less than M.
1199  4. The upper quartile (Q3): 75% of the data points in D are less than Q3 (top of the box).
1200  5. The maximum value of the distribution D (top or right whisker).
1201 
1202 In this implementation a TH2 is considered as a collection of TH1 along
1203 X (option `CANDLE` or `CANDLEX`) or Y (option `CANDLEY`).
1204 Each TH1 is represented as one candle.
1205 
1206 Begin_Macro(source)
1207 ../../../tutorials/hist/candleplotwhiskers.C
1208 End_Macro
1209 
1210 The candle reduces the information coming from a whole distribution into few values.
1211 Independently from the number of entries or the significance of the underlying distribution
1212 a candle will always look like a candle. So candle plots should be used carefully in
1213 particular with unknown distributions. The definition of a candle is based on
1214 __unbinned data__. Here, candles are created from binned data. Because of this, the
1215 deviation is connected to the bin width used. The calculation of the quantiles
1216 normally done on unbinned data also. Because data are binned, this will
1217 only work the best possible way within the resolution of one bin
1218 
1219 Because of all these facts one should take care that:
1220 
1221  - there are enough points per candle
1222  - the bin width is small enough (more bins will increase the maximum
1223  available resolution of the quantiles although there will be some
1224  bins with no entries)
1225  - never make a candle-plot if the underlying distribution is double-distributed
1226  - only create candles of distributions that are more-or-less gaussian (the
1227  MPV should be not too far away from the mean).
1228 
1229 #### What a candle is made of
1230 
1231 \since **ROOT version 6.07/05**
1232 
1233 ##### The box
1234 The box displays the position of the inter-quantile-range of the underlying
1235 distribution. The box contains 25% of the distribution below the median
1236 and 25% of the distribution above the median. If the underlying distribution is large
1237 enough and gaussian shaped the end-points of the box represent \f$ 0.6745\times\sigma \f$
1238 (Where \f$ \sigma \f$ is the standard deviation of the gaussian). The width and
1239 the position of the box can be modified by SetBarWidth() and SetBarOffset().
1240 The +-25% quantiles are calculated by the GetQuantiles() methods.
1241 
1242 \since **ROOT version 6.11/01**
1243 
1244 Using the static function TCandle::SetBoxRange(double) the box definition will be
1245 overwritten. E.g. using a box range of 0.68 will redefine the area of the lower box edge
1246 to the upper box edge in order to cover 68% of the distribution illustrated by that candle.
1247 The static function will affect all candle-charts in the running program.
1248 Default is 0.5.
1249 
1250 Using the static function TCandle::SetScaledCandle(bool) the width of the box (and the
1251 whole candle) can be influenced. Deactivated, the width is constant (to be set by
1252 SetBarWidth() ). Activated, the width of the boxes will be scaled to each other based on the
1253 amount of data in the corresponding candle, the maximum width can be influenced by
1254 SetBarWidth(). The static function will affect all candle-charts in the running program.
1255 Default is false. Scaling between multiple candle-charts (using "same" or THStack) is not
1256 supported, yet
1257 
1258 ##### The Median
1259 For a sorted list of numbers, the median is the value in the middle of the list.
1260 E.g. if a sorted list is made of five numbers "1,2,3,6,7" 3 will be the median
1261 because it is in the middle of the list. If the number of entries is even the
1262 average of the two values in the middle will be used. As histograms are binned
1263 data, the situation is a bit more complex. The following example shows this:
1264 
1265 ~~~ {.cpp}
1266 void quantiles() {
1267  TH1I *h = new TH1I("h","h",10,0,10);
1268  //h->Fill(3);
1269  //h->Fill(3);
1270  h->Fill(4);
1271  h->Draw();
1272  Double_t *p = new Double_t[1];
1273  p[0] = 0.5;
1274  Double_t *q = new Double_t[1];
1275  q[0] = 0;
1276  h->GetQuantiles(1,q,p);
1277 
1278  cout << "Median is: " << q[0] << std::endl;
1279 }
1280 ~~~
1281 
1282 Here the bin-width is 1.0. If the two Fill(3) are commented out, as there are currently,
1283 the example will return a calculated median of 4.5, because that's the bin center
1284 of the bin in which the value 4.0 has been dropped. If the two Fill(3) are not
1285 commented out, it will return 3.75, because the algorithm tries to evenly distribute
1286 the individual values of a bin with bin content > 0. It means the sorted list
1287 would be "3.25, 3.75, 4.5".
1288 
1289 The consequence is a median of 3.75. This shows how important it is to use a
1290 small enough bin-width when using candle-plots on binned data.
1291 If the distribution is large enough and gaussian shaped the median will be exactly
1292 equal to the mean.
1293 The median can be shown as a line or as a circle or not shown at all.
1294 
1295 In order to show the significance of the median notched candle plots apply a "notch" or
1296 narrowing of the box around the median. The significance is defined by
1297 \f$ 1.57\times\frac{iqr}{N} \f$ and will be represented as the size of the notch
1298 (where iqr is the size of the box and N is the number of entries of the whole
1299 distribution). Candle plots like these are usually called "notched candle plots".
1300 
1301 In case the significance of the median is greater that the size of the box, the
1302 box will have an unnatural shape. Usually it means the chart has not enough data,
1303 or that representing this uncertainty is not useful
1304 
1305 ##### The Mean
1306 The mean can be drawn as a dashed line or as a circle or not drawn at all.
1307 The mean is the arithmetic average of the values in the distribution.
1308 It is calculated using GetMean(). Because histograms are
1309 binned data, the mean value can differ from a calculation on the raw-data.
1310 If the distribution is large enough and gaussian shaped the mean will be
1311 exactly the median.
1312 
1313 ##### The Whiskers
1314 The whiskers represent the part of the distribution not covered by the box.
1315 The upper 25% and the lower 25% of the distribution are located within the whiskers.
1316 Two representations are available.
1317 
1318  - A simple one (using w=1) defining the lower whisker from the lowest data value
1319  to the bottom of the box, and the upper whisker from the top of the box to the
1320  highest data value. In this representation the whisker-lines are dashed.
1321  - A more complex one having a further restriction. The whiskers are still connected
1322  to the box but their length cannot exceed \f$ 1.5\times iqr \f$. So it might
1323  be that the outermost part of the underlying distribution will not be covered
1324  by the whiskers. Usually these missing parts will be represented by the outliers
1325  (see points). Of course the upper and the lower whisker may differ in length.
1326  In this representation the whiskers are drawn as solid lines.
1327 
1328 \since **ROOT version 6.11/01**
1329 
1330 Using the static function TCandle::SetWhiskerRange(double) the whisker definition w=1
1331 will be overwritten. E.g. using a whisker-range of 0.95 and w=1 will redefine the area of
1332 the lower whisker to the upper whisker in order to cover 95% of the distribution inside
1333 that candle. The static function will affect all candle-charts in the running program.
1334 Default is 1.
1335 
1336 If the distribution is large enough and gaussian shaped, the maximum length of
1337 the whisker will be located at \f$ \pm 2.698 \sigma \f$ (when using the
1338 1.5*iqr-definition (w=2), where \f$ \sigma \f$ is the standard deviation
1339 (see picture above). In that case 99.3% of the total distribution will be covered
1340 by the box and the whiskers, whereas 0.7% are represented by the outliers.
1341 
1342 ##### The Anchors
1343 The anchors have no special meaning in terms of statistical calculation. They mark
1344 the end of the whiskers and they have the width of the box. Both representation
1345 with and without anchors are common.
1346 
1347 ##### The Points
1348 Depending on the configuration the points can have different meanings:
1349  - If p=1 the points represent the outliers. If they are shown, it means
1350  some parts of the underlying distribution are not covered by the whiskers.
1351  This can only occur when the whiskers are set to option w=2. Here the whiskers
1352  can have a maximum length of \f$ 1.5 \times iqr \f$. So any points outside the
1353  whiskers will be drawn as outliers. The outliers will be represented by crosses.
1354  - If p=2 all points in the distribution will be painted as crosses. This is
1355  useful for small datasets only (up to 10 or 20 points per candle).
1356  The outliers are shown along the candle. Because the underlying distribution
1357  is binned, is frequently occurs that a bin contains more than one value.
1358  Because of this the points will be randomly scattered within their bin along
1359  the candle axis. If the bin content for a bin is exactly 1 (usually
1360  this happens for the outliers) if will be drawn in the middle of the bin along
1361  the candle axis. As the maximum number of points per candle is limited by kNMax/2
1362  on very large datasets scaling will be performed automatically. In that case one
1363  would loose all outliers because they have usually a bin content of 1 (and a
1364  bin content between 0 and 1 after the scaling). Because of this all bin contents
1365  between 0 and 1 - after the scaling - will be forced to be 1.
1366  - As the drawing of all values on large datasets can lead to big amounts of crosses,
1367  one can show all values as a scatter plot instead by choosing p=3. The points will be
1368  drawn as dots and will be scattered within the width of the candle. The color
1369  of the points will be the color of the candle-chart.
1370 
1371 ##### Other Options
1372 Is is possible to combine all options of candle and violin plots with each other. E.g. a box-plot
1373 with a histogram.
1374 
1375 #### How to use the candle-plots drawing option
1376 
1377 There are six predefined candle-plot representations:
1378 
1379  - "CANDLEX1": Standard candle (whiskers cover the whole distribution)
1380  - "CANDLEX2": Standard candle with better whisker definition + outliers.
1381  It is a good compromise
1382  - "CANDLEX3": Like candle2 but with a mean as a circle.
1383  It is easier to distinguish mean and median
1384  - "CANDLEX4": Like candle3 but showing the uncertainty of the median as well
1385  (notched candle plots).
1386  For bigger datasets per candle
1387  - "CANDLEX5": Like candle2 but showing all data points.
1388  For very small datasets
1389  - "CANDLEX6": Like candle2 but showing all datapoints scattered.
1390  For huge datasets
1391 
1392 
1393 The following picture shows how the six predefined representations look.
1394 
1395 Begin_Macro
1396 {
1397  TCanvas *c1 = new TCanvas("c1","c1",700,800);
1398  c1->Divide(2,3);
1399  gStyle->SetOptStat(kFALSE);
1400 
1401  TH2F *hcandle = new TH2F("hcandle"," ",10,-4,4,40,-20,20);
1402  Float_t px, py;
1403  for (Int_t i = 0; i < 15000; i++) {
1404  gRandom->Rannor(px,py);
1405  hcandle->Fill(px,5*py);
1406  }
1407  hcandle->SetMarkerSize(0.5);
1408 
1409  TH2F *h2;
1410  for (Int_t i=1; i<7; i++) {
1411  c1->cd(i);
1412  h2 = (TH2F*)hcandle->DrawClone(Form("CANDLE%d",i));
1413  h2->SetTitle(Form("CANDLE%d",i));
1414  }
1415 }
1416 End_Macro
1417 
1418 
1419 
1420 #### Example 1
1421 Box and improved whisker, no mean, no median, no anchor no outliers
1422 
1423  h1->Draw("CANDLEX(2001)");
1424 
1425 #### Example 2
1426 A Candle-definition like "CANDLEX2" (New standard candle with better whisker definition + outliers)
1427 
1428  h1->Draw("CANDLEX(112111)");
1429 
1430 #### Example 3
1431 The following example shows how several candle plots can be super-imposed using
1432 the option SAME. Note that the bar-width and bar-offset are active on candle plots.
1433 Also the color, the line width, the size of the points and so on can be changed by the
1434 standard attribute setting methods such as SetLineColor() SetLineWidth().
1435 
1436 Begin_Macro(source)
1437 ../../../tutorials/hist/candleplot.C
1438 End_Macro
1439 
1440 #### <a name="HP140b"></a> The VIOLIN option
1441 
1442 <a href="http://en.wikipedia.org/wiki/Violin_plot">A violin plot</a> is a candle plot
1443 that also encodes the pdf information at each point.
1444 
1445 
1446 Quartiles and mean are also represented at each point, with a marker
1447 and two lines.
1448 
1449 In this implementation a TH2 is considered as a collection of TH1 along
1450 X (option `VIOLIN` or `VIOLINX`) or Y (option `VIOLINY`).
1451 
1452 #### What a violin is made of
1453 
1454 \since **ROOT version 6.09/02**
1455 
1456 ##### The histogram
1457 The histogram is typically drawn to both directions with respect to the middle-line of the
1458 corresponding bin. This can be achieved by using h=3. It is possible to draw a histogram only to
1459 one side (h=1, or h=2).
1460 The maximum number of bins in the histogram is limited to 500, if the number of bins in the used
1461 histogram is higher it will be rebinned automatically. The maximum height of the histogram can
1462 be modified by using SetBarWidth() and the position can be changed with SetBarOffset().
1463 A solid fill style is recommended.
1464 
1465 \since **ROOT version 6.11/01**
1466 
1467 Using the static function TCandle::SetScaledViolin(bool) the height of the histogram or the
1468 violin can be influenced. Activated, the height of the bins of the individual violins will be
1469 scaled with respect to each other, the maximum height can be influenced by SetBarWidth().
1470 Deactivated, the height of the bin with the maximum content of each individual violin is
1471 set to a constant value using SetBarWidth(). The static function will affect all violin-charts
1472 in the running program. Default is true. Scaling between multiple violin-charts
1473 (using "same" or THStack) is not supported, yet.
1474 
1475 ##### The zero indicator line
1476 Typical for violin charts is a line in the background over the whole histogram indicating
1477 the bins with zero entries. The zero indicator line can be activated with z=1. The line color
1478 will always be the same as the fill-color of the histogram.
1479 
1480 ##### The Mean
1481 The Mean is illustrated with the same mechanism as used for candle plots. Usually a circle is used.
1482 
1483 ##### Whiskers
1484 The whiskers are illustrated by the same mechanism as used for candle plots. There is only one
1485 difference. When using the simple whisker definition (w=1) and the zero indicator line (z=1), then
1486 the whiskers will be forced to be solid (usually hashed)
1487 
1488 ##### Points
1489 The points are illustrated by the same mechanism as used for candle plots. E.g. VIOLIN2 uses
1490 better whisker definition (w=2) and outliers (p=1).
1491 
1492 ##### Other options
1493 It is possible to combine all options of candle or violin plots with each other. E.g. a violin plot
1494 including a box-plot.
1495 
1496 #### How to use the violin-plots drawing option
1497 
1498 There are two predefined violin-plot representations:
1499  - "VIOLINX1": Standard violin (histogram, mean, whisker over full distribution,
1500  zero indicator line)
1501  - "VIOLINX2": Line VIOLINX1 both with better whisker definition + outliers.
1502 
1503 A solid fill style is recommended for this plot (as opposed to a hollow or
1504 hashed style).
1505 
1506 Begin_Macro(source)
1507 {
1508  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1509  Int_t nx(6), ny(40);
1510  Double_t xmin(0.0), xmax(+6.0), ymin(0.0), ymax(+4.0);
1511  TH2F* hviolin = new TH2F("hviolin", "Option VIOLIN example", nx, xmin, xmax, ny, ymin, ymax);
1512  TF1 f1("f1", "gaus", +0,0 +4.0);
1513  Double_t x,y;
1514  for (Int_t iBin=1; iBin<hviolin->GetNbinsX(); ++iBin) {
1515  Double_t xc = hviolin->GetXaxis()->GetBinCenter(iBin);
1516  f1.SetParameters(1, 2.0+TMath::Sin(1.0+xc), 0.2+0.1*(xc-xmin)/xmax);
1517  for(Int_t i=0; i<10000; ++i){
1518  x = xc;
1519  y = f1.GetRandom();
1520  hviolin->Fill(x, y);
1521  }
1522  }
1523  hviolin->SetFillColor(kGray);
1524  hviolin->SetMarkerStyle(20);
1525  hviolin->SetMarkerSize(0.5);
1526  hviolin->Draw("VIOLIN");
1527  c1->Update();
1528  return c1;
1529 }
1530 End_Macro
1531 
1532 The next example illustrates a time development of a certain value:
1533 
1534 Begin_Macro(source)
1535 ../../../tutorials/hist/candledecay.C
1536 End_Macro
1537 
1538 
1539 ### <a name="HP15"></a> The TEXT and TEXTnn Option
1540 
1541 
1542 For each bin the content is printed. The text attributes are:
1543 
1544 - text font = current TStyle font (`gStyle->SetTextFont()`).
1545 - text size = 0.02*padheight*markersize (if `h` is the histogram drawn
1546  with the option `TEXT` the marker size can be changed with
1547  `h->SetMarkerSize(markersize)`).
1548 - text color = marker color.
1549 
1550 By default the format `g` is used. This format can be redefined
1551 by calling `gStyle->SetPaintTextFormat()`.
1552 
1553 It is also possible to use `TEXTnn` in order to draw the text with
1554 the angle `nn` (`0 < nn < 90`).
1555 
1556 For 2D histograms the text is plotted in the center of each non empty cells.
1557 It is possible to plot empty cells by calling `gStyle->SetHistMinimumZero()`.
1558 For 1D histogram the text is plotted at a y position equal to the bin content.
1559 
1560 For 2D histograms when the option "E" (errors) is combined with the option
1561 text ("TEXTE"), the error for each bin is also printed.
1562 
1563 Begin_Macro(source)
1564 {
1565  TCanvas *c01 = new TCanvas("c01","c01",700,400);
1566  c01->Divide(2,1);
1567  TH1F *htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
1568  TH2F *htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
1569  Float_t px, py;
1570  for (Int_t i = 0; i < 25000; i++) {
1571  gRandom->Rannor(px,py);
1572  htext1->Fill(px,0.1);
1573  htext2->Fill(px,5*py,0.1);
1574  }
1575  gStyle->SetPaintTextFormat("4.1f m");
1576  htext2->SetMarkerSize(1.8);
1577  c01->cd(1);
1578  htext2->Draw("TEXT45");
1579  c01->cd(2);
1580  htext1->Draw();
1581  htext1->Draw("HIST TEXT0 SAME");
1582  return c01;
1583 }
1584 End_Macro
1585 
1586 \since **ROOT version 6.07/07:**
1587 
1588 In case several histograms are drawn on top ot each other (using option `SAME`),
1589 the text can be shifted using `SetBarOffset()`. It specifies an offset for the
1590 text position in each cell, in percentage of the bin width.
1591 
1592 Begin_Macro(source)
1593 {
1594  TCanvas *c03 = new TCanvas("c03","c03",700,400);
1595  gStyle->SetOptStat(0);
1596  TH2F *htext3 = new TH2F("htext3","Several 2D histograms drawn with option TEXT",10,-4,4,10,-20,20);
1597  TH2F *htext4 = new TH2F("htext4","htext4",10,-4,4,10,-20,20);
1598  TH2F *htext5 = new TH2F("htext5","htext5",10,-4,4,10,-20,20);
1599  Float_t px, py;
1600  for (Int_t i = 0; i < 25000; i++) {
1601  gRandom->Rannor(px,py);
1602  htext3->Fill(4*px,20*py,0.1);
1603  htext4->Fill(4*px,20*py,0.5);
1604  htext5->Fill(4*px,20*py,1.0);
1605  }
1606  //gStyle->SetPaintTextFormat("4.1f m");
1607  htext4->SetMarkerSize(1.8);
1608  htext5->SetMarkerSize(1.8);
1609  htext5->SetMarkerColor(kRed);
1610  htext3->Draw("COL");
1611  htext4->SetBarOffset(0.2);
1612  htext4->Draw("TEXT SAME");
1613  htext5->SetBarOffset(-0.2);
1614  htext5->Draw("TEXT SAME");
1615  return c03;
1616 }
1617 End_Macro
1618 
1619 In the case of profile histograms it is possible to print the number
1620 of entries instead of the bin content. It is enough to combine the
1621 option "E" (for entries) with the option "TEXT".
1622 
1623 Begin_Macro(source)
1624 {
1625  TCanvas *c02 = new TCanvas("c02","c02",700,400);
1626  c02->Divide(2,1);
1627  gStyle->SetPaintTextFormat("g");
1628 
1629  TProfile *profile = new TProfile("profile","profile",10,0,10);
1630  profile->SetMarkerSize(2.2);
1631  profile->Fill(0.5,1);
1632  profile->Fill(1.5,2);
1633  profile->Fill(2.5,3);
1634  profile->Fill(3.5,4);
1635  profile->Fill(4.5,5);
1636  profile->Fill(5.5,5);
1637  profile->Fill(6.5,4);
1638  profile->Fill(7.5,3);
1639  profile->Fill(8.5,2);
1640  profile->Fill(9.5,1);
1641  c02->cd(1); profile->Draw("HIST TEXT0");
1642  c02->cd(2); profile->Draw("HIST TEXT0E");
1643 
1644  return c02;
1645 }
1646 End_Macro
1647 
1648 ### <a name="HP16"></a> The CONTour options
1649 
1650 
1651 The following contour options are supported:
1652 
1653 | Option | Description |
1654 |----------|-------------------------------------------------------------------|
1655 | "CONT" | Draw a contour plot (same as CONT0).|
1656 | "CONT0" | Draw a contour plot using surface colors to distinguish contours.|
1657 | "CONT1" | Draw a contour plot using the line colors to distinguish contours.|
1658 | "CONT2" | Draw a contour plot using the line styles to distinguish contours.|
1659 | "CONT3" | Draw a contour plot solid lines for all contours.|
1660 | "CONT4" | Draw a contour plot using surface colors (`SURF` option at theta = 0).|
1661 | "CONT5" | Draw a contour plot using Delaunay triangles.|
1662 
1663 
1664 
1665 The following example shows a 2D histogram plotted with the option
1666 `CONTZ`. The option `CONT` draws a contour plot using surface
1667 colors to distinguish contours. Combined with the option `CONT` (or
1668 `CONT0`), the option `Z` allows to display the color palette
1669 defined by `gStyle->SetPalette()`.
1670 
1671 Begin_Macro(source)
1672 {
1673  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1674  TH2F *hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
1675  Float_t px, py;
1676  for (Int_t i = 0; i < 25000; i++) {
1677  gRandom->Rannor(px,py);
1678  hcontz->Fill(px-1,5*py);
1679  hcontz->Fill(2+0.5*px,2*py-10.,0.1);
1680  }
1681  gStyle->SetPalette(kBird);
1682  hcontz->Draw("CONTZ");
1683  return c1;
1684 }
1685 End_Macro
1686 
1687 The following example shows a 2D histogram plotted with the option
1688 `CONT1Z`. The option `CONT1` draws a contour plot using the
1689 line colors to distinguish contours. Combined with the option `CONT1`,
1690 the option `Z` allows to display the color palette defined by
1691 `gStyle->SetPalette()`.
1692 
1693 Begin_Macro(source)
1694 {
1695  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1696  TH2F *hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
1697  Float_t px, py;
1698  for (Int_t i = 0; i < 25000; i++) {
1699  gRandom->Rannor(px,py);
1700  hcont1->Fill(px-1,5*py);
1701  hcont1->Fill(2+0.5*px,2*py-10.,0.1);
1702  }
1703  gStyle->SetPalette(kBird);
1704  hcont1->Draw("CONT1Z");
1705  return c1;
1706 }
1707 End_Macro
1708 
1709 The following example shows a 2D histogram plotted with the option
1710 `CONT2`. The option `CONT2` draws a contour plot using the
1711 line styles to distinguish contours.
1712 
1713 Begin_Macro(source)
1714 {
1715  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1716  TH2F *hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
1717  Float_t px, py;
1718  for (Int_t i = 0; i < 25000; i++) {
1719  gRandom->Rannor(px,py);
1720  hcont2->Fill(px-1,5*py);
1721  hcont2->Fill(2+0.5*px,2*py-10.,0.1);
1722  }
1723  hcont2->Draw("CONT2");
1724  return c1;
1725 }
1726 End_Macro
1727 
1728 The following example shows a 2D histogram plotted with the option
1729 `CONT3`. The option `CONT3` draws contour plot solid lines for
1730 all contours.
1731 
1732 Begin_Macro(source)
1733 {
1734  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1735  TH2F *hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
1736  Float_t px, py;
1737  for (Int_t i = 0; i < 25000; i++) {
1738  gRandom->Rannor(px,py);
1739  hcont3->Fill(px-1,5*py);
1740  hcont3->Fill(2+0.5*px,2*py-10.,0.1);
1741  }
1742  hcont3->Draw("CONT3");
1743  return c1;
1744 }
1745 End_Macro
1746 
1747 The following example shows a 2D histogram plotted with the option
1748 `CONT4`. The option `CONT4` draws a contour plot using surface
1749 colors to distinguish contours (`SURF` option at theta = 0). Combined
1750 with the option `CONT` (or `CONT0`), the option `Z`
1751 allows to display the color palette defined by `gStyle->SetPalette()`.
1752 
1753 Begin_Macro(source)
1754 {
1755  TCanvas *c1 = new TCanvas("c1","c1",600,400);
1756  TH2F *hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
1757  Float_t px, py;
1758  for (Int_t i = 0; i < 25000; i++) {
1759  gRandom->Rannor(px,py);
1760  hcont4->Fill(px-1,5*py);
1761  hcont4->Fill(2+0.5*px,2*py-10.,0.1);
1762  }
1763  gStyle->SetPalette(kBird);
1764  hcont4->Draw("CONT4Z");
1765  return c1;
1766 }
1767 End_Macro
1768 
1769 The default number of contour levels is 20 equidistant levels and can be changed
1770 with `TH1::SetContour()` or `TStyle::SetNumberContours()`.
1771 
1772 #### <a name="HP16a"></a> The LIST option
1773 
1774 When option `LIST` is specified together with option
1775 `CONT`, the points used to draw the contours are saved in
1776 `TGraph` objects:
1777 
1778  h->Draw("CONT LIST");
1779  gPad->Update();
1780 
1781 The contour are saved in `TGraph` objects once the pad is painted.
1782 Therefore to use this functionality in a macro, `gPad->Update()`
1783 should be performed after the histogram drawing. Once the list is
1784 built, the contours are accessible in the following way:
1785 
1786  TObjArray *contours = gROOT->GetListOfSpecials()->FindObject("contours")
1787  Int_t ncontours = contours->GetSize();
1788  TList *list = (TList*)contours->At(i);
1789 
1790 Where `i` is a contour number, and list contains a list of
1791 `TGraph` objects.
1792 For one given contour, more than one disjoint polyline may be generated.
1793 The number of TGraphs per contour is given by:
1794 
1795  list->GetSize();
1796 
1797 To access the first graph in the list one should do:
1798 
1799  TGraph *gr1 = (TGraph*)list->First();
1800 
1801 
1802 The following example (ContourList.C) shows how to use this functionality.
1803 
1804 Begin_Macro(source)
1805 ../../../tutorials/hist/ContourList.C
1806 End_Macro
1807 
1808 The following options select the `CONT4` option and are useful for
1809 sky maps or exposure maps (earth.C).
1810 
1811 | Option | Description |
1812 |--------------|---------------------------------------------------------------|
1813 | "AITOFF" | Draw a contour via an AITOFF projection.|
1814 | "MERCATOR" | Draw a contour via an Mercator projection.|
1815 | "SINUSOIDAL" | Draw a contour via an Sinusoidal projection.|
1816 | "PARABOLIC" | Draw a contour via an Parabolic projection.|
1817 
1818 Begin_Macro(source)
1819 ../../../tutorials/graphics/earth.C
1820 End_Macro
1821 
1822 
1823 ### <a name="HP17"></a> The LEGO options
1824 
1825 
1826 In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
1827 is proportional to the cell content. The lego aspect is control with the
1828 following options:
1829 
1830 | Option | Description |
1831 |----------|-------------------------------------------------------------------|
1832 | "LEGO" | Draw a lego plot using the hidden lines removal technique.|
1833 | "LEGO1" | Draw a lego plot using the hidden surface removal technique.|
1834 | "LEGO2" | Draw a lego plot using colors to show the cell contents.|
1835 | "LEGO3" | Draw a lego plot with hidden surface removal, like LEGO1 but the border lines of each lego-bar are not drawn.|
1836 | "LEGO4" | Draw a lego plot with hidden surface removal, like LEGO1 but without the shadow effect on each lego-bar.|
1837 | "0" | When used with any LEGO option, the empty bins are not drawn.|
1838 
1839 
1840 See the limitations with [the option "SAME"](#HP060a).
1841 
1842 Line attributes can be used in lego plots to change the edges' style.
1843 
1844 The following example shows a 2D histogram plotted with the option
1845 `LEGO`. The option `LEGO` draws a lego plot using the hidden
1846 lines removal technique.
1847 
1848 Begin_Macro(source)
1849 {
1850  TCanvas *c2 = new TCanvas("c2","c2",600,400);
1851  TH2F *hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
1852  Float_t px, py;
1853  for (Int_t i = 0; i < 25000; i++) {
1854  gRandom->Rannor(px,py);
1855  hlego->Fill(px-1,5*py);
1856  hlego->Fill(2+0.5*px,2*py-10.,0.1);
1857  }
1858  hlego->Draw("LEGO");
1859  return c2;
1860 }
1861 End_Macro
1862 
1863 The following example shows a 2D histogram plotted with the option
1864 `LEGO1`. The option `LEGO1` draws a lego plot using the
1865 hidden surface removal technique. Combined with any `LEGOn` option, the
1866 option `0` allows to not drawn the empty bins.
1867 
1868 Begin_Macro(source)
1869 {
1870  TCanvas *c2 = new TCanvas("c2","c2",600,400);
1871  TH2F *hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0) ",40,-4,4,40,-20,20);
1872  Float_t px, py;
1873  for (Int_t i = 0; i < 25000; i++) {
1874  gRandom->Rannor(px,py);
1875  hlego1->Fill(px-1,5*py);
1876  hlego1->Fill(2+0.5*px,2*py-10.,0.1);
1877  }
1878  hlego1->SetFillColor(kYellow);
1879  hlego1->Draw("LEGO1 0");
1880  return c2;
1881 }
1882 End_Macro
1883 
1884 The following example shows a 2D histogram plotted with the option
1885 `LEGO3`. Like the option `LEGO1`, the option `LEGO3`
1886 draws a lego plot using the hidden surface removal technique but doesn't draw
1887 the border lines of each individual lego-bar. This is very useful for histograms
1888 having many bins. With such histograms the option `LEGO1` gives a black
1889 image because of the border lines. This option also works with stacked legos.
1890 
1891 Begin_Macro(source)
1892 {
1893  TCanvas *c2 = new TCanvas("c2","c2",600,400);
1894  TH2F *hlego3 = new TH2F("hlego3","Option LEGO3 example",40,-4,4,40,-20,20);
1895  Float_t px, py;
1896  for (Int_t i = 0; i < 25000; i++) {
1897  gRandom->Rannor(px,py);
1898  hlego3->Fill(px-1,5*py);
1899  hlego3->Fill(2+0.5*px,2*py-10.,0.1);
1900  }
1901  hlego3->SetFillColor(kRed);
1902  hlego3->Draw("LEGO3");
1903  return c2;
1904 }
1905 End_Macro
1906 
1907 The following example shows a 2D histogram plotted with the option
1908 `LEGO2`. The option `LEGO2` draws a lego plot using colors to
1909 show the cell contents. Combined with the option `LEGO2`, the option
1910 `Z` allows to display the color palette defined by
1911 `gStyle->SetPalette()`.
1912 
1913 Begin_Macro(source)
1914 {
1915  TCanvas *c2 = new TCanvas("c2","c2",600,400);
1916  TH2F *hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
1917  Float_t px, py;
1918  for (Int_t i = 0; i < 25000; i++) {
1919  gRandom->Rannor(px,py);
1920  hlego2->Fill(px-1,5*py);
1921  hlego2->Fill(2+0.5*px,2*py-10.,0.1);
1922  }
1923  gStyle->SetPalette(kBird);
1924  hlego2->Draw("LEGO2Z");
1925  return c2;
1926 }
1927 End_Macro
1928 
1929 
1930 
1931 ### <a name="HP18"></a> The "SURFace" options
1932 
1933 
1934 In a surface plot, cell contents are represented as a mesh.
1935 The height of the mesh is proportional to the cell content.
1936 
1937 | Option | Description |
1938 |----------|-------------------------------------------------------------------|
1939 | "SURF" | Draw a surface plot using the hidden line removal technique.|
1940 | "SURF1" | Draw a surface plot using the hidden surface removal technique.|
1941 | "SURF2" | Draw a surface plot using colors to show the cell contents.|
1942 | "SURF3" | Same as `SURF` with an additional filled contour plot on top.|
1943 | "SURF4" | Draw a surface using the Gouraud shading technique.|
1944 | "SURF5" | Used with one of the options CYL, PSR and CYL this option allows to draw a a filled contour plot.|
1945 | "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.|
1946 | "SURF7" | Same as `SURF2` with an additional line contour plot on top.|
1947 
1948 
1949 
1950 See the limitations with [the option "SAME"](#HP060a).
1951 
1952 The following example shows a 2D histogram plotted with the option
1953 `SURF`. The option `SURF` draws a lego plot using the hidden
1954 lines removal technique.
1955 
1956 Begin_Macro(source)
1957 {
1958  TCanvas *c2 = new TCanvas("c2","c2",600,400);
1959  TH2F *hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
1960  Float_t px, py;
1961  for (Int_t i = 0; i < 25000; i++) {
1962  gRandom->Rannor(px,py);
1963  hsurf->Fill(px-1,5*py);
1964  hsurf->Fill(2+0.5*px,2*py-10.,0.1);
1965  }
1966  hsurf->Draw("SURF");
1967  return c2;
1968 }
1969 End_Macro
1970 
1971 The following example shows a 2D histogram plotted with the option
1972 `SURF1`. The option `SURF1` draws a surface plot using the
1973 hidden surface removal technique. Combined with the option `SURF1`,
1974 the option `Z` allows to display the color palette defined by
1975 `gStyle->SetPalette()`.
1976 
1977 Begin_Macro(source)
1978 {
1979  TCanvas *c2 = new TCanvas("c2","c2",600,400);
1980  gStyle->SetPalette(kBird);
1981  TH2F *hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
1982  Float_t px, py;
1983  for (Int_t i = 0; i < 25000; i++) {
1984  gRandom->Rannor(px,py);
1985  hsurf1->Fill(px-1,5*py);
1986  hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
1987  }
1988  hsurf1->Draw("SURF1");
1989  return c2;
1990 }
1991 End_Macro
1992 
1993 The following example shows a 2D histogram plotted with the option
1994 `SURF2`. The option `SURF2` draws a surface plot using colors
1995 to show the cell contents. Combined with the option `SURF2`, the option
1996 `Z` allows to display the color palette defined by
1997 `gStyle->SetPalette()`.
1998 
1999 Begin_Macro(source)
2000 {
2001  TCanvas *c2 = new TCanvas("c2","c2",600,400);
2002  gStyle->SetPalette(kBird);
2003  TH2F *hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
2004  Float_t px, py;
2005  for (Int_t i = 0; i < 25000; i++) {
2006  gRandom->Rannor(px,py);
2007  hsurf2->Fill(px-1,5*py);
2008  hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
2009  }
2010  hsurf2->Draw("SURF2");
2011  return c2;
2012 }
2013 End_Macro
2014 
2015 The following example shows a 2D histogram plotted with the option
2016 `SURF3`. The option `SURF3` draws a surface plot using the
2017 hidden line removal technique with, in addition, a filled contour view drawn on the
2018 top. Combined with the option `SURF3`, the option `Z` allows
2019 to display the color palette defined by `gStyle->SetPalette()`.
2020 
2021 Begin_Macro(source)
2022 {
2023  TCanvas *c2 = new TCanvas("c2","c2",600,400);
2024  gStyle->SetPalette(kBird);
2025  TH2F *hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
2026  Float_t px, py;
2027  for (Int_t i = 0; i < 25000; i++) {
2028  gRandom->Rannor(px,py);
2029  hsurf3->Fill(px-1,5*py);
2030  hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
2031  }
2032  hsurf3->Draw("SURF3");
2033  return c2;
2034 }
2035 End_Macro
2036 
2037 The following example shows a 2D histogram plotted with the option
2038 `SURF4`. The option `SURF4` draws a surface using the Gouraud
2039 shading technique.
2040 
2041 Begin_Macro(source)
2042 {
2043  TCanvas *c2 = new TCanvas("c2","c2",600,400);
2044  TH2F *hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
2045  Float_t px, py;
2046  for (Int_t i = 0; i < 25000; i++) {
2047  gRandom->Rannor(px,py);
2048  hsurf4->Fill(px-1,5*py);
2049  hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
2050  }
2051  hsurf4->SetFillColor(kOrange);
2052  hsurf4->Draw("SURF4");
2053  return c2;
2054 }
2055 End_Macro
2056 
2057 The following example shows a 2D histogram plotted with the option
2058 `SURF5 CYL`. Combined with the option `SURF5`, the option
2059 `Z` allows to display the color palette defined by `gStyle->SetPalette()`.
2060 
2061 Begin_Macro(source)
2062 {
2063  TCanvas *c2 = new TCanvas("c2","c2",600,400);
2064  gStyle->SetPalette(kBird);
2065  TH2F *hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
2066  Float_t px, py;
2067  for (Int_t i = 0; i < 25000; i++) {
2068  gRandom->Rannor(px,py);
2069  hsurf5->Fill(px-1,5*py);
2070  hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
2071  }
2072  hsurf5->SetFillColor(kOrange);
2073  hsurf5->Draw("SURF5 CYL");
2074  return c2;
2075 }
2076 End_Macro
2077 
2078 The following example shows a 2D histogram plotted with the option
2079 `SURF7`. The option `SURF7` draws a surface plot using the
2080 hidden surfaces removal technique with, in addition, a line contour view drawn on the
2081 top. Combined with the option `SURF7`, the option `Z` allows
2082 to display the color palette defined by `gStyle->SetPalette()`.
2083 
2084 Begin_Macro(source)
2085 {
2086  TCanvas *c2 = new TCanvas("c2","c2",600,400);
2087  gStyle->SetPalette(kBird);
2088  TH2F *hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
2089  Float_t px, py;
2090  for (Int_t i = 0; i < 25000; i++) {
2091  gRandom->Rannor(px,py);
2092  hsurf7->Fill(px-1,5*py);
2093  hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
2094  }
2095  hsurf7->Draw("SURF7");
2096  return c2;
2097 }
2098 End_Macro
2099 
2100 As shown in the following example, when a contour plot is painted on top of a
2101 surface plot using the option `SAME`, the contours appear in 3D on the
2102 surface.
2103 
2104 Begin_Macro(source)
2105 {
2106  TCanvas *c20=new TCanvas("c20","c20",600,400);
2107  int NBins = 50;
2108  double d = 2;
2109  TH2F* hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
2110  for (int bx = 1; bx <= NBins; ++bx) {
2111  for (int by = 1; by <= NBins; ++by) {
2112  double x = hsc->GetXaxis()->GetBinCenter(bx);
2113  double y = hsc->GetYaxis()->GetBinCenter(by);
2114  hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
2115  }
2116  }
2117  gStyle->SetPalette(kBird);
2118  hsc->Draw("surf2");
2119  hsc->Draw("CONT1 SAME");
2120  return c20;
2121 }
2122 End_Macro
2123 
2124 
2125 ### <a name="HP19"></a> Cylindrical, Polar, Spherical and PseudoRapidity/Phi options
2126 
2127 
2128 Legos and surfaces plots are represented by default in Cartesian coordinates.
2129 Combined with any `LEGOn` or `SURFn` options the following
2130 options allow to draw a lego or a surface in other coordinates systems.
2131 
2132 | Option | Description |
2133 |----------|-------------------------------------------------------------------|
2134 | "CYL" | Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y coordinate on the cylinder length.|
2135 | "POL" | Use Polar coordinates. The X coordinate is mapped on the angle and the Y coordinate on the radius.|
2136 | "SPH" | Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y coordinate on the longitude.|
2137 | "PSR" | Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.|
2138 
2139 
2140 
2141 <b>WARNING:</b> Axis are not drawn with these options.
2142 
2143 The following example shows the same histogram as a lego plot is the four
2144 different coordinates systems.
2145 
2146 Begin_Macro(source)
2147 {
2148  TCanvas *c3 = new TCanvas("c3","c3",600,400);
2149  c3->Divide(2,2);
2150  TH2F *hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
2151  Float_t px, py;
2152  for (Int_t i = 0; i < 25000; i++) {
2153  gRandom->Rannor(px,py);
2154  hlcc->Fill(px-1,5*py);
2155  hlcc->Fill(2+0.5*px,2*py-10.,0.1);
2156  }
2157  hlcc->SetFillColor(kYellow);
2158  c3->cd(1); hlcc->Draw("LEGO1 CYL");
2159  c3->cd(2); TH2F *hlpc = (TH2F*) hlcc->DrawClone("LEGO1 POL");
2160  hlpc->SetTitle("Polar coordinates");
2161  c3->cd(3); TH2F *hlsc = (TH2F*) hlcc->DrawClone("LEGO1 SPH");
2162  hlsc->SetTitle("Spherical coordinates");
2163  c3->cd(4); TH2F *hlprpc = (TH2F*) hlcc->DrawClone("LEGO1 PSR");
2164  hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
2165  return c3;
2166 }
2167 End_Macro
2168 
2169 The following example shows the same histogram as a surface plot is the four different coordinates systems.
2170 
2171 Begin_Macro(source)
2172 {
2173  TCanvas *c4 = new TCanvas("c4","c4",600,400);
2174  c4->Divide(2,2);
2175  TH2F *hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
2176  Float_t px, py;
2177  for (Int_t i = 0; i < 25000; i++) {
2178  gRandom->Rannor(px,py);
2179  hscc->Fill(px-1,5*py);
2180  hscc->Fill(2+0.5*px,2*py-10.,0.1);
2181  }
2182  gStyle->SetPalette(kBird);
2183  c4->cd(1); hscc->Draw("SURF1 CYL");
2184  c4->cd(2); TH2F *hspc = (TH2F*) hscc->DrawClone("SURF1 POL");
2185  hspc->SetTitle("Polar coordinates");
2186  c4->cd(3); TH2F *hssc = (TH2F*) hscc->DrawClone("SURF1 SPH");
2187  hssc->SetTitle("Spherical coordinates");
2188  c4->cd(4); TH2F *hsprpc = (TH2F*) hscc->DrawClone("SURF1 PSR");
2189  hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
2190  return c4;
2191 }
2192 End_Macro
2193 
2194 
2195 ### <a name="HP20"></a> Base line for bar-charts and lego plots
2196 
2197 
2198 By default the base line used to draw the boxes for bar-charts and lego plots is
2199 the histogram minimum. It is possible to force this base line to be 0 with the
2200 command:
2201 
2202  gStyle->SetHistMinimumZero();
2203 
2204 Begin_Macro(source)
2205 {
2206  TCanvas *c5 = new TCanvas("c5","c5",700,400);
2207  c5->Divide(2,1);
2208  gStyle->SetHistMinimumZero(1);
2209  TH1F *hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
2210  TH2F *hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
2211  Int_t i;
2212  Double_t x,y;
2213  hz1->SetFillColor(kBlue);
2214  hz2->SetFillColor(kBlue);
2215  for (i=0;i<10000;i++) {
2216  x = gRandom->Gaus(0,1);
2217  y = gRandom->Gaus(0,1);
2218  if (x>0) {
2219  hz1->Fill(x,1);
2220  hz2->Fill(x,y,1);
2221  } else {
2222  hz1->Fill(x,-1);
2223  hz2->Fill(x,y,-2);
2224  }
2225  }
2226  c5->cd(1); hz1->Draw("bar2");
2227  c5->cd(2); hz2->Draw("lego1");
2228  return c5;
2229 }
2230 End_Macro
2231 
2232 This option also works for horizontal plots. The example given in the section
2233 ["The bar chart option"](#HP100) appears as follow:
2234 
2235 Begin_Macro(source)
2236 {
2237  int i;
2238  const Int_t nx = 8;
2239  string os_X[nx] = {"8","32","128","512","2048","8192","32768","131072"};
2240  float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
2241  float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
2242 
2243  TCanvas *cbh = new TCanvas("cbh","cbh",400,600);
2244  cbh->SetGrid();
2245 
2246  gStyle->SetHistMinimumZero();
2247 
2248  TH1F *h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
2249  h1bh->SetFillColor(4);
2250  h1bh->SetBarWidth(0.4);
2251  h1bh->SetBarOffset(0.1);
2252  h1bh->SetStats(0);
2253  h1bh->SetMinimum(-5);
2254  h1bh->SetMaximum(5);
2255 
2256  for (i=1; i<=nx; i++) {
2257  h1bh->Fill(os_X[i-1].c_str(), d_35_0[i-1]);
2258  h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1].c_str());
2259  }
2260 
2261  h1bh->Draw("hbar");
2262 
2263  TH1F *h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
2264  h2bh->SetFillColor(38);
2265  h2bh->SetBarWidth(0.4);
2266  h2bh->SetBarOffset(0.5);
2267  h2bh->SetStats(0);
2268  for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1].c_str(), d_35_1[i-1]);
2269 
2270  h2bh->Draw("hbar same");
2271 
2272  return cbh;
2273 }
2274 End_Macro
2275 
2276 
2277 ### <a name="HP20a"></a> TH2Poly Drawing
2278 
2279 
2280 The following options are supported:
2281 
2282 | Option | Description |
2283 |----------|-------------------------------------------------------------------|
2284 | "SCAT" | Draw a scatter plot (default).|
2285 | "COL" | Draw a color plot. All the bins are painted even the empty bins.|
2286 | "COLZ" | Same as "COL". In addition the color palette is also drawn.|
2287 | "0" | When used with any COL options, the empty bins are not drawn.|
2288 | "TEXT" | Draw bin contents as text (format set via `gStyle->SetPaintTextFormat`).|
2289 | "TEXTN" | Draw bin names as text.|
2290 | "TEXTnn" | Draw bin contents as text at angle nn (0 < nn < 90).|
2291 | "L" | Draw the bins boundaries as lines. The lines attributes are the TGraphs ones.|
2292 | "P" | Draw the bins boundaries as markers. The markers attributes are the TGraphs ones.|
2293 | "F" | Draw the bins boundaries as filled polygons. The filled polygons attributes are the TGraphs ones.|
2294 
2295 
2296 
2297 `TH2Poly` can be drawn as a color plot (option COL). `TH2Poly` bins can have any
2298 shapes. The bins are defined as graphs. The following macro is a very simple
2299 example showing how to book a TH2Poly and draw it.
2300 
2301 Begin_Macro(source)
2302 {
2303  TCanvas *ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
2304  TH2Poly *h2p = new TH2Poly();
2305  h2p->SetName("h2poly_name");
2306  h2p->SetTitle("h2poly_title");
2307  Double_t px1[] = {0, 5, 6};
2308  Double_t py1[] = {0, 0, 5};
2309  Double_t px2[] = {0, -1, -1, 0};
2310  Double_t py2[] = {0, 0, -1, 3};
2311  Double_t px3[] = {4, 3, 0, 1, 2.4};
2312  Double_t py3[] = {4, 3.7, 1, 3.7, 2.5};
2313  h2p->AddBin(3, px1, py1);
2314  h2p->AddBin(4, px2, py2);
2315  h2p->AddBin(5, px3, py3);
2316  h2p->Fill(0.1, 0.01, 3);
2317  h2p->Fill(-0.5, -0.5, 7);
2318  h2p->Fill(-0.7, -0.5, 1);
2319  h2p->Fill(1, 3, 1.5);
2320  Double_t fx[] = {0.1, -0.5, -0.7, 1};
2321  Double_t fy[] = {0.01, -0.5, -0.5, 3};
2322  Double_t fw[] = {3, 1, 1, 1.5};
2323  h2p->FillN(4, fx, fy, fw);
2324  gStyle->SetPalette(kBird);
2325  h2p->Draw("col");
2326 }
2327 End_Macro
2328 
2329 Rectangular bins are a frequent case. The special version of
2330 the `AddBin` method allows to define them more easily like
2331 shown in the following example (th2polyBoxes.C).
2332 
2333 Begin_Macro(source)
2334 ../../../tutorials/hist/th2polyBoxes.C
2335 End_Macro
2336 
2337 One `TH2Poly` bin can be a list of polygons. Such bins are defined
2338 by calling `AddBin` with a `TMultiGraph`. The following example
2339 shows a such case:
2340 
2341 Begin_Macro(source)
2342 {
2343  TCanvas *ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
2344 
2345  Int_t i, bin;
2346  const Int_t nx = 48;
2347  const char *states [nx] = {
2348  "alabama", "arizona", "arkansas", "california",
2349  "colorado", "connecticut", "delaware", "florida",
2350  "georgia", "idaho", "illinois", "indiana",
2351  "iowa", "kansas", "kentucky", "louisiana",
2352  "maine", "maryland", "massachusetts", "michigan",
2353  "minnesota", "mississippi", "missouri", "montana",
2354  "nebraska", "nevada", "new_hampshire", "new_jersey",
2355  "new_mexico", "new_york", "north_carolina", "north_dakota",
2356  "ohio", "oklahoma", "oregon", "pennsylvania",
2357  "rhode_island", "south_carolina", "south_dakota", "tennessee",
2358  "texas", "utah", "vermont", "virginia",
2359  "washington", "west_virginia", "wisconsin", "wyoming"
2360  };
2361  Double_t pop[nx] = {
2362  4708708, 6595778, 2889450, 36961664, 5024748, 3518288, 885122, 18537969,
2363  9829211, 1545801, 12910409, 6423113, 3007856, 2818747, 4314113, 4492076,
2364  1318301, 5699478, 6593587, 9969727, 5266214, 2951996, 5987580, 974989,
2365  1796619, 2643085, 1324575, 8707739, 2009671, 19541453, 9380884, 646844,
2366  11542645, 3687050, 3825657, 12604767, 1053209, 4561242, 812383, 6296254,
2367  24782302, 2784572, 621760, 7882590, 6664195, 1819777, 5654774, 544270
2368  };
2369 
2370  Double_t lon1 = -130;
2371  Double_t lon2 = -65;
2372  Double_t lat1 = 24;
2373  Double_t lat2 = 50;
2374  TH2Poly *p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
2375 
2376  TFile::SetCacheFileDir(".");
2377  TFile *f = TFile::Open("http://root.cern.ch/files/usa.root", "CACHEREAD");
2378 
2379  TMultiGraph *mg;
2380  TKey *key;
2381  TIter nextkey(gDirectory->GetListOfKeys());
2382  while ((key = (TKey*)nextkey())) {
2383  TObject *obj = key->ReadObj();
2384  if (obj->InheritsFrom("TMultiGraph")) {
2385  mg = (TMultiGraph*)obj;
2386  bin = p->AddBin(mg);
2387  }
2388  }
2389 
2390  for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
2391 
2392  gStyle->SetOptStat(11);
2393  gStyle->SetPalette(kBird);
2394  p->Draw("COLZ L");
2395 }
2396 End_Macro
2397 
2398 `TH2Poly` histograms can also be plotted using the GL interface using
2399 the option "GLLEGO".
2400 
2401 \since **ROOT version 6.09/01**
2402 
2403 In some cases it can be useful to not draw the empty bins. the option "0"
2404 combined with the option "COL" et COLZ allows to do that.
2405 
2406 Begin_Macro(source)
2407 {
2408  TCanvas *chc = new TCanvas("chc","chc",600,400);
2409 
2410  TH2Poly *hc = new TH2Poly();
2411  hc->Honeycomb(0,0,.1,25,25);
2412  hc->SetName("hc");
2413  hc->SetTitle("Option COLZ 0");
2414  TRandom ran;
2415  for (int i = 0; i<300; i++) hc->Fill(ran.Gaus(2.,1), ran.Gaus(2.,1));
2416  hc->Draw("colz 0");
2417 }
2418 End_Macro
2419 
2420 ### <a name="HP21"></a> The SPEC option
2421 
2422 
2423 This option allows to use the `TSpectrum2Painter` tools. See the full
2424 documentation in `TSpectrum2Painter::PaintSpectrum`.
2425 
2426 
2427 ### <a name="HP22"></a> Option "Z" : Adding the color palette on the right side of the pad
2428 
2429 
2430 When this option is specified, a color palette with an axis indicating the value
2431 of the corresponding color is drawn on the right side of the picture. In case,
2432 not enough space is left, one can increase the size of the right margin by
2433 calling `TPad::SetRightMargin()`. The attributes used to display the
2434 palette axis values are taken from the Z axis of the object. For example, to
2435 set the labels size on the palette axis do:
2436 
2437  hist->GetZaxis()->SetLabelSize().
2438 
2439 <b>WARNING:</b> The palette axis is always drawn vertically.
2440 
2441 
2442 ### <a name="HP23"></a> Setting the color palette
2443 
2444 
2445 To change the color palette `TStyle::SetPalette` should be used, eg:
2446 
2447  gStyle->SetPalette(ncolors,colors);
2448 
2449 For example the option `COL` draws a 2D histogram with cells
2450 represented by a box filled with a color index which is a function
2451 of the cell content.
2452 If the cell content is N, the color index used will be the color number
2453 in `colors[N]`, etc. If the maximum cell content is greater than
2454 `ncolors`, all cell contents are scaled to `ncolors`.
2455 
2456 If ` ncolors <= 0`, a default palette (see below) of 50 colors is
2457 defined. This palette is recommended for pads, labels ...
2458 
2459 `if ncolors == 1 && colors == 0`, then a Pretty Palette with a
2460 Spectrum Violet->Red is created with 50 colors. That's the default rain bow
2461 palette.
2462 
2463 Other pre-defined palettes with 255 colors are available when `colors == 0`.
2464 The following value of `ncolors` give access to:
2465 
2466 
2467  if ncolors = 51 and colors=0, a Deep Sea palette is used.
2468  if ncolors = 52 and colors=0, a Grey Scale palette is used.
2469  if ncolors = 53 and colors=0, a Dark Body Radiator palette is used.
2470  if ncolors = 54 and colors=0, a two-color hue palette palette is used.(dark blue through neutral gray to bright yellow)
2471  if ncolors = 55 and colors=0, a Rain Bow palette is used.
2472  if ncolors = 56 and colors=0, an inverted Dark Body Radiator palette is used.
2473 
2474 
2475 If `ncolors > 0 && colors == 0`, the default palette is used with a maximum of ncolors.
2476 
2477 The default palette defines:
2478 
2479 - index 0 to 9 : shades of grey
2480 - index 10 to 19 : shades of brown
2481 - index 20 to 29 : shades of blue
2482 - index 30 to 39 : shades of red
2483 - index 40 to 49 : basic colors
2484 
2485 The color numbers specified in the palette can be viewed by selecting
2486 the item `colors` in the `VIEW` menu of the canvas tool bar.
2487 The red, green, and blue components of a color can be changed thanks to
2488 `TColor::SetRGB()`.
2489 
2490 
2491 ### <a name="HP24"></a> Drawing a sub-range of a 2D histogram; the [cutg] option
2492 
2493 
2494 Using a `TCutG` object, it is possible to draw a sub-range of a 2D
2495 histogram. One must create a graphical cut (mouse or C++) and specify the name
2496 of the cut between `[]` in the `Draw()` option.
2497 For example (fit2a.C), with a `TCutG` named `cutg`, one can call:
2498 
2499  myhist->Draw("surf1 [cutg]");
2500 
2501 To invert the cut, it is enough to put a `-` in front of its name:
2502 
2503  myhist->Draw("surf1 [-cutg]");
2504 
2505 It is possible to apply several cuts (`,` means logical AND):
2506 
2507  myhist->Draw("surf1 [cutg1,cutg2]");
2508 
2509 Begin_Macro(source)
2510 ../../../tutorials/fit/fit2a.C
2511 End_Macro
2512 
2513 ### <a name="HP25"></a> Drawing options for 3D histograms
2514 
2515 
2516 | Option | Description |
2517 |----------|-------------------------------------------------------------------|
2518 | "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)`|
2519 | "BOX" | Draw a for each cell with volume proportional to the content's absolute value. An hidden line removal algorithm is used|
2520 | "BOX1" | Same as BOX but an hidden surface removal algorithm is used|
2521 | "BOX2" | The boxes' colors are picked in the current palette according to the bins' contents|
2522 | "BOX2Z" | Same as "BOX2". In addition the color palette is also drawn.|
2523 | "BOX3" | Same as BOX1, but the border lines of each lego-bar are not drawn.|
2524 
2525 Note that instead of `BOX` one can also use `LEGO`.
2526 
2527 By default, like 2D histograms, 3D histograms are drawn as scatter plots.
2528 
2529 The following example shows a 3D histogram plotted as a scatter plot.
2530 
2531 Begin_Macro(source)
2532 {
2533  auto c06 = new TCanvas("c06","c06",600,400);
2534  gStyle->SetOptStat(kFALSE);
2535  auto h3scat = new TH3F("h3scat","Option SCAT (default) ",15,-2,2,15,-2,2,15,0,4);
2536  Double_t x, y, z;
2537  for (Int_t i=0;i<10000;i++) {
2538  gRandom->Rannor(x, y);
2539  z = x*x + y*y;
2540  h3scat->Fill(x,y,z);
2541  }
2542  h3scat->Draw();
2543 }
2544 End_Macro
2545 
2546 The following example shows a 3D histogram plotted with the option `BOX`.
2547 
2548 Begin_Macro(source)
2549 {
2550  auto c16 = new TCanvas("c16","c16",600,400);
2551  gStyle->SetOptStat(kFALSE);
2552  auto h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
2553  Double_t x, y, z;
2554  for (Int_t i=0;i<10000;i++) {
2555  gRandom->Rannor(x, y);
2556  z = x*x + y*y;
2557  h3box->Fill(x,y,z);
2558  }
2559  h3box->Draw("BOX");
2560 }
2561 End_Macro
2562 
2563 The following example shows a 3D histogram plotted with the option `BOX1`.
2564 
2565 Begin_Macro(source)
2566 {
2567  auto c36 = new TCanvas("c36","c36",600,400);
2568  gStyle->SetOptStat(kFALSE);
2569  auto h3box = new TH3F("h3box","Option BOX1",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2570  Double_t x, y, z;
2571  for (Int_t i=0;i<10000;i++) {
2572  gRandom->Rannor(x, y);
2573  z = abs(sin(x)/x + cos(y)*y);
2574  h3box->Fill(x,y,z);
2575  }
2576  h3box->SetFillColor(9);
2577  h3box->Draw("BOX1");
2578 }
2579 End_Macro
2580 
2581 The following example shows a 3D histogram plotted with the option `BOX2`.
2582 
2583 Begin_Macro(source)
2584 {
2585  auto c56 = new TCanvas("c56","c56",600,400);
2586  gStyle->SetOptStat(kFALSE);
2587  auto h3box = new TH3F("h3box","Option BOX2",10,-2.,2.,10,-2.,2.,10,-0.5,2.);
2588  Double_t x, y, z;
2589  for (Int_t i=0;i<10000;i++) {
2590  gRandom->Rannor(x, y);
2591  z = abs(sin(x)/x + cos(y)*y);
2592  h3box->Fill(x,y,z);
2593  }
2594  h3box->Draw("BOX2 Z");
2595 }
2596 End_Macro
2597 
2598 The following example shows a 3D histogram plotted with the option `BOX3`.
2599 
2600 Begin_Macro(source)
2601 {
2602  auto c46 = new TCanvas("c46","c46",600,400);
2603  c46->SetFillColor(38);
2604  gStyle->SetOptStat(kFALSE);
2605  auto h3box = new TH3F("h3box","Option BOX3",15,-2,2,15,-2,2,15,0,4);
2606  Double_t x, y, z;
2607  for (Int_t i=0;i<10000;i++) {
2608  gRandom->Rannor(x, y);
2609  z = x*x + y*y;
2610  h3box->Fill(x,y,z);
2611  }
2612  h3box->Draw("BOX3");
2613 }
2614 End_Macro
2615 
2616 For all the `BOX` options each bin is drawn as a 3D box with a volume proportional
2617 to the absolute value of the bin content. The bins with a negative content are
2618 drawn with a X on each face of the box as shown in the following example:
2619 
2620 Begin_Macro(source)
2621 {
2622  auto c = new TCanvas("c","c",600,400);
2623  gStyle->SetOptStat(kFALSE);
2624  auto h3box = new TH3F("h3box","Option BOX1 with negative bins",3, 0., 4., 3, 0.,4., 3, 0., 4.);
2625  h3box->Fill(0., 2., 2., 10.);
2626  h3box->Fill(2., 2., 2., 5.);
2627  h3box->Fill(2., 2., .5, 2.);
2628  h3box->Fill(2., 2., 3., -1.);
2629  h3box->Fill(3., 2., 2., -10.);
2630  h3box->SetFillColor(8);
2631  h3box->Draw("box1");
2632 }
2633 End_Macro
2634 
2635 The following example shows a 3D histogram plotted with the option `ISO`.
2636 
2637 Begin_Macro(source)
2638 {
2639  auto c26 = new TCanvas("c26","c26",600,400);
2640  gStyle->SetOptStat(kFALSE);
2641  auto h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
2642  Double_t x, y, z;
2643  for (Int_t i=0;i<10000;i++) {
2644  gRandom->Rannor(x, y);
2645  z = x*x + y*y;
2646  h3iso->Fill(x,y,z);
2647  }
2648  h3iso->SetFillColor(kCyan);
2649  h3iso->Draw("ISO");
2650 }
2651 End_Macro
2652 
2653 
2654 ### <a name="HP26"></a> Drawing option for histograms' stacks
2655 
2656 
2657 Stacks of histograms are managed with the `THStack`. A `THStack`
2658 is a collection of `TH1` (or derived) objects. For painting only the
2659 `THStack` containing `TH1` only or
2660 `THStack` containing `TH2` only will be considered.
2661 
2662 By default, histograms are shown stacked:
2663 
2664 1. The first histogram is paint.
2665 2. The the sum of the first and second, etc...
2666 
2667 If the option `NOSTACK` is specified, the histograms are all paint in
2668 the same pad as if the option `SAME` had been specified. This allows to
2669 compute X and Y scales common to all the histograms, like
2670 `TMultiGraph` does for graphs.
2671 
2672 If the option `PADS` is specified, the current pad/canvas is
2673 subdivided into a number of pads equal to the number of histograms and each
2674 histogram is paint into a separate pad.
2675 
2676 The following example shows various types of stacks (hstack.C).
2677 
2678 Begin_Macro(source)
2679 ../../../tutorials/hist/hstack.C
2680 End_Macro
2681 
2682 The option `nostackb` allows to draw the histograms next to each
2683 other as bar charts:
2684 
2685 Begin_Macro(source)
2686 {
2687  TCanvas *cst0 = new TCanvas("cst0","cst0",600,400);
2688  THStack *hs = new THStack("hs","Stacked 1D histograms: option #font[82]{\"nostackb\"}");
2689 
2690  TH1F *h1 = new TH1F("h1","h1",10,-4,4);
2691  h1->FillRandom("gaus",20000);
2692  h1->SetFillColor(kRed);
2693  hs->Add(h1);
2694 
2695  TH1F *h2 = new TH1F("h2","h2",10,-4,4);
2696  h2->FillRandom("gaus",15000);
2697  h2->SetFillColor(kBlue);
2698  hs->Add(h2);
2699 
2700  TH1F *h3 = new TH1F("h3","h3",10,-4,4);
2701  h3->FillRandom("gaus",10000);
2702  h3->SetFillColor(kGreen);
2703  hs->Add(h3);
2704 
2705  hs->Draw("nostackb");
2706  hs->GetXaxis()->SetNdivisions(-10);
2707  cst0->SetGridx();
2708  return cst0;
2709 }
2710 End_Macro
2711 
2712 If at least one of the histograms in the stack has errors, the whole stack is
2713 visualized by default with error bars. To visualize it without errors the
2714 option `HIST` should be used.
2715 
2716 Begin_Macro(source)
2717 {
2718  TCanvas *cst1 = new TCanvas("cst1","cst1",700,400);
2719  cst1->Divide(2,1);
2720 
2721  TH1F * hst11 = new TH1F("hst11", "", 20, -10, 10);
2722  hst11->Sumw2();
2723  hst11->FillRandom("gaus", 1000);
2724  hst11->SetFillColor(kViolet);
2725  hst11->SetLineColor(kViolet);
2726 
2727  TH1F * hst12 = new TH1F("hst12", "", 20, -10, 10);
2728  hst12->FillRandom("gaus", 500);
2729  hst12->SetFillColor(kBlue);
2730  hst12->SetLineColor(kBlue);
2731 
2732  THStack st1("st1", "st1");
2733  st1.Add(hst11);
2734  st1.Add(hst12);
2735 
2736  cst1->cd(1); st1.Draw();
2737  cst1->cd(2); st1.Draw("hist");
2738 
2739  return cst1;
2740 }
2741 End_Macro
2742 
2743 ### <a name="HP27"></a> Drawing of 3D implicit functions
2744 
2745 
2746 3D implicit functions (`TF3`) can be drawn as iso-surfaces.
2747 The implicit function f(x,y,z) = 0 is drawn in cartesian coordinates.
2748 In the following example the options "FB" and "BB" suppress the
2749 "Front Box" and "Back Box" around the plot.
2750 
2751 Begin_Macro(source)
2752 {
2753  TCanvas *c2 = new TCanvas("c2","c2",600,400);
2754  TF3 *f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
2755  f3->SetClippingBoxOn(0,0,0);
2756  f3->SetFillColor(30);
2757  f3->SetLineColor(15);
2758  f3->Draw("FBBB");
2759  return c2;
2760 }
2761 End_Macro
2762 
2763 
2764 ### <a name="HP28"></a> Associated functions drawing
2765 
2766 
2767 An associated function is created by `TH1::Fit`. More than on fitted
2768 function can be associated with one histogram (see `TH1::Fit`).
2769 
2770 A `TF1` object `f1` can be added to the list of associated
2771 functions of an histogram `h` without calling `TH1::Fit`
2772 simply doing:
2773 
2774  h->GetListOfFunctions()->Add(f1);
2775 
2776 or
2777 
2778  h->GetListOfFunctions()->Add(f1,someoption);
2779 
2780 To retrieve a function by name from this list, do:
2781 
2782  TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
2783 
2784 or
2785 
2786  TF1 *f1 = h->GetFunction(name);
2787 
2788 Associated functions are automatically painted when an histogram is drawn.
2789 To avoid the painting of the associated functions the option `HIST`
2790 should be added to the list of the options used to paint the histogram.
2791 
2792 
2793 ### <a name="HP29"></a> Drawing using OpenGL
2794 
2795 
2796 The class `TGLHistPainter` allows to paint data set using the OpenGL 3D
2797 graphics library. The plotting options start with `GL` keyword.
2798 In addition, in order to inform canvases that OpenGL should be used to render
2799 3D representations, the following option should be set:
2800 
2801  gStyle->SetCanvasPreferGL(true);
2802 
2803 
2804 #### <a name="HP29a"></a> General information: plot types and supported options
2805 
2806 The following types of plots are provided:
2807 
2808 For lego plots the supported options are:
2809 
2810 | Option | Description |
2811 |----------|-------------------------------------------------------------------|
2812 | "GLLEGO" | Draw a lego plot. It works also for `TH2Poly`.|
2813 | "GLLEGO2"| Bins with color levels.|
2814 | "GLLEGO3"| Cylindrical bars.|
2815 
2816 
2817 
2818 Lego painter in cartesian supports logarithmic scales for X, Y, Z.
2819 In polar only Z axis can be logarithmic, in cylindrical only Y.
2820 
2821 For surface plots (`TF2` and `TH2`) the supported options are:
2822 
2823 | Option | Description |
2824 |-----------|------------------------------------------------------------------|
2825 | "GLSURF" | Draw a surface.|
2826 | "GLSURF1" | Surface with color levels|
2827 | "GLSURF2" | The same as "GLSURF1" but without polygon outlines.|
2828 | "GLSURF3" | Color level projection on top of plot (works only in cartesian coordinate system).|
2829 | "GLSURF4" | Same as "GLSURF" but without polygon outlines.|
2830 
2831 
2832 
2833 The surface painting in cartesian coordinates supports logarithmic scales along
2834 X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
2835 in cylindrical coordinates only the Y axis.
2836 
2837 Additional options to SURF and LEGO - Coordinate systems:
2838 
2839 | Option | Description |
2840 |----------|-------------------------------------------------------------------|
2841 | " " | Default, cartesian coordinates system.|
2842 | "POL" | Polar coordinates system.|
2843 | "CYL" | Cylindrical coordinates system.|
2844 | "SPH" | Spherical coordinates system.|
2845 
2846 
2847 
2848 #### <a name="HP290"></a> TH3 as color boxes
2849 
2850 The supported option is:
2851 
2852 | Option | Description |
2853 |----------|-------------------------------------------------------------------|
2854 | "GLCOL" | H3 is drawn using semi-transparent colored boxes. See `$ROOTSYS/tutorials/gl/glvox1.C`.|
2855 
2856 
2857 
2858 #### <a name="HP29b"></a> TH3 as boxes (spheres)
2859 
2860 The supported options are:
2861 
2862 | Option | Description |
2863 |----------|-------------------------------------------------------------------|
2864 | "GLBOX" | TH3 as a set of boxes, size of box is proportional to bin content.|
2865 | "GLBOX1" | The same as "glbox", but spheres are drawn instead of boxes.|
2866 
2867 
2868 
2869 #### <a name="HP29c"></a> TH3 as iso-surface(s)
2870 
2871 The supported option is:
2872 
2873 | Option | Description |
2874 |----------|-------------------------------------------------------------------|
2875 | "GLISO" | TH3 is drawn using iso-surfaces.|
2876 
2877 
2878 
2879 #### <a name="HP29d"></a> TF3 (implicit function)
2880 
2881 The supported option is:
2882 
2883 | Option | Description |
2884 |----------|-------------------------------------------------------------------|
2885 | "GLTF3" | Draw a TF3.|
2886 
2887 
2888 
2889 #### <a name="HP29e"></a> Parametric surfaces
2890 
2891 `$ROOTSYS/tutorials/gl/glparametric.C` shows how to create parametric
2892 equations and visualize the surface.
2893 
2894 #### <a name="HP29f"></a> Interaction with the plots
2895 
2896 All the interactions are implemented via standard methods
2897 `DistancetoPrimitive()` and `ExecuteEvent()`. That's why all the
2898 interactions with the OpenGL plots are possible only when the mouse cursor is
2899 in the plot's area (the plot's area is the part of a the pad occupied by
2900 gl-produced picture). If the mouse cursor is not above gl-picture, the standard
2901 pad interaction is performed.
2902 
2903 #### <a name="HP29g"></a> Selectable parts
2904 
2905 Different parts of the plot can be selected:
2906 
2907 - xoz, yoz, xoy back planes: When such a plane selected, it's highlighted in green
2908  if the dynamic slicing by this plane is supported, and it's highlighted in red,
2909  if the dynamic slicing is not supported.
2910 - The plot itself:
2911  On surfaces, the selected surface is outlined in red. (TF3 and
2912  ISO are not outlined). On lego plots, the selected bin is
2913  highlighted. The bin number and content are displayed in pad's
2914  status bar. In box plots, the box or sphere is highlighted and
2915  the bin info is displayed in pad's status bar.
2916 
2917 
2918 #### <a name="HP29h"></a> Rotation and zooming
2919 
2920 
2921 - Rotation:
2922  When the plot is selected, it can be rotated by pressing and
2923  holding the left mouse button and move the cursor.
2924 - Zoom/Unzoom:
2925  Mouse wheel or 'j', 'J', 'k', 'K' keys.
2926 
2927 
2928 #### <a name="HP29i"></a> Panning
2929 
2930 The selected plot can be moved in a pad's area by pressing and
2931 holding the left mouse button and the shift key.
2932 
2933 #### <a name="HP29j"></a> Box cut
2934 
2935 Surface, iso, box, TF3 and parametric painters support box cut by
2936 pressing the 'c' or 'C' key when the mouse cursor is in a plot's
2937 area. That will display a transparent box, cutting away part of the
2938 surface (or boxes) in order to show internal part of plot. This box
2939 can be moved inside the plot's area (the full size of the box is
2940 equal to the plot's surrounding box) by selecting one of the box
2941 cut axes and pressing the left mouse button to move it.
2942 
2943 #### <a name="HP29k"></a> Plot specific interactions (dynamic slicing etc.)
2944 
2945 Currently, all gl-plots support some form of slicing. When back plane
2946 is selected (and if it's highlighted in green) you can press and hold
2947 left mouse button and shift key and move this back plane inside
2948 plot's area, creating the slice. During this "slicing" plot becomes
2949 semi-transparent. To remove all slices (and projected curves for
2950 surfaces) double click with left mouse button in a plot's area.
2951 
2952 #### <a name="HP29l"></a> Surface with option "GLSURF"
2953 
2954 The surface profile is displayed on the slicing plane.
2955 The profile projection is drawn on the back plane
2956 by pressing `'p'` or `'P'` key.
2957 
2958 #### <a name="HP29m"></a> TF3
2959 
2960 The contour plot is drawn on the slicing plane. For TF3 the color
2961 scheme can be changed by pressing 's' or 'S'.
2962 
2963 #### <a name="HP29n"></a> Box
2964 
2965 The contour plot corresponding to slice plane position is drawn in real time.
2966 
2967 #### <a name="HP29o"></a> Iso
2968 
2969 Slicing is similar to "GLBOX" option.
2970 
2971 #### <a name="HP29p"></a> Parametric plot
2972 
2973 No slicing. Additional keys: 's' or 'S' to change color scheme -
2974 about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
2975 increase number of polygons ('l' for "level" of details), 'w' or 'W'
2976 to show outlines ('w' for "wireframe").
2977 
2978 */
2979 
2980 TH1 *gCurrentHist = 0;
2981 
2984 
2985 const Int_t kNMAX = 2000;
2986 
2987 const Int_t kMAXCONTOUR = 104;
2988 const UInt_t kCannotRotate = BIT(11);
2989 
2990 static TString gStringEntries;
2991 static TString gStringMean;
2993 static TString gStringMeanY;
2996 static TString gStringStdDevX;
2998 static TString gStringStdDevZ;
3001 static TString gStringIntegral;
3014 ////////////////////////////////////////////////////////////////////////////////
3015 /// Default constructor.
3020  fH = 0;
3021  fXaxis = 0;
3022  fYaxis = 0;
3023  fZaxis = 0;
3024  fFunctions = 0;
3025  fXbuf = 0;
3026  fYbuf = 0;
3027  fNcuts = 0;
3028  fStack = 0;
3029  fLego = 0;
3030  fPie = 0;
3031  fGraph2DPainter = 0;
3032  fShowProjection = 0;
3033  fShowOption = "";
3034  for (int i=0; i<kMaxCuts; i++) {
3035  fCuts[i] = 0;
3036  fCutsOpt[i] = 0;
3037  }
3038 
3039  gStringEntries = gEnv->GetValue("Hist.Stats.Entries", "Entries");
3040  gStringMean = gEnv->GetValue("Hist.Stats.Mean", "Mean");
3041  gStringMeanX = gEnv->GetValue("Hist.Stats.MeanX", "Mean x");
3042  gStringMeanY = gEnv->GetValue("Hist.Stats.MeanY", "Mean y");
3043  gStringMeanZ = gEnv->GetValue("Hist.Stats.MeanZ", "Mean z");
3044  gStringStdDev = gEnv->GetValue("Hist.Stats.StdDev", "Std Dev");
3045  gStringStdDevX = gEnv->GetValue("Hist.Stats.StdDevX", "Std Dev x");
3046  gStringStdDevY = gEnv->GetValue("Hist.Stats.StdDevY", "Std Dev y");
3047  gStringStdDevZ = gEnv->GetValue("Hist.Stats.StdDevZ", "Std Dev z");
3048  gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
3049  gStringOverflow = gEnv->GetValue("Hist.Stats.Overflow", "Overflow");
3050  gStringIntegral = gEnv->GetValue("Hist.Stats.Integral", "Integral");
3051  gStringIntegralBinWidth = gEnv->GetValue("Hist.Stats.IntegralBinWidth", "Integral(w)");
3052  gStringSkewness = gEnv->GetValue("Hist.Stats.Skewness", "Skewness");
3053  gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
3054  gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
3055  gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
3056  gStringKurtosis = gEnv->GetValue("Hist.Stats.Kurtosis", "Kurtosis");
3057  gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
3058  gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
3059  gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
3060 }
3061 
3062 ////////////////////////////////////////////////////////////////////////////////
3063 /// Default destructor.
3064 
3066 {
3067 }
3068 
3069 ////////////////////////////////////////////////////////////////////////////////
3070 /// Compute the distance from the point px,py to a line.
3071 ///
3072 /// Compute the closest distance of approach from point px,py to elements of
3073 /// an histogram. The distance is computed in pixels units.
3074 ///
3075 /// Algorithm: Currently, this simple model computes the distance from the mouse
3076 /// to the histogram contour only.
3079 {
3080 
3081  Double_t defaultLabelSize = 0.04; // See TAttAxis.h for source of this value
3082 
3083  const Int_t big = 9999;
3084  const Int_t kMaxDiff = 7;
3085 
3086  if (fPie) return fPie->DistancetoPrimitive(px, py);
3087 
3088  Double_t x = gPad->AbsPixeltoX(px);
3089  Double_t x1 = gPad->AbsPixeltoX(px+1);
3091  Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
3092  Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
3093  Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
3094  Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
3095  Int_t curdist = big;
3096  Int_t yxaxis, dyaxis,xyaxis, dxaxis;
3097  Bool_t dsame;
3098  TObject *PadPointer = gPad->GetPadPointer();
3099  if (!PadPointer) return 0;
3100  TString doption = PadPointer->GetDrawOption();
3101  Double_t factor = 1;
3102  if (fH->GetNormFactor() != 0) {
3103  factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3104  }
3105  // return if point is not in the histogram area
3106 
3107  // If a 3D view exists, check distance to axis
3108  TView *view = gPad->GetView();
3109  Int_t d1,d2,d3;
3110  if (view && Hoption.Contour != 14) {
3111  Double_t ratio;
3112  d3 = view->GetDistancetoAxis(3, px, py, ratio);
3113  if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
3114  d1 = view->GetDistancetoAxis(1, px, py, ratio);
3115  if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
3116  d2 = view->GetDistancetoAxis(2, px, py, ratio);
3117  if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
3118  if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
3119  goto FUNCTIONS;
3120  }
3121  // check if point is close to an axis
3122  doption.ToLower();
3123  dsame = kFALSE;
3124  if (doption.Contains("same")) dsame = kTRUE;
3125 
3126  dyaxis = Int_t(2*(puymin-puymax)*TMath::Max(Double_t(fYaxis->GetLabelSize()), defaultLabelSize));
3127  if (doption.Contains("y+")) {
3128  xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3129  if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
3130  if (!dsame) {
3131  if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3132  else gPad->SetSelected(fXaxis);
3133  return 0;
3134  }
3135  }
3136  } else {
3137  xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
3138  if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
3139  if (!dsame) {
3140  if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
3141  else gPad->SetSelected(fXaxis);
3142  return 0;
3143  }
3144  }
3145  }
3146 
3147  dxaxis = Int_t((puymin-puymax)*TMath::Max(Double_t(fXaxis->GetLabelSize()), defaultLabelSize));
3148  if (doption.Contains("x+")) {
3149  yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3150  if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
3151  if (!dsame) {
3152  if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3153  else gPad->SetSelected(fYaxis);
3154  return 0;
3155  }
3156  }
3157  } else {
3158  yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
3159  if (yxaxis < puymin) yxaxis = puymin;
3160  if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
3161  if (!dsame) {
3162  if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
3163  else gPad->SetSelected(fYaxis);
3164  return 0;
3165  }
3166  }
3167  }
3168 
3169  // if object is 2D or 3D return this object
3170  if (fH->GetDimension() == 2) {
3171  if (fH->InheritsFrom(TH2Poly::Class())) {
3172  TH2Poly *th2 = (TH2Poly*)fH;
3173  Double_t xmin, ymin, xmax, ymax;
3174  gPad->GetRangeAxis(xmin, ymin, xmax, ymax);
3175  Double_t pxu = gPad->AbsPixeltoX(px);
3176  Double_t pyu = gPad->AbsPixeltoY(py);
3177  if ((pxu>xmax) || (pxu < xmin) || (pyu>ymax) || (pyu < ymin)) {
3178  curdist = big;
3179  goto FUNCTIONS;
3180  } else {
3181  Int_t bin = th2->FindBin(pxu, pyu);
3182  if (bin>0) curdist = 1;
3183  else curdist = big;
3184  goto FUNCTIONS;
3185  }
3186  }
3187  Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
3188  if ( px > puxmin + delta2
3189  && px < puxmax - delta2
3190  && py > puymax + delta2
3191  && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
3192  }
3193 
3194  // point is inside histogram area. Find channel number
3195  if (gPad->IsVertical()) {
3196  Int_t bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3197  Int_t binsup = fXaxis->FindFixBin(gPad->PadtoX(x1));
3198  Double_t binval = factor*fH->GetBinContent(bin);
3199  Int_t pybin = gPad->YtoAbsPixel(gPad->YtoPad(binval));
3200  if (binval == 0 && pybin < puymin) pybin = 10000;
3201  // special case if more than one bin for the pixel
3202  if (binsup-bin>1) {
3203  Double_t binvalmin, binvalmax;
3204  binvalmin=binval;
3205  binvalmax=binval;
3206  for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3207  Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3208  if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3209  if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3210  }
3211  Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
3212  Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
3213  if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
3214  }
3215  if (bin != binsup) { // Mouse on bin border
3216  Double_t binsupval = factor*fH->GetBinContent(binsup);
3217  Int_t pybinsub = gPad->YtoAbsPixel(gPad->YtoPad(binsupval));
3218  if (py <= TMath::Max(pybinsub,pybin) && py >= TMath::Min(pybinsub,pybin) && pybin != 10000) return 0;
3219  }
3220  if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
3221  } else {
3222  Double_t y = gPad->AbsPixeltoY(py);
3223  Double_t y1 = gPad->AbsPixeltoY(py+1);
3224  Int_t bin = fXaxis->FindFixBin(gPad->PadtoY(y));
3225  Int_t binsup = fXaxis->FindFixBin(gPad->PadtoY(y1));
3226  Double_t binval = factor*fH->GetBinContent(bin);
3227  Int_t pxbin = gPad->XtoAbsPixel(gPad->XtoPad(binval));
3228  if (binval == 0 && pxbin > puxmin) pxbin = 10000;
3229  // special case if more than one bin for the pixel
3230  if (binsup-bin>1) {
3231  Double_t binvalmin, binvalmax;
3232  binvalmin=binval;
3233  binvalmax=binval;
3234  for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
3235  Double_t binvaltmp = factor*fH->GetBinContent(ibin);
3236  if (binvalmin>binvaltmp) binvalmin=binvaltmp;
3237  if (binvalmax<binvaltmp) binvalmax=binvaltmp;
3238  }
3239  Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
3240  Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
3241  if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
3242  }
3243  if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
3244  }
3245  // Loop on the list of associated functions and user objects
3246 FUNCTIONS:
3247  TObject *f;
3248  TIter next(fFunctions);
3249  while ((f = (TObject*) next())) {
3250  Int_t dist;
3251  if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
3252  else dist = f->DistancetoPrimitive(px,py);
3253  if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
3254  }
3255  return curdist;
3256 }
3257 
3258 ////////////////////////////////////////////////////////////////////////////////
3259 /// Display a panel with all histogram drawing options.
3260 
3262 {
3263 
3264  gCurrentHist = fH;
3265  if (!gPad) {
3266  Error("DrawPanel", "need to draw histogram first");
3267  return;
3268  }
3270  editor->Show();
3271  gROOT->ProcessLine(Form("((TCanvas*)0x%lx)->Selected((TVirtualPad*)0x%lx,(TObject*)0x%lx,1)",
3272  (ULong_t)gPad->GetCanvas(), (ULong_t)gPad, (ULong_t)fH));
3274 
3275 ////////////////////////////////////////////////////////////////////////////////
3276 /// Execute the actions corresponding to `event`.
3277 ///
3278 /// This function is called when a histogram is clicked with the locator at
3279 /// the pixel position px,py.
3280 
3281 void THistPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
3282 {
3283 
3284  if (!gPad) return;
3285 
3286  static Int_t bin, px1, py1, px2, py2, pyold;
3287  static TBox *zoombox;
3288  Double_t zbx1,zbx2,zby1,zby2;
3289 
3290  Int_t bin1, bin2;
3291  Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
3292  Bool_t opaque = gPad->OpaqueMoving();
3294  if (!gPad->IsEditable()) return;
3295 
3296  if (fPie) {
3297  fPie->ExecuteEvent(event, px, py);
3298  return;
3299  }
3300  // come here if we have a lego/surface in the pad
3301  TView *view = gPad->GetView();
3302 
3303  if (!fShowProjection && view && view->TestBit(kCannotRotate) == 0) {
3304  view->ExecuteRotateView(event, px, py);
3305  return;
3306  }
3307 
3308  TAxis *xaxis = fH->GetXaxis();
3309  TAxis *yaxis = fH->GetYaxis();
3310  Int_t dimension = fH->GetDimension();
3311 
3312  Double_t factor = 1;
3313  if (fH->GetNormFactor() != 0) {
3314  factor = fH->GetNormFactor()/fH->GetSumOfWeights();
3315  }
3316 
3317  switch (event) {
3318 
3319  case kButton1Down:
3320 
3321  if (!opaque) gVirtualX->SetLineColor(-1);
3322  fH->TAttLine::Modify();
3323 
3324  if (opaque && dimension ==2) {
3325  zbx1 = gPad->AbsPixeltoX(px);
3326  zbx2 = gPad->AbsPixeltoX(px);
3327  zby1 = gPad->AbsPixeltoY(py);
3328  zby2 = gPad->AbsPixeltoY(py);
3329  px1 = px;
3330  py1 = py;
3331  if (gPad->GetLogx()) {
3332  zbx1 = TMath::Power(10,zbx1);
3333  zbx2 = TMath::Power(10,zbx2);
3334  }
3335  if (gPad->GetLogy()) {
3336  zby1 = TMath::Power(10,zby1);
3337  zby2 = TMath::Power(10,zby2);
3338  }
3339  zoombox = new TBox(zbx1, zby1, zbx2, zby2);
3340  Int_t ci = TColor::GetColor("#7d7dff");
3341  TColor *zoomcolor = gROOT->GetColor(ci);
3342  if (!TCanvas::SupportAlpha() || !zoomcolor) zoombox->SetFillStyle(3002);
3343  else zoomcolor->SetAlpha(0.5);
3344  zoombox->SetFillColor(ci);
3345  zoombox->Draw();
3346  gPad->Modified();
3347  gPad->Update();
3348  }
3349  // No break !!!
3350 
3351  case kMouseMotion:
3352 
3353  if (fShowProjection) {ShowProjection3(px,py); break;}
3354 
3355  gPad->SetCursor(kPointer);
3356  if (dimension ==1) {
3357  if (Hoption.Bar) {
3358  baroffset = fH->GetBarOffset();
3359  barwidth = fH->GetBarWidth();
3360  } else {
3361  baroffset = 0;
3362  barwidth = 1;
3363  }
3364  x = gPad->AbsPixeltoX(px);
3365  bin = fXaxis->FindFixBin(gPad->PadtoX(x));
3366  binwidth = fXaxis->GetBinWidth(bin);
3367  xlow = gPad->XtoPad(fXaxis->GetBinLowEdge(bin) + baroffset*binwidth);
3368  xup = gPad->XtoPad(xlow + barwidth*binwidth);
3369  ylow = gPad->GetUymin();
3370  px1 = gPad->XtoAbsPixel(xlow);
3371  px2 = gPad->XtoAbsPixel(xup);
3372  py1 = gPad->YtoAbsPixel(ylow);
3373  py2 = py;
3374  pyold = py;
3375  if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
3376  }
3377 
3378  break;
3379 
3380  case kButton1Motion:
3381 
3382  if (dimension ==1) {
3383  if (gROOT->GetEditHistograms()) {
3384  if (!opaque) {
3385  gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the old box
3386  py2 += py - pyold;
3387  gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow); // Draw the new box
3388  pyold = py;
3389  } else {
3390  py2 += py - pyold;
3391  pyold = py;
3392  binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3393  fH->SetBinContent(bin,binval);
3394  gPad->Modified(kTRUE);
3395  }
3396  }
3397  }
3398 
3399  if (opaque && dimension ==2) {
3400  if (TMath::Abs(px1-px)>5 && TMath::Abs(py1-py)>5) {
3401  zbx2 = gPad->AbsPixeltoX(px);
3402  zby2 = gPad->AbsPixeltoY(py);
3403  if (gPad->GetLogx()) zbx2 = TMath::Power(10,zbx2);
3404  if (gPad->GetLogy()) zby2 = TMath::Power(10,zby2);
3405  zoombox->SetX2(zbx2);
3406  zoombox->SetY2(zby2);
3407  gPad->Modified();
3408  gPad->Update();
3409  }
3410  }
3411 
3412  break;
3413 
3414  case kWheelUp:
3415 
3416  if (dimension ==2) {
3417  bin1 = xaxis->GetFirst()+1;
3418  bin2 = xaxis->GetLast()-1;
3419  bin1 = TMath::Max(bin1, 1);
3420  bin2 = TMath::Min(bin2, xaxis->GetNbins());
3421  if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3422  bin1 = yaxis->GetFirst()+1;
3423  bin2 = yaxis->GetLast()-1;
3424  bin1 = TMath::Max(bin1, 1);
3425  bin2 = TMath::Min(bin2, yaxis->GetNbins());
3426  if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3427  }
3428  gPad->Modified();
3429  gPad->Update();
3430 
3431  break;
3432 
3433  case kWheelDown:
3434 
3435  if (dimension == 2) {
3436  bin1 = xaxis->GetFirst()-1;
3437  bin2 = xaxis->GetLast()+1;
3438  bin1 = TMath::Max(bin1, 1);
3439  bin2 = TMath::Min(bin2, xaxis->GetNbins());
3440  if (bin2>bin1) xaxis->SetRange(bin1,bin2);
3441  bin1 = yaxis->GetFirst()-1;
3442  bin2 = yaxis->GetLast()+1;
3443  bin1 = TMath::Max(bin1, 1);
3444  bin2 = TMath::Min(bin2, yaxis->GetNbins());
3445  if (bin2>bin1) yaxis->SetRange(bin1,bin2);
3446  }
3447  gPad->Modified();
3448  gPad->Update();
3449 
3450  break;
3451 
3452  case kButton1Up:
3453  if (dimension ==1) {
3454  if (gROOT->GetEditHistograms()) {
3455  binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
3456  fH->SetBinContent(bin,binval);
3457  PaintInit(); // recalculate Hparam structure and recalculate range
3458  }
3459 
3460  // might resize pad pixmap so should be called before any paint routine
3461  RecalculateRange();
3462  }
3463  if (opaque && dimension ==2) {
3464  if (zoombox) {
3465  Double_t x1 = TMath::Min(zoombox->GetX1(), zoombox->GetX2());
3466  Double_t x2 = TMath::Max(zoombox->GetX1(), zoombox->GetX2());
3467  Double_t y1 = TMath::Min(zoombox->GetY1(), zoombox->GetY2());
3468  Double_t y2 = TMath::Max(zoombox->GetY1(), zoombox->GetY2());
3469  x1 = TMath::Max(x1,xaxis->GetXmin());
3470  x2 = TMath::Min(x2,xaxis->GetXmax());
3471  y1 = TMath::Max(y1,yaxis->GetXmin());
3472  y2 = TMath::Min(y2,yaxis->GetXmax());
3473  if (x1<x2 && y1<y2) {
3474  xaxis->SetRangeUser(x1, x2);
3475  yaxis->SetRangeUser(y1, y2);
3476  }
3477  zoombox->Delete();
3478  zoombox = 0;
3479  }
3480  }
3481  gPad->Modified(kTRUE);
3482  if (opaque) gVirtualX->SetLineColor(-1);
3483 
3484  break;
3485 
3486  case kButton1Locate:
3487 
3488  ExecuteEvent(kButton1Down, px, py);
3489 
3490  while (1) {
3491  px = py = 0;
3492  event = gVirtualX->RequestLocator(1, 1, px, py);
3493 
3494  ExecuteEvent(kButton1Motion, px, py);
3495 
3496  if (event != -1) { // button is released
3497  ExecuteEvent(kButton1Up, px, py);
3498  return;
3499  }
3500  }
3501  }
3502 }
3503 
3504 ////////////////////////////////////////////////////////////////////////////////
3505 /// Get a contour (as a list of TGraphs) using the Delaunay triangulation.
3506 
3508 {
3509 
3510 
3511 
3512  // Check if fH contains a TGraphDelaunay2D
3513  TList *hl = fH->GetListOfFunctions();
3514  TGraphDelaunay2D *dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
3515  // try with the old painter
3516  TGraphDelaunay *dtOld = nullptr;
3517  if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
3518 
3519  if (!dt && !dtOld) return nullptr;
3520 
3521  gCurrentHist = fH;
3522 
3523  if (!fGraph2DPainter) {
3524  if (dt) ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dt);
3525  else ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dtOld);
3526  }
3527 
3528  return fGraph2DPainter->GetContourList(contour);
3529 }
3530 
3531 ////////////////////////////////////////////////////////////////////////////////
3532 /// Display the histogram info (bin number, contents, integral up to bin
3533 /// corresponding to cursor position px,py.
3534 
3535 char *THistPainter::GetObjectInfo(Int_t px, Int_t py) const
3536 {
3537 
3538  if (!gPad) return (char*)"";
3539  static char info[200];
3540  Double_t x = gPad->PadtoX(gPad->AbsPixeltoX(px));
3541  Double_t y = gPad->PadtoY(gPad->AbsPixeltoY(py));
3542  Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
3543  TString drawOption = fH->GetDrawOption();
3544  drawOption.ToLower();
3545  Double_t xmin, xmax, uxmin,uxmax;
3546  Double_t ymin, ymax, uymin,uymax;
3547  if (fH->GetDimension() == 2) {
3548  if (gPad->GetView() || drawOption.Index("cont") >= 0) {
3549  uxmin=gPad->GetUxmin();
3550  uxmax=gPad->GetUxmax();
3551  xmin = fXaxis->GetBinLowEdge(fXaxis->GetFirst());
3552  xmax = fXaxis->GetBinUpEdge(fXaxis->GetLast());
3553  x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
3554  uymin=gPad->GetUymin();
3555  uymax=gPad->GetUymax();
3556  ymin = fYaxis->GetBinLowEdge(fYaxis->GetFirst());
3557  ymax = fYaxis->GetBinUpEdge(fYaxis->GetLast());
3558  y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
3559  }
3560  }
3561  Int_t binx,biny,binmin=0,binx1;
3562  if (gPad->IsVertical()) {
3563  binx = fXaxis->FindFixBin(x);
3564  if (drawOption.Index("same") >= 0) {
3565  TH1 *h1;
3566  TIter next(gPad->GetListOfPrimitives());
3567  while ((h1 = (TH1 *)next())) {
3568  if (!h1->InheritsFrom(TH1::Class())) continue;
3569  binmin = h1->GetXaxis()->GetFirst();
3570  break;
3571  }
3572  } else {
3573  binmin = fXaxis->GetFirst();
3574  }
3575  binx1 = fXaxis->FindFixBin(x1);
3576  // special case if more than 1 bin in x per pixel
3577  if (binx1-binx>1 && fH->GetDimension() == 1) {
3578  Double_t binval=fH->GetBinContent(binx);
3579  Int_t binnear=binx;
3580  for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3581  Double_t binvaltmp = fH->GetBinContent(ibin);
3582  if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
3583  binval=binvaltmp;
3584  binnear=ibin;
3585  }
3586  }
3587  binx = binnear;
3588  }
3589  } else {
3590  x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
3591  binx = fXaxis->FindFixBin(y);
3592  if (drawOption.Index("same") >= 0) {
3593  TH1 *h1;
3594  TIter next(gPad->GetListOfPrimitives());
3595  while ((h1 = (TH1 *)next())) {
3596  if (!h1->InheritsFrom(TH1::Class())) continue;
3597  binmin = h1->GetXaxis()->GetFirst();
3598  break;
3599  }
3600  } else {
3601  binmin = fXaxis->GetFirst();
3602  }
3603  binx1 = fXaxis->FindFixBin(x1);
3604  // special case if more than 1 bin in x per pixel
3605  if (binx1-binx>1 && fH->GetDimension() == 1) {
3606  Double_t binval=fH->GetBinContent(binx);
3607  Int_t binnear=binx;
3608  for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
3609  Double_t binvaltmp = fH->GetBinContent(ibin);
3610  if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
3611  binval=binvaltmp;
3612  binnear=ibin;
3613  }
3614  }
3615  binx = binnear;
3616  }
3617  }
3618  if (fH->GetDimension() == 1) {
3619  if (fH->InheritsFrom(TProfile::Class())) {
3620  TProfile *tp = (TProfile*)fH;
3621  snprintf(info,200,"(x=%g, y=%g, binx=%d, binc=%g, bine=%g, binn=%d)",
3622  x, y, binx, fH->GetBinContent(binx), fH->GetBinError(binx),
3623  (Int_t) tp->GetBinEntries(binx));
3624  }
3625  else {
3626  Double_t integ = 0;
3627  for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
3628  snprintf(info,200,"(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",
3629  x,y,binx,fH->GetBinContent(binx),integ);
3630  }
3631  } else if (fH->GetDimension() == 2) {
3632  if (fH->InheritsFrom(TH2Poly::Class())) {
3633  TH2Poly *th2 = (TH2Poly*)fH;
3634  biny = th2->FindBin(x,y);
3635  snprintf(info,200,"%s (x=%g, y=%g, bin=%d, binc=%g)",
3636  th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
3637  }
3638  else if (fH->InheritsFrom(TProfile2D::Class())) {
3639  TProfile2D *tp = (TProfile2D*)fH;
3640  biny = fYaxis->FindFixBin(y);
3641  Int_t bin = fH->GetBin(binx,biny);
3642  snprintf(info,200,"(x=%g, y=%g, binx=%d, biny=%d, binc=%g, bine=%g, binn=%d)",
3643  x, y, binx, biny, fH->GetBinContent(bin),
3644  fH->GetBinError(bin), (Int_t) tp->GetBinEntries(bin));
3645  } else {
3646  biny = fYaxis->FindFixBin(y);
3647  snprintf(info,200,"(x=%g, y=%g, binx=%d, biny=%d, binc=%g bine=%g)",
3648  x,y,binx,biny,fH->GetBinContent(binx,biny),
3649  fH->GetBinError(binx,biny));
3650  }
3651  } else {
3652  // 3d case: retrieving the x,y,z bin is not yet implemented
3653  // print just the x,y info
3654  snprintf(info,200,"(x=%g, y=%g)",x,y);
3655  }
3656  return info;
3657 }
3658 
3659 ////////////////////////////////////////////////////////////////////////////////
3660 /// Return `kTRUE` if the cell `ix`, `iy` is inside one of the graphical cuts.
3661 
3663 {
3664 
3665  for (Int_t i=0;i<fNcuts;i++) {
3666  Double_t x = fXaxis->GetBinCenter(ix);
3667  Double_t y = fYaxis->GetBinCenter(iy);
3668  if (fCutsOpt[i] > 0) {
3669  if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3670  } else {
3671  if (fCuts[i]->IsInside(x,y)) return kFALSE;
3672  }
3673  }
3674  return kTRUE;
3675 }
3676 
3677 ////////////////////////////////////////////////////////////////////////////////
3678 /// Return `kTRUE` if the point `x`, `y` is inside one of the graphical cuts.
3679 
3681 {
3682 
3683  for (Int_t i=0;i<fNcuts;i++) {
3684  if (fCutsOpt[i] > 0) {
3685  if (!fCuts[i]->IsInside(x,y)) return kFALSE;
3686  } else {
3687  if (fCuts[i]->IsInside(x,y)) return kFALSE;
3688  }
3689  }
3690  return kTRUE;
3691 }
3693 ////////////////////////////////////////////////////////////////////////////////
3694 /// Decode string `choptin` and fill Hoption structure.
3695 
3697 {
3698 
3699  char *l;
3700  char chopt[128];
3701  Int_t nch = strlen(choptin);
3702  strlcpy(chopt,choptin,128);
3703  Int_t hdim = fH->GetDimension();
3704 
3705  Hoption.Axis = Hoption.Bar = Hoption.Curve = Hoption.Error = 0;
3706  Hoption.Hist = Hoption.Line = Hoption.Mark = Hoption.Fill = 0;
3707  Hoption.Same = Hoption.Func = Hoption.Scat = 0;
3708  Hoption.Star = Hoption.Arrow = Hoption.Box = Hoption.Text = 0;
3709  Hoption.Char = Hoption.Color = Hoption.Contour = Hoption.Logx = 0;
3710  Hoption.Logy = Hoption.Logz = Hoption.Lego = Hoption.Surf = 0;
3711  Hoption.Off = Hoption.Tri = Hoption.Proj = Hoption.AxisPos = 0;
3712  Hoption.Spec = Hoption.Pie = Hoption.Candle = 0;
3713 
3714  // special 2D options
3715  Hoption.List = 0;
3716  Hoption.Zscale = 0;
3717  Hoption.FrontBox = 1;
3718  Hoption.BackBox = 1;
3719  Hoption.System = kCARTESIAN;
3720 
3721  Hoption.Zero = 0;
3722 
3723  //check for graphical cuts
3724  MakeCuts(chopt);
3725 
3726  for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
3727  if (hdim > 1) Hoption.Scat = 1;
3728  if (!nch) Hoption.Hist = 1;
3729  if (fFunctions->First()) Hoption.Func = 1;
3730  if (fH->GetSumw2N() && hdim == 1) Hoption.Error = 2;
3731 
3732  char *l1 = strstr(chopt,"PFC"); // Automatic Fill Color
3733  char *l2 = strstr(chopt,"PLC"); // Automatic Line Color
3734  char *l3 = strstr(chopt,"PMC"); // Automatic Marker Color
3735  if (l1 || l2 || l3) {
3736  Int_t i = gPad->NextPaletteColor();
3737  if (l1) {strncpy(l1," ",3); fH->SetFillColor(i);}
3738  if (l2) {strncpy(l2," ",3); fH->SetLineColor(i);}
3739  if (l3) {strncpy(l3," ",3); fH->SetMarkerColor(i);}
3740  }
3741 
3742  l = strstr(chopt,"SPEC");
3743  if (l) {
3744  Hoption.Scat = 0;
3745  strncpy(l," ",4);
3746  Int_t bs=0;
3747  l = strstr(chopt,"BF(");
3748  if (l) {
3749  if (sscanf(&l[3],"%d",&bs) > 0) {
3750  Int_t i=0;
3751  while (l[i]!=')') {
3752  l[i] = ' ';
3753  i++;
3754  }
3755  l[i] = ' ';
3756  }
3757  }
3758  Hoption.Spec = TMath::Max(1600,bs);
3759  return 1;
3760  }
3761 
3762  l = strstr(chopt,"GL");
3763  if (l) {
3764  strncpy(l," ",2);
3765  }
3766  l = strstr(chopt,"X+");
3767  if (l) {
3768  Hoption.AxisPos = 10;
3769  strncpy(l," ",2);
3770  }
3771  l = strstr(chopt,"Y+");
3772  if (l) {
3773  Hoption.AxisPos += 1;
3774  strncpy(l," ",2);
3775  }
3776  if ((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
3777  if (Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
3778 
3779  l = strstr(chopt,"SAMES");
3780  if (l) {
3781  if (nch == 5) Hoption.Hist = 1;
3782  Hoption.Same = 2;
3783  strncpy(l," ",5);
3784  }
3785  l = strstr(chopt,"SAME");
3786  if (l) {
3787  if (nch == 4) Hoption.Hist = 1;
3788  Hoption.Same = 1;
3789  strncpy(l," ",4);
3790  }
3791 
3792  l = strstr(chopt,"PIE");
3793  if (l) {
3794  Hoption.Pie = 1;
3795  strncpy(l," ",3);
3796  }
3797 
3798 
3799  l = strstr(chopt,"CANDLE");
3800  if (l) {
3801  TCandle candle;
3802  Hoption.Candle = candle.ParseOption(l);
3803  Hoption.Scat = 0;
3804  }
3805 
3806  l = strstr(chopt,"VIOLIN");
3807  if (l) {
3808  TCandle candle;
3809  Hoption.Candle = candle.ParseOption(l);
3810  Hoption.Scat = 0;
3811  }
3812 
3813  l = strstr(chopt,"LEGO");
3814  if (l) {
3815  Hoption.Scat = 0;
3816  Hoption.Lego = 1; strncpy(l," ",4);
3817  if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
3818  if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
3819  if (l[4] == '3') { Hoption.Lego = 13; l[4] = ' '; }
3820  if (l[4] == '4') { Hoption.Lego = 14; l[4] = ' '; }
3821  if (l[4] == '9') { Hoption.Lego = 19; l[4] = ' '; }
3822  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l," ",2); }
3823  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; strncpy(l," ",2); }
3824  l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; strncpy(l," ",1); }
3825  }
3826 
3827  l = strstr(chopt,"SURF");
3828  if (l) {
3829  Hoption.Scat = 0;
3830  Hoption.Surf = 1; strncpy(l," ",4);
3831  if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
3832  if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
3833  if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
3834  if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
3835  if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
3836  if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
3837  if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
3838  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l," ",2); }
3839  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; strncpy(l," ",2); }
3840  }
3841 
3842  l = strstr(chopt,"TF3");
3843  if (l) {
3844  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l," ",2); }
3845  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; strncpy(l," ",2); }
3846  }
3847 
3848  l = strstr(chopt,"ISO");
3849  if (l) {
3850  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l," ",2); }
3851  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; strncpy(l," ",2); }
3852  }
3853 
3854  l = strstr(chopt,"LIST"); if (l) { Hoption.List = 1; strncpy(l," ",4);}
3855 
3856  l = strstr(chopt,"CONT");
3857  if (l) {
3858  strncpy(l," ",4);
3859  if (hdim>1) {
3860  Hoption.Scat = 0;
3861  Hoption.Contour = 1;
3862  if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
3863  if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
3864  if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
3865  if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
3866  if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
3867  } else {
3868  Hoption.Hist = 1;
3869  }
3870  }
3871  l = strstr(chopt,"HBAR");
3872  if (l) {
3873  Hoption.Hist = 0;
3874  Hoption.Bar = 20; strncpy(l," ",4);
3875  if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
3876  if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
3877  if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
3878  if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
3879  }
3880  l = strstr(chopt,"BAR");
3881  if (l) {
3882  Hoption.Hist = 0;
3883  Hoption.Bar = 10; strncpy(l," ",3);
3884  if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
3885  if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
3886  if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
3887  if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
3888  }
3889 
3890  l = strstr(chopt,"ARR" );
3891  if (l) {
3892  strncpy(l," ", 3);
3893  if (hdim>1) {
3894  Hoption.Arrow = 1;
3895  Hoption.Scat = 0;
3896  } else {
3897  Hoption.Hist = 1;
3898  }
3899  }
3900  l = strstr(chopt,"BOX" );
3901  if (l) {
3902  strncpy(l," ", 3);
3903  if (hdim>1) {
3904  Hoption.Scat = 0;
3905  Hoption.Box = 1;
3906  if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
3907  if (l[3] == '2') { Hoption.Box = 12; l[3] = ' '; }
3908  if (l[3] == '3') { Hoption.Box = 13; l[3] = ' '; }
3909  } else {
3910  Hoption.Hist = 1;
3911  }
3912  }
3913  l = strstr(chopt,"COLZ");
3914  if (l) {
3915  strncpy(l," ",4);
3916  if (hdim>1) {
3917  Hoption.Color = 1;
3918  Hoption.Scat = 0;
3919  Hoption.Zscale = 1;
3920  if (l[4] == '2') { Hoption.Color = 3; l[4] = ' '; }
3921  l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; strncpy(l," ",1); }
3922  l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; strncpy(l," ",1); }
3923  } else {
3924  Hoption.Hist = 1;
3925  }
3926  }
3927  l = strstr(chopt,"COL" );
3928  if (l) {
3929  strncpy(l," ", 3);
3930  if (hdim>1) {
3931  Hoption.Color = 1;
3932  Hoption.Scat = 0;
3933  if (l[3] == '2') { Hoption.Color = 3; l[3] = ' '; }
3934  l = strstr(chopt,"0"); if (l) { Hoption.Zero = 1; strncpy(l," ",1); }
3935  l = strstr(chopt,"1"); if (l) { Hoption.Color = 2; strncpy(l," ",1); }
3936  } else {
3937  Hoption.Hist = 1;
3938  }
3939  }
3940  l = strstr(chopt,"CHAR"); if (l) { Hoption.Char = 1; strncpy(l," ",4); Hoption.Scat = 0; }
3941  l = strstr(chopt,"FUNC"); if (l) { Hoption.Func = 2; strncpy(l," ",4); Hoption.Hist = 0; }
3942  l = strstr(chopt,"HIST"); if (l) { Hoption.Hist = 2; strncpy(l," ",4); Hoption.Func = 0; Hoption.Error = 0;}
3943  l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis = 1; strncpy(l," ",4); }
3944  l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis = 2; strncpy(l," ",4); }
3945  l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat = 1; strncpy(l," ",4); }
3946  l = strstr(chopt,"TEXT");
3947  if (l) {
3948  Int_t angle;
3949  if (sscanf(&l[4],"%d",&angle) > 0) {
3950  if (angle < 0) angle=0;
3951  if (angle > 90) angle=90;
3952  Hoption.Text = 1000+angle;
3953  } else {
3954  Hoption.Text = 1;
3955  }
3956  strncpy(l," ", 4);
3957  l = strstr(chopt,"N");
3958  if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
3959  Hoption.Scat = 0;
3960  }
3961  l = strstr(chopt,"POL"); if (l) { Hoption.System = kPOLAR; strncpy(l," ",3); }
3962  l = strstr(chopt,"CYL"); if (l) { Hoption.System = kCYLINDRICAL; strncpy(l," ",3); }
3963  l = strstr(chopt,"SPH"); if (l) { Hoption.System = kSPHERICAL; strncpy(l," ",3); }
3964  l = strstr(chopt,"PSR"); if (l) { Hoption.System = kRAPIDITY; strncpy(l," ",3); }
3965 
3966  l = strstr(chopt,"TRI");
3967  if (l) {
3968  Hoption.Scat = 0;
3969  Hoption.Color = 0;
3970  Hoption.Tri = 1; strncpy(l," ",3);
3971  l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l," ",2); }
3972  l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0; strncpy(l," ",2); }
3973  l = strstr(chopt,"ERR"); if (l) strncpy(l," ",3);
3974  }
3975 
3976  l = strstr(chopt,"AITOFF");
3977  if (l) {
3978  Hoption.Proj = 1; strncpy(l," ",6); //Aitoff projection
3979  }
3980  l = strstr(chopt,"MERCATOR");
3981  if (l) {
3982  Hoption.Proj = 2; strncpy(l," ",8); //Mercator projection
3983  }
3984  l = strstr(chopt,"SINUSOIDAL");
3985  if (l) {
3986  Hoption.Proj = 3; strncpy(l," ",10); //Sinusoidal projection
3987  }
3988  l = strstr(chopt,"PARABOLIC");
3989  if (l) {
3990  Hoption.Proj = 4; strncpy(l," ",9); //Parabolic projection
3991  }
3992  if (Hoption.Proj > 0) {
3993  Hoption.Scat = 0;
3994  Hoption.Contour = 14;
3995  }
3996 
3997  if (strstr(chopt,"A")) Hoption.Axis = -1;
3998  if (strstr(chopt,"B")) Hoption.Bar = 1;
3999  if (strstr(chopt,"C")) { Hoption.Curve =1; Hoption.Hist = -1;}
4000  if (strstr(chopt,"F")) Hoption.Fill =1;
4001  if (strstr(chopt,"][")) {Hoption.Off =1; Hoption.Hist =1;}
4002  if (strstr(chopt,"F2")) Hoption.Fill =2;
4003  if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
4004  if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
4005  if (strstr(chopt,"Z")) Hoption.Zscale =1;
4006  if (strstr(chopt,"*")) Hoption.Star =1;
4007  if (strstr(chopt,"H")) Hoption.Hist =2;
4008  if (strstr(chopt,"P0")) Hoption.Mark =10;
4009 
4010  if (fH->InheritsFrom(TH2Poly::Class())) {
4011  if (Hoption.Fill+Hoption.Line+Hoption.Mark != 0 ) Hoption.Scat = 0;
4012  }
4013 
4014  if (strstr(chopt,"E")) {
4015  if (hdim == 1) {
4016  Hoption.Error = 1;
4017  if (strstr(chopt,"E0")) Hoption.Error = 10;
4018  if (strstr(chopt,"E1")) Hoption.Error = 11;
4019  if (strstr(chopt,"E2")) Hoption.Error = 12;
4020  if (strstr(chopt,"E3")) Hoption.Error = 13;
4021  if (strstr(chopt,"E4")) Hoption.Error = 14;
4022  if (strstr(chopt,"E5")) Hoption.Error = 15;
4023  if (strstr(chopt,"E6")) Hoption.Error = 16;
4024  if (strstr(chopt,"X0")) {
4025  if (Hoption.Error == 1) Hoption.Error += 20;
4026  Hoption.Error += 10;
4027  }
4028  if (Hoption.Text && fH->InheritsFrom(TProfile::Class())) {
4029  Hoption.Text += 2000;
4030  Hoption.Error = 0;
4031  }
4032  } else {
4033  if (Hoption.Error == 0) {
4034  Hoption.Error = 100;
4035  Hoption.Scat = 0;
4036  }
4037  if (Hoption.Text) {
4038  Hoption.Text += 2000;
4039  Hoption.Error = 0;
4040  }
4041  }
4042  }
4043 
4044  if (Hoption.Surf == 15) {
4045  if (Hoption.System == kPOLAR || Hoption.System == kCARTESIAN) {
4046  Hoption.Surf = 13;
4047  Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
4048  }
4049  }
4050 
4051  // Copy options from current style
4052  Hoption.Logx = gPad->GetLogx();
4053  Hoption.Logy = gPad->GetLogy();
4054  Hoption.Logz = gPad->GetLogz();
4055 
4056  // Check options incompatibilities
4057  if (Hoption.Bar == 1) Hoption.Hist = -1;
4058  return 1;
4059 }
4060 
4061 ////////////////////////////////////////////////////////////////////////////////
4062 /// Decode string `choptin` and fill Graphical cuts structure.
4063 
4064 Int_t THistPainter::MakeCuts(char *choptin)
4065 {
4066 
4067  fNcuts = 0;
4068  char *left = (char*)strchr(choptin,'[');
4069  if (!left) return 0;
4070  char *right = (char*)strchr(choptin,']');
4071  if (!right) return 0;
4072  Int_t nch = right-left;
4073  if (nch < 2) return 0;
4074  char *cuts = left+1;
4075  *right = 0;
4076  char *comma, *minus;
4077  Int_t i;
4078  while (1) {
4079  comma = strchr(cuts,',');
4080  if (comma) *comma = 0;
4081  minus = strchr(cuts,'-');
4082  if (minus) cuts = minus+1;
4083  while (*cuts == ' ') cuts++;
4084  Int_t nc = strlen(cuts);
4085  while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
4086  TIter next(gROOT->GetListOfSpecials());
4087  TCutG *cut=0;
4088  TObject *obj;
4089  while ((obj = next())) {
4090  if (!obj->InheritsFrom(TCutG::Class())) continue;
4091  if (strcmp(obj->GetName(),cuts)) continue;
4092  cut = (TCutG*)obj;
4093  break;
4094  }
4095  if (cut) {
4096  fCuts[fNcuts] = cut;
4097  fCutsOpt[fNcuts] = 1;
4098  if (minus) fCutsOpt[fNcuts] = -1;
4099  fNcuts++;
4100  }
4101  if (!comma) break;
4102  cuts = comma+1;
4103  }
4104  for (i=0;i<=nch;i++) left[i] = ' ';
4105  return fNcuts;
4106 }
4107 
4108 ////////////////////////////////////////////////////////////////////////////////
4109 /// [Control routine to paint any kind of histograms](#HP00)
4110 
4111 void THistPainter::Paint(Option_t *option)
4112 {
4113 
4114  if (fH->GetBuffer()) fH->BufferEmpty(-1);
4115 
4116  //For iOS: put the histogram on the top of stack of pickable objects.
4117  const TPickerStackGuard topPush(fH);
4118 
4119  gPad->SetVertical(kTRUE);
4120 
4121  TH1 *oldhist = gCurrentHist;
4122  gCurrentHist = fH;
4123  TH1 *hsave = fH;
4124  Double_t minsav = fH->GetMinimumStored();
4125 
4126  if (!MakeChopt(option)) return; //check options and fill Hoption structure
4127 
4128  // Paint using TSpectrum2Painter
4129  if (Hoption.Spec) {
4130  if (!TableInit()) return;
4131  if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
4132  gROOT->ProcessLineFast(Form("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%lx,\"%s\",%d)",
4133  (ULong_t)fH, option, Hoption.Spec));
4134  return;
4135  }
4136 
4137  if (Hoption.Pie) {
4138  if (fH->GetDimension() == 1) {
4139  if (!fPie) fPie = new TPie(fH);
4140  fPie->Paint(option);
4141  } else {
4142  Error("Paint", "Option PIE is for 1D histograms only");
4143  }
4144  return;
4145  } else {
4146  if (fPie) delete fPie;
4147  fPie = 0;
4148  }
4149 
4150  fXbuf = new Double_t[kNMAX];
4151  fYbuf = new Double_t[kNMAX];
4152  if (fH->GetDimension() > 2) {
4153  PaintH3(option);
4154  fH->SetMinimum(minsav);
4155  if (Hoption.Func) {
4156  Hoption_t hoptsave = Hoption;
4157  Hparam_t hparsave = Hparam;
4158  PaintFunction(option);
4159  SetHistogram(hsave);
4160  Hoption = hoptsave;
4161  Hparam = hparsave;
4162  }
4163  gCurrentHist = oldhist;
4164  delete [] fXbuf; delete [] fYbuf;
4165  return;
4166  }
4167  TView *view = gPad->GetView();
4168  if (view) {
4169  if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
4170  delete view;
4171  gPad->SetView(0);
4172  }
4173  }
4174  if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
4175  // In case of 1D histogram, Z axis becomes Y axis.
4176  Int_t logysav=0, logzsav=0;
4177  if (fH->GetDimension() == 1) {
4178  logysav = Hoption.Logy;
4179  logzsav = Hoption.Logz;
4180  Hoption.Logz = 0;
4181  if (Hoption.Logy) {
4182  Hoption.Logz = 1;
4183  Hoption.Logy = 0;
4184  }
4185  }
4186  PaintTable(option);
4187  if (Hoption.Func) {
4188  Hoption_t hoptsave = Hoption;
4189  Hparam_t hparsave = Hparam;
4190  PaintFunction(option);
4191  SetHistogram(hsave);
4192  Hoption = hoptsave;
4193  Hparam = hparsave;
4194  }
4195  fH->SetMinimum(minsav);
4196  gCurrentHist = oldhist;
4197  delete [] fXbuf; delete [] fYbuf;
4198  if (fH->GetDimension() == 1) {
4199  Hoption.Logy = logysav;
4200  Hoption.Logz = logzsav;
4201  }
4202  return;
4203  }
4204 
4205  if (Hoption.Bar >= 20) {
4206  PaintBarH(option);
4207  delete [] fXbuf; delete [] fYbuf;
4208  return;
4209  }
4210 
4211  // fill Hparam structure with histo parameters
4212  if (!PaintInit()) {
4213  delete [] fXbuf; delete [] fYbuf;
4214  return;
4215  }
4216 
4217  // Picture surround (if new page) and page number (if requested).
4218  // Histogram surround (if not option "Same").
4219  PaintFrame();
4220 
4221  // Paint histogram axis only
4222  Bool_t gridx = gPad->GetGridx();
4223  Bool_t gridy = gPad->GetGridy();
4224  if (Hoption.Axis > 0) {
4225  if (Hoption.Axis > 1) PaintAxis(kTRUE); //axis with grid
4226  else {
4227  if (gridx) gPad->SetGridx(0);
4228  if (gridy) gPad->SetGridy(0);
4229  PaintAxis(kFALSE);
4230  if (gridx) gPad->SetGridx(1);
4231  if (gridy) gPad->SetGridy(1);
4232  }
4233  if (Hoption.Same ==1) Hoption.Same = 2;
4234  goto paintstat;
4235  }
4236  if (gridx || gridy) PaintAxis(kTRUE); // Draw the grid only
4237 
4238  // test for options BAR or HBAR
4239  if (Hoption.Bar >= 10) {
4240  PaintBar(option);
4241  }
4242 
4243  // do not draw histogram if error bars required
4244  if (!Hoption.Error) {
4245  if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
4246  }
4247 
4248  // test for error bars or option E
4249  if (Hoption.Error) {
4250  PaintErrors(option);
4251  if (Hoption.Hist == 2) PaintHist(option);
4252  }
4253 
4254  if (Hoption.Text) PaintText(option);
4255 
4256  // test for associated function
4257  if (Hoption.Func) {
4258  Hoption_t hoptsave = Hoption;
4259  Hparam_t hparsave = Hparam;
4260  PaintFunction(option);
4261  SetHistogram(hsave);
4262  Hoption = hoptsave;
4263  Hparam = hparsave;
4264  }
4265 
4266  if (gridx) gPad->SetGridx(0);
4267  if (gridy) gPad->SetGridy(0);
4268  PaintAxis(kFALSE);
4269  if (gridx) gPad->SetGridx(1);
4270  if (gridy) gPad->SetGridy(1);
4271 
4272  PaintTitle(); // Draw histogram title
4273 
4274  // Draw box with histogram statistics and/or fit parameters
4275 paintstat:
4276  if (Hoption.Same != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4277  TIter next(fFunctions);
4278  TObject *obj = 0;
4279  while ((obj = next())) {
4280  if (obj->InheritsFrom(TF1::Class())) break;
4281  obj = 0;
4282  }
4283 
4284  //Stat is painted twice (first, it will be in canvas' list of primitives),
4285  //second, it will be here, this is not required on iOS.
4286  //Condition is ALWAYS true on a platform different from iOS.
4287  if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
4288  PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4289  }
4290  fH->SetMinimum(minsav);
4291  gCurrentHist = oldhist;
4292  delete [] fXbuf; fXbuf = 0;
4293  delete [] fYbuf; fYbuf = 0;
4294 
4295 }
4296 
4297 ////////////////////////////////////////////////////////////////////////////////
4298 /// [Control function to draw a table as an arrow plot](#HP12)
4299 
4301 {
4302  fH->TAttLine::Modify();
4303 
4304  Double_t xk, xstep, yk, ystep;
4305  Double_t dx, dy, si, co, anr, x1, x2, y1, y2, xc, yc, dxn, dyn;
4306  Int_t ncx = Hparam.xlast - Hparam.xfirst + 1;
4307  Int_t ncy = Hparam.ylast - Hparam.yfirst + 1;
4308  Double_t xrg = gPad->GetUxmin();
4309  Double_t yrg = gPad->GetUymin();
4310  Double_t xln = gPad->GetUxmax() - xrg;
4311  Double_t yln = gPad->GetUymax() - yrg;
4312  Double_t cx = (xln/Double_t(ncx) -0.03)/2;
4313  Double_t cy = (yln/Double_t(ncy) -0.03)/2;
4314  Double_t dn = 1.E-30;
4315 
4316  for (Int_t id=1;id<=2;id++) {
4317  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4318  yk = fYaxis->GetBinLowEdge(j);
4319  ystep = fYaxis->GetBinWidth(j);
4320  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4321  xk = fXaxis->GetBinLowEdge(i);
4322  xstep = fXaxis->GetBinWidth(i);
4323  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4324  if (i == Hparam.xfirst) {
4325  dx = fH->GetBinContent(i+1, j) - fH->GetBinContent(i, j);
4326  } else if (i == Hparam.xlast) {
4327  dx = fH->GetBinContent(i, j) - fH->GetBinContent(i-1, j);
4328  } else {
4329  dx = 0.5*(fH->GetBinContent(i+1, j) - fH->GetBinContent(i-1, j));
4330  }
4331  if (j == Hparam.yfirst) {
4332  dy = fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j);
4333  } else if (j == Hparam.ylast) {
4334  dy = fH->GetBinContent(i, j) - fH->GetBinContent(i, j-1);
4335  } else {
4336  dy = 0.5*(fH->GetBinContent(i, j+1) - fH->GetBinContent(i, j-1));
4337  }
4338  if (id == 1) {
4339  dn = TMath::Max(dn, TMath::Abs(dx));
4340  dn = TMath::Max(dn, TMath::Abs(dy));
4341  } else if (id == 2) {
4342  xc = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
4343  dxn = cx*dx/dn;
4344  x1 = xc - dxn;
4345  x2 = xc + dxn;
4346  yc = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
4347  dyn = cy*dy/dn;
4348  y1 = yc - dyn;
4349  y2 = yc + dyn;
4350  fXbuf[0] = x1;
4351  fXbuf[1] = x2;
4352  fYbuf[0] = y1;
4353  fYbuf[1] = y2;
4354  if (TMath::Abs(x2-x1) > 0.01 || TMath::Abs(y2-y1) > 0.01) {
4355  anr = 0.005*.5*TMath::Sqrt(2/(dxn*dxn + dyn*dyn));
4356  si = anr*(dxn + dyn);
4357  co = anr*(dxn - dyn);
4358  fXbuf[2] = x2 - si;
4359  fYbuf[2] = y2 + co;
4360  gPad->PaintPolyLine(3, fXbuf, fYbuf);
4361  fXbuf[0] = x2;
4362  fXbuf[1] = x2 - co;
4363  fYbuf[0] = y2;
4364  fYbuf[1] = y2 - si;
4365  gPad->PaintPolyLine(2, fXbuf, fYbuf);
4366  }
4367  else {
4368  gPad->PaintPolyLine(2, fXbuf, fYbuf);
4369  }
4370  }
4371  }
4372  }
4373  }
4374 
4375  if (Hoption.Zscale) PaintPalette();
4376 }
4377 
4378 ////////////////////////////////////////////////////////////////////////////////
4379 /// Draw axis (2D case) of an histogram.
4380 ///
4381 /// If `drawGridOnly` is `TRUE`, only the grid is painted (if needed). This allows
4382 /// to draw the grid and the axis separately. In `THistPainter::Paint` this
4383 /// feature is used to make sure that the grid is drawn in the background and
4384 /// the axis tick marks in the foreground of the pad.
4385 
4386 void THistPainter::PaintAxis(Bool_t drawGridOnly)
4387 {
4388 
4389  //On iOS, grid should not be pickable and can not be highlighted.
4390  //Condition is never true on a platform different from iOS.
4391  if (drawGridOnly && (gPad->PadInHighlightMode() || gPad->PadInSelectionMode()))
4392  return;
4393 
4394  if (Hoption.Axis == -1) return;
4395  if (Hoption.Same && Hoption.Axis <= 0) return;
4396 
4397  // Repainting alphanumeric labels axis on a plot done with
4398  // the option HBAR (horizontal) needs some adjustments.
4399  TAxis *xaxis = 0;
4400  TAxis *yaxis = 0;
4401  if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4402  if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
4403  TIter next(gPad->GetListOfPrimitives());
4404  TObject *obj;
4405  // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
4406  while ((obj = next())) {
4407  if (!obj->InheritsFrom(TH1::Class()) &&
4408  !obj->InheritsFrom(THStack::Class())) continue;
4409  TString opt = obj->GetDrawOption();
4410  opt.ToLower();
4411  // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
4412  if (strstr(opt,"hbar")) {
4413  gPad->SetVertical(kFALSE);
4414  xaxis = fXaxis;
4415  yaxis = fYaxis;
4416  if (!strcmp(xaxis->GetName(),"xaxis")) {
4417  fXaxis = yaxis;
4418  fYaxis = xaxis;
4419  }
4420  }
4421  break;
4422  }
4423  }
4424  }
4425 
4426  static char chopt[10] = "";
4427  Double_t gridl = 0;
4428  Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
4429  Int_t useHparam = 0;
4430  Double_t umin, umax, uminsave, umaxsave;
4431  Short_t xAxisPos = Hoption.AxisPos/10;
4432  Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
4433 
4434  Double_t axmin = gPad->GetUxmin();
4435  Double_t axmax = gPad->GetUxmax();
4436  Double_t aymin = gPad->GetUymin();
4437  Double_t aymax = gPad->GetUymax();
4438  char *cw = 0;
4439  TGaxis axis;
4440 
4441  // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
4442  // Hparam must be use for the axis limits.
4443  if (Hoption.Contour == 14) useHparam = 1;
4444  if (Hoption.Same) {
4445  TObject *obj;
4446  TIter next(gPad->GetListOfPrimitives());
4447  while ((obj=next())) {
4448  if (strstr(obj->GetDrawOption(),"cont4")) {
4449  useHparam = 1;
4450  break;
4451  }
4452  }
4453  }
4454 
4455  // Paint X axis
4456 
4457  //To make X-axis selectable on iOS device.
4458  if (gPad->PadInSelectionMode())
4459  gPad->PushSelectableObject(fXaxis);
4460 
4461  //This condition is ALWAYS true, unless it works on iOS (can be false on iOS).
4462  if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fXaxis)) {
4463  ndivx = fXaxis->GetNdivisions();
4464  if (ndivx > 1000) {
4465  nx2 = ndivx/100;
4466  nx1 = TMath::Max(1, ndivx%100);
4467  ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
4468  }
4469  axis.SetTextAngle(0);
4471 
4472  chopt[0] = 0;
4473  strlcat(chopt, "SDH",10);
4474  if (ndivx < 0) strlcat(chopt, "N",10);
4475  if (gPad->GetGridx()) {
4476  gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
4477  strlcat(chopt, "W",10);
4478  }
4479 
4480  // Define X-Axis limits
4481  if (Hoption.Logx) {
4482  strlcat(chopt, "G",10);
4483  ndiv = TMath::Abs(ndivx);
4484  if (useHparam) {
4485  umin = TMath::Power(10,Hparam.xmin);
4486  umax = TMath::Power(10,Hparam.xmax);
4487  } else {
4488  umin = TMath::Power(10,axmin);
4489  umax = TMath::Power(10,axmax);
4490  }
4491  } else {
4492  ndiv = TMath::Abs(ndivx);
4493  if (useHparam) {
4494  umin = Hparam.xmin;
4495  umax = Hparam.xmax;
4496  } else {
4497  umin = axmin;
4498  umax = axmax;
4499  }
4500  }
4501 
4502  // Display axis as time
4503  if (fXaxis->GetTimeDisplay()) {
4504  strlcat(chopt,"t",10);
4505  if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
4506  axis.SetTimeFormat(fXaxis->ChooseTimeFormat(Hparam.xmax-Hparam.xmin));
4507  }
4508  }
4509 
4510  // The main X axis can be on the bottom or on the top of the pad
4511  Double_t xAxisYPos1, xAxisYPos2;
4512  if (xAxisPos == 1) {
4513  // Main X axis top
4514  xAxisYPos1 = aymax;
4515  xAxisYPos2 = aymin;
4516  } else {
4517  // Main X axis bottom
4518  xAxisYPos1 = aymin;
4519  xAxisYPos2 = aymax;
4520  }
4521 
4522  // Paint the main X axis (always)
4523  uminsave = umin;
4524  umaxsave = umax;
4525  ndivsave = ndiv;
4526  axis.SetOption(chopt);
4527  if (xAxisPos) {
4528  strlcat(chopt, "-",10);
4529  gridl = -gridl;
4530  }
4531  if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4532  axis.SetLabelSize(0.);
4533  axis.SetTitle("");
4534  }
4535  axis.PaintAxis(axmin, xAxisYPos1,
4536  axmax, xAxisYPos1,
4537  umin, umax, ndiv, chopt, gridl, drawGridOnly);
4538 
4539  // Paint additional X axis (if needed)
4540  // On iOS, this additional X axis is neither pickable, nor highlighted.
4541  // Additional checks PadInSelectionMode etc. does not effect non-iOS platform.
4542  if (gPad->GetTickx() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4543  if (xAxisPos) {
4544  cw=strstr(chopt,"-");
4545  *cw='z';
4546  } else {
4547  strlcat(chopt, "-",10);
4548  }
4549  if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
4550  if ((cw=strstr(chopt,"W"))) *cw='z';
4551  axis.SetTitle("");
4552  axis.PaintAxis(axmin, xAxisYPos2,
4553  axmax, xAxisYPos2,
4554  uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4555  }
4556  }//End of "if pad in selection mode etc".
4557 
4558  // Paint Y axis
4559  //On iOS, Y axis must pushed into the stack of selectable objects.
4560  if (gPad->PadInSelectionMode())
4561  gPad->PushSelectableObject(fYaxis);
4562 
4563  //This conditions is ALWAYS true on a platform, different from iOS (on iOS can be true, can be false).
4564  if (gPad->PadInSelectionMode() || !gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && gPad->GetSelected() == fYaxis)) {
4565  ndivy = fYaxis->GetNdivisions();
4567 
4568  chopt[0] = 0;
4569  strlcat(chopt, "SDH",10);
4570  if (ndivy < 0) strlcat(chopt, "N",10);
4571  if (gPad->GetGridy()) {
4572  gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
4573  strlcat(chopt, "W",10);
4574  }
4575 
4576  // Define Y-Axis limits
4577  if (Hoption.Logy) {
4578  strlcat(chopt, "G",10);
4579  ndiv = TMath::Abs(ndivy);
4580  if (useHparam) {
4581  umin = TMath::Power(10,Hparam.ymin);
4582  umax = TMath::Power(10,Hparam.ymax);
4583  } else {
4584  umin = TMath::Power(10,aymin);
4585  umax = TMath::Power(10,aymax);
4586  }
4587  } else {
4588  ndiv = TMath::Abs(ndivy);
4589  if (useHparam) {
4590  umin = Hparam.ymin;
4591  umax = Hparam.ymax;
4592  } else {
4593  umin = aymin;
4594  umax = aymax;
4595  }
4596  }
4597 
4598  // Display axis as time
4599  if (fYaxis->GetTimeDisplay()) {
4600  strlcat(chopt,"t",10);
4601  if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
4602  axis.SetTimeFormat(fYaxis->ChooseTimeFormat(Hparam.ymax-Hparam.ymin));
4603  }
4604  }
4605 
4606  // The main Y axis can be on the left or on the right of the pad
4607  Double_t yAxisXPos1, yAxisXPos2;
4608  if (yAxisPos == 1) {
4609  // Main Y axis left
4610  yAxisXPos1 = axmax;
4611  yAxisXPos2 = axmin;
4612  } else {
4613  // Main Y axis right
4614  yAxisXPos1 = axmin;
4615  yAxisXPos2 = axmax;
4616  }
4617 
4618  // Paint the main Y axis (always)
4619  uminsave = umin;
4620  umaxsave = umax;
4621  ndivsave = ndiv;
4622  axis.SetOption(chopt);
4623  if (yAxisPos) {
4624  strlcat(chopt, "+L",10);
4625  gridl = -gridl;
4626  }
4627  if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
4628  axis.SetLabelSize(0.);
4629  axis.SetTitle("");
4630  }
4631  axis.PaintAxis(yAxisXPos1, aymin,
4632  yAxisXPos1, aymax,
4633  umin, umax, ndiv, chopt, gridl, drawGridOnly);
4634 
4635  // Paint the additional Y axis (if needed)
4636  // Additional checks for pad mode are required on iOS: this "second" axis is
4637  // neither pickable, nor highlighted. Additional checks have no effect on non-iOS platform.
4638  if (gPad->GetTicky() && !gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
4639  if (gPad->GetTicky() < 2) {
4640  strlcat(chopt, "U",10);
4641  axis.SetTickSize(-fYaxis->GetTickLength());
4642  } else {
4643  strlcat(chopt, "+L",10);
4644  }
4645  if ((cw=strstr(chopt,"W"))) *cw='z';
4646  axis.SetTitle("");
4647  axis.PaintAxis(yAxisXPos2, aymin,
4648  yAxisXPos2, aymax,
4649  uminsave, umaxsave, ndivsave, chopt, gridl, drawGridOnly);
4650  }
4651  }//End of "if pad is in selection mode etc."
4652 
4653  // Reset the axis if they have been inverted in case of option HBAR
4654  if (xaxis) {
4655  fXaxis = xaxis;
4656  fYaxis = yaxis;
4657  }
4658 }
4659 
4660 ////////////////////////////////////////////////////////////////////////////////
4661 /// [Draw a bar-chart in a normal pad.](#HP10)
4662 
4664 {
4665 
4666  Int_t bar = Hoption.Bar - 10;
4667  Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
4668  Double_t offset = fH->GetBarOffset();
4669  Double_t width = fH->GetBarWidth();
4670  TBox box;
4671  Int_t hcolor = fH->GetFillColor();
4672  if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
4673  Int_t hstyle = fH->GetFillStyle();
4674  box.SetFillColor(hcolor);
4675  box.SetFillStyle(hstyle);
4676  for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
4677  y = fH->GetBinContent(bin);
4678  xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
4679  xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
4680  ymin = gPad->GetUymin();
4681  ymax = gPad->YtoPad(y);
4682  if (ymax < gPad->GetUymin()) continue;
4683  if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
4684  if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
4685  if (gStyle->GetHistMinimumZero() && ymin < 0)
4686  ymin=TMath::Min(0.,gPad->GetUymax());
4687  w = (xmax-xmin)*width;
4688  xmin += offset*(xmax-xmin);
4689  xmax = xmin + w;
4690  if (bar < 1) {
4691  box.PaintBox(xmin,ymin,xmax,ymax);
4692  } else {
4693  umin = xmin + bar*(xmax-xmin)/10.;
4694  umax = xmax - bar*(xmax-xmin)/10.;
4695  //box.SetFillColor(hcolor+150); //bright
4696  box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
4697  box.PaintBox(xmin,ymin,umin,ymax);
4698  box.SetFillColor(hcolor);
4699  box.PaintBox(umin,ymin,umax,ymax);
4700  box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
4701  box.PaintBox(umax,ymin,xmax,ymax);
4702  }
4703  }
4704 }
4705 
4706 ////////////////////////////////////////////////////////////////////////////////
4707 /// [Draw a bar char in a rotated pad (X vertical, Y horizontal)](#HP10)
4708 
4710 {
4711 
4712  gPad->SetVertical(kFALSE);
4713 
4714  PaintInitH();
4715 
4716  TAxis *xaxis = fXaxis;
4717  TAxis *yaxis = fYaxis;
4718  if (!strcmp(xaxis->GetName(),"xaxis")) {
4719  fXaxis = yaxis;
4720  fYaxis = xaxis;
4721  }
4722 
4723  PaintFrame();
4724  PaintAxis(kFALSE);
4725 
4726  Int_t bar = Hoption.Bar - 20;
4727  Double_t xmin,xmax,ymin,ymax,umin,umax,w;
4728  Double_t offset = fH->GetBarOffset();
4729  Double_t width = fH->GetBarWidth();
4730  TBox box;
4731  Int_t hcolor = fH->GetFillColor();
4732  if (hcolor == gPad->GetFrameFillColor()) ++hcolor;
4733  Int_t hstyle = fH->GetFillStyle();
4734  box.SetFillColor(hcolor);
4735  box.SetFillStyle(hstyle);
4736  for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
4737  ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
4738  ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
4739  xmin = gPad->GetUxmin();
4740  xmax = gPad->XtoPad(fH->GetBinContent(bin));
4741  if (xmax < gPad->GetUxmin()) continue;
4742  if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
4743  if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
4744  if (gStyle->GetHistMinimumZero() && xmin < 0)
4745  xmin=TMath::Min(0.,gPad->GetUxmax());
4746  w = (ymax-ymin)*width;
4747  ymin += offset*(ymax-ymin);
4748  ymax = ymin + w;
4749  if (bar < 1) {
4750  box.PaintBox(xmin,ymin,xmax,ymax);
4751  } else {
4752  umin = ymin + bar*(ymax-ymin)/10.;
4753  umax = ymax - bar*(ymax-ymin)/10.;
4754  box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
4755  box.PaintBox(xmin,ymin,xmax,umin);
4756  box.SetFillColor(hcolor);
4757  box.PaintBox(xmin,umin,xmax,umax);
4758  box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
4759  box.PaintBox(xmin,umax,xmax,ymax);
4760  }
4761  }
4762 
4763  PaintTitle();
4764 
4765  // Draw box with histogram statistics and/or fit parameters
4766  if (Hoption.Same != 1 && !fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
4767  TIter next(fFunctions);
4768  TObject *obj = 0;
4769  while ((obj = next())) {
4770  if (obj->InheritsFrom(TF1::Class())) break;
4771  obj = 0;
4772  }
4773  PaintStat(gStyle->GetOptStat(),(TF1*)obj);
4774  }
4775 
4776  fXaxis = xaxis;
4777  fYaxis = yaxis;
4778 }
4779 
4780 ////////////////////////////////////////////////////////////////////////////////
4781 /// [Control function to draw a 2D histogram as a box plot](#HP13)
4782 
4784 {
4785 
4786  Style_t fillsav = fH->GetFillStyle();
4787  Style_t colsav = fH->GetFillColor();
4788  if (fH->GetFillColor() == 0) fH->SetFillStyle(0);
4789  if (Hoption.Box == 11) fH->SetFillStyle(1001);
4790  fH->TAttLine::Modify();
4791  fH->TAttFill::Modify();
4792 
4793  Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
4794  Double_t ux1 = gPad->PixeltoX(1);
4795  Double_t ux0 = gPad->PixeltoX(0);
4796  Double_t uy1 = gPad->PixeltoY(1);
4797  Double_t uy0 = gPad->PixeltoY(0);
4798  Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
4799  Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
4800 
4801  Double_t zmin = TMath::Max(fH->GetMinimum(),0.);
4803  TMath::Abs(fH->GetMinimum()));
4804  Double_t zminlin = zmin, zmaxlin = zmax;
4805 
4806  // In case of option SAME, zmin and zmax values are taken from the
4807  // first plotted 2D histogram.
4808  if (Hoption.Same) {
4809  TH2 *h2;
4810  TIter next(gPad->GetListOfPrimitives());
4811  while ((h2 = (TH2 *)next())) {
4812  if (!h2->InheritsFrom(TH2::Class())) continue;
4813  zmin = TMath::Max(h2->GetMinimum(), 0.);
4814  zmax = TMath::Max(TMath::Abs(h2->GetMaximum()),
4815  TMath::Abs(h2->GetMinimum()));
4816  zminlin = zmin;
4817  zmaxlin = zmax;
4818  if (Hoption.Logz) {
4819  if (zmin <= 0) {
4820  zmin = TMath::Log10(zmax*0.001);
4821  } else {
4822  zmin = TMath::Log10(zmin);
4823  }
4824  zmax = TMath::Log10(zmax);
4825  }
4826  break;
4827  }
4828  } else {
4829  if (Hoption.Logz) {
4830  if (zmin > 0) {
4831  zmin = TMath::Log10(zmin);
4832  zmax = TMath::Log10(zmax);
4833  } else {
4834  return;
4835  }
4836  }
4837  }
4838 
4839  Double_t zratio, dz = zmax - zmin;
4840  Bool_t kZminNeg = kFALSE;
4841  if (fH->GetMinimum()<0) kZminNeg = kTRUE;
4842  Bool_t kZNeg = kFALSE;
4843 
4844  // Define the dark and light colors the "button style" boxes.
4845  Color_t color = fH->GetFillColor();
4846  Color_t light=0, dark=0;
4847  if (Hoption.Box == 11) {
4848  light = TColor::GetColorBright(color);
4849  dark = TColor::GetColorDark(color);
4850  }
4851 
4852  // Loop over all the bins and draw the boxes
4853  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
4854  yk = fYaxis->GetBinLowEdge(j);
4855  ystep = fYaxis->GetBinWidth(j);
4856  ycent = 0.5*ystep;
4857  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
4858  Int_t bin = j*(fXaxis->GetNbins()+2) + i;
4859  xk = fXaxis->GetBinLowEdge(i);
4860  xstep = fXaxis->GetBinWidth(i);
4861  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
4862  xcent = 0.5*xstep;
4863  z = Hparam.factor*fH->GetBinContent(bin);
4864  kZNeg = kFALSE;
4865 
4866  if (TMath::Abs(z) < zminlin) continue; // Can be the case with ...
4867  if (TMath::Abs(z) > zmaxlin) z = zmaxlin; // ... option Same
4868  if (kZminNeg && z==0) continue; // Do not draw empty bins if case of histo with netgative bins.
4869 
4870  if (z < 0) {
4871  if (Hoption.Logz) continue;
4872  z = -z;
4873  kZNeg = kTRUE;
4874  }
4875  if (Hoption.Logz) {
4876  if (z != 0) z = TMath::Log10(z);
4877  else z = zmin;
4878  }
4879 
4880  if (dz == 0) continue;
4881  zratio = TMath::Sqrt((z-zmin)/dz);
4882  if (zratio == 0) continue;
4883 
4884  xup = xcent*zratio + xk + xcent;
4885  xlow = 2*(xk + xcent) - xup;
4886  if (xup-xlow < dxmin) xup = xlow+dxmin;
4887  if (Hoption.Logx) {
4888  if (xup > 0) xup = TMath::Log10(xup);
4889  else continue;
4890  if (xlow > 0) xlow = TMath::Log10(xlow);
4891  else continue;
4892  }
4893 
4894  yup = ycent*zratio + yk + ycent;
4895  ylow = 2*(yk + ycent) - yup;
4896  if (yup-ylow < dymin) yup = ylow+dymin;
4897  if (Hoption.Logy) {
4898  if (yup > 0) yup = TMath::Log10(yup);
4899  else continue;
4900  if (ylow > 0) ylow = TMath::Log10(ylow);
4901  else continue;
4902  }
4903 
4904  xlow = TMath::Max(xlow, gPad->GetUxmin());
4905  ylow = TMath::Max(ylow, gPad->GetUymin());
4906  xup = TMath::Min(xup , gPad->GetUxmax());
4907  yup = TMath::Min(yup , gPad->GetUymax());
4908 
4909  if (xlow >= xup) continue;
4910  if (ylow >= yup) continue;
4911 
4912  if (Hoption.Box == 1) {
4913  fH->SetFillColor(color);
4914  fH->TAttFill::Modify();
4915  gPad->PaintBox(xlow, ylow, xup, yup);
4916  if (kZNeg) {
4917  gPad->PaintLine(xlow, ylow, xup, yup);
4918  gPad->PaintLine(xlow, yup, xup, ylow);
4919  }
4920  } else if (Hoption.Box == 11) {
4921  // Draw the center of the box
4922  fH->SetFillColor(color);
4923  fH->TAttFill::Modify();
4924  gPad->PaintBox(xlow, ylow, xup, yup);
4925 
4926  // Draw top&left part of the box
4927  Double_t x[7], y[7];
4928  Double_t bwidth = 0.1;
4929  x[0] = xlow; y[0] = ylow;
4930  x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
4931  x[2] = x[1]; y[2] = yup - bwidth*(yup-ylow);
4932  x[3] = xup - bwidth*(xup-xlow); y[3] = y[2];
4933  x[4] = xup; y[4] = yup;
4934  x[5] = xlow; y[5] = yup;
4935  x[6] = xlow; y[6] = ylow;
4936  if (kZNeg) fH->SetFillColor(dark);
4937  else fH->SetFillColor(light);
4938  fH->TAttFill::Modify();
4939  gPad->PaintFillArea(7, x, y);
4940 
4941  // Draw bottom&right part of the box
4942  x[0] = xlow; y[0] = ylow;
4943  x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
4944  x[2] = xup - bwidth*(xup-xlow); y[2] = y[1];
4945  x[3] = x[2]; y[3] = yup - bwidth*(yup-ylow);
4946  x[4] = xup; y[4] = yup;
4947  x[5] = xup; y[5] = ylow;
4948  x[6] = xlow; y[6] = ylow;
4949  if (kZNeg) fH->SetFillColor(light);
4950  else fH->SetFillColor(dark);
4951  fH->TAttFill::Modify();
4952  gPad->PaintFillArea(7, x, y);
4953  }
4954  }
4955  }
4956 
4957  if (Hoption.Zscale) PaintPalette();
4958  fH->SetFillStyle(fillsav);
4959  fH->SetFillColor(colsav);
4960  fH->TAttFill::Modify();
4961 }
4962 
4963 
4964 
4965 ////////////////////////////////////////////////////////////////////////////////
4966 /// [Control function to draw a 2D histogram as a candle (box) plot or violin plot](#HP14)
4967 
4969 {
4970  TH1D *hproj;
4971  TH2D *h2 = (TH2D*)fH;
4972 
4973  TCandle myCandle;
4974  myCandle.SetOption((TCandle::CandleOption)Hoption.Candle);
4975  myCandle.SetMarkerColor(fH->GetLineColor());
4976  myCandle.SetLineColor(fH->GetLineColor());
4977  myCandle.SetLineWidth(fH->GetLineWidth());
4978  myCandle.SetFillColor(fH->GetFillColor());
4979  myCandle.SetFillStyle(fH->GetFillStyle());
4981  myCandle.SetMarkerStyle(fH->GetMarkerStyle());
4982  myCandle.SetLog(Hoption.Logx,Hoption.Logy, Hoption.Logz);
4983 
4984  Bool_t swapXY = myCandle.IsHorizontal();
4985  const Double_t standardCandleWidth = 0.66;
4986  const Double_t standardHistoWidth = 0.8;
4987 
4988  double allMaxContent = h2->GetBinContent(h2->GetMaximumBin());
4989  double allMaxIntegral = 0;
4990 
4991  if (!swapXY) { // Vertical candle
4992  //Determining the slice with the maximum content
4993  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
4994  hproj = h2->ProjectionY("_px", i, i);
4995  if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
4996  }
4997  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast; i++) {
4998  Double_t binPosX = fXaxis->GetBinLowEdge(i);
4999  Double_t binWidth = fXaxis->GetBinWidth(i);
5000  hproj = h2->ProjectionY("_px", i, i);
5001  if (hproj->GetEntries() !=0) {
5002  Double_t candleWidth = fH->GetBarWidth();
5003  Double_t offset = fH->GetBarOffset()*binWidth;
5004  double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5005  double myIntegral = hproj->Integral();
5006  Double_t histoWidth = candleWidth;
5007  if (candleWidth > 0.999 && candleWidth < 1.001) {
5008  candleWidth = standardCandleWidth;
5009  histoWidth = standardHistoWidth;
5010  }
5011  if (Hoption.Logz && myMaxContent > 0) {
5012  histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5013  if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0) histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5014  } else if (myCandle.IsViolinScaled()) histoWidth *= myMaxContent/allMaxContent;
5015  if (myCandle.IsCandleScaled()) candleWidth *= myIntegral/allMaxIntegral;
5016 
5017  myCandle.SetAxisPosition(binPosX+binWidth/2. + offset);
5018  myCandle.SetCandleWidth(candleWidth*binWidth);
5019  myCandle.SetHistoWidth(histoWidth*binWidth);
5020  myCandle.SetHistogram(hproj);
5021  myCandle.Paint();
5022  }
5023  }
5024  } else { // Horizontal candle
5025  //Determining the slice with the maximum content
5026  for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5027  hproj = h2->ProjectionX("_py", i, i);
5028  if (hproj->Integral() > allMaxIntegral) allMaxIntegral = hproj->Integral();
5029  }
5030  for (Int_t i=Hparam.yfirst; i<=Hparam.ylast; i++) {
5031  Double_t binPosY = fYaxis->GetBinLowEdge(i);
5032  Double_t binWidth = fYaxis->GetBinWidth(i);
5033  hproj = h2->ProjectionX("_py", i, i);
5034  if (hproj->GetEntries() !=0) {
5035  Double_t candleWidth = fH->GetBarWidth();
5036  Double_t offset = fH->GetBarOffset()*binWidth;
5037  double myMaxContent = hproj->GetBinContent(hproj->GetMaximumBin());
5038  double myIntegral = hproj->Integral();
5039  Double_t histoWidth = candleWidth;
5040  if (candleWidth > 0.999 && candleWidth < 1.001) {
5041  candleWidth = standardCandleWidth;
5042  histoWidth = standardHistoWidth;
5043  }
5044  if (Hoption.Logz && myMaxContent > 0) {
5045  histoWidth *= myMaxContent/TMath::Log10(myMaxContent);
5046  if (myCandle.IsViolinScaled() && myMaxContent > 0 && allMaxContent > 0) histoWidth *= TMath::Log10(myMaxContent)/TMath::Log10(allMaxContent);
5047  } else if (myCandle.IsViolinScaled()) histoWidth *= myMaxContent/allMaxContent;
5048  if (myCandle.IsCandleScaled()) candleWidth *= myIntegral/allMaxIntegral;
5049 
5050  myCandle.SetAxisPosition(binPosY+binWidth/2. + offset);
5051  myCandle.SetCandleWidth(candleWidth*binWidth);
5052  myCandle.SetHistoWidth(histoWidth*binWidth);
5053  myCandle.SetHistogram(hproj);
5054  myCandle.Paint();
5055  }
5056  }
5057  }
5058 }
5059 
5060 
5061 
5062 ////////////////////////////////////////////////////////////////////////////////
5063 /// Returns the rendering regions for an axis to use in the COL2 option
5064 ///
5065 /// The algorithm analyses the size of the axis compared to the size of
5066 /// the rendering region. It figures out the boundaries to use for each color
5067 /// of the rendering region. Only one axis is computed here.
5068 ///
5069 /// This allows for a single computation of the boundaries before iterating
5070 /// through all of the bins.
5071 ///
5072 /// \param pAxis the axis to consider
5073 /// \param nPixels the number of pixels to render axis into
5074 /// \param isLog whether the axis is log scale
5075 
5076 std::vector<THistRenderingRegion>
5078 {
5079  std::vector<THistRenderingRegion> regions;
5080 
5081  enum STRATEGY { Bins, Pixels } strategy;
5082 
5083  Int_t nBins = (pAxis->GetLast() - pAxis->GetFirst() + 1);
5084 
5085  if (nBins >= nPixels) {
5086  // more bins than pixels... we should loop over pixels and sample
5087  strategy = Pixels;
5088  } else {
5089  // fewer bins than pixels... we should loop over bins
5090  strategy = Bins;
5091  }
5092 
5093  if (isLog) {
5094 
5095  Double_t xMin = pAxis->GetBinLowEdge(pAxis->GetFirst());
5096  Int_t binOffset=0;
5097  while (xMin <= 0 && ((pAxis->GetFirst()+binOffset) != pAxis->GetLast()) ) {
5098  binOffset++;
5099  xMin = pAxis->GetBinLowEdge(pAxis->GetFirst()+binOffset);
5100  }
5101  if (xMin <= 0) {
5102  // this should cause an error if we have
5103  return regions;
5104  }
5105  Double_t xMax = pAxis->GetBinUpEdge(pAxis->GetLast());
5106 
5107  if (strategy == Bins) {
5108  // logarithmic plot. we find the pixel for the bin
5109  // pixel = eta * log10(V) - alpha
5110  // where eta = nPixels/(log10(Vmax)-log10(Vmin))
5111  // and alpha = nPixels*log10(Vmin)/(log10(Vmax)-log10(Vmin))
5112  // and V is axis value
5113  Double_t eta = (nPixels-1.0)/(TMath::Log10(xMax) - TMath::Log10(xMin));
5114  Double_t offset = -1.0 * eta * TMath::Log10(xMin);
5115 
5116  for (Int_t bin=pAxis->GetFirst()+binOffset; bin<=pAxis->GetLast(); bin++) {
5117 
5118  // linear plot. we simply need to find the appropriate bin
5119  // for the
5120  Double_t xLowValue = pAxis->GetBinLowEdge(bin);
5121  Double_t xUpValue = pAxis->GetBinUpEdge(bin);
5122  Int_t xPx0 = eta*TMath::Log10(xLowValue)+ offset;
5123  Int_t xPx1 = eta*TMath::Log10(xUpValue) + offset;
5124  THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5125  std::make_pair(bin, bin+1)};
5126  regions.push_back(region);
5127  }
5128 
5129  } else {
5130 
5131  // loop over pixels
5132 
5133  Double_t beta = (TMath::Log10(xMax) - TMath::Log10(xMin))/(nPixels-1.0);
5134 
5135  for (Int_t pixelIndex=0; pixelIndex<(nPixels-1); pixelIndex++) {
5136  // linear plot
5137  Int_t binLow = pAxis->FindBin(xMin*TMath::Power(10.0, beta*pixelIndex));
5138  Int_t binHigh = pAxis->FindBin(xMin*TMath::Power(10.0, beta*(pixelIndex+1)));
5139  THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5140  std::make_pair(binLow, binHigh)};
5141  regions.push_back(region);
5142  }
5143  }
5144  } else {
5145  // standard linear plot
5146 
5147  if (strategy == Bins) {
5148  // loop over bins
5149  for (Int_t bin=pAxis->GetFirst(); bin<=pAxis->GetLast(); bin++) {
5150 
5151  // linear plot. we simply need to find the appropriate bin
5152  // for the
5153  Int_t xPx0 = ((bin - pAxis->GetFirst()) * nPixels)/nBins;
5154  Int_t xPx1 = xPx0 + nPixels/nBins;
5155 
5156  // make sure we don't compute beyond our bounds
5157  if (xPx1>= nPixels) xPx1 = nPixels-1;
5158 
5159  THistRenderingRegion region = {std::make_pair(xPx0, xPx1),
5160  std::make_pair(bin, bin+1)};
5161  regions.push_back(region);
5162  }
5163  } else {
5164  // loop over pixels
5165  for (Int_t pixelIndex=0; pixelIndex<nPixels-1; pixelIndex++) {
5166  // linear plot
5167  Int_t binLow = (nBins*pixelIndex)/nPixels + pAxis->GetFirst();
5168  Int_t binHigh = binLow + nBins/nPixels;
5169  THistRenderingRegion region = { std::make_pair(pixelIndex, pixelIndex+1),
5170  std::make_pair(binLow, binHigh)};
5171  regions.push_back(region);
5172  }
5173  }
5174  }
5175 
5176  return regions;
5177 }
5178 
5179 ////////////////////////////////////////////////////////////////////////////////
5180 /// [Rendering scheme for the COL2 and COLZ2 options] (#HP14)
5181 
5183 {
5184 
5185  if (Hoption.System != kCARTESIAN) {
5186  Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5187  "Only cartesian coordinates supported by 'COL2' option. Using 'COL' option instead.");
5188  PaintColorLevels(nullptr);
5189  return;
5190  }
5191 
5192  Double_t z;
5193 
5194  // Use existing max or min values. If either is already set
5195  // the appropriate value to use.
5196  Double_t zmin = fH->GetMinimumStored();
5197  Double_t zmax = fH->GetMaximumStored();
5198  Double_t originalZMin = zmin;
5199  Double_t originalZMax = zmax;
5200  if ((zmin == -1111) && (zmax == -1111)) {
5201  fH->GetMinimumAndMaximum(zmin, zmax);
5202  fH->SetMinimum(zmin);
5203  fH->SetMaximum(zmax);
5204  } else if (zmin == -1111) {
5205  zmin = fH->GetMinimum();
5206  fH->SetMinimum(zmin);
5207  } else if (zmax == -1111) {
5208  zmax = fH->GetMaximum();
5209  fH->SetMaximum(zmax);
5210  }
5211 
5212  Double_t dz = zmax - zmin;
5213  if (dz <= 0) { // Histogram filled with a constant value
5214  zmax += 0.1*TMath::Abs(zmax);
5215  zmin -= 0.1*TMath::Abs(zmin);
5216  dz = zmax - zmin;
5217  }
5218 
5219  if (Hoption.Logz) {
5220  if (zmin > 0) {
5221  zmin = TMath::Log10(zmin);
5222  zmax = TMath::Log10(zmax);
5223  dz = zmax - zmin;
5224  } else {
5225  Error("THistPainter::PaintColorLevelsFast(Option_t*)",
5226  "Cannot plot logz because bin content is less than 0.");
5227  return;
5228  }
5229  }
5230 
5231  // Initialize the levels on the Z axis
5232  Int_t ndiv = fH->GetContour();
5233  if (ndiv == 0 ) {
5234  ndiv = gStyle->GetNumberContours();
5235  fH->SetContour(ndiv);
5236  }
5237  std::vector<Double_t> colorBounds(ndiv);
5238  std::vector<Double_t> contours(ndiv, 0);
5239  if (fH->TestBit(TH1::kUserContour) == 0) {
5240  fH->SetContour(ndiv);
5241  } else {
5242  fH->GetContour(contours.data());
5243  }
5244 
5245  Double_t step = 1.0/ndiv;
5246  for (Int_t i=0; i<ndiv; ++i) {
5247  colorBounds[i] = step*i;
5248  }
5249 
5250  auto pFrame = gPad->GetFrame();
5251  Int_t px0 = gPad->XtoPixel(pFrame->GetX1());
5252  Int_t px1 = gPad->XtoPixel(pFrame->GetX2());
5253  Int_t py0 = gPad->YtoPixel(pFrame->GetY1());
5254  Int_t py1 = gPad->YtoPixel(pFrame->GetY2());
5255  Int_t nXPixels = px1-px0;
5256  Int_t nYPixels = py0-py1; // y=0 is at the top of the screen
5257 
5258  std::vector<Double_t> buffer(nXPixels*nYPixels, 0);
5259 
5260  auto xRegions = ComputeRenderingRegions(fXaxis, nXPixels, Hoption.Logx);
5261  auto yRegions = ComputeRenderingRegions(fYaxis, nYPixels, Hoption.Logy);
5262  if (xRegions.size() == 0 || yRegions.size() == 0) {
5263  Error("THistPainter::PaintColorLevelFast(Option_t*)",
5264  "Encountered error while computing rendering regions.");
5265  return;
5266  }
5267 
5268  Bool_t minExists = kFALSE;
5269  Bool_t maxExists = kFALSE;
5270  Double_t minValue = 1.;
5271  Double_t maxValue = 0.;
5272  for (auto& yRegion : yRegions) {
5273  for (auto& xRegion : xRegions ) {
5274 
5275  const auto& xBinRange = xRegion.fBinRange;
5276  const auto& yBinRange = yRegion.fBinRange;
5277 
5278  // sample the range
5279  z = fH->GetBinContent(xBinRange.second-1, yBinRange.second-1);
5280 
5281  if (Hoption.Logz) {
5282  if (z > 0) z = TMath::Log10(z);
5283  else z = zmin;
5284  }
5285 
5286  // obey the user's max and min values if they were set
5287  if (z > zmax) z = zmax;
5288  if (z < zmin) z = zmin;
5289 
5290  if (fH->TestBit(TH1::kUserContour) == 1) {
5291  // contours are absolute values
5292  auto index = TMath::BinarySearch(contours.size(), contours.data(), z);
5293  z = colorBounds[index];
5294  } else {
5295  Int_t index = 0;
5296  if (dz != 0) {
5297  index = 0.001 + ((z - zmin)/dz)*ndiv;
5298  }
5299 
5300  if (index == static_cast<Int_t>(colorBounds.size())) {
5301  index--;
5302  }
5303 
5304  // Do a little bookkeeping to use later for getting libAfterImage to produce
5305  // the correct colors
5306  if (index == 0) {
5307  minExists = kTRUE;
5308  } else if (index == static_cast<Int_t>(colorBounds.size()-1)) {
5309  maxExists = kTRUE;
5310  }
5311 
5312  z = colorBounds[index];
5313 
5314  if (z < minValue) {
5315  minValue = z;
5316  }
5317  if (z > maxValue) {
5318  maxValue = z;
5319  }
5320  }
5321 
5322  // fill in the actual pixels
5323  const auto& xPixelRange = xRegion.fPixelRange;
5324  const auto& yPixelRange = yRegion.fPixelRange;
5325  for (Int_t xPx = xPixelRange.first; xPx <= xPixelRange.second; ++xPx) {
5326  for (Int_t yPx = yPixelRange.first; yPx <= yPixelRange.second; ++yPx) {
5327  Int_t pixel = yPx*nXPixels + xPx;
5328  buffer[pixel] = z;
5329  }
5330  }
5331  } // end px loop
5332  } // end py loop
5333 
5334  // This is a bit of a hack to ensure that we span the entire color range and
5335  // don't screw up the colors for a sparse histogram. No one will notice that I set a
5336  // single pixel on the edge of the image to a different color. This is even more
5337  // true because the chosen pixels will be covered by the axis.
5338  if (minValue != maxValue) {
5339  if ( !minExists) {
5340  buffer.front() = 0;
5341  }
5342 
5343  if ( !maxExists) {
5344  buffer[buffer.size()-nXPixels] = 0.95;
5345  }
5346  }
5347 
5348  // Generate the TImage
5350  TImage* pImage = TImage::Create();
5352  pImage->SetImage(buffer.data(), nXPixels, nYPixels, pPalette);
5353  delete pPalette;
5354 
5355  Window_t wid = static_cast<Window_t>(gVirtualX->GetWindowID(gPad->GetPixmapID()));
5356  pImage->PaintImage(wid, px0, py1, 0, 0, nXPixels, nYPixels);
5357  delete pImage;
5358 
5359  if (Hoption.Zscale) PaintPalette();
5360 
5361  // Reset the maximum and minimum values to their original values
5362  // when this function was called. If we don't do this, an initial
5363  // value of -1111 will be replaced with the true max or min values.
5364  fH->SetMinimum(originalZMin);
5365  fH->SetMaximum(originalZMax);
5366 }
5367 
5368 ////////////////////////////////////////////////////////////////////////////////
5369 /// [Control function to draw a 2D histogram as a color plot.](#HP14)
5370 
5372 {
5373  Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
5374 
5375  Double_t zmin = fH->GetMinimum();
5376  Double_t zmax = fH->GetMaximum();
5377 
5378  Double_t dz = zmax - zmin;
5379  if (dz <= 0) { // Histogram filled with a constant value
5380  zmax += 0.1*TMath::Abs(zmax);
5381  zmin -= 0.1*TMath::Abs(zmin);
5382  dz = zmax - zmin;
5383  }
5384 
5385  // In case of option SAME, zmin and zmax values are taken from the
5386  // first plotted 2D histogram.
5387  if (Hoption.Same) {
5388  TH2 *h2;
5389  TIter next(gPad->GetListOfPrimitives());
5390  while ((h2 = (TH2 *)next())) {
5391  if (!h2->InheritsFrom(TH2::Class())) continue;
5392  zmin = h2->GetMinimum();
5393  zmax = h2->GetMaximum();
5394  if (Hoption.Logz) {
5395  if (zmin <= 0) {
5396  zmin = TMath::Log10(zmax*0.001);
5397  } else {
5398  zmin = TMath::Log10(zmin);
5399  }
5400  zmax = TMath::Log10(zmax);
5401  }
5402  dz = zmax - zmin;
5403  break;
5404  }
5405  } else {
5406  if (Hoption.Logz) {
5407  if (zmin > 0) {
5408  zmin = TMath::Log10(zmin);
5409  zmax = TMath::Log10(zmax);
5410  dz = zmax - zmin;
5411  } else {
5412  return;
5413  }
5414  }
5415  }
5416 
5417  Style_t fillsav = fH->GetFillStyle();
5418  Style_t colsav = fH->GetFillColor();
5419  fH->SetFillStyle(1001);
5420  fH->TAttFill::Modify();
5421 
5422  // Initialize the levels on the Z axis
5423  Int_t ncolors = gStyle->GetNumberOfColors();
5424  Int_t ndiv = fH->GetContour();
5425  if (ndiv == 0 ) {
5426  ndiv = gStyle->GetNumberContours();
5427  fH->SetContour(ndiv);
5428  }
5429  Int_t ndivz = TMath::Abs(ndiv);
5430  if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
5431  Double_t scale = ndivz/dz;
5432 
5433  Int_t color;
5434  TProfile2D* prof2d = dynamic_cast<TProfile2D*>(fH);
5435  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
5436  yk = fYaxis->GetBinLowEdge(j);
5437  ystep = fYaxis->GetBinWidth(j);
5438  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
5439  Int_t bin = j*(fXaxis->GetNbins()+2) + i;
5440  xk = fXaxis->GetBinLowEdge(i);
5441  xstep = fXaxis->GetBinWidth(i);
5442  if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
5443  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
5444  z = fH->GetBinContent(bin);
5445  // if fH is a profile histogram do not draw empty bins
5446  if (prof2d) {
5447  const Double_t binEntries = prof2d->GetBinEntries(bin);
5448  if (binEntries == 0)
5449  continue;
5450  } else {
5451  // don't draw the empty bins for non-profile histograms
5452  // with positive content
5453  if (z == 0) {
5454  if (zmin >= 0 || Hoption.Logz) continue;
5455  if (Hoption.Color == 2) continue;
5456  }
5457  }
5458 
5459  if (Hoption.Logz) {
5460  if (z > 0) z = TMath::Log10(z);
5461  else z = zmin;
5462  }
5463  if (z < zmin && !Hoption.Zero) continue;
5464  xup = xk + xstep;
5465  xlow = xk;
5466  if (Hoption.Logx) {
5467  if (xup > 0) xup = TMath::Log10(xup);
5468  else continue;
5469  if (xlow > 0) xlow = TMath::Log10(xlow);
5470  else continue;
5471  }
5472  yup = yk + ystep;
5473  ylow = yk;
5474  if (Hoption.System != kPOLAR) {
5475  if (Hoption.Logy) {
5476  if (yup > 0) yup = TMath::Log10(yup);
5477  else continue;
5478  if (ylow > 0) ylow = TMath::Log10(ylow);
5479  else continue;
5480  }
5481  if (xup < gPad->GetUxmin()) continue;
5482  if (yup < gPad->GetUymin()) continue;
5483  if (xlow > gPad->GetUxmax()) continue;
5484  if (ylow > gPad->GetUymax()) continue;
5485  if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
5486  if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
5487  if (xup > gPad->GetUxmax()) xup = gPad->GetUxmax();
5488  if (yup > gPad->GetUymax()) yup = gPad->GetUymax();
5489  }
5490 
5491  if (fH->TestBit(TH1::kUserContour)) {
5492  zc = fH->GetContourLevelPad(0);
5493  if (z < zc) continue;
5494  color = -1;
5495  for (Int_t k=0; k<ndiv; k++) {
5496  zc = fH->GetContourLevelPad(k);
5497  if (z < zc) {
5498  continue;
5499  } else {
5500  color++;
5501  }
5502  }
5503  } else {
5504  color = Int_t(0.01+(z-zmin)*scale);
5505  }
5506 
5507  Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
5508  if (theColor > ncolors-1) theColor = ncolors-1;
5509  fH->SetFillColor(gStyle->GetColorPalette(theColor));
5510  fH->TAttFill::Modify();
5511  if (Hoption.System != kPOLAR) {
5512  gPad->PaintBox(xlow, ylow, xup, yup);
5513  } else {
5514  TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
5515  crown.SetFillColor(gStyle->GetColorPalette(theColor));
5516  crown.Paint();
5517  }
5518  }
5519  }
5520 
5521  if (Hoption.Zscale) PaintPalette();
5522 
5523  fH->SetFillStyle(fillsav);
5524  fH->SetFillColor(colsav);
5525  fH->TAttFill::Modify();
5526 
5527 }
5528 
5529 ////////////////////////////////////////////////////////////////////////////////
5530 /// [Control function to draw a 2D histogram as a contour plot.](#HP16)
5531 
5533 {
5534 
5535  Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
5536  Int_t itars, mode, ir[4];
5537  Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
5538 
5539  if (Hoption.Contour == 14) {
5540  Hoption.Surf = 12;
5541  Hoption.Axis = 1;
5542  thesave = gPad->GetTheta();
5543  phisave = gPad->GetPhi();
5544  gPad->SetPhi(0.);
5545  gPad->SetTheta(90.);
5546  PaintSurface(option);
5547  gPad->SetPhi(phisave);
5548  gPad->SetTheta(thesave);
5549  TView *view = gPad->GetView();
5550  if (view) view->SetBit(kCannotRotate); //tested in ExecuteEvent
5551  PaintAxis();
5552  return;
5553  }
5554 
5555  if (Hoption.Same) {
5556  // If the contour is painted on a 3d plot, the contour lines are
5557  // paint in 3d too.
5558  TObject *obj;
5559  TIter next(gPad->GetListOfPrimitives());
5560  while ((obj=next())) {
5561  if (strstr(obj->GetDrawOption(),"surf") ||
5562  strstr(obj->GetDrawOption(),"lego") ||
5563  strstr(obj->GetDrawOption(),"tri")) {
5564  Hoption.Surf = 16;
5565  PaintSurface(option);
5566  return;
5567  }
5568  }
5569  }
5570 
5571  if (Hoption.Contour == 15) {
5572  TGraphDelaunay2D *dt = nullptr;
5573  TGraphDelaunay *dtOld = nullptr;
5574  TList *hl = fH->GetListOfFunctions();
5575  dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
5576  if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
5577  if (!dt && !dtOld) return;
5578  if (!fGraph2DPainter) {
5579  if (dt) fGraph2DPainter = new TGraph2DPainter(dt);
5580  else fGraph2DPainter = new TGraph2DPainter(dtOld);
5581  }
5582  fGraph2DPainter->Paint(option);
5583  return;
5584  }
5585 
5586  gPad->SetBit(TGraph::kClipFrame);
5587 
5588  Double_t *levels = new Double_t[2*kMAXCONTOUR];
5589  Double_t *xarr = new Double_t[2*kMAXCONTOUR];
5590  Double_t *yarr = new Double_t[2*kMAXCONTOUR];
5591  Int_t *itarr = new Int_t[2*kMAXCONTOUR];
5592 
5593  Int_t npmax = 0;
5594  for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
5595 
5596  ncontour = fH->GetContour();
5597  if (ncontour == 0) {
5598  ncontour = gStyle->GetNumberContours();
5599  fH->SetContour(ncontour);
5600  }
5601  if (ncontour > kMAXCONTOUR) {
5602  Warning("PaintContour", "maximum number of contours is %d, asked for %d",
5603  kMAXCONTOUR, ncontour);
5604  ncontour = kMAXCONTOUR-1;
5605  }
5606  if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ncontour);
5607 
5608  for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
5609  Int_t linesav = fH->GetLineStyle();
5610  Int_t colorsav = fH->GetLineColor();
5611  Int_t fillsav = fH->GetFillColor();
5612  if (Hoption.Contour == 13) {
5613  fH->TAttLine::Modify();
5614  }
5615 
5616  TPolyLine **polys = 0;
5617  TPolyLine *poly=0;
5618  TObjArray *contours = 0;
5619  TList *list = 0;
5620  TGraph *graph = 0;
5621  Int_t *np = 0;
5622  if (Hoption.Contour == 1) {
5623  np = new Int_t[ncontour];
5624  for (i=0;i<ncontour;i++) np[i] = 0;
5625  polys = new TPolyLine*[ncontour];
5626  for (i=0;i<ncontour;i++) {
5627  polys[i] = new TPolyLine(100);
5628  }
5629  if (Hoption.List == 1) {
5630  contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
5631  if (contours) {
5632  gROOT->GetListOfSpecials()->Remove(contours);
5633  count = contours->GetSize();
5634  for (i=0;i<count;i++) {
5635  list = (TList*)contours->At(i);
5636  if (list) list->Delete();
5637  }
5638  }
5639  contours = new TObjArray(ncontour);
5640  contours->SetName("contours");
5641  gROOT->GetListOfSpecials()->Add(contours);
5642  for (i=0;i<ncontour;i++) {
5643  list = new TList();
5644  contours->Add(list);
5645  }
5646  }
5647  }
5648  Int_t theColor;
5649  Int_t ncolors = gStyle->GetNumberOfColors();
5650  Int_t ndivz = TMath::Abs(ncontour);
5651 
5652  Int_t k,ipoly;
5653  for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
5654  y[0] = fYaxis->GetBinCenter(j);
5655  y[1] = y[0];
5656  y[2] = fYaxis->GetBinCenter(j+1);
5657  y[3] = y[2];
5658  for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
5659  zc[0] = fH->GetBinContent(i, j);
5660  zc[1] = fH->GetBinContent(i+1, j);
5661  zc[2] = fH->GetBinContent(i+1, j+1);
5662  zc[3] = fH->GetBinContent(i, j+1);
5663  if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
5664  if (Hoption.Logz) {
5665  if (zc[0] > 0) zc[0] = TMath::Log10(zc[0]);
5666  else zc[0] = Hparam.zmin;
5667  if (zc[1] > 0) zc[1] = TMath::Log10(zc[1]);
5668  else zc[1] = Hparam.zmin;
5669  if (zc[2] > 0) zc[2] = TMath::Log10(zc[2]);
5670  else zc[2] = Hparam.zmin;
5671  if (zc[3] > 0) zc[3] = TMath::Log10(zc[3]);
5672  else zc[3] = Hparam.zmin;
5673  }
5674  for (k=0;k<4;k++) {
5675  ir[k] = TMath::BinarySearch(ncontour,levels,zc[k]);
5676  }
5677  if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
5678  x[0] = fXaxis->GetBinCenter(i);
5679  x[3] = x[0];
5680  x[1] = fXaxis->GetBinCenter(i+1);
5681  x[2] = x[1];
5682  if (zc[0] <= zc[1]) n = 0; else n = 1;
5683  if (zc[2] <= zc[3]) m = 2; else m = 3;
5684  if (zc[n] > zc[m]) n = m;
5685  n++;
5686  lj=1;
5687  for (ix=1;ix<=4;ix++) {
5688  m = n%4 + 1;
5689  ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
5690  ir[m-1],x[m-1],y[m-1],&xarr[lj-1],&yarr[lj-1],&itarr[lj-1], levels);
5691  lj += 2*ljfill;
5692  n = m;
5693  }
5694 
5695  if (zc[0] <= zc[1]) n = 0; else n = 1;
5696  if (zc[2] <= zc[3]) m = 2; else m = 3;
5697  if (zc[n] > zc[m]) n = m;
5698  n++;
5699  lj=2;
5700  for (ix=1;ix<=4;ix++) {
5701  if (n == 1) m = 4;
5702  else m = n-1;
5703  ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
5704  ir[m-1],x[m-1],y[m-1],&xarr[lj-1],&yarr[lj-1],&itarr[lj-1], levels);
5705  lj += 2*ljfill;
5706  n = m;
5707  }
5708 
5709  // Re-order endpoints
5710 
5711  count = 0;
5712  for (ix=1; ix<=lj-5; ix +=2) {
5713  //count = 0;
5714  while (itarr[ix-1] != itarr[ix]) {
5715  xsave = xarr[ix];
5716  ysave = yarr[ix];
5717  itars = itarr[ix];
5718  for (jx=ix; jx<=lj-5; jx +=2) {
5719  xarr[jx] = xarr[jx+2];
5720  yarr[jx] = yarr[jx+2];
5721  itarr[jx] = itarr[jx+2];
5722  }
5723  xarr[lj-3] = xsave;
5724  yarr[lj-3] = ysave;
5725  itarr[lj-3] = itars;
5726  if (count > 100) break;
5727  count++;
5728  }
5729  }
5730 
5731  if (count > 100) continue;
5732  for (ix=1; ix<=lj-2; ix +=2) {
5733  theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
5734  icol = gStyle->GetColorPalette(theColor);
5735  if (Hoption.Contour == 11) {
5736  fH->SetLineColor(icol);
5737  }
5738  if (Hoption.Contour == 12) {
5739  mode = icol%5;
5740  if (mode == 0) mode = 5;
5741  fH->SetLineStyle(mode);
5742  }
5743  if (Hoption.Contour != 1) {
5744  fH->TAttLine::Modify();
5745  gPad->PaintPolyLine(2,&xarr[ix-1],&yarr[ix-1]);
5746  continue;
5747  }
5748 
5749  ipoly = itarr[ix-1];
5750  if (ipoly >=0 && ipoly <ncontour) {
5751  poly = polys[ipoly];
5752  poly->SetPoint(np[ipoly] ,xarr[ix-1],yarr[ix-1]);
5753  poly->SetPoint(np[ipoly]+1,xarr[ix], yarr[ix]);
5754  np[ipoly] += 2;
5755  if (npmax < np[ipoly]) npmax = np[ipoly];
5756  }
5757  }
5758  } // end of if (ir[0]
5759  } //end of for (i
5760  } //end of for (j
5761 
5762  Double_t xmin,ymin;
5763  Double_t *xp, *yp;
5764  Int_t nadd,iminus,iplus;
5765  Double_t *xx, *yy;
5766  Int_t istart;
5767  Int_t first = ncontour;
5768  Int_t *polysort = 0;
5769  Int_t contListNb;
5770  if (Hoption.Contour != 1) goto theEND;
5771 
5772  //The 2 points line generated above are now sorted/merged to generate
5773  //a list of consecutive points.
5774  // If the option "List" has been specified, the list of points is saved
5775  // in the form of TGraph objects in the ROOT list of special objects.
5776  xmin = gPad->GetUxmin();
5777  ymin = gPad->GetUymin();
5778  xp = new Double_t[2*npmax];
5779  yp = new Double_t[2*npmax];
5780  polysort = new Int_t[ncontour];
5781  //find first positive contour
5782  for (ipoly=0;ipoly<ncontour;ipoly++) {
5783  if (levels[ipoly] >= 0) {first = ipoly; break;}
5784  }
5785  //store negative contours from 0 to minimum, then all positive contours
5786  k = 0;
5787  for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
5788  for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
5789  // we can now draw sorted contours
5790  contListNb = 0;
5791  fH->SetFillStyle(1001);
5792  for (k=0;k<ncontour;k++) {
5793  ipoly = polysort[k];
5794  if (np[ipoly] == 0) continue;
5795  if (Hoption.List) list = (TList*)contours->At(contListNb);
5796  contListNb++;
5797  poly = polys[ipoly];
5798  xx = poly->GetX();
5799  yy = poly->GetY();
5800  istart = 0;
5801  while (1) {
5802  iminus = npmax;
5803  iplus = iminus+1;
5804  xp[iminus]= xx[istart]; yp[iminus] = yy[istart];
5805  xp[iplus] = xx[istart+1]; yp[iplus] = yy[istart+1];
5806  xx[istart] = xmin; yy[istart] = ymin;
5807  xx[istart+1] = xmin; yy[istart+1] = ymin;
5808  while (1) {
5809  nadd = 0;
5810  for (i=2;i<np[ipoly];i+=2) {
5811  if ((iplus < 2*npmax-1) && (xx[i] == xp[iplus]) && (yy[i] == yp[iplus])) {
5812  iplus++;
5813  xp[iplus] = xx[i+1]; yp[iplus] = yy[i+1];
5814  xx[i] = xmin; yy[i] = ymin;
5815  xx[i+1] = xmin; yy[i+1] = ymin;
5816  nadd++;
5817  }
5818  if ((iminus > 0) && (xx[i+1] == xp[iminus]) && (yy[i+1] == yp[iminus])) {
5819  iminus--;
5820  xp[iminus] = xx[i]; yp[iminus] = yy[i];
5821  xx[i] = xmin; yy[i] = ymin;
5822  xx[i+1] = xmin; yy[i+1] = ymin;
5823  nadd++;
5824  }
5825  }
5826  if (nadd == 0) break;
5827  }
5828  theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
5829  icol = gStyle->GetColorPalette(theColor);
5830  if (ndivz > 1) fH->SetFillColor(icol);
5831  fH->TAttFill::Modify();
5832  gPad->PaintFillArea(iplus-iminus+1,&xp[iminus],&yp[iminus]);
5833  if (Hoption.List) {
5834  graph = new TGraph(iplus-iminus+1,&xp[iminus],&yp[iminus]);
5835  graph->SetFillColor(icol);
5836  graph->SetLineWidth(fH->GetLineWidth());
5837  list->Add(graph);
5838  }
5839  //check if more points are left
5840  istart = 0;
5841  for (i=2;i<np[ipoly];i+=2) {
5842  if (xx[i] != xmin && yy[i] != ymin) {
5843  istart = i;
5844  break;
5845  }
5846  }
5847  if (istart == 0) break;
5848  }
5849  }
5850 
5851  for (i=0;i<ncontour;i++) delete polys[i];
5852  delete [] polys;
5853  delete [] xp;
5854  delete [] yp;
5855  delete [] polysort;
5856 
5857 theEND:
5858  gPad->ResetBit(TGraph::kClipFrame);
5859  if (Hoption.Zscale) PaintPalette();
5860  fH->SetLineStyle(linesav);
5861  fH->SetLineColor(colorsav);
5862  fH->SetFillColor(fillsav);
5863  if (np) delete [] np;
5864  delete [] xarr;
5865  delete [] yarr;
5866  delete [] itarr;
5867  delete [] levels;
5868 }
5869 
5870 ////////////////////////////////////////////////////////////////////////////////
5871 /// Fill the matrix `xarr` and `yarr` for Contour Plot.
5872 
5874  Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
5875  Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
5876 {
5877 
5878  Bool_t vert;
5879  Double_t tlen, tdif, elev, diff, pdif, xlen;
5880  Int_t n, i, icount;
5881 
5882  if (x1 == x2) {
5883  vert = kTRUE;
5884  tlen = y2 - y1;
5885  } else {
5886  vert = kFALSE;
5887  tlen = x2 - x1;
5888  }
5889 
5890  n = icont1 +1;
5891  tdif = elev2 - elev1;
5892  i = 0;
5893  icount = 0;
5894  while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
5895  //elev = fH->GetContourLevel(n);
5896  elev = levels[n];
5897  diff = elev - elev1;
5898  pdif = diff/tdif;
5899  xlen = tlen*pdif;
5900  if (vert) {
5901  if (Hoption.Logx)
5902  xarr[i] = TMath::Log10(x1);
5903  else
5904  xarr[i] = x1;
5905  if (Hoption.Logy)
5906  yarr[i] = TMath::Log10(y1 + xlen);
5907  else
5908  yarr[i] = y1 + xlen;
5909  } else {
5910  if (Hoption.Logx)
5911  xarr[i] = TMath::Log10(x1 + xlen);
5912  else
5913  xarr[i] = x1 + xlen;
5914  if (Hoption.Logy)
5915  yarr[i] = TMath::Log10(y1);
5916  else
5917  yarr[i] = y1;
5918  }
5919  itarr[i] = n;
5920  icount++;
5921  i +=2;
5922  n++;
5923  }
5924  return icount;
5925 }
5926 
5927 ////////////////////////////////////////////////////////////////////////////////
5928 /// [Draw 1D histograms error bars.](#HP09)
5929 
5931 {
5932 
5933  // On iOS, we do not highlight histogram, if it's not picked at the moment
5934  // (but part of histogram (axis or pavestat) was picked, that's why this code
5935  // is called at all. This conditional statement never executes on non-iOS platform.
5936  if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
5937 
5938  const Int_t kBASEMARKER=8;
5939  Double_t xp, yp, ex1, ex2, ey1, ey2;
5940  Double_t delta;
5941  Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbase;
5942  Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
5943  Double_t xmin, xmax, ymin, ymax;
5944  Double_t logxmin = 0;
5945  Double_t logymin = 0;
5946  Int_t i, k, npoints, first, last, fixbin;
5947  Int_t if1 = 0;
5948  Int_t if2 = 0;
5949  Int_t drawmarker, errormarker;
5950  Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
5951 
5952  Double_t *xline = 0;
5953  Double_t *yline = 0;
5954  option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
5955  if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
5956  if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
5957  if (Hoption.Error == 10) option0 = 1;
5958  if (Hoption.Error == 11) option1 = 1;
5959  if (Hoption.Error == 12) option2 = 1;
5960  if (Hoption.Error == 13) option3 = 1;
5961  if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
5962  if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
5963  if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
5964  if (option2+option3 == 0) optionE = 1;
5965  if (Hoption.Error == 0) optionE = 0;
5966  if (fXaxis->GetXbins()->fN) fixbin = 0;
5967  else fixbin = 1;
5968 
5969  errormarker = fH->GetMarkerStyle();
5970  if (optionEX0) {
5971  xerror = 0;
5972  } else {
5973  xerror = gStyle->GetErrorX();
5974  }
5975  symbolsize = fH->GetMarkerSize();
5976  if (errormarker == 1) symbolsize = 0.01;
5977  sbase = symbolsize*kBASEMARKER;
5978  // set the graphics attributes
5979 
5980  fH->TAttLine::Modify();
5981  fH->TAttFill::Modify();
5982  fH->TAttMarker::Modify();
5983 
5984  // set the first and last bin
5985 
5986  Double_t factor = Hparam.factor;
5987  first = Hparam.xfirst;
5988  last = Hparam.xlast;
5989  npoints = last - first +1;
5990  xmin = gPad->GetUxmin();
5991  xmax = gPad->GetUxmax();
5992  ymin = gPad->GetUymin();
5993  ymax = gPad->GetUymax();
5994 
5995 
5996  if (option3) {
5997  xline = new Double_t[2*npoints];
5998  yline = new Double_t[2*npoints];
5999  if (!xline || !yline) {
6000  Error("PaintErrors", "too many points, out of memory");
6001  return;
6002  }
6003  if1 = 1;
6004  if2 = 2*npoints;
6005  }
6006 
6007  // compute the offset of the error bars due to the symbol size
6008  s2x = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
6009  s2y =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
6010 
6011  // compute size of the lines at the end of the error bars
6012  Int_t dxend = Int_t(gStyle->GetEndErrorSize());
6013  bxsize = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
6014  bysize =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
6015 
6016 
6017  if (fixbin) {
6018  if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
6019  else xp = Hparam.xmin + 0.5*Hparam.xbinsize;
6020  } else {
6021  delta = fH->GetBinWidth(first);
6022  xp = fH->GetBinLowEdge(first) + 0.5*delta;
6023  }
6024 
6025  // if errormarker = 0 or symbolsize = 0. no symbol is drawn
6026  if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
6027  if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
6028 
6029  // ---------------------- Loop over the points---------------------
6030  for (k=first; k<=last; k++) {
6031 
6032  // get the data
6033  // xp = X position of the current point
6034  // yp = Y position of the current point
6035  // ex1 = Low X error
6036  // ex2 = Up X error
6037  // ey1 = Low Y error
6038  // ey2 = Up Y error
6039  // (xi,yi) = Error bars coordinates
6040 
6041  if (Hoption.Logx) {
6042  if (xp <= 0) goto L30;
6043  if (xp < logxmin) goto L30;
6044  if (xp > TMath::Power(10,xmax)) break;
6045  } else {
6046  if (xp < xmin) goto L30;
6047  if (xp > xmax) break;
6048  }
6049  yp = factor*fH->GetBinContent(k);
6050  if (optionI0 && yp==0) goto L30;
6051  if (fixbin) {
6052  ex1 = xerror*Hparam.xbinsize;
6053  } else {
6054  delta = fH->GetBinWidth(k);
6055  ex1 = xerror*delta;
6056  }
6057  if (fH->GetBinErrorOption() == TH1::kNormal) {
6058  ey1 = factor*fH->GetBinError(k);
6059  ey2 = ey1;
6060  } else {
6061  ey1 = factor*fH->GetBinErrorLow(k);
6062  ey2 = factor*fH->GetBinErrorUp(k);
6063  }
6064  ex2 = ex1;
6065 
6066  xi4 = xp;
6067  xi3 = xp;
6068  xi2 = xp + ex2;
6069  xi1 = xp - ex1;
6070 
6071  yi1 = yp;
6072  yi2 = yp;
6073  yi3 = yp - ey1;
6074  yi4 = yp + ey2;
6075 
6076  // take the LOG if necessary
6077  if (Hoption.Logx) {
6078  xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
6079  xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
6080  xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
6081  xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
6082  }
6083  if (Hoption.Logy) {
6084  yi1 = TMath::Log10(TMath::Max(yi1,logymin));
6085  yi2 = TMath::Log10(TMath::Max(yi2,logymin));
6086  yi3 = TMath::Log10(TMath::Max(yi3,logymin));
6087  yi4 = TMath::Log10(TMath::Max(yi4,logymin));
6088  }
6089 
6090  // test if error bars are not outside the limits
6091  // otherwise they are truncated
6092 
6093  xi1 = TMath::Max(xi1,xmin);
6094  xi2 = TMath::Min(xi2,xmax);
6095  yi3 = TMath::Max(yi3,ymin);
6096  yi4 = TMath::Min(yi4,ymax);
6097 
6098  // test if the marker is on the frame limits. If "Yes", the
6099  // marker will not be drawn and the error bars will be readjusted.
6100 
6101  drawmarker = kTRUE;
6102  if (!option0 && !option3) {
6103  if (Hoption.Logy && yp < logymin) goto L30;
6104  if (yi1 < ymin || yi1 > ymax) goto L30;
6105  if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
6106  }
6107  if (!symbolsize || !errormarker) drawmarker = kFALSE;
6108 
6109  // draw the error rectangles
6110  if (option2) gPad->PaintBox(xi1,yi3,xi2,yi4);
6111 
6112  // keep points for fill area drawing
6113  if (option3) {
6114  xline[if1-1] = xi3;
6115  xline[if2-1] = xi3;
6116  yline[if1-1] = yi4;
6117  yline[if2-1] = yi3;
6118  if1++;
6119  if2--;
6120  }
6121 
6122  // draw the error bars
6123  if (Hoption.Logy && yp < logymin) drawmarker = kFALSE;
6124  if (optionE && drawmarker) {
6125  if ((yi3 < yi1 - s2y) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1 - s2y,ymax));
6126  if ((yi1 + s2y < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1 + s2y, ymin),xi4,yi4);
6127  // don't duplicate the horizontal line
6128  if (Hoption.Hist != 2) {
6129  if (yi1<ymax && yi1>ymin) {
6130  if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
6131  if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
6132  }
6133  }
6134  }
6135  if (optionE && !drawmarker && (ey1 != 0 || ey2 !=0)) {
6136  if ((yi3 < yi1) && (yi3 < ymax)) gPad->PaintLine(xi3,yi3,xi4,TMath::Min(yi1,ymax));
6137  if ((yi1 < yi4) && (yi4 > ymin)) gPad->PaintLine(xi3,TMath::Max(yi1,ymin),xi4,yi4);
6138  // don't duplicate the horizontal line
6139  if (Hoption.Hist != 2) {
6140  if (yi1<ymax && yi1>ymin) {
6141  if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
6142  if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
6143  }
6144  }
6145  }
6146 
6147  // draw line at the end of the error bars
6148 
6149  if (option1 && drawmarker) {
6150  if (yi3 < yi1-s2y) gPad->PaintLine(xi3 - bxsize,yi3,xi3 + bxsize,yi3);
6151  if (yi4 > yi1+s2y) gPad->PaintLine(xi3 - bxsize,yi4,xi3 + bxsize,yi4);
6152  if (xi1 < xi3-s2x) gPad->PaintLine(xi1,yi1 - bysize,xi1,yi1 + bysize);
6153  if (xi2 > xi3+s2x) gPad->PaintLine(xi2,yi1 - bysize,xi2,yi1 + bysize);
6154  }
6155 
6156  // draw the marker
6157 
6158  if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
6159 
6160 L30:
6161  if (fixbin) xp += Hparam.xbinsize;
6162  else {
6163  if (k < last) {
6164  delta = fH->GetBinWidth(k+1);
6165  xp = fH->GetBinLowEdge(k+1) + 0.5*delta;
6166  }
6167  }
6168  } //end of for loop
6169 
6170  // draw the filled area
6171 
6172  if (option3) {
6173  TGraph graph;
6174  graph.SetLineStyle(fH->GetLineStyle());
6175  graph.SetLineColor(fH->GetLineColor());
6176  graph.SetLineWidth(fH->GetLineWidth());
6177  graph.SetFillStyle(fH->GetFillStyle());
6178  graph.SetFillColor(fH->GetFillColor());
6179  Int_t logx = gPad->GetLogx();
6180  Int_t logy = gPad->GetLogy();
6181  gPad->SetLogx(0);
6182  gPad->SetLogy(0);
6183 
6184  // In some cases the number of points in the fill area is smaller than
6185  // 2*npoints. In such cases the array xline and yline must be arranged
6186  // before being plotted. The next loop does that.
6187  if (if2 > npoints) {
6188  for (i=1; i<if1; i++) {
6189  xline[if1-2+i] = xline[if2-1+i];
6190  yline[if1-2+i] = yline[if2-1+i];
6191  }
6192  npoints = if1-1;
6193  }
6194  if (option4) graph.PaintGraph(2*npoints,xline,yline,"FC");
6195  else graph.PaintGraph(2*npoints,xline,yline,"F");
6196  gPad->SetLogx(logx);
6197  gPad->SetLogy(logy);
6198  delete [] xline;
6199  delete [] yline;
6200  }
6201 }
6202 
6203 ////////////////////////////////////////////////////////////////////////////////
6204 /// Draw 2D histograms errors.
6205 
6207 {
6208 
6209  fH->TAttMarker::Modify();
6210  fH->TAttLine::Modify();
6211 
6212  // Define the 3D view
6213  fXbuf[0] = Hparam.xmin;
6214  fYbuf[0] = Hparam.xmax;
6215  fXbuf[1] = Hparam.ymin;
6216  fYbuf[1] = Hparam.ymax;
6217  fXbuf[2] = Hparam.zmin;
6218  fYbuf[2] = Hparam.zmax*(1. + gStyle->GetHistTopMargin());
6220  TView *view = gPad->GetView();
6221  if (!view) {
6222  Error("Paint2DErrors", "no TView in current pad");
6223  return;
6224  }
6225  Double_t thedeg = 90 - gPad->GetTheta();
6226  Double_t phideg = -90 - gPad->GetPhi();
6227  Double_t psideg = view->GetPsi();
6228  Int_t irep;
6229  view->SetView(phideg, thedeg, psideg, irep);
6230 
6231  // Set color/style for back box
6232  fLego->SetFillStyle(gPad->GetFrameFillStyle());
6233  fLego->SetFillColor(gPad->GetFrameFillColor());
6234  fLego->TAttFill::Modify();
6235  Int_t backcolor = gPad->GetFrameFillColor();
6236  if (Hoption.System != kCARTESIAN) backcolor = 0;
6237  view->PadRange(backcolor);
6240  fLego->TAttFill::Modify();
6241 
6242  // Paint the Back Box if needed
6243  if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6244  fLego->InitMoveScreen(-1.1,1.1);
6247  fLego->BackBox(90);
6248  }
6249 
6250  // Paint the Errors
6251  Double_t x, ex, x1, x2;
6252  Double_t y, ey, y1, y2;
6253  Double_t z, ez1, ez2, z1, z2;
6254  Double_t temp1[3],temp2[3];
6255  Double_t xyerror;
6256  if (Hoption.Error == 110) {
6257  xyerror = 0;
6258  } else {
6259  xyerror = gStyle->GetErrorX();
6260  }
6261 
6262  Double_t xk, xstep, yk, ystep;
6263  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
6264  y = fYaxis->GetBinCenter(j);
6265  ey = fYaxis->GetBinWidth(j)*xyerror;
6266  y1 = y-ey;
6267  y2 = y+ey;
6268  if (Hoption.Logy) {
6269  if (y > 0) y = TMath::Log10(y);
6270  else continue;
6271  if (y1 > 0) y1 = TMath::Log10(y1);
6272  else y1 = Hparam.ymin;
6273  if (y2 > 0) y2 = TMath::Log10(y2);
6274  else y2 = Hparam.ymin;
6275  }
6276  yk = fYaxis->GetBinLowEdge(j);
6277  ystep = fYaxis->GetBinWidth(j);
6278  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
6279  xk = fXaxis->GetBinLowEdge(i);
6280  xstep = fXaxis->GetBinWidth(i);
6281  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
6282  Int_t bin = fH->GetBin(i,j);
6283  x = fXaxis->GetBinCenter(i);
6284  ex = fXaxis->GetBinWidth(i)*xyerror;
6285  x1 = x-ex;
6286  x2 = x+ex;
6287  if (Hoption.Logx) {
6288  if (x > 0) x = TMath::Log10(x);
6289  else continue;
6290  if (x1 > 0) x1 = TMath::Log10(x1);
6291  else x1 = Hparam.xmin;
6292  if (x2 > 0) x2 = TMath::Log10(x2);
6293  else x2 = Hparam.xmin;
6294  }
6295  z = fH->GetBinContent(bin);
6296  if (fH->GetBinErrorOption() == TH1::kNormal) {
6297  ez1 = fH->GetBinError(bin);
6298  ez2 = ez1;
6299  }
6300  else {
6301  ez1 = fH->GetBinErrorLow(bin);
6302  ez2 = fH->GetBinErrorUp(bin);
6303  }
6304  z1 = z - ez1;
6305  z2 = z + ez2;
6306  if (Hoption.Logz) {
6307  if (z > 0) z = TMath::Log10(z);
6308  else z = Hparam.zmin;
6309  if (z1 > 0) z1 = TMath::Log10(z1);
6310  else z1 = Hparam.zmin;
6311  if (z2 > 0) z2 = TMath::Log10(z2);
6312  else z2 = Hparam.zmin;
6313 
6314  }
6315  if (z <= Hparam.zmin) continue;
6316  if (z > Hparam.zmax) z = Hparam.zmax;
6317 
6318  temp1[0] = x1;
6319  temp1[1] = y;
6320  temp1[2] = z;
6321  temp2[0] = x2;
6322  temp2[1] = y;
6323  temp2[2] = z;
6324  gPad->PaintLine3D(temp1, temp2);
6325  temp1[0] = x;
6326  temp1[1] = y1;
6327  temp1[2] = z;
6328  temp2[0] = x;
6329  temp2[1] = y2;
6330  temp2[2] = z;
6331  gPad->PaintLine3D(temp1, temp2);
6332  temp1[0] = x;
6333  temp1[1] = y;
6334  temp1[2] = z1;
6335  temp2[0] = x;
6336  temp2[1] = y;
6337  temp2[2] = z2;
6338  gPad->PaintLine3D(temp1, temp2);
6339  temp1[0] = x;
6340  temp1[1] = y;
6341  temp1[2] = z;
6342  view->WCtoNDC(temp1, &temp2[0]);
6343  gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
6344  }
6345  }
6346 
6347  // Paint the Front Box if needed
6348  if (Hoption.FrontBox) {
6349  fLego->InitMoveScreen(-1.1,1.1);
6351  fLego->FrontBox(90);
6352  }
6353 
6354  // Paint the Axis if needed
6355  if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
6356  TGaxis *axis = new TGaxis();
6357  PaintLegoAxis(axis, 90);
6358  delete axis;
6359  }
6360 
6361  delete fLego; fLego = 0;
6362 }
6363 
6364 ////////////////////////////////////////////////////////////////////////////////
6365 /// Calculate range and clear pad (canvas).
6366 
6368 {
6369 
6370  if (Hoption.Same) return;
6371 
6372  RecalculateRange();
6373 
6374  if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
6375  Hoption.Contour == 14 || Hoption.Error >= 100) {
6376  TObject *frame = gPad->FindObject("TFrame");
6377  if (frame) gPad->GetListOfPrimitives()->Remove(frame);
6378  return;
6379  }
6380 
6381  //The next statement is always executed on non-iOS platform,
6382  //on iOS depends on pad mode.
6383  if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode())
6384  gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
6385 }
6386 
6387 ////////////////////////////////////////////////////////////////////////////////
6388 /// [Paint functions associated to an histogram.](#HP28")
6389 
6391 {
6392 
6394  TObject *obj;
6395 
6396  while (lnk) {
6397  obj = lnk->GetObject();
6398  TVirtualPad *padsave = gPad;
6399  if (obj->InheritsFrom(TF2::Class())) {
6400  if (obj->TestBit(TF2::kNotDraw) == 0) {
6401  if (Hoption.Lego || Hoption.Surf || Hoption.Error >= 100) {
6402  TF2 *f2 = (TF2*)obj;
6403  f2->SetMinimum(fH->GetMinimum());
6404  f2->SetMaximum(fH->GetMaximum());
6405  f2->SetRange(fH->GetXaxis()->GetXmin(), fH->GetYaxis()->GetXmin(), fH->GetXaxis()->GetXmax(), fH->GetYaxis()->GetXmax() );
6406  f2->Paint("surf same");
6407  } else {
6408  obj->Paint("cont3 same");
6409  }
6410  }
6411  } else if (obj->InheritsFrom(TF1::Class())) {
6412  if (obj->TestBit(TF1::kNotDraw) == 0) obj->Paint("lsame");
6413  } else {
6414  //Let's make this 'function' selectable on iOS device (for example, it can be TPaveStat).
6415  gPad->PushSelectableObject(obj);
6416 
6417  //The next statement is ALWAYS executed on non-iOS platform, on iOS it depends on pad's mode
6418  //and picked object.
6419  if (!gPad->PadInHighlightMode() || (gPad->PadInHighlightMode() && obj == gPad->GetSelected()))
6420  obj->Paint(lnk->GetOption());
6421  }
6422  lnk = (TObjOptLink*)lnk->Next();
6423  padsave->cd();
6424  }
6425 }
6426 
6427 ////////////////////////////////////////////////////////////////////////////////
6428 /// [Control routine to draw 1D histograms](#HP01b)
6429 
6431 {
6432 
6433  //On iOS: do not highlight hist, if part of it was selected.
6434  //Never executes on non-iOS platform.
6435  if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
6436  return;
6437 
6438  static char chopth[17];
6439 
6440  Int_t htype, oldhtype;
6441  Int_t i, j, first, last, nbins, fixbin;
6443  yb = 0;
6444 
6445  strlcpy(chopth, " ",17);
6446 
6447  Double_t ymin = Hparam.ymin;
6448  Double_t ymax = Hparam.ymax;
6449  Double_t baroffset = fH->GetBarOffset();
6450  Double_t barwidth = fH->GetBarWidth();
6451  Double_t baroffsetsave = gStyle->GetBarOffset();
6452  Double_t barwidthsave = gStyle->GetBarWidth();
6453  gStyle->SetBarOffset(baroffset);
6454  gStyle->SetBarWidth(barwidth);
6455 
6456  // Create "LIFE" structure to keep current histogram status
6457 
6458  first = Hparam.xfirst;
6459  last = Hparam.xlast;
6460  nbins = last - first + 1;
6461 
6462  Double_t *keepx = 0;
6463  Double_t *keepy = 0;
6464  if (fXaxis->GetXbins()->fN) fixbin = 0;
6465  else fixbin = 1;
6466  if (fixbin) keepx = new Double_t[2];
6467  else keepx = new Double_t[nbins+1];
6468  keepy = new Double_t[nbins];
6469  Double_t logymin = 0;
6470  if (Hoption.Logy) logymin = TMath::Power(10,ymin);
6471 
6472  // Loop on histogram bins
6473 
6474  for (j=first; j<=last;j++) {
6475  c1 = Hparam.factor*fH->GetBinContent(j);
6476  if (TMath::Abs(ymax-ymin) > 0) {
6477  if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
6478  else yb = c1;
6479  }
6480  if (!Hoption.Line) {
6481  yb = TMath::Max(yb, ymin);
6482  yb = TMath::Min(yb, ymax);
6483  }
6484  keepy[j-first] = yb;
6485  }
6486 
6487  // Draw histogram according to value of FillStyle and FillColor
6488 
6489  if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
6490  else {
6491  for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
6492  keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
6493  }
6494 
6495  // Prepare Fill area (systematic with option "Bar").
6496 
6497  oldhtype = fH->GetFillStyle();
6498  htype = oldhtype;
6499  if (Hoption.Bar) {
6500  if (htype == 0 || htype == 1000) htype = 1001;
6501  }
6502 
6503  Width_t lw = (Width_t)fH->GetLineWidth();
6504 
6505  // Code option for GrapHist
6506 
6507  if (Hoption.Line) chopth[0] = 'L';
6508  if (Hoption.Star) chopth[1] = '*';
6509  if (Hoption.Mark) chopth[2] = 'P';
6510  if (Hoption.Mark == 10) chopth[3] = '0';
6511  if (Hoption.Line || Hoption.Curve || Hoption.Hist || Hoption.Bar) {
6512  if (Hoption.Curve) chopth[3] = 'C';
6513  if (Hoption.Hist > 0) chopth[4] = 'H';
6514  else if (Hoption.Bar) chopth[5] = 'B';
6515  if (fH->GetFillColor() && htype) {
6516  if (Hoption.Logy) {
6517  chopth[6] = '1';
6518  }
6519  if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
6520  chopth[7] = 'F';
6521  }
6522  }
6523  }
6524  if (!fixbin && strlen(chopth)) {
6525  chopth[8] = 'N';
6526  }
6527 
6528  if (Hoption.Fill == 2) chopth[13] = '2';
6529 
6530  // Option LOGX
6531 
6532  if (Hoption.Logx) {
6533  chopth[9] = 'G';
6534  chopth[10] = 'X';
6535  if (fixbin) {
6536  keepx[0] = TMath::Power(10,keepx[0]);
6537  keepx[1] = TMath::Power(10,keepx[1]);
6538  }
6539  }
6540 
6541  if (Hoption.Off) {
6542  chopth[11] = ']';
6543  chopth[12] = '[';
6544  }
6545 
6546  // Draw the histogram
6547 
6548  TGraph graph;
6549  graph.SetLineWidth(lw);
6550  graph.SetLineStyle(fH->GetLineStyle());
6551  graph.SetLineColor(fH->GetLineColor());
6552  graph.SetFillStyle(htype);
6553  graph.SetFillColor(fH->GetFillColor());
6554  graph.SetMarkerStyle(fH->GetMarkerStyle());
6555  graph.SetMarkerSize(fH->GetMarkerSize());
6556  graph.SetMarkerColor(fH->GetMarkerColor());
6557  if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
6558 
6559  graph.PaintGrapHist(nbins, keepx, keepy ,chopth);
6560 
6561  delete [] keepx;
6562  delete [] keepy;
6563  gStyle->SetBarOffset(baroffsetsave);
6564  gStyle->SetBarWidth(barwidthsave);
6565 
6566  htype=oldhtype;
6567 }
6568 
6569 ////////////////////////////////////////////////////////////////////////////////
6570 /// [Control function to draw a 3D histograms.](#HP01d)
6571 
6572 void THistPainter::PaintH3(Option_t *option)
6573 {
6574 
6575  char *cmd;
6576  TString opt = option;
6577  opt.ToLower();
6578  Int_t irep;
6579 
6580  if (Hoption.Box || Hoption.Lego) {
6581  if (Hoption.Box == 11 || Hoption.Lego == 11) {
6582  PaintH3Box(1);
6583  } else if (Hoption.Box == 12 || Hoption.Lego == 12) {
6585  } else if (Hoption.Box == 13 || Hoption.Lego == 13) {
6586  PaintH3Box(3);
6587  } else {
6588  PaintH3BoxRaster();
6589  }
6590  return;
6591  } else if (strstr(opt,"iso")) {
6592  PaintH3Iso();
6593  return;
6594  } else if (strstr(opt,"tf3")) {
6595  PaintTF3();
6596  return;
6597  } else {
6598  cmd = Form("TPolyMarker3D::PaintH3((TH1 *)0x%lx,\"%s\");",(Long_t)fH,option);
6599  }
6600 
6601  if (strstr(opt,"fb")) Hoption.FrontBox = 0;
6602  if (strstr(opt,"bb")) Hoption.BackBox = 0;
6603 
6604  TView *view = gPad->GetView();
6605  if (!view) return;
6606  Double_t thedeg = 90 - gPad->GetTheta();
6607  Double_t phideg = -90 - gPad->GetPhi();
6608  Double_t psideg = view->GetPsi();
6609  view->SetView(phideg, thedeg, psideg, irep);
6610 
6611  // Paint the data
6612  gROOT->ProcessLine(cmd);
6613 
6614  if (Hoption.Same) return;
6615 
6616  // Draw axis
6617  view->SetOutlineToCube();
6618  TSeqCollection *ol = view->GetOutline();
6619  if (ol && Hoption.BackBox && Hoption.FrontBox) ol->Paint(option);
6620  Hoption.System = kCARTESIAN;
6621  TGaxis *axis = new TGaxis();
6622  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
6623  delete axis;
6624 
6625  // Draw palette. In case of 4D plot with TTree::Draw() the palette should
6626  // be painted with the option colz.
6627  if (fH->GetDrawOption() && strstr(opt,"colz")) {
6628  Int_t ndiv = fH->GetContour();
6629  if (ndiv == 0 ) {
6630  ndiv = gStyle->GetNumberContours();
6631  fH->SetContour(ndiv);
6632  }
6633  PaintPalette();
6634  }
6635 
6636  // Draw title
6637  PaintTitle();
6638 
6639  //Draw stats and fit results
6640  TF1 *fit = 0;
6641  TIter next(fFunctions);
6642  TObject *obj;
6643  while ((obj = next())) {
6644  if (obj->InheritsFrom(TF1::Class())) {
6645  fit = (TF1*)obj;
6646  break;
6647  }
6648  }
6649  if (Hoption.Same != 1) {
6650  if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
6651  PaintStat3(gStyle->GetOptStat(),fit);
6652  }
6653  }
6654 
6655 }
6656 
6657 ////////////////////////////////////////////////////////////////////////////////
6658 /// Compute histogram parameters used by the drawing routines.
6659 
6661 {
6662 
6663  if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
6664 
6665  Int_t i;
6666  static const char *where = "PaintInit";
6667  Double_t yMARGIN = gStyle->GetHistTopMargin();
6668  Int_t maximum = 0;
6669  Int_t minimum = 0;
6670  if (fH->GetMaximumStored() != -1111) maximum = 1;
6671  if (fH->GetMinimumStored() != -1111) minimum = 1;
6673  // Compute X axis parameters
6674 
6675  Int_t last = fXaxis->GetLast();
6676  Int_t first = fXaxis->GetFirst();
6677  Hparam.xlowedge = fXaxis->GetBinLowEdge(first);
6678  Hparam.xbinsize = fXaxis->GetBinWidth(first);
6679  Hparam.xlast = last;
6680  Hparam.xfirst = first;
6681  Hparam.xmin = Hparam.xlowedge;
6682  Hparam.xmax = fXaxis->GetBinLowEdge(last)+fXaxis->GetBinWidth(last);
6683 
6684  // if log scale in X, replace xmin,max by the log
6685  if (Hoption.Logx) {
6686  if (Hparam.xmax<=0) {
6687  Error(where, "cannot set X axis to log scale");
6688  return 0;
6689  }
6690  if (Hparam.xlowedge <=0 ) {
6691  if (Hoption.Same) {
6692  Hparam.xlowedge = TMath::Power(10, gPad->GetUxmin());
6693  } else {
6694  for (i=first; i<=last; i++) {
6695  Double_t binLow = fXaxis->GetBinLowEdge(i);
6696  if (binLow>0) {
6697  Hparam.xlowedge = binLow;
6698  break;
6699  }
6700  if (binLow == 0 && fH->GetBinContent(i) !=0) {
6701  Hparam.xlowedge = fXaxis->GetBinUpEdge(i)*0.001;
6702  break;
6703  }
6704  }
6705  if (Hparam.xlowedge<=0) {
6706  Error(where, "cannot set X axis to log scale");
6707  return 0;
6708  }
6709  }
6710  Hparam.xmin = Hparam.xlowedge;
6711  }
6712  Hparam.xfirst= fXaxis->FindFixBin(Hparam.xmin);
6713  Hparam.xlast = fXaxis->FindFixBin(Hparam.xmax);
6714  Hparam.xmin = TMath::Log10(Hparam.xmin);
6715  Hparam.xmax = TMath::Log10(Hparam.xmax);
6716  if (Hparam.xlast > last) Hparam.xlast = last;
6717  if (Hparam.xfirst < first) Hparam.xfirst = first;
6718  }
6719 
6720  // Compute Y axis parameters
6721  Double_t bigp = TMath::Power(10,32);
6722  Double_t ymax = -bigp;
6723  Double_t ymin = bigp;
6724  Double_t c1, e1;
6725  Double_t xv[1];
6726  Double_t fval;
6727  TObject *f;
6728  TF1 *f1;
6729  Double_t allchan = 0;
6730  Int_t nonNullErrors = 0;
6731  TIter next(fFunctions);
6732  for (i=first; i<=last;i++) {
6733  c1 = fH->GetBinContent(i);
6734  ymax = TMath::Max(ymax,c1);
6735  if (Hoption.Logy) {
6736  if (c1 > 0) ymin = TMath::Min(ymin,c1);
6737  } else {
6738  ymin = TMath::Min(ymin,c1);
6739  }
6740  if (Hoption.Error) {
6741  if (fH->GetBinErrorOption() == TH1::kNormal)
6742  e1 = fH->GetBinError(i);
6743  else
6744  e1 = fH->GetBinErrorUp(i);
6745  if (e1 > 0) nonNullErrors++;
6746  ymax = TMath::Max(ymax,c1+e1);
6747  if (fH->GetBinErrorOption() != TH1::kNormal)
6748  e1 = fH->GetBinErrorLow(i);
6749 
6750  if (Hoption.Logy) {
6751  if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
6752  } else {
6753  ymin = TMath::Min(ymin,c1-e1);
6754  }
6755  }
6756  if (Hoption.Func) {
6757  xv[0] = fXaxis->GetBinCenter(i);
6758  while ((f = (TObject*) next())) {
6759  if (f->IsA() == TF1::Class()) {
6760  f1 = (TF1*)f;
6761  if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
6762  fval = f1->Eval(xv[0],0,0);
6763  if (f1->GetMaximumStored() != -1111) fval = TMath::Min(f1->GetMaximumStored(), fval);
6764  ymax = TMath::Max(ymax,fval);
6765  if (Hoption.Logy) {
6766  if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
6767  }
6768  }
6769  }
6770  next.Reset();
6771  }
6772  allchan += c1;
6773  }
6774  if (!nonNullErrors) {
6775  if (Hoption.Error) {
6776  if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
6777  Hoption.Error=0;
6778  }
6779  }
6780 
6781 
6782  // Take into account maximum , minimum
6783 
6784  if (Hoption.Logy && ymin <= 0) {
6785  if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
6786  else ymin = 0.001*ymax;
6787  }
6788 
6789  Double_t xm = ymin;
6790  if (maximum) ymax = fH->GetMaximumStored();
6791  if (minimum) xm = fH->GetMinimumStored();
6792  if (Hoption.Logy && xm < 0) {
6793  Error(where, "log scale requested with a negative argument (%f)", xm);
6794  return 0;
6795  } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
6796  ymin = 0.01;
6797  ymax = 10.;
6798  } else {
6799  ymin = xm;
6800  }
6801 
6802  if (ymin >= ymax) {
6803  if (Hoption.Logy) {
6804  if (ymax > 0) ymin = 0.001*ymax;
6805  else {
6806  if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
6807  return 0;
6808  }
6809  }
6810  else {
6811  if (ymin > 0) {
6812  ymin = 0;
6813  ymax *= 2;
6814  } else if (ymin < 0) {
6815  ymax = 0;
6816  ymin *= 2;
6817  } else {
6818  ymin = 0;
6819  ymax = 1;
6820  }
6821  }
6822  }
6823 
6824  // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
6825  if (TMath::AreEqualRel(ymin,ymax,1E-15)) {
6826  ymin = ymin*(1-1E-14);
6827  ymax = ymax*(1+1E-14);
6828  }
6829 
6830  // take into account normalization factor
6831  Hparam.allchan = allchan;
6832  Double_t factor = allchan;
6833  if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
6834  if (allchan) factor /= allchan;
6835  if (factor == 0) factor = 1;
6836  Hparam.factor = factor;
6837  ymax = factor*ymax;
6838  ymin = factor*ymin;
6839  //just in case the norm factor is negative
6840  // this may happen with a positive norm factor and a negative integral !
6841  if (ymax < ymin) {
6842  Double_t temp = ymax;
6843  ymax = ymin;
6844  ymin = temp;
6845  }
6846 
6847  // For log scales, histogram coordinates are LOG10(ymin) and
6848  // LOG10(ymax). Final adjustment (if not option "Same"
6849  // or "+" for ymax) of ymax and ymin for logarithmic scale, if
6850  // Maximum and Minimum are not defined.
6851  if (Hoption.Logy) {
6852  if (ymin <=0 || ymax <=0) {
6853  Error(where, "Cannot set Y axis to log scale");
6854  return 0;
6855  }
6856  ymin = TMath::Log10(ymin);
6857  if (!minimum) ymin += TMath::Log10(0.5);
6858  ymax = TMath::Log10(ymax);
6859  if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
6860  if (!Hoption.Same) {
6861  Hparam.ymin = ymin;
6862  Hparam.ymax = ymax;
6863  }
6864  return 1;
6865  }
6866 
6867  // final adjustment of ymin for linear scale.
6868  // if minimum is not set , then ymin is set to zero if >0
6869  // or to ymin - margin if <0.
6870  if (!minimum) {
6871  if (gStyle->GetHistMinimumZero()) {
6872  if (ymin >= 0) ymin = 0;
6873  else ymin -= yMARGIN*(ymax-ymin);
6874  } else {
6875  Double_t dymin = yMARGIN*(ymax-ymin);
6876  if (ymin >= 0 && (ymin-dymin <= 0)) ymin = 0;
6877  else ymin -= dymin;
6878  }
6879  }
6880 
6881  // final adjustment of YMAXI for linear scale (if not option "Same"):
6882  // decrease histogram height to MAX% of allowed height if HMAXIM
6883  // has not been called.
6884  if (!maximum) {
6885  ymax += yMARGIN*(ymax-ymin);
6886  }
6887 
6888  Hparam.ymin = ymin;
6889  Hparam.ymax = ymax;
6890  return 1;
6891 }
6892 
6893 ////////////////////////////////////////////////////////////////////////////////
6894 /// Compute histogram parameters used by the drawing routines for a rotated pad.
6895 
6897 {
6898 
6899  static const char *where = "PaintInitH";
6900  Double_t yMARGIN = gStyle->GetHistTopMargin();
6901  Int_t maximum = 0;
6902  Int_t minimum = 0;
6903  if (fH->GetMaximumStored() != -1111) maximum = 1;
6904  if (fH->GetMinimumStored() != -1111) minimum = 1;
6905 
6906  // Compute X axis parameters
6907 
6908  Int_t last = fXaxis->GetLast();
6909  Int_t first = fXaxis->GetFirst();
6910  Hparam.xlowedge = fXaxis->GetBinLowEdge(first);
6911  Hparam.xbinsize = fXaxis->GetBinWidth(first);
6912  Hparam.xlast = last;
6913  Hparam.xfirst = first;
6914  Hparam.ymin = Hparam.xlowedge;
6915  Hparam.ymax = fXaxis->GetBinLowEdge(last)+fXaxis->GetBinWidth(last);
6916 
6917  // if log scale in Y, replace ymin,max by the log
6918  if (Hoption.Logy) {
6919  if (Hparam.xlowedge <=0 ) {
6920  Hparam.xlowedge = 0.1*Hparam.xbinsize;
6921  Hparam.ymin = Hparam.xlowedge;
6922  }
6923  if (Hparam.ymin <=0 || Hparam.ymax <=0) {
6924  Error(where, "cannot set Y axis to log scale");
6925  return 0;
6926  }
6927  Hparam.xfirst= fXaxis->FindFixBin(Hparam.ymin);
6928  Hparam.xlast = fXaxis->FindFixBin(Hparam.ymax);
6929  Hparam.ymin = TMath::Log10(Hparam.ymin);
6930  Hparam.ymax = TMath::Log10(Hparam.ymax);
6931  if (Hparam.xlast > last) Hparam.xlast = last;
6932  }
6933 
6934  // Compute Y axis parameters
6935  Double_t bigp = TMath::Power(10,32);
6936  Double_t xmax = -bigp;
6937  Double_t xmin = bigp;
6938  Double_t c1, e1;
6939  Double_t xv[1];
6940  Double_t fval;
6941  Int_t i;
6942  TObject *f;
6943  TF1 *f1;
6944  Double_t allchan = 0;
6945  TIter next(fFunctions);
6946  for (i=first; i<=last;i++) {
6947  c1 = fH->GetBinContent(i);
6948  xmax = TMath::Max(xmax,c1);
6949  xmin = TMath::Min(xmin,c1);
6950  if (Hoption.Error) {
6951  e1 = fH->GetBinError(i);
6952  xmax = TMath::Max(xmax,c1+e1);
6953  xmin = TMath::Min(xmin,c1-e1);
6954  }
6955  if (Hoption.Func) {
6956  xv[0] = fXaxis->GetBinCenter(i);
6957  while ((f = (TObject*) next())) {
6958  if (f->IsA() == TF1::Class()) {
6959  f1 = (TF1*)f;
6960  if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
6961  fval = f1->Eval(xv[0],0,0);
6962  xmax = TMath::Max(xmax,fval);
6963  if (Hoption.Logy) {
6964  if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
6965  }
6966  }
6967  }
6968  next.Reset();
6969  }
6970  allchan += c1;
6971  }
6972 
6973  // Take into account maximum , minimum
6974 
6975  if (Hoption.Logx && xmin <= 0) {
6976  if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
6977  else xmin = 0.001*xmax;
6978  }
6979  Double_t xm = xmin;
6980  if (maximum) xmax = fH->GetMaximumStored();
6981  if (minimum) xm = fH->GetMinimumStored();
6982  if (Hoption.Logx && xm <= 0) {
6983  Error(where, "log scale requested with zero or negative argument (%f)", xm);
6984  return 0;
6985  }
6986  else xmin = xm;
6987  if (xmin >= xmax) {
6988  if (Hoption.Logx) {
6989  if (xmax > 0) xmin = 0.001*xmax;
6990  else {
6991  if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
6992  return 0;
6993  }
6994  }
6995  else {
6996  if (xmin > 0) {
6997  xmin = 0;
6998  xmax *= 2;
6999  } else if (xmin < 0) {
7000  xmax = 0;
7001  xmin *= 2;
7002  } else {
7003  xmin = -1;
7004  xmax = 1;
7005  }
7006  }
7007  }
7008 
7009  // take into account normalization factor
7010  Hparam.allchan = allchan;
7011  Double_t factor = allchan;
7012  if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
7013  if (allchan) factor /= allchan;
7014  if (factor == 0) factor = 1;
7015  Hparam.factor = factor;
7016  xmax = factor*xmax;
7017  xmin = factor*xmin;
7018 
7019  // For log scales, histogram coordinates are LOG10(ymin) and
7020  // LOG10(ymax). Final adjustment (if not option "Same"
7021  // or "+" for ymax) of ymax and ymin for logarithmic scale, if
7022  // Maximum and Minimum are not defined.
7023  if (Hoption.Logx) {
7024  if (xmin <=0 || xmax <=0) {
7025  Error(where, "Cannot set Y axis to log scale");
7026  return 0;
7027  }
7028  xmin = TMath::Log10(xmin);
7029  if (!minimum) xmin += TMath::Log10(0.5);
7030  xmax = TMath::Log10(xmax);
7031  if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
7032  if (!Hoption.Same) {
7033  Hparam.xmin = xmin;
7034  Hparam.xmax = xmax;
7035  }
7036  return 1;
7037  }
7038 
7039  // final adjustment of ymin for linear scale.
7040  // if minimum is not set , then ymin is set to zero if >0
7041  // or to ymin - margin if <0.
7042  if (!minimum) {
7043  if (xmin >= 0) xmin = 0;
7044  else xmin -= yMARGIN*(xmax-xmin);
7045  }
7046 
7047  // final adjustment of YMAXI for linear scale (if not option "Same"):
7048  // decrease histogram height to MAX% of allowed height if HMAXIM
7049  // has not been called.
7050  if (!maximum) {
7051  xmax += yMARGIN*(xmax-xmin);
7052  }
7053  Hparam.xmin = xmin;
7054  Hparam.xmax = xmax;
7055  return 1;
7056 }
7057 
7058 ////////////////////////////////////////////////////////////////////////////////
7059 /// [Control function to draw a 3D histogram with boxes.](#HP25)
7060 
7062 {
7063  // Predefined box structure
7064  Double_t wxyz[8][3] = { {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1},
7065  {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} };
7066  Int_t iface[6][4] = { {0,3,2,1}, {4,5,6,7},
7067  {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} };
7068 
7069  // Define dimensions of world space
7070  TGaxis *axis = new TGaxis();
7071  TAxis *xaxis = fH->GetXaxis();
7072  TAxis *yaxis = fH->GetYaxis();
7073  TAxis *zaxis = fH->GetZaxis();
7074 
7075  fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7076  fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7077  fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7078  fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7079  fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7080  fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7081 
7083 
7084  // Set view
7085  TView *view = gPad->GetView();
7086  if (!view) {
7087  Error("PaintH3", "no TView in current pad");
7088  return;
7089  }
7090  Double_t thedeg = 90 - gPad->GetTheta();
7091  Double_t phideg = -90 - gPad->GetPhi();
7092  Double_t psideg = view->GetPsi();
7093  Int_t irep;
7094  view->SetView(phideg, thedeg, psideg, irep);
7095 
7096  Int_t backcolor = gPad->GetFrameFillColor();
7097  view->PadRange(backcolor);
7098 
7099  // Draw back surfaces of frame box
7100  fLego->InitMoveScreen(-1.1,1.1);
7101  if (Hoption.BackBox) {
7104  fLego->BackBox(90);
7105  }
7106 
7108 
7109  // Define order of drawing
7110  Double_t *tnorm = view->GetTnorm();
7111  if (!tnorm) return;
7112  Int_t incrx = (tnorm[ 8] < 0.) ? -1 : +1;
7113  Int_t incry = (tnorm[ 9] < 0.) ? -1 : +1;
7114  Int_t incrz = (tnorm[10] < 0.) ? -1 : +1;
7115  Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7116  Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7117  Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7118  Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7119  Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7120  Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7121 
7122  // Set graphic attributes (colour, style, etc.)
7123  Style_t fillsav = fH->GetFillStyle();
7124  Style_t colsav = fH->GetFillColor();
7125  Style_t coldark = TColor::GetColorDark(colsav);
7126  Style_t colbright = TColor::GetColorBright(colsav);
7127 
7128  fH->SetFillStyle(1001);
7129  fH->TAttFill::Modify();
7130  fH->TAttLine::Modify();
7131  Int_t ncolors = gStyle->GetNumberOfColors();
7132  Int_t theColor;
7133 
7134  // Create bin boxes and draw
7135  Double_t wmin = TMath::Max(fH->GetMinimum(),0.);
7137  TMath::Abs(fH->GetMinimum()));
7138 
7139  Double_t pmin[3], pmax[3], sxyz[8][3];
7140  for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7141  pmin[0] = xaxis->GetBinLowEdge(ix);
7142  pmax[0] = xaxis->GetBinUpEdge(ix);
7143  for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7144  pmin[1] = yaxis->GetBinLowEdge(iy);
7145  pmax[1] = yaxis->GetBinUpEdge(iy);
7146  for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7147  pmin[2] = zaxis->GetBinLowEdge(iz);
7148  pmax[2] = zaxis->GetBinUpEdge(iz);
7149  Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7150  Bool_t neg = kFALSE;
7151  Int_t n = 5;
7152  if (w<0) {
7153  w = -w;
7154  neg = kTRUE;
7155  }
7156  if (w < wmin) continue;
7157  if (w > wmax) w = wmax;
7158  Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7159  if (scale == 0) continue;
7160  for (Int_t i=0; i<3; ++i) {
7161  Double_t c = (pmax[i] + pmin[i])*0.5;
7162  Double_t d = (pmax[i] - pmin[i])*scale;
7163  for (Int_t k=0; k<8; ++k) { // set bin box vertices
7164  sxyz[k][i] = wxyz[k][i]*d + c;
7165  }
7166  }
7167  for (Int_t k=0; k<8; ++k) { // transform to normalized space
7168  view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7169  }
7170  Double_t x[8], y[8]; // draw bin box faces
7171  for (Int_t k=0; k<6; ++k) {
7172  for (Int_t i=0; i<4; ++i) {
7173  Int_t iv = iface[k][i];
7174  x[i] = sxyz[iv][0];
7175  y[i] = sxyz[iv][1];
7176  }
7177  x[4] = x[0] ; y[4] = y[0];
7178  if (neg) {
7179  x[5] = x[2] ; y[5] = y[2];
7180  x[6] = x[3] ; y[6] = y[3];
7181  x[7] = x[1] ; y[7] = y[1];
7182  n = 8;
7183  } else {
7184  n = 5;
7185  }
7186  Double_t z = (x[2]-x[0])*(y[3]-y[1]) - (y[2]-y[0])*(x[3]-x[1]);
7187  if (z <= 0.) continue;
7188  if (iopt == 2) {
7189  theColor = ncolors*((w-wmin)/(wmax-wmin)) -1;
7190  fH->SetFillColor(gStyle->GetColorPalette(theColor));
7191  } else {
7192  if (k == 3 || k == 5) {
7193  fH->SetFillColor(coldark);
7194  } else if (k == 0 || k == 1) {
7195  fH->SetFillColor(colbright);
7196  } else {
7197  fH->SetFillColor(colsav);
7198  }
7199  }
7200  fH->TAttFill::Modify();
7201  gPad->PaintFillArea(4, x, y);
7202  if (iopt != 3)gPad->PaintPolyLine(n, x, y);
7203  }
7204  }
7205  }
7206  }
7207 
7208  // Draw front surfaces of frame box
7209  if (Hoption.FrontBox) fLego->FrontBox(90);
7210 
7211  // Draw axis and title
7212  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7213  PaintTitle();
7214 
7215  // Draw palette. if needed.
7216  if (Hoption.Zscale) {
7217  Int_t ndiv = fH->GetContour();
7218  if (ndiv == 0 ) {
7219  ndiv = gStyle->GetNumberContours();
7220  fH->SetContour(ndiv);
7221  }
7222  PaintPalette();
7223  }
7224 
7225  delete axis;
7226  delete fLego; fLego = 0;
7227 
7228  fH->SetFillStyle(fillsav);
7229  fH->SetFillColor(colsav);
7230  fH->TAttFill::Modify();
7231 }
7232 
7233 ////////////////////////////////////////////////////////////////////////////////
7234 /// [Control function to draw a 3D histogram with boxes.](#HP25)
7235 
7237 {
7238  // Predefined box structure
7239  Double_t wxyz[8][3] = {
7240  {-1,-1,-1}, {1,-1,-1}, {1,1,-1}, {-1,1,-1}, // bottom vertices
7241  {-1,-1, 1}, {1,-1, 1}, {1,1, 1}, {-1,1, 1} // top vertices
7242  };
7243  Int_t iface[6][4] = {
7244  {0,3,2,1}, {4,5,6,7}, // bottom and top faces
7245  {0,1,5,4}, {1,2,6,5}, {2,3,7,6}, {3,0,4,7} // side faces
7246  };
7247  Double_t normal[6][3] = {
7248  {0,0,-1}, {0,0,1}, // Z-, Z+
7249  {0,-1,0}, {1,0,0}, {0,1,0}, {-1,0,0} // Y-, X+, Y+, X-
7250  };
7251 
7252  // Define dimensions of world space
7253  TGaxis *axis = new TGaxis();
7254  TAxis *xaxis = fH->GetXaxis();
7255  TAxis *yaxis = fH->GetYaxis();
7256  TAxis *zaxis = fH->GetZaxis();
7257 
7258  fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7259  fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7260  fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7261  fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7262  fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7263  fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7264 
7266 
7267  // Set view
7268  TView *view = gPad->GetView();
7269  if (!view) {
7270  Error("PaintH3", "no TView in current pad");
7271  return;
7272  }
7273  Double_t thedeg = 90 - gPad->GetTheta();
7274  Double_t phideg = -90 - gPad->GetPhi();
7275  Double_t psideg = view->GetPsi();
7276  Int_t irep;
7277  view->SetView(phideg, thedeg, psideg, irep);
7278 
7279  Int_t backcolor = gPad->GetFrameFillColor();
7280  view->PadRange(backcolor);
7281 
7282  // Draw front surfaces of frame box
7283  if (Hoption.FrontBox) {
7284  fLego->InitMoveScreen(-1.1,1.1);
7286  }
7287 
7288  // Initialize hidden line removal algorithm "raster screen"
7289  fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7290 
7291  // Define order of drawing
7292  Double_t *tnorm = view->GetTnorm();
7293  if (!tnorm) return;
7294  Int_t incrx = (tnorm[ 8] < 0.) ? +1 : -1;
7295  Int_t incry = (tnorm[ 9] < 0.) ? +1 : -1;
7296  Int_t incrz = (tnorm[10] < 0.) ? +1 : -1;
7297  Int_t ix1 = (incrx == +1) ? xaxis->GetFirst() : xaxis->GetLast();
7298  Int_t iy1 = (incry == +1) ? yaxis->GetFirst() : yaxis->GetLast();
7299  Int_t iz1 = (incrz == +1) ? zaxis->GetFirst() : zaxis->GetLast();
7300  Int_t ix2 = (incrx == +1) ? xaxis->GetLast() : xaxis->GetFirst();
7301  Int_t iy2 = (incry == +1) ? yaxis->GetLast() : yaxis->GetFirst();
7302  Int_t iz2 = (incrz == +1) ? zaxis->GetLast() : zaxis->GetFirst();
7303 
7304  // Set line attributes (colour, style, etc.)
7305  fH->TAttLine::Modify();
7306 
7307  // Create bin boxes and draw
7308  const Int_t NTMAX = 100;
7309  Double_t tt[NTMAX][2];
7310  Double_t wmin = TMath::Max(fH->GetMinimum(),0.);
7312  TMath::Abs(fH->GetMinimum()));
7313  Double_t pmin[3], pmax[3], sxyz[8][3], pp[4][2];
7314  for (Int_t ix = ix1; ix !=ix2+incrx; ix += incrx) {
7315  pmin[0] = xaxis->GetBinLowEdge(ix);
7316  pmax[0] = xaxis->GetBinUpEdge(ix);
7317  for (Int_t iy = iy1; iy != iy2+incry; iy += incry) {
7318  pmin[1] = yaxis->GetBinLowEdge(iy);
7319  pmax[1] = yaxis->GetBinUpEdge(iy);
7320  for (Int_t iz = iz1; iz != iz2+incrz; iz += incrz) {
7321  pmin[2] = zaxis->GetBinLowEdge(iz);
7322  pmax[2] = zaxis->GetBinUpEdge(iz);
7323  Double_t w = fH->GetBinContent(fH->GetBin(ix,iy,iz));
7324  Bool_t neg = kFALSE;
7325  if (w<0) {
7326  w = -w;
7327  neg = kTRUE;
7328  }
7329  if (w < wmin) continue;
7330  if (w > wmax) w = wmax;
7331  Double_t scale = (TMath::Power((w-wmin)/(wmax-wmin),1./3.))/2.;
7332  if (scale == 0) continue;
7333  for (Int_t i=0; i<3; ++i) {
7334  Double_t c = (pmax[i] + pmin[i])*0.5;
7335  Double_t d = (pmax[i] - pmin[i])*scale;
7336  for (Int_t k=0; k<8; ++k) { // set bin box vertices
7337  sxyz[k][i] = wxyz[k][i]*d + c;
7338  }
7339  }
7340  for (Int_t k=0; k<8; ++k) { // transform to normalized space
7341  view->WCtoNDC(&sxyz[k][0],&sxyz[k][0]);
7342  }
7343  for (Int_t k=0; k<6; ++k) { // draw box faces
7344  Double_t zn;
7345  view->FindNormal(normal[k][0], normal[k][1], normal[k][2], zn);
7346  if (zn <= 0) continue;
7347  for (Int_t i=0; i<4; ++i) {
7348  Int_t ip = iface[k][i];
7349  pp[i][0] = sxyz[ip][0];
7350  pp[i][1] = sxyz[ip][1];
7351  }
7352  for (Int_t i=0; i<4; ++i) {
7353  Int_t i1 = i;
7354  Int_t i2 = (i == 3) ? 0 : i + 1;
7355  Int_t nt;
7356  fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7357  Double_t xdel = pp[i2][0] - pp[i1][0];
7358  Double_t ydel = pp[i2][1] - pp[i1][1];
7359  Double_t x[2], y[2];
7360  for (Int_t it = 0; it < nt; ++it) {
7361  x[0] = pp[i1][0] + xdel*tt[it][0];
7362  y[0] = pp[i1][1] + ydel*tt[it][0];
7363  x[1] = pp[i1][0] + xdel*tt[it][1];
7364  y[1] = pp[i1][1] + ydel*tt[it][1];
7365  gPad->PaintPolyLine(2, x, y);
7366  }
7367  }
7368  if (neg) {
7369  Int_t i1 = 0;
7370  Int_t i2 = 2;
7371  Int_t nt;
7372  fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7373  Double_t xdel = pp[i2][0] - pp[i1][0];
7374  Double_t ydel = pp[i2][1] - pp[i1][1];
7375  Double_t x[2], y[2];
7376  for (Int_t it = 0; it < nt; ++it) {
7377  x[0] = pp[i1][0] + xdel*tt[it][0];
7378  y[0] = pp[i1][1] + ydel*tt[it][0];
7379  x[1] = pp[i1][0] + xdel*tt[it][1];
7380  y[1] = pp[i1][1] + ydel*tt[it][1];
7381  gPad->PaintPolyLine(2, x, y);
7382  }
7383  i1 = 1;
7384  i2 = 3;
7385  fLego->FindVisibleLine(&pp[i1][0], &pp[i2][0], NTMAX, nt, &tt[0][0]);
7386  xdel = pp[i2][0] - pp[i1][0];
7387  ydel = pp[i2][1] - pp[i1][1];
7388  for (Int_t it = 0; it < nt; ++it) {
7389  x[0] = pp[i1][0] + xdel*tt[it][0];
7390  y[0] = pp[i1][1] + ydel*tt[it][0];
7391  x[1] = pp[i1][0] + xdel*tt[it][1];
7392  y[1] = pp[i1][1] + ydel*tt[it][1];
7393  gPad->PaintPolyLine(2, x, y);
7394  }
7395  }
7396  fLego->FillPolygonBorder(4, &pp[0][0]); // update raster screen
7397  }
7398  }
7399  }
7400  }
7401 
7402  // Draw frame box
7403  if (Hoption.BackBox) {
7406  fLego->BackBox(90);
7407  }
7408 
7409  if (Hoption.FrontBox) fLego->FrontBox(90);
7410 
7411  // Draw axis and title
7412  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7413  PaintTitle();
7414 
7415  delete axis;
7416  delete fLego; fLego = 0;
7417 }
7418 
7419 ////////////////////////////////////////////////////////////////////////////////
7420 /// [Control function to draw a 3D histogram with Iso Surfaces.](#HP25)
7421 
7423 {
7424 
7425  const Double_t ydiff = 1;
7426  const Double_t yligh1 = 10;
7427  const Double_t qa = 0.15;
7428  const Double_t qd = 0.15;
7429  const Double_t qs = 0.8;
7430  Double_t fmin, fmax;
7431  Int_t i, irep;
7432  Int_t nbcol = 28;
7433  Int_t icol1 = 201;
7434  Int_t ic1 = icol1;
7435  Int_t ic2 = ic1+nbcol;
7436  Int_t ic3 = ic2+nbcol;
7437 
7438  TGaxis *axis = new TGaxis();
7439  TAxis *xaxis = fH->GetXaxis();
7440  TAxis *yaxis = fH->GetYaxis();
7441  TAxis *zaxis = fH->GetZaxis();
7442 
7443  Int_t nx = fH->GetNbinsX();
7444  Int_t ny = fH->GetNbinsY();
7445  Int_t nz = fH->GetNbinsZ();
7446 
7447  Double_t *x = new Double_t[nx];
7448  Double_t *y = new Double_t[ny];
7449  Double_t *z = new Double_t[nz];
7450 
7451  for (i=0; i<nx; i++) x[i] = xaxis->GetBinCenter(i+1);
7452  for (i=0; i<ny; i++) y[i] = yaxis->GetBinCenter(i+1);
7453  for (i=0; i<nz; i++) z[i] = zaxis->GetBinCenter(i+1);
7454 
7455  fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
7456  fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
7457  fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
7458  fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
7459  fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
7460  fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
7461 
7462  Double_t s[3];
7463  s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
7464  s[1] = 0.5*s[0];
7465  s[2] = 1.5*s[0];
7466 
7468 
7469  TView *view = gPad->GetView();
7470  if (!view) {
7471  Error("PaintH3Iso", "no TView in current pad");
7472  delete [] x;
7473  delete [] y;
7474  delete [] z;
7475  return;
7476  }
7477  Double_t thedeg = 90 - gPad->GetTheta();
7478  Double_t phideg = -90 - gPad->GetPhi();
7479  Double_t psideg = view->GetPsi();
7480  view->SetView(phideg, thedeg, psideg, irep);
7481 
7482  Int_t backcolor = gPad->GetFrameFillColor();
7483  if (Hoption.System != kCARTESIAN) backcolor = 0;
7484  view->PadRange(backcolor);
7485 
7486  Double_t dcol = 0.5/Double_t(nbcol);
7487  TColor *colref = gROOT->GetColor(fH->GetFillColor());
7488  if (!colref) {
7489  delete [] x;
7490  delete [] y;
7491  delete [] z;
7492  return;
7493  }
7494  Float_t r, g, b, hue, light, satur;
7495  colref->GetRGB(r,g,b);
7496  TColor::RGBtoHLS(r,g,b,hue,light,satur);
7497  TColor *acol;
7498  for (Int_t col=0;col<nbcol;col++) {
7499  acol = gROOT->GetColor(col+icol1);
7500  TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
7501  if (acol) acol->SetRGB(r, g, b);
7502  }
7503 
7504  fLego->InitMoveScreen(-1.1,1.1);
7505 
7506  if (Hoption.BackBox) {
7509  fLego->BackBox(90);
7510  }
7511 
7512  fLego->LightSource(0, ydiff, 0, 0, 0, irep);
7513  fLego->LightSource(1, yligh1, 1, 1, 1, irep);
7514  fLego->SurfaceProperty(qa, qd, qs, 1, irep);
7515  fmin = ydiff*qa;
7516  fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
7517  fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
7518 
7519  fLego->IsoSurface(1, s, nx, ny, nz, x, y, z, "BF");
7520 
7521  if (Hoption.FrontBox) {
7522  fLego->InitMoveScreen(-1.1,1.1);
7524  fLego->FrontBox(90);
7525  }
7526  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7527 
7528  PaintTitle();
7529 
7530  delete axis;
7531  delete fLego; fLego = 0;
7532  delete [] x;
7533  delete [] y;
7534  delete [] z;
7535 }
7536 
7537 ////////////////////////////////////////////////////////////////////////////////
7538 /// [Control function to draw a 2D histogram as a lego plot.](#HP17)
7539 
7541 {
7542 
7543  Int_t raster = 1;
7544  if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
7545  Int_t nx = Hparam.xlast - Hparam.xfirst + 1;
7546  Int_t ny = Hparam.ylast - Hparam.yfirst + 1;
7547  Double_t zmin = Hparam.zmin;
7548  Double_t zmax = Hparam.zmax;
7549  Double_t xlab1 = Hparam.xmin;
7550  Double_t xlab2 = Hparam.xmax;
7551  Double_t ylab1 = Hparam.ymin;
7552  Double_t ylab2 = Hparam.ymax;
7553  Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
7554  Double_t deltaz = TMath::Abs(zmin);
7555  if (deltaz == 0) deltaz = 1;
7556  if (zmin >= zmax) {
7557  zmin -= 0.5*deltaz;
7558  zmax += 0.5*deltaz;
7559  }
7560  Double_t z1c = zmin;
7561  Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
7562 
7563  // Compute the lego limits and instantiate a lego object
7564  fXbuf[0] = -1;
7565  fYbuf[0] = 1;
7566  fXbuf[1] = -1;
7567  fYbuf[1] = 1;
7568  if (Hoption.System == kPOLAR) {
7569  fXbuf[2] = z1c;
7570  fYbuf[2] = z2c;
7571  } else if (Hoption.System == kCYLINDRICAL) {
7572  if (Hoption.Logy) {
7573  if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
7574  else fXbuf[2] = 0;
7575  if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
7576  else fYbuf[2] = 0;
7577  } else {
7578  fXbuf[2] = ylab1;
7579  fYbuf[2] = ylab2;
7580  }
7581  z1c = 0; z2c = 1;
7582  } else if (Hoption.System == kSPHERICAL) {
7583  fXbuf[2] = -1;
7584  fYbuf[2] = 1;
7585  z1c = 0; z2c = 1;
7586  } else if (Hoption.System == kRAPIDITY) {
7587  fXbuf[2] = -1/TMath::Tan(dangle);
7588  fYbuf[2] = 1/TMath::Tan(dangle);
7589  } else {
7590  fXbuf[0] = xlab1;
7591  fYbuf[0] = xlab2;
7592  fXbuf[1] = ylab1;
7593  fYbuf[1] = ylab2;
7594  fXbuf[2] = z1c;
7595  fYbuf[2] = z2c;
7596  raster = 0;
7597  }
7598 
7599  fLego = new TPainter3dAlgorithms(fXbuf, fYbuf, Hoption.System);
7600 
7601  Int_t nids = -1;
7602  TH1 * hid = NULL;
7603  Color_t colormain = -1, colordark = -1;
7604  Bool_t drawShadowsInLego1 = kTRUE;
7605 
7606  // LEGO3 is like LEGO1 except that the black lines around each lego are not drawn.
7607  if (Hoption.Lego == 13) {
7608  Hoption.Lego = 11;
7609  fLego->SetMesh(0);
7610  }
7611  // LEGO4 is like LEGO1 except no shadows are drawn.
7612  if (Hoption.Lego == 14) {
7613  Hoption.Lego = 11;
7614  drawShadowsInLego1 = kFALSE;
7615  }
7616 
7617  // Create axis object
7618 
7619  TGaxis *axis = new TGaxis();
7620 
7621  // Initialize the levels on the Z axis
7622  Int_t ndiv = fH->GetContour();
7623  if (ndiv == 0 ) {
7624  ndiv = gStyle->GetNumberContours();
7625  fH->SetContour(ndiv);
7626  }
7627  Int_t ndivz = TMath::Abs(ndiv);
7628  if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
7629 
7630  // Initialize colors
7631  if (!fStack) {
7633  } else {
7634  for (Int_t id=0;id<=fStack->GetSize();id++) {
7635  hid = (TH1*)fStack->At((id==0)?id:id-1);
7636  fLego->SetEdgeAtt(hid->GetLineColor(),hid->GetLineStyle(),hid->GetLineWidth(),id);
7637  }
7638  }
7639 
7640  if (Hoption.Lego == 11) {
7641  nids = 1;
7642  if (fStack) nids = fStack->GetSize();
7643  hid = fH;
7644  for (Int_t id=0;id<=nids;id++) {
7645  if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
7646  colormain = hid->GetFillColor();
7647  if (colormain == 1) colormain = 17; //avoid drawing with black
7648  if (drawShadowsInLego1) colordark = TColor::GetColorDark(colormain);
7649  else colordark = colormain;
7650  fLego->SetColorMain(colormain,id);
7651  fLego->SetColorDark(colordark,id);
7652  if (id <= 1) fLego->SetColorMain(colormain,-1); // Set Bottom color
7653  if (id == nids) fLego->SetColorMain(colormain,99); // Set Top color
7654  }
7655  }
7656 
7657  // Now ready to draw the lego plot
7658  Int_t irep = 0;
7659 
7660  TView *view = gPad->GetView();
7661  if (!view) {
7662  Error("PaintLego", "no TView in current pad");
7663  return;
7664  }
7665 
7666  Double_t thedeg = 90 - gPad->GetTheta();
7667  Double_t phideg = -90 - gPad->GetPhi();
7668  Double_t psideg = view->GetPsi();
7669  view->SetView(phideg, thedeg, psideg, irep);
7670 
7671  fLego->SetLineColor(kBlack); // zgrid color for lego1 & lego2
7673 
7674  // Set color/style for back box
7675  fLego->SetFillStyle(gPad->GetFrameFillStyle());
7676  fLego->SetFillColor(gPad->GetFrameFillColor());
7677  fLego->TAttFill::Modify();
7678 
7679  Int_t backcolor = gPad->GetFrameFillColor();
7680  if (Hoption.System != kCARTESIAN) backcolor = 0;
7681  view->PadRange(backcolor);
7682 
7685  fLego->TAttFill::Modify();
7686 
7688 
7689  if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
7690  else fLego->InitMoveScreen(-1.1,1.1);
7691 
7692  if (Hoption.Lego == 19) {
7694  if (Hoption.BackBox) fLego->BackBox(90);
7695  if (Hoption.FrontBox) fLego->FrontBox(90);
7696  if (!Hoption.Axis) PaintLegoAxis(axis, 90);
7697  return;
7698  }
7699 
7700  if (Hoption.Lego == 11 || Hoption.Lego == 12) {
7701  if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
7703  fLego->BackBox(90);
7704  }
7705  }
7706 
7707  if (Hoption.Lego == 12) DefineColorLevels(ndivz);
7708 
7713  if (Hoption.System == kPOLAR) {
7714  if (Hoption.Lego == 1) fLego->LegoPolar(1,nx,ny,"FB");
7715  if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
7716  if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
7717  } else if (Hoption.System == kCYLINDRICAL) {
7718  if (Hoption.Lego == 1) fLego->LegoCylindrical(1,nx,ny,"FB");
7719  if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
7720  if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
7721  } else if (Hoption.System == kSPHERICAL) {
7722  if (Hoption.Lego == 1) fLego->LegoSpherical(0,1,nx,ny,"FB");
7723  if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
7724  if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
7725  } else if (Hoption.System == kRAPIDITY) {
7726  if (Hoption.Lego == 1) fLego->LegoSpherical(1,1,nx,ny,"FB");
7727  if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
7728  if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
7729  } else {
7730  if (Hoption.Lego == 1) {
7732  fLego->LegoCartesian(90,nx,ny,"FB");}
7733  if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
7734  if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
7735  }
7736 
7737  if (Hoption.Lego == 1 || Hoption.Lego == 11) {
7738  if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
7740  fLego->BackBox(90);
7741  }
7742  }
7743  if (Hoption.System == kCARTESIAN) {
7744  fLego->InitMoveScreen(-1.1,1.1);
7746  if (Hoption.FrontBox) fLego->FrontBox(90);
7747  }
7748  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
7749  if (Hoption.Zscale) PaintPalette();
7750  delete axis;
7751  delete fLego; fLego = 0;
7752 }
7753 
7754 ////////////////////////////////////////////////////////////////////////////////
7755 /// Draw the axis for legos and surface plots.
7756 
7758 {
7759 
7760  static Double_t epsil = 0.001;
7761 
7762  Double_t cosa, sina;
7763  Double_t bmin, bmax;
7764  Double_t r[24] /* was [3][8] */;
7765  Int_t ndivx, ndivy, ndivz, i;
7766  Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24] /* was [3][8] */;
7767  static char chopax[8], chopay[8], chopaz[8];
7768  Int_t ix1, ix2, iy1, iy2, iz1, iz2;
7770 
7771  TView *view = gPad->GetView();
7772  if (!view) {
7773  Error("PaintLegoAxis", "no TView in current pad");
7774  return;
7775  }
7776 
7777  // In polar coordinates, draw a short line going from the external circle
7778  // corresponding to r = 1 up to r = 1.1
7779  if (Hoption.System == kPOLAR) {
7780  r[0] = 1;
7781  r[1] = 0;
7782  r[2] = 0;
7783  view->WCtoNDC(r, x1);
7784  r[0] = 1.1;
7785  r[1] = 0;
7786  r[2] = 0;
7787  view->WCtoNDC(r, x2);
7788  gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
7789  return;
7790  }
7791 
7792  if (Hoption.System != kCARTESIAN) return;
7793 
7794  rad = TMath::ATan(1.) * 4. /180.;
7795  cosa = TMath::Cos(ang*rad);
7796  sina = TMath::Sin(ang*rad);
7797 
7798  view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
7799  for (i = 1; i <= 8; ++i) {
7800  r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
7801  r[i*3 - 2] = av[i*3 - 2]*sina;
7802  r[i*3 - 1] = av[i*3 - 1];
7803  }
7804 
7805  view->WCtoNDC(&r[ix1*3 - 3], x1);
7806  view->WCtoNDC(&r[ix2*3 - 3], x2);
7807  view->WCtoNDC(&r[iy1*3 - 3], y1);
7808  view->WCtoNDC(&r[iy2*3 - 3], y2);
7809  view->WCtoNDC(&r[iz1*3 - 3], z1);
7810  view->WCtoNDC(&r[iz2*3 - 3], z2);
7811 
7812  view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
7813 
7814  Double_t *rmin = view->GetRmin();
7815  Double_t *rmax = view->GetRmax();
7816  if (!rmin || !rmax) return;
7817 
7818  // Initialize the axis options
7819  if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
7820  else strlcpy(chopax, "SDH=-",8);
7821  if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
7822  else strlcpy(chopay, "SDH=-",8);
7823  if (z2[1] > z1[1]) strlcpy(chopaz, "SDH=+",8);
7824  else strlcpy(chopaz, "SDH=-",8);
7825 
7826  // Option LOG is required ?
7827  if (Hoption.Logx) strlcat(chopax,"G",8);
7828  if (Hoption.Logy) strlcat(chopay,"G",8);
7829  if (Hoption.Logz) strlcat(chopaz,"G",8);
7830 
7831  // Initialize the number of divisions. If the
7832  // number of divisions is negative, option 'N' is required.
7833  ndivx = fXaxis->GetNdivisions();
7834  ndivy = fYaxis->GetNdivisions();
7835  ndivz = fZaxis->GetNdivisions();
7836  if (ndivx < 0) {
7837  ndivx = TMath::Abs(ndivx);
7838  strlcat(chopax, "N",8);
7839  }
7840  if (ndivy < 0) {
7841  ndivy = TMath::Abs(ndivy);
7842  strlcat(chopay, "N",8);
7843  }
7844  if (ndivz < 0) {
7845  ndivz = TMath::Abs(ndivz);
7846  strlcat(chopaz, "N",8);
7847  }
7848 
7849  // Set Axis attributes.
7850  // The variable SCALE rescales the VSIZ
7851  // in order to have the same label size for all angles.
7852 
7853  axis->SetLineWidth(1);
7854 
7855  // X axis drawing
7856  if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
7859  if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
7860  bmin = TMath::Power(10, rmin[0]);
7861  bmax = TMath::Power(10, rmax[0]);
7862  } else {
7863  bmin = rmin[0];
7864  bmax = rmax[0];
7865  }
7866  // Option time display is required ?
7867  if (fXaxis->GetTimeDisplay()) {
7868  strlcat(chopax,"t",8);
7869  if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
7870  axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
7871  } else {
7873  }
7874  }
7875  axis->SetOption(chopax);
7876  axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
7877  }
7878 
7879  // Y axis drawing
7880  if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
7883  if (fYaxis->GetTitleOffset() == 0) axis->SetTitleOffset(1.5);
7884 
7885  if (fH->GetDimension() < 2) {
7886  strlcpy(chopay, "V=+UN",8);
7887  ndivy = 0;
7888  }
7889  if (TMath::Abs(y1[0] - y2[0]) < epsil) {
7890  y2[0] = y1[0];
7891  }
7892  if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
7893  bmin = TMath::Power(10, rmin[1]);
7894  bmax = TMath::Power(10, rmax[1]);
7895  } else {
7896  bmin = rmin[1];
7897  bmax = rmax[1];
7898  }
7899  // Option time display is required ?
7900  if (fYaxis->GetTimeDisplay()) {
7901  strlcat(chopay,"t",8);
7902  if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
7903  axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
7904  } else {
7906  }
7907  }
7908  axis->SetOption(chopay);
7909  axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
7910  }
7911 
7912  // Z axis drawing
7913  if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
7915  if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
7916  bmin = TMath::Power(10, rmin[2]);
7917  bmax = TMath::Power(10, rmax[2]);
7918  } else {
7919  bmin = rmin[2];
7920  bmax = rmax[2];
7921  }
7922  // Option time display is required ?
7923  if (fZaxis->GetTimeDisplay()) {
7924  strlcat(chopaz,"t",8);
7925  if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
7926  axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
7927  } else {
7929  }
7930  }
7931  axis->SetOption(chopaz);
7932  axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
7933  }
7934 
7935  //fH->SetLineStyle(1); /// otherwise fEdgeStyle[i] gets overwritten!
7936 }
7937 
7938 ////////////////////////////////////////////////////////////////////////////////
7939 /// [Paint the color palette on the right side of the pad.](#HP22)
7940 
7942 {
7943 
7944  TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
7945  TView *view = gPad->GetView();
7946  if (palette) {
7947  if (view) {
7948  if (!palette->TestBit(TPaletteAxis::kHasView)) {
7949  fFunctions->Remove(palette);
7950  delete palette; palette = 0;
7951  }
7952  } else {
7954  fFunctions->Remove(palette);
7955  delete palette; palette = 0;
7956  }
7957  }
7958  // make sure the histogram member of the palette is setup correctly. It may not be after a Clone()
7959  if (palette && !palette->GetHistogram()) palette->SetHistogram(fH);
7960  }
7961 
7962  if (!palette) {
7963  Double_t xup = gPad->GetUxmax();
7964  Double_t x2 = gPad->PadtoX(gPad->GetX2());
7965  Double_t ymin = gPad->PadtoY(gPad->GetUymin());
7966  Double_t ymax = gPad->PadtoY(gPad->GetUymax());
7967  Double_t xr = 0.05*(gPad->GetX2() - gPad->GetX1());
7968  Double_t xmin = gPad->PadtoX(xup +0.1*xr);
7969  Double_t xmax = gPad->PadtoX(xup + xr);
7970  if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
7971  palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
7972  fFunctions->AddFirst(palette);
7973  palette->Paint();
7974  }
7975 }
7976 
7977 ////////////////////////////////////////////////////////////////////////////////
7978 /// [Control function to draw a 2D histogram as a scatter plot.](#HP11)
7979 
7981 {
7982 
7983  fH->TAttMarker::Modify();
7984 
7985  Int_t k, marker;
7986  Double_t dz, z, xk,xstep, yk, ystep;
7987  Double_t scale = 1;
7988  Bool_t ltest = kFALSE;
7989  Double_t zmax = fH->GetMaximum();
7990  Double_t zmin = fH->GetMinimum();
7991  if (zmin == 0 && zmax == 0) return;
7992  if (zmin == zmax) {
7993  zmax += 0.1*TMath::Abs(zmax);
7994  zmin -= 0.1*TMath::Abs(zmin);
7995  }
7996  Int_t ncells = (Hparam.ylast-Hparam.yfirst)*(Hparam.xlast-Hparam.xfirst);
7997  if (Hoption.Logz) {
7998  if (zmin > 0) zmin = TMath::Log10(zmin);
7999  else zmin = 0;
8000  if (zmax > 0) zmax = TMath::Log10(zmax);
8001  else zmax = 0;
8002  if (zmin == 0 && zmax == 0) return;
8003  dz = zmax - zmin;
8004  scale = 100/dz;
8005  if (ncells > 10000) scale /= 5;
8006  ltest = kTRUE;
8007  } else {
8008  dz = zmax - zmin;
8009  if (dz >= kNMAX || zmax < 1) {
8010  scale = (kNMAX-1)/dz;
8011  if (ncells > 10000) scale /= 5;
8012  ltest = kTRUE;
8013  }
8014  }
8015  if (fH->GetMinimumStored() == -1111) {
8016  Double_t yMARGIN = gStyle->GetHistTopMargin();
8017  if (gStyle->GetHistMinimumZero()) {
8018  if (zmin >= 0) zmin = 0;
8019  else zmin -= yMARGIN*(zmax-zmin);
8020  } else {
8021  Double_t dzmin = yMARGIN*(zmax-zmin);
8022  if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
8023  else zmin -= dzmin;
8024  }
8025  }
8026 
8027  TString opt = option;
8028  opt.ToLower();
8029  if (opt.Contains("scat=")) {
8030  char optscat[100];
8031  strlcpy(optscat,opt.Data(),100);
8032  char *oscat = strstr(optscat,"scat=");
8033  char *blank = strstr(oscat," "); if (blank) *blank = 0;
8034  sscanf(oscat+5,"%lg",&scale);
8035  }
8036  // use an independent instance of a random generator
8037  // instead of gRandom to avoid conflicts and
8038  // to get same random numbers when drawing the same histogram
8039  TRandom2 random;
8040  marker=0;
8041  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
8042  yk = fYaxis->GetBinLowEdge(j);
8043  ystep = fYaxis->GetBinWidth(j);
8044  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
8045  Int_t bin = j*(fXaxis->GetNbins()+2) + i;
8046  xk = fXaxis->GetBinLowEdge(i);
8047  xstep = fXaxis->GetBinWidth(i);
8048  if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
8049  z = fH->GetBinContent(bin);
8050  if (z < zmin) z = zmin;
8051  if (z > zmax) z = zmax;
8052  if (Hoption.Logz) {
8053  if (z > 0) z = TMath::Log10(z) - zmin;
8054  } else {
8055  z -= zmin;
8056  }
8057  if (z <= 0) continue;
8058  k = Int_t(z*scale);
8059  if (ltest) k++;
8060  if (k > 0) {
8061  for (Int_t loop=0; loop<k; loop++) {
8062  if (k+marker >= kNMAX) {
8063  gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
8064  marker=0;
8065  }
8066  fXbuf[marker] = (random.Rndm()*xstep) + xk;
8067  fYbuf[marker] = (random.Rndm()*ystep) + yk;
8068  if (Hoption.Logx) {
8069  if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
8070  else break;
8071  }
8072  if (Hoption.Logy) {
8073  if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
8074  else break;
8075  }
8076  if (fXbuf[marker] < gPad->GetUxmin()) break;
8077  if (fYbuf[marker] < gPad->GetUymin()) break;
8078  if (fXbuf[marker] > gPad->GetUxmax()) break;
8079  if (fYbuf[marker] > gPad->GetUymax()) break;
8080  marker++;
8081  }
8082  }
8083  }
8084  }
8085  if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
8086 
8087  if (Hoption.Zscale) PaintPalette();
8088 }
8089 
8090 ////////////////////////////////////////////////////////////////////////////////
8091 /// Static function to paint special objects like vectors and matrices.
8092 /// This function is called via `gROOT->ProcessLine` to paint these objects
8093 /// without having a direct dependency of the graphics or histogramming
8094 /// system.
8095 
8096 void THistPainter::PaintSpecialObjects(const TObject *obj, Option_t *option)
8097 {
8098 
8099  if (!obj) return;
8100  Bool_t status = TH1::AddDirectoryStatus();
8102 
8103  if (obj->InheritsFrom(TMatrixFBase::Class())) {
8104  // case TMatrixF
8105  TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
8106  R__TMatrixFBase->SetBit(kCanDelete);
8107  R__TMatrixFBase->Draw(option);
8109  } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
8110  // case TMatrixD
8111  TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
8112  R__TMatrixDBase->SetBit(kCanDelete);
8113  R__TMatrixDBase->Draw(option);
8114 
8115  } else if (obj->InheritsFrom(TVectorF::Class())) {
8116  //case TVectorF
8117  TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
8118  R__TVectorF->SetBit(kCanDelete);
8119  R__TVectorF->Draw(option);
8120 
8121  } else if (obj->InheritsFrom(TVectorD::Class())) {
8122  //case TVectorD
8123  TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
8124  R__TVectorD->SetBit(kCanDelete);
8125  R__TVectorD->Draw(option);
8126  }
8127 
8128  TH1::AddDirectory(status);
8129 }
8130 
8131 ////////////////////////////////////////////////////////////////////////////////
8132 /// [Draw the statistics box for 1D and profile histograms.](#HP07)
8133 
8134 void THistPainter::PaintStat(Int_t dostat, TF1 *fit)
8135 {
8136 
8137  static char t[100];
8138  Int_t dofit;
8139  TPaveStats *stats = 0;
8140  TIter next(fFunctions);
8141  TObject *obj;
8142  while ((obj = next())) {
8143  if (obj->InheritsFrom(TPaveStats::Class())) {
8144  stats = (TPaveStats*)obj;
8145  break;
8146  }
8147  }
8148 
8149  if (stats && dostat) {
8150  dofit = stats->GetOptFit();
8151  dostat = stats->GetOptStat();
8152  } else {
8153  dofit = gStyle->GetOptFit();
8154  }
8155  if (!dofit) fit = 0;
8156  if (dofit == 1) dofit = 111;
8157  if (dostat == 1) dostat = 1111;
8158  Int_t print_name = dostat%10;
8159  Int_t print_entries = (dostat/10)%10;
8160  Int_t print_mean = (dostat/100)%10;
8161  Int_t print_stddev = (dostat/1000)%10;
8162  Int_t print_under = (dostat/10000)%10;
8163  Int_t print_over = (dostat/100000)%10;
8164  Int_t print_integral= (dostat/1000000)%10;
8165  Int_t print_skew = (dostat/10000000)%10;
8166  Int_t print_kurt = (dostat/100000000)%10;
8167  Int_t nlines = print_name + print_entries + print_mean + print_stddev +
8168  print_under + print_over + print_integral +
8169  print_skew + print_kurt;
8170  Int_t print_fval = dofit%10;
8171  Int_t print_ferrors = (dofit/10)%10;
8172  Int_t print_fchi2 = (dofit/100)%10;
8173  Int_t print_fprob = (dofit/1000)%10;
8174  Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
8175  if (fit) {
8176  if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
8177  else nlinesf += fit->GetNpar();
8178  }
8179  if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_stddev;
8180 
8181  // Pavetext with statistics
8182  Bool_t done = kFALSE;
8183  if (!dostat && !fit) {
8184  if (stats) { fFunctions->Remove(stats); delete stats;}
8185  return;
8186  }
8187  Double_t statw = gStyle->GetStatW();
8188  if (fit) statw = 1.8*gStyle->GetStatW();
8189  Double_t stath = (nlines+nlinesf)*gStyle->GetStatFontSize();
8190  if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8191  stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
8192  }
8193  if (stats) {
8194  stats->Clear();
8195  done = kTRUE;
8196  } else {
8197  stats = new TPaveStats(
8198  gStyle->GetStatX()-statw,
8199  gStyle->GetStatY()-stath,
8200  gStyle->GetStatX(),
8201  gStyle->GetStatY(),"brNDC");
8202 
8203  stats->SetParent(fH);
8204  stats->SetOptFit(dofit);
8205  stats->SetOptStat(dostat);
8206  stats->SetFillColor(gStyle->GetStatColor());
8207  stats->SetFillStyle(gStyle->GetStatStyle());
8209  stats->SetTextFont(gStyle->GetStatFont());
8210  if (gStyle->GetStatFont()%10 > 2)
8211  stats->SetTextSize(gStyle->GetStatFontSize());
8212  stats->SetFitFormat(gStyle->GetFitFormat());
8213  stats->SetStatFormat(gStyle->GetStatFormat());
8214  stats->SetName("stats");
8215 
8217  stats->SetTextAlign(12);
8218  stats->SetBit(kCanDelete);
8219  stats->SetBit(kMustCleanup);
8220  }
8221  if (print_name) stats->AddText(fH->GetName());
8222  if (print_entries) {
8223  if (fH->GetEntries() < 1e7) snprintf(t,100,"%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
8224  else snprintf(t,100,"%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
8225  stats->AddText(t);
8226  }
8227  char textstats[50];
8228  if (print_mean) {
8229  if (print_mean == 1) {
8230  snprintf(textstats,50,"%s = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
8231  snprintf(t,100,textstats,fH->GetMean(1));
8232  } else {
8233  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
8234  ,"%",stats->GetStatFormat());
8235  snprintf(t,100,textstats,fH->GetMean(1),fH->GetMeanError(1));
8236  }
8237  stats->AddText(t);
8238  if (fH->InheritsFrom(TProfile::Class())) {
8239  if (print_mean == 1) {
8240  snprintf(textstats,50,"%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8241  snprintf(t,100,textstats,fH->GetMean(2));
8242  } else {
8243  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8244  ,"%",stats->GetStatFormat());
8245  snprintf(t,100,textstats,fH->GetMean(2),fH->GetMeanError(2));
8246  }
8247  stats->AddText(t);
8248  }
8249  }
8250  if (print_stddev) {
8251  if (print_stddev == 1) {
8252  snprintf(textstats,50,"%s = %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat());
8253  snprintf(t,100,textstats,fH->GetStdDev(1));
8254  } else {
8255  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDev.Data(),"%",stats->GetStatFormat()
8256  ,"%",stats->GetStatFormat());
8257  snprintf(t,100,textstats,fH->GetStdDev(1),fH->GetStdDevError(1));
8258  }
8259  stats->AddText(t);
8260  if (fH->InheritsFrom(TProfile::Class())) {
8261  if (print_stddev == 1) {
8262  snprintf(textstats,50,"%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8263  snprintf(t,100,textstats,fH->GetStdDev(2));
8264  } else {
8265  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8266  ,"%",stats->GetStatFormat());
8267  snprintf(t,100,textstats,fH->GetStdDev(2),fH->GetStdDevError(2));
8268  }
8269  stats->AddText(t);
8270  }
8271  }
8272  if (print_under) {
8273  snprintf(textstats,50,"%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
8274  snprintf(t,100,textstats,fH->GetBinContent(0));
8275  stats->AddText(t);
8276  }
8277  if (print_over) {
8278  snprintf(textstats,50,"%s = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
8279  snprintf(t,100,textstats,fH->GetBinContent(fXaxis->GetNbins()+1));
8280  stats->AddText(t);
8281  }
8282  if (print_integral) {
8283  if (print_integral == 1) {
8284  snprintf(textstats,50,"%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8285  snprintf(t,100,textstats,fH->Integral());
8286  } else {
8287  snprintf(textstats,50,"%s = %s%s",gStringIntegralBinWidth.Data(),"%",stats->GetStatFormat());
8288  snprintf(t,100,textstats,fH->Integral("width"));
8289  }
8290  stats->AddText(t);
8291  }
8292  if (print_skew) {
8293  if (print_skew == 1) {
8294  snprintf(textstats,50,"%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
8295  snprintf(t,100,textstats,fH->GetSkewness(1));
8296  } else {
8297  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
8298  ,"%",stats->GetStatFormat());
8299  snprintf(t,100,textstats,fH->GetSkewness(1),fH->GetSkewness(11));
8300  }
8301  stats->AddText(t);
8302  }
8303  if (print_kurt) {
8304  if (print_kurt == 1) {
8305  snprintf(textstats,50,"%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
8306  snprintf(t,100,textstats,fH->GetKurtosis(1));
8307  } else {
8308  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
8309  ,"%",stats->GetStatFormat());
8310  snprintf(t,100,textstats,fH->GetKurtosis(1),fH->GetKurtosis(11));
8311  }
8312  stats->AddText(t);
8313  }
8314 
8315  // Draw Fit parameters
8316  if (fit) {
8317  Int_t ndf = fit->GetNDF();
8318  snprintf(textstats,50,"#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
8319  snprintf(t,100,textstats,(Float_t)fit->GetChisquare());
8320  if (print_fchi2) stats->AddText(t);
8321  if (print_fprob) {
8322  snprintf(textstats,50,"Prob = %s%s","%",stats->GetFitFormat());
8323  snprintf(t,100,textstats,(Float_t)TMath::Prob(fit->GetChisquare(),ndf));
8324  stats->AddText(t);
8325  }
8326  if (print_fval || print_ferrors) {
8327  Double_t parmin,parmax;
8328  Int_t a;
8329  for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8330  fit->GetParLimits(ipar,parmin,parmax);
8331  if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
8332  snprintf(t,100,"%-8s ",fit->GetParName(ipar));
8333  a = strlen(t);
8334  if (a>50) a = 50;
8335  if (print_ferrors) {
8336  snprintf(textstats,50,"= %s%s #pm %s ", "%",stats->GetFitFormat(),
8337  GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
8338  snprintf(&t[a],100-a,textstats,(Float_t)fit->GetParameter(ipar)
8339  ,(Float_t)fit->GetParError(ipar));
8340  } else {
8341  snprintf(textstats,50,"= %s%s ","%",stats->GetFitFormat());
8342  snprintf(&t[a],100-a,textstats,(Float_t)fit->GetParameter(ipar));
8343  }
8344  t[63] = 0;
8345  stats->AddText(t);
8346  }
8347  }
8348  }
8349 
8350  if (!done) fFunctions->Add(stats);
8351  stats->Paint();
8352 }
8353 
8354 ////////////////////////////////////////////////////////////////////////////////
8355 /// [Draw the statistics box for 2D histograms.](#HP07)
8356 
8357 void THistPainter::PaintStat2(Int_t dostat, TF1 *fit)
8358 {
8359 
8360  if (fH->GetDimension() != 2) return;
8361  TH2 *h2 = (TH2*)fH;
8362 
8363  static char t[100];
8364  Int_t dofit;
8365  TPaveStats *stats = 0;
8366  TIter next(fFunctions);
8367  TObject *obj;
8368  while ((obj = next())) {
8370  stats = (TPaveStats*)obj;
8371  break;
8372  }
8373  }
8374  if (stats && dostat) {
8375  dofit = stats->GetOptFit();
8376  dostat = stats->GetOptStat();
8377  } else {
8378  dofit = gStyle->GetOptFit();
8379  }
8380  if (dostat == 1) dostat = 1111;
8381  Int_t print_name = dostat%10;
8382  Int_t print_entries = (dostat/10)%10;
8383  Int_t print_mean = (dostat/100)%10;
8384  Int_t print_stddev = (dostat/1000)%10;
8385  Int_t print_under = (dostat/10000)%10;
8386  Int_t print_over = (dostat/100000)%10;
8387  Int_t print_integral= (dostat/1000000)%10;
8388  Int_t print_skew = (dostat/10000000)%10;
8389  Int_t print_kurt = (dostat/100000000)%10;
8390  Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_stddev + print_integral;
8391  if (print_under || print_over) nlines += 3;
8392 
8393  // Pavetext with statistics
8394  if (!gStyle->GetOptFit()) fit = 0;
8395  Bool_t done = kFALSE;
8396  if (!dostat && !fit) {
8397  if (stats) { fFunctions->Remove(stats); delete stats;}
8398  return;
8399  }
8400  Double_t statw = gStyle->GetStatW();
8401  if (fit) statw = 1.8*gStyle->GetStatW();
8402  Double_t stath = nlines*gStyle->GetStatFontSize();
8403  if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8404  stath = 0.25*nlines*gStyle->GetStatH();
8405  }
8406  if (fit) stath += gStyle->GetStatH();
8407  if (stats) {
8408  stats->Clear();
8409  done = kTRUE;
8410  } else {
8411  stats = new TPaveStats(
8412  gStyle->GetStatX()-statw,
8413  gStyle->GetStatY()-stath,
8414  gStyle->GetStatX(),
8415  gStyle->GetStatY(),"brNDC");
8416 
8417  stats->SetParent(fH);
8418  stats->SetOptFit(dofit);
8419  stats->SetOptStat(dostat);
8420  stats->SetFillColor(gStyle->GetStatColor());
8421  stats->SetFillStyle(gStyle->GetStatStyle());
8423  stats->SetName("stats");
8424 
8426  stats->SetTextAlign(12);
8427  stats->SetTextFont(gStyle->GetStatFont());
8428  if (gStyle->GetStatFont()%10 > 2)
8429  stats->SetTextSize(gStyle->GetStatFontSize());
8430  stats->SetFitFormat(gStyle->GetFitFormat());
8431  stats->SetStatFormat(gStyle->GetStatFormat());
8432  stats->SetBit(kCanDelete);
8433  stats->SetBit(kMustCleanup);
8434  }
8435  if (print_name) stats->AddText(h2->GetName());
8436  if (print_entries) {
8437  if (h2->GetEntries() < 1e7) snprintf(t,100,"%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
8438  else snprintf(t,100,"%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
8439  stats->AddText(t);
8440  }
8441  char textstats[50];
8442  if (print_mean) {
8443  if (print_mean == 1) {
8444  snprintf(textstats,50,"%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8445  snprintf(t,50,textstats,h2->GetMean(1));
8446  stats->AddText(t);
8447  snprintf(textstats,50,"%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8448  snprintf(t,100,textstats,h2->GetMean(2));
8449  stats->AddText(t);
8450  } else {
8451  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8452  ,"%",stats->GetStatFormat());
8453  snprintf(t,100,textstats,h2->GetMean(1),h2->GetMeanError(1));
8454  stats->AddText(t);
8455  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8456  ,"%",stats->GetStatFormat());
8457  snprintf(t,100,textstats,h2->GetMean(2),h2->GetMeanError(2));
8458  stats->AddText(t);
8459  }
8460  }
8461  if (print_stddev) {
8462  if (print_stddev == 1) {
8463  snprintf(textstats,50,"%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8464  snprintf(t,100,textstats,h2->GetStdDev(1));
8465  stats->AddText(t);
8466  snprintf(textstats,50,"%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8467  snprintf(t,100,textstats,h2->GetStdDev(2));
8468  stats->AddText(t);
8469  } else {
8470  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8471  ,"%",stats->GetStatFormat());
8472  snprintf(t,100,textstats,h2->GetStdDev(1),h2->GetStdDevError(1));
8473  stats->AddText(t);
8474  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8475  ,"%",stats->GetStatFormat());
8476  snprintf(t,100,textstats,h2->GetStdDev(2),h2->GetStdDevError(2));
8477  stats->AddText(t);
8478  }
8479  }
8480  if (print_integral) {
8481  snprintf(textstats,50,"%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
8482  snprintf(t,100,textstats,fH->Integral());
8483  stats->AddText(t);
8484  }
8485  if (print_skew) {
8486  if (print_skew == 1) {
8487  snprintf(textstats,50,"%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8488  snprintf(t,100,textstats,h2->GetSkewness(1));
8489  stats->AddText(t);
8490  snprintf(textstats,50,"%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8491  snprintf(t,100,textstats,h2->GetSkewness(2));
8492  stats->AddText(t);
8493  } else {
8494  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8495  ,"%",stats->GetStatFormat());
8496  snprintf(t,100,textstats,h2->GetSkewness(1),h2->GetSkewness(11));
8497  stats->AddText(t);
8498  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8499  ,"%",stats->GetStatFormat());
8500  snprintf(t,100,textstats,h2->GetSkewness(2),h2->GetSkewness(12));
8501  stats->AddText(t);
8502  }
8503  }
8504  if (print_kurt) {
8505  if (print_kurt == 1) {
8506  snprintf(textstats,50,"%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8507  snprintf(t,100,textstats,h2->GetKurtosis(1));
8508  stats->AddText(t);
8509  snprintf(textstats,50,"%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8510  snprintf(t,100,textstats,h2->GetKurtosis(2));
8511  stats->AddText(t);
8512  } else {
8513  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8514  ,"%",stats->GetStatFormat());
8515  snprintf(t,100,textstats,h2->GetKurtosis(1),h2->GetKurtosis(11));
8516  stats->AddText(t);
8517  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8518  ,"%",stats->GetStatFormat());
8519  snprintf(t,100,textstats,h2->GetKurtosis(2),h2->GetKurtosis(12));
8520  stats->AddText(t);
8521  }
8522  }
8523  if (print_under || print_over) {
8524  //get 3*3 under/overflows for 2d hist
8525  Double_t unov[9];
8526 
8527  Int_t cellsX = h2->GetXaxis()->GetNbins() + 1;
8528  Int_t cellsY = h2->GetYaxis()->GetNbins() + 1;
8529  Int_t firstX = std::max(1, h2->GetXaxis()->GetFirst());
8530  Int_t firstY = std::max(1, h2->GetYaxis()->GetFirst());
8531  Int_t lastX = std::min(h2->GetXaxis()->GetLast(), h2->GetXaxis()->GetNbins());
8532  Int_t lastY = std::min(h2->GetYaxis()->GetLast(), h2->GetYaxis()->GetNbins());
8533 
8534  unov[0] = h2->Integral( 0, firstX-1, lastY+1, cellsY );
8535  unov[1] = h2->Integral(firstX , lastX , lastY+1, cellsY );
8536  unov[2] = h2->Integral(lastX+1, cellsX , lastY+1, cellsY );
8537  unov[3] = h2->Integral( 0, firstX-1, firstY , lastY );
8538  unov[4] = h2->Integral(firstX , lastX , firstY , lastY );
8539  unov[5] = h2->Integral(lastX+1, cellsX , firstY , lastY );
8540  unov[6] = h2->Integral( 0, firstX-1, 0, firstY-1);
8541  unov[7] = h2->Integral(firstX, lastX, 0, firstY-1);
8542  unov[8] = h2->Integral(lastX+1, cellsX , 0, firstY-1);
8543 
8544  snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[0], (Int_t)unov[1], (Int_t)unov[2]);
8545  stats->AddText(t);
8546  if (h2->GetEntries() < 1e7)
8547  snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[3], (Int_t)unov[4], (Int_t)unov[5]);
8548  else
8549  snprintf(t, 100," %7d|%14.7g|%7d\n", (Int_t)unov[3], (Float_t)unov[4], (Int_t)unov[5]);
8550  stats->AddText(t);
8551  snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[6], (Int_t)unov[7], (Int_t)unov[8]);
8552  stats->AddText(t);
8553  }
8554 
8555  // Draw Fit parameters
8556  if (fit) {
8557  Int_t ndf = fit->GetNDF();
8558  snprintf(t,100,"#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
8559  stats->AddText(t);
8560  for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8561  snprintf(t,100,"%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
8562  ,(Float_t)fit->GetParameter(ipar)
8563  ,(Float_t)fit->GetParError(ipar));
8564  t[63] = 0;
8565  stats->AddText(t);
8566  }
8567  }
8568 
8569  if (!done) fFunctions->Add(stats);
8570  stats->Paint();
8571 }
8572 
8573 ////////////////////////////////////////////////////////////////////////////////
8574 /// [Draw the statistics box for 3D histograms.](#HP07)
8575 
8576 void THistPainter::PaintStat3(Int_t dostat, TF1 *fit)
8577 {
8578 
8579  if (fH->GetDimension() != 3) return;
8580  TH3 *h3 = (TH3*)fH;
8581 
8582  static char t[100];
8583  Int_t dofit;
8584  TPaveStats *stats = 0;
8585  TIter next(fFunctions);
8586  TObject *obj;
8587  while ((obj = next())) {
8589  stats = (TPaveStats*)obj;
8590  break;
8591  }
8592  }
8593  if (stats && dostat) {
8594  dofit = stats->GetOptFit();
8595  dostat = stats->GetOptStat();
8596  } else {
8597  dofit = gStyle->GetOptFit();
8598  }
8599  if (dostat == 1) dostat = 1111;
8600  Int_t print_name = dostat%10;
8601  Int_t print_entries = (dostat/10)%10;
8602  Int_t print_mean = (dostat/100)%10;
8603  Int_t print_stddev = (dostat/1000)%10;
8604  Int_t print_under = (dostat/10000)%10;
8605  Int_t print_over = (dostat/100000)%10;
8606  Int_t print_integral= (dostat/1000000)%10;
8607  Int_t print_skew = (dostat/10000000)%10;
8608  Int_t print_kurt = (dostat/100000000)%10;
8609  Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_stddev + print_integral;
8610  if (print_under || print_over) nlines += 3;
8611 
8612  // Pavetext with statistics
8613  if (!gStyle->GetOptFit()) fit = 0;
8614  Bool_t done = kFALSE;
8615  if (!dostat && !fit) {
8616  if (stats) { fFunctions->Remove(stats); delete stats;}
8617  return;
8618  }
8619  Double_t statw = gStyle->GetStatW();
8620  if (fit) statw = 1.8*gStyle->GetStatW();
8621  Double_t stath = nlines*gStyle->GetStatFontSize();
8622  if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
8623  stath = 0.25*nlines*gStyle->GetStatH();
8624  }
8625  if (fit) stath += gStyle->GetStatH();
8626  if (stats) {
8627  stats->Clear();
8628  done = kTRUE;
8629  } else {
8630  stats = new TPaveStats(
8631  gStyle->GetStatX()-statw,
8632  gStyle->GetStatY()-stath,
8633  gStyle->GetStatX(),
8634  gStyle->GetStatY(),"brNDC");
8635 
8636  stats->SetParent(fH);
8637  stats->SetOptFit(dofit);
8638  stats->SetOptStat(dostat);
8639  stats->SetFillColor(gStyle->GetStatColor());
8640  stats->SetFillStyle(gStyle->GetStatStyle());
8642  stats->SetName("stats");
8643 
8645  stats->SetTextAlign(12);
8646  stats->SetTextFont(gStyle->GetStatFont());
8647  stats->SetFitFormat(gStyle->GetFitFormat());
8648  stats->SetStatFormat(gStyle->GetStatFormat());
8649  stats->SetBit(kCanDelete);
8650  stats->SetBit(kMustCleanup);
8651  }
8652  if (print_name) stats->AddText(h3->GetName());
8653  if (print_entries) {
8654  if (h3->GetEntries() < 1e7) snprintf(t,100,"%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
8655  else snprintf(t,100,"%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
8656  stats->AddText(t);
8657  }
8658  char textstats[50];
8659  if (print_mean) {
8660  if (print_mean == 1) {
8661  snprintf(textstats,50,"%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
8662  snprintf(t,100,textstats,h3->GetMean(1));
8663  stats->AddText(t);
8664  snprintf(textstats,50,"%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
8665  snprintf(t,100,textstats,h3->GetMean(2));
8666  stats->AddText(t);
8667  snprintf(textstats,50,"%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
8668  snprintf(t,100,textstats,h3->GetMean(3));
8669  stats->AddText(t);
8670  } else {
8671  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
8672  ,"%",stats->GetStatFormat());
8673  snprintf(t,100,textstats,h3->GetMean(1),h3->GetMeanError(1));
8674  stats->AddText(t);
8675  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
8676  ,"%",stats->GetStatFormat());
8677  snprintf(t,100,textstats,h3->GetMean(2),h3->GetMeanError(2));
8678  stats->AddText(t);
8679  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
8680  ,"%",stats->GetStatFormat());
8681  snprintf(t,100,textstats,h3->GetMean(3),h3->GetMeanError(3));
8682  stats->AddText(t);
8683  }
8684  }
8685  if (print_stddev) {
8686  if (print_stddev == 1) {
8687  snprintf(textstats,50,"%s = %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat());
8688  snprintf(t,100,textstats,h3->GetStdDev(1));
8689  stats->AddText(t);
8690  snprintf(textstats,50,"%s = %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat());
8691  snprintf(t,100,textstats,h3->GetStdDev(2));
8692  stats->AddText(t);
8693  snprintf(textstats,50,"%s = %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat());
8694  snprintf(t,100,textstats,h3->GetStdDev(3));
8695  stats->AddText(t);
8696  } else {
8697  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDevX.Data(),"%",stats->GetStatFormat()
8698  ,"%",stats->GetStatFormat());
8699  snprintf(t,100,textstats,h3->GetStdDev(1),h3->GetStdDevError(1));
8700  stats->AddText(t);
8701  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDevY.Data(),"%",stats->GetStatFormat()
8702  ,"%",stats->GetStatFormat());
8703  snprintf(t,100,textstats,h3->GetStdDev(2),h3->GetStdDevError(2));
8704  stats->AddText(t);
8705  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringStdDevZ.Data(),"%",stats->GetStatFormat()
8706  ,"%",stats->GetStatFormat());
8707  snprintf(t,100,textstats,h3->GetStdDev(3),h3->GetStdDevError(3));
8708  stats->AddText(t);
8709  }
8710  }
8711  if (print_integral) {
8712  snprintf(t,100,"%s = %6.4g",gStringIntegral.Data(),h3->Integral());
8713  stats->AddText(t);
8714  }
8715  if (print_skew) {
8716  if (print_skew == 1) {
8717  snprintf(textstats,50,"%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
8718  snprintf(t,100,textstats,h3->GetSkewness(1));
8719  stats->AddText(t);
8720  snprintf(textstats,50,"%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
8721  snprintf(t,100,textstats,h3->GetSkewness(2));
8722  stats->AddText(t);
8723  snprintf(textstats,50,"%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
8724  snprintf(t,100,textstats,h3->GetSkewness(3));
8725  stats->AddText(t);
8726  } else {
8727  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
8728  ,"%",stats->GetStatFormat());
8729  snprintf(t,100,textstats,h3->GetSkewness(1),h3->GetSkewness(11));
8730  stats->AddText(t);
8731  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
8732  ,"%",stats->GetStatFormat());
8733  snprintf(t,100,textstats,h3->GetSkewness(2),h3->GetSkewness(12));
8734  stats->AddText(t);
8735  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
8736  ,"%",stats->GetStatFormat());
8737  snprintf(t,100,textstats,h3->GetSkewness(3),h3->GetSkewness(13));
8738  stats->AddText(t);
8739  }
8740  }
8741  if (print_kurt) {
8742  if (print_kurt == 1) {
8743  snprintf(textstats,50,"%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
8744  snprintf(t,100,textstats,h3->GetKurtosis(1));
8745  stats->AddText(t);
8746  snprintf(textstats,50,"%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
8747  snprintf(t,100,textstats,h3->GetKurtosis(2));
8748  stats->AddText(t);
8749  snprintf(textstats,50,"%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
8750  snprintf(t,100,textstats,h3->GetKurtosis(3));
8751  stats->AddText(t);
8752  } else {
8753  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
8754  ,"%",stats->GetStatFormat());
8755  snprintf(t,100,textstats,h3->GetKurtosis(1),h3->GetKurtosis(11));
8756  stats->AddText(t);
8757  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
8758  ,"%",stats->GetStatFormat());
8759  snprintf(t,100,textstats,h3->GetKurtosis(2),h3->GetKurtosis(12));
8760  stats->AddText(t);
8761  snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
8762  ,"%",stats->GetStatFormat());
8763  snprintf(t,100,textstats,h3->GetKurtosis(3),h3->GetKurtosis(13));
8764  stats->AddText(t);
8765  }
8766  }
8767  if (print_under || print_over) {
8768  // no underflow - overflow printing for a 3D histogram
8769  // one would need a 3D table
8770  }
8771 
8772  // Draw Fit parameters
8773  if (fit) {
8774  Int_t ndf = fit->GetNDF();
8775  snprintf(t,100,"#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
8776  stats->AddText(t);
8777  for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
8778  snprintf(t,100,"%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
8779  ,(Float_t)fit->GetParameter(ipar)
8780  ,(Float_t)fit->GetParError(ipar));
8781  t[32] = 0;
8782  stats->AddText(t);
8783  }
8784  }
8785 
8786  if (!done) fFunctions->Add(stats);
8787  stats->Paint();
8788 }
8789 
8790 ////////////////////////////////////////////////////////////////////////////////
8791 /// [Control function to draw a 2D histogram as a surface plot.](#HP18)
8792 
8794 {
8795 
8796  const Double_t ydiff = 1;
8797  const Double_t yligh1 = 10;
8798  const Double_t qa = 0.15;
8799  const Double_t qd = 0.15;
8800  const Double_t qs = 0.8;
8801  Double_t fmin, fmax;
8802  Int_t raster = 0;
8803  Int_t irep = 0;
8804 
8805  if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
8806  Int_t nx = Hparam.xlast - Hparam.xfirst;
8807  Int_t ny = Hparam.ylast - Hparam.yfirst;
8808  Double_t zmin = Hparam.zmin;
8809  Double_t zmax = Hparam.zmax;
8810  Double_t xlab1 = Hparam.xmin;
8811  Double_t xlab2 = Hparam.xmax;
8812  Double_t ylab1 = Hparam.ymin;
8813  Double_t ylab2 = Hparam.ymax;
8814  Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
8815  Double_t deltaz = TMath::Abs(zmin);
8816  if (deltaz == 0) deltaz = 1;
8817  if (zmin >= zmax) {
8818  zmin -= 0.5*deltaz;
8819  zmax += 0.5*deltaz;
8820  }
8821  Double_t z1c = zmin;
8822  Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
8823  // Compute the lego limits and instantiate a lego object
8824  fXbuf[0] = -1;
8825  fYbuf[0] = 1;
8826  fXbuf[1] = -1;
8827  fYbuf[1] = 1;
8828  if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
8829  if (Hoption.System == kPOLAR) {
8830  fXbuf[2] = z1c;
8831  fYbuf[2] = z2c;
8832  } else if (Hoption.System == kCYLINDRICAL) {
8833  if (Hoption.Logy) {
8834  if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
8835  else fXbuf[2] = 0;
8836  if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
8837  else fYbuf[2] = 0;
8838  } else {
8839  fXbuf[2] = ylab1;
8840  fYbuf[2] = ylab2;
8841  }
8842  z1c = 0; z2c = 1;
8843  } else if (Hoption.System == kSPHERICAL) {
8844  fXbuf[2] = -1;
8845  fYbuf[2] = 1;
8846  z1c = 0; z2c = 1;
8847  } else if (Hoption.System == kRAPIDITY) {
8848  fXbuf[2] = -1/TMath::Tan(dangle);
8849  fYbuf[2] = 1/TMath::Tan(dangle);
8850  } else {
8851  fXbuf[0] = xlab1;
8852  fYbuf[0] = xlab2;
8853  fXbuf[1] = ylab1;
8854  fYbuf[1] = ylab2;
8855  fXbuf[2] = z1c;
8856  fYbuf[2] = z2c;
8857  }
8858 
8859  fLego = new TPainter3dAlgorithms(fXbuf, fYbuf, Hoption.System);
8862 
8863  // Create axis object
8864 
8865  TGaxis *axis = new TGaxis();
8866 
8867  // Initialize the levels on the Z axis
8868  Int_t ndiv = fH->GetContour();
8869  if (ndiv == 0 ) {
8870  ndiv = gStyle->GetNumberContours();
8871  fH->SetContour(ndiv);
8872  }
8873  Int_t ndivz = TMath::Abs(ndiv);
8874  if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
8875 
8876  if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
8877  if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
8878 
8879  // Close the surface in case of non cartesian coordinates.
8880 
8881  if (Hoption.System != kCARTESIAN) {nx++; ny++;}
8882 
8883  // Now ready to draw the surface plot
8884 
8885  TView *view = gPad->GetView();
8886  if (!view) {
8887  Error("PaintSurface", "no TView in current pad");
8888  return;
8889  }
8890 
8891  Double_t thedeg = 90 - gPad->GetTheta();
8892  Double_t phideg = -90 - gPad->GetPhi();
8893  Double_t psideg = view->GetPsi();
8894  view->SetView(phideg, thedeg, psideg, irep);
8895 
8896  // Set color/style for back box
8897  if (Hoption.Same) {
8898  fLego->SetFillStyle(0);
8899  fLego->SetFillColor(1);
8900  } else {
8901  fLego->SetFillStyle(gPad->GetFrameFillStyle());
8902  fLego->SetFillColor(gPad->GetFrameFillColor());
8903  }
8904  fLego->TAttFill::Modify();
8905 
8906  Int_t backcolor = gPad->GetFrameFillColor();
8907  if (Hoption.System != kCARTESIAN) backcolor = 0;
8908  view->PadRange(backcolor);
8909 
8912  fLego->TAttFill::Modify();
8913 
8914  // Draw the filled contour on top
8915  Int_t icol1 = fH->GetFillColor();
8916 
8917  Int_t hoption35 = Hoption.Surf;
8918  if (Hoption.Surf == 13 || Hoption.Surf == 15) {
8919  DefineColorLevels(ndivz);
8920  Hoption.Surf = 23;
8923  if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
8924  if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
8925  if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
8926  if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
8927  if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
8928  Hoption.Surf = hoption35;
8929  fLego->SetMesh(1);
8930  }
8931 
8932  if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
8933  else fLego->InitMoveScreen(-1.1,1.1);
8934 
8935  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
8937  if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
8939  fLego->BackBox(90);
8940  }
8941  }
8942 
8943  // Gouraud Shading surface
8944  if (Hoption.Surf == 14) {
8945  // Set light sources
8946  fLego->LightSource(0, ydiff, 0,0,0,irep);
8947  fLego->LightSource(1, yligh1 ,1,1,1,irep);
8948  fLego->SurfaceProperty(qa, qd, qs, 1, irep);
8949  fmin = ydiff*qa;
8950  fmax = fmin + (yligh1+0.1)*(qd+qs);
8951  Int_t nbcol = 28;
8952  icol1 = 201;
8953  Double_t dcol = 0.5/Double_t(nbcol);
8954  TColor *colref = gROOT->GetColor(fH->GetFillColor());
8955  if (!colref) return;
8956  Float_t r,g,b,hue,light,satur;
8957  colref->GetRGB(r,g,b);
8958  TColor::RGBtoHLS(r,g,b,hue,light,satur);
8959  TColor *acol;
8960  for (Int_t col=0;col<nbcol;col++) {
8961  acol = gROOT->GetColor(col+icol1);
8962  TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
8963  if (acol) acol->SetRGB(r,g,b);
8964  }
8965  fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
8968  if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"BF");
8969  if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
8970  if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
8971  if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
8972  if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"BF");
8973  } else if (Hoption.Surf == 15) {
8974  // The surface is not drawn in this case.
8975  } else {
8976  // Draw the surface
8977  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
8978  DefineColorLevels(ndivz);
8979  } else {
8981  }
8983  if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
8984  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
8985  if (Hoption.System == kPOLAR) {
8986  if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
8987  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
8988  } else if (Hoption.System == kCYLINDRICAL) {
8989  if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
8990  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
8991  } else if (Hoption.System == kSPHERICAL) {
8992  if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
8993  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
8994  } else if (Hoption.System == kRAPIDITY) {
8995  if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
8996  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
8997  } else {
8998  if (Hoption.Surf == 1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
9000  if (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
9001  if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
9002  }
9003  }
9004 
9005  // Paint the line contour on top for option SURF7
9006  if (Hoption.Surf == 17) {
9007  fLego->InitMoveScreen(-1.1,1.1);
9009  Hoption.Surf = 23;
9012  if (Hoption.System == kPOLAR) fLego->SurfacePolar(1,nx,ny,"FB");
9013  if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
9014  if (Hoption.System == kSPHERICAL) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
9015  if (Hoption.System == kRAPIDITY ) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
9016  if (Hoption.System == kCARTESIAN) fLego->SurfaceCartesian(90,nx,ny,"FB");
9017  }
9018 
9019  if ((!Hoption.Same) &&
9020  (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
9021  if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
9023  fLego->BackBox(90);
9024  }
9025  }
9026  if (Hoption.System == kCARTESIAN) {
9027  fLego->InitMoveScreen(-1.1,1.1);
9029  if (Hoption.FrontBox) fLego->FrontBox(90);
9030  }
9031  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
9032 
9033  if (Hoption.Zscale) PaintPalette();
9034 
9035  delete axis;
9036  delete fLego; fLego = 0;
9037 }
9038 
9039 ////////////////////////////////////////////////////////////////////////////////
9040 /// Control function to draw a table using Delaunay triangles.
9041 
9043 {
9044 
9045  TGraphDelaunay2D *dt = nullptr;
9046  TGraphDelaunay *dtOld = nullptr;
9047 
9048  // Check if fH contains a TGraphDelaunay2D
9049  TList *hl = fH->GetListOfFunctions();
9050  dt = (TGraphDelaunay2D*)hl->FindObject("TGraphDelaunay2D");
9051  if (!dt) dtOld = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
9052  if (!dt && !dtOld) return;
9053 
9054  // If needed, create a TGraph2DPainter
9055  if (!fGraph2DPainter) {
9056  if (dt) fGraph2DPainter = new TGraph2DPainter(dt);
9057  else fGraph2DPainter = new TGraph2DPainter(dtOld);
9058  }
9059 
9060  // Define the 3D view
9061  if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
9062  if (Hoption.Same) {
9063  TView *viewsame = gPad->GetView();
9064  if (!viewsame) {
9065  Error("PaintTriangles", "no TView in current pad, do not use option SAME");
9066  return;
9067  }
9068  Double_t *rmin = viewsame->GetRmin();
9069  Double_t *rmax = viewsame->GetRmax();
9070  if (!rmin || !rmax) return;
9071  fXbuf[0] = rmin[0];
9072  fYbuf[0] = rmax[0];
9073  fXbuf[1] = rmin[1];
9074  fYbuf[1] = rmax[1];
9075  fXbuf[2] = rmin[2];
9076  fYbuf[2] = rmax[2];
9077  } else {
9078  fXbuf[0] = Hparam.xmin;
9079  fYbuf[0] = Hparam.xmax;
9080  fXbuf[1] = Hparam.ymin;
9081  fYbuf[1] = Hparam.ymax;
9082  fXbuf[2] = Hparam.zmin;
9083  fYbuf[2] = Hparam.zmax;
9084  }
9085 
9086  fLego = new TPainter3dAlgorithms(fXbuf, fYbuf);
9087  TView *view = gPad->GetView();
9088  if (!view) {
9089  Error("PaintTriangles", "no TView in current pad");
9090  return;
9091  }
9092  Double_t thedeg = 90 - gPad->GetTheta();
9093  Double_t phideg = -90 - gPad->GetPhi();
9094  Double_t psideg = view->GetPsi();
9095  Int_t irep;
9096  view->SetView(phideg, thedeg, psideg, irep);
9097 
9098  // Set color/style for back box
9099  fLego->SetFillStyle(gPad->GetFrameFillStyle());
9100  fLego->SetFillColor(gPad->GetFrameFillColor());
9101  fLego->TAttFill::Modify();
9102  Int_t backcolor = gPad->GetFrameFillColor();
9103  if (Hoption.System != kCARTESIAN) backcolor = 0;
9104  view->PadRange(backcolor);
9107  fLego->TAttFill::Modify();
9108 
9109  // Paint the Back Box if needed
9110  if (Hoption.BackBox && !Hoption.Same) {
9111  fLego->InitMoveScreen(-1.1,1.1);
9114  fLego->BackBox(90);
9115  }
9116 
9117  // Paint the triangles
9118  fGraph2DPainter->Paint(option);
9119 
9120  // Paint the Front Box if needed
9121  if (Hoption.FrontBox) {
9122  fLego->InitMoveScreen(-1.1,1.1);
9124  fLego->FrontBox(90);
9125  }
9126 
9127  // Paint the Axis if needed
9128  if (!Hoption.Axis && !Hoption.Same) {
9129  TGaxis *axis = new TGaxis();
9130  PaintLegoAxis(axis, 90);
9131  delete axis;
9132  }
9133 
9134  if (Hoption.Zscale) PaintPalette();
9135 
9136  delete fLego; fLego = 0;
9137 }
9138 
9139 ////////////////////////////////////////////////////////////////////////////////
9140 /// Define the color levels used to paint legos, surfaces etc..
9141 
9143 {
9144 
9145  Int_t i, irep;
9146 
9147  // Initialize the color levels
9148  if (ndivz >= 100) {
9149  Warning("PaintSurface", "too many color levels, %d, reset to 8", ndivz);
9150  ndivz = 8;
9151  }
9152  Double_t *funlevel = new Double_t[ndivz+1];
9153  Int_t *colorlevel = new Int_t[ndivz+1];
9154  Int_t theColor;
9155  Int_t ncolors = gStyle->GetNumberOfColors();
9156  for (i = 0; i < ndivz; ++i) {
9157  funlevel[i] = fH->GetContourLevelPad(i);
9158  theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
9159  colorlevel[i] = gStyle->GetColorPalette(theColor);
9160  }
9161  colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
9162  fLego->ColorFunction(ndivz, funlevel, colorlevel, irep);
9163  delete [] colorlevel;
9164  delete [] funlevel;
9165 }
9166 
9167 ////////////////////////////////////////////////////////////////////////////////
9168 /// [Control function to draw 2D/3D histograms (tables).](#HP01c)
9169 
9170 void THistPainter::PaintTable(Option_t *option)
9171 {
9172 
9173  // Fill Hparam structure with histo parameters
9174  if (!TableInit()) return;
9175 
9176  // Draw histogram frame
9177  PaintFrame();
9178 
9179  // If palette option not specified, delete a possible existing palette
9180  if (!Hoption.Zscale) {
9181  TObject *palette = fFunctions->FindObject("palette");
9182  if (palette) { fFunctions->Remove(palette); delete palette;}
9183  }
9184 
9185  // Do not draw the histogram. Only the attached functions will be drawn.
9186  if (Hoption.Func == 2) {
9187  if (Hoption.Zscale) {
9188  Int_t ndiv = fH->GetContour();
9189  if (ndiv == 0 ) {
9190  ndiv = gStyle->GetNumberContours();
9191  fH->SetContour(ndiv);
9192  }
9193  PaintPalette();
9194  }
9195 
9196  // Draw the histogram according to the option
9197  } else {
9198  if (fH->InheritsFrom(TH2Poly::Class())) {
9199  if (Hoption.Fill) PaintTH2PolyBins("f");
9200  if (Hoption.Color) PaintTH2PolyColorLevels(option);
9201  if (Hoption.Scat) PaintTH2PolyScatterPlot(option);
9202  if (Hoption.Text) PaintTH2PolyText(option);
9203  if (Hoption.Line) PaintTH2PolyBins("l");
9204  if (Hoption.Mark) PaintTH2PolyBins("P");
9205  } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
9206  if (Hoption.Scat) PaintScatterPlot(option);
9207  if (Hoption.Arrow) PaintArrows(option);
9208  if (Hoption.Box) PaintBoxes(option);
9209  if (Hoption.Color) {
9210  if (Hoption.Color == 3) PaintColorLevelsFast(option);
9211  else PaintColorLevels(option);
9212  }
9213  if (Hoption.Contour) PaintContour(option);
9214  if (Hoption.Text) PaintText(option);
9215  if (Hoption.Error >= 100) Paint2DErrors(option);
9216  if (Hoption.Candle) PaintCandlePlot(option);
9217  }
9218  if (Hoption.Lego) PaintLego(option);
9219  if (Hoption.Surf && !Hoption.Contour) PaintSurface(option);
9220  if (Hoption.Tri) PaintTriangles(option);
9221  }
9222 
9223  // Draw histogram title
9224  PaintTitle();
9225 
9226  // Draw the axes
9227  if (!Hoption.Lego && !Hoption.Surf &&
9228  !Hoption.Tri && !(Hoption.Error >= 100)) PaintAxis(kFALSE);
9229 
9230  TF1 *fit = 0;
9231  TIter next(fFunctions);
9232  TObject *obj;
9233  while ((obj = next())) {
9234  if (obj->InheritsFrom(TF1::Class())) {
9235  fit = (TF1*)obj;
9236  break;
9237  }
9238  }
9239  if (Hoption.Same != 1) {
9240  if (!fH->TestBit(TH1::kNoStats)) { // bit set via TH1::SetStats
9241  if (!gPad->PadInSelectionMode() && !gPad->PadInHighlightMode()) {
9242  //ALWAYS executed on non-iOS platform.
9243  //On iOS, depends on mode.
9244  PaintStat2(gStyle->GetOptStat(),fit);
9245  }
9246  }
9247  }
9248 }
9249 
9250 ////////////////////////////////////////////////////////////////////////////////
9251 /// Control function to draw a TH2Poly bins' contours.
9252 ///
9253 /// - option = "F" draw the bins as filled areas.
9254 /// - option = "L" draw the bins as line.
9255 /// - option = "P" draw the bins as markers.
9256 
9258 {
9259 
9260  //Do not highlight the histogram, if its part was picked.
9261  if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH) return;
9262 
9263  TString opt = option;
9264  opt.ToLower();
9265  Bool_t line = kFALSE;
9266  Bool_t fill = kFALSE;
9267  Bool_t mark = kFALSE;
9268  if (opt.Contains("l")) line = kTRUE;
9269  if (opt.Contains("f")) fill = kTRUE;
9270  if (opt.Contains("p")) mark = kTRUE;
9271 
9272  TH2PolyBin *b;
9273  Double_t z;
9274 
9275  TIter next(((TH2Poly*)fH)->GetBins());
9276  TObject *obj, *poly;
9277 
9278  while ((obj=next())) {
9279  b = (TH2PolyBin*)obj;
9280  z = b->GetContent();
9281  if (z==0 && Hoption.Zero) continue; // Do not draw empty bins in case of option "COL0 L"
9282  poly = b->GetPolygon();
9283 
9284  // Paint the TGraph bins.
9285  if (poly->IsA() == TGraph::Class()) {
9286  TGraph *g = (TGraph*)poly;
9287  g->TAttLine::Modify();
9288  g->TAttMarker::Modify();
9289  g->TAttFill::Modify();
9290  if (line) {
9291  Int_t fs = g->GetFillStyle();
9292  Int_t fc = g->GetFillColor();
9293  g->SetFillStyle(0);
9294  g->SetFillColor(g->GetLineColor());
9295  g->Paint("F");
9296  g->SetFillStyle(fs);
9297  g->SetFillColor(fc);
9298  }
9299  if (fill) g->Paint("F");
9300  if (mark) g->Paint("P");
9301  }
9302 
9303  // Paint the TMultiGraph bins.
9304  if (poly->IsA() == TMultiGraph::Class()) {
9305  TMultiGraph *mg = (TMultiGraph*)poly;
9306  TList *gl = mg->GetListOfGraphs();
9307  if (!gl) return;
9308  TGraph *g;
9309  TIter nextg(gl);
9310  while ((g = (TGraph*) nextg())) {
9311  g->TAttLine::Modify();
9312  g->TAttMarker::Modify();
9313  g->TAttFill::Modify();
9314  if (line) {
9315  Int_t fs = g->GetFillStyle();
9316  Int_t fc = g->GetFillColor();
9317  g->SetFillStyle(0);
9318  g->SetFillColor(g->GetLineColor());
9319  g->Paint("F");
9320  g->SetFillStyle(fs);
9321  g->SetFillColor(fc);
9322  }
9323  if (fill) g->Paint("F");
9324  if (mark) g->Paint("P");
9325  }
9326  }
9327  }
9328 }
9329 
9330 ////////////////////////////////////////////////////////////////////////////////
9331 /// [Control function to draw a TH2Poly as a color plot.](#HP20a)
9332 
9334 {
9335 
9336  //Do not highlight the histogram, if its part was picked.
9337  if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9338  return;
9339 
9340  Int_t ncolors, color, theColor;
9341  Double_t z, zc;
9342  Double_t zmin = fH->GetMinimum();
9343  Double_t zmax = fH->GetMaximum();
9344  if (Hoption.Logz) {
9345  if (zmax > 0) {
9346  if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9347  zmin = TMath::Log10(zmin);
9348  zmax = TMath::Log10(zmax);
9349  } else {
9350  return;
9351  }
9352  }
9353  Double_t dz = zmax - zmin;
9354 
9355  // Initialize the levels on the Z axis
9356  ncolors = gStyle->GetNumberOfColors();
9357  Int_t ndiv = fH->GetContour();
9358  if (ndiv == 0 ) {
9359  ndiv = gStyle->GetNumberContours();
9360  fH->SetContour(ndiv);
9361  }
9362  Int_t ndivz = TMath::Abs(ndiv);
9363  if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
9364  Double_t scale = ndivz/dz;
9365 
9366  TH2PolyBin *b;
9367 
9368  TIter next(((TH2Poly*)fH)->GetBins());
9369  TObject *obj, *poly;
9370 
9371  while ((obj=next())) {
9372  b = (TH2PolyBin*)obj;
9373  poly = b->GetPolygon();
9374 
9375  z = b->GetContent();
9376  if (z==0 && Hoption.Zero) continue;
9377  if (Hoption.Logz) {
9378  if (z > 0) z = TMath::Log10(z);
9379  else z = zmin;
9380  }
9381  if (z < zmin) continue;
9382 
9383  // Define the bin color.
9384  if (fH->TestBit(TH1::kUserContour)) {
9385  zc = fH->GetContourLevelPad(0);
9386  if (z < zc) continue;
9387  color = -1;
9388  for (Int_t k=0; k<ndiv; k++) {
9389  zc = fH->GetContourLevelPad(k);
9390  if (z < zc) {
9391  continue;
9392  } else {
9393  color++;
9394  }
9395  }
9396  } else {
9397  color = Int_t(0.01+(z-zmin)*scale);
9398  }
9399  theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
9400  if (theColor > ncolors-1) theColor = ncolors-1;
9401 
9402  // Paint the TGraph bins.
9403  if (poly->IsA() == TGraph::Class()) {
9404  TGraph *g = (TGraph*)poly;
9405  g->SetFillColor(gStyle->GetColorPalette(theColor));
9406  g->TAttFill::Modify();
9407  g->Paint("F");
9408  }
9409 
9410  // Paint the TMultiGraph bins.
9411  if (poly->IsA() == TMultiGraph::Class()) {
9412  TMultiGraph *mg = (TMultiGraph*)poly;
9413  TList *gl = mg->GetListOfGraphs();
9414  if (!gl) return;
9415  TGraph *g;
9416  TIter nextg(gl);
9417  while ((g = (TGraph*) nextg())) {
9418  g->SetFillColor(gStyle->GetColorPalette(theColor));
9419  g->TAttFill::Modify();
9420  g->Paint("F");
9421  }
9422  }
9423  }
9424  if (Hoption.Zscale) PaintPalette();
9425 }
9426 
9427 ////////////////////////////////////////////////////////////////////////////////
9428 /// [Control function to draw a TH2Poly as a scatter plot.](#HP20a)
9429 
9431 {
9432 
9433  //Do not highlight the histogram, if its part was selected.
9434  if (gPad->PadInHighlightMode() && gPad->GetSelected() != fH)
9435  return;
9436 
9437  Int_t k, loop, marker=0;
9438  Double_t z, xk,xstep, yk, ystep, xp, yp;
9439  Double_t scale = 1;
9440  Double_t zmin = fH->GetMinimum();
9441  Double_t zmax = fH->GetMaximum();
9442  if (Hoption.Logz) {
9443  if (zmax > 0) {
9444  if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
9445  zmin = TMath::Log10(zmin);
9446  zmax = TMath::Log10(zmax);
9447  } else {
9448  return;
9449  }
9450  }
9451  Double_t dz = zmax - zmin;
9452  scale = (kNMAX-1)/dz;
9453 
9454 
9455  // use an independent instance of a random generator
9456  // instead of gRandom to avoid conflicts and
9457  // to get same random numbers when drawing the same histogram
9458  TRandom2 random;
9459 
9460  TH2PolyBin *b;
9461 
9462  TIter next(((TH2Poly*)fH)->GetBins());
9463  TObject *obj, *poly;
9464 
9465  Double_t maxarea = 0, a;
9466  while ((obj=next())) {
9467  b = (TH2PolyBin*)obj;
9468  a = b->GetArea();
9469  if (a>maxarea) maxarea = a;
9470  }
9471 
9472  next.Reset();
9473 
9474  while ((obj=next())) {
9475  b = (TH2PolyBin*)obj;
9476  poly = b->GetPolygon();
9477  z = b->GetContent();
9478  if (z < zmin) z = zmin;
9479  if (z > zmax) z = zmax;
9480  if (Hoption.Logz) {
9481  if (z > 0) z = TMath::Log10(z) - zmin;
9482  } else {
9483  z -= zmin;
9484  }
9485  k = Int_t((z*scale)*(b->GetArea()/maxarea));
9486  xk = b->GetXMin();
9487  yk = b->GetYMin();
9488  xstep = b->GetXMax()-xk;
9489  ystep = b->GetYMax()-yk;
9490 
9491  // Paint the TGraph bins.
9492  if (poly->IsA() == TGraph::Class()) {
9493  TGraph *g = (TGraph*)poly;
9494  if (k <= 0 || z <= 0) continue;
9495  loop = 0;
9496  while (loop<k) {
9497  if (k+marker >= kNMAX) {
9498  gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9499  marker=0;
9500  }
9501  xp = (random.Rndm()*xstep) + xk;
9502  yp = (random.Rndm()*ystep) + yk;
9503  if (g->IsInside(xp,yp)) {
9504  fXbuf[marker] = xp;
9505  fYbuf[marker] = yp;
9506  marker++;
9507  loop++;
9508  }
9509  }
9510  if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9511  }
9512 
9513  // Paint the TMultiGraph bins.
9514  if (poly->IsA() == TMultiGraph::Class()) {
9515  TMultiGraph *mg = (TMultiGraph*)poly;
9516  TList *gl = mg->GetListOfGraphs();
9517  if (!gl) return;
9518  if (k <= 0 || z <= 0) continue;
9519  loop = 0;
9520  while (loop<k) {
9521  if (k+marker >= kNMAX) {
9522  gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9523  marker=0;
9524  }
9525  xp = (random.Rndm()*xstep) + xk;
9526  yp = (random.Rndm()*ystep) + yk;
9527  if (mg->IsInside(xp,yp)) {
9528  fXbuf[marker] = xp;
9529  fYbuf[marker] = yp;
9530  marker++;
9531  loop++;
9532  }
9533  }
9534  if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
9535  }
9536  }
9537  PaintTH2PolyBins("l");
9538 }
9539 
9540 ////////////////////////////////////////////////////////////////////////////////
9541 /// [Control function to draw a TH2Poly as a text plot.](#HP20a)
9542 
9544 {
9545 
9546  TLatex text;
9547  text.SetTextFont(gStyle->GetTextFont());
9548  text.SetTextColor(fH->GetMarkerColor());
9549  text.SetTextSize(0.02*fH->GetMarkerSize());
9550 
9551  Double_t x, y, z, e, angle = 0;
9552  char value[50];
9553  char format[32];
9554  snprintf(format,32,"%s%s","%",gStyle->GetPaintTextFormat());
9555  if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9556  Int_t opt = (Int_t)Hoption.Text/1000;
9557 
9558  text.SetTextAlign(22);
9559  if (Hoption.Text == 1) angle = 0;
9560  text.SetTextAngle(angle);
9561  text.TAttText::Modify();
9562 
9563  TH2PolyBin *b;
9564 
9565  TIter next(((TH2Poly*)fH)->GetBins());
9566  TObject *obj, *p;
9567 
9568  while ((obj=next())) {
9569  b = (TH2PolyBin*)obj;
9570  p = b->GetPolygon();
9571  x = (b->GetXMin()+b->GetXMax())/2;
9572  if (Hoption.Logx) {
9573  if (x > 0) x = TMath::Log10(x);
9574  else continue;
9575  }
9576  y = (b->GetYMin()+b->GetYMax())/2;
9577  if (Hoption.Logy) {
9578  if (y > 0) y = TMath::Log10(y);
9579  else continue;
9580  }
9581  z = b->GetContent();
9582  if (z < Hparam.zmin || (z == 0 && !gStyle->GetHistMinimumZero()) ) continue;
9583  if (opt==2) {
9584  e = fH->GetBinError(b->GetBinNumber());
9585  snprintf(format,32,"#splitline{%s%s}{#pm %s%s}",
9586  "%",gStyle->GetPaintTextFormat(),
9587  "%",gStyle->GetPaintTextFormat());
9588  snprintf(value,50,format,z,e);
9589  } else {
9590  snprintf(value,50,format,z);
9591  }
9592  if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
9593  else text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),value);
9594  }
9595 
9596  PaintTH2PolyBins("l");
9597 }
9598 
9599 ////////////////////////////////////////////////////////////////////////////////
9600 /// [Control function to draw a 1D/2D histograms with the bin values.](#HP15)
9601 
9603 {
9604 
9605  TLatex text;
9606  text.SetTextFont(gStyle->GetTextFont());
9607  text.SetTextColor(fH->GetMarkerColor());
9608  text.SetTextSize(0.02*fH->GetMarkerSize());
9609 
9610  Double_t x, y, z, e, angle = 0;
9611  char value[50];
9612  char format[32];
9613  snprintf(format,32,"%s%s","%",gStyle->GetPaintTextFormat());
9614  if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
9615 
9616  // 1D histograms
9617  if (fH->GetDimension() == 1) {
9618  Bool_t getentries = kFALSE;
9619  Double_t yt;
9620  TProfile *hp = (TProfile*)fH;
9621  if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
9622  Hoption.Text = Hoption.Text-2000;
9623  getentries = kTRUE;
9624  }
9625  if (Hoption.Text == 1) angle = 90;
9626  text.SetTextAlign(11);
9627  if (angle == 90) text.SetTextAlign(12);
9628  if (angle == 0) text.SetTextAlign(21);
9629  text.TAttText::Modify();
9630  Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
9631  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
9632  if (Hoption.Bar) {
9633  x = fH->GetXaxis()->GetBinLowEdge(i)+
9634  fH->GetXaxis()->GetBinWidth(i)*
9635  (fH->GetBarOffset()+0.5*fH->GetBarWidth());
9636  } else {
9637  x = fH->GetXaxis()->GetBinCenter(i);
9638  }
9639  y = fH->GetBinContent(i);
9640  yt = y;
9641  if (gStyle->GetHistMinimumZero() && y<0) y = 0;
9642  if (getentries) yt = hp->GetBinEntries(i);
9643  if (yt == 0.) continue;
9644  snprintf(value,50,format,yt);
9645  if (Hoption.Logx) {
9646  if (x > 0) x = TMath::Log10(x);
9647  else continue;
9648  }
9649  if (Hoption.Logy) {
9650  if (y > 0) y = TMath::Log10(y);
9651  else continue;
9652  }
9653  if (y >= gPad->GetY2()) continue;
9654  if (y <= gPad->GetY1()) continue;
9655  text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),value);
9656  }
9657 
9658  // 2D histograms
9659  } else {
9660  text.SetTextAlign(22);
9661  if (Hoption.Text == 1) angle = 0;
9662  text.SetTextAngle(angle);
9663  text.TAttText::Modify();
9664  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
9665  y = fYaxis->GetBinCenter(j);
9666  if (Hoption.Logy) {
9667  if (y > 0) y = TMath::Log10(y);
9668  else continue;
9669  }
9670  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
9671  Int_t bin = j*(fXaxis->GetNbins()+2) + i;
9672  x = fXaxis->GetBinCenter(i);
9673  if (Hoption.Logx) {
9674  if (x > 0) x = TMath::Log10(x);
9675  else continue;
9676  }
9677  if (!IsInside(x,y)) continue;
9678  z = fH->GetBinContent(bin);
9679  if (z < Hparam.zmin || (z == 0 && !gStyle->GetHistMinimumZero()) ) continue;
9680  if (Hoption.Text>2000) {
9681  e = fH->GetBinError(bin);
9682  snprintf(format,32,"#splitline{%s%s}{#pm %s%s}",
9683  "%",gStyle->GetPaintTextFormat(),
9684  "%",gStyle->GetPaintTextFormat());
9685  snprintf(value,50,format,z,e);
9686  } else {
9687  snprintf(value,50,format,z);
9688  }
9689  text.PaintLatex(x,y+fH->GetBarOffset()*fYaxis->GetBinWidth(j),
9690  angle,0.02*fH->GetMarkerSize(),value);
9691  }
9692  }
9693  }
9694 }
9695 
9696 ////////////////////////////////////////////////////////////////////////////////
9697 /// [Control function to draw a 3D implicit functions.](#HP27)
9698 
9700 {
9701 
9702  Int_t irep;
9703 
9704  TGaxis *axis = new TGaxis();
9705  TAxis *xaxis = fH->GetXaxis();
9706  TAxis *yaxis = fH->GetYaxis();
9707  TAxis *zaxis = fH->GetZaxis();
9708 
9709  fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
9710  fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
9711  fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
9712  fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
9713  fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
9714  fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
9715 
9716  fLego = new TPainter3dAlgorithms(fXbuf, fYbuf);
9717 
9718  TView *view = gPad->GetView();
9719  if (!view) {
9720  Error("PaintTF3", "no TView in current pad");
9721  return;
9722  }
9723  Double_t thedeg = 90 - gPad->GetTheta();
9724  Double_t phideg = -90 - gPad->GetPhi();
9725  Double_t psideg = view->GetPsi();
9726  view->SetView(phideg, thedeg, psideg, irep);
9727 
9728  fLego->InitMoveScreen(-1.1,1.1);
9729 
9730  if (Hoption.BackBox) {
9733  fLego->BackBox(90);
9734  }
9735 
9737 
9738  fLego->ImplicitFunction(fXbuf, fYbuf, fH->GetNbinsX(),
9739  fH->GetNbinsY(),
9740  fH->GetNbinsZ(), "BF");
9741 
9742  if (Hoption.FrontBox) {
9743  fLego->InitMoveScreen(-1.1,1.1);
9745  fLego->FrontBox(90);
9746  }
9747  if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
9748 
9749  PaintTitle();
9750 
9751  delete axis;
9752  delete fLego; fLego = 0;
9753 }
9754 
9755 ////////////////////////////////////////////////////////////////////////////////
9756 /// Draw the histogram title
9757 ///
9758 /// The title is drawn according to the title alignment returned by
9759 /// `GetTitleAlign()`. It is a 2 digits integer): hv
9760 ///
9761 /// where `h` is the horizontal alignment and `v` is the
9762 /// vertical alignment.
9763 ///
9764 /// - `h` can get the values 1 2 3 for left, center, and right
9765 /// - `v` can get the values 1 2 3 for bottom, middle and top
9766 ///
9767 /// for instance the default alignment is: 13 (left top)
9768 
9770 {
9771 
9772  if (Hoption.Same) return;
9773  if (fH->TestBit(TH1::kNoTitle)) return;
9774  Int_t nt = strlen(fH->GetTitle());
9775  TPaveText *title = 0;
9776  TObject *obj;
9777  TIter next(gPad->GetListOfPrimitives());
9778  while ((obj = next())) {
9779  if (!obj->InheritsFrom(TPaveText::Class())) continue;
9780  title = (TPaveText*)obj;
9781  if (strcmp(title->GetName(),"title")) {title = 0; continue;}
9782  break;
9783  }
9784  if (nt == 0 || gStyle->GetOptTitle() <= 0) {
9785  if (title) delete title;
9786  return;
9787  }
9788  Double_t ht = gStyle->GetTitleH();
9789  Double_t wt = gStyle->GetTitleW();
9790  if (ht <= 0) ht = 1.1*gStyle->GetTitleFontSize();
9791  if (ht <= 0) ht = 0.05;
9792  if (wt <= 0) {
9793  TLatex l;
9794  l.SetTextSize(ht);
9795  l.SetTitle(fH->GetTitle());
9796  // adjustment in case the title has several lines (#splitline)
9797  ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
9798  Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
9799  wt = TMath::Min(0.7, 0.02+wndc);
9800  }
9801  if (title) {
9802  TText *t0 = (TText*)title->GetLine(0);
9803  if (t0) {
9804  if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
9805  t0->SetTitle(fH->GetTitle());
9806  if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
9807  }
9808  return;
9809  }
9810 
9811  Int_t talh = gStyle->GetTitleAlign()/10;
9812  if (talh < 1) talh = 1; else if (talh > 3) talh = 3;
9813  Int_t talv = gStyle->GetTitleAlign()%10;
9814  if (talv < 1) talv = 1; else if (talv > 3) talv = 3;
9815  Double_t xpos, ypos;
9816  xpos = gStyle->GetTitleX();
9817  ypos = gStyle->GetTitleY();
9818  if (talh == 2) xpos = xpos-wt/2.;
9819  if (talh == 3) xpos = xpos-wt;
9820  if (talv == 2) ypos = ypos+ht/2.;
9821  if (talv == 1) ypos = ypos+ht;
9822 
9823  TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
9824 
9825  // box with the histogram title
9827  ptitle->SetFillStyle(gStyle->GetTitleStyle());
9828  ptitle->SetName("title");
9831  ptitle->SetTextFont(gStyle->GetTitleFont(""));
9832  if (gStyle->GetTitleFont("")%10 > 2)
9833  ptitle->SetTextSize(gStyle->GetTitleFontSize());
9834  ptitle->AddText(fH->GetTitle());
9835  ptitle->SetBit(kCanDelete);
9836  ptitle->Draw();
9837  ptitle->Paint();
9838 
9839  if(!gPad->IsEditable()) delete ptitle;
9840 }
9841 
9842 ////////////////////////////////////////////////////////////////////////////////
9843 /// Process message `mess`.
9844 
9845 void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
9846 {
9847 
9848  if (!strcmp(mess,"SetF3")) {
9850  } else if (!strcmp(mess,"SetF3ClippingBoxOff")) {
9852  } else if (!strcmp(mess,"SetF3ClippingBoxOn")) {
9853  TVectorD &v = (TVectorD&)(*obj);
9854  Double_t xclip = v(0);
9855  Double_t yclip = v(1);
9856  Double_t zclip = v(2);
9858  }
9859 }
9860 
9861 ////////////////////////////////////////////////////////////////////////////////
9862 /// Static function.
9863 ///
9864 /// Convert Right Ascension, Declination to X,Y using an AITOFF projection.
9865 /// This procedure can be used to create an all-sky map in Galactic
9866 /// coordinates with an equal-area Aitoff projection. Output map
9867 /// coordinates are zero longitude centered.
9868 /// Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
9869 ///
9870 /// source: GMT
9871 ///
9872 /// code from Ernst-Jan Buis
9873 
9875 {
9876 
9877  Double_t x, y;
9878 
9879  Double_t alpha2 = (l/2)*TMath::DegToRad();
9880  Double_t delta = b*TMath::DegToRad();
9881  Double_t r2 = TMath::Sqrt(2.);
9882  Double_t f = 2*r2/TMath::Pi();
9883  Double_t cdec = TMath::Cos(delta);
9884  Double_t denom = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
9885  x = cdec*TMath::Sin(alpha2)*2.*r2/denom;
9886  y = TMath::Sin(delta)*r2/denom;
9887  x *= TMath::RadToDeg()/f;
9888  y *= TMath::RadToDeg()/f;
9889  // x *= -1.; // for a skymap swap left<->right
9890  Al = x;
9891  Ab = y;
9892 
9893  return 0;
9894 }
9895 
9896 ////////////////////////////////////////////////////////////////////////////////
9897 /// Static function
9898 ///
9899 /// Probably the most famous of the various map projections, the Mercator projection
9900 /// takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
9901 /// with no distortion along the equator.
9902 /// The Mercator projection has been used extensively for world maps in which the distortion towards
9903 /// the polar regions grows rather large, thus incorrectly giving the impression that, for example,
9904 /// Greenland is larger than South America. In reality, the latter is about eight times the size of
9905 /// Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
9906 /// whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
9907 /// code from Ernst-Jan Buis
9908 
9910 {
9911 
9912  Al = l;
9914  Ab = TMath::Log(aid);
9915  return 0;
9916 }
9917 
9918 ////////////////////////////////////////////////////////////////////////////////
9919 /// Static function code from Ernst-Jan Buis
9920 
9922 {
9923 
9924  Al = l*cos(b*TMath::DegToRad());
9925  Ab = b;
9926  return 0;
9927 }
9928 
9929 ////////////////////////////////////////////////////////////////////////////////
9930 /// Static function code from Ernst-Jan Buis
9931 
9934 
9935  Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
9936  Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
9937  return 0;
9938 }
9939 
9940 ////////////////////////////////////////////////////////////////////////////////
9941 /// Recompute the histogram range following graphics operations.
9942 
9945 
9946  if (Hoption.Same) return;
9947 
9948  // Compute x,y range
9949  Double_t xmin = Hparam.xmin;
9950  Double_t xmax = Hparam.xmax;
9951  Double_t ymin = Hparam.ymin;
9952  Double_t ymax = Hparam.ymax;
9953 
9954  Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
9955  if (Hoption.Proj ==1) {
9956  // TODO : check x range not lower than -180 and not higher than 180
9957  THistPainter::ProjectAitoff2xy(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
9958  THistPainter::ProjectAitoff2xy(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
9959  THistPainter::ProjectAitoff2xy(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
9960  THistPainter::ProjectAitoff2xy(Hparam.xmax, Hparam.ymin, xmax, ymin);
9961 
9962  if (xmin > xmin_aid) xmin = xmin_aid;
9963  if (ymin > ymin_aid) ymin = ymin_aid;
9964  if (xmax < xmax_aid) xmax = xmax_aid;
9965  if (ymax < ymax_aid) ymax = ymax_aid;
9966  if (Hparam.ymin<0 && Hparam.ymax>0) {
9967  // there is an 'equator', check its range in the plot..
9968  THistPainter::ProjectAitoff2xy(Hparam.xmin*0.9999, 0, xmin_aid, ymin_aid);
9969  THistPainter::ProjectAitoff2xy(Hparam.xmax*0.9999, 0, xmax_aid, ymin_aid);
9970  if (xmin >xmin_aid) xmin = xmin_aid;
9971  if (xmax <xmax_aid) xmax = xmax_aid;
9972  }
9973  if (Hparam.xmin<0 && Hparam.xmax>0) {
9974  THistPainter::ProjectAitoff2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
9975  THistPainter::ProjectAitoff2xy(0, Hparam.ymax, xmax_aid, ymax_aid);
9976  if (ymin >ymin_aid) ymin = ymin_aid;
9977  if (ymax <ymax_aid) ymax = ymax_aid;
9978  }
9979  } else if ( Hoption.Proj ==2) {
9980  if (Hparam.ymin <= -90 || Hparam.ymax >=90) {
9981  Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
9982  Hoption.Proj = 0;
9983  } else {
9984  THistPainter::ProjectMercator2xy(Hparam.xmin, Hparam.ymin, xmin, ymin);
9985  THistPainter::ProjectMercator2xy(Hparam.xmax, Hparam.ymax, xmax, ymax);
9986  }
9987  } else if (Hoption.Proj == 3) {
9988  THistPainter::ProjectSinusoidal2xy(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
9989  THistPainter::ProjectSinusoidal2xy(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
9990  THistPainter::ProjectSinusoidal2xy(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
9991  THistPainter::ProjectSinusoidal2xy(Hparam.xmax, Hparam.ymin, xmax, ymin);
9992 
9993  if (xmin > xmin_aid) xmin = xmin_aid;
9994  if (ymin > ymin_aid) ymin = ymin_aid;
9995  if (xmax < xmax_aid) xmax = xmax_aid;
9996  if (ymax < ymax_aid) ymax = ymax_aid;
9997  if (Hparam.ymin<0 && Hparam.ymax>0) {
9998  THistPainter::ProjectSinusoidal2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
9999  THistPainter::ProjectSinusoidal2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
10000  if (xmin >xmin_aid) xmin = xmin_aid;
10001  if (xmax <xmax_aid) xmax = xmax_aid;
10002  }
10003  if (Hparam.xmin<0 && Hparam.xmax>0) {
10004  THistPainter::ProjectSinusoidal2xy(0,Hparam.ymin, xmin_aid, ymin_aid);
10005  THistPainter::ProjectSinusoidal2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
10006  if (ymin >ymin_aid) ymin = ymin_aid;
10007  if (ymax <ymax_aid) ymax = ymax_aid;
10008  }
10009  } else if (Hoption.Proj == 4) {
10010  THistPainter::ProjectParabolic2xy(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
10011  THistPainter::ProjectParabolic2xy(Hparam.xmin, Hparam.ymax, xmin, ymax_aid);
10012  THistPainter::ProjectParabolic2xy(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
10013  THistPainter::ProjectParabolic2xy(Hparam.xmax, Hparam.ymin, xmax, ymin);
10014 
10015  if (xmin > xmin_aid) xmin = xmin_aid;
10016  if (ymin > ymin_aid) ymin = ymin_aid;
10017  if (xmax < xmax_aid) xmax = xmax_aid;
10018  if (ymax < ymax_aid) ymax = ymax_aid;
10019  if (Hparam.ymin<0 && Hparam.ymax>0) {
10020  THistPainter::ProjectParabolic2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
10021  THistPainter::ProjectParabolic2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
10022  if (xmin >xmin_aid) xmin = xmin_aid;
10023  if (xmax <xmax_aid) xmax = xmax_aid;
10024  }
10025  if (Hparam.xmin<0 && Hparam.xmax>0) {
10026  THistPainter::ProjectParabolic2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
10027  THistPainter::ProjectParabolic2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
10028  if (ymin >ymin_aid) ymin = ymin_aid;
10029  if (ymax <ymax_aid) ymax = ymax_aid;
10030  }
10031  }
10032  Hparam.xmin= xmin;
10033  Hparam.xmax= xmax;
10034  Hparam.ymin= ymin;
10035  Hparam.ymax= ymax;
10036 
10037  Double_t dx = xmax-xmin;
10038  Double_t dy = ymax-ymin;
10039  Double_t dxr = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
10040  Double_t dyr = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
10041 
10042  // Range() could change the size of the pad pixmap and therefore should
10043  // be called before the other paint routines
10044  gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
10045  ymin - dyr*gPad->GetBottomMargin(),
10046  xmax + dxr*gPad->GetRightMargin(),
10047  ymax + dyr*gPad->GetTopMargin());
10048  gPad->RangeAxis(xmin, ymin, xmax, ymax);
10049 }
10050 
10051 ////////////////////////////////////////////////////////////////////////////////
10052 /// Set current histogram to `h`
10053 
10055 {
10056 
10057  if (h == 0) return;
10058  fH = h;
10059  fXaxis = h->GetXaxis();
10060  fYaxis = h->GetYaxis();
10061  fZaxis = h->GetZaxis();
10063 }
10064 
10065 ////////////////////////////////////////////////////////////////////////////////
10066 /// Initialize various options to draw 2D histograms.
10067 
10069 {
10070 
10071  static const char *where = "TableInit";
10072 
10073  Int_t first, last;
10074  Double_t yMARGIN= gStyle->GetHistTopMargin();
10075  Double_t zmin, zmax;
10076  Int_t maximum = 0;
10077  Int_t minimum = 0;
10078  if (fH->GetMaximumStored() != -1111) maximum = 1;
10079  if (fH->GetMinimumStored() != -1111) minimum = 1;
10081  // ----------------- Compute X axis parameters
10082  first = fXaxis->GetFirst();
10083  last = fXaxis->GetLast();
10084  Hparam.xlast = last;
10085  Hparam.xfirst = first;
10086  Hparam.xlowedge = fXaxis->GetBinLowEdge(first);
10087  Hparam.xbinsize = fXaxis->GetBinWidth(first);
10088  Hparam.xmin = Hparam.xlowedge;
10089  Hparam.xmax = fXaxis->GetBinLowEdge(last)+fXaxis->GetBinWidth(last);
10090 
10091  // if log scale in X, replace xmin,max by the log
10092  if (Hoption.Logx) {
10093  // find the first edge of a bin that is > 0
10094  if (Hparam.xlowedge <=0 ) {
10095  Hparam.xlowedge = fXaxis->GetBinUpEdge(fXaxis->FindFixBin(0.01*Hparam.xbinsize));
10096  Hparam.xmin = Hparam.xlowedge;
10097  }
10098  if (Hparam.xmin <=0 || Hparam.xmax <=0) {
10099  Error(where, "cannot set X axis to log scale");
10100  return 0;
10101  }
10102  Hparam.xfirst= fXaxis->FindFixBin(Hparam.xmin);
10103  if (Hparam.xfirst < first) Hparam.xfirst = first;
10104  Hparam.xlast = fXaxis->FindFixBin(Hparam.xmax);
10105  if (Hparam.xlast > last) Hparam.xlast = last;
10106  Hparam.xmin = TMath::Log10(Hparam.xmin);
10107  Hparam.xmax = TMath::Log10(Hparam.xmax);
10108  }
10109 
10110  // ----------------- Compute Y axis parameters
10111  first = fYaxis->GetFirst();
10112  last = fYaxis->GetLast();
10113  Hparam.ylast = last;
10114  Hparam.yfirst = first;
10115  Hparam.ylowedge = fYaxis->GetBinLowEdge(first);
10116  Hparam.ybinsize = fYaxis->GetBinWidth(first);
10117  if (!Hparam.ybinsize) Hparam.ybinsize = 1;
10118  Hparam.ymin = Hparam.ylowedge;
10119  Hparam.ymax = fYaxis->GetBinLowEdge(last)+fYaxis->GetBinWidth(last);
10120 
10121  // if log scale in Y, replace ymin,max by the log
10122  if (Hoption.Logy) {
10123  if (Hparam.ylowedge <=0 ) {
10124  Hparam.ylowedge = fYaxis->GetBinUpEdge(fYaxis->FindFixBin(0.01*Hparam.ybinsize));
10125  Hparam.ymin = Hparam.ylowedge;
10126  }
10127  if (Hparam.ymin <=0 || Hparam.ymax <=0) {
10128  Error(where, "cannot set Y axis to log scale");
10129  return 0;
10130  }
10131  Hparam.yfirst= fYaxis->FindFixBin(Hparam.ymin);
10132  if (Hparam.yfirst < first) Hparam.yfirst = first;
10133  Hparam.ylast = fYaxis->FindFixBin(Hparam.ymax);
10134  if (Hparam.ylast > last) Hparam.ylast = last;
10135  Hparam.ymin = TMath::Log10(Hparam.ymin);
10136  Hparam.ymax = TMath::Log10(Hparam.ymax);
10137  }
10138 
10139 
10140  // ----------------- Compute Z axis parameters
10141  Double_t bigp = TMath::Power(10,32);
10142  zmax = -bigp;
10143  zmin = bigp;
10144  Double_t c1, e1;
10145  Double_t allchan = 0;
10146  for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
10147  for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
10148  c1 = fH->GetBinContent(i,j);
10149  zmax = TMath::Max(zmax,c1);
10150  if (Hoption.Error) {
10151  e1 = fH->GetBinError(i,j);
10152  zmax = TMath::Max(zmax,c1+e1);
10153  }
10154  zmin = TMath::Min(zmin,c1);
10155  allchan += c1;
10156  }
10157  }
10158 
10159  // Take into account maximum , minimum
10160 
10161  if (maximum) zmax = fH->GetMaximumStored();
10162  if (minimum) zmin = fH->GetMinimumStored();
10163  if (Hoption.Logz && zmax < 0) {
10164  if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10165  return 0;
10166  } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
10167  zmin = 0.01;
10168  zmax = 10.;
10169  }
10170  if (zmin >= zmax) {
10171  if (Hoption.Logz) {
10172  if (zmax > 0) zmin = 0.001*zmax;
10173  else {
10174  if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
10175  return 0;
10176  }
10177  }
10178  }
10179 
10180  // take into account normalization factor
10181  Hparam.allchan = allchan;
10182  Double_t factor = allchan;
10183  if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
10184  if (allchan) factor /= allchan;
10185  if (factor == 0) factor = 1;
10186  Hparam.factor = factor;
10187  zmax = factor*zmax;
10188  zmin = factor*zmin;
10189  c1 = zmax;
10190  if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
10191 
10192  // For log scales, histogram coordinates are log10(ymin) and
10193  // log10(ymax). Final adjustment (if not option "Same")
10194  // or "+" for ymax) of ymax and ymin for logarithmic scale, if
10195  // Maximum and Minimum are not defined.
10196  if (Hoption.Logz) {
10197  if (zmin <= 0) {
10198  zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
10199  fH->SetMinimum(zmin);
10200  }
10201  zmin = TMath::Log10(zmin);
10202  if (!minimum) zmin += TMath::Log10(0.5);
10203  zmax = TMath::Log10(zmax);
10204  if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
10205  goto LZMIN;
10206  }
10207 
10208  // final adjustment of YMAXI for linear scale (if not option "Same"):
10209  // decrease histogram height to MAX% of allowed height if HMAXIM
10210  // has not been called.
10211  // MAX% is the value in percent which has been set in HPLSET
10212  // (default is 90%).
10213  if (!maximum) {
10214  zmax += yMARGIN*(zmax-zmin);
10215  }
10216 
10217  // final adjustment of ymin for linear scale.
10218  // if minimum is not set , then ymin is set to zero if >0
10219  // or to ymin - yMARGIN if <0.
10220  if (!minimum) {
10221  if (gStyle->GetHistMinimumZero()) {
10222  if (zmin >= 0) zmin = 0;
10223  else zmin -= yMARGIN*(zmax-zmin);
10224  } else {
10225  Double_t dzmin = yMARGIN*(zmax-zmin);
10226  if (zmin >= 0 && (zmin-dzmin <= 0)) zmin = 0;
10227  else zmin -= dzmin;
10228  }
10229  }
10230 
10231 LZMIN:
10232  Hparam.zmin = zmin;
10233  Hparam.zmax = zmax;
10234 
10235  // Set bar offset and width
10236  Hparam.baroffset = fH->GetBarOffset();
10237  Hparam.barwidth = fH->GetBarWidth();
10238 
10239  return 1;
10240 }
10241 
10242 ////////////////////////////////////////////////////////////////////////////////
10243 /// This function returns the best format to print the error value (e)
10244 /// knowing the parameter value (v) and the format (f) used to print it.
10245 
10246 const char * THistPainter::GetBestFormat(Double_t v, Double_t e, const char *f)
10247 {
10248 
10249  static char ef[20];
10250  char tf[20], tv[64];
10251 
10252  // print v with the format f in tv.
10253  snprintf(tf,20,"%s%s","%",f);
10254  snprintf(tv,64,tf,v);
10255 
10256  // Analyse tv.
10257  TString sv = tv;
10258  int ie = sv.Index("e");
10259  int iE = sv.Index("E");
10260  int id = sv.Index(".");
10261 
10262  // v has been printed with the exponent notation.
10263  // There is 2 cases, the exponent is positive or negative
10264  if (ie >= 0 || iE >= 0) {
10265  if (sv.Index("+") >= 0) {
10266  if (e < 1) {
10267  snprintf(ef,20,"%s.1f","%");
10268  } else {
10269  if (ie >= 0) {
10270  snprintf(ef,20,"%s.%de","%",ie-id-1);
10271  } else {
10272  snprintf(ef,20,"%s.%dE","%",iE-id-1);
10273  }
10274  }
10275  } else {
10276  if (ie >= 0) {
10277  snprintf(ef,20,"%s.%de","%",ie-id-1);
10278  } else {
10279  snprintf(ef,20,"%s.%dE","%",iE-id-1);
10280  }
10281  }
10282 
10283  // There is not '.' in tv. e will be printed with one decimal digit.
10284  } else if (id < 0) {
10285  snprintf(ef,20,"%s.1f","%");
10286 
10287  // There is a '.' in tv and no exponent notation. e's decimal part will
10288  // have the same number of digits as v's one.
10289  } else {
10290  snprintf(ef,20,"%s.%df","%",sv.Length()-id-1);
10291  }
10292 
10293  return ef;
10294 }
10295 
10296 ////////////////////////////////////////////////////////////////////////////////
10297 /// Set projection.
10298 
10299 void THistPainter::SetShowProjection(const char *option,Int_t nbins)
10300 {
10301 
10302  if (fShowProjection) return;
10303  TString opt = option;
10304  opt.ToLower();
10305  Int_t projection = 0;
10306  if (opt.Contains("x")) projection = 1;
10307  if (opt.Contains("y")) projection = 2;
10308  if (opt.Contains("z")) projection = 3;
10309  if (opt.Contains("xy")) projection = 4;
10310  if (opt.Contains("yx")) projection = 5;
10311  if (opt.Contains("xz")) projection = 6;
10312  if (opt.Contains("zx")) projection = 7;
10313  if (opt.Contains("yz")) projection = 8;
10314  if (opt.Contains("zy")) projection = 9;
10315  if (projection < 4) fShowOption = option+1;
10316  else fShowOption = option+2;
10317  fShowProjection = projection+100*nbins;
10318  gROOT->MakeDefCanvas();
10319  gPad->SetName(Form("c_%lx_projection_%d", (ULong_t)fH, fShowProjection));
10320  gPad->SetGrid();
10321 }
10322 
10323 ////////////////////////////////////////////////////////////////////////////////
10324 /// Show projection onto X.
10325 
10326 void THistPainter::ShowProjectionX(Int_t /*px*/, Int_t py)
10327 {
10328 
10329  Int_t nbins = (Int_t)fShowProjection/100;
10330  gPad->SetDoubleBuffer(0); // turn off double buffer mode
10331  gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10332 
10333  // Erase old position and draw a line at current position
10334  static int pyold1 = 0;
10335  static int pyold2 = 0;
10336  float uxmin = gPad->GetUxmin();
10337  float uxmax = gPad->GetUxmax();
10338  int pxmin = gPad->XtoAbsPixel(uxmin);
10339  int pxmax = gPad->XtoAbsPixel(uxmax);
10340  Float_t upy = gPad->AbsPixeltoY(py);
10341  Float_t y = gPad->PadtoY(upy);
10342  Int_t biny1 = fH->GetYaxis()->FindBin(y);
10343  Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
10344  Int_t py1 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
10345  Int_t py2 = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
10346 
10347  if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
10348  gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
10349  pyold1 = py1;
10350  pyold2 = py2;
10351 
10352  // Create or set the new canvas proj x
10353  TVirtualPad *padsav = gPad;
10354  TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
10355  (ULong_t)fH, fShowProjection));
10356  if (c) {
10357  c->Clear();
10358  } else {
10359  fShowProjection = 0;
10360  pyold1 = 0;
10361  pyold2 = 0;
10362  return;
10363  }
10364  c->cd();
10365  c->SetLogy(padsav->GetLogz());
10366  c->SetLogx(padsav->GetLogx());
10367 
10368  // Draw slice corresponding to mouse position
10369  TString prjName = TString::Format("slice_px_of_%s",fH->GetName());
10370  TH1D *hp = ((TH2*)fH)->ProjectionX(prjName, biny1, biny2);
10371  if (hp) {
10372  hp->SetFillColor(38);
10373  // apply a patch from Oliver Freyermuth to set the title in the projection
10374  // using the range of the projected Y values
10375  if (biny1 == biny2) {
10376  Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10377  Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny1);
10378  // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10379  Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10380  if (fH->GetYaxis()->GetLabels() != NULL) {
10381  hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf] %s", biny1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetYaxis()->GetBinLabel(biny1)));
10382  } else {
10383  hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.*lf..%.*lf]", biny1, valuePrecision, valueFrom, valuePrecision, valueTo));
10384  }
10385  } else {
10386  Double_t valueFrom = fH->GetYaxis()->GetBinLowEdge(biny1);
10387  Double_t valueTo = fH->GetYaxis()->GetBinUpEdge(biny2);
10388  // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10389  // biny1 is used here to get equal precision no matter how large the binrange is,
10390  // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10391  Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetYaxis()->GetBinUpEdge(biny1)-valueFrom))+1;
10392  if (fH->GetYaxis()->GetLabels() != NULL) {
10393  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)));
10394  } else {
10395  hp->SetTitle(TString::Format("ProjectionX of biny=[%d,%d] [y=%.*lf..%.*lf]", biny1, biny2, valuePrecision, valueFrom, valuePrecision, valueTo));
10396  }
10397  }
10398  hp->SetXTitle(fH->GetXaxis()->GetTitle());
10399  hp->SetYTitle("Number of Entries");
10400  hp->Draw();
10401  c->Update();
10402  padsav->cd();
10403  }
10404 }
10405 
10406 ////////////////////////////////////////////////////////////////////////////////
10407 /// Show projection onto Y.
10408 
10409 void THistPainter::ShowProjectionY(Int_t px, Int_t /*py*/)
10410 {
10411 
10412  Int_t nbins = (Int_t)fShowProjection/100;
10413  gPad->SetDoubleBuffer(0); // turn off double buffer mode
10414  gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10415 
10416  // Erase old position and draw a line at current position
10417  static int pxold1 = 0;
10418  static int pxold2 = 0;
10419  float uymin = gPad->GetUymin();
10420  float uymax = gPad->GetUymax();
10421  int pymin = gPad->YtoAbsPixel(uymin);
10422  int pymax = gPad->YtoAbsPixel(uymax);
10423  Float_t upx = gPad->AbsPixeltoX(px);
10424  Float_t x = gPad->PadtoX(upx);
10425  Int_t binx1 = fH->GetXaxis()->FindBin(x);
10426  Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
10427  Int_t px1 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
10428  Int_t px2 = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
10429 
10430  if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
10431  gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
10432  pxold1 = px1;
10433  pxold2 = px2;
10434 
10435  // Create or set the new canvas proj y
10436  TVirtualPad *padsav = gPad;
10437  TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
10438  (ULong_t)fH, fShowProjection));
10439  if (c) {
10440  c->Clear();
10441  } else {
10442  fShowProjection = 0;
10443  pxold1 = 0;
10444  pxold2 = 0;
10445  return;
10446  }
10447  c->cd();
10448  c->SetLogy(padsav->GetLogz());
10449  c->SetLogx(padsav->GetLogy());
10450 
10451  // Draw slice corresponding to mouse position
10452  TString prjName = TString::Format("slice_py_of_%s",fH->GetName());
10453  TH1D *hp = ((TH2*)fH)->ProjectionY(prjName, binx1, binx2);
10454  if (hp) {
10455  hp->SetFillColor(38);
10456  // apply a patch from Oliver Freyermuth to set the title in the projection
10457  // using the range of the projected X values
10458  if (binx1 == binx2) {
10459  Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10460  Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx1);
10461  // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10462  Int_t valuePrecision = -TMath::Nint(TMath::Log10(valueTo-valueFrom))+1;
10463  if (fH->GetXaxis()->GetLabels() != NULL) {
10464  hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf] [%s]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo, fH->GetXaxis()->GetBinLabel(binx1)));
10465  } else {
10466  hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.*lf..%.*lf]", binx1, valuePrecision, valueFrom, valuePrecision, valueTo));
10467  }
10468  } else {
10469  Double_t valueFrom = fH->GetXaxis()->GetBinLowEdge(binx1);
10470  Double_t valueTo = fH->GetXaxis()->GetBinUpEdge(binx2);
10471  // Limit precision to 1 digit more than the difference between upper and lower bound (to also catch 121.5-120.5).
10472  // binx1 is used here to get equal precision no matter how large the binrange is,
10473  // otherwise precision may change when moving the mouse to the histogram boundaries (limiting effective binrange).
10474  Int_t valuePrecision = -TMath::Nint(TMath::Log10(fH->GetXaxis()->GetBinUpEdge(binx1)-valueFrom))+1;
10475  if (fH->GetXaxis()->GetLabels() != NULL) {
10476  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)));
10477  } else {
10478  hp->SetTitle(TString::Format("ProjectionY of binx=[%d,%d] [x=%.*lf..%.*lf]", binx1, binx2, valuePrecision, valueFrom, valuePrecision, valueTo));
10479  }
10480  }
10481  hp->SetXTitle(fH->GetYaxis()->GetTitle());
10482  hp->SetYTitle("Number of Entries");
10483  hp->Draw();
10484  c->Update();
10485  padsav->cd();
10486  }
10487 }
10488 
10489 ////////////////////////////////////////////////////////////////////////////////
10490 /// Show projection (specified by `fShowProjection`) of a `TH3`.
10491 /// The drawing option for the projection is in `fShowOption`.
10492 ///
10493 /// First implementation; R.Brun
10494 ///
10495 /// Full implementation: Tim Tran (timtran@jlab.org) April 2006
10496 
10498 {
10499 
10500  Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
10501  if (fH->GetDimension() < 3) {
10502  if (fShowProjection%100 == 1) {ShowProjectionX(px,py); return;}
10503  if (fShowProjection%100 == 2) {ShowProjectionY(px,py); return;}
10504  }
10505 
10506  gPad->SetDoubleBuffer(0); // turn off double buffer mode
10507  gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
10508 
10509  // Erase old position and draw a line at current position
10510  TView *view = gPad->GetView();
10511  if (!view) return;
10512  TH3 *h3 = (TH3*)fH;
10513  TAxis *xaxis = h3->GetXaxis();
10514  TAxis *yaxis = h3->GetYaxis();
10515  TAxis *zaxis = h3->GetZaxis();
10516  Double_t u[3],xx[3];
10517 
10518  static TPoint line1[2];//store end points of a line, initialised 0 by default
10519  static TPoint line2[2];// second line when slice thickness > 1 bin thickness
10520  static TPoint line3[2];
10521  static TPoint line4[2];
10522  static TPoint endface1[5];
10523  static TPoint endface2[5];
10524  static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
10525  static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
10526 
10527  Double_t uxmin = gPad->GetUxmin();
10528  Double_t uxmax = gPad->GetUxmax();
10529  Double_t uymin = gPad->GetUymin();
10530  Double_t uymax = gPad->GetUymax();
10531 
10532  int pxmin = gPad->XtoAbsPixel(uxmin);
10533  int pxmax = gPad->XtoAbsPixel(uxmax);
10534  if (pxmin==pxmax) return;
10535  int pymin = gPad->YtoAbsPixel(uymin);
10536  int pymax = gPad->YtoAbsPixel(uymax);
10537  if (pymin==pymax) return;
10538  Double_t cx = (pxmax-pxmin)/(uxmax-uxmin);
10539  Double_t cy = (pymax-pymin)/(uymax-uymin);
10540  TVirtualPad *padsav = gPad;
10541  TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("c_%lx_projection_%d",
10542  (ULong_t)fH, fShowProjection));
10543  if (!c) {
10544  fShowProjection = 0;
10545  return;
10546  }
10547 
10548  switch ((Int_t)fShowProjection%100) {
10549  case 1:
10550  // "x"
10551  {
10552  Int_t firstY = yaxis->GetFirst();
10553  Int_t lastY = yaxis->GetLast();
10554  Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
10555  Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
10556  yaxis->SetRange(biny,biny2);
10557  Int_t firstZ = zaxis->GetFirst();
10558  Int_t lastZ = zaxis->GetLast();
10559  Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
10560  Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10561  zaxis->SetRange(binz,binz2);
10562  if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
10563  if (nbins>1 && line1[0].GetX()) {
10564  gVirtualX->DrawPolyLine(2,line2);
10565  gVirtualX->DrawPolyLine(2,line3);
10566  gVirtualX->DrawPolyLine(2,line4);
10567  gVirtualX->DrawPolyLine(5,endface1);
10568  gVirtualX->DrawPolyLine(5,endface2);
10569  }
10570  xx[0] = xaxis->GetXmin();
10571  xx[2] = zaxis->GetBinCenter(binz);
10572  xx[1] = yaxis->GetBinCenter(biny);
10573  view->WCtoNDC(xx,u);
10574  line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10575  line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10576  xx[0] = xaxis->GetXmax();
10577  view->WCtoNDC(xx,u);
10578  line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10579  line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10580  gVirtualX->DrawPolyLine(2,line1);
10581  if (nbins>1) {
10582  xx[0] = xaxis->GetXmin();
10583  xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10584  xx[1] = yaxis->GetBinCenter(biny);
10585  view->WCtoNDC(xx,u);
10586  line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10587  line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10588  xx[0] = xaxis->GetXmax();
10589  view->WCtoNDC(xx,u);
10590  line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10591  line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10592 
10593  xx[0] = xaxis->GetXmin();
10594  xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10595  xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10596  view->WCtoNDC(xx,u);
10597  line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10598  line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10599  xx[0] = xaxis->GetXmax();
10600  view->WCtoNDC(xx,u);
10601  line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10602  line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10603 
10604  xx[0] = xaxis->GetXmin();
10605  xx[2] = zaxis->GetBinCenter(binz);
10606  xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10607  view->WCtoNDC(xx,u);
10608  line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10609  line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10610  xx[0] = xaxis->GetXmax();
10611  view->WCtoNDC(xx,u);
10612  line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10613  line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10614 
10615  endface1[0].SetX(line1[0].GetX());
10616  endface1[0].SetY(line1[0].GetY());
10617  endface1[1].SetX(line2[0].GetX());
10618  endface1[1].SetY(line2[0].GetY());
10619  endface1[2].SetX(line3[0].GetX());
10620  endface1[2].SetY(line3[0].GetY());
10621  endface1[3].SetX(line4[0].GetX());
10622  endface1[3].SetY(line4[0].GetY());
10623  endface1[4].SetX(line1[0].GetX());
10624  endface1[4].SetY(line1[0].GetY());
10625 
10626  endface2[0].SetX(line1[1].GetX());
10627  endface2[0].SetY(line1[1].GetY());
10628  endface2[1].SetX(line2[1].GetX());
10629  endface2[1].SetY(line2[1].GetY());
10630  endface2[2].SetX(line3[1].GetX());
10631  endface2[2].SetY(line3[1].GetY());
10632  endface2[3].SetX(line4[1].GetX());
10633  endface2[3].SetY(line4[1].GetY());
10634  endface2[4].SetX(line1[1].GetX());
10635  endface2[4].SetY(line1[1].GetY());
10636 
10637  gVirtualX->DrawPolyLine(2,line2);
10638  gVirtualX->DrawPolyLine(2,line3);
10639  gVirtualX->DrawPolyLine(2,line4);
10640  gVirtualX->DrawPolyLine(5,endface1);
10641  gVirtualX->DrawPolyLine(5,endface2);
10642  }
10643  c->Clear();
10644  c->cd();
10645  TH1 *hp = h3->Project3D("x");
10646  yaxis->SetRange(firstY,lastY);
10647  zaxis->SetRange(firstZ,lastZ);
10648  if (hp) {
10649  hp->SetFillColor(38);
10650  if (nbins == 1)
10651  hp->SetTitle(TString::Format("ProjectionX of biny=%d [y=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny),
10652  binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
10653  else {
10654  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),
10655  binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
10656  }
10657  hp->SetXTitle(fH->GetXaxis()->GetTitle());
10658  hp->SetYTitle("Number of Entries");
10659  hp->Draw(fShowOption.Data());
10660  }
10661  }
10662  break;
10663 
10664  case 2:
10665  // "y"
10666  {
10667  Int_t firstX = xaxis->GetFirst();
10668  Int_t lastX = xaxis->GetLast();
10669  Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
10670  Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
10671  xaxis->SetRange(binx,binx2);
10672  Int_t firstZ = zaxis->GetFirst();
10673  Int_t lastZ = zaxis->GetLast();
10674  Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
10675  Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10676  zaxis->SetRange(binz,binz2);
10677  if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
10678  if (nbins>1 && line1[0].GetX()) {
10679  gVirtualX->DrawPolyLine(2,line2);
10680  gVirtualX->DrawPolyLine(2,line3);
10681  gVirtualX->DrawPolyLine(2,line4);
10682  gVirtualX->DrawPolyLine(5,endface1);
10683  gVirtualX->DrawPolyLine(5,endface2);
10684  }
10685  xx[0]=xaxis->GetBinCenter(binx);
10686  xx[2] = zaxis->GetBinCenter(binz);
10687  xx[1] = yaxis->GetXmin();
10688  view->WCtoNDC(xx,u);
10689  line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10690  line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10691  xx[1] = yaxis->GetXmax();
10692  view->WCtoNDC(xx,u);
10693  line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10694  line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10695  gVirtualX->DrawPolyLine(2,line1);
10696  if (nbins>1) {
10697  xx[1] = yaxis->GetXmin();
10698  xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10699  xx[0] = xaxis->GetBinCenter(binx);
10700  view->WCtoNDC(xx,u);
10701  line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10702  line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10703  xx[1] = yaxis->GetXmax();
10704  view->WCtoNDC(xx,u);
10705  line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10706  line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10707 
10708  xx[1] = yaxis->GetXmin();
10709  xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10710  xx[0] = xaxis->GetBinCenter(binx+nbins-1);
10711  view->WCtoNDC(xx,u);
10712  line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10713  line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10714  xx[1] = yaxis->GetXmax();
10715  view->WCtoNDC(xx,u);
10716  line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10717  line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10718 
10719  xx[1] = yaxis->GetXmin();
10720  xx[2] = zaxis->GetBinCenter(binz);
10721  xx[0] = xaxis->GetBinCenter(binx+nbins-1);
10722  view->WCtoNDC(xx,u);
10723  line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10724  line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10725  xx[1] = yaxis->GetXmax();
10726  view->WCtoNDC(xx,u);
10727  line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10728  line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10729 
10730  endface1[0].SetX(line1[0].GetX());
10731  endface1[0].SetY(line1[0].GetY());
10732  endface1[1].SetX(line2[0].GetX());
10733  endface1[1].SetY(line2[0].GetY());
10734  endface1[2].SetX(line3[0].GetX());
10735  endface1[2].SetY(line3[0].GetY());
10736  endface1[3].SetX(line4[0].GetX());
10737  endface1[3].SetY(line4[0].GetY());
10738  endface1[4].SetX(line1[0].GetX());
10739  endface1[4].SetY(line1[0].GetY());
10740 
10741  endface2[0].SetX(line1[1].GetX());
10742  endface2[0].SetY(line1[1].GetY());
10743  endface2[1].SetX(line2[1].GetX());
10744  endface2[1].SetY(line2[1].GetY());
10745  endface2[2].SetX(line3[1].GetX());
10746  endface2[2].SetY(line3[1].GetY());
10747  endface2[3].SetX(line4[1].GetX());
10748  endface2[3].SetY(line4[1].GetY());
10749  endface2[4].SetX(line1[1].GetX());
10750  endface2[4].SetY(line1[1].GetY());
10751 
10752  gVirtualX->DrawPolyLine(2,line2);
10753  gVirtualX->DrawPolyLine(2,line3);
10754  gVirtualX->DrawPolyLine(2,line4);
10755  gVirtualX->DrawPolyLine(5,endface1);
10756  gVirtualX->DrawPolyLine(5,endface2);
10757  }
10758  c->Clear();
10759  c->cd();
10760  TH1 *hp = h3->Project3D("y");
10761  xaxis->SetRange(firstX,lastX);
10762  zaxis->SetRange(firstZ,lastZ);
10763  if (hp) {
10764  hp->SetFillColor(38);
10765  if (nbins == 1)
10766  hp->SetTitle(TString::Format("ProjectionY of binx=%d [x=%.1f..%.1f] binz=%d [z=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
10767  binz, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz)));
10768  else
10769  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),
10770  binz, binz2, zaxis->GetBinLowEdge(binz), zaxis->GetBinUpEdge(binz2) ) );
10771  hp->SetXTitle(fH->GetYaxis()->GetTitle());
10772  hp->SetYTitle("Number of Entries");
10773  hp->Draw(fShowOption.Data());
10774  }
10775  }
10776  break;
10777 
10778  case 3:
10779  // "z"
10780  {
10781  Int_t firstX = xaxis->GetFirst();
10782  Int_t lastX = xaxis->GetLast();
10783  Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
10784  Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
10785  xaxis->SetRange(binx,binx2);
10786  Int_t firstY = yaxis->GetFirst();
10787  Int_t lastY = yaxis->GetLast();
10788  Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
10789  Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
10790  yaxis->SetRange(biny,biny2);
10791  if (line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
10792  if (nbins>1 && line1[0].GetX()) {
10793  gVirtualX->DrawPolyLine(2,line2);
10794  gVirtualX->DrawPolyLine(2,line3);
10795  gVirtualX->DrawPolyLine(2,line4);
10796  gVirtualX->DrawPolyLine(5,endface1);
10797  gVirtualX->DrawPolyLine(5,endface2);
10798  }
10799  xx[0] = xaxis->GetBinCenter(binx);
10800  xx[1] = yaxis->GetBinCenter(biny);
10801  xx[2] = zaxis->GetXmin();
10802  view->WCtoNDC(xx,u);
10803  line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10804  line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10805  xx[2] = zaxis->GetXmax();
10806  view->WCtoNDC(xx,u);
10807  line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10808  line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10809  gVirtualX->DrawPolyLine(2,line1);
10810  if (nbins>1) {
10811  xx[2] = zaxis->GetXmin();
10812  xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10813  xx[0] = xaxis->GetBinCenter(binx);
10814  view->WCtoNDC(xx,u);
10815  line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10816  line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10817  xx[2] = zaxis->GetXmax();
10818  view->WCtoNDC(xx,u);
10819  line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10820  line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10821 
10822  xx[2] = zaxis->GetXmin();
10823  xx[1] = yaxis->GetBinCenter(biny+nbins-1);
10824  xx[0] = xaxis->GetBinCenter(binx+nbins-1);
10825  view->WCtoNDC(xx,u);
10826  line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10827  line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10828  xx[2] = zaxis->GetXmax();
10829  view->WCtoNDC(xx,u);
10830  line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10831  line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10832 
10833  xx[2] = zaxis->GetXmin();
10834  xx[1] = yaxis->GetBinCenter(biny);
10835  xx[0] = xaxis->GetBinCenter(binx+nbins-1);
10836  view->WCtoNDC(xx,u);
10837  line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10838  line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10839  xx[2] = zaxis->GetXmax();
10840  view->WCtoNDC(xx,u);
10841  line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10842  line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10843 
10844  endface1[0].SetX(line1[0].GetX());
10845  endface1[0].SetY(line1[0].GetY());
10846  endface1[1].SetX(line2[0].GetX());
10847  endface1[1].SetY(line2[0].GetY());
10848  endface1[2].SetX(line3[0].GetX());
10849  endface1[2].SetY(line3[0].GetY());
10850  endface1[3].SetX(line4[0].GetX());
10851  endface1[3].SetY(line4[0].GetY());
10852  endface1[4].SetX(line1[0].GetX());
10853  endface1[4].SetY(line1[0].GetY());
10854 
10855  endface2[0].SetX(line1[1].GetX());
10856  endface2[0].SetY(line1[1].GetY());
10857  endface2[1].SetX(line2[1].GetX());
10858  endface2[1].SetY(line2[1].GetY());
10859  endface2[2].SetX(line3[1].GetX());
10860  endface2[2].SetY(line3[1].GetY());
10861  endface2[3].SetX(line4[1].GetX());
10862  endface2[3].SetY(line4[1].GetY());
10863  endface2[4].SetX(line1[1].GetX());
10864  endface2[4].SetY(line1[1].GetY());
10865 
10866  gVirtualX->DrawPolyLine(2,line2);
10867  gVirtualX->DrawPolyLine(2,line3);
10868  gVirtualX->DrawPolyLine(2,line4);
10869  gVirtualX->DrawPolyLine(5,endface1);
10870  gVirtualX->DrawPolyLine(5,endface2);
10871  }
10872  c->Clear();
10873  c->cd();
10874  TH1 *hp = h3->Project3D("z");
10875  xaxis->SetRange(firstX,lastX);
10876  yaxis->SetRange(firstY,lastY);
10877  if (hp) {
10878  hp->SetFillColor(38);
10879  if (nbins == 1)
10880  hp->SetTitle(TString::Format("ProjectionZ of binx=%d [x=%.1f..%.1f] biny=%d [y=%.1f..%.1f]", binx, xaxis->GetBinLowEdge(binx), xaxis->GetBinUpEdge(binx),
10881  biny, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny)));
10882  else
10883  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),
10884  biny, biny2, yaxis->GetBinLowEdge(biny), yaxis->GetBinUpEdge(biny2) ) );
10885  hp->SetXTitle(fH->GetZaxis()->GetTitle());
10886  hp->SetYTitle("Number of Entries");
10887  hp->Draw(fShowOption.Data());
10888  }
10889  }
10890  break;
10891 
10892  case 4:
10893  // "xy"
10894  {
10895  Int_t first = zaxis->GetFirst();
10896  Int_t last = zaxis->GetLast();
10897  Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
10898  Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10899  zaxis->SetRange(binz,binz2);
10900  if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
10901  if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
10902  xx[0] = xaxis->GetXmin();
10903  xx[1] = yaxis->GetXmax();
10904  xx[2] = zaxis->GetBinCenter(binz);
10905  view->WCtoNDC(xx,u);
10906  rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10907  rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10908  rect1[4].SetX(rect1[0].GetX());
10909  rect1[4].SetY(rect1[0].GetY());
10910  xx[0] = xaxis->GetXmax();
10911  view->WCtoNDC(xx,u);
10912  rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10913  rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10914  xx[1] = yaxis->GetXmin();
10915  view->WCtoNDC(xx,u);
10916  rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10917  rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
10918  xx[0] = xaxis->GetXmin();
10919  view->WCtoNDC(xx,u);
10920  rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10921  rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
10922  gVirtualX->DrawPolyLine(5,rect1);
10923  if (nbins>1) {
10924  xx[0] = xaxis->GetXmin();
10925  xx[1] = yaxis->GetXmax();
10926  xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10927  view->WCtoNDC(xx,u);
10928  rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10929  rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10930  rect2[4].SetX(rect2[0].GetX());
10931  rect2[4].SetY(rect2[0].GetY());
10932  xx[0] = xaxis->GetXmax();
10933  view->WCtoNDC(xx,u);
10934  rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10935  rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10936  xx[1] = yaxis->GetXmin();
10937  view->WCtoNDC(xx,u);
10938  rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10939  rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
10940  xx[0] = xaxis->GetXmin();
10941  view->WCtoNDC(xx,u);
10942  rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10943  rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
10944  gVirtualX->DrawPolyLine(5,rect2);
10945  }
10946 
10947  c->Clear();
10948  c->cd();
10949  TH2 *hp = (TH2*)h3->Project3D("xy");
10950  zaxis->SetRange(first,last);
10951  if (hp) {
10952  hp->SetFillColor(38);
10953  if (nbins==1)hp->SetTitle(TString::Format("ProjectionXY of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
10954  else hp->SetTitle(TString::Format("ProjectionXY, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
10955  hp->SetXTitle(fH->GetYaxis()->GetTitle());
10956  hp->SetYTitle(fH->GetXaxis()->GetTitle());
10957  hp->SetZTitle("Number of Entries");
10958  hp->Draw(fShowOption.Data());
10959  }
10960  }
10961  break;
10962 
10963  case 5:
10964  // "yx"
10965  {
10966  Int_t first = zaxis->GetFirst();
10967  Int_t last = zaxis->GetLast();
10968  Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
10969  Int_t binz2 = TMath::Min(binz+nbins-1,zaxis->GetNbins() );
10970  zaxis->SetRange(binz,binz2);
10971  if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
10972  if (nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
10973  xx[0] = xaxis->GetXmin();
10974  xx[1] = yaxis->GetXmax();
10975  xx[2] = zaxis->GetBinCenter(binz);
10976  view->WCtoNDC(xx,u);
10977  rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10978  rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
10979  rect1[4].SetX(rect1[0].GetX());
10980  rect1[4].SetY(rect1[0].GetY());
10981  xx[0] = xaxis->GetXmax();
10982  view->WCtoNDC(xx,u);
10983  rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10984  rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
10985  xx[1] = yaxis->GetXmin();
10986  view->WCtoNDC(xx,u);
10987  rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10988  rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
10989  xx[0] = xaxis->GetXmin();
10990  view->WCtoNDC(xx,u);
10991  rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
10992  rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
10993  gVirtualX->DrawPolyLine(5,rect1);
10994  if (nbins>1) {
10995  xx[0] = xaxis->GetXmin();
10996  xx[1] = yaxis->GetXmax();
10997  xx[2] = zaxis->GetBinCenter(binz+nbins-1);
10998  view->WCtoNDC(xx,u);
10999  rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11000  rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11001  rect2[4].SetX(rect2[0].GetX());
11002  rect2[4].SetY(rect2[0].GetY());
11003  xx[0] = xaxis->GetXmax();
11004  view->WCtoNDC(xx,u);
11005  rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11006  rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11007  xx[1] = yaxis->GetXmin();
11008  view->WCtoNDC(xx,u);
11009  rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11010  rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11011  xx[0] = xaxis->GetXmin();
11012  view->WCtoNDC(xx,u);
11013  rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11014  rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11015  gVirtualX->DrawPolyLine(5,rect2);
11016  }
11017  c->Clear();
11018  c->cd();
11019  TH2 *hp = (TH2*)h3->Project3D("yx");
11020  zaxis->SetRange(first,last);
11021  if (hp) {
11022  hp->SetFillColor(38);
11023  if (nbins==1)hp->SetTitle(TString::Format("ProjectionYX of binz=%d [z=%.1f..%.f]", binz,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz)));
11024  else hp->SetTitle(TString::Format("ProjectionYX, binz=[%d,%d] [z=%.1f..%.1f]", binz,binz2,zaxis->GetBinLowEdge(binz),zaxis->GetBinUpEdge(binz2)));
11025  hp->SetXTitle(fH->GetXaxis()->GetTitle());
11026  hp->SetYTitle(fH->GetYaxis()->GetTitle());
11027  hp->SetZTitle("Number of Entries");
11028  hp->Draw(fShowOption.Data());
11029  }
11030  }
11031  break;
11032 
11033  case 6:
11034  // "xz"
11035  {
11036  Int_t first = yaxis->GetFirst();
11037  Int_t last = yaxis->GetLast();
11038  Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11039  Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11040  yaxis->SetRange(biny,biny2);
11041  if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11042  if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11043  xx[0] = xaxis->GetXmin();
11044  xx[2] = zaxis->GetXmax();
11045  xx[1] = yaxis->GetBinCenter(biny);
11046  view->WCtoNDC(xx,u);
11047  rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11048  rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11049  rect1[4].SetX(rect1[0].GetX());
11050  rect1[4].SetY(rect1[0].GetY());
11051  xx[0] = xaxis->GetXmax();
11052  view->WCtoNDC(xx,u);
11053  rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11054  rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11055  xx[2] = zaxis->GetXmin();
11056  view->WCtoNDC(xx,u);
11057  rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11058  rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11059  xx[0] = xaxis->GetXmin();
11060  view->WCtoNDC(xx,u);
11061  rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11062  rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11063  gVirtualX->DrawPolyLine(5,rect1);
11064  if (nbins>1) {
11065  xx[0] = xaxis->GetXmin();
11066  xx[2] = zaxis->GetXmax();
11067  xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11068  view->WCtoNDC(xx,u);
11069  rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11070  rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11071  rect2[4].SetX(rect2[0].GetX());
11072  rect2[4].SetY(rect2[0].GetY());
11073  xx[0] = xaxis->GetXmax();
11074  view->WCtoNDC(xx,u);
11075  rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11076  rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11077  xx[2] = zaxis->GetXmin();
11078  view->WCtoNDC(xx,u);
11079  rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11080  rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11081  xx[0] = xaxis->GetXmin();
11082  view->WCtoNDC(xx,u);
11083  rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11084  rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11085  gVirtualX->DrawPolyLine(5,rect2);
11086  }
11087  c->Clear();
11088  c->cd();
11089  TH2 *hp = (TH2*)h3->Project3D("xz");
11090  yaxis->SetRange(first,last);
11091  if (hp) {
11092  hp->SetFillColor(38);
11093  if (nbins==1)hp->SetTitle(TString::Format("ProjectionXZ of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11094  else hp->SetTitle(TString::Format("ProjectionXZ, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11095  hp->SetXTitle(fH->GetZaxis()->GetTitle());
11096  hp->SetYTitle(fH->GetXaxis()->GetTitle());
11097  hp->SetZTitle("Number of Entries");
11098  hp->Draw(fShowOption.Data());
11099  }
11100  }
11101  break;
11102 
11103  case 7:
11104  // "zx"
11105  {
11106  Int_t first = yaxis->GetFirst();
11107  Int_t last = yaxis->GetLast();
11108  Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
11109  Int_t biny2 = TMath::Min(biny+nbins-1,yaxis->GetNbins() );
11110  yaxis->SetRange(biny,biny2);
11111  if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11112  if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11113  xx[0] = xaxis->GetXmin();
11114  xx[2] = zaxis->GetXmax();
11115  xx[1] = yaxis->GetBinCenter(biny);
11116  view->WCtoNDC(xx,u);
11117  rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11118  rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11119  rect1[4].SetX(rect1[0].GetX());
11120  rect1[4].SetY(rect1[0].GetY());
11121  xx[0] = xaxis->GetXmax();
11122  view->WCtoNDC(xx,u);
11123  rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11124  rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11125  xx[2] = zaxis->GetXmin();
11126  view->WCtoNDC(xx,u);
11127  rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11128  rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11129  xx[0] = xaxis->GetXmin();
11130  view->WCtoNDC(xx,u);
11131  rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11132  rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11133  gVirtualX->DrawPolyLine(5,rect1);
11134  if (nbins>1) {
11135  xx[0] = xaxis->GetXmin();
11136  xx[2] = zaxis->GetXmax();
11137  xx[1] = yaxis->GetBinCenter(biny+nbins-1);
11138  view->WCtoNDC(xx,u);
11139  rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11140  rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11141  rect2[4].SetX(rect2[0].GetX());
11142  rect2[4].SetY(rect2[0].GetY());
11143  xx[0] = xaxis->GetXmax();
11144  view->WCtoNDC(xx,u);
11145  rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11146  rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11147  xx[2] = zaxis->GetXmin();
11148  view->WCtoNDC(xx,u);
11149  rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11150  rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11151  xx[0] = xaxis->GetXmin();
11152  view->WCtoNDC(xx,u);
11153  rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11154  rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11155  gVirtualX->DrawPolyLine(5,rect2);
11156  }
11157  c->Clear();
11158  c->cd();
11159  TH2 *hp = (TH2*)h3->Project3D("zx");
11160  yaxis->SetRange(first,last);
11161  if (hp) {
11162  hp->SetFillColor(38);
11163  if (nbins==1)hp->SetTitle(TString::Format("ProjectionZX of biny=%d [y=%.1f..%.f]", biny,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny)));
11164  else hp->SetTitle(TString::Format("ProjectionZX, biny=[%d,%d] [y=%.1f..%.1f]", biny,biny2,yaxis->GetBinLowEdge(biny),yaxis->GetBinUpEdge(biny2)));
11165  hp->SetXTitle(fH->GetXaxis()->GetTitle());
11166  hp->SetYTitle(fH->GetZaxis()->GetTitle());
11167  hp->SetZTitle("Number of Entries");
11168  hp->Draw(fShowOption.Data());
11169  }
11170  }
11171  break;
11172 
11173  case 8:
11174  // "yz"
11175  {
11176  Int_t first = xaxis->GetFirst();
11177  Int_t last = xaxis->GetLast();
11178  Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11179  Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11180  xaxis->SetRange(binx,binx2);
11181  if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11182  if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11183  xx[2] = zaxis->GetXmin();
11184  xx[1] = yaxis->GetXmax();
11185  xx[0] = xaxis->GetBinCenter(binx);
11186  view->WCtoNDC(xx,u);
11187  rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11188  rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11189  rect1[4].SetX(rect1[0].GetX());
11190  rect1[4].SetY(rect1[0].GetY());
11191  xx[2] = zaxis->GetXmax();
11192  view->WCtoNDC(xx,u);
11193  rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11194  rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11195  xx[1] = yaxis->GetXmin();
11196  view->WCtoNDC(xx,u);
11197  rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11198  rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11199  xx[2] = zaxis->GetXmin();
11200  view->WCtoNDC(xx,u);
11201  rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11202  rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11203  gVirtualX->DrawPolyLine(5,rect1);
11204  if (nbins>1) {
11205  xx[2] = zaxis->GetXmin();
11206  xx[1] = yaxis->GetXmax();
11207  xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11208  view->WCtoNDC(xx,u);
11209  rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11210  rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11211  rect2[4].SetX(rect2[0].GetX());
11212  rect2[4].SetY(rect2[0].GetY());
11213  xx[2] = zaxis->GetXmax();
11214  view->WCtoNDC(xx,u);
11215  rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11216  rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11217  xx[1] = yaxis->GetXmin();
11218  view->WCtoNDC(xx,u);
11219  rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11220  rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11221  xx[2] = zaxis->GetXmin();
11222  view->WCtoNDC(xx,u);
11223  rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11224  rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11225  gVirtualX->DrawPolyLine(5,rect2);
11226  }
11227  c->Clear();
11228  c->cd();
11229  TH2 *hp = (TH2*)h3->Project3D("yz");
11230  xaxis->SetRange(first,last);
11231  if (hp) {
11232  hp->SetFillColor(38);
11233  if (nbins==1)hp->SetTitle(TString::Format("ProjectionYZ of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11234  else hp->SetTitle(TString::Format("ProjectionYZ, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11235  hp->SetXTitle(fH->GetZaxis()->GetTitle());
11236  hp->SetYTitle(fH->GetYaxis()->GetTitle());
11237  hp->SetZTitle("Number of Entries");
11238  hp->Draw(fShowOption.Data());
11239  }
11240  }
11241  break;
11242 
11243  case 9:
11244  // "zy"
11245  {
11246  Int_t first = xaxis->GetFirst();
11247  Int_t last = xaxis->GetLast();
11248  Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
11249  Int_t binx2 = TMath::Min(binx+nbins-1,xaxis->GetNbins() );
11250  xaxis->SetRange(binx,binx2);
11251  if (rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
11252  if (nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
11253  xx[2] = zaxis->GetXmin();
11254  xx[1] = yaxis->GetXmax();
11255  xx[0] = xaxis->GetBinCenter(binx);
11256  view->WCtoNDC(xx,u);
11257  rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11258  rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11259  rect1[4].SetX(rect1[0].GetX());
11260  rect1[4].SetY(rect1[0].GetY());
11261  xx[2] = zaxis->GetXmax();
11262  view->WCtoNDC(xx,u);
11263  rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11264  rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11265  xx[1] = yaxis->GetXmin();
11266  view->WCtoNDC(xx,u);
11267  rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11268  rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11269  xx[2] = zaxis->GetXmin();
11270  view->WCtoNDC(xx,u);
11271  rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11272  rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11273  gVirtualX->DrawPolyLine(5,rect1);
11274  if (nbins>1) {
11275  xx[2] = zaxis->GetXmin();
11276  xx[1] = yaxis->GetXmax();
11277  xx[0] = xaxis->GetBinCenter(binx+nbins-1);
11278  view->WCtoNDC(xx,u);
11279  rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11280  rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
11281  rect2[4].SetX(rect2[0].GetX());
11282  rect2[4].SetY(rect2[0].GetY());
11283  xx[2] = zaxis->GetXmax();
11284  view->WCtoNDC(xx,u);
11285  rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11286  rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
11287  xx[1] = yaxis->GetXmin();
11288  view->WCtoNDC(xx,u);
11289  rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11290  rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
11291  xx[2] = zaxis->GetXmin();
11292  view->WCtoNDC(xx,u);
11293  rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
11294  rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
11295  gVirtualX->DrawPolyLine(5,rect2);
11296  }
11297  c->Clear();
11298  c->cd();
11299  TH2 *hp = (TH2*)h3->Project3D("zy");
11300  xaxis->SetRange(first,last);
11301  if (hp) {
11302  hp->SetFillColor(38);
11303  if (nbins==1)hp->SetTitle(TString::Format("ProjectionZY of binx=%d [x=%.1f..%.f]", binx,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx)));
11304  else hp->SetTitle(TString::Format("ProjectionZY, binx=[%d,%d] [x=%.1f..%.1f]", binx,binx2,xaxis->GetBinLowEdge(binx),xaxis->GetBinUpEdge(binx2)));
11305  hp->SetXTitle(fH->GetYaxis()->GetTitle());
11306  hp->SetYTitle(fH->GetZaxis()->GetTitle());
11307  hp->SetZTitle("Number of Entries");
11308  hp->Draw(fShowOption.Data());
11309  }
11310  }
11311  break;
11312  }
11313  c->Update();
11314  padsav->cd();
11315 }
Double_t * fYbuf
Definition: THistPainter.h:59
void PaintGrapHist(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a histogram.
Definition: TGraph.cxx:1977
virtual void SetZTitle(const char *title)
Definition: TH1.h:407
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile2D histogram.
Definition: TProfile2D.cxx:790
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual Double_t GetMaximumStored() const
Definition: TH1.h:283
virtual void SetLineWidth(Width_t lwidth)
Set the line width.
Definition: TAttLine.h:43
const Int_t kMAXCONTOUR
static TString gStringKurtosisX
virtual Float_t GetTickLength() const
Definition: TAttAxis.h:44
int ncy
Definition: THbookFile.cxx:91
void SurfaceProperty(Double_t qqa, Double_t qqd, Double_t qqs, Int_t nnqs, Int_t &irep)
Set surface property coefficients.
int AxisPos
Axis position.
Definition: Hoption.h:59
Color_t GetStatColor() const
Definition: TStyle.h:241
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
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:7807
virtual void PaintFrame()
Calculate range and clear pad (canvas).
Style_t GetTitleFont(Option_t *axis="X") const
Return title font.
Definition: TStyle.cxx:843
void SetBarWidth(Float_t barwidth=0.5)
Definition: TStyle.h:311
void SetX(SCoord_t x)
Definition: TPoint.h:49
virtual void SetAlpha(Float_t a)
Definition: TColor.h:66
An array of TObjects.
Definition: TObjArray.h:37
static TString gStringUnderflow
float xmin
Definition: THbookFile.cxx:93
void SetOptFit(Int_t fit=1)
Set the fit option.
Definition: TPaveStats.cxx:294
To draw a Crown.
Definition: TCrown.h:19
virtual void PaintArrows(Option_t *option)
Control function to draw a table as an arrow plot
virtual void SetName(const char *name="")
Definition: TPave.h:72
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:467
Int_t FindBin(Double_t x, Double_t y, Double_t z=0)
Returns the bin number of the bin at the given coordinate.
Definition: TH2Poly.cxx:562
virtual void Draw(Option_t *option="")
Draw this pavetext with its current attributes.
Definition: TPaveText.cxx:234
virtual void SetLogy(Int_t value=1)=0
auto * tt
Definition: textangle.C:16
virtual void PaintStat2(Int_t dostat, TF1 *fit)
Draw the statistics box for 2D histograms.
Int_t yfirst
first bin number along Y
Definition: Hparam.h:45
void LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
Draw stack of lego-plots in cartesian coordinates.
static TString gStringMeanX
virtual void PaintContour(Option_t *option)
Control function to draw a 2D histogram as a contour plot.
virtual Int_t GetLogy() const =0
Int_t GetFirst() const
Return first bin on the axis i.e.
Definition: TAxis.cxx:444
Double_t factor
multiplication factor (normalization)
Definition: Hparam.h:39
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
virtual void SetMaximum(Double_t maximum=-1111)
Definition: TH1.h:390
Double_t * GetX() const
Definition: TPolyLine.h:54
virtual void PaintH3Box(Int_t iopt)
Control function to draw a 3D histogram with boxes.
auto * m
Definition: textangle.C:8
virtual Int_t GetLogz() const =0
short Style_t
Definition: RtypesCore.h:76
virtual TH1 * Project3D(Option_t *option="x") const
Project a 3-d histogram into 1 or 2-d histograms depending on the option parameter, which may contain a combination of the characters x,y,z,e.
Definition: TH3.cxx:2201
void SetColorDark(Color_t color, Int_t n=0)
Store dark color for stack number n.
Bool_t IsHorizontal()
Definition: TCandle.h:116
const Int_t kMaxCuts
Definition: THistPainter.h:38
int Char
"CHAR" Draw 2D plot with a character set.
Definition: Hoption.h:41
Double_t Log(Double_t x)
Definition: TMath.h:648
Double_t ylowedge
low edge of axis
Definition: Hparam.h:32
Color_t GetTitleTextColor() const
Definition: TStyle.h:256
virtual Double_t GetBinError(Int_t bin) const
Returns the value of error associated to bin number bin.
Definition: TH2Poly.cxx:775
Double_t GetX2() const
Definition: TBox.h:53
Int_t GetNumberContours() const
Definition: TStyle.h:225
static TString gStringMean
void PaintGraph(Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
Draw the (x,y) as a graph.
Definition: TGraph.cxx:1968
TLine * line
Histogram option structure.
Definition: Hoption.h:24
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Computes distance from point (px,py) to the object.
Definition: TObject.cxx:186
float Float_t
Definition: RtypesCore.h:53
static TString gStringSkewnessX
virtual Float_t GetLabelOffset() const
Definition: TAttAxis.h:40
static TString gStringSkewnessZ
virtual void PaintTH2PolyColorLevels(Option_t *option)
Control function to draw a TH2Poly as a color plot.
const char Option_t
Definition: RtypesCore.h:62
virtual Double_t * GetRmax()=0
virtual Float_t GetBarOffset() const
Definition: TH1.h:250
void SetIsoSurfaceParameters(Double_t fmin, Double_t fmax, Int_t ncolor, Int_t ic1, Int_t ic2, Int_t ic3)
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:504
Int_t GetBinNumber() const
Definition: TH2Poly.h:37
return c1
Definition: legend1.C:41
float ymin
Definition: THbookFile.cxx:93
virtual Int_t GetNumberFreeParameters() const
Return the number of free parameters.
Definition: TF1.cxx:1785
int BackBox
= 0 to suppress the back box
Definition: Hoption.h:56
Create a Box.
Definition: TBox.h:24
Random number generator class based on the maximally quidistributed combined Tausworthe generator by ...
Definition: TRandom2.h:27
int Scat
"SCAT" Draw 2D plot a Scatter plot.
Definition: Hoption.h:47
THistPainter()
Default constructor.
Double_t GetHistTopMargin() const
Definition: TStyle.h:223
virtual Double_t GetMinimumStored() const
Definition: TH1.h:287
virtual Double_t GetNormFactor() const
Definition: TH1.h:295
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:1922
int Proj
1: Aitoff, 2: Mercator, 3: Sinusoidal, 4: Parabolic
Definition: Hoption.h:58
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:2328
virtual void SetContour(Int_t nlevels, const Double_t *levels=0)
Set the number and values of contour levels.
Definition: TH1.cxx:7748
R__EXTERN TStyle * gStyle
Definition: TStyle.h:402
virtual void Update()=0
#define mark(osub)
Definition: triangle.c:1206
int Axis
"A" Axis are not drawn around the graph.
Definition: Hoption.h:27
#define BIT(n)
Definition: Rtypes.h:78
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...
THist< 1, float, THistStatContent, THistStatUncertainty > TH1F
Definition: THist.hxx:285
TH1 * h
Definition: legend2.C:5
Definition: Rtypes.h:58
int Logy
log scale in Y. Also set by histogram option
Definition: Hoption.h:67
virtual void Paint(Option_t *option="")
Paint this crown with its current attributes.
Definition: TCrown.cxx:181
virtual Double_t GetSumOfWeights() const
Return the sum of weights excluding under/overflows.
Definition: TH1.cxx:7232
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4763
fill
Definition: fit1_py.py:6
static TString gStringIntegralBinWidth
virtual void SetHistogram(TH1 *h)
Set current histogram to h
A TMultiGraph is a collection of TGraph (or derived) objects.
Definition: TMultiGraph.h:35
TVectorT.
Definition: TMatrixTBase.h:77
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition: TH1.cxx:7256
virtual void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: TList.cxx:97
See TView3D.
Definition: TView.h:25
virtual TText * AddText(Double_t x1, Double_t y1, const char *label)
Add a new Text line to this pavetext at given coordinates.
Definition: TPaveText.cxx:183
void InitRaster(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Int_t nx, Int_t ny)
Initialize hidden lines removal algorithm (RASTER SCREEN)
void 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 SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
int Pie
"PIE" Draw 1D plot as a pie chart.
Definition: Hoption.h:51
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:2288
virtual Double_t GetMeanError(Int_t axis=1) const
Return standard error of mean of this histogram along the X axis.
Definition: TH1.cxx:6923
virtual Int_t GetNbinsZ() const
Definition: TH1.h:293
virtual void SetMinimum(Double_t minimum=-1111)
Definition: TH1.h:391
#define gROOT
Definition: TROOT.h:402
static constexpr double bar
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:6892
Float_t GetEndErrorSize() const
Definition: TStyle.h:171
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:585
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
int ParseOption(char *optin)
Parsing of the option-string.
Definition: TCandle.cxx:244
virtual void PaintTH2PolyBins(Option_t *option)
Control function to draw a TH2Poly bins&#39; contours.
virtual void SetTitle(const char *title="")
Change the title of the axis.
Definition: TGaxis.cxx:2472
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition: TSystem.cxx:1829
void ColorFunction(Int_t nl, Double_t *fl, Int_t *icl, Int_t &irep)
Set correspondance between function and color levels.
Basic string class.
Definition: TString.h:125
static Bool_t AddDirectoryStatus()
Static function: cannot be inlined on Windows/NT.
Definition: TH1.cxx:705
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:567
virtual Int_t PaintInit()
Compute histogram parameters used by the drawing routines.
virtual void Paint2DErrors(Option_t *option)
Draw 2D histograms errors.
virtual void ImportAxisAttributes(TAxis *axis)
Internal method to import TAxis attributes to this TGaxis.
Definition: TGaxis.cxx:688
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:168
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition: TH2.cxx:1187
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1099
int Int_t
Definition: RtypesCore.h:41
virtual void SetYTitle(const char *title)
Definition: TH1.h:406
bool Bool_t
Definition: RtypesCore.h:59
Double_t GetY2() const
Definition: TBox.h:55
void SetBarOffset(Float_t baroff=0.5)
Definition: TStyle.h:310
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition: TColor.h:72
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:39
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside one of the graphs 0 otherwise.
const Int_t kCARTESIAN
Definition: TView3D.cxx:32
static TString gStringStdDevZ
int Text
"TEXT" Draw 2D plot with the content of each cell.
Definition: Hoption.h:49
The histogram statistics painter class.
Definition: TPaveStats.h:18
virtual Double_t GetParError(Int_t ipar) const
Return value of parameter number ipar.
Definition: TF1.cxx:1815
user specified contour levels
Definition: TH1.h:161
void SetHistogram(TH1D *proj)
Definition: TCandle.h:127
An abstract interface to image processing library.
Definition: TImage.h:29
virtual Float_t GetLabelSize() const
Definition: TAttAxis.h:41
virtual void SetPoint(Int_t point, Double_t x, Double_t y)
Set point number n to (x, y) If n is greater than the current size, the arrays are automatically exte...
Definition: TPolyLine.cxx:638
virtual void SetMinimum(Double_t minimum=-1111)
Set the minimum value along Y for this function In case the function is already drawn, set also the minimum in the helper histogram.
Definition: TF1.cxx:3294
int Contour
"CONT" Draw 2D plot as a Contour plot.
Definition: Hoption.h:43
virtual Double_t GetBinLowEdge(Int_t bin) const
Return bin lower edge for 1D histogram.
Definition: TH1.cxx:8408
void Paint(Option_t *option)
Paint a TGraphDelaunay according to the value of "option":
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Double_t zmin
minimum value along Z
Definition: Hparam.h:37
Float_t GetTitleY() const
Definition: TStyle.h:265
TAxis * fYaxis
Definition: THistPainter.h:52
Double_t ymin
minimum value along y
Definition: Hparam.h:33
Profile Histogram.
Definition: TProfile.h:32
virtual void SetX2(Double_t x2)
Definition: TBox.h:64
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.
Double_t zmax
maximum value along Z
Definition: Hparam.h:38
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
static constexpr double rad
void InitMoveScreen(Double_t xmin, Double_t xmax)
Initialize "MOVING SCREEN" method.
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition: TColor.h:50
int Logx
log scale in X. Also set by histogram option
Definition: Hoption.h:66
don&#39;t draw the histogram title
Definition: TH1.h:165
Helper class to represent a bin in the TH2Poly histogram.
Definition: TH2Poly.h:25
const char * GetFitFormat() const
Definition: TStyle.h:185
void SetY(SCoord_t y)
Definition: TPoint.h:50
virtual void SetImageQuality(EImageQuality lquality)
Definition: TAttImage.h:99
Short_t Abs(Short_t d)
Definition: TMathBase.h:108
Double_t ymax
maximum value along y
Definition: Hparam.h:34
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
static TString gStringMeanZ
virtual TVirtualPad * cd(Int_t subpadnumber=0)=0
virtual Width_t GetLineWidth() const
Return the line width.
Definition: TAttLine.h:35
virtual void SetImage(const Double_t *, UInt_t, UInt_t, TImagePalette *=0)
Definition: TImage.h:116
virtual void PaintColorLevelsFast(Option_t *option)
Rendering scheme for the COL2 and COLZ2 options
double cos(double)
don&#39;t draw stats box
Definition: TH1.h:160
void Reset()
Definition: TCollection.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:624
void SetOption(CandleOption opt)
Definition: TCandle.h:121
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:627
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
static constexpr double mg
double beta(double x, double y)
Calculates the beta function.
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
Int_t GetOptFit() const
Return the fit option.
Definition: TPaveStats.cxx:257
virtual void PaintHist(Option_t *option)
Control routine to draw 1D histograms
virtual void PaintTriangles(Option_t *option)
Control function to draw a table using Delaunay triangles.
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition: TH1.cxx:1225
if object in a list can be deleted
Definition: TObject.h:58
virtual Double_t GetBinUpEdge(Int_t bin) const
Return up edge of bin.
Definition: TAxis.cxx:514
virtual Double_t Integral(Option_t *option="") const
Return integral of bin contents.
Definition: TH3.cxx:1213
virtual Style_t GetMarkerStyle() const
Return the marker style.
Definition: TAttMarker.h:32
static void SetF3(TF3 *f3)
Static function Store pointer to current implicit function.
virtual void SetRangeUser(Double_t ufirst, Double_t ulast)
Set the viewing range for the axis from ufirst to ulast (in user coordinates).
Definition: TAxis.cxx:928
void DefineGridLevels(Int_t ndivz)
Define the grid levels drawn in the background of surface and lego plots.
virtual void SetTextFont(Font_t tfont=62)
Set the text font.
Definition: TAttText.h:45
Int_t GetTitleAlign()
Definition: TStyle.h:254
virtual void PaintPalette()
Paint the color palette on the right side of the pad.
virtual Style_t GetLineStyle() const
Return the line style.
Definition: TAttLine.h:34
virtual Int_t GetDimension() const
Definition: TH1.h:277
void LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots in polar coordinates.
virtual Int_t GetContour(Double_t *levels=0)
Return contour values into array levels if pointer levels is non zero.
Definition: TH1.cxx:7676
static struct mg_connection * fc(struct mg_context *ctx)
Definition: civetweb.c:1956
virtual Int_t GetNDF() const
Return the number of degrees of freedom in the fit the fNDF parameter has been previously computed du...
Definition: TF1.cxx:1774
virtual Double_t GetPsi()=0
CandleOption
Definition: TCandle.h:28
Sequenceable collection abstract base class.
Double_t GetXmin() const
Definition: TAxis.h:133
static const double x2[5]
Double_t GetYsize()
Return size of the formula along Y in pad coordinates.
Definition: TLatex.cxx:2601
virtual void Paint(Option_t *)
Paint a Pie chart in a canvas.
Definition: TPie.cxx:803
virtual void PaintBoxes(Option_t *option)
Control function to draw a 2D histogram as a box plot
Graphical cut class.
Definition: TCutG.h:20
Double_t x[n]
Definition: legend1.C:17
int Surf
"SURF" Draw as a Surface (SURF,Surf=1, SURF1,Surf=11, SURF2,Surf=12)
Definition: Hoption.h:48
virtual void Paint(Option_t *chopt="")
Draw this graph with its current attributes.
Definition: TGraph.cxx:1959
virtual Double_t GetBinEntries(Int_t bin) const
Return bin entries of a Profile histogram.
Definition: TProfile.cxx:814
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)
TH1 * GetHistogram()
Definition: TPaletteAxis.h:51
Float_t GetTitleFontSize() const
Definition: TStyle.h:258
virtual void ProcessMessage(const char *mess, const TObject *obj)
Process message mess.
virtual void PaintCandlePlot(Option_t *option)
Control function to draw a 2D histogram as a candle (box) plot or violin plot
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:2365
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) ...
static TVirtualPadEditor * GetPadEditor(Bool_t load=kTRUE)
Returns the pad editor dialog. Static method.
TCutG * fCuts[kMaxCuts]
Definition: THistPainter.h:62
const char * GetBinTitle(Int_t bin) const
Returns the bin title.
Definition: TH2Poly.cxx:801
void Class()
Definition: Class.C:29
virtual Bool_t GetTimeDisplay() const
Definition: TAxis.h:126
virtual void Paint(Option_t *option="")
Paint this pavetext with its current attributes.
Definition: TPaveText.cxx:411
const Double_t * GetBuffer() const
Definition: TH1.h:233
int Line
"L" A simple polyline beetwen every point is drawn.
Definition: Hoption.h:34
void LightSource(Int_t nl, Double_t yl, Double_t xscr, Double_t yscr, Double_t zscr, Int_t &irep)
Set light source.
void SetCandleWidth(const Double_t width)
Definition: TCandle.h:125
void SetHistoWidth(const Double_t width)
Definition: TCandle.h:126
virtual void SetStatFormat(const char *format="6.4g")
Change (i.e. set) the format for printing statistics.
Definition: TPaveStats.cxx:312
void SetMesh(Int_t mesh=1)
virtual void PaintSurface(Option_t *option)
Control function to draw a 2D histogram as a surface plot.
virtual void PaintStat(Int_t dostat, TF1 *fit)
Draw the statistics box for 1D and profile histograms.
To draw Mathematical Formula.
Definition: TLatex.h:18
THashList * GetLabels() const
Definition: TAxis.h:117
Int_t GetOptFit() const
Definition: TStyle.h:228
virtual Int_t GetLogx() const =0
virtual const char * GetStatFormat() const
Definition: TPaveStats.h:36
Double_t Log10(Double_t x)
Definition: TMath.h:651
void SetOption(Option_t *option="")
To set axis options.
Definition: TGaxis.cxx:2464
Bool_t IsCandleScaled()
Definition: TCandle.cxx:185
int Mark
"P" The current Marker is drawn at each point
Definition: Hoption.h:35
constexpr Double_t DegToRad()
Definition: TMath.h:64
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:464
polygon * polys
Definition: X3DBuffer.c:22
virtual Int_t MakeCuts(char *cutsopt)
Decode string choptin and fill Graphical cuts structure.
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondance with function levels)
virtual void SetMarkerColor(Color_t mcolor=1)
Set the marker color.
Definition: TAttMarker.h:38
virtual Int_t MakeChopt(Option_t *option)
Decode string choptin and fill Hoption structure.
virtual void PaintH3(Option_t *option="")
Control function to draw a 3D histograms.
int FrontBox
= 0 to suppress the front box
Definition: Hoption.h:55
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 Double_t * GetTnorm()=0
virtual TSeqCollection * GetOutline()=0
void SetTimeFormat(const char *tformat)
Change the format used for time plotting.
Definition: TGaxis.cxx:2499
virtual Size_t GetMarkerSize() const
Return the marker size.
Definition: TAttMarker.h:33
virtual void Clear(Option_t *option="")
Clear all lines in this pavetext.
Definition: TPaveText.cxx:209
Base class for several text objects.
Definition: TText.h:23
virtual void PaintColorLevels(Option_t *option)
Control function to draw a 2D histogram as a color plot.
Double_t GetXMax()
Returns the maximum value for the x coordinates of the bin.
Definition: TH2Poly.cxx:1368
Double_t baroffset
offset of bin for bars or legos [0,1]
Definition: Hparam.h:41
Float_t GetStatX() const
Definition: TStyle.h:248
TAxis * fZaxis
Definition: THistPainter.h:53
virtual Bool_t IsInside(Int_t x, Int_t y)
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
Float_t GetTitleX() const
Definition: TStyle.h:264
virtual void Show()
Double_t GetYMin()
Returns the minimum value for the y coordinates of the bin.
Definition: TH2Poly.cxx:1476
void ImplicitFunction(Double_t *rmin, Double_t *rmax, Int_t nx, Int_t ny, Int_t nz, const char *chopt)
Draw implicit function FUN(X,Y,Z) = 0 in cartesian coordinates using hidden surface removal algorithm...
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)
Double_t GetYMax()
Returns the maximum value for the y coordinates of the bin.
Definition: TH2Poly.cxx:1440
XFontStruct * id
Definition: TGX11.cxx:108
void LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots in cylindrical coordinates.
Float_t GetBarWidth() const
Definition: TStyle.h:169
Int_t xfirst
first bin number along X
Definition: Hparam.h:43
TH1F * h1
Definition: legend1.C:5
Int_t GetColorPalette(Int_t i) const
Return color number i in current palette.
Definition: TStyle.cxx:735
constexpr Double_t Pi()
Definition: TMath.h:40
virtual void PaintLatex(Double_t x, Double_t y, Double_t angle, Double_t size, const char *text)
Main drawing function.
Definition: TLatex.cxx:2042
virtual void ExecuteRotateView(Int_t event, Int_t px, Int_t py)=0
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:49
virtual Double_t GetMaximumStored() const
Definition: TF1.h:457
Style_t GetStatStyle() const
Definition: TStyle.h:246
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) ...
virtual void PaintTH2PolyScatterPlot(Option_t *option)
Control function to draw a TH2Poly as a scatter plot.
const Int_t kSPHERICAL
virtual const char * GetTimeFormat() const
Definition: TAxis.h:127
int Fill
"F" A fill area is drawn ("CF" draw a smooth fill area).
Definition: Hoption.h:31
The 3-D histogram classes derived from the 1-D histogram classes.
Definition: TH3.h:31
virtual void PaintTH2PolyText(Option_t *option)
Control function to draw a TH2Poly as a text plot.
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 SetLabelSize(Float_t labelsize)
Definition: TGaxis.h:108
TList * fFunctions
Definition: THistPainter.h:54
short Color_t
Definition: RtypesCore.h:79
virtual Double_t GetSkewness(Int_t axis=1) const
Definition: TH1.cxx:6997
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
static TString gStringKurtosisZ
virtual Int_t GetNdivisions() const
Definition: TAttAxis.h:36
virtual void SetTextAlign(Short_t align=11)
Set the text alignment.
Definition: TAttText.h:41
int Bar
"B" A Bar chart is drawn at each point.
Definition: Hoption.h:28
static Bool_t SupportAlpha()
Static function returning "true" if transparency is supported.
Definition: TCanvas.cxx:2235
virtual Option_t * GetDrawOption() const
Get option used by the graphics system to draw this object.
Definition: TObject.cxx:341
virtual Double_t GetBinContent(Int_t bin) const
Returns the content of the input bin For the overflow/underflow/sea bins: -1 | -2 | -3 ---+----+---- ...
Definition: TH2Poly.cxx:762
Definition: TPoint.h:31
A doubly linked list.
Definition: TList.h:44
virtual void GetMinimumAndMaximum(Double_t &min, Double_t &max) const
Retrieve the minimum and maximum values in the histogram.
Definition: TH1.cxx:7988
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition: TColor.h:77
virtual Double_t GetStdDevError(Int_t axis=1) const
Return error of standard deviation estimation for Normal distribution.
Definition: TH1.cxx:6984
virtual const char * GetParName(Int_t ipar) const
Definition: TF1.h:513
TObject * GetPolygon() const
Definition: TH2Poly.h:38
virtual EBinErrorOpt GetBinErrorOption() const
Definition: TH1.h:267
Bool_t AreEqualRel(Double_t af, Double_t bf, Double_t relPrec)
Definition: TMath.h:322
Float_t GetErrorX() const
Definition: TStyle.h:172
virtual void SetLogx(Int_t value=1)=0
const char * GetPaintTextFormat() const
Definition: TStyle.h:234
void SetDrawFace(DrawFaceFunc_t pointer)
Store pointer to current algorithm to draw faces.
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
static TString gStringEntries
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:169
virtual void SetOutlineToCube()=0
virtual Int_t PaintInitH()
Compute histogram parameters used by the drawing routines for a rotated pad.
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:1890
Int_t fN
Definition: TArray.h:38
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
virtual void RecalculateRange()
Recompute the histogram range following graphics operations.
virtual void SetRange(Int_t first=0, Int_t last=0)
Set the viewing range for the axis from bin first to last.
Definition: TAxis.cxx:903
float ymax
Definition: THbookFile.cxx:93
static TString gStringStdDevY
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:738
const Int_t kPOLAR
Definition: TView3D.cxx:33
void SetColorMain(Color_t color, Int_t n=0)
Store color for stack number n.
int Spec
TSpectrum graphics.
Definition: Hoption.h:60
void IsoSurface(Int_t ns, Double_t *s, Int_t nx, Int_t ny, Int_t nz, Double_t *x, Double_t *y, Double_t *z, const char *chopt)
Draw set of iso-surfaces for a scalar function defined on a grid.
void FrontBox(Double_t ang)
Draw front surfaces of surrounding box & axes.
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
virtual void PaintText(Option_t *option)
Control function to draw a 1D/2D histograms with the bin values.
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:124
virtual Int_t TableInit()
Initialize various options to draw 2D histograms.
ROOT::R::TRInterface & r
Definition: Object.C:4
Int_t GetLast() const
Return last bin on the axis i.e.
Definition: TAxis.cxx:455
Service class for 2-Dim histogram classes.
Definition: TH2.h:30
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Evaluate the distance to the chart in gPad.
Definition: TPie.cxx:169
Double_t GetXsize()
Return size of the formula along X in pad coordinates.
Definition: TLatex.cxx:2514
Class to manage histogram axis.
Definition: TAxis.h:30
virtual Double_t GetKurtosis(Int_t axis=1) const
Definition: TH1.cxx:7067
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
Float_t GetTitleH() const
Definition: TStyle.h:267
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2969
Int_t fShowProjection
Definition: THistPainter.h:64
SVector< double, 2 > v
Definition: Dict.h:5
Double_t ybinsize
bin size in case of equidistant bins
Definition: Hparam.h:31
Style_t GetStatFont() const
Definition: TStyle.h:244
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
auto * a
Definition: textangle.C:12
A 3-Dim function with parameters.
Definition: TF3.h:28
virtual void PaintTF3()
Control function to draw a 3D implicit functions.
Float_t GetStatY() const
Definition: TStyle.h:249
Double_t GetContent() const
Definition: TH2Poly.h:35
void LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots spheric coordinates.
virtual Font_t GetTextFont() const
Return the text font.
Definition: TAttText.h:35
TClass * Class()
Float_t GetStatW() const
Definition: TStyle.h:250
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:249
virtual char * GetObjectInfo(Int_t px, Int_t py) const
Display the histogram info (bin number, contents, integral up to bin corresponding to cursor position...
The candle plot painter class.
Definition: TCandle.h:25
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual void Paint(Option_t *option="")
Control routine to paint any kind of histograms
Double_t * GetY() const
Definition: TPolyLine.h:55
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void SetTextAngle(Float_t tangle=0)
Set the text angle.
Definition: TAttText.h:42
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:8477
Bool_t GetHistMinimumZero() const
Definition: TStyle.h:222
void SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in cylindrical coordinates.
virtual void PaintStat3(Int_t dostat, TF1 *fit)
Draw the statistics box for 3D histograms.
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual Float_t GetTitleOffset() const
Definition: TAttAxis.h:42
virtual void Paint(Option_t *option="")
Paint all objects in this collection.
static TImagePalette * CreateCOLPalette(Int_t nContours)
Factory method to creates an image palette for histogram plotting.
Definition: TAttImage.cxx:748
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:386
virtual void PaintTable(Option_t *option)
Control function to draw 2D/3D histograms (tables).
TString fShowOption
Definition: THistPainter.h:65
virtual void Clear(Option_t *option="")=0
short Short_t
Definition: RtypesCore.h:35
int Arrow
"ARR" Draw 2D plot with Arrows.
Definition: Hoption.h:39
virtual ~THistPainter()
Default destructor.
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:1751
virtual void PaintH3Iso()
Control function to draw a 3D histogram with Iso Surfaces.
The axis painter class.
Definition: TGaxis.h:24
virtual void SetMarkerStyle(Style_t mstyle=1)
Set the marker style.
Definition: TAttMarker.h:40
virtual Double_t GetContourLevelPad(Int_t level) const
Return the value of contour number "level" in Pad coordinates.
Definition: TH1.cxx:7705
TAxis * GetYaxis()
Definition: TH1.h:316
Double_t xlowedge
low edge of axis
Definition: Hparam.h:28
float xmax
Definition: THbookFile.cxx:93
virtual void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute the actions corresponding to event.
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:354
virtual void SetFitFormat(const char *format="5.4g")
Change (i.e. set) the format for printing fit parameters in statistics box.
Definition: TPaveStats.cxx:286
virtual const char * GetFitFormat() const
Definition: TPaveStats.h:35
int Color
"COL" Draw 2D plot with Colored boxes.
Definition: Hoption.h:42
void SetLog(int x, int y, int z)
Definition: TCandle.h:122
void SetName(const char *name)
Definition: TCollection.h:202
A 2-Dim function with parameters.
Definition: TF2.h:29
virtual void PaintBar(Option_t *option)
Draw a bar-chart in a normal pad.
virtual Double_t GetXmin() const
Definition: TF1.h:536
1-D histogram with a double per channel (see TH1 documentation)}
Definition: TH1.h:610
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:4665
Definition: graph.py:1
Int_t GetNumberOfColors() const
Return number of colors in the color palette.
Definition: TStyle.cxx:801
virtual void PaintFunction(Option_t *option)
Paint functions associated to an histogram.
int Error
"E" Draw Errors with current marker type and size.
Definition: Hoption.h:30
void DrawLevelLines(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw level lines without hidden line removal.
Int_t ylast
last bin number along Y
Definition: Hparam.h:46
virtual Int_t GetDistancetoAxis(Int_t axis, Int_t px, Int_t py, Double_t &ratio)=0
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
virtual void PaintBox(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Option_t *option="")
Draw this box with new coordinates.
Definition: TBox.cxx:627
virtual void SetMarkerSize(Size_t msize=1)
Set the marker size.
Definition: TAttMarker.h:41
virtual Double_t * GetRmin()=0
Linear Algebra Package.
#define gVirtualX
Definition: TVirtualX.h:350
constexpr Double_t E()
Definition: TMath.h:74
virtual TObjLink * FirstLink() const
Definition: TList.h:108
int Curve
"C" A smooth Curve is drawn.
Definition: Hoption.h:29
virtual void PaintAxis(Bool_t drawGridOnly=kFALSE)
Draw axis (2D case) of an histogram.
virtual void PaintBarH(Option_t *option)
Draw a bar char in a rotated pad (X vertical, Y horizontal)
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
virtual void Paint(Option_t *option="")
Paint one candle with its current attributes.
Definition: TCandle.cxx:674
Double_t Cos(Double_t)
Definition: TMath.h:550
Color_t GetTitleFillColor() const
Definition: TStyle.h:255
void SetLegoFunction(LegoFunc_t pointer)
Store pointer to current lego function.
short Width_t
Definition: RtypesCore.h:78
Hoption_t Hoption
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:7892
errors with Normal (Wald) approximation: errorUp=errorLow= sqrt(N)
Definition: TH1.h:62
const Bool_t kFALSE
Definition: RtypesCore.h:88
The histogram painter class.
Definition: THistPainter.h:47
virtual Color_t GetLineColor() const
Return the line color.
Definition: TAttLine.h:33
Int_t fCutsOpt[kMaxCuts]
Definition: THistPainter.h:61
virtual void SetMaximum(Double_t maximum=-1111)
Set the maximum value along Y for this function In case the function is already drawn, set also the maximum in the helper histogram.
Definition: TF1.cxx:3281
void SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in spheric coordinates.
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:279
virtual void ExecuteEvent(Int_t, Int_t, Int_t)
Execute the mouse events.
Definition: TPie.cxx:394
virtual void SetY2(Double_t y2)
Definition: TBox.h:66
int Hist
"HIST" Draw only the histogram.
Definition: Hoption.h:45
long Long_t
Definition: RtypesCore.h:50
Width_t GetTitleBorderSize() const
Definition: TStyle.h:259
Float_t GetTitleW() const
Definition: TStyle.h:266
virtual Int_t GetSumw2N() const
Definition: TH1.h:309
Double_t GetChisquare() const
Definition: TF1.h:428
virtual void Paint(Option_t *option="")
This method must be overridden if a class wants to paint itself.
Definition: TObject.cxx:519
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:1334
virtual void SetRange(Double_t xmin, Double_t xmax)
Initialize the upper and lower bounds to draw the function.
Definition: TF2.h:150
long Candle
"CANDLE" Draw a 2D histogram as candle/box plot or violin plot (also with "VIOLIN").
Definition: Hoption.h:52
void SetLabelOffset(Float_t labeloffset)
Definition: TGaxis.h:107
virtual void PaintLegoAxis(TGaxis *axis, Double_t ang)
Draw the axis for legos and surface plots.
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width for 1D histogram.
Definition: TH1.cxx:8419
virtual Double_t Rndm()
TausWorth generator from L&#39;Ecuyer, uses as seed 3x32bits integers Use a mask of 0xffffffffUL to make ...
Definition: TRandom2.cxx:56
const Int_t kCYLINDRICAL
static const double x1[5]
Double_t xbinsize
bin size in case of equidistant bins
Definition: Hparam.h:27
A Pave (see TPave) with text, lines or/and boxes inside.
Definition: TPaveText.h:21
#define ClassImp(name)
Definition: Rtypes.h:359
static TString gStringSkewness
Double_t GetX1() const
Definition: TBox.h:52
int Zero
if selected with any LEGO option the empty bins are not drawn.
Definition: Hoption.h:61
virtual Double_t GetBinErrorLow(Int_t bin) const
Return lower error associated to bin number bin.
Definition: TH1.cxx:8335
double Double_t
Definition: RtypesCore.h:55
Int_t GetOptStat() const
Definition: TStyle.h:229
TGraph2DPainter * fGraph2DPainter
Definition: THistPainter.h:56
The Legos and Surfaces painter class.
TText * text
virtual void ShowProjectionX(Int_t px, Int_t py)
Show projection onto X.
int Box
"BOX" Draw 2D plot with proportional Boxes.
Definition: Hoption.h:40
Double_t * fXbuf
Definition: THistPainter.h:58
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
unsigned long ULong_t
Definition: RtypesCore.h:51
int Func
"FUNC" Draw only the function (for example in case of fit).
Definition: Hoption.h:44
Int_t GetOptStat() const
Return the stat option.
Definition: TPaveStats.cxx:266
Double_t y[n]
Definition: legend1.C:17
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its associated colors.
Definition: TColor.cxx:1689
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
static void SetF3ClippingBoxOn(Double_t xclip, Double_t yclip, Double_t zclip)
Static function Set the implicit function clipping box "on" and define the clipping box...
virtual Double_t GetXmax() const
Definition: TF1.h:540
virtual Color_t GetFillColor() const
Return the fill area color.
Definition: TAttFill.h:30
Double_t ey[n]
Definition: legend1.C:17
TGraphDelaunay2D generates a Delaunay triangulation of a TGraph2D.
Double_t GetMinimum() const
Returns the minimum value of the histogram.
Definition: TH2Poly.cxx:859
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:570
The TH1 histogram class.
Definition: TH1.h:56
Int_t xlast
last bin number along X
Definition: Hparam.h:44
static constexpr double s
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
virtual Double_t GetEntries() const
Return the current number of entries.
Definition: TH1.cxx:4178
void SetEdgeAtt(Color_t color=1, Style_t style=1, Width_t width=1, Int_t n=0)
Draw a Pie Chart,.
Definition: TPie.h:23
Abstract base class used by ROOT graphics editor.
The color creation and management class.
Definition: TColor.h:19
THist< 2, double, THistStatContent, THistStatUncertainty > TH2D
Definition: THist.hxx:290
virtual void Paint(Option_t *option="")
Paint this 2-D function with its current attributes.
Definition: TF2.cxx:698
virtual void PaintTitle()
Draw the histogram title.
TList * GetContourList(Double_t contour)
Returns the X and Y graphs building a contour.
Width_t GetStatBorderSize() const
Definition: TStyle.h:243
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:2887
int List
= 1 to generate the TObjArray "contours"
Definition: Hoption.h:57
void Spectrum(Int_t nl, Double_t fmin, Double_t fmax, Int_t ic, Int_t idc, Int_t &irep)
Set Spectrum.
A class to define a conversion from pixel values to pixel color.
Definition: TAttImage.h:33
Profile2D histograms are used to display the mean value of Z and its RMS for each cell in X...
Definition: TProfile2D.h:27
virtual const char * GetTimeFormatOnly() const
Return only the time format from the string fTimeFormat.
Definition: TAxis.cxx:557
virtual void SetLineStyle(Style_t lstyle)
Set the line style.
Definition: TAttLine.h:42
virtual void SetShowProjection(const char *option, Int_t nbins)
Set projection.
virtual void PaintLego(Option_t *option)
Control function to draw a 2D histogram as a lego plot.
virtual void ShowProjectionY(Int_t px, Int_t py)
Show projection onto Y.
int Off
"][" With H option, the first and last vertical lines are not drawn.
Definition: Hoption.h:32
TAxis * GetZaxis()
Definition: TH1.h:317
TList * fStack
Definition: THistPainter.h:63
virtual void Draw(Option_t *option="")
Draw this box with its current attributes.
Definition: TBox.cxx:180
TH1 * gCurrentHist
void BackBox(Double_t ang)
Draw back surfaces of surrounding box.
Mother of all ROOT objects.
Definition: TObject.h:37
virtual Int_t FindFixBin(Double_t x) const
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:405
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
constexpr Double_t RadToDeg()
Definition: TMath.h:60
virtual void DrawPanel()
Display a panel with all histogram drawing options.
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
Float_t GetStatFontSize() const
Definition: TStyle.h:245
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
Handle_t Window_t
Definition: GuiTypes.h:28
virtual Int_t GetNpar() const
Definition: TF1.h:465
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.
virtual void GetParLimits(Int_t ipar, Double_t &parmin, Double_t &parmax) const
Return limits for parameter ipar.
Definition: TF1.cxx:1825
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition: TAxis.cxx:526
void FindVisibleLine(Double_t *p1, Double_t *p2, Int_t ntmax, Int_t &nt, Double_t *t)
Find visible part of a line ("RASTER SCREEN")
virtual void SetXTitle(const char *title)
Definition: TH1.h:405
TList * GetListOfGraphs() const
Definition: TMultiGraph.h:69
TPainter3dAlgorithms * fLego
Definition: THistPainter.h:55
static TString gStringIntegral
virtual void Add(TObject *obj)
Definition: TList.h:87
auto * l
Definition: textangle.C:4
Double_t xmin
minimum value along X
Definition: Hparam.h:29
static TString gStringStdDevX
static TString gStringKurtosisY
const UInt_t kCannotRotate
virtual Double_t GetParameter(Int_t ipar) const
Definition: TF1.h:496
virtual void ShowProjection3(Int_t px, Int_t py)
Show projection (specified by fShowProjection) of a TH3.
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:200
Float_t GetStatH() const
Definition: TStyle.h:251
int Star
"*" A * is plotted at each point
Definition: Hoption.h:38
1-Dim function class
Definition: TF1.h:211
static void SetF3ClippingBoxOff()
Static function Set the implicit function clipping box "off".
static void PaintSpecialObjects(const TObject *obj, Option_t *option)
Static function to paint special objects like vectors and matrices.
virtual void PaintErrors(Option_t *option)
Draw 1D histograms error bars.
Double_t xmax
maximum value along X
Definition: Hparam.h:30
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) ...
A Graph is a graphics object made of two arrays X and Y with npoints each.
Definition: TGraph.h:41
Double_t Sin(Double_t)
Definition: TMath.h:547
static TString gStringKurtosis
Double_t GetArea()
Returns the area of the bin.
Definition: TH2Poly.cxx:1338
TF1 * f1
Definition: legend1.C:11
const Int_t kRAPIDITY
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
RooCmdArg Bins(Int_t nbin)
void SetTickSize(Float_t ticksize)
Definition: TGaxis.h:119
int System
type of coordinate system(1=car,2=pol,3=cyl,4=sph,5=psr)
Definition: Hoption.h:53
Defined by an array on N points in a 2-D space.
Definition: TPolyLine.h:23
#define snprintf
Definition: civetweb.c:822
THist< 1, double, THistStatContent, THistStatUncertainty > TH1D
Definition: THist.hxx:284
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH2.h:84
#define gPad
Definition: TVirtualPad.h:285
virtual Int_t DistancetoPrimitive(Int_t px, Int_t py)
Compute the distance from the point px,py to a line.
Bool_t IsViolinScaled()
Definition: TCandle.cxx:190
virtual void SetTextColor(Color_t tcolor=1)
Set the text color.
Definition: TAttText.h:43
auto * th2
Definition: textalign.C:17
virtual Double_t GetBinErrorUp(Int_t bin) const
Return upper error associated to bin number bin.
Definition: TH1.cxx:8366
virtual Int_t BufferEmpty(Int_t action=0)
Fill histogram with all entries in the buffer.
Definition: TH1.cxx:1346
virtual void PaintScatterPlot(Option_t *option)
Control function to draw a 2D histogram as a scatter plot.
Double_t GetY1() const
Definition: TBox.h:54
void Add(TObject *obj)
Definition: TObjArray.h:73
void SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in polar coordinates.
virtual void Paint(Option_t *option="")
Paint the pave stat.
Definition: TPaveStats.cxx:320
Float_t GetBarOffset() const
Definition: TStyle.h:168
Style_t GetTitleStyle() const
Definition: TStyle.h:257
The TGraphDelaunay painting class.
Double_t allchan
integrated sum of contents
Definition: Hparam.h:40
void ResetBit(UInt_t f)
Definition: TObject.h:171
void SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
Draw surface in cartesian coordinate system.
virtual TList * GetContourList(Double_t contour) const
Get a contour (as a list of TGraphs) using the Delaunay triangulation.
virtual void SetTitle(const char *title)
See GetStatOverflows for more information.
Definition: TH1.cxx:6154
void SetSurfaceFunction(SurfaceFunc_t pointer)
Store pointer to current surface function.
virtual Color_t GetMarkerColor() const
Return the marker color.
Definition: TAttMarker.h:31
Definition: first.py:1
def normal(shape, name=None)
virtual Int_t GetNbinsX() const
Definition: TH1.h:291
int Zscale
"Z" to display the Z scale (color palette)
Definition: Hoption.h:54
virtual Int_t IsInside(Double_t x, Double_t y) const
Return 1 if the point (x,y) is inside the polygon defined by the graph vertices 0 otherwise...
Definition: TGraph.cxx:1823
virtual void Paint(Option_t *option="")
Paint the palette.
virtual Style_t GetFillStyle() const
Return the fill area style.
Definition: TAttFill.h:31
Double_t Sqrt(Double_t x)
Definition: TMath.h:590
virtual void SetTextSize(Float_t tsize=1)
Set the text size.
Definition: TAttText.h:46
int Same
"S" Histogram is plotted in the current PAD.
Definition: Hoption.h:36
static TImage * Create()
Create an image.
Definition: TImage.cxx:36
Color_t GetStatTextColor() const
Definition: TStyle.h:242
static TString gStringStdDev
Int_t GetNbins() const
Definition: TAxis.h:121
static TString gStringSkewnessY
int ncx
Definition: THbookFile.cxx:91
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Int_t GetSize() const
Definition: TCollection.h:180
Histogram parameters structure.
Definition: Hparam.h:26
void SetTitleOffset(Float_t titleoffset=1)
Definition: TGaxis.h:125
TClass * Class()
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
Double_t GetXMin()
Returns the minimum value for the x coordinates of the bin.
Definition: TH2Poly.cxx:1404
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
TList * GetListOfFunctions() const
Definition: TH1.h:238
The palette painting class.
Definition: TPaletteAxis.h:29
THist< 2, float, THistStatContent, THistStatUncertainty > TH2F
Definition: THist.hxx:291
void SetHistogram(TH1 *h)
Definition: TPaletteAxis.h:57
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
static TString gStringMeanY
const Bool_t kTRUE
Definition: RtypesCore.h:87
Int_t Nint(T x)
Definition: TMath.h:606
virtual void PadRange(Int_t rback)=0
virtual Double_t GetStdDev(Int_t axis=1) const
Returns the Standard Deviation (Sigma).
Definition: TH1.cxx:6946
Double_t GetXmax() const
Definition: TAxis.h:134
Double_t ex[n]
Definition: legend1.C:17
Hparam_t Hparam
const Int_t n
Definition: legend1.C:16
virtual Int_t GetMaximumBin() const
Return location of bin with maximum value in the range.
Definition: TH1.cxx:7837
Double_t GetMaximum() const
Returns the maximum value of the histogram.
Definition: TH2Poly.cxx:811
clip to the frame boundary
Definition: TGraph.h:70
Double_t Tan(Double_t)
Definition: TMath.h:553
constexpr Double_t PiOver2()
Definition: TMath.h:48
virtual Float_t GetBarWidth() const
Definition: TH1.h:251
Long64_t BinarySearch(Long64_t n, const T *array, T value)
Definition: TMath.h:1092
Double_t barwidth
width of bin for bars and legos [0,1]
Definition: Hparam.h:42
void FillPolygonBorder(Int_t nn, Double_t *xy)
Fill a polygon including border ("RASTER SCREEN")
virtual void PaintH3BoxRaster()
Control function to draw a 3D histogram with boxes.
const TArrayD * GetXbins() const
Definition: TAxis.h:130
int Logz
log scale in Z. Also set by histogram option
Definition: Hoption.h:68
virtual void SetBorderSize(Int_t bordersize=4)
Definition: TPave.h:70
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
TAxis * GetXaxis()
Get the behaviour adopted by the object about the statoverflows. See EStatOverflows for more informat...
Definition: TH1.h:315
TGraphDelaunay generates a Delaunay triangulation of a TGraph2D.
TAxis * fXaxis
Definition: THistPainter.h:51
2D Histogram with Polygonal Bins
Definition: TH2Poly.h:66
const char * GetStatFormat() const
Definition: TStyle.h:247
static TString gStringOverflow
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual void DefineColorLevels(Int_t ndivz)
Define the color levels used to paint legos, surfaces etc..
virtual Int_t GetNbinsY() const
Definition: TH1.h:292
void SetParent(TObject *obj)
Definition: TPaveStats.h:52
virtual Double_t GetBinError(Int_t bin) const
Return value of error associated to bin number bin.
Definition: TH1.cxx:8319
int Lego
"LEGO" Draw as a Lego plot(LEGO,Lego=1, LEGO1,Lego1=11, LEGO2,Lego=12).
Definition: Hoption.h:46
void SetOptStat(Int_t stat=1)
Set the stat option.
Definition: TPaveStats.cxx:303
Int_t GetOptTitle() const
Definition: TStyle.h:230
const Int_t kNMAX
int Tri
"TRI" Draw 2D plot with Delaunay triangles.
Definition: Hoption.h:50
2-D histogram with a double per channel (see TH1 documentation)}
Definition: TH2.h:290
const char * Data() const
Definition: TString.h:345
void SetAxisPosition(const Double_t candlePos)
Definition: TCandle.h:123
Double_t ATan(Double_t)
Definition: TMath.h:577
static constexpr double g