\documentclass{article}
\usepackage{graphicx}
\usepackage{rotating}
\title{VTK Visualiser Reference}
\author{Jack Kelly}
% Override the date command, so we can get the date later.
\let\olddate\date
\newcommand{\thedate}{\today}
\renewcommand{\date}[1]{
  \olddate{#1}
  \renewcommand{\thedate}{#1}
}

\date{10 Nov 2006} % To prevent it being updated each time the
                   % document is generated; only update this if the
                   % material is being updated.
\begin{document}
\maketitle
\tableofcontents
\newpage
\section{Introduction}
This document provides a simple reference for the new VTK-based
realtime visualiser for the ANUGA project. It covers usage examples,
descriptions of the public interface and explanation of the design.
The contents of this document are accurate as of \thedate.
\section{Examples}
\subsection{A Simple Offline Example}
This is almost the simplest example possible. It reads in a SWW file
and renders the stage in blue and elevation in the default grey.
\begin{verbatim}
#!/usr/bin/env python
# Import the offline visualiser
from anuga.visualiser import OfflineVisualiser

# The argument to OfflineVisualiser is the path to a sww file
o = OfflineVisualiser("path/to/sww/file")

# Specify the height-based-quantities to render.
# Remember to set dynamic=True for time-varying quantities
o.render_quantity_height("elevation", dynamic=False)
o.render_quantity_height("stage", dynamic=True)

# Colour the stage with an RGB 3-tuple of values in [0,1]:
o.colour_height_quantity('stage', (0.0, 0.0, 0.8))

# Start the visualiser (in its own thread).
o.start()

# Wait for the visualiser to terminate before shutting down.
o.join()
\end{verbatim}
The basic pattern for using a visualiser consists of 4 steps: create
the visualiser, configure it to display the required quantities, start
the visualiser in its own thread using start() and finally wait on all
the visualiser threads using join().
\subsection{A More Complicated Realtime Example}
This example demonstrates the realtime visualiser and shows off
additional capabilities of both visualisers.
\begin{verbatim}
#!/usr/bin/env python
# Import the realtime visualiser
from anuga.visualiser import RealtimeVisualiser
from vtk import vtkCubeAxesActor2D

import time
from Numeric import array
from anuga.shallow_water import Domain
from anuga.shallow_water import Reflective_boundary
from anuga.abstract_2d_finite_volumes.mesh_factory import rectangular
class Set_Stage:
    def __init__(self, x0=0.25, x1=0.75, y0=0.0, y1=1.0, h=5.0, h0=0.0):
        self.x0 = x0
        self.x1 = x1
        self.y0 = y0
        self.y1 = y1
        self.h  = h
        self.h0 = h0
    def __call__(self, x, y):
        return self.h0 + self.h*((x>self.x0)&(x<self.x1)&(y>self.y0)&(y<self.y1))
M = 20
points, vertices, boundary = rectangular(M, M, len1 = 1.0, len2 = 1.0)
yieldstep = 0.002
finaltime = 0.8
rect = [0.0, 0.0, 1.0, 1.0]
domain = Domain(points, vertices, boundary)

# Turn on the visualisation. The argument to the realtime visualier
# is a domain object.
v = RealtimeVisualiser(domain)
# Specify the height-based-quantities to render.
v.render_quantity_height("elevation", dynamic=False)
v.render_quantity_height("stage", dynamic=True)

# Colour the stage with a function of the quantities at that point, such as the
# stage height: 0 and 1 are the minimum and maximum values of the stage.
v.colour_height_quantity('stage', (lambda q:q['stage'], 0, 1))

# Draw some axes on the visualiser so we can see how big the wave is
v.render_axes()
# Increase the number of labels on the axes
v.alter_axes(vtkCubeAxesActor2D.SetNumberOfLabels, (5,))

# Draw a yellow polygon at height 2
v.overlay_polygon([(0, 0), (0, 0.1), (0.1, 0)], 2, colour=(1.0, 1.0, 0.0))

# Start the visualiser (in its own thread).
v.start()

R = Reflective_boundary(domain)
domain.set_boundary( {'left': R, 'right': R, 'bottom': R, 'top': R} )
domain.set_quantity('stage', Set_Stage(0.2, 0.4, 0.25, 0.75, 2.0, 0.00))
t0 = time.time()
for t in domain.evolve(yieldstep = yieldstep, finaltime = finaltime):
    v.update()
    domain.write_time()
# Unhook the visualiser from the evolve loop.
# It won't shutdown cleanly unless you do this.
v.evolveFinished()

print 'That took %.2f seconds' %(time.time()-t0)

# Wait for the visualiser to be closed
v.join()
\end{verbatim}
Ignoring the extra code to set up and evaluate a shallow water domain,
the basic principle is the same. The visualiser is created (with a
domain object instead of a string as a parameter), configured (note
the extra features such as the axes and the yellow polygon) and
started in basically the same manner as the offline visualiser.

Within the evolve loop, the visualiser's update() method is called to
keep the displayed render in sync with the actual state of the domain.
After the evolve loop is finished, the visualiser needs to be unhooked
from the evolve loop or else the script will not terminate cleanly.
Finally, the visualiser thread is join()ed so it does not close as
soon as the evolve loop terminates.
\section{Interface Description}
\subsection{Generic Interface}
The functions that form the public interface for both the offline and
realtime visualisers are as follows:
\begin{description}
\item[render\_axes()]
  Draw cube axes around the rendered quantities.  These will be
  adjusted to the bounds of the domain automatically.
\item[alter\_axes(func, args)]
  Apply the function \textit{func}, with arguments tuple \textit{args} to the
  axes. The axes are an instance of vtkCubeAxesActor2D. A sample call:
  \verb|vis.alter_axes(vtkCubeAxesActor2D.SetNumberOfPoints, (5,))|.
  Note that the single argument must be encased in a tuple.
\item[render\_quantity\_height(quantityName, zScale=1.0, offset=0.0, dynamic=True)]
  Register a new quantity to be rendered. The value of the quantity at
  its vertices is used as the height, which is multiplied by
  \textit{zScale} and shifted by \textit{offset}. The \textit{dynamic}
  parameter indicates that the quantity varies as time progresses.
\item[colour\_height\_quantity(quantityName, colour=(0.5, 0.5, 0.5))]
  Colour a quantity that has been registered with
  \verb|render_quantity_height|. The \textit{colour} parameter can
  take one of two forms:
  \begin{itemize}
  \item A 3-tuple of values in [0,1] to specify a single colour in RGB.
  \item A 3-tuple of values where:
    \begin{itemize}
    \item The first element is a function that takes as its only
      parameter a dictionary mapping quantity names to vertex values.
      Its return value is a list of values indicating some scalar
      quantity at each vertex. The magnitude of these scalars is used
      to colour the quantity.
    \item The second element is a number that sets a lower bound on
      the quantity. This defines what magnitude is interpreted as red.
    \item The final element is a number that sets an upper bound on
      the quantity. This defines what magnitude is interpreted as
      blue.
    \end{itemize}
    This results in a colouring that ranges from red to blue based on
    the values returned by the function.
  \end{itemize}
\item[overlay\_polygon(coords, height=0.0, colour=(1.0, 0.0, 0.0))]
  Render a level polygon in the output. \textit{coords} is a list of
  2-tuples representing the vertices of the polygon in the x-y plane.
  Each 2-tuple represents one (x,y) pair. \textit{height} is the value
  used as the z-coordinate for all the points and \textit{colour} is a
  3-tuple of values in [0,1] that represent an RGB value.
\end{description}
\subsection{Additional OfflineVisualiser Methods}
The following additional methods are available for use in the offline
visualiser only:
\begin{description}
\item[precache\_height\_quantities()]
  The offline visualiser maintains a cache of data extracted from the
  sww file as it is being read to speed up repeated accesses to the
  same frame. Normally this cache is empty when the visualiser is
  \verb|start()|ed, but \verb|precache_height_quantities()| will
  populate the cache for every frame, reducing time taken to render
  any frame. Obviously, this increases the startup time.
\end{description}
\subsection{Additional RealtimeVisualiser Methods}
The following additional methods are available for use in the realtime
visualiser only:
\begin{description}
\item[update()]
  Synchronise the rendered image to the values computed in the domain.
  This needs to be called within the \verb|evolve()| loop or else the
  visualiser will only display the first frame.
\item[evolveFinished()]
  Normally, the visualiser waits on updates from the evolve loop (sent
  via \verb|update()|) to prevent either the visualiser or the
  computations from being starved CPU access. Once the evolve loop has
  finished, the visualiser will still be waiting for signals.
  \verb|evolveFinished()| will signal the visualiser to stop waiting
  for more input because the simulation has terminated.
\end{description}
\section{Design}
\subsection{GUI}
The Tkinter GUI is generated by the \verb|setup_gui()| function.
Subclasses are expected to override this function to add their own
controls (e.g., the offline visualiser adds stepping controls). Note
that the all the Tk frames are assembled using the grid layout
manager. Using the pack or place layout managers will probably cause
the gui to hang while Tk tries to place all the components in a way
that is agreeable to all the layout managers.
\subsection{VTK and Thread-Safety}
Implementation of the realtime visualiser using VTK and Tkinter caused
the design of the visualisers to become more complicated. Tkinter's
event loop needs to be run in its own thread to avoid interfering with
the calculations performed during evolve. Each visualiser is therefore
created and run in its own thread.

The VTK library is not thread safe and requires all data structures to
be in the same thread. To safely handle this, none of the
configuration functions (\verb|render_quantity_height()| etc.,) create
or modify VTK data structures. No actual VTK classes are created or
used until the thread is running.
\subsection{Realtime Visualiser Synchronisation Issues}
To prevent starvation (of either the visualiser or the evolve
process), the realtime visualiser is set up to explicitly synchronise
so that only one of them is running at a time. This is achieved
through the use of several condition variables (Event objects in
Python). This simulates the following message passing sequence:\\

\begin{turn}{-90}
\includegraphics[width=0.8\textwidth]{message_passing}
\end{turn}

In addition, pausing the visualiser is done by making the evolution
thread wait on a condition variable called \verb|sync_unpaused|. It is
only clear (i.e., waiting will occur) when the visualiser's pause
button has been pressed. When it has been cleared, the evolve thread
will stall until it is reset by pressing the resume button.
\subsection{Writing New Visualisers}
The visualiser base class has been designed to be agnostic of the
source data. This means that the source parameter can be any python
object, provided a visualiser is written that will understand it. An
overridden constructor will need to call
\verb|Visualiser.__init__(self, source)| (preferably as the first
command) to set up several important data structures used to store the
VTK pipeline. The function \verb|self.alter_tkroot()|, which behaves
in much the same way as \verb|alter_axes()| documented earlier, can be
used to add new events to be run once the Tk mainloop has started. The
OfflineVisualiser uses this technique to start animating the data.

Subclasses of Visualiser are required to fill in the following
additional methods, at a minimum:
\begin{description}
\item[setup\_grid()] Create a \verb|vtkCellArray| instance that
  represents the triangle data and its connectivity and save it as
  self.vtk\_cells.
\item[update\_height\_quantity(quantityName, dynamic=True)] Create a
  vtkPolyData object and store it in self.vtk\_polyData[quantityName].
\item[get\_3d\_bounds()] Get the minimum and maximum bounds for the x,
  y and z directions.  Return as a list of double in the order (xmin,
  xmax, ymin, ymax, zmin, zmax), suitable for passing to
  vtkCubeAxesActor2D::SetRanges().
\item[build\_quantity\_dict()] Build and return a dictionary mapping
  quantity name $\to$ Numeric array of vertex values for that quantity.
\end{description}
\end{document}
