SPM2 Gem 4: –log10 P–values from T images

P-value images are difficult to visualize since “important” values are small and clumped near zero. A -log10 transformation makes for much better visualization while still having interpretability (e.g. a value of 3 cooresponds to P=0.001).

This function, T2nltP, will create -log10 P-value image based on either a contrast number (which must be a T contrast) or a T statistic image and the degrees of freedom.

This version for SPM2 was created Michael Moffitt, based on the SPM99 function of the same name for SPM99. Note that Michael’s version can easily be changed to create P-values instead of -log10 P-values.

t2nltP.m

function T2nltP(a1,a2)
% Write image of P-values (spm_nltP_?) for a T image
%
% FORMAT T2nltP
% SPM will ask you which spmT_? file you want to convert to spm_nltP_?
%
% FORMAT T2nltP(Timg,df)
% Timg  Filename of T image
% df    Degrees of freedom
%
%
% As per SPM convention, T images are zero masked, and so zeros will have
% P-value NaN.
%
% @(#)T2nltP.m  1.2 T. Nichols 03/07/15
% Modified 04/01/20 by MAM - for SPM2 compatibility

if nargin==0

     % Ask user for SPM.mat file and specific contrast
     [SPM,xSPM]=spm_getSPM;

     % If a 'T' contrast, get degrees of freedom (df) and fname of spmT_?
     if xSPM.STAT ~= 'T', error('Not a T contrast'); end
     df=xSPM.df(2);
     Tnm=xSPM.Vspm.fname;

elseif nargin==2
   Tnm = a1;
   df  = a2;
end


Tvol = spm_vol(Tnm);

Pvol        = Tvol;
Pvol.dim(4) = spm_type('float');
Pvol.fname  = strrep(Tvol.fname,'spmT','spm_nltP');
if strcmp(Pvol.fname,Tvol.fname)
   Pvol.fname = fullfile(spm_str_manip(Tvol.fname,'H'), ...
                         ['nltP' spm_str_manip(Tvol.fname,'t')]);
end


Pvol = spm_create_vol(Pvol);

for i=1:Pvol.dim(3),
   img         = spm_slice_vol(Tvol,spm_matrix([0 0 i]),Tvol.dim(1:2),0);
   img(img==0) = NaN;
   tmp         = find(isfinite(img));
   if ~isempty(tmp)
       % Create map of P values
       %img(tmp)  = (max(eps,1-spm_Tcdf(img(tmp),df)));

       % Create map of -log10(P values)
       img(tmp)  = -log10(max(eps,1-spm_Tcdf(img(tmp),df)));
   end
   Pvol        = spm_write_plane(Pvol,img,i);
end;

spm_close_vol(Pvol);

SPM2 Gem 3: Finding p–value and statistics for all voxels

(Note: The program in this email was corrected; I have added the corrections to this message. Also, an additional typo was discovered in Sep 2003 and was fixed.)

Subject: Re: tabulate all voxels of a volume or cluster
From: John Ashburner <john@FIL.ION.UCL.AC.UK>
Date: Thu, 27 Mar 2003 14:26:56 +0000 (09:26 EST)
To: SPM@JISCMAIL.AC.UK

> Is there a possibility to tabulate the p-values and statistics for all
> voxels for the entire volume. (not only the peaks) ?
> Or which data file should I readout to get the desired
> values?

Copy and paste the following into Matlab, and select the appropriate
spmT or spmF images.  The first 3 columns are MNI coordinates.  The
fourth is the statistic.  I haven't included any p-values, but this
would be a relatively simple operation, provifing you can figure out
degres of freedom etc.  Use spm_Tcdf.m or spm_Fcdf.m to do this.



 P=spm_get(1,'*.img','Select statistic image');
 V=spm_vol(P);

 [x,y,z] = ndgrid(1:V.dim(1),1:V.dim(2),0);
 for i=1:V.dim(3),
   z   = z + 1;
   tmp = spm_sample_vol(V,x,y,z,0);
   msk = find(tmp~=0 & finite(tmp));
   if ~isempty(msk),
     tmp = tmp(msk);
     xyz1=[x(msk)'; y(msk)'; z(msk)'; ones(1,length(msk))];
     xyzt=V.mat(1:3,:)*xyz1;
     for j=1:length(tmp),
       fprintf('%.4g %.4g %.4g\t%g\n',xyzt(1,j),xyzt(2,j),xyzt(3,j),tmp(j));
     end;
   end;
 end;


Best regards,
-John
  

SPM2 Gem 2: Making your own MINC SPM2 templates

Subject: Re: FDP template — SPM99 version
From: John Ashburner <john@FIL.ION.UCL.AC.UK>
Date: Thu, 27 Mar 2003 16:53:03 +0000 (11:53 EST)
To: SPM@JISCMAIL.AC.UK

> Those who use the FDG template should know that is was created for SPM99,
> and is thus in the standard orientation for that program, which is the
> opposite from that used in SPM2b.
>
> I believe that John Ashburner has agreed to convert to MINC format for use
> in SPM2b.

Converting from SPM99 to SPM2b templates can be pretty easy. In this case, the
command was (all one line):

rawtominc -transverse -short -signed -range 0 32767 -real_range 0 32767
-orange 0 32767 -xstep 2 -ystep 2 -zstep 2 -xstart -90 -ystart -126
-zstart -72 -xdircos 1 0 0 -ydircos 0 1 0 -zdircos 0 0 1 -pet FDG.mnc
91 109 91 < template_FDG_PET_OSEM_seg.img

The converted template can be downloaded from:
ftp://ftp.fil.ion.ucl.ac.uk/spm/spm2b_updates/templates/

rawtominc can be obtained from:
ftp://ftp.bic.mni.mcgill.ca/pub/minc/

Note that the simple conversion only applies to SPM99 templates in
Analyze format. If you do the same with SPM2b generated templates,
then you will need to do a left-right flip to them first.

Best regards,
-John

SPM2 Gem 1: Transformation Matricies in SPM2 vs SPM99

Subject: Re: spm2b: spm_header_edit.m
From: John Ashburner <john@FIL.ION.UCL.AC.UK>
Date: Fri, 7 Feb 2003 19:09:38 +0000 (14:09 EST)
To: SPM@JISCMAIL.AC.UK

> Following your previous answer it looks like the origin is indeed set to
> the new value in the header, but also the  .mat file is written. In this
> file, I find two matrices: M and mat. I noticed that they are identical if
> defaults.analyze.flip = 0 but if defaults.analyze.flip = 1 one of them is
> flipped (M(1,4)=-mat(1,4)). Why are there two transformation matrices?

Backwards compatibility.  The M variable is for compatibility with SPM99,
whereas the mat variable is the one used for SPM2.  Images produced by
SPM2b that have a .mat file should be compatible between analyses with
different defaults.analyze.flip settings.  In other words, reading the
orientation of images with .mat files containing the mat field does not
require identifying the value of defaults.analyze.flip.  However, if the
orientation etc is read from an SPM99 .mat file, or from the .hdr, then
the defaults.analyze.flip variable is consulted.

If a .mat file exists, then it is read, otherwise the relevant information
is taken from the .hdr and defaults.analyze.flip.  If a mat variable exists
in the mat file then it is used, otherwise the orientation is derived from
the M variable and defaults.analyze.flip.

Best regards,
-John

SPM99 Gem 23: Tabulating T Statistics

Subject: Fwd: Re: tabulating all statistics
From: John Ashburner <john@FIL.ION.UCL.AC.UK>
Date: Tue, 1 Jul 2003 11:47:07 +0000 (07:47 EDT)
To: SPM@JISCMAIL.AC.UK

> I was wondering if it would be possible to write t values for an
> entire volume into a file? 

Try this:

   fid=fopen('t-values.txt','w');
   P=spm_get(1,'*.img','Select statistic image');
   V=spm_vol(P);

   [x,y,z] = ndgrid(1:V.dim(1),1:V.dim(2),0);
   for i=1:V.dim(3),
     z   = z + 1;
     tmp = spm_sample_vol(V,x,y,z,0);
     msk = find(tmp~=0 & finite(tmp));
     if ~isempty(msk),
       tmp = tmp(msk);
       xyz1=[x(msk)'; y(msk)'; z(msk)'; ones(1,length(msk))];
       xyzt=V.mat(1:3,:)*xyz1;
       for j=1:length(tmp),
         fprintf(fid,'%.4g %.4g %.4g\t%g\n',...
                 xyzt(1,j),xyzt(2,j),xyzt(3,j),tmp(j));
       end;
     end;
   end;
   fclose(fid);

best regards,
-John
                

As noted in a 2 Feb 2004 email, to eliminate all voxels below a certain threshold, change

     msk = find(tmp~=0 & finite(tmp));

to

     msk = find(tmp>0 & finite(tmp));


SPM99 Gem 22: spm_orthviews tricks

IMHO, after spatial normalization, John’s key contribution to SPM is spm_orthviews, the function behind the ‘Check Reg’ button which let’s you view many volumes simeltaneously. Some of the Gems use spm_orthviews (e.g. Gems 1 and 16) but listed here are some generally useful tricks for spm_orthviews.

These tricks are usefulanytimea three-view orthogonal slice view is shown, whether from useing ‘Check Reg’, ‘Display’ or when overlaying blobs from the ‘Results’ window.

Turn off/on cross-hairs

spm_orthviews('Xhairs','off')

spm_orthviews('Xhairs','on')
.

Return current x,y,z world space, mm location

spm_orthviews('pos')'

(Note that I transpose the returned value into a row vector, for easier copying and pasting.)

Move to x,y,z world space, mm location

spm_orthviews('reposition',[x y z])

SPM99 Gem 21: ImCalc Script

As posted, this snippet is for SPM2; I’ve edited it to work with SPM99.

Subject: Re: a script to use ImaCal
From: John Ashburner <john@FIL.ION.UCL.AC.UK>
Date: Thu, 16 Oct 2003 11:24:17 +0000 (07:24 EDT)
To: SPM@JISCMAIL.AC.UK

> Brain image for each subject to mask out CSF signal was generated by
> using MPR_seg1.img (i1) and MPR_seg2.img (i2) with (i1+i2)>0.5 in
> ImaCal.(called brainmpr.img for each subject)
>
> Then I have more than two-hundred maps, which need to mask out
> CSF. I think I can use ImaCal again with selecting brainmpr.img (i1)
> and FAmap.img (i1), and then calculating (i1.*i2) to generate a new
> image named as bFAmap.img.  Unfortunately, if I use the ImaCal, it
> take so long time to finish all subjects. Could anyone have a script
> to generate  a multiplication imaging with choosing a brain
> image(brainmpr.img, i1) and a map image (FAmap.img, i2) and writing
> an output image (bFAmap.img) from i1.*i2? 

You can do this with a script in Matlab.  Something along the lines of the
following should do it:

P1=spm_get(Inf,'*.img','Select i1');
P2=spm_get(size(P1,1),'*.img','Select i2');

for i=1:size(P1,1),
    P = strvcat(P1(i,:),P2(i,:)));
    Q = ['brainmpr_' num2str(i) '.img'];
    f = '(i1+i2)>0.5';
    flags = {[],[],[],[]};
    Q = spm_imcalc_ui(P,Q,f,flags);
end;

Note that I have not tested the above script.  I'm sure you can fix it if
it doesn't work.

Best regards,
-John

SPM99 Gem 20: Creating customized templates and priors

From: John Ashburner 
Subject: Re: Help for constructing Template images
Date: Wed, 18 Dec 2002 16:22:59 +0000
To: SPM@JISCMAIL.AC.UK

> What are the advantages of customized template images
> in VBM analysis?

Customised templates are useful when:

1) The contrast in your MR images is not the same as the
   contrast used to generate the existing templates.  If
   the contrast is different, then the mean squared cost
   function is not optimal.  However, for "optimised" VBM
   this only really applies to the initial affine
   registration that is incorporated into the initial
   segmentation.  Contrast differences are likely to have
   a relatively small effect on the final results.

2) The demographics of your subject population differ
   from those used to generate the existing templates and
   prior probability images.  For example, serious problems
   can occur if your subjects have very large ventricles.
   In these data, there would be CSF in regions where the
   existing priors say CSF should not exist.  This would
   force some of the CSF to be classified as white matter,
   seriously affecting the intensity distribution that
   is used to model white matter.  This then has negative
   consequences for the whole of the segmentation.

> Can any one please explain the detailed steps to
> construct a customized template image (gray and white
> matter images) for VBM analysis?

The following script is one possible way of generating your
own template image.  Note that it takes a while to run, and
does not save any intermediate images that could be useful
for quality control.  Also, if it crashes at any point then
it is difficult to recover the work it has done so far.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

make_template.m

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 

You may also wish to do some manual editing of the images
afterwards - especially to remove extra-skull CSF.  When
everything has finished, simply smooth the images by 8mm
and call them templates and prior probability images.
You can modify the default priors for the segmentation step
in order that the customised ones are used.  This can be done
either by changing spm_defaults.m, or by typing the following
in Matlab:

spm_defaults
global defaults
defaults.segment.estimate.priors = ...
     spm_get(3,'*.IMAGE','Select GM,WM & CSF priors');

Note that this will be cleared if you reload the defaults.  This
could be done when you start spm, reset the defaults or if the
optimised VBM script is run, as it calls spm_defaults.m.
Alternatively the optimised VBM script could be modified to
include the above.

Note that I have only tried the script with three images, so
I don't have a good feel for how robust it is likely to be.

>
> Please let me know the number of subjects required to
> construct one?

Its hard to say, but more is best.  The 8mm smoothing means
that you can get away with slightly fewer than otherwise.

Best regards,
-John

Note: The make_template is an updated version of what was originally posted. It is current as of Sep 9, 2003.

SPM99 Gem 19: VBM modulation script

This is the famed script to modulate spatially normalized probability images. For gray matter probability images, modulated images have units of gray matter volume per voxel, instead of gray matter concentration adjusted for differences in local brain size.

In John’s own words, here’s a better explaination.

Note that script below is SPM99 specific. In SPM2, it is done viaspm_write_sn(V,prm,'modulate')(Seespm_write_snhelp fore more.)

Date: Thu, 27 Jul 2000 14:28:39 +0100 (BST)
Subject: Re: matlab question & VBM
From: John Ashburner 
To: spm@mailbase.ac.uk, x.chitnis@iop.kcl.ac.uk


| Following on from John Ashburner's recent reply, is there a matlab function
| that enables you to adjust spatially normalised images in order to preserve
| original tissue volume for VBM?

The function attached to this email will do this.  Type the following bit of
code into Matlab to run it:

	Mats   = spm_get(Inf,'*_sn3d.mat','Select sn3d.mat files');
	Images = spm_get(size(Mats,1),'*.img','Select images to modulate');

	for i=1:size(Mats,1),
	        spm_preserve_quantity(deblank(Mats(i,:)),deblank(Images(i,:)));
	end;

[...]

Best regards,
-John

The attached script is here.spm_preserve_quantity.m~