  function sh = de_ftab_s_iter(fit, fh, varargin)
%|function sh = de_ftab_s_iter(fit, fh, [options])
%| estimate s from fh by iterative LS
%| sh = argmin{s} | fh - fm(s) |^2
%| in
%|	fit			from de_ftab_fit() / de_ftab_curv()
%|	fh	[(Nd) M]	estimates of f (nonlinear BH function)
%| option
%|	'niter'			# of iterations (default: 1 - not enough!)
%|				(if 0, then just initial estimate returned)
%|	'init'	[(Nd) L]	initial estimates (default: linear inverse)
%|	'ctype'	char		curvature type (see de_ftab_curv.m)
%|				default '': inherit from de_ftab_curv.m
%| out
%|	sh	[(Nd) L]	estimates of s (component density integrals)
%|
%| Copyright 2006-05-21, Jeff Fessler, University of Michigan

if nargin == 1 && streq(fit, 'test'), de_ftab_s_iter_test, return, end
if nargin < 2, ir_usage, end

arg.ctype = '';
arg.niter = 1;
arg.init = [];
arg.strue = []; % optional for testing
arg.nprint = 100; % every 100th iteration show rms
arg = vararg_pair(arg, varargin);

LL = fit.LL;
Nd = size(fh); MM = Nd(end); Nd = Nd(1:end-1);
fh = reshapee(fh, [], MM); % [*Nd M]
if MM ~= fit.MM, error 'M', end

if ~isempty(arg.strue)
	arg.strue = reshapee(arg.strue, prod(Nd), LL); % [*Nd L]
end

% initialize
if isempty(arg.init)
	sh = (pinv(fit.mac_eff) * fh')'; % linear inverse (perfect if mono)

	if ~isempty(arg.strue)
		pr 'rms(sh - arg.strue)' % report initial error, for testing!
	end
else
	sh = max(arg.init, 0);
	sh = reshape(sh, prod(Nd), LL); % [*Nd L]
end

if arg.niter < 1, return, end

% curvature
switch arg.ctype
case ''
%	fstep = @(sh, fm, fh) 1 ./ sum(fit.curv2(sh, fm, fh), 2); % [*Nd 1]
	fstep = @(sh, fm, fh) 1 ./ sum(fit.ls_curv(sh, fh, fm), 2); % [*Nd 1]

case 'old'
	[curv1 curv2] = de_ftab_curv_ub(fit); % each is [MM 1]
	fcurv2 = @(fm, fh) max(fh - fm, 0) * curv2; % [*Nd M] * [M 1] -> [*Nd 1]
%	fcurv2 = @(fm, fh) max(fh, 0) * curv2; % [*Nd M] * [M 1] -> [*Nd 1] TOO SLOW!?
	fstep = @(sh, fm, fh) 1 ./ (sum(curv1) + fcurv2(fm, fh)); % [*Nd 1]
	step = fstep(0, 0, fh); % [*Nd 1] precomputed!
	minmax(step)
	step = repmat(step, [1 LL]);

otherwise
	fstep = @(sh, fm, fh) 1 ./ ...
		sum(fit.ls_curv(sh, fh, fm, 'ctype', arg.ctype), 2); % [*Nd 1]
%	fail('bad ctype: %s', arg.ctype)
end

ticker reset
for ii=1:arg.niter % iterate
	ticker(mfilename, ii, arg.niter)

	fm = fit.fmfun(sh); % [*Nd M]
%	cost = mean(col(fh - fm).^2);

	if 1
		fgrad = fit.fgrad(sh); % [*Nd L M]
		tmp = repmat(fh - fm, [1 1 LL]); % [*Nd M L]
		tmp = permute(tmp, [1 3 2]); % [*Nd L M]
		fgrad = fgrad .* tmp;
	else
%		fgrad = fit.ls_grad(fh, sh);
	end

	step = fstep(sh, fm, fh); % [*Nd 1]
	step = repmat(step, [1 LL]); % [*Nd L]
%	minmax(step)
	sh = sh + step .* sum(fgrad, 3);

	if ~isempty(arg.strue) && (~rem(ii, arg.nprint) || ii==arg.niter)
		pr 'rms(sh - arg.strue)' % report error, for testing!
	end
end

sh = reshapee(sh, Nd, LL); % [(Nd) L]

% de_ftab_curv_ub()
% curv* are [M 1] upper bounds
%
function [curv1, curv2] = de_ftab_curv_ub(fit)

MM = fit.MM;
new = fit.fgrad(zeros([1 fit.LL])); % [1 L M]
curv1 = squeeze(sum(new.^2,2)); % [1 1 M] -> [M 1]

neghess = -fit.fhess(zeros([1 fit.LL])); % [1 L L M]
curv2 = zeros(MM,1);
for mm=1:MM
	h0 = squeeze(neghess(1,:,:,mm)); % [1 L L 1] -> [L L]
	curv2(mm) = norm(h0);
end

return

% old way:

oldcurv1 = zeros(MM,1);
oldcurv2 = zeros(MM,1);

for mm=1:MM
	alf = fit.coef{mm}; % [ne 1]
	mac = fit.mac{mm}; % [ne L]
	g0 = mac' * alf; % gradient of fit at s=0 (largest point)
	h0 = mac' * diag(alf) * mac - g0 * g0'; % hessian at s=0 (largest?)
	oldcurv1(mm) = norm(g0)^2;
	oldcurv2(mm) = norm(h0);
end

equivs(curv1, oldcurv1)
equivs(curv2, oldcurv2)

% de_ftab_s_iter_test1
% L=1 M=1 case for sanity checking
%
function de_ftab_s_iter_test1
stype = 'ps1';
stype = 'poly1,100';
xrs = xray_read_spectra(stype);
mtype = 'water';
mas = xray_read_mac(mtype);
s1 = linspace(0, 50, 26)';
fm = de_ftab_fm(s1, mas.mac(xrs.en), xrs.Ide);
fit = de_ftab_fit({s1}, fm, 'type', 'exp', 'mtype', mtype);
ctype = 'newt';
%ctype = 'pre10'; % slow!
fit = de_ftab_curv(fit, 'ctype', ctype);

%fm = fit.fmfun(s1); % test with model fm, not original

% iterate
sh = de_ftab_s_iter(fit, fm, 'strue', s1, 'ctype', '', ...
	'niter', 5, 'nprint', 1);

if im
	clf, plot(s1, s1, 'c-', s1, sh, 'y.-')
	grid, axis equal, axis square
	xlabel 'true', ylabel 'noiseless estimate'
	title(fit.ctype)
prompt
end

% de_ftab_s_iter_test2
%
function de_ftab_s_iter_test2
sl{1} = linspace(0, 50, 26);
sl{2} = linspace(0, 30, 31);
xrs = xray_read_spectra('ps1');
mtype = {'water', 'bone'};
mtype = {'water', 'aluminum'};
mas = xray_read_mac(mtype);
sll = ndgrid_jf('mat', sl{:});
fm = de_ftab_fm(sll, mas.mac(xrs.en), xrs.Ide);
fit = de_ftab_fit(sl, fm, 'type', 'exp', 'mtype', mtype);
fit = de_ftab_curv(fit, 'ctype', 'newt');
%fit = de_ftab_curv(fit, 'ctype', 'pre2');

fm = fit.fmfun(sll); % test with model fm, not original

if 1 % initialize with polynomial inverse
	mac = xray_make_mac(xrs, mas);
	T = pinv(mac.bar);
	inv2 = de_ftab_inv2(fit, sl, 'T', T);
	s0 = inv2.fun(fm);
	s0 = reshapee(s0, [], 2);
else
	% initializing with linear inv.
	s0 = de_ftab_s_iter(fit, fm, 'niter', 0);
end

strue = reshapee(sll, [], 2); % true
pr rms(s0 - strue) % initial error - large!

if 1 % picture of error of initial guess vs (s_1,s_2)
	pr fit.mac_eff
	pr cond(fit.mac_eff)
	tmp = reshape(sqrt(mean((s0 - strue).^2, 2)), size(sll(:,:,1)));
	if im
		clf, im(sl{:}, tmp), cbar % error is smallest at (0,0)
		xlabel(mtype{1}), ylabel(mtype{2})
	end
prompt
end

% todo: run profiler, or pre-tabulate the inverse...
% iterate; initializing with linear inv.
sh = de_ftab_s_iter(fit, fm, 'init', s0, 'niter', 90, ...
		'strue', sll, 'nprint', 10);
pr 'rms(reshapee(sh, [], 2) - strue)'

%sh = reshape(sh, size(sll));
if im
	clf, plot(sl{1}, sh(:,:,1), 'c', sl{2}, sh(:,:,2), 'y')
	grid, axis equal, axis square
	xlabel 'true', ylabel 'noiseless estimate'
prompt
%	plot(fm(:,:,1), fm(:,:,2), '.')
end

% de_ftab_s_iter_test
%
function de_ftab_s_iter_test
de_ftab_s_iter_test2
de_ftab_s_iter_test1


function [Y] = mci_ramsay_gen (P,M,U)
% Generate data from Ramsay model
% FORMAT [Y] = mci_ramsay_gen (P,M,U)
%
% P         Parameters
% M         Model structure
% U         Inputs
%
% Y         Data
%__________________________________________________________________________
% Copyright (C) 2015 Wellcome Trust Centre for Neuroimaging

% Will Penny
% $Id: mci_ramsay_gen.m 6548 2015-09-11 12:39:47Z will $

[G,x] = spm_mci_fwd (P,M,U);
[N,l] = size(G);
e = randn(N,l)*sqrt(M.Ce);
Y = G + e;


function pass = test_repeatedArithmetic(pref)

if ( nargin < 1 )
    pref = chebfunpref();
end
tol = 1e4*pref.cheb3Prefs.chebfun3eps;

% Add 50 functions together:
f = chebfun3(@(x,y,z) cos(x.*y.*z));
g = chebfun3(0);
for jj = 1:50
    g = g + f;
end
pass(1) = norm(g - 50*f ) < 10 * tol;

% Multiply 10 functions together:
f = chebfun3(@(x,y,z) cos(x.*y.*z));
g = f;
for jj = 1:10
    g = g .* f;
end
pass(2) = norm(g - f.^11) < tol;

% Multiply 10 functions together by calling the constructor in different
% ways:
f = chebfun3(@(x,y,z) cos(x.*y.*z));
g = f;
for jj = 1:10
    g = chebfun3(@(x,y,z) g(x,y,z) .* f(x,y,z));
end
pass(3) = norm(g - f.^11) < tol;

g = f;
for jj = 1:10
    g = chebfun3(@(x,y,z) g(x,y,z) .* f(x,y,z), 'fiberDim', 1);
end
pass(4) = norm(g - f.^11) < tol;

g = f;
for jj = 1:10
    g = chebfun3(@(x,y,z) g(x,y,z) .* f(x,y,z), 'fiberDim', 2);
end
pass(5) = norm(g - f.^11) < tol;

g = f;
for jj = 1:10
    g = chebfun3(@(x,y,z) g(x,y,z) .* f(x,y,z), 'fiberDim', 3);
end
pass(6) = norm(g - f.^11) < tol;

% Multiply 20 functions together:
f = chebfun3(@(x,y,z) sin(x.*y.*z));
g = f;
for jj = 1:20
    g = g .* f;
end
pass(7) = norm(g - f.^21) < tol;

% Multiply 20 functions together:
f = chebfun3(@(x,y,z) sin(x.*y.*z));
g = f;
for jj = 1:20
    g = chebfun3(@(x,y,z) g(x,y,z) .* f(x,y,z));
end
pass(8) = norm(g - f.^21) < tol;

end


classdef CEC2008_F4 < PROBLEM
% <single> <real> <large/none> <expensive/none>
% Shifted Rastrign's function

%------------------------------- Reference --------------------------------
% K. Tang, X. Yao, P. N. Suganthan, C. MacNish, Y.-P. Chen, C.-M. Chen, and
% Z. Yang, Benchmark functions for the CEC'2008 special session and
% competition on large scale global optimization, Nature Inspired
% Computation and Applications Laboratory, USTC, China, 2007.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    properties
        O;  % Optimal decision vector
    end
    methods
        %% Default settings of the problem
        function Setting(obj)
            CallStack = dbstack('-completenames');
            load(fullfile(fileparts(CallStack(1).file),'CEC2008.mat'),'Data');
            obj.O = Data{4};
            obj.M = 1;
            if isempty(obj.D); obj.D = 100; end
            obj.D = min(obj.D,length(obj.O));
            obj.lower    = zeros(1,obj.D) - 5;
            obj.upper    = zeros(1,obj.D) + 5;
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,PopDec)
            Z = PopDec - repmat(obj.O(1:size(PopDec,2)),size(PopDec,1),1);
            PopObj = sum(Z.^2-10*cos(2*pi*Z)+10,2);
        end
    end
end


function [T,TI,E] = polygons_to_triangles(PI,PC)
  % POLYGONS_TO_TRIANGLES Given a polygonal mesh, replace each polygon with a
  % fan of triangles.
  %
  % [T,TI,E] = polygons_to_triangles(PI,PC)
  %
  % Inputs:
  %   PI  #PI stream of polygon indices into rows of some V
  %   PC  #polys+1 list of cumulative sum of dual face valences
  % Outputs:
  %   T  #T by 3 list of triangle indices into rows of V
  %   TI  #TI list of indices into input faces (1:#polys)
  %   E  #E by 2 list of edge indices into rows of V
  %
  % See also: dual
  I1 = repelem(PI(PC(1:end-1)+1),diff(PC)-2);
  I2 = PI;
  % remove first and last entries
  I2([PC(1:end-1)+1;PC(2:end)]) = [];
  I3 = PI;
  % remove first two entries
  I3([PC(1:end-1)+1;PC(1:end-1)+2]) = [];
  T = [I1 I2 I3];
  TI = repelem(1:numel(PC)-1,diff(PC)-2);
  if nargout>2
    I1 = PI;
    % order index per polygon
    Pj = [(1:numel(PI))' - repelem(PC(1:end-1),diff(PC))];
    % increment by one mod size
    Pj = mod(Pj,repelem(diff(PC),diff(PC)))+1;
    I2 = PI(repelem(PC(1:end-1),diff(PC)) + Pj);
    E = [I1 I2];
  end
end


function out=sech(x)

out=1./cosh(x);


function ind = contributingVoxels(pos)
%CONTRIBUTINGVOXELS  find indices of voxels not on image border
%
%   usage :
%   IND = contributingVoxels(POS)
%   where POS is a number between 1 and 27 indicating position of tile with
%   respect to image borders
%   and IND is an array of indices, giving only voxels which are not
%   located on the border of image.
%

% get position wrt edges of image
% if pk==1 -> config is on lower bounds in direction k
% if pk==2 -> config is in the middle of the 2 bounds
% if pk==3 -> config is on greater bound in direction k
pz = floor((pos-1)/9)+1;
pos2 = pos-9*(pz-1);
py = floor((pos2-1)/3)+1;
px = pos2-3*(py-1);

% Flags are set to one for contributions which should be computed
% If configuration is on the edge of image, the contributions of some
% vertices are not computed
flags = ones(1,8);
if px==1; flags([1 3 5 7]) = 0; end
if px==3; flags([2 4 6 8]) = 0; end
if py==1; flags([1 2 5 6]) = 0; end
if py==3; flags([3 4 7 8]) = 0; end
if pz==1; flags([1 2 3 4]) = 0; end
if pz==3; flags([5 6 7 8]) = 0; end

% get indices of pixels whose contribution will be computed
ind = find(flags);


function pass = test_diag(pref)
% Test for CHEBFUN/DIAG()

if ( nargin < 1 )
    pref = chebfunpref();
end

%% Test a few things
% No breakpoints
x = chebfun(@(x) x, [-1 6]);
tol = 1e-15;
f = sin(x);
g = cos(4*x);

D = diag(f);
err = norm(D*g -f.*g);
pass(1) = ( err < tol );

%% Breakpoints in g
x = chebfun(@(x) x, [-1 4 6]);
g = cos(4*x);
err = norm(D*g -f.*g);
pass(2) = ( err < tol );

%% Breakpoints in f and g
x = chebfun(@(x) x, [-1 4 6]);
f = sin(x);
g = cos(4*x);
err = norm(D*g -f.*g);
pass(3) = ( err < 10*tol );

end


function nurbs = nrbtform(nurbs,tmat)
%
% Function Name:
%
%   nrbtform - Apply transformation matrix to the NURBS.
%
% Calling Sequence:
%
%   tnurbs = nrbtform(nurbs,tmatrix);
%
% Parameters:
%
%   nurbs	: NURBS data structure (see nrbmak for details).
%
%   tmatrix     : Transformation matrix, a matrix of size (4,4) defining
%                 a single or multiple transformations.
%
%   tnurbs	: The return transformed NURBS data structure.
%
% Description:
%
%   The NURBS is transform as defined a transformation matrix of size (4,4),
%   such as a rotation, translation or change in scale. The transformation
%   matrix can define a single transformation or multiple series of
%   transformations. The matrix can be simple constructed by the functions
%   vecscale, vectrans, vecrotx, vecroty, and vecrotz.
%
% Examples:
%
%   Rotate a square by 45 degrees about the z axis.
%
%   rsqr = nrbtform(nrbrect(), vecrotz(deg2rad(45)));
%   nrbplot(rsqr, 10);
%
% See:
%
%   vecscale, vectrans, vecrotx, vecroty, vecrotz

%  D.M. Spink
%  Copyright (c) 2000

if nargin < 2
  error('Not enough input arguments!');
end;

if iscell(nurbs.knots)
  % NURBS is a surface
  [dim,nu,nv] = size(nurbs.coefs);
  nurbs.coefs = reshape(tmat*reshape(nurbs.coefs,dim,nu*nv),[dim nu nv]);
else
  % NURBS is a curve
  nurbs.coefs = tmat*nurbs.coefs;
end


function output = F_weighting(input, weight, bias)
[dim, N] = size(input);
nWeight = length(weight);
D = dim/nWeight;

input2 = reshape(input, D, nWeight, N);
input2 = permute(input2, [2 1 3]);

output = sum(bsxfun(@times, input2, weight));

if N==1
    output = output';
else
    output = permute(output, [2 3 1]);
end

output = bsxfun(@plus, output, bias);

end


classdef nnhuberloss < nntest
  methods (Test)

    function basic(test)
      x = test.randn([100 1]) ;
      t = test.randn([100 1]) ;
      y = vl_nnhuberloss(x, t) ;

      % check derivatives with numerical approximation
      dzdy = test.randn(size(y)) ;
      dzdx = vl_nnhuberloss(x, t, dzdy) ;
      test.der(@(x) vl_nnhuberloss(x, t), x, dzdy, dzdx, 1e-3*test.range) ;
    end

    function basicWithInstanceWeights(test)
      x = test.randn([100 1]) ;
      t = test.randn([100 1]) ;
      w = test.randn([100 1]) ;
      y = vl_nnhuberloss(x, t, 'instanceWeights', w) ;

      % check derivatives with numerical approximation
      dzdy = test.randn(size(y)) ;
      dzdx = vl_nnhuberloss(x, t, dzdy, 'instanceWeights', w) ;
      test.der(@(x) vl_nnhuberloss(x, t, 'instanceWeights', w), x, ...
                                        dzdy, dzdx, 1e-3*test.range) ;
    end

  end
end


function Cy = computeCy(ny,n_state)
    Cy_tmp1 = cell(ny,ny);
    Cy_tmp2 = cell(ny,ny );
    %Avant 5 a la place de 7
    for i=1:ny
       for j=1:ny
          if i==j
              Cy_tmp1{i,j} = eye(n_state);
              Cy_tmp2{i,j} = -eye(n_state);
          else
              Cy_tmp1{i,j} = zeros(n_state,n_state);
              Cy_tmp2{i,j} = zeros(n_state,n_state);
          end
       end
    end

    Cy = [cell2mat(Cy_tmp1);cell2mat(Cy_tmp2)];
end


close all; clear all; clc;
% Create the directory for storing results
spx.fs.ensure_dir('bin');

h = spx.data.motion.Hopkins155;
ne = h.num_examples;
fprintf('Number of sequences: %d\n', ne);

motion3 = 0;
motion2 = 0;
tstart = tic;
% pre-load all examples
h.load_all_examples();
h.describe();
examples = h.get_2_3_motions();
ne = length(examples);
fprintf('Number of 2, 3 motions: %d\n', ne);
for i=1:ne
    fprintf('Example (%d): ', i);
    example = examples{i};
    fprintf('%s, %d motions, %d points, %d frames;', example.name, example.num_motions, example.num_points, example.num_frames);
    switch example.num_motions
        case 2
            motion2 = motion2 + 1;
        case 3
            motion3 = motion3 + 1;
        otherwise
            error('Invalid number of motions.');
    end
    fprintf(' counts: ');
    fprintf('%d ', example.counts);
    [start_indices, end_indices] = spx.cluster.start_end_indices(example.counts);
    % The dataset
    X = example.X;
    fprintf(' effective rank: ');
    for k=1:example.num_motions
        ss = start_indices(k);
        ee = end_indices(k);
        XX = X(:, ss:ee);
        singular_values  = svd(XX, 'econ')';
        r = spx.la.svd.mahdi_rank(singular_values);
        fprintf('%d,  ', r);
    end
    fprintf('\n');

end
elapsed = toc(tstart);
fprintf('Time taken: %.2f seconds \n', elapsed);
fprintf('3 motions: %d\n', motion3);
fprintf('2 motions: %d\n', motion2);


% LFConvertToFloat - Helper function to convert light fields to floating-point representation
%
% Usage:
%     LF = LFConvertToFloat( LF, [Precision] )
%
% For float inputs, this converts between single and double without changes in scale. For integer
% inputs, the full input precision's range is mapped to a floating point range 0.0-1.0.
%
% Inputs:
%
%    LF :  Must be of type single, double, uint8, or uint16
%
% Optional Inputs:
%
%    Precision : one of 'single' or 'double', default 'single'
%
% Outputs:
%
%    LF : the converted LF
%
% User guide: LFToolbox.pdf
% See also: LFConvertToInt

% Copyright (c) 2013-2020 Donald G. Dansereau

function LF = LFConvertToFloat( LF, Precision )

Precision = LFDefaultVal('Precision', 'single');

OrigClass = class(LF);

if( strcmp( OrigClass, Precision ) )

	% already in the right precision, nothing to do

else
	IsInt = isinteger(LF);

	LF = cast(LF, Precision);

	if( IsInt )
		LF = LF ./ cast(intmax(OrigClass), Precision);
	end

end


function [ptheta] = tapas_sem_prosa_ptheta()
%% Returns the standard priors of the model.
%
% Input
%
% Output
% ptheta -- Structure containing the priors. The prior distribution is assumed
%           to be log Gaussian, so that the prior are the means and covariance
%           matrix. It is assumed that the covariance is diagonal so only the
%           eigenvalues are returned. ptheta.jm is a projection matrix. It can
%           be replaced with a rank deficient matrix in order to project the
%           samples to a lower dimensional space.

%
% aponteeduardo@gmail.com
% copyright (C) 2015
%

DIM_THETA = tapas_sem_prosa_ndims();
[ptheta] = tapas_sem_prosa_gaussian_priors();

% Projection matrix
ptheta.jm = eye(DIM_THETA);

% Likelihood function and priors

ptheta.name = 'prosa';
ptheta.llh = [];
ptheta.lpp = @tapas_sem_prosa_lpp;
ptheta.prepare = @tapas_sem_prepare_gaussian_ptheta;
ptheta.sample_priors = @tapas_sem_sample_gaussian_uniform_priors;
ptheta.ndims = tapas_sem_prosa_ndims();
ptheta.npars = 2; % It has two sets of parameters.

end


function [bnet, Unode, Snode, Lnodes, Rnode, Ynode, Lsnode] = ...
    mk_gmux_robot_dbn(nlandmarks, Q, R, init_x, init_V, robot_block, landmark_block)

% Make DBN

% S
% | L1 -------> L1'
% |  | L2 ----------> L2'
% \  | /
%  v v v
%    Ls
%    |
%    v
%    Y
%    ^
%    |
%    R ------->  R'
%    ^
%    |
%    U
%
%
% S is a switch, Ls is a deterministic gmux, Y = Ls-R,
% R(t+1) = R(t) + U(t+1), L(t+1) = L(t)

% number nodes topologically
Snode = 1;
Lnodes = 2:nlandmarks+1;
Lsnode = nlandmarks+2;
Unode = nlandmarks+3;
Rnode = nlandmarks+4;
Ynode = nlandmarks+5;

nnodes = nlandmarks+5;
intra = zeros(nnodes, nnodes);
intra([Snode Lnodes], Lsnode) =1;
intra(Unode,Rnode)=1;
intra([Rnode Lsnode], Ynode)=1;

inter = zeros(nnodes, nnodes);
inter(Rnode, Rnode)=1;
for i=1:nlandmarks
  inter(Lnodes(i), Lnodes(i))=1;
end

Lsz = 2; % (x y) posn of landmark
Rsz = 2; % (x y) posn of robot
Ysz = 2; % relative distance
Usz = 2; % (dx dy) ctrl
Ssz = nlandmarks; % can switch between any landmark

ns = zeros(1,nnodes);
ns(Snode) = Ssz;
ns(Lnodes) = Lsz;
ns(Lsnode) = Lsz;
ns(Ynode) = Ysz;
ns(Rnode) = Rsz;
ns(Ynode) = Usz;
ns(Unode) = Usz;

bnet = mk_dbn(intra, inter, ns, 'discrete', Snode, 'observed', [Snode Ynode Unode]);

bnet.CPD{Snode} = root_CPD(bnet, Snode); % always observed
bnet.CPD{Unode} = root_CPD(bnet, Unode); % always observed
for i=1:nlandmarks
  bi = landmark_block(:,i);
  bnet.CPD{Lnodes(i)} = gaussian_CPD(bnet, Lnodes(i), 'mean', init_x(bi), 'cov', init_V(bi,bi));
end
bi = robot_block;
bnet.CPD{Rnode} = gaussian_CPD(bnet, Rnode, 'mean', init_x(bi), 'cov', init_V(bi,bi), 'weights', eye(2));
bnet.CPD{Lsnode} = gmux_CPD(bnet, Lsnode, 'cov', repmat(zeros(Lsz,Lsz), [1 1 nlandmarks]), ...
			    'weights', repmat(eye(Lsz,Lsz), [1 1 nlandmarks]));
W = [eye(2) -eye(2)]; % Y = Ls - R, where Ls is the lower-numbered parent
bnet.CPD{Ynode} = gaussian_CPD(bnet, Ynode, 'mean', zeros(Ysz,1), 'cov', R, 'weights', W);

% slice 2
eclass = bnet.equiv_class;
W = [eye(2) eye(2)]; % R(t) = R(t-1) + U(t), where R(t-1) is the lower-numbered parent
bnet.CPD{eclass(Rnode,2)} = gaussian_CPD(bnet, Rnode+nnodes, 'mean', zeros(Rsz,1), 'cov', Q, 'weights', W);
for i=1:nlandmarks
  bnet.CPD{eclass(Lnodes(i), 2)} = gaussian_CPD(bnet, Lnodes(i)+nnodes, 'mean', zeros(2,1), ...
						   'cov', zeros(2,2), 'weights', eye(2));
end


function [xV,yV,zV] = mtoxyz_Dose(rV,cV,sV,planC,doseNum)
%"mtoxyz_Dose"
%   Convert from rcs coordinates to xyz coordinates, in the nonuniformized
%   dataset.
%
%   if flag = 'uniform', uses the uniformized data.
%
%   JRA 07/15/04
%
%Usage:
%   [xV,yV,zV] = mtoxyz_Dose(rV,cV,sV,planC,doseNum)
%
% 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/>.

indexS = planC{end};
 [xVals, yVals, zVals] = getDoseXYZVals(planC{indexS.dose}(doseNum));

 xV = interp1(1:length(xVals), xVals, cV, 'linear', 'extrap');
yV = interp1(1:length(yVals), yVals, rV, 'linear', 'extrap');
zV = interp1(1:length(zVals), zVals, sV, 'linear', 'extrap');
return;


function [cell_metrics] = bz_CellMetricsSimple(spikes,sr)
% [cell_metrics] = bz_CellMetricsSimple(spikes,sr)
%   Calculate waveform and ACG metrics to use for unit classification
%
% USAGE
%
%   [cell_metrics] = bz_CellMetricsSimple(spikes)
%
% INPUTS
%
%   spikes = buzcode spikes structure (i.e. from bz_LoadPhy)
%   sr = sampling rate
%
% OUTPUT
%
%   cell_metrics
%       .filtWaveform
%       .rawWaveform
%           .PeaktoTrough
%           .TroughtoPeak
%           .AB_ratio
%           .trough
%       .refractory
%       .burstRoyer
%       .burstiness
%       .FR

% Antonio FR, 11/2018

if ~isnumeric(sr)
    sr = 30000;
end

%% waveform metrics
   % reshape data
   for i = 1:length(spikes.rawWaveform)
       rawWaveforms(i,:) = spikes.rawWaveform{i};
       filtWaveforms(i,:) = spikes.filtWaveform{i};
   end

   wave = [];t_before = [];t_after = [];peakA = [];peakB = [];trough = [];
   for m = 1:size(rawWaveforms,1)
        wave = interp1([1:size(filtWaveforms,2)],zscore(filtWaveforms(m,:)),[1:0.5:size(filtWaveforms,2),size(filtWaveforms,2)],'spline');
        midPoint = round((length(wave)/2));
        [MIN2,I2] = min(wave(midPoint-10:midPoint+10));
        [MAX3,I3] = max(wave(1:midPoint));
        [MAX4,I4] = max(wave((I2+midPoint-11):end));
        t_before(m) = (I2+midPoint-11)-I3;
        t_after(m) = I4;
        peakA(m) = MAX3;
        peakB(m) = MAX4;
        trough(m) = MIN2;
        clear MIN2 MAX3 MAX4 I2 I3 I4
   end
    cell_metrics.filtWaveform.PeaktoTrough = (t_before/(sr*2))';
    cell_metrics.filtWaveform.TroughtoPeak = (t_after/(sr*2))';
    cell_metrics.filtWaveform.AB_ratio = ((peakB-peakA)./(peakA+peakB))';
    cell_metrics.filtWaveform.trough = (trough)';

   wave = [];t_before = [];t_after = [];peakA = [];peakB = [];trough = [];
   for m = 1:size(rawWaveforms,1)
        wave = interp1([1:size(rawWaveforms,2)],zscore(rawWaveforms(m,:)),[1:0.5:size(rawWaveforms,2),size(rawWaveforms,2)],'spline');
        midPoint = round((length(wave)/2));
        [MIN2,I2] = min(wave(midPoint-10:midPoint+10));
        [MAX3,I3] = max(wave(1:midPoint));
        [MAX4,I4] = max(wave((I2+midPoint-11):end));
        t_before(m) = (I2+midPoint-11)-I3;
        t_after(m) = I4;
        peakA(m) = MAX3;
        peakB(m) = MAX4;
        trough(m) = MIN2;
        clear MIN2 MAX3 MAX4 I2 I3 I4
   end
    cell_metrics.rawWaveform.PeaktoTrough = (t_before/(sr*2))';
    cell_metrics.rawWaveform.TroughtoPeak = (t_after/(sr*2))';
    cell_metrics.rawWaveform.AB_ratio = ((peakB-peakA)./(peakA+peakB))';
    cell_metrics.rawWaveform.trough = (trough)';

%%  ACG metrics
for i = 1:length(spikes.times)
    [ccg,time] = CCG(spikes.times{i},ones(length(spikes.times{i}),1),'binSize',0.0005,'duration',0.100); %100ms wide CCG with 0.5ms bins
    ccg0 = find(time == 0);ccg10 = find(time == 0.01);ccg20 = find(time == 0.02);
    ccg40 = find(time == 0.04);ccg50 = find(time == 0.05);

    % Refractory period and burst index Royer 2012
    CCGmax = find(ccg(ccg0:ccg20)== max(ccg(ccg0:ccg20)));
    CCGmax = CCGmax+ccg0-1;
    if ~isempty(find(diff(ccg(ccg0:CCGmax(1)))>std(diff(ccg(ccg0:CCGmax(1)))),1))% refractory period according to Royer 2012
        cell_metrics.refractory(i,1) = find(diff(ccg(ccg0:CCGmax(1)))>std(diff(ccg(ccg0:CCGmax(1)))),1);
    else
        cell_metrics.refractory(i,1) = NaN;
    end

    CCGbase=mean(ccg(ccg40:ccg50));clear CCGmax; % mean CCG 40-50 ms
    CCGmax=find(ccg(ccg0:ccg10)==max(ccg(ccg0:ccg10)));
    CCGmax = CCGmax+ccg0-1; % only from 0 to 10ms

    if ccg(CCGmax)>CCGbase
       cell_metrics.burstRoyer(i,1)=(ccg(CCGmax(1))-CCGbase)/ccg(CCGmax(1));
    else
       cell_metrics.burstRoyer(i,1)=(ccg(CCGmax(1))-CCGbase)/(CCGbase);
    end

    % Burstiness
     binssum = 6; %for isis below 6ms
     binSize = 1e-3; nBins = 100; binEdges = (0:nBins) * binSize;
     t = ((0:nBins-1) + 0.5)' * binSize;
     ISIs = diff(spikes.times{i});
     hISI = histc(ISIs, binEdges);
     cell_metrics.burstiness(i,1) = sum(hISI(1:binssum))/sum(hISI);

    % Sam's ACG fit
    rsquare = [];   offset = 106;
    g = fittype('c*exp(-x/a)-d*exp(-x/b)');
    for j = 1:size(ccg,2)
        x = [1:95]';
        y = ccg(x+offset,j)/max(ccg(x+offset,j));

        [f0,gof] = fit(x/2,y,g,'StartPoint',[25, 1, 1, 1.5],'Lower',[1,0.1,-Inf, -Inf],'Upper',[100, 10,2, 10]);
    %     f0 = fit(x/2,y,'exp2','StartPoint',[1, -0.015, -1, -1]);
        fit_params(:,j) = coeffvalues(f0);
        xx = linspace(0,48,100);
        rsquare(j) = gof.rsquare;
        %figure, plot(x/2,y,'-o',x/2,f0(x/2),'r-'); title(['Unit ', num2str(j), ' r^2: ' num2str(rsquare(j))])
    end

    ACG.tau_decay = fit_params(1,:);
    ACG.tau_rise = fit_params(2,:);
    ACG.c = fit_params(3,:);
    ACG.d = fit_params(4,:);
    ACG.fit_rsquare = rsquare;

    clear s ccg CCGmax refT CCGbase ISIs hISI ;
end

%% FR
for i = 1:length(spikes.times)
    cell_metrics.FR(i,1) = length(spikes.times{i})/(spikes.times{i}(end)-spikes.times{i}(1));
end

%% Preliminary pyr/int classification
    % avg FR > 6Hz or narrow waveform (trought to peak < 5 ms) = INT
for i = 1:length(spikes.times)
    if cell_metrics.FR(i,1) > 6 || cell_metrics.filtWaveform.TroughtoPeak(i) < 5e-4
        cell_metrics.putativeClass(i,1) = 2; % int
    else
        cell_metrics.putativeClass(i,1) = 1; % pyr
    end
end

end

%%


function DEM_spatial_deconvolution
% FORMAT DEM_spatial_deconvolution
%--------------------------------------------------------------------------
% This (toy) demonstration routine illustrates spatiotemporal
% deconvolution of regional responses from imaging time-series.  The
% generative model assumes the data are generated by a small number of
% anatomical parcels that are smoothly displaced. The resulting data are
% then convolved spatially with a smoothly varying spatial kernel. The smooth
% displacement and dispersion are modelled in the usual way using discrete
% cosine basis set.  The model operates on reduced data features, using
% the eigenvariates of the original time-series - this supplements the
% implicit deconvolution with eigen-de-noising.  The ensuing estimates are
% anatomically informed because the generative model stars with a parcellation
% scheme.
%__________________________________________________________________________
% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: DEM_spatial_deconvolution.m 6975 2016-12-18 20:27:00Z karl $

% parcellation scheme (U) (make an atlas on the fly)
%==========================================================================
rng('default')

ATLAS = spm_conv(randn(64,16),6,6);
AP    = ATLAS;
a     = spm_vec(ATLAS);
[q,x] = hist(a,4);
A     = zeros(size(a));
for i = 1:length(x)
    A(:,i) = a < x(i);
    j      = find(A(:,i));
    a(j)   = Inf;
    AP(j)  = i;
end

U.u   = A;
U.dt  = size(ATLAS);

% Specify the generative model and generate some noisy data
%==========================================================================

% parameters and priors
%--------------------------------------------------------------------------
nD    = numel(U.dt);       % number of dimensions
nB    = 2;                 % number of basis functions
nP    = nB^nD;             % number of parameters
nY    = size(U.u,2);       % number of parcels
nT    = 32;

pE.D  = 0;
pE.S  = zeros(nP,nD);
pC.D  = pE.D + 1;
pC.S  = pE.S + 1;

P.D   = 0;                % true dispersion (log precision)
P.S   = randn(nP,nD)/2;    % true dislocation
G     = randn(nY,nT);      % true time series
G     = spm_conv(G,0,2);

% gradient functions for speed (not implemented here)
%--------------------------------------------------------------------------
M.FS   = @(y,M)M.U'*y;
M.IS   = @spm_gen_image;
M.G    = @(g,M)g';

% create data
%--------------------------------------------------------------------------
y      = spm_gen_image(P,M,U)*M.G(G)';
y      = y + randn(size(y))/128;

% dimension reduction
%--------------------------------------------------------------------------
[u,s,v] = spm_svd(y);
try
    M.U = u(:,1:(nY*2));
    M.V = v(:,1:(nY*2));
catch
    M.U = u;
    M.V = v;
end

% complete data and model specification
%==========================================================================
Y.y    = y*M.V;

M.pE   = pE;
M.pC   = pC;
M.gE   = zeros(nY,size(Y.y,2));
M.gC   = speye(spm_length(M.gE));
M.hE   = 4;
M.hC   = 1/16;
M.Nmax = 32;

% invert (deconvolve)
%==========================================================================
[Ep,Eg] = spm_nlsi_N(M,U,Y);
EG      = Eg*M.V';

% reconstructed data (with no distortions or dispersion)
%--------------------------------------------------------------------------
EP    = Ep;
EP.D  = 3;
EP.S  = EP.S*0;
YQ    = spm_gen_image(EP,M,U)*M.G(EG)';

PS    = P;
PS.D  = 2;
YS    = spm_gen_image(PS,M,U)*M.G(G)';
PS.S  = PS.S*0;
YP    = spm_gen_image(PS,M,U)*M.G(G)';

% Graphics
%==========================================================================
spm_figure('GetWin','Figure 1'); clf

subplot(3,4,1), imagesc(spm_unvec(YP(:,1),ATLAS))
title('True signal','FontSize',16), axis image
subplot(3,4,2), imagesc(spm_unvec(YS(:,1),ATLAS))
title('Displaced','FontSize',16), axis image
subplot(3,4,3), imagesc(spm_unvec(y(:,1),ATLAS))
title('BOLD data','FontSize',16), axis image
subplot(3,4,4), imagesc(spm_unvec(YQ(:,1),ATLAS))
title('Deconvolved','FontSize',16), axis image

subplot(3,1,2),
plot(1:nT,EG,'-.'), hold on
plot(1:nT,G),            hold off
title('True and reconstructed time courses','FontSize',16)
xlabel('Time'), ylabel('regional signal')

subplot(3,2,5), plot(G,EG,'.')
title('Deconvolution','FontSize',16)
xlabel('True'), ylabel('predicted')

subplot(3,2,6), plot(G,(A*diag(1./sum(A)))'*y,'.')
title('Standard ROI averages','FontSize',16)
xlabel('True'), ylabel('predicted')

return

function y = spm_gen_image(P,M,U)
% generative model of image
% FORMAT y = spm_gen_image(P,M,U)
%__________________________________________________________________________
% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging

% convolve
%--------------------------------------------------------------------------
y  = K(P,M,U)*U.u;

function K = K(P,M,U)
% convolution kernel
% FORMAT K = K(P)
%__________________________________________________________________________
% Copyright (C) 2010 Wellcome Trust Centre for Neuroimaging

nV  = U.dt;        % number of voxels
nD  = numel(nV);   % number of dimensions
nP  = size(P.S,1); % number of parameters
nB  = nP^(1/nD);   % number of basis functions

B     = 1;
for i = 1:nD
    b = spm_dctmtx(nV(i),nB)*sqrt(nV(i));
    B = kron(B,b);
end

% dispersion and displacement
%--------------------------------------------------------------------------
D     = exp(P.D)/2;
S     = B*P.S;

% kernel
%--------------------------------------------------------------------------
nK     = size(B,1);
K      = sparse(nK,nK);
[I,J]  = ind2sub(nV,1:nK);
X(:,1) = I;
X(:,2) = J;

k     = 0;
for i = 1:nD
 d    = (X(:,i) + S(:,i))*ones(1,nK) - ones(nK,1)*X(:,i)';
 k    = k + D*(d.^2);
end

% cosine aproximation to Gaussian
%--------------------------------------------------------------------------
i     = find(abs(k) < pi);
K(i)  = (1 + cos(k(i)/pi))/2;
K     = diag(1./sum(K,2))*K;


% function to implement the measurement model
function obs = f_h2(x)
% Input:
% x  = [xc xcd zc zcd p1 p2 w].'

load avar % r1,r2, L, and T

% unpack
xc = x(1); zc = x(3); p1 = x(5); p2 = x(6);

% observation 2
obs = L*(xc+r2*cos(p2))/(zc+r2*sin(p2));


% Test file for @chebfun/subspace.m.

function pass = test_subspace(pref)

if ( nargin == 0 )
   pref = chebfunpref();
end

% Orthonormal array-valued chebfun:
A = chebfun(@(t) [1/sqrt(2)+0*t cos(t) sin(2*t) sin(3*t)]/sqrt(pi), ...
    [0 1 2*pi], pref);

f = chebfun(@(t) sin(10*t)/sqrt(pi), [0 2 2*pi], pref);
alpha = [1e-10 pi/5 pi/2-1e-10];

for k = 1:length(alpha)
    B = cos(alpha(k))*A(:,k) + sin(alpha(k))*f;
    angle = subspace(A, B);
    pass(k) = abs(angle - alpha(k)) < 1e3*eps;
    angle = subspace(B, A);
    pass(k) = pass(k) && (abs(angle - alpha(k)) < 1e3*eps);
end

% Check subspaces with multiple columns.
pass(4) = abs(subspace(A(:,1:2), A(:,3:4)) - pi/2) < 10*vscale(A)*eps;
pass(5) = abs(subspace(A(:,1:3), A(:,4)) - pi/2) < 10*vscale(A)*eps;

% Check operation for row chebfuns.
At = A.';
pass(6) = abs(subspace(At(1:2,:), At(3:4,:)) - pi/2) < ...
    10*vscale(At)*eps;

end


% ------------------------------------------------------------------------
%  Copyright (C)
%  Universitat Politecnica de Catalunya BarcelonaTech (UPC) - Spain
%  University of California Berkeley (UCB) - USA
%
%  Jordi Pont-Tuset <jordi.pont@upc.edu>
%  Pablo Arbelaez <arbelaez@berkeley.edu>
%  June 2014
% ------------------------------------------------------------------------
% This file is part of the MCG package presented in:
%    Arbelaez P, Pont-Tuset J, Barron J, Marques F, Malik J,
%    "Multiscale Combinatorial Grouping,"
%    Computer Vision and Pattern Recognition (CVPR) 2014.
% Please consider citing the paper if you use this code.
% ------------------------------------------------------------------------
function cmap_proba = apply_sigmoid(cmap, thr, fq)
 if nargin<3, fq=1; end,
 if nargin<2, thr =0.5; end
 cmap_proba=cmap;
 cmap_proba(:) = 1./(1+exp(-fq*(cmap(:)-thr)));


function jst=jacprojS(j, i, rt, xyz, r0, a)
% symbolic projection function Jacobian
% code automatically generated with maple

  qr0=r0(j*4+1:(j+1)*4);

  t1 = (rt(1) ^ 2);
  t2 = (rt(2) ^ 2);
  t3 = (rt(3) ^ 2);
  t5 = sqrt((1 - t1 - t2 - t3));
  t10 = -t5 * qr0(2) - qr0(1) * rt(1) - rt(2) * qr0(4) + rt(3) * qr0(3);
  t11 = t10 ^ 2;
  t16 = t5 * qr0(1) - rt(1) * qr0(2) - rt(2) * qr0(3) - rt(3) * qr0(4);
  t17 = t16 ^ 2;
  t22 = t5 * qr0(4) + qr0(1) * rt(3) + rt(1) * qr0(3) - rt(2) * qr0(2);
  t28 = -t5 * qr0(3) - qr0(1) * rt(2) - rt(3) * qr0(2) + rt(1) * qr0(4);
  t29 = t28 ^ 2;
  t32 = t10 * t28;
  t35 = -t16 * t22;
  t36 = 0.2e1 * t32 + t16 * t22 - t35;
  t38 = -t10 * t22;
  t39 = t16 * t28;
  t42 = t38 + 0.2e1 * t39 - t10 * t22;
  t48 = t10 * xyz(1) + t28 * xyz(2) - t22 * xyz(3);
  t53 = t16 * xyz(3) - t10 * xyz(2) + t28 * xyz(1);
  t58 = t16 * xyz(1) - t28 * xyz(3) - t22 * xyz(2);
  t63 = t16 * xyz(2) + t22 * xyz(1) + t10 * xyz(3);
  t65 = -t48 * t22 + t16 * t53 + t58 * t28 - t63 * t10 + rt(6);
  t66 = 0.1e1 / t65;
  t78 = t48 * t28 + t16 * t63 + t53 * t10 + t58 * t22 + rt(5);
  t82 = t65 ^ 2;
  t83 = 0.1e1 / t82;
  t84 = (a(1) * (t48 * t10 + t16 * t58 - t63 * t22 - t53 * t28 + rt(4)) + a(2) * t78 + a(3) * t65) * t83;
  t92 = t22 ^ 2;
  t93 = t29 + t17 - t10 ^ 2 - t92;
  t95 = -t28 * t22;
  t98 = t16 * t10;
  t99 = 0.2e1 * t95 - t16 * t10 - t98;
  t111 = t95 + 0.2e1 * t98 - t28 * t22;
  t114 = t92 + t17 - t28 ^ 2 - t11;
  t127 = (a(4) * t78 + a(5) * t65) * t83;
  jst(1) = (a(1) * (t11 + t17 - t22 ^ 2 - t29) + a(2) * t36 + a(3) * t42) * t66 - t84 * t42;
  jst(2) = (a(1) * (t32 + 0.2e1 * t35 + t10 * t28) + a(2) * t93 + a(3) * t99) * t66 - t84 * t99;
  jst(3) = (a(1) * (0.2e1 * t38 - t16 * t28 - t39) + a(2) * t111 + a(3) * t114) * t66 - t84 * t114;
  jst(4) = (a(4) * t36 + a(5) * t42) * t66 - t127 * t42;
  jst(5) = (a(4) * t93 + a(5) * t99) * t66 - t127 * t99;
  jst(6) = (a(4) * t111 + a(5) * t114) * t66 - t127 * t114;


function [qq]=jacobiana(robot,Xpunto)
    i=1;
    q = [-0.1440 -0.9810 -1.2830 0.0070 -0.0545 1.0050]';
    pause on;

    while i<99
       J = compute_jacobian(robot,q);
       qd = pinv(J)*Xpunto(:,i);
       q = q + qd;

       qq(i,:)=q; %almacenamos en una matriz todas las 'q'

       i = i + 1;
    end
end


function [x, objective, errorFlag, errorMsg] = quadraticProgramming(H, f, A, b, Aeq, beq, lb, ub, x0, options)
% Provides a common interface to several quadratic programming solvers.
% Checks each solver for errors.
%
% That is it solves the problem:
%   min 0.5 * x'*H*x + f'*x
%   subject to A*x<=b, Aeq*x=beq, lb<=x<=ub
%
% Requirements: at least one of the following quadratic programing solvers
% - clp -- open source solve quadratic programming solver
%   http://control.ee.ethz.ch/~joloef/mexclp.zip
% - minq
%   http://www.mat.univie.ac.at/~neum/software/minq/
% - qpip -- open source solve quadratic programming solver
%   http://sigpromu.org/quadprog/index.html
% - Optimization Toolbox - has quadprog, MATLAB's quadratic programming
%   solver. Note: quadprog is not very good. We suggest you use another
%   solver instead.
%   http://www.mathworks.com/products/optimization/
% - Wolf
%   http://www.mathworks.com/matlabcentral/fileexchange/27397-quadratic-programming-by-wolfs-method
%
% Author: Jonathan Karr
% Affiliation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 1/17/2011

solver = 'clp';
if exist('options', 'var') && isstruct(options)
    solver = options.solver;
end

solverOptions = struct;
if exist('options', 'var') && isstruct(options) && isfield(options, 'solverOptions') && isfield(options.solverOptions, options.solver)
    solverOptions = options.solverOptions.(options.solver);
end

switch solver
    case 'clp'
        [x, objective, exitFlag] = clp(H, f, A, b, Aeq, beq, lb, ub, solverOptions);
        switch exitFlag
            case 0, errorMsg = 'optimal';
            case 1, errorMsg = 'infeasible';
            case 2, errorMsg = 'unbounded';
        end
        errorFlag = exitFlag ~= 0;
    case 'minqsep'
        [m, n] = size(Aeq);
        printLevel = 1;
        if isfield(solverOptions, 'printLevel'), printLevel = solverOptions.printLevel; end;
        [x, objective, errorFlag] = minqsep(f, diag(H), [Aeq; eye(n); -eye(n)], ...
            [beq; lb; -ub], [true(m, 1); false(n, 1); false(n, 1)], printLevel, x0);
        switch errorFlag
            case 0, errorMsg = 'global minimizer found';
            case 1, errorMsg = 'approximate solution; feasible set probably empty';
            case 99, errorMsg = 'approximate solution; maxit exceeded';
        end
    case 'qpip'
        display = 0;
        mu = 0.0;
        method = 1;
        if isfield(solverOptions, 'display'), display = solverOptions.display; end;
        if isfield(solverOptions, 'mu'),      mu      = solverOptions.mu;      end;
        if isfield(solverOptions, 'method'),  method  = solverOptions.method;  end;
        [x, exitFlag] = qpip(H, f, A, b, Aeq, beq, lb, ub, display, mu, method);
        objective = x' *H * x + f' * x;
        errorFlag = exitFlag ~= 0;
        switch exitFlag
            case 0,    errorMsg = 'optimal';
            otherwise, errorMsg = 'other error';
        end
    case 'quadprog'
        [x, objective, exitFlag, output] = quadprog(H, f, A, b, Aeq, beq, lb, ub, x0, solverOptions);
        errorFlag = exitFlag <= 0;
        errorMsg = output.message;
    case 'wolf'
        [m, n] = size(Aeq);
        [x, objective] = wolf(H, f, [beq; lb; ub],[Aeq; eye(n); eye(n)], ...
            [zeros(m, 1); ones(n, 1); -ones(n, 1)], 1);
        errorFlag = 0;
        errorMsg = 'optimal';
    otherwise
        throw(MException('ComputationUtil:error', 'Invalid solver'));
end


%% This script simulates the Lyapunov Optimization-based Dynamic Computation Offloading (LODCO) algorithm.
%  author: Hailiang Zhao
clc, clear
opt = optimset('Display', 'none');

%% basic parameter settings (had better not change those paras)
k = 1e-28;                % effective switched capacitance (a constant decided by the chip architecture)
tau = 0.002;              % the length of time slot (in second)
phi = 0.002;              % the cost of task dropping (in second)
omega = 1e6;              % the bandwidth of MEC server (in Hz)
sigma = 1e-13;            % the noise power of the receiver (in W)
p_tx_max = 1;             % the maximum transmit power of mobile device (in W)
f_max = 1.5e9;            % the maximum CPU-cycle frequency of mobile device (in Hz)
E_max = 0.002;            % the maximum amout of battery output energy (in J)
L = 1000;                 % the input size of the computation task (in bit)
X = 737.5;                % the number of CPU cycles needed on processing one bit of task
W = L * X;                % the number of CPU cycles needed on processing one task
E_H_max = 48e-6;          % the upper bound of the energy arrive at the mobile device (in J)
p_H = E_H_max / (2*tau);  % the average Energy Harvesting (EH) power (in W)
g0 = power(10, -4);       % the path-loss constant

%% parameter control
T = 50000;                % the number of time slot (a.k.a. the size of the time horizon)
tau_d = 0.002;            % execution deadline (in second)
d = 50;                   % the distance between the mobile device and the MEC server (in meter)
E_min = 0.02e-3;          % the minimum amout of battery output energy (in J)
V = 1e-5;                 % the weight of penalty (the control parameter introduced by Lyapunov Optimization)
rho = 0.6;                % the probability that the computation task is requested

% the lower bound of perturbation parameter
E_max_hat = min(max(k * W * (f_max)^2, p_tx_max * tau), E_max);
theta = E_max_hat + V * phi / E_min;

%% allocate storage for valuable results
B = zeros(T, 1);          % the battery energy level (in J)
B_hat = zeros(T, 1);      % the virtual battery energy level ($B_hat = B - theta$)
e = zeros(T, 1);          % the amout of the harvested and stored energy (in J)
chosen_mode = zeros(T, 1);% {1: local, 2: remote, 3: drop, 4: no task request}
f = zeros(T, 1);          % the CPU-cycle frequency of local execution (in Hz)
p = zeros(T, 1);          % the transmit power of computation offloading (in W)
cost = zeros(T, 3);       % execution delay for mobile execution, MEC server execution and final choice, respectively (in second)
E = zeros(T, 3);          % energy consumption for mobile execution, MEC server execution and final choice, respectively (in J)

%% simulation begin
t = 1;
while t <= T
    disp(['===> Time slot #', num2str(t), ' <==='])

    %% initialization
    % generate the task request
    zeta = binornd(1, rho);
    % generate the virtual battery energy level
    B_hat(t) = B(t) - theta;

    %% step 1: get the optimal energy harvesting no matter whether task is requested
    E_H_t = unifrnd(0, E_H_max);
    if B_hat(t) <= 0
        e(t) = E_H_t;
    end

    %% step 2: get the optimal computation offloading strategy (I_m, I_s, I_d, f(t), p(t))
    if zeta == 0
        % chosen mode has to be 4
        disp('no task request generated!')
        chosen_mode(t) = 4;
    else
        % chosen_mode is chosen from {1, 2, 3}
        disp('task request generated!')
        % task request exists, generate the channel power gain
        h = exprnd(g0 / power(d, 4));

        %% step 2.1: solve the optimization problem $\mathcal{P}_{ME}$ (f(t) > 0)
        % calculate f_L and f_U
        f_L = max(sqrt(E_min / (k * W)), W / tau_d);
        f_U = min(sqrt(E_max / (k * W)), f_max);
        if f_L <= f_U
            % the sub-problem is feasible
            disp('mobile execution ($\mathcal{P}_{ME}$) is feasible!')

            if B_hat(t) < 0
                f_0 = (V / (-2 * B_hat(t) * k))^(1/3);
            else
                % complex number may exist, which may lead to error
                f_0 = -(V / (2 * B_hat(t) * k))^(1/3);
            end

            if (f_0 > f_U && B_hat(t) < 0) || (B_hat(t) >= 0)
                f(t) = f_U;
            elseif f_0 >= f_L && f_0 <= f_U && B_hat(t) < 0
                f(t) = f_0;
            elseif f_0 < f_L && B_hat(t) < 0
                f(t) = f_L;
            end
            % check whether f(t) is zero
            if f(t) == 0
                disp('Something wrong! f is 0!')
            end

            % calculate the delay of mobile execution
            cost(t, 1) = W / f(t);
            % calculate the energy consumption of mobile execution
            E(t, 1) = k * W * (f(t)^2);
            % calculate the value of optimization goal
            J_m = -B_hat(t) * k * W * (f(t))^2 + V * W / f(t);
        else
            % the sub-problem is not fasible because (i) the limited
            % computation capacity or (ii) time cosumed out of deadline or
            % (iii) the energy consumed out of battery energy level
            % If it is not feasible, it just means that we cannot choose
            % 'I_m=1'. It dosen't mean that the task has to be dropped.
            disp('mobile execution ($\mathcal{P}_{ME}$) is not feasible!')
            f(t) = 0;
            cost(t, 1) = 0;
            E(t, 1) = 0;
            % 'I_m=1' can never be chosen if mobile execution goal is inf
            J_m = inf;
        % Attention! We do not check whether the energy cunsumed is larger than
        % battery energy level because the problem $\mathcal{J}_{CO}$ does
        % not have constraint (8).
        end

        %% step 2.2: solve the optimization problem $\mathcal{P}_{SE}$ (p(t) > 0)
        E_tmp = sigma * L * log(2) / (omega * h);
        p_L_taud = (power(2, L / (omega * tau_d)) - 1) * sigma / h;
        % calculate p_L
        if E_tmp >= E_min
            p_L = p_L_taud;
        else
            % calculate p_E_min (use inline function and fsolve)
            y = @(x) x * L - omega * log2(1 + h*x/sigma) * E_min;
            % accroding to the function figure, p_L_taud is a positive
            % number around 0.2
            p_E_min = fsolve(y, 0.2, opt);
            p_L = max(p_L_taud, p_E_min);
        end
        % calculate p_U
        if E_tmp >= E_max
            p_U = 0;
        else
            % caculate p_E_max (use inline function and fsolve)
            y = @(x) x * L - omega * log2(1 + h*x/sigma) * E_max;
            % accroding to the function figure, p_E_max is a large positive
            % number around 20
            p_E_max = fsolve(y, 100, opt);
            p_U = min(p_tx_max, p_E_max);
        end

        if p_L <= p_U
            % the sub-problem is feasible
            disp('MEC server execution ($\mathcal{P}_{SE}$) is feasible!')
            % calculate p_0
            virtual_battery = B_hat(t);
            y = @(x) virtual_battery * log2(1 + h*x/sigma) + ...
                h * (V - virtual_battery*x) / log(2) / (sigma + h*x);
            p_0 = fsolve(y, 0.5, opt);

            if (p_U < p_0 && B_hat(t) < 0) || B_hat(t) >= 0
                p(t) = p_U;
            elseif p_0 < p_L && B_hat(t) < 0
                p(t) = p_L;
            elseif p_0 >= p_L && p_0 <= p_U && B_hat(t) < 0
                p(t) = p_0;
            end
            % check whether p(t) is zero
            if p(t) == 0
                disp('Something wrong! p is 0!')
            end

            % calculate the delay of MEC server execution
            cost(t, 2) = L / (omega * log2(1 + h*p(t)/sigma));
            % calculate the energy consumption of MEC server execution
            E(t, 2) = p(t) * cost(t, 2);
            % calculate the value of optimization goal
            J_s = (-B_hat(t) * p(t) + V) * cost(t, 2);
        else
            % the sub-problem is not feasible because (i) the limited transmit
            % power or (ii) time cosumed out of deadline or (iii) the energy
            % consumed out of battery energy level
            % If it is not feasible, it just means that we cannot choose
            % 'I_s=1'. It dosen't mean that the task has to be dropped.
            disp('MEC server execution ($\mathcal{P}_{SE}$) is not feasible!')
            p(t) = 0;
            cost(t, 2) = 0;
            E(t, 2) = 0;
            % 'I_s=1' can never be chosen if MEC server execution goal is inf
            J_s = inf;
        % Similarly, we do not check whether the energy cunsumed is larger than
        % battery energy level because the problem $\mathcal{J}_{CO}$ does
        % not have constraint (8).
        end

        %% step 3: choose the best execution mode
        J_d = V * phi;
        disp(['J_m:', num2str(J_m)])
        disp(['J_s:', num2str(J_s)])
        [~, mode] = min([J_m, J_s, J_d]);
        chosen_mode(t) = mode;
    end

    %% step 4: according to the chosen execution mode, calculate the real dealy and energy consumption
    if chosen_mode(t) == 1
        % mobile execution is chosen
        cost(t, 3) = cost(t, 1);
        E(t, 3) = E(t, 1);
    elseif chosen_mode(t) == 2
        % MEC server execution is chosen
        cost(t, 3) = cost(t, 2);
        E(t, 3) = E(t, 2);
    elseif chosen_mode(t) == 3
        % task is dropped, the delay is the task dropping penalty and the
        % energy consumption is zero
        cost(t, 3) = phi;
        E(t, 3) = 0;
    else
        % no task is requested, the delay and the energy consumption are
        % both zero
        cost(t, 3) = 0;
        E(t, 3) = 0;
    end

    %% step 5: update the battery energy level and go to next time slot
    B(t + 1) = B(t) - E(t, 3) + e(t);
    t = t + 1;
end

%% step 6: evaluate the simulation results
% 1. the battery energy level vs. time slot
figure
plot(1:T, B(1:T));
hold on
plot(1:T, repmat(theta + E_H_max, [T, 1]), '-')
title('Envolution of battery energy level')
xlabel('time slot')
ylabel('battery energy level $B_t$', 'Interpreter','latex')

% 2. the average execution cost vs. time slot
accumulated = 0;
average_cost = zeros(T, 1);
request_num = 0;
for t = 1: T
    accumulated = accumulated + cost(t, 3);
    if cost(t, 3) ~= 0
        % there exists task request
        request_num = request_num + 1;
    end
    average_cost(t) = accumulated / request_num;
end
figure
plot(1:T, average_cost);
title('Envolution of average execution cost')
xlabel('time slot')
ylabel('average execution cost $\frac{1}{T} \sum_{t=0}^{T-1} cost^t$', 'Interpreter','latex')

% 3. the average ratio of each chosen mode vs. time slot
average_ratio = zeros(T, 3);
mobile_exe = 0; server_exe = 0; drop = 0;
request_num = 0;
for t = 1: T
    if cost(t, 3) == 0
        continue
    else
        request_num = request_num + 1;
        if chosen_mode(t) == 1
            mobile_exe = mobile_exe + 1;
        elseif chosen_mode(t) == 2
            server_exe = server_exe + 1;
        else
            drop = drop + 1;
        end
    end
    average_ratio(t, :) = [mobile_exe, server_exe, drop] / request_num;
end
figure
plot(1:T, average_ratio(:, 1));
hold on
plot(1:T, average_ratio(:, 2));
hold on
plot(1:T, average_ratio(:, 3));
legend('mobile execution', 'MEC server execution', 'drop')
title('Envolution of average ratio of chosen modes')
xlabel('time slot')
ylabel('average  ratio of chosen modes $\frac{1}{T} \sum_{t=0}^{T-1} \{I_m^t, I_s^t, I_d^t\}$', 'Interpreter','latex')


function airy_ai_prime_values_test ( )

%*****************************************************************************80
%
%% AIRY_AI_PRIME_VALUES_TEST demonstrates the use of AIRY_AI_PRIME_VALUES.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 April 2007
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'AIRY_AI_PRIME_VALUES_TEST:\n' );
  fprintf ( 1, '  AIRY_AI_PRIME_VALUES stores values of \n' );
  fprintf ( 1, '  the Airy function A''(X).\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '      X           Ai''(X)\n' );
  fprintf ( 1, '\n' );

  n_data = 0;

  while ( 1 )

    [ n_data, x, aip ] = airy_ai_prime_values ( n_data );

    if ( n_data == 0 )
      break
    end

    fprintf ( 1, '  %12f  %24.16f\n', x, aip );

  end

  return
end


function [strshocks_estimates]=strsestimates(strshocks_record,n,T,IRFband)

% create first the cell that will contain the estimates
strshocks_estimates=cell(n,1);

% for each variable and each sample period, compute the median, lower and upper bound from the Gibbs sampler records
% consider variables in turn
for ii=1:n
   % consider sample periods in turn
   for jj=1:T
   % compute first the lower bound
   strshocks_estimates{ii,1}(1,jj)=quantile(strshocks_record{ii,1}(:,jj),(1-IRFband)/2);
   % then compute the median
   strshocks_estimates{ii,1}(2,jj)=quantile(strshocks_record{ii,1}(:,jj),0.5);
   % finally compute the upper bound
   strshocks_estimates{ii,1}(3,jj)=quantile(strshocks_record{ii,1}(:,jj),(1-(1-IRFband)/2));
   end
end


function [w,s]=fram2wav(x,tt,mode)
%FRAM2WAV  converts frame values to a continuous waveform [W]=(X,TT,MODE)
%  Inputs:
%          x(nf,p)      is the input signal: one row per frame
%	       tt(nf,3)     specifies the frames. Each row has the form [start_sample end_sample flag]
%                       where flag = 1 for the start of a new spurt.
%                       If tt(:,3) is omitted, a new spurt will be started whenever there is a gap
%                       of more than one between the end of one frame and the beginning or the next.
%                       A new spurt is automatically started if x() = NaN.
%          mode         consists of one or more of the following letters:
%                          z for zero-order hold interpolation (i.e. constant within each frame)
%                          l for linear interpolation within each spurt [default]
%
% Outputs:
%          w(n,p)       contains the interpolated waveforms. Their length is n = tt(nf,2)
%          s(ns,2)      gives the starting and ending sample numbers of each spurt (excluding NaN spurts)
%
%    This routine converts frame-based values to continuous waveforms by performing
%    a chosen method of interpolation. Interpolation is restarted at the beginning of each spurt.

%    Bugs/Suggestions
%      (1)   Additional mode option for cubic interpolation
%      (2)   Additional mode option for interpolation in log domain
%      (3)   Additional mode option for x values being
%            frame averages rather than mid-frame values.

%      Copyright (C) Mike Brookes 1997
%      Version: $Id: fram2wav.m,v 1.4 2007/05/04 07:01:38 dmb Exp $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   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 can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargin<3
    mode='l';
end
[nf,m]=size(x);
n=round(tt(end,2));
w=repmat(NaN,n,m);
nt=size(tt,2);
ix1=ceil(tt(:,1)); % start of frame sample
ix2=floor(tt(:,2)); % end of frame sample

% determine the start and end of spurts

if nt>2
    ty=tt(:,3)>0;   % frame type set by user
else
    ty=zeros(nf,1);
    ty(2:end)=ix1(2:end)>ix2(1:end-1)+1;    % new spurt whenever a gap
end
ty(1)=1;           % first frame always starts a spurt
ty(isnan(x))=1;    % NaN always ends previous spurt
ty(1+find(isnan(x(1:end-1))))=1; % NaN always forces a new spurt
ty=double(ty);
ty(1:end-1)=ty(1:end-1)+2*ty(2:end);
ty(end)=ty(end)+2;   % last frame always ends a spurtw=repmat(NaN,n,m);  % initialize output to all NaN
nx=ix2-ix1+1;

if any(mode=='z')   % zero-order hold
    for i=1:nf
        if nx(i)
            w(ix1(i):ix2(i),:)=repmat(x(i,:),nx(i),1);
        end
    end
else   % linear interpolation is the default
    ttm=(tt(:,1)+tt(:,2))/2;    % mid point of frame
    ixm=floor(ttm); % end of first half of frame
    for i=1:nf
        if i==176
            i
        end
        if nx(i)
            tyi=ty(i);
            if tyi==3    % use a zero order hold
                w(ix1(i):ix2(i),:)=repmat(x(i,:),nx(i),1);
            else
                nxm=ixm(i)-ix1(i)+1;
                if nxm
                    if tyi==1
                        grad=(x(i+1,:)-x(i,:))/(ttm(i+1)-ttm(i));
                    else
                        grad=(x(i,:)-x(i-1,:))/(ttm(i)-ttm(i-1));
                    end
                    w(ix1(i):ixm(i),:)=repmat(x(i,:),nxm,1)+((ix1(i):ixm(i))'-ttm(i))*grad;
                end
                if nx(i)>nxm
                    if tyi==2
                        grad=(x(i,:)-x(i-1,:))/(ttm(i)-ttm(i-1));
                    else
                        grad=(x(i+1,:)-x(i,:))/(ttm(i+1)-ttm(i));
                    end
                    w(ixm(i)+1:ix2(i),:)=repmat(x(i,:),ix2(i)-ixm(i),1)+((ixm(i)+1:ix2(i))'-ttm(i))*grad;
                end
            end
        end
    end
end

% now sort out the start and end spurt positions

ty(isnan(x))=0;    % Don't count NaN spurts
s=repmat(ix1(bitand(ty,1)>0),1,2);
s(:,2)=ix2(bitand(ty,2)>0);
if ~nargout
    tw=(1:n)';
    for i=size(s,1):-1:2
        j=s(i,1);   % start of new spurt
        tw=[tw(1:j-1); tw(j); tw(j:end)];
        w=[w(1:j-1); NaN; w(j:end)];        % insert a NaN to force a plotting break
    end
    plot(tt(:,1:2)',repmat(x(:)',2,1),'r-+',tw,w,'b-');
end


function tapas_hgf_binary_plotTraj(r)
% Plots the estimated or generated trajectories for the binary HGF perceptual model
% Usage example:  est = tapas_fitModel(responses, inputs); tapas_hgf_binary_plotTraj(est);
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2012-2013 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% Optional plotting of standard deviations (true or false)
plotsd = true;

% Optional plotting of responses (true or false)
ploty = true;

% Set up display
scrsz = get(0,'screenSize');
outerpos = [0.2*scrsz(3),0.2*scrsz(4),0.8*scrsz(3),0.8*scrsz(4)];
figure(...
    'OuterPosition', outerpos,...
    'Name', 'HGF trajectories');

% Time axis
if size(r.u,2) > 1
    t = r.u(:,end)';
else
    t = ones(1,size(r.u,1));
end

ts = cumsum(t);
ts = [0, ts];

% Number of levels
try
    l = r.c_prc.n_levels;
catch
    l = (length(r.p_prc.p)+1)/5;
end

% Upper levels
for j = 1:l-1

    % Subplots
    subplot(l,1,j);

    if plotsd == true
        upperprior = r.p_prc.mu_0(l-j+1) +sqrt(r.p_prc.sa_0(l-j+1));
        lowerprior = r.p_prc.mu_0(l-j+1) -sqrt(r.p_prc.sa_0(l-j+1));
        upper = [upperprior; r.traj.mu(:,l-j+1)+sqrt(r.traj.sa(:,l-j+1))];
        lower = [lowerprior; r.traj.mu(:,l-j+1)-sqrt(r.traj.sa(:,l-j+1))];

        plot(0, upperprior, 'ob', 'LineWidth', 1);
        hold all;
        plot(0, lowerprior, 'ob', 'LineWidth', 1);
        fill([ts, fliplr(ts)], [(upper)', fliplr((lower)')], ...
             'b', 'EdgeAlpha', 0, 'FaceAlpha', 0.15);
    end
    plot(ts, [r.p_prc.mu_0(l-j+1); r.traj.mu(:,l-j+1)], 'b', 'LineWidth', 2);
    hold all;
    plot(0, r.p_prc.mu_0(l-j+1), 'ob', 'LineWidth', 2); % prior
    xlim([0 ts(end)]);
    title(['Posterior expectation of x_' num2str(l-j+1)], 'FontWeight', 'bold');
    ylabel(['\mu_', num2str(l-j+1)]);
end

% Input level
subplot(l,1,l);

plot(ts, [tapas_sgm(r.p_prc.mu_0(2), 1); tapas_sgm(r.traj.mu(:,2), 1)], 'r', 'LineWidth', 2);
hold all;
plot(0, tapas_sgm(r.p_prc.mu_0(2), 1), 'or', 'LineWidth', 2); % prior
plot(ts(2:end), r.u(:,1), '.', 'Color', [0 0.6 0]); % inputs
plot(ts(2:end), r.traj.wt(:,1), 'k') % implied learning rate
if (ploty == true) && ~isempty(find(strcmp(fieldnames(r),'y'))) && ~isempty(r.y)
    if ~isempty(find(strcmp(fieldnames(r),'c_sim'))) && strcmp(r.c_sim.obs_model,'tapas_beta_obs')
        y = r.y(:,1);
    else
        y = r.y(:,1) -0.5; y = 1.16 *y; y = y +0.5; % stretch
        if ~isempty(find(strcmp(fieldnames(r),'irr')))
            y(r.irr) = NaN; % weed out irregular responses
            plot(ts(r.irr),  1.08.*ones([1 length(r.irr)]), 'x', 'Color', [1 0.7 0], 'Markersize', 11, 'LineWidth', 2); % irregular responses
            plot(ts(r.irr), -0.08.*ones([1 length(r.irr)]), 'x', 'Color', [1 0.7 0], 'Markersize', 11, 'LineWidth', 2); % irregular responses
        end
    end
    plot(ts(2:end), y, '.', 'Color', [1 0.7 0]); % responses
    title(['Response y (orange), input u (green), learning rate (fine black), and posterior expectation of input s(\mu_2) ', ...
           '(red) for \rho=', num2str(r.p_prc.rho(2:end)), ', \kappa=', ...
           num2str(r.p_prc.ka(2:end)), ', \omega=', num2str(r.p_prc.om(2:end))], ...
      'FontWeight', 'bold');
    ylabel('y, u, s(\mu_2)');
    axis([0 ts(end) -0.15 1.15]);
else
    title(['Input u (green), learning rate (fine black), and posterior expectation of input s(\mu_2) ', ...
           '(red) for \rho=', num2str(r.p_prc.rho(2:end)), ', \kappa=', ...
           num2str(r.p_prc.ka(2:end)), ', \omega=', num2str(r.p_prc.om(2:end))], ...
      'FontWeight', 'bold');
    ylabel('u, s(\mu_2)');
    axis([0 ts(end) -0.1 1.1]);
end
plot(ts(2:end), 0.5, 'k');
xlabel('Trial number');
hold off;


% SIGNALSTAT  -  Computes and plots statistical characteristics of a signal,
%                  including the data histogram, a fitted normal distribution,
%                  a normal distribution fitted on trimmed data, a boxplot, and
%                  the QQ-diagram. The estimates value are printed in a panel and
%                  can be read as output. Optionally, a topographic map (see TOPOPLOT)
%                  can be plotted.
%                  The boxplot and the Kolmogorov-Smirnov test require the
%                  MATLAB Statistics Toolbox.
%
% Usage:
%   >>  signalstat( data )
%   >>  signalstat( data, plotlab, dlabel, percent );
%   >>  [M,SD,sk,k,med,zlow,zhi,tM,tSD,tndx,ksh] = ...
%                 signalstat( data, plotlab, dlabel, percent, dlabel2, map, chan_locs );
%
% Inputs:
%   data        - data vector
%
% Optional inputs:
%   plotlab     - 1: default->plot  |  0: ->no plot
%   dlabel      - A label for the data ([]: default->'Potential [V]')
%   percent     - percentage of data to exclude for trimmed mean & SD ([]:default->5)
%                 Excluded is 'percent'/2 high % and 'percent'/2 low %
%   dlabel2     - A title label for the statistics table
%   map         - Data vector to be displayed as topographic map. If a single integer,
%                 only the corresponding electrode location is displayed
%   chan_locs   - name of an EEG electrode position file (See >> topoplot example for format).
%                 Can also be a structure (see >> help pop_editset)
%
% Outputs:
%   M,SD        - mean and standard deviation
%   sk,k        - skewness and excess kurtosis
%   med         - median
%   zlow,zhi    - low and high 'percent/2'-Percentile ('percent/2'/100-Quantile)
%   tM,tSD      - trimmed mean and SD, removing data<zlow and data>zhigh
%   tndx        - index of the data retained after trimming
%   ksh         - output flag of the Kolmogorov-Smirnov test at level p=0.05
%                 0: data could be normally distributed; 1: data are not normally distributed
%                 -1: test could not be executed
%
% Author: Luca Finelli, CNL / Salk Institute - SCCN, 2 August 2002
%
% See also:
%   POP_SIGNALSTAT, QQDIAGRAM, EEGLAB

% Copyright (C) 2002 Luca Finelli, Salk/SCCN, La Jolla, CA

% Note:
% QQDIAGRAM IS EQUIVALENT TO PERCENTILE/PERCENTILE PLOT
% X = EEG.data(5,:); % data
% Y = randn(1, 1000); % gaussan random distribution
% figure; qqdiagram(X, Y,  2);
% figure; plot(prctile(X,2), prctile(Y,2));

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

function [M,SD,sk,k,med,zlow,zhi,tM,tSD,tndx,ksh] = signalstat( data, plotlab, dlabel, percent, dlabel2, map, chan_locs);

M=[]; SD=[]; sk=[]; k=[]; med=[]; zlow=[]; zhi=[]; tM=[]; tSD=[]; tndx=[]; ksh=[];

istats=1;
%hs = help('stats');
% toolbx = ver;
% if isempty(hs) || all([~any(strcmpi({toolbx.Name},'statistics toolbox')), ~any(strcmpi({toolbx.Name},'statistics and machine learning toolbox'))])
%     disp('SIGNALSTAT note: the boxplot (not shown) requires the MATLAB Statistics Toolbox or Statistics and Machine Learning Toolbox');
%     istats=0;
% end

if (nargin<8 && nargin>5) && min(size(map))~=1
		error('signalstat(): the map input must be a vector')
end

if nargin<7 && nargin>5
	disp('signalstat(): no location file for the topographic map')
	help signalstat;
	return
end

if nargin < 6
	map = [];
end

if nargin < 5
	dlabel2 = '';
end

if nargin>3
	if isempty(percent)
		percent=5;
	end
	if any(percent > 100) || any(percent < 0)
		error('signalstat(): percent must be between 0 and 100');
	end
end

if nargin < 4
	percent = 5;
end

if (nargin < 3 || isempty(dlabel))
	dlabel='Potential [V]';
end

if nargin < 2
  plotlab=1;
end;

if ~isnumeric(plotlab)
	error('signalstat(): plotlab must be numeric');
end

if plotlab ~= 0 && plotlab ~= 1
		error('signalstat(): plotlab must be 0 or 1');
end
if nargin < 1
	help signalstat;
	return;
end;

if ndims(data)>2
	error('signalstat(): data must be a vector (1-dim signal)')
end

if ~isreal(data)
	error('signalstat(): data cannot be complex')
end

fprintf('signalstat(): computing statistics...\n');

% Statistical characteristics
%----------------------------
pnts=length(data);   % number of data points
rg=max(data)-min(data);

M=mean(data);        % mean
med=median(data);    % median

vr=var(data);        % variance (N-1 normalized)
SD=std(data);        % standard deviation

if istats
	sk=skewness(data,0); % skewness (third central moment divided by
                         % the cube of the standard deviation)
    k=kurtosis(data,0)-3;  % kurtosis (fourth central  moment divided by
                         % fourth power of the standard deviation)
else
	sk=NaN;
	k=kurt(data)-3;
end

% Checks on skewness and kurtosis
%--------------------------------
sklab='Distribution is symmetric';
if sk>0.01
	sklab='Distribution is right-skewed';
elseif sk < -0.01
	sklab='Distribution is left-skewed';
end

klab='';
if k>0.01
	klab='Distribution is super-Gaussian'; % i.e. kurtosis bigger then Gaussian
elseif k < -0.01
	klab='Distribution is sub-Gaussian';
end

% Estimates without the highest and lowest 'percent'/2 % of data
%---------------------------------------------------------------
pc=percent/100;

zlow = quantile(data,(pc / 2));   % low  quantile
zhi  = quantile(data,1 - pc / 2); % high quantile
tndx = find((data >= zlow & data <= zhi & ~isnan(data)));

tM=mean(data(tndx)); % mean with excluded pc/2*100% of highest and lowest values
tSD=std(data(tndx)); % trimmed SD

% Selected central tendency estimator
%------------------------------------
cte=M;

% Normal fit
%-----------
if istats
	alpha=0.05;          % 1-alpha confidence interval
	[muhat,sigmahat,muci,sigmaci] = normfit(data,alpha);
end

nbins=max(50,round(pnts/100));
[nel,binpos]=hist(data,nbins);
dx=binpos(2)-binpos(1);               % bin width

datafit=normpdf(binpos,cte,SD);       % estimated pdf
datafit=datafit*pnts*dx;

tdatafit=normpdf(binpos,cte,tSD);     % estimated pdf with trimmed SD
tdatafit=tdatafit*pnts*dx;

%datarnd=normrnd(cte,sigmahat,1,pnts); % synthetic data

if istats
	% Goodness-of-fit hypothesis test
	%--------------------------------
	kstail = 0; % 0 = 2-sided test

	CDF=normcdf(data,cte,sigmahat);        % estimated cdf

	[ksh,ksp,ksstat,kscv] = kstest(data,[data', CDF'],alpha,kstail); % Kolmogorov-Smirnov test

	kstestlab='Kolmogorov-Smirnov test: verified Gaussian';
	kscol=[0.2 1 0.2];
	if ksh
		kstestlab='Kolmogorov-Smirnov test: not Gaussian';
		kscol=[.7 .3 .3];
	end
end

% Graphics
%-------------------------------------

if plotlab
  figure
  try, icadefs; set(gcf, 'color', BACKCOLOR); catch, end
  COLOR = [0.56 .66 .9];
  set(gcf,'NumberTitle','off','Name','Signal statistics -- signalstat()')
  fwidth=800;  % figure size in pixels
  fheight=600;

  funits=get(0,'Units');
  set(0,'Units','Pixel')
  scnsize=get(0,'ScreenSize');
  fpos=[round((scnsize(3)-fwidth)/2),round((scnsize(4)-fheight)/2),fwidth,fheight];
  set(0,'Units',funits)

  set(gcf,'Position',fpos)

  % Plotting the histogram
  %------------------------
  subplot(2,2,1)

  hist(data,nbins);  % 'XLim',[-125 125]
  uapos = get(gca,'Position');
  xlim  = get(gca,'XLim');
  set(gca,'FontSize',14)
  xlabel(dlabel)
  title('Data Histogram and Fitted Normal PDF')

  % HM=pnts*normpdf(M,muhat,sigmahat)/2; % FWHM height
  % plot([cte-sd cte+sd],[HM HM],'r--','LineWidth',2)

  % Overplotting a normal distribution
  %-----------------------------------
  hold on
  h1=plot(binpos,datafit,'c','LineWidth',2);
  set(gca,'XLim',xlim)

  % Overplotting a normal distribution from trimmed SD
  %---------------------------------------------------
  h2=plot(binpos,tdatafit,'y');
  ymin=get(gca,'YLim');
  plot([zlow zlow],[0 ymin(2)/20],'y','LineWidth',2) % low  percentile
  plot([zhi  zhi], [0 ymin(2)/20],'y','LineWidth',2) % high percentile
  set(gca,'XLim',xlim)

  % Overplotting a mean and zero line
  %----------------------------------
 % xmin=get(gca,'XLim');
 % ymin=get(gca,'YLim');
  plot([0 0],ymin,'k')
  h3=plot([cte cte],ymin,'r--','LineWidth',2);
  set(gca,'Color',COLOR,'XMinorTick','on','XLim',xlim)

  if istats
	  set(gca,'XTick',[])
  elseif ~istats && strcmp(dlabel,'Potential [V]')
	  set(gca,'XTick',[-125, -75, -25, 0, 25, 75,  125],...
			  'XTickLabel',['-125' ; ' -75' ; ' -25' ; '  0 ' ; ' 25 ' ; ' 75 ' ; ' 125'])
  end

  if strcmp(dlabel,'Potential [V]')
	  set(gca,'XLim',[-125 125])
  end

  set(gca,'FontSize',10)
  H=[h1 h2 h3];
  legend(H,'Gaussian fit','Trimmed G.fit','Mean')
  legend boxoff

  zoom off

  % Boxplot
  %--------------------
  if istats
	  subplot(2,2,3)

	  boxplot(data,1,'+',0,1.5)
	  lapos=get(gca,'Position');
	  set(gca,'Position', [uapos(1) uapos(2)-uapos(4)/3 uapos(3) uapos(4)/3])
	  nlapos=get(gca,'Position');
	  hold on
	  ymin2=get(gca,'YLim');
	  plot([0 0],[0 ymin2(2)],'k')
	  plot([cte cte],[0 ymin(2)],'r--','LineWidth',2)
	  set(gca,'FontSize',14,'XMinorTick','on')
      set(gca,'XLim',xlim)

      if strcmp(dlabel,'Potential [V]')
		  set(gca,'XTick',[-125 -75 -25 0 25 75  125],...
				  'XTickLabel',['-125' ; ' -75' ; ' -25' ; '  0 ' ; ' 25 ' ; ' 75 ' ; ' 125'],...
				  'XLim',[-125 125])
	  end

	  xlabel(dlabel)
	  ylabel('')
	  zoom off
  end

  % QQ plot
  %--------
  subplot(2,2,2)

  qqdiagram(data)
  apos=get(gca,'Position');
  set(gca,'Position', [1-uapos(1)-uapos(3) uapos(2)-uapos(4)/3 (uapos(3)) (uapos(4)+uapos(4)/3)])
  set(gca,'XTick',[-4 -2 0 2 4])
  xmin=get(gca,'XLim');
  ymin=get(gca,'YLim');
  hold on
  plot([xmin(1) xmin(1)+diff(xmin)/20],[zlow zlow],'y-','LineWidth',2)
  plot([xmin(1) xmin(1)+diff(xmin)/20],[zhi  zhi] ,'y-','LineWidth',2)
  set(gca,'XLim',xmin);
  %plot([0 0],ymin,'k--')
  set(gca,'FontSize',14)
  xlabel('Standard Normal Quantiles [Std.Dev.]')
  if strcmp(dlabel,'Potential [V]')
	  ylabel('Ordered Observations [V]')
  elseif strcmp(dlabel,'Component Activity')
	  ylabel('Ordered Observations [rel. V]')
  else
	  ylabel('Ordered Observations')
  end

  title('QQ Plot (Data vs Standard Normal)')
  set(gca,'Color',COLOR)

  % TOPO plot
  %---------
  if (~isempty(map))
	  sbplot(7,9,6)
	  % th=axes('Position',[]);
	  % subplot('Position',[.10 .86 .20 .14]);
	  fprintf('signalstat(): plotting a topographic map...\n');
	  if length(map) == 1
		  topoplot(map,chan_locs,'electrodes','off', ...
				   'style', 'blank', 'emarkersize1chan', 10);
	  else
		  topoplot(map,chan_locs,'electrodes','off');
	  end
	  axis('square')
  end

  % Color schemes
  %--------------
  nero    = [0 0 0];
  bordeau = [0.7 0.3 0.3];
  rosso   = [1 0 0];
  roschi1 = [1 .3 0.4];
  giallo1 = [1 .9 0];
  arancio = [1 .5 .3];
  verchi1 = [0.2 1 0.2];
  verchi2 = [0.7 1 0.7];
  verchi3 = [0.4 1 0.4];
  verscu1 = [0.1 0.7 0.2];
  bluchi1 = [0.4 0.9 1];
  bluchi2 = [.2 .5 .7];
  grichia = [.95 .95 .95];

  % Data axis
  %------------
  bgcolor=COLOR;

  dah = axes('Position',[uapos(1) .1 1-2*uapos(1) .25]);
  set(dah,'Box','on','Color',bgcolor,'XTick',[],'YTick',[],'FontName','Courier','FontSize',12,'FontWeight','demi')
  title(dlabel2,'FontWeight','bold','FontSize',14,'FontName','Arial');
  text(0.05,0.9,['Mean:          ' num2str(M,3)]  ,'Color',bordeau,'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.05,0.8,['Trimmed mean:  ' num2str(tM,3)] ,'Color',giallo1,'FontName','Courier','FontSize',12,'FontWeight','demi')

  text(0.05,0.5,['Standard dev.: ' num2str(SD,4)] ,'Color',bordeau,'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.05,0.4,['Trimmed st.d.: ' num2str(tSD,4)],'Color',giallo1,'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.05,0.3,['Variance:      ' num2str(vr,4)] ,'Color',giallo1,'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.05,0.2,['Range:         ' num2str(rg,4)] ,'Color',giallo1,'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.05,0.1,['Data points:   ' num2str(pnts)] ,'Color',bordeau,'FontName','Courier','FontSize',12,'FontWeight','demi')

  text(0.4,0.9,[num2str(percent/2/100,'%1.3f') '-quantile: ' num2str(zlow,3)] ,'Color',verchi2,...
	   'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.4,0.8,['0.5  -quantile: ',num2str(med,3),'  (median)'],'Color',verchi1,'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.4,0.7,[num2str((100-percent/2)/100,'%1.3f') '-quantile:  ' num2str(zhi,3)] ,'Color',verchi2,...
	   'FontName','Courier','FontSize',12,'FontWeight','demi')

  text(0.4,0.3,['Excess kurtosis: ' num2str(k, 3) ' (near 0 if Gaussian)'] ,'Color',verchi1,...
				'FontName','Courier','FontSize',12,'FontWeight','demi')
  text(0.4,0.2,klab,'Color',verchi2,'FontName','Courier','FontSize',12,'FontWeight','demi')

  if istats
	  text(0.4,0.5,['Skewness: ' num2str(sk,3) ' (near 0 if Gaussian)'] ,'Color',verchi1,...
		   			'FontName','Courier','FontSize',12,'FontWeight','demi')
	  text(0.4,0.4,sklab,'Color',verchi2,'FontName','Courier','FontSize',12,'FontWeight','demi')
      text(0.4,0.1,kstestlab,'Color',kscol,'FontName','Courier','FontSize',12,'FontWeight','demi')
  end
  axcopy;
end

%--------------------------------------------------
% clone of the normpdf function of the stat toolbox
function fitvals = normpdf(myvals,mymean,mystd)
if nargin < 3,
    mystd = 1;
end
if nargin < 2;
    mymean = 0;
end
if length(mymean) < length(myvals)
	tmpmean = mymean;
	mymean = zeros(size(myvals));
	mymean(:) = tmpmean;
end
if length(mystd) < length(myvals)
	tmpmean = mystd;
	mystd = zeros(size(myvals));
	mystd(:) = tmpmean;
end
mymean(1:10);
mystd(1:10);

fitvals = zeros(size(myvals));
tmp = find(mystd > 0);
if any(tmp)
    myvalsn = (myvals(tmp) - mymean(tmp)) ./ mystd(tmp);
    fitvals(tmp) = exp(-0.5 * myvalsn .^2) ./ (sqrt(2*pi) .* mystd(tmp));
end
tmp1 = find(mystd <= 0);
if any(tmp1)
    tmp2   = NaN;
    fitvals(tmp1) = tmp2(ones(size(tmp1)));
end


function[S,tau,tc] = staogram(data_spk,data_lfp,smp,plt,Tc,Tinc,Tw,w,D)
%
% staogram : calculates a moving window spike triggered ave %
%   Usage:[S,tau,tc] = staogram(data_spk,data_lfp,smp,plt,Tc,Tinc,Tw,w,D)
%
%                 ******** INPUT *********
% Note that all times have to be consistent. If data_spk
% is in seconds, so must be sig and t. If data_spk is in
% samples, so must sig and t. The default is seconds.
%
% data_spk    - strucuture array of spike times data
% data_lfp    - array of lfp data(samples x trials)
% smp         - lfp times of samples
%
% Optional...
%
% Parameter
%
% plt     'y'|'n'
%
% 'y' standard staogram
% 'n' no plot
%
% Tc = start and end times (centres)           whole trial
% Tinc = time increment between windows             0.1
% Tw = time window width                          0.3
% w = smoothing width in seconds
% D = plot sta out to on axis [D(1) D(2)] s
%
%                ******** OUTPUT ********
%  S spike triggered average
%  tau - lag
%  tc  - bin centers

% setup defaults...
if nargin < 3;error('Require spike, lfp and lfptimes ');end
[data_spk]=padNaN(data_spk); % create a zero padded data matrix from input structural array
data_spk=data_spk'; % transposes data to get it in a form compatible with Murray's routine
if nargin < 4; plt = 'y';end
if nargin < 6; Tinc = 0.1; end
if nargin < 7; Tw = 0.5;end
if nargin < 8; w = 0.01;end
if nargin < 9; D = 0.15*[-1 1]; end
if nargin < 5;
    Tc(1) = min(data_spk(:,1)) + Tw/2;
    Tc(2) = max(max(data_spk)) - Tw/2;
end

if isempty(plt); plt = 'y';end
if isempty(Tinc); Tinc = 0.1; end
if isempty(Tw); Tw = 0.5;end
if isempty(w); w = 0.01;end
if isempty(D); D = 0.15*[-1 1]; end
if isempty(Tc);
    Tc(1) = min(data_spk(:,1)) + Tw/2;
    Tc(2) = max(max(data_spk)) - Tw/2;
end

%  round to nearest tinc...

t = smp;
Tc(1) = ceil(Tc(1)/Tinc)*Tinc;
Tc(2) = floor(Tc(2)/Tinc)*Tinc;
tc = Tc(1):Tinc:Tc(2);
for tt=1:length(tc)
  T = [tc(tt)-Tw/2 tc(tt)+Tw/2];
  if tt == 1
    [SS,tau] = sta(data_spk,data_lfp,t,'y',w,T,D,0);
    S = zeros(length(tc),length(SS));
  else
    [SS,tau] = sta(data_spk,data_lfp,t,'y',w,T,D,0);
  end
  S(tt,:) = SS';
  S(tt,:) = SS';
end

if ~strcmp(plt,'n')
  imagesc(tc,tau,squeeze(S)')
  set(gca,'ydir','normal')
  xlabel('time (s)')
  ylabel('frequency (Hz)')
  colorbar;
%  axes(h)
%  line(get(h,'xlim'),conf_C*[1 1],'color','k','linewidth',5)
end


function y=logsum(x,d)
%LOGSUM logsum(x,d)=log(sum(exp(x),d))
%  d gives dimension to sum along

%      Copyright (C) Mike Brookes 1998
%
%      Last modified Mon Oct 12 15:47:25 1998
%
%   VOICEBOX is a MATLAB toolbox for speech processing. Home page is at
%   http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%

if nargin==1
   d=[find(size(x)-1) 1];
   d=d(1);
end
n=size(x,d);
if n<=1, y=x; return; end
s=size(x);
p=[d:ndims(x) 1:d-1];
z=reshape(permute(x,p),n,prod(s)/n);

y=max(z);
y=y+log(sum(exp(z-y(ones(n,1),:))));

s(d)=1;
y=ipermute(reshape(y,s(p)),p);


function xyr = Xr(s)
x = 1+2*s-2*s^2 ;
y = s ;

xyr = [x ; y] ;


function M = mtkronprod(T,U,n,transpose)
%MTKRONPROD Compute a matricized tensor Kronecker product.
%   mtkronprod(T,U,n) computes the product
%
%      tens2mat(T,n)*conj(kron(U([end:-1:n+1 n-1:-1:1])))
%
%   without permuting the tensor T. Note that for improved performance, it
%   is advisable for the largest two dimensions of T to be the first and
%   last modes of T.
%
%   mtkronprod(T,U,n,'T') and mtkronprod(T,U,n,'H') transpose or complex
%   conjugate transpose the matrices U{n} before computing the matricized
%   tensor Kronecker product.

%   Authors: Laurent Sorber (Laurent.Sorber@cs.kuleuven.be)
%            Marc Van Barel (Marc.VanBarel@cs.kuleuven.be)
%            Lieven De Lathauwer (Lieven.DeLathauwer@kuleuven-kulak.be)
%
%   References:
%   [1] L. Sorber, M. Van Barel, L. De Lathauwer, "Structured data fusion,"
%       ESAT-SISTA Internal Report 13-177, KU Leuven, 2013.

if nargin < 4, transpose = 0; end
if ischar(transpose)
    if strcmp(transpose,'T'), transpose = 1;
    elseif strcmp(transpose,'H'), transpose = 1i; end
end
U = U(:).';
if transpose == 0, size_tens = cellfun('size',U,1);
else size_tens = cellfun('size',U,2); end
data = T;
if isstruct(T)
    % Incomplete or sparse tensor.
    T = data.matrix;
    alloc = @sparse;
else
    % Full tensor.
    alloc = @zeros;
end
N = length(size_tens);
if transpose == 0, size_core = cellfun('size',U,2);
else size_core = cellfun('size',U,1); end
if n > 0, size_core(n) = size_tens(n); end
R = prod(size_core([1:n-1 n+1:N]));

% Determine if large-scale version of the algorithm should be executed.
ratio = size_core./size_tens;
perm = zeros(1,N);
l = 1; r = N;
for i = 1:N
    if r == n || (l < n && ratio(l) < ratio(r)), perm(i) = l; l = l+1;
    else perm(i) = r; r = r-1;
    end
end
if n == 0, mem = 8*prod(size_tens);
else mem = 8*prod(size_tens([1:perm(1)-1 perm(1)+1:N]))*size_core(perm(1));
end
largescale = mem > 2e9 || (isstruct(data) && isempty(data.matrix));
if largescale && ~isstruct(data)
    error('mtkronprod:mem',['Intermediate result is too large. Try ' ...
        'to format data with fmt first so that the large-scale ' ...
        'version of the algorithm can be applied.']);
end

if largescale

    % The large scale implementation fires if the required memory would
    % otherwise be larger than 2GB and assumes the dataset has been
    % formatted by fmt.
    idx = [1:n-1 n+1:N];
    jdx = cell(1,N);
    switch transpose
        case 0,  U = cellfun(@(u)conj(u),U,'UniformOutput',false);
        case 1,  U = cellfun(@(u)u',U,'UniformOutput',false);
        case 1i, U = cellfun(@(u)u.',U,'UniformOutput',false);
    end
    if n == 0, M = zeros(1,R);
    else M = zeros(size_tens(n),R); end
    for r = 1:R
        s = data.val;
        [jdx{:}] = ind2sub(size_core([1:n-1 n+1:N]),r);
        for j = 1:length(idx)
            s = s.*U{idx(j)}(data.sub{idx(j)},jdx{j});
        end
        if n == 0, M(r) = sum(s);
        else M(:,r) = accumarray(double(data.sub{n}),s,[size_tens(n) 1]);
        end
    end

else

    % Apply structure-exploiting matricized tensor Kronecker product.
    M = T;
    cpl = cumprod([1 size_core(perm(perm < n))]); l = 1;
    cpr = cumprod([1 size_core(perm(perm > n))]); r = 1;
    for i = 1:length(perm)

        mode = perm(i);
        if mode < n

            tmp = reshape(M,cpl(l)*size_tens(mode),[]);
            M = alloc(cpl(l),size(tmp,2)*size_core(mode));
            for j = 1:cpl(l)
                idx = j:cpl(l):size(tmp,1);
                switch transpose
                    case 0,  tmp2 = U{mode}'*tmp(idx,:);
                    case 1,  tmp2 = conj(U{mode})*tmp(idx,:);
                    case 1i, tmp2 = U{mode}*tmp(idx,:);
                end
                M(j,:) = tmp2(:);
            end
            l = l+1;

        elseif mode > n

            tmp = reshape(M,[],cpr(r)*size_tens(mode));
            M = alloc(size(tmp,1)*size_core(mode),cpr(r));
            for j = 1:cpr(r)
                idx = (1:size_tens(mode))+(j-1)*size_tens(mode);
                switch transpose
                    case 0,  tmp2 = tmp(:,idx)*conj(U{mode});
                    case 1,  tmp2 = tmp(:,idx)*U{mode}';
                    case 1i, tmp2 = tmp(:,idx)*U{mode}.';
                end
                M(:,j) = tmp2(:);
            end
            r = r+1;

        end

    end

    % Permute and reshape output.
    if n > 1
        if issparse(M)
            idx = find(M);
            [i,j,k] = ind2sub([cpl(end) size_tens(n) cpr(end)],idx);
            ik = sub2ind([cpl(end) cpr(end)],i,k);
            M = sparse(j,ik,full(M(idx)),size_tens(n),cpl(end)*cpr(end));
        else
            M = reshape(M,[cpl(end) size_tens(n) cpr(end)]);
            M = reshape(permute(M,[2 1 3]),size_tens(n),[]);
        end
    else
        if n == 0, M = reshape(M,1,[]);
        else M = reshape(M,size_tens(n),[]); end
    end

end

end


function eps_trial = eps_RCUs_Alamouti_stable(R, Mr, L, np, nc, rho, spa,...
                RELSPREAD_MAX, N_MC_MIN, N_MC_MAX, N_REP_TRIALS, d_verbose)
%EPS_RCUS_ALAMOUTI_STABLE returns the error probability computed via RCUs
%in a system using Alamouti coding (Mt=2 tx antennas) with parameters:
%R (rate), Mr (number of rx antennas), L (number of blocks),
%np (number of pilots), nc (size of coherence block), rho (SNR linear).

	% Default values for parameters that are not passed
    if nargin < 12
        d_verbose = 2;      % set verbosity
    end

    if nargin < 11
        ncores = feature('numcores');   % number of cores on current machine
        nworkers = ncores;              % use ncores-1 in parallel
        poolobj = gcp('nocreate');      % if no pool do not create new one
        if isempty(poolobj)
            parpool(nworkers);          % initialise the pool
        end
        % choose N_REP_TRIALS a multiple of no. of workers for high
        % efficiency
        N_REP_TRIALS = 3 * poolobj.NumWorkers;
    end

    if nargin < 10
        N_MC_MAX = 2^19;    % maximum number of Monte Carlo iterations
    end

    if nargin < 9
        N_MC_MIN = 2^10;    % initial number of Monte Carlo iterations
    end

    if nargin < 8
        RELSPREAD_MAX = 0.50;   % max relative spread of outcomes
    end

    if nargin < 7
        spa = 0;
    end
    % Algorithm parameters

    N_MC = min([N_MC_MIN N_MC_MAX]);	% initial number of Monte Carlo trials

    % Algorithm
    n = nc * L;
    b_iter = 1;

    if d_verbose >= 1
        fprintf([' Estimating Pe with ' ...
            '%d trials...\n'],N_MC);
    end

    while b_iter == 1

        eps_trial = zeros(N_REP_TRIALS,1);

        parfor i_trial = 1:N_REP_TRIALS
            if spa == 0
                % Generate information density samples
                i_s = idsamples_Alamouti(Mr, L, np, nc, rho, N_MC);

                % Compute error probability
                eps_trial(i_trial) = eps_RCUs(i_s, n, R);
            else %saddlepoint approximation
                % Generate information density samples with L = 1
                i_s = idsamples_Alamouti(Mr, 1, np, nc, rho, N_MC);

                % Compute error probability using saddlepoint approximation
                eps_trial(i_trial) = eps_RCUs_SPA(i_s, n, L, R);
            end

        end

        % Check spread of data
        relspread_eps = relspread(eps_trial); % relative spread

        if d_verbose >= 2
            fprintf('  %.3e', eps_trial);
            fprintf('\n  Relative spread: %.3e\n', relspread_eps);
        end

        % Stopping conditions
        if relspread_eps < RELSPREAD_MAX % accuracy reached
            b_iter = 0;
            if d_verbose >= 1
                fprintf(' Estimation accuracy reached with %d trials.\n',N_MC);
            end
        else
            if 2 * N_MC <= N_MC_MAX
                N_MC = 2 * N_MC;
                if d_verbose >= 1
                    fprintf(['  Accuracy not reached: '...
                        'trying estimation of Pe with ' ...
                        '%d trials...\n'], N_MC);
                end
            else
                b_iter = 0;
                if d_verbose >= 1
                    warning('::Relative accuracy target not reached');
                end
            end
        end
    end

end % of function


    L = iread('rocks2-l.png', 'reduce', 2);
R = iread('rocks2-r.png', 'reduce', 2);
stdisp(L, R)
d = istereo(L, R, [40, 90], 3, 'interp');
idisp(d, 'bar');
Z = 3740*0.160 ./ d;

clf;
surf(Z)
shading interp; view(-150, 75)
set(gca, 'ZDir', 'reverse'); set(gca, 'XDir', 'reverse');
colormap(flipud(hot))

anaglyph(L,R)


%% sigmoid_pchip
% Below is a demonstration of the features of the |sigmoid_pchip| function

%%
clear; close all; clc;

%% Syntax
% |[s]=sigmoid_pchip(optStruct)|

%% Description
% UNDOCUMENTED

%% Examples

%%
% Plot settings
plotColors=gjet(250);
fontSize=15;

%% Creating sigmoid curves with prescribed start and end slopes

%%

n=10;
plotColor=gjet(n);
nPlot=2000;
t=linspace(0,1,nPlot)';

optStruct.nLin=10;
optStruct.rMode=1;
optStruct.n=nPlot;

%%
% Varying slope with matched slopes

cFigure;
hold on;
title('Slope variation','fontSize',fontSize);

c1_q=linspace(0,1,n); %Slope variations
for q=1:1:n

    optStruct.c1=c1_q(q);
    optStruct.c2=optStruct.c1;
    optStruct.r1=0.4;
    optStruct.r2=optStruct.r1;

    [Vi]=sigmoid_pchip(optStruct);

    hp=plotV(Vi,'r-','LineWidth',3); set(hp,'Color',plotColor(q,:));
end

plotV([t(:) t(:)],'k--','LineWidth',5);
colormap(gjet(250)); colorbar; caxis([min(c1_q) max(c1_q)]);
axis tight; axis equal; hold on; box on; grid on; view(2);
set(gca,'FontSize',15);
drawnow;

%%
% Varying slope with different start/end slopes

cFigure;
hold on;
title('Slope variation','fontSize',fontSize);

c1_q=linspace(0,1,n); %Slope variations
for q=1:1:n

    optStruct.c1=c1_q(q);
    optStruct.c2=optStruct.c1/2;
    optStruct.r1=0.25;
    optStruct.r2=optStruct.r1;

    [Vi]=sigmoid_pchip(optStruct);

    hp=plotV(Vi,'r-','LineWidth',3); set(hp,'Color',plotColor(q,:));
end

plotV([t(:) t(:)],'k--','LineWidth',5);
colormap(gjet(250)); colorbar; caxis([min(c1_q) max(c1_q)]);
axis tight; axis equal; hold on; box on; grid on; view(2);
set(gca,'FontSize',15);
drawnow;

%%
% Varying extent of slope at ends

cFigure;
hold on;
title('Extent variation','fontSize',fontSize);

r1_q=linspace(0.1,0.4,n); %Extent variations
for q=1:1:n

    optStruct.c1=0.25;
    optStruct.c2=optStruct.c1;
    optStruct.r1=r1_q(q);
    optStruct.r2=optStruct.r1;

    [Vi]=sigmoid_pchip(optStruct);

    hp=plotV(Vi,'r-','LineWidth',3); set(hp,'Color',plotColor(q,:));
end

plotV([t(:) t(:)],'k--','LineWidth',5);
plotV([t(:) optStruct.c1*t(:)],'k--','LineWidth',5);
plotV([t(:) optStruct.c1*t(:)+(1-optStruct.c1)],'k--','LineWidth',5);
colormap(gjet(250)); colorbar; caxis([min(r1_q) max(r1_q)]);
axis tight; axis equal; hold on; box on; grid on; view(2);
set(gca,'FontSize',15);
drawnow;

%%
% Varying number of points on the initial linear slope

optStruct.c1=0.2;
optStruct.c2=optStruct.c1;
optStruct.r1=0.35;
optStruct.r2=optStruct.r1;
optStruct.rMode=1;
optStruct.n=nPlot;

cFigure;
hold on;
title('Extent variation','fontSize',fontSize);

nLin_q=2:1:10; %Extent variations
n=numel(nLin_q);
for q=1:1:n

    optStruct.nLin=nLin_q(q);

    [Vi]=sigmoid_pchip(optStruct);

    hp=plotV(Vi,'r-','LineWidth',3); set(hp,'Color',plotColor(q,:));
end

plotV([t(:) t(:)],'k--','LineWidth',5);
plotV([t(:) optStruct.c1*t(:)],'k--','LineWidth',5);
plotV([t(:) optStruct.c1*t(:)+(1-optStruct.c1)],'k--','LineWidth',5);
colormap(gjet(250)); colorbar; caxis([min(nLin_q) max(nLin_q)]);
axis tight; axis equal; hold on; box on; grid on; view(2);
set(gca,'FontSize',15);
drawnow;

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function [LD,p,q] = ldlchol (A,beta)					    %#ok
%LDLCHOL sparse A=LDL' factorization
%   Note that L*L' (LCHOL) and L*D*L' (LDLCHOL) factorizations are faster than
%   R'*R (CHOL2 and CHOL) and use less memory.  The LL' and LDL' factorization
%   methods use tril(A).  A must be sparse.
%
%   Example:
%   LD = ldlchol (A)            return the LDL' factorization of A
%   [LD,p] = ldlchol (A)        similar [R,p] = chol(A), but for L*D*L'
%   [LD,p,q] = ldlchol (A)      factorizes A(q,q) into L*D*L', where q is a
%                               fill-reducing ordering
%
%   LD = ldlchol (A,beta)       return the LDL' factorization of A*A'+beta*I
%   [LD,p] = ldlchol (A,beta)   like [R,p] = chol(A*A'+beta+I)
%   [LD,p,q] = ldlchol (A,beta) factorizes A(q,:)*A(q,:)'+beta*I into L*D*L'
%
%   The output matrix LD contains both L and D.  D is on the diagonal of LD, and
%   L is contained in the strictly lower triangular part of LD.  The unit-
%   diagonal of L is not stored.  You can obtain the L and D matrices with
%   [L,D] = ldlsplit (LD).  LD is in the form needed by ldlupdate.
%
%   Explicit zeros may appear in the LD matrix.  The pattern of LD matches the
%   pattern of L as computed by symbfact2, even if some entries in LD are
%   explicitly zero.  This is to ensure that ldlupdate and ldlsolve work
%   properly.  You must NOT modify LD in MATLAB itself and then use ldlupdate
%   or ldlsolve if LD contains explicit zero entries; ldlupdate and ldlsolve
%   will fail catastrophically in this case.
%
%   You MAY modify LD in MATLAB if you do not pass it back to ldlupdate or
%   ldlsolve.  Just be aware that LD contains explicit zero entries, contrary
%   to the standard practice in MATLAB of removing those entries from all
%   sparse matrices.  LD = sparse2 (LD) will remove any zero entries in LD.
%
%   See also LDLUPDATE, LDLSOLVE, LDLSPLIT, CHOL2, LCHOL, CHOL, SPARSE2

%   Copyright 2006-2007, Timothy A. Davis
%   http://www.cise.ufl.edu/research/sparse

error ('ldlchol mexFunction not found') ;


%SOLVEEIG Solve eigenvalue problem.
%
%   [ U, L ] = SOLVEEIG( PROB, VARARGIN ) Solves the eigenvalue
%   problem described in the PROB finite element struct with
%   homogenous boundary conditions, and returns the eigenvectors U and
%   eigenvalues L. Accepts the following property/value pairs.
%
%       Input       Value/{Default}              Description
%       -----------------------------------------------------------------------------------
%       neigs       scalar/{6}                   Number of eigenvalues
%       sigma       scalar/string/{sm}           Range or type of eigenvalues
%                                                  see the eigs function for options
%       imass       scalar/{4}                   Mass matrix lumping
%                                                  1 - Full mass matrix
%                                                  2 - row sum lumping
%                                                  3 - diagonal lumping
%                                                  4 - HRZ diagonal lumping
%       init        u0|{expr}/{0}                Initial value solution or expression
%                                                for linearization point
%       solcomp     {all dvars}                  Dep. variables/subdomains to solve for
%       icub        scalar/{auto}                Cubature rule/order used in assembly
%                                                Default 1+max(shape function order)
%       isymm       scalar/{0}                   Symmetrize BCs if applicable
%       waitbar     scalar/{0}                   Show waitbar
%       fid         scalar/{1}                   File identifier for output ([]=no output)
%
%   See also EIGS, SOLVESTAT, SOLVETIME

% Copyright 2013-2022 Precise Simulation, Ltd.