test cosmo fmri dataset

function test_suite = test_cosmo_fmri_dataset
    % tests for cosmo_fmri_dataset
    %
    % #   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_init()
    ds = cosmo_synthetic_dataset();

    assertTrue(numel(setxor(fieldnames(ds), ...
                            {'samples', 'a', 'sa', 'fa'})) == 0);

function test_nifti()
    ni = generate_test_nifti_struct();
    g = cosmo_synthetic_dataset('size', 'normal');

    tmpfn = '__tmp1_.nii';
    cleaner = onCleanup(@()delete(tmpfn));
    save_nii(ni, tmpfn);
    ds = cosmo_fmri_dataset(tmpfn, 'targets', g.sa.targets, ...
                            'chunks', g.sa.chunks);

    assertTrue(numel(setxor(fieldnames(ds), ...
                            fieldnames(g))) == 0);

    assertElementsAlmostEqual(ds.samples, g.samples, 'relative', 1e-6);
    assertEqual(ds.sa.targets, g.sa.targets);
    assertEqual(ds.sa.chunks, g.sa.chunks);

function test_io()
    ds = cosmo_synthetic_dataset('size', 'normal');
    tmpfn = '__tmp2_.nii';
    cleaner = onCleanup(@()delete(tmpfn));

    cosmo_map2fmri(ds, tmpfn);

    es = cosmo_fmri_dataset(tmpfn);
    assertElementsAlmostEqual(ds.samples, es.samples, 'relative', 1e-6);
    assertEqual(ds.a.fdim, es.a.fdim);

function ni = generate_test_nifti_struct()
    % Generates a struct that behaves like a NIFTI struct
    ni = struct();

    ds = cosmo_synthetic_dataset('size', 'normal');
    ni.img = shiftdim(cosmo_unflatten(ds), 1);

    hdr = struct();

    dime = struct();
    dime.datatype = 16; % single
    dime.dim = [4 3 2 5 6 1 1 1];
    dime.pixdim = [0 2 2 2 0 0 0 0];
    fns = {'intent_p1', 'intent_p2', 'intent_p3', 'intent_code', ...
           'slice_start', 'slice_duration', 'slice_end', ...
           'scl_slope', 'scl_inter', 'slice_code', 'cal_max', ...
           'cal_min', 'toffset'};

    dime = nifti_helper_set_all(dime, fns);
    dime.xyzt_units = 10;
    hdr.dime = dime;

    hk = struct();
    hk.sizeof_hdr = 348;
    hk.data_type = '';
    hk.db_name = '';
    hk.extents = 0;
    hk.session_error = 0;
    hk.regular = 'r';
    hk.dim_info = 0;
    hdr.hk = hk;

    hist = struct();
    hist.sform_code = 1;
    hist.originator = [2 1 3 3];
    hist = nifti_helper_set_all(hist, {'descrip', 'aux_file'}, '');
    hist = nifti_helper_set_all(hist, {'qform_code', 'quatern_b', ...
                                       'quatern_d', ...
                                       'qoffset_x', 'qoffset_y', 'qoffset_z'});
    hist = nifti_helper_set_all(hist, {'intent_name'}, '');

    hist.srow_x = [2 0 0 -1];
    hist.srow_y = [0 2 0 -1];
    hist.srow_z = [0 0 2 -1];

    hist.quatern_c = 0;
    hdr.hist = hist;

    ni.hdr = hdr;

function s = nifti_helper_set_all(s, fns, v)
    % sets all fields in fns in struct s to v
    % if v is omitted it is set to 0.
    if nargin < 3
        v = 0;
    end
    n = numel(fns);
    for k = 1:n
        fn = fns{k};
        s.(fn) = v;
    end