% MLRC Muli-response Linear Regression Combiner
%
%   W = A*(WU*MLRC)
%   W = WT*MLRC(B*WT)
%   D = C*W
%
% INPUT
%   A   Dataset used for training base classifiers as well as combiner
%   B   Dataset used for training combiner of trained base classifiers
%   C   Dataset used for testing (executing) the combiner
%   WU  Set of untrained base classifiers, see STACKED
%   WT  Set of trained base classifiers, see STACKED
%
% OUTPUT
%   W   Trained Muli-response Linear Regression Combiner
%   D   Dataset with prob. products (over base classifiers) per class
%
% DESCRIPTION
% Using dataset A that contains the posterior probabilities of each instance
% belonging to each class predicted by the base classifiers to train a
% multi-response linear regression combiner.
% If the original classification problem has K classes, it is converted
% into K seperate regression problems, where the problem for class c has
% instances with responses equal to 1 when they have label c and zero
% otherwise. Put in another way, this function establish a multi-response
% linear regression model for each class and utilize these models to estimate
% the probability that the instances belong to each class.
% Note that in the model for class c, only the probabilities of class c
% predicted by the set of base classifiers are used.
%
% REFERENCE
% 1. Ting, KM, Witten IH. Issues in stacked generalization, Journal of
% Artificial Intelligent Research, 1999, 10: 271-289.
% 2. Dzeroski S, Zenko B. Is combining classifiers with stacking better
% than selecting the best one? Machine Learning, 2004, 54(3): 255-273.
%
% SEE ALSO (PRTools Guide)
% DATASETS, MAPPINGS, STACKED, CLASSC, TESTD, LABELD

% Copyright: Chunxia Zhang, R.P.W. Duin, r.p.w.duin@37steps.com
% Faculty EWI, Delft University of Technology
% P.O. Box 5031, 2600 GA Delft, The Netherlands

function W = mlrc(A)

        name = 'MLR combiner';

    % If there are no inputs, return an untrained mapping.
    % Handle untrained calls like MLRC([])
    if nargin < 1 || isempty(A)
        W = prmapping(mfilename);
        W = setname(W,name);
        return
    end

    islabtype(A,'crisp');       % allow crisp labels only
    isvaldfile(A,1,2);          % at least one object per class and 2 classes

    A = testdatasize(A,'features'); % test whether they fit
    A = setprior(A,getprior(A));    % avoid many warnings
    [m,k,c] = getsize(A);           % size of training set; (m objects; k features; c classes)
    L = k/c;                        % compute the number of classifiers
    A = setfeatlab(A,repmat([1:c]',L,1)); % reset the feature labels of dataset A such that the first c features correspond to
                                          % the first classifier, the next c features correspond to the second classifier, ect.
    C = zeros(c*L,c);                     % register the coefficients of each model
    options = optimset('ToLX',1e-4);
    for i = 1:c                         % run over all classes
        Res = zeros(m,1);
        Index = find(A.featlab == i);   % find the indices correspond to the jth class
        B = seldat(A,[],Index);         % select the data corresponding to the jth class(m x L matrix)
        I = A.nlab == i;
        Res(I) = 1;
        [x,resnorm,residual,exitflag] = lsqnonneg(B.data,Res,[],options); % compute the nonnegative coefficients
        if exitflag == 0
            resnorm
        end

        for j = 1:L
            C((j-1)*c+i,i) = x(j);
        end
    end

    W = affine(C,[],A,getlablist(A),k,c);
    W = setname(W,name);

return


classdef RWMOP20 < PROBLEM
% <multi> <real> <constrained>
% Hydro-static thrust bearing design problem

%------------------------------- Reference --------------------------------
% A. Kumar, G. Wu, M. Ali, Q. Luo, R. Mallipeddi, P. Suganthan, and S. Das,
% A benchmark-suite of real-world constrained multi-objective optimization
% problems and some baseline results, Swarm and Evolutionary Computation,
% 2021, 67: 100961.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Initialization
        function Setting(obj)
            obj.M        = 2;
            obj.D        = 4;
            obj.lower    = [ 1, 1,  1e-6,1];
            obj.upper    = [16, 16, 16*1e-6,16];
            obj.encoding = ones(1,obj.D);
        end
        %% Evaluate multiple solutions
        function Population = Evaluation(obj,varargin)
            x = varargin{1};
            R = x(:,1); Ro = x(:,2);  mu = x(:,3); Q = x(:,4);
            gamma = 0.0307; C = 0.5; n = -3.55; C1 = 10.04;
            Ws = 101000; Pmax = 1000; delTmax = 50; hmin = 0.001;
            gg = 386.4; N = 750;
            P    = (log10(log10(8.122*1e6.*mu+0.8))-C1)./n;
            delT = 2.*(10.^P-560);
            Ef   = 9336.*Q.*gamma.*C.*delT;
            h    = (2.*pi.*N./60).^2.*2.*pi.*mu./Ef.*(R.^4./4-Ro.^4./4)-1e-5;
            Po   = (6.*mu.*Q./(pi.*h.^3)).*log(R./Ro);
            W    = pi.*Po./2.*(R.^2-Ro.^2)./(log(R./Ro)-1e-5);
            % Objective function
            f(:,1) = (Q.*Po./0.7+Ef)./12;
            f(:,2) = gamma./(gg.*Po).*(Q./(2.*pi.*R.*h));
            % Constraints
            g(:,1) = Ws-W;
            g(:,2) = Po-Pmax;
            g(:,3) = delT-delTmax;
            g(:,4) = hmin-h;
            g(:,5) = Ro-R;
            g(:,6) = f(:,2)-0.001;
            g(:,7) = W./(pi.*(R.^2-Ro.^2)+1e-5)-5000;
            Population = SOLUTION(varargin{1},f,g,varargin{2:end});
            obj.FE     = obj.FE + length(Population);
        end
        %% Generate a point for hypervolume calculation
        function R = GetOptimum(obj,~)
            R = [2.6725846e+02  -2.7672651e-05];
        end
    end
end


function align_filtered= apply_filter( data, data_Nsamples, align_filter_dB)

global Downsample DATAPADDING_MSECS SEARCHBUFFER Fs

align_filtered= data;
n= data_Nsamples- 2* SEARCHBUFFER* Downsample+ DATAPADDING_MSECS* (Fs/ 1000);
% now find the next power of 2 which is greater or equal to n
pow_of_2= 2^ (ceil( log2( n)));

[number_of_points, trivial]= size( align_filter_dB);
overallGainFilter= interp1( align_filter_dB( :, 1), align_filter_dB( :, 2), ...
    1000);

x= zeros( 1, pow_of_2);
x( 1: n)= data( SEARCHBUFFER* Downsample+ 1: SEARCHBUFFER* Downsample+ n);

x_fft= fft( x, pow_of_2);

freq_resolution= Fs/ pow_of_2;

factorDb( 1: pow_of_2/2+ 1)= interp1( align_filter_dB( :, 1), ...
    align_filter_dB( :, 2), (0: pow_of_2/2)* freq_resolution)- ...
    overallGainFilter;
factor= 10.^ (factorDb/ 20);

factor= [factor, fliplr( factor( 2: pow_of_2/2))];
x_fft= x_fft.* factor;

y= ifft( x_fft, pow_of_2);

align_filtered( SEARCHBUFFER* Downsample+ 1: SEARCHBUFFER* Downsample+ n)...
    = y( 1: n);

% fid= fopen( 'log_mat.txt', 'wt');
% fprintf( fid, '%f\n', y( 1: n));
% fclose( fid);


function square_hex_grid_test02 ( )

%*****************************************************************************80
%
%% SQUARE_HEX_GRID_TEST02 tests HEX_GRID_01_H.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 January 2009
%
%  Author:
%
%    John Burkardt
%
  test_num = 17;

  nodes_per_layer_test = [ ...
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 21, 41, 81, 101, 1001, 10001 ];

  fprintf ( 1, '\n' );
  fprintf ( 1, 'SQUARE_HEX_GRID_TEST02\n' );
  fprintf ( 1, '  For a hexagonal grid of points in the unit square,\n' );
  fprintf ( 1, '  given NODES_PER_LAYER, the number of grid points\n' );
  fprintf ( 1, '  along the first layer,\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  HEX_GRID_01_H computes HX and HY, the spacings\n' );
  fprintf ( 1, '  in the row and column directions.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '    NODES    LAYERS   HX          HY\n' );
  fprintf ( 1, '      PER\n' );
  fprintf ( 1, '    LAYER\n' );
  fprintf ( 1, '\n' );

  for test = 1 : test_num
    nodes_per_layer = nodes_per_layer_test ( test );
    layers = hex_grid_01_layers ( nodes_per_layer );
    [ hx, hy ] = hex_grid_01_h ( nodes_per_layer );
    fprintf ( 1, '  %6d  %6d  %10f  %10f\n', nodes_per_layer, layers, hx, hy );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  LAYERS is chosen so that LAYERS-1 layers just fit\n' );
  fprintf ( 1, '  inside the unit square, but LAYERS layers do not.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  LAYERS      HY     (LAYERS-1)*HY    LAYERS*HY\n' );
  fprintf ( 1, '\n' );

  for test = 1 : test_num
    nodes_per_layer = nodes_per_layer_test ( test );
    layers = hex_grid_01_layers ( nodes_per_layer );
    [ hx, hy ] = hex_grid_01_h ( nodes_per_layer );

    temp1 =  ( layers - 1 ) * hy;
    temp2 =  ( layers ) * hy;

    fprintf ( 1, '  %6d  %10f  %10f  %10f\n', ...
      nodes_per_layer, hy, temp1, temp2 );

  end

  return
end


function linplus_test58 ( )

%*****************************************************************************80
%
%% TEST58 tests R8SS_MXV, R8SS_PRINT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 March 2009
%
%  Author:
%
%    John Burkardt
%
  n = 9;
  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST58\n' );
  fprintf ( 1, '  For a symmetric skyline storage matrix,\n' );
  fprintf ( 1, '  R8SS_MXV computes A*x,\n' );
  fprintf ( 1, '  R8SS_PRINT prints it.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Matrix order N = %d\n', n );
%
%  Set the matrix.
%
  [ na, diag, a, seed ] = r8ss_random ( n, seed );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of nonzero entries stored is %d\n', na );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Diagonal storage indices:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n
    fprintf ( 1, '%6d  %6d\n', i, diag(i) );
  end
%
%  Replace the random entries by marker values.
%
  ij = 0;
  for j = 1 : n

    if ( j == 1 )
      ilo = 1;
    else
      ilo = diag(j-1) - diag(j) + j + 1;
    end

    for i = ilo : j
      ij = ij + 1;
      a(ij) = 10 * i + j;
    end

  end

  r8ss_print ( n, na, diag, a, '  The R8SS matrix:' );
%
%  Copy the matrix into a general matrix.
%
  a2 = r8ss_to_r8ge ( n, na, diag, a );
%
%  Set the vector X.
%
  x = r8vec_indicator ( n );
%
%  Compute the product.
%
  b = r8ss_mxv ( n, na, diag, a, x );
%
%  Compute the product using the general matrix.
%
  b2 = r8ge_mxv ( n, n, a2, x );
%
%  Compare the results.
%
  r8vec2_print_some ( n, b, b2, 10, '  R8SS_MXV verse R8GE_MXV' );

  return
end


function ranks = tied_ranks(x,tol)
% like tiedrank(), but faster and without the bells & whistles.
%
%                               Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                               2013-07-22

if ~exist('tol','var')
    tol = 10*eps; end
ranks = 1:length(x);
[sorted,order] = sort(x);
tie_ranges = reshape(find(diff([false abs(diff(sorted(:)'))<tol false])),2,[])';
for r=1:size(tie_ranges,1)
    range = tie_ranges(r,1):tie_ranges(r,2);
    ranks(range) = sum(ranks(range))/(range(end)-range(1)+1);
end
ranks(order) = ranks;
ranks = reshape(ranks,size(x));


function value = biw_condition ( n )

%*****************************************************************************80
%
%% BIW_CONDITION computes the L1 condition of the BIW matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 April 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Output, real VALUE, the L1 condition.
%
  if ( n == 1 )
    a_norm = 0.6;
  else
    a_norm = 1.6;
  end

  b_norm = 0.0;
  j = n;
  for i = n : -1 : 1
    aii = 0.5 + i / ( 10 * n );
    if ( i == j )
      bij = 1.0 / aii;
    elseif ( i < j )
      bij = bij / aii;
    end
    b_norm = b_norm + abs ( bij );
  end

  value = a_norm * b_norm;

  return
end


function f=loglikGaPfromVWH(varargin)
% f=loglikGaPfromVWH(varargin)
% complete log likellihood of the GaP model
% Vxt =     varargin{1};        %data (XxT)
% Wxk =     varargin{2};        %basis functions (XxK)
% Hkt =     varargin{3};        %intensities (KxT)
% alpha =   varargin{4};        %parameters of the Gamma blinking (Kx1)
% beta =    varargin{5};        %parameters of the Gamma blinking (Kx1)
% peval =   varargin{6};        %parameters
% Gamma distribution with mean alpha/beta!
% X: number of pixels
% T: number of images (time - slices)
% K: number of components

Vxt =     varargin{1};        %data (XxT)
Wxk =     varargin{2};        %basis functions (XxK)
Hkt =     varargin{3};        %intensities (KxT)
alpha =   varargin{4};        %parameters of the Gamma blinking (Kx1)
beta =    varargin{5};        %parameters of the Gamma blinking (Kx1)
peval =   varargin{6};        %parameters

k=size(Wxk,2);
if length(alpha) ==1; alpha = repmat(alpha,k, 1); end
if length(beta) ==1; beta = repmat(beta,k, 1); end
%[Wxkbg,Hktbg]=addbg(Wxk, Hkt, peval.bg);
%P=Wxkbg*Hktbg; %current approximation (XxT)
P=Wxk*Hkt; %current approximation (XxT)

%Poisson contribution
t1=Vxt.*log(P) - P - factorialapprox(Vxt); %(XxT)
%Gamma contribution
t2a=bsxfun(@times,(alpha-1),log(Hkt)) - bsxfun(@times,beta,Hkt); % (KxT)
t2b=-alpha.*log(beta)-log(gamma(alpha)); %(1xK)

f=sum(t1(:))+sum(t2a(:))+sum(t2b(:));
% Conjugate gradient is mimimizing! for this it needs to be f=-f;


function K = anisotropic_rbf(kern,dat1,dat2,ind1,ind2,kerParam),

% K = rbf(d1,d2,ind1,ind2,param), compute the kernel
%     matrix between d1 and d2
% for a rbf kernel exp(-||x-z||^2/(2*param^2))
%     where x is from d1 and z from d2

w = [];
for i = 1:length(kerParam)-1
    w = [w,kerParam{i}];
end
v = kerParam{end};

X2 = get_x(dat2,ind2);
X1 = get_x(dat1,ind1);

for i  =1:size(X1,1)
    for j = 1:size(X2,1)
         s = sum(w.*((X1(i,:) - X2(j,:)).^2));
         K(j,i) = v*exp(-0.5*s);
     end
end


function Cb2n = ch_rotz(theta)
% 3D初等旋转， theta为旋转角度，rad
Cb2n = [cos(theta) -sin(theta) 0; sin(theta) cos(theta) 0; 0 0 1];

end


x = [9 2.140641477955609996536345; ...
	2.5 0.7031566406452431872257; ...
	0.1 -10.42375494041107679516822; ...
	7e-4 -1429.147493371120205005198; ...
	7e-5 -14286.29138623969227538398; ...
	7e-6 -142857.7200612932791081972; ...
	2e-6 -500000.5772123750382073831; ...
	1e-6 -1000000.577214019968668068; ...
	7e-7 -1428572.005785942019703646; ...
	-0.5 .03648997397857652055902367; ...
	-1.1 10.15416395914385769902271 ...
	];
for i = 1:rows(x)
	actual = digamma(x(i,1));
	expected = x(i,2);
	e = abs(actual - expected)/expected;
	if e > 1e-12
		error(sprintf('digamma(%g) = %g should be %g', x(i,1), actual, expected));
	end
end
if digamma(-1) ~= -Inf
	error('digamma(-1) should be -Inf');
end
if digamma(0) ~= -Inf
  error('digamma(0) should be -Inf');
end
if ~isnan(digamma(-Inf))
  error('digamma(-Inf) should be NaN');
end


function [to_fine, from_fine] = twoDquad_spline(x_fine,y_fine,x_knots,y_knots)
% Create 2D quadratic polynomial based spline approximation
%
% by SeHyoun Ahn, July 2016
%
% REFERENCE: To be Written
%
% PARAMTERS:
%    x_fine,y_fine = fine grid points
%    x_knots,y_knots = coarser grid to reduce to
%
% OUTPUTS:
%    to_fine = change of basis from spline basis to finer grid points
%    from_fine = change of basis from finer grid points to spline basis
%
% EXAMPLES:
%   x = linspace(-1,1,100)';
%   y = linspace(-1,1,100)';
%
%   % z = e^(-(x^2+y^2));
%   z = exp(-bsxfun(@plus,x.^2,y'.^2));
%
%   knot_x = linspace(-1,1,4)';
%   knot_y = linspace(-1,1,4)';
%
%   [to_fine, from_fine] = twoDquad_spline(x,y,knot_x,knot_y);
%
%   z_approxed = to_fine*from_fine*z(:);
%
%   surf(z);
%   hold on;
%   disp('press any key');
%   pause();
%   surf(reshape(z_approxed,100,100));
%
% SYNTAX:
% [to_fine, from_fine] = twoDquad_spline(x_fine,y_fine,x_knots,y_knots)

n_x_fine = length(x_fine);
n_y_fine = length(y_fine);

n_x_knots = length(x_knots);
n_y_knots = length(y_knots);
h_x = diff(x_knots);
h_y = diff(y_knots);

% Find the Location of Rectangle
x_locs = sum(bsxfun(@ge,x_fine,x_knots'),2);
x_locs = min(x_locs,n_x_knots-1);
x_adjusted = (x_fine - x_knots(x_locs))./h_x(x_locs);

y_locs = sum(bsxfun(@ge,y_fine,y_knots'),2);
y_locs = min(y_locs,n_y_knots-1);
y_adjusted = (y_fine - y_knots(y_locs))./h_y(y_locs);

xx = bsxfun(@times,x_adjusted,ones(1,n_y_fine));
yy = bsxfun(@times,ones(n_x_fine,1),y_adjusted');

xx_locs = bsxfun(@times,x_locs,ones(1,n_y_fine));
yy_locs = bsxfun(@times,ones(n_x_fine,1),y_locs');

% Stacked value of which rectangle the grid point is in
position = xx_locs(:) + (yy_locs(:)-1)*(n_x_knots-1);

% Evaluation of Polynomial Basis
polynomials_stacked = [ones(n_x_fine*n_y_fine,1),  xx(:),  yy(:),  ...
                        xx(:).^2,  xx(:).*yy(:),  yy(:).^2,  ...
                        xx(:).^2.*yy(:),  xx(:).*yy(:).^2];

evaluation = zeros(n_x_fine*n_y_fine,8*(n_x_knots-1)*(n_y_knots-1));

for i=(n_x_knots-1)*(n_y_knots-1):-1:1
    locs = find(position==i);
    evaluation(locs,(i-1)*8+1:8*i) = polynomials_stacked(locs,:);
end

evaluation = sparse(evaluation);

coeff_change = [1, 0, 0, 0, 0, 0, 0, 0;         % f(0,0)
                1, 1, 0, 1, 0, 0, 0, 0;         % f(1,0)
                1, 0, 1, 0, 0, 1, 0, 0;         % f(0,1)
                1, 1, 1, 1, 1, 1, 1, 1;         % f(1,1)
                0, 1, 0, 0, 0, 0, 0, 0;         % dx(0,0)
                0, 0, 1, 0, 0, 0, 0, 0;         % dy(0,0)
                0, 0, 1, 0, 1, 0, 1, 0;         % dy(1,0)
                0, 1, 0, 0, 1, 0, 0, 1];        % dx(0,1)

revert_change = sparse(inv(coeff_change));
aux = kron(speye(n_y_knots-1),spdiags(ones(n_x_knots-1,1),0,n_x_knots-1,n_x_knots));

%% Unpack Values-Derivatives to Proper Location
f00 = [aux,sparse((n_x_knots-1)*(n_y_knots-1),2*n_x_knots*n_y_knots-n_y_knots)]';
f10 = [sparse((n_x_knots-1)*(n_y_knots-1),1),aux,sparse((n_x_knots-1)*(n_y_knots-1),2*n_x_knots*n_y_knots-n_y_knots-1)]';
f01 = [sparse((n_x_knots-1)*(n_y_knots-1),n_x_knots),aux,sparse((n_x_knots-1)*(n_y_knots-1),2*n_x_knots*n_y_knots-n_x_knots-n_y_knots)]';
f11 = [sparse((n_x_knots-1)*(n_y_knots-1),n_x_knots+1),aux,sparse((n_x_knots-1)*(n_y_knots-1),2*n_x_knots*n_y_knots-n_x_knots-n_y_knots-1)]';
dx00 = [sparse((n_x_knots-1)*(n_y_knots-1),n_x_knots*n_y_knots),spdiags(repmat(h_x,n_y_knots-1,1),0,(n_x_knots-1)*(n_y_knots-1),(n_x_knots-1)*(n_y_knots-1)),sparse((n_x_knots-1)*(n_y_knots-1),n_x_knots*n_y_knots-1)]';
dx01 = [sparse((n_x_knots-1)*(n_y_knots-1),n_x_knots*n_y_knots+n_x_knots-1),spdiags(repmat(h_x,n_y_knots-1,1),0,(n_x_knots-1)*(n_y_knots-1),(n_x_knots-1)*(n_y_knots-1)),sparse((n_x_knots-1)*(n_y_knots-1),n_x_knots*n_y_knots-n_x_knots)]';
aux = kron(spdiags(h_y,0,n_y_knots-1,n_y_knots-1),spdiags(ones(n_x_knots-1,1),0,n_x_knots-1,n_x_knots));
dy00 = [sparse((n_x_knots-1)*(n_y_knots-1),2*n_x_knots*n_y_knots-n_y_knots),aux]';
dy10 = [sparse((n_x_knots-1)*(n_y_knots-1),2*n_x_knots*n_y_knots-n_y_knots+1),aux(:,1:end-1)]';

% Warning: Overwriting aux matrix here
aux = [f00(:),f10(:),f01(:),f11(:),dx00(:),dy00(:),dy10(:),dx01(:)]';

% Change Value/Derivatives to Coefficient Basis
aux = revert_change*aux;

%% A nightmare set of transformations. Good luck!
% These are supposed to reorder things to match location of the basis
% expansion
aux = reshape(aux,8*(3*n_x_knots*n_y_knots-n_x_knots-n_y_knots),(n_x_knots-1)*(n_y_knots-1));
permute = reshape(1:8*(3*n_x_knots*n_y_knots-n_x_knots-n_y_knots),8,3*n_x_knots*n_y_knots-n_x_knots-n_y_knots)';
aux = reshape(aux(permute(:),:),3*n_x_knots*n_y_knots-n_x_knots-n_y_knots,8*(n_x_knots-1)*(n_y_knots-1))';

%% Finally Basis Change
to_fine = evaluation*aux;

% Sometimes less than full basis are required up to machine accuarcy, so reduce with SVD
[u,d,~] = svd(full(to_fine),'econ');
singles = find(diag(d)>d(1,1)*eps*10);

% Basis Change Functions
to_fine = u(:,singles)*d(singles,singles);
% Since we took an SVD, so we can just invert by multiplication
from_fine = (d(singles,singles)\u(:,singles)');


function [u] = spm_u(a,df,STAT)
% uncorrected critical height threshold at a specified significance level
% FORMAT [u] = spm_u(a,df,STAT)
% a     - critical probability - {alpha}
% df    - [df{interest} df{error}]
% STAT  - Statistical field
%               'Z' - Gaussian field
%               'T' - T - field
%               'X' - Chi squared field
%               'F' - F - field
%               'P' - P - value
%
% u     - critical height {uncorrected}
%__________________________________________________________________________
%
% spm_u returns the uncorrected critical threshold at a specified
% significance
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_u.m 2690 2009-02-04 21:44:28Z guillaume $

if     STAT == 'Z'

    u   = spm_invNcdf(1 - a      );

elseif STAT == 'T'

    u   = spm_invTcdf(1 - a,df(2));

elseif STAT == 'X'

    u   = spm_invXcdf(1 - a,df(2));

elseif STAT == 'F'

    u   = spm_invFcdf(1 - a,df   );

elseif STAT == 'P'

    u   = a;

end


function   [A, D, alpha] = LowRankDictionaryUpdate_m(A_prev, D_prev, alpha_prev, lambda)

% min \|E\|_1+ \lambda*(\|D\|_f^2+\|\alpha\|_f^2) s.t. D*\lambda+E=X

% this function is to update the bases D and coefficients \alpha, over
% the constraint D*\alpha = A_prev, by one iteration of ADM

% Xianbiao Shu (xshu2@illinois.edu)
% Updated on Aug-10-2011
% Copyright: Mitsubishi Electric Research Lab

    D = A_prev*alpha_prev'*inv(alpha_prev*alpha_prev'+lambda);
    alpha = inv(D'*D+ lambda)*D'*A_prev;

    A = D*alpha;

end


function Fx = computeFx(x)
    Fx = [0 0 -x(4)*sin(x(3))-x(5)*cos(x(3)) cos(x(3)) -sin(x(3)) 0;...
          0 0 x(4)*cos(x(3))-x(5)*sin(x(3))  sin(x(3))  cos(x(3)) 0;...
          0 0               0                   0           0     1;...
          0 0               0                   0           0     0;...
          0 0               0                   0           0     0;...
          0 0               0                   0           0     0];
end


function [m, ssmp] = cellmean(x, dim)

% [M] = CELLMEAN(X, DIM) computes the mean, across all cells in x along
% the dimension dim.
%
% X should be an linear cell-array of matrices for which the size in at
% least one of the dimensions should be the same for all cells

nx = size(x);
if ~iscell(x) || length(nx)>2 || all(nx>1),
  error('incorrect input for cellmean');
end

if nargin==1,
  scx1 = cellfun('size', x, 1);
  scx2 = cellfun('size', x, 2);
  if     all(scx2==scx2(1)), dim = 2; %let second dimension prevail
  elseif all(scx1==scx1(1)), dim = 1;
  else   error('no dimension to compute mean for');
  end
end

nx   = max(nx);
nsmp = cellfun(@nansum, isfinite(x), repmat({dim},1,nx), 'UniformOutput', 0);
ssmp = cellfun(@nansum,          x,  repmat({dim},1,nx), 'UniformOutput', 0);
m    = nansum(cell2mat(ssmp), dim)./nansum(nsmp);


%fill_mm_bundle Proj. reconstruction from MM [with bundle adjustment].
%
%  Call fill_mm [and bundle adjustment].
%
%  [ P,X, u1,u2, info ] = fill_mm_bundle(M, imsize, nl_params_all_cams [,opt])
%
%  Parameters:
%    M .. measurement matrix (MM) with homogeneous image points with NaNs
%         standing for the unknown elements in all three coordinates
%    imsize .. double(2,m), image sizes: imsize(:,i) is size of image i
%                           m .. No. of cameras
%    opt .. options with default values in ():
%           .no_BA(0) .. whether refine using bundle adjustment
%           .verbose(1) .. whether display info
%           .verbose_short .. see opt in bundle_PX_proj
%           ... other options see in fill_mm
%
%  Return parameters:
%    info.R_lin .. linear estimation of filled M
%    ... other parameters see in fill_mm

function [ P,X, u1,u2, info ] = fill_mm_bundle(M, imsize, nl_params_all_cams, opt)

if nargin < 4, opt = []; end
if ~isfield(opt, 'no_BA')
  opt.no_BA = 0; end
if ~isfield(opt, 'verbose'),
  opt.verbose = 1; end

[P,X, u1,u2, info] = fill_mm(M, opt);

info.R_lin = P*X;

if ~opt.no_BA && length(u1) < size(M,1)/3 && length(u2) < size(M,2)
  if opt.verbose, fprintf(1, 'Bundle adjustment...\n'); tic; end

  [m,n] = size(M); m = m/3; r1 = setdiff(1:m,u1); r2 = setdiff(1:n,u2);
  [P,X] = bundle_PX_proj(P,X, normalize_cut(M(k2i(r1),r2)), imsize, nl_params_all_cams, opt);
  % old bundler:
  %[P,X] = qPXbundle_cmp(P,X, normalize_cut(M(k2i(r1),r2)));

  if opt.verbose, disp(['(' num2str(toc) ' sec)']); end
  info.err.BA = dist(M(k2i(r1),r2), P*X, info.opt.metric);
  if opt.verbose, fprintf('Error (after BA): %f\n', info.err.BA);
  else, fprintf(' %f\n', info.err.BA); end
else, if ~opt.verbose, fprintf('\n'); end; end


function [x, timing] = blendenpik_under_alternative(A, b, params)
% [x, timing] = blendenpik_under(A, b, params)
%
% Alternative function for solving the equation
% x = arg min norm(A * x - b, 2) using Blendenpik, where A has
% more columns than rows. Less stable than the regular version.
%
% "params" - parameters governning the method.
%    params.type - type of mixing transform. Optional values: 'DCT', 'DHT', 'WHT'.
%                  Default is DHT.
%    params.gamma - gamma * m columns will be sampled (A is m-by-n).
%                   Default is 4.
%    params.preprocess_steps - number of mixing steps to do in advance.
%                               Default is 1.
%    params.maxcond - maximum condition number of the preconditioner.
%                     Default is 1 / (5 * epsilon_machine).
%    params.tol - convergence thershold for LSQR.
%                 Default is 1e-14.
%    params.maxit - maximum number of LSQR iterations.
%                   Default is 1000.
%    params.lsvec - whether to output in "timing" the LSQR residuals.
%                   Default is false.
%    params.use_full_lsqr - whether to use LSQR with full
%                           orthogonalization. Useful for
%                           preprocess_steps=0.
%                           Default is false.
%
% Output:
%   x - the solution.
%   timing - statistics on the time spent on various phases.
%
% 6-December 2009, Version 1.3
% Copyright (C) 2009, Haim Avron and Sivan Toledo.

if (nargin < 3)
    params = struct;
end

if (~isfield(params, 'type'));
    params.type = 'DHT';
end

if (~isfield(params, 'gamma'))
    params.gamma = 4;
end

if (~isfield(params, 'preprocess_steps'))
    params.preprocess_steps = 1;
end

if (~isfield(params, 'tol'))
    params.tol = 1e-14;
end

if (~isfield(params, 'maxit'))
    params.maxit = 1000;
end

if (~isfield(params, 'maxcond'))
    params.maxcond = 1 / (5 * eps);
end

if (~isfield(params, 'lsvec'))
    params.lsvec = false;
end

if (~isfield(params, 'slight_coherence'))
    params.slight_coherence = 0;
end

if (~isfield(params, 'use_full_lsqr'))
    params.use_full_lsqr = false;
end

tstart = wtime;

%% Build preconditioner
t1 = wtime;

[m, n] = size(A);
AT = A';
t0 = wtime;
frut_D = sign(randn(n, 1));
B = fast_unitary_transform(AT, frut_D, params.type);
nn = size(B, 1);
frut_D(n+1:nn) = 0;
frut_time = wtime - t0;
disp(sprintf('\t\tRandom unit diagonal + unitary transformation time: %.2f sec', frut_time));
timing.precond_timing.timing.frut_time = frut_time;

t0 = wtime;
t = params.gamma * m / nn;
s = rand(nn, 1);
SB = B(find(s < t), :);
sample_time = wtime - t0;
disp(sprintf('\t\tRandom sampling time: %.2f sec', sample_time));
timing.precond_timing.sample_time = sample_time;

t0 = wtime;
[Y, tau] = mex_dgeqrf(SB);
qr_time = wtime - t0;
disp(sprintf('\t\tQR on random sample time: %.2f sec', qr_time));
timing.qr_time = qr_time;

timing.preprocess_total_time = wtime - t1;
disp(sprintf('\tPreprocessing time: %.2f sec', timing.preprocess_total_time));

%% One solution
t1 = wtime;
y = mex_dtrsm(Y, b, 1.0, 'L', 'U', 'T', 'N');
ssz = size(Y, 1);
p0 = mex_dormqr(Y, tau, [y; zeros(ssz-m, 1)], 'L', 'N');
p1 = zeros(nn, 1); p1(s < t) = p0;
p2 = fast_unitary_transform(p1, frut_D, ['I' params.type]);
p = p2(1:n);
timing.find_non_min_time = wtime - t1;
disp(sprintf('\tFind a non-minimal solution: %.2f sec', timing.find_non_min_time));

%% LSQR
t1 = wtime;
R = triu(Y(1:m, 1:m));
% clear Y;
% clear SB
% clear tau;
if (~params.lsvec)
    if (~params.use_full_lsqr)
        [x0, timing.lsqr_its] = dense_lsqr(AT, p, R, params.tol, params.maxit);
    else
        [x0, timing.lsqr_its] = dense_full_lsqr(AT, p, R, params.tol, params.maxit);
    end
else
    [x0, timing.lsqr_its, timing.lsvec, timing.resvec] = dense_lsqr(AT, p, R, params.tol, params.maxit);
end
timing.lsqr_time = wtime - t1;
disp(sprintf('\tLSQR time: %.2f sec', timing.lsqr_time));

%% Mult by AT to get final solution
t1 = wtime;
x = AT * x0;
timing.multAT_time = wtime - t1;
disp(sprintf('\tMultiply by A'' time: %.2f sec', timing.multAT_time));
timing.total_time = wtime - tstart;
disp(sprintf('Total time: %.2f sec', timing.total_time));


function [f,J] = spm_fx_phase (phi,u,P,M)
% State equation for a phase-coupled oscillator
% FORMAT [f,J] = spm_fx_phase (phi,u,P,M)
%
% phi       state variable
% u         []
% P         model (variable) parameter structure
% M         model (fixed) parameter structure
%
% f         Flow vector, dphi/dt
% J         Jacobian, J(i,j)=df_i/dphi_j
%__________________________________________________________________________
% Copyright (C) 2009 Wellcome Trust Centre for Neuroimaging

% Will Penny
% $Id: spm_fx_phase.m 2908 2009-03-20 14:54:03Z will $

% Sin terms
if isfield(P,'As')
    Nr=size(P.As,1);
    Ns=size(P.As,3);

    % negative abs
    Ahs=~(P.As==0);
    As=-abs(P.As).*Ahs;
else
    Ns=0;
end

% Cos terms
if isfield(P,'Ac')
    Nc=size(P.Ac,3);
    Nr=size(P.Ac,1);

    % Positive abs
    Ahc=~(P.Ac==0);
    Ac=abs(P.Ac).*Ahc;
else
    Nc=0;
end

% Flow vector
f=zeros(Nr,1);
for i=1:Nr,
    change=0;
    for j=1:Nr,
        phi_diff=phi(i)-phi(j);
        for n=1:Ns,
            change=change+As(i,j,n)*sin(n*phi_diff);
        end
        for n=1:Nc,
            change=change+Ac(i,j,n)*cos(n*phi_diff);
        end
    end
    exc=M.freq+P.df(i)+change;
    f(i)=2*pi*exc;
end

if nargout == 1; return, end

% Jacobian
As=-As;
for i=1:Nr,
    for j=1:Nr,
        jac=0;
        if i==j
            % Diagonal
            for jj=1:Nr,
                for n=1:Ns,
                    jac=jac-n*As(i,jj,n);
                end
            end
        else
            % Off-diagonal
            phi_diff=phi(i)-phi(j);
            for n=1:Ns,
                jac=jac+n*As(i,j,n)*cos(n*phi_diff);
            end
            for n=1:Nc,
                jac=jac+n*Ac(i,j,n)*sin(n*phi_diff);
            end
        end
        J(i,j)=jac;
    end
end
J=J*2*pi;


function determ = symm_random_determinant ( n, d, key )

%*****************************************************************************80
%
%% SYMM_RANDOM_DETERMINANT returns the determinant of the SYMM_RANDOM matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 March 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Input, real D(N), the desired eigenvalues for the matrix.
%
%    Input, integer KEY, a positive integer that selects the data.
%
%    Output, real DETERM, the determinant.
%
  determ = prod ( d(1:n) );

  return
end


function [m,im,iu] = unique(m,varargin)
% disjoint list of Miller indices%
%
% Syntax
%   u = unique(m) % find disjoined elements of the vector v
%   u = unique(m,'tolerance',0.01) % use tolerance 0.01
%   [u,im,iu] = unique(m,varargin)]
%
% Input
%  m   - @Miller
%  tol - double (default 1e-7)
%
% Output
%  u - @Miller
%  im - index such that u = m(im)
%  iu - index such that m = u(iu)
%
% Flags
%  stable     - prevent sorting
%  noSymmetry - ignore symmetry
%
% See also
% unique
%

if check_option(varargin,'noSymmetry')

  [~,im,iu] = unique@vector3d(m,varargin{:});

else
  v = vector3d(symmetrise(m,varargin{:}));

  [~,~,iu] = unique(v,varargin{:});

  [~,im,iu] = unique(min(reshape(iu,size(v)),[],1));

end

m = m.subSet(im);


function matrix = pseudoRotation(skel, channels, ind2Compute)

% PSEUDOGRADIENT ths position function of a node is composed with 2
% terms. The first one is the position of the parent node, the second is an
% additional term to get the real position. This function computes the
% derivative of the second term for the node 'ind2Compute' in respect with
% the channels 'rotInd2' given a set of channels.
%
%	Description:
%
%	[gradient matrix] = PSEUDOGRADIENT(skel, channels,gradientDirection, ind,rotInd2, ind2Compute)
%
%	 Returns:
%	  GRADIENT - the coponents of the gradient (x,y,z)
%     MATRIX - the rotation matrix
%	 Arguments:
%	  SKEL - a skeleton structure
%	  CHANNELS - the channels where the gradient has to be computes
%     GRADIENTDIRECTION - the direction of the gradient
%     IND - a recursive paremeter... start with 0 in general
%     ROTIND2 - the gradient has to be computed in respect with this
%     channel
%     IND2COMPUTE - the node ID where the gradient has to be computed

skelTmp = skel.tree(ind2Compute);
parent = skelTmp.parent;
skelParent = skel.tree(parent);
matrix = eye(3);

while (parent~=0)

    skelParent = skel.tree(parent);

rotVal = zeros(1, 3);
    for j = 1:length(skelParent.rotInd)
        rind = skelParent.rotInd(j);
        if rind
            rotVal(j) = channels(rind);
        else
            rotVal(j) = 0;
        end
    end

    tdof = rotationMatrix(deg2rad(rotVal(1)), ...
        deg2rad(rotVal(2)), ...
        deg2rad(rotVal(3)), ...
        skelParent.order);
    torient = rotationMatrix(deg2rad(skelParent.axis(1)), ...
        deg2rad(skelParent.axis(2)), ...
        deg2rad(skelParent.axis(3)), ...
        skelParent.axisOrder);
    torientInv = rotationMatrix(deg2rad(-skelParent.axis(1)), ...
        deg2rad(-skelParent.axis(2)), ...
        deg2rad(-skelParent.axis(3)), ...
        skelParent.axisOrder(end:-1:1));

    matrix = matrix*torientInv*tdof*torient;

    parent = skelParent.parent;

end


function [data,p]=create_data(p)
if nargin==0
    p=struct();
end

gygprrp=load('gygprrp.dat');

p.zss = exp(mean(gygprrp(:,1)));
p.beta = exp(log(p.zss)-mean(gygprrp(:,3)));

start_date='1959Q1';

% per capital GDP growth
gyt = gygprrp(:,1) - log(p.zss);
% Inflation growth
gpt = gygprrp(:,2);
% Real interest rate
rrpt = gygprrp(:,3) - log(p.zss) + log(p.beta);

data=ts(start_date,[gyt,gpt,rrpt],{'GY_HAT','GPAI_HAT','RRPAI_HAT'});
data=pages2struct(data);

end


function [x, R] = orth_at(x, pos, dir, apply)
    %ORTH_AT Orthogonalize single core.
    %   X = ORTH_AT( X, POS, 'LEFT') left-orthogonalizes the core at position POS
    %   and multiplies the corresponding R-factor with core POS+1. All other cores
    %   are untouched. The modified tensor is returned.
    %
    %   X = ORTH_AT( X, POS, 'RIGHT') right-orthogonalizes the core at position POS
    %   and multiplies the corresponding R-factor with core POS-1. All other cores
    %   are untouched. The modified tensor is returned.
    %
    %   See also ORTHOGONALIZE.

    %   TTeMPS Toolbox.
    %   Michael Steinlechner, 2013-2016
    %   Questions and contact: michael.steinlechner@epfl.ch
    %   BSD 2-clause license, see LICENSE.txt

    if ~exist('apply', 'var')
        apply = true;
    end

    sz = size(x.U{pos});

    if length(sz) == 2
        sz = [sz, 1];
    end

    if strcmpi(dir, 'left')
        [Q, R] = qr_unique(unfold(x.U{pos}, 'left'));
        x.U{pos} = reshape(Q, [sz(1), sz(2), size(Q, 2)]);

        if apply
            x.U{pos + 1} = tensorprod_ttemps(x.U{pos + 1}, R, 1);
        end

    elseif strcmpi(dir, 'right')
        % mind the transpose as we want to orthonormalize rows
        [Q, R] = qr_unique(unfold(x.U{pos}, 'right')');
        x.U{pos} = reshape(Q', [size(Q, 2), sz(2), sz(3)]);

        if apply
            x.U{pos - 1} = tensorprod_ttemps(x.U{pos - 1}, R, 3);
        end

    else
        error('Unknown direction specified. Choose either LEFT or RIGHT')
    end

end


% example_nufft1_antenna.m
%
% This m-file is an example of applying the NUFFT method to compute
% the far-field beam pattern of a 2D array of nonuniformly spaced
% (point?) antenna elements.
% In the nomenclature of the 1999 SIAM J Sci. Comput. paper by Nguyen and Liu,
% this is "Problem 1."
%
% This provides an example of how to compute "the Fourier transform"
% of nonuniformly spaced data.
%
% The user should think very carefully about whether it is truly meaningful
% to compute "the FT" of unequally spaced data first.  It certainly is
% meaningful for attenna beam patterns, but may not always be what is really
% useful for all applications with nonuniformly sampled data.
%
% Copyright 2007, Jeff Fessler, University of Michigan

%
% antenna element locations in 2d plane
%
clf, pl = @(p) subplot(220+p);
for choice=1:2
	tmp = [0:40]'/41 * 2 * pi;
	yc = sin(choice*tmp); % funny bowtie pattern for illustration
	xc = cos(tmp); clear tmp
	pl(choice), plot(xc, yc, 'o'), axis square
	xlabel 'x', ylabel 'x', title 'antenna locations'

	% create NUFFT structure
	N = [1 1]*2^8;
	J = [5 5];	% interpolation neighborhood
	K = N*2;	% two-times oversampling
	om = [xc yc];	% 'frequencies' are locations here!

	% the following line probably needs to be changed
	% to get the proper scaling/dimensions in the pattern
	% but for now i just make it fill up [-pi/20,pi/20]
	% in hopes of getting a nice 'picture' of pattern
	om = (pi/20) * om / max(om(:));
	st = nufft_init(om, N, J, K, N/2, 'minmax:kb');

	weights = ones(size(xc)); % equal weights on each element; could change

	% call the *adjoint* NUFFT; this is what does "the FT of unequal data"
	pattern = nufft_adj(weights, st);

	pl(2+choice)
	im(pattern, 'pattern')
end


% [d,xi,yi,thetai] = ellipsedist_hack(xc,yc,a,b,theta,u,v)
% compute distance from points (u,v) to ellipse (xc,yc,a,b,theta)
function [d,xi,yi,thetai] = ellipsedist_hack(xc,yc,a,b,theta,u,v,npoints)

if nargin < 8,
  npoints = 100;
end

[x,y,theta] = ellipsepoints(a,b,xc,yc,theta,npoints);
[d,i] = min(dist2([x(:),y(:)],[u(:),v(:)]),[],1);
d = sqrt(d);
xi = x(i); yi = y(i); thetai = theta(i);
d = reshape(d,size(u));


function [lpp] = tapas_sem_prosa_lpp(theta, ptheta)
%% Log prior probability of the parameters of the prosa model.
%
% Input
%   pv -- Parameters in numerical form.
%   theta -- Parameters of the model
%   ptheta -- Priors of parameters
%
% Output
%   lpp -- Log prior probability
%

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

nconst = ptheta.pconst;

lpp = zeros(1, numel(theta));
for i = 1:numel(theta)
    if isfield(ptheta, 'dkjm')
        err = sum((ptheta.mu - theta{i}) .* ptheta.dkjm .* ...
        (ptheta.mu - theta{i}));
    else
        err = (ptheta.mu - theta{i})' * ptheta.kjm * (ptheta.mu - theta{i});
    end

    alpha = ptheta.mu(ptheta.bdist);
    beta = ptheta.pm(ptheta.bdist);
    lcosh = log(cosh(theta{i}(ptheta.bdist)/2));
    lpp(i) = nconst - 0.5 * err + ...
       ...sum(betaln(alpha, beta) + ...
        sum((alpha - 1) .* (theta{i}(ptheta.bdist)/2 - log(2) - ...
            lcosh) + ...
        (beta - 1) .* (-theta{i}(ptheta.bdist)/2 - log(2) - ...
            lcosh)) - ...
        2 * sum(log(2) + lcosh);
end

end


%%
% \documentclass[12pt]{article}
%
% \title{ODEbox: A Toolbox for Ordinary Differential Equations\\
% Getting Started with the odeSolveIVP Tool}
%
% \author{Matthew Harker and Paul O'Leary\\
% Institute for Automation\\
% University of Leoben\\
% A-8700 Leoben,
% Austria\\
% URL: automation.unileoben.ac.at\\
% \\
% Original: January 9, 2013\\
% $\copyright$ 2013\\
% \\
% Last Modified: \today}
%%
% This is the documentation for the \lstinline{odeSolveIVP.m} file. This is
% a tool for the solution of initial value problems. It offers a very
% simple interface to solving such problems. Two different examples are
% documented here to show the different possible calls to the tool. The
% examples which have been selected are from Kreyszig~\cite{Kreyszig2010}
% and Adams~\cite{Adams}, since this
% give the analytical results enabling a comparison with the numerical
% solutions.
%
%%
% \section{Tidy up the Workspace}
clear all;
close all;
setUpGraphics;
%
%%
% \section{IVP Example 1}
%
% The equation being considered here is:
% %
% \begin{equation}
%   \dddot{y} + 3 \, \ddot{y} + 3 \, \dot{y} + y = 30 \, \mathrm{e}^{-x},
% \end{equation}
% %
% with the initial conditions
% %
% \begin{equation}
%   y(0) = 3,
%   \hspace{2mm}
%   \dot{y}(0) = -3,
%   \hspace{2mm}
%   \text{and}
%   \hspace{2mm}
%   \ddot{y}(0) = -47.
% \end{equation}
% %
% The analytical solution to this equation is,
% %
% \begin{equation}
%   (3 - 25 \, x^2 + 5 \, x^3)  \, \mathrm{e}^{-x}
% \end{equation}
%
% this example is from~\cite[Chapter 2]{Kreyszig2010}.
%%
% \subsection{Define the paramates for $x$.}
%
% Define the minimum, maximum x values and the number of points desired for
% the solution.
%
xMin = 0 ;
xMax = 10 ;
noPts = 73 ;
%%
% Setup the paramater vector
%
params = [xMin, xMax, noPts ];
%%
% \subsection{Call the \lstinline{odeSolveIVP}}
%
% A vector cof constant coefficients are used for this example equation.
%
[y, x, vals] = odeSolveIVP( [1;3;3;1] , '30*exp(-x)', [ 3 ; -3; -47 ] , params, 13);
%%
% Defining a MATLAB inline function for the analytical solution.
%
f = inline('(3 - 25 * x.^2).* exp(-x) + 5 * (x.^3).*exp(-x)') ;
%%
% \subsection{Plot the Results}
%
% The inline analytical solution is computed during plotting.
%
fig1 = figure;
plot( x, f(x), 'k');
hold on;
plot( x, y, 'ro');
grid on;
xlabel('$$x$$');
ylabel('$$y(x)$$');
legend('Analytic','Numerical','Location','SouthEast');
%
%\caption{Comparison of the analytical and the numerical solution for the first example.}
%%
% \section{IVP Example 2}
%
% The equation being considered here is:
% %
% \begin{equation}
%   x^2 \ddot{y} - 3 \, x\, \dot{y} + 13 y = 0,
% \end{equation}
% %
% with the initial conditions
% %
% \begin{equation}
%   y(0) = 5,
%   \hspace{2mm}
%   \text{and}
%   \hspace{2mm}
%   \dot{y}(0) = 0,
% \end{equation}
% %
% The analytical solution to this equation is,
% %
% \begin{equation}
%   5 \, x^2 \, \cos(3 \log(x)) - (10/3) \, x^2 \, \sin(3 \log(x))
% \end{equation}
%
% this example if from~\cite{Adams}.
%%
% \subsection{Define the paramates for $x$.}
%
% Define the minimum, maximum x values and the number of points desired for
% the solution.
%
noPts = 73 ;
xMin = 1 ;
xMax = 5 ;
%%
% Generate the vector of x values for which the equation should be solved.
% We are now artifically generating a nonuniformly spaced set of pointe to
% compute the solution. This is done to demonstrate the possibility of
% working with arbitrary nodes.
%
z = linspace( 0, 1, noPts )';
z = z.^2;
%
x = xMin + z * (xMax - xMin);
%
%%
% \subsection{Call the \lstinline{odeSolveIVP}}
%
% This is an equation with variable coefficients, i.e., the coefficients
% are functions of $x$. the functions are defines as strings which can be
% computed to inline functions. the notation [] is used to indicate that
% its is a homogeneous equation, i.e., the forcing function is identically
% zero. This call is with x as a vector of points where the solution should
% be computed.
%
[y, x, vals] = odeSolveIVP( {'x.^2';'-3*x';'13'} , [], [ 5 ; 0 ] , x, 13);
%%
% The inline for the analytical solution is, this is only needed for
% comparison purposes.
%
f = inline('5*x.^2.*cos(3*log(x)) - (10/3)*x.^2.*sin(3*log(x))') ;
%%
% \subsection{Plot the Results}
fig1 = figure;
plot( x, f(x), 'k');
hold on;
plot( x, y, 'ro');
grid on;
xlabel('$$x$$');
ylabel('$$y(x)$$');
legend('Analytic','Numerical','Location','NorthWest');
%
%\caption{Comparison of the analytical and the numerical solution for the
% second example. Note the non-uniform spacing of the nodes.}
%
%% Define the Bibliography
%
% \bibliographystyle{plain}
% \bibliography{odebib}


% INVWISHIRND - Inverse Wishart Random Matrix
% Copyright (c) 1998, Harvard University. Full copyright in the file Copyright
%
%   [IW] = invwishirnd(S,d)
%
% S = p x p symmetric, postitive definite "scale" matrix
% d = "degrees of freedom" parameter
%   = "precision" parameter
%   (d must be an integer for this routine, see INVWISHRND)
%
% IW = random matrix from the inverse Wishart distribution
%
% Note:
%   different sources use different parameterizations w.r.t. nu
%   this routine uses that of Press and Shigemasu (1989):
%   density(IW) is proportional to
%     exp[-.5*trace(S*inv(IW))] / [det(IW) ^ (d/2)].
%
%   With this density definition:
%   mean(IW) = S/(d-2p-2) when d>2p+2,
%   mode(IW) = S/d.
%
% See also: INVWISHRND, WISHRND

function [IW] = invwishirnd(S,d)
[p,p2] = size(S) ;
W = wishirnd(inv(S),d-p-1) ;
IW = inv(W) ;


function icadat = ica(fmridat_obj, varargin)
% Spatial ICA of an fmri_data object
%   - icadat = ica(fmridat_obj, [number of ICs to save])
%   - icadat is also an fmri_data object, with .dat field voxels x components
%
% :Notes:
%   - icasig = W * mixedsig
%   - icasig = icadat.dat' = W * fmridat_obj.dat'
%
% A is scaled version of fmridat_obj.dat' * icadat.dat
%
% A and W are stored in additional_info field of icadat

nic = 30;
if length(varargin) > 0, nic = varargin{1}; end

neig =  size(fmridat_obj.dat, 2);

[icasig, A, W] = icatb_fastICA(double(fmridat_obj.dat'), 'lastEig', neig, ...
    'numOfIC', nic, 'stabilization', 'on', 'verbose', 'on');

icadat = fmri_data;

icadat.dat = icasig';
icadat.mask = fmridat_obj.mask;
icadat.volInfo = fmridat_obj.volInfo;
icadat.removed_voxels = fmridat_obj.removed_voxels;
icadat.removed_images = 0;

icadat.additional_info{1} = A;
icadat.additional_info{2} = W;
icadat.history{1} = 'Spatial ICA of fmri_data object.';
icadat.history{2} = 'Stored A and W matrices in cells 1,2 of additional_info';
icadat.source_notes = 'fastICA algorithm on images (spatial)';

% Show on orthviews

tmpicadat = icadat;
for i = 1:size(tmpicadat.dat, 2)
    d = tmpicadat.dat(:, i);
    tmpicadat.dat(d < prctile(d, 85) & d > prctile(d, 15), i) = 0;

end

orthviews(tmpicadat);
spm_orthviews_white_background

end

% m1 = prctile(icadat.dat(:), 5);
% m2 = prctile(icadat.dat(:), 95);
%
% spm_orthviews('window', 1:min(24, size(icadat.dat, 2)), [m1 m2]);


function [ CONDXY ] = ConditionalHist( X,Y,varargin)
%[CONDXY] = ConditionalHist(X,Y) Calculates the conditional probabilty
%of Y given X
%
%INPUT
%   X
%   Y
% (options)
%   'numXbins'  (default: 50)
%   'numYbins'  (default: 50)
%   'Xbounds'
%   'Ybounds'
%   'Xbinoverlap' (default: 1)
%   'minX'      (default: 25)
%   'conditionby'   condition on X with different occupancy from datapoints
%
%
%OUTPUT
%   CONDXY
%       .pYX    a [numXbins x numYbins] matrix in which the [x,y]th element is P(y|x)
%       .XYhist joint histogram of X and Y
%       .XYprop joint probability of X and Y
%       .Xhist  histogram of X
%       .Xbins  X bins
%       .Ybins  Y bins
%
%DLevenstein 2019
%%
p = inputParser;
addParameter(p,'numXbins',50)
addParameter(p,'numYbins',50)
addParameter(p,'Xbounds',[])
addParameter(p,'Ybounds',[])
addParameter(p,'minX',25)
addParameter(p,'Xbinoverlap',1)
addParameter(p,'conditionby',[])
parse(p,varargin{:})
numXbins = p.Results.numXbins;
numYbins = p.Results.numYbins;
Xbounds = p.Results.Xbounds;
Ybounds = p.Results.Ybounds;
minX = p.Results.minX;
Xbinoverlap = p.Results.Xbinoverlap;
conditionby = p.Results.conditionby;

%% For cell input

if iscell(Y) && iscell(X)
    CONDXY = cellfun(@(x,y) ConditionalHist(x,y,varargin{:}),...
        X,Y,'UniformOutput',false);
    CONDXY = bz_CollapseStruct([CONDXY{:}],3);
    CONDXY.Xbins = CONDXY.Xbins(1,:,1);
    CONDXY.Ybins = CONDXY.Ybins(1,:,1);
    return
end

%% For multiple columns in X - conditonal probabilty of each

if size(Y,2)>1 && size(X,2)==1
    for yy = 1:size(Y,2)
        CONDXY(yy) = ConditionalHist(X,Y(:,yy),varargin{:});
    end
    CONDXY = bz_CollapseStruct(CONDXY,3);
    return
end

%%
if isempty(Xbounds)
    Xbounds(1) = min(X); Xbounds(2) = max(X);
end
if isempty(Ybounds)
    Ybounds(1) = min(Y(~isinf(Y))); Ybounds(2) = max(Y(~isinf(Y)));
end

Xedges = linspace(Xbounds(1),Xbounds(2),numXbins+1);
Xbins = Xedges(1:end-1)+ 0.5.*diff(Xedges([1 2]));
Xedges(1) = -inf;Xedges(end) = inf;

Yedges = linspace(Ybounds(1),Ybounds(2),numYbins+1);
Ybins = Yedges(1:end-1)+ 0.5.*diff(Yedges([1 2]));
Yedges(1) = -inf;Yedges(end) = inf;

%First calculate the marginal probability of X
[Xhist,~,XbinID] = histcounts(X,Xedges);

%Then calculate the joint probabilty of X and Y
if length(Ybins) ==1
    XYhist = Xhist;
elseif isempty(Y)
    warning('Y is empty... using nans')
    Y = nan(size(X));
    XYhist = nan(length(Xbins),length(Ybins));
else
    [XYhist] = hist3([X,Y],{Xbins,Ybins});
end

% Conditional probability of Y given X
if isempty(conditionby)
    Xhist4norm = Xhist;
else
    Xhist4norm = histcounts(conditionby,Xedges);
end
Xhist4norm(Xhist4norm<=minX) = nan; %Remove bins that don't have enough sampling
pYX = bsxfun(@(x,y) x./y,XYhist,Xhist4norm');

%Mean Y given X
for xx = 1:length(Xbins)
    meanYX(xx) = nanmean(Y(XbinID==xx));
    meanYX(isnan(Xhist4norm)) = nan;
end

CONDXY.pYX = pYX;
CONDXY.XYhist = XYhist;
CONDXY.XYprob = XYhist./nansum(XYhist(:));
CONDXY.meanYX = meanYX;
CONDXY.Xhist = Xhist;
CONDXY.pX = Xhist./nansum(Xhist);
CONDXY.Xbins = Xbins;
CONDXY.Ybins = Ybins;

%%
% figure
% imagesc(CONDXY.Xbins,CONDXY.Ybins,CONDXY.pYX')
% axis xy
end


%  INTERNAL FUNCTION: multikronecker
%
%  ::
%
%    C=kronall(A1,A2,...,An)
%
%  Args:
%
%     - **Ai** [matrix]: input for the kronecker product
%
%  Returns:
%     :
%
%     - **C** [matrix]: kron(A1,kron(A2,kron(A3,...)))
%
%  See also:
%     tensorperm
%
%


% test_itk_tri_rasterization.m

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Cube mesh
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% cube mesh vertices, a bit away from voxel centres to avoid inconsistent
% results (see next section)
x = [
    0.5 -0.1 0
    0.5 -0.1 1.01
    0.5 1.1 0
    0.5 1.1 1.01
    1.505 -0.1 0
    1.505 -0.1 1.01
    1.505 1.1 0
    1.505 1.1 1.01
    ];

% apply alphashape
[~, as] = alphavol(x, 1.3);
tri = as.bnd;
clear as

% plot mesh
hold off
trimesh(tri, x(:,1), x(:,2), x(:,3))
axis([0.5 1.5 0 1 0 1])

% compute parameters of output image
res = [.2 .1 .1]; % r, c, s
origin = [0 -.5 -.5]; % x, y, z
final = [2 1.5 1.5]; % x, y, z
sz = 1 + round((final([2 1 3]) - origin([2 1 3]))./res); % r, c, s

% centers of voxels in the image
cx = linspace(origin(1), final(1), sz(2));
cy = linspace(origin(2), final(2), sz(1));
cz = linspace(origin(3), final(3), sz(3));

% rasterize the mesh
im = itk_tri_rasterization(tri, x, res, sz, origin);

% plot segmentation mask, and overlay mesh
subplot(1, 2, 1)
hold off
imagesc([origin(1) final(1)], [origin(2) final(2)], im(:, :, 6))
hold on
for I = 1:length(cx)
    plot(cx(I)*[1 1], [origin(2) final(2)])
end
for I = 1:length(cy)
    plot([origin(1) final(1)], cy(I)*[1 1])
end
xmin = min(x(:, 1));
xmax = max(x(:, 1));
ymin = min(x(:, 2));
ymax = max(x(:, 2));
plot([xmin xmax xmax xmin xmin], [ymin ymin ymax ymax ymin], 'w')
xlabel('x')
ylabel('y')
axis xy

% plot a vertical cut
subplot(1, 2, 2)
hold off
% imagesc([origin(1) final(1)], [origin(3) final(3)], squeeze(im(:, 11, :)))
imagesc([origin(2) final(2)], [origin(3) final(3)], squeeze(im(:, 11, :))')
hold on
for I = 1:length(cy)
    plot(cy(I)*[1 1], [origin(3) final(3)])
end
for I = 1:length(cz)
    plot([origin(2) final(2)], cz(I)*[1 1])
end
zmin = min(x(:, 3));
zmax = max(x(:, 3));
plot([ymin ymax ymax ymin ymin], [zmin zmin zmax zmax zmin], 'w')
xlabel('y')
ylabel('z')
axis xy

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Note that voxelize offers inconsistent results if the mesh exactly goes
%% through a voxel centre
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% depending on whether the voxel is at the bottom, top, left or right of
% the segmentation, it will be or not set to 1. This can be seen using the
% following set of vertices.

% create a surface mesh that is a cube
x = [
    0.5 0 0
    0.5 0 1
    0.5 1 0
    0.5 1 1
    1.5 0 0
    1.5 0 1
    1.5 1 0
    1.5 1 1
    ];


%
% Generate new exemplars.
%
% Rather than re-sampling from the original log-probability scores,
% take the rank score and sample according to 1/sigma(i)
% where sigma(i) is the rank score from highest to lowest score.
%
% Input
%  G: result of model fitting
%  lib: library
%  nsamp: (default=1) number of samples
%
% Output
%  samples: [nsamp x 1 cell] samples
%  types: [nsamp x 1 cell] samples before token-level is resampled
%
function [samples,types] = task_generate_exemplars_1overk(G,lib,nsamp)

    if ~exist('nsamp','var')
       nsamp = 1;
    end

    % re-score the hypotheses by their rank score instead
    % of the real score
    wts = rescore_by_rank(G.scores);
    G.scores = log(wts);

    [samples,types] = task_generate_exemplars(G,lib,nsamp);
end

%
% Input
%  G: mixture model struct
%  lib: library
%  nsamp: (default=1) number of samples
%
% Output
%  samples: [nsamp x 1 cell] samples
%  types: [nsamp x 1 cell] samples before token-level is resampled
%
function [samples,types] = task_generate_exemplars(G,lib,nsamp)

    if ~exist('nsamp','var')
       nsamp = 1;
    end

    % probability of choosing each parse
    logwts = G.scores;
    wts = exp(logwts-logsumexp(logwts(:)));
    samples = cell(nsamp,1);
    types = cell(nsamp,1);
    for iter = 1:nsamp

        % choose the parse
        [M,kindx] = rand_discrete(G.models,wts);

        % choose the type-level resampling
        Q = rand_discrete(G.samples_type{kindx});
        Q = Q.copy();
        Q.I = M.I;

        % resample at the token-level
        types{iter} = Q;
        Q = generate_exemplar(Q.copy(),lib);
        samples{iter} = Q;
    end

end

%
% Transform a score into 1/sigma(i), where
% sigma(i) is the rank (from highest to lowest)
% of the score.
%
% Input
%  scores: [K x 1] vector of scores where higher is better
%
% Output
%  wts: [K x 1] new scores (not in log space)
%
function wts = rescore_by_rank(scores)

    assert(isvector(scores));
    K = numel(scores);

    [~,rank_indx] = sort(scores(:),1,'descend');

    wts = zeros(K,1);
    for i=1:K
        wts(i) = 1 ./ rank_indx(i);
    end
    logwts = log(wts);
    wts = exp(logwts - logsumexp(logwts(:)));

    % Assure the precise normalization of the weights
    sum_wts = sum(wts);
    assert(aeq(sum_wts,1));
    wts = wts ./ sum(wts);

end


function [output, fs] = eldar_reconstruction(inp_fs, input, time_skew)
    % Reconstruction of a signal from non-uniform samples

    N = length(time_skew); % number of samplers
    fs = inp_fs * N; % full sampling frequency
    T_Q = 1 / fs; % Nyquist sampling period
    T = N * T_Q; % single sampler period

    % index_mapping is used to reorded filters in case the first input
    % signal is actually delayed comparing to the second and not vice versa
    [time_skew, index_mapping] = sort(time_skew);

    H = construct_filters(N, T, time_skew);

    filtered = cell(N, 1);
    for i = 1:N
        % upsampling - according to the interpolation identity
        upsampled_input = upsample(input{index_mapping(i)}, N);
        filtered{i} = filter(H{i}, 1, upsampled_input);
    end

    min_len = min(cellfun('length', filtered));
    filtered_mat = zeros(min_len, N);
    for i=1:N
       filtered_mat(:, i) = filtered{i}(1:min_len);
    end
    output = real(sum(filtered_mat, 2)); % sum filterbank outputs
end

function filter_value = get_filter_value(N, T, a, time_skew, p, t)
    tp = time_skew(p + 1);
    sine_product_elements = ones(N, 1);
    for q = 0:N-1
       if q == p
           continue;
       end

       tq = time_skew(q + 1);
       sine_product_elements(q+1) = sin(pi*(t + tp - tq)/T);
    end
    sine_product = prod(sine_product_elements);
    filter_value = a(p + 1) * sinc((t)/T) * sine_product;
end

function H = construct_filters(N, T, tau)
    a = build_coefficients(N, T, tau);

    TAPS = 48;
    Tq = T/N;
    H = cell(N, 1);
    for p = 0:N-1
        H{p+1} = zeros(TAPS, 1);
        tp = tau(p+1);
        for n = 0:TAPS-1
            t = (n*Tq - tp);
            H{p+1}(n+1) = get_filter_value(N, T, a, tau, p, t);
        end

%         H{p+1}(tp/Tq+1) = 1;
        fvtool(H{p+1});
    end
end

function a = build_coefficients(N, T, tau)
    % compute a coefficients according to Sindhi-Prabhu
    a = ones(N, 1);
    for p = 1:N
        for q = 1:N
            if q ~= p
                a(p) = a(p) / sin(pi*(tau(p) - tau(q)) / T);
            end
        end
    end
end


function [P] = unmixP_NCM(X,E,Sigma,Parameters)
%% Input:
%        X - d-by-N HSI data, matrix
%        E - d-by-M endmember mean set, matrix
%        Sigma - d-by-d-by-M endmember covariance set, matrix
%  Output:
%        P - M-by-N proportion matrix
% Author: Alina Zare et al. Rewriten by Sheng Zou
% Department of Electrical and Computer Engineering, University of Florida
% 09/07/2017

%% Initialization of P
[d,N] = size(X);
M = size(E,2);
P = 1/M.*ones(M,N); % intialize proportion values to be 1/M

%Initialize all Likelihood and Prior Values
LogLikelihoodOld          = ComputeLogLikelihoodAll(X, E, P, Sigma, N);

for iteration = 2:Parameters.NumberIterations+1
    Y = randg(1, N, M) ;
    v = sum(Y,2);
    samples = (Y./repmat(v,[1,size(Y,2)]))';
    LogLikelihoodNew      = ComputeLogLikelihoodAll(X, E, samples, Sigma, N);
    Ratios                = exp(LogLikelihoodNew - LogLikelihoodOld);
    rands                 = rand(1,N);
    Vals                  = rands < Ratios;
    Vrep                  = repmat(Vals,M,1);
    P                     = samples.*Vrep  + P.*(1-Vrep);

    LogLikelihoodOld = (1-Vals).*LogLikelihoodOld + (Vals).*LogLikelihoodNew;
    if mod(iteration, round(Parameters.NumberIterations/10)) == 0
        disp(strcat('iteration = ',num2str(iteration)));
        disp(strcat('loglikelihood = ',num2str(sum(LogLikelihoodOld))));
    end
end

end

function [LogLikelihoodAll] = ComputeLogLikelihoodAll(X, E, P, cov, N)
% compute log likelihood of all points

term1 = zeros(1,N);
term2 = zeros(1,N);

for s = 1:size(E,2)
    statement(s)=isdiag(squeeze(cov(:,:,s))) && length(unique(diag(cov(:,:,s))))==1; % check if all the covariance matrices are diagonal and isotropic
end

if mean(statement) ==1 % all diagonal and isotropic
    for z = 1:size(P,1)
        a(z) = unique(diag(cov(:,:,z)));
    end
    term1 = -.5*size(X,1)*log(a*(P.^2));
    term2 = -.5*(sum((X-E*P).^2)./(a*(P.^2)));
else

    parfor t = 1:N
        P3D = zeros(1,1,size(E,2));
        P3D(:,:,1:size(E,2)) = P(:,t).^2;
        P3D_full = repmat(P3D,size(X,1),size(X,1));
        term1(t) = -.5*logdet(sum(P3D_full.*cov,3));
        term2(t) = -.5*(X(:,t)-E*P(:,t))'*(sum(P3D_full.*cov,3)\(X(:,t)-E*P(:,t)));
    end

end

LogLikelihoodAll = term1 + term2;
end


function [out] = interception_5(p1,p2,In)
%interception_5

% Copyright (C) 2019, 2021 Wouter J.M. Knoben, Luca Trotter
% This file is part of the Modular Assessment of Rainfall-Runoff Models
% Toolbox (MARRMoT).
% MARRMoT is a free software (GNU GPL v3) and distributed WITHOUT ANY
% WARRANTY. See <https://www.gnu.org/licenses/> for details.

% Flux function
% ------------------
% Description:  Interception excess after a combined absolute amount and fraction are intercepted
% Constraints:  f >= 0
% @(Inputs):    p1   - fraction that is not throughfall [-]
%               p2   - constnat interception and evaporation [mm/d]
%               In   - incoming flux [mm/d]

out = max(p1.*In-p2,0);

end


pairs = [0.1 2.2527126517342059598697; ...
			0.6 .39823385806923489961685; ...
			0.7 .26086724653166651438573; ...
			1.0 0; ...
			2.0 0; ...
			3.4 1.0923280598027415674947; ...
			4.0 1.791759469228055000812477; ...
			8.0 8.525161361065414300165531; ...
			64.0 201.00931639928152667928; ...
			256.0 1161.71210111840065079];
err = [];
for i = 1:rows(pairs)
	err(i) = abs(gammaln(pairs(i,1)) - pairs(i,2))/pairs(i,1);
end
if max(err) > 1e-10
	err
	error('maximum err > 1e-10')
end
err = [];
for i = 1:rows(pairs)
	err(i) = abs(gammaln(pairs(i,1),1) - pairs(i,2))/pairs(i,1);
end
if max(err) > 1e-10
	err
	error('maximum err > 1e-10')
end
err = abs(gammaln(1.1,2) - 0.920726359734123);
if err > 1e-10
	error('gammaln(1.1,2) != 0.920726359734123');
end
if gammaln(0) ~= Inf
  error('gammaln(0) should be Inf');
end
if ~isnan(gammaln(-1))
  %error('gammaln(-1) should be NaN');
end
if gammaln(Inf) ~= Inf
  error('gammaln(Inf) should be Inf');
end
% should be NaN?
%gammaln(-Inf)
if ~isnan(gammaln(NaN))
  error('gammaln(NaN) should be NaN');
end


function y = ArbitraryOctaveFilt(x, SPECT, FREQS, N, fs, octBandwidth)
% Filters a signal with any arbitrary spectrum smoothed with any fractional octave band average
%
% Syntax:	Y = ARBITRARYOCTAVEFILT(X, SPECT, FREQS, N, FS, OCTBANDWIDTH)
%
% Inputs:
% 	x - Input signal to filter as a vector
% 	SPECT - The spectrum to shape the input signal to
% 	FREQS - The frequencies of each SPECT element
% 	N - The length of the filter to usee
% 	fs - Description
% 	octBandwidth - Description
%
% Outputs:
% 	y - Description
%
% Example:
%   fs = 16000;
%   T = 10;
%   N = 1000;
%   f = linspace(0,fs/2,N);
%   s = 1./f;
%   x = wgn(T*fs,1,0);
%   y = ArbitraryOctaveFilt(x,s,f,N,fs,1/3);
%   pwelch([x y]);
%
% See also: fir2, filter

% Author: Jacob Donley
% University of Wollongong
% Email: jrd089@uowmail.edu.au
% Copyright: Jacob Donley 2017
% Date: 06 June 2016
% Revision: 0.1
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin < 6
    octBandwidth = 1/6;
end

% Find nth-octave averages
[MAG,f]=Tools.octaveBandMean(SPECT,FREQS,octBandwidth);

% Force even length filter
if isempty(N), if mod(length(SPECT),2), N=length(SPECT)-1; else N=length(SPECT); end; end
% Design arbitrary magnitude (linear-phase) filter
b = fir2(N,f/(fs/2),MAG);
% Apply filter
y = filter(b,1,x);

end


% Test file for unbndfun/compose.m

function pass = test_compose(pref)

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

% Set the domain:
dom = [0 Inf];
domCheck = [0 1e2];

% Generate a few random points to use as test values:
x = diff(domCheck) * rand(100, 1) + domCheck(1);

%%%%%%%%%%%%%%%% Compose an UNBNDFUN with an operator (OP(F)) %%%%%%%%%%%%%%%%%%

opf = @(x) exp(-x);
opg = @(x) sin(exp(-x));
f = unbndfun(opf, struct('domain', dom));
g = compose(f, @sin);
gVals = feval(g, x);
gExact = opg(x);
err = gVals - gExact;
pass(1) = norm(err, inf) < 1e1*eps*get(g,'vscale');

%%%%%%%%%%%%%%%%%%% Compose two UNBNDFUNs (F + G) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

opf = @(x) exp(-x);
opg = @(x) x.*exp(-x);
oph = @(x) (x+1).*exp(-x);
f = unbndfun(opf, struct('domain', dom));
g = unbndfun(opg, struct('domain', dom));
h = compose(f, @plus, g);
hVals = feval(h, x);
hExact = oph(x);
err = hVals - hExact;
pass(2) = norm(err, inf) < 1e1*eps*get(h,'vscale');

%%%%%%%%%%%%%%%%%%% Compose an UNBNDFUN with a BNDFUN (G(F)) %%%%%%%%%%%%%%%%%%%

opf = @(x) exp(-x);
opg = @(x) cos(x);
oph = @(x) cos(exp(-x));
f = unbndfun(opf, struct('domain', dom));
g = bndfun(opg, struct('domain', [-1 1]));
h = compose(f, g);
hVals = feval(h, x);
hExact = oph(x);
err = hVals - hExact;
pass(3) = norm(err, inf) < 1e1*eps*get(h,'vscale');

end


% STE_SWLP Stabilized weighted linear prediction using short-time-energy
% weighting
%   [A,w] = ste_swlp(s,p,m,k)
%
% Description
%   This function fits linear prediction coefficients to the analysis
%   frame using the basic form of stabilized weighted linear prediction
%   (SWLP) that weights each value of the squared prediction error by the
%   short-time energy (STE) of the previous samples.
%
% Inputs
%   s      : Speech signal frame [samples]
%   p      : Order of SWLP analysis
%   m      : Length of the STE window (default to p)
%   k      : Delay of the STE window (default to 1)
%
% Outputs
%   A      : Linear prediction inverse filter coefficients
%   w      : the STE weighting function
%
% Notes
%   SWLP generally gives smoother spectral shapes than the corresponding
%   weighted linear prediction (WLP) using the same weighting function.
%
% Example
%   A = ste_swlp(s,p) gives the linear predictive inverse filter
%   coefficients optimized using STE-SWLP
%
% References
%  [1] C. Magi, J. Pohjalainen, T. Bäckström and P. Alku, "Stabilised
%  weighted linear prediction", Speech Communication, vol. 51, no. 5, pp.
%  401411, 2009.
%  [2] J. Pohjalainen, H. Kallasjoki, K. J. Palomäki, M. Kurimo and P.
%  Alku, "Weighted linear prediction for speech analysis in noisy
%  conditions", in Proc. Interspeech, Brighton, UK, pp. 1315-1318,
%  2009.
%
% Copyright (c) 2013 Aalto University
%
% License
%  This file is under the LGPL license,  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. This file 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.
%
% This function is part of the Common Speech Processing Repository
% http://covarep.github.io/covarep/
%
% Octave Compatible
%
% Author
%  Jouni Pohjalainen jouni.pohjalainen@aalto.fi
%
% $Id <info set by the versioning system> $

function [A,w] = ste_swlp(s,p,m,k)

% handle the special case of all-zero frames
if all(s==0)
  s = eps*randn(size(s));
end

N = length(s);

% default value for the STE window length
if nargin<3
    m = p;
end

% default value for the STE window lag
if nargin<4
    k = 1;
end

% compute STE weighting function
w = stew(s,m,p,k)+eps;

w = w(1:(N+p));

% initialize partial weights for recursive computation (see [2], Eqs.
% (5)-(7), for the partial-weight formulation of SWLP)
Z = zeros(N+p,p+1);
Z(:,1) = sqrt(w);

% delayed and weighted versions of the signal
Y = zeros(N+p,p+1);
Y(:,1) = Z(:,1).*[s;zeros(p,1)];

% recursion for partial weights and weighting of differently lagged
% versions of the signal
for i1=1:p
    Z((i1+1):(N+p),i1+1) = max([ones(N+p-i1,1) sqrt(w((i1+1):(N+p))./w(i1:(N+p-1)))],[],2) .* Z(i1:(N+p-1),i1);
    Y(:,i1+1) = Z(:,i1+1) .* [zeros(i1,1);s;zeros(p-i1,1)];
end

% compute weighted autocorrelations
R = (Y'*Y)/N;

% solve the p predictor coefficients
A = R(2:end,2:end)\R(2:end,1);

% convert to inverse filter form
A = [1;-A]';

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

function w = stew(x,m,p,k)
% STE weighting for an order p predictor using window of length m delayed
% by k samples
w = conv([zeros(k,1);x(:)].^2,ones(m,1));
w = [w;zeros(p-m,1)];


function yval = dif_val ( ntab, xtab, diftab, xval )

%*****************************************************************************80
%
%% DIF_VAL evaluates a divided difference polynomial at a point.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carl de Boor,
%    A Practical Guide to Splines,
%    Springer Verlag, 1978.
%
%  Parameters:
%
%    Input, integer NTAB, the number of divided difference
%    coefficients in DIFTAB, and the number of points XTAB.
%
%    Input, real XTAB(NTAB), the X values upon which the
%    divided difference polynomial is based.
%
%    Input, real DIFTAB(NTAB), the divided difference
%    polynomial coefficients.
%
%    Input, real XVAL, the value where the polynomial
%    is to be evaluated.
%
%    Output, real YVAL, the value of the polynomial at XVAL.
%
  yval = diftab(ntab);
  for i = 1 : ntab-1
    yval = diftab(ntab-i) + ( xval - xtab(ntab-i) ) * yval;
  end

  return
end


function sparse_grid_laguerre_test ( )

%*****************************************************************************80
%
%% SPARSE_GRID_LAGUERRE_TEST tests the SPARSE_GRID_LAGUERRE library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 December 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Fabio Nobile, Raul Tempone, Clayton Webster,
%    A Sparse Grid Stochastic Collocation Method for Partial Differential
%    Equations with Random Input Data,
%    SIAM Journal on Numerical Analysis,
%    Volume 46, Number 5, 2008, pages 2309-2345.
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SPARSE_GRID_LAGUERRE_TEST\n' );
  fprintf ( 1, '  MATLAB version.\n' );
  fprintf ( 1, '  Test the SPARSE_GRID_LAGUERRE library.\n' );
%
%  Count number of points in sparse rule from DIM_MIN to DIM_MAX, LEVEL_MAX_MAX.
%
  dim_min = 1;
  dim_max = 5;
  level_max_min = 0;
  level_max_max = 10;

  sparse_grid_laguerre_test01 ( dim_min, dim_max, level_max_min, level_max_max );

  dim_min = 6;
  dim_max = 10;
  level_max_min = 0;
  level_max_max = 10;

  sparse_grid_laguerre_test01 ( dim_min, dim_max, level_max_min, level_max_max );

  dim_min = 100;
  dim_max = 100;
  level_max_min = 0;
  level_max_max = 2;

  sparse_grid_laguerre_test01 ( dim_min, dim_max, level_max_min, level_max_max );
%
%  Compute abstract grid indices of sparse grid points as selected from product grid
%  for DIMENSION, LEVEL_MAX.
%
  dim_num = 2;
  level_max = 3;
  sparse_grid_laguerre_test02 ( dim_num, level_max );

  dim_num = 2;
  level_max = 4;
  sparse_grid_laguerre_test02 ( dim_num, level_max );

  dim_num = 3;
  level_max = 0;
  sparse_grid_laguerre_test02 ( dim_num, level_max );

  dim_num = 3;
  level_max = 2;
  sparse_grid_laguerre_test02 ( dim_num, level_max );

  dim_num = 6;
  level_max = 2;
  sparse_grid_laguerre_test02 ( dim_num, level_max );
%
%  Compute sparse rule for DIMENSION, LEVEL_MAX.
%
  dim_num = 2;
  level_max = 0;
  sparse_grid_laguerre_test03 ( dim_num, level_max );

  dim_num = 2;
  level_max = 3;
  sparse_grid_laguerre_test03 ( dim_num, level_max );

  dim_num = 2;
  level_max = 4;
  sparse_grid_laguerre_test03 ( dim_num, level_max );

  dim_num = 3;
  level_max = 0;
  sparse_grid_laguerre_test03 ( dim_num, level_max );

  dim_num = 3;
  level_max = 2;
  sparse_grid_laguerre_test03 ( dim_num, level_max );
%
%  Test sum of weights for DIMENSION, LEVEL_MAX.
%
  dim_num = 2;
  level_max = 4;
  sparse_grid_laguerre_test04 ( dim_num, level_max );

  dim_num = 3;
  level_max = 0;
  sparse_grid_laguerre_test04 ( dim_num, level_max );

  dim_num = 3;
  level_max = 1;
  sparse_grid_laguerre_test04 ( dim_num, level_max );

  dim_num = 3;
  level_max = 6;
  sparse_grid_laguerre_test04 ( dim_num, level_max );

  dim_num = 10;
  level_max = 3;
  sparse_grid_laguerre_test04 ( dim_num, level_max );
%
%  Test monomial exactness for DIMENSION, LEVEL_MAX, DEGREE_MAX.
%
  dim_num = 2;
  level_max = 0;
  degree_max = 3;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 2;
  level_max = 1;
  degree_max = 5;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 2;
  level_max = 2;
  degree_max = 7;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 2;
  level_max = 3;
  degree_max = 9;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 2;
  level_max = 4;
  degree_max = 11;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 2;
  level_max = 5;
  degree_max = 13;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 3;
  level_max = 0;
  degree_max = 2;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 3;
  level_max = 1;
  degree_max = 4;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 3;
  level_max = 2;
  degree_max = 6;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );

  dim_num = 3;
  level_max = 3;
  degree_max = 8;
  sparse_grid_laguerre_test05 ( dim_num, level_max, degree_max );
%
%  Show how to write a rule to a file.
%
  dim_num = 2;
  level_max = 3;

  sparse_grid_laguerre_test06 ( dim_num, level_max );
%
%  All done.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SPARSE_GRID_LAGUERRE_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function coef=framecoef2tf(F,coef)
%FRAMECOEF2TF  Convert coefficients to time-frequency plane
%   Usage: cout=framecoef2tf(F,cin);
%
%   `framecoef2tf(F,cin)` converts the frame coefficients *cin* into the
%   time-frequency plane layout. The frame object *F* must have been
%   created using |frame|.
%
%   The time-frequency plane layout is a matrix, where the first
%   dimension indexes frequency and the second dimension time. This is
%   similar to the output format from |dgt| and |wmdct|.
%
%   Not all types of frames support this coefficient conversion. The supported
%   types of frames are: `'dgt'`, `'dgtreal'`, `'dwilt'`, `'wmdct'`, `'ufilterbank'`,
%   `'ufwt'`,`'uwfbt'` and `'uwpfbt'`.
%
%   See also: frame, frametf2coef, framecoef2native

complainif_notenoughargs(nargin,2,'FRAMECOEF2TF');
complainif_notvalidframeobj(F,'FRAMECOEF2TF');

switch(F.type)
 case 'dgt'
  [MN,W]=size(coef);
  N=MN/F.M;
  coef=reshape(coef,[F.M,N,W]);
 case 'dgtreal'
  [MN,W]=size(coef);
  M2=floor(F.M/2)+1;
  N=MN/M2;
  coef=reshape(coef,[M2,N,W]);
 case 'dwilt'
  [MN,W]=size(coef);
  N=MN/F.M;
  coef=wil2rect(reshape(coef,[2*F.M,N/2,W]));
 case 'wmdct'
  [MN,W]=size(coef);
  N=MN/F.M;
  coef=reshape(coef,[F.M,N,W]);
 case 'ufilterbank'
  [MN,W]=size(coef);
  M=numel(F.g);
  N=MN/M;
  coef=permute(reshape(coef,[N,M,W]),[2,1,3]);
 case {'ufwt','uwfbt','uwpfbt'}
  coef = permute(F.coef2native(coef,size(coef)),[2,1,3]);
 otherwise
  error('%s: TF-plane layout not supported for this transform.',upper(mfilename));
end;


%
% Implementation of Exposure Fusion
%
% written by Tom Mertens, Hasselt University, August 2007
% e-mail: tom.mertens@gmail.com
%
% This work is described in
%   "Exposure Fusion"
%   Tom Mertens, Jan Kautz and Frank Van Reeth
%   In Proceedings of Pacific Graphics 2007
%
%
% Usage:
%   result = exposure_fusion(I,m);
%   Arguments:
%     'I': represents a stack of N color images (at double
%       precision). Dimensions are (height x width x 3 x N).
%     'm': 3-tuple that controls the per-pixel measures. The elements
%     control contrast, saturation and well-exposedness, respectively.
%
% Example:
%   'figure; imshow(exposure_fusion(I, [0 0 1]);'
%   This displays the fusion of the images in 'I' using only the well-exposedness
%   measure
%

function [R, W]= exposure_fusion(I,m)

r = size(I,1);
c = size(I,2);
N = size(I,4);

W = ones(r,c,N);

%compute the measures and combines them into a weight map
contrast_parm = m(1);
sat_parm = m(2);
wexp_parm = m(3);

if (contrast_parm > 0)
    W = W.*contrast(I).^contrast_parm;
end
if (sat_parm > 0)
    W = W.*saturation(I).^sat_parm;
end
if (wexp_parm > 0)
    W = W.*well_exposedness(I).^wexp_parm;
end

%normalize weights: make sure that weights sum to one for each pixel
W = W + 1e-12; %avoids division by zero
W = W./repmat(sum(W,3),[1 1 N]);

% create empty pyramid
pyr = gaussian_pyramid_(zeros(r,c,3));
nlev = length(pyr);

% multiresolution blending
for i = 1:N
    % construct pyramid from each input image
	pyrW = gaussian_pyramid_(W(:,:,i));
	pyrI = laplacian_pyramid_(I(:,:,:,i));

    % blend
    for l = 1:nlev
        w = repmat(pyrW{l},[1 1 3]);
        pyr{l} = pyr{l} + w.*pyrI{l};
    end
end

% reconstruct
R = reconstruct_laplacian_pyramid_(pyr);

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

% contrast measure
function C = contrast(I)
h = [0 1 0; 1 -4 1; 0 1 0]; % laplacian filter
N = size(I,4);
C = zeros(size(I,1),size(I,2),N);
for i = 1:N
    mono = rgb2gray(I(:,:,:,i));
    C(:,:,i) = abs(imfilter(mono,h,'replicate'));
end

% saturation measure
function C = saturation(I)
N = size(I,4);
C = zeros(size(I,1),size(I,2),N);
for i = 1:N
    % saturation is computed as the standard deviation of the color channels
    R = I(:,:,1,i);
    G = I(:,:,2,i);
    B = I(:,:,3,i);
    mu = (R + G + B)/3;
    C(:,:,i) = sqrt(((R - mu).^2 + (G - mu).^2 + (B - mu).^2)/3);
end

% well-exposedness measure
function C = well_exposedness(I)
sig = .2;
N = size(I,4);
C = zeros(size(I,1),size(I,2),N);
for i = 1:N
    R = exp(-.5*(I(:,:,1,i) - .5).^2/sig.^2);
    G = exp(-.5*(I(:,:,2,i) - .5).^2/sig.^2);
    B = exp(-.5*(I(:,:,3,i) - .5).^2/sig.^2);
    C(:,:,i) = R.*G.*B;
end


function [quantized] = quantizeContinuous(values, min_v, max_v, num_bins)

    step_size = (max_v - min_v) / num_bins;
    bin_centres = min_v + step_size/2 : step_size : max_v;

    bin_centres = repmat(bin_centres, numel(values),1);
    values = repmat(values, 1, num_bins);

    [~,quantized] = min(abs(values - bin_centres)');
    quantized = quantized';
end


function [eigVec, eigVal] = dtiSplitTensor(tensor)
% Derive eigenvector and eigenvalues from the volume of tensor data
%
% [eigVec, eigVal] = dtiSplitTensor(tensor)
%
% The input tensor array is in XxYxZx6xN format
% The order of the value in the 4th dimension is [Dxx, Dyy, Dzz, Dxy, Dxz, Dyz])
%
% The routine returns a XxYxZx3x3xN volume of eigVec
% and                 a the XxYxZx3xN volume of eigVal arrays
%
% X,Y,Z are positions in the volume
% N is the number of subjects.
%
% SEE ALSO: dtiRebuildTensor
%
% HISTORY:
% 2003.12.08 ASH (armins@stanford.edu) Wrote it.
% 2004.02.03 DTM (merget@cs.stanford.edu) Sort eigVal from high to low
% 2004.02.17 ASH: added extra dimension for subjects
% 2005.01.06 ASH: truly added extra dimension for subjects
%
% The code is implemented in the mex file dtiSplitTensor.c. If you don't
% have a that file compiled for you system, then the (very slow) code below
% will be executed.  In one test, the following code ran in 2.85 minutes,
% and the compiled version ran in about 11 seconds.
%
% (c) Stanford VISTA Team 2003

disp('This function is mexified for speed- compile dtiSplitTensor.c.');

sz = size(tensor);
if (length(sz)<5),
    sz =[sz, 1];
end

% vec = zeros([sz(1:3), 3, 3, sz(5)]);
% val = zeros([sz(1:3), 3, sz(5)]);

h = mrvWaitbar(0, 'Computing tensors...');
for(x=1:sz(1))
    for(y=1:sz(2))
        for(z=1:sz(3))
            for(j=1:sz(5))
                D = [tensor(x, y, z, 1, j), tensor(x, y, z, 4, j), tensor(x, y, z, 5, j);
                     tensor(x, y, z, 4, j), tensor(x, y, z, 2, j), tensor(x, y, z, 6, j);
                     tensor(x, y, z, 5, j), tensor(x, y, z, 6, j), tensor(x, y, z, 3, j)];
                [vec, val] = eig(D);
                [val2, order] = sort(-diag(val));
                eigVec(x, y, z, :, :, j) = vec(:, order);
                eigVal(x, y, z, :, j) = -val2;
            end
        end
    end
    mrvWaitbar(x/sz(1),h);
end
close(h);

return;


function [v] = var(x, normalizeflag, dim, flag)

% [V] = VAR(X, NORMALIZEFLAG, DIM, FLAG) computes the variance,
% across all cells in x along the dimension dim. Normalizeflag = 1 normalizes
% by N, normalizeflag = [] or 0 normalizes by N-1.
%
% X should be an linear cell-array of matrices for which the size in at
% least one of the dimensions should be the same for all cells. If flag==1, the mean will
% be subtracted first (default behavior, but to save time on already demeaned data, it
% can be set to 0).

if nargin<2 || isempty(normalizeflag)
  normalizeflag = 0;
end

D = checkinput(x);
if nargin<3 || isempty(dim),
  dim = find(D,1,'last');
else
  % check whether the requested dim can be used
  if ~D(dim), error('data can not be concatenated across dimension %d',dim); end
end

if nargin<4,
  flag = 1;
end

if flag,
  m    = mean(x, dim);
  x    = cellvecadd(x, -m);
end

nx   = max(size(x));
nsmp = size2(x, dim, 'cell');
ssmp = cellfun(@sumsq,   x, repmat({dim},1,nx), 'UniformOutput', 0);

if normalizeflag
  N = sum(nsmp);
else
  N = sum(nsmp)-1;
end

v = sum(cell2mat(ssmp), dim)./N;

function [s] = sumsq(x, dim)

s = sum(x.^2, dim);


function T = build_toep( c, k, n )
%
%  T = build_toep( c, k, n );
%
%  Given:
%    c - the nonzero part of a central column of a banded Toeplitz
%        matrix
%    k - index of c containing the diagonal element of T
%    n - dimension of the banded Toeplitz matrix
%
%  The banded Toeplitz matrix is constructed explicitly.
%

%  J. Nagy  2/11/02

m = length( c );

col = zeros(n,1);
row = col';
col(1:m-k+1,1) = c(k:m);
row(1,1:k) = c(k:-1:1)';
T = toeplitz( col, row );


% findcircle - returns the coordinates of a circle in an image using the Hough transform
% and Canny edge detection to create the edge map.
%
% Usage:
% [row, col, r] = findcircle(image,lradius,uradius,scaling, sigma, hithres, lowthres, vert, horz)
%
% Arguments:
%	image		    - the image in which to find circles
%	lradius		    - lower radius to search for
%	uradius		    - upper radius to search for
%	scaling		    - scaling factor for speeding up the
%			          Hough transform
%	sigma		    - amount of Gaussian smoothing to
%			          apply for creating edge map.
%	hithres		    - threshold for creating edge map
%	lowthres	    - threshold for connected edges
%	vert		    - vertical edge contribution (0-1)
%	horz		    - horizontal edge contribution (0-1)
%
% Output:
%	circleiris	    - centre coordinates and radius
%			          of the detected iris boundary
%	circlepupil	    - centre coordinates and radius
%			          of the detected pupil boundary
%	imagewithnoise	- original eye image, but with
%			          location of noise marked with
%			          NaN values
%
% Author:
% Libor Masek
% masekl01@csse.uwa.edu.au
% School of Computer Science & Software Engineering
% The University of Western Australia
% November 2003

function [row, col, r] = findcircle(image,lradius,uradius,scaling, sigma, hithres, lowthres, vert, horz)

lradsc = round(lradius*scaling);
uradsc = round(uradius*scaling);
rd = round(uradius*scaling - lradius*scaling);

% generate the edge image
[I2 or] = canny(image, sigma, scaling, vert, horz);
I3 = adjgamma(I2, 1.9);
I4 = nonmaxsup(I3, or, 1.5);
edgeimage = hysthresh(I4, hithres, lowthres);

% perform the circular Hough transform
h = houghcircle(edgeimage, lradsc, uradsc);

maxtotal = 0;

% find the maximum in the Hough space, and hence
% the parameters of the circle
for i=1:rd

    layer = h(:,:,i);
    [maxlayer] = max(max(layer));

    if maxlayer > maxtotal

        maxtotal = maxlayer;

        r = int32((lradsc+i) / scaling);

        [row,col] = ( find(layer == maxlayer) );

        row = int32(row(1) / scaling); % returns only first max value
        col = int32(col(1) / scaling);

    end

end


% Test file for bndfun/innerProduct.m

function pass = test_innerProduct(pref)

% Get preferences.
if ( nargin < 1 )
    pref = chebfunpref();
end

% Set a tolerance.  (pref.chebfuneps doesn't matter here.)
tol = 10*eps;

% Set a domain
dom = [-2 7];

% Fixed arbitrary numbers to use as multiplicative constants.
alpha = -0.194758928283640 + 0.075474485412665i;
beta = -0.526634844879922 - 0.685484380523668i;

%%
% Spot-check a few known results.

f = bndfun(@(x) sin(2*pi*x), struct('domain', dom), pref);
g = bndfun(@(x) cos(2*pi*x), struct('domain', dom), pref);
pass(1) = abs(innerProduct(f, g)) < ...
    10*eps;

g = bndfun(@(x) cos(4*pi*x), struct('domain', dom), pref);
pass(2) = abs(innerProduct(f, g)) < ...
    10*eps;

f = bndfun(@(x) exp(x), struct('domain', dom), pref);
g = bndfun(@(x) exp(-x), struct('domain', dom), pref);
pass(3) = abs(innerProduct(f, g) - 9) < 1e2*max(get(f, 'vscale'), ...
    get(g, 'vscale'))*eps;

g = bndfun(@(x) sin(x), struct('domain', dom), pref);
exact = exp(7)*(sin(7) - cos(7))/2 - exp(-2)*(sin(-2) - cos(-2))/2;
pass(4) = abs(innerProduct(f, g) - exact) < max(get(f, 'vscale'), ...
    get(g, 'vscale'))*10*eps;

%%
% Check a few known properties.

f = bndfun(@(x) exp(1i*x) - 1, struct('domain', dom), pref);
g = bndfun(@(x) 1./(1 + 1i*x.^2), struct('domain', dom), pref);
h = bndfun(@(x) sinh(x*exp(pi*1i/6)), struct('domain', dom), pref);

ip1 = innerProduct(alpha*f, beta*g);
ip2 = conj(alpha)*beta*innerProduct(f, g);
pass(5) = abs(ip1 - ip2) < 10*tol;

ip1 = innerProduct(g, h);
ip2 = innerProduct(h, g);
pass(6) = abs(ip1 - conj(ip2)) < tol;

ip1 = innerProduct(f + g, h);
ip2 = innerProduct(f, h) + innerProduct(g, h);
pass(7) = abs(ip1 - ip2) < ...
    max((get(f, 'vscale') + get(g, 'vscale')), get(h, 'vscale'))*tol;

ip1 = innerProduct(f, g + h);
ip2 = innerProduct(f, g) + innerProduct(f, h);
pass(8) = abs(ip1 - ip2) < ...
    max((get(g, 'vscale') + get(h, 'vscale')), get(f, 'vscale'))*tol;

nf2 = innerProduct(f, f);
ng2 = innerProduct(g, g);
nh2 = innerProduct(h, h);
n2vals = [nf2 ; ng2 ; nh2];
pass(9) = isreal(n2vals) && all(n2vals >= 0);

%%
% Check operation for array-valued bndfun objects.

f = bndfun(@(x) [sin(x) cos(x)], struct('domain', dom), pref);
g = bndfun(@(x) [exp(x) 1./(1 + x.^2) airy(x)], struct('domain', dom), pref);
ip = innerProduct(f, g);
exact = [-53.1070904269318222 0.0025548835039100  -0.4683303433821355;
         773.70343924989359096771 1.3148120368924471 0.6450791915572742];
pass(10) = norm(ip(:) - exact(:), inf) < 10*max([eps, ...
    eps])*max([get(f, 'vscale') get(g, 'vscale')]);

%%
% Check error conditition
% Can't take the inner product of a bndfun and a non-bndfun.
try
    ip = innerProduct(f, 2); %#ok<NASGU>
    pass(11) = false;
catch ME
    pass(11) = strcmp(ME.identifier, ...
        'CHEBFUN:BNDFUN:innerProduct:input');
end

%% Test on singular function:

pow1 = -0.3;
pow2 = -0.5;
op1 = @(x) (x - dom(2)).^pow1.*sin(x);
op2 = @(x) (x - dom(2)).^pow2.*cos(3*x);
pref.blowup = true;
data.domain = dom;
data.exponents = [0 pow1];
f = bndfun(op1, data, pref);
data.domain = dom;
data.exponents = [0 pow2];
g = bndfun(op2, data, pref);
I = innerProduct(f,g);
I_exact = -0.65182492763883119+0.47357853074362785i;
err = abs(I - I_exact);
tol = 5e2*eps*abs(I_exact);
pass(12) = err < tol;

end


function af = naca5gen(iaf)
%
% "naca5gen" Generates the NACA 5 digit airfoil coordinates with desired no.
% of panels (line elements) on it.
%      Author : Divahar Jayaraman (j.divahar@yahoo.com)
%
% INPUTS-------------------------------------------------------------------
%       iaf.designation = NACA 5 digit designation (eg. '23012') - STRING !
%                 iaf.n = no of panels (line elements) PER SIDE (upper/lower)
% iaf.HalfCosineSpacing = 1 for "half cosine x-spacing"
%                       = 0 to give "uniform x-spacing"
%          iaf.wantFile = 1 for creating airfoil data file (eg. 'naca2412.dat')
%                       = 0 to suppress writing into a file
%       iaf.datFilePath = Path where the data  file has to be created
%                         (eg. 'af_data_folder/naca5digitAF/')
%                         use only forward slash '/' (Just for OS portability)
%
% OUTPUTS------------------------------------------------------------------
% Data:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
%       af.x = x cordinate (nx1 array)
%       af.z = z cordinate (nx1 array)
%      af.xU = x cordinate of upper surface (nx1 array)
%      af.zU = z cordinate of upper surface (nx1 array)
%      af.xL = x cordinate of lower surface (nx1 array)
%      af.zL = z cordinate of lower surface (nx1 array)
%      af.xC = x cordinate of camber line (nx1 array)
%      af.zC = z cordinate of camber line (nx1 array)
%    af.name = Name of the airfoil
%  af.header = Airfoil name ; No of panels ; Type of spacing
%              (eg. 'NACA23012 : [50 panels,Uniform x-spacing]')
%
%
% File:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
% First line : Header eg. 'NACA23012 : [50 panels,Half cosine x-spacing]'
% Subsequent lines : (2*iaf.n+1) rows of x and z values
%
% Typical Inputs:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
% iaf.designation='23012';
% iaf.n=56;
% iaf.HalfCosineSpacing=1;
% iaf.wantFile=1;
% iaf.datFilePath='./'; % Current folder
% iaf.is_finiteTE=0;

% % [[Calculating key parameters-----------------------------------------]]
cld=str2num(iaf.designation(1))*(3/2)/10;
p=0.5*str2num(iaf.designation(2:3))/100;
t=str2num(iaf.designation(4:5))/100;

a0= 0.2969;
a1=-0.1260;
a2=-0.3516;
a3= 0.2843;

if iaf.is_finiteTE ==1
    a4=-0.1015; % For finite thick TE
else
    a4=-0.1036;  % For zero thick TE
end

% % [[Giving x-spacing---------------------------------------------------]]
if iaf.HalfCosineSpacing==1
    beta=linspace(0,pi,iaf.n+1)';
    x=(0.5*(1-cos(beta))); % Half cosine based spacing
    iaf.header=['NACA' iaf.designation ' : [' num2str(2*iaf.n) 'panels,Half cosine x-spacing]'];
else
    x=linspace(0,1,iaf.n+1)';
    iaf.header=['NACA' iaf.designation ' : [' num2str(2*iaf.n) 'panels,Uniform x-spacing]'];
end

yt=(t/0.2)*(a0*sqrt(x)+a1*x+a2*x.^2+a3*x.^3+a4*x.^4);

P=[  0.05     0.1     0.15    0.2     0.25  ];
M=[  0.0580   0.1260  0.2025  0.2900  0.3910];
K=[361.4     51.64   15.957   6.643   3.230 ];

m=spline(P,M,p);
k1=spline(M,K,m);

xc1=x(find(x<=p));
xc2=x(find(x>p));
xc=[xc1 ; xc2];

if p==0
    xu=x;
    yu=yt;

    xl=x;
    yl=-yt;

    zc=zeros(size(xc));
else
    yc1=(1/6)*k1*( xc1.^3-3*m*xc1.^2+m^2*(3-m)*xc1 );
    yc2=(1/6)*k1*m^3*(1-xc2);
    zc=(cld/0.3)*[yc1 ; yc2];

    dyc1_dx=(1/6)*k1*( 3*xc1.^2-6*m*xc1+m^2*(3-m) );
    dyc2_dx=repmat((1/6)*k1*m^3,size(xc2));
    dyc_dx=[dyc1_dx ; dyc2_dx];
    theta=atan(dyc_dx);

    xu=x-yt.*sin(theta);
    yu=zc+yt.*cos(theta);

    xl=x+yt.*sin(theta);
    yl=zc-yt.*cos(theta);
end
af.name=['NACA ' iaf.designation];

af.x=[flipud(xu) ; xl(2:end)];
af.z=[flipud(yu) ; yl(2:end)];

indx1=1:min( find(af.x==min(af.x)) );  % Upper surface indices
indx2=min( find(af.x==min(af.x)) ):length(af.x); % Lower surface indices
af.xU=af.x(indx1); % Upper Surface x
af.zU=af.z(indx1); % Upper Surface z
af.xL=af.x(indx2); % Lower Surface x
af.zL=af.z(indx2); % Lower Surface z

af.xC=xc;
af.zC=zc;

lecirFactor=0.8;
af.rLE=0.5*(a0*t/0.2)^2;

le_offs=0.5/100;
dyc_dx_le=(1/6)*k1*( 3*le_offs.^2-6*m*le_offs+m^2*(3-m) );
theta_le=atan(dyc_dx_le);
af.xLEcenter=af.rLE*cos(theta_le);
af.yLEcenter=af.rLE*sin(theta_le);

% % [[Writing iaf data into file------------------------------------------]]
if iaf.wantFile==1
    F1=iaf.header;
    F2=num2str([af.x af.z]);
    F=strvcat(F1,F2);
    fileName=[iaf.datFilePath 'naca' iaf.designation '.dat'];
    dlmwrite(fileName,F,'delimiter','')
end