function test_suite = test_fmri_orientation
% tests for cosmo_fmri_orientation
%
% # For CoSMoMVPA's copyright information and license terms, #
% # see the COPYING file distributed with CoSMoMVPA. #
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
test_functions=localfunctions();
catch % no problem; early Matlab versions can use initTestSuite fine
end
initTestSuite;
function test_orientation()
% make dataset
ds=cosmo_synthetic_dataset('size','big');
ds=cosmo_slice(ds,1);
ds.a.vol.mat(1:3,4)=ds.a.vol.mat(1:3,4)-20;
orig_orient=cosmo_fmri_orientation(ds);
assertEqual(orig_orient,'LPI');
% get all orientation and
orients=get_orients();
norient=numel(orients);
fmts={'nii'};
nfmt=numel(fmts);
nperm=nfmt*norient;
ntest=5;
rp=randperm(nperm);
ncoord=10;
for k=1:ntest
p=rp(k);
orient_idx=ceil(p/nfmt);
fmt_idx=mod(k-1,nfmt)+1;
orient=orients{orient_idx};
fmt=fmts{fmt_idx};
ijk=ceil(bsxfun(@times,rand(4,ncoord),[ds.a.vol.dim(:);1]));
orient_idx=get_feature_index(ds,ijk);
xyz=ds.a.vol.mat*ijk;
% verify equality with re-oriented dataset
ds_ro=cosmo_fmri_reorient(ds,orient); % using CoSMoMVPA
assertEqual(cosmo_fmri_orientation(ds_ro),orient);
assertEqual(cosmo_fmri_orientation(ds_ro.a.vol.mat),orient);
ijk_ro=ds_ro.a.vol.mat\xyz;
idx_ro=get_feature_index(ds_ro,ijk_ro);
assertElementsAlmostEqual(ds.samples(:,orient_idx),...
ds_ro.samples(:,idx_ro),...
'absolute',1e-5);
% verify that going back works fine
ds2=cosmo_fmri_reorient(ds_ro,orig_orient);
assertEqual(ds,ds2);
% check mapping to and from fmri dataset
img=cosmo_map2fmri(ds, ['-' fmt]);
ds3=cosmo_fmri_dataset(img);
assertEqual(ds.a,ds3.a);
end
function test_fmri_orientation_exceptions()
aet=@(varargin)assertExceptionThrown(@()...
cosmo_fmri_orientation(varargin{:}),'');
aet([1 2 3]);
aet({})
aet(zeros(4));
function test_fmri_reorient_exceptions()
aet=@(varargin)assertExceptionThrown(@()...
cosmo_fmri_reorient(varargin{:}),'');
ds=cosmo_synthetic_dataset();
aet(ds,' RAI');
aet(ds,' RAA');
function test_fmri_orientation_with_afni_binary()
if cosmo_skip_test_if_no_external('afni_bin')
return
end
ds=cosmo_synthetic_dataset('size','big');
fmt='.nii';
orients=get_orients();
i=ceil(rand()*numel(orients));
orient=orients{i};
nfeatures=size(ds.samples,2);
xyz=cosmo_vol_coordinates(ds);
ds_rs=afni_resample(ds,fmt,orient); % in AFNI
assertEqual(cosmo_fmri_orientation(ds_rs),orient);
xyz_rs=cosmo_vol_coordinates(ds_rs);
xyz_cell=mat2cell(xyz,[1 1 1],nfeatures);
xyz_rs_cell=mat2cell(xyz_rs,[1 1 1],nfeatures);
mp=cosmo_align(xyz_cell,xyz_rs_cell);
assertElementsAlmostEqual(ds.samples(:,mp),ds_rs.samples,...
'absolute',1e-5)
function idxs=get_feature_index(ds, ijk)
n=size(ijk,2);
idxs=zeros(1,n);
i=ds.fa.i;
j=ds.fa.j;
k=ds.fa.k;
for m=1:n
msk=i==ijk(1,m) & j==ijk(2,m) & k==ijk(3,m);
idx=find(msk);
assert(numel(idx)==1);
idxs(m)=idx;
end
function orients=get_orients()
% get all 48 possible orientations
order=perms(1:3);
signs=[1 0 1 0 1 0 1 0;
1 1 0 0 1 1 0 0;
1 1 1 1 0 0 0 0];
labs=['LR';'PA';'IS'];
orients=cell(48,1);
for k=1:6
for j=1:8
orient=' ';
for dim=1:3
row=order(k,dim);
orient(dim)=(labs(row,signs(row,j)+1));
end
orients{(k-1)*8+j}=orient;
end
end
function [success,output]=run_afni_command(cmd,raise)
if nargin<2
raise=false;
end
dyld_path=getenv('DYLD_LIBRARY_PATH');
cleaner=onCleanup(@()setenv('DYLD_LIBRARY_PATH',dyld_path));
setenv('DYLD_LIBRARY_PATH','/usr/local/bin');
dyld_fb_path=getenv('DYLD_FALLBACK_LIBRARY_PATH');
cleaner2=onCleanup(@()setenv('DYLD_FALLBACK_LIBRARY_PATH',...
dyld_fb_path));
setenv('DYLD_FALLBACK_LIBRARY_PATH',...
[getenv('DYLD_FALLBACK_LIBRARY_PATH') ':/sw/lib']);
[s,output]=unix(cmd);
success=s==0;
if ~success && raise
error(output);
end
function ds_rs=afni_resample(ds,fmt,orient)
tmp_pat=['tmp_%d' fmt];
[fn_orig,cleaner]=get_temp_filename(tmp_pat);
cosmo_map2fmri(ds,fn_orig);
[fn_rs, cleaner2]=get_temp_filename(tmp_pat);
% create command
cmd=sprintf('3dresample -rmode NN -prefix %s -inset %s -orient %s',...
fn_rs, fn_orig, orient);
[success,output]=run_afni_command(cmd);
if ~success
error(output);
end
ds_rs=cosmo_fmri_dataset(fn_rs);
function temp_path=get_temp_path()
c=cosmo_config();
if ~isfield(c,'temp_path')
error('temp_path is not set in cosmo_config');
end
temp_path=c.temp_path;
function [fn, cleaner]=get_temp_filename(pat)
temp_path=get_temp_path();
k=0;
while true
fn=fullfile(temp_path,sprintf(pat,k));
if ~exist(fn,'file')
cleaner=onCleanup(@()delete(fn));
return;
end
k=k+1;
end