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