%pls_train Partial Least Squares (training)
%
%  [B,XRes,YRes,Options] = pls_train(X,Y)
%  [B,XRes,YRes,Options] = pls_train(X,Y,Options)
%
% INPUT
%  X   [N -by- d_X]  the training (input)  data matrix, N samples, d_X variables
%  Y   [N -by- d_Y]  the training (output) data matrix, N samples, d_Y variables
%
%   Options.
%   maxLV        maximal number of latent variables (will be corrected
%                if > rank(X));
%                maxLV=inf means maxLV=min(N,d_X) -- theoretical maximum
%                number of LV;
%                by default =inf
%   method       'NIPALS' or 'SIMPLS'; by default ='SIMPLS'
%
%   X_centering  do nothing (=[] or 0), do mean centering (=nan), center
%                around some vaue v (=v);
%                by default  =[]
%   Y_centering  do nothing (=[] or 0), do mean centering (=nan), center
%                around some vaue v (=v);
%                by default  =[]
%   X_scaling    do nothing (=[] or 1), divide each col by std (=nan),
%                divide by some v (=v);
%                by default =[]
%   Y_scaling    do nothing (=[] or 1), divide each col by std (=nan),
%                divide by some v (=v);
%                by default =[]
%
% OUTPUT
%  B      [d_X -by- d_Y -by- nLV]  collection of regression matrices:
%         Y_new = X_new*B(:,:,n) represents regression on the first n
%         latent variables (X_new here after preprocessing, Y_new before
%         un-preprocessing)
%  XRes.
%   ssq  [1 -by- nLV]    the part of explaind sum of squares of
%        (preprocessed) X matrix
%   T    [N -by- nLV]    scores   (transformed (preprocessed) X)
%   R    [d_X -by- nLV]  weights  (transformation matrix)
%   P    [d_X -by- nLV]  loadings (back-transformation matrix)
%                        P(:,k) are the regression coef of
%                        (preprocessed) X on T(:,k)
%   W    [d_X -by- nLV]  local weights (local transformation matrix);
%                        ONLY FOR NIPALS
%   V    [d_X -by- nLV]  first k columns of this matrix are the
%                        orthornormal basis of the space spanned by k
%                        first columns of P; ONLY FOR SIMPLS
%  YRes.
%   ssq  [1 -by- nLV]    the part of explained sum of squares of
%                        (preprocessed) Y matrix
%   U    [N -by- nLV]    scores   (transformed (preprocessed) Y)
%   Q    [d_Y -by- nLV]  weights  (transformation matrix)
%   C    [d_Y -by- nLV]  C(:,k) are the regression coeff of
%                        (preprocessed) Y on T(:,k)
%   bin  [1 -by- nLV]    bin(k) is the regression coeff of U(:,k) on T(:,k)
%
% Options. contains the same fields as in input, but the values can be changed
% (e.g. after mean centering X_centering = mean(X,1))
%
% DESCRIPTION
% Trains PLS (Partial Least Squares) regression model
%
% Relations between matrices (X end Y are assumed to be preprocessed):
% NIPALS:
% T = X*R (columns of T are orthogonal)
% R = W*prinv(P'*W)
% P = X'*T*prinv(T'*T)
% U = Y*Q - T*(C'*Q-tril(C'*Q))
% C = Y'*T*prinv(T'*T) = Q*diag(bin)
% bin = sqrt(diag(T'*Y*Y'*T))'*prinv(T'*T))
% B = R*C' = W*prinv(P'*W)*C'
%
% SIMPLS:
% T = X*R (columns of T are orthonormal)
% P = X'*T
% U = Y*Q
% C = Y'*T = Q*diag(bin)
% bin = sqrt(diag(T'*Y*Y'*T))'
% B = R*C'
%
% BOTH:
% T_new = X_new*R
% Y_new = X_new*B
%
% SEE ALSO (PRTools Guide)
% PLS_APPLY, PLS_TRANSFORM

% Copyright: S.Verzakov, s.verzakov@ewi.tudelft.nl
% Faculty EWI, Delft University of Technology
% P.O. Box 5031, 2600 GA Delft, The Netherlands

% $Id: pls_train.m,v 1.2 2010/02/08 15:29:48 duin Exp $

function [B, XRes, YRes, Options] = pls_train(X,Y,Options)

[N_X, d_X] = size(X);
[N_Y, d_Y] = size(Y);

if N_X ~= N_Y
  error('size(X,1) must be equal to size(Y,1)');
else
  N = N_X;
end

if nargin < 3
  Options  = [];
end

DefaultOptions.X_centering = [];
DefaultOptions.Y_centering = [];
DefaultOptions.X_scaling = [];
DefaultOptions.Y_scaling = [];
DefaultOptions.maxLV = inf;
DefaultOptions.method = 'SIMPLS';

Options = pls_updstruct(DefaultOptions, Options);

if isinf(Options.maxLV)
  Options.maxLV = min(N,d_X);
elseif Options.maxLV > min(N,d_X)
  error('PLS: The number of LV(s) cannot be greater then min(N,d_X)');
end

[X, Options.X_centering, Options.X_scaling] = pls_prepro(X, Options.X_centering, Options.X_scaling);
[Y, Options.Y_centering, Options.Y_scaling] = pls_prepro(Y, Options.Y_centering, Options.Y_scaling);

ssq_X = sum(X(:).^2);
ssq_Y = sum(Y(:).^2);

B = zeros(d_X,d_Y,Options.maxLV);
XRes.ssq = zeros(1,Options.maxLV);
XRes.T   = zeros(N,Options.maxLV);
XRes.R   = zeros(d_X,Options.maxLV);
XRes.P   = zeros(d_X,Options.maxLV);
XRes.W   = [];
XRes.V   = [];

YRes.ssq = zeros(1,Options.maxLV);
YRes.U   = zeros(N,Options.maxLV);
YRes.Q   = zeros(d_Y,Options.maxLV);
YRes.C   = zeros(d_Y,Options.maxLV);
YRes.bin = zeros(1,Options.maxLV);

ev = zeros(1,Options.maxLV);
nLV = Options.maxLV;
opts.disp   = 0;
opts.issym  = 1;
opts.isreal = 1;

switch upper(Options.method)
case 'NIPALS'
  XRes.W = zeros(d_X,Options.maxLV);
  for LV = 1:Options.maxLV
    S = X'*Y;
    if d_X <= d_Y
      if d_X > 1
        [w, ev(LV)] = eigs(S*S',1,'LA',opts);
      else
        w = 1;
        ev(LV) = S*S';
      end

      t = X*w;
  	  t2 = (t'*t);
      proj = t/t2;
  	  p = X'*proj;

      c = Y'*proj;
      bin = norm(c);  %bin = sqrt(ev)/t2:
      q = c/bin;
      u = Y*q;

    else
      if d_Y > 1
        [q, ev(LV)] = eigs(S'*S,1,'LA',opts);
      else
        q = 1;
        ev(LV) = S'*S;
      end
      u = Y*q;

      w = X'*u;
  	  w = w/norm(w);
  	  t = X*w;
   	  t2 = (t'*t);
      proj = t/t2;
  	  p = X'*proj;

      bin = u'*proj;  %bin = sqrt(ev)/t2:
      c = q*bin;
  	end

	  if LV == 1
      if ev(LV) == 0
        error('PLS: Rank of the covariation matrix X''*Y is zero.');
      end
	  elseif ev(LV) <= 1e-16*ev(1)
      nLV = LV-1;
      WarnMsg = sprintf(['\nPLS: Rank of the covariation matrix X''*Y is exausted ' ...
                         'after removing %d Latent Variable(s).\n'...
                         'Results only for the %d LV(s) will be returned'],nLV,nLV);
      if exist('prwarning')
        prwarning(1, WarnMsg);
      else
        warning(WarnMsg);
      end
      break;
	  end

    %R = W*prinv(P'*W)
    %the next portion of the code makes use of the fact taht P'*W is the upper triangle matrix:
    %
    %if LV == 1
    %  InvPTW(1,1) = 1/(p'*w);
    %  r = w*InvPTW(1,1);
    %else
    %  InvPTW(1:LV,LV) = [(-InvPTW(1:LV-1,1:LV-1)*(XRes.P(:,1:LV-1)'*w)); 1]/(p'*w);
    %  r = [XRes.W(:,1:LV-1), w] * InvPTW(1:LV,LV);
    %end
    %
    %some optimization of the above code (notice that ones(m,0)*ones(0,n) == zeros(m,n)):
    %
    r = (w - (XRes.R(:,1:LV-1)*(XRes.P(:,1:LV-1)'*w)))/(p'*w);

    B(:,:,LV) = r*c';

  	XRes.ssq(:,LV) = t2*(p'*p)/ssq_X;
  	XRes.T(:,LV)   = t;
	  XRes.R(:,LV)   = r;
  	XRes.P(:,LV)   = p;
  	XRes.W(:,LV)   = w;

	  YRes.ssq(:,LV) = t2*(bin.^2)/ssq_Y;
  	YRes.U(:,LV)   = u;
  	YRes.Q(:,LV)   = q;
  	YRes.C(:,LV)   = c;
  	YRes.bin(:,LV) = bin;

  	X = X - t*p';
  	Y = Y - t*c';
  end

  if nLV < Options.maxLV
    XRes.W = XRes.W(:,1:nLV);
  end

case 'SIMPLS'
  XRes.V = zeros(d_X,Options.maxLV);
  S = X'*Y;
  for LV = 1:Options.maxLV
	  if d_X <= d_Y
		  if d_X > 1
        [r, ev(LV)] = eigs(S*S',1,'LA',opts);
      else
        r = 1;
        ev(LV) = S*S';
      end

      t = X*r;
		  norm_t = norm(t);
		  r = r/norm_t;
		  t = t/norm_t;
		  p = X'*t;

		  c = Y'*t;      %c = S'*r;
		  bin = norm(c); %bin = sqrt(ev)/norm_t:
		  q = c/bin;
		  u = Y*q;

    else
      if d_Y > 1
        [q, ev(LV)] = eigs(S'*S,1,'LA',opts);
      else
        q = 1;
        ev(LV) = S'*S;
      end
      r = S*q;
		  t = X*r;
		  norm_t = norm(t);
		  r = r/norm_t;
		  t = t/norm_t;
		  p = X'*t;

			u = Y*q;
		  bin = u'*t;    %bin = ev/norm_t:
		  c = q*bin;
	  end

	  if LV == 1
		  if ev(LV) == 0
        error('PLS: Rank of the covariation matrix X''*Y is zero.');
      else
        v = p;
      end
	  elseif ev(LV) <= 1e-16*ev(1)
      nLV = LV-1;
      WarnMsg = sprintf(['\nPLS: Rank of the covariation matrix X''*Y is exausted ' ...
                         'after removing %d Latent Variable(s).\n'...
                         'Results only for the %d LV(s) will be returned'],nLV,nLV);
      if exist('prwarning')
        prwarning(1, WarnMsg);
      else
        warning(WarnMsg);
      end
      break;
    else
  	  v = p - XRes.V(:,1:LV-1)*(XRes.V(:,1:LV-1)'*p);
	  end

	  v = v/norm(v);

    B(:,:,LV) = r*c';

    XRes.ssq(:,LV) = (p'*p)/ssq_X;
	  XRes.T(:,LV)   = t;
	  XRes.R(:,LV)   = r;
	  XRes.P(:,LV)   = p;
	  XRes.V(:,LV)   = v;

	  YRes.ssq(:,LV) = (bin.^2)/ssq_Y;
	  YRes.U(:,LV)   = u;
	  YRes.Q(:,LV)   = q;
	  YRes.C(:,LV)   = c;
	  YRes.bin(:,LV) = bin;

	  S = S - v*(v'*S);
  end

  if nLV < Options.maxLV
    XRes.V = XRes.V(:,1:nLV);
  end
end

if nLV < Options.maxLV
  B = B(:,:,1:nLV);

  XRes.ssq = XRes.ssq(:,1:nLV);
  XRes.T   = XRes.T(:,1:nLV);
  XRes.R   = XRes.R(:,1:nLV);
  XRes.P   = XRes.P(:,1:nLV);

  YRes.ssq = YRes.ssq(:,1:nLV);
  YRes.U   = YRes.U(:,1:nLV);
  YRes.Q   = YRes.Q(:,1:nLV);
  YRes.C   = YRes.C(:,1:nLV);
  YRes.bin = YRes.bin(:,1:nLV);

  Options.maxLV = nLV;
end

B = cumsum(B,3);

return;

function A = MakeSym(A)
A = 0.5*(A+A');
%A = max(A,A');

return


function lambda = tri_upper_eigenvalues ( n )

%*****************************************************************************80
%
%% TRI_UPPER_EIGENVALUES returns the eigenvalues of the TRI_UPPER matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real LAMBDA(N,1), the eigenvalues.
%
  lambda = zeros ( n, 1 );

  lambda(1:n,1) = 1.0;

  return
end


function varargout = flipdim(varargin)
%FLIPDIM   Flip/reverse a SPHEREFUN in a chosen direction.
%   G = FLIPDIM(F, DIM) returns a SPHEREFUN G with the same domain as F but
%   reversed in a direction, i.e., G(x,y)=F(x, c+d-y). If DIM = 2 (default) then
%   G(x,y) = F(x, c+d-y).  Otherwise DIM = 1 and G(x,y) = F(a+b-x, y). The
%   domain of F is [a, b, c, d].
%
% See also SPHEREFUN/FLIPLR, SPHEREFUN/FLIPUD.

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

[varargout{1:nargout}] = flipdim@separableApprox(varargin{:});

end


%PLOT_CIRCLE Draw a circle
%
% plot_circleC, R, OPTIONS) draws a circle on the current plot with
% centre C=[X,Y] and radius R.  If C=[X,Y,Z] the circle is drawn in the
% XY-plane at height Z.
%
% If C (2xN) then N circles are drawn.  If R (1x1) then all
% circles have the same radius or else R (1xN) to specify the radius of
% each circle.
%
% H = plot_circle(...) as above but return handles. For multiple
% circles H is a vector of handles, one per circle.
%
% Options::
% 'edgecolor'   the color of the circle's edge, Matlab color spec
% 'fillcolor'   the color of the circle's interior, Matlab color spec
% 'alpha'       transparency of the filled circle: 0=transparent, 1=solid
% 'alter',H     alter existing circles with handle H
%
% - For an unfilled circle:
%   - any standard MATLAB LineStyle such as 'r' or 'b---'.
%   - any MATLAB LineProperty options can be given such as 'LineWidth', 2.
% - For a filled circle any MATLAB PatchProperty options can be given.
%
% Example::
%
%          H = plot_circle([3 4]', 2, 'r');  % draw red circle
%          plot_circle([3 4]', 3, 'alter', H); % change the circle radius
%          plot_circle([3 4]', 3, 'alter', H, 'LineColor', 'k'); % change the color
%
% Notes::
% - The 'alter' option can be used to create a smooth animation.
% - The circle(s) is added to the current plot irrespective of hold status.
%
% See also PLOT_ELLIPSE, PLOT_BOX, PLOT_POLY.

% Copyright (C) 1993-2019 Peter I. Corke
%
% This file is part of The Spatial Math Toolbox for MATLAB (SMTB).
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
% of this software and associated documentation files (the "Software"), to deal
% in the Software without restriction, including without limitation the rights
% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
% of the Software, and to permit persons to whom the Software is furnished to do
% so, subject to the following conditions:
%
% The above copyright notice and this permission notice shall be included in all
% copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
% FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
% COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
% IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
%
% https://github.com/petercorke/spatial-math
function handles = plot_circle(centre, rad, varargin)

    opt.fillcolor = [];
    opt.alpha = 1;
    opt.edgecolor = 'k';
    opt.alter = [];

    [opt,arglist] = tb_optparse(opt, varargin);

    if ~isempty(opt.alter) & ~ishandle(opt.alter)
        error('SMTB:plot_circle:badarg', 'argument to alter must be a valid graphic object handle');
    end

    holdon = ishold;
    hold on

	n = 50;
	th = [0:n]'/n*2*pi;

    if length(rad) == 1
        rad = rad*ones(numcols(centre),1);
    end
    if length(centre) == 2 || length(centre) == 3
        centre = centre(:);
    end

    for i=1:numcols(centre)
        x = rad(i)*cos(th) + centre(1,i);
        y = rad(i)*sin(th) + centre(2,i);
        if numrows(centre) > 2
            % plot 3D data
            z = ones(size(x))*centre(3,i);
            if isempty(opt.alter)
                h(i) = plot3(x, y, z, varargin{:});
            else
                set(opt.alter(i), 'xdata', x, 'ydata', y, 'zdata', z, arglist{:});
            end
        else
            % plot 2D data
            if isempty(opt.fillcolor)
                if isempty(opt.alter)
                    h(i) = plot(x, y, arglist{:});
                else
                    set(opt.alter(i), 'xdata', x, 'ydata', y, arglist{:});
                end
            else
                if isempty(opt.alter)
                    h(i) = patch(x, y, 0*y, 'FaceColor', opt.fillcolor, ...
                        'FaceAlpha', opt.alpha, 'EdgeColor', opt.edgecolor, arglist{:});
                else
                    set(opt.alter(i), 'xdata', x, 'ydata', y, arglist{:});
                end

            end
        end
    end

    if holdon == 0
        hold off
    end

    if nargout > 0
        handles = h;
    end


function [kPa] = Pa2kPa(Pa)
% Convert units of pressure from pascals to kilopascals.
% Chad A Greene 2012
kPa = Pa/1000;


function [ishappy, cutoff] = classicCheck(f, values, data, pref)
%CLASSICCHECK   Attempt to trim trailing Fourier coefficients in a TRIGTECH.
%   [ISHAPPY, CUTOFF] = CLASSICCHECK(F, VALUES, DATA) returns an estimated
%   location, the CUTOFF, at which the TRIGTECH F could be truncated to
%   maintain an accuracy of EPSLEVEL (see documentation below) relative to
%   DATA.VSCALE and DATA.HSCALE. ISHAPPY is TRUE if CUTOFF <
%   MIN(LENGTH(VALUES),2) or VSCALE(F) = 0 and FALSE otherwise.
%
%   [ISHAPPY, CUTOFF] = CLASSICCHECK(F, VALUES, DATA, PREF) allows additional
%   preferences to be passed. In particular, one can adjust the target accuracy
%   with PREF.CHEBFUNEPS.
%
%   CLASSICCHECK first queries HAPPINESSREQUIREMENTS to obtain TESTLENGTH and
%   EPSLEVEL (see documentation below). If |F.COEFFS(1:TESTLENGTH)|/VSCALE <
%   EPSLEVEL, then the representation defined by F.COEFFS is deemed happy. The
%   value returned in CUTOFF is essentially that from TESTLENGTH (although it
%   can be reduced if there are further COEFFS which fall below EPSLEVEL).
%
%   HAPPINESSREQUIREMENTS defines what it means for a TRIGTECH to be happy.
%   [TESTLENGTH, EPSLEVEL] = HAPPINESSREQUIREMENTS(VALUES, COEFFS, POINTS,
%   DATA, EPS) returns two scalars TESTLENGTH and EPSLEVEL.  POINTS
%   is the vector of points at which F was sampled to get the values in
%   VALUES.  EPS is the desired accuracy.  A TRIGTECH is deemed to be
%   'happy' if the coefficients COEFFS(END-TESTLENGTH+1:END) (recall that
%   COEFFS are stored in ascending order) are all below EPSLEVEL.
%   The default choice of the test length is:
%       TESTLENGTH = n,             for n = 1:2
%       TESTLENGTH = 3,             for n = 3:44
%       TESTLENGTH = round((n-1)/8) for n > 44
%
%   EPSLEVEL is essentially the maximum of:
%       * pref.chebfuneps
%       * eps*TESTLENGTH
%       * eps*condEst (where condEst is an estimate of the condition number
%                      based upon a finite difference approximation to the
%                      gradient of the function from F.VALUES.).
%   However, the final two estimated values can be no larger than 1e-4.
%
%   Note that the accuracy check implemented in this function is the (roughly)
%   same as that employed in Chebfun v4.x.
%
% See also STRICTCHECK, LOOSECHECK.

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

% Deal with special cases ------------------------------------------------------

% Determine n (the length of the input).
n = length(f);

% Assume we're not happy. (N'aww! :( )
ishappy = false;

% Grab some preferences:
if ( nargin == 1 )
    pref = f.techPref();
    epslevel = pref.chebfuneps;
elseif ( isnumeric(pref) )
    epslevel = pref;
else
    epslevel = pref.chebfuneps;
end

% Convert scalar epslevel/tolerance inputs into vectors.
if ( isscalar(epslevel) )
    epslevel = repmat(epslevel, 1, size(f.coeffs, 2));
end

% Deal with the trivial case:
if ( n < 2 ) % (Can't be simpler than a constant!)
    cutoff = n;
    return
end

% Check the vertical scale:
if ( max(data.vscale) == 0 )
    % This is the zero function, so we must be happy!
    ishappy = true;
    cutoff = 1;
    return
elseif ( any(isinf(data.vscale)) )
    % Inf located. No cutoff.
    cutoff = n;
    return
end

% If one column of f is the zero function, we will get into trouble further
% down when we take the absolute value of the coefficients relative to vscale
% and compute the relative condition number estimate in happinessCheck.  We
% replace zero vscales by eps to avoid division by zero.
data.vscale(data.vscale == 0) = eps;

% NaNs are not allowed.
if ( any(isnan(f.coeffs(:))) )
    error('CHEBFUN:FUN:classicCheck:NaNeval', ...
        'Function returned NaN when evaluated.')
end

% We require values. Get these before we alter the coeffs:
if ( isempty(values) )
    values = f.coeffs2vals(f.coeffs);
end

% Do the test on the vector formed by the sum of the absolute value of the
% positive and negative mode coefficients.
% [TODO] This reversal of coeffs can be removed but then classicCheck will need
% to be written carefully:
absCoeffs = abs(f.coeffs(end:-1:1,:));

% Need to handle odd/even cases separately.
isEven = ~mod(n, 2);
if ( isEven )
    % In this case the negative cofficients have an additional term
    % corresponding to the cos(N/2*x) coefficient.
    f.coeffs = [absCoeffs(n,:);absCoeffs(n-1:-1:n/2+1,:)+absCoeffs(1:n/2-1,:);absCoeffs(n/2,:)];
else
    f.coeffs = [absCoeffs(n:-1:(n+1)/2+1,:)+absCoeffs(1:(n+1)/2-1,:);absCoeffs((n+1)/2,:)];
end

n = size(f.coeffs, 1);

% Check for convergence and chop location --------------------------------------

% Absolute value of coefficients, relative to vscale: (max across columns)
ac = bsxfun(@rdivide, abs(f.coeffs), data.vscale);

% Happiness requirements:
[testLength, epslevel] = ...
    happinessRequirements(values, f.coeffs, f.points(), data, epslevel);

if ( all(max(ac(1:testLength, :)) < epslevel) ) % We have converged! Chop tail:
    % We must be happy.
    ishappy = true;

    % Find first row of coeffs with entry above epslevel:
    rowsWithLargeCoeffs = any(bsxfun(@ge, ac, epslevel), 2);
    Tloc = find(rowsWithLargeCoeffs, 1, 'first') - 1;

    % Check for the zero function!
    if ( isempty(Tloc) )
        cutoff = 1;
        return
    end

    % Compute the cumulative max of eps/4 and the tail entries:
    t = .25*eps*ones(1, size(ac, 2));
    ac = ac(1:Tloc, :);             % Restrict to coefficients of interest.
    for k = 1:size(ac, 1)           % Cumulative maximum.
        ind = ac(k,:) < t;
        ac(k, ind) = t(ind);
        ind = ac(k,:) >= t;
        t(ind) = ac(k,ind);
    end

    % Obtain an estimate for much accuracy we'd gain compared to reducing
    % length ("bang for buck"):
    bang = log(1e3*bsxfun(@rdivide, epslevel, ac));
    buck = n - (1:Tloc).';
    Tbpb = bsxfun(@rdivide, bang, buck);

    % Compute position at which to chop.  Keep greatest number of coefficients
    % demanded by any of the columns.
    [ignored, perColTchop] = max(Tbpb(3:Tloc, :));
    Tchop = min(perColTchop);

    % Cutoff value.
    cutoff = n - Tchop - 2;
    % We want to keep [c(-cutoff), ...,c(-1), c(0), c(1), ..., c(cutoff)],
    % so the number of coefficients that will be thrown away is actually 2*cutoff-1.
    cutoff = 2*cutoff-1;

else

    % We're unhappy. :(
    cutoff = n;

end

end

function [testLength, epslevel] = ...
    happinessRequirements(values, coeffs, x, data, epslevel) %#ok<INUSL>
%HAPPINESSREQUIREMENTS   Define what it means for a TRIGTECH to be happy.
%   See documentation above.

% Grab the size:
n = size(coeffs, 1);

% We will not allow the estimated rounding errors to be cruder than this value:
minPrec = 1e-4; % Worst case precision!

% Length of tail to test.
testLength = min(n, max(3, round((n-1)/8)));

% Look at length of tail to loosen tolerance:
tailErr = eps*testLength;
tailErr = min(tailErr, minPrec);

% Estimate the condition number of the input function by
% ||f(x+eps(x)) - f(x)||_inf / ||f||_inf ~~ (eps(hscale)/vscale)*f'.
dy = diff(values);
dx = diff(x)*ones(1, size(values, 2));
gradEst = max(abs(dy./dx));                       % Finite difference approx.
condEst = eps(data.hscale)./data.vscale.*gradEst; % Condition number estimate.
condEst = min(condEst, minPrec);

% Choose maximum between prescribed tolerance and estimated rounding errors:
epslevel = max(max(epslevel, condEst), tailErr);

end


function output=user5sym()

%**************************************************************************
 %*************************************************************************
                %//input signal form transmitter side for symbol based\\
 clear all;
close all;
clc;
% us=input('enter the number of users');
% nb1=input('number of bits for user1');
% m1=input('enter the message sequence1');
% nb2=input('number of bits for user2');
% m2=input('enter the message sequence2');
% nb3=input('number of bits for user3');
% m3=input('enter the message sequence3');
% nb4=input('number of bits for user4');
% m4=input('enter the message sequence4');
% nb5=input('number of bits for user5');
% m5=input('enter the message sequence5');
us=3;
% nb1=5;
% nb2=5;
% nb3=5;
% nb4=5;
% nb5=5;
% m1=[1 0 0 0 0];
% m2=[1 0 0 1 0];
% m3=[1 0 1 1 0];
% m4=[1 0 1 0 1 ];
% m5=[1 0 1 0 0];

nb1=10;
nb2=10;
nb3=10;
nb4=10;
nb5=10;
m1=[1 0 0 0 0 1 0 1 0 0];
m2=[1 0 0 1 0 0 1 0 0 0];
m3=[1 0 1 0 0 1 0 1 0 1];
m4=[1 0 1 0 1 0 0 0 1 0];
m5=[1 0 1 0 0 0 1 0 0 0];

                    %//message1 into polar form\\

for i=1:nb1
    if m1(i)==1
        mb1(i)=m1(i);
    else
        mb1(i)=-1;
    end
end
  % disp(mb1);

                %//message2 into polar form\\

for i=1:nb2
    if m2(i)==1
        mb2(i)=m2(i);
    else
        mb2(i)=-1;
    end
end
  %disp(mb2);

                %//message3 into polar form\\

for i=1:nb3
    if m3(i)==1
        mb3(i)=m3(i);
    else
        mb3(i)=-1;
    end
end
  %disp(mb3);

       %//message4 into polar form\\

for i=1:nb4
    if m4(i)==1
        mb4(i)=m4(i);
    else
        mb4(i)=-1;
    end
end
  %disp(mb4);

       %//message5 into polar form\\

for i=1:nb5
    if m5(i)==1
        mb5(i)=m5(i);
    else
        mb5(i)=-1;
    end
end
  %disp(mb5);

                  %//generation of maximal length sequence1\\

  f1=1;f2=1;f3=0;f4=0;f5=1;
m=(2^5)-1;
for j=1:m
    p=xor(f2,f5);
    f5=f4;
    op1(j)=f5;
    f4=f3;
    f3=f2;
    f2=f1;
    f1=p;

end
  %disp(op1);

                    %//msequence1 into polar form\\

    for i=1:31

         if op1(i)==1
             pb1(i)=1;
         else
         pb1(i)=-1;
        end
    end
    %disp(op1);
    %disp(pb1);

                    %//generation of maximal length sequence2\\

  f1=1;f2=0;f3=0;f4=1;f5=1;
m=(2^5)-1;
for j=1:m
    p=xor(f3,f5);
    f5=f4;
    op2(j)=f5;
    f4=f3;
    f3=f2;
    f2=f1;
    f1=p;

end
  %disp(op2);

                    %//msequence2 into polar form\\

    for i=1:31
        if op2(i)==1
             pb2(i)=1;
         else
         pb2(i)=-1;
        end
    end
    %disp(op2);
    %disp(pb2);

                     %//generation of maximal length sequence3\\

  f1=1;f2=1;f3=1;f4=0;f5=1;
m=(2^5)-1;
for j=1:m
    p=xor(f4,f5);
    f5=f4;
    op3(j)=f5;
    f4=f3;
    f3=f2;
    f2=f1;
    f1=p;

end
  %disp(op3);

                    %//msequence3 into polar form\\

    for i=1:31

         if op3(i)==1
             pb3(i)=1;
         else
         pb3(i)=-1;
        end
    end
    %disp(op3);
    %disp(pb3);

                     %//generation of maximal length sequence4\\

  f1=0;f2=1;f3=1;f4=0;f5=1;
m=(2^5)-1;
for j=1:m
    p=xor(f4,f5);
    f5=f4;
    op4(j)=f5;
    f4=f3;
    f3=f2;
    f2=f1;
    f1=p;

end
  %disp(op4);

                    %//msequence4 into polar form\\

    for i=1:31

         if op4(i)==1
             pb4(i)=1;
         else
         pb4(i)=-1;
        end
    end
    %disp(op4);
    %disp(pb4);

                     %//generation of maximal length sequence5\\

  f1=1;f2=1;f3=0;f4=0;f5=1;
m=(2^5)-1;
for j=1:m
    p=xor(f4,f5);
    f5=f4;
    op5(j)=f5;
    f4=f3;
    f3=f2;
    f2=f1;
    f1=p;

end
  %disp(op5);

                    %//msequence5 into polar form\\

    for i=1:31

         if op5(i)==1
             pb5(i)=1;
         else
         pb5(i)=-1;
        end
    end
    %disp(op5);
    %disp(pb5);

                    %//spreading signals from transmitter side\\

                         %//first transmit bit\\

k=1;
for i=1:nb1
    for j=1:31
        tb1(k)=mb1(i)*pb1(j);
        k=k+1;
    end
end
%disp(tb1);

                     %//second transmit bit\\

k=1;
for i=1:nb2
    for j=1:31
        tb2(k)=mb2(i)*pb2(j);
        k=k+1;
    end
end
%disp(tb2);

                    %//third transmit bit\\

k=1;
for i=1:nb3
    for j=1:31
        tb3(k)=mb3(i)*pb3(j);
        k=k+1;
    end
end
%disp(tb3);

                %//fourth transmit bit\\

k=1;
for i=1:nb4
    for j=1:31
        tb4(k)=mb4(i)*pb4(j);
        k=k+1;
    end
end
%disp(tb4);

             %//fifth transmit bit\\

k=1;
for i=1:nb5
    for j=1:31
        tb5(k)=mb5(i)*pb5(j);
        k=k+1;
    end
end
%disp(tb5);

                 %//Addition of five  signals transmitted in the channel\\

n=1;
for i=1:k-1
    tb(n)=tb1(n)+tb2(n)+tb3(n)+tb4(n)+tb5(n);
    n=n+1;
end
%disp(tb);
chn=awgn(tb,10);

                         %//%receiver side\\
                    %//reconstruction of user2 signal\\

s2=0;
t2=1;
for i=0:31:k-32
    for j=1:31
        ob2(t2)=chn(i+j)*pb2(j)+s2;
        s2=ob2(t2);
        if ob2(t2)>0
            ob2(t2)=1;
        else ob2(t2)=0;
        end
    end
    t2=t2+1;
    s2=0;
end
%disp('second message is')
%disp(ob2);
n1=awgn(ob2,10);
 figure(1);
grid on;
subplot(2,2,1);
plot(ob2);
title('Received signal with out noise for SB');
xlabel('Time');
ylabel('Amplitude');
%g=awgn(ob2,10);
%disp(g);
subplot(2,2,2);
plot(chn);
title('Received signal with noise for SB');
xlabel('Time');
ylabel('Amplitude');

                    %//reconstruction of received signal from noise\\

for i=1:nb2
     if chn(i)>0
            g2(i)=1;
        else g2(i)=0;
        end
    end

% disp(g2);

                 % //calculating optimum weight using minimum variance\\

 ob=randint(1,31);
q=length(10);
%q1=input('enter the sequence');
s=randsrc(1,q);
c1=complex(ob,s);
%disp(c);
d=conj(c1);
d1=d*d';
%disp(d1);
m=mean(d1);
lamda=5;
teta=45;
k=((2*pi)/lamda);
K=4;
for i=0:K-1
    v=(exp(j*k*i*d*sin(teta)))';
end
%disp(v);
v1=conj(v)';
teta=30;
k=((2*pi)/lamda);
K=5;
for i=0:K-1
    eta=exp(sqrt(-1)*k*i*d*sin(teta))';
end
%u1=[2+2j 3-1j 4+3j 5+2j]'
%m=randsrc(1,124);
%a=randsrc(1,124);
l=length(10);
%l1=input('enter the sequence');
u1=complex(ob2,l);
u=eta*u1;
u2=conj(u)';
u3=u*u2;
Ru=mean(u3);

%Ru1=imresize(Ru,[124 124]);
%a1=inv(Ru1);
%a1=Ru1';
a1=Ru';
%disp(a1);
%calculating beta value
%g=1;
dem1=v*v1*a1;
beta1=dem1.^-1;
 %optimum weight
%Wopt=beta*a1*v';
temp1=beta1*v';
Wopt1=temp1*a1;
%disp(Wopt1);
 subplot(2,2,3);
plot(Wopt1);
title('Received signal with optimum weight for SB');
xlabel('Time');
ylabel('weight');

                    %//beamformer output\\

o1=conj(Wopt1)*ob2;
%disp('Beamformer output for SB')
%disp(o1);
 subplot(2,2,4);
plot(o1);
title('Beamformer output  for SB');
xlabel('Time');
ylabel('Beam former output');

                    %//SINR CALCULATION FOR SB CONFIGURATION\\

%s=length(m2);
%q1=input('enter the sequence');
s=randsrc(1,q);
c=complex(ob2,s);

hop1=conj(pb2)';
hob1=conj(c)';
nr3=hop1*hob1';
sum2=nr3'*Wopt1;
%disp('sum2');
%disp(sum2);
cm2=sum2'*sum2;
signal1=mean(cm2);
%disp('cm2');
%disp(cm2);
hop2=conj(pb2)';
hx2=conj(n1)';
nr5=hop2*hx2';
 sum3=nr5'*Wopt1;
 %disp('sum');
 %disp(sum);
  cm3=sum3'*sum3;
  noise1=mean(cm3);
 %disp('cm3');
 %disp(cm3);
 SSINR=signal1/noise1;
 disp('SSINR');
 disp(SSINR);

                %//GRAPH FOR DOA VERSUS SINR\\

    DOA=-80:10:80;
    figure(4);
    plot(DOA,SSINR,'B-*');
    title('simulation for DOA versus SSINR');
    xlabel('DOA in degree');
    ylabel('SINR in db');

                %// BER CALCULATION FOR SB CONFIGURATION\\

       k1=biterr(m2,g2);
       output=k1;
       disp('biterror rate for Sb configuration');
       disp(k1);

                 %//GRAPH FOR NUMBER USERS VERSUS BER\\

     figure(5);
     plot(us,k1,'R-*');

     title('simulation for NUMBER USERS VERSUS BER SYMBOL BASED) ');
     xlabel('NUMBER OF USERS');
     ylabel('BER');


function vl_test_imintegral

I = ones(5,6);

correct = [1     2     3     4     5     6;
           2     4     6     8    10    12;
           3     6     9    12    15    18;
           4     8    12    16    20    24;
           5    10    15    20    25    30;];

if ~all(all(slow_imintegral(I) == correct))
    fprintf('test_imintegral: FAIL slow ones test\n');
    keyboard;
end

if ~all(all(vl_imintegral(I) == correct))
    fprintf('test_imintegral: FAIL ones test\n');
    keyboard;
end

I = repmat(ones(5,6), [1 1 3]);
integral = vl_imintegral(I);
if ~all(all(all(integral == repmat(correct,[1 1 3]))))
    fprintf('test_imintegral: FAIL multidimensional ones test\n');
    keyboard;
end

ntest = 50;
for i = 1:ntest
    I = rand(5);
    integral = vl_imintegral(I);
    slow_integral = slow_imintegral(I);
    err = abs(integral - slow_integral);
    if max(err(:)) > 0.00001
        fprintf('test_imintegral: FAIL random test\n');
        keyboard;
    end
end

fprintf('test_imintegral: passed.\n');

% The slow but obvious way
function integral = slow_imintegral(I)
integral = zeros(size(I));
for k = 1:size(I,3)
    for r = 1:size(I,1)
        for c = 1:size(I,2)
            integral(r,c,k) = sum(sum(I(1:r,1:c,k)));
        end
    end
end


function p24_title ( )

%*****************************************************************************80
%
% P24_TITLE prints a title for problem 24.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'Problem 24\n' );
  fprintf ( 1, '  Name:       (|4X-2|+C)/(1+C)\n' );
  fprintf ( 1, '  Region:     0 <= X(i) <= 1\n' );
  fprintf ( 1, '  Integrand:  F(X) = prod ( (|4*X(i)-2|+C(i)) / (1+C(i)) )\n' );
  fprintf ( 1, '  Parameters:\n' );
  fprintf ( 1, '              C(1:DIM_NUM) defaults to 0.0\n' );

  return
end


function quality_test_halton ( )

%*****************************************************************************80
%
%% QUALITY_TEST_HALTON calls the QUALITY routines for points in the unit hypercube.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 December 2006
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'QUALITY_TEST_HALTON\n' );
  fprintf ( 1, '  Test the MATLAB QUALITY library\n' );
  fprintf ( 1, '  on points in the unit hypercube.' );

  ns = 100000;
  seed_init = 123456789;
  input_filename = 'halton_02_00100.txt';

  [ dim_num, n ] = r8mat_header_read ( input_filename );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The pointset was read from "%s"\n', input_filename );
  fprintf ( 1, '  The sample routine is SAMPLE_HYPERCUBE_UNIFORM.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The spatial dimension DIM_NUM =  %12d\n', dim_num   );
  fprintf ( 1, '  The number of points N =	   %12d\n', n         );
  fprintf ( 1, '  The number of sample points NS = %12d\n', ns        );
  fprintf ( 1, '  The random number SEED_INIT =    %12d\n', seed_init );
  fprintf ( 1, '\n' );

  z = r8mat_data_read ( input_filename, dim_num, n );

  r8mat_transpose_print_some ( dim_num, n, z, 1, 1, 5, 5, ...
    '  5x5 portion of data read from file:' );
%
%  For 2 dimensional datasets, some quality measures work from the Delaunay triangulation.
%  Compute that here.
%
  if ( dim_num == 2 )

    triangle_node = delaunay ( z(1,1:n), z(2,1:n) );

    triangle_node = triangle_node';
    [ dummy, triangle_num ] = size ( triangle_node );

  else

    triangle_node = [];
    triangle_num = 0;

  end

  if ( dim_num == 2 )
    quality_test005 ( n, z, triangle_num, triangle_node );
    quality_test006 ( n, z, triangle_num, triangle_node );
  end
  quality_test007 ( dim_num, n, z );
  quality_test01 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  quality_test02 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  quality_test03 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  quality_test04 ( dim_num, n, z );
  quality_test05 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  quality_test06 ( dim_num, n, z );
  quality_test07 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  quality_test08 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  if ( dim_num == 2 )
    quality_test083 ( n, z, triangle_num, triangle_node );
  end
  quality_test085 ( dim_num, n, z );
  quality_test09 ( dim_num, n, z );
  quality_test10 ( dim_num, n, z, ns, 'sample_hypercube_uniform', seed_init );
  quality_test11 ( dim_num, n, z );

  return
end


close all
clear all
path(path,'..\..\..\FUZZCLUST')
%the data
load motorcycle.txt
data.X = motorcycle(:,[1 2]);

%parameters
param.c=4;
param.m=2;
param.e=1e-4;
normalas = 1;
param.val=1;
%normalization
data=clust_normalize(data,'range');
%clustering
result = FCMclust(data,param);
param.c=result.data.f;
result = GGclust(data,param);
plot(data.X(:,1),data.X(:,2),'b.',result.cluster.v(:,1),result.cluster.v(:,2),'ro');
hold on
%draw contour-map
new.X=data.X;
eval=clusteval(new,result,param);
%validation
result = validity(result,data,param);
result.validity


function test_bug1425

% MEM 2gb
% WALLTIME 00:10:00
% DEPENDENCY ft_connectivityanalysis ft_connectivity_corr

% the bug pertains to a non-specific error when trying to do coherence computation on single trial data

% reproduce the issue
data = [];
data.trial{1} = randn(3,100);
data.time{1}  = (0:99)./100;
data.label    = {'chan01';'chan02';'chan03'};

cfg = [];
cfg.method = 'mtmfft';
cfg.output = 'fourier';
cfg.taper  = 'hanning';
freq = ft_freqanalysis(cfg, data);

cfg = [];
cfg.method = 'coh';
cfg.channelcmb = {'chan01' 'chan02'};
coh = ft_connectivityanalysis(cfg, freq);

% issue has been reproduced. It can be tracked down to ft_checkdata (fixcsd) where the singleton first dimension is not removed, leading to an incorrect dimensionality of the numeric data with respect to the dimord


function sqi = xsqi(signal,qrs,fs,win)
%xSQI Extravagance SQI
%
% Despite the fancy name, this function does some pretty boring
% calculations, while attempting to describe how different a QRS complex is
% from the rest of the signal. This is particularly important for FECG
% signals, which are often buried into noise.
%
% Input:
%   signal:         single channel (F)ECG [1xN double]
%   qrs:            list with (F)QRS locations [1xNp double]
%   fs:             signal sampling frequency [Hz]
%   win:            half of the window length around (F)QRS complex [ms],
%                   same window is used to noise area
%
% Output:
%   sqi:            resulting xSQI for segment
%
% Fetal Extraction Toolbox, version 1.0, February 2014
% Released under the GNU General Public License
%
% Copyright (C) 2014 Fernando Andreotti4
% Dresden University of Technology, Institute of Biomedical Engineering
% fernando.andreotti@mailbox.tu-dresden.de
%
% Last updated : 30-06-2016
%
% 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.

%% Generate a template
% removing extremities detections
if size(qrs,2) > size(qrs,1); qrs = qrs';end
if size(signal,2) > size(signal,1); signal = signal';end

win =  2.*round(win*fs/2); % rounding to nearest even number
hwin = 0.5*win;
extremities = (qrs <= round(1.5*win) | qrs >= length(signal)-round(1.5*win));        % test if there are peaks on the border that may lead to error
qrs = round(qrs(~extremities));                                    % remove extremity peaks
if length(qrs) <3
    disp('xsqi: skipping due to low number of beats available')
    sqi = 0;
    return
end
% Stacking cycles
M = arrayfun(@(x) signal(x-hwin:x+hwin)'.^2,qrs,'UniformOutput',false);    % creates beat matrix
M = cell2mat(M);                                                        % converting cell output to array form (matrix is 2*width+1 x
N = arrayfun(@(x) signal([(x-hwin-win):(x-hwin) (x+hwin):(x+hwin+win)])'.^2,qrs,'UniformOutput',false);    % creates a surrounding matrix
N = cell2mat(N);                                                        % converting cell output to array form (matrix is 2*width+1 x

%% Check power
Psrd = median(median(N.^2)); % Power of sorroundings
Ppeak=median(median(M.^2)); % Power of peaks
sqi=Ppeak/(Psrd+Ppeak); % percentage of power that the peaks represent

end


function [y,varargout] = bootstrap_(x,Nboot,replacement)

if nargin<3
    replacement = 0;
else
    if replacement>1
        error('replacement is logical, 0 or 1.')
    end
end

[T,N] = size(x);

y = nan(T,N,Nboot);

for nboot =1 :Nboot
    if replacement ==1
        % replacement
        order_(:,nboot)  = randi(T,[T,1]);
    else
        % no replacement
        order_(:,nboot)  = randperm(T);
    end
    y(:,:,nboot) = x(order_(:,nboot),:);
end

varargout = {order_};


function [] = visPatchLearning(RBM,iE,jB);
%-----------------------------------------
%  [] = visPatchLearning(RBM,jB,iE,rotFlag);
%-----------------------------------------
% DES

if RBM.useGPU
	RBM = gpuGather(RBM);
end

if notDefined('iE'),iE = numel(RBM.e); end

if isfield(RBM.auxVars,'invXForm');
	invXForm = RBM.auxVars.invXForm;
else
	invXForm = eye(size(RBM.W,1));
end

nVis = min(64,floor(sqrt(size(RBM.W/3,2))).^2);

subplot(331);
visPatches(RBM.X(RBM.batchIdx{jB},:)',invXForm);
title('Batch Data');

subplot(332);
visPatches(RBM.pVis',invXForm);
title('Fantasies');

subplot(333);
visPatches(RBM.dW(:,1:nVis),invXForm);
title ('Weight Gradients');

subplot(334);
hist(RBM.b);
title('Visible Bias');

subplot(335);
hist(RBM.aHid(:));
title(sprintf('E[hid]=%1.2f\nTarget Sparsity =%0.4f',mean(RBM.aHid(:)),RBM.sparsity))

subplot(336);
visPatches(RBM.W(:,1:nVis),invXForm);
title('Basis/Connection Weights');

subplot(337);
plot(RBM.log.err(1:iE));
title('Reconstruction errors');

subplot(338)
hist(RBM.W(:));
title('Connection Weights');

subplot(339);
semilogy(RBM.log.eta(1:iE));
title('Learning Rate');

drawnow


I=double(imread ('vessel.png'));
Ivessel=FrangiFilter2D(I);
figure,
subplot(1,2,1), imshow(I,[]);
subplot(1,2,2), imshow(Ivessel,[0 0.25]);


function [A,uE2F,uE] = facet_adjacency_matrix(F,varargin)
  % FACET_ADJACENCY_MATRIX  Adjacency matrix between facets determined by
  % whether two facets share an edge.
  %
  % A = facet_adjacency_matrix(F)
  % A = facet_adjacency_matrix(F,'ParameterName',ParameterValue, ...)
  %
  % Inputs:
  %   F  #F by 3 list of triangles
  %   Optional:
  %     'ManifoldOnly' followed by whether to only consider adjacency across
  %     manifold edges (valence <=2) {false}
  % Outputs:
  %   A  #F by #F adjacency matrix
  %   uE2F  #E by #F matrix so that (e,f) = 1 means face f is adjacent to
  %     unique edge e
  %   uE  #E by 2 list of unique edges
  %
  % See also: adjacency_matrix

  manifold_only = false;
  % default values
  % Map of parameter names to variable names
  params_to_variables = containers.Map( ...
    {'ManifoldOnly'},{'manifold_only'});
  v = 1;
  while v <= numel(varargin)
    param_name = varargin{v};
    if isKey(params_to_variables,param_name)
      assert(v+1<=numel(varargin));
      v = v+1;
      % Trick: use feval on anonymous function to use assignin to this workspace
      feval(@()assignin('caller',params_to_variables(param_name),varargin{v}));
    else
      error('Unsupported parameter: %s',varargin{v});
    end
    v=v+1;
  end

  ss = size(F,2);
  switch ss
  case 3
    % List of all "half"-edges: 3*#F by 2
    allE = [F(:,[2 3]); F(:,[3 1]); F(:,[1 2])];
    % Sort each row
    sortallE = sort(allE,2);
    % IC(i) tells us where to find sortallE(i,:) in uE:
    % so that sortallE(i,:) = uE(IC(i),:)
    [uE,~,IC] = unique(sortallE,'rows');
    % uE2F(e,f) = 1 means face f is adjacent to unique edge e
    uE2F = sparse(IC(:),repmat(1:size(F,1),1,ss)',1);
  case 2
    % We're really dealing with edges, so E-->vertices, F-->edges
    uE = 1:max(F(:));
    uE2F = sparse(F,repmat(1:size(F,1),2,1)',1);
  end

  % kill non-manifold edges
  if manifold_only
    uE2F(sum(uE2F,2)>2,:) = 0;
  end
  % Face-face Adjacency matrix
  A = uE2F'*uE2F;
  % All ones
  A = A>0;
end


function I_s = segImageRegion(I,S)

I_s = I;
I_s1 = I(:,:,1);
I_s2 = I(:,:,2);
I_s3 = I(:,:,3);

for i=1:max(S(:))

    mask = S==i;

%     I_s(mask) = mean(I(mask));
    I_s1(mask) = mean(I_s1(mask));
    I_s2(mask) = mean(I_s2(mask));
    I_s3(mask) = mean(I_s3(mask));

    I_s(:,:,1) = I_s1;
    I_s(:,:,2) = I_s2;
    I_s(:,:,3) = I_s3;
end

end


% change in min distance from any point on the ellipse of one fly to the
% nose of another fly
function [data,units] = compute_ddell2nose(trx,n)

flies = trx.exp2flies{n};
nflies = numel(flies);
data = cell(1,nflies);
for i = 1:nflies,
  fly = flies(i);
  if trx(fly).nframes <= 1,
    data{i} = [];
  else
    data{i} = diff(trx(fly).dell2nose,1,2) ./ trx(fly).dt;
  end
end
units = parseunits('mm/s');


function done = mission1(occupiers, player)

captured = zeros(1,6);
for i = 1:6
    captured(i) = all(occupiers{i} == player);
end

done = captured(3) && captured(6) && sum(captured) > 2;


function test_tutorial_connectivity3(datadir)

% MEM 6gb
% WALLTIME 00:10:00
% DEPENDENCY ft_timelockanalysis ft_sourceanalysis ft_connectivityanalysis ft_prepare_sourcemodel headsurface

% This is the third section of the connectivity tutorial, which
% starts with the CMC dataset, extracts a virtual channel and performs
% connectivity analysis on the virtual channel time series.

if nargin==0
  % this is where the data should be located
  datadir = dccnpath('/home/common/matlab/fieldtrip/data/ftp/tutorial/connectivity');
end

load(fullfile(datadir, 'source.mat'));

[maxval, maxindx] = max(source.avg.coh);
maxpos = source.pos(maxindx,:);

load(fullfile(datadir,'data.mat'));

%% compute the beamformer filter
cfg                   = [];
cfg.covariance        = 'yes';
cfg.channel           = 'MEG';
cfg.vartrllength      = 2;
cfg.covariancewindow  = 'all';
timelock              = ft_timelockanalysis(cfg, data);

cfg                  = [];
cfg.method           = 'lcmv';
cfg.hdmfile          = fullfile(datadir,'SubjectCMC.hdm');
cfg.sourcemodel.pos  = maxpos;
cfg.keepfilter       = 'yes';
source               = ft_sourceanalysis(cfg, timelock);

%% construct the 3-D virtual channel at the location of interest
beamformer = source.avg.filter{1};

chansel = ft_channelselection('MEG', data.label); % find the names
chansel = match_str(data.label, chansel);         % find the indices

sourcedata = [];
sourcedata.label = {'x', 'y', 'z'};
sourcedata.time = data.time;
for i=1:length(data.trial)
  sourcedata.trial{i} = beamformer * data.trial{i}(chansel,:);
end

cfg = [];
cfg.viewmode = 'vertical';  % you can also specify 'butterfly'
ft_databrowser(cfg, sourcedata);

%% construct a single virtual channel in the maximum power orientation
timeseries = cat(2, sourcedata.trial{:});

[u, s, v] = svd(timeseries, 'econ');

% whos u s v
%   Name           Size              Bytes  Class     Attributes
%
%   s              3x3                  72  double
%   u              3x3                  72  double
%   v         196800x3             4723200  double

% this is equal to the first column of matrix V, apart from the scaling with s(1,1)
timeseriesmaxproj = u(:,1)' * timeseries;

virtualchanneldata = [];
virtualchanneldata.label = {'cortex'};
virtualchanneldata.time = data.time;
for i=1:length(data.trial)
  virtualchanneldata.trial{i} = u(:,1)' * beamformer * data.trial{i}(chansel,:);
end

%% combine the virtual channel with the two EMG channels
cfg = [];
cfg.channel = 'EMG';
emgdata = ft_selectdata(cfg, data);

cfg = [];
combineddata = ft_appenddata(cfg, virtualchanneldata, emgdata);

% save combineddata combineddata

%% compute the spectral decomposition
cfg            = [];
cfg.output     = 'fourier';
cfg.method     = 'mtmfft';
cfg.foilim     = [5 100];
cfg.tapsmofrq  = 5;
cfg.keeptrials = 'yes';
cfg.channel    = {'cortex' 'EMGlft' 'EMGrgt'};
freq    = ft_freqanalysis(cfg, combineddata);

cfg = [];
cfg.method = 'coh';
coherence = ft_connectivityanalysis(cfg, freq);

cfg = [];
cfg.zlim = [0 0.2];
figure
ft_connectivityplot(cfg, coherence);
title('coherence')

figure
plot(coherence.freq, squeeze(coherence.cohspctrm(1,2,:)))
title(sprintf('connectivity between %s and %s', coherence.label{1}, coherence.label{2}));
xlabel('freq (Hz)')
ylabel('coherence')


function varargout = size( F, varargin )
%SIZE   Size of a BALLFUN.
%   S = SIZE(F) returns the size of the tensor of expansion coefficients
%   for F, where S = [m,n,p] for an mxnxp tensor of coefficients.
%
%   [M, N, P] = SIZE(F) is the same as S = SIZE(F) with S = [M, N, P].

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

if isempty( F )
    S = [];
else
    % Grab dimensions of underlying coefficient tensor:
    S = size( F.coeffs );

    % If F.coeffs is a matrix, then it has one fiber:
    if ( numel( S ) == 2 )
        S(3) = 1;
    end
end

% Prepare output:
if ( nargout <= 1 )
    if nargin > 1
        S = S(varargin{1});
    end
    varargout = { S };
else
    varargout = { S(1), S(2), S(3) };
end
end


function Hrefine2D(refineflag)

% function Hrefine2D(refineflag)
% purpose:  apply non-conforming refinement to elements labelled in refineflag

Globals2D;

% 1.1 Count vertices
Nv    = length(VX(:));

% 1.2 Find and count elements to be refined
ref = sort(find(refineflag));
Nrefine = length(ref);

% 1.3 Extract vertex numbers of elements to refine
v1 = EToV(ref, 1); v2 = EToV(ref, 2); v3 = EToV(ref, 3);

% 1.4 Uniquely number all face centers
v4 = max( 1 + Nfaces*(0:K-1)', EToF(:,1) + Nfaces*(EToE(:,1)-1) );
v5 = max( 2 + Nfaces*(0:K-1)', EToF(:,2) + Nfaces*(EToE(:,2)-1) );
v6 = max( 3 + Nfaces*(0:K-1)', EToF(:,3) + Nfaces*(EToE(:,3)-1) );

% 2.0 Extract face center vertices for elements to refine
v4 = v4(ref);      v5 = v5(ref);      v6 = v6(ref);

% 2.1 Renumber face centers contiguously from Nv+1
ids = unique([v4;v5;v6]);
newids(ids) = (1:length(ids))';
v4 = Nv+newids(v4)'; v5 = Nv+newids(v5)'; v6 = Nv+newids(v6)';

% 2.2 Replace original triangle with triangle connecting edge centers
EToV(ref,:) = [v4,v5,v6];

% 3.0 Add extra triangles to EToV
EToV(K+1:K+3*Nrefine,1) = [v1;v2;v3]; % first  vertices of new elements
EToV(K+1:K+3*Nrefine,2) = [v4;v5;v6]; % second vertices of new elements
EToV(K+1:K+3*Nrefine,3) = [v6;v4;v5]; % third  vertices of new elements

% 3.1 Create boundary condition type for refined elements
bcsave = BCType(ref,:);
BCType(ref, :) = 0; % now internal faces

BCType(K+1:K+Nrefine, 1) = bcsave(:, 1);
BCType(K+1:K+Nrefine, 3) = bcsave(:, 3);

BCType(K+Nrefine+1:K+2*Nrefine, 1) = bcsave(:, 2);
BCType(K+Nrefine+1:K+2*Nrefine, 3) = bcsave(:, 1);

BCType(K+2*Nrefine+1:K+3*Nrefine, 1) = bcsave(:, 3);
BCType(K+2*Nrefine+1:K+3*Nrefine, 3) = bcsave(:, 2);

% 3.2 Find vertex locations of elements to be refined
x1 = VX(v1);  x2 = VX(v2);  x3 = VX(v3);
y1 = VY(v1);  y2 = VY(v2);  y3 = VY(v3);

% 3.3 Add coordinates for refined edge centers
VX(v4) = 0.5*(x1+x2); VX(v5) = 0.5*(x2+x3); VX(v6) = 0.5*(x3+x1);
VY(v4) = 0.5*(y1+y2); VY(v5) = 0.5*(y2+y3); VY(v6) = 0.5*(y3+y1);

% 3.4 Increase element count
K = K+3*Nrefine;
return;


function order = order_code ( code )

%*****************************************************************************80
%
%% ORDER_CODE returns the order for each element.
%
%  List:
%
%    CODE  Order  Definition
%    ----  -----  ----------
%    Q4     4     4 node linear Lagrange/serendipity quadrilateral;
%    Q8     8     8 node quadratic serendipity quadrilateral;
%    Q9     9     9 node quadratic Lagrange quadrilateral;
%    Q12   12     12 node cubic serendipity quadrilateral;
%    Q16   16     16 node cubic Lagrange quadrilateral;
%    QL     6     6 node linear/quadratic quadrilateral;
%    T3     3     3 node linear triangle;
%    T6     6     6 node quadratic triangle;
%    T10   10     10 node cubic triangle.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string CODE, the code for the element.
%
%    Output, integer ORDER, the order of the element.
%
  if ( s_eqi ( code, 'Q4' ) )
    order = 4;
  elseif ( s_eqi ( code, 'Q8' ) )
    order = 8;
  elseif ( s_eqi ( code, 'Q9' ) )
    order = 9;
  elseif ( s_eqi ( code, 'Q12' ) )
    order = 12;
  elseif ( s_eqi ( code, 'Q16' ) )
    order = 16;
  elseif ( s_eqi ( code, 'QL' ) )
    order = 6;
  elseif ( s_eqi ( code, 'T3' ) )
    order = 3;
  elseif ( s_eqi ( code, 'T6' ) )
    order = 6;
  elseif ( s_eqi ( code, 'T10' ) )
    order = 10;
  else
    order = -1;
  end

  return
end


function trgPatch = sr_prep_target_patch(img, patchSize)

% SR_PREP_TARGET_PATCH
%
% Prepare target patches. Target patches are axis-aligned with sizes
% patchSize x patchSize.
%
% Input:
%   - img:       input image
%   - patchSize: typically 5 or 7
% Output:
%   - trgPatch:  target patches [patchSize*patchSize] x [3] x [numUvPix]

% =========================================================================

[imgH, imgW, nCh] = size(img);
numUvPix = (imgH - patchSize + 1)*(imgW - patchSize + 1);

% Initialization
trgPatch = zeros(patchSize*patchSize, 3, numUvPix, 'single');

% Get target patches using im2col
for i = 1 : nCh
    trgPatch(:,i,:) = im2col(img(:, :, i), [patchSize, patchSize], 'sliding');
end

end


function factors = ComputeAllSimilarityFactors (images, K)
% This function computes all of the similarity factors for the images in
% one word.
%
% Input:
%   images: An array of structs containing the 'img' value for each
%     character in the word.
%   K: The alphabet size (accessible in imageModel.K for the provided
%     imageModel).
%
% Output:
%   factors: Every similarity factor in the word. You should use
%     ComputeSimilarityFactor to compute these.
%
% Copyright (C) Daphne Koller, Stanford University, 2012

n = length(images);
nFactors = nchoosek (n, 2);

factors = repmat(struct('var', [], 'card', [], 'val', []), nFactors, 1);
k = 1;
% Your code here:
for i = 1:n-1
	for j = i+1:n
		factors(k) = ComputeSimilarityFactor(images,K,i,j);
		k+=1;
	end
end
end


% @author: Maziar Raissi

function params_list = Fractional()
% quantile(params_list,[0.025 0.25 0.50 0.75 0.975])

clc; close all;

plt = 1;
save_plt = 0;

addpath ..
addpath ../Utilities
addpath ../Kernels/Fractional
addpath ../Utilities/export_fig

function CleanupFun()
    rmpath ..
    rmpath ../Utilities
    rmpath ../Kernels/Fractional
    rmpath ../Utilities/export_fig
end

finishup = onCleanup(@() CleanupFun());

rng('default')

set(0,'defaulttextinterpreter','latex')

%% Load Data
[t_star, x_star, u_star] = gen_data(10^6, 0.01, 5, 100);
% u_star --> 300x5
% t_star --> 5x1
% x_star --> 300x1
N_star = size(x_star,1);
nsteps = size(t_star,1)-1;

if plt ==1
    figure(2);
    plot_surface(t_star, x_star, u_star, '$t$', '$x$', '$u(t,x)$');
    view(3);

    drawnow()
end

%% Setup
noise = 0.0;
u_data = (1 + noise*randn(size(u_star))).*u_star;

N0 = 100;
N1 = 100;
%% Optimize model
params_list = [];
hyp = [log([1.0 0.1]) 0.1 1.2 -4.0];
idx1 = randsample(N_star, N0);
step = 1;
for i = nsteps:step:nsteps
    dt = t_star(i+step) - t_star(i);

    idx0 = idx1;
    x0 = x_star(idx0,:);
    u0 = u_data(idx0,i);

    idx1 = randsample(N_star,N1);
    x1 = x_star(idx1,:);
    u1 = u_data(idx1,i+step);

    model = HPM(x1, u1, x0, u0, dt, hyp);
    model = model.train(500);

    hyp = model.hyp;
    params_list = [params_list; hyp(3:4)];

    [pred_n_star, var_n_star] = model.predict(x_star);
    var_n_star = abs(diag(var_n_star));

    error = norm(pred_n_star - u_star(:,i+step))/norm(u_star(:,i+step));

    fprintf(1,'=========================\n');
    fprintf(1,'Step: %d, Time = %.2f\n\nNLML = %.2f, Error = %.2e\n\n', i, ...
        t_star(i+step), model.NLML, error);

    str = sprintf('%.2f  ', params_list(end,:));
    fprintf('Parameters: %s\n\n', str)

    str = sprintf('%.2f  ', median(params_list,1));
    fprintf('Median: %s\n', str)
    fprintf(1,'=========================\n\n');

    if plt == 1
        if ~exist('fig','var')
            fig = figure(2);
        end
        set(fig,'units','normalized','outerposition',[0 0 1 1])
        clf

        subplot(3,1,1);
        tit = sprintf('Time: %.2f\n%d training points', t_star(i), N0);
        plot_data_1D(x_star, u_star(:,i), x0, u0, '$x$', '$u(t,x)$', tit);

        subplot(3,1,2);
        tit = sprintf('Time: %.2f\n%d training points', t_star(i+step), N1);
        plot_data_1D(x_star, u_star(:,i+step), x1, u1, '$x$', '$u(t,x)$', tit);

        subplot(3,1,3);
        plot_prediction_1D(x_star, u_star(:,i+step), pred_n_star, var_n_star, ...
            '$x$', '$u(t,x)$', tit);

        drawnow;
    end

end

if save_plt == 1
    export_fig ./Figures/Burgers.png -r300
end

end

function [t_star, x_star, u_star] = gen_data(N,dt,m,n)

    pos = cumsum(sqrt(dt)*randn(N,1));

    M = 0;

    P = zeros(length(pos)-m,m);
    for i = 1:length(pos)-m
        y = pos(i+1:i+m) - pos(i);
        M = max([M, max(abs(y))]);
        P(i,:) = y;
    end

    M = M/2;

    bins = linspace(-M,M,n+1);
    x_star = linspace(M*(1/n-1), M*(1-1/n), n)';
    t_star = dt*(1:1:m)';
    u_star = zeros(n,m);

    figure(1)
    clf
    hold
    for i = 1:m
        h = histogram(P(:,i), bins, 'Normalization', 'pdf');
        u_star(:,i) = h.Values;
    end

end


function [ x, y ] = sswap ( n, x, incx, y, incy )

%*****************************************************************************80
%
%% SSWAP interchanges two vectors.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 May 2006
%
%  Author:
%
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979.
%
%    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
%    Basic Linear Algebra Subprograms for Fortran Usage,
%    Algorithm 539,
%    ACM Transactions on Mathematical Software,
%    Volume 5, Number 3, September 1979, pages 308-323.
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vectors.
%
%    Input, real X(*), one of the vectors to swap.
%
%    Input, integer INCX, the increment between successive entries of X.
%
%    Input, real Y(*), one of the vectors to swap.
%
%    Input, integer INCY, the increment between successive elements of Y.
%
%    Output, real X(*), the swapped vector.
%
%    Output, real Y(*), the swapped vector.
%
  if ( n <= 0 )

  elseif ( incx == 1 & incy == 1 )

    m = mod ( n, 3 );

    for i = 1 : m
      temp = x(i);
      x(i) = y(i);
      y(i) = temp;
    end

    for i = m+1 : 3 : n

      temp = x(i);
      x(i) = y(i);
      y(i) = temp;

      temp = x(i+1);
      x(i+1) = y(i+1);
      y(i+1) = temp;

      temp = x(i+2);
      x(i+2) = y(i+2);
      y(i+2) = temp;

    end

  else

    if ( 0 <= incx )
      ix = 1;
    else
      ix = ( - n + 1 ) * incx + 1;
    end

    if ( 0 <= incy )
      iy = 1;
    else
      iy = ( - n + 1 ) * incy + 1;
    end

    for i = 1 : n
      temp = x(ix);
      x(ix) = y(iy);
      y(iy) = temp;
      ix = ix + incx;
      iy = iy + incy;
    end

  end

  return
end


%%*******************************************************************
%% schurmat_qblk: compute schur matrix corresponding to SOCP blocks.
%%
%% HKM direction: output = schur + Ax*Ae' + Ae*Ax' - Ad*Ad'
%% NT  direction: output = schur + Ae*Ae' - Ad*Ad'
%%
%% where schur = A*D*A', and Ad is the modification to ADA'
%% so that the latter is positive definite.
%%
%% [schur,UU,EE] = schurmat_qblk(blk,At,schur,UU,EE,p,dd,ee,xx);
%%
%% UU: stores the dense columns of Ax, Ae, Ad, and possibly
%%     those of A*D^{1/2}. It has the form UU = [Ax Ae Ad].
%% EE: stores the assocaited (2,2) block matrix when the
%%     output matrix is expressed as an augmented matrix.
%%     It has the form EE = [0 -lam 0; -lam 0 0; 0 0 I].
%%
%% options = 0, HKM
%%         = 1, NT
%%
%% SDPT3: version 3.0
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last modified: 10 Jun 02
%%*******************************************************************

   function [schur,UU,VV] = schurmat_qblk(blk,At,schur,UU,VV,p,dd,ee,xx);

   if (nargin == 9); options = 0; else; options = 1; end;

   pblk = blk(p,:); n = sum(pblk{2});  numblk = length(pblk{2});

   Ae = qprod(pblk,At{p}',ee{p});
   if (options == 0)
      Ax = qprod(pblk,At{p}',xx{p});
   end;
   decolidx = checkdense(Ae);
   ddsch = dd{p};
   if ~isempty(decolidx);
      spcolidx = setdiff([1:numblk],decolidx);
      s = 1 + [0 cumsum(pblk{2})];
      idx = s(decolidx);
      tmp = zeros(n,1);
      tmp(idx) = sqrt(2*abs(ddsch(idx)));
      Ad = qprod(pblk,At{p}',tmp);
      ddsch(idx) = abs(ddsch(idx));
      if (options == 0)
         UU = [UU Ax(:,decolidx) Ae(:,decolidx)  Ad];
         VV = [VV Ae(:,decolidx) Ax(:,decolidx) -Ad];
         Ax = Ax(:,spcolidx); Ae = Ae(:,spcolidx);
         schur = schur + Ax*Ae'+ Ae*Ax';
      else
         UU = [UU Ae(:,decolidx)  Ad];
         VV = [VV Ae(:,decolidx) -Ad];
         Ae = Ae(:,spcolidx);
         schur = schur + Ae*Ae';
      end
   else
      if (options == 0)
         schur = schur + Ax*Ae'+ Ae*Ax';
      else
         schur = schur + Ae*Ae';
      end
   end
   decolidx = checkdense(At{p}');
   if ~isempty(decolidx);
      len = length(decolidx);
      tmp = (spdiags(sqrt(abs(ddsch(decolidx))),0,len,len)*At{p}(decolidx,:))';
      UU = [UU tmp];
      VV = [VV tmp*spdiags(sign(ddsch(decolidx)),0,len,len)];
      ddsch(decolidx) = zeros(len,1);
   end
   schur = schur + At{p}' *spdiags(ddsch,0,n,n) *At{p};
%%*******************************************************************


function [rv,rvDebiased,rvSS,rvDebiasedSS,diagnostics] = realized_variance_optimal_sampling(price,time,timeType,samplingType,samplingInterval,subsamples,options)
% Estimates realized variance using Bandi-Russell optimal sampling selection
%
% USAGE:
%   [RV,RVD,RVSS,RVSSD,DIAGNOSTICS] = realized_variance_optimal_sampling(PRICE,TIME,TIMETYPE,SAMPLINGTYPE,SAMPLINGINVERVAL)
%   [RV,RVD,RVSS,RVSSD,DIAGNOSTICS] = realized_variance_optimal_sampling(PRICE,TIME,TIMETYPE,SAMPLINGTYPE,SAMPLINGINVERVAL,SUBSAMPLES,OPTIONS)
%
% INPUTS:
%   PRICE            - m by 1 vector of high frequency prices
%   TIME             - m by 1 vector of times where TIME(i) corresponds to PRICE(i)
%   TIMETYPE         - String describing the way times are measured
%                       'wall'    24-hour clock of the form HHMMSS, e.g. 101543 or 153217
%                       'seconds' Time measured in seconds past midnight on the first day.
%                       'unit'  Unit normalized date format, e.g. .1, .234, .9
%                         Unit normalized times are more general than the other types and can be
%                         applied to data from more than one calendar day
%   SAMPLINGTYPE     - String describing the type of sampling to use when
%                        filtering PRICE
%                        'CalendarTime' - Sample in calendar time using observations separated by
%                          SAMPLINGINTERVAL seconds
%                        'CalendarUniform' - Sample in calendar time using SAMPLINGINTERVAL
%                          observations spread uniformly between TIME(1) and TIME(m)
%                        'BusinessTime' - Sample in business (tick) time using observation separated
%                          by SAMPLINGINTERVAL ticks
%                        'BusinessUniform' - Sample in business (tick) time using observations
%                          uniformly spaced in business time.
%                        'Fixed' - Sample at specific points in time. When using fixed,
%                          SAMPLINGINTERVAL must be a n by 1 vector of times with the same TIMETYPE
%                          as TIME (i.e. seconds if TIME is in seconds)
%   SAMPLINGINTERVAL  - Scalar integer or n by 1 vector whose meaning depends on SAMPLINGTYPE
%   SUBSAMPLES        - [OPTIONAL] Scalar integer indicating the number of subsample realized
%                         variance estimators to average with the original realized variance.
%                         Subsample realized variances are based on prices uniformly spaced between
%                         the times (Calendar sampling) or ticks (Business sampling).  SUBSAMPLES=1
%                         will compute a subsample realized variance using the mid-point of the
%                         price sample points, 2 will use 1/3 and 2/3, and so on. In general this
%                         number should be small so the subsample estimators will be "sparse". If
%                         the computed optimal sampling frequency is smaller than SUBSAMPLES, then
%                         SUBSAMPLES is set to the compute optimal sampling frequency.
%   OPTIONS           - [OPTIONAL] Option structure initialized by realized_options.
%                         See help realized_options for a description of fields.
%
% OUTPUTS:
%   RV                - Realized variance estimated using the Bandi-Russell estimator of the optimal
%                         sampling frequency
%   RVD               - Debiased realized variance estimated using the Bandi-Russell estimator of
%                         the optimal sampling frequency for a debiased estimator
%   RVSS              - Subsample RV using the computed optimal samplig frequency
%   RVSSD             - Debiased version of subsample RV using the computed optimal samplig frequency
%   DIAGNOSTICS       - Structure with fields
%                         OPTIMALSAMPLES          - Optimal number of samples estimated using the
%                                                   Bandi-Russell methodology
%                         OPTIMALSAMPLESDEBIASED  - Optimal number of samples estimated using the
%                                                   Bandi-Russell methodology for use with a
%                                                   debiased estimator.
%                         SAMPLES                 - Number of sampled used.  Should be equal to
%                                                   OPTIMALNUMBEROFSAMPLES unless larger than the
%                                                   number of prices or smaller than 2
%                         SAMPLESDEBIASED         - Number of sampled used in debiased estimator.
%                                                   Should be equal to
%                                                   OPTIMALNUMBEROFSAMPLESDEBIASED unless larger
%                                                   than the number of prices or smaller than 2
%                         NOISEVARIANCE           - Estimated noise variance
%                         DEBIASEDNOISEVARIANCE   - Estimated noise variance bias adjusted
%                         IQESTIMATE              - Estimated IQ
%
% COMMENTS:
%   This function estimates the optimal number of samples to use when computing realized variance
%   using the method of Bandi & Russell (2008).  The role of SAMPLINGTYPE and SAMPLINGINTERVAL are
%   to set the MAXIMUM frequency of returns.  For example, if the maximum frequency was to be 15
%   seconds, set SAMPLINGTYPE='CalendarTime' and SAMPLINGINTERVAL=15.  To use all of the data,
%   set SAMPLINGTYPE='BusinessTime' and SAMPLINGINTERVAL=1.
%
% EXAMPLE:
%  % Optimal sampling in using all data
%  rvos = realized_variance_optimal_sampling(PRICE)
%  % Optimal sampling in business time with subsampling
%  [rvos,rvosSS] = realized_variance_optimal_sampling(PRICE,TIME,'Wall','BusinessTime',1,10)
%  % Optimal sampling in business time, using every 15th trade
%  rvos = realized_variance_optimal_sampling(PRICE,TIME,'Wall','BusinessTime',15)
%  % Optimal sampling where the maximum sampling frequency is 5 seonds
%  rvos = realized_variance_optimal_sampling(PRICE,TIME,'Wall','CalendarTime',5)
%
%  See also REALIZED_VARIANCE, REALIZED_KERNEL, REALIZED_QUANTILE_VARIANCE, REALIZED_RANGE,
%  REALIZED_PRICE_FILTER, REALIZED_THRESHOLD_VARIANCE

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 5/1/2008

%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%

switch nargin
    case 1
        time = linspace(wall2seconds(93000),wall2seconds(160000),length(price));
        timeType = 'seconds';
        samplingType = 'businessuniform';
        samplingInterval = 1;
        subsamples = 1;
        options = realized_options('optimal sampling');
    case 5
        subsamples = 1;
        options = realized_options('optimal sampling');
    case 6
        options = realized_options('optimal sampling');
    case 7
        if isempty(subsamples)
            subsamples = 1;
        end
        % Nothing
    otherwise
        error('5 to 7 inputs required.')
end

errorMessage = realized_variance_optimal_sampling_parameter_check(price,time,timeType,samplingType,samplingInterval,subsamples,options);
if ~isempty(errorMessage )
    error(errorMessage)
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Inserted to protect against inputing integer times
time = double(time);
% Filter the price
[filteredPrice,filteredTime] = realized_price_filter(price,time,timeType,samplingType,samplingInterval);

% Compute the number of prices
m = size(filteredPrice,1);

% Next need to estimate IQ using RV squared
[noiseVariance, debiasedNoiseVariance, IQEstimate] = realized_noise_estimate(filteredPrice, filteredTime, timeType, options);
% Need to double these since these are the variance of the error to returns, not to prices which is
% what is returns from realized_noise_esitmate
noiseVariance = 2*noiseVariance;
debiasedNoiseVariance = 2*debiasedNoiseVariance;

% Need to estimate the IQ,  Variance of Noise, and 4th moment of noise (Eq. (16))
optimalNumberOfSamples = round((IQEstimate/(noiseVariance)^2)^(1/3));
if optimalNumberOfSamples>m
    warning('oxfordRealized:excessiveLags','WARNING')
    SamplesUsed = m;
elseif optimalNumberOfSamples<2
    warning('oxfordRealized:tooFewLags','WARNING')
    SamplesUsed = 2;
else
    SamplesUsed = optimalNumberOfSamples;
end
% Compute the realized variance using BT since the prices have been
% filtered
actualSubsamples = min(subsamples,SamplesUsed);
[rv,rvSS] = realized_variance(filteredPrice, filteredTime, timeType,'BusinessTime',SamplesUsed,actualSubsamples);

filteredPriceNoise = realized_price_filter(filteredPrice, filteredTime, timeType, options.noiseVarianceSamplingType, options.noiseVarianceSamplingInterval);
returns = diff(log(filteredPriceNoise));
if options.useAdjustedNoiseCount
    n = sum(returns~=0);
else
    n = length(returns);
end
noise4thPower = sum(returns.^4)/n;
noiseVariance = sum(returns.^2)/n;
% FIXME: Need to change way denominator is estimated
% Eq. 18
optimalNumberOfSamplesDebiased = round((2*IQEstimate / (2*noise4thPower - 3*noiseVariance^2))^(1/2));
if optimalNumberOfSamplesDebiased >m
    warning('oxfordRealized:excessiveLags','WARNING')
    samplesDebiased = m;
elseif optimalNumberOfSamplesDebiased <2
    warning('oxfordRealized:tooFewLags','WARNING')
    samplesDebiased = 2;
else
    samplesDebiased = optimalNumberOfSamplesDebiased;
end

% TODO See if it is possible to do a debiased using 1-m*/m type change
actualSubsamples = min(subsamples,samplesDebiased);
[rvDebiased,rvDebiasedSS] = realized_variance(filteredPrice,filteredTime,timeType,samplingType,samplesDebiased,actualSubsamples);
rvDebiased = rvDebiased - optimalNumberOfSamplesDebiased * noiseVariance;
rvDebiasedSS = rvDebiasedSS - optimalNumberOfSamplesDebiased * noiseVariance;
rvDebiased = rvDebiased/(1-optimalNumberOfSamplesDebiased/m);
rvDebiasedSS = rvDebiasedSS/(1-optimalNumberOfSamplesDebiased/m);

diagnostics.m = length(filteredPrice) - 1;
diagnostics.optimalSamples = optimalNumberOfSamples;
diagnostics.samples = SamplesUsed;
diagnostics.optimalNumberOfSamplesDebiased = optimalNumberOfSamplesDebiased;
diagnostics.samplesDebiased = samplesDebiased;
diagnostics.noiseVariance = noiseVariance;
diagnostics.debiasedNoiseVariance = debiasedNoiseVariance;
diagnostics.IQEstimate = IQEstimate;

function errorMessage = realized_variance_optimal_sampling_parameter_check(price,time,timeType,samplingType,samplingInterval,subsamples,options)
% Support function for realized_variance_optimal_sampling that does input validation
%
% USAGE:
%   [ERRORMESSAGE,OPTIONS] = realized_variance_optimal_sampling_parameter_check(PRICE,TIME,TIMETYPE,SAMPLINGTYPE,SAMPLINGINVERVAL,OPTIONS)
%
% INPUTS:
%   See realized_variance_optimal_sampling
%
% OUTPUT:
%   ERRORMESSAGE - String containing a description of the error if one is detected.  Empty if no error.
%
% COMMENTS:
%   See realized_options for a description of the other fields in OPTIONS
%
%  See also REALIZED_VARIANCE_OPTIMAL_SAMPLING

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 5/1/2008
errorMessage = [];

if size(price,2)>size(price,1)
    price=price';
end
if size(price,2)>1
    errorMessage = 'PRICE must be a m by 1 vector.';
    return
end
if size(time,2)>size(time,1)
    time=time';
end
if any(diff(time)<0)
    errorMessage = 'TIME must be sorted and increasing';
    return
end
if size(time,2)>1 || length(time)~=length(price)
    errorMessage = 'TIME must be a m by 1 vector.';
    return
end

timeType=lower(timeType);
if ~ismember(timeType,{'wall','seconds','unit'})
    errorMessage = 'TIMETYPE must be one of ''wall'', ''seconds'' or ''unit''.';
    return;
end

samplingType=lower(samplingType);
if ~ismember(samplingType,{'calendartime','calendaruniform','businesstime','businessuniform','fixed'})
    errorMessage = ('SAMPLINGTYPE must be one of ''CalendarTime'', ''CalendarUniform'', ''BusinessTime'', ''BusinessUniform'' or ''Fixed''.');
    return;
end

if ~isempty(subsamples)
    if ~isscalar(subsamples) || subsamples<0 || floor(subsamples)~=subsamples
        errorMessage = 'SUBSAMPLES must be a non-negative scalar.';
        return
    end
end

% SAMPLINGINTERVAL
m=size(price,1);
t0=time(1);
tT=time(m);
if ismember(samplingType,{'calendartime','calendaruniform','businesstime','businessuniform'})
    % Must be a scalar integer if timeType is seconds or wall
    if ismember(timeType,{'wall','seconds'})
        if ~isscalar(samplingInterval) || floor(samplingInterval)~=samplingInterval || samplingInterval<1
            error('SAMPLINGINTERVAL must be a positive integer for the SAMPLINGTYPE selected when using ''wall'' or ''seconds'' as TIMETYPE.')
        end
    else
        if ~isscalar(samplingInterval) || samplingInterval<0
            error('SAMPLINGINTERVAL must be a positive value for the SAMPLINGTYPE selected when using ''unit'' as TIMETYPE.')
        end
    end
else
    if size(samplingInterval,2)>size(samplingInterval,1)
        samplingInterval=samplingInterval';
    end
    if ~(any(samplingInterval>=t0) && any(samplingInterval<=tT))
        error('At least one sampling interval must be between min(TIME) and max(TIME) when using ''Fixed'' as SAMPLINGTYPE.')
    end
    if any(diff(samplingInterval)<=0)
        error('When using ''Fixed'' as SAMPLINGTYPE the vector of sampling times in SAMPLINGINTERVAL must be sorted and strictly increasing.')
    end
end

% Options

% List of flat top kernels
flatTopKernelList = {'bartlett','twoscale','2ndorder','epanechnikov',...
    'cubic','multiscale','5thorder','6thorder','7thorder','8thorder','parzen',...
    'th1','th2','th5','th16'};

% List of non flat top kernels
nonFlatTopKernelList = {'nonflatparzen','qs','fejer','thinf','bnhls'};

% Combined kernel list
kernelList = [flatTopKernelList nonFlatTopKernelList];

% Check fields for valid values
optionsFieldNames = fieldnames(options);
% Insert any missing fiedls
defaultOptions = realized_options('Optimal Sampling');
defaultFieldNames = fieldnames(defaultOptions);
missingFields = setdiff(defaultFieldNames,optionsFieldNames);
if ~isempty(missingFields)
    for i = 1:length(missingFields)
        options.(missingFields{i}) = defaultOptions.(missingFields{i});
    end
end

for i=1:length(optionsFieldNames)
    fieldName = optionsFieldNames{i};
    fieldValue = options.(fieldName);
    if ischar(fieldValue)
        fieldValue = lower(fieldValue);
        options.(fieldName) = fieldValue;
    end

    switch fieldName
        case {'medFrequencyKernel'}
            % Member of kernelList
            if ~ismember(fieldValue,kernelList)
                errorMessage = ['OPTIONS.' fieldName ' must be one of the listed types.'];
                return
            end
        case {'medFrequencyBandwidth'}
            % Non-negative scalar
            if ~isempty(fieldValue) && ~isnonnegativescalar(fieldValue)
                errorMessage = ['OPTIONS.' fieldName ' must a non-negative scalar.'];
                return
            end
        case {'useDebiasedNoise','useAdjustedNoiseCount'}
            % Logical or scalar
            if ~islogical(fieldValue) && ~ismember(fieldValue,[0 1])
                errorMessage = 'OPTIONS.useDebiasedNoise must be a logical value.';
                return
            end
        case {'IQEstimationSamplingType','medFrequencySamplingType','noiseVarianceSamplingType'}
            % One of the sampling types
            if ~ismember(fieldValue,{'calendartime','calendaruniform','businesstime','businessuniform','fixed'})
                errorMessage = ['OPTIONS.' fieldName ' must be one of ''CalendarTime'', ''CalendarUniform'', ''BusinessTime'', ''BusinessUniform'' or ''Fixed''.'];
                return
            end
        case {'medFrequencySamplingInterval','noiseVarianceSamplingInterval','IQEstimationSamplingInterval'}
            % Non-negative scalar, less that 1 if timeType is unit
            if isempty(fieldValue) || ~isnonnegativescalar(fieldValue)
                errorMessage = ['OPTIONS.' fieldName ' must be a non-negative scalar between 0 and 1.'];
                return
            end
            if strcmp(timeType,'unit') && fieldValue>1
                errorMessage = ['OPTIONS.' fieldName ' must be less than 1 if TIMETYPE when ''unit''.'];
                return
            end
    end
end

function condition = isnonnegativescalar(x)
% Function that returns logical true if that input is a non-empty scalar >=0
condition = ~isempty(x) && isscalar(x) && x>=0;


% Calculate the 16-bit CRC used on the payload for DroneID
%
% This code is a MATLAB port of
% https://github.com/dji-sdk/Guidance-SDK/blob/master/examples/uart_example/crc16.cpp
%
% This function can be used to validate a CRC by running with all bytes including the CRC.  If the purpose is to
% calculate what the CRC should be, then do not include the additional two bytes of zeros and instead just remove the
% bytes that will be the CRC
%
% @param byte_vector Row/Column vector of uint8 values
% @return checksum uint16 CRC output value
function [checksum] = calculate_crc(byte_vector)

    crc_table = [
        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, ...
        0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, ...
        0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, ...
        0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, ...
        0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, ...
        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, ...
        0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, ...
        0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, ...
        0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, ...
        0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, ...
        0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, ...
        0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, ...
        0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, ...
        0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, ...
        0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, ...
        0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, ...
        0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, ...
        0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, ...
        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, ...
        0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, ...
        0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, ...
        0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, ...
        0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, ...
        0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, ...
        0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, ...
        0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, ...
        0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, ...
        0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, ...
        0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, ...
        0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, ...
        0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, ...
        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 ...
    ];

    assert(~isempty(byte_vector), "Input vector was empty");
    assert(isrow(byte_vector) || iscolumn(byte_vector), "Input vector must be row/col");

    checksum = uint16(0x3692);

    for idx=1:length(byte_vector)
        % Very verbose due to the amount of strange things that need to be done to make MATLAB play nice with bit ops
        new_byte = uint8(byte_vector(idx));
        table_idx = bitxor(checksum, uint16(new_byte));
        table_idx = bitand(table_idx, uint16(0x00ff));
        val = crc_table(table_idx + 1);
        temp_checksum = bitshift(checksum, -8);
        checksum = bitxor(temp_checksum, val);
    end
end


% test code for tt_qconv()
%
% April 26, 2011
% Vladimir Kazeev
% vladimir.kazeev@gmail.com
% INM RAS
% Moscow, Russia
%

% a,b,eps are parameters
d=10;
a=-1;
b=1;
eps=1E-10;
%

n=2^d;
h=(b-a)/n;
mesh=((1-n:n)'-1/2)*h;
x=exp(-1000*(mesh-0.1).^2);

mesh=((1-n/2:n/2)'-1/2)*h;
y=zeros(n,1);
y(n/2-n/8:n/2+n/8-1)=ones(n/4,1);
y=exp(-1000*(mesh-0.5).^2);

tt_x=full_to_tt(reshape(x,2*ones(1,d+1)),eps);
tt_y=full_to_tt(reshape(y,2*ones(1,d)),eps);

tt_z=tt_qconv(tt_x,tt_y,d);
z=h*tt_qtofull(tt_z,1);

f1=figure; hold on;
set(0,'CurrentFigure',f1)
plot(mesh,x(n/2:n*3/2-1),'r');
f2=figure; hold on;
set(0,'CurrentFigure',f2)
plot(mesh,y,'b');
f3=figure; hold on;
set(0,'CurrentFigure',f3)
plot(mesh,z,'g');


% This subroutine assigns creates a 3D grid with
% spacing dx,dy, dz (in degreees). The size will
% be selected interactiVELY. The pvalue in each
% volume around a grid point containing ni earthquakes
% will be calculated as well as the magnitude
% of completness
%   Stefan Wiemer 1/98

report_this_filefun(mfilename('fullpath'));
global no1 bo1 inb1 inb2

if sel == 'in'
    % get the grid parameter
    % initial values
    %
    dx = 0.1;
    dy = 0.1 ;
    dz = 5.00 ;

    def = {'0.1','0.1',num2str(dz),num2str(max(a.Depth)), num2str(min(a.Depth))};

    tit ='Three dimesional b-value analysis';
    prompt={ 'Spacing in Lat/Lon (dx in [deg])',...
        'Sample Raduis [km])',...
        'Spacing in Depth    (dz in [km ])',...
        'Depth Range: deep limit [km] ',...
        'Depth Range: shallow limit',...
        };

    ni2 = inputdlg(prompt,tit,1,def);

    l = ni2{1}; dx= str2num(l);dy = dx;
    l = ni2{2}; R= str2double(l);
    l = ni2{3}; dz= str2double(l);
    l = ni2{4}; z1= str2double(l);
    l = ni2{5}; z2= str2double(l);

    sel = 'ca'; density_3D

end   % if sel == 'in'

% get the grid-size interactively and
% calculate the b-value in the grid by sorting
% thge seimicity and selectiong the ni neighbors
% to each grid point

if sel == 'ca'
    selgp3dB

    gz = zvect;
    itotal = length(t5);
    zmap_message_center.set_info(' ','Running... ');think
    %  make grid, calculate start- endtime etc.  ...
    %
    bvg = ones(length(gx),length(gy),length(gz))*nan;

    t0b = min(a.Date)  ;
    n = a.Count;
    teb = a(n,3) ;
    tdiff = round((teb - t0b)*365/par1);
    loc = zeros(3, length(gx)*length(gy));
    Rconst = R;
    % loop over  all points
    %
    i2 = 0.;
    i1 = 0.;
    allcount = 0.;
    wai = waitbar(0,' Please Wait ...  ');
    set(wai,'NumberTitle','off','Name',' 3D gridding - percent done');;
    drawnow
    %
    %

    z0 = 0; x0 = 0; y0 = 0; dt = 1;
    % loop over all points
    for il =1:length(t5)

        x = t5(il,1);
        y = t5(il,2);
        z = t5(il,3);

        allcount = allcount + 1.;

        % calculate distance from center point and sort wrt distance
        l = sqrt(((a.Longitude-x)*cos(pi/180*y)*111).^2 + ((a.Latitude-y)*111).^2 + ((a.Depth - z)).^2 ) ;
        [s,is] = sort(l);
        b = a(is(:,1),:) ;       % re-orders matrix to agree row-wise

        l3 = l <= R;
        b = a.subset(l3);      % new data per grid point (b) is sorted in distanc
        rd = length(b(:,1));

        bvg(t5(il,5),t5(il,6),t5(il,7)) = rd;

        waitbar(allcount/itotal)
    end  % for t5

    % save data
    %
    gz = -gz;
    zv2 = bvg;
    zvg = bvg;

    close(wai)
    watchoff

    sel = 'no';

    ButtonName=questdlg('Which viwer would you like to use?', ...
        'Question', ...
        'Slicer - map view','Slicer - 3D ','Help','none');

    switch ButtonName
        case 'Slicer - map view'
            slm = 'new'; slicemap;
        case 'Slicer - 3D '
            ac2 = 'new'; myslicer;
        case 'Help'
            showweb('3dbgrids')
    end % switch

    uicontrol('Units','normal',...
        'Position',[.90 .95 .04 .04],'String','Slicer',...
         'Callback','')

    %ac2 = 'new'; myslicer;

end  % if cal


function pointsOut = applyHomography(pointsIn, H)
%% Apply homography transformation to a set of points.

%% License
% ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY
% Copyright (c) 2018 Bingyao Huang
% All rights reserved.

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

% The above copyright notice and this permission notice shall be included in all
% copies or substantial portions of the Software.

% If you publish results obtained using this software, please cite our paper.

% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.

%%

% convert to homogenious coord and transpose
pointsInHomogen = [pointsIn, ones(size(pointsIn,1),1)]';

% apply homography
pointsOutHomogen = H * pointsInHomogen;

% divide by w and convert back to non-homogenious, then transpose
pointsOut = [pointsOutHomogen(1,:)./pointsOutHomogen(3,:); ...
    pointsOutHomogen(2,:)./pointsOutHomogen(3,:)]';
end


function bw = Bw_Img(I)

if ndims(I) == 3
    I = rgb2gray(I);
end
bw = im2bw(I, graythresh(I));
bw = ~bw;


classdef ErrorMultiClass < dagnn.Loss
% author: Hakan Bilen
% computes multi-class accuracy
% inputs{1}->scores
% inputs{2}->gt labels
  properties
    nImgPerClass = []
    nCorPred = []
    accuracy = []
    resetLayer = false
  end

  methods
    function outputs = forward(obj, inputs, params)

      if numel(inputs)~=2
        error('wrong number of inputs');
      end

      nCls = size(inputs{1},3);

      if obj.resetLayer || isempty(obj.nImgPerClass)
        obj.nImgPerClass = zeros(1,size(inputs{1},3));
        obj.nCorPred = zeros(1,size(inputs{1},3));
        obj.accuracy = zeros(1,size(inputs{1},3));

        if obj.resetLayer
          obj.resetLayer = false ;
          obj.average = 0 ;
        end
      end

      [~,predictions] = max(gather(squeeze(inputs{1})),[],1);

      for c=1:nCls
        obj.nImgPerClass(c) = obj.nImgPerClass(c) + sum(inputs{2}==c);
        obj.nCorPred(c)     = obj.nCorPred(c) + sum(predictions==c & inputs{2}==c);
      end

      ni = obj.nImgPerClass;
      ni(ni==0) = 1;

      obj.accuracy = obj.nCorPred ./ ni;
      obj.average = (1-mean(obj.accuracy));
      outputs{1} =  obj.average;
    end

    function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
      derInputs = cell(1,2);
      derParams = {} ;
    end

    function reset(obj)
      obj.resetLayer = true ;
%       obj.nImgPerClass = [];
%       obj.nCorPred = [];
%       obj.accuracy = [];
%       obj.average = 0;
    end

    function obj = ErrorMultiClass(varargin)
      obj.load(varargin) ;
      obj.loss = 'error_multi_class' ;
    end
  end
end


function plot_MapsSeries4(sFilename)
%
%
%
load(sFilename)

%% plot results mean z values
cmin=-4;cmax=4;

for i=1:size(params.mPolZ,2)

figure_w_normalized_uicontrolunits('Name','Z-probability by overlap','Position',[100 25 400 400]);
pcolor(params.vX,params.vY,...
    reshape(calc_ProbColorbar2Value(1-params.mPolZ(:,i)),...
    size(params.vY,1),size(params.vX,1)));
xlabel('longitude');
ylabel('latitude');
title(sprintf('%6.1f-%6.1f vs. %6.1f-%6.1f',params.fTstart,...
    params.fT-params.mVar(i,1),params.fT-params.mVar(i,1),params.fT));
plot_ProbColorbar2(cmin, cmax);
% set(gca,'XAxisLocation','Top','XTick',0.5,'XTickLabel', 'P(z)')
shading interp;
hold on;plot(params.mCatalog(:,1),params.mCatalog(:,2),'k.','MarkerSize',0.1);
plot_WiemerWyss1994
xlim([-117.1 -115.6]);
ylim([33 35.2]);

end

end

function plot_WiemerWyss1994
mLatLon=[[-117.1 33];
    [-115.6 33];
    [-115.6 35.2];
    [-117.1 35.2];
    [-117.1 33]];
hold on;plot(mLatLon(:,1),mLatLon(:,2),'k--');
mLanders=[-116.4 34.3];
hold on;plot(mLanders(1),mLanders(2),'ko','MarkerSize',20)
end


function [E, T_noise_squared, d] = error_foo(Theta, X, sigma, P_inlier, parameters)

% [E T_noise_squared d] = error_foo(Theta, X, sigma, P_inlier, parameters)
%
% DESC:
% Template to estimate the error due to the foo constraint. To
% return only the error threshold the function call should be:
%
% [dummy T_noise d] = error_foo([], [], sigma, P_inlier, parameters);
%
% INPUT:
% Theta             = foo parameter vector
% X                 = samples on the manifold
% sigma             = noise std
% P_inlier          = Chi squared probability threshold for inliers
%                     If 0 then use directly sigma.
% parameters        = the parameters used by the functions
%
% OUTPUT:
% E                 = squared error
% T_noise_squared   = squared noise threshold
% d                 = degrees of freedom of the error distribution

% compute the error obtained by the orthogonal projection of
% the data points X onto the model manifold instantiated with the
% parameters Theta
E = [];
if ~isempty(Theta) && ~isempty(X)

    % error computation

end;

% compute the error threshold
if (nargout > 1)

    if (P_inlier == 0)
        % in this case the parameter sigma coincides with the noise
        % threshold
        T_noise_squared = sigma;
    else
        % otherwise we compute the error threshold given the standard
        % deviation of the noise assuming that the errors are normally
        % distributed. Hence the sum of their squares is Chi2
        % distributed with d degrees of freedom
        d = ;

        % compute the inverse probability
        T_noise_squared = sigma^2 * chi2inv_LUT(P_inlier, d);

    end;

end;

return;


function es = ESupdate(mu,lambda,iter)

% Create vector of ES weights
es.mu = mu;
es.lambda = lambda;
es.iter = iter;
tot = es.mu + es.lambda;
w = ceil((1./sqrt(1:tot))/sum(1./sqrt(1:tot))*es.lambda);
nonzero = sum(w > 0);
while (sum(w) - es.lambda) > nonzero
    w = max(0, w - 1);
    nonzero = sum(w > 0);
end
delta = sum(w) - es.lambda;
lastnonzero = find(w > 0, 1, 'last');
w(max(1,lastnonzero-delta+1):lastnonzero) = w(max(1,lastnonzero-delta+1):lastnonzero) - 1;

% Create selection mask
cw = cumsum(w) - w + 1;
idx(cw) = 1;
es.selectmask = cumsum(idx(1:end-1));

end


% Reconstruction of 2D Cartesian Pulseq data
% provides an example on how data reordering can be detected from the MR
% sequence with almost no additional prior knowledge
%
% it loads Matlab .mat files with the rawdata in the format
%     adclen x channels x readouts
% if Matlab .mat file not available it attempt to load Siemens .dat (which needs mapVBVD in the path)
% but first it seeks the accompanying .seq file with the same name to interpret
%     the data

%% Load the latest file from the specified directory
path='../IceNIH_RawSend/'; % directory to be scanned for data files
%path='/data/Dropbox/ismrm2021pulseq_liveDemo/dataLive/Vienna_7T_Siemens'; % directory to be scanned for data files

if path(end)~=filesep, path=[path filesep]; end

pattern='*.seq';
D=dir([path pattern]);
[~,I]=sort([D(:).datenum]);
seq_file_path=[path D(I(end-0)).name]; % use end-1 to reconstruct the second-last data set, etc...
                                                % or replace I(end-0) with I(1) to process the first dataset, I(2) for the second, etc...
%seq_file_path='../interpreters/siemens/data_example/gre_example.seq'

% keep basic filename without the extension
[p,n,e] = fileparts(seq_file_path);
basic_file_path=fullfile(p,n);

% try loading Matlab data
data_file_path=[basic_file_path '.mat'];
if isfile(data_file_path)
    fprintf(['loading `' data_file_path '´ ...\n']);
    data_unsorted = load(data_file_path);
    if isstruct(data_unsorted)
        fn=fieldnames(data_unsorted);
        assert(length(fn)==1); % we only expect a single variable
        data_unsorted=data_unsorted.(fn{1});
    end
else
    % revert to Siemens .dat file
    data_file_path=[basic_file_path '.dat'];
    fprintf(['loading `' data_file_path '´ ...\n']);
    twix_obj = mapVBVD(data_file_path);
    if iscell(twix_obj)
        data_unsorted = twix_obj{end}.image.unsorted();
        seqHash_twix=twix_obj{end}.hdr.Dicom.tSequenceVariant;
    else
        data_unsorted = twix_obj.image.unsorted();
        seqHash_twix=twix_obj.hdr.Dicom.tSequenceVariant;
    end

    if length(seqHash_twix)==32
        fprintf(['raw data contain pulseq-file signature ' seqHash_twix '\n']);
    end

end
[adc_len,channels,readouts]=size(data_unsorted);

%% Load sequence from file
fprintf(['loading `' seq_file_path '´ ...\n']);
seq = mr.Sequence();              % Create a new sequence object
seq.read(seq_file_path,'detectRFuse');
seqName=seq.getDefinition('Name');
if ~isempty(seqName), fprintf('sequence name: %s\n',seqName); end
[ktraj_adc, t_adc, ktraj, t_ktraj, t_excitation, t_refocusing] = seq.calculateKspacePP();
figure; plot(ktraj(1,:),ktraj(2,:),'b',...
             ktraj_adc(1,:),ktraj_adc(2,:),'r.'); % a 2D plot
axis('equal'); title('2D k-space trajectory');

%% Analyze the trajectory data (ktraj_adc)
fprintf('analyzing the k-space trajectory ...\n');
k_extent=max(abs(ktraj_adc),[],2);
k_scale=max(k_extent);
k_threshold=k_scale/5000;

% detect unused dimensions and delete them
if any(k_extent<k_threshold)
    ktraj_adc(k_extent<k_threshold,:)=[]; % delete rows
    k_extent(k_extent<k_threshold)=[];
end

% detect dK, k-space reordering and repetitions (or slices, etc)
kt_sorted=sort(ktraj_adc,2);
dk_all=kt_sorted(:,2:end)-kt_sorted(:,1:(end-1));
dk_all(dk_all<k_threshold)=NaN;
dk_min=min(dk_all,[],2);
dk_max=max(dk_all,[],2);
dk_all(dk_all-dk_min(:,ones(1,size(dk_all,2)))>k_threshold)=NaN;
dk_all_cnt=sum(isfinite(dk_all),2);
dk_all(~isfinite(dk_all))=0;
dk=sum(dk_all,2)./dk_all_cnt;
dk(~isfinite(dk))=0;
[~,k0_ind]=min(sum(ktraj_adc.^2,1));
kindex=round((ktraj_adc-ktraj_adc(:,k0_ind*ones(1,size(ktraj_adc,2))))./dk(:,ones(1,size(ktraj_adc,2))));
kindex(~isfinite(kindex))=0;
kindex_min=min(kindex,[],2);
kindex_mat=kindex-kindex_min(:,ones(1,size(ktraj_adc,2)))+1;
kindex_end=max(kindex_mat,[],2);
sampler=zeros(kindex_end');
repeat=zeros(1,size(ktraj_adc,2));
for i=1:size(kindex_mat,2)
    if (size(kindex_mat,1)==3)
        ind=sub2ind(kindex_end,kindex_mat(1,i),kindex_mat(2,i),kindex_mat(3,i));
    else
        ind=sub2ind(kindex_end,kindex_mat(1,i),kindex_mat(2,i));
    end
    repeat(i)=sampler(ind);
    sampler(ind)=repeat(i)+1;
end
if (max(repeat(:))>0)
    kindex=[kindex;(repeat+1)];
    kindex_mat=[kindex_mat;(repeat+1)];
    kindex_end=max(kindex_mat,[],2);
end
%figure; plot(kindex(1,:),kindex(2,:),'.-');

%% sort the k-space data into the data matrix
% the incoming data order is [kx coils acquisitions]
data_coils_last = permute(data_unsorted, [1, 3, 2]);
data_coils_last = reshape(data_coils_last, [adc_len*readouts, channels]);

data=zeros([kindex_end' channels]);
if (size(kindex,1)==3)
    for i=1:size(kindex,2)
        data(kindex_mat(1,i),kindex_mat(2,i),kindex_mat(3,i),:)=data_coils_last(i,:);
    end
else
    for i=1:size(kindex,2)
        data(kindex_mat(1,i),kindex_mat(2,i),:)=data_coils_last(i,:);
    end
end

if size(kindex,1)==3
    nImages=size(data,3);
else
    nImages=1;
    data=reshape(data, [size(data,1) size(data,2) 1 size(data,3)]); % we need a dummy images/slices dimension
end

% account for the matlab's strange convention with data dimensions
data=flip(data,1); % left-right orientation, works on TRIO
data=flip(data,2);

%figure; imab(log(abs(data))); title('k-space data');

%% Reconstruct coil images

images = zeros(size(data));
%figure;

for ii = 1:channels
    images(:,:,:,ii) = ifftshift(ifft2(ifftshift(data(:,:,:,ii)))); % 1.4.0 does not need read inversion
end

% Phase images (possibly channel-by-channel and echo-by-echo)
%figure;imab(angle(images));colormap('jet');
%figure;imab(abs(images));colormap('gray');

%% Image display with optional sum of squares combination
figure;
if channels>1
    sos=abs(sum(images.*conj(images),ndims(images))).^(1/2);
    sos=sos./max(sos(:));
    imab(sos); title('reconstructed image(s), sum-of-squares');
    %imwrite(sos, ['img_combined.png']
else
    imab(abs(images)); title('reconstructed image(s)');
end
colormap('gray');
saveas(gcf,[basic_file_path '_image_2dfft'],'png');

%% reconstruct field map (optional)

if size(images,3)>=2
    cmplx_diff=images(:,:,2,:).*conj(images(:,:,1,:));
    phase_diff_image=angle(sum(cmplx_diff,4));
    figure;
    imab(phase_diff_image);colormap('jet');
    title('phase difference(s) echo2-echo1');
end

%% gif movie export

scale=1.2;
filename='fftReconMovie';
fps=5;

if size(images,3)>4

    clm=gray(256);

    if channels>1
        imex=sos;
    else
        imex=abs(images);
        imex=imex/max(imex(:));
    end

    imex=permute(imex(:,end:-1:1,:),[2,1,3]);

    imind=uint8(scale*imex*(size(clm,1)-1)+1);
    imwrite(imind(:,:,1),clm, [filename, '.gif'],'DelayTime',1/fps,'Loopcount',inf);
    for i=2:size(imind,3),
        imwrite(imind(:,:,i),clm, [filename, '.gif'],'DelayTime',1/fps, 'WriteMode','append');
    end

end