[Neuroimaging] [nipype] updated external mask handling in SPM
Dimitri Papadopoulos Orfanos
dimitri.papadopoulos at cea.fr
Wed Dec 9 06:43:25 EST 2015
Dear all,
I looked into masking in SPM and with some help I came up with the
following findings:
* The SPM user interface only sets "analysis threshold masking", see
file spm_fmri_spm_ui.m around line 375:
%-Masking
%==========================================================================
%-Masking threshold, as proportion of globals
%--------------------------------------------------------------------------
try
gMT = SPM.xM.gMT;
catch
gMT = spm_get_defaults('mask.thresh');
end
TH = g.*gSF*gMT;
%-Place masking structure in xM
%--------------------------------------------------------------------------
SPM.xM = struct(...
'T', ones(q,1),...
'TH', TH,...
'gMT', gMT,...
'I', 0,...
'VM', {[]},...
'xs', struct('Masking','analysis threshold'));
* When specifying the model in batch jobs, SPM itself sets "explicit
masking" in the following way in file /spm_run_fmri_spec.m around line 385:
%-Explicit mask
%--------------------------------------------------------------------------
if ~design_only
if ~isempty(job.mask{1})
SPM.xM.VM = spm_data_hdr_read(job.mask{1});
SPM.xM.xs.Masking = [SPM.xM.xs.Masking, '+explicit mask'];
end
end
* The intent of SPM seems to be that the "explicit mask" is a superset
of the final mask, *not* that it will be the exact mask used during
estimation. From spm_spm.m around line 50:
% xM.VM - struct array of explicit mask image handles
% - (empty if no explicit masks)
% - Explicit mask images are >0 for valid voxels to assess.
% - Mask images can have any orientation, voxel size or data
% type. They are interpolated using nearest neighbour
% interpolation to the voxel locations of the data Y.
% - Note that voxels with constant data (i.e. the same value across
% scans) are also automatically masked out.
* We find different results with Nipype than when running vanilla SPM
batch jobs.
I would therefore suggest removing this Nipype hack by default:
https://github.com/nipy/nipype/commit/fe9d0e07a288afefb34e99f488ef194a443d6089
It could be added as an option, for different "explicit masking" than
initially.
I intend to propose a patch to remove the current hack. Does anyone have
more insight on this Nipype hack that modifies default SPM behavior and
would be against the patch?
Best,
Dimitri
Le 04/12/2015 16:20, Dimitri Papadopoulos Orfanos a écrit :
> Hi Satra,
>
> I understand the whole purpose of this piece of code is to get SPM to
> use an explicit mask. This is done by manipulating the masking structure
> "SPM.xM".
>
> I'm not yet entirely convinced this still needs to be done "behind the
> back of SPM" by modifying SPM.mat outside of the SPM code, but here is
> one of "John's Gems" that recommends this Nipype hack (it refers to SPM2
> though):
> http://blogs.warwick.ac.uk/nichols/entry/spm2_gem_12/
>
> With fMRI data/models, SPM2 is fully capable of doing explicit
> masking, but the user interface for fMRI doesn't ask for it.
> One way to do this type of masking anyway is to change the
> SPM.mat file *after* you specify your model, but *before*
> clicking 'Estimate'.
> Specifically:
> 1. Load the SPM.mat file,
> load SPM
> set the SPM.xM.TH values all to -Inf,
> SPM.xM.TH = -Inf*SPM.xM.TH;
> and, in case that you have an image format not allowing
> NaNs, set SPM.xM.I to 0
> SPM.xM.I = 0;
> 2. If using a mask image, set SPM.xM.VM to a vector of
> structures, where each structure element is the output
> of spm_vol. For instance:
> SPM.xM.VM = spm_vol('Maskimage');
> 3. Finally, save by
> save SPM SPM
>
>
> Most importantly, I am puzzled by the fact that we don't find the same
> results when running SPM8 via Nipype than when running SPM8 back in
> 2010-2012 using batches created from the SPM user interface. At this
> point I am not sure if this is an issue with Nipype, an issue with our
> own scripts created in 2009-2010, or perhaps related to changes in SPM8.
> I would like to the bottom of it - time permitting... I don't feel
> comfortable with the idea that the default SPM workflow could have been
> modified and I'd like to understand the cause of the discrepancy in the
> results.
>
> Best,
> Dimitri
>
> Le 02/12/2015 23:17, Satrajit Ghosh a écrit :
>> hi dimitri,
>>
>> it's been a long while since those lines were written. but i believe
>> this was written as noted in the comments to support the case where the
>> user simply wanted spm to use the explicit mask. the other reason for it
>> was that there were several places that could control spm options (e.g.,
>> config file). we did not want to rely on the config file.
>>
>> i believe it was more of a perspective on what an explicit mask meant. i
>> can't remember if this was discussed on the spm list or came from best
>> practices in our lab at that time.
>>
>> cheers,
>>
>> satra
>>
>> On Wed, Dec 2, 2015 at 9:45 AM, Dimitri Papadopoulos Orfanos
>> <dimitri.papadopoulos at cea.fr <mailto:dimitri.papadopoulos at cea.fr>> wrote:
>>
>> Hi,
>>
>> I have a question on the following commit:
>> https://github.com/nipy/nipype/commit/fe9d0e07a288afefb34e99f488ef194a443d6089
>>
>> Could someone explain the rationale behind the addition of this piece of
>> code in nipype/interfaces/spm/model.py? We came across this code while
>> trying to reproduce the results obtained with an old version of SPM8 run
>> manually vs. the latest version of SPM8 run from Nipype.
>>
>> if isdefined(self.inputs.mask_image):
>> # SPM doesn't handle explicit masking properly, especially
>> # when you want to use the entire mask image
>> postscript = "load SPM;\n"
>> postscript += "SPM.xM.VM = spm_vol('%s');\n" %
>> list_to_filename(self.inputs.mask_image)
>> postscript += "SPM.xM.I = 0;\n"
>> postscript += "SPM.xM.T = [];\n"
>> postscript += "SPM.xM.TH <http://SPM.xM.TH> =
>> ones(size(SPM.xM.TH <http://SPM.xM.TH>))*(%s);\n" %
>> self.inputs.mask_threshold
>> postscript += "SPM.xM.xs = struct('Masking', 'explicit
>> masking only');\n"
>> postscript += "save SPM SPM;\n"
>>
>> We have understood almost all causes for differences in results. The
>> only cause that remains to be explained is this Nipype hack. Has perhaps
>> this issue been discussed on the SPM mailing list?
>>
>> Best,
>> --
>> Dimitri Papadopoulos
>> CEA/Saclay
>> I2BM, NeuroSpin
>> F-91191 Gif-sur-Yvette cedex, France
>> _______________________________________________
>> Neuroimaging mailing list
>> Neuroimaging at python.org <mailto:Neuroimaging at python.org>
>> https://mail.python.org/mailman/listinfo/neuroimaging
>>
>>
>>
>>
>> _______________________________________________
>> Neuroimaging mailing list
>> Neuroimaging at python.org
>> https://mail.python.org/mailman/listinfo/neuroimaging
More information about the Neuroimaging
mailing list