function quadrule_test096 ( )

%*****************************************************************************80
%
%% QUADRULE_TEST096 tests HERMITE_GK**_SET.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 May 2011
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'QUADRULE_TEST096\n' );
  fprintf ( 1, '  HERMITE_GK**_SET sets up a nested rule\n' );
  fprintf ( 1, '  for the Hermite integration problem.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The integration interval is ( -oo, +oo ).\n' );
  fprintf ( 1, '  The weight function is exp ( - x * x )\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  HERMITE_INTEGRAL determines the exact value of\n' );
  fprintf ( 1, '  the integal when f(x) = x^m.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Here, we just test the highest order rule.\n' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  HERMITE_GK16_SET:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '         M         N       Estimate       Exact            Error\n' );
  fprintf ( 1, '\n' );

  n = 35;
  p = 51;

  [ x, w ] = hermite_gk16_set ( n );

  for m = 0 : 2 : min ( p + 2, 20 )

    exact = hermite_integral ( m );

    if ( m == 0 )
      f = ones ( n, 1 );
    else
      f = zeros ( n, 1 );
      f = x.^m;
    end

    estimate = w(1:n)' * f(1:n);

    error = abs ( exact - estimate );

    fprintf ( 1, '  %8d  %8d  %14.6e  %14.6e  %14.6e\n', ...
      m, n, estimate, exact, error );

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  HERMITE_GK18_SET:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '         M         N       Estimate       Exact            Error\n' );
  fprintf ( 1, '\n' );

  n = 37;
  p = 55;

  [ x, w ] = hermite_gk18_set ( n );

  for m = 0 : 2 : min ( p + 2, 20 )

    exact = hermite_integral ( m );

    if ( m == 0 )
      f = ones ( n, 1 );
    else
      f = zeros ( n, 1 );
      f = x.^m;
    end

    estimate = w(1:n)' * f(1:n);

    error = abs ( exact - estimate );

    fprintf ( 1, '  %8d  %8d  %14.6e  %14.6e  %14.6e\n', ...
      m, n, estimate, exact, error );

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  HERMITE_GK22_SET:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '         M         N       Estimate       Exact            Error\n' );
  fprintf ( 1, '\n' );

  n = 41;
  p = 63;

  [ x, w ] = hermite_gk22_set ( n );

  for m = 0 : 2 : min ( p + 2, 20 )

    exact = hermite_integral ( m );

    if ( m == 0 )
      f = ones ( n, 1 );
    else
      f = zeros ( n, 1 );
      f = x.^m;
    end

    estimate = w(1:n)' * f(1:n);

    error = abs ( exact - estimate );

    fprintf ( 1, '  %8d  %8d  %14.6e  %14.6e  %14.6e\n', ...
      m, n, estimate, exact, error );

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  HERMITE_GK24_SET:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '         M         N       Estimate       Exact            Error\n' );
  fprintf ( 1, '\n' );

  n = 43;
  p = 67;

  [ x, w ] = hermite_gk24_set ( n );

  for m = 0 : 2 : min ( p + 2, 20 )

    exact = hermite_integral ( m );

    if ( m == 0 )
      f = ones ( n, 1 );
    else
      f = zeros ( n, 1 );
      f = x.^m;
    end

    estimate = w(1:n)' * f(1:n);

    error = abs ( exact - estimate );

    fprintf ( 1, '  %8d  %8d  %14.6e  %14.6e  %14.6e\n', ...
      m, n, estimate, exact, error );

  end

  return
end


function [e1, e2, E1_l, E2_l] = ahmLinEndpoints(l,t1,t2)

% AHMLINENDPOINTS  AHM line endpoints.
%   AHMLINENDPOINTS(L,T) returns the 3D Euclidean endpoint of the
%   AHM line L at abscissa T.
%
%   [E1,E2] = AHMLINENDPOINTS(L,T1,T2) returns two 3D Euclidean endpoints
%   at abscissas T1 and T2.
%
%   [e1,e2,E1_l,E2_l] = AHMLINENDPINTS(...) returns the Jacobians of the
%   endopints wrt L.
%
%   See also AHMLINSEGMENT, AHMLIN2SEG, AHMLIN2IDPPNTS.

%   Copyright 2009 Teresa Vidal.

if nargout <= 2

    % support segment
    s  = ahmLin2seg(l);

    % support points
    p1 = s(1:3);
    p2 = s(4:6);

    % endpoints
    e1 = (1-t1)*p1 + t1*p2;
    e2 = (1-t2)*p1 + t2*p2;

else

    [s, S_l] = ahmLin2seg(l);       % support segment

    p1 = s(1:3);                    % support points
    p2 = s(4:6);

    P1_l = S_l(1:3,:);              % jacobians of sup points
    P2_l = S_l(4:6,:);

    e1 = (1-t1)*p1 + t1*p2;         % endpoints
    e2 = (1-t2)*p1 + t2*p2;

    E1_p1 = 1-t1;                   % jacobians of endpoints
    E1_p2 = t1;
    E2_p1 = 1-t2;
    E2_p2 = t2;

    E1_l = E1_p1*P1_l + E1_p2*P2_l; % chain rule
    E2_l = E2_p1*P1_l + E2_p2*P2_l;

end

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

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

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function d = p09_fd ( p )

%*****************************************************************************80
%
%% P09_FD is a signed distance function for problem 9.
%
%  Discussion:
%
%    Notice that the V1 and V2 arrays, which define hexagons, contain SEVEN
%    points, not six.  This is necessary in order for DPOLY to carry out its
%    calculations correctly.
%
%  Licensing:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Modified:
%
%    11 March 2006
%
%  Parameters:
%
%    Input, real P, one or more points.
%
%    Output, real D, the signed distance of each point to the boundary of the region.
%
  v1 = [ 0.15, 0.75;
         0.20, 0.6634;
         0.30, 0.6634;
         0.35, 0.75;
         0.30, 0.8366;
         0.20, 0.8366;
         0.15, 0.75 ];

  d1 = dpoly ( p, v1 );

  v2 = [ 0.50, 0.40;
         0.55, 0.3134;
         0.65, 0.3134;
         0.70, 0.40;
         0.65, 0.4866;
         0.55, 0.4866;
         0.50, 0.40 ];

  d2 = dpoly ( p, v2 );

  d3 = dunion ( d1, d2 );

  d4 = drectangle ( p, 0.0, 1.0, 0.0, 1.0 );

  d = ddiff ( d4, d3 );

  return
end


function gb=gabor_fn(sigma,theta,lambda,psi,gamma)

sigma_x = sigma;
sigma_y = sigma/gamma;

% Bounding box
nstds = 3;
xmax = max(abs(nstds*sigma_x*cos(theta)),abs(nstds*sigma_y*sin(theta)));
xmax = ceil(max(1,xmax));
ymax = max(abs(nstds*sigma_x*sin(theta)),abs(nstds*sigma_y*cos(theta)));
ymax = ceil(max(1,ymax));
xmin = -xmax; ymin = -ymax;
[x,y] = meshgrid(xmin:xmax,ymin:ymax);

% Rotation
x_theta=x*cos(theta)+y*sin(theta);
y_theta=-x*sin(theta)+y*cos(theta);

gb= 1/(2*pi*sigma_x *sigma_y) * exp(-.5*(x_theta.^2/sigma_x^2+y_theta.^2/sigma_y^2)).*cos(2*pi/lambda*x_theta+psi);


function polar_to_c8_test ( )

%*****************************************************************************80
%
%% POLAR_TO_C8_TEST tests POLAR_TO_C8.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 February 2015
%
%  Author:
%
%    John Burkardt
%
  test_num = 10;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'POLAR_TO_C8 converts polar form to C8.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '      (R1,T1)=R8_UNIFORM_01()    C2=POLAR_TO_C8(R1,T1)' );
  fprintf ( 1, '    (R3,T3)=C8_TO_POLAR(C2)\n' );
  fprintf ( 1, '       ----------------------       ----------------------' );
  fprintf ( 1, '      -----------------------\n' );
  fprintf ( 1, '\n' );

  seed = 123456789;

  for test = 1 : test_num

    [ r1, seed ] = r8_uniform_01 ( seed );
    [ t1, seed ] = r8_uniform_01 ( seed );
    t1 = t1 * 2.0 * pi;
    c2 = polar_to_c8 ( r1, t1 );;
    [ r3, t3 ] = c8_to_polar ( c2 );

    fprintf ( 1, '  %12f  %12f  (%12f  %12f)  %12f  %12f\n', ...
      r1, t1, real ( c2 ), imag ( c2 ), r3, t3 );

  end

  return
end


function x = triangle_cdf_inv ( cdf, a, b, c )

%*****************************************************************************80
%
%% TRIANGLE_CDF_INV inverts the Triangle CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real CDF, the value of the CDF.
%    0.0 <= CDF <= 1.0.
%
%    Input, real A, B, C, the parameters of the PDF.
%    A <= B <= C and A < C.
%
%    Output, real X, the corresponding argument.
%
  if ( cdf < 0.0 | 1.0 < cdf )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGLE_CDF_INV - Fatal error!\n' );
    fprintf ( 1, '  CDF < 0 or 1 < CDF.\n' );
    error ( 'TRIANGLE_CDF_INV - Fatal error!' );
  end

  d = 2.0 / ( c - a );
  cdf_mid = 0.5 * d * ( b - a );

  if ( cdf <= cdf_mid )
    x = a + sqrt ( cdf * ( b - a ) * ( c - a ) );
  else
    x = c - sqrt ( ( c - b ) * ( ( c - b ) - ( cdf - cdf_mid ) * ( c - a ) ) );
  end

  return
end


function Speciation
% Speciation
%    using MATLAB
%
%   $Ekkehard Holzbecher  $Date: 2006/05/03 $
%--------------------------------------------------------------------------
toll = 1.e-15;                    % tolerance
nmax = 50;                        % max. no. of iterations
Se = [-1 -1 1];                   % reaction matrix
logc = [1.e-10; 1.e-10; 0];       % initial guess (log)
logK = [-0.93];                   % equilibrium constants (log)
logu = [-0.301; 0];               % total concentrations (log)

ln10 = 2.3026;
n=size(Se,1); m=size(Se,2);
S1 = Se(:,1:m-n);
S2 = Se(:,m-n+1:m);
S1star = -S2\S1;
U = [eye(m-n),S1star'];

c=exp(ln10*logc);
u(1:m-n,1) = exp(ln10*logu);
err = toll+1; nit = 0;
while (nit < nmax && err > toll),
    nit = nit+1;
    F = [U*c-u; Se*logc-logK];
    DF = [U; Se*diag((1/ln10)./c)];
    dc = -DF\F;
    cn = max(c+dc,0.005*abs(c));
    err = max(abs(cn-c));
    c = cn;
end
display (['Species concentrations obtained after ' num2str(nit) ' iterations:']);
c
exp(ln10*logK)-c(3)/c(1)/c(2)


function pass = test_dlt(pref)

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

n = 10;
x = legpts(n);
r = rand(n,1)./(1:n)';
rr = [r, r];
tol = 100*n*eps;
P = legpoly(0:n-1);

N = 5001;
R = rand(N,1)./(1:N)';
RR = [R, R];
Tol = 100*N*eps;

%% Basic test (small)
err = norm(P(x)*r - chebfun.dlt(r), inf);
pass(1) = err < tol;

%% Vector test (small)
err = norm(P(x)*rr - chebfun.dlt(rr), inf);
pass(2) = err < tol;

%% Test direct
err = norm(P(x)*r - dlt_direct(r), inf);
pass(3) = err < tol;

%% Basic test (large)
err = norm(dlt_direct(R) - chebfun.dlt(R), inf);
pass(4) = err < Tol;

%% Vector test (large)
err = norm(dlt_direct(RR) - chebfun.dlt(RR), inf);
pass(5) = err < Tol;

end

function v = dlt_direct(c)
N = size(c, 1);
if ( N == 0 ), v = 1 + 0*c; return, end
x = legpts(N);
v = repmat(c(1,:), length(x), 1) + bsxfun(@times, c(2,:), x);
Pm1 = 1 + 0*x; P = x;   % P_0 and P_1.
for n = 1:(N-2) % Recurrence relation.
    Pp1 = (2-1/(n+1))*(P.*x) - (1-1/(n+1))*Pm1;
    Pm1 = P;    P = Pp1;
    v = v + bsxfun(@times, c(n+2,:), P);
end

end


function [bb] = tribal2(pp,tt)
%TRIBAL2 compute the circumballs associated with a 2-simplex
%triangulation embedded in R^2 or R^3.
%   [BB] = TRIBAL2(PP,TT) returns the circumscribing balls
%   associated with the triangles in [PP,TT], such that BB =
%   [XC,YC,RC.^2].

%   Darren Engwirda : 2017 --
%   Email           : de2363@columbia.edu
%   Last updated    : 02/05/2018

    bb = pwrbal2(pp,zeros(size(pp,1),1),tt) ;

end


 function [coef, arg] = nufft_coef(om, J, K, kernel)
%function [coef, arg] = nufft_coef(om, J, K, kernel)
%|
%| NUFFT interpolation coefficient vectors for a given kernel function.
%|
%| in
%|	om	[M 1]	digital frequency omega in radians
%|	J		# of neighbors used per frequency location
%|	K		FFT size (should be >= N, the signal_length)
%|	kernel		kernel function handle
%|
%| out
%|	coef	[J M]	coef vector for each frequency
%|	arg	[J M]	kernel argument
%|
%| Copyright 2002-4-11, Jeff Fessler, University of Michigan

if nargin < 4, ir_usage, end

M = length(om);
gam = 2*pi/K;
dk = om / gam - nufft_offset(om, J, K);		% [M 1]
arg = outer_sum(-[1:J]', dk');			% [J M] kernel arg

coef = feval(kernel, arg, J);			% [J M]


data_masterdir = GetCurrentDataDir();
range_fish = [2,3,4,5,6];
%% a) Histogram of Pairwise Distances for One Fish

%
clear T N
figure;
hold on;
for i = 1:length(range_fish),
    i_fish = range_fish(i);
    [f_cells,M,N(i),T(i),hfig] = getFullFishData(hfig,i_fish,VAR);

    num_select = 1000;%num_cells;
    idx_select = randperm(N(i), num_select);

    f_cells_select = f_cells(idx_select,:);

    %% Correlation
    tic
    Dpairs = 1-pdist(f_cells_select,'correlation');
    % Dpairs is in correlation, not corr dist
    toc

    %% Plot Histogram
    binwidth = .005;
    edges = -1:binwidth:1;

    [counts,edges] = histcounts(Dpairs,edges);
    allBins = edges(1:end-1) + binwidth/2;

    allCorrVals = counts;
    leg{i} = ['Fish ',num2str(i_fish)];

    plot(allBins,allCorrVals/trapz(allBins,allCorrVals));
    xlabel('Pairwise Correlations');
    ylabel('Normalized Frequency');
    xlim([-0.2,0.2]);

end

% Compare to Random Data
T_control = T(end);
f_cells_control = normrnd(0,1,num_select,T_control);
Dpairs_control = 1-pdist(f_cells_control,'correlation');

[ctrlCounts,edgesCtrl] = histcounts(Dpairs_control,edges);
control_allBins = edgesCtrl(1:end-1) + binwidth/2;
control_allCorrVals = ctrlCounts;

plot(control_allBins,control_allCorrVals/trapz(control_allBins,control_allCorrVals)...
    ,'k');

leg{i+1} = 'Control';
legend(leg)

%% b) Percentile Threshold Plot

% Percentile Thresh
threshPerc = .99;
figure;
xlabel('Number of Frames');
ylabel('99th Percentile Correlation');

hold on;
for num_fish = 1:length(range_fish),

    i_fish = range_fish(num_fish);
    [f_cells,M,N(num_fish),T(num_fish),hfig] = getFullFishData(hfig,i_fish,VAR);

    num_select = 1000;%num_cells;
    idx_select = randperm(N(num_fish), num_select);

    f_cells_select = f_cells(idx_select,:);

    T_trunc = T(num_fish)/10:T(num_fish)/10:T(num_fish); %hardcode for now
    clear threshCorr;
    for i = 1:length(T_trunc)
        f_trunc = f_cells_select(:,1:T_trunc(i));

        % Correlation Distance
        tic
        Dpairs = pdist(f_trunc,'correlation');
        % 138 sec for 86k cells
        % 1.8 sec for 10k cells
        toc
        %figure;
        %h = histogram(1-Dpairs);%Plot corr, not corr dist

        sortCorr = sort(1-Dpairs);
        threshIDX = round(length(sortCorr)*threshPerc);
        threshCorr(i) = sortCorr(threshIDX);
    end
    plot(T_trunc,threshCorr,'o-')
    leg2{num_fish} = ['Fish ',num2str(i_fish)];
end

% Compare to Random Data
T_control = T(end);
f_cells_control = normrnd(0,1,num_select,T_control);
Dpairs_control = 1-pdist(f_cells_control,'correlation');

T_trunc = T_control/10:T_control/10:T_control; %hardcode for now
clear threshCorr;
clear threshCorr;
for i = 1:length(T_trunc)
    f_trunc = f_cells_control(:,1:T_trunc(i));

    % Correlation Distance
    tic
    Dpairs = pdist(f_trunc,'correlation');
    % 138 sec for 86k cells
    % 1.8 sec for 10k cells
    toc
    %figure;
    %h = histogram(1-Dpairs);%Plot corr, not corr dist
    sortCorr = sort(1-Dpairs);
    threshIDX = round(length(sortCorr)*threshPerc);
    threshCorr(i) = sortCorr(threshIDX);
end
plot(T_trunc,threshCorr,'ko-')
leg2{num_fish+1} = 'control';
ylim([0 .5]);
legend(leg2);
grid on;


clc;
clearvars;
n = 8;
A = gallery('lotkin',n)
H0 = triu(A, -1)
[H1, Z] = spx.la.schur.francis_step(H0)
% for i=1:4
%     H = spx.la.schur.francis_step(H)
%     H(n, n-1)
% end

HD = H0 - Z * H1 * Z'
max(max(abs(HD)))


function C=tprod(A,B)
% Computes the tensor-product of two P dimensional tensors (A & B)
% All dimensions of the inputed tensor except for the 2nd must be the same.
% The algorithm follows from paper by ...
%
% INPUTS:
%
% A - n1 x n2 x n3 .... nP tensor
% B - n2 x n4 x n3 .... nP tensor
%
% OUTPUTS:
%
% C - n1 x n4 x n3 .... nP tensor
%
% Original author :  Misha Kilmer, Ning Hao
% Edited by       :  G. Ely, S. Aeron, Z. Zhang, ECE, Tufts Univ. 03/16/2015

sa = size(A);
sb = size(B);

faces = length(sa);

nfaces = prod(sb(3:end));

for i = 3:faces
    A = fft(A,[],i);
    B = fft(B,[],i);
end
sc = sa;
sc(2) = sb(2);
C = zeros(sc);
for i = 1:nfaces
    C(:,:,i) = A(:,:,i)*B(:,:,i);
end
for i = 3:faces
    C = ifft(C,[],i);
end


function [mappedX, mapping] = charting(X, no_dims, no_analyzers, max_iterations, eig_impl)
%CHARTING Performs manifold charting on dataset X
%
%   [mappedX, mapping] = charting(X, no_dims, no_analyzers, max_iterations, eig_impl)
%
% Performs manifold charting on dataset X to reduce its dimensionality to
% no_dims dimensions. The variable no_analyzers determines the number of
% local factor analyzers that is used in the mixture of factor analyzers
% (default = 40). The variable max_iterations sets the maximum number of
% iterations that is employed in the EM algorithm (default = 200).
%

% This file is part of the Matlab Toolbox for Dimensionality Reduction.
% The toolbox can be obtained from http://homepage.tudelft.nl/19j49
% You are free to use, change, or redistribute this code in any way you
% want for non-commercial purposes. However, it is appreciated if you
% maintain the name of the original author.
%
% (C) Laurens van der Maaten, Delft University of Technology

    if ~exist('no_dims', 'var')
        no_dims = 2;
    end
    if ~exist('no_analyzers', 'var')
        no_analyzers = 40;
    end
    if ~exist('max_iterations', 'var')
        max_iterations = 200;
    end

    % Initialize some parameters
    tol = 1e-10;                        % regularization parameter
    min_std = 1e-3;                     % minimum STD of Gaussians
    kf = no_analyzers * (no_dims + 1);

    % Construct MFA model on the data
    disp('Running EM algorithm and compute local factor analyzers...');
    [LX, MX, PX] = mppca(X', no_dims, no_analyzers, tol, max_iterations, min_std);
    [R, Z] = infermfa(X', LX, MX, PX);

    % Adds last entry = 1 in posterior mean to handle means of factor analyzers
    Z(no_dims + 1,:,:) = 1;
    Z = permute(Z, [1 3 2]);

    % Construct blockdiagonal matrix D
    disp('Performing manifold charting...');
    D = zeros((no_dims + 1) * no_analyzers, (no_dims + 1) * no_analyzers);
    for i=1:no_analyzers
        Ds = zeros(no_dims + 1, no_dims + 1);
        for j=1:size(X, 1)
            Ds = Ds + R(i, j) .* (Z(:,i,j) * Z(:,i,j)');
        end
        D((i - 1) * (no_dims + 1) + 1:i * (no_dims + 1), (i - 1) * (no_dims + 1) + 1:i * (no_dims + 1)) = Ds;
    end

    % Construct responsibility weighted local representation matrix U
    R = reshape(R, [1 no_analyzers size(X, 1)]);
    U = reshape(bsxfun(@times, R, Z), [kf size(X, 1)])';

    % Solve generalized eigenproblem
    if strcmp(eig_impl, 'Matlab')
        options.disp = 0;
        options.isreal = 1;
        options.issym = 1;
        [V, lambda] = eigs(D - U' * U, U' * U, no_dims + 1, 'SM', options);
    else
        options.Disp = 0;
        options.LSolver = 'bicgstab';
        [V, lambda] = jdqz(D - U' * U, U' * U, no_dims + 1, 'SM', options);
    end
    [lambda, ind] = sort(diag(lambda));
    V = V(:,ind(2:end));

    % Compute final lowdimensional data representation
    mappedX = U * V;

    % Store mapping data for out-of-sample extension
    if nargout > 1
        mapping.LX = LX;
        mapping.MX = MX;
        mapping.PX = PX;
        mapping.V = V;
    end


function [parent_pop] = osy(parent_pop)
%   This procedure implements Osyczka and Kundu's function.
%   The canonical zdt1 function is defined as below --
%   f_1 = -25.0 * ((x_1 - 2)^2 - (x_2 - 2)^2 - (x_3 - 1)^2
%                           - (x_4 - 4)^2 - (x_5 - 1)^2)
%   f_2 = sum_{i=1}^n x_i^2.0
%   s.t.
%       c_1(x) = x_1 + x_2 - 2 >= 0
%       c_2(x) = 6 - x_1 - x_2 >= 0
%       c_3(x) = 2 - x_2 + x_1 >= 0
%       c_4(x) = 2 - x_1 + 3x_2 >= 0
%       c_5(x) = 4 - (x_3 - 3)^2 - x_4 >= 0
%       c_6(x) = (x_5 - 3)^2 + x_6 - 4 >= 0
%   where,
%       0 <= x_1 <= 10.0
%       0 <= x_2 <= 10.0
%       1 <= x_3 <= 5.0
%       0 <= x_4 <= 6.0
%       1 <= x_5 <= 5.0
%       0 <= x_6 <= 10.0

global nreal ;
global ncon ;
global nobj ;

cindex = nreal + nobj + 1 : nreal + nobj + ncon ;

% disp(parent_pop(1,:))

x = parent_pop(:,1:nreal);
f1 = -(25.0 .* ((x(:,1) - 2.0) .^ 2.0) + ((x(:,2) - 2.0) .^ 2.0) ...
             + ((x(:,3) - 1.0) .^ 2.0) + ((x(:,4) - 4.0) .^ 2.0) ...
             + ((x(:,5) - 1.0) .^ 2.0));
f2 = sum((x .^ 2.0), 2) ;

c = parent_pop(:,cindex) ;
% disp(c(1,:))
c(:,1) = ((x(:,1) + x(:,2)) ./ 2.0) - 1.0 ;
c(:,2) = 1.0 - ((x(:,1) + x(:,2)) ./ 6.0);
c(:,3) = 1.0 - (x(:,2) ./ 2.0) + (x(:,1) ./ 2.0);
c(:,4) = 1.0 - (x(:,1) ./ 2.0) + (3.0 .* (x(:,2) ./ 2.0));
c(:,5) = 1.0 - (((x(:,3) - 3.0) .^ 2.0) ./ 4.0) - (x(:,4) ./ 4.0);
c(:,6) = (((x(:,5) - 3.0) .^ 2.0) ./ 4.0) + (x(:,6) ./ 4.0) - 1.0;
parent_pop(:, (nreal+1)) = f1;
parent_pop(:, (nreal+2)) = f2;
parent_pop(:,cindex) = c ;
end


function k = calcWaveNumber(omega,waterDepth,g,deepWater)
% Solves the wave dispersion relation :math:`\omega^2 = g k*tanh(k h)` for
% the wave number
%
% Parameters
% ----------
%     omega : float
%         Wave frequency [rad/s]
%
%     waterDepth : float
%         Water depth [m]
%
%     g : float
%         Gravitational acceleration [m/s^2]
%
%     deepWater : integar
%         waveClass flag inidicating a deep water wave [-]
%
% Returns
% ------------
%    k : float
%        Wave number [m]
%

arguments
    omega
    waterDepth
    g = 9.81;
    deepWater = 0;
end

% Deep water approximation, initial guess
k = omega.^2./g;

% Iterate for shallow and intermediate water, full dispersion relationship
if deepWater == 0
    for i = 1:100
        k = omega.^2./g./tanh(k.*waterDepth);
    end
end

end


function op = proj_l1( q, d )
%PROJ_L1   Projection onto the scaled 1-norm ball.
%    OP = PROJ_L1( Q ) returns an operator implementing the
%    indicator function for the 1-norm ball of radius q,
%    { X | norm( X, 1 ) <= q }. Q is optional; if omitted,
%    Q=1 is assumed. But if Q is supplied, it must be a positive
%    real scalar.
%
%    OP = PROJ_L1( Q, D ) uses a scaled 1-norm ball of radius q,
%    { X | norm( D.*X, 1 ) <= 1 }. D should be the same size as X
%    and non-negative (some zero entries are OK).
%
% Dual: prox_linf.m
% See also: prox_linf, prox_l1, proj_linf

if nargin == 0,
	q = 1;
elseif ~isnumeric( q ) || ~isreal( q ) || numel( q ) ~= 1 || q <= 0,
	error( 'Argument must be positive.' );
end
if nargin < 2 || isempty(d) || numel(d)==1
    if nargin>=2 && ~isempty(d)
        % d is a scalar, so norm( d*x ) <= q is same as norm(x)<=q/d
        if d==0
            error('If d==0 in proj_l1, the set is just {0}, so use proj_0');
        elseif d < 0
            error('Require d >= 0');
        end
        q = q/d;
    end
    op = @(varargin)proj_l1_q(q, varargin{:} );
else
    if any(d<0)
        error('All entries of d must be non-negative');
    end
    op = @(varargin)proj_l1_q_d(q, d, varargin{:} );
end

function [ v, x ] = proj_l1_q( q, x, t )
v = 0;
switch nargin,
case 2,
	if nargout == 2,
		error( 'This function is not differentiable.'  );
	elseif norm( x(:), 1 ) > q,
		v = Inf;
	end
case 3,
    s      = sort(abs(nonzeros(x)),'descend');
    cs     = cumsum(s);
    % ndx    = find( cs - (1:numel(s))' .* [ s(2:end) ; 0 ] >= q, 1 );
    ndx    = find( cs - (1:numel(s))' .* [ s(2:end) ; 0 ] >= q+2*eps(q), 1 ); % For stability
    if ~isempty( ndx )
        thresh = ( cs(ndx) - q ) / ndx;
        x      = x .* ( 1 - thresh ./ max( abs(x), thresh ) ); % May divide very small numbers
    end
otherwise,
    error( 'Not enough arguments.' );
end

% Allows scaling. Added Feb 21 2014
function [ v, x ] = proj_l1_q_d( q, d,  x, t )
v = 0;
switch nargin,
case 3,
	if nargout == 2,
		error( 'This function is not differentiable.'  );
	elseif norm( d(:).*x(:), 1 ) > q,
		v = Inf;
	end
case 4,
    [lambdas,srt]      = sort(abs(nonzeros(x./d)),'descend');
    s   = abs(x(:).*d(:));  s = s(srt);
    dd  = d(:).^2;          dd= dd(srt);
    cs  = cumsum(s);
    cd  = cumsum(dd);
    ndx    = find( cs - lambdas.*cd >= q+2*eps(q), 1, 'first');
    if ~isempty( ndx )
        ndx     = ndx - 1;
        lambda  = ( cs(ndx) - q )/cd(ndx);
        x       = sign(x).*max( 0, abs(x) - lambda*d );
    end
otherwise,
    error( 'Not enough arguments.' );
end

% TFOCS v1.3 by Stephen Becker, Emmanuel Candes, and Michael Grant.
% Copyright 2013 California Institute of Technology and CVX Research.
% See the file LICENSE for full license information.


function [ n_data, x, fx ] = psi_values ( n_data )

%*****************************************************************************80
%
%% PSI_VALUES returns some values of the Psi or Digamma function.
%
%  Discussion:
%
%    In Mathematica, the function can be evaluated by:
%
%      PolyGamma[x]
%
%    or
%
%      PolyGamma[0,x]
%
%    PSI(X) = d ln ( Gamma ( X ) ) / d X = Gamma'(X) / Gamma(X)
%
%    PSI(1) = -Euler's constant.
%
%    PSI(X+1) = PSI(X) + 1 / X.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 June 2013
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%    Stephen Wolfram,
%    The Mathematica Book,
%    Fourth Edition,
%    Wolfram Media / Cambridge University Press, 1999.
%
%  Parameters:
%
%    Input/output, integer N_DATA.  The user sets N_DATA to 0 before the
%    first call.  On each call, the routine increments N_DATA by 1, and
%    returns the corresponding data; when there is no more data, the
%    output value of N_DATA will be 0 again.
%
%    Output, real X, the argument of the function.
%
%    Output, real FX, the value of the function.
%
  n_max = 20;

  fx_vec = [ ...
    -10.42375494041108E+00, ...
     -5.289039896592188E+00, ...
     -3.502524222200133E+00, ...
     -2.561384544585116E+00, ...
     -1.963510026021423E+00, ...
     -1.540619213893190E+00, ...
     -1.220023553697935E+00, ...
     -0.9650085667061385E+00, ...
     -0.7549269499470514E+00, ...
     -0.5772156649015329E+00, ...
     -0.4237549404110768E+00, ...
     -0.2890398965921883E+00, ...
     -0.1691908888667997E+00, ...
     -0.6138454458511615E-01, ...
      0.3648997397857652E-01, ...
      0.1260474527734763E+00, ...
      0.2085478748734940E+00, ...
      0.2849914332938615E+00, ...
      0.3561841611640597E+00, ...
      0.4227843350984671E+00 ];

  x_vec = [ ...
     0.1E+00, ...
     0.2E+00, ...
     0.3E+00, ...
     0.4E+00, ...
     0.5E+00, ...
     0.6E+00, ...
     0.7E+00, ...
     0.8E+00, ...
     0.9E+00, ...
     1.0E+00, ...
     1.1E+00, ...
     1.2E+00, ...
     1.3E+00, ...
     1.4E+00, ...
     1.5E+00, ...
     1.6E+00, ...
     1.7E+00, ...
     1.8E+00, ...
     1.9E+00, ...
     2.0E+00 ];

  if ( n_data < 0 )
    n_data = 0;
  end

  n_data = n_data + 1;

  if ( n_max < n_data )
    n_data = 0;
    x = 0.0;
    fx = 0.0;
  else
    x = x_vec(n_data);
    fx = fx_vec(n_data);
  end

  return
end


function out =  bicubic_interpolation_cell(p, x, y)
v(1) = cubic_interpolation_cell(p(1,:), y);
v(2) = cubic_interpolation_cell(p(2,:), y);
    v(3) = cubic_interpolation_cell(p(3,:), y);
    v(4) = cubic_interpolation_cell(p(4,:), y);
   out =  cubic_interpolation_cell(v, x);

end


function [cc,c0]=lpcpf2cc(pf,np,f)
%LPCPF2CC Convert power spectrum to complex cepstrum CC=(PF,NP)
%
%  Inputs: pf(nf,n)    Power spectrum, uniformly spaced DC to Nyquist
%          np          Number of cepstral coefficients to calculate [n-1]
%          f(1,n)      Frequencies of pf columns [linspace(0,0.5,n)]
%
% Outputs: cc(nf,np)  Complex spectrum from DC to Nyquist
%          c0(nf,1)   The zeroth cepstral coefficient, c(0)
%
% Note since the log spectrum is not normally bandlimited, this conversion is not exact unless n >> np

%      Copyright (C) Mike Brookes 1998-2014
%      Version: $Id: lpcpf2cc.m 5025 2014-08-22 17:07:24Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[nf,nq]=size(pf);
if nargin<2 || ~numel(np) np=nq-1; end
if nargin<3 || ~numel(f)
    cc=rsfft(log(pf.')).'/(2*nq-2);
    c0=cc(:,1)*0.5;
    cc(:,nq)=cc(:,nq)*0.5;
    if np>nq-1
        cc=[cc(:,2:nq) zeros(nf,np-nq+1)];
    else
        cc=cc(:,2:np+1);
    end
else
    cc=0.5*(log(pf)/cos(2*pi*f(:)*(0:min(np,nq-1))));
    c0=cc(:,1);
    cc=cc(:,2:end);
    if np>nq-1
        cc(1,np)=0;
    end
end


function [stats, TABLE] = SummStats(TEMP,p)
% =======================================================================
% Computes descriptive stats of a time series (or a matrix of time series)
% =======================================================================
% [stats, TABLE] = SummStats(TEMP,p)
% -----------------------------------------------------------------------
% INPUT
%   - TEMP  : T obs (rows) x N series (columns)
%   - p = order of time polynomial in the ADF null-hypothesis.
%         p ~exist, does not perform ADF test
%         p = -1, no deterministic part
%         p =  0, for constant term
%         p =  1, for constant plus time-trend
%         p >  1, for higher order polynomial
% -----------------------------------------------------------------------
% OUTPUT
%   - stats: [Obs, mean, median, max, min, StDev, AutoCorr, Skew, Kurt,...
%       ADF(4), ADF(4) Conf, ADF(8), ADF(8) Conf]
%   - TABLE: cell, matrix with the names of the stats & the stats
% =======================================================================
% Ambrogio Cesa Bianchi, March 2015

[~, c] = size(TEMP);

% Compute summary statistics NaN are not considered (like in Excel)
mean    = nanmean(TEMP);
median  = nanmedian(TEMP);
max     = nanmax(TEMP);
min     = nanmin(TEMP);
StDev   = nanstd(TEMP);
CV      = StDev./mean;

% Compute autocorrelation coefficient AutoCorr on the maximum number of
% observation available per series
for i=1:c
    X = TEMP(:,i);
    if isnan(X)==1
        Obs(1,i)  = NaN;
        AutoCorr(1,i)  = NaN;
        Skew(1,i) = NaN;
        Kurt(1,i) = NaN;
        ADF4(1,i) = NaN;
        ADF4conf(1,i) = NaN;
        ADF8(1,i) = NaN;
        ADF8conf(1,i) = NaN;
    else
        X(any(isnan(X),2),:) = [];
        size_X    = size(X);
        Obs(1,i)  = size_X(1);
        AutoCorr(1,i)  = corr(X(2:end),X(1:end-1));
        Skew(1,i) = skewness(X);
        Kurt(1,i) = kurtosis(X);
        % If less than 20 observations don't do ADF4
        if length(X)<20 || ~exist('p','var')
            ADF4(1,i) = NaN;
            ADF4conf(1,i) = NaN;
        else
            test = adf(X,p,4);
            ADF4(1,i) = test.adf;
            if test.adf<test.crit(1)    % cannot reject the null of I(0)
                ADF4conf(1,i) = 0.01;
            elseif test.adf<test.crit(2)
                ADF4conf(1,i) = 0.05;
            elseif test.adf<test.crit(3)
                ADF4conf(1,i) = 0.10;
            else                        % reject the null of I(0) => I(1)
                ADF4conf(1,i) = 0;
            end
        end
        % If less than 40 observations don't do ADF8
        if length(X)<40 || ~exist('p','var')
            ADF8(1,i) = NaN;
            ADF8conf(1,i) = NaN;
        else
            test = adf(X,p,8);
            ADF8(1,i) = test.adf;
            if test.adf<test.crit(1)
                ADF8conf(1,i) = 0.01;
            elseif test.adf<test.crit(2)
                ADF8conf(1,i) = 0.05;
            elseif test.adf<test.crit(3)
                ADF8conf(1,i) = 0.10;
            else
                ADF8conf(1,i) = 0;
            end
        end
    end
end

% Create matrix with all summary stats
stats = [Obs; mean; median; max; min; StDev; AutoCorr; Skew; Kurt; ADF4; ADF4conf; ADF8; ADF8conf; CV];

% Create titles
titles ={'Obs'; 'Mean'; 'Median'; 'Max'; 'Min'; 'St. Dev.'; 'Auto Corr.'; 'Skew.'; 'Kurt.'; 'ADF(4)'; 'ADF(4) Conf.'; 'ADF(8)'; 'ADF(8) Conf.'; 'Coeff. Variation'};

% Create cell
TABLE = TabPrint(stats,[],titles);


function Cont=Contingency(Mem1,Mem2)
%CONTINGENCY Form contigency matrix for two vectors
% C=Contingency(Mem1,Mem2) returns contingency matrix for two
% column vectors Mem1, Mem2. These define which cluster each entity
% has been assigned to.
%
% See also RANDINDEX.
%

%(C) David Corney (2000)   		D.Corney@cs.ucl.ac.uk

if nargin < 2 | min(size(Mem1)) > 1 | min(size(Mem2)) > 1
   error('Contingency: Requires two vector arguments')
   return
end

Cont=zeros(max(Mem1),max(Mem2));

for i = 1:length(Mem1);
   Cont(Mem1(i),Mem2(i))=Cont(Mem1(i),Mem2(i))+1;
end


function b = isPointOnRay(point, ray, varargin)
%ISPOINTONRAY Test if a point belongs to a ray.
%
%   B = isPointOnRay(PT, RAY);
%   Returns 1 if point PT belongs to the ray RAY.
%   PT is given by [x y] and RAY by [x0 y0 dx dy].
%
%   If PT is a N-by-2 array, and RAY is a M-by-4 array, then the result is
%   a N-by-M array containing the result of each pair-wise test.
%
%   B = isPointOnRay(PT, RAY, TOL);
%   Specifies the tolerance to use for testing if point is on the ray.
%
%   Example
%     ray = [10 20 3 4];
%     % test for a point on the ray
%     p1 = [16 28];
%     isPointOnRay(p1, ray)
%     ans =
%       logical
%        0
%     % test for a point on the supporting line but "before" the origin
%     p2 = [7 16];
%     isPointOnRay(p1, ray)
%     ans =
%       logical
%        0
%
%   See also
%   rays2d, points2d, isPointOnLine, isPointOnEdge
%

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2003-10-31
% Copyright 2003-2022 INRA - TPV URPOI - BIA IMASTE

% extract computation tolerance
tol = 1e-14;
if ~isempty(varargin)
    tol = varargin{1};
end

% number of rays and points
Nr = size(ray, 1);
Np = size(point, 1);

% if several rays or several points, adapt sizes of arrays
x0 = repmat(ray(:,1)', Np, 1);
y0 = repmat(ray(:,2)', Np, 1);
dx = repmat(ray(:,3)', Np, 1);
dy = repmat(ray(:,4)', Np, 1);
xp = repmat(point(:,1), 1, Nr);
yp = repmat(point(:,2), 1, Nr);

% test if points belongs to the supporting line
b1 = abs((xp-x0).*dy - (yp-y0).*dx) ./ (dx.*dx + dy.*dy) < tol;

% check if points lie the good direction on the rays
ind     = abs(dx) > abs(dy);
t       = zeros(size(b1));
t(ind)  = (xp(ind) - x0(ind)) ./ dx(ind);
t(~ind) = (yp(~ind) - y0(~ind)) ./ dy(~ind);

% combine the two tests
b = b1 & (t >= 0);


function t = bal_seq_unrank ( rank, n )

%*****************************************************************************80
%
%% BAL_SEQ_UNRANK unranks a balanced sequence.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Donald Kreher, Douglas Simpson,
%    Combinatorial Algorithms,
%    CRC Press, 1998,
%    ISBN: 0-8493-3988-X,
%    LC: QA164.K73.
%
%  Parameters:
%
%    Input, integer RANK, the rank of the balanced sequence.
%
%    Input, integer N, the number of 0's (and 1's) in the sequence.
%    N must be positive.
%
%    Output, integer T(2*N), a balanced sequence.
%

%
%  Check.
%
  if ( n < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'BAL_SEQ_UNRANK - Fatal error!\n' );
    fprintf ( 1, '  Input N is illegal.\n' );
    error ( 'BAL_SEQ_UNRANK - Fatal error!' );
  end

  nseq = bal_seq_enum ( n );

  if ( rank < 0 || nseq < rank )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'BAL_SEQ_UNRANK - Fatal error!\n' );
    fprintf ( 1, '  The input rank is illegal.\n' );
    error ( 'BAL_SEQ_UNRANK - Fatal error!' );
  end

  y = 0;
  low = 0;

  for x = 1 : 2 * n

    m = mountain ( n, x, y + 1 );

    if ( rank <= low + m - 1 )
      y = y + 1;
      t(x) = 0;
    else
      low = low + m;
      y = y - 1;
      t(x) = 1;
    end

  end

  return
end


function btv_test09 ( )

%*****************************************************************************80
%
%% BTV_TEST09 tests BURGERS_TIME_VISCOUS with the spike initial condition.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 April 2012
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'BTV_TEST09\n' );
  fprintf ( 1, '  Test BURGERS_TIME_VISCOUS with the spike initial condition.\n' );

  nx = 81;
  nt = 400;
  t_max = 4.0;
  nu = 0.01;
  bc = 4;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Initial condition: spike\n' );
  fprintf ( 1, '  Number of space nodes = %d\n', nx );
  fprintf ( 1, '  Number of time steps = %d\n', nt );
  fprintf ( 1, '  Final time T_MAX = %g\n', t_max );
  fprintf ( 1, '  Viscosity = %g\n', nu );
  fprintf ( 1, '  Boundary condition = %d\n', bc );

  U = burgers_time_viscous ( @ic_spike, nx, nt, t_max, nu, bc );

  x = linspace ( -1.0, +1.0, nx );

  figure ( 9 )

  plot ( x, U(1:50:(nt+1),:), 'Linewidth', 3 )
  grid on
  xlabel ( '<-- X -->' )
  ylabel ( '<-- U(X,T) -->' )
  title ( 'Burgers equation solutions over time, initial condition spike' )

  filename = 'btv_test09.png';
  print ( '-dpng', filename )
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Saved plot as "%s"\n', filename );

  return
end


function [Du,area,Dlambda] = gradu(node,elem,u,Dlambda)
%% GRADU gradient of a finite element function.
%
% Du = GRADU(node,elem,u) compute the gradient of a finite element function
% u on a mesh representing by (node,elem).
%
% [Du,area,Dlambda] = GRADU(node,elem,u) also outputs area and Dlambda
% which is the gradient of P1 basis.
%
% Du = GRADU(node,elem,u,Dlambda) compute the gradient with Dlambda. It
% will save time when Dlambda is available. See recovery.m
%
% See also gradu3, gradbasis
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

if ~exist('Dlambda','var')
    [Dlambda,area] = gradbasis(node,elem);
end
dudx =  u(elem(:,1)).*Dlambda(:,1,1) + u(elem(:,2)).*Dlambda(:,1,2) ...
      + u(elem(:,3)).*Dlambda(:,1,3);
dudy =  u(elem(:,1)).*Dlambda(:,2,1) + u(elem(:,2)).*Dlambda(:,2,2) ...
      + u(elem(:,3)).*Dlambda(:,2,3);
Du = [dudx, dudy];


function [H W] = createHashTable(K,b,t)
%% function [H W] = createHashTable(K,b,t)
%  Create a hash table for kernelized LSH.
%
%  Inputs: K (kernel matrix)
%          b (number of bits)
%          t (number of Gaussian approximation elements)
%
%  Outputs: H (hash table over elements of K, size p x b)
%           W (weight matrix for computing hash keys over queries, size p x b)
%%

[p,p] = size(K);
%center the kernel matrix
K = K - (1/p)*(K*ones(p,1))*ones(1,p) - (1/p)*ones(p,1)*(ones(1,p)*K) + (1/p^2)*sum(sum(K));
if nargin < 3
    t = min(floor(p/4), 30);
end

[V_K,D_K] = eig(K);
d_k = diag(D_K);
ind_k = find(d_k > 1e-8);
d_k(ind_k) = d_k(ind_k).^(-1/2);
K_half = V_K*diag(d_k)*V_K';

%create indices for the t random points for each hash bit
%then form weight matrix
for i = 1:b
    rp = randperm(p);
    I_s(i,:) = rp(1:t);
    e_s = zeros(p,1);
    e_s(I_s(i,:)) = 1;
    W(:,i) = sqrt((p-1)/t)*K_half*e_s;
end
H = (K*W)>0;
W = real(W);


function [p P_u P_pol] = omni_retro(u, pol)
%
% OMNI_RETRO  Retroproject pixel into 3D space.
%   P = OMNI_RETRO(UP, pol) retro-projects the point UP of the image
%   plane into the point P at depth S in 3D space
%
%   based on M=cam2world(m, ocam_model) from DAVIDE SCARAMUZZA
%   "Omnidirectional camera calibration toolbox" CAM2WORLD Project a give
%   pixel point onto the unit sphere M=CAM2WORLD=(m, ocam_model) returns
%   the 3D coordinates of the vector emanating from the single effective
%   viewpoint on the unit sphere
%
%
% Notes
% - pol: polynom coeff (vec)  -> "distortion" parametes in a0..an order, not polyval() order
%                                 we have 4th order polynome
%
%   Author: Davide Scaramuzza - email: davide.scaramuzza@ieee.org
%   Author: Grigory Abuladze - email: ryhor.a@google.com

%   Copyright (C) 2012 Grigory Abuladze @ ASL-vision.
%   Copyright (C) 2008 DAVIDE SCARAMUZZA, ETH Zurich

  if nargout == 1  % only points
    % Given an image point it returns the 3D coordinates of its correspondent optical ray
    r = (u(1,:).^2 + u(2,:).^2).^0.5;
    p = [u(1,:);
         u(2,:);
         polyval(pol(end:-1:1), r)];
    p = normc(p); % normalizes coordinates so that they have unit length (projection onto the unit sphere)

  else %  nargout > 2  ->  Jacobians

    if size(u,2) > 1
      error('Jacobians not available for multiple points');
    end

    r   = (u(1)^2 + u(2)^2)^0.5;
    n   = numel(pol);
    nn  = 0:n-1;     % orders vector
    r2n = r.^nn;     % powers vector
    p3  = r2n*pol;   %
    p   = [u(1);
           u(2);
           p3];

    [p,P_p] = normvec(p,1);

    a0 = pol(1); a1 = pol(2); a2 = pol(3); a3 = pol(4); a4 = pol(5);
    u1 = u(1);
    u2 = u(2);
    r2 = (u1^2 + u2^2);
    r  = r2^(1/2);

    % all before normalization
    P_u = [...
            [                                            1,                                            0]
            [                                            0,                                            1]
            [ 2*a2*u1 + 4*a4*u1*r2 + (a1*u1)/r + 3*a3*u1*r, 2*a2*u2 + 4*a4*u2*r2 + (a1*u2)/r + 3*a3*u2*r]
          ];

    P_pol = [...
              [ 0, 0,  0,        0,    0]
              [ 0, 0,  0,        0,    0]
              [ 1, r, r2, r2^(3/2), r2^2]
            ];

    % add normalization
    % f = norm(g()) -> use chain rule
    P_u = P_p * P_u;

  end

return

%% Jacobian
syms a0 a1 a2 a3 a4 real
syms u1 u2 s real

u   = [u1 u2]';
pol = [a0 a1 a2 a3 a4]';

p     = omni_retro(u, s, pol);

P_u   = simplify(jacobian(p,u))
P_s   = simplify(jacobian(p,s))
P_pol = simplify(jacobian(p,pol))

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

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

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


%ZSSD Sum of squared differences
%
% M = ZSSD(I1, I2) is the zero-mean sum of squared differences between the
% two equally sized image patches I1 and I2.  The result M is a scalar that
% indicates image similarity, a value of 0 indicates identical pixel patterns
% and is increasingly positive as image dissimilarity increases.
%
% Notes::
% - The ZSSD similarity measure is invariant to changes in image brightness
%   offset.
%
% See also SDD, SAD, NCC, ISIMILARITY.

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

function m = zssd(w1, w2)

	w1 = w1 - mean(w1(:));
	w2 = w2 - mean(w2(:));

	m = (w1-w2).^2;
    m = sum(m(:));


function c=ref_dft(f)
%REF_DFT  Reference Discrete Fourier Transform
%   Usage:  c=ref_dft(f);
%
%   REF_DFT(f) computes the unitary discrete Fourier transform of f.
%
%   AUTHOR: Jordy van Velthoven

L=size(f,1);
W=size(f,2);
c= zeros(L,W);

for w=1:W
for k=0:L-1
  for l=0:L-1
    c(k+1,w) = c(k+1,w) + f(l+1,w) * exp(-2*pi*i*k*l/L);
  end;
end;
end

c = c./sqrt(L);


function [dMu,dMu_n] = log_gmm_div_mu(X,W,Mu,Sigma)
%LOG_GMM_DIV_MU Derivative of the Log liklihood Guassian Mixture Model
%
%
%   input -----------------------------------------------------------------
%
%       o X         : (D x N),      Samples
%
%       o Priors    : (1 x K),      Weights
%
%       o Mu        : (D x K),      Means
%
%       o Sigma     : (D x D x K),  Covariance
%
%
%   output ----------------------------------------------------------------
%
%       o dMu       : (D x N x K), gradients of means for each data point
%                                  and each Gaussian Component
%

K = size(Mu,2);
D = size(Mu,1);
N = size(X,2);

dMu = zeros(D,K);

if nargout > 1
   dMu_n = zeros(D,N,K);
end

for k=1:K
    if nargout > 1
         dMu_n(:,:,k) = repmat(W(:,k)',D,1) .* (inv(Sigma(:,:,k)) * (X - repmat(Mu(:,k),1,N)));
         dMu(:,k)     = mean(dMu_n(:,:,k),2);
    else
         dMu(:,k) = mean(repmat(W(:,k)',D,1) .* (inv(Sigma(:,:,k)) * (X - repmat(Mu(:,k),1,N))),2);
    end
end

end


function result = cone_unit_3d ( func )

%*****************************************************************************80
%
%% CONE_UNIT_3D approximates an integral inside a unit cone in 3D.
%
%  Integration Region:
%
%    X**2 + Y**2 <= 1 - Z
%    0 <= Z <= 1.
%
%  Discussion:
%
%    An 48 point degree 7 formula, Stroud CN:S2:7-1, is used.
%
%    (There is a typographical error in the S2:7-1 formula for B3.)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Arthur Stroud,
%    Approximate Calculation of Multiple Integrals,
%    Prentice Hall, 1971, page 339.
%
%  Parameters:
%
%    Input, external FUNC, the name of the user supplied function which
%    evaluates F(X,Y,Z), of the form
%      function value = func ( x, y, z )
%
%    Output, real RESULT, the approximate integral of the function.
%
  u = [ 0.04850054945E+00, 0.2386007376E+00, 0.5170472951E+00,  0.7958514179E+00 ];
  w1 = [ 0.1108884156E+00,  0.1434587878E+00, 0.06863388717E+00, 0.01035224075E+00 ];

  a = sqrt ( 3.0E+00 ) / 2.0E+00;
  b = sqrt ( ( 27.0E+00 - 3.0E+00 * sqrt ( 29.0E+00 ) ) / 104.0E+00 );
  c = sqrt ( ( 27.0E+00 + 3.0E+00 * sqrt ( 29.0E+00 ) ) / 104.0E+00 );
  w2(1:3) = 3.0E+00 * [ ...
    2.0E+00 / 27.0E+00, ...
    ( 551.0E+00 + 4.0E+00 * sqrt ( 29.0E+00 ) ) / 6264.0E+00, ...
    ( 551.0E+00 - 4.0E+00 * sqrt ( 29.0E+00 ) ) / 6264.0E+00 ];

  quad = 0.0E+00;

  for i = 1 : 4

    x = a * ( 1.0E+00 - u(i) );
    y = 0.0E+00;
    z = u(i);
    quad = quad + w1(i) * w2(1) * feval ( func, x, y, z );

    x = - a * ( 1.0E+00 - u(i) );
    y = 0.0E+00;
    z = u(i);
    quad = quad + w1(i) * w2(1) * feval ( func, x, y, z );

    x = 0.0E+00;
    y = a * ( 1.0E+00 - u(i) );
    z = u(i);
    quad = quad + w1(i) * w2(1) * feval ( func, x, y, z );

    x = 0.0E+00;
    y = - a * ( 1.0E+00 - u(i) );
    z = u(i);
    quad = quad + w1(i) * w2(1) * feval ( func, x, y, z );

  end

  for i = 1 : 4

    x =   b * ( 1.0E+00 - u(i) );
    y =   b * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(2) * feval ( func, x, y, z );

    x = - b * ( 1.0E+00 - u(i) );
    y =   b * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(2) * feval ( func, x, y, z );

    x = - b * ( 1.0E+00 - u(i) );
    y = - b * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(2) * feval ( func, x, y, z );

    x =   b * ( 1.0E+00 - u(i) );
    y = - b * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(2) * feval ( func, x, y, z );

    x =   c * ( 1.0E+00 - u(i) );
    y =   c * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(3) * feval ( func, x, y, z );

    x = - c * ( 1.0E+00 - u(i) );
    y =   c * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(3) * feval ( func, x, y, z );

    x = - c * ( 1.0E+00 - u(i) );
    y = - c * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(3) * feval ( func, x, y, z );

    x =   c * ( 1.0E+00 - u(i) );
    y = - c * ( 1.0E+00 - u(i) );
    z =   u(i);
    quad = quad + w1(i) * w2(3) * feval ( func, x, y, z );

  end

  r = 1.0E+00;
  h = 1.0E+00;

  volume = cone_volume_3d ( r, h );
  result = quad * volume;

  return
end


function PoiseuilleFlow( varargin )
%POISOILLEFLOW Summary of this function goes here
%   Detailed explanation goes here
close all; % closes all figures
addpath('../Functions');

h=4; % height of the channel
dPdx=-0.01; % pressure gradient in x direction
mu=0.001; % dynamic viscosity

% function for the analytical solution
u_analFunc=@(y) -0.5*h^2/mu*dPdx*(1-(y/h).^2);

% create mesh
m=createMesh2D(20,20,2*h,2*h);

%% Boundary Conditions
U_BC = createBC(m); % all Neumann boundary condition structure

% Assign boundary conditions
U_BC.left.a(:) = 1; U_BC.left.b(:)=0; U_BC.left.c(:)=0; % Dirichlet for the left boundary
U_BC.right.a(:) = 1; U_BC.right.b(:)=0; U_BC.right.c(:)=0; % Dirichlet for the left boundary
U_BC.top.a(:) = 0; U_BC.top.b(:)=1; U_BC.top.c(:)=0; % Dirichlet for the left boundary
U_BC.bottom.a(:) = 0; U_BC.bottom.b(:)=1; U_BC.bottom.c(:)=0; % Dirichlet for the left boundary

V_BC = createBC(m); % all Neumann boundary condition structure

% Assign boundary conditions
V_BC.top.a(:) = 0; V_BC.top.b(:)=1; V_BC.top.c(:)=0; % Dirichlet for the left boundary
V_BC.bottom.a(:) = 0; V_BC.bottom.b(:)=1; V_BC.bottom.c(:)=0; % Dirichlet for the left boundary
V_BC.left.a(:) = 0; V_BC.left.b(:)=1; V_BC.left.c(:)=0; % Dirichlet for the left boundary
V_BC.right.a(:) = 0; V_BC.right.b(:)=1; V_BC.right.c(:)=0; % Dirichlet for the left boundary

BC_pressureCorrection = createBC(m);
BC_pressureCorrection.left.a(:) = 1; BC_pressureCorrection.left.b(:)=0; BC_pressureCorrection.left.c(:)=0;
BC_pressureCorrection.right.a(:) = 1; BC_pressureCorrection.right.b(:)=0; BC_pressureCorrection.right.c(:)=0;
BC_pressureCorrection.bottom.a(:) = 1; BC_pressureCorrection.bottom.b(:)=0; BC_pressureCorrection.bottom.c(:)=0;
BC_pressureCorrection.bottom.a(end/2) = 0; BC_pressureCorrection.bottom.b(end/2)=1; BC_pressureCorrection.bottom.c(end/2)=1;
BC_pressureCorrection.top.a(:) = 1; BC_pressureCorrection.top.b(:)=0; BC_pressureCorrection.top.c(:)=0;

% constant pressure - so there is no gradient
p_cellVar=createCellVariable(m,1,BC_pressureCorrection);

mu_cellVar=createCellVariable(m,0.001);
mu_faceVar=createFaceVariable(m,0.001);

rho=1000;
rho_cellVar=createCellVariable(m,rho);
rho_faceVar=createFaceVariable(m,rho);

U_cellVar=createCellVariable(m,0,U_BC);
V_cellVar=createCellVariable(m,0,V_BC);
faceVelocity=createFaceVariable(m,[0 0]);

pGradMat = gradientCellTerm(p_cellVar);
helpVarx = createCellVariable(m,dPdx);
helpVary = createCellVariable(m,0);
pGradMat.xvalue=helpVarx.value(2:end-1,2:end-1);
pGradMat.yvalue=helpVary.value(2:end-1,2:end-1);

% solve momentum equation Momentum equation
[U_cellVar,~,~,~]=MomentumEq(1,m,pGradMat,mu_faceVar,faceVelocity,U_cellVar,V_cellVar,U_BC,V_BC,rho,'SIMPLE');

y_anal=linspace(0,h,100);
u_anal=u_analFunc(y_anal);

figure;
plot(u_anal,y_anal); % plot analytical solution
hold on;
plot(U_cellVar.value(3,2:end-1),U_cellVar.domain.cellcenters.y-h,'o');
hold off;
figure;
visualizeCells(U_cellVar);

end


% test for tensor voting
% Use the tensor structure direction field as an input.

sigma = 0.5;
mu = 3;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% a test image
disp('--> Building test image.');
Radius = 0.9;

n = 75;
x = -1:2/(n-1):1;
y = linspace(0,1,n);
[X,Y] = meshgrid(x,x);

M = double( abs( X.^2+Y.^2-Radius^2 )<0.03 );
M = double( X.^2+Y.^2<Radius^2 );

% add some noise in the middle of the image
sigma = 0.8;    % level of the noise
r = 0.05;        % width of the gap
I = find(abs(X-0.5)<r);
M = M + sigma*randn(n).*(abs(X-0.5)<r);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% structure tensor computation
disp('--> Compute tensor structure.');
h = compute_gaussian_filter([11 11],0.6/n,[n n]);
Mh = perform_convolution(M,h);
ST = compute_rigidity_tensor(Mh);
h = compute_gaussian_filter([11 11],0.3/n,[n n]);
for i=1:4   % convole each entry
    ST(:,:,i) = perform_convolution( ST(:,:,i) ,h);
end
[e1,e2,l1,l2] = perform_tensor_decomp(ST);   % e1 is a regularized gradient

% As the main direction is the direction orthogonal to the discontinuity
% we must swap the eigenvectors.
T = perform_tensor_recomp(e2,e1,l1,l2);

clf;
subplot(2,2,1);
plot_vf(e2,M);
axis off;
colormap gray(256);
title('Original Image and Field');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% an example of field
A = compute_stick_tf([1,0.3],n);
[e1,e2,l1,l2] = perform_tensor_decomp(A);

subplot(2,2,2);
plot_vf(e1,l1);
axis off;
title('Example of Stick Field');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% peform voting
disp('--> Performing tensor voting.');
sigma = 0.2;
c = 0.1*sigma;
T = perform_voting(T,sigma,c);
disp('--> Performing tensor decomposition.');
[e1,e2,l1,l2] = perform_tensor_decomp(T,'abs');

% re-orient vf
e1 = perform_vf_reorientation(e1);
e2 = perform_vf_reorientation(e2);

% plot e1
subplot(2,2,3);
plot_vf(e1,l1);
axis off;
title('New Field with Eigenvalue');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% curve extraction via zeros crossing of A=ds/dn where s=l1-l2, n=e2,
% orthogonal to e1
s = l1-l2;
g = compute_grad(s);
A = prod_vf_vf(g,e2);

% extract only the 20 longest curves
options.min_length = 20;
c_list = perform_curve_extraction( A,0,10 );

% plot curves
subplot(2,2,4);
plot_curve(c_list,A);
axis off;
title('Extracted Curves');
saveas(gcf, 'test_structure', 'png');


function stats = grayrlprops(varargin)

%GRAYCOPROPS Properties of gray-level run-length matrix.
%  -------------------------------------------
%  STATS = GRAYCOPROPS(GLRLM,PROPERTIES) Each element in  GLRLM, (r,c),
%   is the probability occurrence of pixel having gray level values r, run-length c in the image.
%   GRAYCOPROPS is to calculate PROPERTIES.
%  -------------------------------------------
%  Requirements:
%  -------------------------------------------
%   GLRLM mustbe an cell array of valid gray-level run-length
%   matrices.Recall that a valid glrlm must be logical or numerical.
%  -------------------------------------------
%  Current supported statistics include:
%  -------------------------------------------
%   Short Run Emphasis (SRE)
%   Long Run Emphasis (LRE)
%   Gray-Level Nonuniformity (GLN)
%   Run Length Nonuniformity (RLN)
%   Run Percentage (RP)
%   Low Gray-Level Run Emphasis (LGRE)
%   High Gray-Level Run Emphasis (HGRE)
%   Short Run Low Gray-Level Emphasis (SRLGE)
%   Short Run High Gray-Level Emphasis (SRHGE)
%   Long Run Low Gray-Level Emphasis (LRLGE)
%   Long Run High Gray-Level Emphasis (LRHGE)
%  --------------------------------------------
%  Reference:
%  --------------------------------------------
%   Xiaoou Tang,Texture Information in Run-Length Matrices
%   IEEE TRANSACTIONS ON IMAGE PROCESSING, VOL.7, NO.11,NOVEMBER 1998
% ---------------------------------------------
%  See also GRAYRLMATRIX.
% ---------------------------------------------
% Author:
% ---------------------------------------------
%    (C)Xunkai Wei <xunkai.wei@gmail.com>
%    Beijing Aeronautical Technology Research Center
%    Beijing %9203-12,10076
% ---------------------------------------------
% History:
% ---------------------------------------------
% Creation: beta         Date: 01/10/2007
% Revision: 1.0          Date: 12/11/2007
% 1.Accept cell input now
% 2.Using MATLAB file style
% 3.Fully vectorized programming
% 4.Fully support the IEEE reference
% 5. ...

% Check GLRLM
[GLRLM numGLRLM] = ParseInputs(varargin{:});

% Initialize output stats structure.
% 11 statistics for each GLRLM
numStats = 11;

% % count number of GLRLM
% numGLRLM = length(GLRLM);

% Initialization default 4*11 matrix
stats = zeros(numGLRLM,numStats);

for p = 1 : numGLRLM
    %N-D indexing not allowed for sparse.

    if numGLRLM ~= 1
        % transfer to double matrix
        tGLRLM = GLRLM{p};
    else
        tGLRLM = GLRLM;
    end
    %     if numGLRLM ~= 1
    %         % transfer to double matrix
    %         tGLRLM = normalizeGLRL(GLRLM{p});
    %     else
    %         tGLRLM = normalizeGLRL(GLRLM);
    %     end
    % Get row and column subscripts of GLRLM.  These subscripts correspond to the
    % pixel values in the GLRLM.
    s = size(tGLRLM);
    % colum indicator
    c_vector =1:s(1);
    % row indicator
    r_vector =1:s(2);
    % matrix element indicator
    % Matrix form col and row: using meshgrid, you should transpose before using
    % i.e. if tGLRLM is m*n, then this function return c_matrix n*m,
    % r_matrix n*m.
    [c_matrix,r_matrix] = meshgrid(c_vector,r_vector);

    % Total number of runs
    N_runs = sum(sum(tGLRLM));

    % total number of elements
    N_tGLRLM = s(1)*s(2);

    %--------------------Prepare four matrix for speedup--------------
    % 1.Gray Level Run-Length Pixel Number Matrix
    %     p_p = calculate_p_p(tGLRLM,c_matrix');

    % 2.Gray-Level Run-Number Vector
    %   This vector represents the sum distribution of the number of runs
    %   with gray level i.
    p_g = sum(tGLRLM);

    % 3.Run-Length Run-Number Vector
    %   This vector represents the sum distribution of the number of runs
    %   with run length j.
    p_r = sum(tGLRLM,2)';

    % 4.Gray-Level Run-Length-One Vector
    %
    % p_o = tGLRLM(:,1); % Not used yet
    % ----------------------End four matrix---------------------------
    %
    %------------------------Statistics-------------------------------
    % 1. Short Run Emphasis (SRE)
    SRE = sum(p_r./(c_vector.^2))/N_runs;
    % 2. Long Run Emphasis (LRE)
    LRE = sum(p_r.*(c_vector.^2))/N_runs;
    % 3. Gray-Level Nonuniformity (GLN)
    GLN = sum(p_g.^2)/N_runs;
    % 4. Run Length Nonuniformity (RLN)
    RLN = sum(p_r.^2)/N_runs;
    % 5. Run Percentage (RP)
    RP = N_runs/N_tGLRLM;
    % 6. Low Gray-Level Run Emphasis (LGRE)
    LGRE = sum(p_g./(r_vector.^2))/N_runs;
    % 7. High Gray-Level Run Emphasis (HGRE)
    HGRE = sum(p_g.*r_vector.^2)/N_runs;
    % 8. Short Run Low Gray-Level Emphasis (SRLGE)
    SGLGE =calculate_SGLGE(tGLRLM,r_matrix',c_matrix',N_runs);
    % 9. Short Run High Gray-Level Emphasis (SRHGE)
    SRHGE =calculate_SRHGE(tGLRLM,r_matrix',c_matrix',N_runs);
    % 10. Long Run Low Gray-Level Emphasis (LRLGE)
    LRLGE =calculate_LRLGE(tGLRLM,r_matrix',c_matrix',N_runs);
    % 11.Long Run High Gray-Level Emphasis (LRHGE
    LRHGE =calculate_LRHGE(tGLRLM,r_matrix',c_matrix',N_runs);
    %----------------insert statistics----------------------------
    stats(p,:)=[SRE LRE GLN RLN  RP LGRE HGRE SGLGE SRHGE LRLGE  LRHGE ];
end % end all run length matrixs

%   ----------------------Utility functions--------------------
%-----------------------------------------------------------------------------
% function glrl = normalizeGLRL(glrl)
%
% % Normalize glcm so that sum(glcm(:)) is one.
% if any(glrl(:))
%   glrl = glrl ./ sum(glrl(:));
% end
% function p_p = calculate_p_p(GLRLM,c) % Note: currently not used
%
% % p_p(i; j) = GLRLM(i,j)*j
% % Each element of the matrix represents the number of pixels of run length
% % j and gray-level i. Compared to the original matrix, the new matrix gives
% % equal emphasis to all length of runs in an image.
%
% term1 =  c; % j index in matrix size
% term2 = GLRLM;
% p_p = term1 .* term2;
%---------------------------------
function SGLGE =calculate_SGLGE(tGLRLM,r_matrix,c_matrix,N_runs)
% Short Run Low Gray-Level Emphasis (SRLGE):

term = tGLRLM./((r_matrix.*c_matrix).^2);
SGLGE= sum(sum(term))./N_runs;

%------------------------------------
function  SRHGE =calculate_SRHGE(tGLRLM,r_matrix,c_matrix,N_runs)
% Short Run High Gray-Level Emphasis (SRHGE):
%
term  = tGLRLM.*(r_matrix.^2)./(c_matrix.^2);
SRHGE = sum(sum(term))/N_runs;
%------------------------------------
function   LRLGE =calculate_LRLGE(tGLRLM,r_matrix,c_matrix,N_runs)
% Long Run Low Gray-Level Emphasis (LRLGE):
%
term  = tGLRLM.*(c_matrix.^2)./(r_matrix.^2);
LRLGE = sum(sum(term))/N_runs;
%---------------------------------------
function  LRHGE =calculate_LRHGE(tGLRLM,r_matrix,c_matrix,N_runs)
% Long Run High Gray-Level Emphasis (LRHGE):
%
term  = tGLRLM.*(c_matrix.^2).*(r_matrix.^2);
LRHGE = sum(sum(term))/N_runs;
%----------------------------------------

%-----------------------------------------------------------------------------
function [glrlm num_glrlm] = ParseInputs(varargin)
% check stability of inputs
%
% first receive all inputs
glrlm = varargin{:};
% get numbers total
num_glrlm=length(glrlm);
% then for each element, check its stability
for i=1:num_glrlm
    % The 'nonnan' and 'finite' attributes are not added to iptcheckinput because the
    % 'integer' attribute takes care of these requirements.
    % iptcheckinput(glrlm,{'cell'},{'real','nonnegative','integer'}, ...
    % mfilename,'GLRLM',1);
    iptcheckinput(glrlm{i},{'logical','numeric'},{'real','nonnegative','integer'},...
        mfilename,'GLRLM',1);
    % Cast GLRLM to double to avoid truncation by data type. Note that GLRLM is not an
    % image.
    if ~isa(glrlm,'double')
        glrlm{i}= double(glrlm{i});
    end
end


%wrap - Set radian angles in range [0,2pi] or [-pi,pi].
%
%  USAGE
%
%    y = wrap(x,offset)
%
%    x              angles in radians
%    offset         phase angle [0-2*pi] that circularly shifts output data
%
%
%  SEE ALSO
%
%    See also isradians, clinspace.
%

% Copyright (C) 2010-2011 by Michaël Zugaro
% edited by David Tingley, 2017 to add phase offset as input
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 3 of the License, or
% (at your option) any later version.

function y = bz_wrap(x,offset)

% Check number of parameters
if nargin < 1,
  error('Incorrect number of parameters (type ''help wrap'' for details).');
end

% if nargin < 2,
% 	range = 1;
% end

if ~isa(x,'double'), y = []; return; end

% Determine angle in [0,2*pi]
y = mod(mod(x,2*pi)+offset,2*pi);

% Change range if necessary
% if range == 1,
% 	change = y > pi;
% 	y(change) = y(change)-2*pi + offset;
% end


function aid_test ( )

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

  fprintf ( 1, '\n' );
  fprintf ( 1, 'AID_TEST:\n' );
  fprintf ( 1, '  Test AIRY_AI_PRIME_VALUES, R4_AID, R8_AID\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '             X     AIRY_AID(X)\n' );
  fprintf ( 1, '                     R4_AID(X)        Diff\n' );
  fprintf ( 1, '                     R8_AID(X)        Diff\n' );

  n_data = 0;

  while ( 1 )

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

    if ( n_data == 0 )
      break
    end

    fx2 = r4_aid ( single ( x ) );
    fx3 = r8_aid ( x );

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

  end

  rmpath ( '../test_values' );

  return
end


function drawEllipse(h, x, P, c, ns, NP)

% DRAWELLIPSE Draw 2D ellipse or 3D ellipsoid.
%   DRAWELLIPSE(H,X,P) redraws ellipse or ellipsoid in handle H with mean X
%   and covariance P.
%
%   DRAWELLIPSE(...,C) allows the specification of the ellipse color C. If
%   C is not given or is empty, the color is unchanged.
%
%   DRAWELLIPSE(...,C,NS,NP) allows entering the number of sigmas NS and
%   the number of points NP. The default values are NS=3 and NP=10. Use
%   C=[] if you do not want to modify the ellipse color.

%   Copyright 2009 Joan Sola @ LAAS-CNRS.

if nargin < 6,         NP = 10;
    if nargin < 5,     ns = 3;
    end
end

if numel(x) == 2

    [X,Y] = cov2elli(x,P,ns,NP);
    set(h,'xdata',X,'ydata',Y,'vis','on')

elseif numel(x) == 3

    [X,Y,Z] = cov3elli(x,P,ns,NP);
    set(h,'xdata',X,'ydata',Y,'zdata',Z,'vis','on')

else
    error('??? Size of vector ''x'' not correct.')
end

if nargin > 3 && ~isempty(c)
    set(h,'color',c)
end

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

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

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function[varargout]=materncov(varargin)
%MATERNCOV  Autocovariance of the Matern random process and variations.
%
%   [TAU,R]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA) returns the autocovariance
%   function R of a length N complex-valued Matern random process having
%   variance SIGMA^2, slope parameter ALPHA, and damping parameter LAMBDA.
%
%   [TAU,R]=MATERNCOV(...,'real') instead forms the covariance of a real-
%   valued Matern process.
%
%   DT is the sample interval.  Note that LAMBDA is understood to have the
%   same units as the inverse sample interval 1/DT.
%
%   TAU is an array of time lags at which R is computed, and is given by
%   TAU=DT*[0,1,...,N-1].
%
%   By definition, R is one-sided theoretical autocovariance at
%   non-negative time lags.  See below for the relationship between this
%   and the full, length (2N-1) theoretical autocovariance function.
%
%   Note that for LAMBDA=0, the case of fractional Brownian motion, R will
%   contain only INFs because the autocovariance function is unbounded.
%
%   The input parameters SIGMA, ALPHA, and LAMBDA, may all either be
%   scalars or arrays of the same length M.  If the latter, then the output
%   autocovariance function R will be a matrix with N rows and M columns.
%
%   [TAU,R]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,NU,MU) returns the
%   autocovariance function of various extensions of the Matern process.
%   MATERNOISE(...,'composite') also works.  See MATERNSPEC for details.
%
%   See MATERNSPEC for a more thorough discussion of the Matern process.
%
%   For details on the Matern process and its autocovariance function, see:
%
%     Lilly, Sykulski, Early, and Olhede, (2017).  Fractional Brownian
%        motion, the Matern process, and stochastic modeling of turbulent
%        dispersion.  Nonlinear Processes in Geophysics, 24: 481--514.
%   __________________________________________________________________
%
%   Relationship to full autocovariance
%
%   For a time series of length N, the full autocovariance function RF is
%   length 2N-1, defined at time lags -N+1,-N+2...,-1,0,1,...,N-2,N-1.
%
%   The one-sided autocovariance R contains the full autocovariance RF at
%   positive time lags. Negative lags are given by Hermitian symmetry.
%
%   [TAUF,RF]=MATERNCOV(...,'full') returns the full (two-sided)
%   autocovariance RF and the corresponding two-sided time array TAUF.
%
%   RF is constructed from R as RF=[FLIPUD(CONJ(R(2:end,:));R].
%   __________________________________________________________________
%
%   Real-valued processes
%
%   By default MATERNCOV returns the autocovariance of a complex-valued
%   process.
%
%   MATERNCOV(...,'real') instead returns the autocovariance of a real-
%   valued process. This also works with any of extended versions.
%   __________________________________________________________________
%
%   Computational notes
%
%   The autocovariances for the generalized and composite Matern spectra do
%   not have analytic forms. Rather, these are approximated to high
%   precision by inverse Fourier transforming the oversampled spectrum with
%   10 x oversampling over a 10 x longer time period, and then decimating.
%
%   MATERNCOV(...,'general',M,P) or  MATERNCOV(...,'composite',M,P)
%   specifies the numerical oversampling parameters in the calculation.
%
%   The spectrum is then computed over a time window of M times the
%   required  duration, and P times the required sampling density, for a
%   total of M*P time more points.  These values may set to optimize the
%   tradeoff between speed and accuracy.
%
%   This computation method is expected to minimize aliasing effects and
%   resolution errors.
%   __________________________________________________________________
%
%   See also MATERNSPEC, MATERNIMP, MATERNOISE, MATERNFIT.
%
%   'materncov --t' runs some tests.
%
%   Usage: [tau,R]=materncov(dt,N,sigma,alpha,lambda);
%          [tau,R]=materncov(dt,N,sigma,alpha,lambda,nu);
%          [tau,R]=materncov(dt,N,sigma,alpha,lambda,mu,'composite');
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2013--2021 J.M. Lilly --- type 'help jlab_license' for details

%   No longer supported, sorry
%   __________________________________________________________________
%
%   Reverse Matern
%
%   [TAU,R]=MATERNCOV(N,SIGMA,ALPHA,LAMBDA,'reverse') returns the autocovariance
%   of the reverse Matern process, in which the roles of the spectrum and
%   the autocovariance functions are swapped.  The autocovariance is
%
%      R(TAU) = SIGMA^2 / (1+LAMBDA^2*TAU^2)^ALPHA
%
%   Note that the parameter LAMBDA has been inverted so that it still has units
%   of frequency, as in the case of the forward Matern process.

%   __________________________________________________________________
%
%   Extensions
%
%   Several extensions of the basic Matern form are supported, all of which
%   are discussed in more detail in MATERNSPEC.
%
%   Oscillatory Matern
%       [F,SPP,SNN]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,NU)
%   Generalized Matern (+ optional oscillations)
%       [F,SPP,SNN]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,GAMMA,'general')
%       [F,SPP,SNN]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,GAMMA,NU,'general')
%   Extended Matern  (+ optional oscillations)
%       [F,SPP,SNN]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,MU,'extended')
%       [F,SPP,SNN]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,MU,NU,'extended')
%   Composite Matern
%       [F,SPP,SNN]=MATERNCOV(DT,N,SIGMA,ALPHA,LAMBDA,MU,NU,'composite')

if strcmpi(varargin{1}, '--t')
    materncov_test,return
end

sid='one';
model='standard';
flag='complex';

M=10;  %Specifying oversampling rates for numerical computations
P=10;
for i=1:3
    if ischar(varargin{end})
        if strcmpi(varargin{end}(1:3),'rev')||strcmpi(varargin{end}(1:3),'com')||strcmpi(varargin{end}(1:3),'gen')||strcmpi(varargin{end}(1:3),'ext')
            model=varargin{end}(1:3);
        elseif strcmpi(varargin{end}(1:3),'rea')
            flag=varargin{end};
        else
            sid=varargin{end};
        end
        varargin=varargin(1:end-1);
    elseif ischar(varargin{end-2})  %For inputting M and P for testing
        if strcmpi(varargin{end-2}(1:3),'com')||strcmpi(varargin{end-2}(1:3),'gen')
            model=varargin{end-2};
            M=varargin{end-1};
            P=varargin{end};
            varargin=varargin(1:end-3);
        end
    end
end

if strcmpi(model(1:3),'com')&&strcmpi(model(1:3),'rev')
    error('Sorry, the COMPOSITE and REVERSE options cannot be used together.')
end

dt=double(varargin{1});
N=floor(varargin{2});
varargin=varargin(3:end);

if length(varargin)==1
    params=varargin{1};  %for input from materfit
else
    %this will be easier as a matrix
    Ncell=max(cellength(varargin));
    params=zeros(Ncell,length(varargin));
    for i=1:length(varargin)
        params(:,i)=varargin{i};
    end
end

tau=dt*[0:N-1]';
R=zeros(N,size(params,1));
for i=1:size(params,1)
    R(:,i)=materncov_one(tau,params(i,:),model,M,P,flag);
end

if strcmpi(sid(1:3),'ful')
    tau=[-flipud(tau(2:end,:));tau];
    R=[flipud(conj(R(2:end,:)));R];
end
varargout{1}=tau;
varargout{2}=R;

function[R]=materncov_one(tau,params,model,M,P,flag)

sigma=params(1);
alpha=params(2);
lambda=params(3);

nu=0;
if strcmpi(model(1:3),'com')
    mu=params(4);
    nu=params(5);

    N=length(tau);
    dt=tau(2)-tau(1);
    [f,Spp,Snn]=maternspec(dt,M*N*P,sigma,alpha,lambda/P,mu/P,nu/P,'composite',flag);
    S=[flipud(Snn(2:end));Spp];%figure,plot(S)
    Ri=ifft(ifftshift(S))./dt;  %Make sure it's ifftshift not fftshift
    Ri=Ri(1:P:end);
    R=Ri(1:N);
    R=R./R(1);
elseif strcmpi(model(1:3),'gen')
    %Generalized Matern form
    gamma=params(4);
    if length(params)==5
        nu=params(5);
    end
    %sigma,alpha,lambda/P,gamma,nu,flag
    N=length(tau);
    dt=tau(2)-tau(1);
    [f,Spp,Snn]=maternspec(dt,M*N*P,sigma,alpha,lambda/P,gamma,'generalized',flag);
    S=[flipud(Snn(2:end));Spp];%figure,plot(S)
    %figure,plot(f,[Spp Snn]),xlog,ylog,aresame(Spp,Snn,1e-13)
    Ri=ifft(ifftshift(S))./dt;  %Make sure it's ifftshift not fftshift
    %figure,plot(Ri)
    Ri=Ri(1:P:end);
    R=Ri(1:N);
    R=R./R(1);
elseif strcmpi(model(1:3),'ext')
    %Extended Matern, reduces to the standard Matern form for mu=0
    mu=params(4);
    if length(params)==5
        nu=params(5);
    end
    t=lambda.*sqrt(tau.^2+mu.^2);  %This is to support the extended Matern form
    R=frac(maternfun(alpha,t),maternfun(alpha,mu*lambda));
elseif strcmpi(model(1:3),'sta')
    %Standard Matern form
    if length(params)==4
        nu=params(4);
    end
    t=lambda.*tau;
    R=maternfun(alpha,t);
end
if nu~=0 && ~strcmpi(model(1:3),'com')
    R=R.*exp(sqrt(-1)*tau.*nu);
end
R=R.*sigma.^2;

if strcmpi(flag(1:3),'rea')
     R=real(R);
end

% Extended Matern form reduces to this Bessel function form, test is below
% if alpha=-1/2
%     tnorm=sqrt(tau.^2+mu.^2);
%     fact=besselk(1,lambda.*mu);
%     R1=frac(1,fact).*frac(1,tnorm./mu).*besselk(1,lambda.*tnorm);
% end

% function[]=maternfun_fig
%
% alpha=[-4:0.1:4];
% [tau,R]=materncov(dt,10000,1,alpha,0,0,1000);
% figure,plot(tau,R)
%
% hold on,h=plot(r1,xi(:,1)); linestyle -h h 3D
% hold on,h=plot(r1,xi(:,end)); linestyle -h h 3k
% title('The Matern function from \alpha = 1/2 (gray) to \alpha = 4 (black)')

function[]=materncov_test

tic
alpha=1.5;
h=0.1;
sigma=1;

N=1000;
[tau,R]=materncov(1,N,sigma,alpha,h);
[f,Spp,Snn]=maternspec(1,N,sigma,alpha,h);
[f,Spp2,Snn2]=blurspec(1,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC for case with negligible aliasing, even N',b1&&b2)

N=1000;
[tau,R]=materncov(1,N,sigma,alpha,h,h/2);
[f,Spp,Snn]=maternspec(1,N,sigma,alpha,h,h/2);
[f,Spp2,Snn2]=blurspec(1,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC for oscillatory Matern with negligible aliasing, even N',b1&&b2)

N=1000;
[tau,R]=materncov(1,N,sigma,alpha,h,h/2,'real');
[f,Spp,Snn]=maternspec(1,N,sigma,alpha,h,h/2,'real');
[f,Spp2,Snn2]=blurspec(1,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC for real-valued oscillatory Matern with negligible aliasing, even N',b1&&b2)

N=1000;
dt=7;
[tau,R]=materncov(dt,N,sigma,alpha,h/dt);
[f,Spp,Snn]=maternspec(dt,N,sigma,alpha,h/dt);
[f,Spp2,Snn2]=blurspec(dt,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC ..., even N, non-unit sample rate',b1&&b2)

N=1000;
[f,Spp,Snn]=maternspec(2,N,sigma,alpha,h/5,h,h*5,'composite');
[tau,R]=materncov(2,N,sigma,alpha,h/5,h,h*5,'composite');
[f,Spp2,Snn2]=blurspec(2,R,'aliased');

%[tau,R]=materncov(2,N,sigma,alpha,h/5,h*5,h,'composite');
%[f,Spp3,Snn3]=blurspec(2,R,'aliased');

%z=maternoise(N,sigma,alpha,h/5-1i*h*5,h,'composite');

%fact=2*sigma.^2.*(h/5).*((h*5).^2+h.^2).^alpha;
%2*sigma.^2.*H.*(nu.^2+G.^2).^alpha;

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),2e-2);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),2e-2);

%this test is currently not working ... Spp2 is off by a factor of sqrt(3),
%related to the fact that R(1) is not unity in the above code after calling mspec
%reporttest('MATERNCOV Fourier transforms to MATERNSPEC for case composite Matern with negligible aliasing, even N',b1&&b2)

N=1000;
[tau,R]=materncov(1,N,sigma,-1/2,h,alpha*10,'extended');
[f,Spp,Snn]=maternspec(1,N,sigma,-1/2,h,alpha*10,'extended');
[f,Spp2,Snn2]=blurspec(1,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC for case with negligible aliasing, even N, exponential',b1&&b2)

N=1000;
dt=7;
[tau,R]=materncov(dt,N,sigma,-1/2,h/dt,(alpha*10*dt),'extended');
[f,Spp,Snn]=maternspec(dt,N,sigma,-1/2,h/dt,(alpha*10*dt),'extended');
[f,Spp2,Snn2]=blurspec(dt,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC ..., even N, exponential, non-unit sample rate',b1&&b2)

[tau,R]=materncov(1,1000,7,1.5,1/10,20,'extended');
[f,Spp,Snn]=maternspec(1,1000,7,1.5,1/10,20,'extended');
[f,Spp2,Snn2]=blurspec(1,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-10);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-10);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC for case with negligible aliasing, even N, extended Matern',b1&&b2)

dt=1.3;
[tau,R]=materncov(dt,1000,7,1.5,1/10/dt,20/dt,'extended');
[f,Spp,Snn]=maternspec(dt,1000,7,1.5,1/10/dt,20/dt,'extended');
%[f,Spp2,Snn2]=blurspec(dt,R);
[f,Spp2,Snn2]=blurspec(dt,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-10);
b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-10);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC ..., even N, extended Matern, non-unit sample rate',b1&&b2)

N=1000-1;
[tau,R]=materncov(1,N,sigma,alpha,h,2*h,'extended');
[f,Spp,Snn]=maternspec(1,N,sigma,alpha,h,2*h,'extended');
[f,Spp2,Snn2]=blurspec(1,R,'aliased');

b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
b2=aresame(Snn2./maxmax(Spp),Snn./maxmax(Spp),1e-4);

reporttest('MATERNCOV Fourier transforms to MATERNSPEC for case with negligible aliasing, frequency shift case, odd N',b1&&b2)

N=1000;
dt=7;
lambda=h/dt;
mu=(alpha*10*dt);
[tau,R]=materncov(dt,N,sigma,-1/2,lambda,mu,'extended');
tnorm=sqrt(tau.^2+mu.^2);
fact=besselk(1,lambda.*mu);%See notes for this form
R1=frac(1,fact).*frac(1,tnorm./mu).*besselk(1,lambda.*tnorm);
reporttest('MATERNCOV ALPHA = -1/2 case matches expected form',aresame(R,R1,1e-10))

toc
% [tau,R]=materncov(1,N,sigma,alpha,h,'reverse');
% [f,Spp,Snn]=maternspec(1,N,sigma,alpha,h,'reverse');
% R(1)=R(1)/2;
% S=2*real(fft(R));
% Spp2=S(1:length(Spp));
% S=flipud(S);
% Snn2=[S(end);S(1:length(Snn)-1)];
%
% b1=aresame(Spp2./maxmax(Spp),Spp./maxmax(Spp),1e-4);
% b2=aresame(Snn2./maxmax(Snn),Snn./maxmax(Snn),1e-4);
%
% reporttest('MATERNCOV Fourier transforms to MATERNSPEC for case with negligible aliasing, even N, reverse Matern',b1&&b2)

%Playing around with asymptotic results... which don't work for alpha > 3/2
% sigma=7;
% alpha=[0.6 3/4 1.001 1.25 3/2-0.001 1.75];% 1.75 2 3 4 10];
% %alpha=[1.75 2 3 4 10];% 1.75 2 3 4 10];
% lambda=1/10000;
% N=10000;
% [tau,R]=materncov(N,sigma,alpha,lambda);
% Rapprox=zeros(size(R));
% for i=1:length(alpha)
%     %numer=(lambda.*tau).^(2*alpha(i)-1);
%     %denom=2*materncfun(alpha(i)).*cos(pi.*alpha(i)).*gamma(2*alpha(i));
%     numer1=-(lambda.*tau/2).^(2*alpha(i)-1)*gamma(3/2-alpha(i));
%     denom1=gamma(1/2+alpha(i));
%     numer2=(lambda.*tau/2).^2*gamma(3/2-alpha(i));
%     denom2=gamma(5/2-alpha(i));
%     Rapprox1(:,i)=sigma.^2.*(1+frac(numer,denom));
%     %Rapprox2(:,i)=sigma.^2.*(1+frac(numer1,denom2)+frac(numer2,denom2));
% end
% Rapprox(Rapprox<0)=nan;
% Rapprox(Rapprox>2*sigma.^2)=nan;

% alpha=1.5;
% h=0.1;
% sigma=1;
% nu=0.1;
%
% N=1000;
% figure
% [tau,R]=materncov(N,sigma,1,h-1i*nu);
% [f,Spp,Snn]=blurspec(R);
% plot(-f,Snn),hold on,plot(f,Spp)
% [tau,R]=materncov(N,sigma,1,h+1i*nu);
% [f,Spp,Snn]=blurspec(R);
% plot(-f,Snn),hold on,plot(f,Spp)
%
% [f,Spp,Snn]=maternspec(N,sigma,alpha,h);

% N=1000;
% r1=[0:.00001:0.00001]';
% alpha=[1/2:0.1:4];
% R=materncov(r1,1,alpha(:),1/100);
% dr=(R(2,:)-R(1,:))./(r1(2)-r1(1));
% dr2=-frac(gamma(abs(alpha-3/2)),gamma(alpha-1/2)).*frac(1/100,2);
% %dr2(alpha==1)=-1/100;
%
% plot(alpha,-dr,'r*'),hold on,plot(alpha,-dr2,'o')
%
% dxi=-frac(r,2).*frac(gamma(alpha-1),gamma(alpha)).*maternfun(alpha-1,r);
% reporttest('MATERNFUN iterative expression for derivative matches direct expression',aresame(xi1(2:end,:),dxi(2:end,:),1e-10))
%


%% Hough Lines Transform
% An example using the Hough line detector.
%
% This program demonstrates line finding with the Hough transform.
% We show how to use the OpenCV functions |cv.HoughLines| and |cv.HoughLinesP|
% to detect lines in an image.
%
% Sources:
%
% * <https://github.com/opencv/opencv/blob/3.2.0/samples/cpp/houghlines.cpp>
% * <https://github.com/opencv/opencv/blob/3.2.0/samples/python/houghlines.py>
% * <https://docs.opencv.org/3.2.0/d9/db0/tutorial_hough_lines.html>
% * <https://github.com/opencv/opencv/blob/3.2.0/samples/cpp/tutorial_code/ImgTrans/HoughLines_Demo.cpp>
% * <https://docs.opencv.org/3.2.0/d6/d10/tutorial_py_houghlines.html>
%

%% Theory
%
% The explanation below belongs to the book *Learning OpenCV* by
% Bradski and Kaehler.
%
% The Hough Line Transform is a transform used to detect straight lines. To
% apply the Transform, first an edge detection pre-processing is desirable.
%
% As you know, a line in the image space can be expressed with two variables.
% For example:
%
% * In the *Cartesian coordinate system:* Parameters: $(m,b)$.
% * In the *Polar coordinate system:* Parameters: $(r,\theta)$
%
% <<https://docs.opencv.org/3.2.0/Hough_Lines_Tutorial_Theory_0.jpg>>
%
% For Hough Transforms, we will express lines in the _Polar system_. Hence, a
% line equation can be written as:
%
% $$y = \left ( -\frac{\cos \theta}{\sin \theta} \right ) x +
%       \left ( \frac{r}{\sin \theta} \right )$$
%
% Arranging the terms: $r = x \cos \theta + y \sin \theta$
%
% In general for each point $(x_{0}, y_{0})$, we can define the family of
% lines that goes through that point as:
%
% $$r_{\theta} = x_{0} \cdot \cos \theta + y_{0} \cdot \sin \theta$$
%
% Meaning that each pair $(r_{\theta},\theta)$ represents each line that
% passes by $(x_{0}, y_{0})$.
%
% If for a given $(x_{0}, y_{0})$ we plot the family of lines that goes
% through it, we get a sinusoid. For instance, for $x_{0} = 8$ and $y_{0} = 6$
% we get the following plot (in a plane $\theta$ - $r$):
%
% <<https://docs.opencv.org/3.2.0/Hough_Lines_Tutorial_Theory_1.jpg>>
%
% We consider only points such that $r > 0$ and $0< \theta < 2 \pi$.
%
% We can do the same operation above for all the points in an image. If the
% curves of two different points intersect in the plane $\theta$ - $r$, that
% means that both points belong to a same line. For instance, following with
% the example above and drawing the plot for two more points:
% $x_{1} = 4$, $y_{1} = 9$ and $x_{2} = 12$, $y_{2} = 3$, we get:
%
% <<https://docs.opencv.org/3.2.0/Hough_Lines_Tutorial_Theory_2.jpg>>
%
% The three plots intersect in one single point $(0.925, 9.6)$, these
% coordinates are the parameters ($\theta, r$) or the line in which
% $(x_{0}, y_{0})$, $(x_{1}, y_{1})$ and $(x_{2}, y_{2})$ lay.
%
% What does all the stuff above mean? It means that in general, a line can be
% _detected_ by finding the number of intersections between curves. The more
% curves intersecting means that the line represented by that intersection
% have more points. In general, we can define a _threshold_ of the minimum
% number of intersections needed to _detect_ a line.
%
% This is what the Hough Line Transform does. It keeps track of the
% intersection between curves of every point in the image. If the number of
% intersections is above some _threshold_, then it declares it as a line with
% the parameters $(\theta, r_{\theta})$ of the intersection point.
%
%% Standard and Probabilistic Hough Line Transform
%
% OpenCV implements two kind of Hough Line Transforms:
%
% 1) *The Standard Hough Transform*
%
% * It consists in pretty much what we just explained in the previous section.
%   It gives you as result a vector of couples $(\theta, r_{\theta})$
% * In OpenCV it is implemented with the function |cv.HoughLines|
%
% 2) *The Probabilistic Hough Line Transform*
%
% * A more efficient implementation of the Hough Line Transform. It gives as
%   output the extremes of the detected lines $(x_{0}, y_{0}, x_{1}, y_{1})$
% * In OpenCV it is implemented with the function |cv.HoughLinesP|
%

%% Code
%
% This program:
%
% * Loads an image
% * Applies either a _Standard Hough Line Transform_ or a
%   _Probabilistic Line Transform_.
% * Display the original image and the detected line in two windows.
%
% You may observe that the number of lines detected vary while you change the
% _threshold_. The explanation is sort of evident: If you establish a higher
% threshold, fewer lines will be detected (since you will need more points to
% declare a line detected).
%

%%
% Input image
if true
    fname = fullfile(mexopencv.root(), 'test', 'sudoku.jpg');
    thresh = 200;
    threshP = 100;
    minlen = 100;
else
    fname = fullfile(mexopencv.root(), 'test', 'pic1.png');
    thresh = 85;
    threshP = 50;
    minlen = 50;
end
src = cv.imread(fname, 'Color',true);

%%
% Edge Detection
gray = cv.cvtColor(src, 'RGB2GRAY');
edges = cv.Canny(gray, [50, 150], 'ApertureSize',3);
imshow(edges), title('Edges')

%%
% HoughLines: Standard Hough Line Transform
tic
lines = cv.HoughLines(edges, 'Rho',1, 'Theta',pi/180, 'Threshold',thresh);
toc

%%
% draw the lines, and display the result
lines = cat(1, lines{:});
rho = lines(:,1);
theta = lines(:,2);
a = cos(theta); b = sin(theta);
x0 = a.*rho; y0 = b.*rho;
pt1 = round([x0 + 1000*(-b), y0 + 1000*(a)]);
pt2 = round([x0 - 1000*(-b), y0 - 1000*(a)]);
out = cv.line(src, pt1, pt2, ...
    'Color',[0 255 0], 'Thickness',2, 'LineType','AA');
figure, imshow(out), title('Detected Lines')

%%
% HoughLinesP: Probabilistic Hough Line Transform
tic
linesP = cv.HoughLinesP(edges, 'Rho',1, 'Theta',pi/180, ...
    'Threshold',threshP, 'MinLineLength',minlen, 'MaxLineGap',10);
toc

%%
% draw the line segments, and display the result
linesP = cat(1, linesP{:});
outP = cv.line(src, linesP(:,1:2), linesP(:,3:4), ...
    'Color',[0 255 0], 'Thickness',2, 'LineType','AA');
figure, imshow(outP), title('Detected Line Segments')


function gridlines_test02 ( )

%*****************************************************************************80
%
%% GRIDLINES_TEST02 tests GRID_POLAR.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 July 2010
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'GRIDLINES_TEST02\n' );
  fprintf ( 1, '  GRID_POLAR draws a polar grid.\n' );
  fprintf ( 1, '  Compare two methods of sampling the circle.\n' );

  r = sqrt ( rand ( 400, 1 ) );
  t = pi * rand ( 400, 1 );
  plot ( r .* cos ( t ), r .* sin ( t ), 'b*' );

  grid_polar ( 0.0, 0.0, 0.1, 1.0, 10, 0, 180, 13 );

  hold on

  r = - rand ( 400, 1 );
  t = pi * rand ( 400, 1 );
  plot ( r .* cos ( t ), r .* sin ( t ), 'r*' );

  grid_polar ( 0.0, 0.0, 0.1, 1.0, 10, 180, 360, 13 );

  xlabel ( 'X' )
  ylabel ( 'Y' )
  title ( 'Blue: R = sqrt(rand), Red: R = - rand' )
  axis equal

  fprintf ( 1, '\n' );
  fprintf ( 1, 'Press return to continue.\n' )
  hold off
  pause
  clf

  return
end


function value = index2_row ( i_min, i, i_max, j_min, j, j_max, index_min )

%*****************************************************************************80
%
%% INDEX2_ROW indexes a 2D array by row.
%
%  Discussion:
%
%    Entries of the array are indexed starting at entry (I_MIN,J_MIN),
%    and increasing the column index first.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 April 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I_MIN, I, I_MAX, for row indices,
%    the minimum, the index, and the maximum.
%
%    Input, integer J_MIN, J, J_MAX, for column indices,
%    the minimum, the index, and the maximum.
%
%    Input, integer INDEX_MIN, the index of element (I_MIN,J_MIN).
%    Typically, this is 0 or 1.
%
%    Output, integer VALUE, the index of element (I,J).
%
  value = index_min + ( j - j_min ) + ( i - i_min ) * ( j_max + 1 - j_min );

  return
end


%
% This code calculates the interevent distances and the correlation integral
% of a given earthquake distribution.
% Calculation of the 3D distances between all possible pairs
% (combination of n epicenters taken 2 at a time) of earthquakes of
% the given dataset.
% Francesco Pacchiani 1/2000
%
%
% Variables
%
N = size(E,1);				% N= # of events in the catalogue; E= Earthquake catalogue
pairdist = []; 			% pairdist= Vector of interevent distances
j = nchoosek(N,2);			% j= # of interevent distances calculated
pairdist = zeros((N-1),N);
depth = zeros((N-1),N);
k = 1;
%E.Latitude= (max(Da(:,2))+min(Da(:,2)))/2;

%Ho_Wb = waitbar(0,'Calculating the fractal dimension D');
%Hf_Cfig = gcf;
%Hf_child = get(groot,'children');
%set(Hf_child,'pointer','watch','papertype','A4');
%
%
% Calculation of the interevent distances in 2D plus the depths differences.
%
%
for i = 1:(N-1)

    lon1 = repmat(E(i,1), [(N-1),1]);
    lat1 = repmat(E(i,2), [(N-1),1]);
    depth1 = repmat(E(i,7), [(N-1),1]);

    E(i,:) = [];

    lon2 = E.Longitude;
    lat2 = E.Latitude;
    depth2 = E.Depth;

    pairdist(1:(N-1),k) = distance(lat1,lon1,lat2,lon2);
    depth(1:(N-1),k) = depth1-depth2;

    k = k + 1;
    E = newt2;

    %Waitbar((0.75/(N-1))*i, Ho_Wb);

end

clear i j k;
%
%
% Conversion of the interevent distances from degrees to kilometers and calculates
% the interevent distances in three dimensions.
%
%
if dtokm == 1
    pairdist = pairdist.*111;
end

pairdist = (pairdist.^2 + depth.^2).^0.5;		% pairdist = Interevent distances (vector).
clear depth;
%
%
% Calculation of the correlation integral using as input the
% pair distances computed above.
%
%
% Variables
%
d = 3;						%d = the dimension of the embedding volume.
rmax1 = max(pairdist);
rmin1 = min(pairdist);
rmax = max(rmax1);
rmin = min(rmin1);

clear rmax1 rmin1;

if rmin == 0
    rmin = 0.01;
end

lrmin = log10(rmin);
lrmax = log10(rmax);

%u = (log10(rmin):0.15:log10(rmax))';
%
% Defining the distance vector r in order that on the
% log-log graph all the points plot at equal distances from one another.
%
r = (logspace(lrmin, lrmax, 50))';
%r = zeros(size(u,1),1);
%r = 10.^u;
%
%
corint = [];						% corint= Vector of ?cumulative? correlation integral values for increasing interevent radius
cor = zeros(size(r,1),N);
i = 1;

for k = 1:50

    l = [];
    l = pairdist < r(k);
    test(k,1) = sum(l);
    %cor(1:size(r,1),i) = (sum(l));
    %i=i+1;

    %Waitbar(0.75 + (0.25/size(r,1))*k,Ho_Wb);
end

sumcor = sum(cor,2);
sumcor1 = sumcor./N;

for j = 0:20

    corint1(1:50,1,(j+1)) = sumcor1(:,1,(j+1)).^(1/(j-1));
end

corint = corint1(1:50, 1:21);

clear i j j1 k l cor sumcor;
close(Ho_Wb);
Hf_child = get(groot,'children');
set(Hf_child,'pointer','arrow');
%
%
% Plotting of the correlation integral in function of the interevent
% distance r.
%
%
Hf_Fig = figure_w_normalized_uicontrolunits('Numbertitle','off','Name','Fractal Dimension');
Hl_gr1 = loglog(r, corint,'ko', 'MarkerSize',5);
set(Hl_gr1,'MarkerSize',5);
title(sprintf('Correlation Integral versus %.0fD Interevent Distances', d));

Hf_Fig = figure_w_normalized_uicontrolunits('Numbertitle','off','Name','Fractal Dimension');
Hl_gr1 = loglog(r, cor,'r+');
set(Hl_gr1,'MarkerSize',7);
title(sprintf('Correlation Integral versus %.0fD Interevent Distances', d));
%
%
dofd = 'fd';
dofdim;


function circle_trajectory %(p1, p2, p3)

close all

p1=rand(1,3);p2=rand(1,3);p3=rand(1,3);
[pc,r,v1,v2] = circlefit3d(p1,p2,p3);
plot3(p1(:,1),p1(:,2),p1(:,3),'ro');hold on;plot3(p2(:,1),p2(:,2),p2(:,3),'go');plot3(p3(:,1),p3(:,2),p3(:,3),'bo');

x1 = (p1-pc);
x1 = x1/norm(x1);
phi1 = dot(v1,x1);
x2 = (p2-pc);
x2 = x2/norm(x2);
phi2 = dot(v1,x2);

angle = [phi1 phi2];
%angle = 0:0.1:2*pi;
%angle = pi/4:0.1:pi/2;
for i=1:length(angle)
        a = angle(i);
        x = pc(:,1)+cos(a)*r.*v1(:,1)+sin(a)*r.*v2(:,1);
        y = pc(:,2)+cos(a)*r.*v1(:,2)+sin(a)*r.*v2(:,2);
        z = pc(:,3)+cos(a)*r.*v1(:,3)+sin(a)*r.*v2(:,3);
        plot3(x,y,z,'r+');
end
axis equal;grid on;rotate3d on;

% fit a circle with three points

%[pm, r, v1, v2] = circlefit3d(p1', p2', p3');


function [m, A, Eigenfaces] = EigenfaceCore(Training_Data)

%----------------------------Calculate the mean image ------------------------
% ---------------------compute the covariance matrix --------------------------
m = mean(Training_Data,2);
Train_Number = size(Training_Data,2);
temp_m = [];
for i = 1 : Train_Number
    temp_m = [temp_m m];
end
A = double(Training_Data) - temp_m;

%-------------------use the "svd" function to compute the eigenvectors
%--------------------and eigenvalues of the covariance matrix.
disp('Computing...Wait a second please')
L = A'*A;
%size(L)
[V D] = eig(L);

%-----------------------------Sort and eliminate eigenvalues---------------
Eig_vec = [];
for i = 1 : size(V,2)
    if( D(i,i)>1000 ) % Set Threshold value whatever you like
        Eig_vec = [Eig_vec V(:,i)];
    end
end

Eigenfaces = A * Eig_vec;


function [newL2] = bestMap(L1,L2)
%bestmap: permute labels of L2 to match L1 as good as possible
%   [newL2] = bestMap(L1,L2);
%
%   version 2.0 --May/2007
%   version 1.0 --November/2003
%
%   Written by Deng Cai (dengcai AT gmail.com)

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

L1 = L1(:);
L2 = L2(:);
if size(L1) ~= size(L2)
    error('size(L1) must == size(L2)');
end

Label1 = unique(L1);
nClass1 = length(Label1);
Label2 = unique(L2);
nClass2 = length(Label2);

nClass = max(nClass1,nClass2);
G = zeros(nClass);
for i=1:nClass1
	for j=1:nClass2
		G(i,j) = length(find(L1 == Label1(i) & L2 == Label2(j)));
	end
end

[c,t] = hungarian(-G);
newL2 = zeros(size(L2));
for i=1:nClass2
    newL2(L2 == Label2(i)) = Label1(c(i));
end