From 2538b45e1a1ecf99fc4f8ca9abc36490ae3ac645 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Tue, 12 Jan 2016 17:09:50 +0000
Subject: [PATCH] FEAT things do not crash if the feat directory has no stats.

---
 fsl/data/featimage.py                          | 16 ++++++++++++++--
 fsl/data/featresults.py                        | 12 ++++++++++++
 fsl/fsleyes/controls/timeseriescontrolpanel.py |  5 +++--
 fsl/fsleyes/plotting/timeseries.py             |  3 +++
 4 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/fsl/data/featimage.py b/fsl/data/featimage.py
index 240ab15fe..b18193e5b 100644
--- a/fsl/data/featimage.py
+++ b/fsl/data/featimage.py
@@ -72,8 +72,13 @@ class FEATImage(fslimage.Image):
 
         featDir     = op.dirname(path)
         settings    = featresults.loadSettings( featDir)
-        design      = featresults.loadDesign(   featDir)
-        names, cons = featresults.loadContrasts(featDir)
+
+        if featresults.hasStats(featDir):
+            design      = featresults.loadDesign(   featDir)
+            names, cons = featresults.loadContrasts(featDir)
+        else:
+            design      = np.zeros((0, 0))
+            names, cons = [], []
         
         fslimage.Image.__init__(self, path, **kwargs)
 
@@ -113,6 +118,13 @@ class FEATImage(fslimage.Image):
         is not part of another analysis.
         """
         return featresults.getTopLevelAnalysisDir(self.__featDir)
+
+
+    def hasStats(self):
+        """Returns ``True`` if the analysis for this ``FEATImage`` contains
+        a statistical analysis.
+        """
+        return self.__design.size > 0
         
 
     def getDesign(self):
diff --git a/fsl/data/featresults.py b/fsl/data/featresults.py
index 68a64aa2f..2d1015f60 100644
--- a/fsl/data/featresults.py
+++ b/fsl/data/featresults.py
@@ -15,6 +15,7 @@ following functions are provided:
 
    isFEATImage
    isFEATDir
+   hasStats
    hasMelodicDir
    getAnalysisDir
    getTopLevelAnalysisDir
@@ -97,6 +98,17 @@ def isFEATDir(path):
     return True
 
 
+def hasStats(featdir):
+    """Returns ``True`` if it looks like statistics have been calculated
+    for the given FEAT analysis, ``False`` otherwise.
+    """
+
+    statdir   = op.join(featdir, 'stats')
+    statfiles = glob.glob(op.join(statdir, '*'))
+    
+    return op.exists(statdir) and len(statfiles) > 0
+
+
 def hasMelodicDir(featdir):
     """Returns ``True`` if the data for the given FEAT directory has had
     MELODIC run on it, ``False`` otherwise.
diff --git a/fsl/fsleyes/controls/timeseriescontrolpanel.py b/fsl/fsleyes/controls/timeseriescontrolpanel.py
index 008c7cead..09f037d4a 100644
--- a/fsl/fsleyes/controls/timeseriescontrolpanel.py
+++ b/fsl/fsleyes/controls/timeseriescontrolpanel.py
@@ -116,8 +116,9 @@ class TimeSeriesControlPanel(plotcontrolpanel.PlotControlPanel):
         overlay = ts.overlay
         widgets = self.getWidgetList()
 
-        if not (isinstance(overlay, fslfeatimage.FEATImage) and
-                isinstance(ts,      timeseries.FEATTimeSeries)):
+        if not (isinstance(overlay, fslfeatimage.FEATImage)    and
+                isinstance(ts,      timeseries.FEATTimeSeries) and
+                overlay.hasStats()):
             return
 
         full    = props.makeWidget(     widgets, ts, 'plotFullModelFit')
diff --git a/fsl/fsleyes/plotting/timeseries.py b/fsl/fsleyes/plotting/timeseries.py
index f06ed3633..5eefdb388 100644
--- a/fsl/fsleyes/plotting/timeseries.py
+++ b/fsl/fsleyes/plotting/timeseries.py
@@ -274,6 +274,9 @@ class FEATTimeSeries(VoxelTimeSeries):
         self.__evTs        = [None] * numEVs
         self.__peTs        = [None] * numEVs
         self.__copeTs      = [None] * numCOPEs
+
+        if not self.overlay.hasStats():
+            self.plotFullModelFit = False
         
         self.addListener('plotFullModelFit',
                          self.name,
-- 
GitLab