nipy / nipype

Workflows and interfaces for neuroimaging packages
https://nipype.readthedocs.org/en/latest/
Other
745 stars 529 forks source link

SPM model - how to implement orthogonolise option for parametric modulation? #2811

Open hstojic opened 5 years ago

hstojic commented 5 years ago

I am using parametric modulation, using SPM. SPM 12 has an option to switch off the default orthogonolisation of regressors, but it seems that option cannot be set from Nipype.

Is nipype setting it to false by default by any chance? I was trying to look under the hood in modelgen.py, but there is nothing there about exact commands sent to SPM - what code in the library I should look up for that?

I could hack the spm code to achieve that, but I would rather try finding a way to do it from nipype and perhaps send a pull request. How would one go about that? It's definitely an important option to be able to set.

According to the matlab batch file, orth is the option in addition to tmod and pmod

matlabbatch{1}.spm.stats.fmri_spec.sess.cond.pmod = struct('name', {}, 'param', {}, 'poly', {});
matlabbatch{1}.spm.stats.fmri_spec.sess.cond.orth = 0;

so we should enable that SPM specific option in the subject_info, along the tmod and pmod.

hstojic commented 5 years ago

This is what I resorted to, implementing additional interface to use the matlab script to go through the SPM.mat object produced by SPM's Level1Design and correct the orth variable:

I was then creating a node calling this interface and putting it in between the design and estimation nodes:

l1orth = Node(SetOrth(), name = "l1orth")
l1orth.inputs.orth = "No"

l1analysis = Workflow(name = 'l1analysis')
l1analysis.base_dir = os.path.join(dir_neurodata_proc, 'nipype_work')
l1analysis.connect([
    (l1model, l1design, [('session_info', 'session_info')]),
    (l1design, l1orth, [('spm_mat_file', 'spm_mat_file')]),
    (l1orth, l1estimate, [('spm_mat_file', 'spm_mat_file')]),
    (l1estimate, l1contrasts, [
        ('spm_mat_file', 'spm_mat_file'),
        ('beta_images', 'beta_images'),
        ('residual_image', 'residual_image')]
    )
])

I hate the solution, but I really couldn't understand the code in https://nipype.readthedocs.io/en/latest/interfaces/generated/interfaces.spm/model.html#interfaces-spm-model and how to adjust it directly in Level1design class.

Also, when implementing this I first followed the documentation here, but that was returning errors. Then I followed this instead and that worked. Is the documentation on the main website up to date?

I also tried writing a simple function through which the output of design node would be passed before forwarding it to the estimation node. I used scipy to load the SPM.mat file created by the design node, that works fine but it seems object is in a strange format and it wouldn't want to save it back, even if the object is unchanged. This is much cleaner solution, but couldn't figure out why scipy was complaining about the SPM object.

Anyhow, orth option should still be implemented in nipype, any proposals how to go about it and i will gladly submit a pull request.

satra commented 5 years ago

@hstojic - are 0 and 1 the only options orth can take? in that case this could be as simple as adding an orthogonalize input to https://github.com/nipy/nipype/blob/master/nipype/algorithms/modelgen.py#L459

and then updating the session structure returned here:

https://github.com/nipy/nipype/blob/master/nipype/algorithms/modelgen.py#L618

with something along the lines of:

        for i, info in enumerate(concatlist):
                for cid, cond in enumerate(info.conditions):
                    self._sessinfo[i]['cond'][cid]['orth'] = self.inputs.orthogonalize

regarding source of documentation, we are doing some reorganization. @miykael and @djarecka are updating the jupyter notebooks to take over bulk of the training material and resolving such issues.

hstojic commented 5 years ago

Ok, took some time but I implemented it following @satra suggestion and it works as far as I can tell. Instead of supplying it as an additional input it seemed better to implement it as a part of sessioninfo. Submitted PR for it.

vuonghtruong commented 1 year ago

Hi @hstojic,

I am interested in using niype to analyse my fMRI data and am figuring out a way to turn orthogonalization for parametric modulation off. Is there any reason why your implementation has not yet been merged to the latest Nipype version yet? (I saw that it got blocked). I changed the source code locally by myself by looking at your code at it seems to work. Based on my understanding, the issue seem to be that it only works with SPM12 (not SPM8), and for the final release, we will just need to perform a SPM version check before your modified code, right?

Best, Vuong