diff --git a/doc/images/lightboxpanel.png b/doc/images/lightboxpanel.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d67b669f304aa7b08fb5da9c3ec5dd7ce7be8fe
Binary files /dev/null and b/doc/images/lightboxpanel.png differ
diff --git a/doc/images/orthopanel.png b/doc/images/orthopanel.png
new file mode 100644
index 0000000000000000000000000000000000000000..c01e24a8b81929b51a0af7ddb4f4983626011546
Binary files /dev/null and b/doc/images/orthopanel.png differ
diff --git a/fsl/fsleyes/colourmaps.py b/fsl/fsleyes/colourmaps.py
index 67eb64f909f16ade7d6fabdbd77f08ea573b8798..e41127cb359d6fbc39c629818898958101ec06ca 100644
--- a/fsl/fsleyes/colourmaps.py
+++ b/fsl/fsleyes/colourmaps.py
@@ -625,8 +625,17 @@ def randomBrightColour():
 def complementaryColour(rgb):
     """Generate a colour which can be used as a complement/opposite
     to the given colour.
+
+    If the given ``rgb`` sequence contains four values, the fourth
+    value (e.g. alpha) is returned unchanged.
     """
 
+    if len(rgb) >= 4:
+        a   = rgb[3:]
+        rgb = rgb[:3]
+    else:
+        a   = []
+
     h, l, s = colorsys.rgb_to_hls(*rgb)
 
     # My ad-hoc complementary colour calculation:
@@ -646,7 +655,7 @@ def complementaryColour(rgb):
 
     nr, ng, nb = colorsys.hls_to_rgb(nh, nl, ns)
 
-    return nr, ng, nb
+    return [nr, ng, nb] + a
 
 
 _cmapDir = op.join(op.dirname(__file__), 'colourmaps')
diff --git a/fsl/fsleyes/views/lightboxpanel.py b/fsl/fsleyes/views/lightboxpanel.py
index cf161bfe5a7e56a591a9f4347a7b83342c5e7a6c..1211870b23883694d96312afe26e6c821813795e 100644
--- a/fsl/fsleyes/views/lightboxpanel.py
+++ b/fsl/fsleyes/views/lightboxpanel.py
@@ -5,13 +5,11 @@
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
-"""This module defines the :class:`LightBoxPanel, a panel which contains a
-:class:`.LightBoxCanvas`, for displaying multiple slices from a collection of
-overlays.
+"""This module provides the :class:`LightBoxPanel`, which displays multiple
+2D slices of 3D overlays.
 """
 
 import logging
-log = logging.getLogger(__name__)
 
 import wx
 
@@ -22,17 +20,55 @@ import fsl.fsleyes.gl.wxgllightboxcanvas          as lightboxcanvas
 import fsl.fsleyes.controls.lightboxtoolbar       as lightboxtoolbar
 import fsl.fsleyes.controls.overlaydisplaytoolbar as overlaydisplaytoolbar
 import fsl.fsleyes.displaycontext.lightboxopts    as lightboxopts
-import canvaspanel
+import                                               canvaspanel
+
+
+log = logging.getLogger(__name__)
 
 
 class LightBoxPanel(canvaspanel.CanvasPanel):
-    """Convenience Panel which contains a :class:`.LightBoxCanvas` and a
-    scrollbar, and sets up mouse-scrolling behaviour.
+    """The ``LightBoxPanel`` is a *FSLeyes view* which is capable of
+    displaying multiple 2D slices of the 3D overlays conatined in an
+    :class:`.OverlayList`. A ``LightBoxPanel`` looks something like the
+    following:
+
+    .. image:: images/lightboxpanel.png
+       :scale: 50%
+       :align: center
+
+    
+    The ``LightBoxPanel`` uses a :class:`.LightBoxCanvas` panel to display
+    the slices, and a :class:`.LightBoxOpts` instance to manage the display
+    settings. The canvas is accessed through the :meth:`getCanvas` and
+    :meth:`getGLCanvases` methods, and the ``LightBoxOpts`` instanace can
+    be retrieved via the :meth:`.CanvasPanel.getSceneOptions` method.
+
+
+    The ``LightBoxPanel`` adds the following actions to those already
+    provided by the :class:`.CanvasPanel`:
+
+    ========================= ========================================
+    ``toggleLightBoxToolBar`` Shows/hides a :class:`.LightBoxToolBar`.
+    ========================= ========================================
+
+    
+    When a ``LightBoxPanel`` is created, it will automatically add the
+    following control panels:
+
+    .. autosummary::
+       :nosignatures:
+
+       ~fsl.fsleyes.controls.lightboxtoolbar.LightBoxToolBar
+       ~fsl.fsleyes.controls.overlaydisplaytoolbar.OverlayDisplayToolBar
     """
 
 
     def __init__(self, parent, overlayList, displayCtx):
-        """
+        """Create a ``LightBoxPanel``.
+
+        :arg parent:      A :mod:`wx` parent object.
+        :arg overlayList: A :class:`.OverlayList` instance.
+        :arg displayCtx:  A :class:`.DisplayContext` instance.
         """
 
         sceneOpts = lightboxopts.LightBoxOpts()
@@ -49,24 +85,24 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
                                          sceneOpts,
                                          actionz)
 
-        self._scrollbar = wx.ScrollBar(
+        self.__scrollbar = wx.ScrollBar(
             self.getCanvasPanel(),
             style=wx.SB_VERTICAL)
         
-        self._lbCanvas  = lightboxcanvas.LightBoxCanvas(
+        self.__lbCanvas  = lightboxcanvas.LightBoxCanvas(
             self.getCanvasPanel(),
             overlayList,
             displayCtx)
 
-        self._lbCanvas.bindProps('zax',             sceneOpts)
-        self._lbCanvas.bindProps('bgColour',        sceneOpts)
-        self._lbCanvas.bindProps('cursorColour',    sceneOpts)
-        self._lbCanvas.bindProps('showCursor',      sceneOpts)
-        self._lbCanvas.bindProps('showGridLines',   sceneOpts)
-        self._lbCanvas.bindProps('highlightSlice',  sceneOpts)
-        self._lbCanvas.bindProps('renderMode',      sceneOpts)
-        self._lbCanvas.bindProps('softwareMode',    sceneOpts)
-        self._lbCanvas.bindProps('resolutionLimit', sceneOpts)
+        self.__lbCanvas.bindProps('zax',             sceneOpts)
+        self.__lbCanvas.bindProps('bgColour',        sceneOpts)
+        self.__lbCanvas.bindProps('cursorColour',    sceneOpts)
+        self.__lbCanvas.bindProps('showCursor',      sceneOpts)
+        self.__lbCanvas.bindProps('showGridLines',   sceneOpts)
+        self.__lbCanvas.bindProps('highlightSlice',  sceneOpts)
+        self.__lbCanvas.bindProps('renderMode',      sceneOpts)
+        self.__lbCanvas.bindProps('softwareMode',    sceneOpts)
+        self.__lbCanvas.bindProps('resolutionLimit', sceneOpts)
 
         # Bind these properties the other way around,
         # so that the sensible values calcualted by
@@ -74,96 +110,109 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
         # propagated to the LBOpts instance, rather
         # than the non-sensible default values in the
         # LBOpts instance.
-        sceneOpts     .bindProps('nrows',           self._lbCanvas)
-        sceneOpts     .bindProps('ncols',           self._lbCanvas)
-        sceneOpts     .bindProps('topRow',          self._lbCanvas)
-        sceneOpts     .bindProps('sliceSpacing',    self._lbCanvas)
-        sceneOpts     .bindProps('zrange',          self._lbCanvas)
+        sceneOpts.bindProps('nrows',        self.__lbCanvas)
+        sceneOpts.bindProps('ncols',        self.__lbCanvas)
+        sceneOpts.bindProps('topRow',       self.__lbCanvas)
+        sceneOpts.bindProps('sliceSpacing', self.__lbCanvas)
+        sceneOpts.bindProps('zrange',       self.__lbCanvas)
 
-        self._canvasSizer = wx.BoxSizer(wx.HORIZONTAL)
-        self.getCanvasPanel().SetSizer(self._canvasSizer)
+        self.__canvasSizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.getCanvasPanel().SetSizer(self.__canvasSizer)
 
-        self._canvasSizer.Add(self._lbCanvas,  flag=wx.EXPAND, proportion=1)
-        self._canvasSizer.Add(self._scrollbar, flag=wx.EXPAND)
+        self.__canvasSizer.Add(self.__lbCanvas,  flag=wx.EXPAND, proportion=1)
+        self.__canvasSizer.Add(self.__scrollbar, flag=wx.EXPAND)
 
         # When the display context location changes,
         # make sure the location is shown on the canvas
-        self._lbCanvas.pos.xyz = self._displayCtx.location
+        self.__lbCanvas.pos.xyz = self._displayCtx.location
         self._displayCtx .addListener('location',
                                       self._name,
-                                      self._onLocationChange)
+                                      self.__onLocationChange)
         self._displayCtx .addListener('selectedOverlay',
                                       self._name,
-                                      self._selectedOverlayChanged)
+                                      self.__selectedOverlayChanged)
         self._overlayList.addListener('overlays',
                                       self._name,
-                                      self._selectedOverlayChanged)
-
-        sceneOpts.zoom = 750
-
-        self._onLightBoxChange()
-        self._onZoom()
+                                      self.__selectedOverlayChanged)
 
         # When any lightbox properties change,
         # make sure the scrollbar is updated
         sceneOpts.addListener(
-            'ncols',        self._name, self._ncolsChanged)
+            'ncols',        self._name, self.__ncolsChanged)
         sceneOpts.addListener(
-            'nrows',        self._name, self._onLightBoxChange)
+            'nrows',        self._name, self.__onLightBoxChange)
         sceneOpts.addListener(
-            'topRow',       self._name, self._onLightBoxChange)
+            'topRow',       self._name, self.__onLightBoxChange)
         sceneOpts.addListener(
-            'sliceSpacing', self._name, self._onLightBoxChange)
+            'sliceSpacing', self._name, self.__onLightBoxChange)
         sceneOpts.addListener(
-            'zrange',       self._name, self._onLightBoxChange)
+            'zrange',       self._name, self.__onLightBoxChange)
         sceneOpts.addListener(
-            'zax',          self._name, self._onLightBoxChange)
+            'zax',          self._name, self.__onLightBoxChange)
         sceneOpts.addListener(
-            'zoom',         self._name, self._onZoom)
+            'zoom',         self._name, self.__onZoom)
 
         # When the scrollbar is moved,
         # update the canvas display
-        self._scrollbar.Bind(wx.EVT_SCROLL, self._onScroll)
+        self.__scrollbar.Bind(wx.EVT_SCROLL, self.__onScroll)
 
-        self.Bind(wx.EVT_SIZE, self._onResize)
+        self.Bind(wx.EVT_SIZE, self.__onResize)
 
-        self.Layout()
+        sceneOpts.zoom = 750
 
-        self._selectedOverlayChanged()
+        self.__onLightBoxChange()
+        self.__onZoom()
+        self.__selectedOverlayChanged()
+        self.Layout()
         self.initProfile()
 
-        # The FSLEyesFrame AuiManager seems to
+        # The ViewPanel AuiManager seems to
         # struggle if we add these toolbars
         # immediately, so we'll do it asynchronously
         def addToolbars():
-            
             self.togglePanel(overlaydisplaytoolbar.OverlayDisplayToolBar,
                              viewPanel=self)
             self.togglePanel(lightboxtoolbar.LightBoxToolBar, lb=self)
 
         wx.CallAfter(addToolbars)
-            
 
 
     def destroy(self):
-        """Removes property listeners"""
+        """Must be called when this ``LightBoxPanel`` is closed.
+
+        Removes property listeners, destroys the :class:`.LightBoxCanvas`,
+        and calls :meth:`.CanvasPanel.destroy`.
+        """
 
         self._displayCtx .removeListener('location',        self._name)
         self._displayCtx .removeListener('selectedOverlay', self._name)
         self._overlayList.removeListener('overlays',        self._name)
 
-        self._lbCanvas.destroy()
+        self.__lbCanvas.destroy()
 
         canvaspanel.CanvasPanel.destroy(self)
 
+
+    def getGLCanvases(self):
+        """Returns a list containing the :class:`.LightBoxCanvas` contained
+        within this ``LightBoxPanel``.
+        """
+        return [self.__lbCanvas]
         
-    def _selectedOverlayChanged(self, *a):
-        """Called when the selected overlay changes.
 
-        Registers a listener on the :attr:`.Display.transform` property
-        associated with the selected overlay, so that the
-        :meth:`_transformChanged` method will be called on ``transform``
-        changes.
+    def getCanvas(self):
+        """Returns a reference to the :class:`.LightBoxCanvas` instance. """
+        return self.__lbCanvas
+
+        
+    def __selectedOverlayChanged(self, *a):
+        """Called when the :attr:`.DisplayContext.selectedOverlay` changes.
+
+        If the currently selected overlay is an :class:`.Image` instance, or
+        has an associated reference image (see
+        :meth:`.DisplayOpts.getReferenceImage`), a listener is registered on
+        the reference image :attr:`.ImageOpts.transform` property, so that the
+        :meth:`__transformChanged` method will be called when it changes.
         """
 
         if len(self._overlayList) == 0:
@@ -185,17 +234,18 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
             if overlay == selectedOverlay:
                 opts.addListener('transform',
                                  self._name,
-                                 self._transformChanged)
+                                 self.__transformChanged)
 
-        self._transformChanged()
+        self.__transformChanged()
 
 
-    def _transformChanged(self, *a):
-        """Called when the transform for the currently selected overlay
-        changes.
+    def __transformChanged(self, *a):
+        """Called when the :attr:`.ImageOpts.transform` property for the
+        reference image of the currently selected overlay changes.
 
-        Updates the ``sliceSpacing`` and ``zrange`` properties to values
-        sensible to the new overlay display space.
+        Updates the :attr:`.LightBoxOpts.sliceSpacing` and
+        :attr:`.LightBoxOpts.zrange` properties to values sensible to the
+        new overlay display space.
         """
 
         sceneOpts = self.getSceneOptions()
@@ -217,26 +267,12 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
             sceneOpts.zrange.x     = (loBounds[sceneOpts.zax],
                                       hiBounds[sceneOpts.zax])
 
-        self._onResize()
-
-
-    def getGLCanvases(self):
-        """Returns a list of length 1, containing the :class:`.SliceCanvas`
-        contained within this ``LightBoxPanel``.
-        """
-        return [self._lbCanvas]
-        
-
-    def getCanvas(self):
-        """Returns a reference to the :class:`.LightBoxCanvas` instance (which
-        is actually a :class:`.WXGLLightBoxCanvas`).
-        """
-        return self._lbCanvas
+        self.__onResize()
 
         
-    def _onZoom(self, *a):
-        """Called when the :attr:`zoom` property changes. Updates the
-        number of columns on the lightbox canvas.
+    def __onZoom(self, *a):
+        """Called when the :attr:`.SceneOpts.zoom` property changes. Updates
+        the number of slice columns shown.
         """
         opts       = self.getSceneOptions()
         minval     = opts.getConstraint('zoom', 'minval')
@@ -245,10 +281,10 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
         opts.ncols = int(1 + np.round(normZoom * 29))
 
 
-    def _onResize(self, ev=None):
-        """Called when the panel is resized. Automatically adjusts the
-        number of lightbox rows to the maximum displayable number (given
-        that the number of columns is fixed).
+    def __onResize(self, ev=None):
+        """Called when the panel is resized. Automatically adjusts the number
+        of rows to the maximum displayable number (given that the number of
+        columns is fixed).
         """
         if ev is not None: ev.Skip()
 
@@ -256,57 +292,57 @@ class LightBoxPanel(canvaspanel.CanvasPanel):
         # canvas panel size is up to date
         self.Layout()
 
-        width,   height   = self._lbCanvas .GetClientSize().Get()
-        sbWidth, sbHeight = self._scrollbar.GetClientSize().Get()
+        width,   height   = self.__lbCanvas .GetClientSize().Get()
+        sbWidth, sbHeight = self.__scrollbar.GetClientSize().Get()
 
         width = width - sbWidth
 
-        xlen = self._displayCtx.bounds.getLen(self._lbCanvas.xax)
-        ylen = self._displayCtx.bounds.getLen(self._lbCanvas.yax)
+        xlen = self._displayCtx.bounds.getLen(self.__lbCanvas.xax)
+        ylen = self._displayCtx.bounds.getLen(self.__lbCanvas.yax)
 
-        sliceWidth  = width / float(self._lbCanvas.ncols)
+        sliceWidth  = width / float(self.__lbCanvas.ncols)
         sliceHeight = fsllayout.calcPixHeight(xlen, ylen, sliceWidth)
 
         if sliceHeight > 0: 
-            self._lbCanvas.nrows = int(height / sliceHeight)
+            self.__lbCanvas.nrows = int(height / sliceHeight)
 
 
-    def _onLocationChange(self, *a):
-        """Called when the display context location changes.
+    def __onLocationChange(self, *a):
+        """Called when the :attr:`.DisplayContext.location` changes.
 
-        Updates the canvas location.
+        Updates the location shown on the :class:`.LightBoxCanvas`.
         """
         
-        xpos = self._displayCtx.location.getPos(self._lbCanvas.xax)
-        ypos = self._displayCtx.location.getPos(self._lbCanvas.yax)
-        zpos = self._displayCtx.location.getPos(self._lbCanvas.zax)
-        self._lbCanvas.pos.xyz = (xpos, ypos, zpos)
+        xpos = self._displayCtx.location.getPos(self.__lbCanvas.xax)
+        ypos = self._displayCtx.location.getPos(self.__lbCanvas.yax)
+        zpos = self._displayCtx.location.getPos(self.__lbCanvas.zax)
+        self.__lbCanvas.pos.xyz = (xpos, ypos, zpos)
 
 
-    def _ncolsChanged(self, *a):
-        """Called when the lightbox canvas ``ncols`` property changes.
+    def __ncolsChanged(self, *a):
+        """Called when the :attr:`.LightBoxOpts.ncols` property changes.
         Calculates the number of rows to display, and updates the
         scrollbar.
         """
-        self._onResize()
-        self._onLightBoxChange()
+        self.__onResize()
+        self.__onLightBoxChange()
 
 
-    def _onLightBoxChange(self, *a):
-        """Called when any lightbox display properties change.
+    def __onLightBoxChange(self, *a):
+        """Called when any :class:`.LightBoxOpts` property changes.
 
         Updates the scrollbar to reflect the change.
         """
-        self._scrollbar.SetScrollbar(self._lbCanvas.topRow,
-                                     self._lbCanvas.nrows,
-                                     self._lbCanvas.getTotalRows(),
-                                     self._lbCanvas.nrows,
-                                     True)
+        self.__scrollbar.SetScrollbar(self.__lbCanvas.topRow,
+                                      self.__lbCanvas.nrows,
+                                      self.__lbCanvas.getTotalRows(),
+                                      self.__lbCanvas.nrows,
+                                      True)
 
         
-    def _onScroll(self, *a):
+    def __onScroll(self, *a):
         """Called when the scrollbar is moved.
 
-        Updates the top row displayed on the canvas.
+        Updates the top row displayed on the :class:`.LightBoxCanvas`.
         """
-        self._lbCanvas.topRow = self._scrollbar.GetThumbPosition()
+        self.__lbCanvas.topRow = self.__scrollbar.GetThumbPosition()
diff --git a/fsl/fsleyes/views/orthopanel.py b/fsl/fsleyes/views/orthopanel.py
index c6a945c2107539c3f2892a103d5091431f3321c9..52b6dd2a161a1c1b12e974024fc050c699ba0dea 100644
--- a/fsl/fsleyes/views/orthopanel.py
+++ b/fsl/fsleyes/views/orthopanel.py
@@ -1,18 +1,22 @@
 #!/usr/bin/env python
 #
-# orthopanel.py - A wx/OpenGL widget for displaying and interacting with a
-# collection of 3D overlays. 
+# orthopanel.py - The OrthoPanel class.
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
-"""A :mod:`wx`/:mod:`OpenGL` widget for displaying and interacting with a
-collection of 3D overlays.
+"""This module provides the :class:`OrthoPanel` class, which displays a 2D
+view of 3D overlays.
 
-Displays three canvases, each of which shows the same overlay(s) on a
-different orthogonal plane. The displayed location is driven by the
-:attr:`.DisplayContext.location` property.
+A couple of other classes are provided for convenience:
+
+.. autosummary::
+   :nosignatures:
+
+   OrthoFrame
+   OrthoDialog
 """
 
+
 import logging
 
 import wx
@@ -34,14 +38,97 @@ log = logging.getLogger(__name__)
 
 
 class OrthoPanel(canvaspanel.CanvasPanel):
+    """The ``OrthoPanel`` class is a *FSLeyes view* which displays a 2D view
+    of 3D overlays.  The ``OrthoPanel`` is the primary point of user
+    interaction in *FSLeyes*.
+
+
+    **Overview**
+
+    
+    An ``OrthoPanel`` contains three :class:`.SliceCanvas` panels, each of
+    which provide a 2D view of the overlays in the :class:`.OverlayList` along
+    one axis. These ``SliceCanvas`` instances can be accessed through the
+    :meth:`getXCanvas`, :meth:`getYCanvas`, :meth:`getZCanvas`, and
+    :meth:`getGLCanvases` methods.
+
+
+    An ``OrthoPanel`` looks something like this:
+
+
+    .. image:: images/orthopanel.png
+       :scale: 50%
+       :align: center
+
+
+    **Anatomical labels**
+    
+
+    In addition to the three ``SliceCanvas`` panels, the ``OrthoPanel`` is
+    capable of displaying labels around each panel, showing the user the
+    anatomical orientation of the display on each panel. These labels are only
+    shown if the currently selected overlay (as dicated by the
+    :attr:`.DisplayContext.selectedOverlay` property) is a :class:`.Image`
+    instance, **or** the :meth:`.DisplayOpts.getReferenceImage` method for the
+    currently selected overlay returns an :class:`.Image` instance.
+
+
+    **Display**
+
+
+    The display of an ``OrthoPanel`` can be configured through all of the
+    settings provided by the :class:`.OrthoOpts` class. The ``OrthoOpts``
+    instance for a given ``OrthoPanel`` can be accessed via the
+    :meth:`.CanvasPanel.getSceneOptions` method.
+
+
+    **Interaction**
+
+
+    Two interaction profiles are defined for use with the ``OrthoPanel`` (see
+    the :class:`.ViewPanel` for an overview of *profiles*):
+
+    ======== =========================================================
+    ``view`` Viewing/navigation, using the :class:`.OrthoViewProfile`.
+    
+    ``edit`` Simple editing of :class:`.Image` overlays, using the
+             :class:`.OrthoEditProfile` (see also the
+             :mod:`~fsl.fsleyes.editor` package).
+    ======== =========================================================
+    
+
+    **Actions and control panels**
+
+
+    The ``OrthoPanel`` adds a few extra actions to those provided by the 
+    :class:`.CanvasPanel` class:
+
+
+    ====================== ==========================================
+    ``toggleOrthoToolBar`` Shows/hides an :class:`.OrthoToolBar`.
+    ``toggleEditToolBar``  Shows/hides an :class:`.OrthoEditToolBar`.
+    ====================== ==========================================
+
+
+    When an ``OrthoPanel`` is created, it will automatically add the
+    following control panels:
+
+    .. autosummary::
+       :nosignatures:
+    
+       ~fsl.fsleyes.controls.orthotoolbar.OrthoToolBar
+       ~fsl.fsleyes.controls.orthoedittoolbar.OrthoEditToolBar
+       ~fsl.fsleyes.controls.overlaydisplaytoolbar.OverlayDisplayToolBar
+    """
 
 
     def __init__(self, parent, overlayList, displayCtx):
-        """
-        Creates three SliceCanvas objects, each displaying the images
-        in the given image list along a different axis. 
-        """
+        """Create an ``OrthoPanel``.
 
+        :arg parent:      The :mod:`wx` parent.
+        :arg overlayList: An :class:`.OverlayList` instance.
+        :arg displayCtx:  A :class:`.DisplayContext` instance.
+        """
 
         sceneOpts = orthoopts.OrthoOpts()
 
@@ -63,109 +150,100 @@ class OrthoPanel(canvaspanel.CanvasPanel):
 
         # The canvases themselves - each one displays a
         # slice along each of the three world axes
-        self._xcanvas = slicecanvas.WXGLSliceCanvas(canvasPanel,
-                                                    overlayList,
-                                                    displayCtx,
-                                                    zax=0)
-        self._ycanvas = slicecanvas.WXGLSliceCanvas(canvasPanel,
-                                                    overlayList,
-                                                    displayCtx,
-                                                    zax=1)
-        self._zcanvas = slicecanvas.WXGLSliceCanvas(canvasPanel,
-                                                    overlayList,
-                                                    displayCtx,
-                                                    zax=2)
+        self.__xcanvas = slicecanvas.WXGLSliceCanvas(canvasPanel,
+                                                     overlayList,
+                                                     displayCtx,
+                                                     zax=0)
+        self.__ycanvas = slicecanvas.WXGLSliceCanvas(canvasPanel,
+                                                     overlayList,
+                                                     displayCtx,
+                                                     zax=1)
+        self.__zcanvas = slicecanvas.WXGLSliceCanvas(canvasPanel,
+                                                     overlayList,
+                                                     displayCtx,
+                                                     zax=2)
 
         # Labels to show anatomical orientation,
         # stored in a dict for each canvas
-        self._xLabels = {}
-        self._yLabels = {}
-        self._zLabels = {}
+        self.__xLabels = {}
+        self.__yLabels = {}
+        self.__zLabels = {}
+        
         for side in ('left', 'right', 'top', 'bottom'):
-            self._xLabels[side] = wx.StaticText(canvasPanel)
-            self._yLabels[side] = wx.StaticText(canvasPanel)
-            self._zLabels[side] = wx.StaticText(canvasPanel)
+            self.__xLabels[side] = wx.StaticText(canvasPanel)
+            self.__yLabels[side] = wx.StaticText(canvasPanel)
+            self.__zLabels[side] = wx.StaticText(canvasPanel)
 
-        self._xcanvas.bindProps('showCursor',   sceneOpts)
-        self._ycanvas.bindProps('showCursor',   sceneOpts)
-        self._zcanvas.bindProps('showCursor',   sceneOpts)
+        self.__xcanvas.bindProps('showCursor',   sceneOpts)
+        self.__ycanvas.bindProps('showCursor',   sceneOpts)
+        self.__zcanvas.bindProps('showCursor',   sceneOpts)
 
-        self._xcanvas.bindProps('bgColour',     sceneOpts)
-        self._ycanvas.bindProps('bgColour',     sceneOpts)
-        self._zcanvas.bindProps('bgColour',     sceneOpts)
+        self.__xcanvas.bindProps('bgColour',     sceneOpts)
+        self.__ycanvas.bindProps('bgColour',     sceneOpts)
+        self.__zcanvas.bindProps('bgColour',     sceneOpts)
 
-        self._xcanvas.bindProps('cursorColour', sceneOpts)
-        self._ycanvas.bindProps('cursorColour', sceneOpts)
-        self._zcanvas.bindProps('cursorColour', sceneOpts)
+        self.__xcanvas.bindProps('cursorColour', sceneOpts)
+        self.__ycanvas.bindProps('cursorColour', sceneOpts)
+        self.__zcanvas.bindProps('cursorColour', sceneOpts)
 
         # Callbacks for ortho panel layout options
-        sceneOpts.addListener('layout',     self._name, self._refreshLayout)
-        sceneOpts.addListener('showLabels', self._name, self._refreshLabels)
+        sceneOpts.addListener('layout',     self._name, self.__refreshLayout)
+        sceneOpts.addListener('showLabels', self._name, self.__refreshLabels)
         sceneOpts.addListener('bgColour'  , self._name, self.__bgColourChanged)
 
-        self.__bgColourChanged()
-
         # Individual zoom control for each canvas
-        self._xcanvas.bindProps('zoom', sceneOpts, 'xzoom')
-        self._ycanvas.bindProps('zoom', sceneOpts, 'yzoom')
-        self._zcanvas.bindProps('zoom', sceneOpts, 'zzoom')
+        self.__xcanvas.bindProps('zoom', sceneOpts, 'xzoom')
+        self.__ycanvas.bindProps('zoom', sceneOpts, 'yzoom')
+        self.__zcanvas.bindProps('zoom', sceneOpts, 'zzoom')
 
-        self._xcanvas.bindProps('renderMode',      sceneOpts)
-        self._ycanvas.bindProps('renderMode',      sceneOpts)
-        self._zcanvas.bindProps('renderMode',      sceneOpts)
+        self.__xcanvas.bindProps('renderMode',      sceneOpts)
+        self.__ycanvas.bindProps('renderMode',      sceneOpts)
+        self.__zcanvas.bindProps('renderMode',      sceneOpts)
 
-        self._xcanvas.bindProps('softwareMode',    sceneOpts)
-        self._ycanvas.bindProps('softwareMode',    sceneOpts)
-        self._zcanvas.bindProps('softwareMode',    sceneOpts)
+        self.__xcanvas.bindProps('softwareMode',    sceneOpts)
+        self.__ycanvas.bindProps('softwareMode',    sceneOpts)
+        self.__zcanvas.bindProps('softwareMode',    sceneOpts)
 
-        self._xcanvas.bindProps('resolutionLimit', sceneOpts)
-        self._ycanvas.bindProps('resolutionLimit', sceneOpts)
-        self._zcanvas.bindProps('resolutionLimit', sceneOpts) 
+        self.__xcanvas.bindProps('resolutionLimit', sceneOpts)
+        self.__ycanvas.bindProps('resolutionLimit', sceneOpts)
+        self.__zcanvas.bindProps('resolutionLimit', sceneOpts) 
 
         # Callbacks for overlay list/selected overlay changes
         self._overlayList.addListener('overlays',
                                       self._name,
-                                      self._overlayListChanged)
+                                      self.__overlayListChanged)
         self._displayCtx .addListener('bounds',
                                       self._name,
-                                      self._refreshLayout) 
+                                      self.__refreshLayout) 
         self._displayCtx .addListener('selectedOverlay',
                                       self._name,
-                                      self._overlayListChanged)
+                                      self.__overlayListChanged)
 
         # Callback for the display context location - when it
         # changes, update the displayed canvas locations
         self._displayCtx.addListener('location',
                                      self._name,
-                                     self._locationChanged) 
+                                     self.__locationChanged) 
 
         # Callbacks for toggling x/y/z canvas display
-        sceneOpts.addListener('showXCanvas',
-                              self._name,
-                              lambda *a: self._toggleCanvas('x'),
-                              weak=False)
-        sceneOpts.addListener('showYCanvas',
-                              self._name,
-                              lambda *a: self._toggleCanvas('y'),
-                              weak=False)
-        sceneOpts.addListener('showZCanvas',
-                              self._name,
-                              lambda *a: self._toggleCanvas('z'),
-                              weak=False)
-
-        # Call the _resize method to refresh
+        sceneOpts.addListener('showXCanvas', self._name, self.__toggleCanvas)
+        sceneOpts.addListener('showYCanvas', self._name, self.__toggleCanvas)
+        sceneOpts.addListener('showZCanvas', self._name, self.__toggleCanvas)
+
+        # Call the __onResize method to refresh
         # the slice canvases when the canvas
         # panel is resized, so aspect ratio
         # is maintained
-        canvasPanel.Bind(wx.EVT_SIZE, self._onResize)
+        canvasPanel.Bind(wx.EVT_SIZE, self.__onResize)
 
         # Initialise the panel
-        self._refreshLayout()
-        self._overlayListChanged()
-        self._locationChanged()
+        self.__refreshLayout()
+        self.__bgColourChanged()
+        self.__overlayListChanged()
+        self.__locationChanged()
         self.initProfile()
 
-        # The FSLEyesFrame AuiManager seems to
+        # The ViewPanel AuiManager seems to
         # struggle if we add these toolbars
         # immediately, so we'll do it asynchronously 
         def addToolbars():
@@ -180,11 +258,11 @@ class OrthoPanel(canvaspanel.CanvasPanel):
 
 
     def destroy(self):
-        """Called when this panel is closed. 
-        
-        The display context and image list will probably live longer than
-        this OrthoPanel. So when this panel is destroyed, all those
-        registered listeners are removed.
+        """Must be called when this ``OrthoPanel`` is closed.
+
+        Removes listeners from the :class:`.DisplayContext` and
+        :class:`.OverlayList` instances, destroys each of the three
+        :class:`.SliceCanvas` panels, and calls :meth:`.CanvasPanel.destroy`.
         """
 
         self._displayCtx .removeListener('location',        self._name)
@@ -192,9 +270,9 @@ class OrthoPanel(canvaspanel.CanvasPanel):
         self._displayCtx .removeListener('selectedOverlay', self._name)
         self._overlayList.removeListener('overlays',        self._name)
 
-        self._xcanvas.destroy()
-        self._ycanvas.destroy()
-        self._zcanvas.destroy()
+        self.__xcanvas.destroy()
+        self.__ycanvas.destroy()
+        self.__zcanvas.destroy()
 
         # The _overlayListChanged method adds
         # listeners to individual overlays,
@@ -205,99 +283,140 @@ class OrthoPanel(canvaspanel.CanvasPanel):
 
         canvaspanel.CanvasPanel.destroy(self)
 
-
-    def __bgColourChanged(self, *a):
-        
-        bg = self.getSceneOptions().bgColour[:3]
-        fg = colourmaps.complementaryColour(bg[:3])
-
-        bg = [int(round(c * 255)) for c in bg] + [255]
-        fg = [int(round(c * 255)) for c in fg] + [255]
-
-        self.getCanvasPanel().SetBackgroundColour(bg)
-        self.getCanvasPanel().SetForegroundColour(fg)
-
-        self._xcanvas.SetBackgroundColour(bg)
-        self._ycanvas.SetBackgroundColour(bg)
-        self._zcanvas.SetBackgroundColour(bg)
-
-        for side in ('left', 'right', 'top', 'bottom'):
-            self._xLabels[side].SetBackgroundColour(bg)
-            self._yLabels[side].SetBackgroundColour(bg)
-            self._zLabels[side].SetBackgroundColour(bg)
-            self._xLabels[side].SetForegroundColour(fg)
-            self._yLabels[side].SetForegroundColour(fg)
-            self._zLabels[side].SetForegroundColour(fg) 
-
-        self.Refresh()
-        
             
     def getGLCanvases(self):
         """Returns all of the :class:`.SliceCanvas` instances contained
         within this ``OrthoPanel``.
         """
-        return [self._xcanvas, self._ycanvas, self._zcanvas]
+        return [self.__xcanvas, self.__ycanvas, self.__zcanvas]
     
 
     def getXCanvas(self):
-        """Returns a reference to the :class:`.SliceCanvas` instance
-        displaying the X axis.
+        """Returns the :class:`.SliceCanvas` instance displaying the X axis.
         """
-        return self._xcanvas
+        return self.__xcanvas
 
     
     def getYCanvas(self):
-        """Returns a reference to the :class:`.SliceCanvas` instance
-        displaying the Y axis.
+        """Returns the :class:`.SliceCanvas` instance displaying the Y axis.
         """ 
-        return self._ycanvas
+        return self.__ycanvas
 
     
     def getZCanvas(self):
-        """Returns a reference to the :class:`.SliceCanvas` instance
-        displaying the Z axis.
+        """Returns the :class:`.SliceCanvas` instance displaying the Z axis.
         """ 
-        return self._zcanvas 
+        return self.__zcanvas 
+        
+
+    def __bgColourChanged(self, *a):
+        """Called when the :class:`.SceneOpts.bgColour` property changes.
+        Updates the panel and anatomical label background/foreground
+        colours.
+        
+        The :attr:`.SliceCanvasOpts.bgColour` properties are bound to
+        ``SceneOpts.bgColour``,(see :meth:`.HasProperties.bindProps`), so we
+        don't need to manually update them.
+        """
+        
+        bg = self.getSceneOptions().bgColour
+        fg = colourmaps.complementaryColour(bg)
+
+        bg = [int(round(c * 255)) for c in bg]
+        fg = [int(round(c * 255)) for c in fg]
+
+        self.getCanvasPanel().SetBackgroundColour(bg)
+        self.getCanvasPanel().SetForegroundColour(fg)
+
+        self.__xcanvas.SetBackgroundColour(bg)
+        self.__ycanvas.SetBackgroundColour(bg)
+        self.__zcanvas.SetBackgroundColour(bg)
+
+        self.__setLabelColours(bg, fg)
+
+
+    def __setLabelColours(self, bgColour, fgColour):
+        """Used by the :meth:`__bgColourChanged` and :meth:`__refreshLabels`
+        methods.
+
+        Sets the background and foreground label colours to the given
+        ``bgColour`` and ``fgColour``, which should be ``(r, g, b, a)``
+        tuples with each value in the range  ``[0, 255]``.
+        """
+
+        bgColour = tuple(bgColour)
+        fgColour = tuple(fgColour)
+        
+        overlay = self._displayCtx.getReferenceImage(
+            self._displayCtx.getSelectedOverlay())
+
+        allLabels = self.__xLabels.values() + \
+                    self.__yLabels.values() + \
+                    self.__zLabels.values() 
+
+        if overlay is not None:
+            opts = self._displayCtx.getOpts(overlay)
+            
+            if opts.transform in ('pixdim', 'id'):
+                xorient = overlay.getVoxelOrientation(0)
+                yorient = overlay.getVoxelOrientation(1)
+                zorient = overlay.getVoxelOrientation(2)
+            else:
+                xorient = overlay.getWorldOrientation(0)
+                yorient = overlay.getWorldOrientation(1)
+                zorient = overlay.getWorldOrientation(2)
+
+            if constants.ORIENT_UNKNOWN in (xorient, yorient, zorient):
+
+                # If the background colour is black or white,
+                # make the foreground colour red, to highlight
+                # the unknown orientation. It's too difficult
+                # to do this for any background colour.
+                if bgColour == (  0,   0,   0, 255) or \
+                   bgColour == (255, 255, 255, 255):
+                    fgColour = (255,   0,   0, 255)
         
+        for lbl in allLabels:
+            lbl.SetForegroundColour(fgColour)
+            lbl.SetBackgroundColour(bgColour)
 
-    def _toggleCanvas(self, canvas):
-        """Called when any of  show*Canvas properties are changed.
         
-        Shows/hides the specified canvas ('x', 'y', or 'z') - this callback
-        is configured in __init__ above.
+    def __toggleCanvas(self, canvas):
+        """Called when any of the :attr:`.OrthoOpts.showXCanvas`,
+        :attr:`.OrthoOpts.showYCanvas`, or :attr:`.OrthoOpts.showZCanvas`
+        properties are changed.
+
+        Shows/hides each of the :class:`.SliceCanvas` panels and anatomical
+        label panels accordingly.
         """
 
-        opts = self.getSceneOptions()
-
-        if canvas == 'x':
-            canvas = self._xcanvas
-            show   = opts.showXCanvas
-            labels = self._xLabels
-        elif canvas == 'y':
-            canvas = self._ycanvas
-            show   = opts.showYCanvas
-            labels = self._yLabels
-        elif canvas == 'z':
-            canvas = self._zcanvas
-            show   = opts.showZCanvas
-            labels = self._zLabels
-
-        self._canvasSizer.Show(canvas, show)
-        for label in labels.values():
-            if (not show) or (show and opts.showLabels):
-                self._canvasSizer.Show(label, show)
+        opts      = self.getSceneOptions()
+        canvases  = [self.__xcanvas,   self.__ycanvas,   self.__zcanvas]
+        allLabels = [self.__xLabels,   self.__yLabels,   self.__zLabels]
+        shows     = [opts.showXCanvas, opts.showYCanvas, opts.showZCanvas]
+
+        for canvas, labels, show in zip(canvases, allLabels, shows):
+
+            canvas.Show(show)
+            self.__canvasSizer.Show(canvas, show)
+
+            for label in labels.values():
+                self.__canvasSizer.Show(label, show and opts.showLabels)
 
         if opts.layout == 'grid':
-            self._refreshLayout()
+            self.__refreshLayout()
 
         self.PostSizeEvent()
 
 
-    def _overlayListChanged(self, *a):
-        """Called when the overlay list or selected overlay is changed.
+    def __overlayListChanged(self, *a):
+        """Called when the :class:`.OverlayList` or
+        :attr:`.DisplayContext.selectedOverlay` is changed.
 
-        Adds a listener to the currently selected overlay, to listen
-        for changes on its transformation matrix.
+        Adds a listener to the :attr:`.DisplayOpts.bounds` property for the
+        currently selected overlay, to listen for changes to its bounds, which
+        will trigger an update to the anatomical labels (see
+        :meth:`__refreshLabels`).
         """
         
         for i, ovl in enumerate(self._overlayList):
@@ -309,57 +428,54 @@ class OrthoPanel(canvaspanel.CanvasPanel):
             if i == self._displayCtx.selectedOverlay:
                 opts.addListener('bounds',
                                  self._name,
-                                 self._refreshLabels,
+                                 self.__refreshLabels,
                                  overwrite=True)
             else:
                 opts.removeListener('bounds', self._name)
                 
         # anatomical orientation may have changed with an image change
-        self._refreshLabels()
+        self.__refreshLabels()
 
             
-    def _onResize(self, ev):
-        """
-        Called whenever the panel is resized. Makes sure that the canvases
-        are laid out nicely.
+    def __onResize(self, ev):
+        """Called whenever the panel is resized. Makes sure that the
+        :class:`.SliceCanvas` panels are laid out nicely.
         """
         ev.Skip()
-        self._calcCanvasSizes()
+        self.__calcCanvasSizes()
 
 
-    def _refreshLabels(self, *a):
-        """Shows/hides labels depicting anatomical orientation on each canvas.
+    def __refreshLabels(self, *a):
+        """Shows/hides labels depicting anatomical orientation on each
+        :class:`.SliceCanvas`.
         """
 
-        allLabels = self._xLabels.values() + \
-                    self._yLabels.values() + \
-                    self._zLabels.values()
+        sceneOpts = self.getSceneOptions()
+        allLabels = self.__xLabels.values() + \
+                    self.__yLabels.values() + \
+                    self.__zLabels.values()
 
         # Are we showing or hiding the labels?
-        if   len(self._overlayList) == 0:       show = False
+        if len(self._overlayList) == 0:
+            show = False
 
         overlay = self._displayCtx.getReferenceImage(
             self._displayCtx.getSelectedOverlay())
 
         # Labels are only supported if we
         # have a volumetric reference image 
-        if   overlay is None:                   show = False
-        elif self.getSceneOptions().showLabels: show = True
-        else:                                   show = False
+        if   overlay is None:      show = False
+        elif sceneOpts.showLabels: show = True
+        else:                      show = False
 
         for lbl in allLabels:
-            self._canvasSizer.Show(lbl, show)
+            self.__canvasSizer.Show(lbl, show)
 
         # If we're hiding the labels, do no more
         if not show:
             self.PostSizeEvent()
             return
 
-        # Default colour is white - if the orientation labels
-        # cannot be determined, the foreground colour will be
-        # changed to red
-        colour  = 'white'
-
         opts = self._displayCtx.getOpts(overlay)
 
         # The image is being displayed as it is stored on
@@ -377,9 +493,6 @@ class OrthoPanel(canvaspanel.CanvasPanel):
             xorient = overlay.getWorldOrientation(0)
             yorient = overlay.getWorldOrientation(1)
             zorient = overlay.getWorldOrientation(2)
-                
-        if constants.ORIENT_UNKNOWN in (xorient, yorient, zorient):
-            colour = 'red'
 
         xlo = strings.anatomy['Image', 'lowshort',  xorient]
         ylo = strings.anatomy['Image', 'lowshort',  yorient]
@@ -388,29 +501,36 @@ class OrthoPanel(canvaspanel.CanvasPanel):
         yhi = strings.anatomy['Image', 'highshort', yorient]
         zhi = strings.anatomy['Image', 'highshort', zorient]
 
-        for lbl in allLabels:
-            lbl.SetForegroundColour(colour)
-
-        self._xLabels['left']  .SetLabel(ylo)
-        self._xLabels['right'] .SetLabel(yhi)
-        self._xLabels['top']   .SetLabel(zlo)
-        self._xLabels['bottom'].SetLabel(zhi)
-        self._yLabels['left']  .SetLabel(xlo)
-        self._yLabels['right'] .SetLabel(xhi)
-        self._yLabels['top']   .SetLabel(zlo)
-        self._yLabels['bottom'].SetLabel(zhi)
-        self._zLabels['left']  .SetLabel(xlo)
-        self._zLabels['right'] .SetLabel(xhi)
-        self._zLabels['top']   .SetLabel(ylo)
-        self._zLabels['bottom'].SetLabel(yhi)
+        bg = sceneOpts.bgColour
+        fg = colourmaps.complementaryColour(bg)
+        bg = [int(round(c * 255)) for c in bg]
+        fg = [int(round(c * 255)) for c in fg]        
+
+        self.__setLabelColours(bg, fg)
+
+        self.__xLabels['left']  .SetLabel(ylo)
+        self.__xLabels['right'] .SetLabel(yhi)
+        self.__xLabels['top']   .SetLabel(zlo)
+        self.__xLabels['bottom'].SetLabel(zhi)
+        self.__yLabels['left']  .SetLabel(xlo)
+        self.__yLabels['right'] .SetLabel(xhi)
+        self.__yLabels['top']   .SetLabel(zlo)
+        self.__yLabels['bottom'].SetLabel(zhi)
+        self.__zLabels['left']  .SetLabel(xlo)
+        self.__zLabels['right'] .SetLabel(xhi)
+        self.__zLabels['top']   .SetLabel(ylo)
+        self.__zLabels['bottom'].SetLabel(yhi)
 
         self.PostSizeEvent()
 
 
-    def _calcCanvasSizes(self, *a):
-        """Fixes the size for each displayed canvas (by setting their minimum
-        and maximum sizes), so that they are scaled proportionally to each
-        other.
+    def __calcCanvasSizes(self, *a):
+        """Sets the size for each displayed :class:`.SliceCanvas`.
+
+        The minimum/maximum size of each canvas is fixed so that they are
+        scaled proportionally to each other, thus preserving the aspect ratio.
+        The :mod:~fsl.utils.layout` module is used to perform the canvas size
+        calculation.
         """
         
         opts   = self.getSceneOptions()
@@ -418,9 +538,9 @@ class OrthoPanel(canvaspanel.CanvasPanel):
 
         width, height = self.getCanvasPanel().GetClientSize().Get()
 
-        show     = [opts.showXCanvas, opts.showYCanvas, opts.showZCanvas]
-        canvases = [self._xcanvas,    self._ycanvas,    self._zcanvas]
-        labels   = [self._xLabels,    self._yLabels,    self._zLabels]
+        show     = [opts.showXCanvas,  opts.showYCanvas,  opts.showZCanvas]
+        canvases = [self.__xcanvas,    self.__ycanvas,    self.__zcanvas]
+        labels   = [self.__xLabels,    self.__yLabels,    self.__zLabels]
 
         if width == 0 or height == 0:   return
         if len(self._overlayList) == 0: return
@@ -480,21 +600,21 @@ class OrthoPanel(canvaspanel.CanvasPanel):
             height = height -     sumh
             
         else:
-            canvases = [self._ycanvas, self._xcanvas, self._zcanvas]
+            canvases = [self.__ycanvas, self.__xcanvas, self.__zcanvas]
 
             if opts.showLabels:
-                xlw = self._xLabels['left']  .GetClientSize().GetWidth()
-                xrw = self._xLabels['right'] .GetClientSize().GetWidth()
-                ylw = self._yLabels['left']  .GetClientSize().GetWidth()
-                yrw = self._yLabels['right'] .GetClientSize().GetWidth()
-                zlw = self._zLabels['left']  .GetClientSize().GetWidth()
-                zrw = self._zLabels['right'] .GetClientSize().GetWidth()             
-                xth = self._xLabels['top']   .GetClientSize().GetHeight()
-                xbh = self._xLabels['bottom'].GetClientSize().GetHeight()
-                yth = self._yLabels['top']   .GetClientSize().GetHeight()
-                ybh = self._yLabels['bottom'].GetClientSize().GetHeight()
-                zth = self._zLabels['top']   .GetClientSize().GetHeight()
-                zbh = self._zLabels['bottom'].GetClientSize().GetHeight()
+                xlw = self.__xLabels['left']  .GetClientSize().GetWidth()
+                xrw = self.__xLabels['right'] .GetClientSize().GetWidth()
+                ylw = self.__yLabels['left']  .GetClientSize().GetWidth()
+                yrw = self.__yLabels['right'] .GetClientSize().GetWidth()
+                zlw = self.__zLabels['left']  .GetClientSize().GetWidth()
+                zrw = self.__zLabels['right'] .GetClientSize().GetWidth()             
+                xth = self.__xLabels['top']   .GetClientSize().GetHeight()
+                xbh = self.__xLabels['bottom'].GetClientSize().GetHeight()
+                yth = self.__yLabels['top']   .GetClientSize().GetHeight()
+                ybh = self.__yLabels['bottom'].GetClientSize().GetHeight()
+                zth = self.__zLabels['top']   .GetClientSize().GetHeight()
+                zbh = self.__zLabels['bottom'].GetClientSize().GetHeight()
             else:
                 xlw = xrw = xth = xbh = 0
                 ylw = yrw = yth = ybh = 0
@@ -523,9 +643,9 @@ class OrthoPanel(canvaspanel.CanvasPanel):
             canvas.SetMaxSize(size)
 
         
-    def _refreshLayout(self, *a):
-        """Called when the layout property changes, or the canvas layout needs
-        to be refreshed. Updates the orthopanel layout accordingly.
+    def __refreshLayout(self, *a):
+        """Called when the :attr:`.OrthoOpts.layout` property changes, or the
+        canvas layout needs to be refreshed. Updates the layout accordingly.
         """
 
         opts   = self.getSceneOptions()
@@ -558,55 +678,55 @@ class OrthoPanel(canvaspanel.CanvasPanel):
         # if layout is something other than the above three,
         # then something's gone wrong and I'm going to crash
 
-        self._canvasSizer = wx.FlexGridSizer(nrows, ncols)
+        self.__canvasSizer = wx.FlexGridSizer(nrows, ncols)
 
         # The rows/columns that contain
         # canvases must also be growable
         if layout == 'horizontal':
-            self._canvasSizer.AddGrowableRow(1)
+            self.__canvasSizer.AddGrowableRow(1)
             for i in range(nCanvases):
-                self._canvasSizer.AddGrowableCol(i * 3 + 1)
+                self.__canvasSizer.AddGrowableCol(i * 3 + 1)
                 
         elif layout == 'vertical':
-            self._canvasSizer.AddGrowableCol(1)
+            self.__canvasSizer.AddGrowableCol(1)
             for i in range(nCanvases):
-                self._canvasSizer.AddGrowableRow(i * 3 + 1)
+                self.__canvasSizer.AddGrowableRow(i * 3 + 1)
                 
         elif layout == 'grid':
-            self._canvasSizer.AddGrowableRow(1)
-            self._canvasSizer.AddGrowableRow(4)
-            self._canvasSizer.AddGrowableCol(1)
-            self._canvasSizer.AddGrowableCol(4) 
+            self.__canvasSizer.AddGrowableRow(1)
+            self.__canvasSizer.AddGrowableRow(4)
+            self.__canvasSizer.AddGrowableCol(1)
+            self.__canvasSizer.AddGrowableCol(4) 
 
         # Make a list of widgets - the canvases,
         # anatomical labels (if displayed), and
         # spacers for the empty cells
         space = (1, 1)
-        xlbls = self._xLabels
-        ylbls = self._yLabels
-        zlbls = self._zLabels
+        xlbls = self.__xLabels
+        ylbls = self.__yLabels
+        zlbls = self.__zLabels
         
         if layout == 'horizontal':
-            widgets = [space,         xlbls['top'],    space,
-                       space,         ylbls['top'],    space,
-                       space,         zlbls['top'],    space,
-                       xlbls['left'], self._xcanvas,   xlbls['right'],
-                       ylbls['left'], self._ycanvas,   ylbls['right'],
-                       zlbls['left'], self._zcanvas,   zlbls['right'],
-                       space,         xlbls['bottom'], space,
-                       space,         ylbls['bottom'], space,
-                       space,         zlbls['bottom'], space] 
+            widgets = [space,         xlbls['top'],     space,
+                       space,         ylbls['top'],     space,
+                       space,         zlbls['top'],     space,
+                       xlbls['left'], self.__xcanvas,   xlbls['right'],
+                       ylbls['left'], self.__ycanvas,   ylbls['right'],
+                       zlbls['left'], self.__zcanvas,   zlbls['right'],
+                       space,         xlbls['bottom'],  space,
+                       space,         ylbls['bottom'],  space,
+                       space,         zlbls['bottom'],  space] 
                 
         elif layout == 'vertical':
-            widgets = [space,         xlbls['top'],    space,
-                       xlbls['left'], self._xcanvas,   xlbls['right'],
-                       space,         xlbls['bottom'], space,
-                       space,         ylbls['top'],    space,
-                       ylbls['left'], self._ycanvas,   ylbls['right'],
-                       space,         ylbls['bottom'], space,
-                       space,         zlbls['top'],    space,
-                       zlbls['left'], self._zcanvas,   zlbls['right'],
-                       space,         zlbls['bottom'], space]
+            widgets = [space,         xlbls['top'],     space,
+                       xlbls['left'], self.__xcanvas,   xlbls['right'],
+                       space,         xlbls['bottom'],  space,
+                       space,         ylbls['top'],     space,
+                       ylbls['left'], self.__ycanvas,   ylbls['right'],
+                       space,         ylbls['bottom'],  space,
+                       space,         zlbls['top'],     space,
+                       zlbls['left'], self.__zcanvas,   zlbls['right'],
+                       space,         zlbls['bottom'],  space]
 
         # The canvases are laid out in a different order
         # for orthographic, or 'grid' layout.  Assuming
@@ -617,61 +737,75 @@ class OrthoPanel(canvaspanel.CanvasPanel):
         # following manner (the letter denotes the depth
         # axis for the respective canvas):
         #
+        # TODO You need to horizonatlly flip the x canvas
+        #      to achieve true orthographic display.
+        #
         #    Y  X
         #    Z  - 
         elif layout == 'grid':
-            widgets = [space,         ylbls['top'],    space,
-                       space,         xlbls['top'],    space,
-                       ylbls['left'], self._ycanvas,   ylbls['right'],
-                       xlbls['left'], self._xcanvas,   xlbls['right'],
-                       space,         ylbls['bottom'], space,
-                       space,         xlbls['bottom'], space,
-                       space,         zlbls['top'],    space,
-                       space,         space,           space,
-                       zlbls['left'], self._zcanvas,   zlbls['right'],
-                       space,         space,           space,
-                       space,         zlbls['bottom'], space,
-                       space,         space,           space]
+            widgets = [space,         ylbls['top'],     space,
+                       space,         xlbls['top'],     space,
+                       ylbls['left'], self.__ycanvas,   ylbls['right'],
+                       xlbls['left'], self.__xcanvas,   xlbls['right'],
+                       space,         ylbls['bottom'],  space,
+                       space,         xlbls['bottom'],  space,
+                       space,         zlbls['top'],     space,
+                       space,         space,            space,
+                       zlbls['left'], self.__zcanvas,   zlbls['right'],
+                       space,         space,            space,
+                       space,         zlbls['bottom'],  space,
+                       space,         space,            space]
 
         # Add all those widgets to the grid sizer
         flag = wx.ALIGN_CENTRE_HORIZONTAL | wx.ALIGN_CENTRE_VERTICAL
         
         for w in widgets:
-            self._canvasSizer.Add(w, flag=flag)
+            self.__canvasSizer.Add(w, flag=flag)
                                           
-        self.getCanvasPanel().SetSizer(self._canvasSizer)
+        self.getCanvasPanel().SetSizer(self.__canvasSizer)
 
         # Calculate/ adjust the appropriate sizes
         # for each canvas, such that they are scaled
         # appropriately relative to each other, and
         # the displayed world space aspect ratio is
         # maintained
-        self._calcCanvasSizes()
+        self.__calcCanvasSizes()
 
         self.Layout()
         self.getCanvasPanel().Layout()
         self.Refresh()
 
 
-    def _locationChanged(self, *a):
-        """
+    def __locationChanged(self, *a):
+        """Called when the :attr:`.DisplayContext.locavtion` property changes.
+
         Sets the currently displayed x/y/z position (in display
-        coordinates).
+        coordinates) on each of the :class:`.SliceCanvas` panels.
         """
 
         xpos, ypos, zpos = self._displayCtx.location.xyz
 
-        self._xcanvas.pos.xyz = [ypos, zpos, xpos]
-        self._ycanvas.pos.xyz = [xpos, zpos, ypos]
-        self._zcanvas.pos.xyz = [xpos, ypos, zpos]
+        self.__xcanvas.pos.xyz = [ypos, zpos, xpos]
+        self.__ycanvas.pos.xyz = [xpos, zpos, ypos]
+        self.__zcanvas.pos.xyz = [xpos, ypos, zpos]
 
 
 class OrthoFrame(wx.Frame):
-    """
-    Convenience class for displaying an OrthoPanel in a standalone window.
+    """Convenience class for displaying an :class:`OrthoPanel` in a
+    standalone frame.
     """
 
     def __init__(self, parent, overlayList, displayCtx, title=None):
+        """Create an ``OrthoFrame``.
+
+        :arg parent:      A :mod:`wx` parent object.
+        
+        :arg overlayList: An :class:`.OverlayList` instance.
+        
+        :arg displayCtx:  A :class:`.DisplayContext` instance.
+        
+        :arg title:       Dialog title.
+        """
         
         wx.Frame.__init__(self, parent, title=title)
 
@@ -686,9 +820,8 @@ class OrthoFrame(wx.Frame):
 
 
 class OrthoDialog(wx.Dialog):
-    """
-    Convenience class for displaying an OrthoPanel in a (possibly modal)
-    dialog window.
+    """Convenience class for displaying an :class:`OrthoPanel` in a (possibly
+    modal) dialog window.
     """
 
     def __init__(self,
@@ -697,9 +830,22 @@ class OrthoDialog(wx.Dialog):
                  displayCtx,
                  title=None,
                  style=None):
+        """Create an ``OrthoDialog``.
+
+        :arg parent:      A :mod:`wx` parent object.
+        
+        :arg overlayList: An :class:`.OverlayList` instance.
+        
+        :arg displayCtx:  A :class:`.DisplayContext` instance.
+        
+        :arg title:       Dialog title.
+        
+        :arg style:       Dialog style - defaults to
+                          ``wx.DEFAULT_DIALOG_STYLE``.
+        """
 
-        if style is None: style =  wx.DEFAULT_DIALOG_STYLE
-        else:             style |= wx.DEFAULT_DIALOG_STYLE
+        if style is None:
+            style = wx.DEFAULT_DIALOG_STYLE
 
         wx.Dialog.__init__(self, parent, title=title, style=style)
 
diff --git a/fsl/fsleyes/views/timeseriespanel.py b/fsl/fsleyes/views/timeseriespanel.py
index c283a977d46d7d22f07ef4036e03ffa4fc57b118..0a8b0ef05a342f121dc744f9182e338b28f220ae 100644
--- a/fsl/fsleyes/views/timeseriespanel.py
+++ b/fsl/fsleyes/views/timeseriespanel.py
@@ -154,7 +154,7 @@ class FEATTimeSeries(TimeSeries):
 
     .. note:: The ``getData`` method of a ``FEATTimeSeries`` instance will
               return the FEAT input data; therefore, when :attr:`plotData` is
-              ``True``, the ``FEATTimeSeries` instance will itself be included
+              ``True``, the ``FEATTimeSeries`` instance will itself be included
               in the list returned by :meth:`getModelTimeSeries`.
 
     
diff --git a/fsl/fsleyes/views/viewpanel.py b/fsl/fsleyes/views/viewpanel.py
index 069684cee443a7946a24c9a05ee1573e59b1d096..66180dadb5c9cb5ceb3f814e95ac186078f3700c 100644
--- a/fsl/fsleyes/views/viewpanel.py
+++ b/fsl/fsleyes/views/viewpanel.py
@@ -162,6 +162,19 @@ class ViewPanel(fslpanel.FSLEyesPanel):
         fslpanel.FSLEyesPanel.destroy(self)
         
 
+    def initProfile(self):
+        """Must be called by subclasses, after they have initialised all
+        of the attributes which may be needed by their associated
+        :class:`.Profile` instances. 
+        """
+        self.__profileChanged()
+
+
+    def getCurrentProfile(self):
+        """Returns the :class:`.Profile` instance currently in use. """
+        return self.__profileManager.getCurrentProfile()
+
+
     def setCentrePanel(self, panel):
         """Set the primary centre panel for this ``ViewPanel``. """
         
@@ -404,20 +417,6 @@ class ViewPanel(fslpanel.FSLEyesPanel):
                           type(self).__name__, overlay))
             profileProp.enableChoice('edit', self)
         
-
-
-    def initProfile(self):
-        """Must be called by subclasses, after they have initialised all
-        of the attributes which may be needed by their associated
-        :class:`.Profile` instances. 
-        """
-        self.__profileChanged()
-
-
-    def getCurrentProfile(self):
-        """Returns the :class:`.Profile` instance currently in use. """
-        return self.__profileManager.getCurrentProfile()
-
         
     def __profileChanged(self, *a):
         """Called when the current :attr:`profile` property changes. Tells the