THistPainter.cxx

Go to the documentation of this file.
00001 // @(#)root/histpainter:$Id: THistPainter.cxx 37620 2010-12-17 09:14:51Z couet $
00002 // Author: Rene Brun   26/08/99
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <stdio.h>
00015 #include <ctype.h>
00016 
00017 #include "Riostream.h"
00018 #include "TROOT.h"
00019 #include "TClass.h"
00020 #include "TSystem.h"
00021 #include "THistPainter.h"
00022 #include "TH2.h"
00023 #include "TH2Poly.h"
00024 #include "TH3.h"
00025 #include "TProfile.h"
00026 #include "THStack.h"
00027 #include "TF2.h"
00028 #include "TF3.h"
00029 #include "TCutG.h"
00030 #include "TMatrixDBase.h"
00031 #include "TMatrixFBase.h"
00032 #include "TVectorD.h"
00033 #include "TVectorF.h"
00034 #include "TPad.h"
00035 #include "TPaveStats.h"
00036 #include "TFrame.h"
00037 #include "TLatex.h"
00038 #include "TLine.h"
00039 #include "TPolyLine.h"
00040 #include "TPoints.h"
00041 #include "TStyle.h"
00042 #include "TGraph.h"
00043 #include "TMultiGraph.h"
00044 #include "TPie.h"
00045 #include "TGaxis.h"
00046 #include "TColor.h"
00047 #include "TPainter3dAlgorithms.h"
00048 #include "TGraph2DPainter.h"
00049 #include "TGraphDelaunay.h"
00050 #include "TView.h"
00051 #include "TMath.h"
00052 #include "TRandom.h"
00053 #include "TObjArray.h"
00054 #include "TVectorD.h"
00055 #include "Hoption.h"
00056 #include "Hparam.h"
00057 #include "TPluginManager.h"
00058 #include "TPaletteAxis.h"
00059 #include "TCrown.h"
00060 #include "TVirtualPadEditor.h"
00061 #include "TEnv.h"
00062 #include "TPoint.h"
00063 
00064 
00065 //______________________________________________________________________________
00066 /* Begin_Html
00067 <center><h2>The histogram painter class</h2></center>
00068 
00069 <ul>
00070 <li><a href="#HP00">Introduction</li></a>
00071 <li><a href="#HP01">Histograms' plotting options</li></a>
00072 <ul>
00073 <li><a href="#HP01a">Options supported for 1D and 2D histograms</li></a>
00074 <li><a href="#HP01b">Options supported for 1D histograms</li></a>
00075 <li><a href="#HP01c">Options supported for 2D histograms</li></a>
00076 <li><a href="#HP01d">Options supported for 3D histograms</li></a>
00077 <li><a href="#HP01e">Options supported for histograms' stacks (<tt>THStack</tt>)</li></a>
00078 </ul>
00079 <li><a href="#HP02">Setting the Style</li></a>
00080 <li><a href="#HP03">Setting line, fill, marker, and text attributes</li></a>
00081 <li><a href="#HP04">Setting Tick marks on the histogram axis</li></a>
00082 <li><a href="#HP05">Giving titles to the X, Y and Z axis</li></a>
00083 <li><a href="#HP060">The option "SAME"</li></a>
00084 <ul>
00085 <li><a href="#HP060a">Limitations</li></a>
00086 </ul>
00087 <li><a href="#HP06">Superimposing two histograms with different scales in the same pad</li></a>
00088 <li><a href="#HP07">Statistics Display</li></a>
00089 <li><a href="#HP08">Fit Statistics</li></a>
00090 <li><a href="#HP09">The error bars options</li></a>
00091 <li><a href="#HP100">The bar chart option</li></a>
00092 <li><a href="#HP10">The "BAR" and "HBAR" options</li></a>
00093 <li><a href="#HP11">The SCATter plot option (default for 2D histograms)</li></a>
00094 <li><a href="#HP12">The ARRow option</li></a>
00095 <li><a href="#HP13">The BOX option</li></a>
00096 <li><a href="#HP14">The COLor option</li></a>
00097 <li><a href="#HP15">The TEXT and TEXTnn Option</li></a>
00098 <li><a href="#HP16">The CONTour options</li></a>
00099 <ul>
00100 <li><a href="#HP16a">The LIST option</li></a>
00101 </ul>
00102 <li><a href="#HP17">The LEGO options</li></a>
00103 <li><a href="#HP18">The "SURFace" options</li></a>
00104 <li><a href="#HP19">Cylindrical, Polar, Spherical and PseudoRapidity/Phi options</li></a>
00105 <li><a href="#HP20">Base line for bar-charts and lego plots</li></a>
00106 <li><a href="#HP20a">TH2Poly Drawing</li></a>
00107 <li><a href="#HP21">The SPEC option</li></a>
00108 <li><a href="#HP22">Option "Z" : Adding the color palette on the right side of the pad</li></a>
00109 <li><a href="#HP23">Setting the color palette</li></a>
00110 <li><a href="#HP24">Drawing a sub-range of a 2-D histogram; the [cutg] option</li></a>
00111 <li><a href="#HP25">Drawing options for 3D histograms</li></a>
00112 <li><a href="#HP26">Drawing option for histograms' stacks</li></a>
00113 <li><a href="#HP27">Drawing of 3D implicit functions</li></a>
00114 <li><a href="#HP28">Associated functions drawing</li></a>
00115 <li><a href="#HP29">Drawing using OpenGL</li></a>
00116 <ul>
00117 <li><a href="#HP29a">General information: plot types and supported options</li></a>
00118 <li><a href="#HP29b">TH3 as boxes (spheres)</li></a>
00119 <li><a href="#HP29c">TH3 as iso-surface(s)</li></a>
00120 <li><a href="#HP29d">TF3 (implicit function)</li></a>
00121 <li><a href="#HP29e">Parametric surfaces</li></a>
00122 <li><a href="#HP29f">Interaction with the plots</li></a>
00123 <li><a href="#HP29g">Selectable parts</li></a>
00124 <li><a href="#HP29h">Rotation and zooming</li></a>
00125 <li><a href="#HP29i">Panning</li></a>
00126 <li><a href="#HP29j">Box cut</li></a>
00127 <li><a href="#HP29k">Plot specific interactions (dynamic slicing etc.)</li></a>
00128 <li><a href="#HP29l">Surface with option "GLSURF"</li></a>
00129 <li><a href="#HP29m">TF3</li></a>
00130 <li><a href="#HP29n">Box</li></a>
00131 <li><a href="#HP29o">Iso</li></a>
00132 <li><a href="#HP29p">Parametric plot</li></a>
00133 </ul>
00134 </ul>
00135 
00136 
00137 <a name="HP00"></a><h3>Introduction</h3>
00138 
00139 
00140 Histograms are drawn via the <tt>THistPainter</tt> class. Each histogram has a
00141 pointer to its own painter (to be usable in a multithreaded program). When the
00142 canvas has to be redrawn, the <tt>Paint</tt> function of each objects in the
00143 pad is called. In case of histograms, <tt>TH1::Paint</tt> invokes directly
00144 <tt>THistPainter::Paint</tt>.
00145 
00146 <p>To draw a histogram "<tt>h</tt>" is enough to do:
00147 <pre>
00148       h->Draw();
00149 </pre>
00150 "<tt>h</tt>" can be of any kind: 1D, 2D or 3D. To choose how the histogram will
00151 be drawn, the <tt>Draw()</tt> method can be invoked with an option. For instance
00152 to draw a 2D histogram as a lego plot it is enough to do:
00153 <pre>
00154       h->Draw("lego");
00155 </pre>
00156 <tt>THistPainter</tt> offers many options to paint 1D, 2D and 3D histograms.
00157 
00158 <p>When the <tt>Draw()</tt> method of a histogram is called for the first time
00159 (<tt>TH1::Draw</tt>), it creates a <tt>THistPainter</tt> object and saves a
00160 pointer to this "painter" as a data member of the histogram. The
00161 <tt>THistPainter</tt> class specializes in the drawing of histograms. It is
00162 separated from the histogram so that one can have histograms without the
00163 graphics overhead, for example in a batch program. Each histogram have its own
00164 painter rather than a central singleton painter painting all histograms, allows
00165 two histograms to be drawn in two threads without overwriting the painter's
00166 values.
00167 
00168 <p>When a displayed histogram is filled again, there is not need to call the
00169 <tt>Draw()</tt> method again; the image will be refreshed the next time the
00170 pad will be updated.
00171 
00172 <p>A pad is updated after one of these three actions:
00173 <ol>
00174 <li>  a carriage control on the ROOT command line,
00175 <li>  a click inside the pad,
00176 <li>  a call to <tt>TPad::Update</tt>.
00177 </ol>
00178 
00179 <p>By default a call to <tt>TH1::Draw()</tt> clears the pad of all objects
00180 before drawing the new image of the histogram. One can use the <tt>"SAME"</tt>
00181 option to leave the previous display intact and superimpose the new histogram.
00182 The same histogram can be drawn with different graphics options in different
00183 pads.
00184 
00185 <p>When a displayed histogram is deleted, its image is automatically removed
00186 from the pad.
00187 
00188 <p> To create a copy of the histogram when drawing it, one can use
00189 <tt>TH1::DrawClone()</tt>. This will clone the histogram and allow to change
00190 and delete the original one without affecting the clone.
00191 
00192 
00193 <a name="HP01"></a><h3>Histograms' plotting options</h3>
00194 
00195 
00196 Most options can be concatenated with or without spaces or commas, for example:
00197 <pre>
00198       h->Draw("E1 SAME");
00199 </pre>
00200 The options are not case sensitive:
00201 <pre>
00202       h->Draw("e1 same");
00203 </pre>
00204 
00205 The default drawing option can be set with <tt>TH1::SetOption</tt> and retrieve
00206 using <tt>TH1::GetOption</tt>:
00207 <pre>
00208       root [0] h->Draw();          // Draw "h" using the standard histogram representation.
00209       root [1] h->Draw("E");       // Draw "h" using error bars
00210       root [3] h->SetOption("E");  // Change the default drawing option for "h"
00211       root [4] h->Draw();          // Draw "h" using error bars
00212       root [5] h->GetOption();     // Retrieve the default drawing option for "h"
00213       (const Option_t* 0xa3ff948)"E"
00214 </pre>
00215 
00216 <a name="HP01a"></a><h4><u>Options supported for 1D and 2D histograms</u></h4>
00217 
00218 <table border=0>
00219 
00220 <tr><th valign=top>"AXIS"</th><td>
00221 Draw only axis.
00222 </td></tr>
00223 
00224 <tr><th valign=top>"AXIG"</th><td>
00225 Draw only grid (if the grid is requested).
00226 </td></tr>
00227 
00228 <tr><th valign=top>"HIST"</th><td>
00229 When an histogram has errors it is visualized by default with error bars. To
00230 visualize it without errors use the option "HIST" together with the required
00231 option (eg "hist same c").  The "HIST" option can also be used to plot only the
00232 histogram and not the associated function(s).
00233 </td></tr>
00234 
00235 <tr><th valign=top>"FUNC"</th><td>
00236 When an histogram has a fitted function, this option allows to draw the fit
00237 result only.
00238 </td></tr>
00239 
00240 <tr><th valign=top>"SAME"</th><td>
00241 Superimpose on previous picture in the same pad.
00242 </td></tr>
00243 
00244 <tr><th valign=top>"LEGO"</th><td>
00245 Draw a lego plot with hidden line removal.
00246 </td></tr>
00247 
00248 <tr><th valign=top>"LEGO1"</th><td>
00249 Draw a lego plot with hidden surface removal.
00250 </td></tr>
00251 
00252 <tr><th valign=top>"LEGO2"</th><td>
00253 Draw a lego plot using colors to show the cell contents When the option "0" is
00254 used with any LEGO option, the empty bins are not drawn.
00255 </td></tr>
00256 
00257 <tr><th valign=top>"TEXT"</th><td>
00258 Draw bin contents as text (format set via <tt>gStyle->SetPaintTextFormat</tt>).
00259 </td></tr>
00260 
00261 <tr><th valign=top>"TEXTnn"</th><td>
00262 Draw bin contents as text at angle nn (0 < nn < 90).
00263 </td></tr>
00264 
00265 <tr><th valign=top>"X+"</th><td>
00266 The X-axis is drawn on the top side of the plot.
00267 </td></tr>
00268 
00269 <tr><th valign=top>"Y+"</th><td>
00270 The Y-axis is drawn on the right side of the plot.
00271 </td></tr>
00272 
00273 </table>
00274 
00275 <a name="HP01b"></a><h4><u>Options supported for 1D histograms</u></h4>
00276 
00277 <table border=0>
00278 
00279 <tr><th valign=top>" "</th><td>
00280 Default.
00281 </td></tr>
00282 
00283 <tr><th valign=top>"AH"</th><td>
00284 Draw histogram without axis. "A" can be combined with any drawing option. For
00285 instance, "AC" draws the histogram as a smooth Curve without axis.
00286 </td></tr>
00287 
00288 <tr><th valign=top>"]["</th><td>
00289 When this option is selected the first and last vertical lines of the histogram
00290 are not drawn.
00291 </td></tr>
00292 
00293 <tr><th valign=top>"B"</th><td>
00294 Bar chart option.
00295 </td></tr>
00296 
00297 <tr><th valign=top>"BAR"</th><td>
00298 Like option "B", but bars can be drawn with a 3D effect.
00299 </td></tr>
00300 
00301 <tr><th valign=top>"HBAR"</th><td>
00302 Like option "BAR", but bars are drawn horizontally.
00303 </td></tr>
00304 
00305 <tr><th valign=top>"C"</th><td>
00306 Draw a smooth Curve through the histogram bins.
00307 </td></tr>
00308 
00309 <tr><th valign=top>"E"</th><td>
00310 Draw error bars.
00311 </td></tr>
00312 
00313 <tr><th valign=top>"E0"</th><td>
00314 Draw error bars. Markers are drawn for bins with 0 contents.
00315 </td></tr>
00316 
00317 <tr><th valign=top>"E1"</th><td>
00318 Draw error bars with perpendicular lines at the edges.
00319 </td></tr>
00320 
00321 <tr><th valign=top>"E2"</th><td>
00322 Draw error bars with rectangles.
00323 </td></tr>
00324 
00325 <tr><th valign=top>"E3"</th><td>
00326 Draw a fill area through the end points of the vertical error bars.
00327 </td></tr>
00328 
00329 <tr><th valign=top>"E4"</th><td>
00330 Draw a smoothed filled area through the end points of the error bars.
00331 </td></tr>
00332 
00333 <tr><th valign=top>"E5"</th><td>
00334 Like E3 but ignore the bins with 0 contents.
00335 </td></tr>
00336 
00337 <tr><th valign=top>"E6"</th><td>
00338 Like E4 but ignore the bins with 0 contents.
00339 </td></tr>
00340 
00341 <tr><th valign=top>"X0"</th><td>
00342 When used with one of the "E" option, it suppress the error bar along
00343 X as <tt>gStyle->SetErrorX(0)</tt> would do.
00344 </td></tr>
00345 
00346 <tr><th valign=top>"L"</th><td>
00347 Draw a line through the bin contents.
00348 </td></tr>
00349 
00350 <tr><th valign=top>"P"</th><td>
00351 Draw current marker at each bin except empty bins.
00352 </td></tr>
00353 
00354 <tr><th valign=top>"P0"</th><td>
00355 Draw current marker at each bin including empty bins.
00356 </td></tr>
00357 
00358 <tr><th valign=top>"PIE"</th><td>
00359 Draw histogram as a Pie Chart.
00360 </td></tr>
00361 
00362 <tr><th valign=top>"*H"</th><td>
00363 Draw histogram with a * at each bin.
00364 </td></tr>
00365 
00366 <tr><th valign=top>"LF2"</th><td>
00367 Draw histogram like with option "L" but with a fill area. Note that "L" draws
00368 also a fill area if the hist fill color is set but the fill area corresponds to
00369 the histogram contour.
00370 </td></tr>
00371 
00372 <tr><th valign=top>"9"</th><td>
00373 Force histogram to be drawn in high resolution mode. By default, the histogram
00374 is drawn in low resolution in case the number of bins is greater than the number
00375 of pixels in the current pad. This option should be combined with a "drawing
00376 option" like "H" or "L".
00377 </td></tr>
00378 
00379 </table>
00380 
00381 <a name="HP01c"></a><h4><u>Options supported for 2D histograms</u></h4>
00382 
00383 <table border=0>
00384 
00385 <tr><th valign=top>" "</th><td>
00386 Default (scatter plot).
00387 </td></tr>
00388 
00389 <tr><th valign=top>"ARR"</th><td>
00390 Arrow mode. Shows gradient between adjacent cells.
00391 </td></tr>
00392 
00393 <tr><th valign=top>"BOX"</th><td>
00394 A box is drawn for each cell with surface proportional to the content's
00395 absolute value. A negative content is marked with a X.
00396 </td></tr>
00397 
00398 <tr><th valign=top>"BOX1"</th><td>
00399 A button is drawn for each cell with surface proportional to content's absolute
00400 value. A sunken button is drawn for negative values a raised one for positive.
00401 </td></tr>
00402 
00403 <tr><th valign=top>"COL"</th><td>
00404 A box is drawn for each cell with a color scale varying with contents. All the
00405 none empty bins are painted. Empty bins are not painted unless some bins have
00406 a negative content because in that case the null bins might be not empty.
00407 </td></tr>
00408 
00409 <tr><th valign=top>"COLZ"</th><td>
00410 Same as "COL". In addition the color palette is also drawn.
00411 </td></tr>
00412 
00413 <tr><th valign=top>"CONT"</th><td>
00414 Draw a contour plot (same as CONT0).
00415 </td></tr>
00416 
00417 <tr><th valign=top>"CONT0"</th><td>
00418 Draw a contour plot using surface colors to distinguish contours.
00419 </td></tr>
00420 
00421 <tr><th valign=top>"CONT1"</th><td>
00422 Draw a contour plot using line styles to distinguish contours.
00423 </td></tr>
00424 
00425 <tr><th valign=top>"CONT2"</th><td>
00426 Draw a contour plot using the same line style for all contours.
00427 </td></tr>
00428 
00429 <tr><th valign=top>"CONT3"</th><td>
00430 Draw a contour plot using fill area colors.
00431 </td></tr>
00432 
00433 <tr><th valign=top>"CONT4"</th><td>
00434 Draw a contour plot using surface colors (SURF option at theta = 0).
00435 </td></tr>
00436 
00437 <tr><th valign=top>"CONT5"</th><td>
00438 (TGraph2D only) Draw a contour plot using Delaunay triangles.
00439 </td></tr>
00440 
00441 <tr><th valign=top>"LIST"</th><td>
00442 Generate a list of TGraph objects for each contour.
00443 </td></tr>
00444 
00445 <tr><th valign=top>"CYL"</th><td>
00446 Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y
00447 coordinate on the cylinder length.
00448 </td></tr>
00449 
00450 <tr><th valign=top>"POL"</th><td>
00451 Use Polar coordinates. The X coordinate is mapped on the angle and the Y
00452 coordinate on the radius.
00453 </td></tr>
00454 
00455 <tr><th valign=top>"SPH"</th><td>
00456 Use Spherical coordinates. The X coordinate is mapped on the latitude and the Y
00457 coordinate on the longitude.
00458 </td></tr>
00459 
00460 <tr><th valign=top>"PSR"</th><td>
00461 Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.
00462 </td></tr>
00463 
00464 <tr><th valign=top>"SURF"</th><td>
00465 Draw a surface plot with hidden line removal.
00466 </td></tr>
00467 
00468 <tr><th valign=top>"SURF1"</th><td>
00469 Draw a surface plot with hidden surface removal.
00470 </td></tr>
00471 
00472 <tr><th valign=top>"SURF2"</th><td>
00473 Draw a surface plot using colors to show the cell contents.
00474 </td></tr>
00475 
00476 <tr><th valign=top>"SURF3"</th><td>
00477 Same as SURF with in addition a contour view drawn on the top.
00478 </td></tr>
00479 
00480 <tr><th valign=top>"SURF4"</th><td>
00481 Draw a surface using Gouraud shading.
00482 </td></tr>
00483 
00484 <tr><th valign=top>"SURF5"</th><td>
00485 Same as SURF3 but only the colored contour is drawn. Used with option CYL, SPH
00486 or PSR it allows to draw colored contours on a sphere, a cylinder or a in
00487 pseudo rapidity space. In cartesian or polar coordinates, option SURF3 is used.
00488 </td></tr>
00489 
00490 <tr><th valign=top>"FB"</th><td>
00491 With LEGO or SURFACE, suppress the Front-Box.
00492 </td></tr>
00493 
00494 <tr><th valign=top>"BB"</th><td>
00495 With LEGO or SURFACE, suppress the Back-Box.
00496 </td></tr>
00497 
00498 <tr><th valign=top>"A"</th><td>
00499 With LEGO or SURFACE, suppress the axis.
00500 </td></tr>
00501 
00502 <tr><th valign=top>"SCAT"</th><td>
00503 Draw a scatter-plot (default).
00504 </td></tr>
00505 
00506 <tr><th valign=top>"[cutg]"</th><td>
00507 Draw only the sub-range selected by the TCutG named "cutg".
00508 </td></tr>
00509 
00510 </table>
00511 
00512 <a name="HP01d"></a><h4><u>Options supported for 3D histograms</u></h4>
00513 
00514 <table border=0>
00515 
00516 <tr><th valign=top>" "</th><td>
00517 Default (scatter plot).
00518 </td></tr>
00519 
00520 <tr><th valign=top>"ISO"</th><td>
00521 Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one
00522 surface at the value computed as follow:
00523 <tt>SumOfWeights/(NbinsX*NbinsY*NbinsZ)</tt>.
00524 </td></tr>
00525 
00526 <tr><th valign=top>"BOX"</th><td>
00527 Draw a for each cell with volume proportional to the content's absolute value.
00528 </td></tr>
00529 
00530 <tr><th valign=top>"LEGO"</th><td>
00531 Same as <tt>BOX</tt>.
00532 </td></tr>
00533 
00534 </table>
00535 
00536 <a name="HP01e"></a><h4><u>Options supported for histograms' stacks (<tt>THStack</tt>)</u></h4>
00537 
00538 <table border=0>
00539 
00540 <tr><th valign=top>" "</th><td>
00541 Default, the histograms are drawn on top of each other (as lego plots for 2D
00542 histograms).
00543 </td></tr>
00544 
00545 <tr><th valign=top>"NOSTACK"</th><td>
00546 Histograms in the stack are all paint in the same pad as if the option
00547 <tt>"SAME"</tt> had been specified.
00548 </td></tr>
00549 
00550 <tr><th valign=top>"PADS"</th><td>
00551 The current pad/canvas is subdivided into a number of pads equal to the number
00552 of histograms in the stack and each histogram is paint into a separate pad.
00553 </td></tr>
00554 
00555 </table>
00556 
00557 
00558 <a name="HP02"></a><h3>Setting the Style</h3>
00559 
00560 
00561 Histograms use the current style (<tt>gStyle</tt>). When one changes the current
00562 style and would like to propagate the changes to the histogram,
00563 <tt>TH1::UseCurrentStyle</tt> should be called. Call <tt>UseCurrentStyle</tt> on
00564 each histogram is needed.
00565 <br>
00566 To force all the histogram to use the current style use:
00567 <pre>
00568       gROOT->ForceStyle();
00569 </pre>
00570 All the histograms read after this call will use the current style.
00571 
00572 
00573 <a name="HP03"></a><h3>Setting line, fill, marker, and text attributes</h3>
00574 
00575 
00576 The histogram classes inherit from the attribute classes:
00577 <tt>TAttLine</tt>, <tt>TAttFill</tt>, <tt>TAttMarker</tt> and <tt>TAttText</tt>.
00578 See the description of these classes for the list of options.
00579 
00580 
00581 <a name="HP04"></a><h3>Setting Tick marks on the histogram axis</h3>
00582 
00583 
00584 The <tt>TPad::SetTicks</tt> method specifies the type of tick marks on the axis.
00585 If <tt> tx = gPad->GetTickx()</tt> and <tt>ty = gPad->GetTicky()</tt> then:
00586 <pre>
00587       tx = 1;   tick marks on top side are drawn (inside)
00588       tx = 2;   tick marks and labels on top side are drawn
00589       ty = 1;   tick marks on right side are drawn (inside)
00590       ty = 2;   tick marks and labels on right side are drawn
00591 </pre>
00592 By default only the left Y axis and X bottom axis are drawn
00593 (<tt>tx = ty = 0</tt>)
00594 
00595 <p><tt>TPad::SetTicks(tx,ty)</tt> allows to set these options.
00596 See also The <tt>TAxis</tt> functions to set specific axis attributes.
00597 
00598 <p>In case multiple color filled histograms are drawn on the same pad, the fill
00599 area may hide the axis tick marks. One can force a redraw of the axis over all
00600 the histograms by calling:
00601 <pre>
00602       gPad->RedrawAxis();
00603 </pre>
00604 
00605 
00606 <a name="HP05"></a><h3>Giving titles to the X, Y and Z axis</h3>
00607 
00608 
00609 <pre>
00610       h->GetXaxis()->SetTitle("X axis title");
00611       h->GetYaxis()->SetTitle("Y axis title");
00612 </pre>
00613 The histogram title and the axis titles can be any <tt>TLatex</tt> string.
00614 The titles are part of the persistent histogram.
00615 
00616 
00617 <a name="HP060"></a><h3>The option "SAME"</h3>
00618 
00619 
00620 By default, when an histogram is drawn, the current pad is cleared before
00621 drawing. In order to keep the previous drawing and draw on top of it the
00622 option <tt>"SAME"</tt> should be use. The histogram drawn with the option
00623 <tt>"SAME"</tt> uses the coordinates system available in the current pad.
00624 <p>
00625 This option can be used alone or combined with any valid drawing option but
00626 some combinations must be use with care.
00627 
00628 <a name="HP060a"></a><h4><u>Limitations</u></h4>
00629 <ul>
00630 <li>It does not work when
00631 combined with the <tt>"LEGO"</tt> and <tt>"SURF"</tt> options unless the
00632 histogram plotted with the option <tt>"SAME"</tt> has <u>exactly</u> the same
00633 ranges on the X, Y and Z axis as the currently drawn histogram. To superimpose
00634 lego plots <a href="#HP26">histograms' stacks</a> should be used.</li>
00635 </ul>
00636 
00637 <a name="HP06"></a><h3>Superimposing two histograms with different scales in the same pad</h3>
00638 
00639 
00640 The following example creates two histograms, the second histogram is the bins
00641 integral of the first one. It shows a procedure to draw the two histograms in
00642 the same pad and it draws the scale of the second histogram using a new vertical
00643 axis on the right side. See also the tutorial <tt>transpad.C</tt> for a variant
00644 of this example.
00645 
00646 End_Html
00647 Begin_Macro(source)
00648 {
00649    TCanvas *c1 = new TCanvas("c1","c1",600,400);
00650    // create/fill draw h1
00651    gStyle->SetOptStat(kFALSE);
00652    TH1F *h1 = new TH1F("h1","Superimposing two histograms with different scales",100,-3,3);
00653    Int_t i;
00654    for (i=0;i<10000;i++) h1->Fill(gRandom->Gaus(0,1));
00655    h1->Draw();
00656    c1->Update();
00657 
00658    // create hint1 filled with the bins integral of h1
00659    TH1F *hint1 = new TH1F("hint1","h1 bins integral",100,-3,3);
00660    Float_t sum = 0;
00661    for (i=1;i<=100;i++) {
00662       sum += h1->GetBinContent(i);
00663       hint1->SetBinContent(i,sum);
00664    }
00665 
00666    // scale hint1 to the pad coordinates
00667    Float_t rightmax = 1.1*hint1->GetMaximum();
00668    Float_t scale = gPad->GetUymax()/rightmax;
00669    hint1->SetLineColor(kRed);
00670    hint1->Scale(scale);
00671    hint1->Draw("same");
00672 
00673    // draw an axis on the right side
00674    TGaxis *axis = new TGaxis(gPad->GetUxmax(),gPad->GetUymin(),
00675    gPad->GetUxmax(), gPad->GetUymax(),0,rightmax,510,"+L");
00676    axis->SetLineColor(kRed);
00677    axis->SetTextColor(kRed);
00678    axis->Draw();
00679    return c1;
00680 }
00681 End_Macro
00682 Begin_Html
00683 
00684 
00685 <a name="HP07"></a><h3>Statistics Display</h3>
00686 
00687 
00688 The type of information shown in the histogram statistics box can be selected
00689 with:
00690 <pre>
00691       gStyle->SetOptStat(mode);
00692 </pre>
00693 The "<tt>mode</tt>" has up to nine digits that can be set to on(1 or 2), off(0).
00694 <pre>
00695       mode = iourmen  (default = 000001111)
00696       k = 1;  kurtosis printed
00697       k = 2;  kurtosis and kurtosis error printed
00698       s = 1;  skewness printed
00699       s = 2;  skewness and skewness error printed
00700       i = 1;  integral of bins printed
00701       o = 1;  number of overflows printed
00702       u = 1;  number of underflows printed
00703       r = 1;  rms printed
00704       r = 2;  rms and rms error printed
00705       m = 1;  mean value printed
00706       m = 2;  mean and mean error values printed
00707       e = 1;  number of entries printed
00708       n = 1;  name of histogram is printed
00709 </pre>
00710 For example:
00711 <pre>
00712       gStyle->SetOptStat(11);
00713 </pre>
00714 displays only the name of histogram and the number of entries, whereas:
00715 <pre>
00716       gStyle->SetOptStat(1101);
00717 </pre>
00718 displays the name of histogram, mean value and RMS.
00719 
00720 <p><b>WARNING 1:</b> never do:
00721 <pre>
00722       <s>gStyle->SetOptStat(000111);</s>
00723 </pre>
00724 but instead do:
00725 <pre>
00726       gStyle->SetOptStat(1111);
00727 </pre>
00728 because <tt>0001111</tt> will be taken as an octal number!
00729 
00730 <p><b>WARNING 2:</b> for backward compatibility with older versions
00731 <pre>
00732       gStyle->SetOptStat(1);
00733 </pre>
00734 is taken as:
00735 <pre>
00736       gStyle->SetOptStat(1111)
00737 </pre>
00738 To print only the name of the histogram do:
00739 <pre>
00740       gStyle->SetOptStat(1000000001);
00741 </pre>
00742 <b>NOTE</b> that in case of 2D histograms, when selecting only underflow
00743 (10000) or overflow (100000), the statistics box will show all combinations
00744 of underflow/overflows and not just one single number.
00745 
00746 <p>The parameter mode can be any combination of the letters
00747 <tt>kKsSiourRmMen</tt>
00748 <pre>
00749       k :  kurtosis printed
00750       K :  kurtosis and kurtosis error printed
00751       s :  skewness printed
00752       S :  skewness and skewness error printed
00753       i :  integral of bins printed
00754       o :  number of overflows printed
00755       u :  number of underflows printed
00756       r :  rms printed
00757       R :  rms and rms error printed
00758       m :  mean value printed
00759       M :  mean value mean error values printed
00760       e :  number of entries printed
00761       n :  name of histogram is printed
00762 </pre>
00763 For example, to print only name of histogram and number of entries do:
00764 <pre>
00765       gStyle->SetOptStat("ne");
00766 </pre>
00767 To print only the name of the histogram do:
00768 <pre>
00769       gStyle->SetOptStat("n");
00770 </pre>
00771 The default value is:
00772 <pre>
00773       gStyle->SetOptStat("nemr");
00774 </pre>
00775 
00776 <p>When a histogram is painted, a <tt>TPaveStats</tt> object is created and added
00777 to the list of functions of the histogram. If a <tt>TPaveStats</tt> object
00778 already exists in the histogram list of functions, the existing object is just
00779 updated with the current histogram parameters.
00780 
00781 <p>Once a histogram is painted, the statistics box can be accessed using
00782 <tt>h->FindObject("stats")</tt>. In the command line it is enough to do:
00783 <pre>
00784       Root > h->Draw()
00785       Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
00786 </pre>
00787 because after <tt>h->Draw()</tt> the histogram is automatically painted. But
00788 in a script file the painting should be forced using <tt>gPad->Update()</tt>
00789 in order to make sure the statistics box is created:
00790 <pre>
00791       h->Draw();
00792       gPad->Update();
00793       TPaveStats *st = (TPaveStats*)h->FindObject("stats");
00794 </pre>
00795 
00796 <p>Without <tt>gPad->Update()</tt> the line <tt>h->FindObject("stats")</tt>
00797 returns a null pointer.
00798 
00799 <p>When a histogram is drawn with the option "<tt>SAME</tt>", the statistics box
00800 is not drawn. To force the statistics box drawing with the option
00801 "<tt>SAME</tt>", the option "<tt>SAMES</tt>" must be used.
00802 If the new statistics box hides the previous statistics box, one can change
00803 its position with these lines ("<tt>h</tt>" being the pointer to the histogram):
00804 <pre>
00805       Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
00806       Root > st->SetX1NDC(newx1); //new x start position
00807       Root > st->SetX2NDC(newx2); //new x end position
00808 </pre>
00809 To change the type of information for an histogram with an existing
00810 <tt>TPaveStats</tt> one should do:
00811 <pre>
00812       st->SetOptStat(mode);
00813 </pre>
00814 Where "<tt>mode</tt>" has the same meaning than when calling
00815 <tt>gStyle->SetOptStat(mode)</tt> (see above).
00816 
00817 <p>One can delete the statistics box for a histogram <tt>TH1* h</tt> with:
00818 <pre>
00819       h->SetStats(0)
00820 </pre>
00821 and activate it again with:
00822 <pre>
00823       h->SetStats(1).
00824 </pre>
00825 
00826 
00827 <a name="HP08"></a><h3>Fit Statistics</h3>
00828 
00829 
00830 The type of information about fit parameters printed in the histogram statistics
00831 box can be selected via the parameter mode. The parameter mode can be
00832 <tt>= pcev</tt>  (default <tt>= 0111</tt>)
00833 <pre>
00834       p = 1;  print Probability
00835       c = 1;  print Chisquare/Number of degrees of freedom
00836       e = 1;  print errors (if e=1, v must be 1)
00837       v = 1;  print name/values of parameters
00838 </pre>
00839 Example:
00840 <pre>
00841       gStyle->SetOptFit(1011);
00842 </pre>
00843 print fit probability, parameter names/values and errors.
00844 <ol>
00845 <li> When <tt>"v" = 1</tt> is specified, only the non-fixed parameters are
00846      shown.
00847 <li> When <tt>"v" = 2</tt> all parameters are shown.
00848 </ol>
00849 Note: <tt>gStyle->SetOptFit(1)</tt> means "default value", so it is equivalent
00850 to <tt>gStyle->SetOptFit(111)</tt>
00851 
00852 
00853 <a name="HP09"></a><h3>The error bars options</h3>
00854 
00855 
00856 <table border=0>
00857 
00858 <tr><th valign=top>"E"</th><td>
00859 Default. Shows only the error bars, not a marker.
00860 </td></tr>
00861 
00862 <tr><th valign=top>"E1"</th><td>
00863 Small lines are drawn at the end of the error bars.
00864 </td></tr>
00865 
00866 <tr><th valign=top>"E2"</th><td>
00867 Error rectangles are drawn.
00868 </td></tr>
00869 
00870 <tr><th valign=top>"E3"</th><td>
00871 A filled area is drawn through the end points of the vertical error bars.
00872 </td></tr>
00873 
00874 <tr><th valign=top>"E4"</th><td>
00875 A smoothed filled area is drawn through the end points of the vertical error
00876 bars.
00877 </td></tr>
00878 
00879 <tr><th valign=top>"E0"</th><td>
00880 Draw also bins with null contents.
00881 </td></tr>
00882 
00883 </table>
00884 
00885 End_Html
00886 Begin_Macro(source)
00887 {
00888    TCanvas *c1 = new TCanvas("c1","c1",600,400);
00889    TH1F *he = new TH1F("he","Distribution drawn with error bars (option E1)  ",100,-3,3);
00890    Int_t i;
00891    for (i=0;i<10000;i++) he->Fill(gRandom->Gaus(0,1));
00892    gStyle->SetEndErrorSize(3);
00893    gStyle->SetErrorX(1.);
00894    he->SetMarkerStyle(20);
00895    he->Draw("E1");
00896    return c1;
00897 }
00898 End_Macro
00899 Begin_Html
00900 
00901 The options "E3" and "E4" draw an error band through the end points of the
00902 vertical error bars. With "E4" the error band is smoothed. Because of the
00903 smoothing algorithm used some artefacts may appear at the end of the band
00904 like in the following example. In such cases "E3" should be used instead
00905 of "E4".
00906 
00907 End_Html
00908 Begin_Macro(source)
00909 {
00910    TCanvas *ce4 = new TCanvas("ce4","ce4",600,400);
00911    ce4->Divide(2,1);
00912    TH1F *he4 = new TH1F("he4","Distribution drawn with option E4",100,-3,3);
00913    Int_t i;
00914    for (i=0;i<10000;i++) he4->Fill(gRandom->Gaus(0,1));
00915    he4->SetFillColor(kRed);
00916    he4->GetXaxis()->SetRange(40,48);
00917    ce4->cd(1);
00918    he4->Draw("E4");
00919    ce4->cd(2);
00920    TH1F *he3 = he4->DrawClone("E3");
00921    he3->SetTitle("Distribution drawn option E3");
00922    return ce4;
00923 }
00924 End_Macro
00925 Begin_Html
00926 
00927 
00928 <a name="HP100"></a><h3>The bar chart option</h3>
00929 
00930 
00931 The option "B" allows to draw simple vertical bar charts.
00932 The bar width is controlled with <tt>TH1::SetBarWidth()</tt>,
00933 and the bar offset wihtin the bin, with <tt>TH1::SetBarOffset()</tt>.
00934 These two settings are useful to draw several histograms on the
00935 same plot as shown in the following example:
00936 
00937 End_Html
00938 Begin_Macro(source)
00939 {
00940    int i;
00941    const Int_t nx = 8;
00942    char *os_X[nx]   = {"8","32","128","512","2048","8192","32768","131072"};
00943    float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
00944    float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
00945 
00946    TCanvas *cb = new TCanvas("cb","cb",600,400);
00947    cb->SetGrid();
00948 
00949    gStyle->SetHistMinimumZero();
00950 
00951    TH1F *h1b = new TH1F("h1b","Option B example",nx,0,nx);
00952    h1b->SetFillColor(4);
00953    h1b->SetBarWidth(0.4);
00954    h1b->SetBarOffset(0.1);
00955    h1b->SetStats(0);
00956    h1b->SetMinimum(-5);
00957    h1b->SetMaximum(5);
00958 
00959    for (i=1; i<=nx; i++) {
00960       h1b->Fill(os_X[i-1], d_35_0[i-1]);
00961       h1b->GetXaxis()->SetBinLabel(i,os_X[i-1]);
00962    }
00963 
00964    h1b->Draw("b");
00965 
00966    TH1F *h2b = new TH1F("h2b","h2b",nx,0,nx);
00967    h2b->SetFillColor(38);
00968    h2b->SetBarWidth(0.4);
00969    h2b->SetBarOffset(0.5);
00970    h2b->SetStats(0);
00971    for (i=1;i<=nx;i++) h2b->Fill(os_X[i-1], d_35_1[i-1]);
00972 
00973    h2b->Draw("b same");
00974 
00975    return cb;
00976 }
00977 End_Macro
00978 Begin_Html
00979 
00980 
00981 <a name="HP10"></a><h3>The "BAR" and "HBAR" options</h3>
00982 
00983 
00984 When the option "bar" or "hbar" is specified, a bar chart is drawn. A vertical
00985 bar-chart is drawn with the options <tt>"bar"</tt>, <tt>"bar0"</tt>,
00986 <tt>"bar1"</tt>, <tt>"bar2"</tt>, <tt>"bar3"</tt>, <tt>"bar4"</tt>.
00987 An horizontal bar-chart is drawn with the options <tt>"hbar"</tt>,
00988 <tt>"hbar0"</tt>, <tt>"hbar1"</tt>, <tt>"hbar2"</tt></tt>, <tt>"hbar3"</tt>,
00989 <tt>"hbar4"</tt>.
00990 <ul>
00991 <li> The bar is filled with the histogram fill color.
00992 <li> The left side of the bar is drawn with a light fill color.
00993 <li> The right side of the bar is drawn with a dark fill color.
00994 <li> The percentage of the bar drawn with either the light or dark color is:
00995 <ul>
00996 <li>    0% for option "(h)bar" or "(h)bar0"
00997 <li>   10% for option "(h)bar1"
00998 <li>   20% for option "(h)bar2"
00999 <li>   30% for option "(h)bar3"
01000 <li>   40% for option "(h)bar4"
01001 </ul>
01002 </ul>
01003 
01004 End_Html
01005 Begin_Macro(source)
01006 ../../../tutorials/hist/hbars.C
01007 End_Macro
01008 Begin_Html
01009 
01010 To control the bar width (default is the bin width) <tt>TH1::SetBarWidth()</tt>
01011 should be used.
01012 <br>
01013 To control the bar offset (default is 0) <tt>TH1::SetBarOffset()</tt> should
01014 be used.
01015 <br>
01016 These two parameters are useful when several histograms are plotted using
01017 the option <tt>SAME</tt>. They allow to plot the histograms next to each other.
01018 
01019 
01020 <a name="HP11"></a><h3>The SCATter plot option (default for 2D histograms)</h3>
01021 
01022 
01023 For each cell (i,j) a number of points proportional to the cell content is
01024 drawn. A maximum of <tt>kNMAX</tt> points per cell is drawn. If the maximum is above
01025 <tt>kNMAX</tt> contents are normalized to <tt>kNMAX</tt> (<tt>kNMAX=2000</tt>).
01026 If option is of the form <tt>"scat=ff"</tt>, (eg <tt>scat=1.8</tt>,
01027 <tt>scat=1e-3</tt>), then <tt>ff</tt> is used as a scale factor to compute the
01028 number of dots. <tt>"scat=1"</tt> is the default.
01029 
01030 End_Html
01031 Begin_Macro(source)
01032 {
01033    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01034    TH2F *hscat = new TH2F("hscat","Option SCATter example (default for 2D histograms)  ",40,-4,4,40,-20,20);
01035    Float_t px, py;
01036    for (Int_t i = 0; i < 25000; i++) {
01037       gRandom->Rannor(px,py);
01038       hscat->Fill(px,5*py);
01039       hscat->Fill(3+0.5*px,2*py-10.);
01040    }
01041    hscat->Draw("scat=0.5");
01042    return c1;
01043 }
01044 End_Macro
01045 Begin_Html
01046 
01047 
01048 <a name="HP12"></a><h3>The ARRow option</h3>
01049 
01050 
01051 Shows gradient between adjacent cells. For each cell (i,j) an arrow is drawn
01052 The orientation of the arrow follows the cell gradient.
01053 
01054 End_Html
01055 Begin_Macro(source)
01056 {
01057    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01058    TH2F *harr = new TH2F("harr","Option ARRow example",20,-4,4,20,-20,20);
01059    Float_t px, py;
01060    for (Int_t i = 0; i < 25000; i++) {
01061       gRandom->Rannor(px,py);
01062       harr->Fill(px,5*py);
01063       harr->Fill(3+0.5*px,2*py-10.,0.1);
01064    }
01065    harr->Draw("ARR");
01066    return c1;
01067 }
01068 End_Macro
01069 Begin_Html
01070 
01071 
01072 <a name="HP13"></a><h3>The BOX option</h3>
01073 
01074 
01075 For each cell (i,j) a box is drawn. The size (surface) of the box is
01076 proportional to the absolute value of the cell content.
01077 The cells with a negative content draw with a <tt>X</tt> on top of the boxes.
01078 
01079 End_Html
01080 Begin_Macro(source)
01081 {
01082    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01083    hbox  = new TH2F("hbox","Option BOX example",3,0,3,3,0,3);
01084    hbox->SetFillColor(42);
01085    hbox->Fill(0.5, 0.5,  1.);
01086    hbox->Fill(0.5, 1.5,  4.);
01087    hbox->Fill(0.5, 2.5,  3.);
01088    hbox->Fill(1.5, 0.5,  2.);
01089    hbox->Fill(1.5, 1.5, 12.);
01090    hbox->Fill(1.5, 2.5, -6.);
01091    hbox->Fill(2.5, 0.5, -4.);
01092    hbox->Fill(2.5, 1.5,  6.);
01093    hbox->Fill(2.5, 2.5,  0.5);
01094    hbox->Draw("BOX");
01095    return c1;
01096 }
01097 End_Macro
01098 Begin_Html
01099 
01100 With option <tt>"BOX1"</tt> a button is drawn for each cell with surface
01101 proportional to content's absolute value. A sunken button is drawn for
01102 negative values a raised one for positive.
01103 
01104 End_Html
01105 Begin_Macro(source)
01106 {
01107    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01108    hbox1  = new TH2F("hbox1","Option BOX1 example",3,0,3,3,0,3);
01109    hbox1->SetFillColor(42);
01110    hbox1->Fill(0.5, 0.5,  1.);
01111    hbox1->Fill(0.5, 1.5,  4.);
01112    hbox1->Fill(0.5, 2.5,  3.);
01113    hbox1->Fill(1.5, 0.5,  2.);
01114    hbox1->Fill(1.5, 1.5, 12.);
01115    hbox1->Fill(1.5, 2.5, -6.);
01116    hbox1->Fill(2.5, 0.5, -4.);
01117    hbox1->Fill(2.5, 1.5,  6.);
01118    hbox1->Fill(2.5, 2.5,  0.5);
01119    hbox1->Draw("BOX1");
01120    return c1;
01121 }
01122 End_Macro
01123 Begin_Html
01124 
01125 When the option <tt>"SAME"</tt> (or "SAMES") is used with the option <tt>"BOX"</tt>,
01126 the boxes' sizes are computing taking the previous plots into account. The range
01127 along the Z axis is imposed by the first plot (the one without option
01128 <tt>"SAME"</tt>); therefore the order in which the plots are done is relevant.
01129 
01130 End_Html
01131 Begin_Macro(source)
01132 {
01133    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01134    TH2F *hb1 = new TH2F("hb1","Example of BOX plots with option SAME ",40,-3,3,40,-3,3);
01135    TH2F *hb2 = new TH2F("hb2","hb2",40,-3,3,40,-3,3);
01136    TH2F *hb3 = new TH2F("hb3","hb3",40,-3,3,40,-3,3);
01137    TH2F *hb4 = new TH2F("hb4","hb4",40,-3,3,40,-3,3);
01138    for (Int_t i=0;i<1000;i++) {
01139       double x,y;
01140       gRandom->Rannor(x,y);
01141       if(x>0 && y>0) hb1->Fill(x,y,4);
01142       if(x<0 && y<0) hb2->Fill(x,y,3);
01143       if(x>0 && y<0) hb3->Fill(x,y,2);
01144       if(x<0 && y>0) hb4->Fill(x,y,1);
01145    }
01146    hb1->SetFillColor(1);
01147    hb2->SetFillColor(2);
01148    hb3->SetFillColor(3);
01149    hb4->SetFillColor(4);
01150    hb1->Draw("box");
01151    hb2->Draw("box same");
01152    hb3->Draw("box same");
01153    hb4->Draw("box same");
01154    return c1;
01155 }
01156 End_Macro
01157 Begin_Html
01158 
01159 
01160 <a name="HP14"></a><h3>The COLor option</h3>
01161 
01162 
01163 For each cell (i,j) a box is drawn with a color proportional to the cell
01164 content.
01165 
01166 <p>The color table used is defined in the current style.
01167 
01168 <p>If the histogram's minimum and maximum are the same (flat histogram), the
01169 mapping on colors is not possible, therefore nothing is painted. To paint a
01170 flat histogram it is enough to set the histogram minimum
01171 (<tt>TH1::SetMinimum()</tt>) different from the bins' content.
01172 
01173 <p>The default number of color levels used to paint the cells is 20.
01174 It can be changed with <tt>TH1::SetContour()</tt> or
01175 <tt>TStyle::SetNumberContours()</tt>. The higher this number is, the smoother
01176 is the color change between cells.
01177 
01178 <p>The color palette in TStyle can be modified via <tt>gStyle->SetPalette()</tt>.
01179 
01180 <p>All the none empty bins are painted. Empty bins are not painted unless
01181 some bins have a negative content because in that case the null bins
01182 might be not empty.
01183 
01184 <p>Combined with the option <tt>"COL"</tt>, the option <tt>"Z"</tt> allows to
01185 display the color palette defined by <tt>gStyle->SetPalette()</tt>.
01186 
01187 <p>In the following example, the histogram has only positive bins; the empty
01188 bins (containing 0) <u>are not drawn</u>.
01189 
01190 End_Html
01191 Begin_Macro(source)
01192 {
01193    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01194    TH2F *hcol1 = new TH2F("hcol1","Option COLor example ",40,-4,4,40,-20,20);
01195    Float_t px, py;
01196    for (Int_t i = 0; i < 25000; i++) {
01197       gRandom->Rannor(px,py);
01198       hcol1->Fill(px,5*py);
01199    }
01200    gStyle->SetPalette(1);
01201    hcol1->Draw("COLZ");
01202    return c1;
01203 }
01204 End_Macro
01205 Begin_Html
01206 
01207 In the following example, the histogram has some negative bins; the empty
01208 bins (containing 0) <u>are drawn</u>.
01209 
01210 End_Html
01211 Begin_Macro(source)
01212 {
01213    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01214    TH2F *hcol2 = new TH2F("hcol2","Option COLor example ",40,-4,4,40,-20,20);
01215    Float_t px, py;
01216    for (Int_t i = 0; i < 25000; i++) {
01217       gRandom->Rannor(px,py);
01218       hcol2->Fill(px,5*py);
01219    }
01220    hcol2->Fill(0,0,-200);
01221    gStyle->SetPalette(1);
01222    hcol2->Draw("COLZ");
01223    return c1;
01224 }
01225 End_Macro
01226 Begin_Html
01227 
01228 
01229 <a name="HP15"></a><h3>The TEXT and TEXTnn Option</h3>
01230 
01231 
01232 For each bin the content is printed. The text attributes are:
01233 <ul>
01234 <li> text font = current TStyle font (<tt>gStyle->SetTextFont()</tt>).
01235 <li> text size = 0.02*padheight*markersize (if <tt>h</tt> is the histogram drawn
01236      with the option <tt>"TEXT"</tt> the marker size can be changed with
01237      <tt>h->SetMarkerSize(markersize)</tt>).
01238 <li> text color = marker color.
01239 </ul>
01240 By default the format <tt>"g"</tt> is used. This format can be redefined
01241 by calling <tt>gStyle->SetPaintTextFormat()</tt>.
01242 
01243 <p>It is also possible to use <tt>"TEXTnn"</tt> in order to draw the text with
01244 the angle <tt>nn</tt> (<tt>0 < nn < 90</tt>).
01245 
01246 <p>For 2D histograms the text is plotted in the center of each non empty cells.
01247 It is possible to plot empty cells by calling gStyle->SetHistMinimumZero().
01248 For 1D histogram the text is plotted at a y position equal to the bin content.
01249 
01250 <p>For 2D histograms when the option "E" (errors) is combined with the option
01251 text ("TEXTE"), the error for each bin is also printed.
01252 
01253 End_Html
01254 Begin_Macro(source)
01255 {
01256    TCanvas *c01 = new TCanvas("c01","c01",700,400);
01257    c01->Divide(2,1);
01258    TH1F *htext1 = new TH1F("htext1","Option TEXT on 1D histograms ",10,-4,4);
01259    TH2F *htext2 = new TH2F("htext2","Option TEXT on 2D histograms ",10,-4,4,10,-20,20);
01260    Float_t px, py;
01261    for (Int_t i = 0; i < 25000; i++) {
01262       gRandom->Rannor(px,py);
01263         htext1->Fill(px,0.1);
01264       htext2->Fill(px,5*py,0.1);
01265    }
01266    gStyle->SetPaintTextFormat("4.1f m");
01267    htext2->SetMarkerSize(1.8);
01268    c01->cd(1);
01269    htext2->Draw("TEXT45");
01270    c01->cd(2);
01271    htext1->Draw();
01272    htext1->Draw("TEXT0 SAME");
01273    return c01;
01274 }
01275 End_Macro
01276 Begin_Html
01277 
01278 <p>In the case of profile histograms it is possible to print the number
01279 of entries instead of the bin content. It is enough to combine the
01280 option "E" (for entries) with the option "TEXT".
01281 
01282 End_Html
01283 Begin_Macro(source)
01284 {
01285    TCanvas *c02 = new TCanvas("c02","c02",700,400);
01286    c02->Divide(2,1);
01287    gStyle->SetPaintTextFormat("g");
01288 
01289    TProfile *profile = new TProfile("profile","profile",10,0,10);
01290    profile->SetMarkerSize(2.2);
01291    profile->Fill(0.5,1);
01292    profile->Fill(1.5,2);
01293    profile->Fill(2.5,3);
01294    profile->Fill(3.5,4);
01295    profile->Fill(4.5,5);
01296    profile->Fill(5.5,5);
01297    profile->Fill(6.5,4);
01298    profile->Fill(7.5,3);
01299    profile->Fill(8.5,2);
01300    profile->Fill(9.5,1);
01301    c02->cd(1); profile->Draw("HIST TEXT0");
01302    c02->cd(2); profile->Draw("HIST TEXT0E");
01303 
01304    return c02;
01305 }
01306 End_Macro
01307 Begin_Html
01308 
01309 <a name="HP16"></a><h3>The CONTour options</h3>
01310 
01311 
01312 The following contour options are supported:
01313 
01314 <table border=0>
01315 
01316 <tr><th valign=top>"CONT"</th><td>
01317 Draw a contour plot (same as CONT0).
01318 </td></tr>
01319 
01320 <tr><th valign=top>"CONT0"</th><td>
01321 Draw a contour plot using surface colors to distinguish contours.
01322 </td></tr>
01323 
01324 <tr><th valign=top>"CONT1"</th><td>
01325 Draw a contour plot using the line colors to distinguish contours.
01326 </td></tr>
01327 
01328 <tr><th valign=top>"CONT2"</th><td>
01329 Draw a contour plot using the line styles to distinguish contours.
01330 </td></tr>
01331 
01332 <tr><th valign=top>"CONT3"</th><td>
01333 Draw a contour plot solid lines for all contours.
01334 </td></tr>
01335 
01336 <tr><th valign=top>"CONT4"</th><td>
01337 Draw a contour plot using surface colors (<tt>"SURF"</tt> option at theta = 0).
01338 </td></tr>
01339 
01340 <tr><th valign=top>"CONT5"</th><td>
01341 Draw a contour plot using Delaunay triangles.
01342 </td></tr>
01343 
01344 </table>
01345 
01346 The following example shows a 2D histogram plotted with the option
01347 <tt>"CONTZ"</tt>. The option <tt>"CONT"</tt> draws a contour plot using surface
01348 colors to distinguish contours.  Combined with the option <tt>"CONT"</tt> (or
01349 <tt>"CONT0"</tt>), the option <tt>"Z"</tt> allows to display the color palette
01350 defined by <tt>gStyle->SetPalette()</tt>.
01351 
01352 End_Html
01353 Begin_Macro(source)
01354 {
01355    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01356    TH2F *hcontz = new TH2F("hcontz","Option CONTZ example ",40,-4,4,40,-20,20);
01357    Float_t px, py;
01358    for (Int_t i = 0; i < 25000; i++) {
01359       gRandom->Rannor(px,py);
01360       hcontz->Fill(px-1,5*py);
01361       hcontz->Fill(2+0.5*px,2*py-10.,0.1);
01362    }
01363    gStyle->SetPalette(1);
01364    hcontz->Draw("CONTZ");
01365    return c1;
01366 }
01367 End_Macro
01368 Begin_Html
01369 
01370 The following example shows a 2D histogram plotted with the option
01371 <tt>"CONT1Z"</tt>. The option <tt>"CONT1"</tt> draws a contour plot using the
01372 line colors to distinguish contours. Combined with the option <tt>"CONT1"</tt>,
01373 the option <tt>"Z"</tt> allows to display the color palette defined by
01374 <tt>gStyle->SetPalette()</tt>.
01375 
01376 End_Html
01377 Begin_Macro(source)
01378 {
01379    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01380    TH2F *hcont1 = new TH2F("hcont1","Option CONT1Z example ",40,-4,4,40,-20,20);
01381    Float_t px, py;
01382    for (Int_t i = 0; i < 25000; i++) {
01383       gRandom->Rannor(px,py);
01384       hcont1->Fill(px-1,5*py);
01385       hcont1->Fill(2+0.5*px,2*py-10.,0.1);
01386    }
01387    gStyle->SetPalette(1);
01388    hcont1->Draw("CONT1Z");
01389    return c1;
01390 }
01391 End_Macro
01392 Begin_Html
01393 
01394 The following example shows a 2D histogram plotted with the option
01395 <tt>"CONT2"</tt>. The option <tt>"CONT2"</tt> draws a contour plot using the
01396 line styles to distinguish contours.
01397 
01398 End_Html
01399 Begin_Macro(source)
01400 {
01401    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01402    TH2F *hcont2 = new TH2F("hcont2","Option CONT2 example ",40,-4,4,40,-20,20);
01403    Float_t px, py;
01404    for (Int_t i = 0; i < 25000; i++) {
01405       gRandom->Rannor(px,py);
01406       hcont2->Fill(px-1,5*py);
01407       hcont2->Fill(2+0.5*px,2*py-10.,0.1);
01408    }
01409    hcont2->Draw("CONT2");
01410    return c1;
01411 }
01412 End_Macro
01413 Begin_Html
01414 
01415 The following example shows a 2D histogram plotted with the option
01416 <tt>"CONT3"</tt>. The option <tt>"CONT3"</tt> draws contour plot solid lines for
01417 all contours.
01418 
01419 End_Html
01420 Begin_Macro(source)
01421 {
01422    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01423    TH2F *hcont3 = new TH2F("hcont3","Option CONT3 example ",40,-4,4,40,-20,20);
01424    Float_t px, py;
01425    for (Int_t i = 0; i < 25000; i++) {
01426       gRandom->Rannor(px,py);
01427       hcont3->Fill(px-1,5*py);
01428       hcont3->Fill(2+0.5*px,2*py-10.,0.1);
01429    }
01430    hcont3->Draw("CONT3");
01431    return c1;
01432 }
01433 End_Macro
01434 Begin_Html
01435 
01436 The following example shows a 2D histogram plotted with the option
01437 <tt>"CONT4"</tt>. The option <tt>"CONT4"</tt> draws a contour plot using surface
01438 colors to distinguish contours (<tt>"SURF"</tt> option at theta = 0). Combined
01439 with the option <tt>"CONT"</tt> (or <tt>"CONT0"</tt>), the option <tt>"Z"</tt>
01440 allows to display the color palette defined by <tt>gStyle->SetPalette()</tt>.
01441 
01442 End_Html
01443 Begin_Macro(source)
01444 {
01445    TCanvas *c1 = new TCanvas("c1","c1",600,400);
01446    TH2F *hcont4 = new TH2F("hcont4","Option CONT4Z example ",40,-4,4,40,-20,20);
01447    Float_t px, py;
01448    for (Int_t i = 0; i < 25000; i++) {
01449       gRandom->Rannor(px,py);
01450       hcont4->Fill(px-1,5*py);
01451       hcont4->Fill(2+0.5*px,2*py-10.,0.1);
01452    }
01453    gStyle->SetPalette(1);
01454    hcont4->Draw("CONT4Z");
01455    return c1;
01456 }
01457 End_Macro
01458 Begin_Html
01459 
01460 The default number of contour levels is 20 equidistant levels and can be changed
01461 with <tt>TH1::SetContour()</tt> or <tt>TStyle::SetNumberContours()</tt>.
01462 
01463 <a name="HP16a"></a><h4><u>The LIST option</u></h4>
01464 
01465 <p>When option <tt>"LIST"</tt> is specified together with option
01466 <tt>"CONT"</tt>, the points used to draw the contours are saved in
01467 <tt>TGraph</tt> objects:
01468 <pre>
01469       h->Draw("CONT LIST");
01470       gPad->Update();
01471 </pre>
01472 The contour are saved in <tt>TGraph</tt> objects once the pad is painted.
01473 Therefore to use this functionnality in a macro, <tt>gPad->Update()</tt>
01474 should be performed after the histogram drawing. Once the list is
01475 built, the contours are accessible in the following way:
01476 <pre>
01477       TObjArray *contours = gROOT->GetListOfSpecials()->FindObject("contours")
01478       Int_t ncontours     = contours->GetSize();
01479       TList *list         = (TList*)contours->At(i);
01480 </pre>
01481 Where <tt>i</tt> is a contour number, and list contains a list of
01482 <tt>TGraph</tt> objects.
01483 For one given contour, more than one disjoint polyline may be generated.
01484 The number of TGraphs per contour is given by:
01485 <pre>
01486       list->GetSize();
01487 </pre>
01488 To access the first graph in the list one should do:
01489 <pre>
01490       TGraph *gr1 = (TGraph*)list->First();
01491 </pre>
01492 
01493 The following example shows how to use this functionality.
01494 
01495 End_Html
01496 Begin_Macro(source)
01497 ../../../tutorials/hist/ContourList.C
01498 End_Macro
01499 Begin_Html
01500 
01501 The following options select the <tt>"CONT4"</tt> option and are useful for
01502 sky maps or exposure maps.
01503 
01504 <table border=0>
01505 
01506 <tr><th valign=top>"AITOFF"</th><td>
01507 Draw a contour via an AITOFF projection.
01508 </td></tr>
01509 
01510 <tr><th valign=top>"MERCATOR"</th><td>
01511 Draw a contour via an Mercator projection.
01512 </td></tr>
01513 
01514 <tr><th valign=top>"SINUSOIDAL"</th><td>
01515 Draw a contour via an Sinusoidal projection.
01516 </td></tr>
01517 
01518 <tr><th valign=top>"PARABOLIC"</th><td>
01519 Draw a contour via an Parabolic projection.
01520 </td></tr>
01521 
01522 </table>
01523 
01524 End_Html
01525 Begin_Macro(source)
01526 ../../../tutorials/graphics/earth.C
01527 End_Macro
01528 Begin_Html
01529 
01530 
01531 <a name="HP17"></a><h3>The LEGO options</h3>
01532 
01533 
01534 In a lego plot the cell contents are drawn as 3-d boxes. The height of each box
01535 is proportional to the cell content. The lego aspect is control with the
01536 following options:
01537 
01538 <table border=0>
01539 
01540 <tr><th valign=top>"LEGO" </th><td>
01541 Draw a lego plot using the hidden lines removal technique.
01542 </td></tr>
01543 
01544 <tr><th valign=top>"LEGO1"</th><td>
01545 Draw a lego plot using the hidden surface removal technique.
01546 </td></tr>
01547 
01548 <tr><th valign=top>"LEGO2"</th><td>
01549 Draw a lego plot using colors to show the cell contents.
01550 </td></tr>
01551 
01552 <tr><th valign=top>"0"</th><td>
01553 When used with any LEGO option, the empty bins are not drawn.
01554 </td></tr>
01555 
01556 </table>
01557 See the limitations with <a href="#HP060a">the option "SAME"</a>.
01558 <p>
01559 The following example shows a 2D histogram plotted with the option
01560 <tt>"LEGO"</tt>. The option <tt>"LEGO"</tt> draws a lego plot using the hidden
01561 lines removal technique.
01562 
01563 End_Html
01564 Begin_Macro(source)
01565 {
01566    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01567    TH2F *hlego = new TH2F("hlego","Option LEGO example ",40,-4,4,40,-20,20);
01568    Float_t px, py;
01569    for (Int_t i = 0; i < 25000; i++) {
01570       gRandom->Rannor(px,py);
01571       hlego->Fill(px-1,5*py);
01572       hlego->Fill(2+0.5*px,2*py-10.,0.1);
01573    }
01574    hlego->Draw("LEGO");
01575    return c2;
01576 }
01577 End_Macro
01578 Begin_Html
01579 
01580 The following example shows a 2D histogram plotted with the option
01581 <tt>"LEGO1"</tt>. The option <tt>"LEGO1"</tt> draws a lego plot using the
01582 hidden surface removal technique. Combined with any <tt>"LEGOn"</tt> option, the
01583 option <tt>"0"</tt> allows to not drawn the empty bins.
01584 
01585 End_Html
01586 Begin_Macro(source)
01587 {
01588    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01589    TH2F *hlego1 = new TH2F("hlego1","Option LEGO1 example (with option 0)  ",40,-4,4,40,-20,20);
01590    Float_t px, py;
01591    for (Int_t i = 0; i < 25000; i++) {
01592       gRandom->Rannor(px,py);
01593       hlego1->Fill(px-1,5*py);
01594       hlego1->Fill(2+0.5*px,2*py-10.,0.1);
01595    }
01596    gStyle->SetPalette(1);
01597    hlego1->SetFillColor(kYellow);
01598    hlego1->Draw("LEGO1 0");
01599    return c2;
01600 }
01601 End_Macro
01602 Begin_Html
01603 
01604 The following example shows a 2D histogram plotted with the option
01605 <tt>"LEGO2"</tt>. The option <tt>"LEGO2"</tt> draws a lego plot using colors to
01606 show the cell contents.  Combined with the option <tt>"LEGO2"</tt>, the option
01607 <tt>"Z"</tt> allows to display the color palette defined by
01608 <tt>gStyle->SetPalette()</tt>.
01609 
01610 End_Html
01611 Begin_Macro(source)
01612 {
01613    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01614    TH2F *hlego2 = new TH2F("hlego2","Option LEGO2Z example ",40,-4,4,40,-20,20);
01615    Float_t px, py;
01616    for (Int_t i = 0; i < 25000; i++) {
01617       gRandom->Rannor(px,py);
01618       hlego2->Fill(px-1,5*py);
01619       hlego2->Fill(2+0.5*px,2*py-10.,0.1);
01620    }
01621    gStyle->SetPalette(1);
01622    hlego2->Draw("LEGO2Z");
01623    return c2;
01624 }
01625 End_Macro
01626 Begin_Html
01627 
01628 
01629 
01630 <a name="HP18"></a><h3>The "SURFace" options</h3>
01631 
01632 
01633 In a surface plot, cell contents are represented as a mesh.
01634 The height of the mesh is proportional to the cell content.
01635 
01636 <table border=0>
01637 
01638 <tr><th valign=top>"SURF"</th><td>
01639 Draw a surface plot using the hidden line removal technique.
01640 </td></tr>
01641 
01642 <tr><th valign=top>"SURF1"</th><td>
01643 Draw a surface plot using the hidden surface removal technique.
01644 </td></tr>
01645 
01646 <tr><th valign=top>"SURF2"</th><td>
01647 Draw a surface plot using colors to show the cell contents.
01648 </td></tr>
01649 
01650 <tr><th valign=top>"SURF3"</th><td>
01651 Same as <tt>SURF</tt> with an additionial filled contour plot on top.
01652 </td></tr>
01653 
01654 <tr><th valign=top>"SURF4"</th><td>
01655 Draw a surface using the Gouraud shading technique.
01656 </td></tr>
01657 
01658 <tr><th valign=top>"SURF5"</th><td>
01659 Used with one of the options CYL, PSR and CYL this option allows to draw a
01660 a filled contour plot.
01661 </td></tr>
01662 
01663 <tr><th valign=top>"SURF6"</th><td>
01664 This option should not be used directly. It is used internally when the
01665 CONT is used with option the option SAME on a 3D plot.
01666 </td></tr>
01667 
01668 <tr><th valign=top>"SURF7"</th><td>
01669 Same as <tt>SURF2</tt> with an additionial line contour plot on top.
01670 </td></tr>
01671 
01672 </table>
01673 
01674 See the limitations with <a href="#HP060a">the option "SAME"</a>.
01675 <p>
01676 The following example shows a 2D histogram plotted with the option
01677 <tt>"SURF"</tt>. The option <tt>"SURF"</tt> draws a lego plot using the hidden
01678 lines removal technique.
01679 
01680 End_Html
01681 Begin_Macro(source)
01682 {
01683    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01684    TH2F *hsurf = new TH2F("hsurf","Option SURF example ",30,-4,4,30,-20,20);
01685    Float_t px, py;
01686    for (Int_t i = 0; i < 25000; i++) {
01687       gRandom->Rannor(px,py);
01688       hsurf->Fill(px-1,5*py);
01689       hsurf->Fill(2+0.5*px,2*py-10.,0.1);
01690    }
01691    hsurf->Draw("SURF");
01692    return c2;
01693 }
01694 End_Macro
01695 Begin_Html
01696 
01697 The following example shows a 2D histogram plotted with the option
01698 <tt>"SURF1"</tt>. The option <tt>"SURF1"</tt> draws a surface plot using the
01699 hidden surface removal technique.  Combined with the option <tt>"SURF1"</tt>,
01700 the option <tt>"Z"</tt> allows to display the color palette defined by
01701 <tt>gStyle->SetPalette()</tt>.
01702 
01703 End_Html
01704 Begin_Macro(source)
01705 {
01706    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01707    TH2F *hsurf1 = new TH2F("hsurf1","Option SURF1 example ",30,-4,4,30,-20,20);
01708    Float_t px, py;
01709    for (Int_t i = 0; i < 25000; i++) {
01710       gRandom->Rannor(px,py);
01711       hsurf1->Fill(px-1,5*py);
01712       hsurf1->Fill(2+0.5*px,2*py-10.,0.1);
01713    }
01714    hsurf1->Draw("SURF1");
01715    return c2;
01716 }
01717 End_Macro
01718 Begin_Html
01719 
01720 The following example shows a 2D histogram plotted with the option
01721 <tt>"SURF2"</tt>. The option <tt>"SURF2"</tt> draws a surface plot using colors
01722 to show the cell contents. Combined with the option <tt>"SURF2"</tt>, the option
01723 <tt>"Z"</tt> allows to display the color palette defined by
01724 <tt>gStyle->SetPalette()</tt>.
01725 
01726 End_Html
01727 Begin_Macro(source)
01728 {
01729    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01730    TH2F *hsurf2 = new TH2F("hsurf2","Option SURF2 example ",30,-4,4,30,-20,20);
01731    Float_t px, py;
01732    for (Int_t i = 0; i < 25000; i++) {
01733       gRandom->Rannor(px,py);
01734       hsurf2->Fill(px-1,5*py);
01735       hsurf2->Fill(2+0.5*px,2*py-10.,0.1);
01736    }
01737    hsurf2->Draw("SURF2");
01738    return c2;
01739 }
01740 End_Macro
01741 Begin_Html
01742 
01743 The following example shows a 2D histogram plotted with the option
01744 <tt>"SURF3"</tt>. The option <tt>"SURF3"</tt> draws a surface plot using the
01745 hidden line removal technique with, in addition, a filled contour view drawn on the
01746 top.  Combined with the option <tt>"SURF3"</tt>, the option <tt>"Z"</tt> allows
01747 to display the color palette defined by <tt>gStyle->SetPalette()</tt>.
01748 
01749 End_Html
01750 Begin_Macro(source)
01751 {
01752    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01753    TH2F *hsurf3 = new TH2F("hsurf3","Option SURF3 example ",30,-4,4,30,-20,20);
01754    Float_t px, py;
01755    for (Int_t i = 0; i < 25000; i++) {
01756       gRandom->Rannor(px,py);
01757       hsurf3->Fill(px-1,5*py);
01758       hsurf3->Fill(2+0.5*px,2*py-10.,0.1);
01759    }
01760    hsurf3->Draw("SURF3");
01761    return c2;
01762 }
01763 End_Macro
01764 Begin_Html
01765 
01766 The following example shows a 2D histogram plotted with the option
01767 <tt>"SURF4"</tt>. The option <tt>"SURF4"</tt> draws a surface using the Gouraud
01768 shading technique.
01769 
01770 End_Html
01771 Begin_Macro(source)
01772 {
01773    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01774    TH2F *hsurf4 = new TH2F("hsurf4","Option SURF4 example ",30,-4,4,30,-20,20);
01775    Float_t px, py;
01776    for (Int_t i = 0; i < 25000; i++) {
01777       gRandom->Rannor(px,py);
01778       hsurf4->Fill(px-1,5*py);
01779       hsurf4->Fill(2+0.5*px,2*py-10.,0.1);
01780    }
01781    hsurf4->SetFillColor(kOrange);
01782    hsurf4->Draw("SURF4");
01783    return c2;
01784 }
01785 End_Macro
01786 Begin_Html
01787 
01788 The following example shows a 2D histogram plotted with the option
01789 <tt>"SURF5 CYL"</tt>.  Combined with the option <tt>"SURF5"</tt>, the option
01790 <tt>"Z"</tt> allows to display the color palette defined by <tt>gStyle->SetPalette()</tt>.
01791 
01792 End_Html
01793 Begin_Macro(source)
01794 {
01795    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01796    TH2F *hsurf5 = new TH2F("hsurf4","Option SURF5 example ",30,-4,4,30,-20,20);
01797    Float_t px, py;
01798    for (Int_t i = 0; i < 25000; i++) {
01799       gRandom->Rannor(px,py);
01800       hsurf5->Fill(px-1,5*py);
01801       hsurf5->Fill(2+0.5*px,2*py-10.,0.1);
01802    }
01803    hsurf5->SetFillColor(kOrange);
01804    hsurf5->Draw("SURF5 CYL");
01805    return c2;
01806 }
01807 End_Macro
01808 Begin_Html
01809 
01810 The following example shows a 2D histogram plotted with the option
01811 <tt>"SURF7"</tt>. The option <tt>"SURF7"</tt> draws a surface plot using the
01812 hidden surfaces removal technique with, in addition, a line contour view drawn on the
01813 top.  Combined with the option <tt>"SURF7"</tt>, the option <tt>"Z"</tt> allows
01814 to display the color palette defined by <tt>gStyle->SetPalette()</tt>.
01815 
01816 End_Html
01817 Begin_Macro(source)
01818 {
01819    TCanvas *c2 = new TCanvas("c2","c2",600,400);
01820    TH2F *hsurf7 = new TH2F("hsurf3","Option SURF7 example ",30,-4,4,30,-20,20);
01821    Float_t px, py;
01822    for (Int_t i = 0; i < 25000; i++) {
01823       gRandom->Rannor(px,py);
01824       hsurf7->Fill(px-1,5*py);
01825       hsurf7->Fill(2+0.5*px,2*py-10.,0.1);
01826    }
01827    hsurf7->Draw("SURF7");
01828    return c2;
01829 }
01830 End_Macro
01831 Begin_Html
01832 
01833 As shown in the following example, when a contour plot is painted on top of a
01834 surface plot using the option <tt>SAME</tt>, the contours appear in 3D on the
01835 surface.
01836 
01837 End_Html
01838 Begin_Macro(source)
01839 {
01840    TCanvas *c1=new TCanvas("c2","c2",600,400);
01841    int NBins = 50;
01842    double d = 2;
01843    TH2F* hsc = new TH2F("hsc", "Surface and contour with option SAME ", NBins, -d, d, NBins, -d, d);
01844    for (int bx = 1;  bx <= NBins; ++bx) {
01845       for (int by = 1;  by <= NBins; ++by) {
01846          double x = hsc->GetXaxis()->GetBinCenter(bx);
01847          double y = hsc->GetYaxis()->GetBinCenter(by);
01848          hsc->SetBinContent(bx, by, exp(-x*x)*exp(-y*y));
01849       }
01850    }
01851    gStyle->SetPalette(1);
01852    hsc->Draw("surf2");
01853    hsc->Draw("CONT1 SAME");
01854    return c2;
01855 }
01856 End_Macro
01857 Begin_Html
01858 
01859 
01860 <a name="HP19"></a><h3>Cylindrical, Polar, Spherical and PseudoRapidity/Phi options</h3>
01861 
01862 
01863 Legos and surfaces plots are represented by default in Cartesian coordinates.
01864 Combined with any <tt>"LEGOn"</tt> or <tt>"SURFn"</tt> options the following
01865 options allow to draw a lego or a surface in other coordinates systems.
01866 
01867 <table border=0>
01868 
01869 <tr><th valign=top>"CYL"</th><td>
01870 Use Cylindrical coordinates. The X coordinate is mapped on the angle and the Y
01871 coordinate on the cylinder length.
01872 </td></tr>
01873 
01874 <tr><th valign=top>"POL"</th><td>
01875 Use Polar coordinates. The X coordinate is mapped on the angle and the Y
01876 coordinate on the radius.
01877 </td></tr>
01878 
01879 <tr><th valign=top>"SPH"</th><td>
01880 Use Spherical coordinates. The X coordinate is mapped on the latitude and the
01881 Y coordinate on the longitude.
01882 </td></tr>
01883 
01884 <tr><th valign=top>"PSR"</th><td>
01885 Use PseudoRapidity/Phi coordinates. The X coordinate is mapped on Phi.
01886 </td></tr>
01887 
01888 </table>
01889 
01890 <b>WARNING:</b> Axis are not drawn with these options.
01891 
01892 <p>The following example shows the same histogram as a lego plot is the four
01893 different coordinates systems.
01894 
01895 End_Html
01896 Begin_Macro(source)
01897 {
01898    TCanvas *c3 = new TCanvas("c3","c3",600,400);
01899    c3->Divide(2,2);
01900    TH2F *hlcc = new TH2F("hlcc","Cylindrical coordinates",20,-4,4,20,-20,20);
01901    Float_t px, py;
01902    for (Int_t i = 0; i < 25000; i++) {
01903       gRandom->Rannor(px,py);
01904       hlcc->Fill(px-1,5*py);
01905       hlcc->Fill(2+0.5*px,2*py-10.,0.1);
01906    }
01907    hlcc->SetFillColor(kYellow);
01908    c3->cd(1) ; hlcc->Draw("LEGO1 CYL");
01909    c3->cd(2) ; TH2F *hlpc = hlcc->DrawClone("LEGO1 POL");
01910    hlpc->SetTitle("Polar coordinates");
01911    c3->cd(3) ; TH2F *hlsc = hlcc->DrawClone("LEGO1 SPH");
01912    hlsc->SetTitle("Spherical coordinates");
01913    c3->cd(4) ; TH2F *hlprpc = hlcc->DrawClone("LEGO1 PSR");
01914    hlprpc->SetTitle("PseudoRapidity/Phi coordinates");
01915    return c3;
01916 }
01917 End_Macro
01918 Begin_Html
01919 
01920 The following example shows the same histogram as a surface plot is the four
01921 different coordinates systems.
01922 
01923 End_Html
01924 Begin_Macro(source)
01925 {
01926    TCanvas *c4 = new TCanvas("c4","c4",600,400);
01927    c4->Divide(2,2);
01928    TH2F *hscc = new TH2F("hscc","Cylindrical coordinates",20,-4,4,20,-20,20);
01929    Float_t px, py;
01930    for (Int_t i = 0; i < 25000; i++) {
01931       gRandom->Rannor(px,py);
01932       hscc->Fill(px-1,5*py);
01933       hscc->Fill(2+0.5*px,2*py-10.,0.1);
01934    }
01935    gStyle->SetPalette(1);
01936    c4->cd(1) ; hscc->Draw("SURF1 CYL");
01937    c4->cd(2) ; TH2F *hspc = hscc->DrawClone("SURF1 POL");
01938    hspc->SetTitle("Polar coordinates");
01939    c4->cd(3) ; TH2F *hssc = hscc->DrawClone("SURF1 SPH");
01940    hssc->SetTitle("Spherical coordinates");
01941    c4->cd(4) ; TH2F *hsprpc = hscc->DrawClone("SURF1 PSR");
01942    hsprpc->SetTitle("PseudoRapidity/Phi coordinates");
01943    return c4;
01944 }
01945 End_Macro
01946 Begin_Html
01947 
01948 
01949 <a name="HP20"></a><h3>Base line for bar-charts and lego plots</h3>
01950 
01951 
01952 By default the base line used to draw the boxes for bar-charts and lego plots is
01953 the histogram minimum. It is possible to force this base line to be 0 with the
01954 command:
01955 <pre>
01956       gStyle->SetHistMinimumZero();
01957 </pre>
01958 
01959 End_Html
01960 Begin_Macro(source)
01961 {
01962    TCanvas *c5 = new TCanvas("c5","c5",700,400);
01963    c5->Divide(2,1);
01964    gStyle->SetHistMinimumZero(1);
01965    TH1F *hz1 = new TH1F("hz1","Bar-chart drawn from 0",20,-3,3);
01966    TH2F *hz2 = new TH2F("hz2","Lego plot drawn from 0",20,-3,3,20,-3,3);
01967    Int_t i;
01968    Double_t x,y;
01969    hz1->SetFillColor(kBlue);
01970    hz2->SetFillColor(kBlue);
01971    for (i=0;i<10000;i++) {
01972       x = gRandom->Gaus(0,1);
01973       y = gRandom->Gaus(0,1);
01974       if (x>0) {
01975          hz1->Fill(x,1);
01976          hz2->Fill(x,y,1);
01977       } else {
01978          hz1->Fill(x,-1);
01979          hz2->Fill(x,y,-2);
01980       }
01981    }
01982    c5->cd(1); hz1->Draw("bar2");
01983    c5->cd(2); hz2->Draw("lego1");
01984    return c5;
01985 }
01986 End_Macro
01987 Begin_Html
01988 
01989 This option also works for horizontal plots. The example given in the section
01990 <a href="http://root.cern.ch/root/html/THistPainter.html#HP100">
01991 "The bar chart option"</a> appears as follow:
01992 
01993 End_Html
01994 Begin_Macro(source)
01995 {
01996    int i;
01997    const Int_t nx = 8;
01998    char *os_X[nx]   = {"8","32","128","512","2048","8192","32768","131072"};
01999    float d_35_0[nx] = {0.75, -3.30, -0.92, 0.10, 0.08, -1.69, -1.29, -2.37};
02000    float d_35_1[nx] = {1.01, -3.02, -0.65, 0.37, 0.34, -1.42, -1.02, -2.10};
02001 
02002    TCanvas *cbh = new TCanvas("cbh","cbh",400,600);
02003    cbh->SetGrid();
02004 
02005    gStyle->SetHistMinimumZero();
02006 
02007    TH1F *h1bh = new TH1F("h1bh","Option HBAR centered on 0",nx,0,nx);
02008    h1bh->SetFillColor(4);
02009    h1bh->SetBarWidth(0.4);
02010    h1bh->SetBarOffset(0.1);
02011    h1bh->SetStats(0);
02012    h1bh->SetMinimum(-5);
02013    h1bh->SetMaximum(5);
02014 
02015    for (i=1; i<=nx; i++) {
02016       h1bh->Fill(os_X[i-1], d_35_0[i-1]);
02017       h1bh->GetXaxis()->SetBinLabel(i,os_X[i-1]);
02018    }
02019 
02020    h1bh->Draw("hbar");
02021 
02022    TH1F *h2bh = new TH1F("h2bh","h2bh",nx,0,nx);
02023    h2bh->SetFillColor(38);
02024    h2bh->SetBarWidth(0.4);
02025    h2bh->SetBarOffset(0.5);
02026    h2bh->SetStats(0);
02027    for (i=1;i<=nx;i++) h2bh->Fill(os_X[i-1], d_35_1[i-1]);
02028 
02029    h2bh->Draw("hbar same");
02030 
02031    return cbh;
02032 }
02033 End_Macro
02034 Begin_Html
02035 
02036 
02037 <a name="HP20a"></a><h3>TH2Poly Drawing</h3>
02038 
02039 <tt>TH2Poly</tt> can be drawn as a color plot (option COL).
02040 <tt>TH2Poly</tt> bins can have any shapes. The bins are defined as graphs. The
02041 following macro is a very simple example showing how to book a TH2Poly and draw
02042 it.
02043 End_Html
02044 Begin_Macro(source)
02045 {
02046    TCanvas *ch2p1 = new TCanvas("ch2p1","ch2p1",600,400);
02047    TH2Poly *h2p = new TH2Poly();
02048    h2p->SetName("h2poly_name");
02049    h2p->SetTitle("h2poly_title");
02050    Double_t x1[] = {0, 5, 6};
02051    Double_t y1[] = {0, 0, 5};
02052    Double_t x2[] = {0, -1, -1, 0};
02053    Double_t y2[] = {0, 0, -1, 3};
02054    Double_t x3[] = {4, 3, 0, 1, 2.4};
02055    Double_t y3[] = {4, 3.7, 1, 4.7, 3.5};
02056    h2p->AddBin(3, x1, y1);
02057    h2p->AddBin(4, x2, y2);
02058    h2p->AddBin(4, x3, y3);
02059    h2p->Fill(0.1, 0.01, 3);
02060    h2p->Fill(-0.5, -0.5, 7);
02061    h2p->Fill(-0.7, -0.5, 1);
02062    h2p->Fill(1, 3, 1.5);
02063    Double_t fx[] = {0.1, -0.5, -0.7, 1};
02064    Double_t fy[] = {0.01, -0.5, -0.5, 3};
02065    Double_t fw[] = {3, 1, 1, 1.5};
02066    h2p->FillN(4, fx, fy, fw);
02067    gStyle->SetPalette(1);
02068    h2p->Draw("col");
02069    return ch2p1;
02070 }
02071 End_Macro
02072 Begin_Html
02073 
02074 <p>Rectangular bins are a frequent case. The method <tt>AddBinBox</tt> allows
02075 to define them more easily like shown in the following example.
02076 
02077 End_Html
02078 Begin_Macro(source)
02079 ../../../tutorials/hist/th2polyBoxes.C
02080 End_Macro
02081 Begin_Html
02082 
02083 <p>One <tt>TH2Poly</tt> bin can be a list of polygons. Such bins are defined
02084 by calling <tt>AddBin</tt> with a <tt>TMultiGraph</tt>. The following example
02085 shows a such case:
02086 End_Html
02087 Begin_Macro(source)
02088 {
02089    TCanvas *ch2p2 = new TCanvas("ch2p2","ch2p2",600,400);
02090 
02091    Int_t i, bin;
02092    const Int_t nx = 48;
02093    char *states [nx] = {
02094       "alabama",      "arizona",        "arkansas",       "california",
02095       "colorado",     "connecticut",    "delaware",       "florida",
02096       "georgia",      "idaho",          "illinois",       "indiana",
02097       "iowa",         "kansas",         "kentucky",       "louisiana",
02098       "maine",        "maryland",       "massachusetts",  "michigan",
02099       "minnesota",    "mississippi",    "missouri",       "montana",
02100       "nebraska",     "nevada",         "new_hampshire",  "new_jersey",
02101       "new_mexico",   "new_york",       "north_carolina", "north_dakota",
02102       "ohio",         "oklahoma",       "oregon",         "pennsylvania",
02103       "rhode_island", "south_carolina", "south_dakota",   "tennessee",
02104       "texas",        "utah",           "vermont",        "virginia",
02105       "washington",   "west_virginia",  "wisconsin",      "wyoming"
02106    };
02107    Float_t pop[nx] = {
02108     4708708, 6595778,  2889450, 36961664, 5024748,  3518288,  885122, 18537969,
02109     9829211, 1545801, 12910409,  6423113, 3007856,  2818747, 4314113,  4492076,
02110     1318301, 5699478,  6593587,  9969727, 5266214,  2951996, 5987580,   974989,
02111     1796619, 2643085,  1324575,  8707739, 2009671, 19541453, 9380884,   646844,
02112    11542645, 3687050,  3825657, 12604767, 1053209,  4561242,  812383,  6296254,
02113    24782302, 2784572,   621760,  7882590, 6664195,  1819777, 5654774,   544270
02114    };
02115 
02116    Double_t lon1 = -130;
02117    Double_t lon2 = -65;
02118    Double_t lat1 = 24;
02119    Double_t lat2 = 50;
02120    TH2Poly *p = new TH2Poly("USA","USA Population",lon1,lon2,lat1,lat2);
02121 
02122    TFile *f;
02123    f = TFile::Open("http://root.cern.ch/files/usa.root");
02124 
02125    TMultiGraph *mg;
02126    TKey *key;
02127    TIter nextkey(gDirectory->GetListOfKeys());
02128    while (key = (TKey*)nextkey()) {
02129       obj = key->ReadObj();
02130       if (obj->InheritsFrom("TMultiGraph")) {
02131          mg = (TMultiGraph*)obj;
02132          bin = p->AddBin(mg);
02133       }
02134    }
02135 
02136    for (i=0; i<nx; i++) p->Fill(states[i], pop[i]);
02137 
02138    gStyle->SetOptStat(11);
02139    gStyle->SetPalette(1);
02140    p->Draw("COLZ");
02141    return ch2p2;
02142 }
02143 End_Macro
02144 Begin_Html
02145 
02146 <p> <tt>TH2Poly</tt> histograms can also be plotted using the GL interface using
02147 the option "GLLEGO".
02148 
02149 <a name="HP21"></a><h3>The SPEC option</h3>
02150 
02151 
02152 This option allows to use the <tt>TSpectrum2Painter</tt> tools. See the full
02153 documentation in <tt>TSpectrum2Painter::PaintSpectrum</tt>.
02154 
02155 
02156 <a name="HP22"></a><h3>Option "Z" : Adding the color palette on the right side of the pad</h3>
02157 
02158 
02159 When this option is specified, a color palette with an axis indicating the value
02160 of the corresponding color is drawn on the right side of the picture. In case,
02161 not enough space is left, one can increase the size of the right margin by
02162 calling <tt>TPad::SetRightMargin()</tt>. The attributes used to display the
02163 palette axis values are taken from the Z axis of the object. For example, to
02164 set the labels size on the palette axis do:
02165 <pre>
02166       hist->GetZaxis()->SetLabelSize().
02167 </pre>
02168 <b>WARNING:</b> The palette axis is always drawn vertically.
02169 
02170 
02171 <a name="HP23"></a><h3>Setting the color palette</h3>
02172 
02173 
02174 To change the color palette <tt>TStyle::SetPalette</tt> should be used, eg:
02175 <pre>
02176       gStyle->SetPalette(ncolors,colors);
02177 </pre>
02178 For example the option <tt>"COL"</tt> draws a 2D histogram with cells
02179 represented by a box filled with a color index which is a function
02180 of the cell content.
02181 If the cell content is N, the color index used will be the color number
02182 in <tt>colors[N]</tt>, etc. If the maximum cell content is greater than
02183 <tt>ncolors</tt>, all cell contents are scaled to <tt>ncolors</tt>.
02184 
02185 <p>If <tt> ncolors <= 0</tt>, a default palette (see below) of 50 colors is
02186 defined. This palette is recommended for pads, labels ...
02187 
02188 <p>If <tt>ncolors == 1 && colors == 0</tt>, a pretty palette with a violet to
02189 red spectrum is created. It is recommended you use this palette when drawing
02190 legos, surfaces or contours.
02191 
02192 <p>If ncolors > 50 and colors=0, the DeepSea palette is used.
02193 (see <tt>TColor::CreateGradientColorTable</tt> for more details)
02194 
02195 <p> If <tt>ncolors > 0 && colors == 0</tt>, the default palette is used
02196 with a maximum of ncolors.
02197 
02198 <p> The default palette defines:
02199 <ul>
02200 <li> index  0  to  9 : shades of grey
02201 <li> index 10  to 19 : shades of brown
02202 <li> index 20  to 29 : shades of blue
02203 <li> index 30  to 39 : shades of red
02204 <li> index 40  to 49 : basic colors
02205 </ul>
02206 The color numbers specified in the palette can be viewed by selecting
02207 the item <tt>"colors"</tt> in the <tt>"VIEW"</tt> menu of the canvas tool bar.
02208 The red, green, and blue components of a color can be changed thanks to
02209 <tt>TColor::SetRGB()</tt>.
02210 
02211 
02212 <a name="HP24"></a><h3>Drawing a sub-range of a 2D histogram; the [cutg] option</h3>
02213 
02214 
02215 Using a <tt>TCutG</tt> object, it is possible to draw a sub-range of a 2D
02216 histogram. One must create a graphical cut (mouse or C++) and specify the name
02217 of the cut between <tt>[]</tt> in the <tt>Draw()</tt> option.
02218 For example, with a <tt>TCutG</tt> named <tt>"cutg"</tt>, one can call:
02219 <pre>
02220       myhist->Draw("surf1 [cutg]");
02221 </pre>
02222 To invert the cut, it is enough to put a <tt>"-"</tt> in front of its name:
02223 <pre>
02224       myhist->Draw("surf1 [-cutg]");
02225 </pre>
02226 It is possible to apply several cuts (<tt>","</tt> means logical AND):
02227 <pre>
02228       myhist->Draw("surf1 [cutg1,cutg2]");
02229 </pre>
02230 
02231 End_Html
02232 Begin_Macro(source)
02233 ../../../tutorials/fit/fit2a.C
02234 End_Macro
02235 Begin_Html
02236 
02237 
02238 <a name="HP25"></a><h3>Drawing options for 3D histograms</h3>
02239 
02240 
02241 <table border=0>
02242 
02243 <tr><th valign=top>"ISO"</th><td>
02244 Draw a Gouraud shaded 3d iso surface through a 3d histogram. It paints one
02245 surface at the value computed as follow:
02246 <tt>SumOfWeights/(NbinsX*NbinsY*NbinsZ)</tt>
02247 </td></tr>
02248 
02249 <tr><th valign=top>"BOX"</th><td>
02250 Draw a for each cell with volume proportional to the content's absolute value.
02251 </td></tr>
02252 
02253 </table>
02254 
02255 By default, like 2D histograms, 3D histograms are drawn as scatter plots.
02256 
02257 <p>The following example shows a 3D histogram plotted as a scatter plot.
02258 
02259 End_Html
02260 Begin_Macro(source)
02261 {
02262    TCanvas *c06 = new TCanvas("c06","c06",600,400);
02263    gStyle->SetOptStat(kFALSE);
02264    TH3F *h3scat = new TH3F("h3scat","Option SCAT (default) ",15,-2,2,15,-2,2,15,0,4);
02265    Double_t x, y, z;
02266    for (Int_t i=0;i<10000;i++) {
02267       gRandom->Rannor(x, y);
02268       z = x*x + y*y;
02269       h3scat->Fill(x,y,z);
02270    }
02271    h3scat->Draw();
02272    return c06;
02273 }
02274 End_Macro
02275 Begin_Html
02276 
02277 The following example shows a 3D histogram plotted with the option <tt>"BOX"</tt>.
02278 
02279 End_Html
02280 Begin_Macro(source)
02281 {
02282    TCanvas *c16 = new TCanvas("c16","c16",600,400);
02283    gStyle->SetOptStat(kFALSE);
02284    TH3F *h3box = new TH3F("h3box","Option BOX",15,-2,2,15,-2,2,15,0,4);
02285    Double_t x, y, z;
02286    for (Int_t i=0;i<10000;i++) {
02287       gRandom->Rannor(x, y);
02288       z = x*x + y*y;
02289       h3box->Fill(x,y,z);
02290    }
02291    h3box->Draw("BOX");
02292    return c16;
02293 }
02294 End_Macro
02295 Begin_Html
02296 
02297 The following example shows a 3D histogram plotted with the option <tt>"ISO"</tt>.
02298 
02299 End_Html
02300 Begin_Macro(source)
02301 {
02302    TCanvas *c26 = new TCanvas("c26","c26",600,400);
02303    gStyle->SetOptStat(kFALSE);
02304    TH3F *h3iso = new TH3F("h3iso","Option ISO",15,-2,2,15,-2,2,15,0,4);
02305    Double_t x, y, z;
02306    for (Int_t i=0;i<10000;i++) {
02307       gRandom->Rannor(x, y);
02308       z = x*x + y*y;
02309       h3iso->Fill(x,y,z);
02310    }
02311    h3iso->SetFillColor(kCyan);
02312    h3iso->Draw("ISO");
02313    return c26;
02314 }
02315 End_Macro
02316 Begin_Html
02317 
02318 
02319 <a name="HP26"></a><h3>Drawing option for histograms' stacks</h3>
02320 
02321 
02322 Stacks of histograms are managed with the <tt>THStack</tt>. A <tt>THStack</tt>
02323 is a collection of <tt>TH1</tt> (or derived) objects. For painting only the
02324 <tt>THStack</tt> containing <tt>TH1</tt> only or
02325 <tt>THStack</tt> containing <tt>TH2</tt> only will be considered.
02326 
02327 <p>By default, histograms are shown stacked:
02328 <ol>
02329 <li> The first histogram is paint.
02330 <li> The the sum of the first and second, etc...
02331 </ol>
02332 If the option <tt>"NOSTACK"</tt> is specified, the histograms are all paint in
02333 the same pad as if the option <tt>"SAME"</tt> had been specified. This allows to
02334 compute X and Y scales common to all the histograms, like
02335 <tt>TMultiGraph</tt> does for graphs.
02336 
02337 <p>If the option <tt>"PADS"</tt> is specified, the current pad/canvas is
02338 subdivided into a number of pads equal to the number of histograms and each
02339 histogram is paint into a separate pad.
02340 
02341 <p>The following example shows various types of stacks.
02342 
02343 End_Html
02344 Begin_Macro(source)
02345 ../../../tutorials/hist/hstack.C
02346 End_Macro
02347 Begin_Html
02348 
02349 If at least one of the histograms in the stack has errors, the whole stack is
02350 visualized by default with error bars. To visualize it without errors the
02351 option <tt>"HIST"</tt> should be used.
02352 
02353 End_Html
02354 Begin_Macro(source)
02355 {
02356    TCanvas *cst1 = new TCanvas("cst1","cst1",700,400);
02357    cst1->Divide(2,1);
02358 
02359    TH1F * hst11 = new TH1F("hst11", "", 20, -10, 10);
02360    hst11->Sumw2();
02361    hst11->FillRandom("gaus", 1000);
02362    hst11->SetFillColor(kViolet);
02363    hst11->SetLineColor(kViolet);
02364 
02365    TH1F * hst12 = new TH1F("hst12", "", 20, -10, 10);
02366    hst12->FillRandom("gaus", 500);
02367    hst12->SetFillColor(kBlue);
02368    hst12->SetLineColor(kBlue);
02369 
02370    THStack st1("st1", "st1");
02371    st1.Add(hst11);
02372    st1.Add(hst12);
02373 
02374    cst1->cd(1); st1.Draw();
02375    cst1->cd(2); st1.Draw("hist");
02376 
02377    return cst1;
02378 }
02379 End_Macro
02380 Begin_Html
02381 
02382 <a name="HP27"></a><h3>Drawing of 3D implicit functions</h3>
02383 
02384 
02385 3D implicit functions (<tt>TF3</tt>) can be drawn the following way:
02386 
02387 End_Html
02388 Begin_Macro(source)
02389 {
02390    TCanvas *c2 = new TCanvas("c2","c2",600,400);
02391    TF3 *f3 = new TF3("f3","sin(x*x+y*y+z*z-36)",-2,2,-2,2,-2,2);
02392    f3->SetClippingBoxOn(0,0,0);
02393    f3->SetFillColor(30);
02394    f3->SetLineColor(15);
02395    f3->Draw("FBBB");
02396    return c2;
02397 }
02398 End_Macro
02399 Begin_Html
02400 
02401 
02402 <a name="HP28"></a><h3>Associated functions drawing</h3>
02403 
02404 
02405 An associated function is created by <tt>TH1::Fit</tt>. More than on fitted
02406 function can be associated with one histogram (see <tt>TH1::Fit</tt>).
02407 
02408 <p>A <tt>TF1</tt> object <tt>f1</tt> can be added to the list of associated
02409 functions of an histogram <tt>h</tt> without calling <tt>TH1::Fit</tt>
02410 simply doing:
02411 <pre>
02412       h->GetListOfFunctions()->Add(f1);
02413 </pre>
02414 or
02415 <pre>
02416       h->GetListOfFunctions()->Add(f1,someoption);
02417 </pre>
02418 To retrieve a function by name from this list, do:
02419 <pre>
02420       TF1 *f1 = (TF1*)h->GetListOfFunctions()->FindObject(name);
02421 </pre>
02422 or
02423 <pre>
02424       TF1 *f1 = h->GetFunction(name);
02425 </pre>
02426 Associated functions are automatically painted when an histogram is drawn.
02427 To avoid the painting of the associated functions the option <tt>HIST</tt>
02428 should be added to the list of the options used to paint the histogram.
02429 
02430 
02431 <a name="HP29"></a><h3>Drawing using OpenGL</h3>
02432 
02433 
02434 The class <tt>TGLHistPainter</tt> allows to paint data set using the OpenGL 3D
02435 graphics library. The plotting options start with <tt>GL</tt> keyword.
02436 In addition, in order to inform canvases that OpenGL should be used to render
02437 3D representations, the following option should be set:
02438 <pre>
02439       gStyle->SetCanvasPreferGL(true);
02440 </pre>
02441 
02442 <a name="HP29a"></a><h4><u>General information: plot types and supported options</u></h4>
02443 
02444 The following types of plots are provided:
02445 
02446 <p>For lego plots the supported options are:
02447 
02448 <table border=0>
02449 
02450 <tr><th valign=top>"GLLEGO"</th><td>
02451 Draw a lego plot. It works also for <tt>TH2Poly</tt>.
02452 </td></tr>
02453 
02454 <tr><th valign=top>"GLLEGO2</th><td>
02455 Bins with color levels.
02456 </td></tr>
02457 
02458 <tr><th valign=top>"GLLEGO3</th><td>
02459 Cylindrical bars.
02460 </td></tr>
02461 
02462 </table>
02463 
02464 <p>Lego painter in cartesian supports logarithmic scales for X, Y, Z.
02465 In polar only Z axis can be logarithmic, in cylindrical only Y.
02466 
02467 <p>For surface plots (<tt>TF2</tt> and <tt>TH2</tt>) the supported options are:
02468 
02469 <table border=0>
02470 
02471 <tr><th valign=top>"GLSURF" </th><td>
02472 Draw a surface.
02473 </td></tr>
02474 
02475 <tr><th valign=top>"GLSURF1"</th><td>
02476 Surface with color levels
02477 </td></tr>
02478 
02479 <tr><th valign=top>"GLSURF2"</th><td>
02480 The same as "GLSURF1" but without polygon outlines.
02481 </td></tr>
02482 
02483 <tr><th valign=top>"GLSURF3"</th><td>
02484 Color level projection on top of plot (works only in cartesian coordinate
02485 system).
02486 </td></tr>
02487 
02488 <tr><th valign=top>"GLSURF4"</th><td>
02489 Same as "GLSURF" but without polygon outlines.
02490 </td></tr>
02491 
02492 </table>
02493 
02494 The surface painting in cartesian coordinates supports logarithmic scales along
02495 X, Y, Z axis. In polar coordinates only the Z axis can be logarithmic,
02496 in cylindrical coordinates only the Y axis.
02497 
02498 <p>Additional options to SURF and LEGO - Coordinate systems:
02499 
02500 <table border=0>
02501 
02502 <tr><th valign=top>" "</th><td>
02503 Default, cartesian coordinates system.
02504 </td></tr>
02505 
02506 <tr><th valign=top>"POL"</th><td>
02507 Polar coordinates system.
02508 </td></tr>
02509 
02510 <tr><th valign=top>"CYL"</th><td>
02511 Cylindrical coordinates system.
02512 </td></tr>
02513 
02514 <tr><th valign=top>"SPH"</th><td>
02515 Spherical coordinates system.
02516 </td></tr>
02517 
02518 </table>
02519 
02520 <a name="HP29b"></a><h4><u>TH3 as boxes (spheres)</u></h4>
02521 
02522 The supported options are:
02523 
02524 <table border=0>
02525 
02526 <tr><th valign=top>GLBOX" </th><td>
02527 TH3 as a set of boxes, size of box is proportional to bin content.
02528 </td></tr>
02529 
02530 <tr><th valign=top>GLBOX1"</th><td>
02531 The same as "glbox", but spheres are drawn instead of boxes.
02532 </td></tr>
02533 
02534 </table>
02535 
02536 <a name="HP29c"></a><h4><u>TH3 as iso-surface(s)</u></h4>
02537 
02538 The supported option is:
02539 
02540 <table border=0>
02541 
02542 <tr><th valign=top>"GLISO" </th><td>
02543 TH3 is drawn using iso-surfaces.
02544 </td></tr>
02545 
02546 </table>
02547 
02548 <a name="HP29d"></a><h4><u>TF3 (implicit function)</u></h4>
02549 
02550 The supported option is:
02551 
02552 <table border=0>
02553 
02554 <tr><th valign=top>GLTF3" </th><td>
02555 Draw a TF3.
02556 </td></tr>
02557 
02558 </table>
02559 
02560 <a name="HP29e"></a><h4><u>Parametric surfaces</u></h4>
02561 
02562 <tt>$ROOTSYS/tutorials/gl/glparametric.C</tt> shows how to create parametric
02563 equations and visualize the surface.
02564 
02565 <a name="HP29f"></a><h4><u>Interaction with the plots</u></h4>
02566 
02567 All the interactions are implemented via standard methods
02568 <tt>DistancetoPrimitive()</tt> and <tt>ExecuteEvent()</tt>. That's why all the
02569 interactions with the OpenGL plots are possible only when the mouse cursor is
02570 in the plot's area (the plot's area is the part of a the pad occupied by
02571 gl-produced picture). If the mouse cursor is not above gl-picture, the standard
02572 pad interaction is performed.
02573 
02574 <a name="HP29g"></a><h4><u>Selectable parts</u></h4>
02575 
02576 Different parts of the plot can be selected:
02577 <ul>
02578 <li> xoz, yoz, xoy back planes:
02579 When such a plane selected, it's highlighted in green if the
02580 dynamic slicing by this plane is supported, and it's
02581 highlighted in red, if the dynamic slicing is not supported.
02582 <li> The plot itself:
02583 On surfaces, the selected surface is outlined in red. (TF3 and
02584 ISO are not outlined). On lego plots, the selected bin is
02585 highlighted. The bin number and content are displayed in pad's
02586 status bar. In box plots, the box or sphere is highlighted and
02587 the bin info is displayed in pad's status bar.
02588 </ul>
02589 
02590 <a name="HP29h"></a><h4><u>Rotation and zooming</u></h4>
02591 
02592 <ul>
02593 <li>Rotation:
02594 When the plot is selected, it can be rotated by pressing and
02595 holding the left mouse button and move the cursor.
02596 <li>Zoom/Unzoom:
02597 Mouse wheel or 'j', 'J', 'k', 'K' keys.
02598 </ul>
02599 
02600 <a name="HP29i"></a><h4><u>Panning</u></h4>
02601 
02602 The selected plot can be moved in a pad's area by pressing and
02603 holding the left mouse button and the shift key.
02604 
02605 <a name="HP29j"></a><h4><u>Box cut</u></h4>
02606 
02607 Surface, iso, box, TF3 and parametric painters support box cut by
02608 pressing the 'c' or 'C' key when the mouse cursor is in a plot's
02609 area. That will display a transparent box, cutting away part of the
02610 surface (or boxes) in order to show internal part of plot. This box
02611 can be moved inside the plot's area (the full size of the box is
02612 equal to the plot's surrounding box) by selecting one of the box
02613 cut axes and pressing the left mouse button to move it.
02614 
02615 <a name="HP29k"></a><h4><u>Plot specific interactions (dynamic slicing etc.)</u></h4>
02616 
02617 Currently, all gl-plots support some form of slicing. When back plane
02618 is selected (and if it's highlighted in green) you can press and hold
02619 left mouse button and shift key and move this back plane inside
02620 plot's area, creating the slice. During this "slicing" plot becomes
02621 semi-transparent. To remove all slices (and projected curves for
02622 surfaces) double click with left mouse button in a plot's area.
02623 
02624 <a name="HP29l"></a><h4><u>Surface with option "GLSURF"</u></h4>
02625 
02626 The surface profile is displayed on the slicing plane.
02627 The profile projection is drawn on the back plane
02628 by pressing <tt>'p'</tt> or <tt>'P'</tt> key.
02629 
02630 <a name="HP29m"></a><h4><u>TF3</u></h4>
02631 
02632 The contour plot is drawn on the slicing plane. For TF3 the color
02633 scheme can be changed by pressing 's' or 'S'.
02634 
02635 <a name="HP29n"></a><h4><u>Box</u></h4>
02636 
02637 The contour plot corresponding to slice plane position is drawn in real time.
02638 
02639 <a name="HP29o"></a><h4><u>Iso</u></h4>
02640 
02641 Slicing is similar to "GLBOX" option.
02642 
02643 <a name="HP29p"></a><h4><u>Parametric plot</u></h4>
02644 
02645 No slicing. Additional keys: 's' or 'S' to change color scheme -
02646 about 20 color schemes supported ('s' for "scheme"); 'l' or 'L' to
02647 increase number of polygons ('l' for "level" of details), 'w' or 'W'
02648 to show outlines ('w' for "wireframe").
02649 
02650 End_Html */
02651 
02652 TH1 *gCurrentHist = 0;
02653 
02654 Hoption_t Hoption;
02655 Hparam_t  Hparam;
02656 
02657 const Int_t kNMAX = 2000;
02658 
02659 const Int_t kMAXCONTOUR  = 104;
02660 const UInt_t kCannotRotate = BIT(11);
02661 
02662 static TString gStringEntries;
02663 static TString gStringMean;
02664 static TString gStringMeanX;
02665 static TString gStringMeanY;
02666 static TString gStringMeanZ;
02667 static TString gStringRMS;
02668 static TString gStringRMSX;
02669 static TString gStringRMSY;
02670 static TString gStringRMSZ;
02671 static TString gStringUnderflow;
02672 static TString gStringOverflow;
02673 static TString gStringIntegral;
02674 static TString gStringSkewness;
02675 static TString gStringSkewnessX;
02676 static TString gStringSkewnessY;
02677 static TString gStringSkewnessZ;
02678 static TString gStringKurtosis;
02679 static TString gStringKurtosisX;
02680 static TString gStringKurtosisY;
02681 static TString gStringKurtosisZ;
02682 
02683 ClassImp(THistPainter)
02684 
02685 
02686 //______________________________________________________________________________
02687 THistPainter::THistPainter()
02688 {
02689    /* Begin_html
02690    Default constructor.
02691    End_html */
02692 
02693    fH = 0;
02694    fXaxis = 0;
02695    fYaxis = 0;
02696    fZaxis = 0;
02697    fFunctions = 0;
02698    fXbuf  = 0;
02699    fYbuf  = 0;
02700    fNcuts = 0;
02701    fStack = 0;
02702    fLego  = 0;
02703    fPie   = 0;
02704    fGraph2DPainter = 0;
02705    fShowProjection = 0;
02706    fShowOption = "";
02707    for (int i=0; i<kMaxCuts; i++) {
02708       fCuts[i] = 0;
02709       fCutsOpt[i] = 0;
02710    }
02711 
02712    gStringEntries   = gEnv->GetValue("Hist.Stats.Entries",   "Entries");
02713    gStringMean      = gEnv->GetValue("Hist.Stats.Mean",      "Mean");
02714    gStringMeanX     = gEnv->GetValue("Hist.Stats.MeanX",     "Mean x");
02715    gStringMeanY     = gEnv->GetValue("Hist.Stats.MeanY",     "Mean y");
02716    gStringMeanZ     = gEnv->GetValue("Hist.Stats.MeanZ",     "Mean z");
02717    gStringRMS       = gEnv->GetValue("Hist.Stats.RMS",       "RMS");
02718    gStringRMSX      = gEnv->GetValue("Hist.Stats.RMSX",      "RMS x");
02719    gStringRMSY      = gEnv->GetValue("Hist.Stats.RMSY",      "RMS y");
02720    gStringRMSZ      = gEnv->GetValue("Hist.Stats.RMSZ",      "RMS z");
02721    gStringUnderflow = gEnv->GetValue("Hist.Stats.Underflow", "Underflow");
02722    gStringOverflow  = gEnv->GetValue("Hist.Stats.Overflow",  "Overflow");
02723    gStringIntegral  = gEnv->GetValue("Hist.Stats.Integral",  "Integral");
02724    gStringSkewness  = gEnv->GetValue("Hist.Stats.Skewness",  "Skewness");
02725    gStringSkewnessX = gEnv->GetValue("Hist.Stats.SkewnessX", "Skewness x");
02726    gStringSkewnessY = gEnv->GetValue("Hist.Stats.SkewnessY", "Skewness y");
02727    gStringSkewnessZ = gEnv->GetValue("Hist.Stats.SkewnessZ", "Skewness z");
02728    gStringKurtosis  = gEnv->GetValue("Hist.Stats.Kurtosis",  "Kurtosis");
02729    gStringKurtosisX = gEnv->GetValue("Hist.Stats.KurtosisX", "Kurtosis x");
02730    gStringKurtosisY = gEnv->GetValue("Hist.Stats.KurtosisY", "Kurtosis y");
02731    gStringKurtosisZ = gEnv->GetValue("Hist.Stats.KurtosisZ", "Kurtosis z");
02732 }
02733 
02734 
02735 //______________________________________________________________________________
02736 THistPainter::~THistPainter()
02737 {
02738    /* Begin_html
02739    Default destructor.
02740    End_html */
02741 }
02742 
02743 
02744 //______________________________________________________________________________
02745 Int_t THistPainter::DistancetoPrimitive(Int_t px, Int_t py)
02746 {
02747    /* Begin_html
02748    Compute the distance from the point px,py to a line.
02749    <p>
02750    Compute the closest distance of approach from point px,py to elements of
02751    an histogram. The distance is computed in pixels units.
02752    <p>
02753    Algorithm:<br>
02754    Currently, this simple model computes the distance from the mouse to the
02755    histogram contour only.
02756    End_html */
02757 
02758    const Int_t big = 9999;
02759    const Int_t kMaxDiff = 7;
02760 
02761    if (fPie) return fPie->DistancetoPrimitive(px, py);
02762 
02763    Double_t x  = gPad->AbsPixeltoX(px);
02764    Double_t x1 = gPad->AbsPixeltoX(px+1);
02765 
02766    Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
02767    Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
02768    Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
02769    Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
02770    Int_t curdist = big;
02771    Int_t yxaxis, dyaxis,xyaxis, dxaxis;
02772    Bool_t dsame;
02773    TString doption = gPad->GetPadPointer()->GetDrawOption();
02774    Double_t factor = 1;
02775    if (fH->GetNormFactor() != 0) {
02776       factor = fH->GetNormFactor()/fH->GetSumOfWeights();
02777    }
02778    //     return if point is not in the histogram area
02779 
02780    //     If a 3D view exists, check distance to axis
02781    TView *view = gPad->GetView();
02782    Int_t d1,d2,d3;
02783    if (view && Hoption.Contour != 14) {
02784       Double_t ratio;
02785       d3 = view->GetDistancetoAxis(3, px, py, ratio);
02786       if (d3 <= kMaxDiff) {gPad->SetSelected(fZaxis); return 0;}
02787       d1 = view->GetDistancetoAxis(1, px, py, ratio);
02788       if (d1 <= kMaxDiff) {gPad->SetSelected(fXaxis); return 0;}
02789       d2 = view->GetDistancetoAxis(2, px, py, ratio);
02790       if (d2 <= kMaxDiff) {gPad->SetSelected(fYaxis); return 0;}
02791       if ( px > puxmin && px < puxmax && py > puymax && py < puymin) curdist = 1;
02792       goto FUNCTIONS;
02793    }
02794    //     check if point is close to an axis
02795    doption.ToLower();
02796    dsame = kFALSE;
02797    if (doption.Contains("same")) dsame = kTRUE;
02798 
02799    dyaxis = Int_t(2*(puymin-puymax)*fYaxis->GetLabelSize());
02800    if (doption.Contains("y+")) {
02801       xyaxis = puxmax + Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
02802       if (px <= xyaxis+dyaxis && px >= xyaxis && py >puymax && py < puymin) {
02803          if (!dsame) {
02804             if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
02805             else                    gPad->SetSelected(fXaxis);
02806             return 0;
02807          }
02808       }
02809    } else {
02810       xyaxis = puxmin - Int_t((puxmax-puxmin)*fYaxis->GetLabelOffset());
02811       if (px >= xyaxis-dyaxis && px <= xyaxis && py >puymax && py < puymin) {
02812          if (!dsame) {
02813             if (gPad->IsVertical()) gPad->SetSelected(fYaxis);
02814             else                    gPad->SetSelected(fXaxis);
02815             return 0;
02816          }
02817       }
02818    }
02819 
02820    dxaxis = Int_t((puymin-puymax)*fXaxis->GetLabelSize());
02821    if (doption.Contains("x+")) {
02822       yxaxis = puymax - Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
02823       if (py >= yxaxis-dxaxis && py <= yxaxis && px <puxmax && px > puxmin) {
02824          if (!dsame) {
02825             if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
02826             else                    gPad->SetSelected(fYaxis);
02827             return 0;
02828          }
02829       }
02830    } else {
02831       yxaxis = puymin + Int_t((puymin-puymax)*fXaxis->GetLabelOffset());
02832       if (yxaxis < puymin) yxaxis = puymin;
02833       if (py <= yxaxis+dxaxis && py >= yxaxis && px <puxmax && px > puxmin) {
02834          if (!dsame) {
02835             if (gPad->IsVertical()) gPad->SetSelected(fXaxis);
02836             else                    gPad->SetSelected(fYaxis);
02837             return 0;
02838          }
02839       }
02840    }
02841 
02842    //     if object is 2D or 3D return this object
02843    if (fH->GetDimension() == 2) {
02844       if (fH->InheritsFrom(TH2Poly::Class())) {
02845          TH2Poly *th2 = (TH2Poly*)fH;
02846          Int_t bin = th2->FindBin(gPad->AbsPixeltoX(px), gPad->AbsPixeltoY(py));
02847          if (bin>0) {curdist =1; goto FUNCTIONS;}
02848          else return big;
02849       }
02850       Int_t delta2 = 5; //Give a margin of delta2 pixels to be in the 2-d area
02851       if ( px > puxmin + delta2
02852         && px < puxmax - delta2
02853         && py > puymax + delta2
02854         && py < puymin - delta2) {curdist =1; goto FUNCTIONS;}
02855    }
02856 
02857    //     point is inside histogram area. Find channel number
02858    if (gPad->IsVertical()) {
02859       Int_t bin      = fXaxis->FindFixBin(gPad->PadtoX(x));
02860       Int_t binsup   = fXaxis->FindFixBin(gPad->PadtoX(x1));
02861       Double_t binval = factor*fH->GetBinContent(bin);
02862       Int_t pybin    = gPad->YtoAbsPixel(gPad->YtoPad(binval));
02863       if (binval == 0 && pybin < puymin) pybin = 10000;
02864       // special case if more than one bin for the pixel
02865       if (binsup-bin>1) {
02866          Double_t binvalmin, binvalmax;
02867          binvalmin=binval;
02868          binvalmax=binval;
02869          for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
02870             Double_t binvaltmp = factor*fH->GetBinContent(ibin);
02871             if (binvalmin>binvaltmp) binvalmin=binvaltmp;
02872             if (binvalmax<binvaltmp) binvalmax=binvaltmp;
02873          }
02874          Int_t pybinmin = gPad->YtoAbsPixel(gPad->YtoPad(binvalmax));
02875          Int_t pybinmax = gPad->YtoAbsPixel(gPad->YtoPad(binvalmin));
02876          if (py<pybinmax+kMaxDiff/2 && py>pybinmin-kMaxDiff/2) pybin = py;
02877       }
02878       if (TMath::Abs(py - pybin) <= kMaxDiff) return TMath::Abs(py - pybin);
02879    } else {
02880       Double_t y  = gPad->AbsPixeltoY(py);
02881       Double_t y1 = gPad->AbsPixeltoY(py+1);
02882       Int_t bin      = fXaxis->FindFixBin(gPad->PadtoY(y));
02883       Int_t binsup   = fXaxis->FindFixBin(gPad->PadtoY(y1));
02884       Double_t binval = factor*fH->GetBinContent(bin);
02885       Int_t pxbin    = gPad->XtoAbsPixel(gPad->XtoPad(binval));
02886       if (binval == 0 && pxbin > puxmin) pxbin = 10000;
02887       // special case if more than one bin for the pixel
02888       if (binsup-bin>1) {
02889          Double_t binvalmin, binvalmax;
02890          binvalmin=binval;
02891          binvalmax=binval;
02892          for (Int_t ibin=bin+1; ibin<binsup; ibin++) {
02893             Double_t binvaltmp = factor*fH->GetBinContent(ibin);
02894             if (binvalmin>binvaltmp) binvalmin=binvaltmp;
02895             if (binvalmax<binvaltmp) binvalmax=binvaltmp;
02896          }
02897          Int_t pxbinmin = gPad->XtoAbsPixel(gPad->XtoPad(binvalmax));
02898          Int_t pxbinmax = gPad->XtoAbsPixel(gPad->XtoPad(binvalmin));
02899          if (px<pxbinmax+kMaxDiff/2 && px>pxbinmin-kMaxDiff/2) pxbin = px;
02900       }
02901       if (TMath::Abs(px - pxbin) <= kMaxDiff) return TMath::Abs(px - pxbin);
02902    }
02903    //     Loop on the list of associated functions and user objects
02904 FUNCTIONS:
02905    TObject *f;
02906    TIter   next(fFunctions);
02907    while ((f = (TObject*) next())) {
02908       Int_t dist;
02909       if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
02910       else                               dist = f->DistancetoPrimitive(px,py);
02911       if (dist < kMaxDiff) {gPad->SetSelected(f); return dist;}
02912    }
02913    return curdist;
02914 }
02915 
02916 
02917 //______________________________________________________________________________
02918 void THistPainter::DrawPanel()
02919 {
02920    /* Begin_html
02921    Display a panel with all histogram drawing options.
02922    End_html */
02923 
02924    gCurrentHist = fH;
02925    if (!gPad) {
02926       Error("DrawPanel", "need to draw histogram first");
02927       return;
02928    }
02929    TVirtualPadEditor *editor = TVirtualPadEditor::GetPadEditor();
02930    editor->Show();
02931    gROOT->ProcessLine(Form("((TCanvas*)0x%lx)->Selected((TVirtualPad*)0x%lx,(TObject*)0x%lx,1)",
02932                            (ULong_t)gPad->GetCanvas(), (ULong_t)gPad, (ULong_t)fH));
02933 }
02934 
02935 
02936 //______________________________________________________________________________
02937 void THistPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
02938 {
02939    /* Begin_html
02940    Execute the actions corresponding to "event".
02941    <p>
02942    This function is called when a histogram is clicked with the locator at
02943    the pixel position px,py.
02944    End_html */
02945 
02946    static Int_t bin, px1, py1, px2, py2, pyold;
02947    Double_t xlow, xup, ylow, binval, x, baroffset, barwidth, binwidth;
02948 
02949    if (!gPad->IsEditable()) return;
02950 
02951    if (fPie) {
02952       fPie->ExecuteEvent(event, px, py);
02953       return;
02954    }
02955    //     come here if we have a lego/surface in the pad
02956    TView *view = gPad->GetView();
02957 
02958    if (!fShowProjection && view && view->TestBit(kCannotRotate) == 0) {
02959       view->ExecuteRotateView(event, px, py);
02960       return;
02961    }
02962 
02963    Double_t factor = 1;
02964    if (fH->GetNormFactor() != 0) {
02965       factor = fH->GetNormFactor()/fH->GetSumOfWeights();
02966    }
02967 
02968    switch (event) {
02969 
02970    case kButton1Down:
02971 
02972       gVirtualX->SetLineColor(-1);
02973       fH->TAttLine::Modify();
02974 
02975       // No break !!!
02976 
02977    case kMouseMotion:
02978 
02979       if (fShowProjection) {ShowProjection3(px,py); break;}
02980 
02981       if (Hoption.Bar) {
02982          baroffset = fH->GetBarOffset();
02983          barwidth  = fH->GetBarWidth();
02984       } else {
02985          baroffset = 0;
02986          barwidth  = 1;
02987       }
02988       x        = gPad->AbsPixeltoX(px);
02989       bin      = fXaxis->FindFixBin(gPad->PadtoX(x));
02990       binwidth = fH->GetBinWidth(bin);
02991       xlow     = gPad->XtoPad(fH->GetBinLowEdge(bin) + baroffset*binwidth);
02992       xup      = gPad->XtoPad(xlow + barwidth*binwidth);
02993       ylow     = gPad->GetUymin();
02994       px1      = gPad->XtoAbsPixel(xlow);
02995       px2      = gPad->XtoAbsPixel(xup);
02996       py1      = gPad->YtoAbsPixel(ylow);
02997       py2      = py;
02998       pyold    = py;
02999       if (gROOT->GetEditHistograms()) gPad->SetCursor(kArrowVer);
03000       else                            gPad->SetCursor(kPointer);
03001 
03002       break;
03003 
03004    case kButton1Motion:
03005 
03006    if (gROOT->GetEditHistograms()) {
03007          gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow);  //    Draw the old box
03008          py2 += py - pyold;
03009          gVirtualX->DrawBox(px1, py1, px2, py2,TVirtualX::kHollow);  //    Draw the new box
03010          pyold = py;
03011    }
03012 
03013       break;
03014 
03015    case kButton1Up:
03016 
03017       if (gROOT->GetEditHistograms()) {
03018          binval = gPad->PadtoY(gPad->AbsPixeltoY(py2))/factor;
03019          fH->SetBinContent(bin,binval);
03020          PaintInit();   // recalculate Hparam structure and recalculate range
03021       }
03022 
03023       // might resize pad pixmap so should be called before any paint routine
03024       RecalculateRange();
03025 
03026       gPad->Modified(kTRUE);
03027       gVirtualX->SetLineColor(-1);
03028 
03029       break;
03030 
03031    case kButton1Locate:
03032 
03033       ExecuteEvent(kButton1Down, px, py);
03034 
03035       while (1) {
03036          px = py = 0;
03037          event = gVirtualX->RequestLocator(1, 1, px, py);
03038 
03039          ExecuteEvent(kButton1Motion, px, py);
03040 
03041          if (event != -1) {                     // button is released
03042             ExecuteEvent(kButton1Up, px, py);
03043             return;
03044          }
03045       }
03046    }
03047 }
03048 
03049 //______________________________________________________________________________
03050 TList *THistPainter::GetContourList(Double_t contour) const
03051 {
03052    /* Begin_html
03053    Get a contour (as a list of TGraphs) using the Delaunay triangulation.
03054    End_html */
03055 
03056    TGraphDelaunay *dt;
03057 
03058    // Check if fH contains a TGraphDelaunay
03059    TList *hl = fH->GetListOfFunctions();
03060    dt = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
03061    if (!dt) return 0;
03062 
03063    gCurrentHist = fH;
03064 
03065    if (!fGraph2DPainter) ((THistPainter*)this)->fGraph2DPainter = new TGraph2DPainter(dt);
03066 
03067    return fGraph2DPainter->GetContourList(contour);
03068 }
03069 
03070 
03071 //______________________________________________________________________________
03072 char *THistPainter::GetObjectInfo(Int_t px, Int_t py) const
03073 {
03074    /* Begin_html
03075    Display the histogram info (bin number, contents, integral up to bin
03076    corresponding to cursor position px,py.
03077    End_html */
03078 
03079    if (!gPad) return (char*)"";
03080    static char info[100];
03081    Double_t x  = gPad->PadtoX(gPad->AbsPixeltoX(px));
03082    Double_t y  = gPad->PadtoY(gPad->AbsPixeltoY(py));
03083    Double_t x1 = gPad->PadtoX(gPad->AbsPixeltoX(px+1));
03084    const char *drawOption = fH->GetDrawOption();
03085    Double_t xmin, xmax, uxmin,uxmax;
03086    Double_t ymin, ymax, uymin,uymax;
03087    if (fH->GetDimension() == 2) {
03088       if (gPad->GetView() || strncmp(drawOption,"cont",4) == 0
03089                           || strncmp(drawOption,"CONT",4) == 0) {
03090          uxmin=gPad->GetUxmin();
03091          uxmax=gPad->GetUxmax();
03092          xmin = fXaxis->GetBinLowEdge(fXaxis->GetFirst());
03093          xmax = fXaxis->GetBinUpEdge(fXaxis->GetLast());
03094          x = xmin +(xmax-xmin)*(x-uxmin)/(uxmax-uxmin);
03095          uymin=gPad->GetUymin();
03096          uymax=gPad->GetUymax();
03097          ymin = fYaxis->GetBinLowEdge(fYaxis->GetFirst());
03098          ymax = fYaxis->GetBinUpEdge(fYaxis->GetLast());
03099          y = ymin +(ymax-ymin)*(y-uymin)/(uymax-uymin);
03100       }
03101    }
03102    Int_t binx,biny,binmin,binx1;
03103    if (gPad->IsVertical()) {
03104       binx   = fXaxis->FindFixBin(x);
03105       binmin = fXaxis->GetFirst();
03106       binx1  = fXaxis->FindFixBin(x1);
03107       // special case if more than 1 bin in x per pixel
03108       if (binx1-binx>1 && fH->GetDimension() == 1) {
03109          Double_t binval=fH->GetBinContent(binx);
03110          Int_t binnear=binx;
03111          for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
03112             Double_t binvaltmp = fH->GetBinContent(ibin);
03113             if (TMath::Abs(y-binvaltmp) < TMath::Abs(y-binval)) {
03114                binval=binvaltmp;
03115                binnear=ibin;
03116             }
03117          }
03118          binx = binnear;
03119       }
03120    } else {
03121       x1 = gPad->PadtoY(gPad->AbsPixeltoY(py+1));
03122       binx   = fXaxis->FindFixBin(y);
03123       binmin = fXaxis->GetFirst();
03124       binx1  = fXaxis->FindFixBin(x1);
03125       // special case if more than 1 bin in x per pixel
03126       if (binx1-binx>1 && fH->GetDimension() == 1) {
03127          Double_t binval=fH->GetBinContent(binx);
03128          Int_t binnear=binx;
03129          for (Int_t ibin=binx+1; ibin<binx1; ibin++) {
03130             Double_t binvaltmp = fH->GetBinContent(ibin);
03131             if (TMath::Abs(x-binvaltmp) < TMath::Abs(x-binval)) {
03132                binval=binvaltmp;
03133                binnear=ibin;
03134             }
03135          }
03136          binx = binnear;
03137       }
03138    }
03139    if (fH->GetDimension() == 1) {
03140       Double_t integ = 0;
03141       for (Int_t bin=binmin;bin<=binx;bin++) {integ += fH->GetBinContent(bin);}
03142       snprintf(info,100,"(x=%g, y=%g, binx=%d, binc=%g, Sum=%g)",x,y,binx,fH->GetBinContent(binx),integ);
03143    } else {
03144       if (fH->InheritsFrom(TH2Poly::Class())) {
03145          TH2Poly *th2 = (TH2Poly*)fH;
03146          biny = th2->FindBin(x,y);
03147          snprintf(info,100,"%s (x=%g, y=%g, bin=%d, binc=%g)",th2->GetBinTitle(biny),x,y,biny,th2->GetBinContent(biny));
03148       } else {
03149          biny = fYaxis->FindFixBin(y);
03150          snprintf(info,100,"(x=%g, y=%g, binx=%d, biny=%d, binc=%g)",x,y,binx,biny,fH->GetCellContent(binx,biny));
03151       }
03152    }
03153    return info;
03154 }
03155 
03156 
03157 //______________________________________________________________________________
03158 Bool_t THistPainter::IsInside(Int_t ix, Int_t iy)
03159 {
03160    /* Begin_html
03161    Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
03162    End_html */
03163 
03164    for (Int_t i=0;i<fNcuts;i++) {
03165       Double_t x = fXaxis->GetBinCenter(ix);
03166       Double_t y = fYaxis->GetBinCenter(iy);
03167       if (fCutsOpt[i] > 0) {
03168          if (!fCuts[i]->IsInside(x,y)) return kFALSE;
03169       } else {
03170          if (fCuts[i]->IsInside(x,y))  return kFALSE;
03171       }
03172    }
03173    return kTRUE;
03174 }
03175 
03176 
03177 //______________________________________________________________________________
03178 Bool_t THistPainter::IsInside(Double_t x, Double_t y)
03179 {
03180    /* Begin_html
03181    Return kTRUE if the point x,y is inside one of the graphical cuts.
03182    End_html */
03183 
03184    for (Int_t i=0;i<fNcuts;i++) {
03185       if (fCutsOpt[i] > 0) {
03186          if (!fCuts[i]->IsInside(x,y)) return kFALSE;
03187       } else {
03188          if (fCuts[i]->IsInside(x,y))  return kFALSE;
03189       }
03190    }
03191    return kTRUE;
03192 }
03193 
03194 
03195 //______________________________________________________________________________
03196 Int_t THistPainter::MakeChopt(Option_t *choptin)
03197 {
03198    /* Begin_html
03199    Decode string "choptin" and fill Hoption structure.
03200    End_html */
03201 
03202    char *l;
03203    char chopt[128];
03204    Int_t nch = strlen(choptin);
03205    strlcpy(chopt,choptin,128);
03206 
03207    Hoption.Axis = Hoption.Bar    = Hoption.Curve   = Hoption.Error = 0;
03208    Hoption.Hist = Hoption.Line   = Hoption.Mark    = Hoption.Fill  = 0;
03209    Hoption.Same = Hoption.Func   = Hoption.Scat    = 0;
03210    Hoption.Star = Hoption.Arrow  = Hoption.Box     = Hoption.Text  = 0;
03211    Hoption.Char = Hoption.Color  = Hoption.Contour = Hoption.Logx  = 0;
03212    Hoption.Logy = Hoption.Logz   = Hoption.Lego    = Hoption.Surf  = 0;
03213    Hoption.Off  = Hoption.Tri    = Hoption.Proj    = Hoption.AxisPos = 0;
03214    Hoption.Spec = Hoption.Pie    = 0;
03215 
03216    //    special 2D options
03217    Hoption.List     = 0;
03218    Hoption.Zscale   = 0;
03219    Hoption.FrontBox = 1;
03220    Hoption.BackBox  = 1;
03221    Hoption.System   = kCARTESIAN;
03222 
03223    Hoption.HighRes  = 0;
03224 
03225    Hoption.Zero     = 0;
03226 
03227    //check for graphical cuts
03228    MakeCuts(chopt);
03229 
03230    for (Int_t i=0;i<nch;i++) chopt[i] = toupper(chopt[i]);
03231    if (fH->GetDimension() > 1) Hoption.Scat = 1;
03232    if (!nch) Hoption.Hist = 1;
03233    if (fFunctions->First()) Hoption.Func = 2;
03234    if (fH->GetSumw2N() && fH->GetDimension() == 1) Hoption.Error = 2;
03235 
03236    l = strstr(chopt,"SPEC");
03237    if (l) {
03238       Hoption.Scat = 0;
03239       strncpy(l,"    ",4);
03240       Int_t bs=0;
03241       l = strstr(chopt,"BF(");
03242       if (l) {
03243          if (sscanf(&l[3],"%d",&bs) > 0) {
03244             Int_t i=0;
03245             while (l[i]!=')') {
03246                l[i] = ' ';
03247                i++;
03248             }
03249             l[i] = ' ';
03250          }
03251       }
03252       Hoption.Spec = TMath::Max(1600,bs);
03253       return 1;
03254    }
03255 
03256    l = strstr(chopt,"GL");
03257    if (l) {
03258       strncpy(l,"  ",2);
03259    }
03260    l = strstr(chopt,"X+");
03261    if (l) {
03262       Hoption.AxisPos = 10;
03263       strncpy(l,"  ",2);
03264    }
03265    l = strstr(chopt,"Y+");
03266    if (l) {
03267       Hoption.AxisPos += 1;
03268       strncpy(l,"  ",2);
03269    }
03270    if((Hoption.AxisPos == 10 || Hoption.AxisPos == 1) && (nch == 2)) Hoption.Hist = 1;
03271    if(Hoption.AxisPos == 11 && nch == 4) Hoption.Hist = 1;
03272 
03273    l = strstr(chopt,"SAMES");
03274    if (l) {
03275       if (nch == 5) Hoption.Hist = 1;
03276       Hoption.Same = 2;
03277       strncpy(l,"     ",5);
03278    }
03279    l = strstr(chopt,"SAME");
03280    if (l) {
03281       if (nch == 4) Hoption.Hist = 1;
03282       Hoption.Same = 1;
03283       strncpy(l,"    ",4);
03284    }
03285 
03286    l = strstr(chopt,"PIE");
03287    if (l) {
03288       Hoption.Pie = 1;
03289       strncpy(l,"   ",3);
03290    }
03291 
03292    l = strstr(chopt,"LEGO");
03293    if (l) {
03294       Hoption.Scat = 0;
03295       Hoption.Lego = 1; strncpy(l,"    ",4);
03296       if (l[4] == '1') { Hoption.Lego = 11; l[4] = ' '; }
03297       if (l[4] == '2') { Hoption.Lego = 12; l[4] = ' '; }
03298       l = strstr(chopt,"FB"); if (l) { Hoption.FrontBox = 0; strncpy(l,"  ",2); }
03299       l = strstr(chopt,"BB"); if (l) { Hoption.BackBox = 0;  strncpy(l,"  ",2); }
03300       l = strstr(chopt,"0");  if (l) { Hoption.Zero = 1;  strncpy(l," ",1); }
03301    }
03302 
03303    l = strstr(chopt,"SURF");
03304    if (l) {
03305       Hoption.Scat = 0;
03306       Hoption.Surf = 1; strncpy(l,"    ",4);
03307       if (l[4] == '1') { Hoption.Surf = 11; l[4] = ' '; }
03308       if (l[4] == '2') { Hoption.Surf = 12; l[4] = ' '; }
03309       if (l[4] == '3') { Hoption.Surf = 13; l[4] = ' '; }
03310       if (l[4] == '4') { Hoption.Surf = 14; l[4] = ' '; }
03311       if (l[4] == '5') { Hoption.Surf = 15; l[4] = ' '; }
03312       if (l[4] == '6') { Hoption.Surf = 16; l[4] = ' '; }
03313       if (l[4] == '7') { Hoption.Surf = 17; l[4] = ' '; }
03314       l = strstr(chopt,"FB");   if (l) { Hoption.FrontBox = 0; strncpy(l,"  ",2); }
03315       l = strstr(chopt,"BB");   if (l) { Hoption.BackBox = 0;  strncpy(l,"  ",2); }
03316    }
03317 
03318    l = strstr(chopt,"TF3");
03319    if (l) {
03320       l = strstr(chopt,"FB");   if (l) { Hoption.FrontBox = 0; strncpy(l,"  ",2); }
03321       l = strstr(chopt,"BB");   if (l) { Hoption.BackBox = 0;  strncpy(l,"  ",2); }
03322    }
03323 
03324    l = strstr(chopt,"ISO");
03325    if (l) {
03326       l = strstr(chopt,"FB");   if (l) { Hoption.FrontBox = 0; strncpy(l,"  ",2); }
03327       l = strstr(chopt,"BB");   if (l) { Hoption.BackBox = 0;  strncpy(l,"  ",2); }
03328    }
03329 
03330    l = strstr(chopt,"LIST");    if (l) { Hoption.List = 1;  strncpy(l,"    ",4);}
03331 
03332    l = strstr(chopt,"CONT");
03333    if (l) {
03334       Hoption.Scat = 0;
03335       Hoption.Contour = 1; strncpy(l,"    ",4);
03336       if (l[4] == '1') { Hoption.Contour = 11; l[4] = ' '; }
03337       if (l[4] == '2') { Hoption.Contour = 12; l[4] = ' '; }
03338       if (l[4] == '3') { Hoption.Contour = 13; l[4] = ' '; }
03339       if (l[4] == '4') { Hoption.Contour = 14; l[4] = ' '; }
03340       if (l[4] == '5') { Hoption.Contour = 15; l[4] = ' '; }
03341    }
03342    l = strstr(chopt,"HBAR");
03343    if (l) {
03344       Hoption.Hist = 0;
03345       Hoption.Bar = 20; strncpy(l,"    ",4);
03346       if (l[4] == '1') { Hoption.Bar = 21; l[4] = ' '; }
03347       if (l[4] == '2') { Hoption.Bar = 22; l[4] = ' '; }
03348       if (l[4] == '3') { Hoption.Bar = 23; l[4] = ' '; }
03349       if (l[4] == '4') { Hoption.Bar = 24; l[4] = ' '; }
03350    }
03351    l = strstr(chopt,"BAR");
03352    if (l) {
03353       Hoption.Hist = 0;
03354       Hoption.Bar = 10; strncpy(l,"   ",3);
03355       if (l[3] == '1') { Hoption.Bar = 11; l[3] = ' '; }
03356       if (l[3] == '2') { Hoption.Bar = 12; l[3] = ' '; }
03357       if (l[3] == '3') { Hoption.Bar = 13; l[3] = ' '; }
03358       if (l[3] == '4') { Hoption.Bar = 14; l[3] = ' '; }
03359    }
03360 
03361    l = strstr(chopt,"ARR" ); if (l) { Hoption.Arrow  = 1; strncpy(l,"   ", 3); Hoption.Scat = 0; }
03362    l = strstr(chopt,"BOX" );
03363    if (l) {
03364       Hoption.Scat = 0;
03365       Hoption.Box  = 1; strncpy(l,"   ", 3);
03366       if (l[3] == '1') { Hoption.Box = 11; l[3] = ' '; }
03367    }
03368    l = strstr(chopt,"COLZ"); if (l) { Hoption.Color  = 2; strncpy(l,"    ",4); Hoption.Scat = 0; Hoption.Zscale = 1;}
03369    l = strstr(chopt,"COL" ); if (l) { Hoption.Color  = 1; strncpy(l,"   ", 3); Hoption.Scat = 0; }
03370    l = strstr(chopt,"CHAR"); if (l) { Hoption.Char   = 1; strncpy(l,"    ",4); Hoption.Scat = 0; }
03371    l = strstr(chopt,"FUNC"); if (l) { Hoption.Func   = 2; strncpy(l,"    ",4); Hoption.Hist = 0; }
03372    l = strstr(chopt,"HIST"); if (l) { Hoption.Hist   = 2; strncpy(l,"    ",4); Hoption.Func = 0; Hoption.Error = 0;}
03373    l = strstr(chopt,"AXIS"); if (l) { Hoption.Axis   = 1; strncpy(l,"    ",4); }
03374    l = strstr(chopt,"AXIG"); if (l) { Hoption.Axis   = 2; strncpy(l,"    ",4); }
03375    l = strstr(chopt,"SCAT"); if (l) { Hoption.Scat   = 1; strncpy(l,"    ",4); }
03376    l = strstr(chopt,"TEXT");
03377    if (l) {
03378       Int_t angle;
03379       if (sscanf(&l[4],"%d",&angle) > 0) {
03380          if (angle < 0)  angle=0;
03381          if (angle > 90) angle=90;
03382          Hoption.Text = 1000+angle;
03383       } else {
03384          Hoption.Text = 1;
03385       }
03386       strncpy(l,"    ", 4);
03387       l = strstr(chopt,"N");
03388       if (l && fH->InheritsFrom(TH2Poly::Class())) Hoption.Text += 3000;
03389       Hoption.Scat = 0;
03390    }
03391    l = strstr(chopt,"POL");  if (l) { Hoption.System = kPOLAR;       strncpy(l,"   ",3); }
03392    l = strstr(chopt,"CYL");  if (l) { Hoption.System = kCYLINDRICAL; strncpy(l,"   ",3); }
03393    l = strstr(chopt,"SPH");  if (l) { Hoption.System = kSPHERICAL;   strncpy(l,"   ",3); }
03394    l = strstr(chopt,"PSR");  if (l) { Hoption.System = kRAPIDITY;    strncpy(l,"   ",3); }
03395 
03396    l = strstr(chopt,"TRI");
03397    if (l) {
03398       Hoption.Scat = 0;
03399       Hoption.Color  = 0;
03400       Hoption.Tri = 1; strncpy(l,"   ",3);
03401       l = strstr(chopt,"FB");   if (l) { Hoption.FrontBox = 0; strncpy(l,"  ",2); }
03402       l = strstr(chopt,"BB");   if (l) { Hoption.BackBox = 0;  strncpy(l,"  ",2); }
03403       l = strstr(chopt,"ERR");  if (l) strncpy(l,"   ",3);
03404    }
03405 
03406    l = strstr(chopt,"AITOFF");
03407    if (l) {
03408       Hoption.Proj = 1; strncpy(l,"     ",6);       //Aitoff projection
03409    }
03410    l = strstr(chopt,"MERCATOR");
03411    if (l) {
03412       Hoption.Proj = 2; strncpy(l,"       ",8);     //Mercator projection
03413    }
03414    l = strstr(chopt,"SINUSOIDAL");
03415    if (l) {
03416       Hoption.Proj = 3; strncpy(l,"         ",10);  //Sinusoidal projection
03417    }
03418    l = strstr(chopt,"PARABOLIC");
03419    if (l) {
03420       Hoption.Proj = 4; strncpy(l,"        ",9);    //Parabolic projection
03421    }
03422    if (Hoption.Proj > 0) {
03423       Hoption.Scat = 0;
03424       Hoption.Contour = 14;
03425    }
03426 
03427    if (strstr(chopt,"A"))   Hoption.Axis = -1;
03428    if (strstr(chopt,"B"))   Hoption.Bar  = 1;
03429    if (strstr(chopt,"C")) { Hoption.Curve =1; Hoption.Hist = -1;}
03430    if (strstr(chopt,"F"))   Hoption.Fill =1;
03431    if (strstr(chopt,"][")) {Hoption.Off  =1; Hoption.Hist =1;}
03432    if (strstr(chopt,"F2"))  Hoption.Fill =2;
03433    if (strstr(chopt,"L")) { Hoption.Line =1; Hoption.Hist = -1;}
03434    if (strstr(chopt,"P")) { Hoption.Mark =1; Hoption.Hist = -1;}
03435    if (strstr(chopt,"Z"))   Hoption.Zscale =1;
03436    if (strstr(chopt,"*"))   Hoption.Star =1;
03437    if (strstr(chopt,"H"))   Hoption.Hist =2;
03438    if (strstr(chopt,"P0"))  Hoption.Mark =10;
03439 
03440    if (strstr(chopt,"E")) {
03441       if (fH->GetDimension() == 1) {
03442          Hoption.Error = 1;
03443          if (strstr(chopt,"E0"))  Hoption.Error = 10;
03444          if (strstr(chopt,"E1"))  Hoption.Error = 11;
03445          if (strstr(chopt,"E2"))  Hoption.Error = 12;
03446          if (strstr(chopt,"E3"))  Hoption.Error = 13;
03447          if (strstr(chopt,"E4"))  Hoption.Error = 14;
03448          if (strstr(chopt,"E5"))  Hoption.Error = 15;
03449          if (strstr(chopt,"E6"))  Hoption.Error = 16;
03450          if (strstr(chopt,"X0")) {
03451             if (Hoption.Error == 1)  Hoption.Error += 20;
03452             Hoption.Error += 10;
03453          }
03454          if (Hoption.Text && fH->InheritsFrom(TProfile::Class())) {
03455             Hoption.Text += 2000;
03456             Hoption.Error = 0;
03457          }
03458       } else {
03459          if (Hoption.Error == 0) {
03460             Hoption.Error = 100;
03461             Hoption.Scat  = 0;
03462          }
03463          if (Hoption.Text) {
03464             Hoption.Text += 2000;
03465             Hoption.Error = 0;
03466          }
03467       }
03468    }
03469 
03470    if (strstr(chopt,"9"))  Hoption.HighRes = 1;
03471 
03472    if (Hoption.Surf == 15) {
03473       if (Hoption.System == kPOLAR || Hoption.System == kCARTESIAN) {
03474          Hoption.Surf = 13;
03475          Warning("MakeChopt","option SURF5 is not supported in Cartesian and Polar modes");
03476       }
03477    }
03478 
03479    //      Copy options from current style
03480    Hoption.Logx = gPad->GetLogx();
03481    Hoption.Logy = gPad->GetLogy();
03482    Hoption.Logz = gPad->GetLogz();
03483 
03484    //       Check options incompatibilities
03485    if (Hoption.Bar  == 1) Hoption.Hist = -1;
03486    return 1;
03487 }
03488 
03489 
03490 //______________________________________________________________________________
03491 Int_t THistPainter::MakeCuts(char *choptin)
03492 {
03493    /* Begin_html
03494    Decode string "choptin" and fill Graphical cuts structure.
03495    End_html */
03496 
03497    fNcuts = 0;
03498    char *left = (char*)strchr(choptin,'[');
03499    if (!left) return 0;
03500    char *right = (char*)strchr(choptin,']');
03501    if (!right) return 0;
03502    Int_t nch = right-left;
03503    if (nch < 2) return 0;
03504    char *cuts = left+1;
03505    *right = 0;
03506    char *comma, *minus;
03507    Int_t i;
03508    while(1) {
03509       comma = strchr(cuts,',');
03510       if (comma) *comma = 0;
03511       minus = strchr(cuts,'-');
03512       if (minus) cuts = minus+1;
03513       while (*cuts == ' ') cuts++;
03514       Int_t nc = strlen(cuts);
03515       while (cuts[nc-1] == ' ') {cuts[nc-1] = 0; nc--;}
03516       TIter next(gROOT->GetListOfSpecials());
03517       TCutG *cut=0;
03518       TObject *obj;
03519       while ((obj = next())) {
03520          if (!obj->InheritsFrom(TCutG::Class())) continue;
03521          if (strcmp(obj->GetName(),cuts)) continue;
03522          cut = (TCutG*)obj;
03523          break;
03524       }
03525       if (cut) {
03526          fCuts[fNcuts] = cut;
03527          fCutsOpt[fNcuts] = 1;
03528          if (minus) fCutsOpt[fNcuts] = -1;
03529          fNcuts++;
03530       }
03531       if (!comma) break;
03532       cuts = comma+1;
03533    }
03534    for (i=0;i<=nch;i++) left[i] = ' ';
03535    return fNcuts;
03536 }
03537 
03538 
03539 //______________________________________________________________________________
03540 void THistPainter::Paint(Option_t *option)
03541 {
03542    /* Begin_Html
03543    <a href="#HP00">Control routine to paint any kind of histograms.</a>
03544    End_html */
03545 
03546    if (fH->GetBuffer()) fH->BufferEmpty(-1);
03547 
03548    gPad->SetVertical(kTRUE);
03549 
03550    TH1 *oldhist = gCurrentHist;
03551    gCurrentHist = fH;
03552    TH1 *hsave   = fH;
03553    Double_t minsav = fH->GetMinimumStored();
03554 
03555    if (!MakeChopt(option)) return; //check options and fill Hoption structure
03556 
03557    // Paint using TSpectrum2Painter
03558    if (Hoption.Spec) {
03559       if (!TableInit()) return;
03560       if (!TClass::GetClass("TSpectrum2Painter")) gSystem->Load("libSpectrumPainter");
03561       gROOT->ProcessLineFast(Form("TSpectrum2Painter::PaintSpectrum((TH2F*)0x%lx,\"%s\",%d)",
03562                                   (ULong_t)fH, option, Hoption.Spec));
03563       return;
03564    }
03565 
03566    if (Hoption.Pie) {
03567       if (!fPie) fPie = new TPie(fH);
03568       fPie->Paint(option);
03569       return;
03570    } else {
03571       if (fPie) delete fPie;
03572       fPie = 0;
03573    }
03574 
03575    fXbuf  = new Double_t[kNMAX];
03576    fYbuf  = new Double_t[kNMAX];
03577    if (fH->GetDimension() > 2) {
03578       PaintH3(option);
03579       fH->SetMinimum(minsav);
03580       if (Hoption.Func) {
03581          Hoption_t hoptsave = Hoption;
03582          Hparam_t  hparsave = Hparam;
03583          PaintFunction(option);
03584          SetHistogram(hsave);
03585          Hoption = hoptsave;
03586          Hparam  = hparsave;
03587       }
03588       gCurrentHist = oldhist;
03589       delete [] fXbuf; delete [] fYbuf;
03590       return;
03591    }
03592    TView *view = gPad->GetView();
03593    if (view) {
03594       if (!Hoption.Lego && !Hoption.Surf && !Hoption.Tri) {
03595          delete view;
03596          gPad->SetView(0);
03597       }
03598    }
03599    if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) {
03600       // In case of 1D histogram, Z axis becomes Y axis.
03601       Int_t logysav=0, logzsav=0;
03602       if (fH->GetDimension() == 1) {
03603          logysav = Hoption.Logy;
03604          logzsav = Hoption.Logz;
03605          Hoption.Logz = 0;
03606          if (Hoption.Logy) {
03607             Hoption.Logz = 1;
03608             Hoption.Logy = 0;
03609          }
03610       }
03611       PaintTable(option);
03612       fH->SetMinimum(minsav);
03613       if (Hoption.Func) {
03614          Hoption_t hoptsave = Hoption;
03615          Hparam_t  hparsave = Hparam;
03616          PaintFunction(option);
03617          SetHistogram(hsave);
03618          Hoption = hoptsave;
03619          Hparam  = hparsave;
03620       }
03621       gCurrentHist = oldhist;
03622       delete [] fXbuf; delete [] fYbuf;
03623       if (fH->GetDimension() == 1) {
03624          Hoption.Logy = logysav;
03625          Hoption.Logz = logzsav;
03626       }
03627       return;
03628    }
03629 
03630    if (Hoption.Bar >= 20) {PaintBarH(option);
03631       delete [] fXbuf; delete [] fYbuf;
03632       return;
03633    }
03634 
03635    // fill Hparam structure with histo parameters
03636    if (!PaintInit()) {
03637       delete [] fXbuf; delete [] fYbuf;
03638       return;
03639    }
03640 
03641    //          Picture surround (if new page) and page number (if requested).
03642    //          Histogram surround (if not option "Same").
03643    PaintFrame();
03644 
03645    //          Paint histogram axis only
03646    Bool_t gridx = gPad->GetGridx();
03647    Bool_t gridy = gPad->GetGridy();
03648    if (Hoption.Axis > 0) {
03649       if (Hoption.Axis > 1) PaintAxis(kTRUE);  //axis with grid
03650       else {
03651          if (gridx) gPad->SetGridx(0);
03652          if (gridy) gPad->SetGridy(0);
03653          PaintAxis(kFALSE);
03654          if (gridx) gPad->SetGridx(1);
03655          if (gridy) gPad->SetGridy(1);
03656       }
03657       if (Hoption.Same ==1) Hoption.Same = 2;
03658       goto paintstat;
03659    }
03660    if (gridx || gridy) PaintAxis(kTRUE); //    Draw the grid only
03661 
03662    //          test for options BAR or HBAR
03663    if (Hoption.Bar >= 10) {
03664       PaintBar(option);
03665    }
03666 
03667    //          do not draw histogram if error bars required
03668    if (!Hoption.Error) {
03669       if (Hoption.Hist && Hoption.Bar<10) PaintHist(option);
03670    }
03671 
03672    //         test for error bars or option E
03673    if (Hoption.Error) {
03674       PaintErrors(option);
03675       if (Hoption.Hist == 2) PaintHist(option);
03676    }
03677 
03678    if (Hoption.Text) PaintText(option);
03679 
03680    //         test for associated function
03681    if (Hoption.Func) {
03682       Hoption_t hoptsave = Hoption;
03683       Hparam_t  hparsave = Hparam;
03684       PaintFunction(option);
03685       SetHistogram(hsave);
03686       Hoption = hoptsave;
03687       Hparam  = hparsave;
03688    }
03689 
03690    if (gridx) gPad->SetGridx(0);
03691    if (gridy) gPad->SetGridy(0);
03692    PaintAxis(kFALSE);
03693    if (gridx) gPad->SetGridx(1);
03694    if (gridy) gPad->SetGridy(1);
03695 
03696    PaintTitle();  // Draw histogram title
03697 
03698    // Draw box with histogram statistics and/or fit parameters
03699 paintstat:
03700    if (Hoption.Same != 1 && !fH->TestBit(TH1::kNoStats)) {  // bit set via TH1::SetStats
03701       TIter next(fFunctions);
03702       TObject *obj = 0;
03703       while ((obj = next())) {
03704          if (obj->InheritsFrom(TF1::Class())) break;
03705          obj = 0;
03706       }
03707       PaintStat(gStyle->GetOptStat(),(TF1*)obj);
03708    }
03709    fH->SetMinimum(minsav);
03710    gCurrentHist = oldhist;
03711    delete [] fXbuf; fXbuf = 0;
03712    delete [] fYbuf; fYbuf = 0;
03713 
03714 }
03715 
03716 
03717 //______________________________________________________________________________
03718 void THistPainter::PaintArrows(Option_t *)
03719 {
03720    /* Begin_html
03721    <a href="#HP12">Control function to draw a table as an arrow plot.</a>
03722    End_html */
03723 
03724    Style_t linesav   = fH->GetLineStyle();
03725    Width_t widthsav  = fH->GetLineWidth();
03726    fH->SetLineStyle(1);
03727    fH->SetLineWidth(1);
03728    fH->TAttLine::Modify();
03729 
03730    Double_t xk, xstep, yk, ystep;
03731    Double_t dx, dy, si, co, anr, x1, x2, y1, y2, xc, yc, dxn, dyn;
03732    Int_t   ncx  = Hparam.xlast - Hparam.xfirst + 1;
03733    Int_t   ncy  = Hparam.ylast - Hparam.yfirst + 1;
03734    Double_t xrg = gPad->GetUxmin();
03735    Double_t yrg = gPad->GetUymin();
03736    Double_t xln = gPad->GetUxmax() - xrg;
03737    Double_t yln = gPad->GetUymax() - yrg;
03738    Double_t cx  = (xln/Double_t(ncx) -0.03)/2;
03739    Double_t cy  = (yln/Double_t(ncy) -0.03)/2;
03740    Double_t dn  = 1.E-30;
03741 
03742    for (Int_t id=1;id<=2;id++) {
03743       for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
03744          yk    = fYaxis->GetBinLowEdge(j);
03745          ystep = fYaxis->GetBinWidth(j);
03746          for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
03747             xk    = fXaxis->GetBinLowEdge(i);
03748             xstep = fXaxis->GetBinWidth(i);
03749             if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
03750             if (i == Hparam.xfirst) {
03751                dx = fH->GetCellContent(i+1, j) - fH->GetCellContent(i, j);
03752             } else if (i == Hparam.xlast) {
03753                dx = fH->GetCellContent(i, j) - fH->GetCellContent(i-1, j);
03754             } else {
03755                dx = 0.5*(fH->GetCellContent(i+1, j) - fH->GetCellContent(i-1, j));
03756             }
03757             if (j == Hparam.yfirst) {
03758                dy = fH->GetCellContent(i, j+1) - fH->GetCellContent(i, j);
03759             } else if (j == Hparam.ylast) {
03760                dy = fH->GetCellContent(i, j) - fH->GetCellContent(i, j-1);
03761             } else {
03762                dy = 0.5*(fH->GetCellContent(i, j+1) - fH->GetCellContent(i, j-1));
03763             }
03764             if (id == 1) {
03765                dn = TMath::Max(dn, TMath::Abs(dx));
03766                dn = TMath::Max(dn, TMath::Abs(dy));
03767             } else if (id == 2) {
03768                xc  = xrg + xln*(Double_t(i - Hparam.xfirst+1)-0.5)/Double_t(ncx);
03769                dxn = cx*dx/dn;
03770                x1  = xc - dxn;
03771                x2  = xc + dxn;
03772                yc  = yrg + yln*(Double_t(j - Hparam.yfirst+1)-0.5)/Double_t(ncy);
03773                dyn = cy*dy/dn;
03774                y1  = yc - dyn;
03775                y2  = yc + dyn;
03776                fXbuf[0] = x1;
03777                fXbuf[1] = x2;
03778                fYbuf[0] = y1;
03779                fYbuf[1] = y2;
03780                if (TMath::Abs(x2-x1) > 0.01 || TMath::Abs(y2-y1) > 0.01) {
03781                   anr = 0.005*.5*TMath::Sqrt(2/(dxn*dxn + dyn*dyn));
03782                   si  = anr*(dxn + dyn);
03783                   co  = anr*(dxn - dyn);
03784                   fXbuf[2] = x2 - si;
03785                   fYbuf[2] = y2 + co;
03786                   gPad->PaintPolyLine(3, fXbuf, fYbuf);
03787                   fXbuf[0] = x2;
03788                   fXbuf[1] = x2 - co;
03789                   fYbuf[0] = y2;
03790                   fYbuf[1] = y2 - si;
03791                   gPad->PaintPolyLine(2, fXbuf, fYbuf);
03792                }
03793                else {
03794                   gPad->PaintPolyLine(2, fXbuf, fYbuf);
03795                }
03796             }
03797          }
03798       }
03799    }
03800 
03801    if (Hoption.Zscale) PaintPalette();
03802    fH->SetLineStyle(linesav);
03803    fH->SetLineWidth(widthsav);
03804    fH->TAttLine::Modify();
03805 }
03806 
03807 
03808 //______________________________________________________________________________
03809 void THistPainter::PaintAxis(Bool_t drawGridOnly)
03810 {
03811    /* Begin_html
03812    Draw axis (2D case) of an histogram.
03813    <p>
03814    If drawGridOnly is TRUE, only the grid is painted (if needed). This allows
03815    to draw the grid and the axis separately. In THistPainter::Paint this
03816    feature is used to make sure that the grid is drawn in the background and
03817    the axis tick marks in the foreground of the pad.
03818    End_html */
03819 
03820    if (Hoption.Axis == -1) return;
03821    if (Hoption.Same && Hoption.Axis <= 0) return;
03822 
03823    // Repainting alphanumeric labels axis on a plot done with
03824    // the option HBAR (horizontal) needs some adjustements.
03825    TAxis *xaxis = 0;
03826    TAxis *yaxis = 0;
03827    if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
03828       if (fXaxis->GetLabels() || fYaxis->GetLabels()) { // One axis has alphanumeric labels
03829          TIter next(gPad->GetListOfPrimitives());
03830          TObject *obj;
03831          // Check if the first TH1 of THStack in the pad is drawn with the option HBAR
03832          while ((obj = next())) {
03833             if (!obj->InheritsFrom(TH1::Class()) &&
03834                 !obj->InheritsFrom(THStack::Class())) continue;
03835             TString opt = obj->GetDrawOption();
03836             opt.ToLower();
03837             // if drawn with HBAR, the axis should be inverted and the pad set to horizontal
03838             if (strstr(opt,"hbar")) {
03839                gPad->SetVertical(kFALSE);
03840                xaxis = fXaxis;
03841                yaxis = fYaxis;
03842                if (!strcmp(xaxis->GetName(),"xaxis")) {
03843                   fXaxis = yaxis;
03844                   fYaxis = xaxis;
03845                }
03846             }
03847             break;
03848          }
03849       }
03850    }
03851 
03852    static char chopt[10] = "";
03853    Double_t gridl = 0;
03854    Int_t ndiv, ndivx, ndivy, nx1, nx2, ndivsave;
03855    Int_t useHparam = 0;
03856    Double_t umin, umax, uminsave, umaxsave;
03857    Short_t xAxisPos = Hoption.AxisPos/10;
03858    Short_t yAxisPos = Hoption.AxisPos - 10*xAxisPos;
03859 
03860    Double_t axmin = gPad->GetUxmin();
03861    Double_t axmax = gPad->GetUxmax();
03862    Double_t aymin = gPad->GetUymin();
03863    Double_t aymax = gPad->GetUymax();
03864    char *cw = 0;
03865    TGaxis axis;
03866 
03867    // In case of option 'cont4' or in case of option 'same' over a 'cont4 plot'
03868    // Hparam must be use for the axis limits.
03869    if (Hoption.Contour == 14) useHparam = 1;
03870    if (Hoption.Same) {
03871       TObject *obj;
03872       TIter next(gPad->GetListOfPrimitives());
03873       while ((obj=next())) {
03874          if (strstr(obj->GetDrawOption(),"cont4")) {
03875             useHparam = 1;
03876             break;
03877          }
03878       }
03879    }
03880 
03881    // Paint X axis
03882    ndivx = fXaxis->GetNdivisions();
03883    if (ndivx > 1000) {
03884       nx2   = ndivx/100;
03885       nx1   = TMath::Max(1, ndivx%100);
03886       ndivx = 100*nx2 + Int_t(Float_t(nx1)*gPad->GetAbsWNDC());
03887    }
03888    axis.SetTextAngle(0);
03889    axis.ImportAxisAttributes(fXaxis);
03890 
03891    chopt[0] = 0;
03892    // coverity [Calling risky function]
03893    strlcat(chopt, "SDH",10);
03894    // coverity [Calling risky function]
03895    if (ndivx < 0) strlcat(chopt, "N",10);
03896    if (gPad->GetGridx()) {
03897       gridl = (aymax-aymin)/(gPad->GetY2() - gPad->GetY1());
03898       // coverity [Calling risky function]
03899       strlcat(chopt, "W",10);
03900    }
03901 
03902    // Define X-Axis limits
03903    if (Hoption.Logx) {
03904       // coverity [Calling risky function]
03905       strlcat(chopt, "G",10);
03906       ndiv = TMath::Abs(ndivx);
03907       if (useHparam) {
03908          umin = TMath::Power(10,Hparam.xmin);
03909          umax = TMath::Power(10,Hparam.xmax);
03910       } else {
03911          umin = TMath::Power(10,axmin);
03912          umax = TMath::Power(10,axmax);
03913       }
03914    } else {
03915       ndiv = TMath::Abs(ndivx);
03916       if (useHparam) {
03917          umin = Hparam.xmin;
03918          umax = Hparam.xmax;
03919       } else {
03920          umin = axmin;
03921          umax = axmax;
03922       }
03923    }
03924 
03925    // Display axis as time
03926    if (fXaxis->GetTimeDisplay()) {
03927       // coverity [Calling risky function]
03928       strlcat(chopt,"t",10);
03929       if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
03930          axis.SetTimeFormat(fXaxis->ChooseTimeFormat(Hparam.xmax-Hparam.xmin));
03931       }
03932    }
03933 
03934    // The main X axis can be on the bottom or on the top of the pad
03935    Double_t xAxisYPos1, xAxisYPos2;
03936    if (xAxisPos == 1) {
03937       // Main X axis top
03938       xAxisYPos1 = aymax;
03939       xAxisYPos2 = aymin;
03940    } else {
03941       // Main X axis bottom
03942       xAxisYPos1 = aymin;
03943       xAxisYPos2 = aymax;
03944    }
03945 
03946    // Paint the main X axis (always)
03947    uminsave = umin;
03948    umaxsave = umax;
03949    ndivsave = ndiv;
03950    axis.SetOption(chopt);
03951    if (xAxisPos) {
03952       // coverity [Calling risky function]
03953       strlcat(chopt, "-",10);
03954       gridl = -gridl;
03955    }
03956    if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
03957       axis.SetLabelSize(0.);
03958       axis.SetTitle("");
03959    }
03960    axis.PaintAxis(axmin, xAxisYPos1,
03961                   axmax, xAxisYPos1,
03962                   umin, umax,  ndiv, chopt, gridl, drawGridOnly);
03963 
03964    // Paint additional X axis (if needed)
03965    if (gPad->GetTickx()) {
03966       if (xAxisPos) {
03967          cw=strstr(chopt,"-");
03968          *cw='z';
03969       } else {
03970          // coverity [Calling risky function]
03971          strlcat(chopt, "-",10);
03972       }
03973       // coverity [Calling risky function]
03974       if (gPad->GetTickx() < 2) strlcat(chopt, "U",10);
03975       if ((cw=strstr(chopt,"W"))) *cw='z';
03976       axis.SetTitle("");
03977       axis.PaintAxis(axmin, xAxisYPos2,
03978                      axmax, xAxisYPos2,
03979                      uminsave, umaxsave,  ndivsave, chopt, gridl, drawGridOnly);
03980    }
03981 
03982    // Paint Y axis
03983    ndivy = fYaxis->GetNdivisions();
03984    axis.ImportAxisAttributes(fYaxis);
03985 
03986    chopt[0] = 0;
03987    // coverity [Calling risky function]
03988    strlcat(chopt, "SDH",10);
03989    // coverity [Calling risky function]
03990    if (ndivy < 0) strlcat(chopt, "N",10);
03991    if (gPad->GetGridy()) {
03992       gridl = (axmax-axmin)/(gPad->GetX2() - gPad->GetX1());
03993       // coverity [Calling risky function]
03994       strlcat(chopt, "W",10);
03995    }
03996 
03997    // Define Y-Axis limits
03998    if (Hoption.Logy) {
03999       // coverity [Calling risky function]
04000       strlcat(chopt, "G",10);
04001       ndiv = TMath::Abs(ndivy);
04002       if (useHparam) {
04003          umin = TMath::Power(10,Hparam.ymin);
04004          umax = TMath::Power(10,Hparam.ymax);
04005       } else {
04006          umin = TMath::Power(10,aymin);
04007          umax = TMath::Power(10,aymax);
04008       }
04009    } else {
04010       ndiv = TMath::Abs(ndivy);
04011       if (useHparam) {
04012          umin = Hparam.ymin;
04013          umax = Hparam.ymax;
04014       } else {
04015          umin = aymin;
04016          umax = aymax;
04017       }
04018    }
04019 
04020    // Display axis as time
04021    if (fYaxis->GetTimeDisplay()) {
04022       // coverity [Calling risky function]
04023       strlcat(chopt,"t",10);
04024       if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
04025          axis.SetTimeFormat(fYaxis->ChooseTimeFormat(Hparam.ymax-Hparam.ymin));
04026       }
04027    }
04028 
04029    // The main Y axis can be on the left or on the right of the pad
04030    Double_t yAxisXPos1, yAxisXPos2;
04031    if (yAxisPos == 1) {
04032       // Main Y axis left
04033       yAxisXPos1 = axmax;
04034       yAxisXPos2 = axmin;
04035    } else {
04036       // Main Y axis right
04037       yAxisXPos1 = axmin;
04038       yAxisXPos2 = axmax;
04039    }
04040 
04041    // Paint the main Y axis (always)
04042    uminsave = umin;
04043    umaxsave = umax;
04044    ndivsave = ndiv;
04045    axis.SetOption(chopt);
04046    if (yAxisPos) {
04047       // coverity [Calling risky function]
04048       strlcat(chopt, "+L",10);
04049       gridl = -gridl;
04050    }
04051    if (Hoption.Same && Hoption.Axis) { // Axis repainted (TPad::RedrawAxis)
04052       axis.SetLabelSize(0.);
04053       axis.SetTitle("");
04054    }
04055    axis.PaintAxis(yAxisXPos1, aymin,
04056                   yAxisXPos1, aymax,
04057                   umin, umax,  ndiv, chopt, gridl, drawGridOnly);
04058 
04059    // Paint the additional Y axis (if needed)
04060    if (gPad->GetTicky()) {
04061       if (gPad->GetTicky() < 2) {
04062          // coverity [Calling risky function]
04063          strlcat(chopt, "U",10);
04064          axis.SetTickSize(-fYaxis->GetTickLength());
04065       } else {
04066          // coverity [Calling risky function]
04067          strlcat(chopt, "+L",10);
04068       }
04069       if ((cw=strstr(chopt,"W"))) *cw='z';
04070       axis.SetTitle("");
04071       axis.PaintAxis(yAxisXPos2, aymin,
04072                      yAxisXPos2, aymax,
04073                      uminsave, umaxsave,  ndivsave, chopt, gridl, drawGridOnly);
04074    }
04075 
04076    // Reset the axis if they have been inverted in case of option HBAR
04077    if (xaxis) {
04078       fXaxis = xaxis;
04079       fYaxis = yaxis;
04080    }
04081 }
04082 
04083 
04084 //______________________________________________________________________________
04085 void THistPainter::PaintBar(Option_t *)
04086 {
04087    /* Begin_html
04088    <a href="#HP10">Draw a bar-chart in a normal pad.</a>
04089    End_html */
04090 
04091    Int_t bar = Hoption.Bar - 10;
04092    Double_t xmin,xmax,ymin,ymax,umin,umax,w,y;
04093    Double_t offset = fH->GetBarOffset();
04094    Double_t width  = fH->GetBarWidth();
04095    TBox box;
04096    Int_t hcolor = fH->GetFillColor();
04097    Int_t hstyle = fH->GetFillStyle();
04098    box.SetFillColor(hcolor);
04099    box.SetFillStyle(hstyle);
04100    for (Int_t bin=fXaxis->GetFirst();bin<=fXaxis->GetLast();bin++) {
04101       y    = fH->GetBinContent(bin);
04102       xmin = gPad->XtoPad(fXaxis->GetBinLowEdge(bin));
04103       xmax = gPad->XtoPad(fXaxis->GetBinUpEdge(bin));
04104       ymin = gPad->GetUymin();
04105       ymax = gPad->YtoPad(y);
04106       if (ymax < gPad->GetUymin()) continue;
04107       if (ymax > gPad->GetUymax()) ymax = gPad->GetUymax();
04108       if (ymin < gPad->GetUymin()) ymin = gPad->GetUymin();
04109       if (gStyle->GetHistMinimumZero() && ymin < 0)
04110          ymin=TMath::Min(0.,gPad->GetUymax());
04111       w    = (xmax-xmin)*width;
04112       xmin += offset*(xmax-xmin);
04113       xmax = xmin + w;
04114       if (bar < 1) {
04115          box.PaintBox(xmin,ymin,xmax,ymax);
04116       } else {
04117          umin = xmin + bar*(xmax-xmin)/10.;
04118          umax = xmax - bar*(xmax-xmin)/10.;
04119          //box.SetFillColor(hcolor+150); //bright
04120          box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
04121          box.PaintBox(xmin,ymin,umin,ymax);
04122          box.SetFillColor(hcolor);
04123          box.PaintBox(umin,ymin,umax,ymax);
04124          box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
04125          box.PaintBox(umax,ymin,xmax,ymax);
04126       }
04127    }
04128 }
04129 
04130 
04131 //______________________________________________________________________________
04132 void THistPainter::PaintBarH(Option_t *)
04133 {
04134    /* Begin_html
04135    <a href="#HP10">Draw a bar char in a rotated pad (X vertical, Y horizontal).</a>
04136    End_html */
04137 
04138    gPad->SetVertical(kFALSE);
04139 
04140    PaintInitH();
04141 
04142    TAxis *xaxis = fXaxis;
04143    TAxis *yaxis = fYaxis;
04144    if (!strcmp(xaxis->GetName(),"xaxis")) {
04145       fXaxis = yaxis;
04146       fYaxis = xaxis;
04147    }
04148 
04149    PaintFrame();
04150 
04151    Int_t bar = Hoption.Bar - 20;
04152    Double_t xmin,xmax,ymin,ymax,umin,umax,w;
04153    Double_t offset = fH->GetBarOffset();
04154    Double_t width  = fH->GetBarWidth();
04155    TBox box;
04156    Int_t hcolor = fH->GetFillColor();
04157    Int_t hstyle = fH->GetFillStyle();
04158    box.SetFillColor(hcolor);
04159    box.SetFillStyle(hstyle);
04160    for (Int_t bin=fYaxis->GetFirst();bin<=fYaxis->GetLast();bin++) {
04161       ymin = gPad->YtoPad(fYaxis->GetBinLowEdge(bin));
04162       ymax = gPad->YtoPad(fYaxis->GetBinUpEdge(bin));
04163       xmin = gPad->GetUxmin();
04164       xmax = gPad->XtoPad(fH->GetBinContent(bin));
04165       if (xmax < gPad->GetUxmin()) continue;
04166       if (xmax > gPad->GetUxmax()) xmax = gPad->GetUxmax();
04167       if (xmin < gPad->GetUxmin()) xmin = gPad->GetUxmin();
04168       if (gStyle->GetHistMinimumZero() && xmin < 0)
04169          xmin=TMath::Min(0.,gPad->GetUxmax());
04170       w    = (ymax-ymin)*width;
04171       ymin += offset*(ymax-ymin);
04172       ymax = ymin + w;
04173       if (bar < 1) {
04174          box.PaintBox(xmin,ymin,xmax,ymax);
04175       } else {
04176          umin = ymin + bar*(ymax-ymin)/10.;
04177          umax = ymax - bar*(ymax-ymin)/10.;
04178          box.SetFillColor(TColor::GetColorDark(hcolor)); //dark
04179          box.PaintBox(xmin,ymin,xmax,umin);
04180          box.SetFillColor(hcolor);
04181          box.PaintBox(xmin,umin,xmax,umax);
04182          box.SetFillColor(TColor::GetColorBright(hcolor)); //bright
04183          box.PaintBox(xmin,umax,xmax,ymax);
04184       }
04185    }
04186 
04187    PaintTitle();
04188    //    Draw box with histogram statistics and/or fit parameters
04189    if (Hoption.Same != 1 && !fH->TestBit(TH1::kNoStats)) {  // bit set via TH1::SetStats
04190       TIter next(fFunctions);
04191       TObject *obj = 0;
04192       while ((obj = next())) {
04193          if (obj->InheritsFrom(TF1::Class())) break;
04194          obj = 0;
04195       }
04196       PaintStat(gStyle->GetOptStat(),(TF1*)obj);
04197    }
04198 
04199    PaintAxis(kFALSE);
04200    fXaxis = xaxis;
04201    fYaxis = yaxis;
04202 }
04203 
04204 
04205 //______________________________________________________________________________
04206 void THistPainter::PaintBoxes(Option_t *)
04207 {
04208    /* Begin_html
04209    <a href="#HP13">Control function to draw a 2D histogram as a box plot.</a>
04210    End_html */
04211 
04212    Style_t fillsav   = fH->GetFillStyle();
04213    Style_t colsav    = fH->GetFillColor();
04214    if (fH->GetFillColor() == 0)  fH->SetFillStyle(0);
04215    if (Hoption.Box == 11) fH->SetFillStyle(1001);
04216    fH->TAttLine::Modify();
04217    fH->TAttFill::Modify();
04218 
04219    Double_t z, xk,xstep, yk, ystep, xcent, ycent, xlow, xup, ylow, yup;
04220    Double_t ux1 = gPad->PixeltoX(1);
04221    Double_t ux0 = gPad->PixeltoX(0);
04222    Double_t uy1 = gPad->PixeltoY(1);
04223    Double_t uy0 = gPad->PixeltoY(0);
04224    Double_t dxmin = 0.51*(gPad->PadtoX(ux1)-gPad->PadtoX(ux0));
04225    Double_t dymin = 0.51*(gPad->PadtoY(uy0)-gPad->PadtoY(uy1));
04226 
04227    Double_t zmin = fH->GetMinimum();
04228    Double_t zmax = fH->GetMaximum();
04229 
04230    if (Hoption.Logz) {
04231       if (zmin > 0) {
04232          zmin = TMath::Log10(zmin*0.1);
04233          zmax = TMath::Log10(zmax);
04234       } else {
04235          return;
04236       }
04237    } else {
04238       zmax = TMath::Max(TMath::Abs(zmin),TMath::Abs(zmax));
04239       zmin = 0;
04240    }
04241 
04242    // In case of option SAME, zmin and zmax values are taken from the
04243    // first plotted 2D histogram.
04244    if (Hoption.Same) {
04245       TH2 *h2;
04246       TIter next(gPad->GetListOfPrimitives());
04247       while ((h2 = (TH2 *)next())) {
04248          if (!h2->InheritsFrom(TH2::Class())) continue;
04249          zmin = h2->GetMinimum();
04250          zmax = h2->GetMaximum();
04251          if (Hoption.Logz) {
04252             zmax = TMath::Log10(zmax);
04253             if (zmin <= 0) {
04254                zmin = TMath::Log10(zmax*0.001);
04255             } else {
04256                zmin = TMath::Log10(zmin);
04257             }
04258          }
04259          break;
04260       }
04261    }
04262 
04263    Double_t zratio, dz = zmax - zmin;
04264    Bool_t kZNeg        = kFALSE;
04265 
04266    // Define the dark and light colors the "button style" boxes.
04267    Color_t color = fH->GetFillColor();
04268    Color_t light=0, dark=0;
04269    if (Hoption.Box == 11) {
04270       light = TColor::GetColorBright(color);
04271       dark  = TColor::GetColorDark(color);
04272 /*
04273       if (color == 0) {
04274          light = 0;
04275          dark  = 0;
04276       } else if (color <= 50 && color != 0) {
04277          light = color + 150;
04278          dark  = color + 100;
04279       } else {
04280          Float_t r, g, b, h, l, s;
04281          TColor *c = gROOT->GetColor(color);
04282          if (c) c->GetRGB(r, g, b);
04283          else {r = 0.5; g=0.5; b=0.5;}
04284          TColor::RGBtoHLS(r, g, b, h, l, s);
04285          TColor::HLStoRGB(h, 0.7*l, s, r, g, b);
04286          dark = TColor::GetColor(r, g, b);
04287          TColor::HLStoRGB(h, 1.2*l, s, r, g, b);
04288          light = TColor::GetColor(r, g, b);
04289       }
04290 */
04291    }
04292 
04293    // Loop over all the bins and draw the boxes
04294    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
04295       yk    = fYaxis->GetBinLowEdge(j);
04296       ystep = fYaxis->GetBinWidth(j);
04297       ycent = 0.5*ystep;
04298       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
04299          Int_t bin  = j*(fXaxis->GetNbins()+2) + i;
04300          xk    = fXaxis->GetBinLowEdge(i);
04301          xstep = fXaxis->GetBinWidth(i);
04302          if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
04303          xcent = 0.5*xstep;
04304          z     = Hparam.factor*fH->GetBinContent(bin);
04305          kZNeg = kFALSE;
04306          if (z < 0) {
04307             if (Hoption.Logz) continue;
04308             z = -z;
04309             kZNeg = kTRUE;
04310          }
04311          if (Hoption.Logz) {
04312             if (z != 0) z = TMath::Log10(z);
04313             else        z = zmin;
04314          }
04315 
04316          if (z <  zmin) continue; //   Can be the case with
04317          if (z >  zmax) z = zmax; // option Same
04318 
04319          if (dz == 0) continue;
04320          zratio = TMath::Sqrt((z-zmin)/dz);
04321          if (zratio == 0) continue;
04322 
04323          xup  = xcent*zratio + xk + xcent;
04324          xlow = 2*(xk + xcent) - xup;
04325          if (xup-xlow < dxmin) xup = xlow+dxmin;
04326          if (Hoption.Logx) {
04327             if (xup > 0)  xup  = TMath::Log10(xup);
04328             else continue;
04329             if (xlow > 0) xlow = TMath::Log10(xlow);
04330             else continue;
04331          }
04332 
04333          yup  = ycent*zratio + yk + ycent;
04334          ylow = 2*(yk + ycent) - yup;
04335          if (yup-ylow < dymin) yup = ylow+dymin;
04336          if (Hoption.Logy) {
04337             if (yup > 0)  yup  = TMath::Log10(yup);
04338             else continue;
04339             if (ylow > 0) ylow = TMath::Log10(ylow);
04340             else continue;
04341          }
04342 
04343          xlow = TMath::Max(xlow, gPad->GetUxmin());
04344          ylow = TMath::Max(ylow, gPad->GetUymin());
04345          xup  = TMath::Min(xup , gPad->GetUxmax());
04346          yup  = TMath::Min(yup , gPad->GetUymax());
04347 
04348          if (Hoption.Box == 1) {
04349             fH->SetFillColor(color);
04350             fH->TAttFill::Modify();
04351             gPad->PaintBox(xlow, ylow, xup, yup);
04352             if (kZNeg) {
04353                gPad->PaintLine(xlow, ylow, xup, yup);
04354                gPad->PaintLine(xlow, yup, xup, ylow);
04355             }
04356          } else if (Hoption.Box == 11) {
04357             // Draw the center of the box
04358             fH->SetFillColor(color);
04359             fH->TAttFill::Modify();
04360             gPad->PaintBox(xlow, ylow, xup, yup);
04361 
04362             // Draw top&left part of the box
04363             Double_t x[7], y[7];
04364             Double_t bwidth = 0.1;
04365             x[0] = xlow;                     y[0] = ylow;
04366             x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
04367             x[2] = x[1];                     y[2] = yup - bwidth*(yup-ylow);
04368             x[3] = xup - bwidth*(xup-xlow);  y[3] = y[2];
04369             x[4] = xup;                      y[4] = yup;
04370             x[5] = xlow;                     y[5] = yup;
04371             x[6] = xlow;                     y[6] = ylow;
04372             if (kZNeg) fH->SetFillColor(dark);
04373             else       fH->SetFillColor(light);
04374             fH->TAttFill::Modify();
04375             gPad->PaintFillArea(7, x, y);
04376 
04377             // Draw bottom&right part of the box
04378             x[0] = xlow;                     y[0] = ylow;
04379             x[1] = xlow + bwidth*(xup-xlow); y[1] = ylow + bwidth*(yup-ylow);
04380             x[2] = xup - bwidth*(xup-xlow);  y[2] = y[1];
04381             x[3] = x[2];                     y[3] = yup - bwidth*(yup-ylow);
04382             x[4] = xup;                      y[4] = yup;
04383             x[5] = xup;                      y[5] = ylow;
04384             x[6] = xlow;                     y[6] = ylow;
04385             if (kZNeg) fH->SetFillColor(light);
04386             else       fH->SetFillColor(dark);
04387             fH->TAttFill::Modify();
04388             gPad->PaintFillArea(7, x, y);
04389          }
04390       }
04391    }
04392 
04393    if (Hoption.Zscale) PaintPalette();
04394    fH->SetFillStyle(fillsav);
04395    fH->SetFillColor(colsav);
04396    fH->TAttFill::Modify();
04397 }
04398 
04399 
04400 //______________________________________________________________________________
04401 void THistPainter::PaintColorLevels(Option_t *)
04402 {
04403    /* Begin_html
04404    <a href="#HP14">Control function to draw a 2D histogram as a color plot.</a>
04405    End_html */
04406 
04407    Double_t z, zc, xk, xstep, yk, ystep, xlow, xup, ylow, yup;
04408 
04409    Double_t zmin = fH->GetMinimum();
04410    Double_t zmax = fH->GetMaximum();
04411 
04412    Double_t dz = zmax - zmin;
04413    if (dz <= 0) { // Histogram filled with a constant value
04414       zmax += 0.1*TMath::Abs(zmax);
04415       zmin -= 0.1*TMath::Abs(zmin);
04416       dz = zmax - zmin;
04417    }
04418 
04419    if (Hoption.Logz) {
04420       if (zmin > 0) {
04421          zmin = TMath::Log10(zmin);
04422          zmax = TMath::Log10(zmax);
04423          dz = zmax - zmin;
04424       } else {
04425          return;
04426       }
04427    }
04428 
04429    Style_t fillsav   = fH->GetFillStyle();
04430    Style_t colsav    = fH->GetFillColor();
04431    fH->SetFillStyle(1001);
04432    fH->TAttFill::Modify();
04433 
04434    // Initialize the levels on the Z axis
04435    Int_t ncolors  = gStyle->GetNumberOfColors();
04436    Int_t ndiv   = fH->GetContour();
04437    if (ndiv == 0 ) {
04438       ndiv = gStyle->GetNumberContours();
04439       fH->SetContour(ndiv);
04440    }
04441    Int_t ndivz  = TMath::Abs(ndiv);
04442    if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
04443    Double_t scale = ndivz/dz;
04444 
04445    Int_t color;
04446    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
04447       yk    = fYaxis->GetBinLowEdge(j);
04448       ystep = fYaxis->GetBinWidth(j);
04449       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
04450          Int_t bin  = j*(fXaxis->GetNbins()+2) + i;
04451          xk    = fXaxis->GetBinLowEdge(i);
04452          xstep = fXaxis->GetBinWidth(i);
04453          if (Hoption.System == kPOLAR && xk<0) xk= 2*TMath::Pi()+xk;
04454          if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
04455          z     = fH->GetBinContent(bin);
04456          if (z == 0 && (zmin >= 0 || Hoption.Logz)) continue; // don't draw the empty bins for histograms with positive content
04457          if (Hoption.Logz) {
04458             if (z > 0) z = TMath::Log10(z);
04459             else       z = zmin;
04460          }
04461          if (z < zmin) continue;
04462          xup  = xk + xstep;
04463          xlow = xk;
04464          if (Hoption.Logx) {
04465             if (xup > 0)  xup  = TMath::Log10(xup);
04466             else continue;
04467             if (xlow > 0) xlow = TMath::Log10(xlow);
04468             else continue;
04469          }
04470          yup  = yk + ystep;
04471          ylow = yk;
04472          if (Hoption.System != kPOLAR) {
04473             if (Hoption.Logy) {
04474                if (yup > 0)  yup  = TMath::Log10(yup);
04475                else continue;
04476                if (ylow > 0) ylow = TMath::Log10(ylow);
04477                else continue;
04478             }
04479             if (xup  < gPad->GetUxmin()) continue;
04480             if (yup  < gPad->GetUymin()) continue;
04481             if (xlow > gPad->GetUxmax()) continue;
04482             if (ylow > gPad->GetUymax()) continue;
04483             if (xlow < gPad->GetUxmin()) xlow = gPad->GetUxmin();
04484             if (ylow < gPad->GetUymin()) ylow = gPad->GetUymin();
04485             if (xup  > gPad->GetUxmax()) xup  = gPad->GetUxmax();
04486             if (yup  > gPad->GetUymax()) yup  = gPad->GetUymax();
04487          }
04488 
04489          if (fH->TestBit(TH1::kUserContour)) {
04490             zc = fH->GetContourLevelPad(0);
04491             if (z < zc) continue;
04492             color = -1;
04493             for (Int_t k=0; k<ndiv; k++) {
04494                zc = fH->GetContourLevelPad(k);
04495                if (z < zc) {
04496                   continue;
04497                } else {
04498                   color++;
04499                }
04500             }
04501          } else {
04502             color = Int_t(0.01+(z-zmin)*scale);
04503          }
04504 
04505          Int_t theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
04506          if (theColor > ncolors-1) theColor = ncolors-1;
04507          fH->SetFillColor(gStyle->GetColorPalette(theColor));
04508          fH->TAttFill::Modify();
04509          if (Hoption.System != kPOLAR) {
04510             gPad->PaintBox(xlow, ylow, xup, yup);
04511          } else  {
04512             TCrown crown(0,0,ylow,yup,xlow*TMath::RadToDeg(),xup*TMath::RadToDeg());
04513             crown.SetFillColor(gStyle->GetColorPalette(theColor));
04514             crown.Paint();
04515          }
04516       }
04517    }
04518 
04519    if (Hoption.Zscale) PaintPalette();
04520 
04521    fH->SetFillStyle(fillsav);
04522    fH->SetFillColor(colsav);
04523    fH->TAttFill::Modify();
04524 
04525 }
04526 
04527 
04528 //______________________________________________________________________________
04529 void THistPainter::PaintContour(Option_t *option)
04530 {
04531    /* Begin_html
04532    <a href="#HP16">Control function to draw a 2D histogram as a contour plot.</a>
04533    End_html */
04534 
04535    Int_t i, j, count, ncontour, icol, n, lj, m, ix, jx, ljfill;
04536    Int_t itars, mode, ir[4];
04537    Double_t xsave, ysave, thesave,phisave,x[4], y[4], zc[4];
04538 
04539    if (Hoption.Contour == 14) {
04540       Hoption.Surf = 12;
04541       Hoption.Axis = 1;
04542       thesave = gPad->GetTheta();
04543       phisave = gPad->GetPhi();
04544       gPad->SetPhi(0.);
04545       gPad->SetTheta(90.);
04546       PaintSurface(option);
04547       gPad->SetPhi(phisave);
04548       gPad->SetTheta(thesave);
04549       gPad->GetView()->SetBit(kCannotRotate); //tested in ExecuteEvent
04550       PaintAxis();
04551       return;
04552    }
04553 
04554    if (Hoption.Same) {
04555       // If the contour is painted on a 3d plot, the contour lines are
04556       // paint in 3d too.
04557       TObject *obj;
04558       TIter next(gPad->GetListOfPrimitives());
04559       while ((obj=next())) {
04560          if (strstr(obj->GetDrawOption(),"surf") ||
04561              strstr(obj->GetDrawOption(),"lego") ||
04562              strstr(obj->GetDrawOption(),"tri")) {
04563                Hoption.Surf = 16;
04564                PaintSurface(option);
04565                return;
04566          }
04567       }
04568    }
04569 
04570    if (Hoption.Contour == 15) {
04571       TGraphDelaunay *dt;
04572       TList *hl = fH->GetListOfFunctions();
04573       dt = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
04574       if (!dt) return;
04575       if (!fGraph2DPainter) fGraph2DPainter = new TGraph2DPainter(dt);
04576       fGraph2DPainter->Paint(option);
04577       return;
04578    }
04579 
04580    gPad->SetBit(TGraph::kClipFrame);
04581 
04582    Double_t *levels  = new Double_t[2*kMAXCONTOUR];
04583    Double_t *xarr    = new Double_t[2*kMAXCONTOUR];
04584    Double_t *yarr    = new Double_t[2*kMAXCONTOUR];
04585    Int_t  *itarr     = new Int_t[2*kMAXCONTOUR];
04586 
04587    Int_t npmax = 0;
04588    for (i=0;i<2*kMAXCONTOUR;i++) itarr[i] = 0;
04589 
04590    ncontour = fH->GetContour();
04591    if (ncontour == 0) {
04592       ncontour = gStyle->GetNumberContours();
04593       fH->SetContour(ncontour);
04594    }
04595    if (ncontour > kMAXCONTOUR) {
04596       Warning("PaintContour", "maximum number of contours is %d, asked for %d",
04597               kMAXCONTOUR, ncontour);
04598       ncontour = kMAXCONTOUR-1;
04599    }
04600    if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ncontour);
04601 
04602    for (i=0;i<ncontour;i++) levels[i] = fH->GetContourLevelPad(i);
04603    //for (i=0;i<ncontour;i++)
04604    //   levels[i] = Hparam.zmin+(Hparam.zmax-Hparam.zmin)/ncontour*i;
04605    Int_t linesav   = fH->GetLineStyle();
04606    Int_t colorsav  = fH->GetLineColor();
04607    Int_t fillsav  = fH->GetFillColor();
04608    if (Hoption.Contour == 13) {
04609       fH->TAttLine::Modify();
04610    }
04611 
04612    TPolyLine **polys = 0;
04613    TPolyLine *poly=0;
04614    TObjArray *contours = 0;
04615    TList *list = 0;
04616    TGraph *graph = 0;
04617    Int_t *np = 0;
04618    if (Hoption.Contour == 1) {
04619       np = new Int_t[ncontour];
04620       for (i=0;i<ncontour;i++) np[i] = 0;
04621       polys = new TPolyLine*[ncontour];
04622       for (i=0;i<ncontour;i++) {
04623          polys[i] = new TPolyLine(100);
04624       }
04625       if (Hoption.List == 1) {
04626          contours = (TObjArray*)gROOT->GetListOfSpecials()->FindObject("contours");
04627          if (contours) {
04628             gROOT->GetListOfSpecials()->Remove(contours);
04629             count = contours->GetSize();
04630             for (i=0;i<count;i++) {
04631                list = (TList*)contours->At(i);
04632                if (list) list->Delete();
04633             }
04634          }
04635          contours = new TObjArray(ncontour);
04636          contours->SetName("contours");
04637          gROOT->GetListOfSpecials()->Add(contours);
04638          for (i=0;i<ncontour;i++) {
04639             list = new TList();
04640             contours->Add(list);
04641          }
04642       }
04643    }
04644    Int_t theColor;
04645    Int_t ncolors = gStyle->GetNumberOfColors();
04646    Int_t ndivz   = TMath::Abs(ncontour);
04647 
04648    Int_t k,ipoly;
04649    for (j=Hparam.yfirst; j<Hparam.ylast; j++) {
04650       y[0] = fYaxis->GetBinCenter(j);
04651       y[1] = y[0];
04652       y[2] = fYaxis->GetBinCenter(j+1);
04653       y[3] = y[2];
04654       for (i=Hparam.xfirst; i<Hparam.xlast; i++) {
04655          zc[0] = fH->GetBinContent(i,   j);
04656          zc[1] = fH->GetBinContent(i+1, j);
04657          zc[2] = fH->GetBinContent(i+1, j+1);
04658          zc[3] = fH->GetBinContent(i,   j+1);
04659          if (!IsInside(fXaxis->GetBinCenter(i),fYaxis->GetBinCenter(j))) continue;
04660          if (Hoption.Logz) {
04661             if (zc[0] > 0)   zc[0] = TMath::Log10(zc[0]);
04662             else             zc[0] = Hparam.zmin;
04663             if (zc[1] > 0)   zc[1] = TMath::Log10(zc[1]);
04664             else             zc[1] = Hparam.zmin;
04665             if (zc[2] > 0)   zc[2] = TMath::Log10(zc[2]);
04666             else             zc[2] = Hparam.zmin;
04667             if (zc[3] > 0)   zc[3] = TMath::Log10(zc[3]);
04668             else             zc[3] = Hparam.zmin;
04669          }
04670          for (k=0;k<4;k++) {
04671             ir[k] = TMath::BinarySearch(ncontour,levels,zc[k]);
04672          }
04673          if (ir[0] != ir[1] || ir[1] != ir[2] || ir[2] != ir[3] || ir[3] != ir[0]) {
04674             x[0] = fXaxis->GetBinCenter(i);
04675             x[3] = x[0];
04676             x[1] = fXaxis->GetBinCenter(i+1);
04677             x[2] = x[1];
04678             if (zc[0] <= zc[1]) n = 0; else n = 1;
04679             if (zc[2] <= zc[3]) m = 2; else m = 3;
04680             if (zc[n] > zc[m]) n = m;
04681             n++;
04682             lj=1;
04683             for (ix=1;ix<=4;ix++) {
04684                m = n%4 + 1;
04685                ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
04686                      ir[m-1],x[m-1],y[m-1],&xarr[lj-1],&yarr[lj-1],&itarr[lj-1], levels);
04687                lj += 2*ljfill;
04688                n = m;
04689             }
04690 
04691             if (zc[0] <= zc[1]) n = 0; else n = 1;
04692             if (zc[2] <= zc[3]) m = 2; else m = 3;
04693             if (zc[n] > zc[m]) n = m;
04694             n++;
04695             lj=2;
04696             for (ix=1;ix<=4;ix++) {
04697                if (n == 1) m = 4;
04698                else        m = n-1;
04699                ljfill = PaintContourLine(zc[n-1],ir[n-1],x[n-1],y[n-1],zc[m-1],
04700                      ir[m-1],x[m-1],y[m-1],&xarr[lj-1],&yarr[lj-1],&itarr[lj-1], levels);
04701                lj += 2*ljfill;
04702                n = m;
04703             }
04704 
04705    //     Re-order endpoints
04706 
04707             count = 0;
04708             for (ix=1; ix<=lj-5; ix +=2) {
04709                //count = 0;
04710                while (itarr[ix-1] != itarr[ix]) {
04711                   xsave = xarr[ix];
04712                   ysave = yarr[ix];
04713                   itars = itarr[ix];
04714                   for (jx=ix; jx<=lj-5; jx +=2) {
04715                      xarr[jx]  = xarr[jx+2];
04716                      yarr[jx]  = yarr[jx+2];
04717                      itarr[jx] = itarr[jx+2];
04718                   }
04719                   xarr[lj-3]  = xsave;
04720                   yarr[lj-3]  = ysave;
04721                   itarr[lj-3] = itars;
04722                   if (count > 100) break;
04723                   count++;
04724                }
04725             }
04726 
04727             if (count > 100) continue;
04728             for (ix=1; ix<=lj-2; ix +=2) {
04729                theColor = Int_t((itarr[ix-1]+0.99)*Float_t(ncolors)/Float_t(ndivz));
04730                icol = gStyle->GetColorPalette(theColor);
04731                if (Hoption.Contour == 11) {
04732                   fH->SetLineColor(icol);
04733                }
04734                if (Hoption.Contour == 12) {
04735                   mode = icol%5;
04736                   if (mode == 0) mode = 5;
04737                   fH->SetLineStyle(mode);
04738                }
04739                if (Hoption.Contour != 1) {
04740                   fH->TAttLine::Modify();
04741                   gPad->PaintPolyLine(2,&xarr[ix-1],&yarr[ix-1]);
04742                   continue;
04743                }
04744 
04745                ipoly = itarr[ix-1];
04746                if (ipoly >=0 && ipoly <ncontour) {
04747                   poly = polys[ipoly];
04748                   poly->SetPoint(np[ipoly]  ,xarr[ix-1],yarr[ix-1]);
04749                   poly->SetPoint(np[ipoly]+1,xarr[ix],  yarr[ix]);
04750                   np[ipoly] += 2;
04751                   if (npmax < np[ipoly]) npmax = np[ipoly];
04752                }
04753             }
04754          } // end of if (ir[0]
04755       } //end of for (i
04756    } //end of for (j
04757 
04758    Double_t xmin,ymin;
04759    Double_t *xp, *yp;
04760    Int_t nadd,iminus,iplus;
04761    Double_t *xx, *yy;
04762    Int_t istart;
04763    Int_t first = ncontour;
04764    Int_t *polysort = 0;
04765    Int_t contListNb;
04766    if (Hoption.Contour != 1) goto theEND;
04767 
04768    //The 2 points line generated above are now sorted/merged to generate
04769    //a list of consecutive points.
04770    // If the option "List" has been specified, the list of points is saved
04771    // in the form of TGraph objects in the ROOT list of special objects.
04772    xmin = gPad->GetUxmin();
04773    ymin = gPad->GetUymin();
04774    xp = new Double_t[2*npmax];
04775    yp = new Double_t[2*npmax];
04776    polysort = new Int_t[ncontour];
04777    //find first positive contour
04778    for (ipoly=0;ipoly<ncontour;ipoly++) {
04779       if (levels[ipoly] >= 0) {first = ipoly; break;}
04780    }
04781    //store negative contours from 0 to minimum, then all positive contours
04782    k = 0;
04783    for (ipoly=first-1;ipoly>=0;ipoly--) {polysort[k] = ipoly; k++;}
04784    for (ipoly=first;ipoly<ncontour;ipoly++) {polysort[k] = ipoly; k++;}
04785    // we can now draw sorted contours
04786    contListNb = 0;
04787    fH->SetFillStyle(1001);
04788    for (k=0;k<ncontour;k++) {
04789       ipoly = polysort[k];
04790       if (np[ipoly] == 0) continue;
04791       if (Hoption.List) list = (TList*)contours->At(contListNb);
04792       contListNb++;
04793       poly = polys[ipoly];
04794       xx = poly->GetX();
04795       yy = poly->GetY();
04796       istart = 0;
04797       while (1) {
04798          iminus = npmax;
04799          iplus  = iminus+1;
04800          xp[iminus]= xx[istart];   yp[iminus] = yy[istart];
04801          xp[iplus] = xx[istart+1]; yp[iplus]  = yy[istart+1];
04802          xx[istart]   = xmin; yy[istart]   = ymin;
04803          xx[istart+1] = xmin; yy[istart+1] = ymin;
04804          while (1) {
04805             nadd = 0;
04806             for (i=2;i<np[ipoly];i+=2) {
04807                if (xx[i] == xp[iplus] && yy[i] == yp[iplus]) {
04808                   iplus++;
04809                   xp[iplus] = xx[i+1]; yp[iplus]  = yy[i+1];
04810                   xx[i]   = xmin; yy[i]   = ymin;
04811                   xx[i+1] = xmin; yy[i+1] = ymin;
04812                   nadd++;
04813                }
04814                if (xx[i+1] == xp[iminus] && yy[i+1] == yp[iminus]) {
04815                   iminus--;
04816                   xp[iminus] = xx[i];   yp[iminus]  = yy[i];
04817                   xx[i]   = xmin; yy[i]   = ymin;
04818                   xx[i+1] = xmin; yy[i+1] = ymin;
04819                   nadd++;
04820                }
04821             }
04822             if (nadd == 0) break;
04823          }
04824          theColor = Int_t((ipoly+0.99)*Float_t(ncolors)/Float_t(ndivz));
04825          icol = gStyle->GetColorPalette(theColor);
04826          if (ndivz > 1) fH->SetFillColor(icol);
04827          fH->TAttFill::Modify();
04828          gPad->PaintFillArea(iplus-iminus+1,&xp[iminus],&yp[iminus]);
04829          if (Hoption.List) {
04830             graph = new TGraph(iplus-iminus+1,&xp[iminus],&yp[iminus]);
04831             graph->SetFillColor(icol);
04832             graph->SetLineWidth(fH->GetLineWidth());
04833             list->Add(graph);
04834          }
04835          //check if more points are left
04836          istart = 0;
04837          for (i=2;i<np[ipoly];i+=2) {
04838             if (xx[i] != xmin && yy[i] != ymin) {
04839                istart = i;
04840                break;
04841             }
04842          }
04843          if (istart == 0) break;
04844       }
04845    }
04846 
04847    for (i=0;i<ncontour;i++) delete polys[i];
04848    delete [] polys;
04849    delete [] xp;
04850    delete [] yp;
04851    delete [] polysort;
04852 
04853 theEND:
04854    gPad->ResetBit(TGraph::kClipFrame);
04855    if (Hoption.Zscale) PaintPalette();
04856    fH->SetLineStyle(linesav);
04857    fH->SetLineColor(colorsav);
04858    fH->SetFillColor(fillsav);
04859    if (np) delete [] np;
04860    delete [] xarr;
04861    delete [] yarr;
04862    delete [] itarr;
04863    delete [] levels;
04864 }
04865 
04866 
04867 //______________________________________________________________________________
04868 Int_t THistPainter::PaintContourLine(Double_t elev1, Int_t icont1, Double_t x1, Double_t y1,
04869                             Double_t elev2, Int_t icont2, Double_t x2, Double_t y2,
04870                             Double_t *xarr, Double_t *yarr, Int_t *itarr, Double_t *levels)
04871 {
04872    /* Begin_html
04873    Fill the matrix XARR YARR for Contour Plot.
04874    End_html */
04875 
04876    Bool_t vert;
04877    Double_t tlen, tdif, elev, diff, pdif, xlen;
04878    Int_t n, i, icount;
04879 
04880    if (x1 == x2) {
04881       vert = kTRUE;
04882       tlen = y2 - y1;
04883    } else {
04884       vert = kFALSE;
04885       tlen = x2 - x1;
04886    }
04887 
04888    n = icont1 +1;
04889    tdif = elev2 - elev1;
04890    i = 0;
04891    icount = 0;
04892    while (n <= icont2 && i <= kMAXCONTOUR/2 -3) {
04893       //elev = fH->GetContourLevel(n);
04894       elev = levels[n];
04895       diff = elev - elev1;
04896       pdif = diff/tdif;
04897       xlen = tlen*pdif;
04898       if (vert) {
04899          if (Hoption.Logx)
04900             xarr[i] = TMath::Log10(x1);
04901          else
04902             xarr[i] = x1;
04903          if (Hoption.Logy)
04904             yarr[i] = TMath::Log10(y1 + xlen);
04905          else
04906             yarr[i] = y1 + xlen;
04907       } else {
04908          if (Hoption.Logx)
04909             xarr[i] = TMath::Log10(x1 + xlen);
04910          else
04911             xarr[i] = x1 + xlen;
04912          if (Hoption.Logy)
04913             yarr[i] = TMath::Log10(y1);
04914          else
04915             yarr[i] = y1;
04916       }
04917       itarr[i] = n;
04918       icount++;
04919       i +=2;
04920       n++;
04921    }
04922    return icount;
04923 }
04924 
04925 
04926 //______________________________________________________________________________
04927 void THistPainter::PaintErrors(Option_t *)
04928 {
04929    /* Begin_html
04930    <a href="#HP09">Draw 1D histograms error bars.</a>
04931    End_html */
04932 
04933    const Int_t kBASEMARKER=8;
04934    Double_t xp, yp, ex1, ex2, ey1, ey2;
04935    Double_t delta;
04936    Double_t s2x, s2y, bxsize, bysize, symbolsize, xerror, sbase;
04937    Double_t xi1, xi2, xi3, xi4, yi1, yi2, yi3, yi4;
04938    Double_t xmin, xmax, ymin, ymax;
04939    Double_t logxmin = 0;
04940    Double_t logymin = 0;
04941    Int_t i, k, npoints, first, last, fixbin;
04942    Int_t if1 = 0;
04943    Int_t if2 = 0;
04944    Int_t drawmarker, errormarker;
04945    Int_t option0, option1, option2, option3, option4, optionE, optionEX0, optionI0;
04946 
04947    Double_t *xline = 0;
04948    Double_t *yline = 0;
04949    option0 = option1 = option2 = option3 = option4 = optionE = optionEX0 = optionI0 = 0;
04950    if (Int_t(Hoption.Error/10) == 2) {optionEX0 = 1; Hoption.Error -= 10;}
04951    if (Hoption.Error == 31) {optionEX0 = 1; Hoption.Error = 1;}
04952    if (Hoption.Error == 10) option0 = 1;
04953    if (Hoption.Error == 11) option1 = 1;
04954    if (Hoption.Error == 12) option2 = 1;
04955    if (Hoption.Error == 13) option3 = 1;
04956    if (Hoption.Error == 14) {option4 = 1; option3 = 1;}
04957    if (Hoption.Error == 15) {optionI0 = 1; option3 = 1;}
04958    if (Hoption.Error == 16) {optionI0 = 1; option4 = 1; option3 = 1;}
04959    if (option2+option3 == 0) optionE = 1;
04960    if (Hoption.Error == 0) optionE = 0;
04961    if (fXaxis->GetXbins()->fN) fixbin = 0;
04962    else                        fixbin = 1;
04963 
04964    errormarker = fH->GetMarkerStyle();
04965    if (optionEX0) {
04966       xerror = 0;
04967    } else {
04968       xerror = gStyle->GetErrorX();
04969    }
04970    symbolsize  = fH->GetMarkerSize();
04971    if (errormarker == 1) symbolsize = 0.01;
04972    sbase       = symbolsize*kBASEMARKER;
04973    // set the graphics attributes
04974 
04975    fH->TAttLine::Modify();
04976    fH->TAttFill::Modify();
04977    fH->TAttMarker::Modify();
04978 
04979    // set the first and last bin
04980 
04981    Double_t factor = Hparam.factor;
04982    first      = Hparam.xfirst;
04983    last       = Hparam.xlast;
04984    npoints    = last - first  +1;
04985    xmin       = gPad->GetUxmin();
04986    xmax       = gPad->GetUxmax();
04987    ymin       = gPad->GetUymin();
04988    ymax       = gPad->GetUymax();
04989 
04990 
04991    if (option3) {
04992       xline = new Double_t[2*npoints];
04993       yline = new Double_t[2*npoints];
04994       if (!xline || !yline) {
04995          Error("PaintErrors", "too many points, out of memory");
04996          return;
04997       }
04998       if1 = 1;
04999       if2 = 2*npoints;
05000    }
05001 
05002    //  compute the offset of the error bars due to the symbol size
05003    s2x    = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
05004    s2y    =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
05005 
05006    // compute size of the lines at the end of the error bars
05007    Int_t dxend = Int_t(gStyle->GetEndErrorSize());
05008    bxsize    = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
05009    bysize    =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
05010 
05011 
05012    if (fixbin) {
05013       if (Hoption.Logx) xp = TMath::Power(10,Hparam.xmin) + 0.5*Hparam.xbinsize;
05014       else              xp = Hparam.xmin + 0.5*Hparam.xbinsize;
05015    }
05016    else {
05017       delta = fH->GetBinWidth(first);
05018       xp    = fH->GetBinLowEdge(first) + 0.5*delta;
05019    }
05020 
05021    // if errormarker = 0 or symbolsize = 0. no symbol is drawn
05022    if (Hoption.Logx) logxmin = TMath::Power(10,Hparam.xmin);
05023    if (Hoption.Logy) logymin = TMath::Power(10,Hparam.ymin);
05024 
05025    //    ---------------------- Loop over the points---------------------
05026    for (k=first; k<=last; k++) {
05027 
05028       //          get the data
05029       //     xp      = X position of the current point
05030       //     yp      = Y position of the current point
05031       //     ex1   = Low X error
05032       //     ex2   = Up X error
05033       //     ey1   = Low Y error
05034       //     ey2   = Up Y error
05035       //     (xi,yi) = Error bars coordinates
05036 
05037       if (Hoption.Logx) {
05038          if (xp <= 0) goto L30;
05039          if (xp < logxmin) goto L30;
05040          if (xp > TMath::Power(10,xmax)) break;
05041       } else {
05042          if (xp < xmin) goto L30;
05043          if (xp > xmax) break;
05044       }
05045       yp = factor*fH->GetBinContent(k);
05046       if (optionI0 && yp==0) goto L30;
05047       if (fixbin) {
05048          ex1 = xerror*Hparam.xbinsize;
05049       } else {
05050          delta = fH->GetBinWidth(k);
05051          ex1 = xerror*delta;
05052       }
05053       ey1 = factor*fH->GetBinError(k);
05054       ex2 = ex1;
05055       ey2 = ey1;
05056 
05057       xi4 = xp;
05058       xi3 = xp;
05059       xi2 = xp + ex2;
05060       xi1 = xp - ex1;
05061 
05062       yi1 = yp;
05063       yi2 = yp;
05064       yi3 = yp - ey1;
05065       yi4 = yp + ey2;
05066 
05067       //          take the LOG if necessary
05068       if (Hoption.Logx) {
05069          xi1 = TMath::Log10(TMath::Max(xi1,logxmin));
05070          xi2 = TMath::Log10(TMath::Max(xi2,logxmin));
05071          xi3 = TMath::Log10(TMath::Max(xi3,logxmin));
05072          xi4 = TMath::Log10(TMath::Max(xi4,logxmin));
05073       }
05074       if (Hoption.Logy) {
05075          yi1 = TMath::Log10(TMath::Max(yi1,logymin));
05076          yi2 = TMath::Log10(TMath::Max(yi2,logymin));
05077          yi3 = TMath::Log10(TMath::Max(yi3,logymin));
05078          yi4 = TMath::Log10(TMath::Max(yi4,logymin));
05079       }
05080 
05081       // test if error bars are not outside the limits
05082       //  otherwise they are truncated
05083 
05084       xi1 = TMath::Max(xi1,xmin);
05085       xi2 = TMath::Min(xi2,xmax);
05086       yi3 = TMath::Max(yi3,ymin);
05087       yi4 = TMath::Min(yi4,ymax);
05088 
05089       //  test if the marker is on the frame limits. If "Yes", the
05090       //  marker will not be drawn and the error bars will be readjusted.
05091 
05092       drawmarker = kTRUE;
05093       if (!option0 && !option3) {
05094          if (Hoption.Logy && yp < logymin) goto L30;
05095          if (yi1 < ymin || yi1 > ymax) goto L30;
05096          if (Hoption.Error != 0 && yp == 0 && ey1 <= 0) drawmarker = kFALSE;
05097       }
05098       if (!symbolsize || !errormarker) drawmarker = kFALSE;
05099 
05100       //  draw the error rectangles
05101       if (option2) gPad->PaintBox(xi1,yi3,xi2,yi4);
05102 
05103       //  keep points for fill area drawing
05104       if (option3) {
05105          xline[if1-1] = xi3;
05106          xline[if2-1] = xi3;
05107          yline[if1-1] = yi4;
05108          yline[if2-1] = yi3;
05109          if1++;
05110          if2--;
05111       }
05112 
05113       //          draw the error bars
05114 
05115       if (optionE && drawmarker) {
05116          if (yi3 < yi1 - s2y) gPad->PaintLine(xi3,yi3,xi4,yi1 - s2y);
05117          if (yi1 + s2y < yi4) gPad->PaintLine(xi3,yi1 + s2y,xi4,yi4);
05118          // don't duplicate the horizontal line
05119          if (Hoption.Hist != 2){
05120             if (xi1 < xi3 - s2x) gPad->PaintLine(xi1,yi1,xi3 - s2x,yi2);
05121             if (xi3 + s2x < xi2) gPad->PaintLine(xi3 + s2x,yi1,xi2,yi2);
05122          }
05123       }
05124       if (optionE && !drawmarker && ey1 != 0) {
05125          if (yi3 < yi4) gPad->PaintLine(xi3,yi3,xi4,yi4);
05126          if (yi1 < yi4) gPad->PaintLine(xi3,yi1,xi4,yi4);
05127          // don't duplicate the horizontal line
05128          if (Hoption.Hist != 2){
05129             if (xi1 < xi3) gPad->PaintLine(xi1,yi1,xi3,yi2);
05130             if (xi3 < xi2) gPad->PaintLine(xi3,yi1,xi2,yi2);
05131          }
05132       }
05133 
05134       //          draw line at the end of the error bars
05135 
05136       if (option1 && drawmarker) {
05137          if (yi3 < yi1-s2y) gPad->PaintLine(xi3 - bxsize,yi3,xi3 + bxsize,yi3);
05138          if (yi4 > yi1+s2y) gPad->PaintLine(xi3 - bxsize,yi4,xi3 + bxsize,yi4);
05139          if (xi1 < xi3-s2x) gPad->PaintLine(xi1,yi1 - bysize,xi1,yi1 + bysize);
05140          if (xi2 > xi3+s2x) gPad->PaintLine(xi2,yi1 - bysize,xi2,yi1 + bysize);
05141       }
05142 
05143       //          draw the marker
05144 
05145       if (drawmarker) gPad->PaintPolyMarker(1, &xi3, &yi1);
05146 
05147 L30:
05148       if (fixbin) xp += Hparam.xbinsize;
05149       else {
05150          if (k < last) {
05151             delta = fH->GetBinWidth(k+1);
05152             xp    = fH->GetBinLowEdge(k+1) + 0.5*delta;
05153          }
05154       }
05155    }  //end of for loop
05156 
05157    //          draw the filled area
05158 
05159    if (option3) {
05160       TGraph graph;
05161       graph.SetLineStyle(fH->GetLineStyle());
05162       graph.SetLineColor(fH->GetLineColor());
05163       graph.SetLineWidth(fH->GetLineWidth());
05164       graph.SetFillStyle(fH->GetFillStyle());
05165       graph.SetFillColor(fH->GetFillColor());
05166       Int_t logx = gPad->GetLogx();
05167       Int_t logy = gPad->GetLogy();
05168       gPad->SetLogx(0);
05169       gPad->SetLogy(0);
05170 
05171       // In some cases the number of points in the fill area is smaller than
05172       // 2*npoints. In such cases the array xline and yline must be arranged
05173       // before being plotted. The next loop does that.
05174       if (if2 > npoints) {
05175          for(i=1; i<if1 ;i++) {
05176             xline[if1-2+i] = xline[if2-1+i];
05177             yline[if1-2+i] = yline[if2-1+i];
05178          }
05179          npoints = if1-1;
05180       }
05181       if (option4) graph.PaintGraph(2*npoints,xline,yline,"FC");
05182       else         graph.PaintGraph(2*npoints,xline,yline,"F");
05183       gPad->SetLogx(logx);
05184       gPad->SetLogy(logy);
05185       delete [] xline;
05186       delete [] yline;
05187    }
05188 }
05189 
05190 
05191 //______________________________________________________________________________
05192 void THistPainter::Paint2DErrors(Option_t *)
05193 {
05194    /* Begin_html
05195    Draw 2D histograms errors.
05196    End_html */
05197 
05198    fH->TAttMarker::Modify();
05199    fH->TAttLine::Modify();
05200 
05201    // Define the 3D view
05202    fXbuf[0] = Hparam.xmin;
05203    fYbuf[0] = Hparam.xmax;
05204    fXbuf[1] = Hparam.ymin;
05205    fYbuf[1] = Hparam.ymax;
05206    fXbuf[2] = Hparam.zmin;
05207    fYbuf[2] = Hparam.zmax;
05208    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf);
05209    TView *view = gPad->GetView();
05210    if (!view) {
05211       Error("Paint2DErrors", "no TView in current pad");
05212       return;
05213    }
05214    Double_t thedeg =  90 - gPad->GetTheta();
05215    Double_t phideg = -90 - gPad->GetPhi();
05216    Double_t psideg = view->GetPsi();
05217    Int_t irep;
05218    view->SetView(phideg, thedeg, psideg, irep);
05219 
05220    // Set color/style for back box
05221    fLego->SetFillStyle(gPad->GetFrameFillStyle());
05222    fLego->SetFillColor(gPad->GetFrameFillColor());
05223    fLego->TAttFill::Modify();
05224    Int_t backcolor = gPad->GetFrameFillColor();
05225    if (Hoption.System != kCARTESIAN) backcolor = 0;
05226    view->PadRange(backcolor);
05227    fLego->SetFillStyle(fH->GetFillStyle());
05228    fLego->SetFillColor(fH->GetFillColor());
05229    fLego->TAttFill::Modify();
05230 
05231    // Paint the Back Box if needed
05232    if (Hoption.BackBox && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
05233       fLego->InitMoveScreen(-1.1,1.1);
05234       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
05235       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
05236       fLego->BackBox(90);
05237    }
05238 
05239    // Paint the Errors
05240    Double_t x, ex, x1, x2;
05241    Double_t y, ey, y1, y2;
05242    Double_t z, ez, z1, z2;
05243    Double_t temp1[3],temp2[3];
05244    Double_t xyerror;
05245    if (Hoption.Error == 110) {
05246       xyerror = 0 ;
05247    } else {
05248       xyerror = gStyle->GetErrorX();
05249    }
05250 
05251    Double_t xk, xstep, yk, ystep;
05252    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
05253       y  = fYaxis->GetBinCenter(j);
05254       ey = fYaxis->GetBinWidth(j)*xyerror;
05255       y1 = y-ey;
05256       y2 = y+ey;
05257       if (Hoption.Logy) {
05258          if (y > 0)  y = TMath::Log10(y);
05259          else        continue;
05260          if (y1 > 0) y1 = TMath::Log10(y1);
05261          else        y1 = Hparam.ymin;
05262          if (y2 > 0) y2 = TMath::Log10(y2);
05263          else        y2 = Hparam.ymin;
05264       }
05265       yk    = fYaxis->GetBinLowEdge(j);
05266       ystep = fYaxis->GetBinWidth(j);
05267       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
05268          xk    = fXaxis->GetBinLowEdge(i);
05269          xstep = fXaxis->GetBinWidth(i);
05270          if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
05271          Int_t bin = fH->GetBin(i,j);
05272          x  = fXaxis->GetBinCenter(i);
05273          ex = fXaxis->GetBinWidth(i)*xyerror;
05274          x1 = x-ex;
05275          x2 = x+ex;
05276          if (Hoption.Logx) {
05277             if (x > 0)  x = TMath::Log10(x);
05278             else        continue;
05279             if (x1 > 0) x1 = TMath::Log10(x1);
05280             else        x1 = Hparam.xmin;
05281             if (x2 > 0) x2 = TMath::Log10(x2);
05282             else        x2 = Hparam.xmin;
05283          }
05284          z  = fH->GetBinContent(bin);
05285          ez = fH->GetBinError(bin);
05286          z1 = z-ez;
05287          z2 = z+ez;
05288          if (Hoption.Logz) {
05289             if (z > 0)   z = TMath::Log10(z);
05290             else         z = Hparam.zmin;
05291             if (z1 > 0) z1 = TMath::Log10(z1);
05292             else        z1 = Hparam.zmin;
05293             if (z2 > 0) z2 = TMath::Log10(z2);
05294             else        z2 = Hparam.zmin;
05295 
05296          }
05297          if (z <= Hparam.zmin) continue;
05298          if (z >  Hparam.zmax) z = Hparam.zmax;
05299 
05300          temp1[0] = x1;
05301          temp1[1] = y;
05302          temp1[2] = z;
05303          temp2[0] = x2;
05304          temp2[1] = y;
05305          temp2[2] = z;
05306          gPad->PaintLine3D(temp1, temp2);
05307          temp1[0] = x;
05308          temp1[1] = y1;
05309          temp1[2] = z;
05310          temp2[0] = x;
05311          temp2[1] = y2;
05312          temp2[2] = z;
05313          gPad->PaintLine3D(temp1, temp2);
05314          temp1[0] = x;
05315          temp1[1] = y;
05316          temp1[2] = z1;
05317          temp2[0] = x;
05318          temp2[1] = y;
05319          temp2[2] = z2;
05320          gPad->PaintLine3D(temp1, temp2);
05321          temp1[0] = x;
05322          temp1[1] = y;
05323          temp1[2] = z;
05324          view->WCtoNDC(temp1, &temp2[0]);
05325          gPad->PaintPolyMarker(1, &temp2[0], &temp2[1]);
05326       }
05327    }
05328 
05329    // Paint the Front Box if needed
05330    if (Hoption.FrontBox) {
05331       fLego->InitMoveScreen(-1.1,1.1);
05332       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
05333       fLego->FrontBox(90);
05334    }
05335 
05336    // Paint the Axis if needed
05337    if (!Hoption.Axis && !Hoption.Same && !Hoption.Lego && !Hoption.Surf) {
05338       TGaxis *axis = new TGaxis();
05339       PaintLegoAxis(axis, 90);
05340       delete axis;
05341    }
05342 
05343    delete fLego; fLego = 0;
05344 }
05345 
05346 
05347 //______________________________________________________________________________
05348 void THistPainter::PaintFrame()
05349 {
05350    /* Begin_html
05351    Calculate range and clear pad (canvas).
05352    End_html */
05353 
05354    if (Hoption.Same) return;
05355 
05356    RecalculateRange();
05357 
05358    if (Hoption.Lego || Hoption.Surf || Hoption.Tri ||
05359        Hoption.Contour == 14 || Hoption.Error >= 100) {
05360       TObject *frame = gPad->FindObject("TFrame");
05361       if (frame) gPad->GetListOfPrimitives()->Remove(frame);
05362       return;
05363    }
05364    gPad->PaintPadFrame(Hparam.xmin,Hparam.ymin,Hparam.xmax,Hparam.ymax);
05365 }
05366 
05367 
05368 //______________________________________________________________________________
05369 void THistPainter::PaintFunction(Option_t *)
05370 {
05371    /* Begin_html
05372    <a href="#HP28">Paint functions associated to an histogram.</a>
05373    End_html */
05374 
05375    TObjOptLink *lnk = (TObjOptLink*)fFunctions->FirstLink();
05376    TObject *obj;
05377 
05378    while (lnk) {
05379       obj = lnk->GetObject();
05380       TVirtualPad *padsave = gPad;
05381       if (obj->InheritsFrom(TF1::Class())) {
05382          if (obj->TestBit(TF1::kNotDraw) == 0) obj->Paint("lsame");
05383       } else  {
05384          obj->Paint(lnk->GetOption());
05385       }
05386       lnk = (TObjOptLink*)lnk->Next();
05387       padsave->cd();
05388    }
05389 }
05390 
05391 
05392 //______________________________________________________________________________
05393 void THistPainter::PaintHist(Option_t *)
05394 {
05395    /* Begin_html
05396    <a href="#HP01b">Control routine to draw 1D histograms.</a>
05397    End_html */
05398 
05399    static char chopth[17];
05400 
05401    Int_t htype, oldhtype;
05402    Int_t i, j, first, last, nbins, fixbin;
05403    Double_t c1, yb;
05404    yb = 0;
05405 
05406    strlcpy(chopth, "                ",17);
05407 
05408    Double_t ymin = Hparam.ymin;
05409    Double_t ymax = Hparam.ymax;
05410    Double_t baroffset = fH->GetBarOffset();
05411    Double_t barwidth  = fH->GetBarWidth();
05412    Double_t baroffsetsave = gStyle->GetBarOffset();
05413    Double_t barwidthsave  = gStyle->GetBarWidth();
05414    gStyle->SetBarOffset(baroffset);
05415    gStyle->SetBarWidth(barwidth);
05416 
05417    //       Create "LIFE" structure to keep current histogram status
05418 
05419    first = Hparam.xfirst;
05420    last  = Hparam.xlast;
05421    nbins = last - first + 1;
05422 
05423    Double_t *keepx = 0;
05424    Double_t *keepy = 0;
05425    if (fXaxis->GetXbins()->fN) fixbin = 0;
05426    else                        fixbin = 1;
05427    if (fixbin) keepx = new Double_t[2];
05428    else        keepx = new Double_t[nbins+1];
05429    keepy = new Double_t[nbins];
05430    Double_t logymin = 0;
05431    if (Hoption.Logy) logymin = TMath::Power(10,ymin);
05432 
05433    //      Loop on histogram bins
05434 
05435    for (j=first; j<=last;j++) {
05436       c1 = Hparam.factor*fH->GetBinContent(j);
05437       if (TMath::Abs(ymax-ymin) > 0) {
05438          if (Hoption.Logy) yb = TMath::Log10(TMath::Max(c1,.1*logymin));
05439          else              yb = c1;
05440       }
05441       yb = TMath::Max(yb, ymin);
05442       yb = TMath::Min(yb, ymax);
05443       keepy[j-first] = yb;
05444    }
05445 
05446    //              Draw histogram according to value of FillStyle and FillColor
05447 
05448    if (fixbin) { keepx[0] = Hparam.xmin; keepx[1] = Hparam.xmax; }
05449    else {
05450       for (i=0; i<nbins; i++) keepx[i] = fXaxis->GetBinLowEdge(i+first);
05451       keepx[nbins] = fXaxis->GetBinUpEdge(nbins-1+first);
05452    }
05453 
05454    //         Prepare Fill area (systematic with option "Bar").
05455 
05456    oldhtype = fH->GetFillStyle();
05457    htype    = oldhtype;
05458    if (Hoption.Bar) {
05459       if (htype == 0 || htype == 1000) htype = 1001;
05460    }
05461 
05462    Width_t lw = (Width_t)fH->GetLineWidth();
05463 
05464    //         Code option for GrapHist
05465 
05466    if (Hoption.Line) chopth[0] = 'L';
05467    if (Hoption.Star) chopth[1] = '*';
05468    if (Hoption.Mark) chopth[2] = 'P';
05469    if (Hoption.Mark == 10) chopth[3] = '0';
05470    if (Hoption.Line || Hoption.Curve || Hoption.Hist || Hoption.Bar) {
05471       if (Hoption.Curve)    chopth[3] = 'C';
05472       if (Hoption.Hist > 0) chopth[4] = 'H';
05473       else if (Hoption.Bar) chopth[5] = 'B';
05474       if (fH->GetFillColor() && htype) {
05475          if (Hoption.Logy) {
05476             chopth[6] = '1';
05477          }
05478          if (Hoption.Hist > 0 || Hoption.Curve || Hoption.Line) {
05479             chopth[7] = 'F';
05480          }
05481       }
05482    }
05483    if (!fixbin && strlen(chopth)) {
05484       chopth[8] = 'N';
05485    }
05486 
05487    // coverity [Calling risky function]
05488    if (Hoption.Fill == 2)    strlcat(chopth,"2",17);
05489    // coverity [Calling risky function]
05490    if (Hoption.HighRes != 0) strlcat(chopth,"9",17);
05491 
05492    //         Option LOGX
05493 
05494    if (Hoption.Logx) {
05495       chopth[9]  = 'G';
05496       chopth[10] = 'X';
05497       if (fixbin) {
05498          keepx[0] = TMath::Power(10,keepx[0]);
05499          keepx[1] = TMath::Power(10,keepx[1]);
05500       }
05501    }
05502 
05503    if (Hoption.Off) {
05504       chopth[11] = ']';
05505       chopth[12] = '[';
05506    }
05507 
05508    //         Draw the histogram
05509 
05510    TGraph graph;
05511    graph.SetLineWidth(lw);
05512    graph.SetLineStyle(fH->GetLineStyle());
05513    graph.SetLineColor(fH->GetLineColor());
05514    graph.SetFillStyle(htype);
05515    graph.SetFillColor(fH->GetFillColor());
05516    graph.SetMarkerStyle(fH->GetMarkerStyle());
05517    graph.SetMarkerSize(fH->GetMarkerSize());
05518    graph.SetMarkerColor(fH->GetMarkerColor());
05519    if (!Hoption.Same) graph.ResetBit(TGraph::kClipFrame);
05520 
05521    graph.PaintGrapHist(nbins, keepx, keepy ,chopth);
05522 
05523    delete [] keepx;
05524    delete [] keepy;
05525    gStyle->SetBarOffset(baroffsetsave);
05526    gStyle->SetBarWidth(barwidthsave);
05527 
05528    htype=oldhtype;
05529 }
05530 
05531 
05532 //______________________________________________________________________________
05533 void THistPainter::PaintH3(Option_t *option)
05534 {
05535    /* Begin_html
05536    <a href="#HP01d">Control function to draw a 3D histograms.</a>
05537    End_html */
05538 
05539    char *cmd;
05540    TString opt = fH->GetDrawOption();
05541    opt.ToLower();
05542 
05543    if (fH->GetDrawOption() && (strstr(opt,"box") ||  strstr(opt,"lego"))) {
05544       cmd = Form("TMarker3DBox::PaintH3((TH1 *)0x%lx,\"%s\");",(Long_t)fH,option);
05545    } else if (fH->GetDrawOption() && strstr(opt,"iso")) {
05546       PaintH3Iso();
05547       return;
05548    } else if (strstr(option,"tf3")) {
05549       PaintTF3();
05550       return;
05551    } else {
05552       cmd = Form("TPolyMarker3D::PaintH3((TH1 *)0x%lx,\"%s\");",(Long_t)fH,option);
05553    }
05554    gROOT->ProcessLine(cmd);
05555 
05556    // Draw axis
05557    if (Hoption.Same) return;
05558    TView *view = gPad->GetView();
05559    if (!view) return;
05560    view->SetOutlineToCube();
05561    view->GetOutline()->Paint(option);
05562    Hoption.System = kCARTESIAN;
05563    TGaxis *axis = new TGaxis();
05564    PaintLegoAxis(axis,90);
05565    delete axis;
05566 
05567    // Draw palette. In case of 4D plot with TTree::Draw() the palette should
05568    // be painted with the option colz.
05569    if (fH->GetDrawOption() && strstr(opt,"colz")) {
05570       Int_t ndiv   = fH->GetContour();
05571       if (ndiv == 0 ) {
05572          ndiv = gStyle->GetNumberContours();
05573          fH->SetContour(ndiv);
05574       }
05575       PaintPalette();
05576    }
05577 
05578    // Draw title
05579    PaintTitle();
05580 
05581    //Draw stats and fit results
05582    TF1 *fit  = 0;
05583    TIter next(fFunctions);
05584    TObject *obj;
05585    while ((obj = next())) {
05586       if (obj->InheritsFrom(TF1::Class())) {
05587          fit = (TF1*)obj;
05588          break;
05589       }
05590    }
05591    if (Hoption.Same != 1) {
05592       if (!fH->TestBit(TH1::kNoStats)) {  // bit set via TH1::SetStats
05593          PaintStat3(gStyle->GetOptStat(),fit);
05594       }
05595    }
05596 
05597 }
05598 
05599 
05600 //______________________________________________________________________________
05601 Int_t THistPainter::PaintInit()
05602 {
05603    /* Begin_html
05604    Compute histogram parameters used by the drawing routines.
05605    End_html */
05606 
05607    if (fH->GetDimension() > 1 || Hoption.Lego || Hoption.Surf) return 1;
05608 
05609    static const char *where = "PaintInit";
05610    Double_t yMARGIN = gStyle->GetHistTopMargin();
05611    Int_t maximum = 0;
05612    Int_t minimum = 0;
05613    if (fH->GetMaximumStored() != -1111) maximum = 1;
05614    if (fH->GetMinimumStored() != -1111) minimum = 1;
05615 
05616    //     Compute X axis parameters
05617 
05618    Int_t last      = fXaxis->GetLast();
05619    Int_t first     = fXaxis->GetFirst();
05620    Hparam.xlowedge = fXaxis->GetBinLowEdge(first);
05621    Hparam.xbinsize = fXaxis->GetBinWidth(first);
05622    Hparam.xlast    = last;
05623    Hparam.xfirst   = first;
05624    Hparam.xmin     = Hparam.xlowedge;
05625    Hparam.xmax     = fXaxis->GetBinLowEdge(last)+fXaxis->GetBinWidth(last);
05626 
05627    //       if log scale in X, replace xmin,max by the log
05628    if (Hoption.Logx) {
05629       if (Hparam.xlowedge <=0 ) {
05630          if (Hoption.Same) {
05631             Hparam.xlowedge = TMath::Power(10, gPad->GetUxmin());
05632          } else {
05633             Hparam.xlowedge = 0.1*Hparam.xbinsize;
05634          }
05635          Hparam.xmin  = Hparam.xlowedge;
05636       }
05637       if (Hparam.xmin <=0 || Hparam.xmax <=0) {
05638          Error(where, "cannot set X axis to log scale");
05639          return 0;
05640       }
05641       Hparam.xfirst= fXaxis->FindFixBin(Hparam.xmin);
05642       Hparam.xlast = fXaxis->FindFixBin(Hparam.xmax);
05643       Hparam.xmin  = TMath::Log10(Hparam.xmin);
05644       Hparam.xmax  = TMath::Log10(Hparam.xmax);
05645       if (Hparam.xlast  > last)  Hparam.xlast  = last;
05646       if (Hparam.xfirst < first) Hparam.xfirst = first;
05647    }
05648 
05649    //     Compute Y axis parameters
05650    Double_t bigp = TMath::Power(10,32);
05651    Double_t ymax = -bigp;
05652    Double_t ymin = bigp;
05653    Double_t c1, e1;
05654    Double_t xv[1];
05655    Double_t fval;
05656    Int_t i;
05657    TObject *f;
05658    TF1 *f1;
05659    Double_t allchan = 0;
05660    Int_t nonNullErrors = 0;
05661    TIter   next(fFunctions);
05662    for (i=first; i<=last;i++) {
05663       c1 = fH->GetBinContent(i);
05664       ymax = TMath::Max(ymax,c1);
05665       if (Hoption.Logy) {
05666          if (c1 > 0) ymin = TMath::Min(ymin,c1);
05667       } else {
05668          ymin = TMath::Min(ymin,c1);
05669       }
05670       if (Hoption.Error) {
05671          e1 = fH->GetBinError(i);
05672          if (e1 > 0) nonNullErrors++;
05673          ymax = TMath::Max(ymax,c1+e1);
05674          if (Hoption.Logy) {
05675             if (c1-e1>0.01*TMath::Abs(c1)) ymin = TMath::Min(ymin,c1-e1);
05676          } else {
05677             ymin = TMath::Min(ymin,c1-e1);
05678          }
05679       }
05680       if (Hoption.Func) {
05681          xv[0] = fXaxis->GetBinCenter(i);
05682          while ((f = (TObject*) next())) {
05683             if (f->IsA() == TF1::Class()) {
05684                f1 = (TF1*)f;
05685                if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
05686                fval = f1->Eval(xv[0],0,0);
05687                ymax = TMath::Max(ymax,fval);
05688                if (Hoption.Logy) {
05689                   if (c1 > 0 && fval > 0.3*c1) ymin = TMath::Min(ymin,fval);
05690                }
05691             }
05692          }
05693          next.Reset();
05694       }
05695       allchan += c1;
05696    }
05697    if (!nonNullErrors) {
05698       if (Hoption.Error) {
05699          if (!Hoption.Mark && !Hoption.Line && !Hoption.Star && !Hoption.Curve) Hoption.Hist = 2;
05700          Hoption.Error=0;
05701       }
05702    }
05703 
05704 
05705    //     Take into account maximum , minimum
05706 
05707    if (Hoption.Logy && ymin <= 0) {
05708       if (ymax >= 1) ymin = TMath::Max(.005,ymax*1e-10);
05709       else           ymin = 0.001*ymax;
05710    }
05711 
05712    Double_t xm = ymin;
05713    if (maximum) ymax = fH->GetMaximumStored();
05714    if (minimum) xm   = fH->GetMinimumStored();
05715    if (Hoption.Logy && xm < 0) {
05716       Error(where, "log scale requested with a negative argument (%f)", xm);
05717       return 0;
05718    } else if (Hoption.Logy && xm>=0 && ymax==0) { // empty histogram in log scale
05719       ymin = 0.01;
05720       ymax = 10.;
05721    } else {
05722       ymin = xm;
05723    }
05724 
05725    if (ymin >= ymax) {
05726       if (Hoption.Logy) {
05727          if (ymax > 0) ymin = 0.001*ymax;
05728          else {
05729             if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", ymax);
05730             return 0;
05731          }
05732       }
05733       else {
05734          if (ymin > 0) {
05735             ymin = 0;
05736             ymax *= 2;
05737          } else if (ymin < 0) {
05738             ymax = 0;
05739             ymin *= 2;
05740          } else {
05741             ymin = 0;
05742             ymax = 1;
05743          }
05744       }
05745    }
05746 
05747    // In some cases, mainly because of precision issues, ymin and ymax could almost equal.
05748    if(TMath::AreEqualRel(ymin,ymax,1E-15)) {
05749       ymin = ymin*(1-1E-14);
05750       ymax = ymax*(1+1E-14);
05751    }
05752 
05753    //     take into account normalization factor
05754    Hparam.allchan = allchan;
05755    Double_t factor = allchan;
05756    if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
05757    if (allchan) factor /= allchan;
05758    if (factor == 0) factor = 1;
05759    Hparam.factor = factor;
05760    ymax = factor*ymax;
05761    ymin = factor*ymin;
05762    //just in case the norm factor is negative
05763    // this may happen with a positive norm factor and a negative integral !
05764    if (ymax < ymin) {
05765       Double_t temp = ymax;
05766       ymax = ymin;
05767       ymin = temp;
05768    }
05769 
05770    //         For log scales, histogram coordinates are LOG10(ymin) and
05771    //         LOG10(ymax). Final adjustment (if not option "Same"
05772    //         or "+" for ymax) of ymax and ymin for logarithmic scale, if
05773    //         Maximum and Minimum are not defined.
05774    if (Hoption.Logy) {
05775       if (ymin <=0 || ymax <=0) {
05776          Error(where, "Cannot set Y axis to log scale");
05777          return 0;
05778       }
05779       ymin = TMath::Log10(ymin);
05780       if (!minimum) ymin += TMath::Log10(0.5);
05781       ymax = TMath::Log10(ymax);
05782       if (!maximum) ymax += TMath::Log10(2*(0.9/0.95));
05783       if (!Hoption.Same) {
05784          Hparam.ymin = ymin;
05785          Hparam.ymax = ymax;
05786       }
05787       return 1;
05788    }
05789 
05790    //         final adjustment of ymin for linear scale.
05791    //         if minimum is not set , then ymin is set to zero if >0
05792    //         or to ymin - margin if <0.
05793    if (!minimum) {
05794       if (gStyle->GetHistMinimumZero()) {
05795          if (ymin >= 0) ymin = 0;
05796          else           ymin -= yMARGIN*(ymax-ymin);
05797       } else {
05798          Double_t dymin = yMARGIN*(ymax-ymin);
05799          if (ymin >= 0 && (ymin-dymin <= 0)) ymin  = 0;
05800          else                                ymin -= dymin;
05801       }
05802    }
05803 
05804    //         final adjustment of YMAXI for linear scale (if not option "Same"):
05805    //         decrease histogram height to MAX% of allowed height if HMAXIM
05806    //         has not been called.
05807    if (!maximum) {
05808       ymax += yMARGIN*(ymax-ymin);
05809    }
05810 
05811    Hparam.ymin = ymin;
05812    Hparam.ymax = ymax;
05813    return 1;
05814 }
05815 
05816 
05817 //______________________________________________________________________________
05818 Int_t THistPainter::PaintInitH()
05819 {
05820    /* Begin_html
05821    Compute histogram parameters used by the drawing routines for a rotated pad.
05822    End_html */
05823 
05824    static const char *where = "PaintInitH";
05825    Double_t yMARGIN = gStyle->GetHistTopMargin();
05826    Int_t maximum = 0;
05827    Int_t minimum = 0;
05828    if (fH->GetMaximumStored() != -1111) maximum = 1;
05829    if (fH->GetMinimumStored() != -1111) minimum = 1;
05830 
05831    //     Compute X axis parameters
05832 
05833    Int_t last      = fXaxis->GetLast();
05834    Int_t first     = fXaxis->GetFirst();
05835    Hparam.xlowedge = fXaxis->GetBinLowEdge(first);
05836    Hparam.xbinsize = fXaxis->GetBinWidth(first);
05837    Hparam.xlast    = last;
05838    Hparam.xfirst   = first;
05839    Hparam.ymin     = Hparam.xlowedge;
05840    Hparam.ymax     = fXaxis->GetBinLowEdge(last)+fXaxis->GetBinWidth(last);
05841 
05842    //       if log scale in Y, replace ymin,max by the log
05843    if (Hoption.Logy) {
05844       if (Hparam.xlowedge <=0 ) {
05845          Hparam.xlowedge = 0.1*Hparam.xbinsize;
05846          Hparam.ymin  = Hparam.xlowedge;
05847       }
05848       if (Hparam.ymin <=0 || Hparam.ymax <=0) {
05849          Error(where, "cannot set Y axis to log scale");
05850          return 0;
05851       }
05852       Hparam.xfirst= fXaxis->FindFixBin(Hparam.ymin);
05853       Hparam.xlast = fXaxis->FindFixBin(Hparam.ymax);
05854       Hparam.ymin  = TMath::Log10(Hparam.ymin);
05855       Hparam.ymax  = TMath::Log10(Hparam.ymax);
05856       if (Hparam.xlast > last) Hparam.xlast = last;
05857    }
05858 
05859    //     Compute Y axis parameters
05860    Double_t bigp = TMath::Power(10,32);
05861    Double_t xmax = -bigp;
05862    Double_t xmin = bigp;
05863    Double_t c1, e1;
05864    Double_t xv[1];
05865    Double_t fval;
05866    Int_t i;
05867    TObject *f;
05868    TF1 *f1;
05869    Double_t allchan = 0;
05870    TIter   next(fFunctions);
05871    for (i=first; i<=last;i++) {
05872       c1 = fH->GetBinContent(i);
05873       xmax = TMath::Max(xmax,c1);
05874       xmin = TMath::Min(xmin,c1);
05875       if (Hoption.Error) {
05876          e1 = fH->GetBinError(i);
05877          xmax = TMath::Max(xmax,c1+e1);
05878          xmin = TMath::Min(xmin,c1-e1);
05879       }
05880       if (Hoption.Func) {
05881          xv[0] = fXaxis->GetBinCenter(i);
05882          while ((f = (TObject*) next())) {
05883             if (f->IsA() == TF1::Class()) {
05884                f1 = (TF1*)f;
05885                if (xv[0] < f1->GetXmin() || xv[0] > f1->GetXmax()) continue;
05886                fval = f1->Eval(xv[0],0,0);
05887                xmax = TMath::Max(xmax,fval);
05888                if (Hoption.Logy) {
05889                   if (fval > 0.3*c1) xmin = TMath::Min(xmin,fval);
05890                }
05891             }
05892          }
05893          next.Reset();
05894       }
05895       allchan += c1;
05896    }
05897 
05898    //     Take into account maximum , minimum
05899 
05900    if (Hoption.Logx && xmin <= 0) {
05901       if (xmax >= 1) xmin = TMath::Max(.5,xmax*1e-10);
05902       else           xmin = 0.001*xmax;
05903    }
05904    Double_t xm = xmin;
05905    if (maximum) xmax = fH->GetMaximumStored();
05906    if (minimum) xm   = fH->GetMinimumStored();
05907    if (Hoption.Logx && xm <= 0) {
05908       Error(where, "log scale requested with zero or negative argument (%f)", xm);
05909       return 0;
05910    }
05911    else xmin = xm;
05912    if (xmin >= xmax) {
05913       if (Hoption.Logx) {
05914          if (xmax > 0) xmin = 0.001*xmax;
05915          else {
05916             if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", xmax);
05917             return 0;
05918          }
05919       }
05920       else {
05921          if (xmin > 0) {
05922             xmin = 0;
05923             xmax *= 2;
05924          } else if (xmin < 0) {
05925             xmax = 0;
05926             xmin *= 2;
05927          } else {
05928             xmin = -1;
05929             xmax = 1;
05930          }
05931       }
05932    }
05933 
05934    //     take into account normalization factor
05935    Hparam.allchan = allchan;
05936    Double_t factor = allchan;
05937    if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
05938    if (allchan) factor /= allchan;
05939    if (factor == 0) factor = 1;
05940    Hparam.factor = factor;
05941    xmax = factor*xmax;
05942    xmin = factor*xmin;
05943 
05944    //         For log scales, histogram coordinates are LOG10(ymin) and
05945    //         LOG10(ymax). Final adjustment (if not option "Same"
05946    //         or "+" for ymax) of ymax and ymin for logarithmic scale, if
05947    //         Maximum and Minimum are not defined.
05948    if (Hoption.Logx) {
05949       if (xmin <=0 || xmax <=0) {
05950          Error(where, "Cannot set Y axis to log scale");
05951          return 0;
05952       }
05953       xmin = TMath::Log10(xmin);
05954       if (!minimum) xmin += TMath::Log10(0.5);
05955       xmax = TMath::Log10(xmax);
05956       if (!maximum) xmax += TMath::Log10(2*(0.9/0.95));
05957       if (!Hoption.Same) {
05958          Hparam.xmin = xmin;
05959          Hparam.xmax = xmax;
05960       }
05961       return 1;
05962    }
05963 
05964    //         final adjustment of ymin for linear scale.
05965    //         if minimum is not set , then ymin is set to zero if >0
05966    //         or to ymin - margin if <0.
05967    if (!minimum) {
05968       if (xmin >= 0) xmin = 0;
05969       else           xmin -= yMARGIN*(xmax-xmin);
05970    }
05971 
05972    //         final adjustment of YMAXI for linear scale (if not option "Same"):
05973    //         decrease histogram height to MAX% of allowed height if HMAXIM
05974    //         has not been called.
05975    if (!maximum) {
05976       xmax += yMARGIN*(xmax-xmin);
05977    }
05978    Hparam.xmin = xmin;
05979    Hparam.xmax = xmax;
05980    return 1;
05981 }
05982 
05983 
05984 //______________________________________________________________________________
05985 void THistPainter::PaintH3Iso()
05986 {
05987    /* Begin_html
05988    <a href="#HP25">Control function to draw a 3D histogram with Iso Surfaces.</a>
05989    End_html */
05990 
05991    const Double_t ydiff = 1;
05992    const Double_t yligh1 = 10;
05993    const Double_t qa = 0.15;
05994    const Double_t qd = 0.15;
05995    const Double_t qs = 0.8;
05996    Double_t fmin, fmax;
05997    Int_t i, irep;
05998    Int_t nbcol = 28;
05999    Int_t icol1 = 201;
06000    Int_t ic1 = icol1;
06001    Int_t ic2 = ic1+nbcol;
06002    Int_t ic3 = ic2+nbcol;
06003 
06004    TGaxis *axis = new TGaxis();
06005    TAxis *xaxis = fH->GetXaxis();
06006    TAxis *yaxis = fH->GetYaxis();
06007    TAxis *zaxis = fH->GetZaxis();
06008 
06009    Int_t nx = fH->GetNbinsX();
06010    Int_t ny = fH->GetNbinsY();
06011    Int_t nz = fH->GetNbinsZ();
06012 
06013    Double_t *x = new Double_t[nx];
06014    Double_t *y = new Double_t[ny];
06015    Double_t *z = new Double_t[nz];
06016 
06017    for ( i=0 ; i<nx ; i++) x[i] = xaxis->GetBinCenter(i+1);
06018    for ( i=0 ; i<ny ; i++) y[i] = yaxis->GetBinCenter(i+1);
06019    for ( i=0 ; i<nz ; i++) z[i] = zaxis->GetBinCenter(i+1);
06020 
06021    fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
06022    fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
06023    fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
06024    fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
06025    fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
06026    fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
06027 
06028    Double_t s[3];
06029    s[0] = fH->GetSumOfWeights()/(fH->GetNbinsX()*fH->GetNbinsY()*fH->GetNbinsZ());
06030    s[1] = 0.5*s[0];
06031    s[2] = 1.5*s[0];
06032 
06033    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf);
06034 
06035    TView *view = gPad->GetView();
06036    if (!view) {
06037       Error("PaintH3Iso", "no TView in current pad");
06038       delete [] x;
06039       delete [] y;
06040       delete [] z;
06041       return;
06042    }
06043    Double_t thedeg =  90 - gPad->GetTheta();
06044    Double_t phideg = -90 - gPad->GetPhi();
06045    Double_t psideg = view->GetPsi();
06046    view->SetView(phideg, thedeg, psideg, irep);
06047 
06048    Int_t backcolor = gPad->GetFrameFillColor();
06049    if (Hoption.System != kCARTESIAN) backcolor = 0;
06050    view->PadRange(backcolor);
06051 
06052    Double_t dcol = 0.5/Double_t(nbcol);
06053    TColor *colref = gROOT->GetColor(fH->GetFillColor());
06054    Float_t r, g, b, hue, light, satur;
06055    colref->GetRGB(r,g,b);
06056    TColor::RGBtoHLS(r,g,b,hue,light,satur);
06057    TColor *acol;
06058    for (Int_t col=0;col<nbcol;col++) {
06059       acol = gROOT->GetColor(col+icol1);
06060       TColor::HLStoRGB(hue, .4+col*dcol, satur, r, g, b);
06061       acol->SetRGB(r, g, b);
06062    }
06063 
06064    fLego->InitMoveScreen(-1.1,1.1);
06065 
06066    if (Hoption.BackBox) {
06067       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
06068       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
06069       fLego->BackBox(90);
06070    }
06071 
06072    fLego->LightSource(0, ydiff, 0, 0, 0, irep);
06073    fLego->LightSource(1, yligh1, 1, 1, 1, irep);
06074    fLego->SurfaceProperty(qa, qd, qs, 1, irep);
06075    fmin = ydiff*qa;
06076    fmax = ydiff*qa + (yligh1+0.1)*(qd+qs);
06077    fLego->SetIsoSurfaceParameters(fmin, fmax, nbcol, ic1, ic2, ic3);
06078 
06079    fLego->IsoSurface(1, s, nx, ny, nz, x, y, z, "BF");
06080 
06081    if (Hoption.FrontBox) {
06082       fLego->InitMoveScreen(-1.1,1.1);
06083       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
06084       fLego->FrontBox(90);
06085    }
06086    if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
06087 
06088    PaintTitle();
06089 
06090    delete axis;
06091    delete fLego; fLego = 0;
06092    delete [] x;
06093    delete [] y;
06094    delete [] z;
06095 }
06096 
06097 
06098 //______________________________________________________________________________
06099 void THistPainter::PaintLego(Option_t *)
06100 {
06101    /* Begin_html
06102    <a href="#HP17">Control function to draw a 2D histogram as a lego plot.</a>
06103    End_html */
06104 
06105    Int_t raster = 1;
06106    if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
06107    Int_t   nx      = Hparam.xlast - Hparam.xfirst + 1;
06108    Int_t   ny      = Hparam.ylast - Hparam.yfirst + 1;
06109    Double_t zmin   = Hparam.zmin;
06110    Double_t zmax   = Hparam.zmax;
06111    Double_t xlab1  = Hparam.xmin;
06112    Double_t xlab2  = Hparam.xmax;
06113    Double_t ylab1  = Hparam.ymin;
06114    Double_t ylab2  = Hparam.ymax;
06115    Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
06116    Double_t deltaz = TMath::Abs(zmin);
06117    if (deltaz == 0) deltaz = 1;
06118    if (zmin >= zmax) {
06119       zmin -= 0.5*deltaz;
06120       zmax += 0.5*deltaz;
06121    }
06122    Double_t z1c = zmin;
06123    Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
06124 
06125    //     Compute the lego limits and instantiate a lego object
06126    fXbuf[0] = -1;
06127    fYbuf[0] =  1;
06128    fXbuf[1] = -1;
06129    fYbuf[1] =  1;
06130    if (Hoption.System == kPOLAR) {
06131       fXbuf[2] = z1c;
06132       fYbuf[2] = z2c;
06133    } else if (Hoption.System == kCYLINDRICAL) {
06134       if (Hoption.Logy) {
06135          if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
06136          else           fXbuf[2] = 0;
06137          if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
06138          else           fYbuf[2] = 0;
06139       } else {
06140          fXbuf[2] = ylab1;
06141          fYbuf[2] = ylab2;
06142       }
06143       z1c = 0; z2c = 1;
06144    } else if (Hoption.System == kSPHERICAL) {
06145       fXbuf[2] = -1;
06146       fYbuf[2] =  1;
06147       z1c = 0; z2c = 1;
06148    } else if (Hoption.System == kRAPIDITY) {
06149       fXbuf[2] = -1/TMath::Tan(dangle);
06150       fYbuf[2] =  1/TMath::Tan(dangle);
06151    } else {
06152       fXbuf[0] = xlab1;
06153       fYbuf[0] = xlab2;
06154       fXbuf[1] = ylab1;
06155       fYbuf[1] = ylab2;
06156       fXbuf[2] = z1c;
06157       fYbuf[2] = z2c;
06158       raster  = 0;
06159    }
06160 
06161    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf, Hoption.System);
06162 
06163    //          Create axis object
06164 
06165    TGaxis *axis = new TGaxis();
06166 
06167    //                  Initialize the levels on the Z axis
06168    Int_t ndiv   = fH->GetContour();
06169    if (ndiv == 0 ) {
06170       ndiv = gStyle->GetNumberContours();
06171       fH->SetContour(ndiv);
06172    }
06173    Int_t ndivz  = TMath::Abs(ndiv);
06174    if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
06175 
06176    //     Initialize colors for the lighting model (option Lego1 only)
06177    if (Hoption.Lego == 1) {
06178          Color_t colormain = fH->GetLineColor();
06179          fLego->SetColorMain(colormain,0);
06180    }
06181    if (Hoption.Lego == 11) {
06182       Int_t nids = 1;
06183       if (fStack) nids = fStack->GetSize();
06184       TH1 *hid = fH;
06185       for (Int_t id=0;id<=nids;id++) {
06186          if (id > 0 && fStack) hid = (TH1*)fStack->At(id-1);
06187          Color_t colormain = hid->GetFillColor();
06188          if (colormain == 1) colormain = 17; //avoid drawing with black
06189          Color_t colordark = TColor::GetColorDark(colormain);
06190          fLego->SetColorMain(colormain,id);
06191          fLego->SetColorDark(colordark,id);
06192          if (id == 0)    fLego->SetColorMain(colormain,-1);  // Set Bottom color
06193          if (id == nids) fLego->SetColorMain(colormain,99);  // Set Top color
06194       }
06195    }
06196 
06197    //     Now ready to draw the lego plot
06198    Int_t irep = 0;
06199 
06200    TView *view = gPad->GetView();
06201    if (!view) {
06202       Error("PaintLego", "no TView in current pad");
06203       return;
06204    }
06205 
06206    Double_t thedeg =  90 - gPad->GetTheta();
06207    Double_t phideg = -90 - gPad->GetPhi();
06208    Double_t psideg = view->GetPsi();
06209    view->SetView(phideg, thedeg, psideg, irep);
06210 
06211    fLego->SetLineColor(fH->GetLineColor());
06212    fLego->SetFillStyle(fH->GetFillStyle());
06213 
06214    //     Set color/style for back box
06215    fLego->SetFillStyle(gPad->GetFrameFillStyle());
06216    fLego->SetFillColor(gPad->GetFrameFillColor());
06217    fLego->TAttFill::Modify();
06218 
06219    Int_t backcolor = gPad->GetFrameFillColor();
06220    if (Hoption.System != kCARTESIAN) backcolor = 0;
06221    view->PadRange(backcolor);
06222 
06223    fLego->SetFillStyle(fH->GetFillStyle());
06224    fLego->SetFillColor(fH->GetFillColor());
06225    fLego->TAttFill::Modify();
06226 
06227    fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
06228 
06229    if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
06230    else        fLego->InitMoveScreen(-1.1,1.1);
06231 
06232    if (Hoption.Lego == 11 || Hoption.Lego == 12) {
06233       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
06234          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
06235          fLego->BackBox(90);
06236       }
06237    }
06238 
06239    if (Hoption.Lego == 12) DefineColorLevels(ndivz);
06240 
06241    fLego->SetLegoFunction(&TPainter3dAlgorithms::LegoFunction);
06242    if (Hoption.Lego ==  1) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster2);
06243    if (Hoption.Lego == 11) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode3);
06244    if (Hoption.Lego == 12) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
06245    if (Hoption.System == kPOLAR) {
06246       if (Hoption.Lego ==  1) fLego->LegoPolar(1,nx,ny,"FB");
06247       if (Hoption.Lego == 11) fLego->LegoPolar(1,nx,ny,"BF");
06248       if (Hoption.Lego == 12) fLego->LegoPolar(1,nx,ny,"BF");
06249    } else if (Hoption.System == kCYLINDRICAL) {
06250       if (Hoption.Lego ==  1) fLego->LegoCylindrical(1,nx,ny,"FB");
06251       if (Hoption.Lego == 11) fLego->LegoCylindrical(1,nx,ny,"BF");
06252       if (Hoption.Lego == 12) fLego->LegoCylindrical(1,nx,ny,"BF");
06253    } else if (Hoption.System == kSPHERICAL) {
06254       if (Hoption.Lego ==  1) fLego->LegoSpherical(0,1,nx,ny,"FB");
06255       if (Hoption.Lego == 11) fLego->LegoSpherical(0,1,nx,ny,"BF");
06256       if (Hoption.Lego == 12) fLego->LegoSpherical(0,1,nx,ny,"BF");
06257    } else if (Hoption.System == kRAPIDITY) {
06258       if (Hoption.Lego ==  1) fLego->LegoSpherical(1,1,nx,ny,"FB");
06259       if (Hoption.Lego == 11) fLego->LegoSpherical(1,1,nx,ny,"BF");
06260       if (Hoption.Lego == 12) fLego->LegoSpherical(1,1,nx,ny,"BF");
06261    } else {
06262       if (Hoption.Lego ==  1) {
06263                               fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
06264                               fLego->LegoCartesian(90,nx,ny,"FB");}
06265       if (Hoption.Lego == 11) fLego->LegoCartesian(90,nx,ny,"BF");
06266       if (Hoption.Lego == 12) fLego->LegoCartesian(90,nx,ny,"BF");
06267    }
06268 
06269    if (Hoption.Lego == 1 || Hoption.Lego == 11) {
06270       fLego->SetLineColor(1);
06271       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
06272          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
06273          fLego->BackBox(90);
06274       }
06275    }
06276    if (Hoption.System == kCARTESIAN) {
06277       fLego->InitMoveScreen(-1.1,1.1);
06278       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
06279       if (Hoption.FrontBox) fLego->FrontBox(90);
06280    }
06281    if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
06282    if (Hoption.Zscale) PaintPalette();
06283    delete axis;
06284    delete fLego; fLego = 0;
06285 }
06286 
06287 
06288 //______________________________________________________________________________
06289 void THistPainter::PaintLegoAxis(TGaxis *axis, Double_t ang)
06290 {
06291    /* Begin_html
06292    Draw the axis for legos and surface plots.
06293    End_html */
06294 
06295    static Double_t epsil = 0.001;
06296 
06297    Double_t cosa, sina;
06298    Double_t bmin, bmax;
06299    Double_t r[24]        /* was [3][8] */;
06300    Int_t ndivx, ndivy, ndivz, i;
06301    Double_t x1[3], x2[3], y1[3], y2[3], z1[3], z2[3], av[24]  /*  was [3][8] */;
06302    static char chopax[8], chopay[8], chopaz[8];
06303    Int_t ix1, ix2, iy1, iy2, iz1, iz2;
06304    Double_t rad;
06305 
06306    TView *view = gPad->GetView();
06307    if (!view) {
06308       Error("PaintLegoAxis", "no TView in current pad");
06309       return;
06310    }
06311 
06312    // In polar coordinates, draw a short line going from the external circle
06313    // corresponding to r = 1 up to r = 1.1
06314    if (Hoption.System == kPOLAR) {
06315       r[0] = 1;
06316       r[1] = 0;
06317       r[2] = 0;
06318       view->WCtoNDC(r, x1);
06319       r[0] = 1.1;
06320       r[1] = 0;
06321       r[2] = 0;
06322       view->WCtoNDC(r, x2);
06323       gPad->PaintLine(x1[0],x1[1],x2[0],x2[1]);
06324       return ;
06325    }
06326 
06327    if (Hoption.System != kCARTESIAN) return ;
06328 
06329    rad = TMath::ATan(1.) * 4. /180.;
06330    cosa = TMath::Cos(ang*rad);
06331    sina = TMath::Sin(ang*rad);
06332 
06333    view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
06334    for (i = 1; i <= 8; ++i) {
06335       r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
06336       r[i*3 - 2] = av[i*3 - 2]*sina;
06337       r[i*3 - 1] = av[i*3 - 1];
06338    }
06339 
06340    view->WCtoNDC(&r[ix1*3 - 3], x1);
06341    view->WCtoNDC(&r[ix2*3 - 3], x2);
06342    view->WCtoNDC(&r[iy1*3 - 3], y1);
06343    view->WCtoNDC(&r[iy2*3 - 3], y2);
06344    view->WCtoNDC(&r[iz1*3 - 3], z1);
06345    view->WCtoNDC(&r[iz2*3 - 3], z2);
06346 
06347    view->SetAxisNDC(x1, x2, y1, y2, z1, z2);
06348 
06349    Double_t *rmin = view->GetRmin();
06350    Double_t *rmax = view->GetRmax();
06351 
06352    // Initialize the axis options
06353    if (x1[0] > x2[0]) strlcpy(chopax, "SDH=+",8);
06354    else               strlcpy(chopax, "SDH=-",8);
06355    if (y1[0] > y2[0]) strlcpy(chopay, "SDH=+",8);
06356    else               strlcpy(chopay, "SDH=-",8);
06357    strlcpy(chopaz, "SDH+=",8);
06358 
06359    // Option LOG is required ?
06360    // coverity [Calling risky function]
06361    if (Hoption.Logx) strlcat(chopax,"G",8);
06362    // coverity [Calling risky function]
06363    if (Hoption.Logy) strlcat(chopay,"G",8);
06364    // coverity [Calling risky function]
06365    if (Hoption.Logz) strlcat(chopaz,"G",8);
06366 
06367    // Initialize the number of divisions. If the
06368    // number of divisions is negative, option 'N' is required.
06369    ndivx = fXaxis->GetNdivisions();
06370    ndivy = fYaxis->GetNdivisions();
06371    ndivz = fZaxis->GetNdivisions();
06372    if (ndivx < 0) {
06373       ndivx = TMath::Abs(ndivx);
06374       // coverity [Calling risky function]
06375       strlcat(chopax, "N",8);
06376    }
06377    if (ndivy < 0) {
06378       ndivy = TMath::Abs(ndivy);
06379       // coverity [Calling risky function]
06380       strlcat(chopay, "N",8);
06381    }
06382    if (ndivz < 0) {
06383       ndivz = TMath::Abs(ndivz);
06384       // coverity [Calling risky function]
06385       strlcat(chopaz, "N",8);
06386    }
06387 
06388    // Set Axis attributes.
06389    // The variable SCALE  rescales the VSIZ
06390    // in order to have the same label size for all angles.
06391 
06392    axis->SetLineWidth(1);
06393 
06394    // X axis drawing
06395    if (TMath::Abs(x1[0] - x2[0]) >= epsil || TMath::Abs(x1[1] - x2[1]) > epsil) {
06396       axis->ImportAxisAttributes(fXaxis);
06397       axis->SetLabelOffset(fXaxis->GetLabelOffset()+fXaxis->GetTickLength());
06398       if (Hoption.Logx && !fH->InheritsFrom(TH3::Class())) {
06399          bmin = TMath::Power(10, rmin[0]);
06400          bmax = TMath::Power(10, rmax[0]);
06401       } else {
06402          bmin = rmin[0];
06403          bmax = rmax[0];
06404       }
06405       // Option time display is required ?
06406       if (fXaxis->GetTimeDisplay()) {
06407          // coverity [Calling risky function]
06408          strlcat(chopax,"t",8);
06409          if (strlen(fXaxis->GetTimeFormatOnly()) == 0) {
06410             axis->SetTimeFormat(fXaxis->ChooseTimeFormat(bmax-bmin));
06411          } else {
06412             axis->SetTimeFormat(fXaxis->GetTimeFormat());
06413          }
06414       }
06415       axis->SetOption(chopax);
06416       axis->PaintAxis(x1[0], x1[1], x2[0], x2[1], bmin, bmax, ndivx, chopax);
06417    }
06418 
06419    // Y axis drawing
06420    if (TMath::Abs(y1[0] - y2[0]) >= epsil || TMath::Abs(y1[1] - y2[1]) > epsil) {
06421       axis->ImportAxisAttributes(fYaxis);
06422       axis->SetLabelOffset(fYaxis->GetLabelOffset()+fYaxis->GetTickLength());
06423 
06424       if (fH->GetDimension() < 2) {
06425          strlcpy(chopay, "V=+UN",8);
06426          ndivy = 0;
06427       }
06428       if (TMath::Abs(y1[0] - y2[0]) < epsil) {
06429          y2[0] = y1[0];
06430       }
06431       if (Hoption.Logy && !fH->InheritsFrom(TH3::Class())) {
06432          bmin = TMath::Power(10, rmin[1]);
06433          bmax = TMath::Power(10, rmax[1]);
06434       } else {
06435          bmin = rmin[1];
06436          bmax = rmax[1];
06437       }
06438       // Option time display is required ?
06439       if (fYaxis->GetTimeDisplay()) {
06440          // coverity [Calling risky function]
06441          strlcat(chopay,"t",8);
06442          if (strlen(fYaxis->GetTimeFormatOnly()) == 0) {
06443             axis->SetTimeFormat(fYaxis->ChooseTimeFormat(bmax-bmin));
06444          } else {
06445             axis->SetTimeFormat(fYaxis->GetTimeFormat());
06446          }
06447       }
06448       axis->SetOption(chopay);
06449       axis->PaintAxis(y1[0], y1[1], y2[0], y2[1], bmin, bmax, ndivy, chopay);
06450    }
06451 
06452    // Z axis drawing
06453    if (TMath::Abs(z1[0] - z2[0]) >= 100*epsil || TMath::Abs(z1[1] - z2[1]) > 100*epsil) {
06454       axis->ImportAxisAttributes(fZaxis);
06455       if (Hoption.Logz && !fH->InheritsFrom(TH3::Class())) {
06456          bmin = TMath::Power(10, rmin[2]);
06457          bmax = TMath::Power(10, rmax[2]);
06458       } else {
06459          bmin = rmin[2];
06460          bmax = rmax[2];
06461       }
06462       // Option time display is required ?
06463       if (fZaxis->GetTimeDisplay()) {
06464          // coverity [Calling risky function]
06465          strlcat(chopaz,"t",8);
06466          if (strlen(fZaxis->GetTimeFormatOnly()) == 0) {
06467             axis->SetTimeFormat(fZaxis->ChooseTimeFormat(bmax-bmin));
06468          } else {
06469             axis->SetTimeFormat(fZaxis->GetTimeFormat());
06470          }
06471       }
06472       axis->SetOption(chopaz);
06473       axis->PaintAxis(z1[0], z1[1], z2[0], z2[1], bmin, bmax, ndivz, chopaz);
06474    }
06475 
06476    fH->SetLineStyle(1);
06477 }
06478 
06479 
06480 //______________________________________________________________________________
06481 void THistPainter::PaintPalette()
06482 {
06483    /* Begin_html
06484    <a href="#HP22">Paint the color palette on the right side of the pad.</a>
06485    End_html */
06486 
06487    TPaletteAxis *palette = (TPaletteAxis*)fFunctions->FindObject("palette");
06488    TView *view = gPad->GetView();
06489    if (palette) {
06490       if (view) {
06491          if (!palette->TestBit(TPaletteAxis::kHasView)) {
06492             delete palette; palette = 0;
06493          }
06494       } else {
06495          if (palette->TestBit(TPaletteAxis::kHasView)) {
06496             delete palette; palette = 0;
06497          }
06498       }
06499    }
06500 
06501    if (!palette) {
06502       Double_t xup  = gPad->GetUxmax();
06503       Double_t x2   = gPad->PadtoX(gPad->GetX2());
06504       Double_t ymin = gPad->PadtoY(gPad->GetUymin());
06505       Double_t ymax = gPad->PadtoY(gPad->GetUymax());
06506       Double_t xr   = 0.05*(gPad->GetX2() - gPad->GetX1());
06507       Double_t xmin = gPad->PadtoX(xup +0.1*xr);
06508       Double_t xmax = gPad->PadtoX(xup + xr);
06509       if (xmax > x2) xmax = gPad->PadtoX(gPad->GetX2()-0.01*xr);
06510       palette = new TPaletteAxis(xmin,ymin,xmax,ymax,fH);
06511       fFunctions->Add(palette);
06512       palette->Paint();
06513    }
06514 }
06515 
06516 
06517 //______________________________________________________________________________
06518 void THistPainter::PaintScatterPlot(Option_t *option)
06519 {
06520    /* Begin_html
06521    <a href="#HP11">Control function to draw a 2D histogram as a scatter plot.</a>
06522    End_html */
06523 
06524    fH->TAttMarker::Modify();
06525 
06526    Int_t k, marker;
06527    Double_t dz, z, xk,xstep, yk, ystep;
06528    Double_t scale = 1;
06529    Bool_t ltest  = kFALSE;
06530    Double_t zmax  = fH->GetMaximum();
06531    Double_t zmin  = fH->GetMinimum();
06532    if (zmin == 0 && zmax == 0) return;
06533    if (zmin == zmax) {
06534       zmax += 0.1*TMath::Abs(zmax);
06535       zmin -= 0.1*TMath::Abs(zmin);
06536    }
06537    Int_t ncells = (Hparam.ylast-Hparam.yfirst)*(Hparam.xlast-Hparam.xfirst);
06538    if (Hoption.Logz) {
06539       if (zmin > 0) zmin = TMath::Log10(zmin);
06540       else          zmin = 0;
06541       if (zmax > 0) zmax = TMath::Log10(zmax);
06542       else          zmax = 0;
06543       if (zmin == 0 && zmax == 0) return;
06544       dz = zmax - zmin;
06545       scale = 100/dz;
06546       if (ncells > 10000) scale /= 5;
06547       ltest = kTRUE;
06548    } else {
06549       dz = zmax - zmin;
06550       if (dz >= kNMAX || zmax < 1) {
06551          scale = (kNMAX-1)/dz;
06552          if (ncells > 10000) scale /= 5;
06553          ltest = kTRUE;
06554       }
06555    }
06556    if (fH->GetMinimumStored() == -1111) {
06557       Double_t yMARGIN = gStyle->GetHistTopMargin();
06558       if (gStyle->GetHistMinimumZero()) {
06559          if (zmin >= 0) zmin = 0;
06560          else           zmin -= yMARGIN*(zmax-zmin);
06561       } else {
06562          Double_t dzmin = yMARGIN*(zmax-zmin);
06563          if (zmin >= 0 && (zmin-dzmin <= 0)) zmin  = 0;
06564          else                                zmin -= dzmin;
06565       }
06566    }
06567 
06568    TString opt = option;
06569    opt.ToLower();
06570    if (opt.Contains("scat=")) {
06571       char optscat[100];
06572       strlcpy(optscat,opt.Data(),100);
06573       char *oscat = strstr(optscat,"scat=");
06574       char *blank = strstr(oscat," "); if (blank) *blank = 0;
06575       sscanf(oscat+5,"%lg",&scale);
06576    }
06577    UInt_t seedsave = gRandom->GetSeed();
06578    gRandom->SetSeed();
06579    marker=0;
06580    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
06581       yk    = fYaxis->GetBinLowEdge(j);
06582       ystep = fYaxis->GetBinWidth(j);
06583       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
06584          Int_t bin  = j*(fXaxis->GetNbins()+2) + i;
06585          xk    = fXaxis->GetBinLowEdge(i);
06586          xstep = fXaxis->GetBinWidth(i);
06587          if (!IsInside(xk+0.5*xstep,yk+0.5*ystep)) continue;
06588          z     = fH->GetBinContent(bin);
06589          if (z < zmin) z = zmin;
06590          if (z > zmax) z = zmax;
06591          if (Hoption.Logz) {
06592             if (z > 0) z = TMath::Log10(z) - zmin;
06593          } else {
06594             z    -=  zmin;
06595          }
06596          if (z <= 0) continue;
06597          k = Int_t(z*scale);
06598          if (ltest) k++;
06599          if (k > 0) {
06600             for (Int_t loop=0; loop<k; loop++) {
06601                if (k+marker >= kNMAX) {
06602                   gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
06603                   marker=0;
06604                }
06605                fXbuf[marker] = (gRandom->Rndm(loop)*xstep) + xk;
06606                fYbuf[marker] = (gRandom->Rndm(loop)*ystep) + yk;
06607                if (Hoption.Logx){
06608                   if (fXbuf[marker] > 0) fXbuf[marker] = TMath::Log10(fXbuf[marker]);
06609                   else                   break;
06610                }
06611                if (Hoption.Logy){
06612                   if (fYbuf[marker] > 0) fYbuf[marker] = TMath::Log10(fYbuf[marker]);
06613                   else                  break;
06614                }
06615                if (fXbuf[marker] < gPad->GetUxmin()) break;
06616                if (fYbuf[marker] < gPad->GetUymin()) break;
06617                if (fXbuf[marker] > gPad->GetUxmax()) break;
06618                if (fYbuf[marker] > gPad->GetUymax()) break;
06619                marker++;
06620             }
06621          }
06622       }
06623    }
06624    if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
06625    gRandom->SetSeed(seedsave);
06626 
06627    if (Hoption.Zscale) PaintPalette();
06628 }
06629 
06630 
06631 //______________________________________________________________________________
06632 void THistPainter::PaintSpecialObjects(const TObject *obj, Option_t *option)
06633 {
06634    /* Begin_html
06635    Static function to paint special objects like vectors and matrices.
06636    This function is called via gROOT->ProcessLine to paint these objects
06637    without having a direct dependency of the graphics or histogramming
06638    system.
06639    End_html */
06640 
06641    if (!obj) return;
06642    Bool_t status = TH1::AddDirectoryStatus();
06643    TH1::AddDirectory(kFALSE);
06644 
06645    if (obj->InheritsFrom(TMatrixFBase::Class())) {
06646       // case TMatrixF
06647       TH2F *R__TMatrixFBase = new TH2F((TMatrixFBase &)*obj);
06648       R__TMatrixFBase->SetBit(kCanDelete);
06649       R__TMatrixFBase->Draw(option);
06650 
06651    } else if (obj->InheritsFrom(TMatrixDBase::Class())) {
06652       // case TMatrixD
06653       TH2D *R__TMatrixDBase = new TH2D((TMatrixDBase &)*obj);
06654       R__TMatrixDBase->SetBit(kCanDelete);
06655       R__TMatrixDBase->Draw(option);
06656 
06657    } else if (obj->InheritsFrom(TVectorF::Class())) {
06658       //case TVectorF
06659       TH1F *R__TVectorF = new TH1F((TVectorF &)*obj);
06660       R__TVectorF->SetBit(kCanDelete);
06661       R__TVectorF->Draw(option);
06662 
06663    } else if (obj->InheritsFrom(TVectorD::Class())) {
06664       //case TVectorD
06665       TH1D *R__TVectorD = new TH1D((TVectorD &)*obj);
06666       R__TVectorD->SetBit(kCanDelete);
06667       R__TVectorD->Draw(option);
06668    }
06669 
06670    TH1::AddDirectory(status);
06671 }
06672 
06673 
06674 //______________________________________________________________________________
06675 void THistPainter::PaintStat(Int_t dostat, TF1 *fit)
06676 {
06677    /* Begin_html
06678    <a href="#HP07">Draw the statistics box for 1D and profile histograms.</a>
06679    End_html */
06680 
06681    static char t[100];
06682    Int_t dofit;
06683    TPaveStats *stats  = 0;
06684    TIter next(fFunctions);
06685    TObject *obj;
06686    while ((obj = next())) {
06687       if (obj->InheritsFrom(TPaveStats::Class())) {
06688          stats = (TPaveStats*)obj;
06689          break;
06690       }
06691    }
06692 
06693    if (stats && dostat) {
06694       dofit  = stats->GetOptFit();
06695       dostat = stats->GetOptStat();
06696    } else {
06697       dofit  = gStyle->GetOptFit();
06698    }
06699    if (!dofit) fit = 0;
06700    if (dofit  == 1) dofit  =  111;
06701    if (dostat == 1) dostat = 1111;
06702    Int_t print_name    = dostat%10;
06703    Int_t print_entries = (dostat/10)%10;
06704    Int_t print_mean    = (dostat/100)%10;
06705    Int_t print_rms     = (dostat/1000)%10;
06706    Int_t print_under   = (dostat/10000)%10;
06707    Int_t print_over    = (dostat/100000)%10;
06708    Int_t print_integral= (dostat/1000000)%10;
06709    Int_t print_skew    = (dostat/10000000)%10;
06710    Int_t print_kurt    = (dostat/100000000)%10;
06711    Int_t nlines = print_name + print_entries + print_mean + print_rms +
06712                   print_under + print_over + print_integral +
06713                   print_skew + print_kurt;
06714    Int_t print_fval    = dofit%10;
06715    Int_t print_ferrors = (dofit/10)%10;
06716    Int_t print_fchi2   = (dofit/100)%10;
06717    Int_t print_fprob   = (dofit/1000)%10;
06718    Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
06719    if (fit) {
06720       if (print_fval < 2) nlinesf += fit->GetNumberFreeParameters();
06721       else                nlinesf += fit->GetNpar();
06722    }
06723    if (fH->InheritsFrom(TProfile::Class())) nlinesf += print_mean + print_rms;
06724 
06725    // Pavetext with statistics
06726    Bool_t done = kFALSE;
06727    if (!dostat && !fit) {
06728       if (stats) { fFunctions->Remove(stats); delete stats;}
06729       return;
06730    }
06731    Double_t  statw  = gStyle->GetStatW();
06732    if (fit) statw   = 1.8*gStyle->GetStatW();
06733    Double_t  stath  = (nlines+nlinesf)*gStyle->GetStatFontSize();
06734    if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
06735       stath = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
06736    }
06737    if (stats) {
06738       stats->Clear();
06739       done = kTRUE;
06740    } else {
06741       stats  = new TPaveStats(
06742                gStyle->GetStatX()-statw,
06743                gStyle->GetStatY()-stath,
06744                gStyle->GetStatX(),
06745                gStyle->GetStatY(),"brNDC");
06746 
06747       stats->SetParent(fH);
06748       stats->SetOptFit(dofit);
06749       stats->SetOptStat(dostat);
06750       stats->SetFillColor(gStyle->GetStatColor());
06751       stats->SetFillStyle(gStyle->GetStatStyle());
06752       stats->SetBorderSize(gStyle->GetStatBorderSize());
06753       stats->SetTextFont(gStyle->GetStatFont());
06754       if (gStyle->GetStatFont()%10 > 2)
06755          stats->SetTextSize(gStyle->GetStatFontSize());
06756       stats->SetFitFormat(gStyle->GetFitFormat());
06757       stats->SetStatFormat(gStyle->GetStatFormat());
06758       stats->SetName("stats");
06759 
06760       stats->SetTextColor(gStyle->GetStatTextColor());
06761       stats->SetTextAlign(12);
06762       stats->SetBit(kCanDelete);
06763       stats->SetBit(kMustCleanup);
06764    }
06765    if (print_name)  stats->AddText(fH->GetName());
06766    if (print_entries) {
06767       if (fH->GetEntries() < 1e7) snprintf(t,100,"%s = %-7d",gStringEntries.Data(),Int_t(fH->GetEntries()+0.5));
06768       else                        snprintf(t,100,"%s = %14.7g",gStringEntries.Data(),Float_t(fH->GetEntries()));
06769       stats->AddText(t);
06770    }
06771    char textstats[50];
06772    if (print_mean) {
06773       if (print_mean == 1) {
06774          snprintf(textstats,50,"%s  = %s%s",gStringMean.Data(),"%",stats->GetStatFormat());
06775          snprintf(t,100,textstats,fH->GetMean(1));
06776       } else {
06777          snprintf(textstats,50,"%s  = %s%s #pm %s%s",gStringMean.Data(),"%",stats->GetStatFormat()
06778                                                   ,"%",stats->GetStatFormat());
06779          snprintf(t,100,textstats,fH->GetMean(1),fH->GetMeanError(1));
06780       }
06781       stats->AddText(t);
06782       if (fH->InheritsFrom(TProfile::Class())) {
06783          if (print_mean == 1) {
06784             snprintf(textstats,50,"%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
06785             snprintf(t,100,textstats,fH->GetMean(2));
06786          } else {
06787             snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
06788                                                       ,"%",stats->GetStatFormat());
06789             snprintf(t,100,textstats,fH->GetMean(2),fH->GetMeanError(2));
06790          }
06791          stats->AddText(t);
06792       }
06793    }
06794    if (print_rms) {
06795       if (print_rms == 1) {
06796          snprintf(textstats,50,"%s   = %s%s",gStringRMS.Data(),"%",stats->GetStatFormat());
06797          snprintf(t,100,textstats,fH->GetRMS(1));
06798       } else {
06799          snprintf(textstats,50,"%s   = %s%s #pm %s%s",gStringRMS.Data(),"%",stats->GetStatFormat()
06800                                                   ,"%",stats->GetStatFormat());
06801          snprintf(t,100,textstats,fH->GetRMS(1),fH->GetRMSError(1));
06802       }
06803       stats->AddText(t);
06804       if(fH->InheritsFrom(TProfile::Class())) {
06805          if (print_rms == 1) {
06806             snprintf(textstats,50,"%s = %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat());
06807             snprintf(t,100,textstats,fH->GetRMS(2));
06808          } else {
06809             snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat()
06810                                                      ,"%",stats->GetStatFormat());
06811             snprintf(t,100,textstats,fH->GetRMS(2),fH->GetRMSError(2));
06812          }
06813          stats->AddText(t);
06814       }
06815    }
06816    if (print_under) {
06817       snprintf(textstats,50,"%s = %s%s",gStringUnderflow.Data(),"%",stats->GetStatFormat());
06818       snprintf(t,100,textstats,fH->GetBinContent(0));
06819       stats->AddText(t);
06820    }
06821    if (print_over) {
06822       snprintf(textstats,50,"%s  = %s%s",gStringOverflow.Data(),"%",stats->GetStatFormat());
06823       snprintf(t,100,textstats,fH->GetBinContent(fXaxis->GetNbins()+1));
06824       stats->AddText(t);
06825    }
06826    if (print_integral) {
06827       snprintf(textstats,50,"%s = %s%s",gStringIntegral.Data(),"%",stats->GetStatFormat());
06828       snprintf(t,100,textstats,fH->Integral());
06829       stats->AddText(t);
06830    }
06831    if (print_skew) {
06832       if (print_skew == 1) {
06833          snprintf(textstats,50,"%s = %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat());
06834          snprintf(t,100,textstats,fH->GetSkewness(1));
06835       } else {
06836          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewness.Data(),"%",stats->GetStatFormat()
06837                                                      ,"%",stats->GetStatFormat());
06838          snprintf(t,100,textstats,fH->GetSkewness(1),fH->GetSkewness(11));
06839       }
06840       stats->AddText(t);
06841    }
06842    if (print_kurt) {
06843       if (print_kurt == 1) {
06844          snprintf(textstats,50,"%s = %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat());
06845          snprintf(t,100,textstats,fH->GetKurtosis(1));
06846       } else {
06847          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosis.Data(),"%",stats->GetStatFormat()
06848                                                      ,"%",stats->GetStatFormat());
06849          snprintf(t,100,textstats,fH->GetKurtosis(1),fH->GetKurtosis(11));
06850       }
06851       stats->AddText(t);
06852    }
06853 
06854    // Draw Fit parameters
06855    if (fit) {
06856       Int_t ndf = fit->GetNDF();
06857       snprintf(textstats,50,"#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
06858       snprintf(t,100,textstats,(Float_t)fit->GetChisquare());
06859       if (print_fchi2) stats->AddText(t);
06860       if (print_fprob) {
06861          snprintf(textstats,50,"Prob  = %s%s","%",stats->GetFitFormat());
06862          snprintf(t,100,textstats,(Float_t)TMath::Prob(fit->GetChisquare(),ndf));
06863          stats->AddText(t);
06864       }
06865       if (print_fval || print_ferrors) {
06866          Double_t parmin,parmax;
06867          for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
06868             fit->GetParLimits(ipar,parmin,parmax);
06869             if (print_fval < 2 && parmin*parmax != 0 && parmin >= parmax) continue;
06870             if (print_ferrors) {
06871                snprintf(textstats,50,"%-8s = %s%s #pm %s ",fit->GetParName(ipar), "%",stats->GetFitFormat(),
06872                        GetBestFormat(fit->GetParameter(ipar), fit->GetParError(ipar), stats->GetFitFormat()));
06873                snprintf(t,100,textstats,(Float_t)fit->GetParameter(ipar)
06874                                ,(Float_t)fit->GetParError(ipar));
06875             } else {
06876                snprintf(textstats,50,"%-8s = %s%s ",fit->GetParName(ipar),"%",stats->GetFitFormat());
06877                snprintf(t,100,textstats,(Float_t)fit->GetParameter(ipar));
06878             }
06879             t[63] = 0;
06880             stats->AddText(t);
06881          }
06882       }
06883    }
06884 
06885    if (!done) fFunctions->Add(stats);
06886    stats->Paint();
06887 }
06888 
06889 
06890 //______________________________________________________________________________
06891 void THistPainter::PaintStat2(Int_t dostat, TF1 *fit)
06892 {
06893    /* Begin_html
06894    <a href="#HP07">Draw the statistics box for 2D histograms.</a>
06895    End_html */
06896 
06897    if (fH->GetDimension() != 2) return;
06898    TH2 *h2 = (TH2*)fH;
06899 
06900    static char t[100];
06901    Int_t dofit;
06902    TPaveStats *stats  = 0;
06903    TIter next(fFunctions);
06904    TObject *obj;
06905    while ((obj = next())) {
06906       if (obj->InheritsFrom(TPaveStats::Class())) {
06907          stats = (TPaveStats*)obj;
06908          break;
06909       }
06910    }
06911    if (stats && dostat) {
06912       dofit  = stats->GetOptFit();
06913       dostat = stats->GetOptStat();
06914    } else {
06915       dofit  = gStyle->GetOptFit();
06916    }
06917    if (dostat == 1) dostat = 1111;
06918    Int_t print_name    = dostat%10;
06919    Int_t print_entries = (dostat/10)%10;
06920    Int_t print_mean    = (dostat/100)%10;
06921    Int_t print_rms     = (dostat/1000)%10;
06922    Int_t print_under   = (dostat/10000)%10;
06923    Int_t print_over    = (dostat/100000)%10;
06924    Int_t print_integral= (dostat/1000000)%10;
06925    Int_t print_skew    = (dostat/10000000)%10;
06926    Int_t print_kurt    = (dostat/100000000)%10;
06927    Int_t nlines = print_name + print_entries + 2*print_mean + 2*print_rms + print_integral;
06928    if (print_under || print_over) nlines += 3;
06929 
06930    // Pavetext with statistics
06931    if (!gStyle->GetOptFit()) fit = 0;
06932    Bool_t done = kFALSE;
06933    if (!dostat && !fit) {
06934       if (stats) delete stats;
06935       return;
06936    }
06937    Double_t  statw  = gStyle->GetStatW();
06938    if (fit) statw   = 1.8*gStyle->GetStatW();
06939    Double_t  stath  = nlines*gStyle->GetStatFontSize();
06940    if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
06941       stath = 0.25*nlines*gStyle->GetStatH();
06942    }
06943    if (fit) stath += gStyle->GetStatH();
06944    if (stats) {
06945       stats->Clear();
06946       done = kTRUE;
06947    } else {
06948       stats  = new TPaveStats(
06949                gStyle->GetStatX()-statw,
06950                gStyle->GetStatY()-stath,
06951                gStyle->GetStatX(),
06952                gStyle->GetStatY(),"brNDC");
06953 
06954       stats->SetParent(fH);
06955       stats->SetOptFit(dofit);
06956       stats->SetOptStat(dostat);
06957       stats->SetFillColor(gStyle->GetStatColor());
06958       stats->SetFillStyle(gStyle->GetStatStyle());
06959       stats->SetBorderSize(gStyle->GetStatBorderSize());
06960       stats->SetName("stats");
06961 
06962       stats->SetTextColor(gStyle->GetStatTextColor());
06963       stats->SetTextAlign(12);
06964       stats->SetTextFont(gStyle->GetStatFont());
06965       if (gStyle->GetStatFont()%10 > 2)
06966          stats->SetTextSize(gStyle->GetStatFontSize());
06967       stats->SetFitFormat(gStyle->GetFitFormat());
06968       stats->SetStatFormat(gStyle->GetStatFormat());
06969       stats->SetBit(kCanDelete);
06970       stats->SetBit(kMustCleanup);
06971    }
06972    if (print_name)  stats->AddText(h2->GetName());
06973    if (print_entries) {
06974       if (h2->GetEntries() < 1e7) snprintf(t,100,"%s = %-7d",gStringEntries.Data(),Int_t(h2->GetEntries()+0.5));
06975       else                        snprintf(t,100,"%s = %14.7g",gStringEntries.Data(),Float_t(h2->GetEntries()));
06976       stats->AddText(t);
06977    }
06978    char textstats[50];
06979    if (print_mean) {
06980       if (print_mean == 1) {
06981          snprintf(textstats,50,"%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
06982          snprintf(t,50,textstats,h2->GetMean(1));
06983          stats->AddText(t);
06984          snprintf(textstats,50,"%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
06985          snprintf(t,100,textstats,h2->GetMean(2));
06986          stats->AddText(t);
06987       } else {
06988          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
06989                                                    ,"%",stats->GetStatFormat());
06990          snprintf(t,100,textstats,h2->GetMean(1),h2->GetMeanError(1));
06991          stats->AddText(t);
06992          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
06993                                                    ,"%",stats->GetStatFormat());
06994          snprintf(t,100,textstats,h2->GetMean(2),h2->GetMeanError(2));
06995          stats->AddText(t);
06996       }
06997    }
06998    if (print_rms) {
06999       if (print_rms == 1) {
07000          snprintf(textstats,50,"%s = %s%s",gStringRMSX.Data(),"%",stats->GetStatFormat());
07001          snprintf(t,100,textstats,h2->GetRMS(1));
07002          stats->AddText(t);
07003          snprintf(textstats,50,"%s = %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat());
07004          snprintf(t,100,textstats,h2->GetRMS(2));
07005          stats->AddText(t);
07006       } else {
07007          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringRMSX.Data(),"%",stats->GetStatFormat()
07008                                                   ,"%",stats->GetStatFormat());
07009          snprintf(t,100,textstats,h2->GetRMS(1),h2->GetRMSError(1));
07010          stats->AddText(t);
07011          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat()
07012                                                   ,"%",stats->GetStatFormat());
07013          snprintf(t,100,textstats,h2->GetRMS(2),h2->GetRMSError(2));
07014          stats->AddText(t);
07015       }
07016    }
07017    if (print_integral) {
07018       snprintf(t,100,"%s  = %6.4g",gStringIntegral.Data(),h2->Integral());
07019       stats->AddText(t);
07020    }
07021    if (print_skew) {
07022       if (print_skew == 1) {
07023          snprintf(textstats,50,"%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
07024          snprintf(t,100,textstats,h2->GetSkewness(1));
07025          stats->AddText(t);
07026          snprintf(textstats,50,"%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
07027          snprintf(t,100,textstats,h2->GetSkewness(2));
07028          stats->AddText(t);
07029       } else {
07030          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
07031                                                        ,"%",stats->GetStatFormat());
07032          snprintf(t,100,textstats,h2->GetSkewness(1),h2->GetSkewness(11));
07033          stats->AddText(t);
07034          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
07035                                                        ,"%",stats->GetStatFormat());
07036          snprintf(t,100,textstats,h2->GetSkewness(2),h2->GetSkewness(12));
07037          stats->AddText(t);
07038       }
07039    }
07040    if (print_kurt) {
07041       if (print_kurt == 1) {
07042          snprintf(textstats,50,"%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
07043          snprintf(t,100,textstats,h2->GetKurtosis(1));
07044          stats->AddText(t);
07045          snprintf(textstats,50,"%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
07046          snprintf(t,100,textstats,h2->GetKurtosis(2));
07047          stats->AddText(t);
07048       } else {
07049          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
07050                                                        ,"%",stats->GetStatFormat());
07051          snprintf(t,100,textstats,h2->GetKurtosis(1),h2->GetKurtosis(11));
07052          stats->AddText(t);
07053          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
07054                                                        ,"%",stats->GetStatFormat());
07055          snprintf(t,100,textstats,h2->GetKurtosis(2),h2->GetKurtosis(12));
07056          stats->AddText(t);
07057       }
07058    }
07059    if (print_under || print_over) {
07060       //get 3*3 under/overflows for 2d hist
07061       Double_t unov[9];
07062 
07063       unov[0] = h2->Integral(0,h2->GetXaxis()->GetFirst()-1,h2->GetYaxis()->GetLast()+1,h2->GetYaxis()->GetNbins()+1);
07064       unov[1] = h2->Integral(h2->GetXaxis()->GetFirst(),h2->GetXaxis()->GetLast(),h2->GetYaxis()->GetLast()+1,h2->GetYaxis()->GetNbins()+1);
07065       unov[2] = h2->Integral(h2->GetXaxis()->GetLast()+1,h2->GetXaxis()->GetNbins()+1,h2->GetYaxis()->GetLast()+1,h2->GetYaxis()->GetNbins()+1);
07066       unov[3] = h2->Integral(0,h2->GetXaxis()->GetFirst()-1,h2->GetYaxis()->GetFirst(),h2->GetYaxis()->GetLast());
07067       unov[4] = h2->Integral(h2->GetXaxis()->GetFirst(),h2->GetXaxis()->GetLast(),h2->GetYaxis()->GetFirst(),h2->GetYaxis()->GetLast());
07068       unov[5] = h2->Integral(h2->GetXaxis()->GetLast()+1,h2->GetXaxis()->GetNbins()+1,h2->GetYaxis()->GetFirst(),h2->GetYaxis()->GetLast());
07069       unov[6] = h2->Integral(0,h2->GetXaxis()->GetFirst()-1,0,h2->GetYaxis()->GetFirst()-1);
07070       unov[7] = h2->Integral(h2->GetXaxis()->GetFirst(),h2->GetXaxis()->GetLast(),0,h2->GetYaxis()->GetFirst()-1);
07071       unov[8] = h2->Integral(h2->GetXaxis()->GetLast()+1,h2->GetXaxis()->GetNbins()+1,0,h2->GetYaxis()->GetFirst()-1);
07072 
07073       snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[0], (Int_t)unov[1], (Int_t)unov[2]);
07074       stats->AddText(t);
07075       if (h2->GetEntries() < 1e7)
07076          snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[3], (Int_t)unov[4], (Int_t)unov[5]);
07077       else
07078          snprintf(t, 100," %7d|%14.7g|%7d\n", (Int_t)unov[3], (Float_t)unov[4], (Int_t)unov[5]);
07079       stats->AddText(t);
07080       snprintf(t, 100," %7d|%7d|%7d\n", (Int_t)unov[6], (Int_t)unov[7], (Int_t)unov[8]);
07081       stats->AddText(t);
07082    }
07083 
07084    // Draw Fit parameters
07085    if (fit) {
07086       Int_t ndf = fit->GetNDF();
07087       snprintf(t,100,"#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
07088       stats->AddText(t);
07089       for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
07090          snprintf(t,100,"%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
07091                                    ,(Float_t)fit->GetParameter(ipar)
07092                                    ,(Float_t)fit->GetParError(ipar));
07093          t[32] = 0;
07094          stats->AddText(t);
07095       }
07096    }
07097 
07098    if (!done) fFunctions->Add(stats);
07099    stats->Paint();
07100 }
07101 
07102 
07103 //______________________________________________________________________________
07104 void THistPainter::PaintStat3(Int_t dostat, TF1 *fit)
07105 {
07106    /* Begin_html
07107    <a href="#HP07">Draw the statistics box for 3D histograms.</a>
07108    End_html */
07109 
07110    if (fH->GetDimension() != 3) return;
07111    TH3 *h3 = (TH3*)fH;
07112 
07113    static char t[100];
07114    Int_t dofit;
07115    TPaveStats *stats  = 0;
07116    TIter next(fFunctions);
07117    TObject *obj;
07118    while ((obj = next())) {
07119       if (obj->InheritsFrom(TPaveStats::Class())) {
07120          stats = (TPaveStats*)obj;
07121          break;
07122       }
07123    }
07124    if (stats && dostat) {
07125       dofit  = stats->GetOptFit();
07126       dostat = stats->GetOptStat();
07127    } else {
07128       dofit  = gStyle->GetOptFit();
07129    }
07130    if (dostat == 1) dostat = 1111;
07131    Int_t print_name    = dostat%10;
07132    Int_t print_entries = (dostat/10)%10;
07133    Int_t print_mean    = (dostat/100)%10;
07134    Int_t print_rms     = (dostat/1000)%10;
07135    Int_t print_under   = (dostat/10000)%10;
07136    Int_t print_over    = (dostat/100000)%10;
07137    Int_t print_integral= (dostat/1000000)%10;
07138    Int_t print_skew    = (dostat/10000000)%10;
07139    Int_t print_kurt    = (dostat/100000000)%10;
07140    Int_t nlines = print_name + print_entries + 3*print_mean + 3*print_rms + print_integral;
07141    if (print_under || print_over) nlines += 3;
07142 
07143    // Pavetext with statistics
07144    if (!gStyle->GetOptFit()) fit = 0;
07145    Bool_t done = kFALSE;
07146    if (!dostat && !fit) {
07147       if (stats) delete stats;
07148       return;
07149    }
07150    Double_t  statw  = gStyle->GetStatW();
07151    if (fit) statw   = 1.8*gStyle->GetStatW();
07152    Double_t  stath  = nlines*gStyle->GetStatFontSize();
07153    if (stath <= 0 || 3 == (gStyle->GetStatFont()%10)) {
07154       stath = 0.25*nlines*gStyle->GetStatH();
07155    }
07156    if (fit) stath += gStyle->GetStatH();
07157    if (stats) {
07158       stats->Clear();
07159       done = kTRUE;
07160    } else {
07161       stats  = new TPaveStats(
07162                gStyle->GetStatX()-statw,
07163                gStyle->GetStatY()-stath,
07164                gStyle->GetStatX(),
07165                gStyle->GetStatY(),"brNDC");
07166 
07167       stats->SetParent(fH);
07168       stats->SetOptFit(dofit);
07169       stats->SetOptStat(dostat);
07170       stats->SetFillColor(gStyle->GetStatColor());
07171       stats->SetFillStyle(gStyle->GetStatStyle());
07172       stats->SetBorderSize(gStyle->GetStatBorderSize());
07173       stats->SetName("stats");
07174 
07175       stats->SetTextColor(gStyle->GetStatTextColor());
07176       stats->SetTextAlign(12);
07177       stats->SetTextFont(gStyle->GetStatFont());
07178       stats->SetFitFormat(gStyle->GetFitFormat());
07179       stats->SetStatFormat(gStyle->GetStatFormat());
07180       stats->SetBit(kCanDelete);
07181       stats->SetBit(kMustCleanup);
07182    }
07183    if (print_name)  stats->AddText(h3->GetName());
07184    if (print_entries) {
07185       if (h3->GetEntries() < 1e7) snprintf(t,100,"%s = %-7d",gStringEntries.Data(),Int_t(h3->GetEntries()+0.5));
07186       else                        snprintf(t,100,"%s = %14.7g",gStringEntries.Data(),Float_t(h3->GetEntries()+0.5));
07187       stats->AddText(t);
07188    }
07189    char textstats[50];
07190    if (print_mean) {
07191       if (print_mean == 1) {
07192          snprintf(textstats,50,"%s = %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat());
07193          snprintf(t,100,textstats,h3->GetMean(1));
07194          stats->AddText(t);
07195          snprintf(textstats,50,"%s = %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat());
07196          snprintf(t,100,textstats,h3->GetMean(2));
07197          stats->AddText(t);
07198          snprintf(textstats,50,"%s = %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat());
07199          snprintf(t,100,textstats,h3->GetMean(3));
07200          stats->AddText(t);
07201       } else {
07202          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanX.Data(),"%",stats->GetStatFormat()
07203                                                    ,"%",stats->GetStatFormat());
07204          snprintf(t,100,textstats,h3->GetMean(1),h3->GetMeanError(1));
07205          stats->AddText(t);
07206          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanY.Data(),"%",stats->GetStatFormat()
07207                                                    ,"%",stats->GetStatFormat());
07208          snprintf(t,100,textstats,h3->GetMean(2),h3->GetMeanError(2));
07209          stats->AddText(t);
07210          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringMeanZ.Data(),"%",stats->GetStatFormat()
07211                                                    ,"%",stats->GetStatFormat());
07212          snprintf(t,100,textstats,h3->GetMean(3),h3->GetMeanError(3));
07213          stats->AddText(t);
07214       }
07215    }
07216    if (print_rms) {
07217       if (print_rms == 1) {
07218          snprintf(textstats,50,"%s = %s%s",gStringRMSX.Data(),"%",stats->GetStatFormat());
07219          snprintf(t,100,textstats,h3->GetRMS(1));
07220          stats->AddText(t);
07221          snprintf(textstats,50,"%s = %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat());
07222          snprintf(t,100,textstats,h3->GetRMS(2));
07223          stats->AddText(t);
07224          snprintf(textstats,50,"%s = %s%s",gStringRMSZ.Data(),"%",stats->GetStatFormat());
07225          snprintf(t,100,textstats,h3->GetRMS(3));
07226          stats->AddText(t);
07227       } else {
07228          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringRMSX.Data(),"%",stats->GetStatFormat()
07229                                                   ,"%",stats->GetStatFormat());
07230          snprintf(t,100,textstats,h3->GetRMS(1),h3->GetRMSError(1));
07231          stats->AddText(t);
07232          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringRMSY.Data(),"%",stats->GetStatFormat()
07233                                                   ,"%",stats->GetStatFormat());
07234          snprintf(t,100,textstats,h3->GetRMS(2),h3->GetRMSError(2));
07235          stats->AddText(t);
07236          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringRMSZ.Data(),"%",stats->GetStatFormat()
07237                                                   ,"%",stats->GetStatFormat());
07238          snprintf(t,100,textstats,h3->GetRMS(3),h3->GetRMSError(3));
07239          stats->AddText(t);
07240       }
07241    }
07242    if (print_integral) {
07243       snprintf(t,100,"%s  = %6.4g",gStringIntegral.Data(),h3->Integral());
07244       stats->AddText(t);
07245    }
07246    if (print_skew) {
07247       if (print_skew == 1) {
07248          snprintf(textstats,50,"%s = %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat());
07249          snprintf(t,100,textstats,h3->GetSkewness(1));
07250          stats->AddText(t);
07251          snprintf(textstats,50,"%s = %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat());
07252          snprintf(t,100,textstats,h3->GetSkewness(2));
07253          stats->AddText(t);
07254          snprintf(textstats,50,"%s = %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat());
07255          snprintf(t,100,textstats,h3->GetSkewness(3));
07256          stats->AddText(t);
07257       } else {
07258          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessX.Data(),"%",stats->GetStatFormat()
07259                                                        ,"%",stats->GetStatFormat());
07260          snprintf(t,100,textstats,h3->GetSkewness(1),h3->GetSkewness(11));
07261          stats->AddText(t);
07262          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessY.Data(),"%",stats->GetStatFormat()
07263                                                        ,"%",stats->GetStatFormat());
07264          snprintf(t,100,textstats,h3->GetSkewness(2),h3->GetSkewness(12));
07265          stats->AddText(t);
07266          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringSkewnessZ.Data(),"%",stats->GetStatFormat()
07267                                                        ,"%",stats->GetStatFormat());
07268          snprintf(t,100,textstats,h3->GetSkewness(3),h3->GetSkewness(13));
07269          stats->AddText(t);
07270       }
07271    }
07272    if (print_kurt) {
07273       if (print_kurt == 1) {
07274          snprintf(textstats,50,"%s = %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat());
07275          snprintf(t,100,textstats,h3->GetKurtosis(1));
07276          stats->AddText(t);
07277          snprintf(textstats,50,"%s = %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat());
07278          snprintf(t,100,textstats,h3->GetKurtosis(2));
07279          stats->AddText(t);
07280          snprintf(textstats,50,"%s = %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat());
07281          snprintf(t,100,textstats,h3->GetKurtosis(3));
07282          stats->AddText(t);
07283       } else {
07284          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisX.Data(),"%",stats->GetStatFormat()
07285                                                        ,"%",stats->GetStatFormat());
07286          snprintf(t,100,textstats,h3->GetKurtosis(1),h3->GetKurtosis(11));
07287          stats->AddText(t);
07288          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisY.Data(),"%",stats->GetStatFormat()
07289                                                        ,"%",stats->GetStatFormat());
07290          snprintf(t,100,textstats,h3->GetKurtosis(2),h3->GetKurtosis(12));
07291          stats->AddText(t);
07292          snprintf(textstats,50,"%s = %s%s #pm %s%s",gStringKurtosisZ.Data(),"%",stats->GetStatFormat()
07293                                                        ,"%",stats->GetStatFormat());
07294          snprintf(t,100,textstats,h3->GetKurtosis(3),h3->GetKurtosis(13));
07295          stats->AddText(t);
07296       }
07297    }
07298    if (print_under || print_over) {
07299       // no underflow - overflow printing for a 3D histogram
07300       // one would need a 3D table
07301 //       //get 3*3 under/overflows for 2d hist
07302 //       Double_t unov[9];
07303 
07304 //       unov[0] = h3->Integral(0,h3->GetXaxis()->GetFirst()-1,h3->GetYaxis()->GetLast()+1,h3->GetYaxis()->GetNbins()+1);
07305 //       unov[1] = h3->Integral(h3->GetXaxis()->GetFirst(),h3->GetXaxis()->GetLast(),h3->GetYaxis()->GetLast()+1,h3->GetYaxis()->GetNbins()+1);
07306 //       unov[2] = h3->Integral(h3->GetXaxis()->GetLast()+1,h3->GetXaxis()->GetNbins()+1,h3->GetYaxis()->GetLast()+1,h3->GetYaxis()->GetNbins()+1);
07307 //       unov[3] = h3->Integral(0,h3->GetXaxis()->GetFirst()-1,h3->GetYaxis()->GetFirst(),h3->GetYaxis()->GetLast());
07308 //       unov[4] = h3->Integral(h3->GetXaxis()->GetFirst(),h3->GetXaxis()->GetLast(),h3->GetYaxis()->GetFirst(),h3->GetYaxis()->GetLast());
07309 //       unov[5] = h3->Integral(h3->GetXaxis()->GetLast()+1,h3->GetXaxis()->GetNbins()+1,h3->GetYaxis()->GetFirst(),h3->GetYaxis()->GetLast());
07310 //       unov[6] = h3->Integral(0,h3->GetXaxis()->GetFirst()-1,0,h3->GetYaxis()->GetFirst()-1);
07311 //       unov[7] = h3->Integral(h3->GetXaxis()->GetFirst(),h3->GetXaxis()->GetLast(),0,h3->GetYaxis()->GetFirst()-1);
07312 //       unov[8] = h3->Integral(h3->GetXaxis()->GetLast()+1,h3->GetXaxis()->GetNbins()+1,0,h3->GetYaxis()->GetFirst()-1);
07313 
07314 //       sprintf(t, " %7d|%7d|%7d\n", (Int_t)unov[0], (Int_t)unov[1], (Int_t)unov[2]);
07315 //       stats->AddText(t);
07316 //       if (h3->GetEntries() < 1e7)
07317 //          sprintf(t, " %7d|%7d|%7d\n", (Int_t)unov[3], (Int_t)unov[4], (Int_t)unov[5]);
07318 //       else
07319 //          sprintf(t, " %7d|%14.7g|%7d\n", (Int_t)unov[3], (Float_t)unov[4], (Int_t)unov[5]);
07320 //       stats->AddText(t);
07321 //       sprintf(t, " %7d|%7d|%7d\n", (Int_t)unov[6], (Int_t)unov[7], (Int_t)unov[8]);
07322 //       stats->AddText(t);
07323    }
07324 
07325    // Draw Fit parameters
07326    if (fit) {
07327       Int_t ndf = fit->GetNDF();
07328       snprintf(t,100,"#chi^{2} / ndf = %6.4g / %d",(Float_t)fit->GetChisquare(),ndf);
07329       stats->AddText(t);
07330       for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
07331          snprintf(t,100,"%-8s = %5.4g #pm %5.4g ",fit->GetParName(ipar)
07332                                    ,(Float_t)fit->GetParameter(ipar)
07333                                    ,(Float_t)fit->GetParError(ipar));
07334          t[32] = 0;
07335          stats->AddText(t);
07336       }
07337    }
07338 
07339    if (!done) fFunctions->Add(stats);
07340    stats->Paint();
07341 }
07342 
07343 
07344 //______________________________________________________________________________
07345 void THistPainter::PaintSurface(Option_t *)
07346 {
07347    /* Begin_html
07348    <a href="#HP18">Control function to draw a 2D histogram as a surface plot.</a>
07349    End_html */
07350 
07351    const Double_t ydiff = 1;
07352    const Double_t yligh1 = 10;
07353    const Double_t qa = 0.15;
07354    const Double_t qd = 0.15;
07355    const Double_t qs = 0.8;
07356    Double_t fmin, fmax;
07357    Int_t raster = 0;
07358    Int_t irep   = 0;
07359 
07360    if (Hparam.zmin == 0 && Hparam.zmax == 0) {Hparam.zmin = -1; Hparam.zmax = 1;}
07361    Int_t   nx      = Hparam.xlast - Hparam.xfirst;
07362    Int_t   ny      = Hparam.ylast - Hparam.yfirst;
07363    Double_t zmin   = Hparam.zmin;
07364    Double_t zmax   = Hparam.zmax;
07365    Double_t xlab1  = Hparam.xmin;
07366    Double_t xlab2  = Hparam.xmax;
07367    Double_t ylab1  = Hparam.ymin;
07368    Double_t ylab2  = Hparam.ymax;
07369    Double_t dangle = 10*3.141592/180; //Delta angle for Rapidity option
07370    Double_t deltaz = TMath::Abs(zmin);
07371    if (deltaz == 0) deltaz = 1;
07372    if (zmin >= zmax) {
07373       zmin -= 0.5*deltaz;
07374       zmax += 0.5*deltaz;
07375    }
07376    Double_t z1c = zmin;
07377    Double_t z2c = zmin + (zmax-zmin)*(1+gStyle->GetHistTopMargin());
07378    //     Compute the lego limits and instantiate a lego object
07379    fXbuf[0] = -1;
07380    fYbuf[0] =  1;
07381    fXbuf[1] = -1;
07382    fYbuf[1] =  1;
07383    if (Hoption.System >= kPOLAR && (Hoption.Surf == 1 || Hoption.Surf == 13)) raster = 1;
07384    if (Hoption.System == kPOLAR) {
07385       fXbuf[2] = z1c;
07386       fYbuf[2] = z2c;
07387    } else if (Hoption.System == kCYLINDRICAL) {
07388       if (Hoption.Logy) {
07389          if (ylab1 > 0) fXbuf[2] = TMath::Log10(ylab1);
07390          else           fXbuf[2] = 0;
07391          if (ylab2 > 0) fYbuf[2] = TMath::Log10(ylab2);
07392          else           fYbuf[2] = 0;
07393       } else {
07394          fXbuf[2] = ylab1;
07395          fYbuf[2] = ylab2;
07396       }
07397       z1c = 0; z2c = 1;
07398    } else if (Hoption.System == kSPHERICAL) {
07399       fXbuf[2] = -1;
07400       fYbuf[2] =  1;
07401       z1c = 0; z2c = 1;
07402    } else if (Hoption.System == kRAPIDITY) {
07403       fXbuf[2] = -1/TMath::Tan(dangle);
07404       fYbuf[2] =  1/TMath::Tan(dangle);
07405    } else {
07406       fXbuf[0] = xlab1;
07407       fYbuf[0] = xlab2;
07408       fXbuf[1] = ylab1;
07409       fYbuf[1] = ylab2;
07410       fXbuf[2] = z1c;
07411       fYbuf[2] = z2c;
07412    }
07413 
07414    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf, Hoption.System);
07415    fLego->SetLineColor(fH->GetLineColor());
07416    fLego->SetFillColor(fH->GetFillColor());
07417 
07418    //          Create axis object
07419 
07420    TGaxis *axis = new TGaxis();
07421 
07422    //                  Initialize the levels on the Z axis
07423    Int_t ndiv   = fH->GetContour();
07424    if (ndiv == 0 ) {
07425       ndiv = gStyle->GetNumberContours();
07426       fH->SetContour(ndiv);
07427    }
07428    Int_t ndivz  = TMath::Abs(ndiv);
07429    if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
07430 
07431    if (Hoption.Surf == 13 || Hoption.Surf == 15) fLego->SetMesh(3);
07432    if (Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) fLego->SetMesh(0);
07433 
07434    //     Close the surface in case of non cartesian coordinates.
07435 
07436    if (Hoption.System != kCARTESIAN) {nx++; ny++;}
07437 
07438    //     Now ready to draw the surface plot
07439 
07440    TView *view = gPad->GetView();
07441    if (!view) {
07442       Error("PaintSurface", "no TView in current pad");
07443       return;
07444    }
07445 
07446    Double_t thedeg =  90 - gPad->GetTheta();
07447    Double_t phideg = -90 - gPad->GetPhi();
07448    Double_t psideg = view->GetPsi();
07449    view->SetView(phideg, thedeg, psideg, irep);
07450 
07451    //     Set color/style for back box
07452    if (Hoption.Same) {
07453       fLego->SetFillStyle(0);
07454       fLego->SetFillColor(1);
07455    } else {
07456       fLego->SetFillStyle(gPad->GetFrameFillStyle());
07457       fLego->SetFillColor(gPad->GetFrameFillColor());
07458    }
07459    fLego->TAttFill::Modify();
07460 
07461    Int_t backcolor = gPad->GetFrameFillColor();
07462    if (Hoption.System != kCARTESIAN) backcolor = 0;
07463    view->PadRange(backcolor);
07464 
07465    fLego->SetFillStyle(fH->GetFillStyle());
07466    fLego->SetFillColor(fH->GetFillColor());
07467    fLego->TAttFill::Modify();
07468 
07469    //     Draw the filled contour on top
07470    Int_t icol1 = fH->GetFillColor();
07471 
07472    Int_t hoption35 = Hoption.Surf;
07473    if (Hoption.Surf == 13 || Hoption.Surf == 15) {
07474       DefineColorLevels(ndivz);
07475       Hoption.Surf = 23;
07476       fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
07477       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
07478       if (Hoption.System == kPOLAR)       fLego->SurfacePolar(1,nx,ny,"BF");
07479       if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
07480       if (Hoption.System == kSPHERICAL)   fLego->SurfaceSpherical(0,1,nx,ny,"BF");
07481       if (Hoption.System == kRAPIDITY )   fLego->SurfaceSpherical(1,1,nx,ny,"BF");
07482       if (Hoption.System == kCARTESIAN)   fLego->SurfaceCartesian(90,nx,ny,"BF");
07483       Hoption.Surf = hoption35;
07484       fLego->SetMesh(1);
07485    }
07486 
07487    if (raster) fLego->InitRaster(-1.1,-1.1,1.1,1.1,1000,800);
07488    else        fLego->InitMoveScreen(-1.1,1.1);
07489 
07490    if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 14 || Hoption.Surf == 17) {
07491       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
07492       fLego->SetLineColor(1);
07493       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
07494          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
07495          fLego->BackBox(90);
07496       }
07497    }
07498 
07499    //     Gouraud Shading surface
07500    if (Hoption.Surf == 14) {
07501    //    Set light sources
07502       fLego->LightSource(0, ydiff, 0,0,0,irep);
07503       fLego->LightSource(1, yligh1 ,1,1,1,irep);
07504       fLego->SurfaceProperty(qa, qd, qs, 1, irep);
07505       fmin = ydiff*qa;
07506       fmax = fmin + (yligh1+0.1)*(qd+qs);
07507       Int_t nbcol = 28;
07508       icol1 = 201;
07509       Double_t dcol = 0.5/Double_t(nbcol);
07510       TColor *colref = gROOT->GetColor(fH->GetFillColor());
07511       Float_t r,g,b,hue,light,satur;
07512       colref->GetRGB(r,g,b);
07513       TColor::RGBtoHLS(r,g,b,hue,light,satur);
07514       TColor *acol;
07515       for (Int_t col=0;col<nbcol;col++) {
07516          acol = gROOT->GetColor(col+icol1);
07517          TColor::HLStoRGB(hue,.4+col*dcol,satur,r,g,b);
07518          acol->SetRGB(r,g,b);
07519       }
07520       fLego->Spectrum(nbcol, fmin, fmax, icol1, 1, irep);
07521       fLego->SetSurfaceFunction(&TPainter3dAlgorithms::GouraudFunction);
07522       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
07523       if (Hoption.System == kPOLAR)       fLego->SurfacePolar(1,nx,ny,"BF");
07524       if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"BF");
07525       if (Hoption.System == kSPHERICAL)   fLego->SurfaceSpherical(0,1,nx,ny,"BF");
07526       if (Hoption.System == kRAPIDITY )   fLego->SurfaceSpherical(1,1,nx,ny,"BF");
07527       if (Hoption.System == kCARTESIAN)   fLego->SurfaceCartesian(90,nx,ny,"BF");
07528    } else if (Hoption.Surf == 15) {
07529    // The surface is not drawn in this case.
07530    } else {
07531    //     Draw the surface
07532       if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 16 || Hoption.Surf == 17) {
07533          DefineColorLevels(ndivz);
07534       } else {
07535          fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
07536       }
07537       fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
07538       if (Hoption.Surf ==  1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceRaster1);
07539       if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode2);
07540       if (Hoption.System == kPOLAR) {
07541          if (Hoption.Surf ==  1 || Hoption.Surf == 13) fLego->SurfacePolar(1,nx,ny,"FB");
07542          if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfacePolar(1,nx,ny,"BF");
07543       } else if (Hoption.System == kCYLINDRICAL) {
07544          if (Hoption.Surf ==  1 || Hoption.Surf == 13) fLego->SurfaceCylindrical(1,nx,ny,"FB");
07545          if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCylindrical(1,nx,ny,"BF");
07546       } else if (Hoption.System == kSPHERICAL) {
07547          if (Hoption.Surf ==  1 || Hoption.Surf == 13) fLego->SurfaceSpherical(0,1,nx,ny,"FB");
07548          if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(0,1,nx,ny,"BF");
07549       } else if (Hoption.System == kRAPIDITY) {
07550          if (Hoption.Surf ==  1 || Hoption.Surf == 13) fLego->SurfaceSpherical(1,1,nx,ny,"FB");
07551          if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceSpherical(1,1,nx,ny,"BF");
07552       } else {
07553          if (Hoption.Surf ==  1 || Hoption.Surf == 13) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
07554          if (Hoption.Surf == 16) fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
07555          if (Hoption.Surf ==  1 || Hoption.Surf == 13 || Hoption.Surf == 16) fLego->SurfaceCartesian(90,nx,ny,"FB");
07556          if (Hoption.Surf == 11 || Hoption.Surf == 12 || Hoption.Surf == 17) fLego->SurfaceCartesian(90,nx,ny,"BF");
07557       }
07558    }
07559 
07560    // Paint the line contour on top for option SURF7
07561    if (Hoption.Surf == 17) {
07562       fLego->InitMoveScreen(-1.1,1.1);
07563       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
07564       Hoption.Surf = 23;
07565       fLego->SetSurfaceFunction(&TPainter3dAlgorithms::SurfaceFunction);
07566       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove3);
07567       if (Hoption.System == kPOLAR)       fLego->SurfacePolar(1,nx,ny,"FB");
07568       if (Hoption.System == kCYLINDRICAL) fLego->SurfaceCylindrical(1,nx,ny,"FB");
07569       if (Hoption.System == kSPHERICAL)   fLego->SurfaceSpherical(0,1,nx,ny,"FB");
07570       if (Hoption.System == kRAPIDITY )   fLego->SurfaceSpherical(1,1,nx,ny,"FB");
07571       if (Hoption.System == kCARTESIAN)   fLego->SurfaceCartesian(90,nx,ny,"FB");
07572    }
07573 
07574    if ((!Hoption.Same) &&
07575        (Hoption.Surf == 1 || Hoption.Surf == 13 || Hoption.Surf == 16)) {
07576       fLego->SetLineColor(1);
07577       if (Hoption.System == kCARTESIAN && Hoption.BackBox) {
07578          fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
07579          fLego->BackBox(90);
07580       }
07581    }
07582    if (Hoption.System == kCARTESIAN) {
07583       fLego->InitMoveScreen(-1.1,1.1);
07584       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
07585       if (Hoption.FrontBox) fLego->FrontBox(90);
07586    }
07587    if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
07588 
07589    if (Hoption.Zscale) PaintPalette();
07590 
07591    delete axis;
07592    delete fLego; fLego = 0;
07593 }
07594 
07595 
07596 //______________________________________________________________________________
07597 void THistPainter::PaintTriangles(Option_t *option)
07598 {
07599    /* Begin_html
07600    Control function to draw a table using Delaunay triangles.
07601    End_html */
07602 
07603    TGraphDelaunay *dt;
07604 
07605    // Check if fH contains a TGraphDelaunay
07606    TList *hl = fH->GetListOfFunctions();
07607    dt = (TGraphDelaunay*)hl->FindObject("TGraphDelaunay");
07608    if (!dt) return;
07609 
07610    // If needed, create a TGraph2DPainter
07611    if (!fGraph2DPainter) fGraph2DPainter = new TGraph2DPainter(dt);
07612 
07613    // Define the 3D view
07614    if (Hoption.Same) {
07615       TView *viewsame = gPad->GetView();
07616       if (!viewsame) {
07617          Error("PaintTriangles", "no TView in current pad, do not use option SAME");
07618          return;
07619       }
07620       Double_t *rmin = viewsame->GetRmin();
07621       Double_t *rmax = viewsame->GetRmax();
07622       fXbuf[0] = rmin[0];
07623       fYbuf[0] = rmax[0];
07624       fXbuf[1] = rmin[1];
07625       fYbuf[1] = rmax[1];
07626       fXbuf[2] = rmin[2];
07627       fYbuf[2] = rmax[2];
07628    } else {
07629       fXbuf[0] = Hparam.xmin;
07630       fYbuf[0] = Hparam.xmax;
07631       fXbuf[1] = Hparam.ymin;
07632       fYbuf[1] = Hparam.ymax;
07633       fXbuf[2] = Hparam.zmin;
07634       fYbuf[2] = Hparam.zmax;
07635    }
07636 
07637    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf);
07638    TView *view = gPad->GetView();
07639    if (!view) {
07640       Error("PaintTriangles", "no TView in current pad");
07641       return;
07642    }
07643    Double_t thedeg =  90 - gPad->GetTheta();
07644    Double_t phideg = -90 - gPad->GetPhi();
07645    Double_t psideg = view->GetPsi();
07646    Int_t irep;
07647    view->SetView(phideg, thedeg, psideg, irep);
07648 
07649    // Set color/style for back box
07650    fLego->SetFillStyle(gPad->GetFrameFillStyle());
07651    fLego->SetFillColor(gPad->GetFrameFillColor());
07652    fLego->TAttFill::Modify();
07653    Int_t backcolor = gPad->GetFrameFillColor();
07654    if (Hoption.System != kCARTESIAN) backcolor = 0;
07655    view->PadRange(backcolor);
07656    fLego->SetFillStyle(fH->GetFillStyle());
07657    fLego->SetFillColor(fH->GetFillColor());
07658    fLego->TAttFill::Modify();
07659 
07660    // Paint the Back Box if needed
07661    if (Hoption.BackBox && !Hoption.Same) {
07662       fLego->InitMoveScreen(-1.1,1.1);
07663       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
07664       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
07665       fLego->BackBox(90);
07666    }
07667 
07668    // Paint the triangles
07669    fGraph2DPainter->Paint(option);
07670 
07671    // Paint the Front Box if needed
07672    if (Hoption.FrontBox) {
07673       fLego->InitMoveScreen(-1.1,1.1);
07674       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
07675       fLego->FrontBox(90);
07676    }
07677 
07678    // Paint the Axis if needed
07679    if (!Hoption.Axis && !Hoption.Same) {
07680       TGaxis *axis = new TGaxis();
07681       PaintLegoAxis(axis, 90);
07682       delete axis;
07683    }
07684 
07685    if (Hoption.Zscale) PaintPalette();
07686 
07687    delete fLego; fLego = 0;
07688 }
07689 
07690 
07691 //______________________________________________________________________________
07692 void THistPainter::DefineColorLevels(Int_t ndivz)
07693 {
07694    /* Begin_html
07695    Define the color levels used to paint legos, surfaces etc..
07696    End_html */
07697 
07698    Int_t i, irep;
07699 
07700    // Initialize the color levels
07701    if (ndivz >= 100) {
07702       Warning("PaintSurface", "too many color levels, %d, reset to 8", ndivz);
07703       ndivz = 8;
07704    }
07705    Double_t *funlevel = new Double_t[ndivz+1];
07706    Int_t *colorlevel = new Int_t[ndivz+1];
07707    Int_t theColor;
07708    Int_t ncolors = gStyle->GetNumberOfColors();
07709    for (i = 0; i < ndivz; ++i) {
07710       funlevel[i] = fH->GetContourLevelPad(i);
07711       theColor = Int_t((i+0.99)*Float_t(ncolors)/Float_t(ndivz));
07712       colorlevel[i] = gStyle->GetColorPalette(theColor);
07713    }
07714    colorlevel[ndivz] = gStyle->GetColorPalette(ncolors-1);
07715    fLego->ColorFunction(ndivz, funlevel, colorlevel, irep);
07716    delete [] colorlevel;
07717    delete [] funlevel;
07718 }
07719 
07720 
07721 //______________________________________________________________________________
07722 void THistPainter::PaintTable(Option_t *option)
07723 {
07724    /* Begin_html
07725    <a href="#HP01c">Control function to draw 2D/3D histograms (tables).</a>
07726    End_html */
07727 
07728    if (!TableInit()) return;  //fill Hparam structure with histo parameters
07729 
07730    PaintFrame();
07731 
07732    //if palette option not specified, delete a possible existing palette
07733    if (!Hoption.Zscale) {
07734       TObject *palette = fFunctions->FindObject("palette");
07735       if (palette) delete palette;
07736    }
07737 
07738    if (fH->InheritsFrom(TH2Poly::Class())) {
07739       if (Hoption.Color)   PaintTH2PolyColorLevels(option);
07740       if (Hoption.Scat)    PaintTH2PolyScatterPlot(option);
07741       if (Hoption.Text)    PaintTH2PolyText(option);
07742    } else if (fH->GetEntries() != 0 && Hoption.Axis<=0) {
07743       if (Hoption.Scat)    PaintScatterPlot(option);
07744       if (Hoption.Arrow)   PaintArrows(option);
07745       if (Hoption.Box)     PaintBoxes(option);
07746       if (Hoption.Color)   PaintColorLevels(option);
07747       if (Hoption.Contour) PaintContour(option);
07748       if (Hoption.Text)    PaintText(option);
07749       if (Hoption.Error >= 100)   Paint2DErrors(option);
07750    }
07751 
07752    if (Hoption.Lego) PaintLego(option);
07753    if (Hoption.Surf && !Hoption.Contour) PaintSurface(option);
07754    if (Hoption.Tri) PaintTriangles(option);
07755 
07756    if (!Hoption.Lego && !Hoption.Surf &&
07757        !Hoption.Tri  && !(Hoption.Error >= 100)) PaintAxis(kFALSE); // Draw the axes
07758 
07759    PaintTitle();    //    Draw histogram title
07760 
07761    TF1 *fit  = 0;
07762    TIter next(fFunctions);
07763    TObject *obj;
07764    while ((obj = next())) {
07765       if (obj->InheritsFrom(TF1::Class())) {
07766          fit = (TF1*)obj;
07767          break;
07768       }
07769    }
07770    if (Hoption.Same != 1) {
07771       if (!fH->TestBit(TH1::kNoStats)) {  // bit set via TH1::SetStats
07772          PaintStat2(gStyle->GetOptStat(),fit);
07773       }
07774    }
07775 }
07776 
07777 
07778 //______________________________________________________________________________
07779 void THistPainter::PaintTH2PolyBins(Option_t *option)
07780 {
07781    /* Begin_html
07782     Control function to draw a TH2Poly bins' contours.
07783     option = "F" draw the bins as filled areas.
07784     option = "L" draw the bins as line.
07785     option = "P" draw the bins as markers.
07786     End_html */
07787 
07788    TString opt = option;
07789    opt.ToLower();
07790    Bool_t line = kFALSE;
07791    Bool_t fill = kFALSE;
07792    Bool_t mark = kFALSE;
07793    if (opt.Contains("l")) line = kTRUE;
07794    if (opt.Contains("f")) fill = kTRUE;
07795    if (opt.Contains("p")) mark = kTRUE;
07796 
07797    TH2PolyBin  *b;
07798 
07799    TIter next(((TH2Poly*)fH)->GetBins());
07800    TObject *obj, *poly;
07801 
07802    while ((obj=next())) {
07803       b     = (TH2PolyBin*)obj;
07804       poly  = b->GetPolygon();
07805 
07806       // Paint the TGraph bins.
07807       if (poly->IsA() == TGraph::Class()) {
07808          TGraph *g  = (TGraph*)poly;
07809          g->TAttLine::Modify();
07810          g->TAttMarker::Modify();
07811          g->TAttFill::Modify();
07812          if (line) g->Paint("L");
07813          if (fill) g->Paint("F");
07814          if (mark) g->Paint("P");
07815       }
07816 
07817       // Paint the TMultiGraph bins.
07818       if (poly->IsA() == TMultiGraph::Class()) {
07819          TMultiGraph *mg = (TMultiGraph*)poly;
07820          TList *gl = mg->GetListOfGraphs();
07821          if (!gl) return;
07822          TGraph *g;
07823          TIter nextg(gl);
07824          while ((g = (TGraph*) nextg())) {
07825             g->TAttLine::Modify();
07826             g->TAttMarker::Modify();
07827             g->TAttFill::Modify();
07828             if (line) g->Paint("L");
07829             if (fill) g->Paint("F");
07830             if (mark) g->Paint("P");
07831          }
07832       }
07833    }
07834 }
07835 
07836 
07837 //______________________________________________________________________________
07838 void THistPainter::PaintTH2PolyColorLevels(Option_t *)
07839 {
07840    /* Begin_html
07841     <a href="#HP20a">Control function to draw a TH2Poly as a color plot.</a>
07842     End_html */
07843 
07844    Int_t ncolors, color, theColor;
07845    Double_t z, zc;
07846    Double_t zmin = fH->GetMinimum();
07847    Double_t zmax = fH->GetMaximum();
07848    if (Hoption.Logz) {
07849       if (zmax > 0) {
07850          if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
07851          zmin = TMath::Log10(zmin);
07852          zmax = TMath::Log10(zmax);
07853       } else {
07854          return;
07855       }
07856    }
07857    Double_t dz = zmax - zmin;
07858 
07859    // Initialize the levels on the Z axis
07860    ncolors     = gStyle->GetNumberOfColors();
07861    Int_t ndiv  = fH->GetContour();
07862    if (ndiv == 0 ) {
07863       ndiv = gStyle->GetNumberContours();
07864       fH->SetContour(ndiv);
07865    }
07866    Int_t ndivz  = TMath::Abs(ndiv);
07867    if (fH->TestBit(TH1::kUserContour) == 0) fH->SetContour(ndiv);
07868    Double_t scale = ndivz/dz;
07869 
07870    TH2PolyBin  *b;
07871 
07872    TIter next(((TH2Poly*)fH)->GetBins());
07873    TObject *obj, *poly;
07874 
07875    while ((obj=next())) {
07876       b     = (TH2PolyBin*)obj;
07877       poly  = b->GetPolygon();
07878 
07879       z = b->GetContent();
07880       if (Hoption.Logz) {
07881          if (z > 0) z = TMath::Log10(z);
07882          else       z = zmin;
07883       }
07884       if (z < zmin) continue;
07885 
07886       // Define the bin color.
07887       if (fH->TestBit(TH1::kUserContour)) {
07888          zc = fH->GetContourLevelPad(0);
07889          if (z < zc) continue;
07890          color = -1;
07891          for (Int_t k=0; k<ndiv; k++) {
07892             zc = fH->GetContourLevelPad(k);
07893             if (z < zc) {
07894                continue;
07895             } else {
07896                color++;
07897             }
07898          }
07899       } else {
07900          color = Int_t(0.01+(z-zmin)*scale);
07901       }
07902       theColor = Int_t((color+0.99)*Float_t(ncolors)/Float_t(ndivz));
07903       if (theColor > ncolors-1) theColor = ncolors-1;
07904 
07905       // Paint the TGraph bins.
07906       if (poly->IsA() == TGraph::Class()) {
07907          TGraph *g  = (TGraph*)poly;
07908          g->SetFillColor(gStyle->GetColorPalette(theColor));
07909          g->TAttFill::Modify();
07910          g->Paint("F");
07911       }
07912 
07913       // Paint the TMultiGraph bins.
07914       if (poly->IsA() == TMultiGraph::Class()) {
07915          TMultiGraph *mg = (TMultiGraph*)poly;
07916          TList *gl = mg->GetListOfGraphs();
07917          if (!gl) return;
07918          TGraph *g;
07919          TIter nextg(gl);
07920          while ((g = (TGraph*) nextg())) {
07921             g->SetFillColor(gStyle->GetColorPalette(theColor));
07922             g->TAttFill::Modify();
07923             g->Paint("F");
07924          }
07925       }
07926    }
07927    if (Hoption.Zscale) PaintPalette();
07928 }
07929 
07930 
07931 //______________________________________________________________________________
07932 void THistPainter::PaintTH2PolyScatterPlot(Option_t *)
07933 {
07934    /* Begin_html
07935     <a href="#HP20a">Control function to draw a TH2Poly as a scatter plot.</a>
07936     End_html */
07937 
07938    Int_t k, loop, marker=0;
07939    Double_t z, xk,xstep, yk, ystep, xp, yp;
07940    Double_t scale = 1;
07941    Double_t zmin = fH->GetMinimum();
07942    Double_t zmax = fH->GetMaximum();
07943    if (Hoption.Logz) {
07944       if (zmax > 0) {
07945          if (zmin <= 0) zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
07946          zmin = TMath::Log10(zmin);
07947          zmax = TMath::Log10(zmax);
07948       } else {
07949          return;
07950       }
07951    }
07952    Double_t dz = zmax - zmin;
07953    scale = (kNMAX-1)/dz;
07954 
07955    UInt_t seedsave = gRandom->GetSeed();
07956    gRandom->SetSeed();
07957 
07958    TH2PolyBin  *b;
07959 
07960    TIter next(((TH2Poly*)fH)->GetBins());
07961    TObject *obj, *poly;
07962 
07963    Double_t maxarea = 0, a;
07964    while ((obj=next())) {
07965       b     = (TH2PolyBin*)obj;
07966       a     = b->GetArea();
07967       if (a>maxarea) maxarea = a;
07968    }
07969 
07970    next.Reset();
07971 
07972    while ((obj=next())) {
07973       b     = (TH2PolyBin*)obj;
07974       poly  = b->GetPolygon();
07975       z     = b->GetContent();
07976       if (z < zmin) z = zmin;
07977       if (z > zmax) z = zmax;
07978       if (Hoption.Logz) {
07979          if (z > 0) z = TMath::Log10(z) - zmin;
07980       } else {
07981          z    -=  zmin;
07982       }
07983       k     = Int_t((z*scale)*(b->GetArea()/maxarea));
07984       xk    = b->GetXMin();
07985       yk    = b->GetYMin();
07986       xstep = b->GetXMax()-xk;
07987       ystep = b->GetYMax()-yk;
07988 
07989       // Paint the TGraph bins.
07990       if (poly->IsA() == TGraph::Class()) {
07991          TGraph *g  = (TGraph*)poly;
07992          if (k <= 0 || z <= 0) continue;
07993          loop = 0;
07994          while (loop<k) {
07995             if (k+marker >= kNMAX) {
07996                gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
07997                marker=0;
07998             }
07999             xp = (gRandom->Rndm(loop)*xstep) + xk;
08000             yp = (gRandom->Rndm(loop)*ystep) + yk;
08001             if (g->IsInside(xp,yp)) {
08002                fXbuf[marker] = xp;
08003                fYbuf[marker] = yp;
08004                marker++;
08005                loop++;
08006             }
08007          }
08008          if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
08009       }
08010 
08011       // Paint the TMultiGraph bins.
08012       if (poly->IsA() == TMultiGraph::Class()) {
08013          TMultiGraph *mg = (TMultiGraph*)poly;
08014          TList *gl = mg->GetListOfGraphs();
08015          if (!gl) return;
08016          if (k <= 0 || z <= 0) continue;
08017          loop = 0;
08018          while (loop<k) {
08019             if (k+marker >= kNMAX) {
08020                gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
08021                marker=0;
08022             }
08023             xp = (gRandom->Rndm(loop)*xstep) + xk;
08024             yp = (gRandom->Rndm(loop)*ystep) + yk;
08025             if (mg->IsInside(xp,yp)) {
08026                fXbuf[marker] = xp;
08027                fYbuf[marker] = yp;
08028                marker++;
08029                loop++;
08030             }
08031          }
08032          if (marker > 0) gPad->PaintPolyMarker(marker, fXbuf, fYbuf);
08033       }
08034    }
08035    PaintTH2PolyBins("l");
08036    gRandom->SetSeed(seedsave);
08037 }
08038 
08039 
08040 //______________________________________________________________________________
08041 void THistPainter::PaintTH2PolyText(Option_t *)
08042 {
08043    /* Begin_html
08044     <a href="#HP20a">Control function to draw a TH2Poly as a text plot.</a>
08045     End_html */
08046 
08047    TLatex text;
08048    text.SetTextFont(gStyle->GetTextFont());
08049    text.SetTextColor(fH->GetMarkerColor());
08050    text.SetTextSize(0.02*fH->GetMarkerSize());
08051 
08052    Double_t x, y, z, e, angle = 0;
08053    char value[50];
08054    char format[32];
08055    snprintf(format,32,"%s%s","%",gStyle->GetPaintTextFormat());
08056    if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
08057    Int_t opt = (Int_t)Hoption.Text/1000;
08058 
08059    text.SetTextAlign(22);
08060    if (Hoption.Text ==  1) angle = 0;
08061    text.SetTextAngle(angle);
08062    text.TAttText::Modify();
08063 
08064    TH2PolyBin *b;
08065 
08066    TIter next(((TH2Poly*)fH)->GetBins());
08067    TObject *obj, *p;
08068 
08069    while ((obj=next())) {
08070       b = (TH2PolyBin*)obj;
08071       p = b->GetPolygon();
08072       x = (b->GetXMin()+b->GetXMax())/2;
08073       if (Hoption.Logx) {
08074          if (x > 0)  x  = TMath::Log10(x);
08075          else continue;
08076       }
08077       y = (b->GetYMin()+b->GetYMax())/2;
08078       if (Hoption.Logy) {
08079          if (y > 0)  y  = TMath::Log10(y);
08080          else continue;
08081       }
08082       z = b->GetContent();
08083       if (z < Hparam.zmin || (z == 0 && !gStyle->GetHistMinimumZero()) ) continue;
08084       if (opt==2) {
08085          e = fH->GetBinError(b->GetBinNumber());
08086          snprintf(format,32,"#splitline{%s%s}{#pm %s%s}",
08087                                     "%",gStyle->GetPaintTextFormat(),
08088                                     "%",gStyle->GetPaintTextFormat());
08089          snprintf(value,50,format,z,e);
08090       } else {
08091          snprintf(value,50,format,z);
08092       }
08093       if (opt==3) text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),p->GetName());
08094       else        text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),value);
08095    }
08096 
08097    PaintTH2PolyBins("l");
08098 }
08099 
08100 
08101 //______________________________________________________________________________
08102 void THistPainter::PaintText(Option_t *)
08103 {
08104    /* Begin_html
08105    <a href="#HP15">Control function to draw a 1D/2D histograms with the bin values.</a>
08106    End_html */
08107 
08108    TLatex text;
08109    text.SetTextFont(gStyle->GetTextFont());
08110    text.SetTextColor(fH->GetMarkerColor());
08111    text.SetTextSize(0.02*fH->GetMarkerSize());
08112 
08113    Double_t x, y, z, e, angle = 0;
08114    char value[50];
08115    char format[32];
08116    snprintf(format,32,"%s%s","%",gStyle->GetPaintTextFormat());
08117    if (Hoption.Text >= 1000) angle = Hoption.Text%1000;
08118 
08119    // 1D histograms
08120    if (fH->GetDimension() == 1) {
08121       Bool_t getentries = kFALSE;
08122       Double_t yt;
08123       TProfile *hp = (TProfile*)fH;
08124       if (Hoption.Text>2000 && fH->InheritsFrom(TProfile::Class())) {
08125          Hoption.Text = Hoption.Text-2000;
08126          getentries = kTRUE;
08127       }
08128       if (Hoption.Text ==  1) angle = 90;
08129       text.SetTextAlign(11);
08130       if (angle == 90) text.SetTextAlign(12);
08131       if (angle ==  0) text.SetTextAlign(21);
08132       text.TAttText::Modify();
08133       Double_t dt = 0.02*(gPad->GetY2()-gPad->GetY1());
08134       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
08135          x  = fH->GetXaxis()->GetBinCenter(i);
08136          y  = fH->GetBinContent(i);
08137          yt = y;
08138          if (getentries) yt = hp->GetBinEntries(i);
08139          snprintf(value,50,format,yt);
08140          if (Hoption.Logx) {
08141             if (x > 0)  x  = TMath::Log10(x);
08142             else continue;
08143          }
08144          if (Hoption.Logy) {
08145             if (y > 0)  y  = TMath::Log10(y);
08146             else continue;
08147          }
08148          if (y >= gPad->GetY2()) continue;
08149          if (y <= gPad->GetY1()) continue;
08150          text.PaintLatex(x,y+0.2*dt,angle,0.02*fH->GetMarkerSize(),value);
08151       }
08152 
08153    // 2D histograms
08154    } else {
08155       text.SetTextAlign(22);
08156       if (Hoption.Text ==  1) angle = 0;
08157       text.SetTextAngle(angle);
08158       text.TAttText::Modify();
08159       for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
08160          y    = fYaxis->GetBinCenter(j);
08161          if (Hoption.Logy) {
08162             if (y > 0)  y  = TMath::Log10(y);
08163             else continue;
08164          }
08165          for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
08166             Int_t bin  = j*(fXaxis->GetNbins()+2) + i;
08167             x    = fXaxis->GetBinCenter(i);
08168             if (Hoption.Logx) {
08169                if (x > 0)  x  = TMath::Log10(x);
08170                else continue;
08171             }
08172             if (!IsInside(x,y)) continue;
08173             z = fH->GetBinContent(bin);
08174             if (z < Hparam.zmin || (z == 0 && !gStyle->GetHistMinimumZero()) ) continue;
08175             if (Hoption.Text>2000) {
08176                e = fH->GetBinError(bin);
08177                snprintf(format,32,"#splitline{%s%s}{#pm %s%s}",
08178                                           "%",gStyle->GetPaintTextFormat(),
08179                                           "%",gStyle->GetPaintTextFormat());
08180                snprintf(value,50,format,z,e);
08181             } else {
08182                snprintf(value,50,format,z);
08183             }
08184             text.PaintLatex(x,y,angle,0.02*fH->GetMarkerSize(),value);
08185          }
08186       }
08187    }
08188 }
08189 
08190 
08191 //______________________________________________________________________________
08192 void THistPainter::PaintTF3()
08193 {
08194    /* Begin_html
08195    <a href="#HP27">Control function to draw a 3D implicit functions.</a>
08196    End_html */
08197 
08198    Int_t irep;
08199 
08200    TGaxis *axis = new TGaxis();
08201    TAxis *xaxis = fH->GetXaxis();
08202    TAxis *yaxis = fH->GetYaxis();
08203    TAxis *zaxis = fH->GetZaxis();
08204 
08205    fXbuf[0] = xaxis->GetBinLowEdge(xaxis->GetFirst());
08206    fYbuf[0] = xaxis->GetBinUpEdge(xaxis->GetLast());
08207    fXbuf[1] = yaxis->GetBinLowEdge(yaxis->GetFirst());
08208    fYbuf[1] = yaxis->GetBinUpEdge(yaxis->GetLast());
08209    fXbuf[2] = zaxis->GetBinLowEdge(zaxis->GetFirst());
08210    fYbuf[2] = zaxis->GetBinUpEdge(zaxis->GetLast());
08211 
08212    fLego = new TPainter3dAlgorithms(fXbuf, fYbuf);
08213 
08214    TView *view = gPad->GetView();
08215    if (!view) {
08216       Error("PaintTF3", "no TView in current pad");
08217       return;
08218    }
08219    Double_t thedeg =  90 - gPad->GetTheta();
08220    Double_t phideg = -90 - gPad->GetPhi();
08221    Double_t psideg = view->GetPsi();
08222    view->SetView(phideg, thedeg, psideg, irep);
08223 
08224    fLego->InitMoveScreen(-1.1,1.1);
08225 
08226    if (Hoption.BackBox) {
08227       fLego->DefineGridLevels(fZaxis->GetNdivisions()%100);
08228       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove1);
08229       fLego->BackBox(90);
08230    }
08231 
08232    fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMode1);
08233 
08234    fLego->ImplicitFunction(fXbuf, fYbuf, fH->GetNbinsX(),
08235                                          fH->GetNbinsY(),
08236                                          fH->GetNbinsZ(), "BF");
08237 
08238    if (Hoption.FrontBox) {
08239       fLego->InitMoveScreen(-1.1,1.1);
08240       fLego->SetDrawFace(&TPainter3dAlgorithms::DrawFaceMove2);
08241       fLego->FrontBox(90);
08242    }
08243    if (!Hoption.Axis && !Hoption.Same) PaintLegoAxis(axis, 90);
08244 
08245    PaintTitle();
08246 
08247    delete axis;
08248    delete fLego; fLego = 0;
08249 }
08250 
08251 
08252 //______________________________________________________________________________
08253 void THistPainter::PaintTitle()
08254 {
08255    /* Begin_html
08256    Draw the histogram title
08257    <p>
08258    The title is drawn according to the title alignment returned by
08259    <tt>GetTitleAlign()</tt>. It is a 2 digits integer): hv
08260    <p>
08261    where <tt>"h"</tt> is the horizontal alignment and <tt>"v"</tt> is the
08262    vertical alignment.
08263    <ul>
08264    <li> <tt>"h"</tt> can get the values 1 2 3 for left, center, and right
08265    <li> <tt>"v"</tt> can get the values 1 2 3 for bottom, middle and top
08266    </ul>
08267    for instance the default alignment is: 13 (left top)
08268    End_html */
08269 
08270    if (Hoption.Same) return;
08271    if (fH->TestBit(TH1::kNoTitle)) return;
08272    Int_t nt = strlen(fH->GetTitle());
08273    TPaveText *title = 0;
08274    TObject *obj;
08275    TIter next(gPad->GetListOfPrimitives());
08276    while ((obj = next())) {
08277       if (!obj->InheritsFrom(TPaveText::Class())) continue;
08278       title = (TPaveText*)obj;
08279       if (strcmp(title->GetName(),"title")) {title = 0; continue;}
08280       break;
08281    }
08282    if (nt == 0 || gStyle->GetOptTitle() <= 0) {
08283       if (title) delete title;
08284       return;
08285    }
08286    Double_t ht = gStyle->GetTitleH();
08287    Double_t wt = gStyle->GetTitleW();
08288    if (ht <= 0) ht = 1.1*gStyle->GetTitleFontSize();
08289    if (ht <= 0) ht = 0.05;
08290    if (wt <= 0) {
08291       TLatex l;
08292       l.SetTextSize(ht);
08293       l.SetTitle(fH->GetTitle());
08294       // adjustment in case the title has several lines (#splitline)
08295       ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
08296       Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
08297       wt = TMath::Min(0.7, 0.02+wndc);
08298    }
08299    if (title) {
08300       TText *t0 = (TText*)title->GetLine(0);
08301       if (t0) {
08302          if (!strcmp(t0->GetTitle(),fH->GetTitle())) return;
08303          t0->SetTitle(fH->GetTitle());
08304          if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
08305       }
08306       return;
08307    }
08308 
08309    Int_t talh = gStyle->GetTitleAlign()/10;
08310    if (talh < 1) talh = 1; if (talh > 3) talh = 3;
08311    Int_t talv = gStyle->GetTitleAlign()%10;
08312    if (talv < 1) talv = 1; if (talv > 3) talv = 3;
08313    Double_t xpos, ypos;
08314    xpos = gStyle->GetTitleX();
08315    ypos = gStyle->GetTitleY();
08316    if (talh == 2) xpos = xpos-wt/2.;
08317    if (talh == 3) xpos = xpos-wt;
08318    if (talv == 2) ypos = ypos+ht/2.;
08319    if (talv == 1) ypos = ypos+ht;
08320 
08321    TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
08322 
08323    //     box with the histogram title
08324    ptitle->SetFillColor(gStyle->GetTitleFillColor());
08325    ptitle->SetFillStyle(gStyle->GetTitleStyle());
08326    ptitle->SetName("title");
08327    ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
08328    ptitle->SetTextColor(gStyle->GetTitleTextColor());
08329    ptitle->SetTextFont(gStyle->GetTitleFont(""));
08330    if (gStyle->GetTitleFont("")%10 > 2)
08331       ptitle->SetTextSize(gStyle->GetTitleFontSize());
08332    ptitle->AddText(fH->GetTitle());
08333    ptitle->SetBit(kCanDelete);
08334    ptitle->Draw();
08335    ptitle->Paint();
08336 
08337 }
08338 
08339 
08340 //______________________________________________________________________________
08341 void THistPainter::ProcessMessage(const char *mess, const TObject *obj)
08342 {
08343    /* Begin_html
08344     Process message "mess".
08345    End_html */
08346 
08347    if (!strcmp(mess,"SetF3")) {
08348       TPainter3dAlgorithms::SetF3((TF3*)obj);
08349    } else if (!strcmp(mess,"SetF3ClippingBoxOff")) {
08350       TPainter3dAlgorithms::SetF3ClippingBoxOff();
08351    } else if (!strcmp(mess,"SetF3ClippingBoxOn")) {
08352       TVectorD &v =  (TVectorD&)(*obj);
08353       Double_t xclip = v(0);
08354       Double_t yclip = v(1);
08355       Double_t zclip = v(2);
08356       TPainter3dAlgorithms::SetF3ClippingBoxOn(xclip,yclip,zclip);
08357    }
08358 }
08359 
08360 
08361 //______________________________________________________________________________
08362 Int_t THistPainter::ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
08363 {
08364    /* Begin_html
08365    Static function.<br>
08366    Convert Right Ascension, Declination to X,Y using an AITOFF projection.
08367    This procedure can be used to create an all-sky map in Galactic
08368    coordinates with an equal-area Aitoff projection.  Output map
08369    coordinates are zero longitude centered.
08370    Also called Hammer-Aitoff projection (first presented by Ernst von Hammer in 1892)
08371    <p>
08372    source: GMT<br>
08373    code from  Ernst-Jan Buis
08374    End_html */
08375 
08376    Double_t x, y;
08377 
08378    Double_t alpha2 = (l/2)*TMath::DegToRad();
08379    Double_t delta  = b*TMath::DegToRad();
08380    Double_t r2     = TMath::Sqrt(2.);
08381    Double_t f      = 2*r2/TMath::Pi();
08382    Double_t cdec   = TMath::Cos(delta);
08383    Double_t denom  = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
08384    x      = cdec*TMath::Sin(alpha2)*2.*r2/denom;
08385    y      = TMath::Sin(delta)*r2/denom;
08386    x     *= TMath::RadToDeg()/f;
08387    y     *= TMath::RadToDeg()/f;
08388    //  x *= -1.; // for a skymap swap left<->right
08389    Al = x;
08390    Ab = y;
08391 
08392    return 0;
08393 }
08394 
08395 
08396 //______________________________________________________________________________
08397 Int_t THistPainter::ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
08398 {
08399    /* Begin_html
08400    Static function <br>
08401    Probably the most famous of the various map projections, the Mercator projection
08402    takes its name from Mercator who presented it in 1569. It is a cylindrical, conformal projection
08403    with no distortion along the equator.
08404    The Mercator projection has been used extensively for world maps in which the distortion towards
08405    the polar regions grows rather large, thus incorrectly giving the impression that, for example,
08406    Greenland is larger than South America. In reality, the latter is about eight times the size of
08407    Greenland. Also, the Former Soviet Union looks much bigger than Africa or South America. One may wonder
08408    whether this illusion has had any influence on U.S. foreign policy.' (Source: GMT)
08409    code from  Ernst-Jan Buis
08410    End_html */
08411 
08412    Al = l;
08413    Double_t aid = TMath::Tan((TMath::PiOver2() + b*TMath::DegToRad())/2);
08414    Ab = TMath::Log(aid);
08415    return 0;
08416 }
08417 
08418 
08419 //______________________________________________________________________________
08420 Int_t THistPainter::ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
08421 {
08422    /* Begin_html
08423    Static function code from  Ernst-Jan Buis
08424    End_html */
08425 
08426    Al = l*cos(b*TMath::DegToRad());
08427    Ab = b;
08428    return 0;
08429 }
08430 
08431 
08432 //______________________________________________________________________________
08433 Int_t THistPainter::ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
08434 {
08435    /* Begin_html
08436    Static function code from  Ernst-Jan Buis
08437    End_html */
08438 
08439    Al = l*(2.*TMath::Cos(2*b*TMath::DegToRad()/3) - 1);
08440    Ab = 180*TMath::Sin(b*TMath::DegToRad()/3);
08441    return 0;
08442 }
08443 
08444 
08445 //______________________________________________________________________________
08446 void THistPainter::RecalculateRange()
08447 {
08448    /* Begin_html
08449    Recompute the histogram range following graphics operations.
08450    End_html */
08451 
08452    if (Hoption.Same) return;
08453 
08454    //     Compute x,y range
08455    Double_t xmin = Hparam.xmin;
08456    Double_t xmax = Hparam.xmax;
08457    Double_t ymin = Hparam.ymin;
08458    Double_t ymax = Hparam.ymax;
08459 
08460    Double_t xmin_aid, ymin_aid, xmax_aid, ymax_aid;
08461    if (Hoption.Proj ==1) {
08462       // TODO : check x range not lower than -180 and not higher than 180
08463       THistPainter::ProjectAitoff2xy(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
08464       THistPainter::ProjectAitoff2xy(Hparam.xmin, Hparam.ymax, xmin,     ymax_aid);
08465       THistPainter::ProjectAitoff2xy(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
08466       THistPainter::ProjectAitoff2xy(Hparam.xmax, Hparam.ymin, xmax,     ymin);
08467 
08468       if (xmin > xmin_aid) xmin = xmin_aid;
08469       if (ymin > ymin_aid) ymin = ymin_aid;
08470       if (xmax < xmax_aid) xmax = xmax_aid;
08471       if (ymax < ymax_aid) ymax = ymax_aid;
08472       if (Hparam.ymin<0 && Hparam.ymax>0) {
08473          // there is an  'equator', check its range in the plot..
08474          THistPainter::ProjectAitoff2xy(Hparam.xmin*0.9999, 0, xmin_aid, ymin_aid);
08475          THistPainter::ProjectAitoff2xy(Hparam.xmax*0.9999, 0, xmax_aid, ymin_aid);
08476          if (xmin >xmin_aid) xmin = xmin_aid;
08477          if (xmax <xmax_aid) xmax = xmax_aid;
08478       }
08479       if (Hparam.xmin<0 && Hparam.xmax>0) {
08480          THistPainter::ProjectAitoff2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
08481          THistPainter::ProjectAitoff2xy(0, Hparam.ymax, xmax_aid, ymax_aid);
08482          if (ymin >ymin_aid) ymin = ymin_aid;
08483          if (ymax <ymax_aid) ymax = ymax_aid;
08484       }
08485    } else if ( Hoption.Proj ==2) {
08486       if (Hparam.ymin <= -90 || Hparam.ymax >=90) {
08487          Warning("Mercator Projection", "Latitude out of range %f or %f", Hparam.ymin, Hparam.ymax);
08488          Hoption.Proj = 0;
08489       } else {
08490          THistPainter::ProjectMercator2xy(Hparam.xmin, Hparam.ymin, xmin, ymin);
08491          THistPainter::ProjectMercator2xy(Hparam.xmax, Hparam.ymax, xmax, ymax);
08492       }
08493    } else if (Hoption.Proj == 3) {
08494       THistPainter::ProjectSinusoidal2xy(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
08495       THistPainter::ProjectSinusoidal2xy(Hparam.xmin, Hparam.ymax, xmin,     ymax_aid);
08496       THistPainter::ProjectSinusoidal2xy(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
08497       THistPainter::ProjectSinusoidal2xy(Hparam.xmax, Hparam.ymin, xmax,     ymin);
08498 
08499       if (xmin > xmin_aid) xmin = xmin_aid;
08500       if (ymin > ymin_aid) ymin = ymin_aid;
08501       if (xmax < xmax_aid) xmax = xmax_aid;
08502       if (ymax < ymax_aid) ymax = ymax_aid;
08503       if (Hparam.ymin<0 && Hparam.ymax>0) {
08504          THistPainter::ProjectSinusoidal2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
08505          THistPainter::ProjectSinusoidal2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
08506          if (xmin >xmin_aid) xmin = xmin_aid;
08507          if (xmax <xmax_aid) xmax = xmax_aid;
08508       }
08509       if (Hparam.xmin<0 && Hparam.xmax>0) {
08510          THistPainter::ProjectSinusoidal2xy(0,Hparam.ymin, xmin_aid, ymin_aid);
08511          THistPainter::ProjectSinusoidal2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
08512          if (ymin >ymin_aid) ymin = ymin_aid;
08513          if (ymax <ymax_aid) ymax = ymax_aid;
08514       }
08515    } else if (Hoption.Proj == 4) {
08516       THistPainter::ProjectParabolic2xy(Hparam.xmin, Hparam.ymin, xmin_aid, ymin_aid);
08517       THistPainter::ProjectParabolic2xy(Hparam.xmin, Hparam.ymax, xmin,     ymax_aid);
08518       THistPainter::ProjectParabolic2xy(Hparam.xmax, Hparam.ymax, xmax_aid, ymax);
08519       THistPainter::ProjectParabolic2xy(Hparam.xmax, Hparam.ymin, xmax,     ymin);
08520 
08521       if (xmin > xmin_aid) xmin = xmin_aid;
08522       if (ymin > ymin_aid) ymin = ymin_aid;
08523       if (xmax < xmax_aid) xmax = xmax_aid;
08524       if (ymax < ymax_aid) ymax = ymax_aid;
08525       if (Hparam.ymin<0 && Hparam.ymax>0) {
08526          THistPainter::ProjectParabolic2xy(Hparam.xmin, 0, xmin_aid, ymin_aid);
08527          THistPainter::ProjectParabolic2xy(Hparam.xmax, 0, xmax_aid, ymin_aid);
08528          if (xmin >xmin_aid) xmin = xmin_aid;
08529          if (xmax <xmax_aid) xmax = xmax_aid;
08530       }
08531       if (Hparam.xmin<0 && Hparam.xmax>0) {
08532          THistPainter::ProjectParabolic2xy(0, Hparam.ymin, xmin_aid, ymin_aid);
08533          THistPainter::ProjectParabolic2xy(0, Hparam.ymax, xmax_aid, ymin_aid);
08534          if (ymin >ymin_aid) ymin = ymin_aid;
08535          if (ymax <ymax_aid) ymax = ymax_aid;
08536       }
08537    }
08538    Hparam.xmin= xmin;
08539    Hparam.xmax= xmax;
08540    Hparam.ymin= ymin;
08541    Hparam.ymax= ymax;
08542 
08543    Double_t dx   = xmax-xmin;
08544    Double_t dy   = ymax-ymin;
08545    Double_t dxr  = dx/(1 - gPad->GetLeftMargin()   - gPad->GetRightMargin());
08546    Double_t dyr  = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
08547 
08548    // Range() could change the size of the pad pixmap and therefore should
08549    // be called before the other paint routines
08550    gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
08551                       ymin - dyr*gPad->GetBottomMargin(),
08552                       xmax + dxr*gPad->GetRightMargin(),
08553                       ymax + dyr*gPad->GetTopMargin());
08554    gPad->RangeAxis(xmin, ymin, xmax, ymax);
08555 }
08556 
08557 
08558 //______________________________________________________________________________
08559 void THistPainter::SetHistogram(TH1 *h)
08560 {
08561    /* Begin_html
08562    Set current histogram to "h".
08563    End_html */
08564 
08565    if (h == 0)  return;
08566    fH = h;
08567    fXaxis = h->GetXaxis();
08568    fYaxis = h->GetYaxis();
08569    fZaxis = h->GetZaxis();
08570    fFunctions = fH->GetListOfFunctions();
08571 }
08572 
08573 
08574 //______________________________________________________________________________
08575 Int_t THistPainter::TableInit()
08576 {
08577    /* Begin_html
08578    Initialize various options to draw 2D histograms.
08579    End_html */
08580 
08581    static const char *where = "TableInit";
08582 
08583    Int_t first, last;
08584    Double_t yMARGIN= gStyle->GetHistTopMargin();
08585    Double_t zmin, zmax;
08586    Int_t maximum = 0;
08587    Int_t minimum = 0;
08588    if (fH->GetMaximumStored() != -1111) maximum = 1;
08589    if (fH->GetMinimumStored() != -1111) minimum = 1;
08590 
08591    //    -----------------  Compute X axis parameters
08592    first           = fXaxis->GetFirst();
08593    last            = fXaxis->GetLast();
08594    Hparam.xlast    = last;
08595    Hparam.xfirst   = first;
08596    Hparam.xlowedge = fXaxis->GetBinLowEdge(first);
08597    Hparam.xbinsize = fXaxis->GetBinWidth(first);
08598    Hparam.xmin     = Hparam.xlowedge;
08599    Hparam.xmax     = fXaxis->GetBinLowEdge(last)+fXaxis->GetBinWidth(last);
08600 
08601    //       if log scale in X, replace xmin,max by the log
08602    if (Hoption.Logx) {
08603    //   find the first edge of a bin that is > 0
08604       if (Hparam.xlowedge <=0 ) {
08605          Hparam.xlowedge = fXaxis->GetBinUpEdge(fXaxis->FindFixBin(0.01*Hparam.xbinsize));
08606          Hparam.xmin  = Hparam.xlowedge;
08607       }
08608       if (Hparam.xmin <=0 || Hparam.xmax <=0) {
08609          Error(where, "cannot set X axis to log scale");
08610          return 0;
08611       }
08612       Hparam.xfirst= fXaxis->FindFixBin(Hparam.xmin);
08613       if (Hparam.xfirst < first) Hparam.xfirst = first;
08614       Hparam.xlast = fXaxis->FindFixBin(Hparam.xmax);
08615       if (Hparam.xlast > last) Hparam.xlast = last;
08616       Hparam.xmin  = TMath::Log10(Hparam.xmin);
08617       Hparam.xmax  = TMath::Log10(Hparam.xmax);
08618    }
08619 
08620    //    -----------------  Compute Y axis parameters
08621    first           = fYaxis->GetFirst();
08622    last            = fYaxis->GetLast();
08623    Hparam.ylast    = last;
08624    Hparam.yfirst   = first;
08625    Hparam.ylowedge = fYaxis->GetBinLowEdge(first);
08626    Hparam.ybinsize = fYaxis->GetBinWidth(first);
08627    if (!Hparam.ybinsize) Hparam.ybinsize = 1;
08628    Hparam.ymin     = Hparam.ylowedge;
08629    Hparam.ymax     = fYaxis->GetBinLowEdge(last)+fYaxis->GetBinWidth(last);
08630 
08631    //       if log scale in Y, replace ymin,max by the log
08632    if (Hoption.Logy) {
08633       if (Hparam.ylowedge <=0 ) {
08634          Hparam.ylowedge = fYaxis->GetBinUpEdge(fYaxis->FindFixBin(0.01*Hparam.ybinsize));
08635          Hparam.ymin  = Hparam.ylowedge;
08636       }
08637       if (Hparam.ymin <=0 || Hparam.ymax <=0) {
08638          Error(where, "cannot set Y axis to log scale");
08639          return 0;
08640       }
08641       Hparam.yfirst= fYaxis->FindFixBin(Hparam.ymin);
08642       if (Hparam.yfirst < first) Hparam.yfirst = first;
08643       Hparam.ylast = fYaxis->FindFixBin(Hparam.ymax);
08644       if (Hparam.ylast > last) Hparam.ylast = last;
08645       Hparam.ymin  = TMath::Log10(Hparam.ymin);
08646       Hparam.ymax  = TMath::Log10(Hparam.ymax);
08647    }
08648 
08649 
08650    //    -----------------  Compute Z axis parameters
08651    Double_t bigp = TMath::Power(10,32);
08652    zmax = -bigp;
08653    zmin = bigp;
08654    Double_t c1, e1;
08655    Double_t allchan = 0;
08656    for (Int_t j=Hparam.yfirst; j<=Hparam.ylast;j++) {
08657       for (Int_t i=Hparam.xfirst; i<=Hparam.xlast;i++) {
08658          c1 = fH->GetCellContent(i,j);
08659          zmax = TMath::Max(zmax,c1);
08660          if (Hoption.Error) {
08661             e1 = fH->GetCellError(i,j);
08662             zmax = TMath::Max(zmax,c1+e1);
08663          }
08664          zmin = TMath::Min(zmin,c1);
08665          allchan += c1;
08666       }
08667    }
08668 
08669    //     Take into account maximum , minimum
08670 
08671    if (maximum) zmax = fH->GetMaximumStored();
08672    if (minimum) zmin = fH->GetMinimumStored();
08673    if (Hoption.Logz && zmax < 0) {
08674       if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
08675       return 0;
08676    } else if (Hoption.Logz && zmin>=0 && zmax==0) { // empty histogram in log scale
08677       zmin = 0.01;
08678       zmax = 10.;
08679    }
08680    if (zmin >= zmax) {
08681       if (Hoption.Logz) {
08682          if (zmax > 0) zmin = 0.001*zmax;
08683          else {
08684             if (!Hoption.Same) Error(where, "log scale is requested but maximum is less or equal 0 (%f)", zmax);
08685             return 0;
08686          }
08687       }
08688    }
08689 
08690    //     take into account normalization factor
08691    Hparam.allchan = allchan;
08692    Double_t factor = allchan;
08693    if (fH->GetNormFactor() > 0) factor = fH->GetNormFactor();
08694    if (allchan) factor /= allchan;
08695    if (factor == 0) factor = 1;
08696    Hparam.factor = factor;
08697    zmax = factor*zmax;
08698    zmin = factor*zmin;
08699    c1 = zmax;
08700    if (TMath::Abs(zmin) > TMath::Abs(c1)) c1 = zmin;
08701 
08702    //         For log scales, histogram coordinates are log10(ymin) and
08703    //         log10(ymax). Final adjustment (if not option "Same")
08704    //         or "+" for ymax) of ymax and ymin for logarithmic scale, if
08705    //         Maximum and Minimum are not defined.
08706    if (Hoption.Logz) {
08707       if (zmin <= 0) {
08708          zmin = TMath::Min((Double_t)1, (Double_t)0.001*zmax);
08709          fH->SetMinimum(zmin);
08710       }
08711       zmin = TMath::Log10(zmin);
08712       if (!minimum) zmin += TMath::Log10(0.5);
08713       zmax = TMath::Log10(zmax);
08714       if (!maximum) zmax += TMath::Log10(2*(0.9/0.95));
08715       goto LZMIN;
08716    }
08717 
08718    //         final adjustment of YMAXI for linear scale (if not option "Same"):
08719    //         decrease histogram height to MAX% of allowed height if HMAXIM
08720    //         has not been called.
08721    //         MAX% is the value in percent which has been set in HPLSET
08722    //         (default is 90%).
08723    if (!maximum) {
08724       zmax += yMARGIN*(zmax-zmin);
08725    }
08726 
08727    //         final adjustment of ymin for linear scale.
08728    //         if minimum is not set , then ymin is set to zero if >0
08729    //         or to ymin - yMARGIN if <0.
08730    if (!minimum) {
08731       if (gStyle->GetHistMinimumZero()) {
08732          if (zmin >= 0) zmin = 0;
08733          else           zmin -= yMARGIN*(zmax-zmin);
08734       } else {
08735          Double_t dzmin = yMARGIN*(zmax-zmin);
08736          if (zmin >= 0 && (zmin-dzmin <= 0)) zmin  = 0;
08737          else                                zmin -= dzmin;
08738       }
08739    }
08740 
08741 LZMIN:
08742    Hparam.zmin = zmin;
08743    Hparam.zmax = zmax;
08744 
08745    //     Set bar offset and width
08746    Hparam.baroffset = fH->GetBarOffset();
08747    Hparam.barwidth  = fH->GetBarWidth();
08748 
08749    return 1;
08750 }
08751 
08752 
08753 //______________________________________________________________________________
08754 const char * THistPainter::GetBestFormat(Double_t v, Double_t e, const char *f)
08755 {
08756    /* Begin_html
08757    This function returns the best format to print the error value (e)
08758    knowing the parameter value (v) and the format (f) used to print it.
08759    End_html */
08760 
08761    static char ef[20];
08762    char tf[20], tv[64];
08763 
08764    // print v with the format f in tv.
08765    snprintf(tf,20,"%s%s","%",f);
08766    snprintf(tv,64,tf,v);
08767 
08768    // Analyse tv.
08769    TString sv = tv;
08770    int ie = sv.Index("e");
08771    int iE = sv.Index("E");
08772    int id = sv.Index(".");
08773 
08774    // v has been printed with the exponent notation.
08775    // There is 2 cases, the exponent is positive or negative
08776    if (ie >= 0 || iE >= 0) {
08777       if (sv.Index("+") >= 0) {
08778          if (e < 1) {
08779             snprintf(ef,20,"%s.1f","%");
08780          } else {
08781             if (ie >= 0) {
08782                snprintf(ef,20,"%s.%de","%",ie-id-1);
08783             } else {
08784                snprintf(ef,20,"%s.%dE","%",iE-id-1);
08785             }
08786          }
08787       } else {
08788          if (ie >= 0) {
08789             snprintf(ef,20,"%s.%de","%",ie-id-1);
08790          } else {
08791             snprintf(ef,20,"%s.%dE","%",iE-id-1);
08792          }
08793       }
08794 
08795    // There is not '.' in tv. e will be printed with one decimal digit.
08796    } else if (id < 0) {
08797       snprintf(ef,20,"%s.1f","%");
08798 
08799    // There is a '.' in tv and no exponent notation. e's decimal part will
08800    // have the same number of digits as v's one.
08801    } else {
08802       snprintf(ef,20,"%s.%df","%",sv.Length()-id-1);
08803    }
08804 
08805    return ef;
08806 }
08807 
08808 
08809 //______________________________________________________________________________
08810 void THistPainter::SetShowProjection(const char *option,Int_t nbins)
08811 {
08812    /* Begin_html
08813    Set projection.
08814    End_html */
08815 
08816    if (fShowProjection) return;
08817    TString opt = option;
08818    opt.ToLower();
08819    Int_t projection = 0;
08820    if (opt.Contains("x"))  projection = 1;
08821    if (opt.Contains("y"))  projection = 2;
08822    if (opt.Contains("z"))  projection = 3;
08823    if (opt.Contains("xy")) projection = 4;
08824    if (opt.Contains("yx")) projection = 5;
08825    if (opt.Contains("xz")) projection = 6;
08826    if (opt.Contains("zx")) projection = 7;
08827    if (opt.Contains("yz")) projection = 8;
08828    if (opt.Contains("zy")) projection = 9;
08829    if (projection < 4) fShowOption = option+1;
08830    else                fShowOption = option+2;
08831    fShowProjection = projection+100*nbins;
08832    gROOT->MakeDefCanvas();
08833    gPad->SetName(Form("%lx_c_projection_%d", (ULong_t)fH, fShowProjection));
08834    gPad->SetGrid();
08835 }
08836 
08837 
08838 //______________________________________________________________________________
08839 void THistPainter::ShowProjectionX(Int_t /*px*/, Int_t py)
08840 {
08841    /* Begin_html
08842    Show projection onto X.
08843    End_html */
08844 
08845    Int_t nbins = (Int_t)fShowProjection/100;
08846    gPad->SetDoubleBuffer(0); // turn off double buffer mode
08847    gVirtualX->SetDrawMode(TVirtualX::kInvert); // set the drawing mode to XOR mode
08848 
08849    // Erase old position and draw a line at current position
08850    static int pyold1 = 0;
08851    static int pyold2 = 0;
08852    float uxmin = gPad->GetUxmin();
08853    float uxmax = gPad->GetUxmax();
08854    int pxmin   = gPad->XtoAbsPixel(uxmin);
08855    int pxmax   = gPad->XtoAbsPixel(uxmax);
08856    Float_t upy = gPad->AbsPixeltoY(py);
08857    Float_t y   = gPad->PadtoY(upy);
08858    Int_t biny1 = fH->GetYaxis()->FindBin(y);
08859    Int_t biny2 = TMath::Min(biny1+nbins-1, fH->GetYaxis()->GetNbins());
08860    Int_t py1   = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinLowEdge(biny1));
08861    Int_t py2   = gPad->YtoAbsPixel(fH->GetYaxis()->GetBinUpEdge(biny2));
08862 
08863    if (pyold1 || pyold2) gVirtualX->DrawBox(pxmin,pyold1,pxmax,pyold2,TVirtualX::kFilled);
08864    gVirtualX->DrawBox(pxmin,py1,pxmax,py2,TVirtualX::kFilled);
08865    pyold1 = py1;
08866    pyold2 = py2;
08867 
08868    // Create or set the new canvas proj x
08869    TVirtualPad *padsav = gPad;
08870    TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("%lx_c_projection_%d",
08871                                                                               (ULong_t)fH, fShowProjection));
08872    if (c) {
08873       c->Clear();
08874    } else {
08875       fShowProjection = 0;
08876       pyold1 = 0;
08877       pyold2 = 0;
08878       return;
08879    }
08880    c->cd();
08881    c->SetLogy(padsav->GetLogz());
08882    c->SetLogx(padsav->GetLogx());
08883 
08884    // Draw slice corresponding to mouse position
08885    TH1D *hp = ((TH2*)fH)->ProjectionX("_px", biny1, biny2);
08886    hp->SetFillColor(38);
08887    if (biny1 == biny2) hp->SetTitle(Form("ProjectionX of biny=%d", biny1));
08888    else hp->SetTitle(Form("ProjectionX of biny=[%d,%d]", biny1,biny2));
08889    hp->SetXTitle(fH->GetXaxis()->GetTitle());
08890    hp->SetYTitle("Number of Entries");
08891    hp->Draw();
08892    c->Update();
08893    padsav->cd();
08894 }
08895 
08896 
08897 //______________________________________________________________________________
08898 void THistPainter::ShowProjectionY(Int_t px, Int_t /*py*/)
08899 {
08900    /* Begin_html
08901    Show projection onto Y.
08902    End_html */
08903 
08904    Int_t nbins = (Int_t)fShowProjection/100;
08905    gPad->SetDoubleBuffer(0);             // turn off double buffer mode
08906    gVirtualX->SetDrawMode(TVirtualX::kInvert);  // set the drawing mode to XOR mode
08907 
08908    // Erase old position and draw a line at current position
08909    static int pxold1 = 0;
08910    static int pxold2 = 0;
08911    float uymin = gPad->GetUymin();
08912    float uymax = gPad->GetUymax();
08913    int pymin   = gPad->YtoAbsPixel(uymin);
08914    int pymax   = gPad->YtoAbsPixel(uymax);
08915    Float_t upx = gPad->AbsPixeltoX(px);
08916    Float_t x   = gPad->PadtoX(upx);
08917    Int_t binx1 = fH->GetXaxis()->FindBin(x);
08918    Int_t binx2 = TMath::Min(binx1+nbins-1, fH->GetXaxis()->GetNbins());
08919    Int_t px1   = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinLowEdge(binx1));
08920    Int_t px2   = gPad->XtoAbsPixel(fH->GetXaxis()->GetBinUpEdge(binx2));
08921 
08922    if (pxold1 || pxold2) gVirtualX->DrawBox(pxold1,pymin,pxold2,pymax,TVirtualX::kFilled);
08923    gVirtualX->DrawBox(px1,pymin,px2,pymax,TVirtualX::kFilled);
08924    pxold1 = px1;
08925    pxold2 = px2;
08926 
08927    // Create or set the new canvas proj y
08928    TVirtualPad *padsav = gPad;
08929    TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("%lx_c_projection_%d",
08930                                                                               (ULong_t)fH, fShowProjection));
08931    if(c) {
08932       c->Clear();
08933    } else {
08934       fShowProjection = 0;
08935       pxold1 = 0;
08936       pxold2 = 0;
08937       return;
08938    }
08939    c->cd();
08940    c->SetLogy(padsav->GetLogz());
08941    c->SetLogx(padsav->GetLogy());
08942 
08943    // Draw slice corresponding to mouse position
08944    TH1D *hp = ((TH2*)fH)->ProjectionY("_py", binx1, binx2);
08945    hp->SetFillColor(38);
08946    if (binx1 == binx2) hp->SetTitle(Form("ProjectionY of binx=%d", binx1));
08947    else hp->SetTitle(Form("ProjectionY of binx=[%d,%d]", binx1,binx2));
08948    hp->SetXTitle(fH->GetYaxis()->GetTitle());
08949    hp->SetYTitle("Number of Entries");
08950    hp->Draw();
08951    c->Update();
08952    padsav->cd();
08953 }
08954 
08955 
08956 //______________________________________________________________________________
08957 void THistPainter::ShowProjection3(Int_t px, Int_t py)
08958 {
08959    /* Begin_html
08960    Show projection (specified by <tt>fShowProjection</tt>) of a <tt>TH3</tt>.
08961    The drawing option for the projection is in <tt>fShowOption</tt>.
08962    <p>
08963    First implementation; R.Brun <br>
08964    Full implementation: Tim Tran (timtran@jlab.org)  April 2006
08965    End_html */
08966 
08967    Int_t nbins=(Int_t)fShowProjection/100; //decode nbins
08968    if (fH->GetDimension() < 3) {
08969       if (fShowProjection%100 == 1) {ShowProjectionX(px,py); return;}
08970       if (fShowProjection%100 == 2) {ShowProjectionY(px,py); return;}
08971    }
08972 
08973    gPad->SetDoubleBuffer(0);             // turn off double buffer mode
08974    gVirtualX->SetDrawMode(TVirtualX::kInvert);  // set the drawing mode to XOR mode
08975 
08976    // Erase old position and draw a line at current position
08977    TView *view = gPad->GetView();
08978    TH3 *h3 = (TH3*)fH;
08979    TAxis *xaxis = h3->GetXaxis();
08980    TAxis *yaxis = h3->GetYaxis();
08981    TAxis *zaxis = h3->GetZaxis();
08982    Double_t u[3],xx[3];
08983 
08984    static TPoint line1[2];//store end points of a line, initialised 0 by default
08985    static TPoint line2[2];// second line when slice thickness > 1 bin thickness
08986    static TPoint line3[2];
08987    static TPoint line4[2];
08988    static TPoint endface1[5];
08989    static TPoint endface2[5];
08990    static TPoint rect1[5];//store vertices of the polyline (rectangle), initialsed 0 by default
08991    static TPoint rect2[5];// second rectangle when slice thickness > 1 bin thickness
08992 
08993    Double_t value1=0, value2=0; //bin values cooresponding to the lower and upper bins of the slice
08994    Double_t uxmin = gPad->GetUxmin();
08995    Double_t uxmax = gPad->GetUxmax();
08996    Double_t uymin = gPad->GetUymin();
08997    Double_t uymax = gPad->GetUymax();
08998 
08999    int pxmin = gPad->XtoAbsPixel(uxmin);
09000    int pxmax = gPad->XtoAbsPixel(uxmax);
09001    int pymin = gPad->YtoAbsPixel(uymin);
09002    int pymax = gPad->YtoAbsPixel(uymax);
09003    Double_t cx    = (pxmax-pxmin)/(uxmax-uxmin);
09004    Double_t cy    = (pymax-pymin)/(uymax-uymin);
09005    TVirtualPad *padsav = gPad;
09006    TVirtualPad *c = (TVirtualPad*)gROOT->GetListOfCanvases()->FindObject(Form("%lx_c_projection_%d",
09007                                                                               (ULong_t)fH, fShowProjection));
09008    if(!c) {
09009       fShowProjection = 0;
09010       return;
09011    }
09012 
09013    switch ((Int_t)fShowProjection%100) {
09014       case 1:
09015          // "x"
09016          {
09017             Int_t firstY = yaxis->GetFirst();
09018             Int_t lastY  = yaxis->GetLast();
09019             Int_t biny = firstY + Int_t((lastY-firstY)*(px-pxmin)/(pxmax-pxmin));
09020             yaxis->SetRange(biny,biny+nbins-1);
09021             Int_t firstZ = zaxis->GetFirst();
09022             Int_t lastZ  = zaxis->GetLast();
09023             Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
09024             zaxis->SetRange(binz,binz+nbins-1);
09025             if(line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
09026             if (nbins>1 && line1[0].GetX()) {
09027                gVirtualX->DrawPolyLine(2,line2);
09028                gVirtualX->DrawPolyLine(2,line3);
09029                gVirtualX->DrawPolyLine(2,line4);
09030                gVirtualX->DrawPolyLine(5,endface1);
09031                gVirtualX->DrawPolyLine(5,endface2);
09032             }
09033             xx[0] = xaxis->GetXmin();
09034             xx[2] = zaxis->GetBinCenter(binz);
09035             xx[1] = yaxis->GetBinCenter(biny);
09036             view->WCtoNDC(xx,u);
09037             line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09038             line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09039             xx[0] = xaxis->GetXmax();
09040             view->WCtoNDC(xx,u);
09041             line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09042             line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09043             gVirtualX->DrawPolyLine(2,line1);
09044             if (nbins>1) {
09045                xx[0] = xaxis->GetXmin();
09046                xx[2] = zaxis->GetBinCenter(binz+nbins-1);
09047                xx[1] = yaxis->GetBinCenter(biny);
09048                view->WCtoNDC(xx,u);
09049                line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09050                line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09051                xx[0] = xaxis->GetXmax();
09052                view->WCtoNDC(xx,u);
09053                line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09054                line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09055 
09056                xx[0] = xaxis->GetXmin();
09057                xx[2] = zaxis->GetBinCenter(binz+nbins-1);
09058                xx[1] = yaxis->GetBinCenter(biny+nbins-1);
09059                view->WCtoNDC(xx,u);
09060                line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09061                line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09062                xx[0] = xaxis->GetXmax();
09063                view->WCtoNDC(xx,u);
09064                line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09065                line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09066 
09067                xx[0] = xaxis->GetXmin();
09068                xx[2] = zaxis->GetBinCenter(binz);
09069                xx[1] = yaxis->GetBinCenter(biny+nbins-1);
09070                view->WCtoNDC(xx,u);
09071                line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09072                line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09073                xx[0] = xaxis->GetXmax();
09074                view->WCtoNDC(xx,u);
09075                line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09076                line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09077 
09078                endface1[0].SetX(line1[0].GetX());
09079                endface1[0].SetY(line1[0].GetY());
09080                endface1[1].SetX(line2[0].GetX());
09081                endface1[1].SetY(line2[0].GetY());
09082                endface1[2].SetX(line3[0].GetX());
09083                endface1[2].SetY(line3[0].GetY());
09084                endface1[3].SetX(line4[0].GetX());
09085                endface1[3].SetY(line4[0].GetY());
09086                endface1[4].SetX(line1[0].GetX());
09087                endface1[4].SetY(line1[0].GetY());
09088 
09089                endface2[0].SetX(line1[1].GetX());
09090                endface2[0].SetY(line1[1].GetY());
09091                endface2[1].SetX(line2[1].GetX());
09092                endface2[1].SetY(line2[1].GetY());
09093                endface2[2].SetX(line3[1].GetX());
09094                endface2[2].SetY(line3[1].GetY());
09095                endface2[3].SetX(line4[1].GetX());
09096                endface2[3].SetY(line4[1].GetY());
09097                endface2[4].SetX(line1[1].GetX());
09098                endface2[4].SetY(line1[1].GetY());
09099 
09100                gVirtualX->DrawPolyLine(2,line2);
09101                gVirtualX->DrawPolyLine(2,line3);
09102                gVirtualX->DrawPolyLine(2,line4);
09103                gVirtualX->DrawPolyLine(5,endface1);
09104                gVirtualX->DrawPolyLine(5,endface2);
09105             }
09106             c->Clear();
09107             c->cd();
09108             TH1 *hp = h3->Project3D("x");
09109             yaxis->SetRange(firstY,lastY);
09110             zaxis->SetRange(firstZ,lastZ);
09111             hp->SetFillColor(38);
09112             hp->SetTitle(Form("ProjectionX of biny=%d binz=%d", biny, binz));
09113             hp->SetXTitle(fH->GetXaxis()->GetTitle());
09114             hp->SetYTitle("Number of Entries");
09115             hp->Draw(fShowOption.Data());
09116          }
09117          break;
09118 
09119       case 2:
09120          // "y"
09121          {
09122             Int_t firstX = xaxis->GetFirst();
09123             Int_t lastX  = xaxis->GetLast();
09124             Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
09125             xaxis->SetRange(binx,binx+nbins-1);
09126             Int_t firstZ = zaxis->GetFirst();
09127             Int_t lastZ  = zaxis->GetLast();
09128             Int_t binz = firstZ + Int_t((lastZ-firstZ)*(py-pymin)/(pymax-pymin));
09129             zaxis->SetRange(binz,binz+nbins-1);
09130             if(line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
09131             if (nbins>1 && line1[0].GetX()) {
09132                gVirtualX->DrawPolyLine(2,line2);
09133                gVirtualX->DrawPolyLine(2,line3);
09134                gVirtualX->DrawPolyLine(2,line4);
09135                gVirtualX->DrawPolyLine(5,endface1);
09136                gVirtualX->DrawPolyLine(5,endface2);
09137             }
09138             xx[0]=xaxis->GetBinCenter(binx);
09139             xx[2] = zaxis->GetBinCenter(binz);
09140             xx[1] = yaxis->GetXmin();
09141             view->WCtoNDC(xx,u);
09142             line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09143             line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09144             xx[1] = yaxis->GetXmax();
09145             view->WCtoNDC(xx,u);
09146             line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09147             line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09148             gVirtualX->DrawPolyLine(2,line1);
09149             if (nbins>1) {
09150                xx[1] = yaxis->GetXmin();
09151                xx[2] = zaxis->GetBinCenter(binz+nbins-1);
09152                xx[0] = xaxis->GetBinCenter(binx);
09153                view->WCtoNDC(xx,u);
09154                line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09155                line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09156                xx[1] = yaxis->GetXmax();
09157                view->WCtoNDC(xx,u);
09158                line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09159                line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09160 
09161                xx[1] = yaxis->GetXmin();
09162                xx[2] = zaxis->GetBinCenter(binz+nbins-1);
09163                xx[0] = xaxis->GetBinCenter(binx+nbins-1);
09164                view->WCtoNDC(xx,u);
09165                line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09166                line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09167                xx[1] = yaxis->GetXmax();
09168                view->WCtoNDC(xx,u);
09169                line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09170                line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09171 
09172                xx[1] = yaxis->GetXmin();
09173                xx[2] = zaxis->GetBinCenter(binz);
09174                xx[0] = xaxis->GetBinCenter(binx+nbins-1);
09175                view->WCtoNDC(xx,u);
09176                line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09177                line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09178                xx[1] = yaxis->GetXmax();
09179                view->WCtoNDC(xx,u);
09180                line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09181                line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09182 
09183                endface1[0].SetX(line1[0].GetX());
09184                endface1[0].SetY(line1[0].GetY());
09185                endface1[1].SetX(line2[0].GetX());
09186                endface1[1].SetY(line2[0].GetY());
09187                endface1[2].SetX(line3[0].GetX());
09188                endface1[2].SetY(line3[0].GetY());
09189                endface1[3].SetX(line4[0].GetX());
09190                endface1[3].SetY(line4[0].GetY());
09191                endface1[4].SetX(line1[0].GetX());
09192                endface1[4].SetY(line1[0].GetY());
09193 
09194                endface2[0].SetX(line1[1].GetX());
09195                endface2[0].SetY(line1[1].GetY());
09196                endface2[1].SetX(line2[1].GetX());
09197                endface2[1].SetY(line2[1].GetY());
09198                endface2[2].SetX(line3[1].GetX());
09199                endface2[2].SetY(line3[1].GetY());
09200                endface2[3].SetX(line4[1].GetX());
09201                endface2[3].SetY(line4[1].GetY());
09202                endface2[4].SetX(line1[1].GetX());
09203                endface2[4].SetY(line1[1].GetY());
09204 
09205                gVirtualX->DrawPolyLine(2,line2);
09206                gVirtualX->DrawPolyLine(2,line3);
09207                gVirtualX->DrawPolyLine(2,line4);
09208                gVirtualX->DrawPolyLine(5,endface1);
09209                gVirtualX->DrawPolyLine(5,endface2);
09210             }
09211             c->Clear();
09212             c->cd();
09213             TH1 *hp = h3->Project3D("y");
09214             xaxis->SetRange(firstX,lastX);
09215             zaxis->SetRange(firstZ,lastZ);
09216             hp->SetFillColor(38);
09217             hp->SetTitle(Form("ProjectionY of binx=%d binz=%d", binx, binz));
09218             hp->SetXTitle(fH->GetYaxis()->GetTitle());
09219             hp->SetYTitle("Number of Entries");
09220             hp->Draw(fShowOption.Data());
09221          }
09222          break;
09223 
09224       case 3:
09225          // "z"
09226          {
09227             Int_t firstX = xaxis->GetFirst();
09228             Int_t lastX  = xaxis->GetLast();
09229             Int_t binx = firstX + Int_t((lastX-firstX)*(px-pxmin)/(pxmax-pxmin));
09230             xaxis->SetRange(binx,binx+nbins-1);
09231             Int_t firstY = yaxis->GetFirst();
09232             Int_t lastY  = yaxis->GetLast();
09233             Int_t biny = firstY + Int_t((lastY-firstY)*(py-pymin)/(pymax-pymin));
09234             yaxis->SetRange(biny,biny+nbins-1);
09235             if(line1[0].GetX()) gVirtualX->DrawPolyLine(2,line1);
09236             if (nbins>1 && line1[0].GetX()) {
09237                gVirtualX->DrawPolyLine(2,line2);
09238                gVirtualX->DrawPolyLine(2,line3);
09239                gVirtualX->DrawPolyLine(2,line4);
09240                gVirtualX->DrawPolyLine(5,endface1);
09241                gVirtualX->DrawPolyLine(5,endface2);
09242             }
09243             xx[0] = xaxis->GetBinCenter(binx);
09244             xx[1] = yaxis->GetBinCenter(biny);
09245             xx[2] = zaxis->GetXmin();
09246             view->WCtoNDC(xx,u);
09247             line1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09248             line1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09249             xx[2] = zaxis->GetXmax();
09250             view->WCtoNDC(xx,u);
09251             line1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09252             line1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09253             gVirtualX->DrawPolyLine(2,line1);
09254             if (nbins>1) {
09255                xx[2] = zaxis->GetXmin();
09256                xx[1] = yaxis->GetBinCenter(biny+nbins-1);
09257                xx[0] = xaxis->GetBinCenter(binx);
09258                view->WCtoNDC(xx,u);
09259                line2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09260                line2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09261                xx[2] = zaxis->GetXmax();
09262                view->WCtoNDC(xx,u);
09263                line2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09264                line2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09265 
09266                xx[2] = zaxis->GetXmin();
09267                xx[1] = yaxis->GetBinCenter(biny+nbins-1);
09268                xx[0] = xaxis->GetBinCenter(binx+nbins-1);
09269                view->WCtoNDC(xx,u);
09270                line3[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09271                line3[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09272                xx[2] = zaxis->GetXmax();
09273                view->WCtoNDC(xx,u);
09274                line3[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09275                line3[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09276 
09277                xx[2] = zaxis->GetXmin();
09278                xx[1] = yaxis->GetBinCenter(biny);
09279                xx[0] = xaxis->GetBinCenter(binx+nbins-1);
09280                view->WCtoNDC(xx,u);
09281                line4[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09282                line4[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09283                xx[2] = zaxis->GetXmax();
09284                view->WCtoNDC(xx,u);
09285                line4[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09286                line4[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09287 
09288                endface1[0].SetX(line1[0].GetX());
09289                endface1[0].SetY(line1[0].GetY());
09290                endface1[1].SetX(line2[0].GetX());
09291                endface1[1].SetY(line2[0].GetY());
09292                endface1[2].SetX(line3[0].GetX());
09293                endface1[2].SetY(line3[0].GetY());
09294                endface1[3].SetX(line4[0].GetX());
09295                endface1[3].SetY(line4[0].GetY());
09296                endface1[4].SetX(line1[0].GetX());
09297                endface1[4].SetY(line1[0].GetY());
09298 
09299                endface2[0].SetX(line1[1].GetX());
09300                endface2[0].SetY(line1[1].GetY());
09301                endface2[1].SetX(line2[1].GetX());
09302                endface2[1].SetY(line2[1].GetY());
09303                endface2[2].SetX(line3[1].GetX());
09304                endface2[2].SetY(line3[1].GetY());
09305                endface2[3].SetX(line4[1].GetX());
09306                endface2[3].SetY(line4[1].GetY());
09307                endface2[4].SetX(line1[1].GetX());
09308                endface2[4].SetY(line1[1].GetY());
09309 
09310                gVirtualX->DrawPolyLine(2,line2);
09311                gVirtualX->DrawPolyLine(2,line3);
09312                gVirtualX->DrawPolyLine(2,line4);
09313                gVirtualX->DrawPolyLine(5,endface1);
09314                gVirtualX->DrawPolyLine(5,endface2);
09315             }
09316             c->Clear();
09317             c->cd();
09318             TH1 *hp = h3->Project3D("z");
09319             xaxis->SetRange(firstX,lastX);
09320             yaxis->SetRange(firstY,lastY);
09321             hp->SetFillColor(38);
09322             hp->SetTitle(Form("ProjectionZ of binx=%d biny=%d", binx, biny));
09323             hp->SetXTitle(fH->GetZaxis()->GetTitle());
09324             hp->SetYTitle("Number of Entries");
09325             hp->Draw(fShowOption.Data());
09326          }
09327          break;
09328 
09329       case 4:
09330          // "xy"
09331          {
09332             Int_t first = zaxis->GetFirst();
09333             Int_t last  = zaxis->GetLast();
09334             Int_t binz  = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
09335             zaxis->SetRange(binz,binz+nbins-1);
09336             if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
09337             if(nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
09338             xx[0] = xaxis->GetXmin();
09339             xx[1] = yaxis->GetXmax();
09340             xx[2] = zaxis->GetBinCenter(binz);
09341             value1=xx[2]; // for screen display
09342             view->WCtoNDC(xx,u);
09343             rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09344             rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09345             rect1[4].SetX(rect1[0].GetX());
09346             rect1[4].SetY(rect1[0].GetY());
09347             xx[0] = xaxis->GetXmax();
09348             view->WCtoNDC(xx,u);
09349             rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09350             rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09351             xx[1] = yaxis->GetXmin();
09352             view->WCtoNDC(xx,u);
09353             rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09354             rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09355             xx[0] = xaxis->GetXmin();
09356             view->WCtoNDC(xx,u);
09357             rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09358             rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09359             gVirtualX->DrawPolyLine(5,rect1);
09360             if (nbins>1) {
09361                xx[0] = xaxis->GetXmin();
09362                xx[1] = yaxis->GetXmax();
09363                xx[2] = zaxis->GetBinCenter(binz+nbins-1);
09364                value2=xx[2];
09365                view->WCtoNDC(xx,u);
09366                rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09367                rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09368                rect2[4].SetX(rect2[0].GetX());
09369                rect2[4].SetY(rect2[0].GetY());
09370                xx[0] = xaxis->GetXmax();
09371                view->WCtoNDC(xx,u);
09372                rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09373                rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09374                xx[1] = yaxis->GetXmin();
09375                view->WCtoNDC(xx,u);
09376                rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09377                rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09378                xx[0] = xaxis->GetXmin();
09379                view->WCtoNDC(xx,u);
09380                rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09381                rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09382                gVirtualX->DrawPolyLine(5,rect2);
09383             }
09384 
09385             c->Clear();
09386             c->cd();
09387             TH2 *hp = (TH2*)h3->Project3D("xy");
09388             zaxis->SetRange(first,last);
09389             hp->SetFillColor(38);
09390             if(nbins==1)hp->SetTitle(Form("ProjectionXY of binz=%d (%.1f)", binz,value1));
09391             else        hp->SetTitle(Form("ProjectionXY, binz range=%d-%d (%.1f-%.1f)", binz,binz+nbins-1,value1,value2));
09392             hp->SetXTitle(fH->GetYaxis()->GetTitle());
09393             hp->SetYTitle(fH->GetXaxis()->GetTitle());
09394             hp->SetZTitle("Number of Entries");
09395             hp->Draw(fShowOption.Data());
09396          }
09397          break;
09398 
09399       case 5:
09400          // "yx"
09401          {
09402             Int_t first = zaxis->GetFirst();
09403             Int_t last  = zaxis->GetLast();
09404             Int_t binz = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
09405             zaxis->SetRange(binz,binz+nbins-1);
09406             if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
09407             if(nbins>1 && rect2[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
09408             xx[0] = xaxis->GetXmin();
09409             xx[1] = yaxis->GetXmax();
09410             xx[2] = zaxis->GetBinCenter(binz);
09411             value1=xx[2]; // for screen display
09412             view->WCtoNDC(xx,u);
09413             rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09414             rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09415             rect1[4].SetX(rect1[0].GetX());
09416             rect1[4].SetY(rect1[0].GetY());
09417             xx[0] = xaxis->GetXmax();
09418             view->WCtoNDC(xx,u);
09419             rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09420             rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09421             xx[1] = yaxis->GetXmin();
09422             view->WCtoNDC(xx,u);
09423             rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09424             rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09425             xx[0] = xaxis->GetXmin();
09426             view->WCtoNDC(xx,u);
09427             rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09428             rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09429             gVirtualX->DrawPolyLine(5,rect1);
09430             if (nbins>1) {
09431                xx[0] = xaxis->GetXmin();
09432                xx[1] = yaxis->GetXmax();
09433                xx[2] = zaxis->GetBinCenter(binz+nbins-1);
09434                value2=xx[2];
09435                view->WCtoNDC(xx,u);
09436                rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09437                rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09438                rect2[4].SetX(rect2[0].GetX());
09439                rect2[4].SetY(rect2[0].GetY());
09440                xx[0] = xaxis->GetXmax();
09441                view->WCtoNDC(xx,u);
09442                rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09443                rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09444                xx[1] = yaxis->GetXmin();
09445                view->WCtoNDC(xx,u);
09446                rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09447                rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09448                xx[0] = xaxis->GetXmin();
09449                view->WCtoNDC(xx,u);
09450                rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09451                rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09452                gVirtualX->DrawPolyLine(5,rect2);
09453             }
09454             c->Clear();
09455             c->cd();
09456             TH2 *hp = (TH2*)h3->Project3D("yx");
09457             zaxis->SetRange(first,last);
09458             hp->SetFillColor(38);
09459             if(nbins==1)hp->SetTitle(Form("ProjectionYX of binz=%d (%.1f)", binz,value1));
09460             else        hp->SetTitle(Form("ProjectionXY, binz range=%d-%d (%.1f-%.1f)", binz,binz+nbins-1,value1,value2));
09461             hp->SetXTitle(fH->GetXaxis()->GetTitle());
09462             hp->SetYTitle(fH->GetYaxis()->GetTitle());
09463             hp->SetZTitle("Number of Entries");
09464             hp->Draw(fShowOption.Data());
09465          }
09466          break;
09467 
09468       case 6:
09469          // "xz"
09470          {
09471             Int_t first = yaxis->GetFirst();
09472             Int_t last  = yaxis->GetLast();
09473             Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
09474             yaxis->SetRange(biny,biny+nbins-1);
09475             if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
09476             if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
09477             xx[0] = xaxis->GetXmin();
09478             xx[2] = zaxis->GetXmax();
09479             xx[1] = yaxis->GetBinCenter(biny);
09480             value1=xx[1];
09481             view->WCtoNDC(xx,u);
09482             rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09483             rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09484             rect1[4].SetX(rect1[0].GetX());
09485             rect1[4].SetY(rect1[0].GetY());
09486             xx[0] = xaxis->GetXmax();
09487             view->WCtoNDC(xx,u);
09488             rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09489             rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09490             xx[2] = zaxis->GetXmin();
09491             view->WCtoNDC(xx,u);
09492             rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09493             rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09494             xx[0] = xaxis->GetXmin();
09495             view->WCtoNDC(xx,u);
09496             rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09497             rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09498             gVirtualX->DrawPolyLine(5,rect1);
09499             if (nbins>1) {
09500                xx[0] = xaxis->GetXmin();
09501                xx[2] = zaxis->GetXmax();
09502                xx[1] = yaxis->GetBinCenter(biny+nbins-1);
09503                value2=xx[1];
09504                view->WCtoNDC(xx,u);
09505                rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09506                rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09507                rect2[4].SetX(rect2[0].GetX());
09508                rect2[4].SetY(rect2[0].GetY());
09509                xx[0] = xaxis->GetXmax();
09510                view->WCtoNDC(xx,u);
09511                rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09512                rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09513                xx[2] = zaxis->GetXmin();
09514                view->WCtoNDC(xx,u);
09515                rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09516                rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09517                xx[0] = xaxis->GetXmin();
09518                view->WCtoNDC(xx,u);
09519                rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09520                rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09521                gVirtualX->DrawPolyLine(5,rect2);
09522             }
09523             c->Clear();
09524             c->cd();
09525             TH2 *hp = (TH2*)h3->Project3D("xz");
09526             yaxis->SetRange(first,last);
09527             hp->SetFillColor(38);
09528             if(nbins==1)hp->SetTitle(Form("ProjectionXZ of biny=%d (%.1f)", biny,value1));
09529             else        hp->SetTitle(Form("ProjectionXZ, biny range=%d-%d (%.1f-%.1f)", biny,biny+nbins-1,value1,value2));
09530             hp->SetXTitle(fH->GetZaxis()->GetTitle());
09531             hp->SetYTitle(fH->GetXaxis()->GetTitle());
09532             hp->SetZTitle("Number of Entries");
09533             hp->Draw(fShowOption.Data());
09534          }
09535          break;
09536 
09537       case 7:
09538          // "zx"
09539          {
09540             Int_t first = yaxis->GetFirst();
09541             Int_t last  = yaxis->GetLast();
09542             Int_t biny = first + Int_t((last-first)*(py-pymin)/(pymax-pymin));
09543             yaxis->SetRange(biny,biny+nbins-1);
09544             if(rect1[0].GetX())            gVirtualX->DrawPolyLine(5,rect1);
09545             if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
09546             xx[0] = xaxis->GetXmin();
09547             xx[2] = zaxis->GetXmax();
09548             xx[1] = yaxis->GetBinCenter(biny);
09549             value1=xx[1];
09550             view->WCtoNDC(xx,u);
09551             rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09552             rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09553             rect1[4].SetX(rect1[0].GetX());
09554             rect1[4].SetY(rect1[0].GetY());
09555             xx[0] = xaxis->GetXmax();
09556             view->WCtoNDC(xx,u);
09557             rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09558             rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09559             xx[2] = zaxis->GetXmin();
09560             view->WCtoNDC(xx,u);
09561             rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09562             rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09563             xx[0] = xaxis->GetXmin();
09564             view->WCtoNDC(xx,u);
09565             rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09566             rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09567             gVirtualX->DrawPolyLine(5,rect1);
09568             if (nbins>1) {
09569                xx[0] = xaxis->GetXmin();
09570                xx[2] = zaxis->GetXmax();
09571                xx[1] = yaxis->GetBinCenter(biny+nbins-1);
09572                value2=xx[1];
09573                view->WCtoNDC(xx,u);
09574                rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09575                rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09576                rect2[4].SetX(rect2[0].GetX());
09577                rect2[4].SetY(rect2[0].GetY());
09578                xx[0] = xaxis->GetXmax();
09579                view->WCtoNDC(xx,u);
09580                rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09581                rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09582                xx[2] = zaxis->GetXmin();
09583                view->WCtoNDC(xx,u);
09584                rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09585                rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09586                xx[0] = xaxis->GetXmin();
09587                view->WCtoNDC(xx,u);
09588                rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09589                rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09590                gVirtualX->DrawPolyLine(5,rect2);
09591             }
09592             c->Clear();
09593             c->cd();
09594             TH2 *hp = (TH2*)h3->Project3D("zx");
09595             yaxis->SetRange(first,last);
09596             hp->SetFillColor(38);
09597             if(nbins==1)hp->SetTitle(Form("ProjectionZX of biny=%d (%.1f)", biny,value1));
09598             else        hp->SetTitle(Form("ProjectionZX, binY range=%d-%d (%.1f-%.1f)", biny,biny+nbins-1,value1,value2));
09599             hp->SetXTitle(fH->GetXaxis()->GetTitle());
09600             hp->SetYTitle(fH->GetZaxis()->GetTitle());
09601             hp->SetZTitle("Number of Entries");
09602             hp->Draw(fShowOption.Data());
09603          }
09604          break;
09605 
09606       case 8:
09607          // "yz"
09608          {
09609             Int_t first = xaxis->GetFirst();
09610             Int_t last  = xaxis->GetLast();
09611             Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
09612             xaxis->SetRange(binx,binx+nbins-1);
09613             if(rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
09614             if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
09615             xx[2] = zaxis->GetXmin();
09616             xx[1] = yaxis->GetXmax();
09617             xx[0] = xaxis->GetBinCenter(binx);
09618             value1=xx[0];
09619             view->WCtoNDC(xx,u);
09620             rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09621             rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09622             rect1[4].SetX(rect1[0].GetX());
09623             rect1[4].SetY(rect1[0].GetY());
09624             xx[2] = zaxis->GetXmax();
09625             view->WCtoNDC(xx,u);
09626             rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09627             rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09628             xx[1] = yaxis->GetXmin();
09629             view->WCtoNDC(xx,u);
09630             rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09631             rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09632             xx[2] = zaxis->GetXmin();
09633             view->WCtoNDC(xx,u);
09634             rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09635             rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09636             gVirtualX->DrawPolyLine(5,rect1);
09637             if (nbins>1) {
09638                xx[2] = zaxis->GetXmin();
09639                xx[1] = yaxis->GetXmax();
09640                xx[0] = xaxis->GetBinCenter(binx+nbins-1);
09641                value2=xx[0];
09642                view->WCtoNDC(xx,u);
09643                rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09644                rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09645                rect2[4].SetX(rect2[0].GetX());
09646                rect2[4].SetY(rect2[0].GetY());
09647                xx[2] = zaxis->GetXmax();
09648                view->WCtoNDC(xx,u);
09649                rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09650                rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09651                xx[1] = yaxis->GetXmin();
09652                view->WCtoNDC(xx,u);
09653                rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09654                rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09655                xx[2] = zaxis->GetXmin();
09656                view->WCtoNDC(xx,u);
09657                rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09658                rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09659                gVirtualX->DrawPolyLine(5,rect2);
09660             }
09661             c->Clear();
09662             c->cd();
09663             TH2 *hp = (TH2*)h3->Project3D("yz");
09664             xaxis->SetRange(first,last);
09665             hp->SetFillColor(38);
09666             if(nbins==1)hp->SetTitle(Form("ProjectionYZ of binx=%d (%.1f)", binx,value1));
09667             else        hp->SetTitle(Form("ProjectionYZ, binx range=%d-%d (%.1f-%.1f)", binx,binx+nbins-1,value1,value2));
09668             hp->SetXTitle(fH->GetZaxis()->GetTitle());
09669             hp->SetYTitle(fH->GetYaxis()->GetTitle());
09670             hp->SetZTitle("Number of Entries");
09671             hp->Draw(fShowOption.Data());
09672          }
09673          break;
09674 
09675       case 9:
09676          // "zy"
09677          {
09678             Int_t first = xaxis->GetFirst();
09679             Int_t last  = xaxis->GetLast();
09680             Int_t binx = first + Int_t((last-first)*(px-pxmin)/(pxmax-pxmin));
09681             xaxis->SetRange(binx,binx+nbins-1);
09682             if(rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect1);
09683             if(nbins>1 && rect1[0].GetX()) gVirtualX->DrawPolyLine(5,rect2);
09684             xx[2] = zaxis->GetXmin();
09685             xx[1] = yaxis->GetXmax();
09686             xx[0] = xaxis->GetBinCenter(binx);
09687             value1=xx[0];
09688             view->WCtoNDC(xx,u);
09689             rect1[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09690             rect1[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09691             rect1[4].SetX(rect1[0].GetX());
09692             rect1[4].SetY(rect1[0].GetY());
09693             xx[2] = zaxis->GetXmax();
09694             view->WCtoNDC(xx,u);
09695             rect1[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09696             rect1[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09697             xx[1] = yaxis->GetXmin();
09698             view->WCtoNDC(xx,u);
09699             rect1[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09700             rect1[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09701             xx[2] = zaxis->GetXmin();
09702             view->WCtoNDC(xx,u);
09703             rect1[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09704             rect1[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09705             gVirtualX->DrawPolyLine(5,rect1);
09706             if (nbins>1) {
09707                xx[2] = zaxis->GetXmin();
09708                xx[1] = yaxis->GetXmax();
09709                xx[0] = xaxis->GetBinCenter(binx+nbins-1);
09710                value2=xx[0];
09711                view->WCtoNDC(xx,u);
09712                rect2[0].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09713                rect2[0].SetY(pymin + Int_t((u[1]-uymin)*cy));
09714                rect2[4].SetX(rect2[0].GetX());
09715                rect2[4].SetY(rect2[0].GetY());
09716                xx[2] = zaxis->GetXmax();
09717                view->WCtoNDC(xx,u);
09718                rect2[1].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09719                rect2[1].SetY(pymin + Int_t((u[1]-uymin)*cy));
09720                xx[1] = yaxis->GetXmin();
09721                view->WCtoNDC(xx,u);
09722                rect2[2].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09723                rect2[2].SetY(pymin + Int_t((u[1]-uymin)*cy));
09724                xx[2] = zaxis->GetXmin();
09725                view->WCtoNDC(xx,u);
09726                rect2[3].SetX(pxmin + Int_t((u[0]-uxmin)*cx));
09727                rect2[3].SetY(pymin + Int_t((u[1]-uymin)*cy));
09728                gVirtualX->DrawPolyLine(5,rect2);
09729             }
09730             c->Clear();
09731             c->cd();
09732             TH2 *hp = (TH2*)h3->Project3D("zy");
09733             xaxis->SetRange(first,last);
09734             hp->SetFillColor(38);
09735 
09736             if(nbins==1)hp->SetTitle(Form("ProjectionZY of binx=%d (%.1f)", binx,value1));
09737             else        hp->SetTitle(Form("ProjectionZY, binx range=%d-%d (%.1f-%.1f)", binx,binx+nbins-1,value1,value2));
09738             hp->SetXTitle(fH->GetYaxis()->GetTitle());
09739             hp->SetYTitle(fH->GetZaxis()->GetTitle());
09740             hp->SetZTitle("Number of Entries");
09741             hp->Draw(fShowOption.Data());
09742          }
09743          break;
09744 
09745    }
09746    c->Update();
09747    padsav->cd();
09748 }

Generated on Tue Jul 5 14:24:30 2011 for ROOT_528-00b_version by  doxygen 1.5.1