Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > ab972abb34adf97ebe2e94ab6b5a0050 > files > 82

HippoDraw-1.21.1-14.fc15.i686.rpm

<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>HippoDraw Documenation</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="lib/hippoApp.ico">
</head><body>
<!-- Generated by Doxygen 1.7.3 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
    </ul>
  </div>
</div>
<div class="header">
  <div class="headertitle">
<h1>Python extension module tutorial </h1>  </div>
</div>
<div class="contents">
<div class="textblock"><p>The <b>hippo</b> Python extension module is designed to be used interactively or via Python scripts.</p>
<p>Thus the interface is somewhat different from the C++ interface to the <b>HippoDraw</b> library.</p>
<p>Using <b>HippoDraw</b> interactively can be as simple as two lines of Python code. Below is an example session.</p>
<div class="fragment"><pre class="fragment">
&gt; python
Python 2.4 (#2, Apr 15 2005, 17:09:59)
[GCC 3.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import hippo
&gt;&gt;&gt; app = hippo.HDApp()
&gt;&gt;&gt;
</pre></div><p>Obviously, even typing these two lines for every session can get boring. Instead one can put the commands in a file and use that as initialization step for the Python session. For example, the file, <em>canvas.py</em>, in the testsuite directory contains</p>
<div class="fragment"><pre class="fragment">
import hippo
app = hippo.HDApp()
canvas = app.canvas()
</pre></div><p>where we also show how to get a handle on the current canvas window. One can run this script from a UNIX shell or Windows command prompt like this</p>
<div class="fragment"><pre class="fragment">
&gt; python -i canvas.py
&gt;&gt;&gt;
</pre></div><p>This launches the complete <b>HippoDraw</b> application in a separate thread with the ability to interact with it from the Python shell.</p>
<h2><a class="anchor" id="python_interact_help"></a>
Getting help and documentation</h2>
<p>Python has interactive help system. The get all help for the <em>hippo</em> module, just do the following...</p>
<div class="fragment"><pre class="fragment">
&gt; python
Python 2.4 (#2, Apr 15 2005, 17:09:59)
[GCC 3.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import hippo
&gt;&gt;&gt; help ( hippo )
</pre></div><p>This gives you all the built-in documentation in a pager like the UNIX <em>more</em> or <em>less</em> command which is not always convienent. However, one can get the documentation on one class by ...</p>
<div class="fragment"><pre class="fragment">
&gt; python
Python 2.4 (#2, Apr 15 2005, 17:09:59)
[GCC 3.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import hippo
&gt;&gt;&gt; help ( hippo.HDApp )
</pre></div><p>Or even one member function like this ...</p>
<div class="fragment"><pre class="fragment">
&gt; python
Python 2.4 (#2, Apr 15 2005, 17:09:59)
[GCC 3.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import hippo
&gt;&gt;&gt; help ( hippo.HDApp.canvas )
</pre></div><p>Another way to access the same information is to use the <em>pydoc</em> program that came with your Python installation (except under Windows).</p>
<div class="fragment"><pre class="fragment">
&gt; pydoc hippo
</pre></div><p>This also gives you all the built-in help in a pager. Probably the most convienent method is to generate html version of the documentation. You do this by typing ...</p>
<div class="fragment"><pre class="fragment">
&gt; pydoc -w hippo
</pre></div><p>and a <em> hippo.html </em> file is created in your working directory. <a href="hippo.html">Here</a> is what it looks like. Not very pretty, but it is the standard ouput from <em>pydoc</em>. You can use this link as your documentation for <b>HippoDraw</b>. However, it will get updated for each release and you may be using an older version.</p>
<p>The following sections shows and explains some example script. See also <a class="el" href="examples_page.html">Examples of HippoDraw use with Python</a> for more examples</p>
<h2><a class="anchor" id="python_interact_generate"></a>
Creating the NTuple in Python</h2>
<p>One might generate some data in Python that you want to display with <b>HippoDraw</b>. For example, you could generate a Python list with random Gaussian distribution like this</p>
<div class="fragment"><pre class="fragment">
&gt;&gt;&gt; import random
&gt;&gt;&gt; x = []
&gt;&gt;&gt; for i in range ( 10000 ) :
...     x.append ( random.gauss ( 45, 10 ) )
...
&gt;&gt;&gt;
</pre></div><p>To display the data as a histogram, one can then type</p>
<div class="fragment"><pre class="fragment">
&gt;&gt;&gt; from hippo import Display
&gt;&gt;&gt; hist = Display ( 'Histogram', ( x, ), ('Gaussian', ) )
&gt;&gt;&gt; canvas.addDisplay ( hist )
&gt;&gt;&gt;
</pre></div><p>The first argument to the Display function specifies the type of display to create. The second is a Python tuple of Python list objects that will be used by the display. The third argument is a Python tuple of string labels for the lists.</p>
<p>You can now modify the plot, for example, changing the width of the bins in two ways. From the Python shell, one can invoke a member function of the histogram object like this...</p>
<div class="fragment"><pre class="fragment">
&gt;&gt;&gt; hist.setBinWidth ( 'x', 2 )
&gt;&gt;&gt;
</pre></div><p>But it is much easier to use <a class="el" href="inspector_root.html#inspector_axis">Axis inspector</a> and change it with the slider or text field.</p>
<p>The function created a DataSource called a ListTuple. It holds references to the Python list objects as columns. The list is not copied, just referenced. It also holds the labels of each column. Displays don't redraw themselves unless they know there's been a change, like changing the bin width. But should the contents of your Python list change, the Display wouldn't know about it. But you can force the display to redraw like this...</p>
<div class="fragment"><pre class="fragment">
&gt;&gt;&gt; hist.update()
&gt;&gt;&gt;
</pre></div><p>The Python tuple of strings provide the data source labels, but they also giving the bindings of the displays to the data source. Some displays have binding that are optional. For the example, an "XY
Plot" display had binding for the X and Y axis, and optionally, for an error on X or Y. To say which optional bindings not to use the "nil" column label is used. The we can do the following</p>
<div class="fragment"><pre class="fragment">"""
   Demonstrates making simple XY plot.  

   author Paul F. Kunz &lt;Paul_Kunz@slac.stanford.edu&gt;
"""
#
# load the HippoDraw module
#
from load_hippo import app, canvas

from hippo import Display

# Create list of data
energy = [90.74, 91.06, 91.43, 91.50, 92.16, 92.22, 92.96, 89.24, 89.98, 90.35]
sigma  = [ 29.0, 30.0,  28.40, 28.80, 21.95, 22.90, 13.50,  4.50, 10.80, 24.20]
errors = [  5.9,  3.15,  3.0,   5.8,  7.9,   3.1,   4.6,    3.5,   4.6,   3.6]

# make a plot to test it.
xy = Display ( "XY Plot", [ energy, sigma, errors ],
               ['Energy', 'Sigma', 'nil', 'error' ] )

canvas.addDisplay ( xy )

xy.setTitle ( 'Mark II Z0 scan' )

print "An XY plot is now displayed.   You can use the Inspector dialog"
print "to modify the appearance or fit a function to it."
</pre></div><p>The "nil" string can also be use by the <a class="el" href="inspector_root.html#inspector_data">Data inspector</a> as well. Note in this example, we used list of lists instead of tuple of lists. Either can be used.</p>
<p>Speaking of the <b>Data</b> <b>Inspector</b>, sometimes it is more convenient to give <b>HippoDraw</b> all the data you might want to use for displays, and use the <b>Data</b> <b>Inspector</b> to create them. To do this, one creates a DataSource manually. There are three kinds supported: ListTuple, NTuple, and NumArrayTuple. They share a common interface and differ on how they store the column data. As we've seen, the ListTuple stores references to Python list objects. The NTuple makes copies of Python list objects and stores it internally as a C++ vector of doubles. The NumArrayTuple stores references to rank 1 <a href="http://www.stsci.edu/resources/software_hardware/numarray">numarray </a> objects. The NTuple has the feature that you can add and replace rows or columns.</p>
<p>Creating displays with the DataInspector doesn't preclude one from also creating them with Python. The interface is similar to what we've already seen. For example</p>
<div class="fragment"><pre class="fragment">
&gt;&gt;&gt; energy = [90.74, 91.06, 91.43, 91.5, 92.16, 92.22, 92.96, 89.24, 89.98 ]
&gt;&gt;&gt; sigma  = [ 29.0, 30.0,  28.40, 28.8, 21.95, 22.9,  13.5,   4.5,  10.8 ]
&gt;&gt;&gt; errors = [  5.9,  3.15,  3.0,   5.8,  7.9,   3.1,   4.6,   3.5,   4.6,]
&gt;&gt;&gt; ntuple = NTuple () # an empty NTuple
&gt;&gt;&gt; ntc = NTupleController.instance ()
&gt;&gt;&gt; ntc.registerNTuple ( ntuple )
&gt;&gt;&gt; ntuple.addColumn ( 'Energy', energy )
&gt;&gt;&gt; ntuple.addColumn ( 'Sigma', sigma )
&gt;&gt;&gt; ntuple.addColumn ( 'error', errors )

&gt;&gt;&gt; xy = Display ( "XY Plot", ntuple,  ('Energy', 'Sigma', 'nil', 'error' ) )
&gt;&gt;&gt; canvas.addDisplay ( xy )
&gt;&gt;&gt;
</pre></div><p>Registering the ntuple with the NTupleController is necessary in order for the <b>Data</b> <b>Inspector</b> to know of their existence.</p>
<h2><a class="anchor" id="python_interact_file"></a>
Getting data from a file</h2>
<p>An NTuple data source can also be created by reading a plain text file. See <a class="el" href="files_root.html#file_ascii">ASCII file</a> for the details. The example file, <em>histogram.py</em>, in the testsuite directory shows how to read a file and create displays from Python. It contains ...</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="stringliteral">&quot;&quot;&quot; -*- mode: python -*-</span>
<a name="l00002"></a>00002 <span class="stringliteral"></span>
<a name="l00003"></a>00003 <span class="stringliteral">This script tests the creation and modification of Histogram along</span>
<a name="l00004"></a>00004 <span class="stringliteral">with some test of exception handling.</span>
<a name="l00005"></a>00005 <span class="stringliteral"></span>
<a name="l00006"></a>00006 <span class="stringliteral">Copyright (C) 2001, 2003, 2004   The Board of Trustees of The Leland</span>
<a name="l00007"></a>00007 <span class="stringliteral">Stanford Junior University.  All Rights Reserved.</span>
<a name="l00008"></a>00008 <span class="stringliteral"></span>
<a name="l00009"></a>00009 <span class="stringliteral">@author Paul F. Kunz &lt;Paul_Kunz@slac.stanford.edu&gt;</span>
<a name="l00010"></a>00010 <span class="stringliteral"></span>
<a name="l00011"></a>00011 <span class="stringliteral">$Id: histogram.py.in,v 1.26 2006/02/15 19:29:56 pfkeb Exp $</span>
<a name="l00012"></a>00012 <span class="stringliteral"></span>
<a name="l00013"></a>00013 <span class="stringliteral">&quot;&quot;&quot;</span>
<a name="l00014"></a>00014 <span class="keyword">import</span> setPath
<a name="l00015"></a>00015 <span class="keyword">from</span> hippo <span class="keyword">import</span> HDApp
<a name="l00016"></a>00016 app = HDApp.instance()
<a name="l00017"></a>00017 canvas = app.canvas()
<a name="l00018"></a>00018 
<a name="l00019"></a>00019 <span class="keyword">from</span> hippo <span class="keyword">import</span> NTupleController
<a name="l00020"></a>00020 ntc = NTupleController.instance()
<a name="l00021"></a>00021 
<a name="l00022"></a>00022 nt1 = ntc.createNTuple ( <span class="stringliteral">&#39;../examples/aptuple.tnt&#39;</span> )
<a name="l00023"></a>00023 
<a name="l00024"></a>00024 <span class="keyword">from</span> hippo <span class="keyword">import</span> Display
<a name="l00025"></a>00025 
<a name="l00026"></a>00026 hist = Display (<span class="stringliteral">&quot;Histogram&quot;</span>, nt1, (<span class="stringliteral">&#39;Cost&#39;</span>,) )
<a name="l00027"></a>00027 canvas.addDisplay( hist )
<a name="l00028"></a>00028 hist.setAspectRatio ( 1.5 )
<a name="l00029"></a>00029 
<a name="l00030"></a>00030 hist.setRange ( <span class="stringliteral">&#39;x&#39;</span>, 0., 30000. )
</pre></div><p>After reading a <b>HippoDraw</b> compatible <a class="el" href="ntuple_root.html">data source</a> file, this Python script creates two displays. It sets the range on the first and the bin width on the second. The results of running this script are shown below.</p>
<div align="center">
<img src="hist_2.png" alt="hist_2.png"/>
<p><strong>Result of using <em>histogram</em>.py</strong></p></div>
 <p>The <code>Display</code> class is actually a small wrapper around the internal <b>HippoDraw</b> C++ library class. It is needed because Qt is running in a separate thread from Python. Since creating a display and perhaps modifying it requires interaction with Qt's event loop, the application must be locked before calling a member function of the actual <b>HippoDraw</b> class and then unlocked when returning.</p>
<h2><a class="anchor" id="python_interact_hippoplotter"></a>
Using the hippoplotter interface</h2>
<p>Making use of Python's default parameter value feature in calling functions, Jim Chiang has extended the HippoDraw interface with his <a class="el" href="hippoplotter.html">The hippoplotter.py module</a>.</p>
<p>The file, <em>pl_exp_test.py</em>, in the testsuite directory shows an example of using this module.</p>
<div class="fragment"><pre class="fragment">""" -*- mode: python -*-

   Testing the PowerLaw and Exponential classes and
   exercising the hippoplotter.py wrapper.

   author: James Chiang &lt;jchiang@slac.stanford.edu&gt;
   
"""
#
# $Id: pl_exp_test.py.in,v 1.12 2005/04/08 02:08:42 jchiang Exp $
#
# Author: J. Chiang &lt;jchiang@slac.stanford.edu&gt;
#

from setPath import *

import random, math

import hippoplotter as plot

#
# Generate power-law and exponential distributions
#
nt1 = plot.newNTuple( ([], ), ("x", ) )
pl_display = plot.Histogram(nt1, "x", xlog=1, ylog=1,
                               title="power-law dist.")

nt2 = plot.newNTuple( ([], ), ("x", ) )
exp_display = plot.Histogram(nt2, "x", ylog=1, title="exponential dist.")

both = plot.newNTuple( ([], ), ("x",) )
combo_display =plot.Histogram(both, "x", ylog=1,
                                 title="power-law &amp; exponential dists.")

shoot = random.uniform

#
# The parameters describing the distributions
#
x0 = 5.            # Characteristic scale for exponential

xmin = 1.          # Bounds for the power-law distribution
xmax = 100.
gamma = 2.1        # The power-law index

xpmax = math.pow(xmax, 1.-gamma)
xpmin = math.pow(xmin, 1.-gamma)

nsamp = 10000

print "Filling NTuple with data."

for i in range(nsamp):
    xi = shoot(0, 1)
    xx1 = math.pow( xi*(xpmax - xpmin) + xpmin, 1./(1.-gamma) )
    nt1.addRow( (xx1, ) )
    both.addRow( (xx1,) )
    
    xi = shoot(0, 1)
    xx2 = -x0*math.log(1. - xi)
    nt2.addRow( (xx2, ) )
    both.addRow( (xx2, ) )

#
# Fit these distributions
#
Function = plot.hippo.Function
powerlaw = Function( "PowerLaw", pl_display.getDataRep() )
powerlaw.addTo( pl_display )
powerlaw.fit()

exponential = Function( "Exponential", exp_display.getDataRep() )
exponential.addTo( exp_display )
exponential.fit()

#
# Do a fit to sum of functions.
#
pl = Function ( "PowerLaw", combo_display.getDataRep() )
pl.addTo( combo_display )

exp2 = Function ( "Exponential", combo_display.getDataRep() )
exp2.addTo( combo_display )

# Fit to linear sum
exp2.fit()

print "Demonstrated power law, exponential, and linear sum fitting"
print ""
</pre></div><p>The above script leads to the canvas shown below</p>
<div align="center">
<img src="hist_exp.png" alt="hist_exp.png"/>
<p><strong>Results of <em>pl_exp_test</em>.py script</strong></p></div>
 <h2><a class="anchor" id="python_interact_extract"></a>
Extracting data from a display</h2>
<p>The interaction with <b>HippoDraw</b> from Python is not just one direction. Once can extract data from the displays and use them in Python. The file <em>function_ntuple.py</em> illustrates this...</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="stringliteral">&quot;&quot;&quot; -*- python -*-</span>
<a name="l00002"></a>00002 <span class="stringliteral"></span>
<a name="l00003"></a>00003 <span class="stringliteral">   This is a script to test adding functions and fitting.  It only</span>
<a name="l00004"></a>00004 <span class="stringliteral">works with the C Python interface.  Jython interface needs Function</span>
<a name="l00005"></a>00005 <span class="stringliteral">class in Java.</span>
<a name="l00006"></a>00006 <span class="stringliteral"></span>
<a name="l00007"></a>00007 <span class="stringliteral">Copyright (C) 2002, 2003 The Board of Trustees of The Leland Stanford</span>
<a name="l00008"></a>00008 <span class="stringliteral">Junior University.  All Rights Reserved.</span>
<a name="l00009"></a>00009 <span class="stringliteral"></span>
<a name="l00010"></a>00010 <span class="stringliteral">Author: Paul_Kunz@slac.stanford.edu</span>
<a name="l00011"></a>00011 <span class="stringliteral"></span>
<a name="l00012"></a>00012 <span class="stringliteral">$Id: function_ntuple.py.in,v 1.4 2004/07/07 21:48:48 pfkeb Exp $nt</span>
<a name="l00013"></a>00013 <span class="stringliteral"></span>
<a name="l00014"></a>00014 <span class="stringliteral">&quot;&quot;&quot;</span>
<a name="l00015"></a>00015 <span class="keyword">import</span> setPath
<a name="l00016"></a>00016 <span class="keyword">from</span> load_hippo <span class="keyword">import</span> app, canvas
<a name="l00017"></a>00017 
<a name="l00018"></a>00018 <span class="keyword">from</span> hippo <span class="keyword">import</span> NTupleController
<a name="l00019"></a>00019 ntc = NTupleController.instance()
<a name="l00020"></a>00020 
<a name="l00021"></a>00021 <span class="comment"># Create NTuple with its controller so Inspector can see it.</span>
<a name="l00022"></a>00022 nt1 = ntc.createNTuple ( <span class="stringliteral">&#39;../examples/aptuple.tnt&#39;</span> )
<a name="l00023"></a>00023 
<a name="l00024"></a>00024 <span class="keyword">from</span> hippo <span class="keyword">import</span> Display
<a name="l00025"></a>00025 
<a name="l00026"></a>00026 hist = Display ( <span class="stringliteral">&quot;Histogram&quot;</span>, nt1, (<span class="stringliteral">&quot;Cost&quot;</span>, ) )
<a name="l00027"></a>00027 canvas.addDisplay( hist )
<a name="l00028"></a>00028 datarep1 = hist.getDataRep()
<a name="l00029"></a>00029 
<a name="l00030"></a>00030 <span class="keyword">from</span> hippo <span class="keyword">import</span> Function
<a name="l00031"></a>00031 
<a name="l00032"></a>00032 gauss = Function ( <span class="stringliteral">&quot;Gaussian&quot;</span>, datarep1 )
<a name="l00033"></a>00033 <span class="comment"># hist.addDataRep ( gauss )</span>
<a name="l00034"></a>00034 gauss.addTo ( hist )
<a name="l00035"></a>00035 
<a name="l00036"></a>00036 <span class="keywordflow">print</span> <span class="stringliteral">&quot;Before fitting&quot;</span>
<a name="l00037"></a>00037 parmnames = gauss.parmNames ( )
<a name="l00038"></a>00038 <span class="keywordflow">print</span> parmnames
<a name="l00039"></a>00039 
<a name="l00040"></a>00040 parms = gauss.parameters ( )
<a name="l00041"></a>00041 <span class="keywordflow">print</span> parms
<a name="l00042"></a>00042 
<a name="l00043"></a>00043 <span class="comment"># Now do the fitting.</span>
<a name="l00044"></a>00044 gauss.fit ( )
<a name="l00045"></a>00045 
<a name="l00046"></a>00046 <span class="keywordflow">print</span> <span class="stringliteral">&quot;After fitting&quot;</span>
<a name="l00047"></a>00047 parms = gauss.parameters ( )
<a name="l00048"></a>00048 <span class="keywordflow">print</span> parms
<a name="l00049"></a>00049 
<a name="l00050"></a>00050 gauss1 = Function ( <span class="stringliteral">&quot;Gaussian&quot;</span>, datarep1 )
<a name="l00051"></a>00051 gauss1.addTo ( hist )
<a name="l00052"></a>00052 
<a name="l00053"></a>00053 <span class="comment"># Do another fit, should fit to linear sum</span>
<a name="l00054"></a>00054 gauss1.fit ()
<a name="l00055"></a>00055 
<a name="l00056"></a>00056 result = hist.createNTuple ()
<a name="l00057"></a>00057 ntc.registerNTuple ( result )
<a name="l00058"></a>00058 
<a name="l00059"></a>00059 coords = result.getColumn ( <span class="stringliteral">&#39;Cost&#39;</span> )
<a name="l00060"></a>00060 values = result.getColumn ( <span class="stringliteral">&#39;Density&#39;</span> )
<a name="l00061"></a>00061 res = []
<a name="l00062"></a>00062 <span class="keywordflow">for</span> i <span class="keywordflow">in</span> range ( result.rows ) :
<a name="l00063"></a>00063     x = coords[i]
<a name="l00064"></a>00064     diff = values[i] - gauss1.valueAt ( x )
<a name="l00065"></a>00065     res.append ( diff )
<a name="l00066"></a>00066 
<a name="l00067"></a>00067 result.addColumn ( <span class="stringliteral">&#39;residuals&#39;</span>, res )
<a name="l00068"></a>00068 resplot=Display ( <span class="stringliteral">&quot;XY Plot&quot;</span>, result, ( <span class="stringliteral">&#39;Cost&#39;</span>, <span class="stringliteral">&#39;residuals&#39;</span>, <span class="stringliteral">&#39;nil&#39;</span>, <span class="stringliteral">&#39;Error&#39;</span> ) )
<a name="l00069"></a>00069 canvas.addDisplay ( resplot )
</pre></div><p>Like the previous script, it fits two functions to a histogram. It also shows how to extract the function parameter names and their values. Near the end of the script, one extracts the contents of the histogram bins in the form of an NTuple. In the <code>for</code> loop at the end, one uses the NTuple to calculate the residuals between the function and the bin contents and put them in a Python list. The the list is added as a column to the NTuple. Finally, one creates an XYPlot to display them and adds it to the canvas. The result looks like this...</p>
<div align="center">
<img src="hist_resid.png" alt="hist_resid.png"/>
<p><strong>Results of <em>function_ntuple</em>.py</strong></p></div>
 <p>However, one didn't have to write this script to plot the residuals, as the is a control in the <a class="el" href="inspector_root.html#inspector_functions">Function inspector</a> that does it for you.</p>
<h2><a class="anchor" id="python_interact_fits"></a>
Using a FITS file</h2>
<p>A <a href="http://heasarc.gsfc.nasa.gov/docs/heasarc/fits.html">FITS</a> file can be used as input to <b>HippoDraw</b>. Here's how one can it to view an image of the EGRET All-Sky survey from such a file</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="stringliteral">&quot;&quot;&quot; -*- mode: python -*-</span>
<a name="l00002"></a>00002 <span class="stringliteral"></span>
<a name="l00003"></a>00003 <span class="stringliteral">   Displaying the EGRET All Sky survey</span>
<a name="l00004"></a>00004 <span class="stringliteral"></span>
<a name="l00005"></a>00005 <span class="stringliteral">   author: James Chiang &lt;jchiang@slac.stanford.edu&gt;</span>
<a name="l00006"></a>00006 <span class="stringliteral">   </span>
<a name="l00007"></a>00007 <span class="stringliteral">&quot;&quot;&quot;</span>
<a name="l00008"></a>00008 <span class="comment">#</span>
<a name="l00009"></a>00009 <span class="comment"># $Id: egret.py.in,v 1.11 2003/09/29 18:12:50 jchiang Exp $</span>
<a name="l00010"></a>00010 <span class="comment">#</span>
<a name="l00011"></a>00011 
<a name="l00012"></a>00012 <span class="keyword">import</span> sys
<a name="l00013"></a>00013 sys.path.reverse()
<a name="l00014"></a>00014 sys.path.append(<span class="stringliteral">&#39;../python&#39;</span>)
<a name="l00015"></a>00015 sys.path.append(<span class="stringliteral">&#39;../python&#39;</span>)
<a name="l00016"></a>00016 sys.path.reverse()
<a name="l00017"></a>00017 
<a name="l00018"></a>00018 <span class="keyword">from</span> setPath <span class="keyword">import</span> *
<a name="l00019"></a>00019 
<a name="l00020"></a>00020 <span class="keyword">import</span> hippoplotter <span class="keyword">as</span> plot
<a name="l00021"></a>00021 
<a name="l00022"></a>00022 file = <span class="stringliteral">&quot;../examples/EGRET_AllSky.fits&quot;</span>
<a name="l00023"></a>00023 plot.fitsImage(file, zlog=1, aspect=2)
</pre></div><p>The resulting canvas is shown below</p>
<div align="center">
<img src="canvas_egret.png" alt="canvas_egret.png"/>
<p><strong>The EGRET All-Sky survey.</strong></p></div>
 <p>The FITS data format is a standard astronomical data and mandated by NASA for some projects. It supports images as well as binary or ASCII tables. A FITS table is essentially a NTuple with added information in the form of keyword-value pairs. James Chiang also wrote the following Python function to convert a FITS table to a <b>HippoDraw</b> NTuple.</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="stringliteral">&quot;&quot;&quot;</span>
<a name="l00002"></a>00002 <span class="stringliteral">Read in a series of FITS table files and make them accessible as</span>
<a name="l00003"></a>00003 <span class="stringliteral">numarrays, optionally creating a HippoDraw NTuple.</span>
<a name="l00004"></a>00004 <span class="stringliteral"></span>
<a name="l00005"></a>00005 <span class="stringliteral">@author J. Chiang &lt;jchiang@slac.stanford.edu&gt;</span>
<a name="l00006"></a>00006 <span class="stringliteral">&quot;&quot;&quot;</span>
<a name="l00007"></a>00007 <span class="comment">#</span>
<a name="l00008"></a>00008 <span class="comment"># $Id: FitsNTuple.py,v 1.12 2007/06/25 19:28:16 jchiang Exp $</span>
<a name="l00009"></a>00009 <span class="comment">#</span>
<a name="l00010"></a>00010 <span class="keyword">import</span> sys, pyfits
<a name="l00011"></a>00011 <span class="keywordflow">try</span>:
<a name="l00012"></a>00012     <span class="keyword">import</span> numarray <span class="keyword">as</span> num
<a name="l00013"></a>00013 <span class="keywordflow">except</span> ImportError:
<a name="l00014"></a>00014     <span class="keyword">import</span> numpy <span class="keyword">as</span> num
<a name="l00015"></a>00015 
<a name="l00016"></a>00016 <span class="keyword">class </span>FitsNTuple:
<a name="l00017"></a>00017     <span class="keyword">def </span>__init__(self, fitsfiles, extension=1):
<a name="l00018"></a>00018         cat = num.concatenate
<a name="l00019"></a>00019         <span class="comment">#</span>
<a name="l00020"></a>00020         <span class="comment"># If fitsfile is not a list or tuple of file names, assume</span>
<a name="l00021"></a>00021         <span class="comment"># it&#39;s a single file name and put it into a single element</span>
<a name="l00022"></a>00022         <span class="comment"># tuple.</span>
<a name="l00023"></a>00023         <span class="comment">#</span>
<a name="l00024"></a>00024         <span class="keywordflow">if</span> type(fitsfiles) != type([]) <span class="keywordflow">and</span> type(fitsfiles) != type(()):
<a name="l00025"></a>00025             fitsfiles = (fitsfiles, )
<a name="l00026"></a>00026         <span class="comment">#</span>
<a name="l00027"></a>00027         <span class="comment"># Process each file named in the list or tuple.</span>
<a name="l00028"></a>00028         <span class="comment">#</span>
<a name="l00029"></a>00029         columnData = {}
<a name="l00030"></a>00030         <span class="keywordflow">for</span> i, file <span class="keywordflow">in</span> zip(xrange(sys.maxint), fitsfiles):
<a name="l00031"></a>00031             <span class="comment">#print &quot;adding&quot;, file</span>
<a name="l00032"></a>00032             table = pyfits.open(file.strip(<span class="stringliteral">&quot; &quot;</span>))
<a name="l00033"></a>00033             <span class="keywordflow">if</span> i == 0: 
<a name="l00034"></a>00034                 self.names = table[extension].columns.names
<a name="l00035"></a>00035             <span class="keywordflow">for</span> name <span class="keywordflow">in</span> self.names:
<a name="l00036"></a>00036                 <span class="keywordflow">if</span> i == 0:
<a name="l00037"></a>00037                     columnData[name] = table[extension].data.field(name)
<a name="l00038"></a>00038                 <span class="keywordflow">else</span>:
<a name="l00039"></a>00039                     columnData[name] = cat((columnData[name],
<a name="l00040"></a>00040                                             table[extension].data.field(name)))
<a name="l00041"></a>00041         <span class="comment">#</span>
<a name="l00042"></a>00042         <span class="comment"># Add these columns to the internal dictionary.</span>
<a name="l00043"></a>00043         <span class="comment">#</span>
<a name="l00044"></a>00044         self.__dict__.update(columnData)
<a name="l00045"></a>00045         
<a name="l00046"></a>00046     <span class="keyword">def </span>makeNTuple(self, name=None, useNumArray=1):
<a name="l00047"></a>00047         <span class="keyword">import</span> hippo
<a name="l00048"></a>00048         <span class="keywordflow">if</span> useNumArray:
<a name="l00049"></a>00049             nt = hippo.NumArrayTuple()
<a name="l00050"></a>00050         <span class="keywordflow">else</span>:
<a name="l00051"></a>00051             nt = hippo.NTuple()
<a name="l00052"></a>00052         <span class="keywordflow">if</span> name != <span class="keywordtype">None</span>:
<a name="l00053"></a>00053             nt.setTitle(name)
<a name="l00054"></a>00054         ntc = hippo.NTupleController.instance()
<a name="l00055"></a>00055         ntc.registerNTuple(nt)
<a name="l00056"></a>00056         <span class="keywordflow">for</span> name <span class="keywordflow">in</span> self.names:
<a name="l00057"></a>00057             <span class="keywordflow">if</span> len(self.__dict__[name].shape) &gt; 1: <span class="comment"># have multicolumn variable</span>
<a name="l00058"></a>00058                 columns = self.__dict__[name]
<a name="l00059"></a>00059                 columns.transpose()
<a name="l00060"></a>00060                 <span class="keywordflow">for</span> i, col <span class="keywordflow">in</span> enumerate(columns):
<a name="l00061"></a>00061                     colname = <span class="stringliteral">&quot;%s%i&quot;</span> % (name, i)
<a name="l00062"></a>00062                     nt.addColumn(colname, col)
<a name="l00063"></a>00063             <span class="keywordflow">else</span>:
<a name="l00064"></a>00064                 <span class="keywordflow">try</span>:
<a name="l00065"></a>00065                     nt.addColumn(name, self.__dict__[name])
<a name="l00066"></a>00066                 <span class="keywordflow">except</span> TypeError:
<a name="l00067"></a>00067                     <span class="keywordflow">pass</span>
<a name="l00068"></a>00068         <span class="keywordflow">return</span> nt
</pre></div><h2><a class="anchor" id="python_interact_root"></a>
Using ROOT files</h2>
<p>Another example is reading a <a href="http://root.cern.ch">ROOT</a> file that has the form of an ntuple as define in <a class="el" href="ntuple_root.html#ntuple_roottuple">RootNTuple class</a>. The Python code might look like this...</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="stringliteral">&quot;&quot;&quot; -*- mode:python -*-</span>
<a name="l00002"></a>00002 <span class="stringliteral"></span>
<a name="l00003"></a>00003 <span class="stringliteral">Demo of reading ROOT file with function, cuts, and calculation</span>
<a name="l00004"></a>00004 <span class="stringliteral"></span>
<a name="l00005"></a>00005 <span class="stringliteral">author: Paul F. Kunz &lt;Paul_Kunz@slac.stanford.edu&gt;</span>
<a name="l00006"></a>00006 <span class="stringliteral"></span>
<a name="l00007"></a>00007 <span class="stringliteral">&quot;&quot;&quot;</span>
<a name="l00008"></a>00008 
<a name="l00009"></a>00009 <span class="keyword">import</span> setPath
<a name="l00010"></a>00010 <span class="keyword">from</span> load_hippo <span class="keyword">import</span>  app, canvas
<a name="l00011"></a>00011 
<a name="l00012"></a>00012 <span class="keyword">from</span> hippo <span class="keyword">import</span> RootController, Display
<a name="l00013"></a>00013 rc = RootController.instance()
<a name="l00014"></a>00014 
<a name="l00015"></a>00015 filename = <span class="stringliteral">&quot;/nfs/farm/g/glast/u33/InstrumentAnalysis/MC/EngineeringModel-v6r070329p28/Surface_muons/surface_muons_4M_merit.root&quot;</span>
<a name="l00016"></a>00016 
<a name="l00017"></a>00017 ntuple_names = rc.getNTupleNames ( filename  )
<a name="l00018"></a>00018 <span class="keywordflow">print</span> <span class="stringliteral">&quot;In this file, tree names are &quot;</span>, ntuple_names
<a name="l00019"></a>00019 
<a name="l00020"></a>00020 ntuple = rc.createDataArray ( filename, ntuple_names[1] )
<a name="l00021"></a>00021 <span class="keywordflow">print</span> <span class="stringliteral">&quot;Number of columns = &quot;</span>, ntuple.columns
<a name="l00022"></a>00022 
<a name="l00023"></a>00023 labels = ntuple.getLabels()
<a name="l00024"></a>00024 <span class="keywordflow">print</span> <span class="stringliteral">&quot;First ten column labels are ... &quot;</span>, labels[:10]
<a name="l00025"></a>00025 
<a name="l00026"></a>00026 <span class="keywordflow">print</span> <span class="stringliteral">&quot;Number of rows = &quot;</span>, ntuple.rows
<a name="l00027"></a>00027 
<a name="l00028"></a>00028 hist = Display ( <span class="stringliteral">&quot;Histogram&quot;</span>, ntuple, (<span class="stringliteral">&#39;TkrEnergy&#39;</span>, ) )
<a name="l00029"></a>00029 canvas.addDisplay ( hist )
<a name="l00030"></a>00030 
<a name="l00031"></a>00031 hist.setLog ( <span class="stringliteral">&#39;y&#39;</span>, <span class="keyword">True</span> )
<a name="l00032"></a>00032 
<a name="l00033"></a>00033 <span class="keyword">from</span> hippo <span class="keyword">import</span> Cut
<a name="l00034"></a>00034 
<a name="l00035"></a>00035 hits_cut = Cut ( ntuple, (<span class="stringliteral">&#39;TkrTotalHits&#39;</span>,) )
<a name="l00036"></a>00036 canvas.addDisplay ( hits_cut )
<a name="l00037"></a>00037 hits_cut.setLog ( <span class="stringliteral">&#39;y&#39;</span>, <span class="keyword">True</span> )
<a name="l00038"></a>00038 
<a name="l00039"></a>00039 hits_cut.addTarget ( hist )
<a name="l00040"></a>00040 hits_cut.setCutRange ( 4, 110, <span class="stringliteral">&#39;x&#39;</span> )
<a name="l00041"></a>00041 
<a name="l00042"></a>00042 hist.setRange ( <span class="stringliteral">&#39;x&#39;</span>, 40, 700 )
<a name="l00043"></a>00043 
<a name="l00044"></a>00044 <span class="keyword">from</span> hippo <span class="keyword">import</span> Function
<a name="l00045"></a>00045 datarep = hist.getDataRep ()
<a name="l00046"></a>00046 
<a name="l00047"></a>00047 exp1 = Function ( <span class="stringliteral">&quot;Exponential&quot;</span>, datarep )
<a name="l00048"></a>00048 exp1.addTo ( hist )
<a name="l00049"></a>00049 
<a name="l00050"></a>00050 exp1.fit ()
<a name="l00051"></a>00051 pnames = exp1.parmNames ()
<a name="l00052"></a>00052 <span class="keywordflow">print</span> pnames
<a name="l00053"></a>00053 
<a name="l00054"></a>00054 parms = exp1.parameters ()
<a name="l00055"></a>00055 <span class="keywordflow">print</span> parms
<a name="l00056"></a>00056 
<a name="l00057"></a>00057 exp2 = Function ( <span class="stringliteral">&quot;Exponential&quot;</span>, datarep )
<a name="l00058"></a>00058 exp2.addTo ( hist )
<a name="l00059"></a>00059 
<a name="l00060"></a>00060 exp1.fit() <span class="comment"># always fit to linear sum</span>
<a name="l00061"></a>00061 
<a name="l00062"></a>00062 label = <span class="stringliteral">&quot;Raw sum&quot;</span>
<a name="l00063"></a>00063 ntuple [ label ] = ntuple [ <span class="stringliteral">&#39;TkrEnergy&#39;</span> ] + ntuple [ <span class="stringliteral">&#39;CalEnergyRaw&#39;</span> ]
<a name="l00064"></a>00064 
<a name="l00065"></a>00065 sum_hist = Display ( <span class="stringliteral">&#39;Histogram&#39;</span>, ntuple, (label, ) )
<a name="l00066"></a>00066 canvas.addDisplay ( sum_hist )
<a name="l00067"></a>00067 
<a name="l00068"></a>00068 sum_hist.setLog ( <span class="stringliteral">&#39;x&#39;</span>, <span class="keyword">True</span> )
<a name="l00069"></a>00069 sum_hist.setLog ( <span class="stringliteral">&#39;y&#39;</span>, <span class="keyword">True</span> )
<a name="l00070"></a>00070 
<a name="l00071"></a>00071 merit_sum = Display ( <span class="stringliteral">&#39;Histogram&#39;</span>, ntuple, ( <span class="stringliteral">&#39;EvtEnergyCorr&#39;</span>, ) )
<a name="l00072"></a>00072 canvas.addDisplay ( merit_sum )
<a name="l00073"></a>00073 
<a name="l00074"></a>00074 merit_sum.setLog ( <span class="stringliteral">&#39;x&#39;</span>, <span class="keyword">True</span> )
<a name="l00075"></a>00075 merit_sum.setLog ( <span class="stringliteral">&#39;y&#39;</span>, <span class="keyword">True</span> )
<a name="l00076"></a>00076 
<a name="l00077"></a>00077 sum_hist.setRange ( <span class="stringliteral">&#39;x&#39;</span>, 1.0, 1e+06 )
</pre></div><p>This script not only uses ROOT, but it also uses numarray. It converts a ROOT brach into a numarray array so it can do vector calculations. The ROOT C++ macro to do the equivalent of the above Python script would be considerable more complex.</p>
<h2><a class="anchor" id="python_interact_limitations"></a>
Limitations.</h2>
<p>With this release, not all of <b>HippoDraw's</b> C++ library is exposed to Python. Although this could be done, it is thought to be not necessary. Rather, selected higher level components are exposed in one of two ways. Some classes are exposed directly with a one to one relationship between the C++ member functions and Python member functions. An example is the NTuple class.</p>
<p>One can view the reference documentation for the hippo extension module with Python's online help command, One can also use the pydoc program to view it or generated HTML file with the command "pydoc -w
hippo".</p>
<p>In order to be able to have an interactive Python session that interacts with the <b>HippoDraw</b> canvas items and at the same time have interaction with the same items from the Inspector, it was necessary to run the <b>HippoDraw</b> application object in a separate thread. Threading conflicts could then occur. Thus some of <b>HippoDraw's</b> C++ classes are exposed to Python via a thin wrapper class which locks the Qt application object before invoking an action and unlocks it when done.</p>
<p>One good thing about Python is that what ever you do, Python never crashes. Thus, what ever you do with the <b>HippoDraw</b> extension module should not crash Python. An interactive user, however, can easily mis-type an argument to a function. For example, he could try to create a display with "ContourPlot" instead of "Contour Plot". For such errors, the C++ library throws a C++ exception. The <b>HippoDraw</b> extension module catches them and translates them to a Python exception. Thus, when the Python user makes an error, he will receive a message instead of crashing his session.</p>
<p>Another reason the wrapper classes exist is to try to present a more Python "interactive friendly" interface to the user than the raw C++ interface which was designed for the application writer. With this release, it is not clear what a more "friendly" interface should look like. Maybe the Python extension module should be closer to the C++ interface and provide Python classes to wrap them in a more friendly way like James Chiang has done. Feed back on this topic would be very welcome. </p>
</div></div>
<hr size="1"><address style="align: right;"><small>
Generated for HippoDraw by <a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
</a> </small></address>
</body>
</html>