function ds=cosmo_fmri_reorient(ds, new_orient)
% Change the orientation of an fmri dataset
%
% ds_reorient=cosmo_fmri_reorient(ds, new_orient)
%
% Inputs
% ds fmri-dataset
% new_orient new orientation for the dataset (see below for a
% full list)
%
% Example:
% ds=cosmo_synthetic_dataset();
% cosmo_disp(ds.a);
% %|| .fdim
% %|| .labels
% %|| { 'i' 'j' 'k' }
% %|| .values
% %|| { [ 1 2 3 ] [ 1 2 ] [ 1 ] }
% %|| .vol
% %|| .mat
% %|| [ 2 0 0 -3
% %|| 0 2 0 -3
% %|| 0 0 2 -3
% %|| 0 0 0 1 ]
% %|| .dim
% %|| [ 3 2 1 ]
% %|| .xform
% %|| 'scanner_anat'
% cosmo_disp(ds.fa);
% %|| .i
% %|| [ 1 2 3 1 2 3 ]
% %|| .j
% %|| [ 1 1 1 2 2 2 ]
% %|| .k
% %|| [ 1 1 1 1 1 1 ]
% ds_reorient=cosmo_fmri_reorient(ds,'AIR');
% cosmo_disp(ds_reorient.a);
% %|| .fdim
% %|| .labels
% %|| { 'i' 'j' 'k' }
% %|| .values
% %|| { [ 1 2 ] [ 1 ] [ 1 2 3 ] }
% %|| .vol
% %|| .mat
% %|| [ 0 0 -2 5
% %|| -2 0 0 3
% %|| 0 2 0 -3
% %|| 0 0 0 1 ]
% %|| .dim
% %|| [ 2 1 3 ]
% %|| .xform
% %|| 'scanner_anat'
% cosmo_disp(ds_reorient.fa);
% %|| .i
% %|| [ 1 2 1 2 1 2 ]
% %|| .j
% %|| [ 1 1 1 1 1 1 ]
% %|| .k
% %|| [ 1 1 2 2 3 3 ]
%
% % Many orientations are invalid, for example
% ds=cosmo_synthetic_dataset();
% cosmo_reorient(ds,'ALR');
% error('illegal orientation');
%
% Notes:
% - there are 3!*3^2 valid orientations, these are:
% 'SAR' 'SAL' 'SPR' 'SPL' 'IAR' 'IAL' 'IPR' 'IPL'
% 'SRA' 'SLA' 'SRP' 'SLP' 'IRA' 'ILA' 'IRP' 'ILP'
% 'ASR' 'ASL' 'PSR' 'PSL' 'AIR' 'AIL' 'PIR' 'PIL'
% 'ARS' 'ALS' 'PRS' 'PLS' 'ARI' 'ALI' 'PRI' 'PLI'
% 'RAS' 'LAS' 'RPS' 'LPS' 'RAI' 'LAI' 'RPI' 'LPI'
% 'RSA' 'LSA' 'RSP' 'LSP' 'RIA' 'LIA' 'RIP' 'LIP'
% For example, 'LPI' (used in Talairach/MNI) means that
% * the first dimension goes from left to right
% * the second dimension goes from posterior to anterior
% * the third dimension goes from inferior to superior
% - this function chances the orientation information by adjusting
% information in .fa and .a.fdim; contents of .samples remains
% unchanged.
%
% # For CoSMoMVPA's copyright information and license terms, #
% # see the COPYING file distributed with CoSMoMVPA. #
cosmo_check_dataset(ds,'fmri');
ds_orient=cosmo_fmri_orientation(ds);
upper_new_orient=upper(new_orient);
[perm, flip]=get_transform(ds_orient,upper_new_orient);
fmri_dim_labels={'i','j','k'};
ds_fa=ds.fa;
% initialize output
fa=ds_fa;
mat=zeros(4);
mat(4,4)=1;
dim_size=zeros(1,3);
dim_values=cell(3,1);
for dim=1:3
dim_label=fmri_dim_labels{perm(dim)};
v=ds_fa.(dim_label);
[unused,idx,unused,dim_name,values]=cosmo_dim_find(ds,dim_label);
nvalues=max(values);
if flip(dim)
v=nvalues+1-v;
mat(perm(dim),4)=nvalues+1;
mat(perm(dim),dim)=-1;
else
mat(perm(dim),dim)=1;
end
dim_size((dim))=nvalues;
new_dim_label=fmri_dim_labels{(dim)};
fa.(new_dim_label)=v;
dim_values{dim}=1:nvalues;
end
ds.a.fdim.values=dim_values;
ds.a.vol.mat=ds.a.vol.mat*(mat);
ds.a.vol.dim=dim_size;
ds.fa=fa;
ind=sub2ind(dim_size,ds.fa.i, ds.fa.j, ds.fa.k);
[foo,i]=sort(ind);
ds=cosmo_slice(ds,i,2,false);
assert(isequal(cosmo_fmri_orientation(ds),upper_new_orient));
function [perm, flip]=get_transform(src, trg)
is_valid=true;
labs=['LR';'PA';'IS'];
perm=zeros(1,3);
flip=false(1,3);
for dim=1:3
[src_i,src_j]=find(src(dim)==labs);
[trg_i,trg_j]=find(bsxfun(@eq,trg',labs(src_i,:)));
if numel(trg_i)~=1
is_valid=false;
break;
end
perm(trg_i)=dim;
flip(trg_i)=src_j~=trg_j;
end
if ~isequal(sort(perm),1:3)
is_valid=false;
end
if ~is_valid
error(['illegal target orientation; run\n'...
' help %s\nto see a list of valid orientations'],...
mfilename());
end