# All 45 entries tagged Johns-Gems

Essential tips & tricks from John Asburner

No other Warwick Blogs use the tag Johns-Gems on entries | View entries tagged Johns-Gems at Technorati | There are no images tagged Johns-Gems on this blog

## February 16, 2012

### Creating Paired Differences

If you analyze 2-time point longitudinal data, you will eventually observe that it is easier to create and analyze difference data (e.g. data from time 2 minus data from time 1). However, if you’re not a scripting guru this might be an annoying task.

This `PairDiff.m` script will take an even number of images and produce a set of paired difference images, even minus odd.

```function PairDiff(Imgs,BaseNm)
% PairDiff(Imgs,BaseNm)
% Imgs   - Matrix of (even-number of) filenames
% BaseNm - Basename for difference images
%
% Create pairwise difference for a set of images (img2-img1, img4-img3, etc),
% named according to BaseNm (BaseNm_0001, BaseNm_0002, BaseNm_0003, etc).
%______________________________________________________________________
% \$Id: PairDiff.m,v 1.2 2012/02/16 21:36:41 nichols Exp \$

if nargin<1 | isempty(Imgs)
Imgs = spm_select(Inf,'image','Select n*2 images');
end
if nargin<2 | isempty(BaseNm)
BaseNm = spm_input('Enter difference basename','+1','s','Diff');
end
V = spm_vol(Imgs);
n = length(V);
if rem(n,2)~=0
error('Must specify an even number of images')
end

V1 = V(1);
V1  = rmfield(V1,{'fname','descrip','n','private'});
V1.dt = [spm_type('float32') spm_platform('bigend')];

for i=1:n/2
V1.fname = sprintf('%s_%04d.img',BaseNm,i);
V1.descrip = sprintf('Difference %d',i);
Vo(i) = spm_create_vol(V1);
end

%
% Do the differencing
%

fprintf('Creating differenced data ')

for i=1:2:n

img = img2-img1;

spm_write_vol(Vo((i+1)/2),img);

end
```
After I created this I realized that Ged Ridgway also has a similar script, make_diffs.m , that takes two lists of images (baseline, followup) and does the same thing, though with perhaps more intuitive filenames.

## April 01, 2011

### SPM8 Gem 1: Zero NaN's with the zeronan.m script

This was the topic of SPM99 Gem 3, converting NaN’s to zeros. For SPM8, see the following script `zeronan.m` that will zero NaN’s for you.

-Tom

```function ofNm = zeronan(ifNm,val)
% FORMAT ofNm = zeronan(ifNm,val)
% ifNm  - Input filename(s)
% val   - Value to set NaN's to (defaults to zero)
%
% Output:
% ofNm  - Cell array of output filenames.
%
%
% Images have NaN's replaced with zeros, and new images, prefixed with a
% 'z', are created.
%
%________________________________________________________________________
% Based on zeronan.m,v 1.3 2005/10/26 21:58:55 nichols Exp
% Thomas Nichols, 1 April 2011

if nargin<2, val = 0; end
if nargin<1, ifNm = spm_select(Inf,'image','Select images for NaN->0'); end

if ~iscell(ifNm)
ifNm = cellstr(ifNm)';
else
ifNm = ifNm(:)';
end

OtfNm = {};

for fNm = ifNm

fNm = fNm{:};

OfNm = ['z' fNm];
[pth,nm,xt,vol] = spm_fileparts(fNm);
OfNm = fullfile(pth,['z' nm xt]);

% Code snippet from John Ashburner...
VI       = spm_vol(fNm);
VO       = VI;
VO.fname = OfNm;
VO       = spm_create_vol(VO);
for i=1:VI.dim(3),
img      = spm_slice_vol(VI,spm_matrix([0 0 i]),VI.dim(1:2),0);
tmp      = find(isnan(img));
img(tmp) = val;
VO       = spm_write_plane(VO,img,i);
end;

OtfNm = {OtfNm{:} OfNm};

end

if nargout>0
ofNm = OtfNm;
end
```

## June 03, 2010

### SPM5 Gem 6: Corrected cluster size threshold

This is SPM5 version of SPM2 Gem 13.

This is a script that will tell you the corrected cluster size threshold for given cluster-defining threshold: CorrClusTh.m

The usage is pretty self explanatory:

``` Find the corrected cluster size threshold for a given alpha
function [k,Pc] =CorrClusTh(SPM,u,alpha,guess)
SPM   - SPM data structure
u     - Cluster defining threshold
If less than zero, u is taken to be uncorrected P-value
alpha - FWE-corrected level (defaults to 0.05)
guess - Set to NaN to use a Newton-Rhapson search (default)
Or provide a explicit list (e.g. 1:1000) of cluster sizes to
search over.
If guess is a (non-NaN) scalar nothing happens, except the the
corrected P-value of guess is printed.

Finds the corrected cluster size (spatial extent) threshold for a given
cluster defining threshold u and FWE-corrected level alpha.
```

To find the 0.05 (default alpha) corrected cluster size threshold for a 0.01 cluster-defining threshold:

```>> load SPM
>> CorrClusTh(SPM,0.01)
For a cluster-defining threshold of 2.4671 the level 0.05 corrected
cluster size threshold is 7860 and has size (corrected P-value) 0.0499926
```

Notice that, due to the discreteness of cluster sizes you cannot get an exact 0.05 threshold.

The function uses an automated search which may sometimes fail. If you specify a 4th argument you can manually specify the cluster sizes to search over:

```>> CorrClusTh(SPM,0.01,0.05,6000:7000)

WARNING: Within the range of cluster sizes searched (6000...7000)

Try increasing the range or an automatic search.
```

Lastly, you can use it as a look up for a specific cluster size threshold. For example, how much over the 0.05 level would a cluster size of 7859 be?

```>> CorrClusTh(SPM,0.01,0.05,7859)
For a cluster-defining threshold of 2.4671 a cluster size threshold of
7859 has corrected P-value 0.050021
```

Just a pinch!

### SPM5 Gem 5: Unnormalizing a point

This script of Johns will find the corresponding co-ordinate in the un-normalized image: get_orig_coord2.m (same script as for SPM2).

### SPM5 Gem 4: Switching between SPM versions

This function will allow you to switch between different SPM versions. WARNING! As SPM depends on various global (and sometimes, local workspace) variables, this function clears all variables as part of the switch.

The function will need to be put in a directory in your Matlab path that does not contain SPM. spmsel.m

### SPM5 Gem 3: Resizing images

A generalized version of John's reorient script (see Gem2) by Ged Ridgeway, which allows specification of arbitrary voxel dimensions: resize_img.m (this was current as of April 2007; see Ged's script directory for updates.)

### SPM5 Gem 2: Reslicing images

To reslice an image at 1mm cubic voxels, axial orientation, use this reorient.m script (from an email from John dated Mon, 5 Jun 2006 13:02:05 +0100; see also Gem3 and SPM99 Gem7).

### SPM5 Gem 1: Introduction to SPM5 scripting

```Date: Tue, 13 Dec 2005 17:03:13 +0100
From: John Ashburner <john@FIL.ION.UCL.AC.UK>
To: SPM@JISCMAIL.AC.UK
Subject: Re: [SPM] Where can we find some development materials for SPM ?

>    As you know,we usually need to modify the code of SPM to fit our
> problem.but we can not find some relevant development  tutorials. Would you
> please tell me how to learn the framework of SPM step by step ?
>   In addition, I want to know where I can find the details of the SPM
> structure.

It may be easiest to learn by example.  If you want to develop a new
user-interface for SPM5, then you would create a file called spm_config_*.m,
similar to the other spm_config.m files (if you strip out the documentation
parts, you will see that these are actually quite small).  Your spm_config*
file can then be added to the toolbox subdirectory and accessed through the
TOOLS pulldown.

The help button allows you to navigate through the documentation of each of
the Matlab functions, which you may find useful.

For reading and writing images, you would use these functions.
spm_vol
spm_slice_vol
spm_sample_vol

spm_create_vol
spm_write_plane
spm_write_vol

spm_get_space

There is Matlab help on all these functions.  Alternatively, you could use the
NIFTI routines directly.  There is no documentation on this, but here are a
few examples of how you can use them:
======================================

% Example of creating a simulated .nii file.
dat            = file_array;
dat.fname = 'junk.nii';
dat.dim     = [64 64 32];
dat.dtype  = 'FLOAT64-BE';
dat.offset  = ceil(348/8)*8;

% alternatively:
% dat = file_array( 'junk.nii',dim,dtype,off,scale,inter)

disp(dat)

% Create an empty NIFTI structure
N = nifti;

fieldnames(N) % Dump fieldnames

% Creating all the NIFTI header stuff
N.dat = dat;
N.mat = [2 0 0 -110 ; 0 2 0 -110; 0 0 -2 92; 0 0 0 1];
N.mat_intent = 'xxx'
N.mat_intent = 'Scanner';
N.mat0 = N.mat;
N.mat0_intent = 'Aligned';

N.diminfo.slice = 3;
N.diminfo.phase = 2;
N.diminfo.frequency = 2;
N.diminfo.slice_time.code='xxx';
N.diminfo.slice_time.code = 'sequential_increasing';
N.diminfo.slice_time.start = 1;
N.diminfo.slice_time.end = 32;
N.diminfo.slice_time.duration = 3/32;

N.intent.code='xxx' ; % dump possibilities
N.intent.code='FTEST'; % or N.intent.code=4;
N.intent.param = [4 8];

N.timing.toffset = 28800;
N.timing.tspace=3;
N.descrip = 'This is a NIFTI-1 file';
N.aux_file='aux-file-name.txt';
N.cal = [0 1];

create(N); % Writes hdr info

dat(:,:,:)=0;

[i,j,k] = ndgrid(1:64,1:64,1:32);
dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 30^2))=1;
dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 15^2))=2;

% displaying a slice
imagesc(dat(:,:,12));colorbar

% get a handle to 'junk.nii';
M=nifti('junk.nii');

imagesc(M.dat(:,:,12));
======================================

Best regards,
-John```

### SPM2 Gem 13: Corrected cluster size threshold

This is a script that will tell you the corrected cluster size threshold for given cluster-defining threshold: corrclusth.m

The usage is pretty self explanatory:

``` Find the corrected cluster size threshold for a given alpha
function [k,Pc] =CorrClusTh(SPM,u,alpha,guess)
SPM   - SPM data structure
u     - Cluster defining threshold
If less than zero, u is taken to be uncorrected P-value
alpha - FWE-corrected level (defaults to 0.05)
guess - Set to NaN to use a Newton-Rhapson search (default)
Or provide a explicit list (e.g. 1:1000) of cluster sizes to
search over.
If guess is a (non-NaN) scalar nothing happens, except the the
corrected P-value of guess is printed.

Finds the corrected cluster size (spatial extent) threshold for a given
cluster defining threshold u and FWE-corrected level alpha.
```

To find the 0.05 (default alpha) corrected cluster size threshold for a 0.01 cluster-defining threshold:

```>> load SPM
>> CorrClusTh(SPM,0.01)
For a cluster-defining threshold of 2.4671 the level 0.05 corrected
cluster size threshold is 7860 and has size (corrected P-value) 0.0499926
```

Notice that, due to the discreteness of cluster sizes you cannot get an exact 0.05 threshold.

The function uses an automated search which may sometimes fail. If you specify a 4th argument you can manually specify the cluster sizes to search over:

```>> CorrClusTh(SPM,0.01,0.05,6000:7000)

WARNING: Within the range of cluster sizes searched (6000...7000)

Try increasing the range or an automatic search.
```

Lastly, you can use it as a look up for a specific cluster size threshold. For example, how much over the 0.05 level would a cluster size of 7859 be?

```>> CorrClusTh(SPM,0.01,0.05,7859)
For a cluster-defining threshold of 2.4671 a cluster size threshold of
7859 has corrected P-value 0.050021
```

Just a pinch!

### SPM2 Gem 12: fMRI Analysis threshold

This is an update of Gem12 for SPM99, originally by Stefan Kiebel.

```> Is it possible to instruct spm99 to search all voxels within a given
> mask image rather than all above a fixed or a %mean threshold?

Yes, with SPM2 it's possible to use several masking options.

To recap, there are 3 sorts of masks used in SPM2:
1. an analysis threshold

1: One can set this threshold for each image to -Inf to switch off this
threshold.
2: If the image allows this, NaN at a voxel position masks this voxel
from the statistics, otherwise the mask value is zero (and the user
can choose, whether implicit masking should be used at all).
3: Use mask image file(s), where NaN (when image format allows this) or
a non-positive value masks a voxel.

On top of this, SPM automatically removes any voxels with constant
values over time.

So what you want is an analysis, where one only applies an explicit

In SPM2 for PET, you can do this by going for the Full Monty and
choosing -Inf for the implicit mask and no 0-thresholding. Specify one
or more mask images. (You could also define a new model structure,
controlling the way SPM for PET asks questions).

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:

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:

3. Finally, save by
save SPM SPM

```

## Tags

• Hi This doesn't really address the issue at hand (powerpoint to html), but an alternative and very e… by Rose on this entry
• @Michael. You are a SAINT. BLESS. by emma riley on this entry
• I look this up every couple of years, and always struggle with it, so here are some notes for improv… by johann beda on this entry
• I love this quote: "Complete reporting of results, i.e. filing of statistical maps in public reposit… by Kevin Black on this entry
• Taylor: I've just quickly scanned the BrainVoyager documentation, and it appears that the Cluster–Le… by Thomas Nichols on this entry