function test_suite = test_align
% tests for cosmo_align
%
% # 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_align_basics
x = cosmo_synthetic_dataset('type', 'meeg', 'size', 'big');
y = cosmo_slice(x, x.fa.chan <= 6, 2);
orig_ds = cosmo_dim_transpose(y, 'time');
[nsamples, nfeatures] = size(orig_ds.samples);
ds1 = cosmo_slice(orig_ds, randperm(nsamples));
ds2 = cosmo_slice(orig_ds, randperm(nsamples));
[mp, pm] = cosmo_align({ds1.sa.targets, ds1.sa.chunks, ds1.sa.time}, ...
{ds2.sa.targets, ds2.sa.chunks, ds2.sa.time});
assertEqual(cosmo_slice(ds1, mp), ds2);
assertEqual(cosmo_slice(ds2, pm), ds1);
[mp, pm] = cosmo_align([2 3 4], [4 2 3]);
assertEqual(mp, [3 1 2]);
assertEqual(pm, [2 3 1]);
[mp, pm] = cosmo_align({{'b', 'c', 'c'}, [3 2 3]}, ...
{{'c', 'b', 'c'}, [3 3 2]});
assertEqual(mp, [3 1 2]);
assertEqual(pm, [2 3 1]);
% test structs
p = struct();
p.x = {'b', 'c', 'c'};
p.y = [3 2 3];
q = struct();
q.y = [3 3 2];
q.x = {'c', 'b', 'c'};
[mp, pm] = cosmo_align(p, q);
assertEqual(mp, [3 1 2]);
assertEqual(pm, [2 3 1]);
% test NaN
[mp, pm] = cosmo_align([2 NaN 4], [4 2 NaN]);
assertEqual(mp, [3 1 2]);
assertEqual(pm, [2 3 1]);
% test exceptions
ds_small = cosmo_slice(ds1, 1:nsamples - 1);
aet = @(varargin)assertExceptionThrown(@() ...
cosmo_align(varargin{:}), '');
aet(ds1, ds2);
aet([2 3 4 3], [4 2 3 4]);
aet([2 3 4 3], [4 2 3 4]);
aet([2 3 4 3], [4 2 3]);
aet([2 3 4], {[2, 3, 4], [2, 3, 4]});
aet([2 3 NaN NaN], [2 3 NaN Inf]);
aet([2 NaN 3], [4 2 NaN]);
aet(struct, struct('a', 1));
aet(struct('a', 1), 1);
aet({'b', 'c', 'd', 'd'}, {'d', 'b', 'c', 'd'});
function test_align_multiple_nans
n_rows_half = 20 + ceil(rand() * 20);
x = ceil(rand(n_rows_half * 2, 2) * sqrt(n_rows_half));
rp = randperm(2 * n_rows_half);
rp1 = rp(1:n_rows_half);
rp2 = rp(n_rows_half + (1:n_rows_half));
% half of the rows become NaN
x(rp1, 1) = NaN;
x(rp1, 2) = 1:n_rows_half;
x(rp2, 1) = 1:n_rows_half;
x(rp2, 2) = 1:n_rows_half;
rp2 = randperm(n_rows_half * 2);
y = x(rp2, :);
assertExceptionThrown(@()cosmo_align( ...
{x(:, 1), x(:, 2)}, {y(:, 1), y(:, 2)}), '');