diff --git a/fsl/data/image.py b/fsl/data/image.py
index f27dfdb404a63b25ddad4bdd7e43fc52ea17fcd8..249b7a56cbfa63f11e96a3e35fd11f9027687b0c 100644
--- a/fsl/data/image.py
+++ b/fsl/data/image.py
@@ -277,23 +277,29 @@ class Image(props.HasProperties):
         return len(self.shape) > 3 and self.shape[3] > 1
 
 
-    def getXFormCode(self):
+    def getXFormCode(self, code=None):
         """This method returns the code contained in the NIFTI1 header,
         indicating the space to which the (transformed) image is oriented.
+
+        The ``code`` parameter may be either ``sform`` (the default) or
+        ``qform`` in which case the corresponding matrix is used. 
         """
-        sform_code = self.nibImage.get_header()['sform_code']
 
-        # Invalid values
-        if   sform_code > 4: code = constants.NIFTI_XFORM_UNKNOWN
-        elif sform_code < 0: code = constants.NIFTI_XFORM_UNKNOWN
+        if   code is None:     code = 'sform_code'
+        elif code == 'sform' : code = 'sform_code'
+        elif code == 'qform' : code = 'qform_code'
+        else: raise ValueError('code must be None, sform, or qform')
 
-        # All is well
-        else:                code = sform_code
+        code = self.nibImage.get_header()[code]
 
+        # Invalid values
+        if   code > 4: code = constants.NIFTI_XFORM_UNKNOWN
+        elif code < 0: code = constants.NIFTI_XFORM_UNKNOWN
+        
         return int(code)
 
 
-    def getWorldOrientation(self, axis):
+    def getWorldOrientation(self, axis, code=None):
         """Returns a code representing the orientation of the specified axis
         in world space.
 
@@ -316,17 +322,17 @@ class Image(props.HasProperties):
         to superior).
         """
 
-        if self.getXFormCode() == constants.NIFTI_XFORM_UNKNOWN:
-            return -1
+        if self.getXFormCode(code) == constants.NIFTI_XFORM_UNKNOWN:
+            return constants.ORIENT_UNKNOWN
 
         if   axis == 0: return constants.ORIENT_L2R
         elif axis == 1: return constants.ORIENT_P2A
         elif axis == 2: return constants.ORIENT_I2S
 
-        else: return -1
+        else: return constants.ORIENT_UNKNOWN
 
 
-    def getVoxelOrientation(self, axis):
+    def getVoxelOrientation(self, axis, code=None):
         """Returns a code representing the (estimated) orientation of the
         specified voxelwise axis.
 
@@ -334,17 +340,23 @@ class Image(props.HasProperties):
         of the return value.
         """
         
-        if self.getXFormCode() == constants.NIFTI_XFORM_UNKNOWN:
-            return -1 
+        if self.getXFormCode(code) == constants.NIFTI_XFORM_UNKNOWN:
+            return constants.ORIENT_UNKNOWN
+
+        if   code is None:    xform = self.nibImage.get_affine()
+        elif code == 'sform': xform = self.nibImage.get_sform()
+        elif code == 'qform': xform = self.nibImage.get_qform()
+        else: raise ValueError('code must be None, qform, or sform')
         
         # the aff2axcodes returns one code for each 
         # axis in the image array (i.e. in voxel space),
         # which denotes the real world direction
         code = nib.orientations.aff2axcodes(
-            self.nibImage.get_affine(),
+            xform,
             ((constants.ORIENT_R2L, constants.ORIENT_L2R),
              (constants.ORIENT_A2P, constants.ORIENT_P2A),
              (constants.ORIENT_S2I, constants.ORIENT_I2S)))[axis]
+        
         return code
 
 
@@ -354,8 +366,8 @@ class Image(props.HasProperties):
 # so i'm just providing '*.gz'for now
 ALLOWED_EXTENSIONS = ['.nii.gz', '.nii', '.img', '.hdr', '.img.gz', '.gz']
 """The file extensions which we understand. This list is used as the default
-if if the ``allowedExts`` parameter is not passed to any of the functions in
-this module.
+if if the ``allowedExts`` parameter is not passed to any of the functions
+below.
 """
 
 EXTENSION_DESCRIPTIONS = ['Compressed NIFTI1 images',
diff --git a/fsl/data/strings.py b/fsl/data/strings.py
index 98b961fe5da7e42803d5dad576afae651d5de3d1..0a84a375a3bc23c78c6d9e6a0f8a59ed101fd5ee 100644
--- a/fsl/data/strings.py
+++ b/fsl/data/strings.py
@@ -145,6 +145,7 @@ titles = TypeDict({
     'HistogramListPanel'     : 'Histogram list',
     'HistogramControlPanel'  : 'Histogram control',
     'ClusterPanel'           : 'Cluster browser',
+    'OverlayInfoPanel'       : 'Overlay information',
 
     'LookupTablePanel.loadLut'     : 'Select a lookup table file',
     'LookupTablePanel.labelExists' : 'Label already exists',
@@ -170,6 +171,7 @@ actions = TypeDict({
     'CanvasPanel.toggleAtlasPanel'        : 'Atlas panel',
     'CanvasPanel.toggleLookupTablePanel'  : 'Lookup tables',
     'CanvasPanel.toggleClusterPanel'      : 'Cluster browser',
+    'CanvasPanel.toggleOverlayInfo'       : 'Overlay information',
     
     'OrthoPanel.toggleOrthoToolBar'     : 'View properties',
     'OrthoPanel.toggleProfileToolBar'   : 'Mode controls',
@@ -292,7 +294,10 @@ labels = TypeDict({
     'CanvasSettingsPanel.scene'    : 'Scene settings',
     'CanvasSettingsPanel.ortho'    : 'Ortho view settings',
     'CanvasSettingsPanel.lightbox' : 'Lightbox settings',
-    
+
+    'OverlayInfoPanel.Image.dimensions'   : 'Dimensions',
+    'OverlayInfoPanel.Image.transform'    : 'Transform/space',
+    'OverlayInfoPanel.Image.orient'       : 'Orientation',
 })
 
 
@@ -548,3 +553,66 @@ anatomy = TypeDict({
     ('Image', 'space',     constants.NIFTI_XFORM_TALAIRACH)    : 'Talairach', 
     ('Image', 'space',     constants.NIFTI_XFORM_MNI_152)      : 'MNI152',
 })
+
+
+nifti = TypeDict({
+
+    'dimensions' : 'Number of dimensions',
+    'dataSource' : 'Data source',
+    
+    'datatype'    : 'Data type',
+    'vox_units'   : 'XYZ units',
+    'time_units'  : 'Time units',
+    'descrip'     : 'Description',
+    'qform_code'  : 'QForm code',
+    'sform_code'  : 'SForm code',
+
+    'voxOrient.0'   : 'X voxel orientation',
+    'voxOrient.1'   : 'Y voxel orientation',
+    'voxOrient.2'   : 'Z voxel orientation',
+    'sformOrient.0' : 'X sform orientation',
+    'sformOrient.1' : 'Y sform orientation',
+    'sformOrient.2' : 'Z sform orientation',
+    'qformOrient.0' : 'X qform orientation',
+    'qformOrient.1' : 'Y qform orientation',
+    'qformOrient.2' : 'Z qform orientation', 
+
+    'qform' : 'QForm matrix',
+    'sform' : 'SForm matrix',
+
+    'dim1' : 'dim1',
+    'dim2' : 'dim2',
+    'dim3' : 'dim3',
+    'dim4' : 'dim4',
+    'dim5' : 'dim5',
+    'dim6' : 'dim6',
+    'dim7' : 'dim7',
+
+    'pixdim1' : 'pixdim1',
+    'pixdim2' : 'pixdim2',
+    'pixdim3' : 'pixdim3',
+    'pixdim4' : 'pixdim4',
+    'pixdim5' : 'pixdim5',
+    'pixdim6' : 'pixdim6',
+    'pixdim7' : 'pixdim7', 
+
+    ('datatype', 0)    : 'UNKNOWN',
+    ('datatype', 1)    : 'BINARY',
+    ('datatype', 2)    : 'UINT8',
+    ('datatype', 4)    : 'INT16',
+    ('datatype', 8)    : 'INT32',
+    ('datatype', 16)   : 'FLOAT32',
+    ('datatype', 32)   : 'COMPLEX64',
+    ('datatype', 64)   : 'DOUBLE64',
+    ('datatype', 128)  : 'RGB',
+    ('datatype', 255)  : 'ALL',
+    ('datatype', 256)  : 'INT8',
+    ('datatype', 512)  : 'UINT16',
+    ('datatype', 768)  : 'UINT32',
+    ('datatype', 1024) : 'INT64',
+    ('datatype', 1280) : 'UINT64',
+    ('datatype', 1536) : 'FLOAT128',
+    ('datatype', 1792) : 'COMPLEX128',
+    ('datatype', 2048) : 'COMPLEX256',
+    ('datatype', 2304) : 'RGBA32',
+})
diff --git a/fsl/fslview/actions/__init__.py b/fsl/fslview/actions/__init__.py
index 7ace0c048452fb7dfff0d4981693ea9967290302..9f4249cec40e65d5418ea772915a9152b7662559 100644
--- a/fsl/fslview/actions/__init__.py
+++ b/fsl/fslview/actions/__init__.py
@@ -22,6 +22,7 @@ or more actions.  As the :class:`.FSLViewPanel` class derives from
 
 
 import logging
+import collections
 
 import props
 
@@ -210,7 +211,7 @@ class ActionProvider(props.SyncableHasProperties):
         if actions is None:
             actions = {}
 
-        self.__actions = {}
+        self.__actions = collections.OrderedDict()
 
         for name, func in actions.items():
             act = Action(overlayList, displayCtx, action=func)
@@ -246,7 +247,7 @@ class ActionProvider(props.SyncableHasProperties):
         """Return a dictionary containing ``{name -> Action}`` mappings for
         all defined actions.
         """
-        return dict(self.__actions)
+        return collections.OrderedDict(self.__actions)
 
 
     def isEnabled(self, name):
diff --git a/fsl/fslview/controls/__init__.py b/fsl/fslview/controls/__init__.py
index a9471fdad551b58a595041c24ae62fc14f19f333..39ad296b6424c216047f0c963f55f8e7251e4225 100644
--- a/fsl/fslview/controls/__init__.py
+++ b/fsl/fslview/controls/__init__.py
@@ -16,6 +16,7 @@ from histogramlistpanel     import HistogramListPanel
 from histogramcontrolpanel  import HistogramControlPanel
 from clusterpanel           import ClusterPanel
 from canvassettingspanel    import CanvasSettingsPanel
+from overlayinfopanel       import OverlayInfoPanel
 
 from orthotoolbar           import OrthoToolBar
 from orthoprofiletoolbar    import OrthoProfileToolBar
diff --git a/fsl/fslview/controls/overlayinfopanel.py b/fsl/fslview/controls/overlayinfopanel.py
new file mode 100644
index 0000000000000000000000000000000000000000..b0edb0b4b611c48d7b15577c120644b0e1bef1ee
--- /dev/null
+++ b/fsl/fslview/controls/overlayinfopanel.py
@@ -0,0 +1,233 @@
+#!/usr/bin/env python
+#
+# overlayinfopanel.py -
+#
+# Author: Paul McCarthy <pauldmccarthy@gmail.com>
+#
+
+import collections
+
+import wx
+import wx.html as wxhtml
+
+import fsl.data.strings  as strings
+import fsl.fslview.panel as fslpanel
+
+
+class OverlayInfo(object):
+    """A little class which encapsulates human-readable information about
+    one overlay. ``OverlayInfo`` objects are created and returned by the
+    ``OverlayInfoPanel.__get*Info`` methods.
+    """
+
+    def __init__(self, title):
+        
+        self.title    = title
+        self.info     = []
+        self.sections = collections.OrderedDict()
+
+        
+    def addSection(self, section):
+        self.sections[section] = []
+
+        
+    def addInfo(self, name, info, section=None):
+        if section is None: self.info             .append((name, info))
+        else:               self.sections[section].append((name, info))
+        
+
+
+class OverlayInfoPanel(fslpanel.FSLViewPanel):
+
+
+    def __init__(self, parent, overlayList, displayCtx):
+
+        fslpanel.FSLViewPanel.__init__(self, parent, overlayList, displayCtx)
+
+        self.__info  = wxhtml.HtmlWindow(self)
+        self.__sizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.__sizer.Add(self.__info, flag=wx.EXPAND, proportion=1)
+        
+        self.SetSizer(self.__sizer)
+
+        displayCtx .addListener('selectedOverlay',
+                                self._name,
+                                self.__selectedOverlayChanged)
+        overlayList.addListener('overlays',
+                                self._name,
+                                self.__selectedOverlayChanged)
+
+        self.__currentOverlay = None
+        self.__currentDisplay = None
+        self.__selectedOverlayChanged()
+        self.Layout()
+
+    def destroy(self):
+        self._displayCtx .removeListener('selectedOverlay', self._name)
+        self._overlayList.removeListener('overlays',        self._name)
+
+        if self.__currentDisplay is not None:
+            self.__currentDisplay.removeListener('name', self._name)
+
+        self.__currentOverlay = None
+        self.__currentDisplay = None
+
+        fslpanel.FSLViewPanel.destroy(self)
+
+
+    def __selectedOverlayChanged(self, *a):
+
+        overlay = self._displayCtx.getSelectedOverlay()
+
+        if overlay == self.__currentOverlay:
+            return
+        
+        if self.__currentDisplay is not None:
+            self.__currentDisplay.removeListener('name', self._name)
+            
+        self.__currenOverlay = None
+        self.__currenDisplay = None
+        
+        if overlay is not None:
+            self.__currentOverlay = overlay
+            self.__currentDisplay = self._displayCtx.getDisplay(overlay)
+
+            self.__currentDisplay.addListener('name',
+                                              self._name,
+                                              self.__overlayNameChanged)
+        
+        self.__updateInformation()
+
+        
+    def __overlayNameChanged(self, *a):
+        self.__updateInformation()
+
+
+    def __updateInformation(self):
+
+        overlay  = self.__currentOverlay
+        display  = self.__currentDisplay
+        infoFunc = '_{}__get{}Info'.format(type(self)   .__name__,
+                                           type(overlay).__name__)
+        infoFunc = getattr(self, infoFunc, None)
+        
+        if infoFunc is None:
+            self.__info.SetPage('')
+            return
+
+        info = infoFunc(overlay, display)
+
+        self.__info.SetPage(self.__formatOverlayInfo(info))
+
+
+    def __formatOverlayInfo(self, info):
+        lines  = [info.title]
+        lines += map(str, info.info)
+
+        for sec in info.sections.keys():
+            lines += [sec]
+            lines += map(str, info.sections[sec])
+        
+        return '<br>'.join(lines)
+
+
+    def __getImageInfo(self, overlay, display):
+        
+        info = OverlayInfo(display.name)
+        img  = overlay.nibImage
+        hdr  = img.get_header()
+
+        voxUnits, timeUnits = hdr.get_xyzt_units()
+        
+        dimSect    = strings.labels[self, overlay, 'dimensions']
+        xformSect  = strings.labels[self, overlay, 'transform']
+        orientSect = strings.labels[self, overlay, 'orient']
+
+        info.addSection(dimSect)
+        info.addSection(xformSect)
+        info.addSection(orientSect)
+
+        info.addInfo(strings.nifti['dataSource'], overlay.dataSource)
+        info.addInfo(strings.nifti['datatype'],
+                     strings.nifti['datatype', int(hdr['datatype'])])
+        info.addInfo(strings.nifti['descrip'], hdr['descrip'])
+
+        info.addInfo(strings.nifti['vox_units'],  voxUnits,  section=dimSect)
+        info.addInfo(strings.nifti['time_units'], timeUnits, section=dimSect)
+        
+        info.addInfo(strings.nifti['dimensions'],
+                     '{}D'.format(len(overlay.shape)),
+                     section=dimSect)
+
+        for i in range(len(overlay.shape)):
+            info.addInfo(strings.nifti['dim{}'.format(i + 1)],
+                         str(overlay.shape[i]),
+                         section=dimSect)
+
+        for i in range(len(overlay.shape)):
+            
+            pixdim = hdr['pixdim'][i + 1]
+
+            if   i  < 3: pixdim = '{} {}'.format(pixdim, voxUnits)
+            elif i == 3: pixdim = '{} {}'.format(pixdim, timeUnits)
+                
+            info.addInfo(
+                strings.nifti['pixdim{}'.format(i + 1)],
+                pixdim,
+                section=dimSect)
+
+        info.addInfo(strings.nifti['qform_code'],
+                     strings.anatomy['Image', 'space', int(hdr['qform_code'])],
+                     section=xformSect)
+        info.addInfo(strings.nifti['sform_code'],
+                     strings.anatomy['Image', 'space', int(hdr['sform_code'])],
+                     section=xformSect)
+
+        # TODO matrix formatting (you'll need to use
+        #      HTML, or maybe get the formatOverlayInfo
+        #      method to support different types)
+        info.addInfo(strings.nifti['qform'],
+                     str(img.get_qform()),
+                     section=xformSect)
+        info.addInfo(strings.nifti['sform'],
+                     str(img.get_sform()),
+                     section=xformSect) 
+
+        for i in range(3):
+            orient = overlay.getVoxelOrientation(i)
+            orient = '{} - {}'.format(
+                strings.anatomy['Image', 'lowlong',  orient],
+                strings.anatomy['Image', 'highlong', orient])
+            info.addInfo(strings.nifti['voxOrient.{}'.format(i)],
+                         orient,
+                         section=orientSect)
+
+        for i in range(3):
+            orient = overlay.getWorldOrientation(i, code='sform')
+            orient = '{} - {}'.format(
+                strings.anatomy['Image', 'lowlong',  orient],
+                strings.anatomy['Image', 'highlong', orient])
+            info.addInfo(strings.nifti['sformOrient.{}'.format(i)],
+                         orient,
+                         section=orientSect)
+
+        for i in range(3):
+            orient = overlay.getWorldOrientation(i, code='qform')
+            orient = '{} - {}'.format(
+                strings.anatomy['Image', 'lowlong',  orient],
+                strings.anatomy['Image', 'highlong', orient])
+            info.addInfo(strings.nifti['qformOrient.{}'.format(i)],
+                         orient,
+                         section=orientSect) 
+
+        return info
+
+
+    def __getFEATImageInfo(self, overlay, display):
+        return self.__getImageInfo(overlay)
+
+    
+    def __getModelInfo(self, overlay, display):
+        info = OverlayInfo(display.name)
+
+        return info
diff --git a/fsl/fslview/views/canvaspanel.py b/fsl/fslview/views/canvaspanel.py
index 0c7f9d3f226dfaf79c47730f56e82dd876fa0bc8..521d31ef213a7908c523285a26e0bc16cea3983b 100644
--- a/fsl/fslview/views/canvaspanel.py
+++ b/fsl/fslview/views/canvaspanel.py
@@ -12,6 +12,7 @@ class for all panels which display image data (e.g. the
 """
 
 import logging
+import collections
 
 import wx
 
@@ -57,22 +58,24 @@ class CanvasPanel(viewpanel.ViewPanel):
         if extraActions is None:
             extraActions = {}
 
-        actionz = dict({
-            'screenshot'              : self.screenshot,
-            'showCommandLineArgs'     : self.showCommandLineArgs,
-            'toggleOverlayList'         : lambda *a: self.togglePanel(
-                fslcontrols.OverlayListPanel),
-            'toggleAtlasPanel'        : lambda *a: self.togglePanel(
-                fslcontrols.AtlasPanel),
-            'toggleDisplayProperties' : lambda *a: self.togglePanel(
-                fslcontrols.OverlayDisplayToolBar, False, self),
-            'toggleLocationPanel'     : lambda *a: self.togglePanel(
-                fslcontrols.LocationPanel),
-            'toggleClusterPanel'     : lambda *a: self.togglePanel(
-                fslcontrols.ClusterPanel), 
-            'toggleLookupTablePanel'  : lambda *a: self.togglePanel(
-                fslcontrols.LookupTablePanel), 
-        }.items() + extraActions.items())
+        actionz = [
+            ('screenshot',              self.screenshot),
+            ('showCommandLineArgs',     self.showCommandLineArgs),
+            ('toggleOverlayList',       lambda *a: self.togglePanel(
+                fslcontrols.OverlayListPanel)),
+            ('toggleOverlayInfo',       lambda *a: self.togglePanel(
+                fslcontrols.OverlayInfoPanel)), 
+            ('toggleAtlasPanel',        lambda *a: self.togglePanel(
+                fslcontrols.AtlasPanel)),
+            ('toggleDisplayProperties', lambda *a: self.togglePanel(
+                fslcontrols.OverlayDisplayToolBar, False, self)),
+            ('toggleLocationPanel',     lambda *a: self.togglePanel(
+                fslcontrols.LocationPanel)),
+            ('toggleClusterPanel',      lambda *a: self.togglePanel(
+                fslcontrols.ClusterPanel)), 
+            ('toggleLookupTablePanel',  lambda *a: self.togglePanel(
+                fslcontrols.LookupTablePanel))]
+        actionz = collections.OrderedDict(actionz + extraActions.items())
         
         viewpanel.ViewPanel.__init__(
             self, parent, overlayList, displayCtx, actionz)