function zi = interp2_mine(varargin)
%INTERP2 2-D interpolation (table lookup).
%   ZI = INTERP2(X,Y,Z,XI,YI) interpolates to find ZI, the values of the
%   underlying 2-D function Z at the points in matrices XI and YI.
%   Matrices X and Y specify the points at which the data Z is given.
%
%   XI can be a row vector, in which case it specifies a matrix with
%   constant columns. Similarly, YI can be a column vector and it
%   specifies a matrix with constant rows.
%
%   ZI = INTERP2(Z,XI,YI) assumes X=1:N and Y=1:M where [M,N]=SIZE(Z).
%   ZI = INTERP2(Z,NTIMES) expands Z by interleaving interpolates between
%   every element, working recursively for NTIMES.  INTERP2(Z) is the
%   same as INTERP2(Z,1).
%
%   ZI = INTERP2(...,METHOD) specifies alternate methods.  The default
%   is linear interpolation.  Available methods are:
%
%     'nearest' - nearest neighbor interpolation
%     'linear'  - bilinear interpolation
%     'spline'  - spline interpolation
%     'cubic'   - bicubic interpolation as long as the data is
%                 uniformly spaced, otherwise the same as 'spline'
%
%   For faster interpolation when X and Y are equally spaced and monotonic,
%   use the syntax ZI = INTERP2(...,*METHOD).
%
%   ZI = INTERP2(...,METHOD,EXTRAPVAL) specificies a method and a scalar
%   value for ZI outside of the domain created by X and Y.  Thus, ZI will
%   equal EXTRAPVAL for any value of YI or XI which is not spanned by Y
%   or X respectively. A method must be specified for EXTRAPVAL to be used,
%   the default method is 'linear'.
%
%   All the interpolation methods require that X and Y be monotonic and
%   plaid (as if they were created using MESHGRID).  If you provide two
%   monotonic vectors, interp2 changes them to a plaid internally.
%   X and Y can be non-uniformly spaced.
%
%   For example, to generate a coarse approximation of PEAKS and
%   interpolate over a finer mesh:
%       [x,y,z] = peaks(10); [xi,yi] = meshgrid(-3:.1:3,-3:.1:3);
%       zi = interp2(x,y,z,xi,yi); mesh(xi,yi,zi)
%
%   Class support for inputs X, Y, Z, XI, YI:
%      float: double, single
%
%   See also INTERP1, INTERP3, INTERPN, MESHGRID, TriScatteredInterp.

%   Copyright 1984-2011 The MathWorks, Inc.
%   $Revision: 5.33.4.24 $  $Date: 2011/05/17 02:32:27 $

% error(nargchk(1,7,nargin,'struct')); % allowing for an ExtrapVal

bypass = false;
uniform = true;
if (nargin > 1)
    if nargin == 7 && ~isnumeric(varargin{end})
        error(message('MATLAB:interp2:extrapvalNotNumeric'));
    end
    if ischar(varargin{end})
        narg = nargin-1;
        method = [varargin{end} '    ']; % Protect against short string.
        if strncmpi(method,'s',1) || strncmpi(method, '*s', 2)
            ExtrapVal = 'extrap'; % Splines can extrapolate
        else
            ExtrapVal = nan; % setting default ExtrapVal as NAN
        end
        index = 1; %subtract off the elements not in method
    elseif ischar(varargin{end-1}) && isnumeric(varargin{end})
        narg = nargin-2;
        method = [ varargin{end-1} '    '];
        ExtrapVal = varargin{end}; % user specified ExtrapVal
        index = 2; % subtract off the elements not in method and ExtrapVal
    else
        narg = nargin;
        method = 'linear';
        ExtrapVal = nan; % protecting default
        index = 0;
    end
    if strncmpi(method,'*',1) % Direct call bypass.
        if (narg ==5 || narg ==3)
            xitemp = varargin{end-index - 1};
            yitemp = varargin{end-index};
            if isrow(xitemp) && iscolumn(yitemp)
                varargin{end-index - 1} = repmat(xitemp, [size(yitemp,1), 1]);
                varargin{end-index} = repmat(yitemp, [1, size(xitemp,2)]);
            elseif iscolumn(xitemp) && isrow(yitemp)
                varargin{end-index - 1} = repmat(xitemp', [size(yitemp, 2), 1]);
                varargin{end-index} = repmat(yitemp', [1, size(xitemp,1)]);
            end
        end
        if strcmpi(method(2),'l') || strcmpi(method(2:4),'bil')
            % bilinear interpolation.
            zi = linear(ExtrapVal, varargin{1:end-index});
            return
        elseif strcmpi(method(2),'c') || strcmpi(method(2:4),'bic')
            % bicubic interpolation
            zi = cubic(ExtrapVal, varargin{1:end-index});
            return
        elseif strcmpi(method(2),'n')
            % Nearest neighbor interpolation
            zi = nearest(ExtrapVal, varargin{1:end-index});
            return
        elseif strcmpi(method(2),'s')
            % spline interpolation
            method = 'spline'; bypass = true;
        else
            error(message('MATLAB:interp2:InvalidMethod', deblank( method )));
        end
    elseif strncmpi(method,'s',1), % Spline interpolation
        method = 'spline'; bypass = true;
    end
else
    narg = nargin;
    method = 'linear';
    ExtrapVal = nan; % default ExtrapVal is NaN
end

% if narg==1, % interp2(z), % Expand Z
%     [nrows,ncols] = size(varargin{1});
%     xi = 1:.5:ncols; yi = (1:.5:nrows)';
%     x = 1:ncols; y = 1:nrows;
%     [msg,x,y,z,xi,yi] = xyzchk(x,y,varargin{1},xi,yi);
%
% elseif narg==2. % interp2(z,n), Expand Z n times
%     [nrows,ncols] = size(varargin{1});
%     ntimes = floor(varargin{2}(1));
%     xi = 1:1/(2^ntimes):ncols; yi = (1:1/(2^ntimes):nrows)';
%     x = 1:ncols; y = 1:nrows;
%     [msg,x,y,z,xi,yi] = xyzchk(x,y,varargin{1},xi,yi);
%
% elseif narg==3, % interp2(z,xi,yi)
%     [nrows,ncols] = size(varargin{1});
%     x = 1:ncols; y = 1:nrows;
%     [msg,x,y,z,xi,yi] = xyzchk(x,y,varargin{1:3});
%
% elseif narg==4,
%     error(message('MATLAB:interp2:nargin'));

% elseif narg==5, % linear(x,y,z,xi,yi)
%     [msg,x,y,z,xi,yi] = xyzchk(varargin{1:5});
%
% end
x = varargin{1};
y = varargin{2};
z = varargin{3};
xi = varargin{4};
yi = varargin{5};

% if ~isempty(msg)
%     error(message(msg.identifier));
% end

%
% Check for plaid data.
%
xx = x(1,:); yy = y(:,1);
% if (size(x,2)>1 && ~isequal(repmat(xx,size(x,1),1),x)) || ...
%    (size(y,1)>1 && ~isequal(repmat(yy,1,size(y,2)),y)),
%     error(message('MATLAB:interp2:meshgrid'));
% end

%
% Check for non-equally spaced data.  If so, map (x,y) and
% (xi,yi) to matrix (row,col) coordinate system.
%
if ~bypass,
    xx = xx.'; % Make sure it's a column.
    dx = diff(xx); dy = diff(yy);
    xdiff = max(abs(diff(dx))); if isempty(xdiff), xdiff = 0; end
    ydiff = max(abs(diff(dy))); if isempty(ydiff), ydiff = 0; end
    if (xdiff > eps(class(xx))*max(abs(xx))) || (ydiff > eps(class(yy))*max(abs(yy)))
        if any(dx < 0), % Flip orientation of data so x is increasing.
            x = fliplr(x); y = fliplr(y); z = fliplr(z);
            xx = flipud(xx); dx = -flipud(dx);
        end
        if any(dy < 0), % Flip orientation of data so y is increasing.
            x = flipud(x); y = flipud(y); z = flipud(z);
            yy = flipud(yy); dy = -flipud(dy);
        end

        if any(dx<=0) || any(dy<=0),
            error(message('MATLAB:interp2:XorYNotMonotonic'));
        end

        % Bypass mapping code for cubic
        if ~strncmp(method(1),'c',1)
            % Determine the nearest location of xi in x
            [xxi,j] = sort(xi(:));
            [~,i] = sort([xx;xxi]);
            ui(i) = 1:length(i);
            ui = (ui(length(xx)+1:end)-(1:length(xxi)))';
            ui(j) = ui;

            % Map values in xi to index offset (ui) via linear interpolation
            ui(ui<1) = 1;
            ui(ui>length(xx)-1) = length(xx)-1;
            ui = ui + (xi(:)-xx(ui))./(xx(ui+1)-xx(ui));

            % Determine the nearest location of yi in y
            [yyi,j] = sort(yi(:));
            [~,i] = sort([yy;yyi(:)]);
            vi(i) = 1:length(i);
            vi = (vi(length(yy)+1:end)-(1:length(yyi)))';
            vi(j) = vi;

            % Map values in yi to index offset (vi) via linear interpolation
            vi(vi<1) = 1;
            vi(vi>length(yy)-1) = length(yy)-1;
            vi = vi + (yi(:)-yy(vi))./(yy(vi+1)-yy(vi));

            [x,y] = meshgrid(ones(class(x)):size(x,2),ones(class(y)):size(y,1));
            xi(:) = ui; yi(:) = vi;
        else
            uniform = false;
        end
    end
end

% Now do the interpolation based on method.
if strncmpi(method,'l',1) || strncmpi(method,'bil',3) % bilinear interpolation.
    zi = linear(ExtrapVal,x,y,z,xi,yi);

elseif strncmpi(method,'c',1) || strncmpi(method,'bic',3) % bicubic interpolation
    if uniform
        zi = cubic(ExtrapVal,x,y,z,xi,yi);
    else
        zi = spline2(x,y,z,xi,yi,ExtrapVal);
    end

elseif strncmpi(method,'n',1) % Nearest neighbor interpolation
    zi = nearest(ExtrapVal,x,y,z,xi,yi);

elseif strncmpi(method,'s',1) % Spline interpolation
    % A column is removed from z if it contains a NaN.
    % Orient to preserve as much data as possible.
    [inan, jnan] = find(isnan(z));
    ncolnan = length(unique(jnan));
    nrownan = length(unique(inan));
    if ncolnan > nrownan
        zi = spline2(y',x',z',yi,xi,ExtrapVal);
    else
        zi = spline2(x,y,z,xi,yi,ExtrapVal);
    end
else
    error(message('MATLAB:interp2:InvalidMethod', deblank( method )));

end

%------------------------------------------------------
function F = linear(ExtrapVal,arg1,arg2,arg3,arg4,arg5)
%LINEAR 2-D bilinear data interpolation.
%   ZI = LINEAR(EXTRAPVAL,X,Y,Z,XI,YI) uses bilinear interpolation to
%   find ZI, the values of the underlying 2-D function in Z at the points
%   in matrices XI and YI.  Matrices X and Y specify the points at which
%   the data Z is given.  X and Y can also be vectors specifying the
%   abscissae for the matrix Z as for MESHGRID. In both cases, X
%   and Y must be equally spaced and monotonic.
%
%   Values of EXTRAPVAL are returned in ZI for values of XI and YI that are
%   outside of the range of X and Y.
%
%   If XI and YI are vectors, LINEAR returns vector ZI containing
%   the interpolated values at the corresponding points (XI,YI).
%
%   ZI = LINEAR(EXTRAPVAL,Z,XI,YI) assumes X = 1:N and Y = 1:M, where
%   [M,N] = SIZE(Z).
%
%   ZI = LINEAR(EXTRAPVAL,Z,NTIMES) returns the matrix Z expanded by
%   interleaving bilinear interpolates between every element, working
%   recursively for NTIMES. LINEAR(EXTRAPVAL,Z) is the same as
%   LINEAR(EXTRAPVAL,Z,1).
%
%   See also INTERP2, CUBIC.

if nargin==2 % linear(extrapval,z), Expand Z
    [nrows,ncols] = size(arg1);
    s = 1:.5:ncols; lengths = length(s);
    t = (1:.5:nrows)'; lengtht = length(t);
    s = repmat(s,lengtht,1);
    t = repmat(t,1,lengths);

elseif nargin==3 % linear(extrapval,z,n), Expand Z n times
    [nrows,ncols] = size(arg1);
    ntimes = floor(arg2);
    s = 1:1/(2^ntimes):ncols; lengths = length(s);
    t = (1:1/(2^ntimes):nrows)'; lengtht = length(t);
    s = repmat(s,lengtht,1);
    t = repmat(t,1,lengths);

elseif nargin==4 % linear(extrapval,z,s,t), No X or Y specified.
    [nrows,ncols] = size(arg1);
    s = arg2; t = arg3;

elseif nargin==5
    error(message('MATLAB:interp2:linear:nargin'));

elseif nargin==6 % linear(extrapval,x,y,z,s,t), X and Y specified.
    [nrows,ncols] = size(arg3);
    mx = numel(arg1); my = numel(arg2);
    if (mx ~= ncols || my ~= nrows) && ~isequal(size(arg1),size(arg2),size(arg3))
        error(message('MATLAB:interp2:linear:XYZLengthMismatch'));
    end
    if nrows < 2 || ncols < 2
        error(message('MATLAB:interp2:linear:sizeZ'));
    end
    s = 1 + (arg4-arg1(1))/(arg1(end)-arg1(1))*(ncols-1);
    t = 1 + (arg5-arg2(1))/(arg2(end)-arg2(1))*(nrows-1);

end

if nrows < 2 || ncols < 2
    error(message('MATLAB:interp2:linear:sizeZsq'));
end
if ~isequal(size(s),size(t))
    error(message('MATLAB:interp2:linear:XIandYISizeMismatch'));
end

% Check for out of range values of s and set to 1
sout = find((s<1)|(s>ncols));
if ~isempty(sout), s(sout) = 1; end

% Check for out of range values of t and set to 1
tout = find((t<1)|(t>nrows));
if ~isempty(tout), t(tout) = 1; end

% Matrix element indexing
ndx = floor(t)+floor(s-1)*nrows;

% Compute intepolation parameters, check for boundary value.
if isempty(s), d = s; else d = find(s==ncols); end
s(:) = (s - floor(s));
if ~isempty(d), s(d) = s(d)+1; ndx(d) = ndx(d)-nrows; end

% Compute intepolation parameters, check for boundary value.
if isempty(t), d = t; else d = find(t==nrows); end
t(:) = (t - floor(t));
if ~isempty(d), t(d) = t(d)+1; ndx(d) = ndx(d)-1; end

% Now interpolate.
onemt = 1-t;
if nargin==6,
    F =  ( arg3(ndx).*(onemt) + arg3(ndx+1).*t ).*(1-s) + ...
         ( arg3(ndx+nrows).*(onemt) + arg3(ndx+(nrows+1)).*t ).*s;
else
    F =  ( arg1(ndx).*(onemt) + arg1(ndx+1).*t ).*(1-s) + ...
         ( arg1(ndx+nrows).*(onemt) + arg1(ndx+(nrows+1)).*t ).*s;
end

% Now set out of range values to ExtrapVal.
if ~isempty(sout), F(sout) = ExtrapVal; end
if ~isempty(tout), F(tout) = ExtrapVal; end

%------------------------------------------------------
function F = cubic(ExtrapVal,arg1,arg2,arg3,arg4,arg5)
%CUBIC 2-D bicubic data interpolation.
%   CUBIC(...) is the same as LINEAR(....) except that it uses
%   bicubic interpolation.
%
%   This function needs about 7-8 times SIZE(XI) memory to be available.
%
%   See also LINEAR.

%   Based on "Cubic Convolution Interpolation for Digital Image
%   Processing", Robert G. Keys, IEEE Trans. on Acoustics, Speech, and
%   Signal Processing, Vol. 29, No. 6, Dec. 1981, pp. 1153-1160.

if nargin==2, % cubic(extrapval,z), Expand Z
    [nrows,ncols] = size(arg1);
    s = 1:.5:ncols; lengths = length(s);
    t = (1:.5:nrows)'; lengtht = length(t);
    s = repmat(s,lengtht,1);
    t = repmat(t,1,lengths);

elseif nargin==3, % cubic(extrapval,z,n), Expand Z n times
    [nrows,ncols] = size(arg1);
    ntimes = floor(arg2);
    s = 1:1/(2^ntimes):ncols; lengths = length(s);
    t = (1:1/(2^ntimes):nrows)'; lengtht = length(t);
    s = repmat(s,lengtht,1);
    t = repmat(t,1,lengths);

elseif nargin==4, % cubic(extrapval,z,s,t), No X or Y specified.
    [nrows,ncols] = size(arg1);
    s = arg2; t = arg3;

elseif nargin==5,
    error(message('MATLAB:interp2:cubic:nargin'));

elseif nargin==6, % cubic(extrapval,x,y,z,s,t), X and Y specified.
    [nrows,ncols] = size(arg3);
    mx = numel(arg1); my = numel(arg2);
    if (mx ~= ncols || my ~= nrows) && ~isequal(size(arg1),size(arg2),size(arg3))
        error(message('MATLAB:interp2:cubic:XYZLengthMismatch'));
    end
    if nrows < 3 || ncols < 3
        error(message('MATLAB:interp2:cubic:sizeZ'));
    end
    s = 1 + (arg4-arg1(1))/(arg1(end)-arg1(1))*(ncols-1);
    t = 1 + (arg5-arg2(1))/(arg2(end)-arg2(1))*(nrows-1);

end

if nrows < 3 || ncols < 3
    error(message('MATLAB:interp2:cubic:sizeZsq'));
end
if ~isequal(size(s),size(t)),
    error(message('MATLAB:interp2:cubic:XIandYISizeMismatch'));
end

% Check for out of range values of s and set to 1
sout = find((s<1)|(s>ncols));
if ~isempty(sout), s(sout) = 1; end

% Check for out of range values of t and set to 1
tout = find((t<1)|(t>nrows));
if ~isempty(tout), t(tout) = 1; end

% Matrix element indexing
ndx = floor(t)+floor(s-1)*(nrows+2);

% Compute intepolation parameters, check for boundary value.
if isempty(s), d = s; else d = find(s==ncols); end
s(:) = (s - floor(s));
if ~isempty(d), s(d) = s(d)+1; ndx(d) = ndx(d)-nrows-2; end

% Compute intepolation parameters, check for boundary value.
if isempty(t), d = t; else d = find(t==nrows); end
t(:) = (t - floor(t));
if ~isempty(d), t(d) = t(d)+1; ndx(d) = ndx(d)-1; end

if nargin==6,
    % Expand z so interpolation is valid at the boundaries.
    zz = zeros(size(arg3)+2);
    zz(1,2:ncols+1) = 3*arg3(1,:)-3*arg3(2,:)+arg3(3,:);
    zz(2:nrows+1,2:ncols+1) = arg3;
    zz(nrows+2,2:ncols+1) = 3*arg3(nrows,:)-3*arg3(nrows-1,:)+arg3(nrows-2,:);
    zz(:,1) = 3*zz(:,2)-3*zz(:,3)+zz(:,4);
    zz(:,ncols+2) = 3*zz(:,ncols+1)-3*zz(:,ncols)+zz(:,ncols-1);
    nrows = nrows+2; %also ncols = ncols+2;
else
    % Expand z so interpolation is valid at the boundaries.
    zz = zeros(size(arg1)+2);
    zz(1,2:ncols+1) = 3*arg1(1,:)-3*arg1(2,:)+arg1(3,:);
    zz(2:nrows+1,2:ncols+1) = arg1;
    zz(nrows+2,2:ncols+1) = 3*arg1(nrows,:)-3*arg1(nrows-1,:)+arg1(nrows-2,:);
    zz(:,1) = 3*zz(:,2)-3*zz(:,3)+zz(:,4);
    zz(:,ncols+2) = 3*zz(:,ncols+1)-3*zz(:,ncols)+zz(:,ncols-1);
    nrows = nrows+2; %also ncols = ncols+2;
end

% Now interpolate using computationally efficient algorithm.
t0 = ((2-t).*t-1).*t;
t1 = (3*t-5).*t.*t+2;
t2 = ((4-3*t).*t+1).*t;
t(:) = (t-1).*t.*t;
F     = ( zz(ndx).*t0 + zz(ndx+1).*t1 + zz(ndx+2).*t2 + zz(ndx+3).*t ) ...
    .* (((2-s).*s-1).*s);
ndx(:) = ndx + nrows;
F(:)  = F + ( zz(ndx).*t0 + zz(ndx+1).*t1 + zz(ndx+2).*t2 + zz(ndx+3).*t ) ...
    .* ((3*s-5).*s.*s+2);
ndx(:) = ndx + nrows;
F(:)  = F + ( zz(ndx).*t0 + zz(ndx+1).*t1 + zz(ndx+2).*t2 + zz(ndx+3).*t ) ...
    .* (((4-3*s).*s+1).*s);
ndx(:) = ndx + nrows;
F(:)  = F + ( zz(ndx).*t0 + zz(ndx+1).*t1 + zz(ndx+2).*t2 + zz(ndx+3).*t ) ...
    .* ((s-1).*s.*s);
F(:) = F/4;

% Now set out of range values to ExtrapVal.
if ~isempty(sout), F(sout) = ExtrapVal; end
if ~isempty(tout), F(tout) = ExtrapVal; end

%------------------------------------------------------
function F = nearest(ExtrapVal,arg1,arg2,arg3,arg4,arg5)
%NEAREST 2-D Nearest neighbor interpolation.
%   ZI = NEAREST(EXTRAPVAL,X,Y,Z,XI,YI) uses nearest neighbor interpolation
%   to find ZI, the values of the underlying 2-D function in Z at the points
%   in matrices XI and YI.  Matrices X and Y specify the points at which
%   the data Z is given.  X and Y can also be vectors specifying the
%   abscissae for the matrix Z as for MESHGRID. In both cases, X
%   and Y must be equally spaced and monotonic.
%
%   Values of EXTRAPVAL are returned in ZI for values of XI and YI that are
%   outside of the range of X and Y.
%
%   If XI and YI are vectors, NEAREST returns vector ZI containing
%   the interpolated values at the corresponding points (XI,YI).
%
%   ZI = NEAREST(EXTRAPVAL,Z,XI,YI) assumes X = 1:N and Y = 1:M, where
%   [M,N] = SIZE(Z).
%
%   F = NEAREST(EXTRAPVAL,Z,NTIMES) returns the matrix Z expanded by
%   interleaving interpolates between every element.  NEAREST(EXTRAPVAL,Z)
%   is the same as NEAREST(EXTRAPVAL,Z,1).
%
%   See also INTERP2, LINEAR, CUBIC.

if nargin==2, % nearest(z), Expand Z
    [nrows,ncols] = size(arg1);
    u = 1:.5:ncols; lengthu = length(u);
    v = (1:.5:nrows)'; lengthv = length(v);
    u = repmat(u,lengthv,1);
    v = repmat(v,1,lengthu);

elseif nargin==3, % nearest(z,n), Expand Z n times
    [nrows,ncols] = size(arg1);
    ntimes = floor(arg2);
    u = 1:1/(2^ntimes):ncols; lengthu = length(u);
    v = (1:1/(2^ntimes):nrows)'; lengthv = length(v);
    u = repmat(u,lengthv,1);
    v = repmat(v,1,lengthu);

elseif nargin==4, % nearest(z,u,v)
    [nrows,ncols] = size(arg1);
    u = arg2; v = arg3;

elseif nargin==5,
    error(message('MATLAB:interp2:nearest:nargin'));

elseif nargin==6, % nearest(x,y,z,u,v), X and Y specified.
    [nrows,ncols] = size(arg3);
    mx = numel(arg1); my = numel(arg2);
    if (mx ~= ncols || my ~= nrows) && ...
            ~isequal(size(arg1),size(arg2),size(arg3))
        error(message('MATLAB:interp2:nearest:XYZLengthMismatch'));
    end
    if nrows > 1 && ncols > 1
        u = 1 + (arg4-arg1(1))/(arg1(mx)-arg1(1))*(ncols-1);
        v = 1 + (arg5-arg2(1))/(arg2(my)-arg2(1))*(nrows-1);
    else
        u = 1 + (arg4-arg1(1));
        v = 1 + (arg5-arg2(1));
    end
end

if ~isequal(size(u),size(v))
    error(message('MATLAB:interp2:nearest:XIandYISizeMismatch'));
end

% Check for out of range values of u and set to 1
uout = (u<.5)|(u>=ncols+.5);
anyuout = any(uout(:));
if anyuout, u(uout) = 1; end

% Check for out of range values of v and set to 1
vout = (v<.5)|(v>=nrows+.5);
anyvout = any(vout(:));
if anyvout, v(vout) = 1; end

% Interpolation parameters
u = round(u); v = round(v);

% Now interpolate
ndx = v+(u-1)*nrows;
if nargin==6,
    F = arg3(ndx);
else
    F = arg1(ndx);
end

% Now set out of range values to ExtrapVal.
if anyuout, F(uout) = ExtrapVal; end
if anyvout, F(vout) = ExtrapVal; end

%----------------------------------------------------------
function F = spline2(varargin)
%2-D spline interpolation

% Determine abscissa vectors
varargin{1} = varargin{1}(1,:);
varargin{2} = varargin{2}(:,1).';

%
% Check for plaid data.
%
xi = varargin{4}; yi = varargin{5};
xxi = xi(1,:); yyi = yi(:,1);

if ~isequal(repmat(xxi,size(xi,1),1),xi) || ...
        ~isequal(repmat(yyi,1,size(yi,2)),yi)
    F = splncore(varargin(2:-1:1),varargin{3},varargin(5:-1:4));
else
    F = splncore(varargin(2:-1:1),varargin{3},{yyi(:).' xxi},'gridded');
end

ExtrapVal = varargin{6};
% Set out-of-range values to ExtrapVal
if isnumeric(ExtrapVal)
    d = xi < min(varargin{1}) | xi > max(varargin{1}) | ...
        yi < min(varargin{2}) | yi > max(varargin{2});
    F(d) = ExtrapVal;
end


function [ node_coord, node_att, node_marker ] = triangle_node_data_example ( ...
  node_num, node_dim, node_att_num, node_marker_num )

%*****************************************************************************80
%
%% TRIANGLE_NODE_DATA_EXAMPLE returns the node information for the example.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 October 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, integer NODE_DIM, the spatial dimension.
%
%    Input, integer NODE_ATT_NUM, number of node attributes
%    listed on each node record.
%
%    Input, integer NODE_MARKER_NUM, 1 if every node record
%    includes a final boundary marker value.
%
%    Output, real NODE_COORD(NODE_DIM,NODE_NUM), the nodal
%    coordinates.
%
%    Output, real NODE_ATT(NODE_ATT_NUM,NODE_NUM), the nodal
%    attributes.
%
%    Output, integer NODE_MARKER(NODE_MARKER_NUM,NODE_NUM),
%    the node markers.
%
  node_coord = [ ...
    0.0, 0.0; ...
    1.0, 0.0; ...
    2.0, 0.0; ...
    3.0, 0.0; ...
    4.0, 0.0; ...
    0.0, 1.0; ...
    1.0, 1.0; ...
    2.0, 1.0; ...
    3.0, 1.0; ...
    4.0, 1.0; ...
    0.0, 2.0; ...
    1.0, 2.0; ...
    2.0, 2.0; ...
    3.0, 2.0; ...
    4.0, 2.0; ...
    0.0, 3.0; ...
    1.0, 3.0; ...
    2.0, 3.0; ...
    0.0, 4.0; ...
    1.0, 4.0; ...
    2.0, 4.0 ]';

  node_att = [];

  node_marker = [ ...
    1; 1; 1; 1; 1; 1; 0; 0; 0; 1; ...
    1; 0; 0; 1; 1; 1; 0; 1; 1; 1; ...
    1 ]';

  return
end


%ADDCIRCLE  Add a circle to the current plot
%
%   addcircle(center, radius)
%   addcircle(center, radius, linestyle)
%
%  Returns the graphics handle for the circle.

% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Machine Vision Toolbox for Matlab (MVTB).
%
% MVTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% MVTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with MVTB.  If not, see <http://www.gnu.org/licenses/>.

function h = addcircle(center, radius, varargin)

	n = 100;

	th = [0:n]'/n*2*pi;
	cth = cos(th);
	sth = sin(th);

    ih = ishold;
    hold on
    handles = [];   % list of handles for circles

    for i=1:numrows(center)
        handles = [handles; patch(radius(i)*cos(th)+center(i,1), radius(i)*sin(th)+center(i,2), varargin{:})];
    end
    if ih == 0,
        hold off
    end

    if nargout > 0,
        h = handles;
    end


function [y,ysup] = erfc_rnd(x,rnd)
% input x real non-negative column vector
% rnd  -1  y = lower bound for erf(x)
%       1  y = upper bound for erf(x)
%      []  [y,ysup] inclusion of erf(x)
% rounding may be altered after leaving erfc_rnd

% written  05/30/13     S.M. Rump
%

  xmax = hex2num('403b369a6244e684');   % ~27.2: erfc(x)<subrealmin fuer x>=xmax

  y = x;
  if isempty(rnd)
    ysup = x;
  end

  index = ( x<-0.5 );                   % Use 2-erfc(-x)
  if any(index)                         % x in [-inf,-0.5)
    if isempty(rnd)
      [yindex,ysupindex] = erfc_rnd(-x(index),-rnd);
      setround(-1)
      y(index) = 2 - ysupindex;
      setround(1)
      ysup(index) = 2 - yindex;
    else
      yindex = erfc_rnd(-x(index),-rnd);
      setround(rnd)
      y(index) = 2 - yindex;
    end
  end
  Index = index;                        % store finished indices

  index = ( ~Index ) & ( x<0 );         % first method
  if any(index)                         % x in [-0.5,0)
    if isempty(rnd)
      [yindex,ysupindex] = erf_rnd1(-x(index),rnd,6);
      setround(-1)
      y(index) = 1 + yindex;
      setround(1)
      ysup(index) = 1 + ysupindex;
    else
      yindex = erf_rnd1(-x(index),rnd,6);
      setround(rnd)
      y(index) = 1 + yindex;
    end
  end
  Index = Index | index;                % store finished indices

  index = ( ~Index ) & ( x<=0.5 );      % first method
  if any(index)                         % x in [0,0.5]
    if isempty(rnd)
      [yindex,ysupindex] = erf_rnd1(x(index),rnd,6);
      setround(-1)
      y(index) = 1 - ysupindex;
      setround(1)
      ysup(index) = 1 - yindex;
    else
      yindex = erf_rnd1(x(index),-rnd,6);
      setround(rnd)
      y(index) = 1 - yindex;
    end
  end
  Index = Index | index;                % store finished indices

  index = ( ~Index ) & ( x<=7 );        % second method
  if any(index)                         % x in (0.5,7]
    yindex = erfc_rnd2(x(index));
    if rnd==-1
      y(index) = yindex.inf;
    elseif rnd==1
      y(index) = yindex.sup;
    else
      y(index) = yindex.inf;
      ysup(index) = yindex.sup;
    end
  end
  Index = Index | index;                % store finished indices

  index = ( ~Index ) & ( x<=10 );       % third method
  if any(index)                         % x in (7,10]
    if isempty(rnd)
      [y(index),ysup(index)] = erfc_rnd3(x(index),rnd,16);
    else
      y(index) = erfc_rnd3(x(index),rnd,16);
    end
  end
  Index = Index | index;                % store finished indices

  index = ( ~Index ) & ( x<=xmax );     % third method
  if any(index)                         % x in (10,xmax]
    if isempty(rnd)
      [y(index),ysup(index)] = erfc_rnd3(x(index),rnd,10);
    else
      y(index) = erfc_rnd3(x(index),rnd,10);
    end
  end

  index = ( x>xmax );
  if any(index)                         % x in (xmax,inf]
    if isempty(rnd)                     % inclusion [y,ysup] of erfc(x)
      y(index) = 0;
      ysup(index) = hex2num('0000000000000001');    % subrealmin
    elseif rnd==1                       % y upper bound for erfc(x)
      y(index) = hex2num('0000000000000001');    % subrealmin
    else                                % y lower bound for erfc(x)
      y(index) = 0;
    end
  end


% takes NimgFirstRegistration mean image and aligns it to itself
% does nonrigid registration across specified blocks
% returns mean image for registration

function ops = nonrigidAlignIterative(data, ops)

% uu = squeeze(sum(sum(data(:,:,:).^2,1),2));
% [~, isort] = sort(uu, 'descend');
% ops.mimg        = data(:,:,isort(50));

% take most correlated frames to compute initial mean image
mimg = pick_reg_init(data);

numBlocks = numel(ops.yBL);
dsold = zeros(size(data,3), 2, numBlocks);
err = zeros(ops.NiterPrealign, 1);
%%
for i = 1:ops.NiterPrealign
    dsnew = zeros(size(data,3), 2, numBlocks,'double');
    Corr = zeros(size(data,3), numBlocks,'double');
    for ib = 1:numBlocks
        % collect ds
        ops.mimg = mimg(ops.yBL{ib},ops.xBL{ib});
        % compute offsets from each frame to mean image and subtract mean
        % offset (centered at offset = 0)
	if ops.kriging
	  [dsnew(:,:,ib), Corr(:,ib)]  = ...
	      regoffKriging(data(ops.yBL{ib},ops.xBL{ib},:), ops, 1);
	else
	  [dsnew(:,:,ib), Corr(:,ib)]  = ...
	      regoffLinear(data(ops.yBL{ib},ops.xBL{ib},:), ops, 1);
	end
    end

    % register frames
    dreg = nonrigidRegFrames(data, ops.xyMask, dsnew);

    % sort by correlation and take mean of most correlated frames
    [~, igood] = sort(mean(Corr,2), 'descend');
    if i<floor(ops.NiterPrealign/2)
        igood = igood(1:100);
    else
        igood = igood(1:round(size(data,3)/2));
    end
    mimg = mean(dreg(:,:,igood),3);

    err(i) = mean(mean(sum((dsold - dsnew).^2,2),3)).^.5;

    dsold = dsnew;
end
ops.mimg = mimg;

ops.AlignNanThresh = median(Corr) - 4*std(Corr);
ops.ErrorInitialAlign = err;
ops.dsprealign = dsnew;

end


function hf_out = lhs_operation_joint(hf, samplesf, reg_filter, feature_reg, init_samplef, XH, init_hf, proj_reg)

% This is the left-hand-side operation in Conjugate Gradient

hf_out = cell(size(hf));

% Extract projection matrix and filter separately
P = cellfun(@real, hf(2,1,:), 'uniformoutput',false);
hf = hf(1,1,:);

% size of the padding
num_features = length(hf);
output_sz = [size(hf{1},1), 2*size(hf{1},2)-1];

% Compute the operation corresponding to the data term in the optimization
% (blockwise matrix multiplications)
%implements: A' diag(sample_weights) A f

% sum over all features in each block
sh_cell = cell(1,1,num_features);
for k = 1:num_features
    sh_cell{k} = mtimesx(samplesf{k}, permute(hf{k}, [3 4 1 2]), 'speed');
end

% sum over all feature blocks
sh = sh_cell{1};    % assumes the feature with the highest resolution is first
pad_sz = cell(1,1,num_features);
for k = 2:num_features
    pad_sz{k} = (output_sz - [size(hf{k},1), 2*size(hf{k},2)-1]) / 2;

    sh(:,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end) = ...
        sh(:,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end) + sh_cell{k};
end

% weight all the samples
% sh = bsxfun(@times,sample_weights,sh);

% multiply with the transpose
hf_out1 = cell(1,1,num_features);
hf_out1{1} = permute(conj(mtimesx(sh, 'C', samplesf{1}, 'speed')), [3 4 2 1]);
for k = 2:num_features
    hf_out1{k} = permute(conj(mtimesx(sh(:,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end), 'C', samplesf{k}, 'speed')), [3 4 2 1]);
end

% compute the operation corresponding to the regularization term (convolve
% each feature dimension with the DFT of w, and the tramsposed operation)
% add the regularization part
% hf_conv = cell(1,1,num_features);
for k = 1:num_features
    reg_pad = min(size(reg_filter{k},2)-1, size(hf{k},2)-1);

    % add part needed for convolution
    hf_conv = cat(2, hf{k}, conj(rot90(hf{k}(:, end-reg_pad:end-1, :), 2)));

    % do first convolution
    hf_conv = convn(hf_conv, reg_filter{k});

    % do final convolution and put toghether result
    hf_out1{k} = hf_out1{k} + convn(hf_conv(:,1:end-reg_pad,:), reg_filter{k}, 'valid');
end

% Stuff related to the projection matrix

% Set the filter to the current one instead (test)
% init_hf = cellfun(@(hf) permute(hf, [3 4 1 2]), hf, 'uniformoutput', false);

% B * P
BP_cell = cell(1,1,num_features);
for k = 1:num_features
    BP_cell{k} = mtimesx(mtimesx(init_samplef{k}, P{k}, 'speed'), init_hf{k}, 'speed');
end

BP = BP_cell{1};
for k = 2:num_features
    BP(1,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end) = ...
        BP(1,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end) + BP_cell{k};
end

% multiply with the transpose: A^H * BP
hf_out{1,1,1} = hf_out1{1} +  permute(bsxfun(@times, BP, conj(samplesf{1})), [3 4 2 1]);

% B^H * BP
fBP = cell(1,1,num_features);
fBP{1} = reshape(bsxfun(@times, conj(init_hf{1}), BP), size(init_hf{1},1), []).';

% Compute proj matrix part: B^H * A_m * f
shBP = cell(1,1,num_features);
shBP{1} = reshape(bsxfun(@times, conj(init_hf{1}), sh), size(init_hf{1},1), []).';

for k = 2:num_features
    % multiply with the transpose: A^H * BP
    hf_out{1,1,k} = hf_out1{k} +  permute(bsxfun(@times, BP(1,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end), conj(samplesf{k})), [3 4 2 1]);

    % B^H * BP
    fBP{k} = reshape(bsxfun(@times, conj(init_hf{k}), BP(1,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end)), size(init_hf{k},1), []).';

    % Compute proj matrix part: B^H * A_m * f
    shBP{k} = reshape(bsxfun(@times, conj(init_hf{k}), sh(1,1,1+pad_sz{k}(1):end-pad_sz{k}(1), 1+pad_sz{k}(2):end)), size(init_hf{k},1), []).';
end

% hf_out2 = cell(1,1,num_features);
for k = 1:num_features
    fi = size(hf{k},1) * (size(hf{k},2)-1) + 1;  % index where the last frequency column starts

    % B^H * BP
    hf_out2 = 2*real(XH{k} * fBP{k} - XH{k}(:,fi:end) * fBP{k}(fi:end,:)) + proj_reg * P{k};

    % Compute proj matrix part: B^H * A_m * f
    hf_out{2,1,k} = hf_out2 + (2*real(XH{k} * shBP{k} - XH{k}(:,fi:end) * shBP{k}(fi:end,:)));
end
end


%------------------------------------------------------------------------
% AL-AZHAR UNIVERSITY
% FACULTY OF ENGINEERING
% SYSTEMS & COMPUTERS ENGINEERING Department
%------------------------------------------------------------------------
% Author : Ahmed Samieh Abd El-Wahab
% Date   : 14 December 2006
%------------------------------------------------------------------------
% Shapes Classifier
% Step 1: Read image Read in
% Step 2: Convert image from rgb to gray
% Step 3: Threshold the image
% Step 4: Invert the Binary Image
% Step 5: Find the boundaries Concentrate
% Step 6: Determine Shapes properties
% Step 7: Classify Shapes according to properties
% Square      = 3
% Rectangular = 2
% Circle      = 1
% UNKNOWN     = 0
%------------------------------------------------------------------------
function W = Classify(ImageFile)
% Step 1: Read image Read in
RGB = imread(ImageFile);
figure,
imshow(RGB),
title('Original Image');

% Step 2: Convert image from rgb to gray
GRAY = rgb2gray(RGB);
figure,
imshow(GRAY),
title('Gray Image');

% Step 3: Threshold the image Convert the image to black and white in order
% to prepare for boundary tracing using bwboundaries.
threshold = graythresh(GRAY);
BW = im2bw(GRAY, threshold);
figure,
imshow(BW),
title('Binary Image');

% Step 4: Invert the Binary Image
BW = ~ BW;
figure,
imshow(BW),
title('Inverted Binary Image');

% Step 5: Find the boundaries Concentrate only on the exterior boundaries.
% Option 'noholes' will accelerate the processing by preventing
% bwboundaries from searching for inner contours.
[B,L] = bwboundaries(BW, 'noholes');

% Step 6: Determine objects properties
STATS = regionprops(L, 'all'); % we need 'BoundingBox' and 'Extent'

% Step 7: Classify Shapes according to properties
% Square = 3 = (1 + 2) = (X=Y + Extent = 1)
% Rectangular = 2 = (0 + 2) = (only Extent = 1)
% Circle = 1 = (1 + 0) = (X=Y , Extent < 1)
% UNKNOWN = 0

figure,
imshow(RGB),
title('Results');
hold on
for i = 1 : length(STATS)
  W(i) = uint8(abs(STATS(i).BoundingBox(3)-STATS(i).BoundingBox(4)) < 0.1);
  W(i) = W(i) + 2 * uint8((STATS(i).Extent - 1) == 0 );
  centroid = STATS(i).Centroid;
  switch W(i)
      case 1
          plot(centroid(1),centroid(2),'wO');
      case 2
          plot(centroid(1),centroid(2),'wX');
      case 3
          plot(centroid(1),centroid(2),'wS');
  end
end
return


function [W, info] = MTFLC_ADMM(X, y, lambda1, lambda2, opts)
%
% Multi-Task Feature Learning with Calibration - ADMM
%
% OBJECTIVE
%    min_W { sum_i^m ||Xi wi - yi|| + lambda1 ||W||_{1,2} + lambda2/2 ||W||_F^2 }
%
% We use ADMM to solve the problem.
%
% INPUT
%  X - cell array of {n_i by d matrices} by m
%  y - cell array of {n_i by 1 vectors}  by m
%  lambda1 - regularization parameter of the l2,1 norm penalty
%  lambda2 - regularization parameter of the Fro norm penalty
%
% OUTPUT
%  W - task weights: d by t.
%  funcVal - the funcion value.
%
% Author: Jiayu Zhou

%% Initialization
if(nargin<5), opts = []; end

opts = setOptsDefault( opts, 'verbose', 1);
opts = setOptsDefault( opts, 'maxIter', 10000);
opts = setOptsDefault( opts, 'tol',     1e-4);
verbose = opts.verbose;

innerOpts = [];
innerOpts = setOptsDefault( innerOpts, 'maxIter', 5000);
innerOpts = setOptsDefault( innerOpts, 'tol',     1e-8);
innerOpts = setOptsDefault( innerOpts, 'tFlag',   1);

if verbose > 0
    fprintf('ADMM Config: [MaxIter %u][Tol %.4g]\n', opts.maxIter, opts.tol);
    fprintf('ADMM Subsolver Config: [MaxIter %u][Tol %.4g]\n', innerOpts.maxIter, innerOpts.tol);
end

m = length(X); % task number
d = size(X{1}, 2); % dimension.

funcVal  = zeros(opts.maxIter, 1);

% init for variables.
Th = cell(m, 1); % each element is n_i by 1
for tt = 1:m
    Th{tt} = L2proj(randn(size(X{tt}, 1), 1));
end
Z = Th; % this initialization indicates that w_init = 0.
W = zeros(d, m);

rho = 1; rhoInc = 1;

%% Computation
if verbose == 1; fprintf('Iteration:     '); end
for iter = 1: opts.maxIter

    % Update W
    innerOpts.init = W;
    [W, innerInfo] = MTFLC_ADMM_WSolver(X, y, Th, Z, rho, lambda1, lambda2, innerOpts); %#ok

    % Update Z (the same size as Tht)
    for t = 1: m
        vt = Th{t} / rho + y{t} - X{t} * W(:, t);
        vtNrm = sqrt(sum(vt.^2));
        Z{t} = max(0, 1- 1/(rho * vtNrm)) * vt;
    end

    % Update theta
    for t = 1: m
        Th{t} = Th{t} + rho * (y{t} - Z{t} - X{t} * W(:, t));
    end

    %if verbose >=2, fprintf('Th: %.4f\n', augLagObjective(W, Th, Z)); end

    % Update rho
    rho = rho * rhoInc;

    funcVal(iter) = augLagObjective(W, Th, Z);
    if verbose == 1; fprintf('\b\b\b\b\b%5i',iter); end

    % check stop criteria
    if (iter >1)
        diffW = sum(sum((W - W_old).^2));
        diffZ = 0; diffTh = 0;
        for t = 1: m
            diffZ  = diffZ  + sum((Z{t}  - Z_old{t}) .^2);
            diffTh = diffTh + sum((Th{t} - Th_old{t}).^2);
        end

        if verbose>1
            fprintf('Iter: Fv: %.4f Fv+L: %.4f dW %.4g, dZ %.4g, dTh %.4g\n', ...
                primalObjective(W), funcVal(iter), diffW, diffZ, diffTh);
        end

        if( max(diffW, max(diffZ, diffTh)) < opts.tol)
            break;
        end
    end

    W_old  = W; Z_old  = Z; Th_old = Th;
end
if verbose == 1; fprintf('\n'); end

%% Output
info.funcVal = funcVal(1: iter);
% use the last to show the 'real' objective without aug Lagrange.
info.funcVal(end + 1) = primalObjective(W);
% NOTE: the primal should be the same as augmented when converged.

%% Nested Functions
    function fvP = primalObjective(W)
        % primal objective (without augmented terms)
        %  P(W)  sum_i^m ||Xi wi - yi|| + lambda1 ||W||_{1,2} + lambda2/2 ||W||_F^2

        fvP = lambda1 * L21norm(W) + lambda2 /2 * sum(sum(W.^2));
        for i = 1: m
            fvP = fvP + sqrt(sum((X{i} * W(:, i) - y{i}).^2));
        end
    end

    function fvP = augLagObjective(W, Th, Z)
        % primal objective with augmented Lagrange terms.
        %  P(W)  sum_i^m ||Xi wi - yi|| + lambda1 ||W||_{1,2} + lambda2/2 ||W||_F^2
        %         + sum_i^m {Th_i' (y_i - z_i - X_i w_i) + 2 ||y_i - z_i - X_i w_i||^2/rho }

        fvP = lambda1 * L21norm(W) + lambda2 /2 * sum(sum(W.^2));
        for i = 1: m
            fvP = fvP + sqrt(sum((X{i} * W(:, i) - y{i}).^2)); % loss
            ti = y{i} - Z{i} - X{i} * W(:, i);
            fvP = fvP + Th{i}' * ti;             % dual
            fvP = fvP + 2 * sum(ti.^2) / rho;    % augment term.
        end
    end

end

function [Xnrm] = L21norm(X)
% ||X||_{1,2} = sum_i ||X^i||_2
Xnrm = sum(sqrt(sum(X.^2, 2)));
end

function [x] = L2proj(x)
nrm = sqrt(sum(x.^2));
x = x ./ max(1, nrm) ;
end


function M = median_filter(im)
  % MEDIAN_FILTER simpler wrapper for calling medfilt2 on each channel
  %
  % M = median_filter(im)
  %
  % Input:
  %   im  w by h by c image
  % Output:
  %   M  median filtered image in each channel
  %

  % This could probably be a one-liner using num2cell and cellfun
  M = zeros(size(im));
  for c = 1 : size(im,3)
    M(:,:,c) = medfilt2(im(:,:,c));
  end
end


% Ryan Steindl based on Robotics Toolbox for MATLAB (v6 and v9)
%
% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
function qu = unit(q)
%Quaternion.unit Unitize a quaternion
%
% QU = Q.unit() is a quaternion which is a unitized version of  Q

  qu = q / norm(q);
end


function [ spect, frqs ] = LTASS( speech_folder_OR_vec, nfft, fs )
% Computes the Long-Term Average Speech Spectrum from a folder of speech files or vector of speech samples
%
% Syntax:	[ spect, frqs ] = LTASS( speech_folder_OR_vec, nfft )
%
% Inputs:
% 	speech_folder_OR_vec - The path to the folder containing the speech
%                          files OR a vector of concatenated speech signals
% 	nfft - The number of FFT points used to compute the LTASS
% 	fs - The sampling frequency to use (if not provided then the sampling
%        frequency of the file is used)
%
% Outputs:
% 	spect - The LTASS spectrum
% 	frqs - The frequency vector for the spectrum

% Author: Jacob Donley
% University of Wollongong
% Email: jrd089@uowmail.edu.au
% Copyright: Jacob Donley 2017
% Date: 17 June 2016
% Revision: 0.4 (30 March 2017)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if isa(speech_folder_OR_vec,'char') % if a character array (string)
    % Just incase this function tries to call getAllFiles within a class folder we
    % should create a function handle for getAllFiles regardless
    inf = dbstack('-completenames');
    funcName = 'getAllFiles';
    funcPath = inf.file;
    classDirs = getClassDirs(funcPath);
    getAllFiles_ = str2func([classDirs funcName]);

    %% Start LTASS
    files = getAllFiles_(speech_folder_OR_vec);
    speech=[];
    F = length(files);
    for file = 1:F
        try
            [audioSig,fs_] = audioread(files{file});
            if nargin < 3, fs = fs_; end
            audioSig = audioSig ./ rms(audioSig(:));
        catch err
            if strcmp(err.identifier, 'MATLAB:audiovideo:audioread:FileTypeNotSupported')
                continue; % Skip unsupported files
            end
        end
        speech = [speech; audioSig];
    end
    if nargin < 2
        nfft = numel(speech);
    end
    if logical(mod(nfft,2)) % if isodd( nfft )
        nfft = nfft-1; % Force nfft to be even so that pwelch returns normalised frequencies [0,...,1]
    end

else
    speech = speech_folder_OR_vec;
end

%%
win_=rectwin(nfft);
ovlap = 0;

[spect,frqs]=pwelch(speech,win_,nfft*ovlap,nfft,fs,'power'); % Power spectrum
spect = sqrt(spect); % Magnitude spectrum

end

function classDirs = getClassDirs(FullPath)
classDirs = '';
classes = strfind(FullPath,'+');
for c = 1:length(classes)
    clas = FullPath(classes(c):end);
    stp = strfind(clas,filesep);
    classDirs = [classDirs  clas(2:stp(1)-1) '.'];
end
end


function calpak_test012 ( )

%*****************************************************************************80
%
%% CALPAK_TEST012 tests JED_TO_YJF_ROMAN and YJF_TO_JED_ROMAN.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 March 2013
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CALPAK_TEST012\n' );
  fprintf ( 1, '  For the Roman calendar:\n' );
  fprintf ( 1, '  JED_TO_YJF_ROMAN: JED -> YJF.\n' );
  fprintf ( 1, '  YJF_TO_JED_ROMAN: YJF -> JED.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  JED (in)    YJF                JED (out)\n' );
  fprintf ( 1, '\n' );

  jed_epoch = epoch_to_jed_roman ( );

  i = 0;

  while ( 1 )

    i = i + 1;
    jed1 = jed_test ( i );

    if ( jed1 < 0.0 )
      break
    end

    if ( jed_epoch <= jed1 )

      [ y2, j2, f2 ] = jed_to_yjf_roman ( jed1 );

      s2 = yjf_to_s_roman ( y2, j2, f2 );

      jed3 = yjf_to_jed_roman ( y2, j2, f2 );

      fprintf ( 1, '  %11.2f  %20s  %11.2f\n', jed1, s2, jed3 );

    end

  end

  return
end


function p = PlotHVLines(positions,direction,varargin)

%PlotHVLines - Plot vertical (resp. horizontal) lines at listed x (resp. y).
%
%  USAGE
%
%    p = PlotHVLines(positions,direction,options)
%
%    positions      list of abscissae/ordinates
%    direction      optional direction: 'h' or 'v' (default = 'v')
%    <options>      options for function plot
%

% Copyright (C) 2008-2012 by Michaël Zugaro
%
% 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.

if nargin < 1,
 	error('Incorrect number of parameters (type ''help PlotHVLines'' for details).');
end
if nargin < 2,
	direction = 'v';
else
	direction = lower(direction);
end
if min(size(positions)) > 2,
 	error('List of abscissae/ordinates is not a vector (type ''help PlotHVLines'' for details).');
else
	positions = positions(:);
end

if ~isstring_FMAT(direction,'h','v'),
	varargin = {direction,varargin{:}};
	direction = 'v';
end

hold on;
if strcmp(direction,'v'),
	yLim = ylim;
	for i = 1:size(positions,1),
		plot([positions(i,1) positions(i,1)],yLim,varargin{:});
	end
else
	xLim = xlim;
	for i = 1:size(positions,1),
		plot(xLim,[positions(i,1) positions(i,1)],varargin{:});
	end
end


function layer2colors=riverplot_recolor_layer2(sim_matrix,layer1colors)

% ..
%    Programmers' notes:
%    List dates and changes here, and author of changes
%    Created July 2016 by Tor Wager
%
%    8/21/2017 Stephan Geuter
%    changed normalization to used absolute similarity values (l21). Before, negative
%    values could distort the normalization factor resulting RGB values
%    outside the [0-1] interval.
% ..

[n2, n1]=size(sim_matrix);
for i=1:n2
    temp_color=[0 0 0];
    for j=1:n1
        temp_color= temp_color + layer1colors{j}*abs(sim_matrix(i,j))/sum(abs(sim_matrix(i,:)));
    end

    if any(isnan(temp_color));
       temp_color=[.5 .5 .5];
    end
    layer2colors{i}=temp_color;
end


function Pset=str2poly(strcell,varnames)
% POLY2STR - convert multivariate polynomials from strings to arrays
% usage: Pset=poly2str(strcell,varnames)
%
% INPUTS: strcell, varnames
%  strcell is a cell array of strings, one per polynomial
%    all numbers must be whole or decimal form (no scientific notation)
%    brackets and double negatives are not allowed.
%    All spaces in the strings are ignored.
%  varnames (optional) is a cell array of strings which must include all
%    variable names that occur in strcell [default: {'x1','x2',...}]
%
% OUTPUTS: Pset
%  Pset is a cell array of polynomial coefficients where row j of Pset{i}
%    is [c,k1,k2,...] representing the monomial c*x1^k1*x2^k2*...
%
% EXAMPLE:
%  str2poly({'x1*x2^2'})    % returns {[1,1,2]}
%  str2poly({'-x1*x2^2'})   % returns {[-1,1,2]}
%  str2poly({'-1*x1*x2^2'}) % returns {[-1,1,2]}
%  str2poly({'- 1 * x 1 * x 2 ^ 2'}) % returns {[-1,1,2]}
%
% SEE ALSO:
%  groebner, poly2str

% Author: Ben Petschel 19/6/2009
%
% Change history:
%  19/6/2009 - first release
%  22/6/2009 - fixed bug in handling "-x1" etc.
%  17/7/2009 - allow whitespace in strings
%  20/3/2010 - changed array representation to rectangular instead of n-d

if nargin<2,
  varnames = {}; % will fill in varnames later, as needed
end;
Pset = cell(size(strcell));

for i=1:numel(strcell),
  str = strcell{i};

  % ignore all spaces
  remain = str;
  remain = strrep(remain,' ','');

  % first insert "+" before every "-", for easier term separation later
  str = '';
  while ~isempty(remain),
    if remain(1)=='-',
      if isempty(str),
        str = '-';
      else
        str = [str,'+-'];
      end;
    end;
    [tok,remain]=strtok(remain,'-');
    str = [str,tok];
  end;

  % now separate into terms
  remain = str;
  terms = [];
  while ~isempty(remain),
    coeff = 1;
    exps = [];
    [term,remain]=strtok(remain,'+');
    % process term, separating into products
    rem2 = term;
    while ~isempty(rem2),
      [part,rem2]=strtok(rem2,'*');
      if ~isnan(str2double(part)),
        % part is a number, multiply it by the coefficient
        coeff = coeff * str2double(part);
      else
        % part is var^n or var or -var^n or -var
        if part(1)=='-',
          coeff = -coeff;
          part=part(2:end);
          if isempty(part),
            error('isolated minus sign');
          end;
        end;
        ind = find(part=='^');
        if isempty(ind),
          var = part;
          expo = 1;
        else
          ind = ind(1);
          var = part(1:ind-1);
          expo = str2double(part(ind+1:end));
          if isnan(expo),
            % exponent is not valid
            error('invalid exponent in part %s',part);
          end;
        end;
        if isempty(varnames),
          % see if var is of form 'x1' etc
          if (length(var)>1) && (var(1)=='x') && ~isnan(str2double(var(2:end))),
            % variable name is ok
            k = str2double(var(2:end));
          else
            error('variable name not of form "x1","x2",...');
          end;
        else
          ind = strmatch(var,varnames);
          if isempty(ind),
            error('variable name not in list');
          end;
          k = ind(1);
        end;
        if length(exps)<k,
          exps = [exps,zeros(1,k-length(exps))];
        end;
        exps(k) = exps(k)+expo;
      end;
    end; % while ~isempty(rem2),
    % term is processed, now add it to the list of terms
    if size(terms,2)<(length(exps)+1),
      terms = [terms,zeros(size(terms,1),length(exps)+1-size(terms,2))];
    elseif length(exps)<size(terms,2)-1,
      exps = [exps,zeros(1,size(terms,2)-1-length(exps))];
    end;
    terms = [terms;coeff,exps];
  end; % while ~isempty(remain),

  Pset{i}=terms;
end; % for i=1:numel(strcell),

end % main function str2poly(...)


function [ output_im ] = patch_sew(input_patches, output_sz, patch_stsz)
% function [ output_im ] = patch_sew(input_patches, output_sz, patch_stsz)
%   Combine evenly spaced patches into a single image, averaging at voxels
%   in more than one patch. Allows for the input of patches from multiple
%   output images (assuming each image has been divided into similarly
%   sized and spaced patches.
%
%   Note: patch_create and patch_sew differ from im2col and col2im by
%   allowing a custom stride, and were designed to output a stack of 2d
%   patches for direct input to a 2d neural network.
%
% Inputs:
%   input_patches   [nlin_patch, ncol_patch, npatch]  stack of input patches
%   output size     2x1   dimensions of output 2D image (or images)
%   patch_stsz      1x1   step size btwn patches (stride)
%
% Outputs:
%   output_im       [nlin, ncol, nims]   sewed together images
%
%  Melissa Haskell, University of Michigan, 2021-09-08

if nargin < 3, ir_usage, end

%% Find patch size and determine the indices of each patch using createpatches

patch_sz = size(input_patches,1);

% input 2D image to get number of patches for 2d image of that size
[~, patch_indices] = patch_create(zeros(output_sz), patch_sz, patch_stsz);

%% Calculate total number of images and initialize output

npatch_per_image = size(patch_indices,3);
npatch = size(input_patches,3);
nrow = output_sz(1);
ncol = output_sz(2);
nims = npatch / npatch_per_image;
output_im = zeros(nrow,ncol,nims);

%% Sew all the patches together
for ii = 1:nims
    psf_img = zeros(nrow, ncol);  % for tracking how many patches are at each voxel
    sum_img = zeros(nrow, ncol);  % for adding all the patch values together
    for jj = 1:npatch_per_image

        patch_indx = (ii-1)*npatch_per_image + jj;
        patch = reshape(input_patches(:,:,patch_indx),[patch_sz, patch_sz]);

        ind_2dim = patch_indices(:,:,jj);
        r1 = ind_2dim(1); c1 = ind_2dim(2);
        r2 = ind_2dim(3); c2 = ind_2dim(4);

        psf_img(r1:r2,c1:c2) = psf_img(r1:r2,c1:c2) + 1;
        sum_img(r1:r2,c1:c2) = sum_img(r1:r2,c1:c2) + patch;

    end
    % scale summation image by the psf image
    output_im(:,:,ii) = sum_img ./ (psf_img + 1e-12);
end

end


%%*******************************************************************
%%  Convert problem from SeDuMi format to DSDP format
%%
%%  [AC,b] = readsedumi(At,b,C,K)
%%
%%  Input: At, b, C, K = Data in SeDuMi format.
%%
%%
%% DSDP: version 5.0
%% Copyright (c) 2004 by
%% S. Benson Y. Ye
%% Last modified: 2 Jan 04
%%******************************************************************

  function [AC,b]=readsedumi(At,bb,c,K);
%%
%%  First, load the matlab file containing At, c, b, and K
%%
  if (size(c,1) == 1), c = c'; end;
  if (size(bb,1) == 1), bb = bb'; end;
  [nn,mm] = size(At); if (max(size(c)) == 1); c = c*ones(nn,1); end;

  if ~isfield(K,'l'); K.l = 0; end
  if ~isfield(K,'q'); K.q = 0; end
  if ~isfield(K,'s'); K.s = 0; end
  if K.l == 0 | isempty(K.l); K.l = 0; end;
  if sum(K.q) == 0 | isempty(K.q); K.q = 0; end
  if sum(K.s) == 0 | isempty(K.s); K.s = 0; end
%%
%%
%%
  AC=cell(1,3);
block=1;
top=1;

   m = length(bb);
   b = -bb;

   if (K.l > 0)
      AC{block,1} = 'LP';
      AC{block,2} = K.l;
      A = At(top:top+n-1,:);
      CC = c(top:top+n-1,:);
      AC{block,3} = [-A(:,1:m) CC(:,1)];
      block = block+1;
      top = top+K.l;
   end
   if (K.q > 0)
      error(' Cannot accept SOCP cones\n');
   end

   if (K.s > 0)
      for i = 1:length(K.s)
         n = K.s(i);
         AC{block,1} = 'SDP';
         AC{block,2} = n;
         A = At(top:top+n^2-1,:);
         CC = c(top:top+n^2-1,:);
         indicies = triu(reshape(1:n^2,n,n));
         indicies = indicies(find(indicies));
         AC{block,3} = [-A(indicies,1:m) CC(indicies,1)];
         block = block+1;
         top = top+n*n;
       end
   end

%%


function [LOSS, CSP, LDA] = MI_calibration_2(file,band,fs,interval,varargin)

opt=opt_cellToStruct(varargin{:});
cls=opt.nClass;
switch cls
    case 2
        marker={'1','right';'2','left'};
    case 3
        marker={'1','right';'2','left';'3','foot'};
    case 4
        marker={'1','right';'2','left';'3','foot';'4','rest'};
end
field={'x','t','fs','y_dec','y_logic','y_class','class', 'chan'};
[EEG.data, EEG.marker, EEG.info]=Load_EEG(file,{'device','brainVision';'marker',marker;'fs',fs});
CNT_=opt_eegStruct({EEG.data, EEG.marker, EEG.info}, field);

if ~isfield(opt,'channel'),opt.channel=1:EEG.data.nCh;end
if ~isfield(opt,'erd'),opt.erd=0;end

% cross validation parameters
CV.var.band=band;
CV.var.interval=interval;
CV.var.fv='logvar';        % temp
CV.var.classfier='LDA';    % temp
CV.var.evaluation='KFold'; % temp
CV.var.k=5;                % temp
CV.prep={
    'CNT=prep_filter(CNT, {"frequency", band})'
    'SMT=prep_segmentation(CNT, {"interval", interval})'
    };
CV.train={
    '[SMT, CSP_W, CSP_D]=func_csp(SMT,{"nPatterns", [3]})'
    'FT=func_featureExtraction(SMT, {"feature",fv})'
    '[CF_PARAM]=func_train(FT,{"classifier",classfier})'
    };
CV.test={
    'SMT=func_projection(SMT, CSP_W)'
    'FT=func_featureExtraction(SMT, {"feature",fv})'
    '[cf_out]=func_predict(FT, CF_PARAM)'
    };
CV.option={
    'evaluation' , 'k'
    };

n=size(CNT_.class,1);
pairIndex=[];
for i=1:(n-1)
    pairIndex=[pairIndex,[1:i;(1:i)+(n-i)]];
end
[~,I]=sort(sum(pairIndex));
pairIndex=pairIndex(:,I);
pairClass=cell(size(pairIndex));
for i=1:length(pairClass(:))
    pairClass{i}=CNT_.class(pairIndex(i),2);
end
pairNum=size(pairIndex,2);
LOSS=cell(pairNum,2);
CSP=cell(pairNum,2);
LDA=cell(pairNum,2);

for pair=1:pairNum

    pairstr=sprintf('%s vs %s',char(pairClass{1,pair}),char(pairClass{2,pair}));
    disp(pairstr);

    CNT=prep_selectClass(CNT_,{'class',{pairClass{1,pair}, pairClass{2,pair}}});
    CNT=prep_selectChannels(CNT,{'Index',opt.channel});

    %% Pre-processing module
    CNT=prep_filter(CNT, {'frequency', band});
    SMT=prep_segmentation(CNT, {'interval', interval});

    %% Spatial-frequency optimization module
    [SMT, CSP_W, CSP_D]=func_csp(SMT,{'nPatterns', [3]});
    FT=func_featureExtraction(SMT, {'feature',CV.var.fv});

    %% Classifier module
    [CF_PARAM]=func_train(FT,{'classifier',CV.var.classfier});

    %% Evaluation
    [loss]=eval_crossValidation_(CNT, CV);

    CSP{pair,1}=CSP_W; CSP{pair,2}=pairstr;
    LDA{pair,1}=CF_PARAM; LDA{pair,2}=pairstr;
    LOSS{pair,1}=loss;LOSS{pair,2}=pairstr;

end


function y = h2y(h)

% Y = h2y(H)
%
% Hybrid-H to Admittance transformation
%
% H and Y are matrices of size [2,2,F]
% where F is the number of frequencies

% 30.09.2011    - better 0-protection, faster division
%                 add multiple frequencies (old: martie 27)

if any(h(1,1,:) == 0)
    disp('h2y > correspondent admittance matrix non-existent');
else
    y = zeros(size(h));
    den = 1./h(1,1,:);
    y(1,1,:) = den;
    y(1,2,:) = -h(1,2,:).*den;
    y(2,1,:) = h(2,1,:).*den;
    y(2,2,:) = h(2,2,:) - h(1,2,:).*h(2,1,:).*den;
end


function [x,pnum,pgauss] = spm_mci_postslices (post,M,U,Y,Nbins)
% Univariate slices through posterior density
% FORMAT [x,pnum,pgauss] = spm_mci_postslices (post,M,U,Y,Nbins)
%
% post      posterior data structure
% M,U,Y     as usual
% Nbins     Number of bins per dimension
%
% x         [Np x Nbins] matrix where x(p,:) is domain for pth variable
% pnum      [Np x Nbins] where pnum(p,j) = p(x(p)=xj|x(\p),Y) ie. the posterior
%           density of variable p conditioned on the posterior mean of the other
%           variables. This is estimated numerically from evaluation of log joint
% pgauss    As pnum but under assumption that posterior is multivariate Gaussian
%__________________________________________________________________________
% Copyright (C) 2015 Wellcome Trust Centre for Neuroimaging

% Will Penny
% $Id: spm_mci_postslices.m 6697 2016-01-27 14:57:28Z spm $

try, Nbins=Nbins; catch, Nbins=50; end

k=5; % Defines width of domain in number of SDs

% For computing log prior term
M = spm_mci_priors (M);
M = spm_mci_minit (M);

% Need high tolerances to avoid drop-outs in log-joint plots
M.reltol=1e-6;
M.abstol=1e-6;

Np=length(post.Ep);
Ep=post.Ep;
s=sqrt(diag(post.Cp));
pE=spm_vec(M.pE);
for p=1:Np,
    xmin=Ep(p)-k*s(p);
    xmax=Ep(p)+k*s(p);
    x(p,:)=linspace(xmin,xmax,Nbins);
    P = Ep;
    for j=1:Nbins,
        % Get parameters in eigenspace of prior
        P(p) = x(p,j);
        par = M.V'*(P-pE);
        eq(j) = spm_mci_joint (par,M,U,Y);
        pg(j) = spm_mvNpdf(P,Ep,post.Cp);
    end
    eq=exp(eq);
    pnum(p,:)=eq/sum(eq);
    pgauss(p,:)=pg/sum(pg);
end

figure
for i=1:Np,
    subplot(Np,1,i);
    plot(x(i,:),pgauss(i,:),'r');
    hold on
    plot(x(i,:),pnum(i,:),'k');
    legend('Gaussian','Numeric');
    xlabel(sprintf('P(%d)',i));
end


function view = computeSpatialGradient(view)
%
% view = computeSpatialGradient(view)
%
% Loads the meanMap, then uses estFilIntGrad to compute the spatial gradient.
%
% To use this spatial gradient for inhomogeneity correction,
% - set dataTYPES(*).blockedAnalysis(*).inhomoCorrect = 2
% - load spatial gradient (from the File menu)
% - compute corAnal (from the Analysis menu)
%
% djh, 7/11/01
% Ress, 04/05 Modified to allow NaNs in meanMap.

% Tried various alternatives for computing spatial gradient:
% - more blurring in estFilIntGrad
%   [not much difference]
% - aniso3
%   [looks essentially like no blurring]
% - do nothing
%   [looks a lot like estFilIntGrad, except for a scale factor]

% Load meanMap from spatialGradMap.mat, if it exists
view = loadMeanMap(view);

% Initialize to empty cell array
nScans = numScans(view);
map = cell(1,nScans);

%% Compute the robust estimate of spatial gradient from meanMap
% put up a mrvWaitbar if needed
verbose = prefsVerboseCheck;
if verbose
    waitHandle = mrvWaitbar(0,'Computing spatial gradient from mean images.  Please wait...');
end

% main loop: across scans
for iScan = 1:nScans
    map1 = view.map{iScan};
    map1(~isfinite(map1)) = min(map1(:));
    map{iScan} = estFilIntGrad(map1);
    %map{iScan} = estPolIntGrad(view.map{iScan},[3,3,3],1);
    %map{iScan} = aniso3(view.map{iScan},'tukeyPsi',100,100);

    % a 2nd check for non-finite values is necessary (e.g., for motioncomp
    % data)
    map{iScan}( isnan(map{iScan}) | isinf(map{iScan}) ) = min(map1(:));

    if verbose, mrvWaitbar(iScan/nScans); end
end

if verbose
    close(waitHandle);
end

% Initial save; so if setParameterMap fails we're not screwed
mapName = 'spatialGrad';
save( fullfile(dataDir(view), 'spatialGrad.mat'), 'map', 'mapName' );

% Set parameter map
view = setParameterMap(view,map,'spatialGrad');

% Save file (again)
saveParameterMap(view);

return


function ll = fgplvmLogLikelihood(model)

% FGPLVMLOGLIKELIHOOD Log-likelihood for a GP-LVM.
% FORMAT
% DESC returns the log likelihood for a given GP-LVM model.
% ARG model : the model for which the log likelihood is to be
% computed. The model contains the data for which the likelihood is
% being computed in the 'y' component of the structure.
% RETURN ll : the log likelihood of the data given the model.
%
% COPYRIGHT : Neil D. Lawrence, 2005, 2006, 2009
%
% SEEALSO : gpLogLikelihood, fgplvmCreate
%
% MODIFICATIONS : Carl Henrik Ek, 2008, 2009
%
% FGPLVM

ll = gpLogLikelihood(model);

if isfield(model, 'dynamics') && ~isempty(model.dynamics)
  % A dynamics model is being used.
  ll = ll + modelLogLikelihood(model.dynamics);
elseif isfield(model, 'prior') &&  ~isempty(model.prior)
  for i = 1:model.N
    ll = ll + priorLogProb(model.prior, model.X(i, :));
  end
end

switch model.approx
  case {'dtc', 'dtcvar', 'fitc', 'pitc'}
   if isfield(model, 'inducingPrior') && ~isempty(model.inducingPrior)
     for i = 1:model.k
       ll = ll + priorLogProb(model.inducingPrior, model.X_u(i, :));
     end
   end
 otherwise
  % do nothing
end

if(isfield(model,'constraints')&&~isempty(model.constraints))
  for(i = 1:1:model.constraints.numConstraints)
    ll = ll + constraintLogLikelihood(model.constraints.comp{i},model.X);
  end
end


display('Testing data')
total_test = cell(5+1,1);
test_folder = 'C:\Users\brend_000\Documents\MATLAB\Machine Learning\Ghost Target\Images\cambridge';
for x = 1:5
    display(['Reading img', num2str(x)])
    img = imread([test_folder,'\img', num2str(x),'.jpg']);
    data = cell(8,8);
    mynxel = nxel(8,img);
    [a,b] = size(mynxel);
    for i = 1:a
        for j = 1:b
            data{i,j} = readImage(mynxel{i,j});
        end
    end
    total_test{1,1} = 'Image';
    total_test{x+1,1} = ['img',num2str(x)];
    total_test{1,2} = 'Feature';
    total_test{x+1,2} = data;

    load([test_folder,'_labels\img',num2str(x),'.mat']);
    total_test{1,3} = 'Label Set';
    total_test{x+1,3} = imgLabel;
end
load('model.mat')
load('pca_model')

[x_test, y_test, accuracy, test_labels, confusion_matrix] = validate(total_test,model,'naive');
save('Results\confusion_matrix_naive.mat','confusion_matrix');

[x_test, y_test, accuracy, test_labels, pca_confusion_matrix] = validate(total_test,pca_model,'pca');
save('Results\confusion_matrix_pca.mat','pca_confusion_matrix');


function [dWdB, dWdD, dWdS, dWdalpha, dWdgParam, dWdn] = gpsimMapWGradient(model, ...
                                                  k)
% GPSIMMAPWGRADIENT Compute the gradients of W with respect to the parameters of the k-th gene.
% FORMAT
% DESC computes the gradients of W with respect to the parameters of the k-th gene given
% Gaussian process for use in a single input motif protein network.
% ARG model : the model for which the log likelihood is computed.
% ARG k : the k-th gene.
% RETURN dWdB : the gradients of W w.r.t the model paramter Bk.
% RETURN dWdD : the gradients of W w.r.t the model paramter Dk.
% RETURN dWdS : the gradients of W w.r.t the model paramter Sk.
% RETURN dWdalpha : the gradients of W w.r.t the model paramter alpha_k.
% RETURN dWdgParam : the gradients of W w.r.t the model paramter gamma_k
% RETURN dWdn : the gradients of W w.r.t the general noise variance of the k-gene.
%
% SEEALSO : gpsimMapCreate, gpsimMapLogLikelihood,
% gpsimMapGradient, gpsimMapFunctionalLogLikeGradients
%
% COPYRIGHT : Pei Gao, Magnus Rattray and Neil D. Lawrence, 2008

% GPSIM

intPoints = model.times_index(1)+1:(model.numMapPts);
step2 = model.step*model.step;
S2 = model.S.*model.S;
numData = length(model.t);

[w1, w2] = size(model.W);

dWdB = zeros(w1, w2);
dWdD = zeros(w1, w2);
dWdS = zeros(w1, w2);
dWdalpha = [];
dWdgParam = [];
dWdn = [];
dWdalpha = [];
if model.ngParam > 0
  ngParamk = model.ngParam/model.numGenes;
  dWdgParam= zeros(w1, w2, ngParamk);
  gInd = k;
else
  gInd = 1;
end

% check if it's multiple g(f).
if isfield(model, 'isGroupNonlinearity') && strcmp(model.nonLinearity{k}, ...
                                                   'repression')
  dWdalpha = zeros(w1, w2);
end

if isfield(model, 'includeNoise') && model.includeNoise
  noiseMat = ones(numData, 1)*model.noiseVar;
  yvar = model.yvar + noiseMat;
  dWdn = zeros(w1, w2);
else
  yvar = model.yvar;
end

for p = intPoints
    for i=1:numData
      arg = model.t(i)-model.mapt(p);
      if arg >= 0
        ind = i + (k-1)*numData;
        beta_ik=1/yvar(ind);

        [dxdB dxdD dxdS dxdalpha dxdgParam] = gpsimXGradient(model, i, k);

        dWdB(p, p)=dWdB(p, p)+beta_ik*model.g_grad2(p,gInd)*dxdB* ...
                exp(-model.D(k)*arg+log(model.S(k)) +log(model.step));

        if isfield(model, 'isGroupNonlinearity')
          if strcmp(model.nonLinearity{k}, 'repression')
            dWdalpha(p,p) = dWdalpha(p, p)+beta_ik*model.g_grad2(p,gInd)* ...
                dxdalpha*exp(-model.D(k)*arg+log(model.S(k)) +log(model.step));
          end
        end

        factor = model.ypred(model.times_index(i), k)-model.y(ind);

        dWdD(p, p) = dWdD(p, p)+model.step*beta_ik*model.g_grad2(p,gInd)* ...
                (dxdD-factor*arg)*exp(-model.D(k)*arg+log(model.S(k))) ;

        dWdS(p, p) = dWdS(p, p)+model.step*beta_ik*exp(-model.D(k)* ...
                           arg)*(dxdS*model.S(k)*model.g_grad2(p,gInd)+ ...
                                 factor*model.g_grad2(p,gInd));

        if model.ngParam > 0
          for gParamInd = 1:ngParamk
            dWdgParam(p, p, gParamInd)= dWdgParam(p, p, gParamInd)+ ...
                model.step*beta_ik*exp(-model.D(k)*arg)* ...
                (dxdgParam(gParamInd)*model.S(k)*model.g_grad2(p, ...
                gInd)+ factor*model.S(k)*model.dggrad2(p,gInd));
          end
        end

        if isfield(model,'includeNoise') && model.includeNoise
          dWdn(p, p) = dWdn(p, p)-2*sqrt(model.noiseVar(k))* ...
              beta_ik^2*factor*model.g_grad2(p,gInd)*exp(-model.D(k)*arg+ ...
                                                         log(model.step)+ ...
                                                         log(model.S(k)));
        end
      end
    end
end

for p = intPoints
  for q = intPoints
    for i = 1:numData
      arg1 = model.t(i)-model.mapt(p);
      arg2 = model.t(i)-model.mapt(q);
      if arg1 >= 0 && arg2 >= 0
        ind = i + (k-1)*numData;
        beta_ik = 1/yvar(ind);

        dWdD(p,q) = dWdD(p,q)-beta_ik*model.g_grad(p,gInd)* ...
            model.g_grad(q,gInd)*(arg1+arg2)*exp(-model.D(k)*(arg1+arg2)+ ...
                                                 log(S2(k))+log(step2));

        dWdS(p,q) = dWdS(p,q)+2*beta_ik*model.S(k)* model.g_grad(q,gInd)* ...
            model.g_grad(p,gInd) * exp(-model.D(k)*(arg1+arg2)+log(step2));

        if model.ngParam > 0
          for gParamInd = 1:ngParamk
            dWdgParam(p, q, gParamInd)= dWdgParam(p, q, gParamInd)+beta_ik*(model.dggrad(q,gInd)*model.g_grad(p,gInd)+model.g_grad(q,gInd)*model.dggrad(p,gInd))*exp(-model.D(k)*(arg1+arg2)+log(S2(k))+log(step2));
          end
        end

        if isfield(model, 'includeNoise') && model.includeNoise
          dWdn(p, q) = dWdn(p, q)-2*sqrt(model.noiseVar(k))* ...
              beta_ik^2*model.g_grad(p,gInd)*model.g_grad(q,gInd)*exp(- ...
                    model.D(k)*(arg1+arg2)+log(step2)+log(S2(k)));
        end
      end
    end
  end
end


% Copyright 2017 Google Inc.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%     https://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.

% Returns set of parameters
% set light_mode = true to run the code in a sub optimal but faster mode
% set light_mode = false to obtain the results reported in the RED paper

function params = GetUniformDeblurSDParams(light_mode)

% regularization factor
params.lambda = 0.02;

% number of outer iterations
if light_mode
    params.outer_iters = 500;
else
    params.outer_iters = 1500;
end

% level of noise assumed in the regularization-denoiser
params.effective_sigma = 3.25;


function test_ft_spike_jpsth()

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_spike_jpsth

%%
% 1 channelcmb with same latency, gamma
% 1 channelcmb with fixed spike times
% 1 channelcmb with shifted latency to see effect
% 1 lfp channel
% latencies equal

spikesPerTrial = 10;
nTrials        = 10;
shapePar       = 2;
scalePar       = 3;
time           = linspace(0, 1, 1000);

data.trial(1:nTrials) = {zeros(1, length(time))};
data.time(1:nTrials) = {time};
data.fsample = 1000;

for iTrial = 1:nTrials
  iUnit = 1; % lfp channel
  data.trial{iTrial}(iUnit, :) = rand(1, 1000);

  iUnit = 2;
  spikeTimes = [];
  while length(spikeTimes)<spikesPerTrial
    spikeTimes = 0.015*gamrnd(shapePar, scalePar, [spikesPerTrial 1]);
    smp = [];
    spikeTimes(spikeTimes>1) = [];
  end
  spikeTimes = spikeTimes(1:spikesPerTrial);
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(time, spikeTimes(iSpike));
  end
  data.trial{iTrial}(iUnit, smp) = 1;
  data.trial{iTrial}(3, smp) = 1;

  iUnit = 4; % unit with fixed positions
  spikeTimes = spikeTimes + 0.01;
  smp = [];
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(time, spikeTimes(iSpike));
  end
  data.trial{iTrial}(iUnit, smp) = 1;

  iUnit = 5;
  spikeTimes = [];
  while length(spikeTimes)<spikesPerTrial
    spikeTimes = 0.015*gamrnd(shapePar, scalePar, [spikesPerTrial 1]);
    smp = [];
    spikeTimes(spikeTimes>1) = [];
  end
  spikeTimes = spikeTimes(1:spikesPerTrial);
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(time, spikeTimes(iSpike));
  end
  data.trial{iTrial}(iUnit, smp) = 1;

  iUnit = 6;
  smp = [];
  spikeTimes = linspace(0.1, 0.9, 9);
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(time, spikeTimes(iSpike));
  end
  data.trial{iTrial}(iUnit:iUnit+1, smp) = 1;

  iUnit = 8;
  smp = [];
  spikeTimes = linspace(0.1, 0.9, 9)+0.01;
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(time, spikeTimes(iSpike));
  end
  data.trial{iTrial}(iUnit:iUnit+1, smp) = 1;

end % for each trial

for iChan = 1:9
  data.label{iChan} = strcat('chan', num2str(iChan));
end

%%
% show that the psth works also with the poisson format

cfgDE.spikechannel = 2:9;
spike = ft_checkdata(data, 'datatype', 'spike', 'feedback', 'yes');

%%
% we compute the psth by calling the psth function
cfg = [];
cfg.binsize       = 0.003;
cfg.outputunit    = 'rate';
cfg.keeptrials    ='yes';
psth = ft_spike_psth(cfg, spike);

%%
cfg = [];
cfg.method = 'jpsth';
tic, jpsth = ft_spike_jpsth(cfg, psth);toc

%%
figure
cfg = [];
cfg.interpolate = 4;
cfg.window = 'gausswin';
cfg.winlen = 0.02
cfg.channelcmb = {jpsth.label{1}, jpsth.label{2}};
ft_spike_plot_jpsth(cfg, jpsth)
pause(1)
close all
%%
figure
cfg.channelcmb = {jpsth.label{1}, jpsth.label{3}};
ft_spike_plot_jpsth(cfg, jpsth)
% note the shift along the diagonal
figure
cfg = [];
cfg.channelcmb  = {'chan7' 'chan6'};
ft_spike_plot_jpsth(cfg, jpsth)

figure
cfg = [];
cfg.channelcmb  = {'chan8' 'chan6'};
ft_spike_plot_jpsth(cfg, jpsth)
pause(1)
close all

%% test with the sdf
cfg = [];
cfg.keeptrials = 'yes';
cfg.timwin = [-0.01 0.01];
[sdf] = ft_spikedensity(cfg, data);
cfg = [];
cfg.channelcmb = {'chan2' 'chan3'};
tic, jpsth = ft_spike_jpsth(cfg, sdf);toc
% note that it works on SDF as well!
figure
cfg = [];
cfg.channelcmb = {'chan3' 'chan2'};
ft_spike_plot_jpsth(cfg, jpsth)
pause(1)
close all

%%
cfg = [];
cfg.method = 'shiftpredictor';
tic, jpsth = ft_spike_jpsth(cfg, psth);toc
cfg = [];
figure
cfg.channelcmb = {'chan5' 'chan2'};
ft_spike_plot_jpsth(cfg, jpsth)
pause(1)
close all

% note the randomness around 0, shiftpredictor gives same result
%%
figure
cfg.channelcmb = {'chan3' 'chan2'};
ft_spike_plot_jpsth(cfg, jpsth)

pause(1)
close all

%% test the normalization option
cfg = [];
cfg.normalization = 'yes';
tic, jpsth = ft_spike_jpsth(cfg, psth);toc
cfg = [];
for iCmb1 = 1:7
  for iCmb2 = iCmb1:8
    figure
    cfg.channelcmb = {jpsth.label{iCmb1}, jpsth.label{iCmb2}};
    ft_spike_plot_jpsth(cfg, jpsth)
  end
end
figure
cfg.channelcmb = {'chan8', 'chan9'};
ft_spike_plot_jpsth(cfg, jpsth)

nanmax(jpsth.jpsth(:))
nanmin(jpsth.jpsth(:))
pause(1)
close all

% note how the normalized lies between -1 and 1
%%
cfg = [];
cfg.normalization = 'yes';
cfg.method = 'shiftpredictor';
tic, jpsth = ft_spike_jpsth(cfg, psth);toc
cfg = [];
%%
for iCmb1 = 1:7
  for iCmb2 = iCmb1:8
    figure
    cfg.channelcmb = {jpsth.label{iCmb1}, jpsth.label{iCmb2}};
    ft_spike_plot_jpsth(cfg, jpsth)
  end
end
pause(1)
close all

%%
figure
cfg.channelcmb = {'chan8' , 'chan9'};
ft_spike_plot_jpsth(cfg, jpsth)

figure
cfg.channelcmb = {'chan3' , 'chan2'};
ft_spike_plot_jpsth(cfg, jpsth)
pause(1)
close all

% note how the normalized lies between -1 and 1

%% check how the jpsth behaves if psth was based on variable trial length
% create data with variable length at the start

clear
spikesPerTrial  = 10;
nTrials         = 100;
shapePar        = 2;
scalePar        = 3;

data = [];
data.time = cell(1, nTrials);
data.trial = cell(1, nTrials);

for iTrial = 1:nTrials

  % create the latency, start and end have a jitter of 100 ms
  latencyBeg = 0 + (100*(rand-0.5))/1000; % is going to include some trials, and exlude some
  latencyEnd = 1 + (100*(rand-0.5))/1000;
  timeAxis   = latencyBeg:0.001:latencyEnd;
  n          = length(timeAxis);

  data.trial{iTrial} = zeros(3, n);

  iUnit = 1;
  spikeTimes = [];
  smp = [];
  while length(spikeTimes)<spikesPerTrial && length(smp)<spikesPerTrial
    spikeTimes = 0.015*gamrnd(shapePar, scalePar, [spikesPerTrial 1]);
  end
  spikeTimes = spikeTimes(1:spikesPerTrial);

  smp = [];
  spikeTimes(spikeTimes>1) = [];
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(timeAxis, spikeTimes(iSpike));
  end
  smp(smp>n) = [];
  data.trial{iTrial}(iUnit, smp) = 1;

  iUnit = 2;
  spikeTimes = spikeTimes + 0.02;
  smp = [];
  spikeTimes(spikeTimes>1) = [];
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(timeAxis, spikeTimes(iSpike));
  end
  smp(smp>n) = [];
  data.trial{iTrial}(iUnit, smp) = 1;

  iUnit = 3;
  spikeTimes = linspace(0, 1, 10);
  spikeTimes(spikeTimes>timeAxis(end) | spikeTimes<timeAxis(1)) = [];
  smp = [];
  for iSpike = 1:length(spikeTimes)
    smp(iSpike)        = nearest(timeAxis, spikeTimes(iSpike));
  end
  data.trial{iTrial}(iUnit, smp) = 1;

  data.time{iTrial}   = timeAxis;
  latencies(iTrial, 1) = timeAxis(1);
  latencies(iTrial, 2) = timeAxis(end);
end
data.fsample = 1000;
data.hdr = [];
data.cfg.trl = [];
data.label = {};
data.label{end+1} = 'spk2';
data.label{end+1} = 'spk3';
data.label{end+1} = 'spk4';
spike = ft_checkdata(data, 'datatype', 'spike', 'feedback', 'yes');

%%
% we compute the psth by calling the psth function
cfg = [];
cfg.binsize       = 0.003;
cfg.outputunit    = 'rate';
cfg.keeptrials    = 'yes';
psth = ft_spike_psth(cfg, spike);

%%
cfg = [];
cfg.trials = 1:10;
tic, jpsth = ft_spike_jpsth(cfg, psth);toc

%% check whether plotting still works fine with nans
figure
cfg = [];
cfg.channelcmb = {jpsth.label{1}, jpsth.label{2}};
ft_spike_plot_jpsth(cfg, jpsth)
pause(1)
close all


function h=hor_slice(xvect,yvect,data,const)
%FUNCTION H=VERT_SLICE(HVECT,VVECT,DATA,CONST)
% plots the 2D data of, say a seismic survey, GPR,
% resistivity survey in 3D as vertical slices
% For multiple vertical slice note that this only work
% for surveys that are mutually perpendicular.
% You have to provide:
% - HVECT: a vector with the 1st horizontal data (say offset in GPR)
% - VVECT: a vector with values for the 2nd horizontal axis.
% - DATA: the data to be displayed (make sure that the dimensions
%   match with the two vectors
% - CONST: a constant defining the depth of the slice (intersection point
%   with the z-axis.
%
% The function returns the handle of the surface plot.
%
% CAREFUL: Plotting too many slices kills your computer when dong graphical
% adjustments (rotation rescaling, ...) - you will have to be very patient
% ... or you need a faster machine.
%
% Ulrich Theune, 2003
%
%

if ~ishold
    hold on
end

[m,n]=size(data);

z=const*ones(m,n);
[x,y]=meshgrid(xvect,yvect);
h=surf(x,y,z,data);
plot3([min(xvect) min(xvect) max(xvect) max(xvect) min(xvect)],...
    [min(yvect) max(yvect) max(yvect) min(yvect) min(yvect)],...
    [const const const const const],'k','linewidth',0.1);
shading interp

clear x y z
view(3)


function [ y, m, d, f] = frac_borrow_julian ( y, m, d, f )

%*****************************************************************************80
%
%% FRAC_BORROW_JULIAN borrows fractions from days in a Julian YMDF date.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 December 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y, integer M, integer D, real F,
%    a YMDF date.
%
%    Output, integer Y, integer M, integer D, real F,
%    a YMDF date.
%
  while ( f < 0.0 )

    f = f + 1.0;

    d = d - 1;

  end

  [ y, m, d ] = day_borrow_julian ( y, m, d );

  return
end


function suborder = tetrahedron_ncc_suborder ( rule, suborder_num )

%*****************************************************************************80
%
%% TETRAHEDRON_NCC_SUBORDER returns the suborders for an NCC rule.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 January 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Peter Silvester,
%    Symmetric Quadrature Formulae for Simplexes,
%    Mathematics of Computation,
%    Volume 24, Number 109, January 1970, pages 95-100.
%
%  Parameters:
%
%    Input, integer RULE, the index of the rule.
%
%    Input, integer SUBORDER_NUM, the number of suborders of the rule.
%
%    Output, integer SUBORDER(SUBORDER_NUM), the suborders of the rule.
%
  if ( rule == 1 )
    suborder(1:suborder_num) = [ ...
      1 ];
  elseif ( rule == 2 )
    suborder(1:suborder_num) = [ ...
      4 ];
  elseif ( rule == 3 )
    suborder(1:suborder_num) = [ ...
      4, 6 ];
  elseif ( rule == 4 )
    suborder(1:suborder_num) = [ ...
      4, 12, 4 ];
  elseif ( rule == 5 )
    suborder(1:suborder_num) = [ ...
      4, 12, 6, 12, 1 ];
  elseif ( rule == 6 )
    suborder(1:suborder_num) = [ ...
      4, 12, 12, 12, 12, 4 ];
  elseif ( rule == 7 )
    suborder(1:suborder_num) = [ ...
      4, 12, 12, 12, 6, 24, 4, 4, 6 ];

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'TETRAHEDRON_NCC_SUBORDER - Fatal error!\n' );
    fprintf ( 1, '  Illegal RULE = %d\n', rule );
    error ( 'TETRAHEDRON_NCC_SUBORDER - Fatal error!' )

  end

  return
end


function zi = interp(DEM,xi,yi,method)

%INTERP interpolate to query locations
%
% Syntax
%
%     zi = interp(DEM,xi,yi)
%     zi = interp(DEM,xi,yi,method)
%
% Description
%
%     INTERP uses the griddedInterpolant class to interpolate values in the
%     instance of GRIDobj (DEM) to query locations at xi and yi.
%     If DEM.Z is an integer class, interp will convert it to single
%     precision and use linear interpolation as default. If DEM.Z is
%     logical, nearest neigbhor will be used by default.
%
% Input arguments
%
%     DEM     instance of GRIDobj
%     xi,yi   x- and y-coordinates of query locations
%     method  interpolation method (default = 'linear'). See the
%             documentation of the griddedInterpolant class for further
%             methods
%
% Output arguments
%
%     zi      interpolated values at query locations
%
% Example
%
%     DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif');
%     [x,y] = getoutline(DEM);
%     xy = rand(20,2);
%     xy(:,1) = xy(:,1)*(max(x)-min(x)) + min(x);
%     xy(:,2) = xy(:,2)*(max(y)-min(y)) + min(y);
%     z = interp(DEM,xy(:,1),xy(:,2));
%
%
% Author: Wolfgang Schwanghart (w.schwanghart[at]geo.uni-potsdam.de)
% Date: 17. August, 2017

narginchk(3,4)

if nargin == 3;
    method = 'linear';
else
    method = validatestring(method,...
        {'linear','nearest','spline','pchip','cubic'},'interp','method',4);
end

% created griddedInterpolant class
[x,y] = getcoordinates(DEM);
% flip y to get monotonic increasing grid vectors
y     = y(end:-1:1);

if isinteger(DEM.Z)
    cla   = class(DEM.Z);
    DEM.Z = single(DEM.Z);
    convoutput = true;
elseif islogical(DEM.Z)
    cla   = class(DEM.Z);
    DEM.Z = single(DEM.Z);
    if nargin == 3;
        method = 'nearest';
    end
    convoutput = true;
else
    convoutput = false;
end

F     = griddedInterpolant({x,y},flipud(DEM.Z)',method,'none');

% interpolate
zi     = F(xi,yi);

if convoutput
    zi = cast(zi,cla);
end


%% gedge
% Below is a demonstration of the features of the |dihedralAngles| function

%%
clear; close all; clc;

%% Syntax
% |[h]=gedge(E,V,AE,5,AE);|

%% Description
% The |gedge| function aids in the visualization of edges e.g. of meshes.
% Edge coloring and transparency can be prescribed.
%
% SEe also |gpatch|.

%% Examples
%

%%
% Plot settings
fontSize=20;
edgeThickness=5;
cmap=gjet(250);

%%
% Create example data, mesh data for a hex mesh

%Create mesh for a cube
boxDim=2*ones(1,3);
boxEl=1*ones(1,3);
[meshStruct]=hexMeshBox(boxDim,boxEl);
Eh=meshStruct.E;
V=meshStruct.V;
F=meshStruct.F;

%Distorting the shape (shear)
d=eye(3,3); %Identity
d(1,2)=1; %Add shear
V=V*d; %Deform

%Get mesh edges
E=patchEdges(F,V);

%% Example 1: Visualizing edges in a single color

cFigure;
subplot(1,2,1); hold on;
title('gpatch visualization of mesh faces and edges');
gpatch(F,V,'rw','r',1,edgeThickness);
axisGeom; camlight headlight;

subplot(1,2,2); hold on;
title('gedge visualization of mesh edges only');
gedge(E,V,'r',edgeThickness);
axisGeom; camlight headlight;

drawnow;

%% Example 2: Using colormapping on the edges

%%
% Create example color data on edges, e.g. the mesh dihedral angle

[~,E,AE]=dihedralAngles(Eh,V,'hex8');
AE=180*(AE./pi);

%%

cFigure; hold on;
title('Color data on edges')
gedge(E,V,AE,edgeThickness);
axisGeom; camlight headlight;
colormap(cmap); colorbar;
gdrawnow;

%% Example 3: Specifying edge transparency as well

cFigure; hold on;
title('Alpha data and color data on edges')
gedge(E,V,AE,edgeThickness,AE);
axisGeom; camlight headlight;
colormap(cmap); colorbar;
alim([25 135]);
gdrawnow;

%% Example 4: Interpolated colors from vertex (node) data

[F,V]=geoSphere(1,1);
E=patchEdges(F);
VE=patchCentre(E,V);
CE=VE(:,1); %Example edge color data  = mid-edge x-coordinate
CV=V(:,1); %Example vertex color data = x-coordinate

%%

cFigure; hold on;
title('Color data on vertices')
h= gedge(E,V,CV,edgeThickness);
h.EdgeColor='interp'; %Turn on interpolated shading
axisGeom; camlight headlight;
colormap(cmap); colorbar;
gdrawnow;

%% Example 5: Specifying RGB color data on edges

C_rgb1=cmaperise(CE,gjet(250));
C_rgb2=cmaperise(CE,viridis(250));
C_rgb3=cmaperise(CE,spectral(250));

V2=V;
V2(:,1)=V2(:,1)+2.5;
V3=V2;
V3(:,1)=V3(:,1)+2.5;

%%

cFigure; hold on;
title('RGB data on edges')
h1= gedge(E,V ,C_rgb1,edgeThickness);
h2= gedge(E,V2,C_rgb2,edgeThickness);
h3= gedge(E,V3,C_rgb3,edgeThickness);
axisGeom; camlight headlight;
gdrawnow;

%% Example 6: Specifying RGB color data on vertices (nodes)

C_rgb1=cmaperise(CV,gjet(250));
C_rgb2=cmaperise(CV,viridis(250));
C_rgb3=cmaperise(CV,spectral(250));

%%

cFigure; hold on;
title('RGB data on vertices (interpolated)')
h1= gedge(E,V ,C_rgb1,edgeThickness); h1.EdgeColor='interp';
h2= gedge(E,V2,C_rgb2,edgeThickness); h2.EdgeColor='interp';
h3= gedge(E,V3,C_rgb3,edgeThickness); h3.EdgeColor='interp';
axisGeom; camlight headlight;
gdrawnow;

%%
%
% <<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 [ V ] = GetValues( Q , knn , p )
%GETVALUE Summary of this function goes here
%   Detailed explanation goes here

V = Q(knn,:)' * p ;

end


function [ know, x ] = p42_sol ( n )

%*****************************************************************************80
%
%% P42_SOL returns the solution for problem 42.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 March 2002
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the problem.  This value
%    is only needed for those problems with variable N.
%
%    Output, integer KNOW.
%    If KNOW is 0, then the solution is not known.
%    If KNOW is positive, then the solution is known, and is returned in X.
%
%    Output, real X(N), the solution, if known.
%
  know = 1;

  x = ones ( n, 1 );

  return
end