melodicanalysis.py 5.19 KB
Newer Older
1
2
#!/usr/bin/env python
#
3
4
# melodicanalysis.py - Utility functions for loading/querying the contents of
# a MELODIC analysis directory.
5
#
6
7
8
9
10
11
12
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides a set of functions for accessing the contents of a
MELODIC analysis directory. These functions are primarily intended to be used
by the :class:`.MELODICImage` class, but are available for other uses. The
following functions are provided:

13

14
.. autosummary::
15
   :nosignatures:
16

17
   isMelodicImage
18
   isMelodicDir
19
   getAnalysisDir
20
21
   getTopLevelAnalysisDir
   getDataFile
22
   getICFile
23
   getMixFile
24
   getFTMixFile
25
26
   getNumComponents
   getComponentTimeSeries
27
   getComponentPowerSpectra
28
29
30
"""


31
32
import logging

33
34
35
import os.path as op
import numpy   as np

36
37
import fsl.data.image        as fslimage
import fsl.data.featanalysis as featanalysis
38
39


40
41
42
log = logging.getLogger(__name__)


43
44
def isMelodicImage(path):
    """Returns ``True`` if the given path looks like it is a melodic
45
    component image file, ``False`` otherwise.
46
47
    """

48
49

    try:
50
        path = fslimage.addExt(path)
Paul McCarthy's avatar
Paul McCarthy committed
51
    except fslimage.PathError:
52
53
        return False

54
55
    dirname  = op.dirname( path)
    filename = op.basename(path)
56
    filename = fslimage.removeExt(filename)
57

58
59
60
61
    prefixes = ['melodic_IC',
                'melodic_oIC']

    return any([filename == p for p in prefixes]) and isMelodicDir(dirname)
62

63

64
def isMelodicDir(path):
65
66
    """Returns ``True`` if the given path looks like it is a MELODIC directory,
    ``False`` otherwise. A MELODIC directory:
67

68
69
      - Must contain a file called ``melodic_IC.nii.gz`` or
        ``melodic_oIC.nii.gz``.
70
71
72
      - Must contain a file called ``melodic_mix``.
      - Must contain a file called ``melodic_FTmix``.
    """
73

74
    path = op.abspath(path)
75

76
    if not op.isdir(path):
77
        return False
78

79
80
81
82
83
    # Must contain an image file called
    # melodic_IC or melodic_oIC
    prefixes = ['melodic_IC', 'melodic_oIC']
    for p in prefixes:
        try:
84
            fslimage.addExt(op.join(path, p))
85
86
87
88
            break
        except fslimage.PathError:
            pass
    else:
89
        return False
90

91
92
    # Must contain files called
    # melodic_mix and melodic_FTmix
93
94
    if not op.exists(op.join(path, 'melodic_mix')):   return False
    if not op.exists(op.join(path, 'melodic_FTmix')): return False
95

96
    return True
97
98


99
100
101
102
103
def getAnalysisDir(path):
    """If the given path is contained within a MELODIC directory, the path
    to that MELODIC directory is returned. Otherwise, ``None`` is returned.
    """

104
105
    if not op.isdir(path):
        path = op.dirname(path)
106

107
108
109
110
    while path not in (op.sep, ''):
        if isMelodicDir(path):
            return path
        path = op.dirname(path)
111

112
113
114
115
116
117
118
119
    return None


def getTopLevelAnalysisDir(path):
    """If the given path is contained within a hierarchy of FEAT or MELODIC
    directories, the path to the highest-level (i.e. the shallowest in the
    file system) directory is returned. Otherwise, ``None`` is returned.

120
    See :func:`.featanalysis.getTopLevelAnalysisDir`.
121
    """
122
    return featanalysis.getTopLevelAnalysisDir(path)
123

124

125
126
127
128
def getDataFile(meldir):
    """If the given melodic directory is contained within another analysis
    directory, the path to the data file is returned. Otherwise ``None`` is
    returned.
129
    """
130
131
132
133
134
135
136
137

    topDir = getTopLevelAnalysisDir(meldir)

    if topDir is None:
        return None

    dataFile = op.join(topDir, 'filtered_func_data')

138
    try:                       return fslimage.addExt(dataFile)
Paul McCarthy's avatar
Typo    
Paul McCarthy committed
139
    except fslimage.PathError: return None
140
141


142
143
144
145
146
def getMeanFile(meldir):
    """Return a path to the mean image of the meloidic input data. """
    return fslimage.addExt(op.join(meldir, 'mean'))


147
148
def getICFile(meldir):
    """Returns the path to the melodic IC image. """
149
150
151
152
    try:
        return fslimage.addExt(op.join(meldir, 'melodic_IC'))
    except fslimage.PathError:
        return fslimage.addExt(op.join(meldir, 'melodic_oIC'))
153
154
155


def getMixFile(meldir):
156
    """Returns the path to the melodic mix file. """
157

158
159
160
    mixfile = op.join(meldir, 'melodic_mix')
    if op.exists(mixfile): return mixfile
    else:                  return None
161
162


163
164
def getFTMixFile(meldir):
    """Returns the path to the melodic FT mix file. """
165

166
167
168
    ftmixfile = op.join(meldir, 'melodic_FTmix')
    if op.exists(ftmixfile): return ftmixfile
    else:                    return None
169
170


171
def getReportFile(meldir):
172
173
174
    """Returns the path to the MELODIC report index file, or ``None`` if there
    is no report.
    """
175

176
177
    report = op.join(meldir, '..', 'report.html')
    if op.exists(report): return report
178
    else:                 return None
179
180


181
def getNumComponents(meldir):
182
183
    """Returns the number of components generated in the melodic analysis
    contained in the given directrory.
184
185
    """

186
    icImg = fslimage.Image(getICFile(meldir), loadData=False, calcRange=False)
187
188
189
190
    return icImg.shape[3]


def getComponentTimeSeries(meldir):
191
192
    """Returns a ``numpy`` array containing the melodic mix for the given
    directory.
193
194
    """

195
196
    mixfile = getMixFile(meldir)
    return np.loadtxt(mixfile)
197
198
199
200
201
202
203
204


def getComponentPowerSpectra(meldir):
    """Returns a ``numpy`` array containing the melodic FT mix for the
    given directory.
    """
    ftmixfile = getFTMixFile(meldir)
    return np.loadtxt(ftmixfile)