function f = eval(SO3F,rot,varargin)
% pointwise evaluation of SO3F at rotations rot
%
% sum_i \sum_j \sum_k  weights * psi(g*s_j h_i . s_k r_i)

% if isa(rot,'orientation')
%   ensureCompatibleSymmetries(SO3F,rot)
% end

s = size(rot);
rot = rot(:);

h = symmetrise(SO3F.h.normalize,'unqiue');

% rot x SS x CS x h
gh = reshape((SO3F.SS.properGroup * rot).' * h, length(rot),[],length(SO3F.h));

f = mean(SO3F.psi.eval(dot(gh,reshape(normalize(SO3F.r),1,1,[]),'noSymmetry')),2);

f = reshape(reshape(f,length(rot),[]) * SO3F.weights,s);

if isalmostreal(f)
  f = real(f);
end


function [L,e] = spm_mci_like_ind (P,R,M,U,Y)
% Compute likelihood wrt selected time points
% FORMAT [L,e] = spm_mci_like_ind (P,R,M,U,Y)
%
% P         Flow parameters
% R         Initial state parameters
% M         Model structure
% U         Inputs  [Nin x N]
% Y         data
%
% L         Log likelihood
% e         Prediction errors
%__________________________________________________________________________
% Copyright (C) 2015 Wellcome Trust Centre for Neuroimaging

% Will Penny and Biswa Sengupta
% $Id: spm_mci_like_ind.m 6697 2016-01-27 14:57:28Z spm $

% Read data points and time indices
try, ind=Y.ind; catch, ind=1:M.N; end
Nt=length(ind);
y=Y.y;

M.x0=R; % Initial conditions
[G,sy,st] = spm_mci_fwd (P,M,U);

if st==-1, disp('Problem !'); return; end

% Prediction errors
g=G(ind,:);
e=Y.y-g;

% Log Likelihood
L = -0.5*trace(M.iCe*e'*e) + M.logdet_Ce - 0.5*Nt*log(2*pi);


function tests = test_ft_connectivity_mim

% MEM 1gb
% WALLTIME 00:10:00
% DEPENDENCY ft_connectivity_mim

if nargout
  % assume that this is called by RUNTESTS
  tests = functiontests(localfunctions);
else
  % assume that this is called from the command line
  func = localfunctions;
  for i=1:numel(func)
    fprintf('evaluating %s\n', func2str(func{i}));
    feval(func{i});
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function test_chan_chan_freq(testCase)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

nchan   = 6;
nfreq   = 5;
dimord  = 'chan_chan_freq';
input   = zeros(nchan, nchan, nfreq);

for freq=1:nfreq
  fdat = 10 * randn(nchan, 1) + 1i * 10 * randn(nchan, 1);
  input(:,:,freq) = fdat * ctranspose(fdat); % compute the cross-spectral density
end

result = {};
result{end+1} = ft_connectivity_cancorr(input, 'dimord', dimord, 'indices', [1 1 2 2 3 3]); % e.g. three pair of planar channels
result{end+1} = ft_connectivity_cancorr(input, 'dimord', dimord, 'indices', [1 1 1 2 2 2]); % e.g. two dipole moments (xyz)

% all iterations were done with (slightly) different options, hence the results should not be equal
for i=1:numel(result)
  for j=(i+1):numel(result)
    assert(~isequaln(result{i}, result{j}), 'the results %d and %d should not be equal', i, j);
  end
end


function risultati = fhme(net, nodes_info, data, n)
%HMEFWD	Forward propagation through an HME model
%
% Each row of the (n x class_num) matrix 'risultati' containes the estimated class posterior prob.
%
% ----------------------------------------------------------------------------------------------------
% -> pierpaolo_b@hotmail.com   or   -> pampo@interfree.it
% ----------------------------------------------------------------------------------------------------
%
ns=net.node_sizes;
if nargin==3
    ndata=n;
else
    ndata=size(data, 1);
end
altezza=size(ns,2);
coeff=cell(altezza-1,1);
for m=1:ndata
    %- i=2 --------------------------------------------------------------------------------------
    s=struct(net.CPD{2});
    if nodes_info(1,2)==0,
        mu=[]; W=[]; predict=[];
        mu=s.mean(:,:);
        W=s.weights(:,:,:);
        predict=mu(:,:)+W(:,:,:)*data(m,:)';
        coeff{1,1}=predict';
    elseif nodes_info(1,2)==1,
        coeff{1,1}=fglm(s.glim{1}, data(m,:));
    else,
        coeff{1,1}=fmlp(s.mlp{1}, data(m,:));
    end
    %----------------------------------------------------------------------------------------------
    if altezza>3,
        for i=3:altezza-1,
            s=[]; f=[]; dpsz=[];
            f=family(net.dag,i); f=f(2:end-1); dpsz=prod(ns(f));
            s=struct(net.CPD{i});
            for j=1:dpsz,
                if nodes_info(1,i)==1,
                    coeff{i-1,1}(j,:)=coeff{i-2,1}(1,j)*fglm(s.glim{j}, data(m,:));
                else
                    coeff{i-1,1}(j,:)=coeff{i-2,1}(1,j)*fmlp(s.mlp{j}, data(m,:));
                end
            end
            app=cat(2, coeff{i-1,1}(:)); coeff{i-1,1}=app'; clear app;
        end
    end
    %- i=altezza ----------------------------------------------------------------------------------
    if altezza>2,
        i=altezza;
        s=[]; f=[]; dpsz=[];
        f=family(net.dag,i); f=f(2:end-1); dpsz=prod(ns(f));
        s=struct(net.CPD{i});
        if nodes_info(1,i)==0,
            mu=[]; W=[];
            mu=s.mean(:,:);
            W=s.weights(:,:,:);
        end
        for j=1:dpsz,
            if nodes_info(1,i)==0,
                predict=[];
                predict=mu(:,j)+W(:,:,j)*data(m,:)';
                coeff{i-1,1}(j,:)=coeff{i-2,1}(1,j)*predict';
            elseif nodes_info(1,i)==1,
                coeff{i-1,1}(j,:)=coeff{i-2,1}(1,j)*fglm(s.glim{j}, data(m,:));
            else
                coeff{i-1,1}(j,:)=coeff{i-2,1}(1,j)*fmlp(s.mlp{j}, data(m,:));
            end
        end
    end
    %----------------------------------------------------------------------------------------------
    risultati(m,:)=sum(coeff{altezza-1,1},1);
    clear coeff; coeff=cell(altezza-1,1);
end
return

%-------------------------------------------------------------------

function [y, a] = fglm(net, x)
%GLMFWD	Forward propagation through 1-layer net->GLM statistical model

ndata = size(x, 1);

a = x*net.w1 + ones(ndata, 1)*net.b1;

nout = size(a,2);
% Ensure that sum(exp(a), 2) does not overflow
maxcut = log(realmax) - log(nout);
% Ensure that exp(a) > 0
mincut = log(realmin);
a = min(a, maxcut);
a = max(a, mincut);
temp = exp(a);
y = temp./(sum(temp, 2)*ones(1,nout));

%-------------------------------------------------------------------

function [y, z, a] = fmlp(net, x)
%MLPFWD	Forward propagation through 2-layer network.

ndata = size(x, 1);

z = tanh(x*net.w1 + ones(ndata, 1)*net.b1);
a = z*net.w2 + ones(ndata, 1)*net.b2;
temp = exp(a);
nout = size(a,2);
y = temp./(sum(temp,2)*ones(1,nout));

%-------------------------------------------------------------------


%
% LibQPEP: A Library for Globally Optimal Solving Quadratic Pose Estimation Problems (QPEPs),
%          It also gives highly accurate uncertainty description of the solutions.
%
%
% Article:
%      Wu, J., Zheng, Y., Gao, Z., Jiang, Y., Hu, X., Zhu, Y., Jiao, J., Liu, M. (2020)
%           Quadratic Pose Estimation Problems: Globally Optimal Solutions,
%           Solvability/Observability Analysis and Uncertainty Description.
%           IEEE Transactions on Robotics.
%           https://doi.org/10.1109/TRO.2022.3155880
%
%
% Authors:      Jin Wu and Ming Liu
% Affiliation:  Hong Kong University of Science and Technology (HKUST)
% Emails:       jin_wu_uestc@hotmail.com; eelium@ust.hk
% Websites:     https://zarathustr.github.io
%               https://ram-lab.com
%
%
% test_stewart.m: The QPEP illustration of forwart kinematics of hexapod
%                 Stewart platform

clear all
close all
clc

if(verLessThan('matlab', '8.0.0'))
   error('The MATLAB version is too old to be supported.');
end

format long g

addpath('func_files');
addpath('solvers');
addpath('utils');
addpath('homotopy');

R0 = angle2dcm(-8 * pi / 180, 12 * pi / 180, -15 * pi / 180, 'XYZ');
q0 = dcm2quat(R0).';
if(q0(1) < 0)
    q0 = - q0;
end
t0 = 1e-2 * randn(3, 1);
X0 = inv([R0, t0;
     zeros(1, 3), 1]);

base = [
     0.1448888739433600, 1,  0.0388228567653781;
    -0.0388228567653781, 1,  0.1448888739433600;
    -0.1060660171779820, 1,  0.1060660171779820;
    -0.1060660171779820, 1, -0.1060660171779820;
    -0.0388228567653781, 1, -0.1448888739433600;
     0.1448888739433600, 1, -0.0388228567653781;
    ].';
plat = [
     0.0707106781186548, 1, 0.07071067811865480;
     0.0258819045102521, 1, 0.09659258262890680;
    -0.0965925826289068, 1, 0.02588190451025210;
    -0.0965925826289068, 1, -0.0258819045102521;
     0.0258819045102521, 1, -0.0965925826289068;
     0.0707106781186548, 1, -0.0707106781186548;
    ].';

conv = [
    1, 0, 0;
    0, 0, 1;
    0, -1, 0;
    ];
height = 0.15;
base = conv * base;
plat = conv * plat;
plat(3, :) = plat(3, :) + height;
plat00 = plat;
base00 = base;

leg0 = zeros(6, 1);
plat0 = zeros(3, 6);
for i = 1 : 6
    plat0(:, i) = R0 * plat(:, i)  + t0;
    res = base(:, i) - plat0(:, i);
    leg0(i) = sqrt(res.' * res);
end
colors = linspecer(8);

figure(1);
subplot(1, 2, 1);
plot3(base(1, :), base(2, :), base(3, :), 'LineStyle', 'None', 'Marker', '.', 'MarkerSize', 10); hold on
plot3(base(1, 1 : 6), base(2, 1 : 6), base(3, 1 : 6), 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
plot3([base(1, 1), base(1, 6)], [base(2, 1), base(2, 6)], [base(3, 1), base(3, 6)], 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
plot3(plat0(1, :), plat0(2, :), plat0(3, :), 'LineStyle', 'None', 'Marker', '.', 'MarkerSize', 10); hold on
plot3(plat0(1, 1 : 6), plat0(2, 1 : 6), plat0(3, 1 : 6), 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
plot3([plat0(1, 1), plat0(1, 6)], [plat0(2, 1), plat0(2, 6)], [plat0(3, 1), plat0(3, 6)], 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
for i = 1 : 6
    plot3([base(1, i), plat0(1, i)], [base(2, i), plat0(2, i)], [base(3, i), plat0(3, i)], 'LineStyle', '-', 'LineWidth', 4, 'Marker', 'None'); hold on
end
hold on
fill3(base(1, :), base(2, :), base(3, :), colors(8, :)); hold on
fill3(plat0(1, :), plat0(2, :), plat0(3, :), colors(5, :)); hold off
grid on
grid minor
title('Reference Result', 'Interpreter', 'LaTeX', 'FontSize', 14);

base_ = base.';
plat_ = plat.';
counter = 1;
base = [];
plat = [];
for i = 1 : 6
    base = [base; base_(i, :)];
    plat = [plat; plat_(i, :)];
    if(i < 6)
        tmp = (base_(i, :) + base_(i + 1, :)) / 2;
        base = [base; tmp];

        tmp = (plat_(i, :) + plat_(i + 1, :)) / 2;
        plat = [plat; tmp];
    end

end
base = base.';
plat = plat.';
len = size(base, 2);

leg0 = zeros(len, 1);
plat0 = zeros(3, len);
for i = 1 : len
    plat0(:, i) = R0 * plat(:, i)  + t0;
    res = base(:, i) - plat0(:, i);
    leg0(i) = sqrt(res.' * res);
end

syms q0 q1 q2 q3
q = [q0; q1; q2; q3];
syms t1 t2 t3;
t = [t1; t2; t3];
R = q2R(q);
syms r1 r2 r3 r4
r = [r1; r2; r3; r4];
rr = r(1 : 3);
eqs = sym(zeros(len + 3, 1));
for i = 1 : len
    eqs(i) = base(:, i).' * base(:, i) - 2 * plat(:, i).' * R.' * base(:, i) + ...
             plat(:, i).' * plat(:, i) - 2 * base(:, i).' * t + 2 * plat(:, i).' * rr + r4 - leg0(i)^2;
end
eqs(len + 1) = q.' * q - 1;
eqs(len + 2) = rr.' * rr - r4;
eqs(len + 3) = t.' * t - r4;
eqs = expand(eqs);
x = [q; t; r];
H = expand(jacobian(eqs, x).' * eqs);
assumeAlso(q.' * q == 1);
assumeAlso(rr.' * rr - r4 == 0);
assumeAlso(t.' * t - r4 == 0);
eq = vpa(expand(simplify(H)), 32);

eq_ = eq(1 : 4);
G = jacobian(eq(5 : 11), [t; r]);
ss = - pinv(G) * (eq(5 : 11) - G * [t; r]);
ss = neglect_tiny_terms(ss, 32);
ss = ss.';
eq_ = eq(1 : 4);
eq_ = subs(eq_, t1, ss(1));
eq_ = subs(eq_, t2, ss(2));
eq_ = subs(eq_, t3, ss(3));
eq_ = subs(eq_, r1, ss(4));
eq_ = subs(eq_, r2, ss(5));
eq_ = subs(eq_, r3, ss(6));
eq_ = subs(eq_, r4, ss(7));
t_func = matlabFunction([ss(1); ss(2); ss(3)], 'Vars', {q});
r_func = matlabFunction([ss(4); ss(5); ss(6)], 'Vars', {q});
r4_func = matlabFunction(ss(7), 'Vars', {q});
eq_ = vpa(expand(eval(eq_)), 32);
syms lambda
eq_ = [
    neglect_tiny_terms(eq_, 32).';
    q.' * q - 1;
    ]

eqs = [
    eq_(1 : 4) + lambda * q;
    eq_(5);
    ];
str = '';
for i = 1 : length(eqs)
    str = strcat(str, sprintf(' PP{%d} = char(vpa(%%s, 32));', i));
end

str_ = sprintf(str, char(eqs(1)), ...
                    char(eqs(2)), ...
                    char(eqs(3)), ...
                    char(eqs(4)), ...
                    char(eqs(5)));
eval(str_);
[S, vars] = psolve(PP);
S = S.';
SS = S;
for i = 1 : length(vars)
    if(strcmp(vars{i}, 'q0'))
        SS(:, 1) = S(:, i);
    elseif(strcmp(vars{i}, 'q1'))
        SS(:, 2) = S(:, i);
    elseif(strcmp(vars{i}, 'q2'))
        SS(:, 3) = S(:, i);
    elseif(strcmp(vars{i}, 'q3'))
        SS(:, 4) = S(:, i);
    elseif(strcmp(vars{i}, 'lambda'))
        SS(:, 5) = S(:, i);
    end
end
S = real(SS);
xs_ = S;
sols = SS.';

num = size(sols, 2);
sol = zeros(4, num);
ts = zeros(3, num);
Ls = 1e50 * ones(num, 1);
q_true = dcm2quat(R0).';
if(q_true(1) < 0)
    q_true = - q_true;
end
for i = 1 : num
    sol(:, i) = real(sols(1 : 4, i));
    sol(:, i) = sol(:, i) ./ norm(sol(:, i));
    if(sol(1, i) < 0)
        sol(:, i) = - sol(:, i);
    end
    C = q2R(sol(:, i));
    t = t_func(sol(:, i));
    r4 = r4_func(sol(:, i));
    ts(:, i) = t;
    res = abs(q_true - sol(:, i));
    loss = res.' * res;
    Ls(i) = loss;
end
[~, idx] = sort(Ls);

q_ = sol(:, idx(1)).'
q_true_ = q_true.'

R_ = quat2dcm(sol(:, idx(1)).');
t_ = t0;
plat0 = zeros(3, 6);
for i = 1 : 6
    plat0(:, i) = R_ * plat00(:, i)  + t_;
end
base = base00;

subplot(1, 2, 2);
plot3(base(1, :), base(2, :), base(3, :), 'LineStyle', 'None', 'Marker', '.', 'MarkerSize', 10); hold on
plot3(base(1, 1 : 6), base(2, 1 : 6), base(3, 1 : 6), 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
plot3([base(1, 1), base(1, 6)], [base(2, 1), base(2, 6)], [base(3, 1), base(3, 6)], 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
plot3(plat0(1, :), plat0(2, :), plat0(3, :), 'LineStyle', 'None', 'Marker', '.', 'MarkerSize', 10); hold on
plot3(plat0(1, 1 : 6), plat0(2, 1 : 6), plat0(3, 1 : 6), 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
plot3([plat0(1, 1), plat0(1, 6)], [plat0(2, 1), plat0(2, 6)], [plat0(3, 1), plat0(3, 6)], 'LineStyle', '-', 'LineWidth', 2, 'Marker', 'None'); hold on
for i = 1 : 6
    plot3([base(1, i), plat0(1, i)], [base(2, i), plat0(2, i)], [base(3, i), plat0(3, i)], 'LineStyle', '-', 'LineWidth', 4, 'Marker', 'None'); hold on
end
hold on
fill3(base(1, :), base(2, :), base(3, :), colors(8, :)); hold on
fill3(plat0(1, :), plat0(2, :), plat0(3, :), colors(5, :)); hold off
grid on
grid minor
title('QPEP Result', 'Interpreter', 'LaTeX', 'FontSize', 14);

if(~ispc())
    set(gcf, 'Position', [634 780 1159 320])
end


function varargout = process_test_permutation2( varargin )
% PROCESS_TEST_PERMUTATION2: Permutation two-sample tests (independent).

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, Dimitrios Pantazis, 2016

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Permutation test: Independent';
    sProcess.Category    = 'Stat2';
    sProcess.SubGroup    = 'Test';
    sProcess.Index       = 104;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/Statistics';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data',  'results',  'timefreq',  'matrix'};
    sProcess.OutputTypes = {'pdata', 'presults', 'ptimefreq', 'pmatrix'};
    sProcess.nInputs     = 2;
    sProcess.nMinFiles   = 2;

    % === GENERIC EXTRACT OPTIONS
    % Label
    sProcess.options.extract_title.Comment    = 'Select data to test:';
    sProcess.options.extract_title.Type       = 'label';
    % Options
    sProcess = process_extract_values('DefineExtractOptions', sProcess);
    % DISABLE ABSOLUTE VALUE
    sProcess.options.isabs.Value = 0;
    sProcess.options.isnorm.Value = 0;
    sProcess.options.isabs.Hidden = 1;
    sProcess.options.isnorm.Hidden = 1;

    % === EXCLUDE ZERO VALUES
    sProcess.options.iszerobad.Comment = 'Exclude the zero values from the computation';
    sProcess.options.iszerobad.Type    = 'checkbox';
    sProcess.options.iszerobad.Value   = 1;
    % === OUTPUT COMMENT
    sProcess.options.Comment.Comment = 'Comment (empty=default): ';
    sProcess.options.Comment.Type    = 'text';
    sProcess.options.Comment.Value   = '';

    % === TEST: title
    sProcess.options.test_title.Comment    = '
Test statistic:';
    sProcess.options.test_title.Type       = 'label';
    % === TEST: type
    sProcess.options.test_type.Comment = {['Student''s t-test   (equal variance)
t = (mean(A)-mean(B)) / (Sx * sqrt(1/nA + 1/nB))
' ...
                                           'Sx = sqrt(((nA-1)*var(A) + (nB-1)*var(B)) / (nA+nB-2))'], ...
                                          ['Student''s t-test   (unequal variance)
', ...
                                           't = (mean(A)-mean(B)) / sqrt(var(A)/nA + var(B)/nB)'], ...
                                          ['Absolute mean test:    (works with unconstrained sources)
' ...
                                           'T = (|mean(A)|-|mean(B)|) / sqrt(|var(A)|/nA + |var(B)|/nB)']; ...
                                          ...  ['Wilcoxon rank-sum test
', ...
                                          ...  'R = tiedrank([A,B]),    W = sum(R(1:nA))']; ...
                                          'ttest_equal', 'ttest_unequal', 'absmean'}; % , 'wilcoxon'};
    sProcess.options.test_type.Type    = 'radio_label';
    sProcess.options.test_type.Value   = 'ttest_equal';

    % ===== STATISTICAL TESTING OPTIONS =====
    sProcess.options.label2.Comment  = '
Statistical testing (Monte-Carlo):';
    sProcess.options.label2.Type     = 'label';
    % === NUMBER OF RANDOMIZATIONS
    sProcess.options.randomizations.Comment = 'Number of randomizations:';
    sProcess.options.randomizations.Type    = 'value';
    sProcess.options.randomizations.Value   = {1000, '', 0};
    % === TAIL FOR THE TEST STATISTIC
    sProcess.options.tail.Comment  = {'One-tailed (-)', 'Two-tailed', 'One-tailed (+)', ''; ...
                                      'one-', 'two', 'one+', ''};
    sProcess.options.tail.Type     = 'radio_linelabel';
    sProcess.options.tail.Value    = 'two';
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    Comment = process_test_parametric2('FormatComment', sProcess);
    Comment = ['Perm ' Comment];
end

%% ===== RUN =====
function sOutput = Run(sProcess, sInputsA, sInputsB) %#ok<DEFNU>
    % Initialize returned variables
    sOutput = [];

    % ===== GET OPTIONS =====
    % Get generic extract options
    OPTIONS = process_extract_values('GetExtractOptions', sProcess, sInputsA(1));
    % Exclude zero values
    if isfield(sProcess.options, 'iszerobad') && isfield(sProcess.options.iszerobad, 'Value') && ~isempty(sProcess.options.iszerobad.Value)
        OPTIONS.isZeroBad = sProcess.options.iszerobad.Value;
    else
        OPTIONS.isZeroBad = 1;
    end
    % Get test type
    OPTIONS.TestType = sProcess.options.test_type.Value;
    OPTIONS.TestTail = sProcess.options.tail.Value;
    Randomizations = sProcess.options.randomizations.Value{1};
    % Invalid test/tail combinations
    if ismember(OPTIONS.TestType, {'ttest_onesample'}) && OPTIONS.isAbsolute && ismember(OPTIONS.TestTail, {'two', 'one-'})
        bst_report('Warning', sProcess, [], 'Testing |X|>0: Using a positive one-tailed test (one+) instead.');
        OPTIONS.TestTail = 'one+';
    elseif strcmpi(OPTIONS.TestType, 'chi2_onesample') && ismember(OPTIONS.TestTail, {'two', 'one-'})
        bst_report('Warning', sProcess, [], 'Testing |X|>0: Using a positive one-tailed test (one+) instead.');
        OPTIONS.TestTail = 'one+';
    elseif strcmpi(OPTIONS.TestType, 'signtest') && ismember(OPTIONS.TestTail, {'two', 'one-'})
        bst_report('Warning', sProcess, [], 'The sign test statistic produces positive values only: Using a positive one-tailed test (one+) instead.');
        OPTIONS.TestTail = 'one+';
    end

    % ===== CHECK INPUT FILES =====
    % Make sure that file type is indentical for both sets
    if ~isempty(sInputsA) && ~isempty(sInputsB) && ~strcmpi(sInputsA(1).FileType, sInputsB(1).FileType)
        bst_report('Error', sProcess, [], 'Cannot process inputs from different types.');
        return;
    end
    % Check the number of files in input
    if (length(sInputsA) < 2)
        bst_report('Error', sProcess, [], 'Not enough files in input.');
        return;
    end
    % Load time vector from the first file: if same as input, discard input
    TimeVector = in_bst(sInputsA(1).FileName, 'Time');
    if ~isempty(OPTIONS.TimeWindow) && (abs(TimeVector(1) - OPTIONS.TimeWindow(1)) < 1e-4) && (abs(TimeVector(end) - OPTIONS.TimeWindow(2)) < 1e-4)
        OPTIONS.TimeWindow = [];
    end
    % Load freq range from the first file: if same as input, discard input
    if ~isempty(OPTIONS.FreqRange)
        % Load Freqs field from the input file
        TfMat = in_bst_timefreq(sInputsA(1).FileName, 0, 'Freqs');
        if iscell(TfMat.Freqs)
            BandBounds = process_tf_bands('GetBounds', TfMat.Freqs);
            FreqList = unique(BandBounds(:));
        else
            FreqList = TfMat.Freqs;
        end
        if (abs(OPTIONS.FreqRange(1) - FreqList(1)) < 1e-4) && (abs(OPTIONS.FreqRange(2) - FreqList(end)) < 1e-4)
            OPTIONS.FreqRange = [];
        end
    end

    % ===== INPUT DATA =====
    % Concatenante values in the 4th dimension
    OPTIONS.Dim = 4;
    % Set all the bad values to 0
    OPTIONS.isBadZero = 1;
    % Call extraction process: FilesA
    [sDataA, OutputType, matName] = process_extract_values('Extract', sProcess, sInputsA, OPTIONS);
    if isempty(sDataA)
        bst_report('Error', sProcess, [], 'No data read from FilesA.');
        return;
    end
    % Read FilesB
    sDataB = process_extract_values('Extract', sProcess, sInputsB, OPTIONS);
    if isempty(sDataB)
        bst_report('Error', sProcess, [], 'No data read from FilesB.');
        return;
    elseif (size(sDataA.(matName),1) ~= size(sDataB.(matName),1)) || (size(sDataA.(matName),2) ~= size(sDataB.(matName),2)) || (size(sDataA.(matName),3) ~= size(sDataB.(matName),3))
        bst_report('Error', sProcess, [], 'Files A and B do not have the same number of signals or time samples.');
        return;
    end
% WARNING ONLY APPLIES TO PARAMETRIC TESTS
%     % Time-frequency: Warning if processing power
%     if strcmpi(sInputsA(1).FileType, 'timefreq') && isfield(sDataA, 'Measure') && isequal(sDataA.Measure, 'power')
%         bst_report('Warning', sProcess, [], ['You are testing power values, while a more standard analysis is to test the magnitude (ie. sqrt(power)).' 10 ...
%             'Option #1: Recompute the time-frequency maps using the option "Measure: Magnitude".' 10 ...
%             'Option #2: Run the process "Extract > Measure from complex values", with option "Magntiude".']);
%     end

    % ===== UNCONSTRAINED SOURCES =====
    % Detect if the source model is unconstrained
    isUnconstrained = panel_scout('isUnconstrained', sDataA);
    % Do not allow unconstrained sources without a norm
    if isUnconstrained && ~OPTIONS.isAbsolute
        % Unconstrained models: Ok if using
        if strcmpi(OPTIONS.TestType, 'absmean') % && (sDataA.nComponents == 3)
            OPTIONS.TestType = 'absmean_unconstr';
        else
            bst_report('Error', sProcess, [], ['Cannot run this test on unconstrained sources:' 10 'you must compute the norm of the three orientations first.']);
            return;
        end
    end

    % === COMPUTE TEST ===
    % Run the permutation test
    [pmap, tmap, nA, nB] = bst_permtest(sDataA.(matName), sDataB.(matName), OPTIONS.TestType, OPTIONS.Dim, Randomizations, OPTIONS.TestTail, OPTIONS.isZeroBad);
    % Finished processing
    bst_progress('text', 'Saving the results...');

    % Bad channels: For recordings, keep only the channels that are good in BOTH A and B sets
    switch lower(sInputsA(1).FileType)
        case 'data'
            ChannelFlag = sDataA.ChannelFlag;
            ChannelFlag(sDataB.ChannelFlag == -1) = -1;
        case {'results', 'timefreq', 'matrix'}
            ChannelFlag = [];
    end

    % === DISPLAYED UNITS ===
    switch (OPTIONS.TestType)
        case 'ttest_equal',      DisplayUnits = 't';
        case 'ttest_unequal',    DisplayUnits = 't';
        case 'ttest_paired',     DisplayUnits = 't';
        case 'signtest',         DisplayUnits = 'N';
        case 'wilcoxon_paired',  DisplayUnits = 'W';
        case 'absmean',          DisplayUnits = 'T';
        case 'absmean_unconstr', DisplayUnits = 'T';
        % case 'wilcoxon',        DisplayUnits = 'W';
        otherwise,              error('Invalid statistic.');
    end

    % === CONVERT BACK MATRIX => DATA ===
    % If processing recordings with only some sensor types selected
    if strcmpi(sInputsA(1).FileType, 'data') && strcmpi(OutputType, 'matrix') && ~isempty(OPTIONS.SensorTypes) && ~OPTIONS.isAvgTime && ~OPTIONS.isAvgRow && ~OPTIONS.isAvgFreq
        % Get the list of selected sensors
        dataTypes = strtrim(str_split(OPTIONS.SensorTypes, ',;'));
        % If only major data types were selected: save results in "data" format
        if ~isempty(dataTypes) && all(ismember(dataTypes, {'MEG','EEG','MEG MAG''MEG GRAD','MEG GRAD2','MEG GRAD3','SEEG','ECOG','NIRS'}))
            % Load channel file
            ChannelMat = in_bst_channel(sInputsA(1).ChannelFile);
            % Find channel names in the output row names
            iChannels = channel_find(ChannelMat.Channel, OPTIONS.SensorTypes);
            % Convert output data matrices
            % tmap
            tmap_tmp = zeros(length(ChannelMat.Channel), size(tmap,2), size(tmap,3));
            tmap_tmp(iChannels,:,:) = tmap;
            tmap = tmap_tmp;
            % pmap
            pmap_tmp = zeros(size(tmap_tmp));
            pmap_tmp(iChannels,:,:) = pmap;
            pmap = pmap_tmp;
            % nA
            if ~isempty(nA)
                nA_tmp = zeros(size(tmap_tmp));
                nA_tmp(iChannels,:,:) = nA;
                nA = nA_tmp;
            end
            % nB
            if ~isempty(nB)
                nB_tmp = zeros(size(tmap_tmp));
                nB_tmp(iChannels,:,:) = nB;
                nB = nB_tmp;
            end
            % New channel flag
            tmpChannelFlag = -1 .* ones(length(ChannelMat.Channel), 1);
            if ~isempty(ChannelFlag) && (length(ChannelFlag) == length(iChannels))
                tmpChannelFlag(iChannels) = ChannelFlag;
            else
                tmpChannelFlag(iChannels) = 1;
            end
            ChannelFlag = tmpChannelFlag;
            % Convert Stat structure
            OutputType = 'data';
            sDataA.RowNames = [];
        end
    end

    % === OUTPUT STRUCTURE ===
    % Initialize output structure
    sOutput = db_template('statmat');
    sOutput.pmap         = pmap;
    sOutput.tmap         = tmap;
    sOutput.df           = [];
    sOutput.Correction   = 'no';
    sOutput.Type         = OutputType;
    sOutput.ChannelFlag  = ChannelFlag;
    sOutput.Time         = sDataA.Time;
    sOutput.ColormapType = 'stat2';
    sOutput.DisplayUnits = DisplayUnits;
    if strcmpi(OPTIONS.TestType, 'absmean_unconstr')
        sOutput.nComponents = 1;
    elseif isfield(sDataA, 'nComponents')
        sOutput.nComponents = sDataA.nComponents;
    end
    if isfield(sDataA, 'GridAtlas')
        sOutput.GridAtlas = sDataA.GridAtlas;
    end
    if isfield(sDataA, 'Freqs')
        sOutput.Freqs = sDataA.Freqs;
    end
    if isfield(sDataA, 'TFmask')
        sOutput.TFmask = sDataA.TFmask;
    end
    % Row names
    if isfield(sDataA, 'Description') && ~isempty(sDataA.Description)
        RowNames = sDataA.Description;
    elseif isfield(sDataA, 'RowNames') && ~isempty(sDataA.RowNames)
        RowNames = sDataA.RowNames;
    else
        RowNames = [];
    end
    if ~isempty(RowNames)
        if strcmpi(OutputType, 'matrix')
            sOutput.Description = RowNames;
        elseif strcmpi(OutputType, 'timefreq')
            sOutput.RowNames = RowNames;
        end
    end
    % Save options
    sOutput.Options = OPTIONS;
    % Save the number of good samples used for both sets:
    % In compressed format (keeping only one value per row, if all the other dimensions are the same)
    if isequal(nA(1:size(nA,1))', mean(mean(nA,2),3))
        sOutput.Options.nGoodSamplesA = nA(1:size(nA,1))';
        sOutput.Options.nGoodSamplesB = nB(1:size(nB,1))';
    % Or saving the full list of good samples
    else
        sOutput.Options.nGoodSamplesA = nA;
        sOutput.Options.nGoodSamplesB = nB;
    end
end


function [ a, det, inert ] = chidi ( a, lda, n, ipvt, job )

%*****************************************************************************80
%
%% CHIDI computes the determinant and inverse of a matrix factored by CHIFA.
%
%  Discussion:
%
%    CHIDI computes the determinant, inertia (number of positive, zero,
%    and negative eigenvalues) and inverse of a complex hermitian matrix
%    using the factors from CHIFA.
%
%    A division by zero may occur if the inverse is requested
%    and CHICO has set RCOND == 0.0 or CHIFA has set INFO /= 0.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex A(LDA,N); the factored matrix from CHIFA.
%
%    Input, integer LDA, the leading dimension of A.
%
%    Input, integer N, the order of the matrix.
%
%    Input, integer IPVT(N), the pivot vector from CHIFA.
%
%    Input, integer JOB, has the decimal expansion ABC where:
%    if C /= 0, the inverse is computed,
%    if B /= 0, the determinant is computed,
%    if A /= 0, the inertia is computed.
%    For example, JOB = 111 gives all three.
%
%    Output, complex A(LDA,N); if the inverse was requested, A contains
%    the inverse matrix.  The strict lower triangle of A is never
%    referenced.
%
%    Output, real DET(2), the determinant of the original matrix.
%    Determinant = DET(1) * 10.0**DET(2) with 1.0 <= abs ( DET(1) ) < 10.0
%    or DET(1) = 0.0.
%
%    Output, integer INERT(3), the inertia of the original matrix.
%    INERT(1) = number of positive eigenvalues.
%    INERT(2) = number of negative eigenvalues.
%    INERT(3) = number of zero eigenvalues.
%
  inert = [];
  det = [];

  noinv = floor ( mod ( job,   10 )       ) == 0;
  nodet = floor ( mod ( job,  100 ) /  10 ) == 0;
  noert = floor ( mod ( job, 1000 ) / 100 ) == 0;

  if ( ~nodet || ~noert )

    if ( ~noert )
      inert(1:3) = 0;
    end

    if ( ~nodet )
      det(1) = 1.0;
      det(2) = 0.0;
    end

    t = 0.0;

    for k = 1 : n

      d = real ( a(k,k) );
%
%  Check if 1 by 1.
%
      if ( ipvt(k) <= 0 )
%
%  2 by 2 block
%  Use DET = ( D / T * C - T ) * T, T = abs ( S )
%  to avoid underflow/overflow troubles.
%  Take two passes through scaling.  Use T for flag.
%
        if ( t == 0.0 )
          t = abs ( a(k,k+1) );
          d = ( d / t ) * real ( a(k+1,k+1) ) - t;
        else
          d = t;
          t = 0.0;
        end

      end

      if ( ~noert )
        if ( 0.0 < d )
          inert(1) = inert(1) + 1;
        elseif ( d < 0.0 )
          inert(2) = inert(2) + 1;
        elseif ( d == 0.0 )
          inert(3) = inert(3) + 1;
        end
      end

      if ( ~nodet )

        det(1) = det(1) * d;

        if ( det(1) ~= 0.0 )

          while ( abs ( det(1) ) < 1.0 )
            det(1) = det(1) * 10.0;
            det(2) = det(2) - 1.0;
          end

          while ( 10.0 <= abs ( det(1) ) )
            det(1) = det(1) / 10.0;
            det(2) = det(2) + 1.0;
          end

        end

      end

    end

  end
%
%  Compute inverse(A).
%
  if ( ~noinv )

    k = 1;

    while ( k <= n )

      km1 = k - 1;

      if ( 0 <= ipvt(k) )
%
%  1 by 1
%
        a(k,k) = 1.0 / real ( a(k,k) );

        if ( 1 <= km1 )

          work(1:km1) = a(1:km1,k);

          for j = 1 : km1
            a(j,k) = work(1:j) * conj ( a(1:j,j) );
            a(1:j-1,k) = a(1:j-1,k) + work(j) * a(1:j-1,j);
          end

          a(k,k) = a(k,k) + real ( conj ( work(1:km1) ) * a(1:km1,k) );

        end

        kstep = 1;

      else
%
%  2 by 2
%
        t = abs ( a(k,k+1) );
        ak = real ( a(k,k) ) / t;
        akp1 = real ( a(k+1,k+1) ) / t;
        akkp1 = a(k,k+1) / t;
        d = t * ( ak * akp1 - 1.0 );
        a(k,k) = akp1 / d;
        a(k+1,k+1) = ak / d;
        a(k,k+1) = -akkp1 / d;

        if ( 1 <= km1 )

          work(1:km1) = a(1:km1,k+1);

          for j = 1 : km1
            a(j,k+1) = work(1:j) * conj ( a(1:j,j) );
            a(1:j-1,k+1) = a(1:j-1,k+1) + work(j) * a(1:j-1,j);
          end

          a(k+1,k+1) = a(k+1,k+1) + ...
            real ( conj ( work(1:km1) ) * a(1:km1,k+1) );

          a(k,k+1) = a(k,k+1) ...
            + transpose ( conj ( a(1:km1,k) ) ) * a(1:km1,k+1);

          work(1:km1) = a(1:km1,k);

          for j = 1 : km1
            a(j,k) = work(1:j) * conj ( a(1:j,j) );
            a(1:j-1,k) = a(1:j-1,k) + work(j) * a(1:j-1,j);
          end

          a(k,k) = a(k,k) + real ( conj ( work(1:km1) ) * a(1:km1,k) );

        end

        kstep = 2;

      end
%
%  Swap
%
      ks = abs ( ipvt(k) );

      if ( ks ~= k )

        temp       = a(1:ks,ks);
        a(1:ks,ks) = a(1:ks,k);
        a(1:ks,k)  = temp;

        for j = k : -1 : ks
          temp    = conj ( a(j,k) );
          a(j,k)  = conj ( a(ks,j) );
          a(ks,j) = temp;
        end

        if ( kstep ~= 1 )
          temp      = a(ks,k+1);
          a(ks,k+1) = a(k,k+1);
          a(k,k+1)  = temp;
        end

      end

      k = k + kstep;

    end

  end

  return
end


function permutations = dtiBootGetPermutations(permuteMatrix, numPermutations, bRepetition)
%
% permutations = dtiBootGetPermutations(permuteMatrix, numPermutations, [bRepetition=0])
%
%
% HISTORY:
% 2007.06.22 RFD wrote it

if ieNotDefined('bRepetition')
    bRepetition = 0;
end

if(bRepetition==0)
    numVols = permuteMatrix;
    permutations = zeros(numVols,numPermutations);
    for(ii=1:numVols)
        %permutations(ii,:) = randsample(1:numVols,numPermutations,true);
        permutations(ii,:) = ceil(numVols*rand(1,numPermutations));
    end
else
    numVols = size(permuteMatrix,1);
    permutations = zeros(numVols,numPermutations);
    for(ii=1:numVols)
        permutations(ii,:) = permuteMatrix{ii}(ceil(length(permuteMatrix{ii}).*rand(1,numPermutations)));
    end
end

return


function z=smooth_lf(x,y,varargin)

% must (unlike R smooth.lf() function) give x and y.
% also R's direct=T is automatic.
%

xev = x;
if (k>1)
  if (strcmp(varargin{1},'xev'))
    xev = varargin{2};
    varargin(1:2) = [];
  end;
end;
fit = locfit(x,y,varargin{:},'ev',xev,'module','simple');
z = lfknots(fit);
fv = invlink(z(:,1),fit.fit_points.family_link);

z = { xev, fv };

return;


% This is used to set the evaluation metrics that to be computed
%
% Author:Xingchen Zhang, Ping Ye, Gang Xiao
% Contact: xingchen.zhang@imperial.ac.uk

function metrics=configMetrics

 metricVIFB={struct('name','Avg_gradient'),...
     struct('name','Cross_entropy'),...
     struct('name','Edge_intensity'),...
     struct('name','Entropy'),...
     struct('name','Mutinf'),...
     struct('name','Psnr'),...
     struct('name','Qabf'),...
     struct('name','Qcb'),...
     struct('name','Qcv'),...
     struct('name','Rmse'),...
     struct('name','Spatial_frequency'),...
     struct('name','Ssim'),...
     struct('name','Variance'),...
     };

 metrics = [metricVIFB];


function a = one_vs_one(c,hyper)

%=========================================================================
% ONE_VS_ONE one_vs_one object
%=========================================================================
% A=ONE_VS_ONE(C,H) returns an one_vs_one object which trains several
% algorithm C on pairwise problems of class i against class j,
% and is initialized with hyperparameters H. The classifiers are combined
% by outputting the class with the most votes.
%
% Model
%  child=svm            -- classifier to use for each sub-problem
%
% Methods:
%  train, test, get_w
%=========================================================================
% Reference : Multi-class Support Vector Machines
% Author    : Jason Weston , C. Watkins
% Link      : http://citeseer.ist.psu.edu/8884.html
%=========================================================================

  % model
  a.nrofclasses=[];
  if nargin==0
    a.child={svm};
  else
    a.child=c;   %% algorithms to use
    if ~isa(c,'cell')
        a.child={c};
    end;
  end

  %% set to use unsigned output if possible
  for i=1:length(a.child)
    a.child{i}.algorithm.use_signed_output=0;
  end

  p=algorithm('one-vs-one');
  a= class(a,'one_vs_one',p);
  %hyperparams are supplied
  if nargin==2
    eval_hyper;
  end


% DEMSILHOUETTELINEAR1 Model silhouette data with independent linear models.

% FORMAT
% DESC runs a simple regression on the Agawal and Triggs data.
%
% SEEALSO : demSilhouetteGp1, demSilhouetteAverage
%
% COPYRIGHT : Neil D. Lawrence, 2008

% GP

randn('seed', 1e7)
rand('seed', 1e7)

dataSetName = 'silhouette';
experimentNo = 1;

% load data
[X, y, XTest, yTest] = mapLoadData(dataSetName);

% Set up the model
options = linearOptions;

q = size(X, 2);
d = size(y, 2);
model = linearCreate(q, d, options);

model = linearOptimise(model, X, y);
modelDisplay(model)

% Save results
capName = dataSetName;;
capName(1) = upper(capName(1));
fileBaseName = ['dem' capName 'Linear' num2str(experimentNo)];
save([fileBaseName '.mat'], 'model');

demSilhouettePlot


function tfc_data = readBESAtfcs(filename)

% readBESAtfcs reads single trial TFC data exported from BESA Research.
%
% Use as
%   tfc = readBESAtfcs(filename)
%
% The output is a structure containing a 3D matrix with complex numbers
% for every trial. The size of the matrix is
% [NChannels x NFreqSamples x NTimeSamples].
%
% Created June 28, 2012 Todor Jordanov

if isempty(findstr(filename,'.'))

  filename = [filename,'.tfcs'];

end

fp = fopen(filename, 'r');

if (fp)

    tfc_data.trials = {};

    n_trials = 0;
    n_channels = 0;
    n_freqs = 0;

    tline = fgetl(fp);
    tline = strtrim(tline);

    while ischar(tline)

        if(strncmpi(tline, 'Trial', 5))

            n_trials = n_trials + 1;
            n_channels = 0;
            n_freqs = 0;

        elseif(strncmpi(tline, 'Channel', 7))

            n_channels = n_channels + 1;
            n_freqs = 0;

        else

            tline = strtrim(tline);
            tmp = regexp(tline, '\t', 'split');
            n_samples = size(tmp, 2);
            n_freqs = n_freqs + 1;

            for i=1:n_samples

                two_reals = sscanf(tmp{i}, '%f +i* %f');
                tfc_data.trials{n_trials}(n_channels, n_freqs, i) = ...
                    complex(two_reals(1), two_reals(2));

            end

        end

        tline = fgetl(fp);

    end

    fclose(fp);

end


function res = im2row(im, winSize)
%res = im2row(im, winSize)
[sx,sy,sz] = size(im);

res = zeros((sx-winSize(1)+1)*(sy-winSize(2)+1),prod(winSize),sz);
count=0;
for y=1:winSize(2)
    for x=1:winSize(1)
        count = count+1;
        res(:,count,:) = reshape(im(x:sx-winSize(1)+x,y:sy-winSize(2)+y,:),...
            (sx-winSize(1)+1)*(sy-winSize(2)+1),1,sz);
    end
end


function u = tan(a)
%TAN          Slope tangent tan(a)
%

% written  12/06/98     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 09/28/08     S.M. Rump  check for rounding to nearest improved
% modified 08/26/12     S.M. Rump  global variables removed
%

  e = 1e-30;
  if 1+e==1-e                           % fast check for rounding to nearest
    rndold = 0;
  else
    rndold = getround;
    setround(0)
  end

  INTLAB_SLOPE = getappdata(0,'INTLAB_SLOPE');

  u = a;

  u.r = tan(a.r);
  indexc = 1:INTLAB_SLOPE.NUMVAR;
  indexr = 2:INTLAB_SLOPE.NUMVAR+1;
  Xxs = hull(a.r(:,indexc),a.r(:,indexr));
  u.s = a.s ./ sqr(cos(Xxs));

  if rndold
    setround(rndold)
  end


function spm_dartel_dotprods(job)
% Generate a kernel from dot-products of images
% FORMAT spm_dartel_dotprods(job)
% job.images  - Images to use
% job.dotprod - Part of filename for results
%_______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_dartel_dotprods.m 4492 2011-09-16 12:11:09Z guillaume $

P      = strvcat(job.images);
[pth,nam,ext] = fileparts(job.dotprod);
ofname = fullfile(pwd,['dp_' nam '.mat']);

N = nifti(P);
n = numel(N);
dm= size(N(1).dat);
dat=cell(1,numel(N));
for i=1:numel(N),
    dat{i} = reshape(N(i).dat,[prod(dm),1]);
end
Phi = zeros(n,n);

if isfield(job,'weight') && ~isempty(job.weight),
    Pmsk = strvcat(job.weight);
    Nmsk = nifti(Pmsk);
    msk  = Nmsk.dat;
    dmsk = size(msk);
    if any(dmsk(1:3) ~= dm(1:3)),
        error('Wrong sized weighting image.');
    end
    msk = reshape(msk,[prod(dmsk),1]);
    if numel(dmsk)==3,
        msk1 = msk;
        for i=2:prod(dm(4:end)),
            msk = [msk;msk1];
        end
    end
end

mem = 32*1024*1024;  % Mbytes of RAM to use
bs  = ceil(mem/8/n); % Block size
nd  = prod(dm);
nblock = ceil(prod(dm)/bs);
spm_progress_bar('Init',nblock,...
                 'Generating kernel','Blocks complete');
for k=1:nblock,
    o = bs*(k-1)+(1:bs);
    o = o(o<nd);
    if exist('msk','var'),
        wt  = msk(o);
        tmp = wt>0;
        o   = o(tmp);
        wt  = wt(tmp);
    end
    if ~isempty(o),
        X = zeros(numel(o),numel(dat));
        for i=1:n,
            tmp    = dat{i}(o);
            tmp(~isfinite(tmp)) = 0;
            if exist('wt','var'), tmp = tmp.*wt; end
            X(:,i) = tmp;
        end
        Phi    = Phi + X'*X;
        clear X
    end
    spm_progress_bar('Set',k);
end
spm_progress_bar('Clear');
input = job;
typ   = 'images';
save(ofname,'Phi','input','typ', spm_get_defaults('mat.format'));


report_this_filefun(mfilename('fullpath'));

clf
[X,Y,Z] = meshgrid(gx,gy,gz);
v = [];
i = 0.05
ii = 0.05
for i3 = 1:2:length(gy)
    i3 = gy(i3);
    l = loc(2,:) == i3;
    re3 = reshape(as(l),length(gz),length(gx));
    r = reshape(loc(4,l),length(gz),length(gx));
    l = r > tresh;
    re3(l) = zeros(1,length(find(l)))*nan;
    rect = [i ii 0.15 0.15];
    i = i+0.20;
    if i > 0.9 ; i = 0.05 ; ii = ii + 0.20; end
    axes('position',rect)
    pcolor(gx,-gz,re3)
    caxis([min(as) max(as)])
    colormap(jet)
    title([ 'Lat=' num2str(i3) ' km'],'FontSize',8)
    set(gca,'FontSize',8)
    hold on
    l = a.Latitude > i3-dy/2 & a.Latitude < i3+dy/2;
    plot3(a(l,1),-a(l,7),a(l,7)*0,'k.')
    shading interp
    % axis('off')
    hold on
end


function [W, a, train_err] = train_foe(images, basis, no_experts, a)
%TRAIN_FOE Trains a Field of Experts model on a collection of images
%
%   [W, a, train_err] = train_foe(images, basis, no_experts)
%   [W, a, train_err] = train_foe(images, basis, W, a)
%
% Trains a Field of Experts model on a set of (grayscale) images. The
% potential functions of the MRF are given by the energy function of a
% product of no_experts Student-t distributions (with parameters W and a).
% The potential functions are defined over a cliques that are image patches
% of patch_size x patch_size pixels.
%
%
% (C) Laurens van der Maaten, 2009
% Delft University of Technology

    % Initialize parameters
    eta_W = .01;
    eta_a = .1;
    max_iter = 1000;
    no_images = size(images, 1);
    size_im = sqrt(size(images, 2));
    batch_size = min(200, no_images);
    momentum = .9;
    train_err = zeros(max_iter, 1);
    addpath(genpath('netlab'));

    % Initialize model
    if exist('a', 'var')
        W = no_experts;
    else
        W = randn(size(basis, 1), no_experts);
        a = repmat(0.01, [no_experts 1]);
    end
    prev_dW = zeros(size(W));
    prev_da = zeros(size(a));

    % Perform training of the model
    for iter=1:max_iter

        % Create batches
        tic
        ind = randperm(no_images);
        disp(['Iteration ' num2str(iter) '...']);

        % Loop over batches
        for b=1:batch_size:no_images

            % Get batch and initialize positive and negative data
            batch = images(ind(b:b + batch_size - 1),:);
            pos_W = zeros(size(W)); pos_a = zeros(size(a));
            neg_W = zeros(size(W)); neg_a = zeros(size(a));

            % Loop over all training images to compute gradient terms
            for i=1:batch_size

                % Get image
                im = reshape(batch(i,:), [size_im size_im]);

%                 % Check gradients
%                 options = zeros(18, 1);
%                 options(9) = 1;
%                 hmc('foe_energy_w', W(1:end), options, 'foe_energy_grad_w', im, basis, a);
%                 hmc('foe_energy_a', a, options, 'foe_energy_grad_a', im, basis, W);
%                 hmc('foe_energy', im(1:end), options, 'foe_energy_grad_x', basis, W, a, [size_im size_im 1]);

                % Compute positive part of gradient
                pos_W = pos_W + reshape(foe_energy_grad_w(W(1:end), im, basis, a), size(W));
                pos_a = pos_a + foe_energy_grad_a(a, im, basis, W);

                % Draw samples from model using hybrid Monte Carlo
                options = zeros(18, 1);
                options(1)  = 0;                    % do not print diagnostics
                options(5)  = 0;                    % do not use momentum persistence
                options(7)  = 30;                   % number of leaps (= steps in leap-frog)
                options(9)  = 0;                    % do not check gradient
                options(14) = 1;                    % number of samples to return
                options(15) = 0;                    % number of samples to omit from start
                sample = hmc('foe_energy', batch(i,:), options, 'foe_energy_grad_x', basis, W, a, [size_im size_im 1]);

                % Compute negative CD part
                neg_W = neg_W + reshape(foe_energy_grad_w(W(1:end), sample, basis, a), size(W));
                neg_a = neg_a + foe_energy_grad_a(a, sample, basis, W);
            end

            % Perform the gradient updates
            prev_dW = eta_W * (momentum * prev_dW + (1 - momentum) * (1 / batch_size) * (pos_W - neg_W));
            prev_da = eta_a * (momentum * prev_da + (1 - momentum) * (1 / batch_size) * (pos_a - neg_a));
            W = W + prev_dW;
            a = exp(log(a) + a .* prev_da);
        end

        % Evaluate sum of energies of training data
        sum_E = 0;
        for i=1:no_images
            im = reshape(images(i,:), [size_im size_im]);
            sum_E = sum_E + foe_energy(im, basis, W, a);
        end
        disp(['     mean energy of training data is ' num2str(sum_E ./ no_images)]);
        train_err(iter) = sum_E ./ no_images;
        toc
    end


function [x] = spm_gen_phase(P,M,U)
% Generate state activities for trial-specific phase-coupled activity
% FORMAT [x] = spm_gen_phase(P,M,U)
%
% P - parameters
% M - model structure
% U - trial-specific effects
%
% x - states
%
%__________________________________________________________________________
% Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging

% Will Penny
% $Id: spm_gen_phase.m 2908 2009-03-20 14:54:03Z will $

% between-trial inputs
%==========================================================================
try, X = U.X; catch, X = sparse(1,0); end

if isfield(M,'trial')
    Mx=M.x;
end

% cycle over trials
%--------------------------------------------------------------------------
for  c = 1:size(X,1)

    % baseline parameters
    %----------------------------------------------------------------------
    Q  = P;

    % trial-specific inputs
    %----------------------------------------------------------------------
    for i = 1:size(X,2)
          Q.As = Q.As + X(c,i)*Q.Bs{i};
    end
    if isfield(Q,'Ac')
        for i = 1:size(X,2)
            Q.Ac = Q.Ac + X(c,i)*Q.Bc{i};
        end
    end

    if isfield(M,'trial')
        % Set up trial-specific initial state
        M.x=M.trial{c}.x;
    end

    x{c,1} = spm_int_ode(Q,M,U);

end

if isfield(M,'trial')
    M.x=Mx;
end


%% Copyright (C) 2014-2016 Colin B. Macdonald
%%
%% This file is part of OctSymPy
%%
%% OctSymPy 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 software 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 software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defmethod @@sym isallconstant (@var{x})
%% Whether all elements of a symbolic array are constant.
%%
%% Example:
%% @example
%% @group
%% A = [1 2 sym(pi); sym(4) 5 6]
%%   @result{} A = (sym 2×3 matrix)
%%       ⎡1  2  π⎤
%%       ⎢       ⎥
%%       ⎣4  5  6⎦
%%
%% isallconstant (A)
%%   @result{} ans = 1
%% @end group
%%
%% @group
%% A(1) = sym('x')
%%   @result{} A = (sym 2×3 matrix)
%%       ⎡x  2  π⎤
%%       ⎢       ⎥
%%       ⎣4  5  6⎦
%%
%% isallconstant (A)
%%   @result{} ans = 0
%% @end group
%% @end example
%%
%% @seealso{@@sym/isconstant, @@sym/symvar, findsymbols}
%% @end defmethod

function z = isallconstant(x)

  z = isempty (findsymbols (x));

end

%!assert (isallconstant([sym(1) 2 3]))

%!test
%! syms x
%! assert (~isallconstant([sym(1) x 3]))

%!test
%! syms x
%! assert (~isallconstant([sym(1) x; sym(2) 3]))


%DEMO_MODELASSESMENT2  Demonstration for model assessment when the observation
%                      model is non-Gaussian
%
%  Description
%    We will consider the classification problem in demo_classific.
%    The analysis is conducted with full Gaussian process using
%    both probit and logit likelihood. The performance of these two
%    models are compared by evaluating the ten-fold
%    cross-validation, leave-one-out cross-validation, WAIC, DIC
%    and the effective number of parameters The inference will be
%    conducted using maximum a posterior (MAP) estimate for the
%    parameters using EP and Laplace approximation, via full Markov
%    chain Monte Carlo (MCMC) and with an integration approximation
%    (IA) for the parameters.
%
%    This demo is organised in two parts:
%     1) data analysis with with probit likelihood
%     2) data analysis with with logit likelihood
%
%  See also
%    DEMO_CLASSIFIC1, DEMO_MODELASSESMENT1

% Copyright (c) 2009-2010 Jarno Vanhatalo
% Copyright (c) 2010 Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

% =====================================
% 1) data analysis with probit likelihood
% =====================================
disp('Data analysis with probit likelihood')
S = which('demo_classific');
L = strrep(S,'demo_classific.m','demodata/synth.tr');
x=load(L);
y=x(:,end);
y = 2.*y-1;
x(:,end)=[];
[n, nin] = size(x);

DIC=repmat(NaN,1,8);DIC2=repmat(NaN,1,8);DIC_latent=repmat(NaN,1,8);
p_eff=repmat(NaN,1,8);p_eff2=repmat(NaN,1,8);p_eff_latent=repmat(NaN,1,8);p_eff_latent2=repmat(NaN,1,8);

% Create covariance functions
gpcf = gpcf_sexp('lengthScale', [0.9 0.9], 'magnSigma2', 2);

% Set the prior for the parameters of covariance functions
pl = prior_logunif();
gpcf = gpcf_sexp(gpcf, 'lengthScale_prior', pl,'magnSigma2_prior', pl); %

% Create the GP structure
gp = gp_set('lik', lik_probit, 'cf', gpcf, 'jitterSigma2', 1e-4);

% ------- Laplace approximation --------
disp(['Probit with Laplace integration over the latent values '; ...
      'and MAP estimate for the parameters                    '])

% Set the approximate inference method
gp = gp_set(gp, 'latent_method', 'Laplace');

n=length(y);

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);
% Optimize with the quasi-Newton method
gp=gp_optim(gp,x,y,'opt',opt,'optimf',@fminlbfgs);

% Evaluate the effective number of parameters and DIC with focus on
% latent variables.
models{1} = 'pr_Laplace';
p_eff_latent(1) = gp_peff(gp, x, y);
[DIC_latent(1), p_eff_latent2(1)] = gp_dic(gp, x, y, 'focus', 'latent');
WAIC(1) = gp_waic(gp,x,y);

% Evaluate the 10-fold cross-validation results.
cvres = gp_kfcv(gp, x, y, 'display', 'fold');
mlpd_cv(1) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(gp, x, y);
mlpd_loo(1) = mean(lpy);

% ------- Expectation propagation --------
disp(['Probit with EP integration over the latent values and MAP '; ...
      'estimate for the parameters                               '])

% Set the approximate inference method
gp = gp_set(gp, 'latent_method', 'EP');

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);
% Optimize with the BFGS quasi-Newton method
gp=gp_optim(gp,x,y,'opt',opt,'optimf',@fminlbfgs);

% Evaluate the effective number of parameters and DIC with focus on
% latent variables.
models{2} = 'pr_EP';
p_eff_latent(2) = gp_peff(gp, x, y) ;
[DIC_latent(2), p_eff_latent2(2)] = gp_dic(gp, x, y, 'focus', 'latent');
WAIC(2) = gp_waic(gp,x,y);

% Evaluate the 10-fold cross-validation results.
cvres = gp_kfcv(gp, x, y, 'display', 'fold');
mlpd_cv(2) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(gp, x, y);
mlpd_loo(2) = mean(lpy);

% ------- MCMC ---------------
disp(['Probit with MCMC integration over the latent values and '; ...
      'the parameters                                          '])

% Set the approximate inference method
gp = gp_set(gp, 'latent_method', 'MCMC');

% Sample
mcopt.nsamples=220;mcopt.display=20;
[rgp,gp]=gp_mc(gp, x, y, mcopt);
rgp=thin(rgp, 21, 2);

% Evaluate the effective number of parameters and DIC with focus on
% latent variables.
models{3} = 'pr_MCMC';
[DIC(3), p_eff(3)] =  gp_dic(rgp, x, y, 'focus', 'param');
[DIC2(3), p_eff2(3)] =  gp_dic(rgp, x, y, 'focus', 'all');
WAIC(3) = gp_waic(rgp,x,y);

% Evaluate the 10-fold cross-validation results.
mcopt.nsamples=50;mcopt.display=20;
cvres = gp_kfcv(gp, x, y, 'inf_method', 'MCMC', 'opt', mcopt, 'display', 'fold');
mlpd_cv(3) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(rgp, x, y);
mlpd_loo(3) = mean(lpy);

% --- Integration approximation approach ---
disp(['Probit with EP integration over the latent values and '; ...
      'grid integration over the parameters                  '])

% Use EP
gp = gp_set(gp, 'latent_method', 'EP');

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);
% Optimize with the BFGS quasi-Newton method
gp=gp_optim(gp,x,y,'opt',opt,'optimf',@fminlbfgs);

% now perform the integration
clear opt
opt.int_method = 'grid';
opt.step_size = 2;
gp_array = gp_ia(gp, x, y, opt);

models{4} = 'pr_IA';
[DIC(4), p_eff(4)] =  gp_dic(gp_array, x, y, 'focus', 'param');
[DIC2(4), p_eff2(4)] =  gp_dic(gp_array, x, y, 'focus', 'all');
WAIC(4) = gp_waic(gp_array,x,y);

% Then the 10 fold cross-validation.
cvres = gp_kfcv(gp, x, y, 'inf_method', 'IA', 'opt', opt, 'display', 'fold');
mlpd_cv(4) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(gp_array, x, y);
mlpd_loo(4) = mean(lpy);

% =====================================
% 2) data analysis with logit likelihood
% =====================================
disp('Data analysis with logit likelihood')

S = which('demo_classific');
L = strrep(S,'demo_classific.m','demodata/synth.tr');
x=load(L);
y=x(:,end);
y = 2.*y-1;
x(:,end)=[];
[n, nin] = size(x);

% Create covariance functions
gpcf = gpcf_sexp('lengthScale', [0.9 0.9], 'magnSigma2', 2);

% Set the prior for the parameters of covariance functions
pl = prior_logunif();
gpcf = gpcf_sexp(gpcf, 'lengthScale_prior', pl,'magnSigma2_prior', pl); %

% Create the likelihood structure
lik = ('init');

% Create the GP structure
gp = gp_set('lik', lik_logit, 'cf', gpcf, 'jitterSigma2', 1e-4);

% ------- Laplace approximation --------
disp(['Logit with Laplace integration over the latent values and '; ...
      'MAP estimate for the parameters                           '])

% Set the approximate inference method
gp = gp_set(gp, 'latent_method', 'Laplace');

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);
% Optimize with the BFGS quasi-Newton method
gp=gp_optim(gp,x,y,'opt',opt,'optimf',@fminlbfgs);

% Evaluate the effective number of parameters and DIC with focus on
% latent variables.
models{5} = 'lo_Laplace';
p_eff_latent(5) = gp_peff(gp, x, y);
[DIC_latent(5), p_eff_latent2(5)] = gp_dic(gp, x, y, 'focus', 'latent');
WAIC(5) = gp_waic(gp,x,y);

% Evaluate the 10-fold cross-validation results.
cvres = gp_kfcv(gp, x, y, 'display', 'fold');
mlpd_cv(5) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(gp, x, y);
mlpd_loo(5) = mean(lpy);

% ------- Expectation propagation --------
disp(['Logit with EP integration over the latent values and MAP'; ...
      'estimate for the parameters                             '])

% Set the approximate inference method
gp = gp_set(gp, 'latent_method', 'EP');

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);
% Optimize with the BFGS quasi-Newton method
gp=gp_optim(gp,x,y,'opt',opt,'optimf',@fminlbfgs);

% Evaluate the effective number of parameters and DIC with focus on
% latent variables.
models{6} = 'lo_EP';
p_eff_latent(6) = gp_peff(gp, x, y) ;
[DIC_latent(6), p_eff_latent2(6)] = gp_dic(gp, x, y, 'focus', 'latent');
WAIC(6) = gp_waic(gp,x,y);

% Evaluate the 10-fold cross-validation results.
cvres = gp_kfcv(gp, x, y, 'display', 'fold');
mlpd_cv(6) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(gp, x, y);
mlpd_loo(6) = mean(lpy);

% ------- MCMC ---------------
disp(['Logit with MCMC integration over the latent values and '; ...
      'the parameters                                         '])

% Set the approximate inference method
gp = gp_set(gp, 'latent_method', 'MCMC');

% Sample
mcopt.nsamples=200;mcopt.display=20;
[rgp,gp] = gp_mc(gp, x, y, mcopt);
rgp=thin(rgp, 21, 2);

% Evaluate the effective number of parameters and DIC with focus on latent variables.
models{7} = 'lo_MCMC';
[DIC(7), p_eff(7)] =  gp_dic(rgp, x, y, 'focus', 'param');
[DIC2(7), p_eff2(7)] =  gp_dic(rgp, x, y, 'focus', 'all');
WAIC(7) = gp_waic(rgp,x,y);

% Evaluate the 10-fold cross-validation results.
mcopt.nsamples=50;mcopt.display=20;
cvres = gp_kfcv(gp, x, y, 'inf_method', 'MCMC', 'opt', mcopt, 'display', 'fold');
mlpd_cv(7) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(rgp, x, y);
mlpd_loo(7) = mean(lpy);

% --- Integration approximation approach ---
disp(['Logit with EP integration over the latent values and grid '; ...
      'integration over the parameters                           '])

% Use EP
gp = gp_set(gp, 'latent_method', 'EP');

% Set the options for the optimization
opt=optimset('TolFun',1e-3,'TolX',1e-3);
% Optimize with the BFGS quasi-Newton method
gp=gp_optim(gp,x,y,'opt',opt,'optimf',@fminlbfgs);

% now perform the integration
clear opt
opt.int_method = 'grid';
opt.step_size = 2;
gp_array = gp_ia(gp, x, y, opt);

models{8} = 'lo_IA';
[DIC(8), p_eff(8)] =  gp_dic(gp_array, x, y, 'focus', 'param');
[DIC2(8), p_eff2(8)] =  gp_dic(gp_array, x, y, 'focus', 'all');
WAIC(8) = gp_waic(gp_array,x,y);

% Then the 10 fold cross-validation.
cvres = gp_kfcv(gp, x, y, 'inf_method', 'IA', 'opt', opt, 'display', 'fold');
mlpd_cv(8) = cvres.mlpd_cv;

% Evaluate the leave-one-out cross-validation results.
[Ef,Varf,lpy] =  gp_loopred(gp_array, x, y);
mlpd_loo(8) = mean(lpy);

%========================================================
% PART 4 Print the results
%========================================================
disp('Summary of the results')

S = '       ';
for i = 1:length(models)
    S = [S '  ' models{i}];
end

S = sprintf([S '\n CV-mlpd  %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], mlpd_cv);
S = sprintf([S '\n LOO-mlpd %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], mlpd_loo);
S = sprintf([S '\n ']);
S = sprintf([S '\n WAIC     %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], WAIC);
S = sprintf([S '\n ']);
S = sprintf([S '\n DIC_h    %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], DIC);
S = sprintf([S '\n DIC_a    %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], DIC2);
S = sprintf([S '\n DIC_l    %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], DIC_latent);
S = sprintf([S '\n peff_h   %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], p_eff);
S = sprintf([S '\n peff_a   %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], p_eff2);
S = sprintf([S '\n peff_l   %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], p_eff_latent);
S = sprintf([S '\n peff_l2  %6.2f    %6.2f  %6.2f  %6.2f   %6.2f    %6.2f  %6.2f  %6.2f'], p_eff_latent2);
S = sprintf([S '\n ']);
S = sprintf([S '\n The notation is as follows:']);
S = sprintf([S '\n pr_*     = probit likelihood and inference method']);
S = sprintf([S '\n lo_*     = logit likelihood and inference method']);
S = sprintf([S '\n CV-mlpd  = mean log predictive density from the 10-fold CV. ']);
S = sprintf([S '\n LOO-mlpd = mean log predictive density from the 10-fold CV. ']);
S = sprintf([S '\n WAIC     = Widely applicable information criterion. ']);
S = sprintf([S '\n DIC_h    = DIC with focus on parameters. ']);
S = sprintf([S '\n DIC_a    = DIC with focus on parameters and laten variables (all). ']);
S = sprintf([S '\n DIC_l    = DIC with focus on latent variables. ']);
S = sprintf([S '\n peff_h   = effective number of parameters (latent variables marginalized). ']);
S = sprintf([S '\n peff_a   = effective number of parameters and latent variables. ']);
S = sprintf([S '\n peff_l   = effective number of latent variables evaluated with gp_peff. ']);
S = sprintf([S '\n peff_l2  = effective number of latent variables evaluated with gp_dic. ']);
S = sprintf([S '\n '])


% SYNTAX:
% [data_dN, tInc, svs, nSV, tInc0] = hmrR_MotionCorrectPCArecurse(data_d, probe, mlActMan, mlActAuto, tIncMan, tMotion, tMask, STDEVthresh, AMPthresh, nSV, maxIter, turnon)
%
%
% UI NAME:
% Motion_Correct_PCA_Recurse
%
%
% DESCRIPTION:
% Identified motion artifacts in an input data matrix d. If any active
% data channel exhibits a signal change greater than STDEVthresh or
% AMPthresh, then a segment of data around that time point is marked as a
% motion artifact. Set maxIter=0 to skip this function.
%
%
% INPUTS:
% data_d: data matrix, timepoints x sd pairs
% sd: Source Detector Structure. The active data channels are indicated in
%     SD.MeasListAct.
% mlActMan: Cell array of vectors, one for each time base in data, specifying
%        active/inactive channels with 1 meaning active, 0 meaning inactive
% mlActAuto: Cell array of vectors, one for each time base in data, specifying
%        active/inactive channels with 1 meaning active, 0 meaning inactive
% tIncMan: Data that has been manually excluded. 0-excluded. 1-included.
%          Vector same length as d.
% tMotion: Check for signal change indicative of a motion artifact over
%     time range tMotion. Units of seconds. Typically tMotion=0.5.
% tMask: Mark data over +/- tMask seconds around the identified motion
%     artifact as a motion artifact. Units of seconds. Typicall tMask=1.
% STDEVthresh: If the signal d for any given active channel changes by more
%     that stdev_thresh * stdev(d) over the time interval tMotion, then
%     this time point is marked as a motion artifact. The standard deviation is
%     determined for each channel independently.
% AMPthresh: If the signal d for any given active channel changes by more
%     that AMPthresh over the time interval tMotion, then this time point
%     is marked as a motion artifact.
% nSV: This is the number of principal components to remove from the data.
%      If this number is less than 1, then the filter removes the first n
%      components of the data that removes a fraction of the variance
%      up to nSV. Yucel et al uses nSV=0.97.
% maxIter: Maximum number of iterations. Yucel et al uses maxIter=5;
%
%
% OUTPUTS:
% data_dN: This is the the motion corrected data.
% tInc: a vector of length time points with 1's indicating data included
%       and 0's indicate motion artifact AFTER correction of motion
%       artifacts
% svs: the singular values of the PCA for each iteration in each column
%      vector
% nSV: number of singular values removed from the data.
% tInc0: a vector of length time points with 1's indicating data included
%       and 0's indicate motion artifact BEFORE correction of motion
%       artifacts
%
% USAGE OPTIONS:
% Motion_Correct_PCA_Recurse:  [dod, tInc, svs, nSV, tInc0] = hmrR_MotionCorrectPCArecurse(dod, probe, mlActMan, mlActAuto, tIncMan, tMotion, tMask, STDEVthresh, AMPthresh, nSV, maxIter, turnon)
%
% PARAMETERS:
% tMotion: 0.5
% tMask: 1.0
% STDEVthresh: 20.0
% AMPthresh: 5.00
% nSV: 0.97
% maxIter: 5
% turnon: 1
%
% PREREQUISITES:
% Intensity_to_Delta_OD: dod = hmrR_Intensity2OD( intensity )
%

function [data_dN, tInc, svs, nSV, tInc0] = hmrR_MotionCorrectPCArecurse(data_d, probe, mlActMan,  mlActAuto, tIncMan, tMotion, tMask, STDEVthresh, AMPthresh, nSV, maxIter, turnon)

nBlks = length(data_d);
for iBlk=1:nBlks
    data_dN(iBlk) = DataClass(data_d(iBlk));
end

% Initialize output
tInc    = tIncMan;
svs     = cell(nBlks,1);
nSV     = repmat({nSV}, nBlks,1);
tInc0   = tIncMan;

% Check input args
if isempty(mlActMan)
    mlActMan = cell(nBlks,1);
end
if isempty(mlActAuto)
    mlActAuto = cell(nBlks,1);
end
if isempty(tIncMan)
    tIncMan = cell(nBlks,1);
end
if ~exist('turnon','var')
    turnon = 1;
end
if turnon==0
    return;
end

for iBlk=1:nBlks
    data_dN(iBlk) = DataClass(data_d(iBlk));

    tInc(iBlk) = hmrR_MotionArtifact(data_d(iBlk), probe, mlActMan(iBlk),  mlActAuto(iBlk), tIncMan(iBlk), tMotion, tMask, STDEVthresh, AMPthresh);

    tInc0{iBlk} = tInc{iBlk};

    ii=0;
    while length(find(tInc{iBlk}==0))>0 & ii<maxIter
        ii=ii+1;
        [data_dN(iBlk), svs_ii, nSV(iBlk)] = hmrR_MotionCorrectPCA(data_d(iBlk), mlActMan(iBlk), mlActAuto(iBlk), tIncMan(iBlk), tInc(iBlk), nSV(iBlk));
        tInc(iBlk) = hmrR_MotionArtifact(data_dN(iBlk), probe, mlActMan(iBlk), mlActAuto(iBlk), tIncMan(iBlk), tMotion, tMask, STDEVthresh, AMPthresh);
        data_d(iBlk).Copy(data_dN(iBlk));
        svs{iBlk}(:,ii) = svs_ii{1};
    end
end


function out=sum(x,dim)

precision=x(1).precision;
% can only handle up to 2 dimensions
s=size(x);
if nargin==1
 if any(s==1)
  out=mp(0,precision);
  for ii=1:numel(x)
   out=out+x(ii);
  end
 else
  out=mp(zeros(1,s(2)),precision);
  for j=1:s(2)
   for i=1:s(1)
    out(1,j)=out(1,j)+x(i,j);
   end
  end
 end
elseif nargin==2
 if dim==1
  out=mp(zeros(1,s(2)),precision);
  for j=1:s(2)
   for i=1:s(1)
    out(1,j)=out(1,j)+x(i,j);
   end
  end
 elseif dim==2
  out=mp(zeros(s(1),1),precision);
  for j=1:s(2)
   for i=1:s(1)
    out(i,1)=out(i,1)+x(i,j);
   end
  end
 else
  error('mp sum can only handle up to 2-D arrays (11/04)');
 end
end


function [f, logscale] = fwd(engine, fpast, ev, t)
% Forwards pass.

f.obslik = mk_hmm_obs_lik_vec(engine, ev);
transmat = engine.transprob;
f.past_alpha = fpast.alpha;
if engine.maximize
  Q = length(fpast.alpha);
  A = repmat(fpast.alpha, [1 Q]);
  m = max(transmat .* A, [], 1);
  [f.alpha, scale] = normalise(m(:) .* f.obslik);
else
  [f.alpha, scale] = normalise((transmat' * fpast.alpha) .* f.obslik);
end
logscale = log(scale);
%f.xi = normalise((fpast.alpha * obslik') .* transmat); % t-1,t
f.t = t;


function perm0_uniform_test ( )

%*****************************************************************************80
%
%% PERM0_UNIFORM_TEST tests PERM0_UNIFORM.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 May 2015
%
%  Author:
%
%    John Burkardt
%
  n = 10;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'PERM0_UNIFORM_TEST\n' );
  fprintf ( 1, '  PERM0_UNIFORM randomly selects a permutation of 0, ..., N-1.\n' );
  fprintf ( 1, '\n' );

  seed = 123456789;

  for test = 1 : 5

    [ p, seed ] = perm0_uniform ( n, seed );

    fprintf ( 1, '  ' );
    for i = 1 : n
      fprintf ( 1, '%4d', p(i) );
    end
    fprintf ( 1, '\n' );

  end

  return
end


% MATCORR - Find matching rows in two matrices and their corrs.
%             Uses the Hungarian (default), VAM, or maxcorr assignment methods.
%             (Follow with MATPERM to permute and sign x -> y).
%
% Usage: >> [corr,indx,indy,corrs] = matcorr(x,y,rmmean,method,weighting);
%
% Inputs:
%   x     = first input matrix
%   y     = matrix with same number of columns as x
%
% Optional inputs:
%   rmmean    = When present and non-zero, remove row means prior to correlation
%               {default: 0}
%   method    = Method used to find assignments.
%               0= Hungarian Method - maximize sum of abs corrs {default: 2}
%               1= Vogel's Assignment Method -find pairs in order of max contrast
%               2= Max Abs Corr Method - find pairs in order of max abs corr
%               Note that the methods 0 and 1 require matrices to be square.
%   weighting = An optional weighting matrix size(weighting) = size(corrs) that
%               weights the corrs matrix before pair assignment {def: 0/[] -> ones}
% Outputs:
%   corr  = a column vector of correlation coefficients between
%           best-correlating rows of matrice x and y
%   indx  = a column vector containing the index of the maximum
%           abs-correlated x row in descending order of abs corr
%           (no duplications)
%   indy  = a column vector containing the index of the maximum
%           abs-correlated row of y in descending order of abs corr
%           (no duplications)
%   corrs = an optional square matrix of row-correlation coefficients
%           between matrices x and y
%
% Note: outputs are sorted by abs(corr)
%
% Authors: Scott Makeig & Sigurd Enghoff, SCCN/INC/UCSD, La Jolla, 11-30-96

% Copyright (C) 11-30-96 Scott Makeig, SCCN/INC/UCSD, scott@sccn.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.

% 04-22-99 Re-written using VAM by Sigurd Enghoff, CNL/Salk
% 04-30-99 Added revision of algorithm loop by SE -sm
% 05-25-99 Added Hungarian method assignment by SE
% 06-15-99 Maximum correlation method reinstated by SE
% 08-02-99 Made order of outputs match help msg -sm
% 02-16-00 Fixed order of corr output under VAM added method explanations,
%          and returned corr signs in abs max method -sm
% 01-25-02 reformated help & license, added links -ad

% Uses function hungarian.m

function [corr,indx,indy,corrs] = matcorr(x,y,rmmean,method,weighting)
%
if nargin < 2 || nargin > 5
  help matcorr
  return
end

if nargin < 4
	method = 2; % default: Max Abs Corr - select successive best abs(corr) pairs
end

[m,n] = size(x);
[p,q] = size(y);
m = min(m,p);

if m~=n || p~=q
   if nargin>3 && method~=2
     fprintf('matcorr(): Matrices are not square: using max abs corr method (2).\n');
   end
   method = 2; % Can accept non-square matrices
end

if n~=q
  error('Rows in the two input matrices must be the same length.');
end

if nargin < 3 || isempty(rmmean)
  rmmean = 0;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if rmmean
  x = x - mean(x')'*ones(1,n); % optionally remove means
  y = y - mean(y')'*ones(1,n);
end
dx = sum(x'.^2);
dy = sum(y'.^2);
dx(find(dx==0)) = 1;
dy(find(dy==0)) = 1;
corrs = x*y'./sqrt(dx'*dy);

if nargin > 4 && ~isempty(weighting) && norm(weighting) > 0,
  if any(size(corrs) ~= size(weighting))
    fprintf('matcorr(): weighting matrix size must match that of corrs\n.')
    return
  else
	corrs = corrs.*weighting;
  end
end

cc = abs(corrs);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
switch method
case 0
	ass = hungarian(-cc);   % Performs Hungarian algorithm matching

	idx1 = sub2ind(size(cc),ass,1:m);
	[dummy idx2] = sort(-cc(idx1));
	corr = corrs(idx1);
	corr = corr(idx2)';
	indy = [1:m]';
	indx = ass(idx2)';
	indy = indy(idx2);

case 1                      % Implements the VAM assignment method
	indx = zeros(m,1);
	indy = zeros(m,1);
	corr = zeros(m,1);

	for i=1:m,
		[sx ix] = sort(cc);  % Looks for maximum salience along a row/column
		[sy iy] = sort(cc'); % rather than maximum correlation.
		[sxx ixx] = max(sx(end,:)-sx(end-1,:));
		[syy iyy] = max(sy(end,:)-sy(end-1,:));

		if sxx == syy
			if sxx == 0 && syy == 0
        	   [sxx ixx] = max((sx(end,:)-sx(end-1,:)) .* sx(end,:));
    	       [syy iyy] = max((sy(end,:)-sy(end-1,:)) .* sy(end,:));
			else
				sxx = sx(end,ixx); % takes care of identical vectors
				syy = sy(end,iyy); % and zero vectors
			end
		end

		if sxx > syy
			indx(i) = ix(end,ixx);
			indy(i) = ixx;
		else
			indx(i) = iyy;
			indy(i) = iy(end,iyy);
		end
		cc(indx(i),:) = -1;
		cc(:,indy(i)) = -1;
	end

	i = sub2ind(size(corrs),indx,indy);
	corr = corrs(i);

	[tmp j] = sort(-abs(corr)); % re-sort by abs(correlation)
	corr = corr(j);
	indx = indx(j);
	indy = indy(j);

case 2                       % match successive max(abs(corr)) pairs
	indx = zeros(size(cc,1),1);
	indy = zeros(size(cc,1),1);
	corr = zeros(size(cc,1),1);

	for i = 1:size(cc,1)
		[tmp j] = max(cc(:));
		% [corr(i) j] = max(cc(:));
		[indx(i) indy(i)] = ind2sub(size(cc),j);
        corr(i) = corrs(indx(i),indy(i));
		cc(indx(i),:) = -1; % remove from contention
		cc(:,indy(i)) = -1;
	end

otherwise
	error('Unknown method');
end


function tests = test_imDistanceMap(varargin)
% Test suite for function imDistanceMap.
%
%   output = test_imDistanceMap(input)
%
%   Example
%   test_imDistanceMap
%
%   See also
%

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2018-02-22,    using Matlab 2017b
% Copyright 2010 INRA - Cepia Software Platform.

tests = functiontests(localfunctions);

function test_TouchingParticles(testCase)
% Aim is to compute distance map within each label, even if some of them
% touch each other.
% Uses an image with a completely landlocked label region.

img = [...
    0 0 0 0 0 0 0 0 0 0 0; ...
    0 1 1 1 2 2 2 3 3 3 0; ...
    0 1 1 1 2 2 2 3 3 3 0; ...
    0 1 1 1 2 2 2 3 3 3 0; ...
    0 1 1 1 4 4 4 3 3 3 0; ...
    0 1 1 1 4 4 4 3 3 3 0; ...
    0 1 1 1 4 4 4 3 3 3 0; ...
    0 1 1 1 5 5 5 3 3 3 0; ...
    0 1 1 1 5 5 5 3 3 3 0; ...
    0 1 1 1 5 5 5 3 3 3 0; ...
    0 0 0 0 0 0 0 0 0 0 0; ...
];

exp = [...
    0 0 0 0 0 0 0 0 0 0 0; ...
    0 1 1 1 1 1 1 1 1 1 0; ...
    0 1 2 1 1 2 1 1 2 1 0; ...
    0 1 2 1 1 1 1 1 2 1 0; ...
    0 1 2 1 1 1 1 1 2 1 0; ...
    0 1 2 1 1 2 1 1 2 1 0; ...
    0 1 2 1 1 1 1 1 2 1 0; ...
    0 1 2 1 1 1 1 1 2 1 0; ...
    0 1 2 1 1 2 1 1 2 1 0; ...
    0 1 1 1 1 1 1 1 1 1 0; ...
    0 0 0 0 0 0 0 0 0 0 0; ...
];

dist = imDistanceMap(img, [3 4]);

assertEqual(testCase, dist, exp);


% This is material illustrating the methods from the book
% Financial Modelling  - Theory, Implementation and Practice with Matlab
% source
% Wiley Finance Series
% ISBN 978-0-470-74489-5
%
% Date: 02.05.2012
%
% Authors:  Joerg Kienitz
%           Daniel Wetterau
%
% Please send comments, suggestions, bugs, code etc. to
% kienitzwetterau_FinModelling@gmx.de
%
% (C) Joerg Kienitz, Daniel Wetterau
%
% Since this piece of code is distributed via the mathworks file-exchange
% it is covered by the BSD license
%
% This code is being provided solely for information and general
% illustrative purposes. The authors will not be responsible for the
% consequences of reliance upon using the code or for numbers produced
% from using the code.

function y = StuCVaR4(x)
% General method to compute CVaR for Student distribution with 4 degrees
% of freedom
    f = @(t,n) -(n^(n-2)*(n+t.^2).^(.5-.5*n)*gamma(.5*(n-1))/(2*sqrt(pi)*gamma(.5*n)));
    arg = InverseCDF4(x);
    y = 1 / sqrt(2)*f(arg,4)./x;
end


function D = compute_deviator_tensor(T)

% compute_deviator_tensor - compute trace free tensor
%
%   D = compute_deviator_tensor(T);
%
%   D = T - trace(T)/2*Id
%
%   Copyright (c) Gabriel Peyre

n = size(T,1);

if size(T,3)==2 && size(T,4)==2
    t = (T(:,:,1)+T(:,:,4))/2;
    D = cat(3, t, zeros(n), zeros(n), t);
    D = T - reshape(D,[n n 2 2]);
elseif size(T,3)==3 && size(T,4)==1
    t = (T(:,:,1)+T(:,:,2))/2;
    D = cat(3, t, t, zeros(n));
    D = T - D;
else
    error('Wrong size');
end


%
% LibQPEP: A Library for Globally Optimal Solving Quadratic Pose Estimation Problems (QPEPs),
%          It also gives highly accurate uncertainty description of the solutions.
%
%
% Article:
%      Wu, J., Zheng, Y., Gao, Z., Jiang, Y., Hu, X., Zhu, Y., Jiao, J., Liu, M. (2020)
%           Quadratic Pose Estimation Problems: Unified Solutions,
%           Solvability/Observability Analysis and Uncertainty Description
%           in A Globally Optimal Framework.
%
%
% Authors:      Jin Wu and Ming Liu
% Affiliation:  Hong Kong University of Science and Technology (HKUST)
% Emails:       jin_wu_uestc@hotmail.com; eelium@ust.hk
% Websites:     https://zarathustr.github.io
%               https://ram-lab.com

function x = sym2vec(X)
n = size(X, 1);
x = [];
for i = 1 : n
    x = [x; X(i, i : n).'];
end
end


function h = fh03 ( p, varargin )

%*****************************************************************************80
%
%% FH03 returns a uniform mesh size function.
%
%  Copyright:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input, real P(NP,ND), the point coordinates.
%
%    Input, VARARGIN, room for extra arguments.
%
%    Output, real H(NP,1), the mesh size function.
%
  np = size ( p, 1 );
  h = ones ( np, 1 );

  return
end


function M = spm_mesh_refine(M)
% Refine a triangle mesh
% FORMAT M = spm_mesh_refine(M)
% M        - a patch structure or gifti object
%__________________________________________________________________________
%
% See also:
%
% R.E. Bank, A.H. Sherman and A. Weiser. Refinement Algorithms and Data
% Structures for Regular Local Mesh Refinement. Scientific Computing
% (Applications of Mathematics and Computing to the Physical Sciences)
% (R. S. Stepleman, ed.), North-Holland (1983), 3-17.
% https://ccom.ucsd.edu/~reb/reports/a23.pdf.gz
%__________________________________________________________________________
% Copyright (C) 2018-2019 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_mesh_refine.m 7514 2019-01-16 16:18:52Z guillaume $

V  = M.vertices;
F  = M.faces;

Nv = size(V,1);
Nf = size(F,1);

Vo = V;
Fo = zeros(4*Nf,3);
A  = spm_mesh_adjacency(M);
if isfield(M,'cdata')
    cdata = M.cdata;
else
    cdata = [];
end

for f=1:Nf
    T0 = F(f,:);
    T1 = T0([2 3 1]);
    v  = (V(T0,:) + V(T1,:)) / 2;
    if ~isempty(cdata), C = (cdata(T0,:) + cdata(T1,:)) / 2; end

    s = 1:3;
    b = [false false false];
    for j=1:3
        if A(T0(j),T1(j)) == 1
            s(j) = Nv + 1;
            A(T0(j),T1(j)) = s(j);
            A(T1(j),T0(j)) = s(j);
            Nv = s(j);
            b(j) = true;
        else
            s(j) = A(T0(j),T1(j));
        end
    end
    Vo(end+1:end+nnz(b),:) = v(b,:);
    if ~isempty(cdata), cdata(end+1:end+nnz(b),:) = C(b,:); end
    T0(4:6) = s;

    Fo(4*f+(-3:0),:) = T0([1 4 6;4 2 5;6 5 3;4 5 6]);
end

M.faces = Fo;
M.vertices = Vo;
if ~isempty(cdata), M.cdata = cdata; end


function cin_test ( )

%*****************************************************************************80
%
%% CIN_TEST tests R4_CIN and R8_CIN.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 September 2011
%
%  Author:
%
%    John Burkardt
%
  addpath ( '../test_values' );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'CIN_TEST:\n' );
  fprintf ( 1, '  Test CIN_VALUES, R4_CIN, R8_CIN.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '             X          CIN(X)\n' );
  fprintf ( 1, '                     R4_CIN(X)        Diff\n' );
  fprintf ( 1, '                     R8_CIN(X)        Diff\n' );

  n_data = 0;

  while ( 1 )

    [ n_data, x, fx1 ] = cin_values ( n_data );

    if ( n_data == 0 )
      break
    end

    fx2 = r4_cin ( single ( x ) );
    fx3 = r8_cin ( x );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  %14.4f  %14.6g\n', x, fx1 );
    fprintf ( 1, '                  %14.6g  %14.6g\n', fx2, abs ( fx1 - fx2 ) );
    fprintf ( 1, '                  %14.6g  %14.6g\n', fx3, abs ( fx1 - fx3 ) );

  end

  rmpath ( '../test_values' );

  return
end


function mObject3 = timeAlignedDirectSTRAIGHTmorphing(mObject1,mObject2,mRate,mixMethod);
%   Morphing based on time-aligned mixing of STRAIGHT parameters
%   mObject3 = timeAlignedDirectSTRAIGHTmorphing(mObject1,mObject2,mRate,mixMethod);

%   Designed and coded by Hideki Kawahara
%   28/Feb./2005
%   Copyright(c) 2005, Hideki Kawahara

mObject3 = checkForSimilarity(mObject1,mObject2);
if length(mObject3) ==0;return;end;
dtFrame = mObject1.frameUpdateInterval;
endLocation1 = (length(mObject1.F0)-1)*dtFrame; % in ms
endLocation2 = (length(mObject2.F0)-1)*dtFrame; % in ms
timeAnchor1 = [0;mObject1.anchorTimeLocation;endLocation1];
timeAnchor2 = [0;mObject2.anchorTimeLocation;endLocation2];
locationOn1 = (0:length(mObject1.F0)-1)*dtFrame;
locationOn2 = (0:length(mObject2.F0)-1)*dtFrame;
mapFrom1to2 = interp1(timeAnchor1,timeAnchor2,locationOn1);
[nr1,nc1] = size(mObject1.spectrogram);
[nr2,nc2] = size(mObject2.spectrogram);

%---- mixing on mObject1's time axis
nAxis1 = length(locationOn1);
nAxis2 = length(locationOn2);
morphedF0 = zeros(nAxis1,1);
morphedAp = zeros(nr1,nAxis1);
morphedSgram = zeros(nr1,nAxis1);
weightSumF0 = zeros(nAxis1,1);
for ii=1:nAxis1
    mappedIndexOn2 = mapFrom1to2(ii)/dtFrame+1;
    iFloor = floor(mappedIndexOn2);
    iFraction = mappedIndexOn2-iFloor;
    dAp = iFraction*(mObject2.aperiodicityIndex(:,min(iFloor+1,nAxis2))-mObject2.aperiodicityIndex(:,iFloor));
    morphedAp(:,ii) = (1-mRate)*mObject1.aperiodicityIndex(:,ii)+mRate*(mObject2.aperiodicityIndex(:,iFloor)+dAp);
    switch mixMethod
        case 'linear'
            dSgram = iFraction*(mObject2.spectrogram(:,min(iFloor+1,nAxis2))-mObject2.spectrogram(:,iFloor));
            morphedSgram(:,ii) = (1-mRate)*mObject1.spectrogram(:,ii)+mRate*(mObject2.spectrogram(:,iFloor)+dSgram);
        case 'log'
            dSgram = iFraction*(log(mObject2.spectrogram(:,min(iFloor+1,nAxis2)))-log(mObject2.spectrogram(:,iFloor)));
            tmp = (1-mRate)*log(mObject1.spectrogram(:,ii))+mRate*(log(mObject2.spectrogram(:,iFloor))+dSgram);
            morphedSgram(:,ii) = exp(tmp);
    end;
    if mObject1.F0(ii)>0
        morphedF0(ii) = (1-mRate)*log(mObject1.F0(ii));
        weightSumF0(ii) = (1-mRate);
    end;
    if (mObject2.F0(iFloor)>0) & (mObject2.F0(min(iFloor+1,nAxis2))>0)
        dF0 = iFraction*(log(mObject2.F0(min(iFloor+1,nAxis2)))-log(mObject2.F0(iFloor)));
        morphedF0(ii) = mRate*(log(mObject2.F0(iFloor))+dF0)+morphedF0(ii);
        weightSumF0(ii) = weightSumF0(ii)+mRate;
    end;
end;
morphedF0(weightSumF0>0) = exp(morphedF0(weightSumF0>0)./weightSumF0(weightSumF0>0));

%----- mapping back onto morphed time axis
timeAnchorMorph = (1-mRate)*timeAnchor1 + mRate*timeAnchor2;
locationOnMorph = (0:(timeAnchorMorph(end)/dtFrame))*dtFrame;
mapFormMorphTo1 = interp1(timeAnchorMorph,timeAnchor1,locationOnMorph);
nAxisMorph = length(locationOnMorph);
morphedApOnMorph = zeros(nr1,nAxisMorph);
morphedSgramOnMorph = zeros(nr1,nAxisMorph);
morphedF0onMorph = zeros(nAxisMorph,1);
for ii=1:nAxisMorph
    mappedIndexOn1 = mapFormMorphTo1(ii)/dtFrame+1;
    iFloor = floor(mappedIndexOn1);
    iFraction = mappedIndexOn1-iFloor;
    morphedApOnMorph(:,ii) = morphedAp(:,iFloor) ...
        +iFraction*(morphedAp(:,min(iFloor+1,nAxis1))-morphedAp(:,iFloor));
    morphedSgramOnMorph(:,ii) = morphedSgram(:,iFloor) ...
        +iFraction*(morphedSgram(:,min(iFloor+1,nAxis1))-morphedSgram(:,iFloor));
    if (morphedF0(iFloor)>0) & (morphedF0(min(iFloor+1,nAxis1))>0)
        dF0 = iFraction*(morphedF0(min(iFloor+1,nAxis1))-morphedF0(iFloor));
        morphedF0onMorph(ii) = morphedF0(iFloor)+dF0;
    end;
end;
mObject3.F0 = morphedF0onMorph;
mObject3.aperiodicityIndex = morphedApOnMorph;
mObject3.spectrogram = morphedSgramOnMorph;
mObject3.anchorTimeLocation = timeAnchorMorph(2:end-1);
mObject3.anchorFrequency = (1-mRate)*mObject1.anchorFrequency+mRate*mObject2.anchorFrequency;
%mObject3 = morphedAp; % This line is a dummy.

%%% ------ Internal function to check for object's similarity
function mObject3 = checkForSimilarity(mObject1,mObject2)
mObject3 = [];
if mObject1.samplingFrequency ~= mObject2.samplingFrequency;mObject3 = [];return;end;
if mObject1.frameUpdateInterval ~= mObject2.frameUpdateInterval;mObject3 = [];return;end;
if length(mObject1.anchorTimeLocation) ~= length(mObject2.anchorTimeLocation);mObject3 = [];return;end;
nAnchor = length(mObject1.anchorTimeLocation);
for ii=1:nAnchor % check for similarity of anchor structure
    frequencyAnchor1 = mObject1.anchorFrequency;
    frequencyAnchor2 = mObject2.anchorFrequency;
    if (sum(frequencyAnchor1>0) ~= sum(frequencyAnchor2>0)) | ...
            (sum(frequencyAnchor1<0) ~= sum(frequencyAnchor2<0))
        return;
    end;
end;
mObject3 = createMobject;


function Cu = computeCu(nu)
    Cu_tmp1 = cell(nu,nu);
    Cu_tmp2 = cell(nu,nu);

    for i=1:nu
       for j=1:nu
          if i==j
              Cu_tmp1{i,j} = eye(2);
              Cu_tmp2{i,j} = -eye(2);
          else
              Cu_tmp1{i,j} = zeros(2,2);
              Cu_tmp2{i,j} = zeros(2,2);
          end
       end
    end

    Cu = [cell2mat(Cu_tmp1);cell2mat(Cu_tmp2)];
end


function y = UpDyadLo(x,qmf)
% UpDyadLo -- Lo-Pass Upsampling operator; periodized
%  Usage
%    u = UpDyadLo(d,f)
%  Inputs
%    d    1-d signal at coarser scale
%    f    filter
%  Outputs
%    u    1-d signal at finer scale
%
%  See Also
%    DownDyadLo, DownDyadHi, UpDyadHi, IWT_PO, iconv
%
	y =  iconv(qmf, UpSampleN(x) );

%  Revision History
%  10/1/05       AM      UpSample is changed to UpSampleN

%
% Copyright (c) 1993. Iain M. Johnstone
% Last modified on October 2005.
%

%
%  Part of Wavelab Version 850
%  Built Tue Jan  3 13:20:40 EST 2006
%  This is Copyrighted Material
%  For Copying permissions see COPYING.m
%  Comments? e-mail wavelab@stat.stanford.edu


function n = dim(A)
%DIM          Dimension of a square matrix
%
%    n = dim(A)
%

% written  10/16/98     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  if A.complex
    [m n] = size(A.mid);
  else
    [m n] = size(A.inf);
  end

  if m ~= n
    error('function dim called with non-square matrix')
  end;


function [C,Atp,Btp]=etprod(Cidx,A,Aidx,B,Bidx)
% tprod wrapper to make calls more similar to Einstein Summation Convention
%
% [C,Atp,Btp]=etprod(Cidx,A,Aidx,B,Bidx);
% Wrapper function for tprod to map between Einstein summation
% convetion (ESC) and tprod's numeric calling convention e.g.
% 1) Matrix Matrix product:
%   ESC: C_ij = A_ik B_kj <=> C = etprod('ij',A,'ik',B,'kj');
% 2) Vector outer product
%   ESC: C_ij = A_i B_j   <=> C = etprod('ij',A,'i',B,'j');   % A,B col vec
%                             C = etprod('ij',A,' i',B,' j'); % A,B row vec
% N.B. use spaces ' ' to indicate empty/ignored *singlenton* dimensions
% 3) Matrix vector product
%   ESC: C_i  = A_ik B_k  <=> C = etprod('i',A,'ik',B,'k');
% 4) Spatial Filtering
%   ESC: FX_fte = A_cte B_cf <=> C = etprod('fte',A,'cte',B,'cf')
% OR:
%   C = etprod({'feat','time','epoch'},A,{'ch','time','epoch'},B,{'ch','feat'})
%
% Inputs:
%  Cidx -- the list of dimension labels for the output
%  A    -- [n-d] array of the A values
%  Aidx -- [ndims(A) x 1] (array, string, or cell array of strings)
%          list of dimension labels for A array
%  B    -- [m-d] array of the B values
%  Bidx -- [ndims(B) x 1] (array, string or cell array of strings)
%          list of dimension labels for B array
% Outputs:
%  C    -- [p-d] array of output values.  Dimension labels are as in Cidx
%  Atp  -- [ndims(A) x 1] A's dimspec as used in the core tprod call
%  Btp  -- [ndims(B) x 1] B's dimspec as used in the core tprod call
%
% See Also: tprod, tprod_testcases
%
% Copyright 2006-     by Jason D.R. Farquhar (jdrf@zepler.org)
% Permission is granted for anyone to copy, use, or modify this
% software and accompanying documents for any uncommercial
% purposes, provided this copyright notice is retained, and note is
% made of any changes that have been made. This software and
% documents are distributed without any warranty, express or
% implied
if ( iscell(Aidx)~=iscell(Bidx) || iscell(Cidx)~=iscell(Aidx) )
 error('Aidx,Bidx and Cidx cannot be of different types, all cells or arrays');
end

Atp = zeros(size(Aidx));
Btp = zeros(size(Bidx));
% Map inner product dimensions, to unique *negative* index
for i=1:numel(Aidx)
   if ( iscell(Aidx) ) Bmatch = strcmp(Aidx{i}, Bidx);
   else                Bmatch =       (Aidx(i)==Bidx);
   end
   if ( any(Bmatch) ) Btp(Bmatch)=-i; Atp(i)=-i; end;
end
% Spaces/empty values in the input become 0's, i.e. ignored dimensions
if ( iscell(Aidx) )
   Btp(strcmp(' ',Bidx))=0;Btp(strcmp('',Bidx))=0;
   Atp(strcmp(' ',Aidx))=0;Atp(strcmp('',Aidx))=0;
else
   Btp(' '==Bidx)=0;
   Atp(' '==Aidx)=0;
end

% Map to output position numbers, to correct *positive* index
for i=1:numel(Cidx);
   if ( iscell(Aidx) )
      Atp(strcmp(Cidx{i}, Aidx))=i;
      Btp(strcmp(Cidx{i}, Bidx))=i;
   else
      Atp(Cidx(i)==Aidx)=i;
      Btp(Cidx(i)==Bidx)=i;
   end
end

% now do the tprod call.
global LOG; if ( isempty(LOG) ) LOG=0; end; % N.B. set LOG to valid fd to log
if ( LOG>0 )
   fprintf(LOG,'tprod(%s,[%s], %s,[%s])\n',mxPrint(A),sprintf('%d ',Atp),mxPrint(B),sprintf('%d ',Btp));
end
C=tprod(A,Atp,B,Btp,'n');
return;

function [str]=mxPrint(mx)
sz=size(mx);
if ( isa(mx,'double') ) str='d'; else  str='s'; end;
if ( isreal(mx)) str=[str 'r']; else str=[str 'c']; end;
str=[str ' [' sprintf('%dx',sz(1:end-1)) sprintf('%d',sz(end)) '] '];
return;

%----------------------------------------------------------------------------
function testCase();
A=randn(10,10); B=randn(10,10);
C2 = tprod(A,[1 -2],B,[-2 2]);
C  = etprod('ij',A,'ik',B,'kj'); mad(C2,C)
C  = etprod({'i' 'j'},A,{'i' 'k'},B,{'k' 'j'});
A=randn(100,100);B=randn(100,100,4);
C3 = tprod(A,[-1 -2],B,[-1 -2 3]);
C3 = tprod(B,[-1 -2 1],A,[-1 -2]);
C3 = tprod(A,[-1 -2],B,[-1 -2 1]);
C  = etprod('3',A,'12',B,'123');
C  = etprod([3],A,[1 2],B,[1 2 3]);
C  = etprod({'3'},A,{'1' '2'},B,{'1' '2' '3'})