diff --git a/fsl/data/featimage.py b/fsl/data/featimage.py
index 6c536ba109048b588ad1a9940563d61085c30027..a535ba92cfc20891164718280c053fe304433d8a 100644
--- a/fsl/data/featimage.py
+++ b/fsl/data/featimage.py
@@ -63,15 +63,14 @@ class FEATImage(fslimage.Image):
                   ``<directory>.feat/filtered_func_data.nii.gz``.
         """
 
-        featDir = featresults.getFEATDir(path)
-        
-        if featDir is None:
-            raise ValueError('{} does not appear to be data from a '
-                             'FEAT analysis'.format(path))
-
         if op.isdir(path):
-            path = op.join(featDir, 'filtered_func_data')
+            path = op.join(path, 'filtered_func_data')
+
+        if not featresults.isFEATImage(path):
+            raise ValueError('{} does not appear to be data '
+                             'from a FEAT analysis'.format(path))
 
+        featDir     = op.dirname(path)
         settings    = featresults.loadSettings( featDir)
         design      = featresults.loadDesign(   featDir)
         names, cons = featresults.loadContrasts(featDir)
@@ -176,7 +175,7 @@ class FEATImage(fslimage.Image):
 
         if self.__pes[ev] is None:
             pefile = featresults.getPEFile(self.__featDir, ev)
-            self.__pes[ev] = FEATImage(
+            self.__pes[ev] = fslimage.Image(
                 pefile,
                 name='{}: PE{} ({})'.format(
                     self.__analysisName,
@@ -191,7 +190,7 @@ class FEATImage(fslimage.Image):
         
         if self.__residuals is None:
             resfile = featresults.getResidualFile(self.__featDir)
-            self.__residuals = FEATImage(
+            self.__residuals = fslimage.Image(
                 resfile,
                 name='{}: residuals'.format(self.__analysisName))
         
@@ -203,7 +202,7 @@ class FEATImage(fslimage.Image):
         
         if self.__copes[con] is None:
             copefile = featresults.getPEFile(self.__featDir, con)
-            self.__copes[con] = FEATImage(
+            self.__copes[con] = fslimage.Image(
                 copefile,
                 name='{}: COPE{} ({})'.format(
                     self.__analysisName,
@@ -220,7 +219,7 @@ class FEATImage(fslimage.Image):
         if self.__zstats[con] is None:
             zfile = featresults.getZStatFile(self.__featDir, con)
 
-            self.__zstats[con] = FEATImage(
+            self.__zstats[con] = fslimage.Image(
                 zfile,
                 name='{}: zstat{} ({})'.format(
                     self.__analysisName,
@@ -237,7 +236,7 @@ class FEATImage(fslimage.Image):
         if self.__clustMasks[con] is None:
             mfile = featresults.getClusterMaskFile(self.__featDir, con)
 
-            self.__clustMasks[con] = FEATImage(
+            self.__clustMasks[con] = fslimage.Image(
                 mfile,
                 name='{}: cluster mask for zstat{} ({})'.format(
                     self.__analysisName,
diff --git a/fsl/data/featresults.py b/fsl/data/featresults.py
index 138c0379e11563504f39f4aac6ece0cb44db0036..5250788f65325f3762a46ecc9df442956e9c7915 100644
--- a/fsl/data/featresults.py
+++ b/fsl/data/featresults.py
@@ -13,8 +13,8 @@ following functions are provided:
 .. autosummary::
    :nosignatures:
 
+   isFEATImage
    isFEATDir
-   getFEATDir
    hasMelodicDir
    loadDesign
    loadContrasts
@@ -51,59 +51,48 @@ import fsl.utils.transform as transform
 log = logging.getLogger(__name__)
 
 
-def isFEATDir(path):
-    """Returns ``True`` if the given path looks like a FEAT directory, or
-    looks like the input data for a FEAT analysis, ``False`` otherwise.
-
-    :arg path: A file / directory path.
+def isFEATImage(path):
+    """Returns ``True`` if the given path looks like it is the input data to
+    a FEAT analysis, ``False`` otherwise.
     """
+    dirname  = op.dirname( path)
+    filename = op.basename(path) 
 
-    dirname, filename = op.split(path)
+    return filename.startswith('filtered_func_data') and isFEATDir(dirname) 
 
-    featDir   = getFEATDir(dirname)
-    isfeatdir = featDir is not None
-
-    try:
-        hasdesfsf = op.exists(op.join(featDir, 'design.fsf'))
-        hasdesmat = op.exists(op.join(featDir, 'design.mat'))
-        hasdescon = op.exists(op.join(featDir, 'design.con'))
-        
-        isfeat    = (isfeatdir and
-                     hasdesmat and
-                     hasdescon and
-                     hasdesfsf)
-
-        return isfeat
-    
-    except:
-        return False
 
+def isFEATDir(path):
+    """Returns ``True`` if the given path looks like a FEAT directory, or
+    looks like the input data for a FEAT analysis, ``False`` otherwise.  A
+    FEAT directory:
 
-def getFEATDir(path):
-    """Given the path of any file/directory which is within a ``.feat`` or
-    ``.gfeat`` directory, strips all trailing components of the path name,
-    and returns the root FEAT directory.
-    
-    Returns ``None`` if the given path is not contained within a ``.feat``
-    or ``.gfeat`` directory.
+     - Must be named ``*.feat``.
+     - Must contain a file called ``filtered_func_data.nii.gz``.
+     - Must contain a file called ``design.fsf``.
+     - Must contain a file called ``design.mat``.
+     - Must contain a file called ``design.con``.
 
     :arg path: A file / directory path.
     """
 
-    sufs     = ['.feat', '.gfeat']
-    idxs     = [(path.rfind(s), s) for s in sufs]
-    idx, suf = max(idxs, key=lambda (i, s): i)
-
-    if idx == -1:
-        return None
-
-    idx  += len(suf)
-    path  = path[:idx]
+    path = op.abspath(path)
+    
+    if op.isdir(path): dirname = path
+    else:              dirname = op.dirname(path)
+    
+    if not dirname.endswith('.feat'):
+        return False
 
-    if path.endswith(suf) or path.endswith('{}{}'.format(suf, op.sep)):
-        return path
-                                           
-    return None
+    try:
+        fslimage.addExt(op.join(path, 'filtered_func_data'), mustExist=True)
+    except ValueError:
+        return False
+    
+    if not op.exists(op.join(dirname, 'design.fsf')): return False
+    if not op.exists(op.join(dirname, 'design.mat')): return False
+    if not op.exists(op.join(dirname, 'design.con')): return False
+        
+    return True
 
 
 def hasMelodicDir(featdir):
diff --git a/fsl/data/melodicimage.py b/fsl/data/melodicimage.py
index 7e3d7a0f2acee1e660a8e0be4de0ca59fd5d94d1..fd9772744611064de5dd9b37f09c27abfd7e1a6c 100644
--- a/fsl/data/melodicimage.py
+++ b/fsl/data/melodicimage.py
@@ -59,31 +59,18 @@ class MelodicImage(fslimage.Image):
         """
 
         if op.isdir(path):
-            dirname  = path
-            filename = 'melodic_IC'
+            path = op.join(path, 'melodic_IC')
 
-        else:
-            dirname  = op.dirname( path)
-            filename = op.basename(path)
-
-        dirname = dirname.rstrip(op.sep)
-
-        if not melresults.isMelodicDir(dirname):
+        if not melresults.isMelodicImage(path):
             raise ValueError('{} does not appear to be a '
-                             'MELODIC directory'.format(dirname)) 
-        
-        if not filename.startswith('melodic_IC'):
-            raise ValueError('{} does not appear to be a MELODIC '
-                             'component file'.format(filename))
+                             'MELODIC component file'.format(path)) 
             
-        fslimage.Image.__init__(self,
-                                op.join(dirname, filename),
-                                *args,
-                                **kwargs)
-
-        self.__meldir     = dirname
-        self.__melmix     = melresults.getComponentTimeSeries(  dirname)
-        self.__melFTmix   = melresults.getComponentPowerSpectra(dirname)
+        fslimage.Image.__init__(self, path, *args, **kwargs)
+
+        meldir            = op.dirname(path)
+        self.__meldir     = meldir
+        self.__melmix     = melresults.getComponentTimeSeries(  meldir)
+        self.__melFTmix   = melresults.getComponentPowerSpectra(meldir)
         self.__melICClass = melresults.MelodicClassification(   self)
 
         # Automatically set the
diff --git a/fsl/data/melodicresults.py b/fsl/data/melodicresults.py
index 3b8d8dc33be34509741543a5957e873935898fc2..46e78a624a2ceec41a30836976907e3f2000e0cf 100644
--- a/fsl/data/melodicresults.py
+++ b/fsl/data/melodicresults.py
@@ -14,8 +14,8 @@ following functions are provided:
 .. autosummary::
    :nosignatures:
 
+   isMelodicImage
    isMelodicDir
-   getMelodicDir
    getTopLevelAnalysisDir
    getDataFile
    getICFile
@@ -38,62 +38,54 @@ import numpy   as np
 
 import props
 
-import fsl.data.image       as fslimage
-import fsl.data.featresults as featresults
+import fsl.data.image as fslimage
 
 
 log = logging.getLogger(__name__)
 
 
-def isMelodicDir(path):
-    """Returns ``True`` if the given path looks like it is contained within
-    a MELODIC directory, ``False`` otherwise. 
+def isMelodicImage(path):
+    """Returns ``True`` if the given path looks like it is a melodic
+    component image file, ``False`` otherwise. 
     """
 
-    # Must be named *.ica or *.gica
-    return getMelodicDir(path) is not None
-
     
-def getMelodicDir(path):
-    """Returns the MELODIC directory in which the given path is contained,
-    or ``None`` if it is not contained within a MELODIC directory. A melodic
-    directory:
-
-      - Must be named ``*.ica`` or ``*.gica``
-      - Must contain a file called ``melodic_IC.nii.gz``
-      - Must contain a file called ``melodic_mix``.
-    """
+    dirname  = op.dirname( path)
+    filename = op.basename(path)
 
-    # TODO This code is identical to featresults.getFEATDir.
-    # Can you generalise it and put it somewhere in fsl.utils?
-
-    path     = op.abspath(path)
+    return filename.startswith('melodic_IC') and isMelodicDir(dirname)
+ 
 
-    sufs     = ['.ica', '.gica']
-    idxs     = [(path.rfind(s), s) for s in sufs]
-    idx, suf = max(idxs, key=lambda (i, s): i)
+def isMelodicDir(path):
+    """Returns ``True`` if the given path looks like it is contained within
+    a MELODIC directory, ``False`` otherwise. A melodic directory:
 
-    if idx == -1:
-        return None
+      - Must be named ``*.ica``.
+      - Must contain a file called ``melodic_IC.nii.gz``.
+      - Must contain a file called ``melodic_mix``.
+      - Must contain a file called ``melodic_FTmix``.
+    """
 
-    idx  += len(suf)
-    path  = path[:idx].rstrip(op.sep)
+    path = op.abspath(path)
+    
+    if op.isdir(path): dirname = path
+    else:              dirname = op.dirname(path)
 
-    if not path.endswith(suf):
-        return None
+    if not dirname.endswith('.ica'):
+        return False
 
     # Must contain an image file called melodic_IC
     try:
-        fslimage.addExt(op.join(path, 'melodic_IC'), mustExist=True)
+        fslimage.addExt(op.join(dirname, 'melodic_IC'), mustExist=True)
     except ValueError:
-        return None
+        return False
 
     # Must contain files called
     # melodic_mix and melodic_FTmix
-    if not op.exists(op.join(path, 'melodic_mix')):   return None
-    if not op.exists(op.join(path, 'melodic_FTmix')): return None
-                                           
-    return path
+    if not op.exists(op.join(dirname, 'melodic_mix')):   return False
+    if not op.exists(op.join(dirname, 'melodic_FTmix')): return False
+ 
+    return True
 
 
 def getTopLevelAnalysisDir(path):
@@ -102,30 +94,24 @@ def getTopLevelAnalysisDir(path):
     directory is returned. Otherwise, ``None`` is returned.
     """
 
-    meldir = getMelodicDir(path)
-    sufs   =  ['.feat', '.gfeat', '.ica', '.gica']
-    
-    if meldir is None:
-        return None
+    path = path.strip()
 
-    if featresults.isFEATDir(meldir):
-        return featresults.getFEATDir(meldir)
+    # We've reached the root of the file system
+    if path == op.sep or path == '':
+        return None
 
-    parentDir = op.dirname(meldir)
-    parentDir = parentDir.rstrip(op.sep)
+    path   = path.rstrip(op.sep)
+    parent = getTopLevelAnalysisDir(op.dirname(path))
 
-    if not any([parentDir.endswith(s) for s in sufs]):
-        return None
+    if parent is not None:
+        return parent
 
-    # Must contain a file called filtered_func_data.nii.gz
-    dataFile = op.join(parentDir, 'filtered_func_data')
+    sufs = ['.ica', '.gica', '.feat', '.gfeat']
 
-    try:
-        dataFile = fslimage.addExt(dataFile, mustExist=True)
-    except ValueError:
-        return None
+    if any([path.endswith(suf) for suf in sufs]):
+        return path
 
-    return parentDir
+    return None
 
     
 def getDataFile(meldir):
diff --git a/fsl/fsleyes/overlay.py b/fsl/fsleyes/overlay.py
index 053801d5f8db5d2e1667920a47045449a2a696af..1ede376e0f14418db55981c6f2431c992a9aac5a 100644
--- a/fsl/fsleyes/overlay.py
+++ b/fsl/fsleyes/overlay.py
@@ -204,37 +204,21 @@ def guessDataSourceType(path):
     if path.endswith('.vtk'):
         return fslmodel.Model, path
 
-    # Now, we check to see if the given
-    # path is part of a FEAT or MELODIC
-    # analysis. The way we go about this is
-    # a bit silly, but is necessary due to
-    # the fact thet a melodic analysis can
-    # be contained  within a feat analysis
-    # (or another melodic analysis). So we
-    # check for all analysis types and, if
-    # more than one analysis type matches,
-    # we return the one with the longest
-    # path name.
-    analyses = [
-        (fslfeatimage.FEATImage,    featresults.getFEATDir(   path)),
-        (fslmelimage .MelodicImage, melresults .getMelodicDir(path))]
-
-    # Remove the analysis types that didn't match
-    # (the get*Dir function returned None)
-    analyses = [(t, d) for (t, d) in analyses if d is not None]
-
-    # If we have one or more matches for
-    # an analysis directory, we return
-    # the one with the longest path
-    if len(analyses) > 0:
-
-        dirlens = map(len, [d for (t, d) in analyses])
-        maxidx  = dirlens.index(max(dirlens))
-        
-        return analyses[maxidx]
 
-    # If the path is not an analysis directory,
-    # see if it is a regular nifti image
+    if op.isdir(path):
+        if melresults.isMelodicDir(path):
+            return fslmelimage.MelodicImage, path
+
+        if featresults.isFEATDir(path):
+            return fslfeatimage.FEATImage, path
+
+    elif melresults.isMelodicImage(path):
+        return fslmelimage.MelodicImage, path
+    
+    elif featresults.isFEATImage(path):
+        return fslfeatimage.FEATImage, path
+
+    # A regular NIFTI image?
     try:
         path = fslimage.addExt(path, mustExist=True)
         return fslimage.Image, path