function x = intercept_model(nvols_per_run, varargin)
% Build design matrix X for intercepts
% given vector of session lengths [s1 s2 s3] in images
%
% :Usage:
% ::
%
%     x = intercept_model(nvols_per_run, [indx of dummy scans in each session])
%
% :Examples:
% ::
%
%    nvols_per_run = [166 166 144 137];
%    x = intercept_model(nvols_per_run);
%
%    x = intercept_model(repmat(166, 1, 5));
%
%    Xi = intercept_model(EXPT.FIR.nruns, 1:2);
%
% ..
%    tor modified april 07: separate column for each run
% ..

    if ~isvector(nvols_per_run), error('nvols_per_run must be a vector of the number of volumes for each run'); end
    nvols_per_run = nvols_per_run(:)'; %ensure row vector

    npoints = sum(nvols_per_run); % number of time points total
    nruns = length(nvols_per_run); % number of runs

    x = zeros(npoints, nruns);

    st = cumsum([1 nvols_per_run]);
    en = st(2:end) - 1; % ending values
    st = st(1:end-1); % starting values

    for i = 1:nruns
        x(st(i):en(i), i) = 1;
    end

    if length(varargin) > 0 && ~isempty(varargin{1})
        % Model dummy regressors
        x = [x model_dummy(npoints, st', varargin{1})];
    end
end

function x = model_dummy(npoints, st, wh)
    % dummy regressors for first scan or two (at least, that's the intended
    % use)
    % separate column for each run!

    k = length(wh) .* length(st);
    x = zeros(npoints, k);

    dosamecol = 0;

    if dosamecol
        for i = 1:k
            ind = st(r) + wh(i) - 1; % which to filter
            ind(ind < 1) = []; % if negative numbers (end of runs), this makes it ok
            x(ind, i) = 1;
        end

    else

        colindx = 1;

        for r = 1:length(st) % for each run
            for i = 1:length(wh)

                ind = st(r) + wh(i) - 1; % which to filter
                ind(ind < 1) = []; % if negative numbers (end of runs), this makes it ok

                x(ind, colindx) = 1;
                colindx = colindx + 1;
            end
        end

    end

end


function pass = test_domainChck()
% Test chebfun3/domainCheck

% Default domain:
ff = @(x,y,z) cos(x+y+z);
gg = @(x,y,z) sin(x.*y.*z);
f = chebfun3(ff);
g = chebfun3(gg);
pass(1) = domainCheck(f, g);

% A different domain:
dom = [-1 2 -2 1 -3 0];
ff = @(x,y,z) cos(x+y+z);
gg = @(x,y,z) sin(x.*y.*z);
f = chebfun3(ff, dom);
g = chebfun3(gg, dom);
pass(2) = domainCheck(f, g);

end


function test_interp_2d_test03 ( )

%*****************************************************************************80
%
%% TEST_INTERP_2D_TEST03 plots each grid.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 July 2012
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST_INTERP_2D_TEST03\n' );
  fprintf ( 1, '  Plot each grid.\n' );

  g_num = g00_num ( );
  filename = 'grid_00.png';

  for gi = 1 : g_num

    gt = g00_title ( gi );
    gn = g00_size ( gi );

    [ gx, gy ] = g00_xy ( gi, gn );

    plot ( gx, gy, 'b.', 'Markersize', 25 );
    title ( gt );
    grid on
    xlabel ( '<--- X --->' );
    ylabel ( '<--- Y --->' );
    axis ( 'equal' );

    filename = filename_inc ( filename );
    print ( '-dpng', filename );
    fprintf ( 1, '  Created file "%s".\n', filename );

  end

  return
end


function Z = sparsemultipart(Z1,Z2,info)

% Find the elements in Z1 that are in the convex hull of Z2, where Z2 is bipartite

% This file is part of SOSTOOLS - Sum of Squares Toolbox ver 3.00.
%
% Copyright (C)2002, 2004, 2013  A. Papachristodoulou (1), J. Anderson (1),
%                                G. Valmorbida (1), S. Prajna (2),
%                                P. Seiler (3), P. A. Parrilo (4)
% (1) Department of Engineering Science, University of Oxford, Oxford, U.K.
% (2) Control and Dynamical Systems - California Institute of Technology,
%     Pasadena, CA 91125, USA.
% (3) Aerospace and Engineering Mechanics Department, University of
%     Minnesota, Minneapolis, MN 55455-0153, USA.
% (4) Laboratory for Information and Decision Systems, M.I.T.,
%     Massachusetts, MA 02139-4307
%
% Send bug reports and feedback to: sostools@cds.caltech.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.

% AP Feb 01 0

[Y,I] = find(sum(Z2,1)==0);
sizeinf = length(info);

if sizeinf == 1
   error('Error in sparsemultipart option - at least two sets are required');
end

for i = 1:sizeinf
  Z3{i} = inconvhull(Z1(:,info{i}),Z2(:,info{i}));
end

for i = 1:sizeinf-1%GVcomment for the variables introducing homogeneous monomials
  Z3{i+1} = [repmat(Z3{i},size(Z3{i+1},1),1),kron(Z3{i+1},ones(size(Z3{i},1),1))];
end
Z3 = Z3{sizeinf};
Z = zeros(size(Z3,1),size(Z2,2));
lgth = 0;
for i = 1:sizeinf
   Z(:,info{i})= Z3(:,(1+lgth):(lgth+length(info{i})));
   lgth = length(info{i})+lgth;
end
Z(:,I) = zeros(size(Z,1),size(I,2));


function x = modhs52(p)
  n=4;

  x(1)=4.0*p(1)-p(2);
  x(2)=p(2)+p(3)-2.0;
  x(3)=p(4)-1.0;
  x(4)=p(5)-1.0;


function drawbtf (A, p, q, r)
%DRAWBTF plot the BTF form of a matrix
%
% A(p,q) is in BTF form, r the block boundaries
%
% Example:
%   [p,q,r] = dmperm (A)
%   drawbtf (A, p, q, r)
%
% See also btf, maxtrans, strongcomp, dmperm.

% Copyright 2004-2007, Tim Davis, University of Florida

nblocks = length (r) - 1 ;

hold off
spy (A (p,abs(q)))
hold on

for k = 1:nblocks
    k1 = r (k) ;
    k2 = r (k+1) ;
    nk = k2 - k1 ;
    if (nk > 1)
        plot ([k1 k2 k2 k1 k1]-.5, [k1 k1 k2 k2 k1]-.5, 'r') ;
    end
end


%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2 of the License, or
%  (at your option) any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; if not, write to the Free Software
%  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
%function sigmergt
%SIGMERGT Unit test for the function SIGMERGE.

%	O. Lemoine - March 1996.

N=256;

s1=noisecg(N);
s2=amgauss(N);
R=10;
sig=sigmerge(s1,s2,R);
E1=norm(s1)^2;
E2=norm(s2)^2;
h=sqrt(E1/(E2*10^(R/10)));
err=sig-s1-h*s2;
if any(abs(err)>sqrt(eps)),
 error('sigmerge test 1 failed');
end

s1=noisecu(N);
s2=fmlin(N);
R=-2.4;
sig=sigmerge(s1,s2,R);
E1=norm(s1)^2;
E2=norm(s2)^2;
h=sqrt(E1/(E2*10^(R/10)));
err=sig-s1-h*s2;
if any(abs(err)>sqrt(eps)),
 error('sigmerge test 2 failed');
end

N=245;

s1=noisecg(N);
s2=amgauss(N);
R=10;
sig=sigmerge(s1,s2,R);
E1=norm(s1)^2;
E2=norm(s2)^2;
h=sqrt(E1/(E2*10^(R/10)));
err=sig-s1-h*s2;
if any(abs(err)>sqrt(eps)),
 error('sigmerge test 3 failed');
end

s1=noisecu(N);
s2=fmlin(N);
R=-2.4;
sig=sigmerge(s1,s2,R);
E1=norm(s1)^2;
E2=norm(s2)^2;
h=sqrt(E1/(E2*10^(R/10)));
err=sig-s1-h*s2;
if any(abs(err)>sqrt(eps)),
 error('sigmerge test 4 failed');
end


function [Eft, Varft, lpyt, Eyt, Varyt] = gpia_loopred(gp_array, x, y, varargin)
%GPIA_LOOPRED  Leave-one-out predictions with Gaussian Process IA approximation
%
%  Description
%    [EFT, VARFT, LPYT, EYT, VARYT] = GPIA_LOOPRED(RECGP, X, Y)
%    takes a cell array of GP structures together with matrix X of
%    input vectors, matrix X of training inputs and vector Y of
%    training targets, and evaluates the leave-one-out predictive
%    distribution at inputs X and returns means EFT and variances
%    VARFT of latent variables, the logarithm of the predictive
%    densities PYT, and the predictive means EYT and variances
%    VARYT of observations at input locations X.
%
%    OPTIONS is optional parameter-value pair
%      z      - optional observed quantity in triplet (x_i,y_i,z_i)
%               Some likelihoods may use this. For example, in case of
%               Poisson likelihood we have z_i=E_i, that is, expected value
%               for ith case.
%      is     - defines if importance sampling weighting is used 'on'
%               (default). If set to 'off', integration points and
%               weights for the full posterior are used.
%
%    Given Gaussian likelihood or non-Gaussian likelihood and
%    latent method Laplace or EP, LOO-posterior given
%    hyperparameters is computed analytically or with analytic
%    approximation and LOO-posterior of the hyperparameters is
%    approximated using importance sampling reweighted integration
%    points from gp_ia. Optionally integration weights for full data
%    posterior of hyperparameters can be used (by setting option
%    'is' to 'off').
%
%  References:
%    Aki Vehtari and Jouko Lampinen (2002). Bayesian model
%    assessment and comparison using cross-validation predictive
%    densities. Neural Computation, 14(10):2439-2468.
%
%  See also
%   GP_LOOPRED, GP_IA, GP_PRED
%
% Copyright (c) 2009 Ville Pietil�inen
% Copyright (c) 2009-2010 Jarno Vanhatalo
% Copyright (c) 2010,2012 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.

  ip=inputParser;
  ip.FunctionName = 'GPIA_LOOPRED';
  ip.addRequired('gp_array',@iscell);
  ip.addRequired('x', @(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
  ip.addRequired('y', @(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('z', [], @(x) isreal(x) && all(isfinite(x(:))))
  ip.addParamValue('is', 'on', @(x) ismember(x,{'on' 'off'}))
  ip.parse(gp_array, x, y, varargin{:});
  z=ip.Results.z;
  is=ip.Results.is;

  nGP = numel(gp_array);
  n=size(x,1);

  P_TH = zeros(1,nGP);
  Efts = zeros(n,nGP);
  Varfts = zeros(n,nGP);
  lpyts = zeros(n,nGP);
  if nargout > 3
    Eyts = zeros(n,nGP);
    Varyts = zeros(n,nGP);
  end

  for i1=1:nGP
    Gp=gp_array{i1};
    P_TH(1,i1) = Gp.ia_weight;
    % compute leave-one-out predictions for each hyperparameter sample
    % if latent method is MCMC, then these samples are for latent values, too
    if nargout <= 3
      [Efts(:,i1), Varfts(:,i1), lpyts(:,i1)] = gp_loopred(Gp, x, y, 'z', z);
    else
      [Efts(:,i1), Varfts(:,i1), lpyts(:,i1), Eyts_temp, Varyts_temp] = gp_loopred(Gp, x, y, 'z', z);
      if ~isempty(Eyts_temp)
        Eyts(:,i1) = Eyts_temp;
      end
      if ~isempty(Varyts_temp)
        Varyts(:,i1) = Varyts_temp;
      end
    end
  end

  if isequal(is,'off')
    P_TH=repmat(P_TH,n,1);
  else
    % log importance sampling weights
    lw=-lpyts;
    % normalize weights
    for i2=1:n
      % this works even when lw have large magnitudes
      lw(i2,:)=lw(i2,:)-sumlogs(lw(i2,:));
    end
    % importance sampling weights
    w=exp(lw);
    % reweight ia weights
    P_TH=bsxfun(@times,P_TH,w);
    P_TH=bsxfun(@rdivide,P_TH,sum(P_TH,2));
    % check the effective sample size
    m_eff=1./sum(P_TH.^2,2);
    if min(m_eff)<nGP/5
      warning(sprintf('For %d folds the effective sample size in IS is less than m/5',sum(m_eff<(nGP/5))))
    end
    %fprintf('nGP=%d, min(neff)=%.0f, min(neff)/nGP=%.2f\n',nGP, min(1./sum(P_TH.^2,2)), min(1./sum(P_TH.^2,2))./nGP)
    % PSIS
    if nGP>=200
        % (new) default sample size for is_normal and is_t is 200
        % CCD with nParam>=12 has at least 281 points
        [lw,pk] = psislw(log(P_TH'),10);
        P_TH=exp(lw');
        % check whether the variance and mean of the raw importance ratios is finite
        % PSIS weights have always finite variance and mean, but if raw importance
        % ratios have infinite variance the convergence to true value is
        % slower and if raw importance ratios have non-existing mean the the
        % estimate can't converge to true value
        vkn1=sum(pk>=0.5&pk<0.7);
        vkn2=sum(pk>=0.7&pk<1);
        vkn3=sum(pk>=1);
        n=numel(pk);
        if vkn1>0
            warning('%d (%.0f%%) PSIS Pareto k estimates between 0.5 and .7',vkn1,vkn1/n*100)
        end
        if vkn2>0
            warning('%d (%.0f%%) PSIS Pareto k estimates between 0.7 and 1',vkn2,vkn2/n*100)
        end
        if vkn3>0
            warning('%d (%.0f%%) PSIS Pareto k estimates greater than 1',vkn3,vkn3/n*100)
        end
    end
  end

  % compute combined predictions
  Eft = sum(Efts.*P_TH, 2);
  Varft = sum(Varfts.*P_TH,2) + sum(bsxfun(@minus,Efts,Eft).^2.*P_TH,2);
  if nargout > 2
    lpyt = log(sum(exp(lpyts+log(P_TH)),2));
    if nargout > 3
      Eyt = sum(Eyts.*P_TH,2);
      Varyt = sum(Varyts.*P_TH,2) + sum(bsxfun(@minus,Eyts,Eyt).^2.*P_TH, 2);
    end
  end


function [dimLabels, resolutions, nSamples, units, firstSamplingPoint] = ...
    read_nifti(~, fileName)
% Reads nifti files and extracts properties for dimInfo
%
%   Y = MrDimInfo()
%   [dimLabels, resolutions, nSamples, units] = Y.read_nifti(fileName)
%   used in Y.load(fileName)
%
% This is a method of class MrDimInfo.
%
% IN
%
% OUT
%
% EXAMPLE
%   read_nifti
%
%   See also MrDimInfo

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

%% read header info
V = spm_vol(fileName);

%% nSamples
% for nifti files, nSamples should always has 3 entries, even if just a
% single line or slice is in the data (the nifti header will have
% information on the remaining singleton dimensions)
nSamples = [1, 1, 1];

% fill with info from file
tempSamples = V(1).private.dat.dim;
nSamples(1:numel(tempSamples)) = tempSamples;
tempDimInfo = MrDimInfo('nSamples', nSamples);
nDims = numel(nSamples);

%% dimLabels
dimLabels = tempDimInfo.dimLabels;

%% units
units = tempDimInfo.units;

%% resolutions
N = floor(abs(log10(eps('double'))));
P = round(tapas_uniqc_spm_imatrix(V(1).mat),N);
resolution_mm  = P(7:9);
% some nifti formats supply timing information (for files with more than 3
% dimension)
if isfield(V(1), 'private') && nDims > 3
    if isstruct(V(1).private.timing)
        TR_s = V(1).private.timing.tspace;
        tStart = 0;
    else
        TR_s = 1;
        units{4} = 'samples';
        tStart = 1;
    end
end
% need nifti to reference first sampling point as offcenter
resolutions = ones(1, nDims);
resolutions(1, 1:3) = resolution_mm;
if nDims > 3
    resolutions(1,4) = TR_s;
end

%% firstSamplingPoint
% voxel position by voxel center
% first sampling points for x,y,z are -FOV/2+res/2 such that [0 0 0] is in
% the centre of the matrix
% time starts at 0 seconds or 1 (1st) sample
FOV = nSamples(1:3) .* resolutions(1:3);
firstSamplingPoint = zeros(1, nDims);
firstSamplingPoint(1:3) = -FOV/2 + resolutions(1:3)/2;
if nDims > 3
    firstSamplingPoint(4) = tStart;
end
end


function [A, B] = kafbox_covProd(covfunc, logtheta, x, z);

% covProd - compose a covariance function as the product of other covariance
% functions. This function doesn't actually compute very much on its own, it
% merely does some bookkeeping, and calls other covariance functions to do the
% actual work.
%
% For more help on design of covariance functions, try "help covFunctions".
%
% (C) Copyright 2006 by Carl Edward Rasmussen, 2006-04-06.

for i = 1:length(covfunc)                   % iterate over covariance functions
  f = covfunc(i);
  if iscell(f{:}), f = f{:}; end          % dereference cell array if necessary
  j(i) = cellstr(feval(f{:}));
end

if nargin == 1,                                   % report number of parameters
  A = char(j(1)); for i=2:length(covfunc), A = [A, '+', char(j(i))]; end
  return
end

[n, D] = size(x);

v = [];              % v vector indicates to which covariance parameters belong
for i = 1:length(covfunc), v = [v repmat(i, 1, eval(char(j(i))))]; end

switch nargin
case 3                                              % compute covariance matrix
  A = ones(n, n);                       % allocate space for covariance matrix
  for i = 1:length(covfunc)                   % iteration over factor functions
    f = covfunc(i);
    if iscell(f{:}), f = f{:}; end        % dereference cell array if necessary
    A = A .* feval(f{:}, logtheta(v==i), x);             % multiply covariances
  end

case 4                      % compute derivative matrix or test set covariances
  if nargout == 2                                % compute test set cavariances
    A = ones(size(z,1),1); B = ones(size(x,1),size(z,1));      % allocate space
    for i = 1:length(covfunc)
      f = covfunc(i);
      if iscell(f{:}), f = f{:}; end      % dereference cell array if necessary
      [AA BB] = feval(f{:}, logtheta(v==i), x, z);   % compute test covariances
      A = A .* AA; B = B .* BB;                                % and accumulate
    end
  else                                            % compute derivative matrices
    A = ones(n, n);
    ii = v(z);                                      % which covariance function
    j = sum(v(1:z)==ii);                   % which parameter in that covariance
    for i = 1:length(covfunc)
      f = covfunc(i);
      if iscell(f{:}), f = f{:}; end      % dereference cell array if necessary
      if i == ii
        A = A .* feval(f{:}, logtheta(v==i), x, j);       % multiply derivative
      else
        A = A .* feval(f{:}, logtheta(v==i), x);          % multiply covariance
      end
    end
  end

end


% Author: Guanghan Ning, Dec 2016
clear all;
addpath('../utils_eval_mpii/');
addpath('../eval_MPII/');

% Load annotations: validation
load('../eval_MPII/mpii_Tompson_validation', 'annolist');
load('../eval_MPII/mpii_Tompson_validation', 'RELEASE_img_index');
load('../eval_MPII/mpii_Tompson_validation', 'RELEASE_person_index');
annolist_validate = annolist;
num_validate_imgs = size(annolist_validate, 2);

% Load annotations: train + validation
load('../eval_MPII/mpii_human_pose_v1_u12_1','RELEASE');
annolist_all = RELEASE.annolist;

% Load scales extracted from image height
scale_in_cpp = load('../scale_in_cpp_MPII_validate_bigger_1.4.mat');
scale_in_cpp = scale_in_cpp.output_scale;

%%
img_folder_path = '/home/ngh/dev/POSE/POSE-dev/dataset/MPI/images/';%'../../../dataset/MPI/images/';

for scale_id = 1
    for iter_id = 1176058
        mat_folder_path = strcat('../dataset_mpii/results_all_validate_cropped_bigger_1.4/', num2str(iter_id), '_', num2str(scale_id-1), '/quantitative/');

        for img_id = 1:num_validate_imgs

            img_index = RELEASE_img_index(img_id);
            img_name = annolist_all(img_index).image.name;
            img_path = strcat(img_folder_path, '/', img_name);
            img_org_full = imread(img_path);

            % Display predicted results on the original image
            figure;
            imshow(img_org_full);
            hold on;

            % Get rect id. Note the difference between rect_ct and rect_id
            rect_id = RELEASE_person_index(img_id);

            % Find scale and mid-points in order to convert prediction
            x_mid = annolist_validate(img_id).annorect.objpos.x;
            y_mid = annolist_validate(img_id).annorect.objpos.y;
            mid_point = [x_mid, y_mid];  %scale = annolist_test(img_id).annorect.scale;

            % Load our algorithm predictions for this rect
            [folder_path, base_name, extension] = fileparts(img_name);
            [x_preds_raw, y_preds_raw] = load_pred_result(mat_folder_path, base_name, rect_id);

            for joint_id = 1:14
                % Convert predictions for un-cropped image scale for evaluation
                %id = convert_joint_order(joint_id);
                id = convert_joint_order_to_gt_order(joint_id);

                pred_point_raw = [x_preds_raw(joint_id), y_preds_raw(joint_id)];
                [x_pred, y_pred]= convert_trans_and_scale_validation(pred_point_raw, scale_in_cpp(img_id), mid_point);

                plot(x_pred, y_pred,'o');
            end
            hold off;
            pause;
        end
    end
end


function [y]=rake_fft(x, tol)
% Discrete Fourier Transform in the QTT-Tucker format
%   function [y]=rake_fft(x, tol)
%   Computes the multidimensional DFT of the vector x in the QTT-Tucker format with
%   the approximation tolerance tol.
%   Returns the quantized dimensions in the correct order.
%
%   !!WARNING!! employs a (probably) costly rank reverse procedure.

D = size(x.tuck);
tuck = x.tuck;
crx = core2cell(x.core);
for i=1:D
    [tuck{i}, rv]=qr(tuck{i}, 'lr');
    r1 = size(crx{i}, 1); r2 = size(crx{i}, 3); rt = size(crx{i},2);
    crx{i} = permute(crx{i}, [2, 1, 3]);
    crx{i} = reshape(crx{i}, rt, r1*r2);
    crx{i} = rv*crx{i};
    rt = size(rv,1);
    crx{i} = reshape(crx{i}, rt, r1, r2);
    crx{i} = permute(crx{i}, [2, 1, 3]);
end;
% [crx,rv]=qr(crx, 'rl');
% crx = rv.'*crx;
for i=D:-1:2
    r1 = size(crx{i}, 1); rt = size(crx{i}, 2); r2 = size(crx{i}, 3);
    crx{i} = reshape(crx{i}, r1, rt*r2);
    [crx{i}, rv]=qr(crx{i}.', 0);
    r0 = size(crx{i-1}, 1); rt0 = size(crx{i-1}, 2);
    crx{i-1} = reshape(crx{i-1}, r0*rt0, r1);
    crx{i-1}=crx{i-1}*rv.';
    r1 = size(rv,1);
    crx{i-1} = reshape(crx{i-1}, r0, rt0, r1);
    crx{i} = reshape(crx{i}.', r1, rt, r2);
end;
for i=1:D
    r1 = size(crx{i}, 1); r2 = size(crx{i}, 3); rt = size(crx{i},2);
    crx{i} = permute(crx{i}, [1, 3, 2]);
    crx{i} = reshape(crx{i}, r1*r2, rt);
    [crx{i}, rv]=qr(crx{i}, 0);
    tuck{i} = tuck{i}*rv.';
    tuck{i} = qtt_fft1(tuck{i}, tol);
    % rank is reversed
    r = tuck{i}.r;
    rq1 = r(1);
    for k=1:rq1
        ek = [zeros(1,k-1), 1, zeros(1,rq1-k)];
        yk = ek*tuck{i}; % first rank is 1
        if (k==1)
            ynew = yk;
        else
            ynew = [ynew, yk];
            ynew = round(ynew, tol);
        end;
    end;
    [tuck{i}, rv]=qr(ynew, 'lr');
%     % reversing 2
%     % nonorth block is the last, but we need to SVD from the first
%     tuck{i} = core2cell(tuck{i});
%     for j=numel(tuck{i}):-1:2
%         tuck{i}{j} = reshape(tuck{i}{j}, r(j), 2*r(j+1));
%         [tuck{i}{j}, rv]=qr(tuck{i}{j}.', 0);
%         tuck{i}{j-1} = reshape(tuck{i}{j-1}, r(j-1)*2, r(j));
%         tuck{i}{j-1} = tuck{i}{j-1}*rv.';
%         r(j) = size(rv, 1);
%         tuck{i}{j} = reshape(tuck{i}{j}.', r(j), 2, r(j+1));
%         tuck{i}{j-1} = reshape(tuck{i}{j-1}, r(j-1), 2, r(j));
%     end;
%     tuck{i}{1} = permute(tuck{i}{1}, [2, 1, 3]);
%     tuck{i}{1} = reshape(tuck{i}{1}, 2, rq1*r(2));
%     [u,s,v]=svd(tuck{i}{1}, 'econ');
%     s = diag(s);
%     rnew = my_chop2(s, norm(s)*tol/sqrt(numel(tuck{i})-1));
%     u=u(:,1:rnew);
%     v=v(:,1:rnew)*diag(s(1:rnew));
%     tuck{i}{1} = reshape(u, 1, 2, rnew);
%     r(1) = 1;
%     rv = reshape(v', rnew*rq1, r(2));
%     for j=2:numel(tuck{i})
%         tuck{i}{j} = reshape(tuck{i}{j}, r(j), 2*r(j+1));
%         tuck{i}{j} = rv*tuck{i}{j};
%         r(j) = rnew;
%         tuck{i}{j} = reshape(tuck{i}{j}, r(j), rq1, 2, r(j+1));
%         tuck{i}{j} = permute(tuck{i}{j}, [1, 3, 2, 4]);
%         tuck{i}{j} = reshape(tuck{i}{j}, r(j)*2, rq1*r(j+1));
%         [u,s,v]=svd(tuck{i}{j}, 'econ');
%         s = diag(s);
%         rnew = my_chop2(s, norm(s)*tol/sqrt(numel(tuck{i})-1));
%         u=u(:,1:rnew);
%         v=v(:,1:rnew)*diag(s(1:rnew));
%         tuck{i}{j} = reshape(u, r(j), 2, rnew);
%         rv = reshape(v', rnew*rq1, r(j+1));
%     end;
%     rv = reshape(rv, rnew, rq1);
%     tuck{i} = cell2core(tt_tensor, tuck{i});

    crx{i} = crx{i}*rv.';
    rt = size(rv,1);
    crx{i} = reshape(crx{i}, r1, r2, rt);
    crx{i} = permute(crx{i}, [1, 3, 2]);
    if (i<D)
        crx{i} = reshape(crx{i}, r1*rt, r2);
        [crx{i}, rv]=qr(crx{i}, 0);
        r3 = size(crx{i+1}, 3); rt2 = size(crx{i+1},2);
        crx{i+1} = reshape(crx{i+1}, r2, rt2*r3);
        crx{i+1} = rv*crx{i+1};
        r2 = size(rv,1);
        crx{i} = reshape(crx{i}, r1, rt, r2);
        crx{i+1} = reshape(crx{i+1}, r2, rt2, r3);
    end;
end;

y = x;
y.core = cell2core(tt_tensor, crx);
y.tuck = tuck;
end


function [ key ] = generate_checksum( X, k )
    sum_ = sum(X(:));
    key = [num2str(sum_) '_' num2str(k)];
end


function cMap = Make3dColormap(name, nColors)
%
% cMap = Make3dColormap(name[, nColors]);
%
% Create a standard set of colormaps for 3D rendering. Name determines
% which standard map to use. Only the first 3 letters are significant.
% Maps include 'red' (red-green), 'hot', 'cool', 'jet', and 'hsv'. All
% other inputs give back the 'prism' color table. The nColors input is
% defaults to 100.
%
% Ress, 6/03

if ~exist('nColors', 'var'), nColors = 100; end

switch name(1:3)
  case 'red'
    red = (0:(nColors-1)) / (nColors-1);
    green = red(nColors:-1:1);
    blue = red * 0;
    cMap = [red; green; blue]';
  case 'hot'
    cMap = hot(nColors);
  case 'coo'
    cMap = cool(nColors);
  case 'jet'
    cMap = jet(nColors);
  case 'hsv'
    cMap = hsv(nColors);
  otherwise
    cMap = prism(nColors);
end

cMap = round(cMap * 255)';


function plot_ideal_deconv5(rmsd,msdstd,msdb,biasmean,meanest,min95est,max95est,INFO,hrf,snr,TR,varargin)
% :Usage:
% ::
%
%     function plot_ideal_deconv5(rmsd,msdstd,msdb,biasmean,meanest,min95est,max95est,INFO,hrf,snr,TR,[truer])
%
% delta should be matrix of column vectors
%
% optional: truer, vector of "true" responses for each trial type
%
% ..
%    Tor Wager
% ..

msdblim = max(max(abs(msdb)));
bmlim = max(max(abs(biasmean))); bmlim = [-bmlim bmlim];

if isfield(INFO,'ideal_data') & isfield(INFO,'delta')
    figure('Color','w'), myleg{1} = 'Ideal response';
    h(1) = plot(INFO.ideal_data,'LineWidth',2);, hold on;
    mycols = {'r' 'g' 'y' 'c' 'm'}; mycols = repmat(mycols,1,10);
    delta = INFO.delta;
    for i = 1:size(delta,2)
        tmp1 = find(delta(:,i));
        hh = plot([tmp1 tmp1]',[-1*ones(size(tmp1)) zeros(size(tmp1))]',mycols{i},'LineWidth',2);
        h(i+1) = hh(1);
        myleg{i+1} = ['Trial type ' num2str(i) ' onsets'];
    end
    set(gca,'FontSize',18)
    legend(myleg)
    set(gcf,'Position',[19         606        1561         360])

    %tmp = conv(hrf,delta(:,1));figure;plot(tmp),title('ttype1')
    %tmp = conv(hrf,sum(delta,2));figure;plot(tmp),title('alltypes')
end
%figure;plot([find(tmp);find(tmp)],[zeros(size(find(tmp)),1); ones(size(find(tmp)),1)])

if length(varargin) > 0
    truer = varargin{1};
else
    truer = ones(1,size(INFO.delta,2));
end

figure; subplot 221; hold on; set(gcf,'Color','w');
if ~isempty(INFO.autocorrelation)
    figure('Color','w'); set(gca,'FontSize',18)
    plot((1:length(INFO.autocorrelation))./(length(INFO.autocorrelation) / length(hrf)),INFO.autocorrelation,'k-','LineWidth',2)
end
title('Noise autocorrelation function')

% old plot of RMSD
% -----------------
%plot(snr,rmsd,'ko-','MarkerFaceColor','k','MarkerSize',3,'LineWidth',2)
%plot(snr,msdstd(:,1),'k--')
%plot(snr,msdstd(:,2),'k--')
%legend({'Mean population value' '95% CI for one regression'})
%ylabel('Root Mean Squared Deviation')
%xlabel('Signal to Noise Ratio')

%title(['Est. - True response: ' INFO.condition_tested],'FontSize',14)

subplot 222; hold on;
x = (1:length(hrf)) * TR;
plot(x, hrf.*truer(INFO.ttype),'k','LineWidth',2)
myleg = {'HRF'};
legend(myleg)
title(['Est. vs. True response: ' INFO.condition_tested],'FontSize',14)
xlabel('Time from trial onset')

mycolors = {'r' 'b' 'g' 'c' 'm'};
for i = 1:min(5,length(snr))
    plot(x(1:size(meanest,2)),meanest(i,:),mycolors{i})
    myleg{end+1} = ['Estimated, snr = ' num2str(snr(i))];
end

if ~isempty(min95est) & ~isempty(max95est)
    plot(x(1:size(min95est,2)),min95est(1,:),'r--');
    plot(x(1:size(min95est,2)),max95est(1,:),'r--');
    myleg{end+1} = ['95% CI for ind. regressions, snr = ' num2str(snr(1))];
end
legend(myleg)

subplot 223; hold on;
imagesc(msdb,[0 msdblim]), colormap copper
xlabel('Time from trial onset')
ylabel('Signal to Noise Ratio')
%set(gca,'YDir','Reverse')
set(gca,'YTick',1:length(snr))
set(gca,'YTickLabel',snr)
set(gca,'XTick',(1:2:INFO.estlength))
set(gca,'XTickLabel',get(gca,'XTick') .* TR)
title('Mean abs. dev. by time from event onset','FontSize',14)
colorbar('horiz')

subplot 224; hold on;
imagesc(biasmean,bmlim), colormap jet
xlabel('Time from trial onset')
ylabel('Signal to Noise Ratio')
set(gca,'YTick',1:length(snr))
set(gca,'YTickLabel',snr)
set(gca,'XTick',(1:2:INFO.estlength))
set(gca,'XTickLabel',get(gca,'XTick') .* TR)
title('Bias in estimation by time from event onset','FontSize',14)
colorbar('horiz')

return


%This Matlab script can be used to reproduce Figure 6.7 in the monograph:
%
%Emil Bjornson, Jakob Hoydis and Luca Sanguinetti (2017),
%"Massive MIMO Networks: Spectral, Energy, and Hardware Efficiency",
%Foundations and Trends in Signal Processing: Vol. 11, No. 3-4,
%pp. 154-655. DOI: 10.1561/2000000093.
%
%For further information, visit: https://www.massivemimobook.com
%
%This is version 1.0 (Last edited: 2017-11-04)
%
%License: This code is licensed under the GPLv2 license. If you in any way
%use this code for research that results in publications, please cite our
%monograph as described above.

%Empty workspace and close figures
close all;
clear;

%Number of BSs
L = 16;

%Number of UEs per BS
K = 10;

%Number of BS antennas
M = 100;

%Define the range of pilot reuse factors
fRange = [1 2];

%Select the number of setups with random UE locations
nbrOfSetups = 20;

%Select the number of channel realizations per setup
nbrOfRealizations = 200;

%Select the range of hardware qualities. The values at the same position in
%the different vectors are considered simultaneously.
kappatUE = [0.99 0.99 0.99 0.99 0.99 0.95 0.97 0.98 0.99 0.995 1];
kapparUE = [0.95 0.97 0.98 0.995 1 0.99 0.99 0.99 0.99 0.99 0.99];
kappatBS = kapparUE;
kapparBS = kappatUE;

%% Propagation parameters

%Communication bandwidth
B = 20e6;

%Total uplink transmit power per UE (mW)
p = 100;

%Total downlink transmit power per UE (mW)
rho = 100;

%Noise figure at the BS (in dB)
noiseFigure = 7;

%Compute noise power
noiseVariancedBm = -174 + 10*log10(B) + noiseFigure;

%Select length of coherence block
tau_c = 200;

%Use the approximation of the Gaussian local scattering model
accuracy = 2;

%Angular standard deviation in the local scattering model (in degrees)
ASDdeg = 10;

%Prepare to save simulation results
sumSE_MR = zeros(length(kappatUE),length(fRange),nbrOfSetups);
sumSE_RZF = zeros(length(kappatUE),length(fRange),nbrOfSetups);
sumSE_MMMSE = zeros(length(kappatUE),length(fRange),nbrOfSetups);

%% Go through all setups
for n = 1:nbrOfSetups

    %Output simulation progress
    disp([num2str(n) ' setups out of ' num2str(nbrOfSetups)]);

    %Compute channel statistics for one setup
    [R,channelGaindB] = functionExampleSetup(L,K,M,accuracy,ASDdeg);

    %Compute the normalized average channel gain, where the normalization
    %is based on the noise power
    channelGainOverNoise = channelGaindB - noiseVariancedBm;

    %Go through all pilot reuse factors
    for s = 1:length(fRange)

        %Extract pilot reuse factor
        f = fRange(s);

        %Output simulation progress
        disp([num2str(f) ' reuse factor out of ' num2str(length(fRange))]);

        %Go through all hardware qualities
        for r = 1:length(kappatUE)

            %Generate channel realizations with estimates and estimation
            %error correlation matrices, using LMMSE estimation
            [Hhat,C,tau_p,~,H] = functionChannelEstimates_impairments(R,channelGainOverNoise,nbrOfRealizations,M,K,L,p,f,kappatUE(r),kapparBS(r));

            %Compute SE using Monte-Carlo realizations
            [SE_MR,SE_RZF,SE_MMMSE] = functionComputeSE_DL_impairments(H,Hhat,C,tau_c,tau_p,nbrOfRealizations,M,K,L,p,rho,kappatBS(r),kapparUE(r));

            %Save results
            sumSE_MR(r,s,n) = mean(sum(SE_MR,1));
            sumSE_RZF(r,s,n) = mean(sum(SE_RZF,1));
            sumSE_MMMSE(r,s,n) = mean(sum(SE_MMMSE,1));

            %Delete large matrices
            clear Hhat C H;

        end

    end

    %Delete large matrices
    clear R;

end

%Plot the simulation results
figure;
hold on; box on;

plot(kapparUE([1 2 3 9 4 5]),max(mean(sumSE_MMMSE([1 2 3 9 4 5],:,:),3),[],2),'rd-','LineWidth',1);
plot(kapparUE([1 2 3 9 4 5]),max(mean(sumSE_RZF([1 2 3 9 4 5],:,:),3),[],2),'r-.','LineWidth',1);
plot(kapparUE([1 2 3 9 4 5]),max(mean(sumSE_MR([1 2 3 9 4 5],:,:),3),[],2),'bs-','LineWidth',1);

xlabel('DL hardware quality');
ylabel('Average sum SE [bit/s/Hz/cell]');
legend('M-MMSE','RZF','MR','Location','SouthEast');
xlim([0.95 1]);
ylim([0 40]);

%Plot the simulation results
figure;
hold on; box on;

plot(kappatUE(6:11),max(mean(sumSE_MMMSE(6:11,:,:),3),[],2),'rd-','LineWidth',1);
plot(kappatUE(6:11),max(mean(sumSE_RZF(6:11,:,:),3),[],2),'r-.','LineWidth',1);
plot(kappatUE(6:11),max(mean(sumSE_MR(6:11,:,:),3),[],2),'bs-','LineWidth',1);

xlabel('UL hardware quality');
ylabel('Average sum SE [bit/s/Hz/cell]');
legend('M-MMSE','RZF','MR','Location','SouthEast');
xlim([0.95 1]);
ylim([0 40]);


% -----------------------------------------------------------
% |Nagi Hatoum, Candlestick chart "ploter" function, 5/29/03 |
% |Edited and expanded by Jelle C.J. Veraa, 3/28/2009        |
% -----------------------------------------------------------
%
% Important: date plotting subroutine needs 'tlabel' by Carlos Adrian
%   Vargas Aguilera
%   Available at the MATLAB Central File Exchange site, File ID: #19314
%   http://www.mathworks.com/matlabcentral/fileexchange/19314
%
% function cndlV2(O,H,L,C)
%          cndlV2(O,H,L,C,date)
%          cndlV2(O,H,L,C,date,colorUp,colorDown,colorLine)
%          cndlV2(OHLC)
%          cndlV2(OHLC,date)
%          cndlV2(OHLC,date,colorUp,colorDown,colorLine)
%
% To use colors without a date, put '0' as date
%     i.e. cndlV2(OHLC,0,'b','r','k');
%
% required inputs: column vectors of O(pen), H(igh), L(ow)
% and C(lose) prices of commodity.
% Alternative: OHLC matrix of size [rowsx4]
%
% optional inputs [default]:
% - date: serial date number (make with 'datenum') [no dates, index#]
% - colorUp: Color for up candle                   ['w']
% - colorDown: Color for down candle               ['k']
% - colorLine: Color for lines                     ['k']
%
% Note: identical inputs as required for barChartPlot except for colors

function cndlV2(varargin)
% See if we have [OHLC] or seperate vectors and retrieve our
% required variables (Feel free to make this code more pretty ;-)
isMat = size(varargin{1},2);
indexShift = 0;
useDate = 0;

if isMat == 4,
    O = varargin{1}(:,1);
    H = varargin{1}(:,2);
    L = varargin{1}(:,3);
    C = varargin{1}(:,4);
else
    O = varargin{1};
    H = varargin{2};
    L = varargin{3};
    C = varargin{4};
    indexShift = 3;
end
if nargin+isMat < 7,
    colorDown = 'k';
    colorUp = 'w';
    colorLine = 'k';
else
    colorUp = varargin{3+indexShift};
    colorDown = varargin{4+indexShift};
    colorLine = varargin{5+indexShift};
end
if nargin+isMat < 6,
    date = (1:length(O))';
else
    if varargin{2+indexShift} ~= 0
        date = varargin{2+indexShift};
        useDate = 1;
    else
        date = (1:length(O))';
    end
end

% w = Width of body, change multiplier to draw body thicker or thinner
% the 'min' ensures no errors on weekends ('time gap Fri. Mon.' > wanted
% spacing)
w=.3*min([(date(2)-date(1)) (date(3)-date(2))]);
%%%%%%%%%%%Find up and down days%%%%%%%%%%%%%%%%%%%
d=C-O;
l=length(d);
hold on
%%%%%%%%draw line from Low to High%%%%%%%%%%%%%%%%%
for i=1:l
   line([date(i) date(i)],[L(i) H(i)],'Color',colorLine)
end
%%%%%%%%%%draw white (or user defined) body (down day)%%%%%%%%%%%%%%%%%
n=find(d<0);
for i=1:length(n)
    x=[date(n(i))-w date(n(i))-w date(n(i))+w date(n(i))+w date(n(i))-w];
    y=[O(n(i)) C(n(i)) C(n(i)) O(n(i)) O(n(i))];
    fill(x,y,colorDown)
end
%%%%%%%%%%draw black (or user defined) body(up day)%%%%%%%%%%%%%%%%%%%
n=find(d>=0);
for i=1:length(n)
    x=[date(n(i))-w date(n(i))-w date(n(i))+w date(n(i))+w date(n(i))-w];
    y=[O(n(i)) C(n(i)) C(n(i)) O(n(i)) O(n(i))];
    fill(x,y,colorUp)
end

if (nargin+isMat > 5) && useDate,
    tlabel('x');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
hold off


function gX = rbfardjitKernDiagGradX(kern, X)

% RBFARDJITKERNDIAGGRADX Gradient of RBFARDJIT kernel's diagonal with respect to X.
% FORMAT
% DESC computes the gradient of the diagonal of the automatic relevance determination radial basis function kernel matrix with
% respect to the elements of the design matrix given in X.
% ARG kern : the kernel structure for which gradients are being computed.
% ARG X : the input data in the form of a design matrix.
% RETURN gX : the gradients of the diagonal with respect to each element
% of X. The returned matrix has the same dimensions as X.
%
% SEEALSO : rbfard2KernParamInit, kernDiagGradX, rbfard2kernGradX
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005, 2006
%
% COPYRIGHT : Michalis K. Titsias, 2009

% KERN

gX = zeros(size(X));


% Data Quality specification snippet to populate default values
% and verify times are in range
% axs June 2019, ERPLAB
% ams Dec 2022, ERPLAB update: incl'd smaller window for short epoch(<100ms)
function DQ_spec_out = make_DQ_spec(timelimits_ms)

% Check and populate missing args
if exist('timelimits_ms','var') == 0 || isempty(timelimits_ms)

    try
        evalin('base','timelimits = [EEG.xmin EEG.xmax];');
        timelimits_ms = timelimits * 1000;

    catch
        %warning('Couldn''t find time limits for DQ range, trying defaults')
        timelimits_ms = [-200 500];
    end
end

% Prepare time range and time-windows
win_size = 100; %ms
%     If crossing zero, ensure windows are centered on zero
if (min(timelimits_ms) < 0) && (max(timelimits_ms) > 0)
    % if crossing zero, grow 0:-win_size:min and 0:win_size:max

    tw_neg = sort([0:-win_size:timelimits_ms(1)]);
    tw_pos = [0:win_size:timelimits_ms(2)];

    % concatenate
    tw_starts = unique([tw_neg tw_pos]);
    tw_ends = tw_starts + win_size;

else
    % else, grow min:win_size:term

    tw_starts = min(timelimits_ms):win_size:max(timelimits_ms);
    tw_ends = tw_starts + win_size;
end

% remove time-windows out of range
if tw_ends(end) > max(timelimits_ms)
    tw_starts(end) = [];
    tw_ends(end) = [];
end

% for tw less than 100ms
if isempty(tw_starts) & isempty(tw_ends)
    win_size = 2;  %considers typical auditory brainstem responses (ABRs) (eg, 25ms epochs)
                   %thanks Dr. Kelsey Mankel!
    if (min(timelimits_ms) < 0) && (max(timelimits_ms) > 0)
        % if crossing zero, grow 0:-win_size:min and 0:win_size:max

        tw_neg = sort([0:-win_size:timelimits_ms(1)]);
        tw_pos = [0:win_size:timelimits_ms(2)];

        % concatenate
        tw_starts = unique([tw_neg tw_pos]);
        tw_ends = tw_starts + win_size;

    else
        % else, grow min:win_size:term

        tw_starts = min(timelimits_ms):win_size:max(timelimits_ms);
        tw_ends = tw_starts + win_size;
    end

    % remove time-windows out of range
    if tw_ends(end) > max(timelimits_ms)
        tw_starts(end) = [];
        tw_ends(end) = [];
    end

end

% make labels
root_str = 'aSME at ';
for i = 1:numel(tw_starts)
    tw_labels{i} = [root_str num2str(tw_starts(i)) ' to ' num2str(tw_ends(i)) ];
end

root_str = 'aSD Across Trials at ';
for i = 1:numel(tw_starts)
    tw_labels_sd{i} = [root_str num2str(tw_starts(i)) ' to ' num2str(tw_ends(i)) ];
end

tw = [tw_starts; tw_ends]';

% Build spec with these times
DQ_defaults(1).type = 'Baseline Measure - SD';

DQ_defaults(2).type = 'Point-wise SEM';

DQ_defaults(3).type = 'aSME';
DQ_defaults(3).times = tw;
DQ_defaults(3).time_window_labels = tw_labels;
DQ_defaults(3).comments = [];

%add SD across trials (01/05/22)
DQ_defaults(4).type = 'SD Across Trials';
DQ_defaults(4).times = tw;
DQ_defaults(4).time_window_labels = tw_labels_sd;
DQ_defaults(4).comments=[];

DQ_spec_out = DQ_defaults;


function out=mtimes(x,y)

precisionx=0;   precisiony=0;
xmp=isa(x,'mp');
if xmp
 precisionx=x(1).precision;
 ymp=isa(y,'mp');
else
 ymp=true;
end
if ymp
 precisiony=y(1).precision;
end
precision=max(precisionx,precisiony);
ex=numel(x);
ey=numel(y);

if ex==1 | ey==1
 if ~xmp,  x=mp(x);  end
 if ~ymp,  y=mp(y);  end
 if ex==1
  out_rval=cell(size(y));
  out_ival=out_rval;

  [xrval,xival]=getVals(x,1);
  %xrval=x(1).rval;  xival=x(1).ival;  if isempty(xival), xival='0'; end

  xReal=hasimag(xival);
  for ii=1:ey
   [yrval,yival]=getVals(y,ii);
   %yrval=y(ii).rval;  yival=y(ii).ival;  if isempty(yival), yival='0'; end
   if xReal | hasimag(yival)
    [out_rval{ii},out_ival{ii}]=mpfr_mulc(precision,xrval,xival,yrval,yival);
   else
    %if isempty(xrval),  'xxxxxxxxxxxx',kb, end
    out_rval{ii}=mpfr_mul(precision,xrval,yrval);
   end
  end
 else
  out_rval=cell(size(x));
  out_ival=out_rval;
  [yrval,yival]=getVals(y,1);
  yReal=hasimag(yival);
  for ii=1:ex
   [xrval,xival]=getVals(x,ii);
   if hasimag(xival) | yReal
    [out_rval{ii},out_ival{ii}]=mpfr_mulc(precision,xrval,xival,yrval,yival);
   else
    out_rval{ii}=mpfr_mul(precision,xrval,yrval);
   end
  end
 end
 out=class(struct('rval',out_rval,...
                  'ival',out_ival,...
                  'precision',precision),'mp');
else %%% out=x*y;
 sx=size(x);
 sy=size(y);
 if sx(2)~=sy(1)
  disp(['size of matrix 1 => ',num2str(sx(1)),'x',num2str(sx(2))]);
  disp(['size of matrix 2 => ',num2str(sy(1)),'x',num2str(sy(2))]);
  error('array size mismatch for mtimes')
 else
  out=mp(zeros(sx(1),sy(2)),precision);
  for ii=1:sx(1)
   for jj=1:sy(2)
    out(ii,jj)=sum(x(ii,1:end).*y(1:end,jj).');
   end
  end
 end
end


function [B] = KB2B(KB)
% Convert computery things from kilobytes to bytes.
% Chad A. Greene 2012
B = KB*1024;


%
%   FILE NAME:    getRxnsFromMNX.m
%
%   PURPOSE: Generate the data structure for MetaNetX reactions
%

% Move to the target MNX folder

% Load the MNX reactions
T=readtable('reac_prop.xlsx','ReadVariableNames',1);
MNXRxns=table2struct(T,'ToScalar',true);
% Refine the equations by removing compartment suffix
MNXRxns.equations=regexprep(MNXRxns.Equation,'\@MNXD\d+','');
MNXRxns.equations=regexprep(MNXRxns.equations,'=','<=>');
MNXRxns.Description=regexprep(MNXRxns.Description,'1 `','');
MNXRxns.Description=regexprep(MNXRxns.Description,'`','');

% Construct the S matrix and list of metabolites
[S, mets, badRxns, reversible]=constructS(MNXRxns.equations);  %time-consuming
MNXRxns.S=S;
MNXRxns.mets=mets;
MNXRxns.badRxns=badRxns;
% Count metabolite number for reactions
num=numel(MNXRxns.EC);
MNXRxns.metNum=zeros(num,1);
for i=1:num
	MNXRxns.metNum(i,1)=numel(find(MNXRxns.S(:,i)));
end

% Construct the full S matrix and list of metabolites
MNXRxns.fullequations=regexprep(MNXRxns.Equation,'=','<=>');
[fullS, fullMets, badRxns, reversible]=constructS(MNXRxns.fullequations);  %time-consuming
MNXRxns.fullS=fullS;
MNXRxns.fullMets=fullMets;
MNXRxns.fullSbadRxns=badRxns;
% Count metabolite number for reactions
MNXRxns.fullMetNum=zeros(num,1);
for i=1:num
	MNXRxns.fullMetNum(i,1)=numel(find(MNXRxns.fullS(:,i)));
end

save('MNXRxns.mat','MNXRxns');


function dt = datatypes
% Datatype
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

%
% $Id: datatypes.m 1143 2008-02-07 19:33:33Z spm $

persistent dtype
if isempty(dtype),
    t = true;
    f = false;
    table = {...
        0   ,'UNKNOWN'   ,'uint8'   ,@uint8  ,1,1  ,t,t,f
        1   ,'BINARY'    ,'uint1'   ,@logical,1,1/8,t,t,f
        256 ,'INT8'      ,'int8'    ,@int8   ,1,1  ,t,f,t
        2   ,'UINT8'     ,'uint8'   ,@uint8  ,1,1  ,t,t,t
        4   ,'INT16'     ,'int16'   ,@int16  ,1,2  ,t,f,t
        512 ,'UINT16'    ,'uint16'  ,@uint16 ,1,2  ,t,t,t
        8   ,'INT32'     ,'int32'   ,@int32  ,1,4  ,t,f,t
        768 ,'UINT32'    ,'uint32'  ,@uint32 ,1,4  ,t,t,t
        1024,'INT64'     ,'int64'   ,@int64  ,1,8  ,t,f,f
        1280,'UINT64'    ,'uint64'  ,@uint64 ,1,8  ,t,t,f
        16  ,'FLOAT32'   ,'float32' ,@single ,1,4  ,f,f,t
        64  ,'FLOAT64'   ,'double'  ,@double ,1,8  ,f,f,t
        1536,'FLOAT128'  ,'float128',@crash  ,1,16 ,f,f,f
        32  ,'COMPLEX64' ,'float32' ,@single ,2,4  ,f,f,f
        1792,'COMPLEX128','double'  ,@double ,2,8  ,f,f,f
        2048,'COMPLEX256','float128',@crash  ,2,16 ,f,f,f
        128 ,'RGB24'     ,'uint8'   ,@uint8  ,3,1  ,t,t,f};
    dtype = struct(...
        'code'     ,table(:,1),...
        'label'    ,table(:,2),...
        'prec'     ,table(:,3),...
        'conv'     ,table(:,4),...
        'nelem'    ,table(:,5),...
        'size'     ,table(:,6),...
        'isint'    ,table(:,7),...
        'unsigned' ,table(:,8),...
        'min',-Inf,'max',Inf',...
        'supported',table(:,9));
    for i=1:length(dtype),
        if dtype(i).isint
            if dtype(i).unsigned
                dtype(i).min =  0;
                dtype(i).max =  2^(8*dtype(i).size)-1;
            else
                dtype(i).min = -2^(8*dtype(i).size-1);
                dtype(i).max =  2^(8*dtype(i).size-1)-1;
            end;
        end;
    end;
end;

dt = dtype;


function tests = test_ft_preproc_rereference

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

if nargout
  % assume that this is called by RUNTESTS
  tests = functiontests(localfunctions);
else
  % assume that this is called from the command line
  fn = localfunctions;
  for i=1:numel(fn)
    feval(fn{i});
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function testOptions(testCase)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

nchan   = 8;
nsample = 1000;
dat     = randn(nchan, nsample) + 1;

handlenan = false;
leadfield = randn(8, 1000);

result = {};
result{end+1} = ft_preproc_rereference(dat, 1,   'avg', handlenan);
result{end+1} = ft_preproc_rereference(dat, 1:4, 'avg', handlenan);
result{end+1} = ft_preproc_rereference(dat, 1:8, 'avg', handlenan);
result{end+1} = ft_preproc_rereference(dat, 1:4, 'median', handlenan);
result{end+1} = ft_preproc_rereference(dat, 1:8, 'median', handlenan);
result{end+1} = ft_preproc_rereference(dat, 1,   'rest', handlenan, leadfield);
result{end+1} = ft_preproc_rereference(dat, 1:4, 'rest', handlenan, leadfield);
result{end+1} = ft_preproc_rereference(dat, 1:8, 'rest', handlenan, leadfield);

% 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(~isequal(result{i}, result{j}), 'the results %d and %d should not be equal', i, j);
  end
end


function ebsd = flipud(ebsd)
% flip spatial ebsd-data from upside down
%
% Input
%  ebsd - @EBSD
%
% Output
%  flipped ebsd - @EBSD

m(1) = max(ebsd.prop.x);
m(2) = max(ebsd.prop.y);
ebsd = affinetrans(ebsd,[],[0 -m(2)]);

ebsd = rotate(ebsd,rotation.byAxisAngle(xvector,pi));


%% Background Subtraction demo
% An example using drawContours to clean up a background segmentation result.
%
% This program demonstrates a simple method of connected components clean up
% of background subtraction.
% When the program starts, it begins learning the background.
% You can toggle background learning on and off using the checkbox.
%
% Sources:
%
% * <https://github.com/opencv/opencv/blob/3.2.0/samples/cpp/segment_objects.cpp>
%

%% Set up video source: video file or camera
fname = fullfile(mexopencv.root(),'test','768x576.avi');
if exist(fname, 'file') ~= 2
    % download video from Github
    disp('Downloading video...')
    url = 'https://cdn.rawgit.com/opencv/opencv/3.1.0/samples/data/768x576.avi';
    urlwrite(url, fname);
end
cap = cv.VideoCapture(fname);
%cap = cv.VideoCapture(0); pause(2);
assert(cap.isOpened(), 'Cannot open video source');

frame = cap.read();
assert(~isempty(frame), 'Cannot read data from the video source');

%% Create a background subtractor
bs = cv.BackgroundSubtractorMOG2('VarThreshold',10);

%%
ZR = zeros(size(frame,1), size(frame,2), 'uint8');
niters = 3;

%% Prepare window
hFig = figure('Position',[100 100 840 630], ...
    'KeyPressFcn',@(o,e)setappdata(o,'flag',true));
setappdata(hFig, 'flag',false);
subplot(221), hImg(1) = imshow(frame); title('video')
subplot(222), hImg(2) = imshow(frame); title('BG model')
subplot(223), hImg(3) = imshow(ZR); title('FG segmented')
subplot(224), hImg(4) = imshow(ZR); title('FG largest component')
hCB = uicontrol('Style','checkbox', 'Position',[20 20 200 20], ...
    'String','Update Background Model', 'Value',true);

%% Main loop
while ishghandle(hFig)
    % get next frame
    frame = cap.read();
    if isempty(frame), break; end

    % determine whether to update BG model or not, then compute FG mask
    update_bg_model = get(hCB,'Value');
    if update_bg_model
        learnRate = -1; % automatically chosen learning rate
    else
        learnRate = 0;  % dont update BG model
    end
    fgmask = bs.apply(frame, 'LearningRate',learnRate);

    % process mask and extract largest connected component
    bw = cv.dilate(fgmask, 'Iterations',niters);
    bw = cv.erode(bw, 'Iterations',niters*2);
    bw = cv.dilate(bw, 'Iterations',niters);
    [contours, hierarchy] = cv.findContours(bw, ...
        'Mode','CComp', 'Method','Simple');
    if ~isempty(contours)
        maxArea = 0;
        largestComp = 0;
        idx = 0;
        while idx >= 0
            % compute contour area
            a = abs(cv.contourArea(contours{idx+1}));
            if a > maxArea
                maxArea = a;
                largestComp = idx;
            end
            % iterate through all the top-level contours
            idx = hierarchy{idx+1}(1);
        end
        out_frame = cv.drawContours(ZR, contours, ...
            'ContourIdx',largestComp, 'Hierarchy',hierarchy, ...
            'Color',255, 'Thickness','Filled');
    else
        out_frame = ZR;
    end

    % update images
    set(hImg(1), 'CData',frame)     % video frame
    if update_bg_model
        % get the current BG model
        set(hImg(2), 'CData',bs.getBackgroundImage())
    end
    set(hImg(3), 'CData',fgmask)    % FG mask
    set(hImg(4), 'CData',out_frame) % largest contour in FG mask

    % Terminate if any user input
    flag = getappdata(hFig, 'flag');
    if isempty(flag)||flag, break; end
    pause(0.1);
end

%%
% release camera
cap.release()


function b = rhs(disc, f)
%RHS   Discretize the right-hand side of a linear system for VALSDISCRETIZATION.
%   B = RHS(DISC, F) returns a discrete version, B,  of the function (or
%   chebmatrix) F, as defined by the discretization DISC.
%
% See also MATRIX, REDUCE.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% Developers note: This method works as follows.
%   The original function(s) are discretized, then reduced in dimension the same
%   way as the operator. The constraints are prepended to the top of the vector.

xOut = equationPoints(disc);
for k = 1:numel(f.blocks)
    if ( ~isnumeric(f.blocks{k}) )
        f.blocks{k} = feval(f.blocks{k}, xOut);
    end
end
b = cell2mat(f.blocks);

% Developer note:
%   The continuity conditions go above the constraints. See getConstraints().

% Prepend the values of the constraints and continuity conditions.
L = disc.source;

if ( ~isempty(L.constraint) )
    b = [ L.constraint.values ; b ];
end
if ( ~isempty(L.continuity) )
    b = [ L.continuity.values ; b ];
end

end


function kern = whitefixedKernParamInit(kern)

% WHITEFIXEDKERNPARAMINIT WHITEFIXED kernel parameter initialisation.
% The white noise kernel arises from assuming independent Gaussian
% noise for each point in the function. The variance of the noise is
% given by the kern.variance parameter. The fixed white noise kernel
% is a simple variant of the white kernel that doesn't allow the noise
% parameter to be optimised. It is useful when the level of noise is
% known a priori.
%
% This kernel is not intended to be used independently, it is provided
% so that it may be combined with other kernels in a compound
% kernel.
%
% SEEALSO : cmpndKernParamInit
%
% FORMAT
% DESC initialises the fixed parameter white noise
%  kernel structure with some default parameters.
% ARG kern : the kernel structure which requires initialisation.
% RETURN kern : the kernel structure with the default parameters placed in.
%
% SEEALSO : kernCreate, kernParamInit
%
% COPYRIGHT : Nathaniel J. King, 2006

% KERN

kern.variance = exp(-2);
kern.nParams = 0;

kern.isStationary = true;


classdef GridMap < handle
    properties
        boundary;       % size of Metric Map(leftdownPoint + rightupPoint)
        blocks;         % coordinate of obstacles on the Metric Map
        res;            % resolution
        margin;
        maxIndex;       % max index of ijk of GridMap
        occ_map;        % flag obstacles on the GridMap
    end
    methods
        function obj = GridMap()
        end

        function load_map(obj, filename, xy_res, z_res, margin)
            fid = fopen(filename);
            tline = fgets(fid);
            obj.blocks = [];
            while ischar(tline)
                % skip empty line and comments
                if numel(tline) > 1 & tline(1)~='#'
                    % convert char array to string
                    if strncmpi(tline, 'boundary', 8)
                        boundarys = strread(tline(9:end));
                    end
                    if strncmpi(tline, 'block', 5)
                        block = strread(tline(6:end));
                        assert(size(block,2) == 9);
                        obj.blocks = [obj.blocks; block];
                    end
                end
                tline = fgets(fid);
            end
            obj.boundary.ld = boundarys(1:3);
            obj.boundary.ru = boundarys(4:6);
            obj.res = [xy_res xy_res z_res];
            obj.margin = margin;
            obj.maxIndex = ceil(abs( (obj.boundary.ru - obj.boundary.ld)./obj.res ));
        end

        % obstacles = block + margin
        function flag_obstacles(obj)
            obj.occ_map = false(obj.maxIndex);
            for i = 1 : size(obj.blocks,1)
                block = obj.blocks(i, :);
                leftdownPoint = [min(block(1), block(4)) min(block(2), block(5)) min(block(3), block(6))];
                rightUpPoint = [max(block(1), block(4)) max(block(2), block(5)) max(block(3), block(6))];
                obj.blocks(i, 1:3) = leftdownPoint;
                obj.blocks(i, 4:6) = rightUpPoint;
                xyzs = obj.points_to_idx(leftdownPoint - obj.margin);
                xyze = obj.points_to_idx(rightUpPoint + obj.margin);
                obj.occ_map(xyzs(1):xyze(1), xyzs(2):xyze(2), xyzs(3):xyze(3)) = 1;
            end
        end

        function ijk = points_to_idx(obj, xyz)
            assert(size(xyz,1) > 0);
            ijk = floor((xyz - obj.boundary.ld)./obj.res + 1);
            ijk = min(max(ijk, 1), obj.maxIndex);
        end

        function xyz = idx_to_points(obj, ijk)
            assert(size(ijk,1) > 0);
            xyz = obj.boundary.ld + (ijk - 1 + 0.5).* obj.res;
        end

        function ret = idOverflowCheck(obj, i, j, k)
            ret = (i < 1 || i > obj.maxIndex(1) || j < 1 || j > obj.maxIndex(2) || k < 1 || k > obj.maxIndex(3));
        end

        % check points collide
        function C = collide(obj, points)
            ijk = obj.points_to_idx(points);
            C = false(size(ijk, 1), 1);
            for i = 1 : size(ijk, 1)
                id = ijk(i,:);
                C(i) =  obj.occ_map(id(1), id(2), id(3)) ~= 0;
            end
        end

        %% generate intermedia points
        function pts = generateiIntermediaPoints(obj, start_pos, end_pos)
            %% generate Tiny direction vector
            dd = end_pos - start_pos;
            dir = obj.res(1)*(dd/norm(dd, 2))/(100);

            %% generate intermedia points
            lenxy = sqrt(sum((start_pos(1:2) - end_pos(1:2)).^2));
            lenz = sqrt(sum((start_pos(3) - end_pos(3)).^2));
            n_pts = int32(max(lenxy/obj.res(1), lenz/obj.res(3))) + 3;
            pts = [linspace(start_pos(1), end_pos(1), n_pts);
                   linspace(start_pos(2), end_pos(2), n_pts);
                   linspace(start_pos(3), end_pos(3), n_pts)]';

            %% mid-point + Tiny direction vector
            for j = 2 : size(pts,1) - 1
                m1 = mod(pts(j,1), obj.res(1));
                m2 = mod(pts(j,2), obj.res(1));
                m3 = mod(pts(j,3), obj.res(1));
                if(m1*m2*m3 == 0)
                    pts(j,:) = pts(j,:) + dir;
                end
            end
        end
    end
end


function x = spm_coreg(varargin)
% Between modality coregistration using information theory
% FORMAT x = spm_coreg(VG,VF,flags)
% VG    - handle for reference image (see spm_vol).
% VF    - handle for source (moved) image.
% flags - a structure containing the following elements:
%          sep      - optimisation sampling steps (mm)
%                     default: [4 2]
%          params   - starting estimates (6 elements)
%                     default: [0 0 0  0 0 0]
%          cost_fun - cost function string:
%                       'mi'  - Mutual Information
%                       'nmi' - Normalised Mutual Information
%                       'ecc' - Entropy Correlation Coefficient
%                       'ncc' - Normalised Cross Correlation
%                     default: 'nmi'
%          tol      - tolerences for accuracy of each param
%                     default: [0.02 0.02 0.02 0.001 0.001 0.001]
%          fwhm     - smoothing to apply to 256x256 joint histogram
%                     default: [7 7]
%          graphics - display coregistration outputs
%                     default: ~spm('CmdLine')
%
% x     - the parameters describing the rigid body rotation, such that a
%         mapping from voxels in G to voxels in F is attained by:
%         VF.mat\spm_matrix(x(:)')*VG.mat
%
% At the end, the voxel-to-voxel affine transformation matrix is
% displayed, along with the histograms for the images in the original
% orientations, and the final orientations. The registered images are
% displayed at the bottom.
%__________________________________________________________________________
%
% The registration method used here is based on the work described in:
% A Collignon, F Maes, D Delaere, D Vandermeulen, P Suetens & G Marchal
% (1995) "Automated Multi-modality Image Registration Based On
% Information Theory". In the proceedings of Information Processing in
% Medical Imaging (1995).  Y. Bizais et al. (eds.).  Kluwer Academic
% Publishers.
%
% The original interpolation method described in this paper has been
% changed in order to give a smoother cost function.  The images are
% also smoothed slightly, as is the histogram.  This is all in order to
% make the cost function as smooth as possible, to give faster convergence
% and less chance of local minima.
%__________________________________________________________________________
% Copyright (C) 1994-2011 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_coreg.m 6435 2015-05-14 09:59:54Z guillaume $

%--------------------------------------------------------------------------
% References
%==========================================================================
%
% Mutual Information
% -------------------------------------------------------------------------
% Collignon, Maes, Delaere, Vandermeulen, Suetens & Marchal (1995).
% "Automated multi-modality image registration based on information theory".
% In Bizais, Barillot & Di Paola, editors, Proc. Information Processing
% in Medical Imaging, pages 263--274, Dordrecht, The Netherlands, 1995.
% Kluwer Academic Publishers.
%
% Wells III, Viola, Atsumi, Nakajima & Kikinis (1996).
% "Multi-modal volume registration by maximisation of mutual information".
% Medical Image Analysis, 1(1):35-51, 1996.
%
% Entropy Correlation Coefficient
% -------------------------------------------------------------------------
% Maes, Collignon, Vandermeulen, Marchal & Suetens (1997).
% "Multimodality image registration by maximisation of mutual
% information". IEEE Transactions on Medical Imaging 16(2):187-198
%
% Normalised Mutual Information
% -------------------------------------------------------------------------
% Studholme, Hill & Hawkes (1998).
% "A normalized entropy measure of 3-D medical image alignment".
% in Proc. Medical Imaging 1998, vol. 3338, San Diego, CA, pp. 132-143.
%
% Optimisation
% -------------------------------------------------------------------------
% Press, Teukolsky, Vetterling & Flannery (1992).
% "Numerical Recipes in C (Second Edition)".
% Published by Cambridge.
%--------------------------------------------------------------------------

SVNid = '$Rev: 6435 $';

if nargin >= 4
    x = optfun(varargin{:});
    return;
end

%-Say hello
%--------------------------------------------------------------------------
SPMid = spm('FnBanner',mfilename,SVNid);

def_flags          = spm_get_defaults('coreg.estimate');
def_flags.params   = [0 0 0  0 0 0];
def_flags.graphics = ~spm('CmdLine');
if nargin < 3
    flags = def_flags;
else
    flags = varargin{3};
    fnms  = fieldnames(def_flags);
    for i=1:length(fnms)
        if ~isfield(flags,fnms{i})
            flags.(fnms{i}) = def_flags.(fnms{i});
        end
    end
end

if nargin < 1
    VG = spm_vol(spm_select(1,'image','Select reference image'));
else
    VG = varargin{1};
    if ischar(VG), VG = spm_vol(VG); end
end
if nargin < 2
    VF = spm_vol(spm_select(Inf,'image','Select moved image(s)'));
else
    VF = varargin{2};
    if ischar(VF) || iscellstr(VF), VF = spm_vol(char(VF)); end;
end

if ~isfield(VG, 'uint8')
    VG.uint8 = loaduint8(VG);
    vxg      = sqrt(sum(VG.mat(1:3,1:3).^2));
    fwhmg    = sqrt(max([1 1 1]*flags.sep(end)^2 - vxg.^2, [0 0 0]))./vxg;
    VG       = smooth_uint8(VG,fwhmg); % Note side effects
end

sc = flags.tol(:)'; % Required accuracy
sc = sc(1:length(flags.params));
xi = diag(sc*20);
x = zeros(numel(VF),numel(flags.params));

for k=1:numel(VF)
    VFk = VF(k);
    if ~isfield(VFk, 'uint8')
        VFk.uint8 = loaduint8(VFk);
        vxf       = sqrt(sum(VFk.mat(1:3,1:3).^2));
        fwhmf     = sqrt(max([1 1 1]*flags.sep(end)^2 - vxf.^2, [0 0 0]))./vxf;
        VFk       = smooth_uint8(VFk,fwhmf); % Note side effects
    end

    xk  = flags.params(:);
    for samp=flags.sep(:)'
        xk     = spm_powell(xk(:), xi,sc,mfilename,VG,VFk,samp,flags.cost_fun,flags.fwhm);
        x(k,:) = xk(:)';
    end
    if flags.graphics
        display_results(VG(1),VFk(1),xk(:)',flags);
    end
end

fprintf('%-40s: %30s\n','Completed',spm('time'))                        %-#

%==========================================================================
% function o = optfun(x,VG,VF,s,cf,fwhm)
%==========================================================================
function o = optfun(x,VG,VF,s,cf,fwhm)
% The function that is minimised.
if nargin<6, fwhm = [7 7];   end
if nargin<5, cf   = 'mi';    end
if nargin<4, s    = [1 1 1]; end

% Voxel sizes
vxg = sqrt(sum(VG.mat(1:3,1:3).^2));sg = s./vxg;

% Create the joint histogram
H = spm_hist2(VG.uint8,VF.uint8, VF.mat\spm_matrix(x(:)')*VG.mat ,sg);

% Smooth the histogram
lim  = ceil(2*fwhm);
krn1 = spm_smoothkern(fwhm(1),-lim(1):lim(1)) ; krn1 = krn1/sum(krn1); H = conv2(H,krn1);
krn2 = spm_smoothkern(fwhm(2),-lim(2):lim(2))'; krn2 = krn2/sum(krn2); H = conv2(H,krn2);

% Compute cost function from histogram
H  = H+eps;
sh = sum(H(:));
H  = H/sh;
s1 = sum(H,1);
s2 = sum(H,2);

switch lower(cf)
    case 'mi'
        % Mutual Information:
        H   = H.*log2(H./(s2*s1));
        mi  = sum(H(:));
        o   = -mi;
    case 'ecc'
        % Entropy Correlation Coefficient of:
        % Maes, Collignon, Vandermeulen, Marchal & Suetens (1997).
        % "Multimodality image registration by maximisation of mutual
        % information". IEEE Transactions on Medical Imaging 16(2):187-198
        H   = H.*log2(H./(s2*s1));
        mi  = sum(H(:));
        ecc = -2*mi/(sum(s1.*log2(s1))+sum(s2.*log2(s2)));
        o   = -ecc;
    case 'nmi'
        % Normalised Mutual Information of:
        % Studholme,  Hill & Hawkes (1998).
        % "A normalized entropy measure of 3-D medical image alignment".
        % in Proc. Medical Imaging 1998, vol. 3338, San Diego, CA, pp. 132-143.
        nmi = (sum(s1.*log2(s1))+sum(s2.*log2(s2)))/sum(sum(H.*log2(H)));
        o   = -nmi;
    case 'ncc'
        % Normalised Cross Correlation
        i     = 1:size(H,1);
        j     = 1:size(H,2);
        m1    = sum(s2.*i');
        m2    = sum(s1.*j);
        sig1  = sqrt(sum(s2.*(i'-m1).^2));
        sig2  = sqrt(sum(s1.*(j -m2).^2));
        [i,j] = ndgrid(i-m1,j-m2);
        ncc   = sum(sum(H.*i.*j))/(sig1*sig2);
        o     = -ncc;
    otherwise
        error('Invalid cost function specified');
end

%==========================================================================
% function udat = loaduint8(V)
%==========================================================================
function udat = loaduint8(V)
% Load data from file indicated by V into an array of unsigned bytes.
if size(V.pinfo,2)==1 && V.pinfo(1) == 2
    mx = 255*V.pinfo(1) + V.pinfo(2);
    mn = V.pinfo(2);
else
    spm_progress_bar('Init',V.dim(3),...
        ['Computing max/min of ' spm_file(V.fname,'filename')],...
        'Planes complete');
    mx = -Inf; mn =  Inf;
    for p=1:V.dim(3)
        img = spm_slice_vol(V,spm_matrix([0 0 p]),V.dim(1:2),1);
        img = img(isfinite(img));
        mx  = max([max(img(:))+paccuracy(V,p) mx]);
        mn  = min([min(img(:)) mn]);
        spm_progress_bar('Set',p);
    end
end

% Another pass to find a maximum that allows a few hot-spots in the data.
spm_progress_bar('Init',V.dim(3),...
        ['2nd pass max/min of ' spm_file(V.fname,'filename')],...
        'Planes complete');
nh = 2048;
h  = zeros(nh,1);
for p=1:V.dim(3)
    img = spm_slice_vol(V,spm_matrix([0 0 p]),V.dim(1:2),1);
    img = img(isfinite(img));
    img = round((img+((mx-mn)/(nh-1)-mn))*((nh-1)/(mx-mn)));
    h   = h + accumarray(img,1,[nh 1]);
    spm_progress_bar('Set',p);
end
tmp = [find(cumsum(h)/sum(h)>0.9999); nh];
mx  = (mn*nh-mx+tmp(1)*(mx-mn))/(nh-1);

% Load data from file indicated by V into an array of unsigned bytes.
spm_progress_bar('Init',V.dim(3),...
    ['Loading ' spm_file(V.fname,'filename')],...
    'Planes loaded');
udat = zeros(V.dim,'uint8');
st = rand('state'); % st = rng;
rand('state',100); % rng(100,'v5uniform'); % rng('defaults');
for p=1:V.dim(3)
    img = spm_slice_vol(V,spm_matrix([0 0 p]),V.dim(1:2),1);
    acc = paccuracy(V,p);
    if acc==0
        udat(:,:,p) = uint8(max(min(round((img-mn)*(255/(mx-mn))),255),0));
    else
        % Add random numbers before rounding to reduce aliasing artifact
        r = rand(size(img))*acc;
        udat(:,:,p) = uint8(max(min(round((img+r-mn)*(255/(mx-mn))),255),0));
    end
    spm_progress_bar('Set',p);
end
spm_progress_bar('Clear');
rand('state',st); % rng(st);

%==========================================================================
% function acc = paccuracy(V,p)
%==========================================================================
function acc = paccuracy(V,p)
if ~spm_type(V.dt(1),'intt')
    acc = 0;
else
    if size(V.pinfo,2)==1
        acc = abs(V.pinfo(1,1));
    else
        acc = abs(V.pinfo(1,p));
    end
end

%==========================================================================
% function V = smooth_uint8(V,fwhm)
%==========================================================================
function V = smooth_uint8(V,fwhm)
% Convolve the volume in memory (fwhm in voxels).
lim = ceil(2*fwhm);
x  = -lim(1):lim(1); x = spm_smoothkern(fwhm(1),x); x  = x/sum(x);
y  = -lim(2):lim(2); y = spm_smoothkern(fwhm(2),y); y  = y/sum(y);
z  = -lim(3):lim(3); z = spm_smoothkern(fwhm(3),z); z  = z/sum(z);
i  = (length(x) - 1)/2;
j  = (length(y) - 1)/2;
k  = (length(z) - 1)/2;
spm_conv_vol(V.uint8,V.uint8,x,y,z,-[i j k]);

%==========================================================================
% function display_results(VG,VF,x,flags)
%==========================================================================
function display_results(VG,VF,x,flags)
fig = spm_figure('FindWin','Graphics');
if isempty(fig), return; end;
set(0,'CurrentFigure',fig);
spm_figure('Clear','Graphics');

%txt = 'Information Theoretic Coregistration';
switch lower(flags.cost_fun)
    case 'mi',  txt = 'Mutual Information Coregistration';
    case 'ecc', txt = 'Entropy Correlation Coefficient Registration';
    case 'nmi', txt = 'Normalised Mutual Information Coregistration';
    case 'ncc', txt = 'Normalised Cross Correlation';
    otherwise, error('Invalid cost function specified');
end

% Display text
%--------------------------------------------------------------------------
ax = axes('Position',[0.1 0.8 0.8 0.15],'Visible','off','Parent',fig);
text(0.5,0.7, txt,'FontSize',16,...
    'FontWeight','Bold','HorizontalAlignment','center','Parent',ax);

Q = inv(VF.mat\spm_matrix(x(:)')*VG.mat);
text(0,0.5, sprintf('X1 = %0.3f*X %+0.3f*Y %+0.3f*Z %+0.3f',Q(1,:)),'Parent',ax);
text(0,0.3, sprintf('Y1 = %0.3f*X %+0.3f*Y %+0.3f*Z %+0.3f',Q(2,:)),'Parent',ax);
text(0,0.1, sprintf('Z1 = %0.3f*X %+0.3f*Y %+0.3f*Z %+0.3f',Q(3,:)),'Parent',ax);

% Display joint histograms
%--------------------------------------------------------------------------
ax  = axes('Position',[0.1 0.5 0.35 0.3],'Visible','off','Parent',fig);
H   = spm_hist2(VG.uint8,VF.uint8,VF.mat\VG.mat,[1 1 1]);
tmp = log(H+1);
image(tmp*(64/max(tmp(:))),'Parent',ax');
set(ax,'DataAspectRatio',[1 1 1],...
    'PlotBoxAspectRatioMode','auto','XDir','normal','YDir','normal',...
    'XTick',[],'YTick',[]);
title('Original Joint Histogram','Parent',ax);
xlabel(spm_file(VG.fname,'short22'),'Parent',ax,'Interpreter','none');
ylabel(spm_file(VF.fname,'short22'),'Parent',ax,'Interpreter','none');

H   = spm_hist2(VG.uint8,VF.uint8,VF.mat\spm_matrix(x(:)')*VG.mat,[1 1 1]);
ax  = axes('Position',[0.6 0.5 0.35 0.3],'Visible','off','Parent',fig);
tmp = log(H+1);
image(tmp*(64/max(tmp(:))),'Parent',ax');
set(ax,'DataAspectRatio',[1 1 1],...
    'PlotBoxAspectRatioMode','auto','XDir','normal','YDir','normal',...
    'XTick',[],'YTick',[]);
title('Final Joint Histogram','Parent',ax);
xlabel(spm_file(VG.fname,'short22'),'Parent',ax,'Interpreter','none');
ylabel(spm_file(VF.fname,'short22'),'Parent',ax,'Interpreter','none');

% Display ortho-views
%--------------------------------------------------------------------------
spm_orthviews('Reset');
     spm_orthviews('Image',VG,[0.01 0.01 .48 .49]);
h2 = spm_orthviews('Image',VF,[.51 0.01 .48 .49]);
global st
st.vols{h2}.premul = inv(spm_matrix(x(:)'));
spm_orthviews('Space');

spm_print;


function P=compute_constraint_distance_3param_6eq_6unk(m1,m2,m3)

% Copyright (C) <2007>  <Francesc Moreno-Noguer, Vincent Lepetit, Pascal Fua>
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the version 3 of the GNU General Public License
% as published by the Free Software Foundation.
%
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
% General Public License for more details.
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Francesc Moreno-Noguer, CVLab-EPFL, September 2007.
% fmorenoguer@gmail.com, http://cvlab.epfl.ch/~fmoreno/

%redefine variables name, for compatibility with maple
m1_1=m1(1);
m1_2=m1(2);
m1_3=m1(3);
m1_4=m1(4);
m1_5=m1(5);
m1_6=m1(6);
m1_7=m1(7);
m1_8=m1(8);
m1_9=m1(9);
m1_10=m1(10);
m1_11=m1(11);
m1_12=m1(12);

m2_1=m2(1);
m2_2=m2(2);
m2_3=m2(3);
m2_4=m2(4);
m2_5=m2(5);
m2_6=m2(6);
m2_7=m2(7);
m2_8=m2(8);
m2_9=m2(9);
m2_10=m2(10);
m2_11=m2(11);
m2_12=m2(12);

m3_1=m3(1);
m3_2=m3(2);
m3_3=m3(3);
m3_4=m3(4);
m3_5=m3(5);
m3_6=m3(6);
m3_7=m3(7);
m3_8=m3(8);
m3_9=m3(9);
m3_10=m3(10);
m3_11=m3(11);
m3_12=m3(12);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

t1 = (m1_2 ^ 2);
t4 = (m1_6 ^ 2);
t5 = (m1_3 ^ 2);
t6 = (m1_5 ^ 2);
t11 = (m1_4 ^ 2);
t12 = (m1_1 ^ 2);
t20 = m1_4 * m2_4;
t21 = m1_3 * m2_3;
t22 = m1_5 * m2_5;
t23 = m1_2 * m2_2;
t24 = m1_6 * m2_6;
t25 = m1_1 * m2_1;
t26 = (-m2_4 * m1_1 - m2_5 * m1_2 - m2_6 * m1_3 - m1_6 * m2_3 - m1_4 * m2_1 - m1_5 * m2_2 + t20 + t21 + t22 + t23 + t24 + t25);
t27 = m1_6 * m3_6;
t29 = m1_5 * m3_5;
t30 = m1_4 * m3_4;
t33 = m1_3 * m3_3;
t35 = m1_1 * m3_1;
t38 = m1_2 * m3_2;
t39 = (t27 - m1_6 * m3_3 + t29 + t30 - m1_4 * m3_1 - m3_6 * m1_3 + t33 - m3_5 * m1_2 + t35 - m3_4 * m1_1 - m1_5 * m3_2 + t38);
t40 = (m2_4 ^ 2);
t41 = (m2_2 ^ 2);
t42 = (m2_5 ^ 2);
t43 = (m2_1 ^ 2);
t44 = (m2_6 ^ 2);
t45 = (m2_3 ^ 2);
t53 = m2_4 * m3_4;
t56 = m2_5 * m3_5;
t57 = m2_2 * m3_2;
t60 = m2_1 * m3_1;
t62 = m2_6 * m3_6;
t63 = m2_3 * m3_3;
t65 = (t53 - m2_4 * m3_1 - m3_4 * m2_1 + t56 + t57 - m2_5 * m3_2 - m2_6 * m3_3 + t60 - m3_6 * m2_3 + t62 + t63 - m3_5 * m2_2);
t66 = (m3_5 ^ 2);
t69 = (m3_4 ^ 2);
t70 = (m3_3 ^ 2);
t71 = (m3_2 ^ 2);
t72 = (m3_6 ^ 2);
t75 = (m3_1 ^ 2);
t81 = (m1_9 ^ 2);
t82 = (m1_8 ^ 2);
t83 = (m1_7 ^ 2);
t90 = m1_8 * m2_8;
t91 = m1_7 * m2_7;
t93 = m1_9 * m2_9;
t98 = (-m1_9 * m2_3 + t21 + t90 + t23 + t91 + t25 - m2_7 * m1_1 + t93 - m2_9 * m1_3 - m1_8 * m2_2 - m1_7 * m2_1 - m2_8 * m1_2);
t101 = m1_9 * m3_9;
t102 = m1_7 * m3_7;
t106 = m1_8 * m3_8;
t108 = (-m3_8 * m1_2 + t38 + t33 - m3_9 * m1_3 + t101 + t102 - m1_7 * m3_1 - m1_9 * m3_3 + t35 - m3_7 * m1_1 + t106 - m1_8 * m3_2);
t113 = (m2_8 ^ 2);
t116 = (m2_9 ^ 2);
t117 = (m2_7 ^ 2);
t119 = m2_8 * m3_8;
t122 = m2_9 * m3_9;
t125 = m2_7 * m3_7;
t128 = (t119 - m2_7 * m3_1 - m3_8 * m2_2 + t57 + t63 + t60 + t122 - m2_8 * m3_2 - m3_7 * m2_1 + t125 - m3_9 * m2_3 - m2_9 * m3_3);
t129 = (m3_7 ^ 2);
t130 = (m3_8 ^ 2);
t133 = (m3_9 ^ 2);
t141 = (m1_10 ^ 2);
t142 = (m1_11 ^ 2);
t143 = (m1_12 ^ 2);
t151 = m1_10 * m2_10;
t152 = m1_12 * m2_12;
t154 = m1_11 * m2_11;
t158 = (-m2_10 * m1_1 - m2_12 * m1_3 + t151 + t23 + t25 + t152 + t21 - m1_10 * m2_1 + t154 - m1_11 * m2_2 - m2_11 * m1_2 - m1_12 * m2_3);
t160 = m1_12 * m3_12;
t164 = m1_10 * m3_10;
t165 = m1_11 * m3_11;
t168 = (-m3_10 * m1_1 + t160 - m3_11 * m1_2 + t38 + t33 - m1_12 * m3_3 - m3_12 * m1_3 + t164 + t35 + t165 - m1_11 * m3_2 - m1_10 * m3_1);
t169 = (m2_12 ^ 2);
t170 = (m2_10 ^ 2);
t171 = (m2_11 ^ 2);
t179 = m2_10 * m3_10;
t181 = m2_12 * m3_12;
t185 = m2_11 * m3_11;
t188 = (t57 + t60 + t179 - m2_10 * m3_1 + t181 - m2_12 * m3_3 - m3_12 * m2_3 - m3_10 * m2_1 + t63 + t185 - m2_11 * m3_2 - m3_11 * m2_2);
t191 = (m3_12 ^ 2);
t192 = (m3_10 ^ 2);
t193 = (m3_11 ^ 2);
t212 = (t22 + t91 + t93 - m1_7 * m2_4 + t20 - m2_7 * m1_4 + t90 - m2_8 * m1_5 - m1_8 * m2_5 - m1_9 * m2_6 + t24 - m2_9 * m1_6);
t219 = (t101 + t30 - m3_9 * m1_6 - m3_8 * m1_5 - m1_8 * m3_5 - m3_7 * m1_4 + t27 - m1_9 * m3_6 - m1_7 * m3_4 + t102 + t106 + t29);
t233 = (t53 - m2_8 * m3_5 - m2_9 * m3_6 - m2_7 * m3_4 + t125 + t122 - m3_8 * m2_5 + t62 + t119 + t56 - m3_7 * m2_4 - m3_9 * m2_6);
t254 = (-m2_11 * m1_5 + t154 + t151 - m1_12 * m2_6 + t20 - m1_10 * m2_4 - m2_12 * m1_6 - m2_10 * m1_4 - m1_11 * m2_5 + t152 + t24 + t22);
t261 = (t30 - m3_12 * m1_6 - m1_10 * m3_4 - m1_11 * m3_5 + t160 + t27 + t164 + t165 - m3_11 * m1_5 - m3_10 * m1_4 - m1_12 * m3_6 + t29);
t275 = (-m3_10 * m2_4 + t56 - m2_10 * m3_4 + t62 - m3_12 * m2_6 - m2_11 * m3_5 + t53 - m3_11 * m2_5 - m2_12 * m3_6 + t179 + t181 + t185);
t296 = (-m2_12 * m1_9 + t152 + t91 + t90 - m1_11 * m2_8 + t151 - m2_11 * m1_8 + t93 - m1_10 * m2_7 - m1_12 * m2_9 - m2_10 * m1_7 + t154);
t303 = (t164 + t102 - m3_10 * m1_7 + t160 - m3_12 * m1_9 - m1_10 * m3_7 - m3_11 * m1_8 + t101 - m1_12 * m3_9 + t106 + t165 - m1_11 * m3_8);
t317 = (t125 + t119 - m3_12 * m2_9 - m3_10 * m2_7 - m2_11 * m3_8 - m3_11 * m2_8 + t122 + t179 - m2_12 * m3_9 + t181 - m2_10 * m3_7 + t185);
P(1,1) = t1 - 2 * m1_4 * m1_1 + t4 + t5 + t6 - 2 * m1_5 * m1_2 - 2 * m1_6 * m1_3 + t11 + t12;
P(1,2) = 2 * t26;
P(1,3) = 2 * t39;
P(1,4) = t40 + t41 + t42 + t43 + t44 + t45 - 2 * m2_5 * m2_2 - 2 * m2_6 * m2_3 - 2 * m2_4 * m2_1;
P(1,5) = 2 * t65;
P(1,6) = t66 - 2 * m3_4 * m3_1 + t69 + t70 + t71 + t72 - 2 * m3_6 * m3_3 + t75 - 2 * m3_5 * m3_2;
P(2,1) = -2 * m1_8 * m1_2 + t12 + t81 + t5 + t82 + t83 + t1 - 2 * m1_9 * m1_3 - 2 * m1_7 * m1_1;
P(2,2) = 2 * t98;
P(2,3) = 2 * t108;
P(2,4) = -2 * m2_8 * m2_2 - 2 * m2_9 * m2_3 + t113 - 2 * m2_7 * m2_1 + t116 + t117 + t41 + t43 + t45;
P(2,5) = 2 * t128;
P(2,6) = t75 + t70 + t129 + t71 + t130 - 2 * m3_9 * m3_3 + t133 - 2 * m3_8 * m3_2 - 2 * m3_7 * m3_1;
P(3,1) = -2 * m1_11 * m1_2 + t141 + t142 + t12 + t1 + t5 + t143 - 2 * m1_10 * m1_1 - 2 * m1_12 * m1_3;
P(3,2) = 2 * t158;
P(3,3) = 2 * t168;
P(3,4) = t169 + t41 + t43 + t45 + t170 + t171 - 2 * m2_12 * m2_3 - 2 * m2_10 * m2_1 - 2 * m2_11 * m2_2;
P(3,5) = 2 * t188;
P(3,6) = t71 - 2 * m3_12 * m3_3 + t75 + t191 + t70 + t192 + t193 - 2 * m3_10 * m3_1 - 2 * m3_11 * m3_2;
P(4,1) = -2 * m1_9 * m1_6 + t11 + t4 + t81 + t82 + t6 + t83 - 2 * m1_7 * m1_4 - 2 * m1_8 * m1_5;
P(4,2) = 2 * t212;
P(4,3) = 2 * t219;
P(4,4) = t117 + t113 - 2 * m2_8 * m2_5 - 2 * m2_7 * m2_4 - 2 * m2_9 * m2_6 + t116 + t40 + t42 + t44;
P(4,5) = 2 * t233;
P(4,6) = t129 - 2 * m3_9 * m3_6 + t69 + t66 + t72 + t133 - 2 * m3_8 * m3_5 - 2 * m3_7 * m3_4 + t130;
P(5,1) = t4 + t143 + t11 - 2 * m1_12 * m1_6 - 2 * m1_11 * m1_5 - 2 * m1_10 * m1_4 + t6 + t141 + t142;
P(5,2) = 2 * t254;
P(5,3) = 2 * t261;
P(5,4) = t170 + t171 + t169 - 2 * m2_10 * m2_4 - 2 * m2_11 * m2_5 - 2 * m2_12 * m2_6 + t40 + t42 + t44;
P(5,5) = 2 * t275;
P(5,6) = t69 + t66 + t72 - 2 * m3_12 * m3_6 - 2 * m3_10 * m3_4 + t193 - 2 * m3_11 * m3_5 + t192 + t191;
P(6,1) = t142 - 2 * m1_10 * m1_7 + t141 + t83 + t143 + t82 - 2 * m1_12 * m1_9 + t81 - 2 * m1_11 * m1_8;
P(6,2) = 2 * t296;
P(6,3) = 2 * t303;
P(6,4) = t171 + t170 - 2 * m2_12 * m2_9 - 2 * m2_10 * m2_7 - 2 * m2_11 * m2_8 + t113 + t169 + t116 + t117;
P(6,5) = 2 * t317;
P(6,6) = -2 * m3_11 * m3_8 + t193 + t133 + t129 + t192 + t130 - 2 * m3_12 * m3_9 + t191 - 2 * m3_10 * m3_7;


function weight = olmar1_kernel(data, weight_o, epsilon, W)
% This program output the final portfolio the OLMAR-1 algorithm
% OLMAR-1 has only one experts, thus, we go expert directly.
% If we want buy and hold, combine the experts here.
%
% function [weight] = olmar1_expert(data, weight_o, epsilon, W);
%
% weight: final portfolio, used for next rebalance
%
% data: market sequence vectors
% weight_o: last portfolio
% epsilon: mean reversion threshold
% W: window size for calculating moving average
%
% Example: [weight] = olmar1_expert(data, weight_o, epsilon, W);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of OLPS: http://OLPS.stevenhoi.org/
% Original authors: Bin LI, Steven C.H. Hoi
% Contributors:
% Change log:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

weight = olmar1_expert(data, weight_o, epsilon, W);

end


%% Copyright (C) 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 gammaln (@var{x})
%% @defmethodx @@sym lgamma (@var{x})
%% Symbolic logarithm of the gamma function.
%%
%% Example:
%% @example
%% @group
%% syms x
%% y = gammaln(x)
%%   @result{} y = (sym) loggamma(x)
%% y = lgamma(x)
%%   @result{} y = (sym) loggamma(x)
%% @end group
%% @end example
%%
%% @seealso{gammaln, @@sym/gamma, @@sym/psi}
%% @end defmethod

function y = lgamma(x)
  y = gammaln(x);
end

%!test
%! % tested by gammaln
%! assert (isequal (lgamma (sym ('x')), gammaln (sym ('x'))))


function [ y, next ] = p08_equil ( neqn, next )

%*****************************************************************************80
%
%% P08_EQUIL returns equilibrium solutions of problem p08.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NEQN, the number of equations.
%
%    Input, integer NEXT, the index of the previous
%    equilibrium, which should be 0 on first call.
%
%    Output, real Y(NEQN), the "next" equilibrium solution, if any.
%
%    Output, integer NEXT, the index of the current equilibrium,
%    or 0 if there are no more.
%

  if ( next == 0 )
    next = 1;
    y(1:neqn,1) = [ 0.0; 0.0; 0.0 ];
  else
    next = 0;
    y = [];
  end

  return
end


function [segclassifier] = mcmcTrainSegmentClassifier2(features, labels, weights, maxdata, classparams)

if exist('classparams') && ~isempty(classparams)
    nnodes = classparams(1);
    ntrees = classparams(2);
    stopval = classparams(3);
else
    ntrees = 20;
    nnodes = 8;
    stopval = 0;
end

if ~exist('maxdata') || isempty(maxdata)
    maxdata = 25000;
end

[data, lab, w] = formatData(features, labels, weights, maxdata);

segclassifier = train_boosted_dt_2c(data, [], lab, ntrees, nnodes, stopval, w);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [data, lab, w] = formatData(features, labels, weights, maxdata)
% concatenate data
%disp(num2str(maxdata))
nimages = numel(features);

[tmp, nvars] = size(features{1});

% count segments
tseg = 0;
nseg = 0;
for f = 1:nimages
    nseg = nseg + sum((labels{f}~=0) & (weights{f}>0));
    tseg = tseg + numel(labels{f});
end
%disp(num2str([nseg tseg]))

data = zeros(nseg, nvars);
lab = zeros(nseg, 1);
w = zeros(nseg, 1);

% concatenate data
vc = 0;
for f = 1:nimages
    ind = find((labels{f}~=0) & (weights{f}>0));
    data(vc+1:vc+numel(ind), :) = features{f}(ind, :);
    lab(vc+1:vc+numel(ind)) = (labels{f}(ind)>0)*2-1;
    w(vc+1:vc+numel(ind)) = weights{f}(ind); % weight according to area in image
    vc = vc + numel(ind);
end

if nseg > maxdata
    rind = randperm(nseg);
    rind = rind(1:maxdata);
    data = data(rind, :);
    lab = lab(rind);
    w = w(rind);
end

w = w / sum(w);


function [ matlabdatenum ] = rawjavacalendar2datenum( cal )
%   Converts a java.util.Calendar date local time into a Matlab datenum.
%   Keeps the original local time, does not try to convert to UTC.
    javaSerialDate = cal.getTimeInMillis() + cal.get(cal.ZONE_OFFSET) + cal.get(cal.DST_OFFSET);
    matlabdatenum = datenum([1970 1 1 0 0 javaSerialDate / 1000]);
end

%http://www.mathworks.co.uk/support/solutions/en/data/1-9B9H2S/index.html?product=ML&solution=1-9B9H2S


function check = semicircular_check ( a, b )

%*****************************************************************************80
%
%% SEMICIRCULAR_CHECK checks the parameters of the Semicircular CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, B, the parameter of the PDF.
%    0.0 < B.
%
  if ( b <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SEMICIRCULAR_CHECK - Fatal error!\n' );
    fprintf ( 1, '  B <= 0.0\n' );
    check = 0;
    return
  end

  check = 1;

  return
end


function doseStat = dispDoseStats(doseBinsV, volHistV, name, nameVol, planC, indexS, opt)
%Command line display of basic dose statistics
%doseBinsV is a vector of the midpoint doseBin values.
%volHistV is either a histogram of volumes or surface areas.
%LM: 14 Oct 02, JOD.
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

switch lower(opt)

  case 'standarddose'
    disp('-----------------------')
    disp('')
    disp(['Structure is:  ' name])

    totalVol = sum(volHistV);
    disp(['Total volume is:  ' num2str(totalVol) ' cubic cm.'])

    disp(['Dose map name is:  ' nameVol])

    meanD = sum(doseBinsV(:).*volHistV(:))/sum(volHistV);
    disp(['Mean dose is:  ' num2str(meanD)])

    ind = max(find([volHistV~=0]));
    maxD = doseBinsV(ind);
    disp(['Max dose is:  ' num2str(maxD)])

    ind = min(find([volHistV~=0]));
    minD = doseBinsV(ind);

    disp(['Min dose is:  ' num2str(minD)])
    disp('')
    disp('-----------------------')

    doseStat.volume = totalVol;

  case 'dshdose'

    disp('-----------------------')
    disp('')
    disp(['Structure is:  ' name])

    areaV = volHistV;  %actually areas, not volumes.
    dosesV = doseBinsV;

    totalArea = sum(areaV);
    disp(['Total surface area is:  ' num2str(totalArea) ' square cm.'])

    disp(['Dose map name is:  ' nameVol])

    meanD = sum(dosesV(:).*areaV(:))/sum(areaV);
    disp(['Mean surface dose is:  ' num2str(meanD)])

    maxD = max(dosesV);
    disp(['Max dose is:  ' num2str(maxD)])

    minD = min(dosesV);

    disp(['Min dose is:  ' num2str(minD)])
    disp('')
    disp('-----------------------')

    doseStat.volume = totalArea;

end

doseStat.min    = minD;
doseStat.mean   = meanD;
doseStat.max    = maxD;


function s=dIOU(pred,gt)
Ibox=In(pred,gt);
I=(Ibox.b-Ibox.t)*(Ibox.r-Ibox.l);
U=(pred.b-pred.t)*(pred.r-pred.l)+(gt.b-gt.t)*(gt.r-gt.l)-I;
dI=dIbox(pred,gt);
dU=dUbox(pred,gt);
s.dt=0;
s.db=0;
s.dl=0;
s.dr=0;
if Ibox.t<Ibox.b&&Ibox.l<Ibox.r&&U>0
    s.dt=(U*dI.dt-I*dU.dt)/U^2;
    s.db=(U*dI.db-I*dU.db)/U^2;
    s.dl=(U*dI.dl-I*dU.dl)/U^2;
    s.dr=(U*dI.dr-I*dU.dr)/U^2;
else
    s.dt=0;
    s.db=0;
    s.dl=0;
    s.dr=0;
end
if pred.t<pred.b
    s.dt=s.dt;
    s.db=s.db;
else
    s.dt=s.db;
    s.db=s.dt;
end
if pred.l<pred.r
    s.dl=s.dl;
    s.dr=s.dr;
else
    s.dl=s.dr;
    s.dr=s.dl;
end


%FIG_DESCI_CASSI_BIRD Demonstrate decompress snapshot compressive imaging
%(DeSCI) results of simulated coded aperture snapshot spectral imaging
%(CASSI) `bird` dataset.
% Note: Run this demonstration script after completing the reconstruction
%       process TEST_DESCI_CASSI_BIRD and obtaining the saved .mat file.
%   See also TEST_DESCI_CASSI_BIRD, GAPDENOISE_CACTI, GAPDENOISE.
clear; clc;
% close all
addpath('../'); % repository root
addpath(genpath('../packages/')); % packages
% [1] run the corresponding test file for recovery or load the saved
% results
% test_desci_cassi_bird; % run the corresponding test file for recovery
load('../results/savedmat/desci_cassi_bird.mat'); % load the saved results

methods   = {'gaptv','desci'}; % all methods for comparison
methnames = {'GAP-TV','DeSCI'}; % corresponding names of the methods
nim = nframe*nmask; % number of images

%% [2.1] demonstrate the reconstructed spectum
colors = {'Yellow bird', 'Green bird', 'Blue bird', 'Purple bird'}; % colors of the four birds
crops  =  [ 79 413 60 60;  % yellow [x y width height] as insertShape
           356 500 60 60;  % green
           780 460 60 60;  % blue
           950 600 60 60]; % purple
locos = {'southeast','southeast','southeast','northwest'};

markers   = {'bx--','r*-'}; % markers

linewidth = 2;
markersize = 4;
textfontsize = 14;
legendfontsize = 12;

% Change default axes fonts.
set(0,'DefaultAxesFontName','Arial');
set(0,'DefaultAxesFontSize',textfontsize);
set(0,'DefaultAxesFontWeight','normal');
% Change default text fonts.
set(0,'DefaultAxesFontName','Arial');
set(0,'DefaultTextFontSize',textfontsize);
set(0,'DefaultTextFontWeight','normal');

% legends
lgall = 'lgtruth';
lgtruth = 'Ground truth';
for imeth = 1:length(methods)
    meth = methods{imeth}; % method
    eval(sprintf('lg%s=''%s'';',meth,methnames{imeth}));
    lgall = [lgall ',lg' meth];
end

f = figure('position',[25 50 800 900]); % PSNR plot
h = tight_subplot(3,2,[0.07 0.08],[.07 .035],[.1 .02]);
axes(h(1));
imshow(insertShape(orig_rgb,'Rectangle',crops,'Color','cyan','Linewidth',8));
title('Original');
axes(h(2));
imshow(meas,[]);
title('Coded frame');
for ic = 1:length(colors)
    color = colors{ic};
    crop = crops(ic,:);
    sp_truth = squeeze(sum(sum(orig(crop(2):crop(2)+crop(4)-1,crop(1):crop(1)+crop(3)-1,:)/MAXB,2),1));
    axes(h(ic+2));
    plot(wavelength,sp_truth/max(sp_truth),'k-','linewidth',linewidth,'markersize',markersize); hold on;

    for imeth = 1:length(methods)
        meth = methods{imeth};
        eval(sprintf('sp_%s = squeeze(sum(sum(v%s(crop(2):crop(2)+crop(4)-1,crop(1):crop(1)+crop(3)-1,:),2),1));',meth,meth));
        eval(sprintf('plot(wavelength,rescale(sp_%s,min(sp_truth)/max(sp_truth),1),markers{imeth},''linewidth'',linewidth,''markersize'',markersize);',meth));
        eval(sprintf('corrall(ic,imeth)=corr(sp_%s,sp_truth);',meth));
        % legend with correlation
        eval(sprintf('lg%s=''%s, corr: %.5f'';',meth,methnames{imeth},corrall(ic,imeth)));
    end
    xlim([390 700]); xticks(400:100:700);
    title(color);
    if ic==3 || ic==4
        xlabel('Wavelength (nm)');
    end
    if ic==1 || ic==3
        ylabel('Intensity (a.u.)');
    end
    eval(sprintf('hlg=legend(%s);',lgall));
    set(hlg,'FontSize',legendfontsize);
    legend('location',locos{ic});
    legend('boxoff');
end

%% [2.2] show exemplar frames (wavelength)
bands = [9 11 16 21];

nb = length(bands);
nmeth = length(methods);
f = figure('Position',[50 50 1010 950]);
h = tight_subplot(nb,nmeth+1,[.002 .002],[.03 .03],[.02 .02]);
set(f, 'Color', 'white');
for ib = 1:nb
    band = bands(ib);
    lambda = wavelength(band);
    wlmap = (gray*kron(ones(3,1),spectrumRGB(lambda))); % colormap with the corresponding RGB wavelength
    wlmap = wlmap/max(wlmap(:));

    axes(h(1+(ib-1)*(nmeth+1)));
    imshow(orig(:,:,band)/MAXB,'colormap',wlmap);
    if ib==1
        title('Ground truth');
    end
    for imeth = 1:nmeth
        meth = methods{imeth};
        axes(h(imeth+1+(ib-1)*(nmeth+1)));
        eval(sprintf('imshow(v%s(:,:,band),''colormap'',wlmap);',meth));
        if ib==1
            title(sprintf('%s',methnames{imeth}));
        end
    end
end

%% [2.3] show all the frames wavelength-by-wavelength
%         via vshowSpectralData
addpath(genpath('../packages/'));

opts = [];
  opts.npcol      = 6; % number of columns for subplots
  % opts.magsize    = 0.7; % magnification of the image size
  opts.width      = 1080; % width of the plot
  opts.textpos    = [600 600]; % position of the text on the sub-images
  opts.fontname   = 'Myriad Pro'; % font name of the text on sub-images
  opts.fontsize   = 15; % fone size of the text on sub-images
  opts.fontweight = 'bold'; % font weight of the text on sub-images
% show ground truth
vshowSpectralData(orig/MAXB,wavelength,opts);
for imeth = 1:length(methods)
    meth = methods{imeth};
    eval(sprintf('vshowSpectralData(v%s,wavelength,opts);',meth));
end


function [cfg] = ft_spike_plot_isi(cfg, isih)

% FT_SPIKE_PLOT_ISI makes an inter-spike-interval bar plot.
%
% Use as
%   ft_spike_plot_isi(cfg, isih)
%
% Inputs:
%   ISIH is the output from FT_SPIKE_ISIHIST
%
% Configurations:
%   cfg.spikechannel     = string or index or logical array to to select 1 spike channel.
%                          (default = 1).
%   cfg.ylim             = [min max] or 'auto' (default)
%                          If 'auto', we plot from 0 to 110% of maximum plotted value);
%   cfg.plotfit          = 'yes' (default) or 'no'. This requires that when calling
%                          FT_SPIKESTATION_ISI, cfg.gammafit = 'yes'.
%
% Outputs:
%   hdl.fit              = handle for line fit. Use SET and GET to access.
%   hdl.isih             = handle for bar isi histogram. Use SET and GET to access.

% Copyright (C) 2010, Martin Vinck
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble provenance isih

% get the default options
cfg.spikechannel = ft_getopt(cfg,'spikechannel', 'all');
cfg.ylim         = ft_getopt(cfg,'ylim', 'auto');
cfg.plotfit      = ft_getopt(cfg,'plotfit', 'no');

% ensure that the options are valid
cfg = ft_checkopt(cfg,'spikechannel',{'cell', 'char', 'double'});
cfg = ft_checkopt(cfg,'ylim', {'char','ascendingdoublebivector'});
cfg = ft_checkopt(cfg,'plotfit', 'char', {'yes', 'no'});

% get the spikechannels
cfg.channel = ft_channelselection(cfg.spikechannel, isih.label);
spikesel    = match_str(isih.label, cfg.channel);
nUnits      = length(spikesel); % number of spike channels
if nUnits~=1, error('One spikechannel should be selected by means of cfg.spikechannel'); end

% plot the average isih
isiHdl = bar(isih.time,isih.avg(spikesel,:),'k');
set(isiHdl,'BarWidth', 1)

if strcmp(cfg.plotfit,'yes')

  if ~isfield(isih,'gamfit'), error('isih.gamfit should be present when cfg.plotfit = yes'); end

  % generate the probabilities according to the gamma model
  pGamma = gampdf(isih.time, isih.gamfit(spikesel,1), isih.gamfit(spikesel,2));
  sel    = isfinite(pGamma);
  pGamma = pGamma(sel)./sum(pGamma(sel));

  % scale the fit in the same way (total area is equal)
  sumIsih = sum(isih.avg(spikesel,:),2);
  pGamma  = pGamma*sumIsih;

  % plot the fit
  hold on
  fitHdl = plot(isih.time(sel), pGamma,'r');
else
  pGamma = 0;
end

try
  if strcmp(isih.cfg.outputunit, 'proportion')
    ylabel('probability')
  elseif strcmp(isih.cfg.outputunit, 'spikecount')
    ylabel('spikecount')
  end
catch
  ylabel('intensity');
end

xlabel('bin edges (sec)')

% set the x axis
set(gca,'XLim', [min(isih.time) max(isih.time)])

% set the y axis
if strcmp(cfg.ylim, 'auto')
  y = [isih.avg(spikesel,:) pGamma];
  cfg.ylim = [0 max(y(:))*1.1+eps];
end
set(gca,'YLim', cfg.ylim)
set(gca,'TickDir','out')

% store the handles
if strcmp(cfg.plotfit,'yes'),     H.fit    = fitHdl;    end
H.isih   = isiHdl;

% as usual, make sure that panning and zooming does not distort the y limits
set(zoom,'ActionPostCallback',{@mypostcallback,cfg.ylim,[min(isih.time) max(isih.time)]});
set(pan,'ActionPostCallback',{@mypostcallback,cfg.ylim,[min(isih.time) max(isih.time)]});

% do the general cleanup and bookkeeping at the end of the function

ft_postamble previous isih
ft_postamble provenance

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [] = mypostcallback(fig,evd,limY,limX)

% get the x limits and reset them
ax = evd.Axes;
xlim = get(ax(1), 'XLim');
ylim = get(ax(1), 'YLim');
if limX(1)>xlim(1), xlim(1) = limX(1); end
if limX(2)<xlim(2), xlim(2) = limX(2); end
if limY(1)>ylim(1), ylim(1) = limY(1); end
if limY(2)<ylim(2), ylim(2) = limY(2); end

set(ax(1), 'XLim',xlim)
set(ax(1), 'YLim',ylim);