# cosmo alignΒΆ

```function [map_x2y, map_y2x]=cosmo_align(x,y)
% find permutation so that values in two inputs are matched
%
% [map_x2y, map_y2x]=cosmo_align(x,y)
%
% Inputs:
%   x               } both x and y must be a cell with K elements, each
%   y               } being a vector or a cellstring with the same number
%                     of elements (say N). Alternatively it can
%                     be a single vector  or cellstrings v, which is
%                     interpreted as {v}.
%
% Outputs:
%   map_x2y           a vector with N elements, so that for all values I in
%                     1:K it holds that map_x2y(x{I}) is equal to y{I}.
%   map_y2x           a vector with N elements, so that for all values I in
%                     1:K it holds that map_y2x(y{I}) is equal to x{I}.
%
% #   see the COPYING file distributed with CoSMoMVPA.           #

[x_cell,x_label]=as_cell(x,1);
[y_cell,y_label]=as_cell(y,2);

ensure_matching_labels(x_label, y_label);

nx=numel(x_cell);
ny=numel(y_cell);

if nx~=ny
error(['number of elements in each cell is not equal; first '...
'input has %d elements, second input has %d'],...
nx,ny);
end

[xi,xv]=cosmo_index_unique(x_cell);
[yi,yv]=cosmo_index_unique(y_cell);

if ~cosmo_isequaln(xv,yv)
error(['the two inputs do not have the same unique '...
'combination of elements']);
end

nxi=cellfun(@numel,xi);
nyi=cellfun(@numel,yi);

if ~isequal(nxi,nyi)
error(['the two inputs do have matching elements '...
'but their number of occurences is not matched']);
elseif any(cellfun(@numel,xi)>1)
error('combinations of elements are non-unique');
end

xv=cat(1,xi{:});
yv=cat(1,yi{:});

n=numel(xi);
map_x2y=zeros(1,n);
map_x2y(yv)=xv;

map_y2x=zeros(1,n);
map_y2x(xv)=yv;

function [v_cell,labels]=as_cell(v,pos)
if iscell(v) && ~iscellstr(v)
n=numel(v);

for j=1:n
ensure_vector(v{j},pos,j);
end
v_cell=v;
labels=[];
elseif isstruct(v)
labels=sort(fieldnames(v));
n=numel(labels);

v_cell=cell(n,1);
for k=1:n
label=labels{k};
v_value=v.(label);
ensure_vector(v_value,pos,label);
v_cell{k}=v_value;
end
else
ensure_vector(v,pos,1);
v_cell={v(:)};
labels=[];
end

function ensure_vector(v,pos,i)
if ~isvector(v)
msg='only input with vectors is supported';
elseif ~(isnumeric(v) || iscellstr(v))
msg=['only inputs with numeric vectors or cellstrings '...
'are supported'];
else
% all fine
return
end

if ischar(i)
elem_str=['field ' i];
else
elem_str=sprintf('element %d', i);
end

% throw error
error('input %d, %s: %s',pos,elem_str,msg);

function ensure_matching_labels(x_label, y_label)
if ~isequal(x_label, y_label)
if iscellstr(x_label) && iscellstr(y_label)
error(['field name mismatch between two inputs: '...
'[%s] ~= [%s]'],...
cosmo_strjoin(x_label),cosmo_strjoin(y_label));
else
error(['either both inputs must be cells or vectors, ',...
'or both must be structs']);
end
end
```