Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
DynamicSlice.py
Go to the documentation of this file.
1 ## \file
2 ## \ingroup tutorial_pyroot
3 ## \notebook
4 ## Example of function called when a mouse event occurs in a pad.
5 ## When moving the mouse in the canvas, a second canvas shows the
6 ## projection along X of the bin corresponding to the Y position
7 ## of the mouse. The resulting histogram is fitted with a gaussian.
8 ## A "dynamic" line shows the current bin position in Y.
9 ## This more elaborated example can be used as a starting point
10 ## to develop more powerful interactive applications exploiting CINT
11 ## as a development engine.
12 ##
13 ## Note that a class is used to hold on to the canvas that display
14 ## the selected slice.
15 ##
16 ## \macro_image
17 ## \macro_code
18 ##
19 ## \author Rene Brun, Johann Cohen-Tanugi, Wim Lavrijsen, Enric Tejedor
20 
21 import sys
22 import ctypes
23 
24 from ROOT import gRandom, gPad, gROOT, gVirtualX
25 from ROOT import kTRUE, kRed
26 from ROOT import TCanvas, TH2, TH2F
27 
28 
29 class DynamicExec:
30 
31  def __init__( self ):
32  self._cX = None
33  self._cY = None
34  self._old = None
35 
36  def __call__( self ):
37 
38  h = gPad.GetSelected();
39  if not h:
40  return
41 
42  if not isinstance( h, TH2 ):
43  return
44 
45  gPad.GetCanvas().FeedbackMode( kTRUE )
46 
47  # erase old position and draw a line at current position
48  px = gPad.GetEventX()
49  py = gPad.GetEventY()
50 
51  uxmin, uxmax = gPad.GetUxmin(), gPad.GetUxmax()
52  uymin, uymax = gPad.GetUymin(), gPad.GetUymax()
53  pxmin, pxmax = gPad.XtoAbsPixel( uxmin ), gPad.XtoAbsPixel( uxmax )
54  pymin, pymax = gPad.YtoAbsPixel( uymin ), gPad.YtoAbsPixel( uymax )
55 
56  if self._old != None:
57  gVirtualX.DrawLine( pxmin, self._old[1], pxmax, self._old[1] )
58  gVirtualX.DrawLine( self._old[0], pymin, self._old[0], pymax )
59  gVirtualX.DrawLine( pxmin, py, pxmax, py )
60  gVirtualX.DrawLine( px, pymin, px, pymax )
61 
62  self._old = px, py
63 
64  upx = gPad.AbsPixeltoX( px )
65  x = gPad.PadtoX( upx )
66  upy = gPad.AbsPixeltoY( py )
67  y = gPad.PadtoY( upy )
68 
69  padsav = gPad
70 
71  # create or set the display canvases
72  if not self._cX:
73  self._cX = TCanvas( 'c2', 'Projection Canvas in X', 730, 10, 700, 500 )
74  else:
75  self._DestroyPrimitive( 'X' )
76 
77  if not self._cY:
78  self._cY = TCanvas( 'c3', 'Projection Canvas in Y', 10, 550, 700, 500 )
79  else:
80  self._DestroyPrimitive( 'Y' )
81 
82  self.DrawSlice( h, y, 'Y' )
83  self.DrawSlice( h, x, 'X' )
84 
85  padsav.cd()
86 
87  def _DestroyPrimitive( self, xy ):
88  proj = getattr( self, '_c'+xy ).GetPrimitive( 'Projection '+xy )
89  if proj:
90  proj.IsA().Destructor( proj )
91 
92  def DrawSlice( self, histo, value, xy ):
93  yx = xy == 'X' and 'Y' or 'X'
94 
95  # draw slice corresponding to mouse position
96  canvas = getattr( self, '_c'+xy )
97  canvas.SetGrid()
98  canvas.cd()
99 
100  bin = getattr( histo, 'Get%saxis' % xy )().FindBin( value )
101  hp = getattr( histo, 'Projection' + yx )( '', bin, bin )
102  hp.SetFillColor( 38 )
103  hp.SetName( 'Projection ' + xy )
104  hp.SetTitle( xy + 'Projection of bin=%d' % bin )
105  hp.Fit( 'gaus', 'ql' )
106  hp.GetFunction( 'gaus' ).SetLineColor( kRed )
107  hp.GetFunction( 'gaus' ).SetLineWidth( 6 )
108  canvas.Update()
109 
110 
111 if __name__ == '__main__':
112  # create a new canvas.
113  c1 = TCanvas('c1', 'Dynamic Slice Example', 10, 10, 700, 500 )
114  c1.SetFillColor( 42 )
115  c1.SetFrameFillColor( 33 )
116 
117  # create a 2-d histogram, fill and draw it
118  hpxpy = TH2F( 'hpxpy', 'py vs px', 40, -4, 4, 40, -4, 4 )
119  hpxpy.SetStats( 0 )
120  x, y = ctypes.c_double( 0.1 ), ctypes.c_double( 0.101 )
121  for i in range( 50000 ):
122  # pass ctypes doubles by reference, then retrieve their modified values with .value
123  gRandom.Rannor( x, y )
124  hpxpy.Fill( x.value, y.value )
125  hpxpy.Draw( 'COL' )
126 
127  # Add a TExec object to the canvas (explicit use of __main__ is for IPython)
128  import __main__
129  __main__.slicer = DynamicExec()
130  c1.AddExec( 'dynamic', 'TPython::Exec( "slicer()" );' )
131  c1.Update()