Skip to content

Commit

Permalink
Merge pull request #3650 from adamnarai/master
Browse files Browse the repository at this point in the history
[FIX] mat 7.3 support for SPM.mat files
  • Loading branch information
effigies authored Oct 31, 2024
2 parents 8bffa93 + bd0d585 commit 00c490c
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 8 deletions.
14 changes: 7 additions & 7 deletions nipype/interfaces/spm/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

# Local imports
from ... import logging
from ...utils.filemanip import ensure_list, simplify_list, split_filename
from ...utils.filemanip import ensure_list, simplify_list, split_filename, load_spm_mat
from ..base import (
Bunch,
traits,
Expand Down Expand Up @@ -313,12 +313,10 @@ def _parse_inputs(self):
return einputs

def _list_outputs(self):
import scipy.io as sio

outputs = self._outputs().get()
pth = os.path.dirname(self.inputs.spm_mat_file)
outtype = "nii" if "12" in self.version.split(".")[0] else "img"
spm = sio.loadmat(self.inputs.spm_mat_file, struct_as_record=False)
spm = load_spm_mat(self.inputs.spm_mat_file, struct_as_record=False)

betas = [vbeta.fname[0] for vbeta in spm["SPM"][0, 0].Vbeta[0]]
if (
Expand Down Expand Up @@ -503,6 +501,10 @@ def _make_matlab_command(self, _):
load(jobs{1}.stats{1}.con.spmmat{:});
SPM.swd = '%s';
save(jobs{1}.stats{1}.con.spmmat{:},'SPM');
[msg,id] = lastwarn('');
if strcmp(id,'MATLAB:save:sizeTooBigForMATFile')
save(jobs{1}.stats{1}.con.spmmat{:},'SPM','-v7.3');
end
names = SPM.xX.name;"""
% (self.inputs.spm_mat_file, os.getcwd())
]
Expand Down Expand Up @@ -581,11 +583,9 @@ def _make_matlab_command(self, _):
return "\n".join(script)

def _list_outputs(self):
import scipy.io as sio

outputs = self._outputs().get()
pth, _ = os.path.split(self.inputs.spm_mat_file)
spm = sio.loadmat(self.inputs.spm_mat_file, struct_as_record=False)
spm = load_spm_mat(self.inputs.spm_mat_file, struct_as_record=False)
con_images = []
spmT_images = []
for con in spm["SPM"][0, 0].xCon[0]:
Expand Down
2 changes: 1 addition & 1 deletion nipype/interfaces/tests/test_matlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def test_run_interface(tmpdir):
# bypasses ubuntu dash issue
mc = mlab.MatlabCommand(script="foo;", paths=[tmpdir.strpath], mfile=True)
assert not os.path.exists(default_script_file), "scriptfile should not exist 4."
with pytest.raises(OSError):
with pytest.raises(RuntimeError):
mc.run()
assert os.path.exists(default_script_file), "scriptfile should exist 4."
if os.path.exists(default_script_file): # cleanup
Expand Down
57 changes: 57 additions & 0 deletions nipype/utils/filemanip.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from pathlib import Path
import simplejson as json
from time import sleep, time
import scipy.io as sio

from .. import logging, config, __version__ as version
from .misc import is_container
Expand Down Expand Up @@ -927,3 +928,59 @@ def indirectory(path):
yield
finally:
os.chdir(cwd)


def load_spm_mat(spm_mat_file, **kwargs):
try:
mat = sio.loadmat(spm_mat_file, **kwargs)
except NotImplementedError:
import h5py
import numpy as np

mat = dict(SPM=np.array([[sio.matlab.mat_struct()]]))

# Get Vbeta, Vcon, and Vspm file names
with h5py.File(spm_mat_file, "r") as h5file:
fnames = dict()
try:
fnames["Vbeta"] = [
u"".join(chr(c[0]) for c in h5file[obj_ref[0]])
for obj_ref in h5file["SPM"]["Vbeta"]["fname"]
]
except Exception:
fnames["Vbeta"] = []
for contr_type in ["Vcon", "Vspm"]:
try:
fnames[contr_type] = [
u"".join(chr(c[0]) for c in h5file[obj_ref[0]]["fname"])
for obj_ref in h5file["SPM"]["xCon"][contr_type]
]
except Exception:
fnames[contr_type] = []

# Structure Vbeta as returned by scipy.io.loadmat
obj_list = []
for i in range(len(fnames["Vbeta"])):
obj = sio.matlab.mat_struct()
setattr(obj, "fname", np.array([fnames["Vbeta"][i]]))
obj_list.append(obj)
if len(obj_list) > 0:
setattr(mat["SPM"][0, 0], "Vbeta", np.array([obj_list]))
else:
setattr(mat["SPM"][0, 0], "Vbeta", np.empty((0, 0), dtype=object))

# Structure Vcon and Vspm as returned by scipy.io.loadmat
obj_list = []
for i in range(len(fnames["Vcon"])):
obj = sio.matlab.mat_struct()
for contr_type in ["Vcon", "Vspm"]:
temp = sio.matlab.mat_struct()
setattr(temp, "fname", np.array([fnames[contr_type][i]]))
setattr(obj, contr_type, np.array([[temp]]))
obj_list.append(obj)
if len(obj_list) > 0:
setattr(mat["SPM"][0, 0], "xCon", np.array([obj_list]))
else:
setattr(mat["SPM"][0, 0], "xCon", np.empty((0, 0), dtype=object))

return mat

0 comments on commit 00c490c

Please sign in to comment.