From df52dc8e1fe51412d871ae92dfaa22230befea54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20N=C3=A1rai?= Date: Thu, 23 May 2024 18:53:14 +0200 Subject: [PATCH 1/3] Adding mat 7.3 support for SPM.mat files in the spm interface --- nipype/interfaces/spm/model.py | 14 +++++----- nipype/utils/filemanip.py | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/nipype/interfaces/spm/model.py b/nipype/interfaces/spm/model.py index 62bf4447ea..6ae9a955e4 100644 --- a/nipype/interfaces/spm/model.py +++ b/nipype/interfaces/spm/model.py @@ -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, @@ -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 ( @@ -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()) ] @@ -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]: diff --git a/nipype/utils/filemanip.py b/nipype/utils/filemanip.py index ef52d00cc6..7e47d1519c 100644 --- a/nipype/utils/filemanip.py +++ b/nipype/utils/filemanip.py @@ -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 @@ -932,3 +933,51 @@ 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 \ No newline at end of file From b3303859b08ad011de283c068f292b75bbe46071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20N=C3=A1rai?= Date: Thu, 23 May 2024 18:56:46 +0200 Subject: [PATCH 2/3] Fix in test_matlab.py --- nipype/interfaces/tests/test_matlab.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nipype/interfaces/tests/test_matlab.py b/nipype/interfaces/tests/test_matlab.py index 0150b64eb5..d028dd3059 100644 --- a/nipype/interfaces/tests/test_matlab.py +++ b/nipype/interfaces/tests/test_matlab.py @@ -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 From bd0d5856d183ba3918eda31f80db3b1d4387c55c Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Thu, 31 Oct 2024 10:01:38 -0400 Subject: [PATCH 3/3] STY: black [ignore-rev] --- nipype/utils/filemanip.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/nipype/utils/filemanip.py b/nipype/utils/filemanip.py index 7e47d1519c..783363b31f 100644 --- a/nipype/utils/filemanip.py +++ b/nipype/utils/filemanip.py @@ -934,24 +934,32 @@ def indirectory(path): 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"]] + 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]] + 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] = [] @@ -980,4 +988,4 @@ def load_spm_mat(spm_mat_file, **kwargs): else: setattr(mat["SPM"][0, 0], "xCon", np.empty((0, 0), dtype=object)) - return mat \ No newline at end of file + return mat