function download_algorithms(simulate_no_download)
% Downloads and compiles/preps different external codes needed for RIGOR
%
% @authors:     Ahmad Humayun
% @contact:     ahumayun@cc.gatech.edu
% @affiliation: Georgia Institute of Technology
% @date:        Fall 2013 - Summer 2014

clc

% if you don't want to download the files (for testing this script)
if ~exist('simulate_no_download', 'var')
    simulate_no_download = false;
end
no_download_dir = 'pre_downloaded';

fprintf(2, '---------------------------------------------------------------------------\n                              Download Notice                              \n---------------------------------------------------------------------------\nBy running this script, you accept all licensing agreements accompanied\nwith the 3rd party softwares that will now be downloaded and used later in\nour scripts.\n\nPress ''y'' to accept (any other key to stop the script): ');
user_inp = input('','s');
if isempty(user_inp) || ~strncmpi(user_inp(1), 'y', 1)
    return;
end

% destination algorithms directory
curr_dir = pwd;
code_root_dir = fullfile(fileparts(which(mfilename)), '..');
extern_src_rel = 'extern_src';
algos_dir = fullfile(code_root_dir, extern_src_rel);
dont_delete = {'DataHash', 'extra_gb_code', 'para_pseudoflow', 'fuxin_lib_src', 'stein_boundaryprocessing'};
if exist(algos_dir,'dir')
    % only delete the dir/files not in dont_delete
    d = dir(algos_dir);
    for idx = 1:length(d)
        if strcmp(d(idx).name,'.') || strcmp(d(idx).name,'..')
            continue;
        end
        if ~any(strcmp(d(idx).name, dont_delete))
            if d(idx).isdir
                rmdir(fullfile(algos_dir,d(idx).name), 's');
            else
                delete(fullfile(algos_dir,d(idx).name));
            end
        end
    end
else
    mkdir(algos_dir);
end

% create temp download directory
if ~simulate_no_download
    temp_dir = fullfile(code_root_dir, sprintf('temp%d', randi(1e8)));
    mkdir(temp_dir);
else
    temp_dir = no_download_dir;
end

try
    % Point Fuxin library to the right directory
    fuxin_lib_rel = fullfile(extern_src_rel, 'fuxin_lib_src');
    replaceInTextFile(fullfile(code_root_dir, 'internal_params.m'), '''/home/ahumayun/videovolumes/fuxin_lib_src''', ['fullfile(fp.code_root_dir, ''', fuxin_lib_rel, ''')'], true);
    classregtree_dir = fullfile(fuxin_lib_rel, '@classregtree_fuxin', 'private');
    fprintf(1, 'mex''ing fuxin library code\n');
    eval(sprintf('mex -O %s/regtreeEval.cpp -output %s/regtreeEval', classregtree_dir, classregtree_dir));
    eval(sprintf('mex -O %s/regtree_findbestsplit.cpp -output %s/regtree_findbestsplit', classregtree_dir, classregtree_dir));
    fprintf(1, 'Done mex''ing\n');

    % move stein boundary processing code to the segmentation folder
    mkdir(fullfile(algos_dir, 'segmentation'));
    copyfile(fullfile(algos_dir, 'stein_boundaryprocessing'), fullfile(algos_dir, 'segmentation', 'stein_boundaryprocessing'));

    % download Leordeanu''s GB code
    success = download_code('http://109.101.234.42/documente/code/doc_8.zip', ...
        fullfile(temp_dir, 'doc_8.zip'), 'Leordeanu''s GB flow code', simulate_no_download);

    if success
        mkdir(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb'));
        unzip(fullfile(temp_dir, 'doc_8.zip'), fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb'));
        movefile(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb', 'Gb_Code_Oct2012', '*'), fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb'));
        rmdir(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb', 'Gb_Code_Oct2012'), 's');
        replaceInTextFile(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb', 'Gb_data_lambda.m'), 'gb\(f\) = T/2 \+ sqrt\(\(T \.\^ 2 \) /4 \- D\);', 'gb(f) = T(f)/2 + sqrt((T(f) .^ 2 ) /4 - D(f));');
        replaceInTextFile(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb', 'Gb_data_lambda.m'), 'or_C\(f, 1\) = -Ms\(:, 2\);', 'or_C(f, 1) = -Ms(f, 2);');
        replaceInTextFile(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb', 'Gb_data_lambda.m'), 'or_C\(f, 2\) = gb\(:\) - Ms\(:, 1\);', 'or_C(f, 2) = gb(f) - Ms(f, 1);');
        adjustAttributes(fullfile(algos_dir, 'segmentation', 'boundaries--leordeanu_ECCV_2012_gb'));
    end

    % download Joseph Lim's SketchTokens code
    success = download_code('https://github.com/joelimlimit/SketchTokens/archive/master.zip', ...
        fullfile(temp_dir, 'master.zip'), 'Joseph Lim''s SketchTokens code', simulate_no_download);
    success = success & download_code('http://people.csail.mit.edu/lim/lzd_cvpr2013/st_data.tgz', ...
        fullfile(temp_dir, 'st_data.tgz'), 'Joseph Lim''s SketchTokens data', simulate_no_download);

    if success
        mkdir(fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens'));
        unzip(fullfile(temp_dir, 'master.zip'), fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens'));
        untar(fullfile(temp_dir, 'st_data.tgz'), fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens'));
        rmdir(fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens', 'SketchTokens-master', 'models'), 's');
        movefile(fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens', 'models'), fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens', 'SketchTokens-master'));
        movefile(fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens', 'SketchTokens-master', '*'), fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens'));
        rmdir(fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens', 'SketchTokens-master'), 's');
        cd(fullfile(algos_dir, 'segmentation', 'boundaries--lim_CVPR_2013_sketchtokens'));
        mex stDetectMex.cpp 'OPTIMFLAGS="$OPTIMFLAGS' '/openmp"'
        fprintf(1, 'Done mex''ing\n');
        cd(curr_dir);
    end

    % download Piotr's toolbox code
    success = download_code('http://vision.ucsd.edu/~pdollar/toolbox/piotr_toolbox.zip', ...
        fullfile(temp_dir, 'piotr_toolbox.zip'), 'Piotr''s toolbox code', simulate_no_download);

    if success
        mkdir(fullfile(algos_dir, 'toolboxes', 'piotr_toolbox'));
        unzip(fullfile(temp_dir, 'piotr_toolbox.zip'), fullfile(algos_dir, 'toolboxes', 'piotr_toolbox'));
        movefile(fullfile(algos_dir, 'toolboxes', 'piotr_toolbox', 'toolbox', '*'), fullfile(algos_dir, 'toolboxes', 'piotr_toolbox'));
        rmdir(fullfile(algos_dir, 'toolboxes', 'piotr_toolbox', 'toolbox'), 's');
        % do not compile for linux - there is some problem when running
        % struct edges with compiled code (rather than with the compiled
        % code that comes with the library)
        if ~isunix
            cd(fullfile(algos_dir, 'toolboxes', 'piotr_toolbox', 'external'));
            toolboxCompile;
            fprintf(1, 'Done mex''ing\n');
            cd(curr_dir);
        end
    end

    % download Piotr's Struct Edges code
    success = download_code('http://ftp.research.microsoft.com/downloads/389109f6-b4e8-404c-84bf-239f7cbf4e3d/releaseV3.zip', ...
        fullfile(temp_dir, 'release.zip'), 'Piotr''s Struct Edges code', simulate_no_download);

    if success
        mkdir(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges'));
        unzip(fullfile(temp_dir, 'release.zip'), fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges'));
        movefile(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges', 'releaseV3', '*'), fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges'));
        rmdir(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges', 'releaseV3'), 's');
        cd(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges'));
        if isunix
            mex private/edgesDetectMex.cpp -outdir private '-DUSEOMP' CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp"
            mex private/edgesNmsMex.cpp    -outdir private '-DUSEOMP' CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp"
        else
            % if windows
            mex private/edgesDetectMex.cpp -outdir private '-DUSEOMP' 'OPTIMFLAGS="$OPTIMFLAGS' '/openmp"'
            mex private/edgesNmsMex.cpp    -outdir private '-DUSEOMP' 'OPTIMFLAGS="$OPTIMFLAGS' '/openmp"'
        end
        fprintf(1, 'Done mex''ing\n');
        cd(curr_dir);
        replaceInTextFile(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges', 'edgesDetect.m'), '\[E,O,inds,segs\]', '[E,T,O,inds,segs]');
        replaceInTextFile(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges', 'edgesDetect.m'), '% perform nms', 'T = [];\n% perform nms');
        replaceInTextFile(fullfile(algos_dir, 'segmentation', 'boundaries--dollar_ICCV_2013_structedges', 'edgesDetect.m'), 'E\s*=\s*edgesNmsMex', 'T=edgesNmsMex');
    end

    % download Woodford's Image-Based Rendering and Stereo code
    success = download_code('http://www.robots.ox.ac.uk/~ojw/files/imrender_v2.4.zip', ...
        fullfile(temp_dir, 'imrender_v2.4.zip'), 'Woodford''s Image-Based Rendering and Stereo code', simulate_no_download);

    if success
        unzip(fullfile(temp_dir, 'imrender_v2.4.zip'), fullfile(algos_dir, 'segmentation'));
        cd(fullfile(algos_dir, 'segmentation', 'imrender', 'vgg'));
        % segment as a test - which also compiles the file
        temp = vgg_segment_gb(imread('peppers.png'), 0.5, 10, 10);
        fprintf(1, 'Done mex''ing\n');
        cd(curr_dir);
    end

    % download export_fig code
    success = download_code('https://codeload.github.com/ojwoodford/export_fig/legacy.zip/master', ...
        fullfile(temp_dir, 'ojwoodford-export_fig.zip'), 'Woodford''s matlab export fig code', simulate_no_download);

    if success
        mkdir(fullfile(algos_dir, 'utils'));
        unzip(fullfile(temp_dir, 'ojwoodford-export_fig.zip'), fullfile(algos_dir, 'utils'));
        d = dir(fullfile(algos_dir, 'utils', '*export_fig*'));
        movefile(fullfile(algos_dir, 'utils', d(1).name), fullfile(algos_dir, 'utils', 'export_fig'));
        replaceInTextFile(fullfile(code_root_dir, 'utils', 'drawFigFrames.m'), '~/videovolumes/extern_src', algos_dir, true);
    end

    % download Vedaldi's vlfeat code
    success = download_code('https://github.com/vlfeat/vlfeat/archive/master.zip', ...
        fullfile(temp_dir, 'vlfeat.zip'), 'Vedaldi''s vlfeat code', simulate_no_download);

    if success
        unzip(fullfile(temp_dir, 'vlfeat.zip'), fullfile(algos_dir, 'toolboxes'));
        d = dir(fullfile(algos_dir, 'toolboxes', '*vlfeat*'));
        movefile(fullfile(algos_dir, 'toolboxes', d(1).name), fullfile(algos_dir, 'toolboxes', 'vlfeat'));
    end

    % change the extern code path in the internal parameters script
    replaceInTextFile(fullfile(code_root_dir, 'internal_params.m'), '''/home/ahumayun/videovolumes/extern_src''', ['fullfile(fp.code_root_dir, ''', extern_src_rel, ''')'], true);

    % delete temp directory
    if ~simulate_no_download
        rmdir(temp_dir, 's');
    end

catch exception
    % remove temp dir
    rmdir(temp_dir, 's');
    rethrow(exception)
end

end

function success = download_code(url, filepath, desc, simulate_no_download)
try
    fprintf(1, 'Downloading %s ...\n', desc);
    if ~simulate_no_download
        [f, status] = urlwrite(url, filepath);
        success = status == 1;
    else
        success = true;
    end
catch exception
    success = false;
end

if success
    if ~simulate_no_download
        fprintf(1, 'Done downloading\n');
    else
        fprintf(1, 'Simulated download call\n');
    end
else
    fprintf(2, 'Downloading failure\n');
end
end

function transferMatlabFromGNU(makefilepath, dest_dir)
fd = fopen(makefilepath, 'r');
str = fread(fd);
str = char(str');
fclose(fd);

files = {};
re_matches = regexp(str, '(?:matlab)\s+:=\s+(\S+.(?:(mat)|m)(?:\s*\\?\s*((\$\(wildcard)|(\)))?\s+))*', 'tokens');
for idx = 1:length(re_matches)
    f = regexp(re_matches{idx}{1}, '(\S+.(?:(mat)|m))', 'tokens');
    files = [files cellfun(@(x)x, f)];
end
for idx = 1:length(files)
    movefile(fullfile(fileparts(makefilepath), files{idx}), dest_dir);
end
end

function adjustAttributes(folder_path)
% dont need to change file permissions on windows
if ispc == 1
    return;
end

d = dir(folder_path);
for idx = 1:length(d)
    if strcmp(d(idx).name,'.') || strcmp(d(idx).name,'..')
        continue;
    end

    curr_path = fullfile(folder_path,d(idx).name);
    if d(idx).isdir == 1
        adjustAttributes(curr_path);
    else
        unix(['chmod 0644 "' curr_path '"']);
    end
end
end


function [group_metrics individual_metrics values gwcsf gwcsfmean gwcsf_l2norm] = qc_metrics_second_level(obj, varargin)
%
% Quality metrics for a 2nd-level analysis (set of images from different subjects)
% The goal is to obtain measures that are simple and scale invariant, and
% so can be compared across image datasets
%
% :Usage:
% ::
%
%     [group_metrics individual_metrics values gwcsf gwcsfmean gwcsf_l2norm] = qc_metrics_second_level(list inputs here, [optional inputs])
%
% For objects: Type methods(object_name) for a list of special commands
%              Type help object_name.method_name for help on specific
%              methods.
%
% ..
%     Author and copyright information:
%
%     Copyright (C) 2016 Tor Wager
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
% ..
%
% :Inputs:
%
%   **obj:**
%        An fmri_data object with a set of images
%        Intended to be individual-participant beta or contrast images from
%        first-level analyses.
%
% :Optional Inputs:
%   **noverbose:**
%        Turn off text display reporting of warnings and metrics
%
%   **param2:**
%        description of param2
%
% :Outputs:
%
%   **group_metrics:**
%        Quality metrics indicating potential problems, as described below
%
%   **individual_metrics:**
%        Individual image-level values for quality metrics
%        These can be used to identify individuals with problematic images
%        or as covariates in analyses.
%
%   **values:**
%        Grand Mean Gray, white, and CSF values - one number per metric per
%        image
%
%   **gwcsf:**
%        Gray, white, and CSF image objects with values for all images
%
%   **gwcsfmean:**
%        Gray, white, and CSF image objects mean values across images
%
%   **gwcsfl2norm:**
%        L2 norm of Gray, white, and CSF components for each image
%
% :References:
%   None.
%
%
% --------------------------------------------------------------------------------
% Coverage:  Percentage of standard MNI gray-matter mask with non-zero/non-nan values
%       NOT IMPLEMENTED YET
%       Range: [0 100],  100 is good (full coverage). Low values indicate
%       dropout due to artifacts or space mis-match
%
% Template match:  Dice coefficient (point-biserial r?) with standard MNI gray-matter mask
%       NOT IMPLEMENTED YET
%       Range: [0 100],  100 is good (full coverage). Low values indicate
%       dropout due to artifacts or space mis-match
%
% Bright-edge bias:  "brightedge"
%       NOT IMPLEMENTED YET
%       High inter-image variability around edge of brain
%       median absolute deviation (MAD) in brain edge-mask / MAD in center
%       of brain.
%       Range: [0 Inf],  1 is good (homogeneous). High values may indicate
%       head movement artifacts
%
% Signal in ventricles: "csf_to_gm_signal_ratio"
%       In most contrast maps, there should be less non-zero signal in the CSF space (e.g., ventricles)
%       than in gray matter.  This measures the ratio of mean absolute signal in CSF / GM.
%       Range: [0 Inf]. Values < 1 indicate low ventricle signal, which is good.
%       Higher values are worse.
%       Apply to: Individual or group. Contrast images (differences across conditions) for a series of individual participants
%
% Effect size in ventricles: "global_d_ventricles"
%       d = Mean / standard error (STD) of whole-ventricle average signal
%       Indicates a shift towards global activation or deactivation of the
%       ventricles in the group.
%       Range: [-Inf Inf], farther from zero is bad.
%       Apply to: Group. Contrast images (differences across conditions) for group of participants
%
% Significant global activation of ventricles: "global_logp_ventricles"
%       -log(p-value) in ventricle global mean across subjects, divided by -log(0.05)
%       Any value > 1 indicates a significant global activation in the
%       ventricles.
%       Range: [0 Inf], higher is worse. Values > 1 are bad.
%       Apply to: Group. Contrast images (differences across conditions) for group of participants
%
% Effect size in white matter: "global_d_wm"
%       d = Mean / standard error (STD) of whole-WM average signal
%       Indicates a shift towards global activation or deactivation of the
%       WM in the group. This is not completely redundant with CSF, because
%       some artifacts can affect one tissue compartment but not another.
%       WM values are, however, more likely to be influenced by true
%       signal.
%       Range: [-Inf Inf], farther from zero is bad.
%
% Significant global activation of WM: "global_logp_wm"
%       -log(p-value) in WM global mean across subjects, divided by -log(0.05)
%       Any value > 1 indicates a significant global activation in WM.
%       Range: [0 Inf], higher is worse. Values > 1 are bad.
%
% Non-spatially specific signal contamination: "r2_explained_by_csf"
%       Variance in individual differences in whole-gray-matter activity
%       Range: [-1 1], usually [0 1].  Farther from zero is bad.
%       Apply to: Group. Contrast images (differences across conditions) for group of participants
%
% Scale inhomogeneity across participants: "csf_scale_inhom"
%       Assumption: Subjects should be on the same scale (e.g., if you look
%       at histograms of contrast images for each subject). We assume that
%       the signal in gray matter may vary for meaningful reasons, but the
%       scale of the signal in CSF (and maybe WM?) should be similar across
%       participants.
%       Measure: The coefficient of variation of the L1-norm across CSF voxels for each participant.
%       The L1-norm is a measure of scale (across voxels, for each observation/image)
%       that is more robust than the variance.
%       High variability in these individual scale parameters is a sign of inhomogeneity.
%       The coefficient of variation is the standard dev. of this whole-image scale value divided by its mean.
%       This is a scale-invariant measure of inhomogeneity across images.
%       It also avoids the instability that occurs by dividing by values that may
%       be near zero, such as the mean.
%       Range: [0 Inf].  Lower is better.
%       Apply to: Group. Condition images (betas) for group of participants
%
% Scale inhomogeneity across participants in gray matter: "gm_scale_inhom"
%       The coefficient of variation of the L1-norm across GM voxels for each participant.
%       The L1-norm is a measure of scale (across voxels, for each observation/image)
%       that is more robust than the variance.
%       High variability in these individual scale parameters is a sign of inhomogeneity.
%       The coefficient of variation is the standard dev. of this whole-image scale value divided by its mean.
%       This is a scale-invariant measure of inhomogeneity across images.
%       It also avoids the instability that occurs by dividing by values that may
%       be near zero, such as the mean.
%       Range: [0 Inf].  Lower is better, but GM values may also be influenced by large differences in true signal.
%
% :Examples:
% ::
%    % Load sample images
%    obj = load_image_set('emotionreg');
%
%    % Run QC metrics
%    [group_metrics individual_metrics] = qc_metrics_second_level(obj);
%
%    % Plot histograms of gray, white, CSF values
%    hist_han = histogram(obj, 'byimage', 'by_tissue_type');
%
% :See also:
%   - extract_gray_white_csf, histogram
%

% ..
%    DEFAULTS AND INPUTS
% ..

doverbose = 1;

% optional inputs with default values
for i = 1:length(varargin)
    if ischar(varargin{i})
        switch varargin{i}

            case 'noverbose', doverbose = 0;

            otherwise, warning(['Unknown input string option:' varargin{i}]);
        end
    end
end

[values, components, gwcsf, gwcsf_l2norm] = extract_gray_white_csf(obj);

% Get mean signal in each tissue compartment for visualization, if desired
% -------------------------------------------------------------------------
gwcsfmean = mean(gwcsf{1});
gwcsfmean = replace_empty(gwcsfmean);
for i = 2:3
    m = mean(gwcsf{i});
    m = replace_empty(m);
    gwcsfmean.dat(:, i) = m.dat;
end

% -------------------------------------------------------------------------
% METRICS
% -------------------------------------------------------------------------

% Get coverage of gray-matter a priori mask space (do we have data in all vox?)
% -------------------------------------------------------------------------

objmasked = apply_mask(obj, mean(gwcsf{1}));

wh = isnan(objmasked.dat) | objmasked.dat == 0;
individual_metrics.gray_matter_coverage = sum(~wh) ./ size(objmasked.dat, 1);
group_metrics.mean_gray_matter_coverage = mean(individual_metrics.gray_matter_coverage);

%brightedge
% NOT DONE YET

% Global activation/deactivation in CSF and white matter
% -------------------------------------------------------------------------

individual_metrics.global_ventricle_values = mean(values(:, 3));

group_metrics.global_d_ventricles = mean(values(:, 3)) ./ std(values(:, 3));

n = size(values, 1);
t = group_metrics.global_d_ventricles .* sqrt(n);   % t-value
p = 2 .* min(tcdf(t, n - 1), tcdf(-t, n - 1));      % two-tailed

group_metrics.global_logp_ventricles = -log(p) ./ (-log(.05));

% --- wm ---
individual_metrics.global_white_matter_values = mean(values(:, 2));

group_metrics.global_d_wm = mean(values(:, 2)) ./ std(values(:, 2));

t = group_metrics.global_d_wm .* sqrt(n);   % t-value
p = 2 .* min(tcdf(t, n - 1), tcdf(-t, n - 1));      % two-tailed

group_metrics.global_logp_wm = -log(p) ./ (-log(.05));

% Gray-matter signal explained by CSF
% -------------------------------------------------------------------------

[r, p] = corr(values(:, 1), values(:, 3));

group_metrics.gm_explained_by_csf_pvalue = p;
group_metrics.r2_explained_by_csf = r .^ 2;

% Gray-matter scale (l2 norm) explained by CSF scale
% -------------------------------------------------------------------------

[r, p] = corr(gwcsf_l2norm(:, 1), gwcsf_l2norm(:, 3));

group_metrics.gm_l2norm_explained_by_csf_pvalue = p;
group_metrics.r2_l2norm_explained_by_csf = r .^ 2;

% Signal in ventricles
% -------------------------------------------------------------------------

csfsignal = mean(abs(gwcsf{3}.dat)) ./ mean(abs(gwcsf{1}.dat));
group_metrics.csf_to_gm_signal_ratio = mean(csfsignal);
individual_metrics.csf_to_gm_signal_ratio = csfsignal;

% Scale Inhomogeneity
% -------------------------------------------------------------------------

L1norm = sum(abs(gwcsf{1}.dat))';
group_metrics.gm_scale_inhom = std(L1norm) ./ mean(L1norm);
individual_metrics.gm_L1norm = L1norm;

L1norm = sum(abs(gwcsf{3}.dat))';
group_metrics.csf_scale_inhom = std(L1norm) ./ mean(L1norm);
individual_metrics.csf_L1norm = L1norm;

% Add warnings
% -------------------------------------------------------------------------
group_metrics.warnings = {};

if any(individual_metrics.gray_matter_coverage < .9)
    group_metrics.warnings{end + 1} = sprintf('Warning: Incomplete coverage, missing gray-matter data in some images.\n   - Mean coverage is d = %3.2f%%\n', group_metrics.mean_gray_matter_coverage .* 100);
end

if group_metrics.global_logp_ventricles > 1
    group_metrics.warnings{end + 1} = sprintf('Warning: Significant global activation in CSF space/ventricles.\n   - Effect size is d = %3.2f\n', group_metrics.global_d_ventricles);
end

if group_metrics.global_logp_wm > 1
    group_metrics.warnings{end + 1} = sprintf('Warning: Significant global activation in white matter.\n   - Effect size is d = %3.2f\n', group_metrics.global_d_wm);
end

if group_metrics.gm_explained_by_csf_pvalue < .05
    group_metrics.warnings{end + 1} = sprintf('Warning: Gray-matter individual diffs significantly correlated with mean CSF value.\n   - Var explained (r^2) = %3.2f%%', group_metrics.r2_explained_by_csf .* 100);
end

if group_metrics.gm_l2norm_explained_by_csf_pvalue < .05
    group_metrics.warnings{end + 1} = sprintf('Warning: Gray-matter scale (L2 norm) significantly correlated with mean CSF L2 norm.\n   - Var explained (r^2) = %3.2f%%', group_metrics.r2_l2norm_explained_by_csf .* 100);
end

if group_metrics.csf_to_gm_signal_ratio > 1
    group_metrics.warnings{end + 1} = sprintf('Warning: Strong non-zero signal in CSF relative to gray matter.\n   - Ratio is = %3.2f', group_metrics.csf_to_gm_signal_ratio);
end

if group_metrics.csf_scale_inhom > .3
    group_metrics.warnings{end + 1} = sprintf('Warning: High individual diffs in image scaling estimated from CSF.\n   - CV is = %3.2f', group_metrics.csf_scale_inhom);
end

% Display warnings
% -------------------------------------------------------------------------

if doverbose

    disp(' ');
    disp(group_metrics)
    disp(char(group_metrics.warnings{:}))

end

end % function


classdef TestDescriptorExtractor
    %TestDescriptorExtractor

    properties (Constant)
        im = fullfile(mexopencv.root(),'test','tsukuba_l.png');
        extractors = { ...
            ... % features2d (opencv)
            'BRISK', 'ORB', 'KAZE', 'AKAZE', ...
            ... % xfeatures2d (opencv_contrib)
            'SIFT', 'SURF', ...
            'BriefDescriptorExtractor', 'DAISY', 'FREAK', 'LATCH', 'LUCID', ...
            'VGG', 'BoostDesc'
        };
    end

    methods (Static)
        function test_compute_img
            img = cv.imread(TestDescriptorExtractor.im, ...
                'Grayscale',true, 'ReduceScale',2);
            kpts0 = cv.FAST(img, 'Threshold',20);
            for i=1:numel(TestDescriptorExtractor.extractors)
                try
                    obj = cv.DescriptorExtractor(...
                        TestDescriptorExtractor.extractors{i});
                catch ME
                    %TODO: check if opencv_contrib/xfeatures2d is available
                    %error('mexopencv:testskip', 'contrib');
                    continue;
                end
                typename = obj.typeid();
                ntype = obj.defaultNorm();

                % KAZE/AKAZE descriptors only work with their own detectors
                switch TestDescriptorExtractor.extractors{i}
                    case 'KAZE'
                        if ~mexopencv.isOctave()
                            kpts = detect(cv.KAZE(), img);
                        else
                            %HACK: https://savannah.gnu.org/bugs/index.php?54800
                            o = cv.KAZE();
                            kpts = o.detect(img);
                        end
                    case 'AKAZE'
                        if ~mexopencv.isOctave()
                            kpts = detect(cv.AKAZE(), img);
                        else
                            %HACK: https://savannah.gnu.org/bugs/index.php?54800
                            o = cv.AKAZE();
                            kpts = o.detect(img);
                        end
                    otherwise
                        kpts = kpts0;
                end

                % LUCID works on RGB images
                if strcmp(TestDescriptorExtractor.extractors{i}, 'LUCID')
                    im = cv.cvtColor(img, 'GRAY2RGB');
                else
                    im = img;
                end

                [desc, kpts2] = obj.compute(im, kpts);
                validateattributes(kpts2, {'struct'}, {'vector'});
                assert(all(ismember(fieldnames(kpts), fieldnames(kpts2))));
                validateattributes(desc, {obj.descriptorType()}, ...
                    {'size',[numel(kpts2) obj.descriptorSize()]});
            end
        end

        function test_compute_imgset
            img = cv.imread(TestDescriptorExtractor.im, ...
                'Grayscale',true, 'ReduceScale',2);
            kpts0 = cv.FAST(img, 'Threshold',50);
            for i=1:numel(TestDescriptorExtractor.extractors)
                try
                    obj = cv.DescriptorExtractor(...
                        TestDescriptorExtractor.extractors{i});
                catch ME
                    %TODO: check if opencv_contrib/xfeatures2d is available
                    %error('mexopencv:testskip', 'contrib');
                    continue;
                end

                % KAZE/AKAZE descriptors only work with their own detectors
                switch TestDescriptorExtractor.extractors{i}
                    case 'KAZE'
                        if ~mexopencv.isOctave()
                            kpts = detect(cv.KAZE(), img);
                        else
                            %HACK: https://savannah.gnu.org/bugs/index.php?54800
                            o = cv.KAZE();
                            kpts = o.detect(img);
                        end
                    case 'AKAZE'
                        if ~mexopencv.isOctave()
                            kpts = detect(cv.AKAZE(), img);
                        else
                            %HACK: https://savannah.gnu.org/bugs/index.php?54800
                            o = cv.AKAZE();
                            kpts = o.detect(img);
                        end
                    otherwise
                        kpts = kpts0;
                end
                kpts = {kpts, kpts};

                % LUCID works on RGB images
                if strcmp(TestDescriptorExtractor.extractors{i}, 'LUCID')
                    im = cv.cvtColor(img, 'GRAY2RGB');
                else
                    im = img;
                end
                imgs = {im, im};

                [descs, kpts] = obj.compute(imgs, kpts);
                validateattributes(kpts, {'cell'}, {'vector'});
                validateattributes(descs, {'cell'}, ...
                    {'vector', 'numel',numel(imgs)});
                cellfun(@(d,k) validateattributes(d, ...
                    {obj.descriptorType()}, ...
                    {'size',[numel(k) obj.descriptorSize()]}), descs, kpts);
            end
        end
    end

end


function idx = getclassindex(cnames,g)
%GETCLASSINDEX Find indices for class names in another list of names
%   IDX = GETCLASSINDEX(CNAMES,G) takes a list CNAMES of class names
%   (such as the grouping variable values in the treefit or classify
%   function) and another list G of group names (as might be supplied
%   in the "prior" argument to those functions), and finds the indices
%   of the CNAMES names in the G list.  CNAMES should be a cell array
%   of strings.  G can be numbers, a string array, or a cell array of
%   strings

%   Copyright 1993-2002 The MathWorks, Inc.
%   $Revision: 1.1 $  $Date: 2002/03/22 22:03:02 $

% Convert to common string form, whether input is char, cell, or numeric
if isnumeric(g)
   g = cellstr(strjust(num2str(g(:)), 'left'));
elseif ~iscell(g)
   g = cellstr(g);
end

nclasses = length(cnames);
idx = zeros(1,nclasses);

% Look up each class in the grouping variable.
for i = 1:nclasses
   j = strmatch(cnames{i}, g, 'exact');
   if ~isempty(j)
      idx(i) = j(1);
   end
end


function I = movieToImages( M )
% Creates a stack of images from a matlab movie M.
%
% Repeatedly calls frame2im. Useful for playback with playMovie.
%
% USAGE
%  I = movieToImages( M )
%
% INPUTS
%  M   - a matlab movie
%
% OUTPUTS
%  I   - MxNxT array (of images)
%
% EXAMPLE
%  load( 'images.mat' );  [X,map]=gray2ind(video(:,:,1));
%  M = fevalArrays( video, @(x) im2frame(gray2ind(x),map) );
%  I = movieToImages(M); playMovie(I);
%
% See also PLAYMOVIE
%
% Piotr's Computer Vision Matlab Toolbox      Version 2.0
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]

I = fevalArrays( M, @frame2Ii );

function I = frame2Ii( F )

[I,map] = frame2im( F );
if( isempty(map) )
  if( size(I,3)==3 )
    classname = class( I );
    I = sum(I,3)/3;
    I = feval( classname, I );
  end
else
  I = ind2gray( I, map );
end


function [new_gait, sol, info, total_time] = solve(nlp, x0, info)

    % Link the NLP problem to a NLP solver
    solver = IpoptApplication(nlp);

    solver.Options.ipopt.bound_frac = 1e-8;
    solver.Options.ipopt.bound_push = 1e-8;
    % Possible parameter changes to solver
    solver.Options.ipopt.tol = 1e-3;
    solver.Options.ipopt.dual_inf_tol = 1e-3;
    solver.Options.ipopt.constr_viol_tol = 1e-4;
    solver.Options.ipopt.compl_inf_tol = 1e-4;
    solver.Options.ipopt.max_iter = 1000;

    %%% Only use this if contraints are the same
    if nargin > 2
        solver.Options.ipopt.point_perturbation_radius = 0;
        solver.Options.ipopt.warm_start_bound_push = 1e-8;
        solver.Options.ipopt.warm_start_mult_bound_push = 1e-8;
        solver.Options.ipopt.mu_init = 1e-6;
        solver.Options.ipopt.warm_start_init_point = 'yes';
        solver.Options.zl = info.zl;
        solver.Options.zu = info.zu;
        solver.Options.lambda = info.lambda;
    end

    solver.Options.ipopt.acceptable_tol = 1e-2;
    solver.Options.ipopt.acceptable_constr_viol_tol = 1e-4;
    solver.Options.ipopt.acceptable_dual_inf_tol = 1e-2;
    solver.Options.ipopt.acceptable_compl_inf_tol = 1e-2;

    % Run the optimization
    start_time = tic();
    if nargin < 2
        [sol, info] = optimize(solver);
    else
        [sol, info] = optimize(solver, x0);
    end
    [tspan, states, inputs, params] = exportSolution(nlp, sol);
    tspan{3} = tspan{1}(end) + tspan{3};

    total_time = toc(start_time);
    new_gait = struct(...
        'tspan', tspan,...
        'states', states,...
        'inputs', inputs,...
        'params', params);

end


% VOLTYPE determines the type of volume conduction model
%
% Use as
%   [type] = voltype(vol)
% to get a string describing the type, or
%   [flag] = voltype(vol, desired)
% to get a boolean value.
%
% See also COMPUTE_LEADFIELD

% Copyright (C) 2007, Robert Oostenveld
%
function [type] = voltype(vol, desired)

if isfield(vol, 'type')
  type = vol.type;
elseif isfield(vol, 'r') && prod(size(vol.r))==1
  type = 'singlesphere';
elseif isfield(vol, 'r') && isfield(vol, 'o') && all(size(vol.r)==size(vol.o))
  type = 'multisphere';
elseif isfield(vol, 'r')
  type = 'concentric';
elseif isfield(vol, 'bnd')
  type = 'bem';
end

if nargin>1
  type = strcmp(type, desired);
end


function varargout=pow2cep(varargin)
%
% For calling details please see v_pow2cep.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_pow2cep.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: pow2cep.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_pow2cep(varargin{:});
else
    v_pow2cep(varargin{:});
end


function [hdr] = read_ctf_res4(fname)

% READ_CTF_RES4 reads the header in RES4 format from a CTF dataset
%
% Use as
%   [hdr] = read_ctf_res4(filename)
%
% See also READ_CTF_MEG4

% "VSM MedTech Ltd. authorizes the release into public domain under the
% GPL licence of the Matlab source code files "read_ctf_res4.m" and
% "read_ctf_meg4.m" by the authors of said files from the F.C. Donders
% Centre, Nijmegen, The Netherlands."

% Author(s): Jim McKay November 1999
% Last revision: Jim McKay
% Copyright (c) 1999-2000 CTF Systems Inc. All Rights Reserved.
%
% modifications Copyright (C) 2002, Ole Jensen
% modifications Copyright (C) 2003, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% read header information
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

try
  fid = fopen_or_error(fname,'r','ieee-be');
catch err
  ft_error('Cound not open header file: %s', err.message);
end

% First 8 bytes contain filetype, check is fileformat is correct.
% This function was written for MEG41RS, but also seems to work for some other formats
CTFformat=char(fread(fid,8,'uint8'))';
if ~strcmp(CTFformat(1,1:7),'MEG41RS') && ~strcmp(CTFformat(1,1:7),'MEG42RS') && ~strcmp(CTFformat(1,1:7),'MEG3RES')
  ft_warning('res4 format (%s) is not supported for file %s, trying anyway...', CTFformat(1,1:7), fname);
end

% Read the initial parameters
appName       = char(fread(fid,256,'uint8'))' ;
dataOrigin    = char(fread(fid,256,'uint8'))' ;
dataDescrip   = char(fread(fid,256,'uint8'))' ;
no_trial_avgd = fread(fid,1,'int16')          ;
data_time     = char(fread(fid,255,'uint8'))';
data_date     = char(fread(fid,255,'uint8'))';

fseek(fid,1288,'bof');
% Read the general recording parameters
no_samples  = fread(fid,1,'int32');
no_channels = fread(fid,1,'int16');
fseek(fid,2,'cof');         % hole of 2 bytes due to improper alignment
sample_rate = fread(fid,1,'double');
epoch       = fread(fid,1,'double');
no_trials   = fread(fid,1,'int16');
fseek(fid,2,'cof');         % hole of 2 bytes due to improper alignment
preTrigpts=fread(fid,1,'int32');

fseek(fid,1360,'bof');
% read in the meg4Filesetup structure
run_name     = char(fread(fid,32,'uint8')');
run_title    = char(fread(fid,256,'uint8')');
instruments  = char(fread(fid,32,'uint8')');
coll_desc    = char(fread(fid,32,'uint8')');
subj_id      = char(fread(fid,32,'uint8')');
operator     = char(fread(fid,32,'uint8')');
sensFilename = char(fread(fid,60,'uint8')');

% not nececssary to seek, the file pointer is already at the desired location
% fseek(fid,1836,'bof');

% Read in the run description length
rd_len=fread(fid,1,'uint32');
% Go to the run description and read it in
fseek(fid,1844,'bof');
run_desc=char(fread(fid,rd_len,'uint8')');

% read in the filter information
num_filt=fread(fid,1,'uint16');
for fi=0:(num_filt-1),
  %filt_info=fread(fid,18,'uint8');
  filt_freq =fread(fid,1, 'double');
  filt_class=fread(fid,1, 'uint32');
  filt_type =fread(fid,1, 'uint32');
  num_fparm=fread(fid, 1, 'uint16');
  %num_fparm=filt_info(18);
  if num_fparm ~= 0,
    filt_parm=fread(fid,8*num_fparm,'uint8');
  end % if
end % for fi

% Read in the channel names
for i=1:no_channels,
  temp=fread(fid,32,'uint8')';
  temp(find(temp<32 )) = ' ';       % remove non-printable characters
  temp(find(temp>126)) = ' ';       % remove non-printable characters
  endstr = strfind(temp, '-'); temp(endstr:end) = ' ';  % cut off at '-'
  endstr = strfind(temp, ' '); temp(endstr:end) = ' ';  % cut off at ' '
  chan_name(i,:) = char(temp);      % as char array
  chan_label{i}  = deblank(char(temp)); % as cell-array
end %for

% pre-allocate some memory space
sensGain = zeros([no_channels,1]);
qGain    = zeros([no_channels,1]);
ioGain   = zeros([no_channels,1]);
sensType = zeros([no_channels,1]);

% Read in the sensor information
fp = ftell(fid);
for chan=1:no_channels,
  fread(fid,1,'uint8');         % Read and ignore 1 byte from enum
  sensType(chan)=fread(fid,1,'uint8');  % Read sensor type
  fread(fid,2,'uint8');         % Read and ignore originalRunNum
  fread(fid,4,'uint8');         % Read and ignore coilShape
  sensGain(chan)=fread(fid,1,'double'); % Read sensor gain in Phi0/Tesla
  qGain(chan)=fread(fid,1,'double');        % Read qxx gain (usually 2^20 for Q20)
  ioGain(chan)=fread(fid,1,'double');       % Read i/o gain of special sensors (usually 1.0)
  ioOffset(chan)=fread(fid,1,'double');
  numCoils(chan)=fread(fid,1,'int16');
  grad_order_no(chan)=fread(fid,1,'int16');
  fread(fid,4,'uint8');

  % read the coil positions and orientations
  for i=1:8
    Chan(chan).coil(i).pos = fread(fid,3,'double')';
    fread(fid,1,'double');
    Chan(chan).coil(i).ori = fread(fid,3,'double')';
    fread(fid,3,'double');
  end

  % read the coil positions and orientations in head coordinates(?)
  for i=1:8
    Chan(chan).coilHC(i).pos = fread(fid,3,'double')';
    fread(fid,1,'double');
    Chan(chan).coilHC(i).ori = fread(fid,3,'double')';
    fread(fid,3,'double');
  end

  % jump to the next sensor info record
  fseek(fid, fp+chan*1328, 'bof');
end % for chan

% close the header file
fclose(fid);

% according to Tom Holroyd, the sensor types are
%
% meg channels are 5, refmag 0, refgrad 1, adcs 18.
% UPPT001 is 11
% UTRG001 is 11
% SCLK01 is 17
% STIM is 11
% SCLK01 is 17
% EEG057 is 9
% ADC06 is 18
% ADC07 is 18
% ADC16 is 18
% V0 is 15

% assign all the variables that should be outputted as header information
hdr.Fs          = sample_rate;
hdr.nChans      = no_channels;
hdr.nSamples    = no_samples;
hdr.nSamplesPre = preTrigpts;
hdr.timeVec     = (1:no_samples)/sample_rate - preTrigpts/sample_rate - 1/sample_rate;
hdr.nTrials     = no_trials;
hdr.gainV       = ioGain./(qGain.*sensGain);
hdr.ioGain      = ioGain;
hdr.qGain       = qGain;
hdr.sensGain    = sensGain;
hdr.sensType    = sensType;

hdr.label       = chan_label(:);
hdr.nameALL     = chan_name;
hdr.Chan        = Chan;
% hdr.rowMEG      = rowMEG;
% hdr.rowEEG      = rowEEG;
% hdr.rowTRIG     = rowTRIG;
% hdr.rowREF      = rowREF;
% hdr.nameEEG     = [];
% hdr.nameMEG     = [];
% hdr.nameEOG     = [];
% hdr.trigV       = [];
% hdr.SwapData    = [];


function lstOut = pyrLst2OP(lstIn1, lstIn2, fun)
%
%
%        lstOut = pyrLst2OP(lstIn1, lstIn2, fun)
%
%
%        Input:
%           -lstIn1: a list of image pyramids (first operand of fun)
%           -lstIn2: a list of image pyramids (second operand of fun)
%           -fun: a function to apply to lstIn1 and lstIn2
%
%        Output:
%           -lstOut: the result of the function
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
%

n = length(lstIn1);

lstOut = [];

for i=1:n
    p = fun(lstIn1(i), lstIn2(i));
    lstOut = [lstOut, p];
end

end


%  Function arranges given network (net) according to given layers to use
%  (layers_to_use), and outputs the arranged nework.
%
%  @authors: ufukefe, kutalmisince
%  Created on March 23, 2021
%  @Middle East Technical University, Center for Image Analysis
%  Last Edited on July 1, 2021

function net = ArrangeNetwork(net,layers_to_use)

    % Loads the network into the wrapper
    net = dagnn.DagNN.loadobj(net);

    % Set network to test model.
    net.mode = 'test';

    % Remove unnecessary layers
    net.removeLayer({net.layers(getLayerIndex(net, layers_to_use{1})+1:size(net.layers,2)).name})

    % Remove unused activations from RAM
    net.conserveMemory = 1;

    % Keep activations that will be used
    for i=1:size(layers_to_use,1)
    net.vars(getVarIndex(net,net.layers(getLayerIndex(net, layers_to_use{i})).outputs)).precious = 1;
    end

    % Move network to gpu
    net.move('gpu');

end


function x = cvx_getdual( x )
x = x.dual_;

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


classdef graphics

methods(Static)

    function result = plot_styles()
        % plot styles for multiple plots
        result = {...
        '--+','-.o',':*',...
        '--.','-.x',':s',...
        '--d','-.^',':v',...
        '-->','-.<',':p',...
        '--h'};
    end

end

end


function name = RemoveExt(filename)
%
%
%        name = RemoveExt(filename)
%
%
%        Description: remove file extension
%
%        Input:
%           -filename: the name of the file
%
%        Output:
%           -name: the filename without extension
%
%     Copyright (C) 2013  Francesco Banterle
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
%

k = strfind(filename, '.');

if(size(k) == 0) %no extension
    name = filename;
else
    k = k(end); %get the real extension
    name = filename(1:(k - 1));
end

end


function obj=geom_vline(obj,varargin)
% geom_abline Display vertical reference lines in each facet
%
% Example syntax: gramm_object.geom_abline('xintercept',1,'style','k--')
% See geom_abline for details

p=inputParser;
my_addParameter(p,'xintercept',0);
my_addParameter(p,'style','k--');
my_addParameter(p,'extent',2);
my_addParameter(p,'linewidth',1);
parse(p,varargin{:});

for obj_ind=1:numel(obj)
    obj(obj_ind).abline=fill_abline(obj(obj_ind).abline,NaN,NaN,p.Results.xintercept,NaN,@(x)x,p.Results.style,p.Results.extent,p.Results.linewidth);
end
end


function excelrecord4fcn(identified, IRFperiods, IRFt, endo, strctident, irf_estimates, n, pref)
% script excelrecord4
% records the information contained in the worksheet 'IRF' of the excel spreadsheet 'results.xls'

% create the cell that will be saved on excel
irfcell={};

% build preliminary elements: space between the tables
horzspace=repmat({''},2,5*identified);
vertspace=repmat({''},IRFperiods+3,1);

% loop over variables (vertical dimension)
for ii=1:n
tempcell={};
   % loop over shocks (horizontal dimension)
   for jj=1:identified
   % create cell of IRF record for variable ii in response to shock jj
      % if a sign restriction identification scheme has been used, use the structural shock labels
      if IRFt==4||IRFt==5||IRFt==6
      temp=['response of ' endo{ii,1} ' to ' strctident.signreslabels_shocks{jj,1} ' shocks'];
      else
      temp=['response of ' endo{ii,1} ' to ' endo{jj,1} ' shocks'];
      end
   irf_ij=[temp {''} {''} {''};{''} {''} {''} {''};{''} {'lw. bound'} {'median'} {'up. bound'};num2cell((1:IRFperiods)') num2cell((irf_estimates{ii,jj})')];
   tempcell=[tempcell irf_ij vertspace];
   end
irfcell=[irfcell;horzspace;tempcell];
end

% trim
irfcell=irfcell(3:end,1:end-1);

% write in excel
    bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),irfcell,'IRF','B2');


function rectangle_node = bezier_surface_rectangle_read ( rectangle_file_name, ...
  rectangle_num )

%*****************************************************************************80
%
%% BEZIER_SURFACE_RECTANGLE_READ reads rectangles from a rectangle file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 June 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string RECTANGLE_FILE_NAME, the name of the
%    rectangle file.
%
%    Input, integer RECTANGLE_NUM, the number of rectangles.
%
%    Output, real RECTANGLE_NODE(16,RECTANGLE_NUM),
%    the nodes that make up each rectangle.
%
  dim_num = 16;

  rectangle_node = i4mat_data_read ( rectangle_file_name, dim_num, ...
    rectangle_num );

  return
end


function [features, num_of_success] = extract_features(db, func)
	% db - a database to extract the features from
	% func - a function that extracts the features for a single database entry

    TRIM_SILENCE = true;
    GYRO = true;

    NUM_OF_ENTRIES = length(db);
	GYRO_DIM = 1;
    FS = 8000;

    features = {};
	num_of_success = 0;

	for k = 1:NUM_OF_ENTRIES
		try
			[wavdata, samp_rate] = read(db, k);
			wavdata = (wavdata{1});
            if GYRO
                wavdata = wavdata(:, GYRO_DIM);
            end
            wavdata = resample(wavdata, FS, samp_rate);
            fs = FS;

            if TRIM_SILENCE
                if GYRO
                    % cut 0.5 second at the beginning and a second from the end
                    wavdata = wavdata(4000:end-8000);
                end
                [wavdata, nseg] = get_voiced_segments(wavdata, fs);
            else
                nseg = 1;
            end

            if nseg > 0
                num_of_success = num_of_success + 1;
                features{num_of_success} = func(wavdata, fs);
            end
		catch ME
			% print error source
			ME.stack(1)
		end
	end
end


function neighborsCell = identifyNeighborsAuto(inputImages, inputSignals, varargin)
	% This code automatically sorts through to find all obj neighbors within a certain distance of the target (boundary to boundary). The output is a cell array with vectors of the neighbor indices to each obj.
	% Biafra Ahanonu
	% started: 2013.11.01
	% based on code by laurie burns, started: sept 2010.
	% inputs
		% inputImages - [x y nCells] matrices containing each set of filters
		% inputSignals - [nFilters frames] matrices containing each set of filter traces
	% options
		% _
	% outputs
		% _
	% changelog
		% 2013.11.01 refactored so accepts ICA filters and traces as input, also changed display to it matches ICAchooser, e.g. it applies a cellmap along with the identified and new cells
		% 2017.06.29 - change to using centroids since faster than imdilate and more accurate.
		% 2021.08.08 [19:30:20] - Updated to handle CIAtah v4.0 switch to all functions inside ciapkg package.
	% TODO
		%

	import ciapkg.api.* % import CIAtah functions in ciapkg package API.

	%========================
	options.plottingOn = 0;
	options.overlapradius = 10;
	% overlap radius in pixels (so convert properly)
	options.overlapDistance = 10;
	% 'centroid', 'imdilate'
	options.neighborMethod = 'centroid';
	%
	options.waitbarOn = 1;
	% Input pre-computed x,y coordinates for objects in images
	options.xCoords = [];
	options.yCoords = [];

	options.inputImagesThres = [];;

	%
	options.startCellNo = 1;
	%
	options.cropSizeLength = 20;

	% get options
	options = getOptions(options,varargin);
	% unpack options into current workspace
	fn=fieldnames(options);
	for i=1:length(fn)
		eval([fn{i} '=options.' fn{i} ';']);
	end
	%========================

	% cell vector info
	cellvec(1) = 1;
	cellvec(2) = size(inputImages,3);

	%% look for overlap of IC and dilated IC
	neighborsCell=cell(cellvec(2),1);
	% reshape to (x,y,z) indexing for compatibility
	% inputImages = permute(inputImages, [2 3 1]);

	reverseStr = '';
	nSignals = cellvec(2);
	if options.plottingOn==1
		figure(222)
	end

	ignoreDistanceReplace = 1e7;

	% [xCoords yCoords] = findCentroid(signalImages,'thresholdValue',0.8,'imageThreshold',0.3);
	% coordsGlobal = [xCoords; yCoords]';
	% distanceMatrix = squareform(pdist(coordsGlobal));
	switch options.neighborMethod
		case 'centroid'
			% body
			% find all cells below distance threshold
			distanceThreshold = options.overlapDistance; % 1px = 1um, 20 um per Jesse's procedures
			nCells = size(inputImages,3);

			% get the centroids and other info for movie
			if isempty(options.xCoords)
				% [xCoords, yCoords] = findCentroid(inputImagesThres,'waitbarOn',options.waitbarOn,'runImageThreshold',0);
				[thresholdedImages boundaryIndices] = thresholdImages(inputImages,'binary',1,'getBoundaryIndex',1,'threshold',0.35,'imageFilter','');
				[xCoords yCoords] = findCentroid(thresholdedImages,'runImageThreshold',0);
			else
				xCoords = options.xCoords(:)';
				yCoords = options.yCoords(:)';
			end

			coordsGlobal = [xCoords; yCoords]';
			% size(coordsGlobal)
			% nCells
			distanceMatrix = squareform(pdist(coordsGlobal));
			% distanceMatrix = distanceMatrix.*~diag(1e5*ones(1,nCells));
			distanceMatrix(logical(eye(size(distanceMatrix)))) = ignoreDistanceReplace;

			distanceMatrixThres = distanceMatrix<distanceThreshold;
			neighborsCell = {};
			reverseStr = '';
			for cellNo = 1:nCells
				neighborIdx = find(distanceMatrixThres(cellNo,:));
				neighborsCell{cellNo,1} = neighborIdx;
				% if mod(cellNo,50)==1
				%     fprintf('up to cell number %d of %d \n',cellNo,nCells)
				% end
				if (cellNo==1||mod(cellNo,50)==0||cellNo==nCells)&options.waitbarOn==1
					reverseStr = cmdWaitbar(cellNo,nCells,reverseStr,'inputStr','Finding cell neighbors');
				end
			end
			fprintf('Done assigning neighbor IDs...\n')
		case 'imdilate'
			% do nothing
		otherwise
			for c = 1:nSignals
				se = strel('disk',overlapradius,0);
				% threshold ICs
				inputImages = thresholdImages(inputImages);
				% get a dilated version of the thresholded image
				thisCellDilateCopy = repmat(imdilate(squeeze(inputImages(:,:,c)),se),[1 1 size(inputImages,3)]);
				% thisCellDilateCopy = permute(thisCellDilateCopy, [3 1 2]);
				% matrix multiple, any overlap will be labeled
				res = inputImages.*thisCellDilateCopy;
				res = squeeze(sum(sum(res,2),1));
				% all cells above threshold are neighbors
				res = find(res>1);
				neighborsCell{c,1} = setdiff(res,c);
				% reduce waitbar access
				if c==1||mod(c,7)==0|c==nSignals
					reverseStr = cmdWaitbar(c,nSignals,reverseStr,'inputStr','identifying neighboring cells');
				end
				if options.plottingOn==1
					keyIn = get(gcf,'CurrentCharacter');
					if strcmp(keyIn,'f')%user wants to exit
						set(gcf,'currentch','3');drawnow;
						keyIn = get(gcf,'CurrentCharacter');
						break
					end
				end
			end
	end
	if plottingOn
		viewNeighborsAuto(inputImages, inputSignals, neighborsCell);
	end
end


function [names, ids] = getMultiSpeciesModelId(modelJoint, nameTagsModels, nameTagHost, metTagRe, rxnTagRe, compCom, compHost)
% Get names and IDs for metabolites and exchange reactions in the [u] and [b] space
%
% USAGE:
%
%    [names, ids] = getMultiSpeciesModelId(modelJoint, nameTagsModels, nameTagHost, metTagRe, rxnTagRe, compCom, compHost)
%
% INPUTS:
%    modelJoint:       COBRA multi-organism model
%    nameTagsModels:   cell array of tags for species to identify the respective
%                      reactions and metabolites from `modelJoint.rxns` and `.mets`
%
% OPTIONAL INPUTS:
%    nameTagHost:      string of tag for the host model if exist. Input [] if no host is present
%    metTagRe:         a regular expression to identify the tag in nameTagsModels from `modelJoint.mets`.
%                      Use '%s' for the tag in `nameTagsModels` for each species.
%                      Default '^%s', the beginning of the string. In this case, if the tag for species 1 is
%                      'SP1', then mets with id 'SP1glc-D[e]' will be identified as belonging to species 1.
%                      E.g., 'met[compartment_SP1]' where 'SP1' is the tag for species 1, input '\[[^_]+_%s\]$'.
%    rxnTagRe:         a regular expression to idenify the tag in `nameTagsModels` from `modelJoint.rxns`.
%                      Default '^%s', the beginning of the string
%    compCom:          compartment Id for the community exchange compartment. Default 'u'
%    compHost:         compartment Id for the exchange compartment specific to the host. Default 'b'
%
% OUTPUTS:
%    names:            structure of reaction/metabolite name (.rxns/.mets) with the following fields:
%
%                        * spAbbr - species abbreviation (= `nameTags`). Host put at the end
%                        * EXcom - #met[u]-by-1 cell. Exchange reactions for community metabolites `met[u]`
%                        * EXhost - #met[b]-by-1 cell. Exchange reactions for host-specific exchange metabolites `met[b]`
%                        * EXsp - #met[u]-by-#species cell. `EXsp(i,j)` is the species-community exchange reactions
%                          for the i-th met[u] and the j-th species
%                        * Mcom - #met[u]-by-1 cell. All community metabolites `met[u]`
%                        * Mhost - #met[u]-by-1 cell. Host-specific exchange metabolites `met[b]`
%                        * Msp - #met[u]-by-#species cell. `Msp(i,j)` is the metabolite in `met[e]` of the `j`-th species
%                          participating in reaction `EXsp(i,j)`
%                        * rxnSps - #rxns-by-1 cell. `rxnSps(i)` would be `spAbbr(j)` if the `i`-th reaction belongs to the `j`-th species
%                        * metSps - #mets-by-1 cell. `metSps(i)` would be `spAbbr(j)` if the i-th metabolite belongs to the `j`-th species
%
%    ids:              structure of reaction/metabolite index with the same fields as names except without `spAbbr`

if nargin < 7 || isempty(compHost)
    compHost = 'b';
end
if nargin < 6 || isempty(compCom)
    compCom = 'u';
end
compHost = regexprep(compHost, '^\[(.*)\]$', '$1');
compCom = regexprep(compCom, '^\[(.*)\]$', '$1');
% regular expression for identifying species
if nargin < 5 || isempty(rxnTagRe)
    rxnTagRe = '^%s';
end
if nargin < 4 || isempty(metTagRe)
    metTagRe = '^%s';
end
metCompartment = getCompartment(modelJoint.mets);
% mets in the common exchange space ([u]) or the biomass (use biomass[c] to be consistent with createMultipleSpeciesModel)
metCom = strcmp(metCompartment, compCom) | strcmp(modelJoint.mets, 'biomass[c]');
% mets in exchange space accessible only by the host ([b])
metHost = strcmp(metCompartment, compHost);
hostExist = any(metHost) && nargin >= 3 && ~isempty(nameTagHost);   % use && to avoid error if nameTagHost not given
if hostExist && iscell(nameTagHost)
    nameTagHost = nameTagHost{1};
end
if ischar(nameTagsModels)
    nameTagsModels = {nameTagsModels};
end
% get the regular expression of identifiers for species-specific mets and rxns
nSp = numel(nameTagsModels);
[metTagReSp, rxnTagReSp] = deal(repmat({''}, nSp + hostExist, 1));
for jSp = 1:nSp
    metTagReSp{jSp} = strrep(metTagRe, '%s', nameTagsModels{jSp});
    rxnTagReSp{jSp} = strrep(rxnTagRe, '%s', nameTagsModels{jSp});
end
metHost = find(metHost);
if hostExist
    % add regular expression for host
    metTagReSp{nSp + 1} = strrep(metTagRe, '%s', nameTagHost);
    rxnTagReSp{nSp + 1} = strrep(rxnTagRe, '%s', nameTagHost);
    % try to sort metHost to have the same order as metCom by comparing met names
    metHostName = regexprep(modelJoint.mets(metHost), metTagReSp{nSp + 1}, '');
    metHostName = strrep(metHostName, ['[' compHost ']'], '');
    metComName = strrep(modelJoint.mets(metCom), ['[' compCom ']'], '');
    [yn, id] = ismember(metComName, metHostName);
    if all(yn) && numel(union(metComName, metHostName)) == numel(metComName)
        % one-to-one mapping exists. Reorder
        metHost = metHost(id);
    end
end

% get system exchange rxns
rxnEX = find(sum(modelJoint.S ~= 0, 1) == 1);
% exchange rxns for mets in [u], in the same order as metCom
[EXcom, ~] = find(modelJoint.S(metCom, rxnEX)');
EXcom = rxnEX(EXcom);
% exchange rxns for mets in [b], in the same order as metHost
[EXhost, ~] = find(modelJoint.S(metHost, rxnEX)');
EXhost = rxnEX(EXhost);

% Get the species number for each met and rxn. 0 for those in [u]
[nMets, nRxns] = size(modelJoint.S);
metSps = zeros(nMets, 1);
rxnSps = zeros(nRxns, 1);
for jSp = 1:nSp
    metSps(~cellfun(@isempty, regexp(modelJoint.mets, metTagReSp{jSp}, 'once')) & ~metCom) = jSp;
    rxnSps(~cellfun(@isempty, regexp(modelJoint.rxns, rxnTagReSp{jSp}, 'once'))) = jSp;
    %     metSps(strncmp(modelJoint.mets, nameTagsModels{j}, numel(nameTagsModels{j})) & ~metCom) = j;
    %     rxnSps(strncmp(modelJoint.rxns, nameTagsModels{j}, numel(nameTagsModels{j}))) = j;
    rxnSps(EXcom) = 0;  % in case some mets or exchange rxns in [u] have prefix equal to the name tags
    % check if the model is properly compartmentalized.
    if nnz(modelJoint.S(metSps == jSp, rxnSps ~= jSp)) > 0 ...
            || nnz(modelJoint.S(metSps ~= jSp & metSps > 0, rxnSps == jSp)) > 0
        error('The model for species %s is not correctly compartmentalized. Check the name tags.');
    end
end
if hostExist
    metSps(~cellfun(@isempty, regexp(modelJoint.mets, metTagReSp{nSp + 1}, 'once')) & ~metCom) = nSp + 1;
    rxnSps(~cellfun(@isempty, regexp(modelJoint.rxns, rxnTagReSp{nSp + 1}, 'once'))) = nSp + 1;
    %     metSps(strncmp(modelJoint.mets, nameTagHost, numel(nameTagHost))) = nSp + 1;
    %     rxnSps(strncmp(modelJoint.rxns, nameTagHost, numel(nameTagHost))) = nSp + 1;
end

% species-community exchange rxns (between members' [e] and [u])
EXeu = any(modelJoint.S(metCom, :), 1);
EXeu(EXcom) = false;  % exclude system input/output exchange rxns
EXeu = find(EXeu);
% EXsp is a #met[u] x #species matrix with (i,j)-entry being the index for exchange reactionn
% for the i-th met in [u] between [u] and [e] of the j-th organism.
% Msp similar but the index for the exchanged metabolite in [e] of the organism
[EXsp, Msp] = deal(zeros(sum(metCom), nSp + hostExist));
for j = 1:numel(EXeu)
    mJcom = find(modelJoint.S(:, EXeu(j)) ~= 0 & metCom);  % met in [u]
    mJsp = find(modelJoint.S(:, EXeu(j)) ~= 0 & ~metCom);  % met in [e]
    EXsp(sum(metCom(1:mJcom)), rxnSps(EXeu(j))) = EXeu(j);
    Msp(sum(metCom(1:mJcom)), rxnSps(EXeu(j))) = mJsp;
end
% store all rxns/mets and their ids
names.spAbbr = nameTagsModels(:);  % species abbreviation
if hostExist
    names.spAbbr = [names.spAbbr; {nameTagHost}];
end
names.spName = names.spAbbr;
names.EXcom = modelJoint.rxns(EXcom);
ids.EXcom = EXcom(:);
names.EXhost = modelJoint.rxns(EXhost);
ids.EXhost = EXhost(:);
names.EXsp = repmat({''}, size(EXsp, 1), size(EXsp, 2));
names.EXsp(EXsp ~= 0) = modelJoint.rxns(EXsp(EXsp ~= 0));
ids.EXsp = EXsp;
names.Mcom = modelJoint.mets(metCom);
ids.Mcom = find(metCom);
names.Mhost = modelJoint.mets(metHost);
ids.Mhost = metHost;
names.Msp = repmat({''}, size(EXsp, 1), size(EXsp, 2));
names.Msp(Msp ~= 0) = modelJoint.mets(Msp(Msp ~= 0));
ids.Msp = Msp;
names.rxnSps = cell(nRxns, 1);
names.rxnSps(rxnSps > 0) = names.spAbbr(rxnSps(rxnSps > 0));
names.rxnSps(rxnSps == 0) = {'com'};
ids.rxnSps = rxnSps;
names.metSps = cell(nMets, 1);
names.metSps(metSps > 0) = names.spAbbr(metSps(metSps > 0));
names.metSps(metSps == 0) = {'com'};
ids.metSps = metSps;


function obj = fcn_autonn_custom_fn(block, inputs, ~)
% FCN_AUTONN_CUSTOM_FN autonn custom layer converter
%
% Copyright (C) 2017 Samuel Albanie
% Licensed under The MIT License [see LICENSE.md for details]

  switch class(block)
    case 'dagnn.Crop'
      obj = vl_nncrop_wrapper(inputs{1}, inputs{2}, block.crop) ;
  end


function [err] = pco_uint32err(error_code)
 if(error_code<0)
  e=error_code*-1;
  err=uint32(e)-1;
  err=bitcmp(err,'uint32');
 else
  err=uint32(error_code);
 end
end


function varargout = tapas_physio_report_contrasts(varargin)
% This function reports all relevant F-contrast-maps for physIO-created regressors
% in a given GLM
%
%  - Section plots on an anatomical overlay are created and saved as
%    post-script file with one page for each contrasts
%
%  - Input parameters are specified via name/value pairs, e.g.
%
%
%   args = tapas_physio_report_contrasts(...
%                   'fileReport', 'physio.ps', ...
%                   'fileSpm', 'analysisFolder/SPM.mat', ...
%                   'filePhysIO', 'analysisFolder/physio.mat', ...
%                   'fileStructural', 'anatomyFolder/warpedAnatomy.nii')
%
% IN
%
%   Required parameters:
%
%                  fileReport: sets the path and file name for the postscript
%                              file your contrast report is printed to.
%                              A reasonable (and default) location is the
%                              single subject analysis folder so the file
%                              resides with the GLM (fileSPM)
%                              default: 'pathSpm/physio_report_contrasts.ps';
%              fileStructural: structural underlay for results,
%                              e.g. 'mean.nii'
%                     fileSpm: SPM.mat holding physiological regressors,
%                              e.g.'SPM.mat'
%                  filePhysIO:  mat-file where PhysIO-object was saved
%                               e.g. physio.mat
%
%   Optional Parameters:
%
%          namesPhysContrasts: cell Array of contrast names in design matrix
%                              e.g. {'All Phys', 'Cardiac', 'Respiratory',
%                               'Card X Resp Interation',
%                               'HeartRateVariability',
%                               'RespiratoryVolumePerTime', 'Movement'}
%
%      indReportPhysContrasts: vector of contrast indices to be reported
%                               e.g. [1:7] for all physiological contrasts
%     reportContrastThreshold: 0.001
%    reportContrastCorrection: 'none' or 'FWE'
%    reportContrastMax:        maximum value of contrast colormap
%                              to scale different contrasts with equal
%                              F-values (default: Inf, scales to max F of
%                              map)
%      reportContrastPosition: 'max' or [1,3] vector of crosshair position
%                               (in mm)
%               fovMillimeter: field of view in mm; set to 0 for full FOV
%         doPlotSliceParallel: if true, slices are plotted parallel to
%                              their slice acquisition direction
%                       model: physio.model-substructure holding
%                              model orders, i.e. .c .r .cr
%                              See also tapas_physio_new
%         titleGraphicsWindow: additional title prepended to contrast name
%                              in each plot
%       saveTable              true of false (default)
%                              prints screenshot of results table to
%                              ps-file as well
%
% OUT
%   args    structure of default and updated arguments used in this
%           function; the fields of args hold all possible options of this
%           function
%
% EXAMPLE
%   tapas_physio_report_contrasts
%
%   See also tapas_physio_overlay_contrasts

% Author: Lars Kasper
% Created: 2014-10-16
% Copyright (C) 2014 TNU, Institute for Biomedical Engineering, University of Zurich and ETH Zurich.
%
% This file is part of the TAPAS PhysIO Toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

%% START #MOD =============================================================

% general paths study
defaults.titleGraphicsWindow = '';
% PhysIO Toolbox code should be in same folder as this file
defaults.filePhysIO      = 'physio.mat';
defaults.fileReport      = 'physio_report_contrasts.ps'; % where contrast maps are saved
defaults.fileStructural  = 'mean.nii';
defaults.fileSpm         = 'SPM.mat';
defaults.drawCrosshair   = true;

defaults.namesPhysContrasts = tapas_physio_get_contrast_names_default();

% selection of physiological contrasts to be reported, corresponding to
% namesPhysContrasts order
defaults.indReportPhysContrasts = 1:9;

defaults.reportContrastThreshold     = 0.001; % 0.05; 0.001;
defaults.reportContrastCorrection    = 'none'; % 'FWE'; 'none';
defaults.reportContrastMax           = Inf;
defaults.reportContrastPosition      = 'max'; % 'max' to jump to max; or [x,y,z] in mm
defaults.fovMillimeter               = 0; %mm; choose 0 to plot whole FOV (bounding box)

% if true, voxel space (parallel to slices), not world space (with interpolation) is used
defaults.doPlotSliceParallel          = true;
defaults.saveTable                    = false;
physio                                = tapas_physio_new('RETROICOR');
defaults.model                        = physio.model; % holding number of physiological regressors

% END #MOD
%% ========================================================================

args = tapas_physio_propval(varargin, defaults);
tapas_physio_strip_fields(args);

spm('defaults', 'FMRI');

% make sure to use absolute paths from now on...
fileSpm = tapas_physio_filename2path(fileSpm);
fileStructural = tapas_physio_filename2path(fileStructural);
fileReport = tapas_physio_filename2path(fileReport);
filePhysIO = tapas_physio_filename2path(filePhysIO);

load(fileSpm);
nContrasts = numel(indReportPhysContrasts);

if ~exist(fileStructural, 'file')
    % take standard structural from SPM, if overlay file does not exist
    pathSpm = fileparts(which('spm'));
    fileStructural = fullfile(pathSpm, 'canonical', 'avg152T1.nii');
end

% if input file given, load PhysIO-object
if exist(filePhysIO, 'file')
    load(filePhysIO, 'physio');
    model = physio.model;
end

% Temporarily set window style to undocked, so that SPM opens as usual
tmpWindowStyle = get(0, 'DefaultFigureWindowStyle');
set(0, 'DefaultFigureWindowStyle', 'normal');

% create physiological contrasts that don't exist so far and can be created
% due to the model components included
SPM = tapas_physio_create_missing_physio_contrasts(SPM, model, namesPhysContrasts);

%% report contrasts with overlays

for c = 1:nContrasts
    iC = indReportPhysContrasts(c);
    idxContrasts(c) = tapas_physio_check_get_xcon_index(SPM, ...
        namesPhysContrasts{iC});
end

idxContrasts = idxContrasts(idxContrasts > 0);

% TODO: harmonize option labels in both functions
tapas_physio_overlay_contrasts( ...
    'idxContrasts', idxContrasts, ...
    'titleGraphicsWindow', titleGraphicsWindow, ...
    'fileReport', fileReport, ...
    'fileSpm', fileSpm, ...
    'fileStructural', fileStructural, ...
    'threshold', reportContrastThreshold, ...
    'correction', reportContrastCorrection, ...
    'doPlotSliceParallel', doPlotSliceParallel, ...
    'fovMillimeter', fovMillimeter, ...
    'position', reportContrastPosition, ...
    'drawCrosshair', drawCrosshair, ...
    'colorbarMax', reportContrastMax, ...
    'saveTable', saveTable);

if nargout
    varargout{1} = args;
end


% STD_MAKETRIALINFO - create trial information structure using the
%                       .epoch structure of EEGLAB datasets
%
% Usage:
%   >> [STUDY,trialinfo] = std_maketrialinfo(STUDY, ALLEEG);
%   >> [~,trialinfo]     = std_maketrialinfo([], EEG);
%
% Inputs:
%   STUDY      - EEGLAB STUDY set
%   ALLEEG     - vector of the EEG datasets included in the STUDY structure
%
% Inputs:
%   STUDY      - EEGLAB STUDY set updated. The fields which is created or
%                updated is STUDY.datasetinfo.trialinfo
%   trialinfo  - Trial information structure (cell array)
%
% Authors: Arnaud Delorme, SCCN/INC/UCSD, April 2010

% Copyright (C) Arnaud Delorme arno@ucsd.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function [STUDY,alltrialinfo] = std_maketrialinfo(STUDY, ALLEEG)

%% test if .epoch field exist in ALLEEG structure
epochfield = cellfun(@isempty, { ALLEEG.epoch });
if any(epochfield)
    fprintf('Warning: some datasets are continuous and trial information cannot be created. Please use [ALLEEG.trials] to see which ones.\n');
    return;
end

for iEEG = 1:length(ALLEEG)
    % fill in empty field values and fill in with values in the same epoch
    ALLEEG(iEEG) = eeg_uniformepochinfo(ALLEEG(iEEG));
end

%% check if conversion of event is necessary
ff = {};
flagConvert = true;
for index = 1:length(ALLEEG), ff = union(ff, fieldnames(ALLEEG(index).event)); end
for iField = 1:length(ff)

    fieldChar = zeros(1,length(ALLEEG))*NaN;
    for index = 1:length(ALLEEG)
        if isfield(ALLEEG(index).event, ff{iField})
            if ischar(ALLEEG(index).event(1).(ff{iField}))
                 fieldChar(index) = 1;
            else fieldChar(index) = 0;
            end
        end
    end
    if ~all(fieldChar(~isnan(fieldChar)) == 1) && ~all(fieldChar(~isnan(fieldChar)) == 0)
        % need conversion to char
        for index = 1:length(ALLEEG)
            if fieldChar(index) == 0
                if flagConvert, disp('Warning: converting some event fields to strings - this may be slow'); flagConvert = false; end
                for iEvent = 1:length(ALLEEG(index).event)
                    ALLEEG(index).event(iEvent).(ff{iField}) = num2str(ALLEEG(index).event(iEvent).(ff{iField}));
                end
            end
        end
    end
end

%% Make trial info
for index = 1:length(ALLEEG)
    tmpevent = ALLEEG(index).event;
    eventlat = abs(eeg_point2lat( [ tmpevent.latency ], [ tmpevent.epoch ], ALLEEG(index).srate, [ALLEEG(index).xmin ALLEEG(index).xmax]));
    events   = ALLEEG(index).event;
    ff = fieldnames(events);
    ff = setdiff_bc(ff, { 'latency' 'urevent' 'epoch' });
    trialinfo = [];

    % process time locking event fields
    % ---------------------------------
    indtle    = find(eventlat == 0);
    epochs    = [ events(indtle).epoch ];
    extractepoch = true;

    % Double checking and changing threshold
    if length(epochs) < ALLEEG(index).trials
        indtle    = find(eventlat < 0.02);
        epochs    = [ events(indtle).epoch ];
    end

    if length(epochs) ~= ALLEEG(index).trials
        % special case where there are not the same number of time-locking
        % event as there are data epochs
        if length(unique(epochs)) ~= ALLEEG(index).trials
            extractepoch = false;
            disp('std_maketrialinfo: not the same number of time-locking events as trials, trial info ignored');
        else
            % pick one event per epoch
            [tmp tmpind] = unique_bc(epochs(end:-1:1)); % reversing the array ensures the first event gets picked
            tmpind = length(epochs)+1-tmpind;
            indtle = indtle(tmpind);
            if length(indtle) ~= ALLEEG(index).trials
                extractepoch = false;
                disp('std_maketrialinfo: not the same number of time-locking events as trials, trial info ignored');
            end
        end
    end
    if extractepoch
        commands = {};
        for f = 1:length(ff)
            eval( [ 'eventvals = {events(indtle).' ff{f} '};' ]);
            %if isnumeric(eventvals{1})
                %eventvals = cellfun(@num2str, eventvals, 'uniformoutput', false);
            %    eventvals = [ eventvals{:} ];
            %end
            commands = { commands{:} ff{f} eventvals };
        end
        trialinfo = struct(commands{:});
        STUDY.datasetinfo(index).trialinfo = trialinfo;
    end
    alltrialinfo{index} = trialinfo;

%    % same as above but 10 times slower
%     for e = 1:length(ALLEEG(index).event)
%         if eventlat(e) < 0.0005 % time locking event only
%             epoch = events(e).epoch;
%             for f = 1:length(ff)
%                 fieldval  = getfield(events, {e}, ff{f});
%                 trialinfo = setfield(trialinfo, {epoch}, ff{f}, fieldval);
%             end
%         end
%     end
end

% check HED field with unicode characters
% ---------------------------------------
if isfield(STUDY.datasetinfo, 'trialinfo')
    if isfield(STUDY.datasetinfo(1).trialinfo(1), 'HED')
        changeUnicode = false;
        for iDat = 1:length(STUDY.datasetinfo)
            for iTrial = 1:length(STUDY.datasetinfo(iDat).trialinfo)
                STUDY.datasetinfo(iDat).trialinfo(iTrial).HED(STUDY.datasetinfo(iDat).trialinfo(iTrial).HED > 255) = 32;
                changeUnicode = true;
            end
        end
        if changeUnicode
            disp('Unicode character detected in HED event field, removing them to improve stability');
        end
    end
end


function convertDicom2Vista_UU_UMC(subjectName,SkipVols,TR,SessionName)
% convertDicom2Vista_UU_UMC(subjectName,SkipVols,TR,SessionName)
%
%
% Input:
%   subjectName: subject last name, no capitals
%   SkipVols: number of initial time-frames to remove from the data
%   TR: repetition time of fMRI scanner (should really get from the data)
%   SessionName: name of the experiment
%
% The script takes (3D) nifti files converted usign r2agui and converts
% them to mrVista format.
%
% It is adapted from prepareUCSFParnassusUniversal and relies on spm(5) to
% read the nifti files.
%

%% Some checks

if(isempty(which('spm_dicom_headers')))
    error('Requires spm2+ tools! I recommend spm5');
end
if ~exist('subjectName','var') || isempty(subjectName)
    error('Need the lastname of subject as input');
end
if ~exist('SessionName','var') || isempty(SessionName)
    error('Need SessionName, i.e. what is the experiment called');
end
if ~exist('SkipVols','var') || isempty(SkipVols);
    error('Need SkipVols, i.e. the number of initial time frames to remove from the data');
end
if ~exist('TR','var') || isempty(TR);
    error('Need TR, FIX ME I need to be able to read this from the data');
end

%% Clean up old mrVista structure
fprintf('[%s]:WARNING:Removing old mrVista structures!',mfilename);
if exist('mrSESSION_backup.mat','file')
    delete mrSESSION_backup
end
if exist('mrSESSION.mat','file')
    delete mrSESSION
end
if exist('prepareUUvars.mat','file')
    delete prepareUUvars.mat
end

%% Some defaults
if ~exist('Raw','dir')
    error('Data needs to be stored in directories under Raw directory');
end
RawDir = 'Raw';

%% find scans
d = dir(RawDir);
% find directory names
d = d([d.isdir]);
% remove '.' and '..'
remove = false(numel(d),1);
for n=1:numel(d)
    if strcmp(d(n).name,'.') || strcmp(d(n).name,'..')
        remove(n) = true;
    end
end
dirs = d(~remove);

if isempty(dirs)
    fprintf(1,'[%s]:WARNING:No directories found in %sRaw\n',mfilename,filesep);
    if ~isempty(dir(fullfile(RawDir,'*nii*')))
        dirs(1).name = [];
        fprintf(1,'[%s]:WARNING:But found nifti files continuing...\n',mfilename);
    else
        fprintf(1,'[%s]:WARNING:EXITING.\n',mfilename);
        return
    end
end

%% find functionals
c = 0;
for n=1:numel(dirs)
    % find files
    f = dir(fullfile(RawDir,dirs(n).name,'*.nii'));

    if numel(f)>10
        c = c+1;
        foundScans(c).Action = 'Functional'; %#ok<AGROW>

        hdr = spm_vol(['Raw/' dirs(n).name filesep f(1).name]);
        if c==1
            roughAlignment = hdr.mat;
        end

        % sort files in order
        fileNameOrder=zeros(numel(f),1);
        % hack time number is after (-)
        for ii=1:numel(f)
            sep1 = findstr(f(ii).name,'-');
            sep2 = findstr(f(ii).name,'.');
            fileNameOrder(ii) = str2double(f(ii).name(sep1+1:sep2-1));
        end
        [junk,sIndex] = sort(fileNameOrder); % Because we don't know how DIR might order the output
        f             = f(sIndex); % Apply the sort

        foundScans(c).FileNames = cell(numel(f),1); %#ok<AGROW>
        for ii=1:numel(f);
            foundScans(c).FileNames{ii} = f(ii).name; %#ok<AGROW>
        end
        foundScans(c).DirName   = dirs(n).name;%#ok<AGROW>
        foundScans(c).Sequence  = hdr.descrip;%#ok<AGROW>
        foundScans(c).SkipVols  = SkipVols;%#ok<AGROW>
        foundScans(c).Cycles    = 8;%#ok<AGROW>

        foundScans(c).TR        = TR;%#ok<AGROW>
        foundScans(c).RawDir    = RawDir;%#ok<AGROW>
        foundScans(c).Files     = numel(f);%#ok<AGROW>
        foundScans(c).Slices    = hdr.dim(3);%#ok<AGROW>
        foundScans(c).Volumes   = numel(f);%#ok<AGROW>
    else
        c = c+1;
        foundScans(c).Action = 'Anatomical'; %#ok<AGROW>

        hdr = spm_vol(['Raw/' dirs(n).name filesep f(1).name]);
        if c==1
            roughAlignment = hdr.mat;
        end

        % sort files in order
        fileNameOrder=zeros(numel(f),1);
        % hack time number is after (-)
        for ii=1:numel(f)
            sep1 = findstr(f(ii).name,'-');
            sep2 = findstr(f(ii).name,'.');
            fileNameOrder(ii) = str2double(f(ii).name(sep1+1:sep2-1));
        end
        [junk,sIndex] = sort(fileNameOrder); % Because we don't know how DIR might order the output
        f             = f(sIndex); % Apply the sort

        foundScans(c).FileNames = cell(numel(f),1); %#ok<AGROW>
        for ii=1:numel(f);
            foundScans(c).FileNames{ii} = f(ii).name; %#ok<AGROW>
        end
        foundScans(c).DirName   = dirs(n).name;%#ok<AGROW>
        foundScans(c).Sequence  = hdr.descrip;%#ok<AGROW>
        foundScans(c).SkipVols  = SkipVols;%#ok<AGROW>
        foundScans(c).Cycles    = 8;%#ok<AGROW>

        foundScans(c).TR        = TR;%#ok<AGROW>
        foundScans(c).RawDir    = RawDir;%#ok<AGROW>
        foundScans(c).Files     = numel(f);%#ok<AGROW>
        foundScans(c).Slices    = hdr.dim(3);%#ok<AGROW>
        foundScans(c).Volumes   = numel(f);%#ok<AGROW>
    end
end

disp('Making directories');
mkdir('Inplane');
mkdir('Volume');
mkdir('Gray');

save prepareUUvars

status=mrInitRetFromNifti(foundScans,lower(subjectName),SessionName);

disp('Result of mrInitRetFromNifti');
disp(status);

loadSession;
mrSESSION.alignment = roughAlignment;
saveSession;

return


function [trMatrix,elecStatus] = fns_read_transfer(datafile)
% Note that Data only stores the potential values for nodes, which  belong to
% the head

trMatrix      = hdf5read(datafile, '/forward/transfer_matrix');
elecStatus    = hdf5read(datafile, '/forward/status');


function ui = mrViewMeshMenu(ui);
%
% ui = mrViewMeshMenu(ui);
%
% Attaches a mesh menu to a mrViewer UI. Initializes
% it to be hidden, until a segmentation is loaded.
%
% ras 07/05.
if ~exist('ui', 'var') | isempty(ui),  ui = get(gcf, 'UserData'); end

ui.menus.mesh = uimenu(ui.fig, 'Label', 'Mesh');

%%%%%mesh build, display, close options
hFile = uimenu(ui.menus.mesh, 'Label', 'Build \ Open \ Close', ...
                              'Separator', 'off');

cb = 'mrViewLoad(gcf, [], ''Mesh''); mrViewDisplayMesh; ';
ui.menus.meshLoadDisp = uimenu(hFile, 'Label', 'Load and Display', ...
                        'Callback', cb);

ui.menus.meshBuild = uimenu(hFile, 'Label', 'Build Mesh', ...
                        'Separator', 'on', 'Callback', 'mrViewBuildMesh; ');

ui.menus.meshSave = uimenu(hFile, 'Label', 'Save Selected Mesh', ...
                        'Callback', 'mrViewSave(gcf, [], ''Mesh''); ');

ui.menus.meshDisp = uimenu(hFile, 'Label', 'Display Selected Mesh', ...
                        'Callback', 'mrViewDisplayMesh;');

cb = 'mrmSet( mrViewGet(gcf, ''CurMesh''), ''Close'' ); ';
ui.menus.meshCloseDisp = uimenu(hFile, 'Label', 'Close Mesh Display', ...
                        'Callback', cb);

ui.menus.meshClose = uimenu(hFile, 'Label', 'Close Mesh', ...
                        'Callback', 'mrViewCloseMesh(gcf);');

%%%%%project data onto mesh options
ui.menus.meshUpdate = uimenu(ui.menus.mesh, 'Label', 'Project Data Onto Mesh', ...
                            'Separator', 'on', 'Callback', 'mrViewMesh(gcf); ');
ui.menus.meshUpdateAll = uimenu(ui.menus.mesh, 'Label', 'Update All Meshes', ...
                            'Separator', 'off', 'Callback', 'mrViewUpdateAllMeshes; ', ...
                            'Accelerator', '0');

%%%%%mesh smooth, revert options
hInflate = uimenu(ui.menus.mesh, 'Label', 'Inflation', 'Separator', 'on');

cb = ['tmp = mrViewGet(gcf, ''CurMesh''); ' ...
      'tmp = meshSmooth(tmp); ' ...
      'mrViewSet(gcf, ''CurMesh'', tmp); ' ...
      'clear tmp '];
ui.menus.meshSmooth = uimenu(hInflate, 'Label', 'Inflate Mesh', ...
                        'Separator', 'off', 'Callback', cb);

cb = ['tmp = mrViewGet(gcf, ''CurMesh''); ' ...
      'tmp = meshSmooth(tmp, 1); ' ...
      'mrViewSet(gcf, ''CurMesh'', tmp); ' ...
      'clear tmp '];
ui.menus.meshSmooth2 = uimenu(hInflate, 'Label', 'Inflate (Set Params)', ...
                                        'Callback', cb);

cb = ['tmp = mrViewGet(gcf, ''CurMesh''); ' ...
      'tmp = meshSet(tmp, ''Vertices'', meshGet(tmp, ''InitialVertices'')); ' ...
      'tmp = meshSet(tmp, ''Smooth_Relaxation'', 0); ' ...
      'mrmSet(tmp, ''Vertices''); ' ...
      'mrViewSet(gcf, ''CurMesh'', tmp); ' ...
      'clear tmp '];
ui.menus.meshRevert = uimenu(hInflate, 'Label', 'Revert to InitVertices', ...
                                       'Callback', cb);

%%%%%display tools (screenshot, multi-angle, movie)
hDisp = uimenu(ui.menus.mesh, 'Label', 'Display Tools', 'Separator', 'off');

ui.menus.meshPrefs = uimenu(hDisp, 'Label', 'Set Mesh Preferences', ...
                            'Accelerator', '.', 'Callback', 'mrmPreferences');

ui.menus.meshToggleCursor = uimenu(hDisp, 'Label', 'Toggle Cursor', ...
						'Accelerator', '/', ...
						'Callback', 'meshToggleCursor(mrViewGet(gcf, ''mesh''));');

% recolor sulcul/gyral curvature
cb = ['msh = mrViewGet(gcf, ''CurMesh''); ' ...
	 'msh = meshColor(msh, 1); ' ...
	 'mrViewSet(gcf, ''CurMesh'', msh); ' ...
	 'mrViewMesh(gcf); '...
	 'clear msh '];
uimenu(hDisp, 'Label', 'Set Sulcus/Gyrus Modulation', 'Callback', cb);

% Set lighting parameters
uimenu(hDisp, 'Label', 'Set Lighting Levels', 'Callback', 'mrViewMeshLighting;');

% Take mesh snapshot
cb = ['img = mrmGet( mrViewGet(gcf, ''Mesh''), ''screenshot'' ) ./ 255; ' ...
	  'hTmp = figure(''Color'', ''w''); ' ...
	  'imagesc(img); axis image; axis off; ' ...
	  'try, figToCB(hTmp); end; clear hTmp; '...
	  'disp(''Image copied to clipboard as well as variable "img".'')'];
uimenu(hDisp, 'Label', 'Copy Mesh Image to Clipboard', 'Callback', cb);

ui.menus.meshBgColor = uimenu(hDisp, 'Label', 'Set background color...');

% individual callbacks for different colors
colors = {[0 0 0], [.3 .3 .3], [1 1 1], [0 .1 .8]};
names = {'black' 'gray' 'white' 'blue'};
for i = 1:length(colors)
    ui.menus.meshBgColor(i+1) = uimenu(ui.menus.meshBgColor(1), ...
        'Label', names{i}, 'UserData', colors{i}, 'Separator', 'off', ...
        'Callback', 'mrViewSet(gcf, ''MeshBackground'', gcbo); ');
end

cb = 'meshMultiAngle2(mrViewGet(gcf, ''CurMesh''), ''dialog''); ';
ui.menus.meshMultiAngle = uimenu(hDisp, 'Label', 'Multi-Angle Snapshot', ...
                                    'Separator', 'off', 'Callback', cb);

cb = ['VOLUME{1}.mesh{1} = mrViewGet(gcf, ''mesh''); ' ...
	  'meshMovie(VOLUME{1}); ' ...
	  'VOLUME{1}.mesh = {}; '];
ui.menus.meshMovie = uimenu(hDisp, 'Label', 'Mesh Movie', ...
						'Separator', 'off', 'Callback', cb);

%%%%%ROI tools
hRoi = uimenu(ui.menus.mesh, 'Label', 'Mesh ROIs', 'Separator', 'off');

ui.menus.meshCursor = uimenu(hRoi, 'Label', 'Get Cursor Position From Mesh', ...
						'Callback', 'mrViewSetCursorFromMesh(gcf); ');

ui.menus.meshROI1 = uimenu(hRoi, 'Label', 'Get From Mesh (Layer 1)', ...
						'Callback', 'mrViewROI(''mesh'', gcf, ''layer1'');');

ui.menus.meshROI2 = uimenu(hRoi, 'Label', 'Get From Mesh (All Layers)', ...
						'Callback', 'mrViewROI(''mesh'', gcf, ''all'');');

ui.menus.diskROI = uimenu(hRoi, 'Label', 'Create Disk ROI', ...
							'Callback', 'mrViewROI(''disk'', gcf);');

%%%%%select segmentation submenu
% (will be added to in mrViewLoad([], [], 'segmentation'))
ui.menus.meshSeg = uimenu(ui.menus.mesh, 'Label', 'Selected Segmentation', ...
                          'Separator', 'on');

%%%%%select mesh submenu (will be added to in mrViewLoad([], [], 'mesh'))
ui.menus.meshSelect = uimenu(ui.menus.mesh, 'Label', 'Selected Mesh', ...
                             'Separator', 'off');

% initialize to invisible, until a segmentation is loaded
set(ui.menus.mesh, 'Visible', 'off');

return


% this function is dedicated for crossover operation used by MATLAB ga
% function.
function mutationChildren = SP_mutation(parents ,options,NVARS, ...
    FitnessFcn, state, thisScore,thisPopulation,mutationRate)

mutationChildren = cell(length(parents),1);% Normally zeros(length(parents),NVARS);
for i=1:length(parents)
    parent = thisPopulation{parents(i)}; % Normally thisPopulation(parents(i),:)
    p = ceil(length(parent) * rand(1,2));
    child = parent;
    child(p(1)) = parent(p(2));
    child(p(2)) = parent(p(1));
    mutationChildren{i} = child; % Normally mutationChildren(i,:)
end


function [exp,waschanged] = exp_replacerepeated(exp,rules)
% Apply substitution rules to some expression until it no longer changes.
% [Out-Expression,Changed] = exp_replacerepeated(In-Expression,Rule-List)
%
% Rules may contain blanks and placeholders.
%
% In:
%   In-Expression : some expression in which substitution shall take place
%   Rule-List     : cell array of substutition rules; may also be a struct, where field names are
%                   taken as symbol names
%
% Out:
%   Out-Expression     : In-Expression with substitutions performed
%   Changed            : whether a replacement has taken place
%
% Notes:
%   Impure expressions degrade into pure expressions when substitutions are performed on them (i.e.
%   they lose their value).
%
% See also:
%   exp_replaceall, exp_match
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-04-19

if ~exp_beginfun('symbolic') return; end

[exp,waschanged] = utl_replacerepeated(exp,rules);

exp_endfun;


function gB = flip(gB,ind)
% flip a boundary from phase1/phase2 to phase2/phase1
%
% Syntax
%   gB = flip(gB) % flip all boundaries
%   gB = flip(gB,ind) % flip the boundaries specified in ind
%
% Input
%  gB  - @grainBoundary
%  ind - indeces of the boundaries to flip
%
% Output
%  grains - @grainBoundary
%

if nargin == 2
  gB.ebsdId(ind,:) = fliplr(gB.ebsdId(ind,:));
  gB.grainId(ind,:) = fliplr(gB.grainId(ind,:));
  gB.phaseId(ind,:) = fliplr(gB.phaseId(ind,:));
  gB.misrotation(ind) = inv(gB.misrotation(ind));
else
  gB.eebsdId = fliplr(gB.ebsdId);
  gB.grainId = fliplr(gB.grainId);
  gB.phaseId = fliplr(gB.phaseId);
  gB.misrotation = inv(gB.misrotation);
end


% OtMatrixCubeSet Put a matrix into a matrix cube.
%
% Usage:
%    OtMatrixCubeSet(hmcube, pmtu, matrix)
% where:
%    hmcube matrix cube handle as created by OtMatrixCubeNew()
%    pmtu   is a PMTU struct as created by OtPmtu(),
%    matrix is the matrix to store in the cube
%

% OtMatlab: Matlab interface to the Omnitrans transport planning software

% Copyright (c) 2008, VORtech Computing
% Copyright (c) 2010, Omnitrans International

% All rights reserved.

% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:

%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * Redistributions in binary form must reproduce the above copyright
%       notice, this list of conditions and the following disclaimer in
%       the documentation and/or other materials provided with the distribution
%     * Neither the name of VORtech Computing and Omnitrans International nor the names
%       of its contributors may be used to endorse or promote products derived
%       from this software without specific prior written permission.

% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.

% 2006-04-19 Created (Johan Meijdam, VORtech)

function iret = OtMatrixCubeSet(hmcube, pmtu, matrix)
	iret = Ot('matrixcube.set', hmcube, pmtu, matrix);
end