diff --git a/fsl/data/strings.py b/fsl/data/strings.py
index 1691e050f59bcc8bd096bed08548f6e1ccd1f570..e44661918c450926956342bcbd3bc4576d7f0ce6 100644
--- a/fsl/data/strings.py
+++ b/fsl/data/strings.py
@@ -527,15 +527,16 @@ properties = TypeDict({
     'ImageOpts.transform'  : 'Image transform',
     'ImageOpts.volume'     : 'Volume',
     
-    'VolumeOpts.displayRange'   : 'Display range',
-    'VolumeOpts.clippingRange'  : 'Clipping range',
-    'VolumeOpts.centreRanges'   : 'Centre display/clipping ranges at 0',
-    'VolumeOpts.linkLowRanges'  : 'Link low display/clipping ranges',
-    'VolumeOpts.linkHighRanges' : 'Link high display/clipping ranges',
-    'VolumeOpts.cmap'           : 'Colour map',
-    'VolumeOpts.invert'         : 'Invert colour map',
-    'VolumeOpts.invertClipping' : 'Invert clipping range',
-    'VolumeOpts.interpolation'  : 'Interpolation',
+    'VolumeOpts.displayRange'       : 'Display range',
+    'VolumeOpts.clippingRange'      : 'Clipping range',
+    'VolumeOpts.linkLowRanges'      : 'Link low display/clipping ranges',
+    'VolumeOpts.linkHighRanges'     : 'Link high display/clipping ranges',
+    'VolumeOpts.cmap'               : 'Colour map',
+    'VolumeOpts.negativeCmap'       : '-ve colour map',
+    'VolumeOpts.enableNegativeCmap' : '-ve colour map',
+    'VolumeOpts.invert'             : 'Invert colour map',
+    'VolumeOpts.invertClipping'     : 'Invert clipping range',
+    'VolumeOpts.interpolation'      : 'Interpolation',
 
     'MaskOpts.colour'         : 'Colour',
     'MaskOpts.invert'         : 'Invert',
diff --git a/fsl/fsleyes/colourmaps.py b/fsl/fsleyes/colourmaps.py
index a8b551ca0f393a6b5cbf1917d1e82c20e3e2a6b0..f5b8b763b47e609e4009feec8ef4e89eb99d1bf7 100644
--- a/fsl/fsleyes/colourmaps.py
+++ b/fsl/fsleyes/colourmaps.py
@@ -275,16 +275,19 @@ def registerColourMap(cmapFile,
     
     # update the VolumeOpts colour map property
     # for any existing VolumeOpts instances
-    cmapProp = fsldisplay.VolumeOpts.getProp('cmap')
+    cmapProp    = fsldisplay.VolumeOpts.getProp('cmap')
+    negCmapProp = fsldisplay.VolumeOpts.getProp('negativeCmap')
     
     for overlay in overlayList:
         opts = displayCtx.getOpts(overlay)
         
         if isinstance(opts, fsldisplay.VolumeOpts):
-            cmapProp.addColourMap(key, opts)
+            cmapProp   .addColourMap(key, opts)
+            negCmapProp.addColourMap(key, opts)
 
     # and for all future volume overlays
-    cmapProp.addColourMap(key)
+    cmapProp   .addColourMap(key)
+    negCmapProp.addColourMap(key)
                 
 
 def registerLookupTable(lut,
diff --git a/fsl/fsleyes/controls/overlaydisplaypanel.py b/fsl/fsleyes/controls/overlaydisplaypanel.py
index a8f4842e4b535b08eb8555ac4b414a47c5c8a7c3..0c9fe561fbbfe8d04d06c7ad2be85a62f8f1b6af 100644
--- a/fsl/fsleyes/controls/overlaydisplaypanel.py
+++ b/fsl/fsleyes/controls/overlaydisplaypanel.py
@@ -216,15 +216,11 @@ class OverlayDisplayPanel(fslpanel.FSLEyesPanel):
 
         for p in dispProps:
 
-            widget = props.buildGUI(self.__widgets,
-                                    target,
-                                    p,
-                                    showUnlink=False)            
+            widget = props.buildGUI(self.__widgets, target, p)
 
-            # Add a 'load colour map' button next 
-            # to the VolumeOpts.cmap control
+            # Build a panel for the VolumeOpts colour map controls.
             if isinstance(target, displayctx.VolumeOpts) and p.key == 'cmap':
-                widget = self.__buildColourMapWidget(widget)
+                widget = self.__buildColourMapWidget(target, widget)
                 
             widgets.append(widget)
 
@@ -238,24 +234,43 @@ class OverlayDisplayPanel(fslpanel.FSLEyesPanel):
         self.Layout()
 
 
-    def __buildColourMapWidget(self, cmapWidget):
-        """Creates a control which allows the user to load a custom colour
-        map. This control is added to the settings for :class:`.Image`
-        overlays with a :attr:`.Display.overlayType`  of ``'volume'``.
+    def __buildColourMapWidget(self, target, cmapWidget):
+        """Builds a panel which contains widgets for controlling the
+        :attr:`.VolumeOpts.cmap`, :attr:`.VolumeOpts.negativeCmap`, and
+        :attr:`.VolumeOpts.enableNegativeCmap`.
         """
 
-        action = loadcmap.LoadColourMapAction(self._displayCtx,
-                                              self._overlayList)
+        widgets = self.__widgets
 
-        button = wx.Button(self.__widgets)
-        button.SetLabel(strings.labels[self, 'loadCmap'])
+        # Button to load a new
+        # colour map from file
+        loadAction = loadcmap.LoadColourMapAction(self._displayCtx,
+                                                  self._overlayList)
 
-        action.bindToWidget(self, wx.EVT_BUTTON, button)
+        loadButton = wx.Button(widgets)
+        loadButton.SetLabel(strings.labels[self, 'loadCmap'])
 
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        loadAction.bindToWidget(self, wx.EVT_BUTTON, loadButton)
 
-        sizer.Add(cmapWidget, flag=wx.EXPAND, proportion=1)
-        sizer.Add(button,     flag=wx.EXPAND)
+        # Negative colour map widget
+        negCmap       = props.Widget('negativeCmap',
+                                     enabledWhen=lambda i, enc: enc,
+                                     dependencies=['enableNegativeCmap'])
+        enableNegCmap = props.Widget('enableNegativeCmap')
+        
+        negCmap       = props.buildGUI(widgets, target, negCmap)
+        enableNegCmap = props.buildGUI(widgets, target, enableNegCmap)
+
+        enableNegCmap.SetLabel(
+            strings.properties[target, 'enableNegativeCmap'])
+
+        sizer = wx.FlexGridSizer(2, 2)
+        sizer.AddGrowableCol(0)
+
+        sizer.Add(cmapWidget,    flag=wx.EXPAND)
+        sizer.Add(loadButton,    flag=wx.EXPAND)
+        sizer.Add(negCmap,       flag=wx.EXPAND)
+        sizer.Add(enableNegCmap, flag=wx.EXPAND)
         
         return sizer
 
@@ -288,7 +303,6 @@ _DISPLAY_PROPS = td.TypeDict({
         props.Widget('cmap'),
         props.Widget('invert'),
         props.Widget('invertClipping'),
-        props.Widget('centreRanges'),
         props.Widget('linkLowRanges'),
         props.Widget('linkHighRanges'),
         props.Widget('displayRange',
diff --git a/fsl/fsleyes/displaycontext/volumeopts.py b/fsl/fsleyes/displaycontext/volumeopts.py
index a4135b83197b04ef8f97789e9989d034203e717d..4e303f0ec971d8566d2ba5167f443db9f3e67ced 100644
--- a/fsl/fsleyes/displaycontext/volumeopts.py
+++ b/fsl/fsleyes/displaycontext/volumeopts.py
@@ -492,6 +492,28 @@ class VolumeOpts(ImageOpts):
     cmap = props.ColourMap()
     """The colour map, a :class:`matplotlib.colors.Colourmap` instance."""
 
+
+    negativeCmap = props.ColourMap()
+    """A second colour map, used if :attr:`enableNegativeCmap` is ``True``.
+    When active, the :attr:`cmap` is used to colour positive values, and
+    the :attr:`negativeCmap` is used to colour negative values.
+    """
+
+    
+    enableNegativeCmap = props.Boolean(default=False)
+    """When ``True``, the :attr:`cmap` is used to colour positive values,
+    and the :attr:`negativeCmap` is used to colour negative values.
+    When this property is enabled, the minimum value for both the
+    :attr:`displayRange` and :attr:`clippingRange` is set to zero. Both
+    ranges are applied to positive values, and negated/inverted for negative
+    values.
+
+    .. note:: When this property is set to ``True``, the
+              :attr:`.Display.brightness` and :attr:`.Display.contrast`
+              properties are disabled, as managing the interaction between
+              them would be far too complicated.
+    """
+
     
     interpolation = props.Choice(('none', 'linear', 'spline'))
     """How the value shown at a real world location is derived from the
@@ -506,19 +528,6 @@ class VolumeOpts(ImageOpts):
     """
 
 
-    centreRanges = props.Boolean(default=False)
-    """If ``True``, the :attr:`displayRange` and :attr:`clippingRange` ranges
-    will be kept centred at zero. A change to the negative end of either range
-    will result in the positive end being changed, and vice versa.
-
-    .. note:: When this property is set to ``True``, the
-              :attr:`.Display.brightness`, :attr:`.Display.contrast`,
-              :attr:`.linkLowRanges` and :attr:`.linkHighRanges` properties
-              are all disabled, as managing the interaction between all of
-              them would be far too complicated.
-    """
-
-
     linkLowRanges = props.Boolean(default=True)
     """If ``True``, the low bounds on both the :attr:`displayRange` and
     :attr:`clippingRange` ranges will be linked together.
@@ -598,9 +607,9 @@ class VolumeOpts(ImageOpts):
             self   .addListener('displayRange',
                                 self.name,
                                 self.__displayRangeChanged)
-            self   .addListener('centreRanges',
+            self   .addListener('enableNegativeCmap',
                                 self.name,
-                                self.__centreRangesChanged)
+                                self.__enableNegativeCmapChanged)
             self   .addListener('linkLowRanges',
                                 self.name,
                                 self.__linkLowRangesChanged)
@@ -621,14 +630,13 @@ class VolumeOpts(ImageOpts):
                            display,
                            display.getSyncPropertyName('contrast'))
 
-            # If centreRanges, linkLowRanges or linkHighRanges
+            # If enableNegativeCmap, linkLowRanges or linkHighRanges
             # have been set to True (this will happen if they
             # are true on the parent VolumeOpts instance), make
             # sure the property / listener states are up to date.
-            if self.centreRanges: self.__centreRangesChanged()
-            else:
-                if self.linkLowRanges:  self.__linkLowRangesChanged()
-                if self.linkHighRanges: self.__linkHighRangesChanged()
+            if self.enableNegativeCmap: self.__enableNegativeCmapChanged()
+            if self.linkLowRanges:      self.__linkLowRangesChanged()
+            if self.linkHighRanges:     self.__linkHighRangesChanged()
 
 
     @actions.action
@@ -733,7 +741,7 @@ class VolumeOpts(ImageOpts):
         See :func:`.colourmaps.displayRangeToBricon`.
         """
 
-        if self.centreRanges:
+        if self.enableNegativeCmap:
             return
 
         brightness, contrast = fslcm.displayRangeToBricon(
@@ -749,32 +757,24 @@ class VolumeOpts(ImageOpts):
         self.__toggleListeners(True)
 
 
-    def __centreRangesChanged(self, *a):
-        """Called when the :attr:`centreRanges` property changes. Configures
-        property listeners on the :attr:`clippingRange` and
-        :attr:`displayRange` properties.
+    def __enableNegativeCmapChanged(self, *a):
+        """Called when the :attr:`enableNegativeCmap` property changes.
+        Enables/disables the :attr:`.Display.brightness` and
+        :attr:`.Display.contrast` properties, and configures limits
+        on the :attr:`clippingRange` and :attr:`displayRange` properties.
         """
 
-        if self.centreRanges:
+        if self.enableNegativeCmap:
             self.display.disableProperty('brightness')
             self.display.disableProperty('contrast')
-            self        .disableProperty('linkLowRanges')
-            self        .disableProperty('linkHighRanges')
-            self.setConstraint('displayRange',  'dimCentres', [0.0])
-            self.setConstraint('clippingRange', 'dimCentres', [0.0])
-
-            # Make sure that lowLinkRanges and
-            # highLinkRanges are not active
-            self.__linkRangesChanged(False, 0)
-            self.__linkRangesChanged(False, 1)
+            self.displayRange .xmin = 0.0
+            self.clippingRange.xmin = 0.0
             
         else:
             self.display.enableProperty('brightness')
             self.display.enableProperty('contrast')
-            self        .enableProperty('linkLowRanges')
-            self        .enableProperty('linkHighRanges') 
-            self.setConstraint('displayRange',  'dimCentres', [None])
-            self.setConstraint('clippingRange', 'dimCentres', [None])
+            self.displayRange .xmin = self.dataMin
+            self.clippingRange.xmin = self.dataMin
 
 
     def __linkLowRangesChanged(self, *a):
diff --git a/fsl/fsleyes/tooltips.py b/fsl/fsleyes/tooltips.py
index 47f2b9bd4023e9e8a14e1921124076e03300829d..f5c62a995f1a2249c63b3d2579ef56415a14c8e2 100644
--- a/fsl/fsleyes/tooltips.py
+++ b/fsl/fsleyes/tooltips.py
@@ -80,12 +80,12 @@ properties = TypeDict({
                                    'voxels outside of the range are displayed.'
                                    'This option is useful for displaying '
                                    'statistic images.',
-    'VolumeOpts.centreRanges'    : 'If checked, the low and high values '
-                                   'of both the clipping and display '
-                                   'ranges will be yoked together, so '
-                                   'that both ranges stay centered at '
-                                   'zero.' ,
-    'VolumeOpts.cmap'            : 'The colour map to use.',
+    'VolumeOpts.cmap'               : 'The colour map to use.',
+    'VolumeOpts.negativeCmap'       : 'The colour map to use for negative '
+                                      'values.',
+    'VolumeOpts.enableNegativeCmap' : 'Enable the negative colour map - '
+                                      'this allows positive and negative '
+                                      'values to be coloured independently.',
     'VolumeOpts.interpolation'   : 'Interpolate the image data for display '
                                    'purposes. You can choose no  '
                                    'interpolation (equivalent to nearest '