Skip to content
Snippets Groups Projects
Commit 94ef1366 authored by Paul McCarthy's avatar Paul McCarthy :mountain_bicyclist:
Browse files

RF: Don't keep file handles open, clear image references

parent 87592d11
No related branches found
No related tags found
No related merge requests found
...@@ -427,48 +427,49 @@ def loadClusterResults(featdir, settings, contrast): ...@@ -427,48 +427,49 @@ def loadClusterResults(featdir, settings, contrast):
# whitespace, and discarding # whitespace, and discarding
# empty lines # empty lines
lines = f.readlines() lines = f.readlines()
lines = [l.strip() for l in lines]
lines = [l for l in lines if l != ''] lines = [line.strip() for line in lines]
lines = [line for line in lines if line != '']
# the first line should contain column
# names, and each other line should # the first line should contain column
# contain the data for one cluster # names, and each other line should
colNames = lines[0] # contain the data for one cluster
clusterLines = lines[1:] colNames = lines[0]
clusterLines = lines[1:]
# each line should be tab-separated
colNames = colNames.split('\t') # each line should be tab-separated
clusterLines = [cl .split('\t') for cl in clusterLines] colNames = colNames.split('\t')
clusterLines = [cl .split('\t') for cl in clusterLines]
# Turn each cluster line into a
# Cluster instance. An error will # Turn each cluster line into a
# be raised if the columm names # Cluster instance. An error will
# are unrecognised (i.e. not in # be raised if the columm names
# the colmap above), or if the # are unrecognised (i.e. not in
# file is poorly formed. # the colmap above), or if the
clusters = [Cluster(**dict(zip(colNames, cl))) for cl in clusterLines] # file is poorly formed.
clusters = [Cluster(**dict(zip(colNames, cl))) for cl in clusterLines]
# Make sure all coordinates are in voxels -
# for first level analyses, the coordXform # Make sure all coordinates are in voxels -
# will be an identity transform (the coords # for first level analyses, the coordXform
# are already in voxels). But for higher # will be an identity transform (the coords
# level, the coords are in mm, and need to # are already in voxels). But for higher
# be transformed to voxels. # level, the coords are in mm, and need to
for c in clusters: # be transformed to voxels.
for c in clusters:
zmax = [c.zmaxx, c.zmaxy, c.zmaxz]
zcog = [c.zcogx, c.zcogy, c.zcogz] zmax = [c.zmaxx, c.zmaxy, c.zmaxz]
copemax = [c.copemaxx, c.copemaxy, c.copemaxz] zcog = [c.zcogx, c.zcogy, c.zcogz]
copemax = [c.copemaxx, c.copemaxy, c.copemaxz]
zmax = transform.transform([zmax], coordXform)[0].round()
zcog = transform.transform([zcog], coordXform)[0].round() zmax = transform.transform([zmax], coordXform)[0].round()
copemax = transform.transform([copemax], coordXform)[0].round() zcog = transform.transform([zcog], coordXform)[0].round()
copemax = transform.transform([copemax], coordXform)[0].round()
c.zmaxx, c.zmaxy, c.zmaxz = zmax
c.zcogx, c.zcogy, c.zcogz = zcog c.zmaxx, c.zmaxy, c.zmaxz = zmax
c.copemax, c.copemaxy, c.copemaxz = copemax c.zcogx, c.zcogy, c.zcogz = zcog
c.copemax, c.copemaxy, c.copemaxz = copemax
return clusters
return clusters
def getDataFile(featdir): def getDataFile(featdir):
......
...@@ -169,30 +169,15 @@ class FEATFSFDesign(object): ...@@ -169,30 +169,15 @@ class FEATFSFDesign(object):
if level == 1: getEVs = getFirstLevelEVs if level == 1: getEVs = getFirstLevelEVs
else: getEVs = getHigherLevelEVs else: getEVs = getHigherLevelEVs
self.__settings = collections.OrderedDict(settings.items()) self.__loadVoxEVs = loadVoxelwiseEVs
self.__design = np.array(designMatrix) self.__settings = collections.OrderedDict(settings.items())
self.__numEVs = self.__design.shape[1] self.__design = np.array(designMatrix)
self.__evs = getEVs(featDir, self.__settings, self.__design) self.__numEVs = self.__design.shape[1]
self.__evs = getEVs(featDir, self.__settings, self.__design)
if len(self.__evs) != self.__numEVs: if len(self.__evs) != self.__numEVs:
raise FSFError('Number of EVs does not match design.mat') raise FSFError('Number of EVs does not match design.mat')
# Load the voxelwise images now,
# so they're ready to be used by
# the getDesign method.
for ev in self.__evs:
if not isinstance(ev, (VoxelwiseEV, VoxelwiseConfoundEV)):
continue
ev.image = None
# The path to some voxelwise
# EVs may not be present -
# see the VoxelwisEV class.
if loadVoxelwiseEVs and (ev.filename is not None):
ev.image = fslimage.Image(ev.filename)
def getEVs(self): def getEVs(self):
"""Returns a list containing the :class:`EV` instances that represent """Returns a list containing the :class:`EV` instances that represent
...@@ -224,7 +209,7 @@ class FEATFSFDesign(object): ...@@ -224,7 +209,7 @@ class FEATFSFDesign(object):
if not isinstance(ev, (VoxelwiseEV, VoxelwiseConfoundEV)): if not isinstance(ev, (VoxelwiseEV, VoxelwiseConfoundEV)):
continue continue
if ev.image is None: if (not self.__loadVoxEVs) or (ev.filename is None):
log.warning('Voxel EV image missing ' log.warning('Voxel EV image missing '
'for ev {}'.format(ev.index)) 'for ev {}'.format(ev.index))
continue continue
...@@ -300,14 +285,15 @@ class VoxelwiseEV(NormalEV): ...@@ -300,14 +285,15 @@ class VoxelwiseEV(NormalEV):
============ ====================================================== ============ ======================================================
``filename`` Path to the image file containing the data for this EV ``filename`` Path to the image file containing the data for this EV
``image`` Reference to the :class:`.Image` object
============ ====================================================== ============ ======================================================
.. note:: The file for voxelwise EVs in a higher level analysis are not .. note:: The file for voxelwise EVs in a higher level analysis are not
copied into the FEAT directory, so if the user has removed them, copied into the FEAT directory, so if the user has removed them,
or moved the .gfeat directory, the file path here will not be or moved the .gfeat directory, the file path here will not be
valid. Therefore, a ``VoxelwiseEV`` will test to see if the valid. Therefore, a ``VoxelwiseEV`` will test to see if the
file exists, and will set the ``filename`` attribute to ``None`` file exists, and will set the ``filename`` and ``image``
it it does not exist. attributes to ``None`` it it does not exist.
""" """
def __init__(self, realIdx, origIdx, title, filename): def __init__(self, realIdx, origIdx, title, filename):
...@@ -330,6 +316,27 @@ class VoxelwiseEV(NormalEV): ...@@ -330,6 +316,27 @@ class VoxelwiseEV(NormalEV):
'exist: {}'.format(filename)) 'exist: {}'.format(filename))
self.filename = None self.filename = None
self.__image = None
def __del__(self):
"""Clears any reference to the voxelwise EV image. """
self.__image = None
@property
def image(self):
"""Returns the :class:`.Image` containing the voxelwise EV data. """
if self.filename is None:
return None
if self.__image is not None:
return self.__image
self.__image = fslimage.Image(self.filename, mmap=False)
return self.__image
class ConfoundEV(EV): class ConfoundEV(EV):
"""Class representing a confound EV. """Class representing a confound EV.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment