diff --git a/fsl/data/image.py b/fsl/data/image.py
index fe179c4e714f5a2c6bfbd2cf609bcd573862ae7c..8fcbb7e895b3d0d2f30d4ec7915076f9041919dc 100644
--- a/fsl/data/image.py
+++ b/fsl/data/image.py
@@ -23,7 +23,7 @@ file names:
 .. autosummary::
    :nosignatures:
 
-   isSupported
+   looksLikeImage
    removeExt
    addExt
    loadImage
@@ -146,8 +146,10 @@ class Nifti1(object):
         else:
             self.nibImage = image
 
-        self.shape         = self.nibImage.get_shape()
-        self.pixdim        = self.nibImage.get_header().get_zooms()
+        shape, pixdim = self.__determineShape(self.nibImage)
+        
+        self.shape         = shape
+        self.pixdim        = pixdim
         self.voxToWorldMat = np.array(self.nibImage.get_affine())
         self.worldToVoxMat = transform.invert(self.voxToWorldMat)
 
@@ -158,6 +160,39 @@ class Nifti1(object):
 
         if len(self.shape) < 3 or len(self.shape) > 4:
             raise RuntimeError('Only 3D or 4D images are supported')
+
+
+    def __determineShape(self, nibImage):
+        """This method is called by :meth:`__init__`. It figures out the shape
+        of the image data, and the zooms/pixdims for each data axis. Any empty
+        trailing dimensions are squeezed, but the returned shape is guaranteed
+        to be at least 3 dimensions.
+        """
+
+        nibHdr  = nibImage.get_header()
+        shape   = list(nibImage.shape)
+        pixdims = list(nibHdr.get_zooms())
+
+        # Squeeze out empty dimensions, as
+        # 3D image can sometimes be listed
+        # as having 4 or more dimensions 
+        for i in reversed(range(len(shape))):
+            if shape[i] == 1: shape = shape[:i]
+            else:             break
+
+        # But make sure the shape is 3D
+        if len(shape) < 3:
+            shape = shape + [1] * (3 - len(shape))
+
+        # The same goes for the pixdim - if get_zooms()
+        # doesn't return at least 3 values, we'll fall
+        # back to the pixdim field in the header.
+        if len(pixdims) < 3:
+            pixdims = nibHdr['pixdim'][1:]
+
+        pixdims = pixdims[:len(shape)]
+        
+        return shape, pixdims
  
     
     def loadData(self):
@@ -165,30 +200,26 @@ class Nifti1(object):
         be called if the ``loadData`` parameter passed to :meth:`__init__`
         was ``False``.
         """
-        
-        data = self.nibImage.get_data()
 
-        # Squeeze out empty dimensions, as
-        # 3D image can sometimes be listed
-        # as having 4 or more dimensions
-        shape = data.shape
-        
-        for i in reversed(range(len(shape))):
-            if shape[i] == 1: data = data.squeeze(axis=i)
-            else:             break
+        # Get the data, and reshape it according
+        # to the shape that the __determineShape
+        # method figured out.
+        data      = self.nibImage.get_data()
+        origShape = data.shape
+        data      = data.reshape(self.shape)
 
+        # Tell numpy to make the
+        # data array read-only
         data.flags.writeable = False
+        
+        self.data = data
 
         log.debug('Loaded image data ({}) - original '
                   'shape {}, squeezed shape {}'.format(
                       self.dataSource,
-                      shape,
+                      origShape,
                       data.shape))
 
-        self.data    = data
-        self.shape   = self.shape[ :len(data.shape)]
-        self.pixdim  = self.pixdim[:len(data.shape)]
-        
         
     # TODO: Remove this method, and use the shape attribute directly
     def is4DImage(self):
@@ -556,8 +587,8 @@ DEFAULT_EXTENSION  = '.nii.gz'
 """The default file extension (TODO read this from ``$FSLOUTPUTTYPE``)."""
 
 
-def isSupported(filename, allowedExts=None):
-    """Returns ``True`` if the given file has a supported extension, ``False``
+def looksLikeImage(filename, allowedExts=None):
+    """Returns ``True`` if the given file looks like an image, ``False``
     otherwise.
 
     :arg filename:    The file name to test.
@@ -568,6 +599,9 @@ def isSupported(filename, allowedExts=None):
 
     if allowedExts is None: allowedExts = ALLOWED_EXTENSIONS
 
+    # TODO A much more robust approach would be
+    #      to try loading the file using nibabel.
+
     return any(map(lambda ext: filename.endswith(ext), allowedExts))
 
 
@@ -787,7 +821,8 @@ def saveImage(image, fromDir=None):
     path     = dlg.GetPath()
     nibImage = image.nibImage
 
-    if not isSupported(path):
+    # Add a file extension if not specified
+    if not looksLikeImage(path):
         path = addExt(path, False)
 
     # this is an image which has been
diff --git a/fsl/data/tensorimage.py b/fsl/data/tensorimage.py
index 838910c8a9438e366a47e83aa1715db900b96b3a..0bc0627ac47e6e46f7779c5ec2b24cedcf812560 100644
--- a/fsl/data/tensorimage.py
+++ b/fsl/data/tensorimage.py
@@ -34,26 +34,46 @@ def getTensorDataPrefix(path):
     fas   = glob.glob(op.join(path, '*_FA.*'))
     mds   = glob.glob(op.join(path, '*_MD.*'))
     files = [v1s, v2s, v3s, l1s, l2s, l3s, fas, mds]
-    
-    # Make sure there is exactly one
-    # of each of the above files
-    def lenone(l):
-        return len(l) == 1
-
-    if not all(map(lenone, files)):
-        return None
 
-    files = [f[0] for f in files]
-
-    # Make sure that all of the above
-    # files have the same prefix
+    # Gather all of the existing file
+    # prefixes into a dictionary of
+    # prefix : [file list] mappings.
     pattern  = '^(.*)_(?:V1|V2|V3|L1|L2|L3|FA|MD).*$'
-    prefixes = [re.findall(pattern, f)[0] for f in files]
-
-    if any([p != prefixes[0] for p in prefixes]):
+    prefixes = {}
+
+    for f in [f for flist in files for f in flist]:
+        prefix = re.findall(pattern, f)[0]
+
+        if prefix not in prefixes: prefixes[prefix] = [f]
+        else:                      prefixes[prefix].append(f)
+                
+    # Discard any prefixes which are 
+    # not present for every file type.
+    for prefix, files in list(prefixes.items()):
+        if len(files) != 8:
+            prefixes.pop(prefix)
+
+    # Discard any prefixes which
+    # match any files that do
+    # not look like image files
+    for prefix, files in list(prefixes.items()):
+        if not all([fslimage.looksLikeImage(f) for f in files]):
+            prefixes.pop(prefix)
+
+    prefixes = list(prefixes.keys())
+
+    # No more prefixes remaining -
+    # this is probably not a dtifit
+    # directory
+    if len(prefixes) == 0:
         return None
 
-    # And there's our prefix
+    # If there's more than one remaining
+    # prefix, I don't know what to do -
+    # just return the first one. 
+    if len(prefixes) > 1:
+        log.warning('Multiple dtifit prefixes detected: {}'.format(prefixes))
+
     return op.basename(prefixes[0])
 
 
diff --git a/fsl/fsleyes/displaycontext/vectoropts.py b/fsl/fsleyes/displaycontext/vectoropts.py
index dcfb79f46bc5e7af067d1da54195dfa9a73927a0..4326dbe28f9e0a271cddb4f425561adb616b33b0 100644
--- a/fsl/fsleyes/displaycontext/vectoropts.py
+++ b/fsl/fsleyes/displaycontext/vectoropts.py
@@ -181,7 +181,7 @@ class VectorOpts(volumeopts.Nifti1Opts):
         """
         
         prop     = self.getProp(imageName)
-        val      = self.modulateImage
+        val      = getattr(self, imageName)
         overlays = self.displayCtx.getOrderedOverlays()
 
         options = [None]
diff --git a/fsl/fsleyes/gl/gl21/glvector_funcs.py b/fsl/fsleyes/gl/gl21/glvector_funcs.py
index 3a95d81e7f7197726d9afaef71cd83634a7bfea5..2e4b59320d9737d574a112f462b3039f158b3334 100644
--- a/fsl/fsleyes/gl/gl21/glvector_funcs.py
+++ b/fsl/fsleyes/gl/gl21/glvector_funcs.py
@@ -31,6 +31,8 @@ def compileShaders(self, vertShader, indexed=False):
     opts                = self.displayOpts
     useVolumeFragShader = opts.colourImage is not None
 
+    self.useVolumeFragShader = useVolumeFragShader
+
     if useVolumeFragShader: fragShader = 'glvolume'
     else:                   fragShader = 'glvector'
 
@@ -48,7 +50,6 @@ def updateFragmentShaderState(self, useSpline=False):
     changed             = False
     opts                = self.displayOpts
     shader              = self.shader
-    useVolumeFragShader = opts.colourImage is not None
 
     invClipValXform = self.clipTexture.invVoxValXform
     clippingRange   = opts.clippingRange
@@ -67,7 +68,7 @@ def updateFragmentShaderState(self, useSpline=False):
         clipLow  = -0.1
         clipHigh =  1.1
 
-    if useVolumeFragShader:
+    if self.useVolumeFragShader:
 
         voxValXform     = self.colourTexture.voxValXform
         invVoxValXform  = self.colourTexture.invVoxValXform
diff --git a/fsleyes_doc/editing_images.rst b/fsleyes_doc/editing_images.rst
index a6cf5c36b81b62a3a32aac3105c3f423bab3181d..a63669dc89484f4582f6965966d4974b92716c59 100644
--- a/fsleyes_doc/editing_images.rst
+++ b/fsleyes_doc/editing_images.rst
@@ -1,39 +1,172 @@
+.. |command_key| unicode:: U+2318
+.. |shift_key|   unicode:: U+21E7
+.. |control_key| unicode:: U+2303
+.. |alt_key|     unicode:: U+2325 
+.. |right_arrow| unicode:: U+21D2
+
+
 .. _editing-images:
 
 
-Editing images
-==============
+Editing NIFTI images
+====================
+
+
+The ortho view has an *edit mode* which allows you to edit the values of NIFTI
+overlays.
 
 
 .. _editing-images-edit-toolbar:
 
 
+Create a copy!
+--------------
+
+
+If you are worried about destroying your data, you may wish to create a copy
+of your image, and edit that copy - you can do this via the *File*
+|right_arrow| *Copy overlay* menu option.
+
+
 The edit toolbar
-^^^^^^^^^^^^^^^^
+----------------
+
+
+.. TODO:: Image of edit toolbar goes here.
+
+
+Open the edit toolbar (via the *Settings* |right_arrow| *Ortho view*
+|right_arrow| *Edit toolbar* menu option), and click on the pencil button to
+enter edit mode.
+
+Modifying the data in an image is a two-stage process:
+
+ 1. Select the voxels you wish to change.
+ 
+ 2. Change the value of the selected voxels.
+
+
+Selecting voxels
+----------------
+
+
+Voxels can be selected by right-clicking and dragging, or by holding down the
+|command_key|/|control_key| and |shift_key| keys and left-clicking and
+dragging.
+
+Voxels can be de-selected by holding down the |command_key|/|control_key| and
+|shift_key| keys, and right-clicking and dragging.
+
+The selection size can be adjusted via the Selection size field in the edit
+toolbar, or by holding down the |command_key|/|control_key| and |shift_key|
+keys and spinning the mouse wheel.
+
+By default, the selection block is a 2-dimensional rectangle in the current
+slice, but it can be made into a 3-dimensional cube by toggling the 2D/3D
+button on the edit toolbar.
+
+
+Select-by-value
+---------------
+
+
+.. image:: images/editing_images_select_by_value_button.png
+   :align: left
+
+As an alternate to manually drawing the selection, voxels can be selected by
+value. Select-by-value mode is enabled via the select-by-value button on the
+edit toolbar.
+
+
+In select-by-value mode, clicking on a voxel (the *seed*) will result in all
+voxels that have a value similar to that voxel being selected.  The threshold
+by which voxels are considered to be similar can be changed via the edit
+toolbar, or by spinning the mouse wheel.
+
+
+When in select-by-value mode, the search region can be restricted in the
+following ways:
+
+
+.. image:: images/editing_images_2D_button.png
+   :align: left
+           
+The region can be limited to the current slice, or the entire volume, via the
+2D/3D buttons.
+
+   
+.. image:: images/editing_images_select_radius_button.png
+   :align: left
+              
+The region be limited to a radius by pushing the radius button.  The radius
+can be changed on the edit toolbar, or by holding down the |alt_key| and
+|shift_key| keys, and spinning the mouse wheel.
+
+   
+.. image:: images/editing_images_local_search_button.png
+   :align: left
+              
+The search can be restricted to adjacent voxels by pushing the local search
+button.  When local search is enabled, voxels which are not adjacent to an
+already-selected voxel are excluded from the search.
+
+
+Changing voxel values
+---------------------
+
+
+Once you are happy with your selection you can change the value of the
+selected voxels in one of the following ways:
+
+.. image:: images/editing_images_bucket_fill_button.png
+   :align: left
+              
+The values of all selected voxels can be replaced with the current fill value,
+by clicking the bucket-fill button:
+
+
+.. image:: images/editing_images_erase_button.png
+   :align: left
+              
+The values of all selected voxels can be erased (replaced with 0) by clicking
+the erase button:
+
+              
+The current fill value can be modified via the Fill value field on the edit
+toolbar.
+
 
+Creating masks/ROIs
+-------------------
 
-.. _editing-images-fill-value:
 
+Once you have made a selection, you can copy that selection into a new overlay,
+with the *Create mask* and *Create ROI* buttons. Both buttons will create a new
+image which has the same dimensions as the image being edited.
 
-Filling the selection
-^^^^^^^^^^^^^^^^^^^^^
 
 
-.. _editing-images-erasing:
+.. image:: images/editing_images_create_roi_button.png
+   :align: left
 
-Erasing the selection
-^^^^^^^^^^^^^^^^^^^^^
+The *Create ROI* button will create a new image, and will copy the values of
+all selected voxels over from the image being edited. All other voxels in the
+new image will be set to 0.
 
 
-.. _editing-images-selectionIs3D:
 
+.. image:: images/editing_images_create_mask_button.png
+   :align: left
 
-3D selections
-^^^^^^^^^^^^^
+The *Create Mask* button will create a new image, and will set the value of
+all selected voxels to 1, and the value of all other voxels to 0.
 
+   
 
-.. _editing-images-select-by-intensity:
+Saving your changes
+-------------------
 
 
-Select by value
-^^^^^^^^^^^^^^^
+When you have made changes to an image, or created a mask/ROI image, don't
+forget to save them via the *File* |right_arrow| *Save overlay* menu item, or
+the floppy disk button on the :ref:`controls-overlay-list`.
diff --git a/fsleyes_doc/images/editing_images_2D_button.png b/fsleyes_doc/images/editing_images_2D_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..f6ae443adc6b9fd018815825730bc12991a464ed
Binary files /dev/null and b/fsleyes_doc/images/editing_images_2D_button.png differ
diff --git a/fsleyes_doc/images/editing_images_bucket_fill_button.png b/fsleyes_doc/images/editing_images_bucket_fill_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..2bf40da113b17d5ccd46558e788cb560035e05ad
Binary files /dev/null and b/fsleyes_doc/images/editing_images_bucket_fill_button.png differ
diff --git a/fsleyes_doc/images/editing_images_create_mask_button.png b/fsleyes_doc/images/editing_images_create_mask_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..dfacd2d17c3716ddfb0d39dd7070627ae01f43f4
Binary files /dev/null and b/fsleyes_doc/images/editing_images_create_mask_button.png differ
diff --git a/fsleyes_doc/images/editing_images_create_roi_button.png b/fsleyes_doc/images/editing_images_create_roi_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..03e58dd6538ad0f9a8381271893c803a6f778226
Binary files /dev/null and b/fsleyes_doc/images/editing_images_create_roi_button.png differ
diff --git a/fsleyes_doc/images/editing_images_erase_button.png b/fsleyes_doc/images/editing_images_erase_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8126d7d69a9c790c59d94bde771c2f83cf51b86
Binary files /dev/null and b/fsleyes_doc/images/editing_images_erase_button.png differ
diff --git a/fsleyes_doc/images/editing_images_local_search_button.png b/fsleyes_doc/images/editing_images_local_search_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..7bf629fca5963da9eed100f12db8b8d946318bc0
Binary files /dev/null and b/fsleyes_doc/images/editing_images_local_search_button.png differ
diff --git a/fsleyes_doc/images/editing_images_select_by_value_button.png b/fsleyes_doc/images/editing_images_select_by_value_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..eec43d184eb1087c0363bcfbf5f4a7a7fab0dae4
Binary files /dev/null and b/fsleyes_doc/images/editing_images_select_by_value_button.png differ
diff --git a/fsleyes_doc/images/editing_images_select_radius_button.png b/fsleyes_doc/images/editing_images_select_radius_button.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffaf7f5ab9952829c202177f56b173ebe14361b7
Binary files /dev/null and b/fsleyes_doc/images/editing_images_select_radius_button.png differ
diff --git a/fsleyes_doc/quick_start.rst b/fsleyes_doc/quick_start.rst
index e43d3d02d235be50ce07ac98ba330c1cf1665cbd..6573b7b7e44d02d904d47d37a7971ec746ed98b7 100644
--- a/fsleyes_doc/quick_start.rst
+++ b/fsleyes_doc/quick_start.rst
@@ -30,8 +30,9 @@ looks like this:
    :align: center
 
 
-This is slightly boring, so let's load an image. Select the *File/Add overlay
-from file* menu option, and choose a `.nii.gz` image to load.
+This is slightly boring, so let's load an image. Select the *File
+|right_arrow| Add overlay from file* menu option, and choose a `.nii.gz` image
+to load.
           
 Now things are a bit more interesting:
 
@@ -242,54 +243,9 @@ Edit a NIFTI1 image?
 
 You can :ref:`edit NIFTI1 image data <editing-images>` from within an ortho
 view. Open the :ref:`edit toolbar <editing-images-edit-toolbar>` (via the
-*Settings* |right_arrow| *<view name>* |right_arrow| *Edit toolbar* menu
-option), and click on the pencil button to enter edit mode.
-
-Modifying the data in an image is a two-stage process:
-
- 1. Select the voxels you wish to change.
- 2. Change the value of the selected voxels.
-
-
-**Selecting voxels**
-
- - Voxels can be selected by right-clicking and dragging, or by holding down
-   the |command_key|/|control_key| and |shift_key| keys and left-clicking and
-   dragging.
-   
- - Voxels can be deselected by holding down the |command_key|/|control_key|
-   and |shift_key| keys, and right-clicking and dragging.
-
- - The selection size can be adjusted via the *Selection size* field in the
-   edit toolbar, or by holding down the |command_key|/|control_key| and
-   |shift_key| keys and spinning the mouse wheel.
-
- - By default, the selection block is a 2-dimensional rectangle in the
-   current slice, but it can be made into a 3-dimensional cube by toggling
-   the :ref:`2D/3D button <editing-images-selectionIs3D>` on the
-   edit toolbar.
-
- - As an alternate to manually drawing the selection, voxels can be
-   :ref:`selected by value <editing-images-select-by-intensity>`.
-
-           
-**Changing voxel values**
-       
- - The values of all selected voxels can be replaced with the current
-   :ref:`fill value <editing-images-fill-value>`, by clicking the
-   bucket-fill button on the edit toolbar.
-
- - The values of all selected voxels can be *erased* (replaced with 0) by
-   clicking the :ref:`erase button <editing-images-erasing>` on the edit
-   toolbar.
-
- - The current fill value can be modified via the *Fill value* field
-   on the edit toolbar.
-
-      
-When you have made changes to an image, don't forget to save them via the
-*File* |right_arrow| *Save overlay* menu item, or the floppy disk button on
-the :ref:`controls-overlay-list`.
+*Settings* |right_arrow| *Ortho view* |right_arrow| *Edit toolbar* menu
+option), and click on the pencil button to enter edit mode. See the page on
+:ref:`editing images <editing-images>` for more details.
 
 
 Classify ICA components?