Index: /anuga_core/documentation/vtk_visualiser_reference/message_passing.fig
===================================================================
--- /anuga_core/documentation/vtk_visualiser_reference/message_passing.fig	(revision 3966)
+++ /anuga_core/documentation/vtk_visualiser_reference/message_passing.fig	(revision 3966)
@@ -0,0 +1,51 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 3525 3600 6000
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 1200 2550 1200 2850
+2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 1200 2850 1200 6000
+2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 1800 3600 3525
+2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 1200 1200 1200 2550
+2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 1200 3600 1800
+2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4800 1500 5400 1500
+2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4800 1200 5400 1200
+2 1 3 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4800 1800 5400 1800
+2 1 3 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 1205 2833 3605 3508
+2 1 3 1 0 7 50 -1 -1 3.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 1725 1200 2475
+4 0 0 50 -1 0 12 0.0000 4 135 1095 3075 1050 Evolve Thread\001
+4 0 0 50 -1 0 12 0.0000 4 135 1350 675 1050 Visualiser Thread\001
+4 0 0 50 -1 0 12 0.0000 4 180 600 5475 1275 Waiting\001
+4 0 0 50 -1 0 12 0.0000 4 180 765 5475 1575 Executing\001
+4 0 0 50 -1 0 12 0.0000 4 180 1350 5475 1875 Passing Message\001
+4 0 0 50 -1 0 12 0.0000 4 135 1110 2100 3000 Visualiser Idle\001
+4 0 0 50 -1 0 12 0.0000 4 180 870 2625 3150 (sync_idle)\001
+4 0 0 50 -1 0 12 0.0000 4 180 1245 2100 1875 Ready to redraw\001
+4 0 0 50 -1 0 12 0.0000 4 180 1605 1350 2100 (sync_redrawReady)\001
Index: /anuga_core/documentation/vtk_visualiser_reference/vtk_visualiser_reference.tex
===================================================================
--- /anuga_core/documentation/vtk_visualiser_reference/vtk_visualiser_reference.tex	(revision 3966)
+++ /anuga_core/documentation/vtk_visualiser_reference/vtk_visualiser_reference.tex	(revision 3966)
@@ -0,0 +1,276 @@
+\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}
Index: /anuga_core/source/anuga/examples/visualise_rectangle.py
===================================================================
--- /anuga_core/source/anuga/examples/visualise_rectangle.py	(revision 3965)
+++ /anuga_core/source/anuga/examples/visualise_rectangle.py	(revision 3966)
@@ -7,5 +7,5 @@
 ##########
 
-# Import the offline visualiser
+# Import the realtime visualiser
 from anuga.visualiser import RealtimeVisualiser
 from vtk import vtkCubeAxesActor2D
Index: /anuga_core/source/anuga/visualiser/realtime.py
===================================================================
--- /anuga_core/source/anuga/visualiser/realtime.py	(revision 3965)
+++ /anuga_core/source/anuga/visualiser/realtime.py	(revision 3966)
@@ -38,9 +38,5 @@
         self.sync_redrawReady = Event()
         self.sync_redrawReady.clear()
-
-    def run(self):
-        self.alter_tkroot(Tk.after, (100, self.sync_idle.set))
-        Visualiser.run(self)
-
+        
     def setup_grid(self):
         self.vtk_cells = vtkCellArray()
