function [orient, cano_rot] = cosmo_fmri_orientation(ds)
% get orientation of a dataset
%
% [orient,cano_rot]=cosmo_fmri_orientation(ds)
%
% Inputs:
% ds fmri dataset struct;
%
% Output:
% orient three letter string indicating the orientation of this
% dataset
% cano_rot canonical rotation matrix (relative to LPI)
%
% Example:
% ds=cosmo_synthetic_dataset();
% [orient,cano_rot]=cosmo_fmri_orientation(ds);
% disp(orient)
% %|| LPI
% disp(cano_rot)
% %|| 1 0 0 0
% %|| 0 1 0 0
% %|| 0 0 1 0
% %|| 0 0 0 1
%
% 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
%
% # For CoSMoMVPA's copyright information and license terms, #
% # see the COPYING file distributed with CoSMoMVPA. #
mx = get_affine_matrix(ds);
rot_orig = mx(1:3, 1:3);
% normalize the rows
rot_row_norms = sqrt(sum(rot_orig.^2, 2));
rot = bsxfun(@rdivide, rot_orig, rot_row_norms);
cano_rot = get_canonical_matrix(rot);
orient = get_orientation(cano_rot);
function cano_rot = get_canonical_matrix(rot)
% find the three major axes of the rotation matrix
visited = false(3);
cano_rot = zeros(4);
cano_rot(4, 4) = 1;
for dim = 1:3
max_v = 0;
for row = 1:3
for col = 1:3
v = abs(rot(row, col));
if ~visited(row, col) && v > max_v
max_row = row;
max_col = col;
max_v = v;
end
end
end
if max_v == 0
error('Illegal matrix');
end
visited(max_row, :) = true;
visited(:, max_col) = true;
cano_rot(max_row, max_col) = sign(rot(max_row, max_col));
end
assert(all(visited(:)));
assert(all(sum(cano_rot ~= 0, 1) == 1));
assert(all(sum(cano_rot ~= 0, 2) == 1));
function orient = get_orientation(cano_rot)
labs = ['LR'; 'PA'; 'IS'];
orient = ' ';
for k = 1:3
col = find(cano_rot(1:3, k) ~= 0);
assert(numel(col) == 1);
v = cano_rot(col, k);
orient(k) = labs(col, 1 + (v < 0));
end
function mx = get_affine_matrix(ds)
if cosmo_isfield(ds, 'a.vol.mat')
mx = ds.a.vol.mat;
elseif isnumeric(ds) && size(ds, 1) >= 3 && size(ds, 2) >= 3
mx = ds;
else
error('cannot find affine transformation matrix');
end