function [worldmat spmvoxmat fslvoxmat] = flirtmat2worldmat(flirtmat, src, trg) %flirtmat2worldmat: convert saved flirt matrix to NIfTI world coords matrix % flirt matrix is from text file specified in "flirt -omat mat.txt" command % world matrix maps from NIfTI world coordinates in target to source. Note: % mat.txt contains a mapping from source to target in FSL's *scaled* coords % which are not NIfTI world coordinates, and note src-trg directionality! % worldmat from this script reproduces "img2imgcoord -mm ...". % % The script can also return a matrix to map from target to source voxels % in MATLAB/SPM's one-based convention, or in FSL's zero-based convention % % Example: % [worldmat spmvoxmat fslvoxmat] = flirtmat2worldmat(flirtmat, src, trg); % % See also: worldmat2flirtmat, flirtmat_read, flirtmat_write % Copyright 2009 Ged Ridgway if ischar(src) src = nifti(src); end if ischar(trg) trg = nifti(trg); end if ischar(flirtmat) flirtmat = flirtmat_read(flirtmat); end % src = inv(flirtmat) * trg % srcvox = src.mat \ inv(flirtmat) * trg.mat * trgvox % BUT, flirt doesn't use src.mat, only absolute values of the % scaling elements from it, % AND, if images are not radiological, the x-axis is flipped, see: % https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind0810&L=FSL&P=185638 % https://www.jiscmail.ac.uk/cgi-bin/webadmin?A2=ind0903&L=FSL&P=R93775 trgscl = nifti2scl(trg); srcscl = nifti2scl(src); fslvoxmat = inv(srcscl) * inv(flirtmat) * trgscl; % AND, Flirt's voxels are zero-based, while SPM's are one-based... addone = eye(4); addone(:, 4) = 1; spmvoxmat = addone * fslvoxmat * inv(addone); worldmat = src.mat * spmvoxmat * inv(trg.mat); %% function scl = nifti2scl(N) % not sure if this is always correct with rotations in mat, but seems okay! scl = diag([sqrt(sum(N.mat(1:3,1:3).^2)) 1]); if det(N.mat) > 0 % neurological, x-axis is flipped, such that [3 2 1 0] and [0 1 2 3] % have the same *scaled* coordinates: xflip = diag([-1 1 1 1]); xflip(1, 4) = N.dat.dim(1)-1; % reflect about centre scl = scl * xflip; end