/** @page examples_page Examples of HippoDraw use with Python
Using @b HippoDraw as a Python extension module allows one to write
Python scripts to do repetitive tasks.
Examples scripts are in the @em examples subdirectory of the @b
HippoDraw installation. To get an overview of what the examples do,
try running the script that runs each of the examples like the
following.
@verbatim
> cd /usr/local/share/HippoDraw/examples
> python -i run_examples.py
Hit return to run named script
Run static_vs_dynamic:
@endverbatim
An empty canvas window and the Inspector will be created. Recall
your shell window and hit return to run each example in turn.
See the @ref python_interact to see how to get started and getting help.
The next section lists some typical tasks one might want to do from
Python. For each task, an example is listed to illustrate how it is
done.
@section examples_index Index to the examples
The following is a list of task one might want to do with a Python
script and a link to which of the examples that follow illustrate that
task.
NTuple creation by reading ASCII file:
@li @ref examples_function
NTuple creation by reading ROOT file:
@li @ref examples_root_file
@li @ref examples_root_array
NTuple creation by reading FITS file:
@li @ref examples_fits_file
@li @ref examples_cuts
@li @ref examples_cut_array
Finding NTuple names from a file:
@li @ref examples_fits_file
@li @ref examples_root_file
@li @ref examples_root_array
Finding NTuple column labels:
@li @ref examples_root_file
@li @ref examples_fits_file
Adding rows to an NTuple:
@li @ref examples_static
@li @ref examples_root_file
NTuple creation from Python lists:
@li @ref examples_simple
@li @ref examples_function
Create and use DataArray:
@li @ref examples_appending
@li @ref examples_fits_file
@li @ref examples_fitting
@li @ref examples_static
@li @ref examples_root_file
@li @ref examples_root_array
@li @ref examples_cut_array
Adding columns to DataArray:
@li @ref examples_appending
@li @ref examples_fits_file
@li @ref examples_static
@li @ref examples_root_file
@li @ref examples_root_array
Adding an array column to DataArray:
@li @ref examples_appending
@li @ref examples_fits_file
Registering NTuple with the Inspector:
@li @ref examples_static
Registering DataArray with Inspector:
@li @ref examples_fitting
@li @ref examples_static
Adding cuts to dynamic histogram:
@li @ref examples_cuts
@li @ref examples_cut_array
Dynamic histogram:
@li @ref examples_static
@li @ref examples_fits_file
@li @ref examples_root_file
@li @ref examples_root_array
Static histogram:
@li @ref examples_static
Retrieving bin contents from a histogram:
@li @ref examples_function
@li @ref examples_static.
Taking difference between two histograms and plotting it:
@li @ref examples_static.
Setting title of plot:
@li @ref examples_simple
@li @ref examples_static
Setting bin width:
@li @ref examples_static
@li @ref examples_log
Setting plot range:
@li @ref examples_static
@li @ref examples_root_file
Setting log scales:
@li @ref examples_log
@li @ref examples_fits_file
@li @ref examples_root_file
@li @ref examples_root_array
Changing the line style:
@li @ref examples_overlay
Changing color:
@li @ref examples_overlay
Changing point type:
@li @ref examples_overlay
Change the plot matrix:
@li @ref examples_displays
Overlaying plots:
@li @ref examples_overlay
Fitting functions:
@li @ref examples_function
@li @ref examples_log
@li @ref examples_fitting
@li @ref examples_root_file
Retrieving fitted function parameters:
@li @ref examples_function
@li @ref examples_fitting
@li @ref examples_root_file
Fitting with direct manipulation of the minimizers:
@li @ref examples_fitting.
Writing custom functions in Python:
@li @ref examples_fitting
@li @ref examples_fitting2
Retrieving statistical data:
@li @ref examples_static
Adding statistical data to plot:
@li @ref examples_static
@li @ref examples_function
Doing vector algebra with numarray:
@li @ref examples_appending
@li @ref examples_static
@li @ref examples_root_file
@li @ref examples_root_array
@li @ref examples_cut_array
Using numarray functions and expressions
@li @ref examples_appending
@li @ref examples_root_array
Using hippo module without graphics.
@li @ref examples_fitting2
Doing a FFT
@li @ref examples_fft
@section examples_examples The examples
@subsection examples_static Using dynamic and static histograms
This example shows the comparison between static and dynamic
histograms. A static histogram is one with which the range and bin
width is fixed at time of creation, and is filled by calling the
histogram object with the values to be histogrammed. A dynamic
histogram is one which is bound to a NTuple. When displayed, it sets
its range to make all the entries visible and has about 50 bins. One
can change the attributes, such a bin width, at any time since the
dynamic histogram gets its data from the NTuple.
The Python code is shown below.
@verbinclude examples/static_vs_dynamic.py
The script first creates static histograms, sets their attributes, and
adds it to the canvas. It then creates an empty NTuple, sets its
title, and labels for the columns. Since there is only one string in the tuple of labels, the ntuple will have only one column. The dynamic
histogram is then created, bound to the ntuple, and adding to the
canvas.
The script generates some data. In the for loop, it fills one static
histogram with all the generated data and the other one with only the
first 1000 "events". It also adds a rows to the ntuple. Both
histograms are initially empty and you can watch them grow when you
run the script.
When the data generation is done, some statistical quantities are
retrieved from the static histogram and printed. One can now use the
@ref inspector_root to change the attributes of the histograms. With
the dynamic histogram one can change the size of the bins, but not
with the static one. They are then added to overlay the plot.
Finally the we take the difference between the high and low statistics
histograms. This is done by creating a DataArray which wraps an NTuple
containing the contents of the bins. DataArray objects a column of
data as a numarray using syntax of a Python dictionary. Numarray
objects overload the arithmetic operators, so we can take the difference
with vector algebra. Adding the created column to the small
DataArray also has the syntax of adding an entry to a Python
dictionary. An XY plot is then created using DataArray.
@subsection examples_log Logarithmic axes
This script creates a dynamic histogram with logarithmic axes scales.
The Python source code is shown below.
@verbinclude examples/loglog.py
After creating of the histogram, the display is set to be a log-log
plot. When the X axis is set to log scale, the width of the bins are
logarithmically increasing in size. They only appear uniform in width
on the screen. The function used is a power law, which appears as
straight line on this log-log plot.
@subsection examples_cuts Applying cuts
This section shows how to apply cuts to a plot. One can think in
terms of creating a cut then applying it to one or more displays, or
of having one or more cuts and applying it to a display. An example
of the former is shown below.
@verbinclude examples/cut_multi_displays.py
Applying multiple cuts to a display is shown in the example below
@verbinclude examples/cuts_one_display.py
@subsection examples_cut_array Creating a cut from Boolean numarray
Numarray allows one to create array of Boolean values just by writing
a logical expression. An example is the following
@verbatim
zenith = events['zenith_angle']
z_array = zenith > 80.
@endverbatim
In the above, the numarray is created from the DataArray with label
"zenith_angle". The second expression creates a numarray containing
@c true and @c false values. One can use this Boolean array to create
a cut. Thus one can have aribitrary complex cuts by combining Boolean
expressions. An example of doing two cuts explicitly and with numarry
is shown below.
@verbinclude examples/cuts_complex.py
@subsection examples_overlay Overlaying plots and changing style
The example overlays data representations and changing the style of
the drawing. The Python code is shown below.
@verbinclude examples/datareps.py
With @b HippoDraw one can overlay data representations of different
kinds. One can even overlay two histograms with different bin widths
as is shown in this example. One can also change the line style or
symbol type as well as the color. How to do these is easily seen in
the Python code.
@subsection examples_function Using functions and fitting
This example fits a histogram to a sum of two Gaussian. The Python
code is shown below.
@verbinclude examples/function_ntuple.py
After creating an NTuple from a ASCII file, a histogram is placed on
the canvas. Then the data representation of it is retrieved, a
function created and added to the representation. Next the function
parameter names are retrieved along with the initial parameter values
and printed. The parameter values are printed again after fitting. A
second Gaussian function is added and the sum of the two is used for a
fit. Then the chi-squared per degree of freedom is add to the plot.
The last part of the example illustrates retrieving information from
the histogram. One asks the histogram to make an NTuple
representation of itself. The NTuple is registered with the
NTupleController so it will be visible from the Inspector. . One can
thus access the histogram information by column. In the example, the
residuals are calculated. The list of residuals are then added to the
NTuple created by the histogram. Since this NTuple is of the same
type as used to hold the initial data set, we can use it to make an XY
plot as is shown in the example.
Everything done in this script could have been done with @ref
inspector_root. This includes creating of the residuals display as
there is a button on the @ref inspector_functions to do this.
@subsection examples_simple A simple XY Plot
This example creates an XY Plot. The Python code is shown below.
@verbinclude examples/simple_xyplot.py
After creating three Python lists of the data, one creates the
display. The first argument to @em Display is the type of plot. The
types available can be seen in the @em Data tabbed panel of the
inspector. The second argument is a list of the data lists. This
will have the effect of creating a NTuple and it will be visible from
the Inspector. The third argument is also a Python list and it serves
two purposes. It gives labels for the NTuple columns and it sets the
binding options for the XY plot. The 3rd binding option is the X
error, which is optional, so we use the "`nil'" string to indicate
that binding is not to be used.
@subsection examples_displays All kinds of plots
This example creates one instance of each kind of display available to
the Inspector. The Python source code is shown below.
@verbinclude examples/displays.py
The beginning of the script sets the form factor of how the plots will
be displayed, name 3 across and 4 down. This was done so they would
all fit on one page. Nothing else is new compared to the previous
examples.
@subsection examples_root_file Using data from a ROOT file
This example shows how to use data from a ROOT file. Quite
frequently, a ROOT file is simply a table made up of a TTree
consisting of a number of TBranch objects (the columns of the table)
of the same length. If the columns contain simple scalar data types,
then this sort of ROOT file can be read by @b HippoDraw. The Python
script is shown below followed by a description of what is being done.
@verbinclude examples/merit.py
One uses the single instance of the RootController object to read the
file. First one gets the names of the top level TTree which @b
HippoDraw interprets as NTuple names.
In the next step, one could have created an NTuple with the method @em
createNTuple and the same arguments. It would be implemented by the
RootNTuple class. This class only reads the data into memory as it is
needed, so it is quite efficient even for files that have a large
number of columns.
Instead of a NTuple, one creates a DataArray. It contains a NTuple
and behaves like one for most purposes but gives us additional
flexibility as will be seen near the end of the example.
The next few lines shows how to get the number of rows and columns as
well as the labels for the columns. The script then creates a
histogram and adds it to the canvas. Since the distribution falls off
rather quickly, the Y axis is set to a log scale.
The script then applies a cut and adds the display of the cut variable
to the canvas. The cut distribution also falls rather quickly to its
Y axis is also put on a log scale.
The next step gets a handle on the data representation, i.e.
the actual histogram, in order to fit a function to it. Not satisfied
with the fit, a second function is applied. Note that when two
functions are applied, a fit is done to the linear sum of the
functions.
The last part of the script shows the power of using a DataArray. In
one line the script adds two columns together, row by row, and adds
the result to the DataArray. Let's take it step by step to understand
it. The expression
@verbatim
ntuple [ 'TkrEnergy' ]
@endverbatim
shows that the DataArray behaves like a Python dictionary in that we
can access a column by a key. The key is the label of the column. It
returns a numarray. The expression
@verbatim
ntuple [ 'TkrEnergy' ] + ntuple [ 'CalEnergySum' ]
@endverbatim
thus accesses two columns and adds them together because the numarray
class overload the operator + to create a new numarray whose values are
the sum of the others, element by element.
Finally, a column is added with the expression
@verbatim
ntuple [ label ] =
@endverbatim
where again the DataArray behaves like a Python dictionary. The right
hand side of the assignment must be a numarray, which it is in this
case. The column is not added to the ROOT file, it is only logically
added in memory.
Treating columns of the data source as vectors and doing vector
algebra on them can be considerably faster than writing @em for loops.
The code is much easier to write and understand as well.
@subsection examples_root_array Doing analysis with numarray and ROOT file
The examples shows some aspects of doing an analysis with numarray and
numarray functions and expressions. The benefits of using numarrays
are two fold. First, the elimination of explictit @em for-loops make
the code easier to read. Second, factors of 20-30 speed up of the
analysis have been seen because more of it is the compiled Python
extension module instead of in the Python intepreter.
The example code is shown below. The explanation of the code is in
the comments.
@verbinclude examples/svac_array.py
@subsection examples_fits_file Reading and writing FITS files
This example shows how to use data from a FITS file and writing a data
to a FITS file. An explanation of the code below follows.
The instance of the FitsController is used to read the FITS file.
FITS files can contain multiple images and tables. You can use the
FitsController to find the names of the Header/Data Units (HDU) as
shown. The first HDU is always an image, so the tabular data is
probably the second HDU. The FitsController creates DataArray object
(see @ref ntuple_dataarray)
from given the filename and the name of the HDU. The DataArray holds
a FitsNTuple object that knows how to read columns from a ASCII or
binary table.
The FitsController and FitsNTuple classes are written in C++ and use
the standard CFITSIO package for reading the FITS file.
@verbinclude examples/fitsWriting.py
The first part of the script shows how to get information about the
file and its tables. it than creates a two dimensional histogram and
adds it to the canvas. Next a column is added to the DataArray which
is the log10 of the column containing `energy' and a plot of it is
added to the canvas, with the Y axis on a log scale. For comparison,
another plot of energy is added to the canvas with both the X and Y
axes on a log scale. For histograms, this also sets the bin widths
to a logrithmically increasing size. Thus, these last two plots
should look the same.
The script next creates a cut on time and sets it to an arbitrary
range. The cut itself is placed on the canvas. The cut is then
applied to all three plots.
Next, a simple vector is added as a column. using numarray. It is
added to DataArray in the same manner as any other array.
The script then writes the DataArray, including the added columns,
to the FITS file @em sim2.fits. This has the same effect as
Export text ntuple menu item of the CanvasWindow. Although this
DataArray contains a FitsNTuple, and type of @ref ntuple_root could have
been used.
The script then creates another FITS file from the DataArray, but only
with the rows that pass the cut and the selected columns. This has
the same effect as the Create NTuple... menu item of the
CanvasWindow.
The last part of the script reads the newly created FITS file and
checks if it contains what is expected.
@subsection examples_appending Appending one data source to another.
This example shows how to append one data source to another. Of
course the two data sources should have the same number of columns.
In this example, DataArray objects are used, but the one could use any
of the DataSource derived classes. One can even append from a
DataSource of a different type.
The example is shown below. It also illustrates use of numarray to
do vector arithmatic.
@verbinclude examples/append_ntuple.py
If you are new to Python and/or numarray, this line in the example you
may find confusing
@verbatim
da1 [ 'data' ] = numarray.array ( range ( 10 ) )
@endverbatim
What is happening here is that the @em range function returns a Python
@em list object. It is then used to construct a numarray object.
The resulting numarray is added to the data array as a new column with
the label @em data.
@subsection examples_fitting Fitting to functions written in Python
This example shows how to write a function in Python the one can use
with the built-in fitting packages. The function is written in
Python, yet it is derived from a class written in C++.
This example also illustrates how to directly manipulate the fitting
process, using various components. In future releases, some of these
components could also be written in Python.
Finally, this example uses a DataArray to
hold the data set.
@verbinclude examples/fitting.py
@subsection examples_fitting2 Fitting to 2D functions written in Python
This example shows how to write a 2D function in Python the one can
use with the built-in fitting packages. It is similar to @ref
examples_fitting. This examples also shows using the hippo module
without using the graphics.
This example also illustrates how to directly manipulate the fitting
process, using features, some of which are only available with the
Minuit fitter.
@verbinclude examples/fitting2.py
@subsection examples_fft Doing a Fast Fourier Transform
This example shows how to do a Fast Fourier Transform and plot the results.
The Python code is shown below.
@verbinclude examples/fft.py
The first part generates white noise time series in atribitary units.
We create a NumArrayTuple to holds the data as a one column
DataSource. This type of %DataSource holds a reference to the data
instead of making a copy of it.
Then the hippofft.simpleLightCur function is calledwith the
data source and the label of the (only) column. The last srgument is
optionsal and is the number of bins to be used to generate the light
curve. The default is 1024. The function returns two objects. The
first is the histogram of the data. It can be added to the canvas as
shown. The second is the contents of the bins appropriately
normalized.
The power spectrum is then calculated given the bins, the range of the
data, and the units of time in seconds. The function returns a
DataArray containing an NTuple object with two columns. The first
column is the frequency and the second is the power. One can create a
XY plot of the spectrum as shown.
To check that hte transform is correct, the script creates a histogram
of the power and plots it on a log scale. It then fits it to an
exponential. The resulting fit should havethe scale factor around
2.0.
*/