function [Y,W,SetupStruc] = Process_maxSNR(s,Transfer,SetupStruc)
K = SetupStruc.maxSNR.K;
hop = SetupStruc.maxSNR.hop;
win = hanning(K,'periodic');
win = win/sqrt(sum(win(1:hop:K).^2));
SetupStruc.maxSNR.win = win;  % Preserve 'win' in 'SetupStruc'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
N = size(s,2);
for i = 1:N
    X(:,:,i) = fft(enframe(s(:,i),win,hop)');
end
frame_N = size(X,2);
K_m = K/2+1;
Num = size(Transfer,3);
Y = zeros((frame_N-1)*hop+K,Num);
Y_f = zeros(size(X,1),size(X,2),Num);
covMa = cal_covMa(SetupStruc.unS,K,hop,win);
%%%%%%%%%%%%%%%%%%%%%%%%%% Obtain processing matrix 'W'
theta = 10^-4;
W = zeros(Num,N,K_m);
for i = 2:K_m
    X_f = permute(X(i,:,:),[3 2 1]);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%% maxSNR
    W_f = zeros(N,Num);
    for j = 1:Num
        R_d = covMa(:,:,i,j);
        R_i = zeros(N);
        for k = 1:Num
            if(k==j) continue;end
            R_i = R_i+covMa(:,:,i,k);
        end
        if(rcond(R_i)<theta)
            R_i = R_i+eye(N)*min(diag(R_i))*theta;
        end
%         [E,~] = PCA(R_i\R_d,1,1);
        [E,D] = eig(R_i\R_d);
        [~,index] = max(diag(D));
        E = E(:,index);
        W_f(:,j) = E*sqrt(E'*R_i*R_i*E/N)/(E'*R_i*E);  %%%%%% WAN post filtering
    end
    W_f = W_f';
    W(:,:,i) = W_f;
    Y_ = W_f*X_f;
    Y_f(i,:,:) = Y_.';
    if(i~=K_m)
        Y_f(K+2-i,:,:) = Y_';
    end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Recover signals
if(K/hop==2)
    win = ones(K,1);
end
for i = 1:Num
    Y(:,i) = overlapadd(real(ifft(Y_f(:,:,i)))',win,hop);
end

return;


function [mv1, mv2, mv3] = specificIMCDetails(img, varargin)
%SPECIFICIMCDETAILS Ohser's Integral of Mean Curvature
%
%   this version is just for debugging.
%   It allows to extract contribution for each directions.
%
%   ---------
%
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 16/02/2005.
%

%   HISTORY

img = img~=0;

delta = [1 1 1];

% square faces of the unit cell
kr = [...
    1 2 3 4;...
    1 2 5 6;...
    1 3 5 7;...
    1 2 7 8;...
    3 5 4 6;...
    1 6 3 8;...
    2 4 5 7;...
    2 3 6 7;...
    1 5 3 8];

% triangle faces of the unit cell
kt = [...
    1 7 6;...
    2 5 8;...
    4 7 6;...
    3 5 8;...
    2 3 8;...
    4 1 7;...
    2 3 5;...
    4 1 6];

% unit surface for each cell
c1 = 0.045778;
c2 = 0.036981;
c3 = 0.035196;
c = [c1 c1 c1   c2 c2 c2   c2 c2 c2   c3 c3 c3 c3];

% distances between pixels
d1 = delta(1);
d2 = delta(2);
d3 = delta(3);
d12  = sqrt(delta(1)*delta(1) + delta(2)*delta(2));
d13  = sqrt(delta(1)*delta(1) + delta(3)*delta(3));
d23  = sqrt(delta(2)*delta(2) + delta(3)*delta(3));
s = (d12 + d23 + d13)/2;
a123 = 2*sqrt(s*(s-d12)*(s-d13)*(s-d23));

a = [d1*d2 d1*d3 d2*d3   d3*d12 d3*d12 d2*d13 d2*d13 d1*d23 d1*d23  a123 a123 a123 a123];

% compute gray-tone histogram of the image
h = grayHist(img);

mv1 = 0;
mv2 = 0;
mv3 = 0;

% for each type of configuration
for l=1:256

    v = l-1;
    b(1) = bitand(v,1)~=0;
    b(2) = bitand(v,2)~=0;
    b(3) = bitand(v,4)~=0;
    b(4) = bitand(v,8)~=0;
    b(5) = bitand(v,16)~=0;
    b(6) = bitand(v,32)~=0;
    b(7) = bitand(v,64)~=0;
    b(8) = bitand(v,128)~=0;

    % for each square face
    for nu=1:3

        b1 = b(kr(nu, 1));
        b2 = b(kr(nu, 2));
        b3 = b(kr(nu, 3));
        b4 = b(kr(nu, 4));

        s = sum([b1 b2 b3 b4]);
        if s==1
            mv1 = mv1 + h(l)*c(nu)/4/a(nu);
        elseif s==3
            mv1 = mv1 - h(l)*c(nu)/4/a(nu);
        end
    end

    % for each square diagonal face
    for nu = 4:9

        b1 = b(kr(nu, 1));
        b2 = b(kr(nu, 2));
        b3 = b(kr(nu, 3));
        b4 = b(kr(nu, 4));

        s = sum([b1 b2 b3 b4]);
        if s==1
            mv2 = mv2 + h(l)*c(nu)/4/a(nu);
        elseif s==3
            mv2 = mv2 - h(l)*c(nu)/4/a(nu);
        end
    end

    % for each triangular face
    for nu=10:13

        b1 = b(kt(nu-9, 1));
        b2 = b(kt(nu-9, 2));
        b3 = b(kt(nu-9, 3));
        b4 = b(kt(nu-5, 1));
        b5 = b(kt(nu-5, 2));
        b6 = b(kt(nu-5, 3));

        s1 = sum([b1 b2 b3]);
        s2 = sum([b4 b5 b6]);
        if s1==1
            mv3 = mv3 + h(l)*c(nu)/3/a(nu);
        end
        if s2==2
            mv3 = mv3 - h(l)*c(nu)/3/a(nu);
        end
    end
end

%imc = 4*pi*mv/sum(h(:));


%% (Internal) Design the wavelet decomposition filters for wavedet algorithm
%
% Prototype:
% ----------
% q_filters = qs_filter_design(scales, fs, N);
%
% Description:
% ------------
% Mimics the transfer function of the filters used for ECG delineation in
% [Martinez et al. 2004] for an arbitrary sampling frequency and filter order N.
%
% Martinez et al. "A Wavelet-Based ECG Delineator: Evaluation on Standard
% Databases" IEEE TRANSACTIONS ON BIOMEDICAL ENGINEERING, VOL. 51, NO. 4,
% APRIL 2004.
%
% WARNING :
% ---------
% As this routines iterates through several configurations in order to
% converge, the user should check the transfer functions of the filters. My
% suggestion is once you obtain a desired filter bank for a given Fs or
% configuration, save or cache it in a .mat file in order to use it during
% operation. For example, if you usually work with signals sampled at 360
% Hz, a good choice is to have a cached version of the filters for this Fs
% in a .mat file called "wt_filters_6 scales_360 Hz.mat". You can use this
% function on-line with your algorithm at your own risk.
%
% Examples :
% ----------
%
% q_filters = qs_filter_design(4, 250);
%
% q_filters = qs_filter_design(5, 360);
%
% q_filters = qs_filter_design(6, 1000);
%
% you can check filter characteristics using:
%
% fss = [250 360 500 1000]; %Hz
% for fs  = fss
%     fvtool(q_filters, 'fs', fs )
% end
%
% Author: Mariano Llamedo Soria (llamedom at frba.utn.edu.ar)
% Version: 0.1 beta
% Birthdate: 17/2/11
% Last update: 22/02/13
% Copyright 2008-2015
%
function q_filters = qs_filter_design(scales, fs, N)

design_iter_attemps = 10;

if( nargin < 2 || isempty(fs) )
    fs = 250; %Hz
end

if( nargin < 3 || isempty(N) )
    %valor emp�rico obtenido de varios dise�os.
    N = max(10, round(fs*4/30 + 16+2/3));
end

%Pruebo que N no sea demasiado distinto a lo recomendable.
recommended_N = max(10, round(fs*4/30 + 16+2/3));
if( abs(N - recommended_N) > 0.1*N )
    warning(['Check the transfer functions of the differentiator filters designed. Recommended order N = ' num2str(recommended_N) ]);
end

%frecuencia a la que est� dise�ado el delineador, y que se toma para
%referencia para que las escalas signifiquen lo mismo a cualquier Fs.
f_ref = 250; %Hz
f_ratio = f_ref/fs;

% Funciones de transferencia correctas para el dise�o de los filtros utilizadas
% por el wavedet a 250 Hz.
empirical_tf = { ...
    [2;-2] ...
    [0.250000000000000;0.750000000000000;0.500000000000000;-0.500000000000000;-0.750000000000000;-0.250000000000000;] ...
    [0.0312500000000000;0.0937500000000000;0.187500000000000;0.312500000000000;0.343750000000000;0.281250000000000;0.125000000000000;-0.125000000000000;-0.281250000000000;-0.343750000000000;-0.312500000000000;-0.187500000000000;-0.0937500000000000;-0.0312500000000000;] ...
    [0.00390625000000000;0.0117187500000000;0.0234375000000000;0.0390625000000000;0.0585937500000000;0.0820312500000000;0.109375000000000;0.140625000000000;0.160156250000000;0.167968750000000;0.164062500000000;0.148437500000000;0.121093750000000;0.0820312500000000;0.0312500000000000;-0.0312500000000000;-0.0820312500000000;-0.121093750000000;-0.148437500000000;-0.164062500000000;-0.167968750000000;-0.160156250000000;-0.140625000000000;-0.109375000000000;-0.0820312500000000;-0.0585937500000000;-0.0390625000000000;-0.0234375000000000;-0.0117187500000000;-0.00390625000000000;] ...
    [0.000488281250000000;0.00146484375000000;0.00292968750000000;0.00488281250000000;0.00732421875000000;0.0102539062500000;0.0136718750000000;0.0175781250000000;0.0219726562500000;0.0268554687500000;0.0322265625000000;0.0380859375000000;0.0444335937500000;0.0512695312500000;0.0585937500000000;0.0664062500000000;0.0727539062500000;0.0776367187500000;0.0810546875000000;0.0830078125000000;0.0834960937500000;0.0825195312500000;0.0800781250000000;0.0761718750000000;0.0708007812500000;0.0639648437500000;0.0556640625000000;0.0458984375000000;0.0346679687500000;0.0219726562500000;0.00781250000000000;-0.00781250000000000;-0.0219726562500000;-0.0346679687500000;-0.0458984375000000;-0.0556640625000000;-0.0639648437500000;-0.0708007812500000;-0.0761718750000000;-0.0800781250000000;-0.0825195312500000;-0.0834960937500000;-0.0830078125000000;-0.0810546875000000;-0.0776367187500000;-0.0727539062500000;-0.0664062500000000;-0.0585937500000000;-0.0512695312500000;-0.0444335937500000;-0.0380859375000000;-0.0322265625000000;-0.0268554687500000;-0.0219726562500000;-0.0175781250000000;-0.0136718750000000;-0.0102539062500000;-0.00732421875000000;-0.00488281250000000;-0.00292968750000000;-0.00146484375000000;-0.000488281250000000;] ...
    [6.10351562500000e-05;0.000183105468750000;0.000366210937500000;0.000610351562500000;0.000915527343750000;0.00128173828125000;0.00170898437500000;0.00219726562500000;0.00274658203125000;0.00335693359375000;0.00402832031250000;0.00476074218750000;0.00555419921875000;0.00640869140625000;0.00732421875000000;0.00830078125000000;0.00933837890625000;0.0104370117187500;0.0115966796875000;0.0128173828125000;0.0140991210937500;0.0154418945312500;0.0168457031250000;0.0183105468750000;0.0198364257812500;0.0214233398437500;0.0230712890625000;0.0247802734375000;0.0265502929687500;0.0283813476562500;0.0302734375000000;0.0322265625000000;0.0339965820312500;0.0355834960937500;0.0369873046875000;0.0382080078125000;0.0392456054687500;0.0401000976562500;0.0407714843750000;0.0412597656250000;0.0415649414062500;0.0416870117187500;0.0416259765625000;0.0413818359375000;0.0409545898437500;0.0403442382812500;0.0395507812500000;0.0385742187500000;0.0374145507812500;0.0360717773437500;0.0345458984375000;0.0328369140625000;0.0309448242187500;0.0288696289062500;0.0266113281250000;0.0241699218750000;0.0215454101562500;0.0187377929687500;0.0157470703125000;0.0125732421875000;0.00921630859375000;0.00567626953125000;0.00195312500000000;-0.00195312500000000;-0.00567626953125000;-0.00921630859375000;-0.0125732421875000;-0.0157470703125000;-0.0187377929687500;-0.0215454101562500;-0.0241699218750000;-0.0266113281250000;-0.0288696289062500;-0.0309448242187500;-0.0328369140625000;-0.0345458984375000;-0.0360717773437500;-0.0374145507812500;-0.0385742187500000;-0.0395507812500000;-0.0403442382812500;-0.0409545898437500;-0.0413818359375000;-0.0416259765625000;-0.0416870117187500;-0.0415649414062500;-0.0412597656250000;-0.0407714843750000;-0.0401000976562500;-0.0392456054687500;-0.0382080078125000;-0.0369873046875000;-0.0355834960937500;-0.0339965820312500;-0.0322265625000000;-0.0302734375000000;-0.0283813476562500;-0.0265502929687500;-0.0247802734375000;-0.0230712890625000;-0.0214233398437500;-0.0198364257812500;-0.0183105468750000;-0.0168457031250000;-0.0154418945312500;-0.0140991210937500;-0.0128173828125000;-0.0115966796875000;-0.0104370117187500;-0.00933837890625000;-0.00830078125000000;-0.00732421875000000;-0.00640869140625000;-0.00555419921875000;-0.00476074218750000;-0.00402832031250000;-0.00335693359375000;-0.00274658203125000;-0.00219726562500000;-0.00170898437500000;-0.00128173828125000;-0.000915527343750000;-0.000610351562500000;-0.000366210937500000;-0.000183105468750000;-6.10351562500000e-05;] ...
                };

Grid_size = 1024;

% Creo una grilla de muestreo en frecuencia logaritmica para que la
% zona en que derivan los filtros sea una recta de pendiente constante.
F_log = logspace(-3, min(0, log10(fs/f_ref)), Grid_size) * pi;

filter_count = 1;

for ii = rowvec(scales)

    [g_amp F] = freqz(empirical_tf{ii},1, F_log);
    F = F * f_ratio / pi;
    g_amp = abs(g_amp);

    %averiguo hasta qu� muestra se comporta como un derivador, ya que ser�
    %un par�metro de dise�o.
    slope_aux = diff( log10(g_amp) );
    end_diff_idx = find(slope_aux < 0.95*slope_aux(1), 1, 'first');

    %dise�o un derivador hasta dicha frecuencia, con una banda de
    %transici�n dada por la expresion , cuando sea posible.
    ftrans = min(70, 251 * exp(-0.63*ii));
    diff_order = round(N*1.8.^((ii*0.4 -0.6)));
    %Los N tienen que ser necesariamente pares para el dise�o del derivador.
    if( rem(diff_order,2) ~= 0 )
        diff_order = diff_order + 1;
    end

    [msgstr, msgid] = lastwarn;
    %itero hasta que se dise�a correctamente.
    jj = 0;
    effective_order = diff_order;
    aux_seq = linspace(0.5,1.1,design_iter_attemps);
    while( jj < design_iter_attemps )
        d = fdesign.differentiator('n,fp,fst', effective_order, F(end_diff_idx), min( 0.95, F(end_diff_idx)+(ftrans*2/fs) ) );
        try
            Hd = design(d,'equiripple');
            [~, msgid] = lastwarn('','');
        catch MException
            %on error, force iteration with different config.
            msgid = 'signal:firpm:DidNotConverge';
        end
        if(strcmpi(msgid,'signal:firpm:DidNotConverge'))
            %fallo en la convergencia, iteramos de nuevo.
            %recorro linealmente por el rango +10:-50%
            effective_order = round(diff_order * aux_seq(jj+1));
            %Los effective_order tienen que ser necesariamente pares para el dise�o del derivador.
            if( rem(effective_order,2) ~= 0 )
                effective_order = effective_order + 1;
            end
            jj = jj + 1;
        else
            jj = design_iter_attemps;
        end
    end

    if(strcmpi(msgid,'signal:firpm:DidNotConverge'))
    %fallo en la convergencia, reportamos el error.
        error('qs_filter_design:Impossible2Design', 'Impossible to design the differentiator filter. Please try another N value, or check the filters transfer functions manually.')
    end

    %Vuelvo a ver la transferencia real del derivador dise�ado y del filtro
    %a emular para que tengan una respuesta similar en la zona en que se
    %comporta como derivador. Averiguo el factor de escala entre ambas
    %transferencias.
    g_amp_emp = freqz(empirical_tf{ii},1, F_log);
    g_amp_emp = abs(g_amp_emp);

    g_amp_real = freqz(Hd, F * pi);
    g_amp_real = abs(g_amp_real);

    aux_idx = round(end_diff_idx/2);
    aux_scale = g_amp_emp(aux_idx)/g_amp_real(aux_idx);

    %Escalo la zona del derivador.
    Hd.Numerator = Hd.Numerator * aux_scale;
    g_amp_real = g_amp_real * aux_scale;

    %ahora dise�o un filtro de compensaci�n para que la zona en que no se
    %deriva sea similar al filtro de referencia. Esta ir� desde el m�ximo
    %de la transferencia pasobanda hasta donde haya una amplitud mayor a
    %0.5 veces.
    [~, max_idx] = max(g_amp);

    aux_3db_unique = find( g_amp_real > 0.5 & g_amp_emp > 0.5, 1, 'last');

    if( max_idx >= aux_3db_unique)
        max_idx = end_diff_idx;
    end
    aux_idx = max_idx:aux_3db_unique;

    %Creo una grilla de frecuencia - magnitud arbitraria para el dise�o del
    %filtro. Esta transferencia no deber� afectar la zona derivadora (H(w)
    %= 1) y compensar la zona indicada por aux_idx, emulando la
    %transferencia de referencia y teniendo un valor de atenuaci�n
    %considerable en Nyquist (H(w) = 1e-3)
    F_comp = [0 max(0.9*F(end_diff_idx), (F(max_idx)-F(end_diff_idx))/2) F(aux_idx) 1];
    g_amp_comp = [1 1 g_amp(aux_idx)./g_amp_real(aux_idx) 1e-3];
    W = ones(1, length(F_comp));
    W(3:end-1) = 10;

    %Se dise�a el filtro
    d = fdesign.arbmag('N,F,A', diff_order, F_comp, g_amp_comp);
    Hd_comp = design(d,'firls', 'weights', W, 'FilterStructure', 'dfsymfir');

    % y se cascadea al original.
    Hd = dfilt.cascade(Hd, Hd_comp);

    q_filters(filter_count) = Hd;

    filter_count = filter_count + 1;

end


function acc = ContinuousAccuracy(obj, pattern, predrange, unit)
% Calculate forced choice accuracy for unit increases in continuous
% predictions.  Requires units to be ranked ordered from 1:end.  Will work
% for Gianaros or Pain datasets.  Accuracies are not penalized for missing
% cases.  Probably best to run this on single subjects and then aggregate
% accuracies across subjects.
%
% :Usage:
% ::
%
%     acc = ContinuousAccuracy(obj, pattern, unit)
%
% :Inputs:
%
%   **obj:**
%        fmri_data() object with data stacked by
%        increasing levels of prediction.  Make sure
%        obj.Y includes the training labels
%
%   **pattern:**
%        fmri_data() object with weight pattern
%
%   **predrange:**
%        specify the range of predictions (e.g., 1:5)
%
%   **unit:**
%        specify the unit increase in prediction (e.g., 1 or 2)
%
% :Outputs:
%
%   **acc:**
%        accuracy of prediction for specified units
%
% :Examples:
% ::
%
%    acc = ContinuousAccuracy(dat, pine, 1:5, 1)
%
% ..
%    Original version: Copyright Luke Chang 12/2013
% ..

pexp = apply_mask(obj, pattern, 'pattern_expression', 'ignore_missing'); %Calculate pattern expression

%Create pairwise matrix and find positive values for lower triangle
%-need to force it to be 5 and fill in missing with NaNs
for i = predrange
    for j = predrange
        if ~any(obj.Y==i) || ~any(obj.Y==j)
            a(i,j) = nan;
        else
            a(i,j) = pexp(obj.Y == i) - pexp(obj.Y == j);
        end
    end
end
lt = double(tril(a) > 0);
lt(isnan(a)) = nan;

%remove by a factor of unit
i = 1;
while i < max(predrange)
    lt(i:i+unit-1,i) = 0;
    i = i + 1;
end

n = length(predrange)-unit;
miss = tril(isnan(lt)); %calculate lower triangle accuracy
miss(logical(eye(length(predrange))))=0; %remove any nans on diagonal
total = (n*(n+1)/2) - sum(sum(miss));  %subtract out any nans from total
acc = sum(nansum(lt))/total;


function  [C,phi,S12,confC,phierr,Cerr]=cohmathelper(J,err,Nsp)
% Helper function called by coherency matrix computations.
%
% Usage: [C,phi,S12,confC,phierr,Cerr]=cohmathelper(J,err,Nsp)
% Inputs:
% J   : Fourier transforms of data
% err : [0 p] or 0 for no errors; [1 p] for theoretical confidence level,
%       [2 p] for Jackknife (p - p value)
% Nsp : pass the number of spikes in each channel if finite size corrections are desired
%
% Outputs:
%
% C   : coherence
% phi : phase of coherency
% S12 : cross spectral matrix
% confC : confidence level for coherency - only for err(1)>=1
%       phierr - standard deviation for phi (note that the routine gives phierr as phierr(1,...)
%                and phierr(2,...) in order to incorporate Jackknife (eventually).
%                Currently phierr(1,...)=phierr(2,...). Note that phi + 2 phierr(1,...) and phi -2
%                phierr(2,...) will give 95% confidence bands for phi - only for err(1)>=1
% Cerr  : error bars for coherency (only for Jackknife estimates)-only for err(1)=2
%

errtype=err(1);
trialave=0;
[nf,K,Ch]=size(J);
clear K
confC=zeros(Ch,Ch);
C=zeros(nf,Ch,Ch);
S12=zeros(nf,Ch,Ch);
phi=zeros(nf,Ch,Ch);
phierr=zeros(2,nf,Ch,Ch);
if errtype==2; Cerr=zeros(2,nf,Ch,Ch);end;

for ch1=1:Ch;
     J1=squeeze(J(:,:,ch1));
     C(1:nf,ch1,ch1)=1;
     phi(1:nf,ch1,ch1)=0;
%      if errtype==2;
%           phierr(1:nf,ch1,ch1)=0;
%           Cerr(1:2,1:nf,ch1,ch1)=0;
%      elseif errtype==1
%            phierr(1:2,1:nf,ch1,ch1)=0;
%      end;
     s1=squeeze(mean(conj(J1).*J1,2));
     for ch2=1:ch1-1;
          J2=squeeze(J(:,:,ch2));
          s12=squeeze(mean(conj(J1).*J2,2));
          s2=squeeze(mean(conj(J2).*J2,2));
          C12=s12./sqrt(s1.*s2);
          C(:,ch1,ch2)=abs(C12);
          C(:,ch2,ch1)=C(:,ch1,ch2);
          phi(:,ch1,ch2)=angle(C12);
          phi(:,ch2,ch1)=phi(:,ch1,ch2);
          S12(:,ch1,ch2)=s12;
          S12(:,ch2,ch1)=S12(:,ch1,ch2);
          if errtype==2
             if nargin<3;
                 [conf,phie,Ce]=coherr(abs(C12),J1,J2,err,trialave);
             else
                 [conf,phie,Ce]=coherr(abs(C12),J1,J2,err,trialave,Nsp(ch1),Nsp(ch2));
             end
             confC(ch1,ch2)=conf;
             phierr(1,:,ch1,ch2)=phie;phierr(2,:,ch1,ch2)=phie;
             Cerr(1,:,ch1,ch2)=Ce(1,:);
             Cerr(2,:,ch1,ch2)=Ce(2,:);
             confC(ch2,ch1)=conf;
             phierr(1,:,ch2,ch1)=phie;phierr(2,:,ch2,ch1)=phie;
             Cerr(:,:,ch2,ch1)=Ce;
          elseif errtype==1
             if nargin<3;
                 [conf,phie]=coherr(abs(C12),J1,J2,err,trialave);
             else
                 [conf,phie]=coherr(abs(C12),J1,J2,err,trialave,Nsp(ch1),Nsp(ch2));
             end
             confC(ch1,ch2)=conf;
             phierr(1,:,ch1,ch2)=phie;phierr(2,:,ch1,ch2)=phie;
             confC(ch2,ch1)=conf;
             phierr(1,:,ch2,ch1)=phie;phierr(2,:,ch2,ch1)=phie;
          end;
     end;
end;


function [beta_gibbs,F_gibbs,gamma_gibbs,L_gibbs,phi_gibbs,sigma_gibbs,lambda_t_gibbs,sigma_t_gibbs,sbar,favar,It,Bu]=...
    favar_stvol2gibbs(Xbart,yt,beta0,omega0,alpha0,delta0,gamma0,zeta0,f0,upsilon0,betahat,sigmahat,I_o,omega,T,n,q,It,Bu,pick,pickf,favar,data_endo,lags)

%% preliminaries
% initialise variables
nfactorvar=favar.nfactorvar;
numpc=favar.numpc;
favarX=favar.X(:,favar.plotX_index);
onestep=favar.onestep;
Sigma=bear.nspd(favar.Sigma);
Ll=favar.L;
favar_X=favar.X;
% load priors
L0=favar.L0*eye(n);
a0=favar.a0;
b0=favar.b0;
% sigmahat=(1/T)*(EPS'*EPS);

% preallocation
Ll_gibbs=zeros(size(Ll(:),1),It-Bu);
R2_gibbs=zeros(size(favarX,2),It-Bu);

if onestep==0 %static factors in this case
    FY=data_endo;
    pbstring='two-step'; %string for the progress bar
    % elseif onestep==1
    %     pbstring='one-step'; %string for the progress bar
end

% preliminary elements for the algorithm
% compute alphabar
alphabar=T+alpha0;

% initiate the Gibbs sampler
% initiate the counting of iterations
count=1;
pickcount=1;
% initiate the record matrices and cells
beta_gibbs=[];
F_gibbs=[];
L_gibbs=[];
phi_gibbs=[];
sigma_gibbs=[];
lambda_t_gibbs={};
sigma_t_gibbs={};

% step 1: determine initial values for the algorithm

% initial value for beta
beta=betahat;
% initial value for f_2,...,f_n
% obtain the triangular factorisation of sigmahat
[Fhat,Lambdahat]=bear.triangf(sigmahat);
% obtain the inverse of Fhat
[invFhat]=bear.invltod(Fhat,n);
% create the cell storing the different vectors of invF
Finv=cell(n,1);
% store the vectors
for ii=2:n
    Finv{ii,1}=invFhat(ii,1:ii-1);
end
% initial values for L_1,...,L_n
L=zeros(T,n);
% initial values for gamma_1,...,gamma_n
gamma=0.85*ones(1,n);
% initial values for G_1,...,G_n
G=cell(n,1);
for ii=1:n
    G{ii,1}=speye(T)-sparse(diag(gamma(1,ii)*ones(T-1,1),-1));
end
% initial values for phi_1,...,phi_n
phi=ones(1,n);

% step 2: determine the sbar values and Lambda
sbar=diag(Lambdahat);
Lambda=sparse(diag(sbar));

% step 3: recover the series of initial values for lambda_1,...,lambda_T and sigma_1,...,sigma_T
lambda_t=repmat(diag(sbar),1,1,T);
sigma_t=repmat(sigmahat,1,1,T);

% create a progress bar
hbar = bear.parfor_progressbar(It,['Progress of the Gibbs sampler (',pbstring,').']);

%% run the Gibbs sampler
while count<=It

    % step 4: draw beta from its conditional posterior
    % first compute the summations required for omegabar and betabar
    summ1=zeros(q,q);
    summ2=zeros(q,1);
    % run the summation
    for jj=1:T
        prodt=Xbart{jj,1}'/sigma_t(:,:,jj);
        summ1=summ1+prodt*Xbart{jj,1};
        summ2=summ2+prodt*yt(:,:,jj);
    end
    % then obtain the inverse of omega0
    invomega0=diag(1./diag(omega0));
    % obtain the inverse of omegabar
    invomegabar=summ1+invomega0;
    % recover omegabar
    C=chol(bear.nspd(invomegabar),'Lower')';
    invC=C\speye(q);
    omegabar=invC*invC';
    % recover betabar
    betabar=omegabar*(summ2+invomega0*beta0);
    % finally, draw beta from its posterior
    beta=betabar+chol(bear.nspd(omegabar),'lower')*randn(q,1);

    % step 5: draw the series f_2,...,f_n from their conditional posteriors
    % recover first the residuals
    for jj=1:T
        epst(:,:,jj)=yt(:,:,jj)-Xbart{jj,1}*beta;
    end
    % then draw the vectors in turn
    for jj=2:n
        % first compute the summations required for upsilonbar and fbar
        summ1=zeros(jj-1,jj-1);
        summ2=zeros(jj-1,1);
        % run the summation
        for kk=1:T
            prodt=epst(1:jj-1,1,kk)*exp(-L(kk,jj));
            summ1=summ1+prodt*epst(1:jj-1,1,kk)';
            summ2=summ2+prodt*epst(jj,1,kk)';
        end
        summ1=(1/sbar(jj,1))*summ1;
        summ2=(-1/sbar(jj,1))*summ2;
        % then obtain the inverse of upsilon0
        invupsilon0=diag(1./diag(upsilon0{jj,1}));
        % obtain upsilonbar
        invupsilonbar=summ1+invupsilon0;
        C=chol(bear.nspd(invupsilonbar));
        invC=C\speye(jj-1);
        upsilonbar=full(invC*invC');
        % recover fbar
        fbar=upsilonbar*(summ2+invupsilon0*f0{jj,1});
        % finally draw f_i^(-1)
        Finv{jj,1}=fbar+chol(bear.nspd(upsilonbar),'lower')*randn(jj-1,1);
    end
    % recover the inverse of F
    invF=eye(n);
    for jj=2:n
        invF(jj,1:jj-1)=Finv{jj,1};
    end
    % eventually recover F
    F=bear.invltod(invF,n);
    % then update sigma
    sigma=F*Lambda*F';

    % step 6: draw the series gamma_1,...,gamma_n from their conditional posteriors
    % draw the parameters in turn
    for jj=1:n
        % estimate zetabar
        zetabar=1/((1/phi(1,jj))*L(1:T-1,jj)'*L(1:T-1,jj)+1/zeta0);
        % estimate zetabar
        gammabar=zetabar*((1/phi(1,jj))*L(2:T,jj)'*L(1:T-1,jj)+gamma0/zeta0);
        % draw the value gamma_i
        gamma(1,jj)=gammabar+zetabar^0.5*randn;
        % obtain G_i
        G{jj,1}=speye(T)-sparse(diag(gamma(1,jj)*ones(T-1,1),-1));
    end

    % step 7: draw the series phi_1,...,phi_n from their conditional posteriors
    % draw the parameters in turn
    for jj=1:n
        % estimate deltabar
        deltabar=L(:,jj)'*G{jj,1}'*I_o*G{jj,1}*L(:,jj)+delta0;
        % draw the value phi_i
        phi(1,jj)=bear.igrandn(alphabar/2,deltabar/2);
    end

    % step 8: draw the series lambda_i,t from their conditional posteriors, i=1,...,n and t=1,...,T
    % consider variables in turn
    for jj=1:n
        % consider periods in turn
        for kk=1:T
            % a candidate value will be drawn from N(lambdabar,phibar)
            % the definitions of lambdabar and phibar varies with the period, thus define them first
            % if the period is the first period
            if kk==1
                lambdabar=(gamma(1,jj)*L(2,jj))/(1/omega+gamma(1,jj)^2);
                phibar=phi(1,jj)/(1/omega+gamma(1,jj)^2);
                % if the period is the final period
            elseif kk==T
                lambdabar=gamma(1,jj)*L(T-1,jj);
                phibar=phi(1,jj);
                % if the period is any period in-between
            else
                lambdabar=(gamma(1,jj)/(1+gamma(1,jj)^2))*(L(kk-1,jj)+L(kk+1,jj));
                phibar=phi(1,jj)/(1+gamma(1,jj)^2);
            end
            % now draw the candidate
            cand=lambdabar+phibar^0.5*randn;
            % compute the acceptance probability
            prob=bear.mhprob2(jj,cand,L(kk,jj),sbar(jj,1),epst(:,1,kk),Finv{jj,1});
            % draw a uniform random number
            draw=rand;
            % keep the candidate if the draw value is lower than the prob
            if draw<=prob
                L(kk,jj)=cand;
                % if not, just keep the former value
            end
        end
    end
    % then recover the series of matrices lambda_t and sigma_t
    for jj=1:T
        lambda_t(:,:,jj)=diag(sbar).*diag(exp(L(jj,:)));
        sigma_t(:,:,jj)=F*lambda_t(:,:,jj)*F';
    end

    %% Sample Sigma and Ll (static)
    [Sigma,Ll]=bear.favar_SigmaL(Sigma,Ll,nfactorvar,numpc,onestep,n,favar_X,FY,a0,b0,T,lags,L0);

    %% record phase
    % if the burn-in sample phase is not yet over
    if count<=Bu
        % simply add 1 to the iteration count
        count=count+1;
        % on the other hand, if the burn-in sample phase is over
    elseif count>Bu
        % adding one iteration to the count will depend on wether post-burn selection applies
        % if there is no post burn selection
        if pick==0
            % record the results
            beta_gibbs(:,count-Bu)=beta;
            F_gibbs(:,:,count-Bu)=F;
            gamma_gibbs(count-Bu,:)=gamma;
            L_gibbs(:,:,count-Bu)=L;
            phi_gibbs(count-Bu,:)=phi;
            sigma_gibbs(:,count-Bu)=sigma(:);
            % save the factors and loadings (keep the notation in the code consistent, although - except L - they don't change)
            Ll_gibbs(:,count-Bu)=Ll(:);

            % compute R2 (Coefficient of Determination) for plotX variables (keep the notation in the code consistent, although they don't change)
            R2=bear.favar_R2(favarX,FY);
            R2_gibbs(:,count-Bu)=R2(:);
            for jj=1:T
                lambda_t_gibbs{jj,1}(:,:,count-Bu)=lambda_t(:,:,jj);
                sigma_t_gibbs{jj,1}(:,:,count-Bu)=sigma_t(:,:,jj);
            end
            % then add one to the count
            count=count+1;
            % if there is post burn selection, only one draw over 'fpick' draws will be retained
        elseif pick==1
            % if the iteration does not correspond to fpick, don't record the results, don't increase the regular count, but do increase pickcount by 1, and do record the acceptance rate of the Metropolis-Hastings step
            if pickcount~=pickf
                pickcount=pickcount+1;
                % on the other hand, if the iteration does correspond to fpick
            elseif pickcount==pickf
                % do record the results
                beta_gibbs(:,count-Bu)=beta;
                F_gibbs(:,:,count-Bu)=F;
                gamma_gibbs(count-Bu,:)=gamma;
                L_gibbs(:,:,count-Bu)=L;
                phi_gibbs(count-Bu,:)=phi;
                sigma_gibbs(:,count-Bu)=sigma(:);
                % save the factors and loadings (keep the notation in the code consistent, although - except L - they don't change)
                Ll_gibbs(:,count-Bu)=Ll(:);

                % compute R2 (Coefficient of Determination) for plotX variables (keep the notation in the code consistent, although they don't change)
                R2=bear.favar_R2(favarX,FY);
                R2_gibbs(:,count-Bu)=R2(:);
                for jj=1:T
                    lambda_t_gibbs{jj,1}(:,:,count-Bu)=lambda_t(:,:,jj);
                    sigma_t_gibbs{jj,1}(:,:,count-Bu)=sigma_t(:,:,jj);
                end
                % then increase the regular count by 1 and re-initialise pickcount
                count=count+1;
                pickcount=1;
            end
        end
    end

    % update progress by one iteration
    hbar.iterate(1);

end

% in case we have thinning of the draws,
thin=abs(round(favar.thin)); % should be a positive integer
if thin~=1
    beta_gibbs=beta_gibbs(:,thin:thin:end);
    F_gibbs=F_gibbs(:,thin:thin:end);
    L_gibbs=L_gibbs(:,thin:thin:end);
    phi_gibbs=phi_gibbs(:,thin:thin:end);
    sigma_gibbs=sigma_gibbs(:,thin:thin:end);
    Ll_gibbs=Ll_gibbs(:,thin:thin:end);
    R2_gibbs=R2_gibbs(:,thin:thin:end);
    for jj=1:T
        lambda_t_gibbs=lambda_t_gibbs(:,:,thin:thin:end);
        sigma_t_gibbs=sigma_t_gibbs(:,:,thin:thin:end);
    end
    It=(1/thin)*It;
    Bu=(1/thin)*Bu;
end

% save in favar structure
favar.L_gibbs=Ll_gibbs;
favar.R2_gibbs=R2_gibbs;

close(hbar);   %close progress bar


function evaluate(resPath, wwwPath, class, width, height)

if strcmp(class, 'chair') || strcmp(class, 'bed')
  param_length = [5, 6, 12, 14];
elseif strcmp(class, 'swivelchair') || strcmp(class, 'sofa')
  param_length = [7, 8, 14, 16];
end

load(resPath, 'outputs');
numInst = size(outputs, 1);
alphaPred = outputs(:, 1 : param_length(1));
finvPred = outputs(:, (param_length(1) + 1) : param_length(2));
sincosThetaPred = outputs(:, (param_length(2) + 1) : param_length(3));
sincosThetaPred(:, 3) = 0;
sincosThetaPred(:, 6) = 1;
tranPred = outputs(:, (param_length(3) + 1) : param_length(4));

addpath(fullfile('3D', 'genSynData'));
addpath(fullfile('3D', 'tools'));
stickStruct = getStickFigure('class', class);

for i = 1 : numInst
  im = visualize3Dpara(alphaPred(i, :)', sincosThetaPred(i, :)', ...
    tranPred(i, :)', 1 ./ finvPred(i, :), stickStruct.baseShape{1}, ...
    stickStruct.edgeAdj{1}, 'h', height, 'w', width, 'lineWidth', 6);
  imwrite(im, fullfile(wwwPath, sprintf('%08d.jpg', i)));
end

end


function [ln,lf]=dfa(varargin)
%
% [ln,lf]=dfa(x,p,integrateFlag,minBoxSize,maxBoxSize,slideWindowFlag)
%
%
% Wrapper to the DFA Algorithm in:
%    http://www.physionet.org/physiotools/dfa/
%
% References:
% Peng C-K, Buldyrev SV, Havlin S, Simons M, Stanley HE, Goldberger AL. Mosaic organization of DNA nucleotides. Phys Rev E 1994;49:1685-1689.
% Peng C-K, Havlin S, Stanley HE, Goldberger AL. Quantification of scaling exponents and crossover phenomena in nonstationary heartbeat time series. Chaos 1995;5:82-87.
%
% Please cite at least one of the above publications when referencing this
% material.
%
% Required Input Options are:
%
% x
%       A Nx1 vector of doubles.
%
% Optional Input Options are:
%
% p
%       Detrend using a polynomial of degree p (default: p=1, linear
%       detrending).
%
% integrateFlag
%       Input series is already integrated ( default= false ).
%
% minBoxSize
%       Smallest box width (default: 2p+2)
%
% maxBoxSize
%       Largest box width (default: N/4)
%
% slideWindowFlag
%       Sliding window DFA (default =false);
%
%
% The Output variables are:
%
% ln
%       A (MaxBoxSize -MinBoxSize) x 1 vector of log(boxsize)
%
% lf
%       A (MaxBoxSize -MinBoxSize) x 1 vector of the log of the root
%       mean square fluctuation for the given boxsize.
%
%
% Written by Ikaro Silva, 2014
% Last Modified: November 21, 2014
% Version 1.0
%
% Since 0.9.8
%
% %Example:
%
%  gqrs('mitdb/117');
%  [rr]=ann2rr('mitdb/117','qrs');
%  [ln,lf]=dfa(rr);
%  plot(ln,lf)

%
%
% See also MSENTROPY, SURROGATE

%endOfHelp

persistent javaWfdbExec config
if(isempty(javaWfdbExec))
    [javaWfdbExec,config]=getWfdbClass('dfa');
end

%Set default pararamter values
inputs={'x','p','integrateFlag','minBoxSize','maxBoxSize','slideWindowFlag'};
p=[];
integrateFlag=false;
minBoxSize=[];
maxBoxSize=[];
slideWindowFlag=false;
wfdb_argument={};
for n=1:nargin
    if(~isempty(varargin{n}))
        eval([inputs{n} '=varargin{n};'])
    end
end
if(~isempty(p))
    wfdb_argument{end+1}='-d';
    wfdb_argument{end+1}=[num2str(p)];
end
if(integrateFlag)
    wfdb_argument{end+1}='-i';
end
if(~isempty(minBoxSize))
    wfdb_argument{end+1}='-l';
    wfdb_argument{end+1}=[num2str(minBoxSize)];
end
if(~isempty(maxBoxSize))
    wfdb_argument{end+1}='-u';
    wfdb_argument{end+1}=[num2str(maxBoxSize)];
end
if(slideWindowFlag)
    wfdb_argument{end+1}='-s';
end

javaWfdbExec.setArguments(wfdb_argument);

if(config.inOctave)
    x=cellstr(num2str(x));
    x=java2mat(javaWfdbExec.execWithStandardInput(x));
    Nx=x.size;
    out=cell(Nx,1);
    for n=1:Nx
        out{n}=x.get(n-1);
    end
else
    out=cell(javaWfdbExec.execWithStandardInput(x).toArray);
end

M=length(out);
ln=zeros(M,1)+NaN;
lf=zeros(M,1)+NaN;
for m=1:M
    str=out{m};
    sep=regexp(str,'\s');
    ln(m)=str2num(str(1:sep));
    lf(m)=str2num(str(sep(1):end));
end


function [K] = ku1v0(x, xp, hyp, ubarp, vbarp, dt, i)

logsigmau = hyp(1);
logthetau = hyp(2);
logsigmav = hyp(3);
logthetav = hyp(4);

a1 = hyp(5);
a2 = hyp(6);

n_x = size(x,1);
n_xp = size(xp,1);

x = repmat(x,1,n_xp);
xp = repmat(xp',n_x,1);

ubarp = repmat(ubarp',n_x,1);
vbarp = repmat(vbarp',n_x,1);

switch i

case 0

K=(-1).*dt.*exp(1).^(logsigmau+(-2).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a2.*exp(1).^(2.*logthetau).*(ubarp.^2+ ...
  vbarp.^2)+a1.*((-1).*exp(1).^logthetau+(x+(-1).*xp).^2));

case 1 % logsigmau

K=(-1).*dt.*exp(1).^(logsigmau+(-2).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a2.*exp(1).^(2.*logthetau).*(ubarp.^2+ ...
  vbarp.^2)+a1.*((-1).*exp(1).^logthetau+(x+(-1).*xp).^2));

case 2 % logthetau

K=(-1/2).*dt.*exp(1).^(logsigmau+(-3).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*(a1.*(2.*exp(1).^(2.*logthetau)+(-5).*exp( ...
  1).^logthetau.*(x+(-1).*xp).^2+(x+(-1).*xp).^4)+a2.*exp(1).^(2.* ...
  logthetau).*(ubarp.^2+vbarp.^2).*(x+(-1).*xp).^2);

case 3 % logsigmav

K=0;

case 4 % logthetav

K=0;

case 5 % a1

K=(-1).*dt.*exp(1).^(logsigmau+(-2).*logthetau+(-1/2).*exp(1).^((-1).* ...
  logthetau).*(x+(-1).*xp).^2).*((-1).*exp(1).^logthetau+(x+(-1).*xp).^2); ...

case 6 % a2

K=(-1).*dt.*exp(1).^(logsigmau+(-1/2).*exp(1).^((-1).*logthetau).*(x+(-1) ...
  .*xp).^2).*(ubarp.^2+vbarp.^2);

otherwise

        K = zeros(n_x, n_xp);
end

if K == 0

    K = zeros(n_x, n_xp);

end

end


function strat = randomBetStrategy_timeseries(dat_dir, files, bet, hours, nValidOdds, nGamesStrategy, nSamps, preload, s1)

% 1- Select random sample of games, same number as number of games in Beat
% the Bookie strategy
% For each game, select random time before the game, random outcome (home, draw, away)
% bet on the maximum odds for that outcome at that time
% calculate returns

% Proportion of Home, Draw or away that our strategy employed
pHome = s1.pHome;
pDraw = s1.pDraw;
pAway = s1.pAway;

% preload all files for speed
if preload
   all_data = nan(32,length(cell2mat(hours)),size(files,1));
   for fi = 1 : size(files,1)
       if mod(fi,1000) == 0
          fprintf('Preloading Game #%d \n', fi)
       end
       fid = fopen([dat_dir files(fi).name], 'r');
       C = textscan(fid, repmat('%f ' , [1,72*3]), 'delimiter', ',');
       fclose(fid);
       aux = cell2mat(C);
       all_data(:,:,fi) =  aux(:,cell2mat(hours));
   end
   hours{1} = hours{1} - hours{1}(1) + 1;
   hours{2} = hours{2} - hours{2}(1) + 1 + length(hours{1});
   hours{3} = hours{3} - hours{3}(1) + 1 + length(hours{1}) + length(hours{3});
end

% Pre-allocate matrixes
money = nan(nSamps, nGamesStrategy);
money(:,1) = 0;
accuracy = nan(nSamps, nGamesStrategy);
ids = nan(nSamps, nGamesStrategy);
c = 1;
wodds = 1;
wZeros = 1;

for samp = 1 : nSamps

    fprintf('Sample #%d \n', samp);
    dat_rnd = randperm(size(files,1));
    m = 1; % counter for money (returns always start at '0')

    fi = 1;
    while 1

        % Loop through until we get all valid games for the strategy
        if (m) > nGamesStrategy
            break
        end

        if mod(fi,1000) == 0
            fprintf('Game #%d \n', fi);
        end

        if preload
            data = squeeze(all_data(:,:,dat_rnd(fi)));
        else
            fid = fopen([dat_dir files(dat_rnd(fi)).name], 'r');
            C = textscan(fid, repmat('%f ' , [1,72*3]), 'delimiter', ',');
            fclose(fid);
            data = cell2mat(C);
        end

        % sanity check: there are some games that had odds more than 8
        % hours away from the beginning of the game and then got cancelled.
        % We discard those few games here.
        if sum(isnan(data(:))) == (32 * 216)
            fprintf('Skip Game number %d, %s \n', dat_rnd(fi), files(dat_rnd(fi)).name);
            fi = fi + 1;
            continue;
        end

        % get result of the game
        name = strrep(files(dat_rnd(fi)).name, '.txt', '');
        C = strsplit(name, '_');
        score_home = str2double(C{end-1});
        score_away = str2double(C{end});
        if score_home > score_away
            result = 1;
        elseif score_home == score_away
            result = 2;
        else
            result = 3;
        end

        % Select what to bet (Home, Draw or away) according to the
        % respective probabilities. These probabilities come from
        % the results of our strategy.
        bet_result = sum(rand >= cumsum([0, pHome, pDraw, pAway]));

        % Choose time randomly
        randomTimeOutcome = randsample(hours{bet_result},1);

         % Check that there are at least nValidOdds in the selected hour
        if sum(~isnan(data(:, randomTimeOutcome))) < nValidOdds
%             fprintf('Game without odds')
            wodds = wodds + 1;
            fi = fi + 1;
            continue
        end

        if any(data(:, randomTimeOutcome)) == 0
%             fprintf('Game with odds 0')
            wZeros = wZeros + 1;
            fi = fi + 1;
            continue
        end

        % select max odds at time/outcome
        max_odds(samp, m) = nanmax(data(:, randomTimeOutcome));
        mean_odds(samp, m) = nanmean(data(:, randomTimeOutcome));

        % Estimate return for each game
        if (~isnan(max_odds(samp, m)))
            aux_possible_earn = bet  * (max_odds(samp, m) - 1);

            % calculate loss / earning
            if isequal(bet_result, result)
                money(samp, m + 1) = money(samp, m) + aux_possible_earn;
                accuracy(samp, m) = 1;
                ids(samp, m) = bet_result;
                m = m + 1;
            else
                money(samp, m + 1) = money(samp, m) - bet;
                accuracy(samp, m) = 0;
                ids(samp, m) = bet_result;
                m = m + 1;
            end

        % Some games have bookies with very few valid odds. Skip them
        else
            c = c + 1;
            fi = fi + 1;
            continue;
        end

        fi = fi + 1;
    end
end

% sprintf('There were %d games with invalid / insufficient number of odds', c)
strat.money = money;
strat.name = 'RandomStrategy';
strat.max_odds = max_odds;
strat.mean_odds = mean_odds;
strat.accuracy = accuracy;
strat.ids = ids;
strat.wodds = wodds;
strat.wZeros = wZeros;

end


function r8_erf_test ( )

%*****************************************************************************80
%
%% R8_ERF_TEST tests R8_ERF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 August 2010
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'R8_ERF_TEST:\n' );
  fprintf ( 1, '  R8_ERF evaluates the error function.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '     X      Exact F   R8_ERF(X)\n' );
  fprintf ( 1, '\n' );

  n_data = 0;

  while ( 1 )

    [ n_data, x, fx ] = erf_values ( n_data );

    if ( n_data == 0 )
      break
    end

    fx2 = r8_erf ( x );

    fprintf ( 1, '  %6f  %12f  %12f\n', x, fx, fx2 );

  end

  return
end


classdef SPX_MatchedFilter < handle

    properties(SetAccess=private)
        % The signals to be used by the filter
        Signals
    end

    methods
        function self  = SPX_MatchedFilter(signals)
            self.Signals  = signals;
        end

        function [ matchedFilterStatistic ] = apply(self, receivedSequence)
            %APPLY Computes matched filter based statistic on sequence
            signals = self.Signals;

            % Length of each signal to compare (N) and number of signals to compare (L)
            % Each signal is stored in one column
            % There are S such columns
            [N, S] = size(signals); % NxS
            % Number of received samples
            numReceivedSamples = length(receivedSequence);
            % Number of received bits
            B = round(numReceivedSamples/N);
            % We initialize output data
            % Number of rows = number of received bits
            % Each row contains results for each of the signals
            % Number of columns = number of signals
            % We reshape the received sequence
            % each column contains received sequence for one sample
            receivedSequence = reshape(receivedSequence, N, B); % NxB
            matchedFilterStatistic = receivedSequence' * signals;
        end
    end

    methods(Static)
        function [ matchedFilterStatistic ] = filter( receivedSequence,...
            signals )
            mf = SPX_MatchedFilter(signals);
            matchedFilterStatistic = mf.apply(receivedSequence);
        end
    end
end


% NMF-MU: NMF solved by Multiplicative Updates
% process_video('NMF', 'NMF-MU', 'dataset/demo.avi', 'output/demo_NMF-MU.avi');
alg_path_aux = fullfile(lrs_conf.nmf_path,'NMF-DTU-Toolbox');
addpath(genpath(alg_path_aux));

M = sparse(M);

% mm: Multiplicative update method using euclidean distance measure.
[W, H] = nmf(M,1,'mm');

L = W * H;
S = M - L;

rmpath(genpath(alg_path_aux));


function plot_mix_gaussian( u,sig,prob,X )
%
% plot_mix_gaussian - plot the samples and the estimation.
%                     for 1D distribution, plot the normalized histogram and the 1D distribution function
%                     for 2D distribution, plot the samples and the contour of FWHM
%                     for mD distribution (m>2) - do not plot nothing.
%
% format:   plot_mix_gaussian( u,sig,prob,X )
%
% input:    u       - mean of each gaussian in the distribution. 1xM vector or 2xM matrix.
%                     each gaussian mean is stored in a separate column.
%           sig     - for 1D distribution -> standard deviation of each gaussian in the distribution
%                     each gaussian mean is stored in a separate column -> a 1xM vector
%                     for 2D distribution -> covariance matrix for each gaussian in the distribution
%                     2x2xM matrix, the 3rd dimension is the gaussians index,
%                     the 1st and 2nd dimensions are the covariance matrix
%           prob    - probability of each gaussian in the distribution to create the current sample.
%                     this is a 1xM vector
%           X       - the samples, 1xN vector or 2xN matrix, depends on the dimension of the
%                     distribution (i.e. 1D or 2D)
%
% output:   to the graphic current axis.
%
%
%

% check input
if (nargin<3)
    error( 'plot_mix_gaussian - insufficient input parameters' );
end
if ~exist( 'X' )
    X = [];
end

% constants
nbins = 200;

% check the size of the input to determin if it's 1D or 2D distribution
if (size(u,1)==2) & (size(u,2)==size(prob,2))
    plot_mix_gaussian_2d( u,sig,prob,X );
else
    plot_mix_gaussian_1d( u,sig,prob,X,nbins );
end
drawnow;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                              Inner function implementation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function plot_mix_gaussian_1d( u,sig,prob,X,nbins )
% plot normalized histogram and normalized distribution on top of it

% constant
points = 1000;

if ~isempty( X )
    [n,x]   = hist( X,nbins );              % calc the histogram
    dx      = x(2)-x(1);                    % calc a single bin width
    n       = n / sum( n*dx );              % normalize histogram to have area of 1
    bar( x,n,'hist' );                      % plot normalized histogram
    xlim( [x(1)-dx/2,x(end)+dx/2] );        % make sure that the axis is squeezed to it's limits
    g       = gca;
    c       = [1 0 0];                      % choose the red color
    x_c     = linspace( x(1)-dx/2,x(end)+dx/2,points );
else
    g       = gca;
    X       = xlim( g );                    % get the axis limits
    c       = [0 1 0];                      % choose the green color
    x_c     = linspace( X(1),X(2),points );
end

% plot the distribution
for m = 1:length(prob)
    y   = prob(m) / sqrt( 2*pi*sig(m)^2 ) * exp( -((x_c-u(m)).^2)/(2*sig(m)^2) );
    line( x_c,y,'color',c,'parent',g,'linewidth',2 );
end
shg;
drawnow;

% ----------------------------------------------------------------------------------------

function plot_mix_gaussian_2d( u,covar,prob,X )
% plot 2D samples and distribution data on top of it

if ~isempty( X )
    if size(X,2)<size(X,1),
        X = X.';
    end
    plot( X(1,:),X(2,:),'.k' );             % plot samples
    xlim( [min(X(1,:)) max(X(1,:))] );      % squeeze axis limits
    ylim( [min(X(2,:)) max(X(2,:))] );       % squeeze axis limits
    g       = gca;
    c       = [1 0 0];                      % choose the red color
else
    g       = gca;
    c       = [0 1 0];                      % choose the green color
end

% plot each gaussian's FWHM and mean (center)
a           = linspace(0,2*pi,361); % degree vector
unit_circle = [cos(a);sin(a)];      % a unit circle for the case of sig_x=sig_y=1
for m = 1:length(prob)
    U       = u(:,m);               % the mean of the mth gaussian
    [V,D]   = eig(covar(:,:,m));    % eigen value and vectors for the covariance of the mth gaussian
    A       = V*sqrt(D);            % factorization: covar = A*A' = positive matrix
    outline = A * unit_circle * sqrt(2*log(2)) + U*ones(1,length(unit_circle)); % the contour
    line( U(1),U(2),'color',c,'parent',g,'marker','o' );
    line( outline(1,:),outline(2,:),'color',c,'parent',g,'linewidth',2 );
end


function a = c8vec_nint ( n, a )

%*****************************************************************************80
%
%% C8VEC_NINT rounds the entries of a C8VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 March 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, complex A(N), the vector to be rounded.
%
%    Output, complex A(N), the rounded vector.
%
  for i = 1 : n
    a(i) = c8_nint ( a(i) );
  end

  return
end


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
%
% Tutorial for FAIR: distances and SSD forces for hand data
%
%   - data                 Hand, Omega=(0,20)x(0,25), level=3:7, m=[128,128]
%   - viewer               viewImage2D
%   - interpolation        splineInter
%   - distance             MI
%   - transformation       translation2D
%==============================================================================

clear, close all, help(mfilename);

fprintf('setup data, viewer, interpolation, transformation\n');
setup2DhandData; level = 6; omega = ML{level}.omega; m = ML{level}.m;
viewImage('reset',viewPara{:},'axis','off');
imgModel('reset','imgModel','splineInter');
trafo('reset','trafo','translation2D');
R  = imgModel('coefficients',ML{level}.R,[],omega,'out',0);
xc = reshape(getCellCenteredGrid(omega,m),[],2);
yc = reshape(trafo([0.75;0],xc(:)),[],2);

fprintf('%20s : %s\n','viewImage',viewImage);
fprintf('%20s : %s\n','imgModel',imgModel);

% compute R(xc), T(yc), dT and forces
Rc = imgModel(R,omega,xc);
[Tc,dT] = imgModel(R,omega,yc);
dT = full(spdiags(dT,[0,size(dT,1)]));
F  = spdiags(Tc-Rc,0,length(Tc),length(Tc))*dT;

% compute lengthes for plots
fac = 128/norm(dT(:),'inf');
lengthdT = sqrt(sum(dT.^2,2));
normdT   = max(lengthdT);
J  = find(lengthdT>1e-2*normdT);
lengthF = sum(F.^2,2);
normF   = sqrt(max(lengthF));
K  = find(lengthF>1e-2*normF);

% plot R, T, T-R
FAIRfigure(1,'figname',mfilename); clf;
subplot(1,3,1);  viewImage(Rc,omega,m);            th(1) = title('R');
subplot(1,3,2);  viewImage(Tc,omega,m);            th(2) = title('T');
subplot(1,3,3);  viewImage(128+(Tc-Rc)/2,omega,m); th(3) = title('T-R');
set(th,'fontsize',30);
FAIRpause;

% plot \partial_j T and \nabla T
figure(2); clf;  colordef(gcf,'black');
subplot(1,3,1);  viewImage(128+fac*dT(:,1),omega,m);    th(1) = title('\partial_1T');
subplot(1,3,2);  viewImage(128+fac*dT(:,2),omega,m);    th(2) = title('\partial_2T');
subplot(1,3,3);  viewImage(128+Tc/2,omega,m); hold on;
qh = quiver(xc(J,1),xc(J,2),dT(J,1)/normdT,dT(J,2)/normdT,2);
set(qh,'color','b','linewidth',1.5);
th(3) = title('\nabla T');
set(th,'fontsize',30);
FAIRpause;

% plot \nabla T, T-R, forces
figure(3); clf;  colordef(gcf,'black');
subplot(1,3,1);  viewImage(128+Tc/2,omega,m); hold on;
qh = quiver(xc(J,1),xc(J,2),dT(J,1)/normdT,dT(J,2)/normdT,0);
set(qh,'color','b','linewidth',1.5);
th(1) = title('\nabla T');

subplot(1,3,2);  vh = viewImage(128+(Tc-Rc)/2,omega,m); th(2) = title('T-R');

subplot(1,3,3);  viewImage(128+Tc/2,omega,m); hold on;
qh = quiver(xc(K,1),xc(K,2),F(K,1)/normF,F(K,2)/normF,2);
set(qh,'color','r','linewidth',1.5);
th(3) = title('forces');
set(th','fontsize',30);

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


function material_cell = mean_material_node(grid3d, gt, material_node)

chkarg(istypesizeof(grid3d, 'Grid3d'), '"grid3d" should be instance of Grid.');
chkarg(istypesizeof(gt, 'GT'), '"gt" should be instance of GT.');
chkarg(istypesizeof(material_node, 'complexcell', [1 Axis.count], grid3d.N), ...
	'"material_node" should be length-%d cell array, whose each element is %d-by-%d-by-%d array with complex elements.', ...
	Axis.count, grid3d.Ncell{:});

for w = Axis.elems
	material_node{w} = expand_node_array(grid3d, material_node{w});  % (Nx+2) x (Ny+2) x (Nz+2)
end

if gt == GT.prim
	% material parameters for fields on primary grid
	material_cell = arithmetic_mean_material_node(material_node);
else  % gt == GT.dual
	% material parameters for fields on dual grid
	material_cell = harmonic_mean_material_node(material_node);
end

function material_edge_cell = arithmetic_mean_material_node(material_node)
material_edge_cell = cell(1, Axis.count);

material_edge_cell{Axis.x} = (...
	material_node{Axis.x}(2:end-1, 2:end-1, 2:end-1) ...
	+ material_node{Axis.x}(2:end-1, 1:end-2, 2:end-1) ...
	+ material_node{Axis.x}(2:end-1, 2:end-1, 1:end-2) ...
	+ material_node{Axis.x}(2:end-1, 1:end-2, 1:end-2)...
) / 4;

material_edge_cell{Axis.y} = (...
	material_node{Axis.y}(2:end-1, 2:end-1, 2:end-1) ...
	+ material_node{Axis.y}(2:end-1, 2:end-1, 1:end-2) ...
	+ material_node{Axis.y}(1:end-2, 2:end-1, 2:end-1) ...
	+ material_node{Axis.y}(1:end-2, 2:end-1, 1:end-2)...
) / 4;

material_edge_cell{Axis.z} = (...
	material_node{Axis.z}(2:end-1, 2:end-1, 2:end-1) ...
	+ material_node{Axis.z}(1:end-2, 2:end-1, 2:end-1) ...
	+ material_node{Axis.z}(2:end-1, 1:end-2, 2:end-1) ...
	+ material_node{Axis.z}(1:end-2, 1:end-2, 2:end-1)...
) / 4;

function material_face_cell = harmonic_mean_material_node(material_node)
material_face_cell = cell(1, Axis.count);
material_face_cell{Axis.x} = 2./(1./material_node{Axis.x}(1:end-2, 2:end-1, 2:end-1) + 1./material_node{Axis.x}(2:end-1, 2:end-1, 2:end-1));
material_face_cell{Axis.y} = 2./(1./material_node{Axis.y}(2:end-1, 1:end-2, 2:end-1) + 1./material_node{Axis.y}(2:end-1, 2:end-1, 2:end-1));
material_face_cell{Axis.z} = 2./(1./material_node{Axis.z}(2:end-1, 2:end-1, 1:end-2) + 1./material_node{Axis.z}(2:end-1, 2:end-1, 2:end-1));


function [y,feature_names,cache] = ComputeHarmonicWindowFeatures(x,varargin)

x = x(:)';
N = numel(x);
y = nan(0,N);
feature_names = {};

%% default parameters

[windows,window_offsets,...
  window_radii,min_window_radius,...
  max_window_radius,nwindow_radii] = ...
  SetDefaultWindowParameters();

% use all transformation types by default
%trans_types = 'all';
trans_types = uint8(15);

% for debugging purposes
SANITY_CHECK = true;

% whether to cache results
DOCACHE = true;

% initialize empty cache
cache = InitializeCache();

% initialize feature_types already computed to empty
feature_types = {};

% harmonic features
num_harmonic = 1;

% relative params
relativeParams = [];
%% parse parameters

[...
  windows,...
  window_radii,window_offsets,...
  min_window_radius,max_window_radius,nwindow_radii,...
  feature_types,...
  trans_types,...
  SANITY_CHECK,...
  DOCACHE,...
  cache,...
  num_harmonic,...
  relativeParams...
  ] = myparse(varargin,...
  'windows',windows,...
  'window_radii',window_radii,'window_offsets',window_offsets,...
  'min_window_radius',min_window_radius,'max_window_radius',max_window_radius,'nwindow_radii',nwindow_radii,...
  'feature_types',feature_types,...
  'trans_types',trans_types,...
  'sanitycheck',SANITY_CHECK,...
  'docache',DOCACHE,...
  'cache',cache,...
  'num_harmonic',num_harmonic,...
  'relativeParams',relativeParams); %#ok<ASGLU>

%% whether we've specified to use all trans types by default
%if ischar(trans_types) && strcmpi(trans_types,'all'),
%  trans_types = {'none','abs','flip','relative'};
%end

%% select default windows from various ways of specifying windows

[windows,window_radii,windowi2radiusi,nradii] = ...
  SetWindowParameters(...
  windows,window_offsets,...
  window_radii,min_window_radius,...
  max_window_radius,nwindow_radii);

%% main computation

%if ismember('relative',trans_types)
if bitand(8,trans_types)
  if DOCACHE && ~isempty(cache.relX)
    modX = cache.relX;
  else
    modX = convertToRelative(x,relativeParams);
    cache.relX = modX;
  end
end

for radiusi = 1:nradii,
  r = window_radii(radiusi);
  w = 2*r+1;

  for num_harmonic_curr = 1:num_harmonic,

    % can't split into more segments than frames
    if num_harmonic_curr >= w,
      continue;
    end

    res = HarmonicWindowCore(x,w,num_harmonic_curr);

    %if ismember('relative',trans_types),
    if bitand(8,trans_types),
       resRel = HarmonicWindowCore(modX,w,num_harmonic_curr);
    end

    % all offsets for this radius
    windowis = find(windowi2radiusi == radiusi);
    for windowi = windowis',
      off = windows(windowi,2);
      res1 = padgrab2(res,nan,1,1,1+off,N+off);

      %if ismember('none',trans_types),
      if bitand(1,trans_types),
        y(end+1,:) = res1; %#ok<*AGROW>
        feature_names{end+1} = {'stat','harmonic','trans','none','radius',r,'offset',off,'num_harmonic',num_harmonic_curr};
      end

      %if ismember('abs',trans_types),
      if bitand(2,trans_types),
        y(end+1,:) = abs(res1);
        feature_names{end+1} = {'stat','harmonic','trans','abs','radius',r,'offset',off,'num_harmonic',num_harmonic_curr};
      end

      %if ismember('relative',trans_types),
      if bitand(8,trans_types),
        resRel1 = padgrab2(resRel,nan,1,1,1+off,N+off);
        y(end+1,:) = resRel1;
        feature_names{end+1} = {'stat','harmonic','trans','relative','radius',r,'offset',off,'num_harmonic',num_harmonic_curr};
      end

      if SANITY_CHECK,
        extraStr = sprintf('num_harmonic = %d ',num_harmonic_curr);
        funcType = 'harmonic';

        %if ismember('none',trans_types),
        if bitand(1,trans_types),
          fastY = res1; %#ok<*AGROW>
          res_dumb = nan(1,N);
          for n_dumb = 1:N,
            r_dumb = min([r,n_dumb+off-1,N-n_dumb-off]);
            if r_dumb < 1,
              continue;
            end
            w_dumb = 2*r_dumb+1;
            fil_dumb = cos(linspace(0,pi*num_harmonic_curr,w_dumb))/w_dumb*(num_harmonic_curr+1);
            res_dumb(n_dumb) = sum(fil_dumb.*x(n_dumb+off-r_dumb:n_dumb+off+r_dumb));
          end
          checkSanity(fastY,res1,r,off,funcType,'none',extraStr);
        end

        %if ismember('abs',trans_types),
        if bitand(2,trans_types),
          fastY = abs(res1);
          res_dumb = nan(1,N);
          for n_dumb = 1:N,
            r_dumb = min([r,n_dumb+off-1,N-n_dumb-off]);
            if r_dumb < 1,
              continue;
            end
            w_dumb = 2*r_dumb+1;
            fil_dumb = cos(linspace(0,pi*num_harmonic_curr,w_dumb))/w_dumb*(num_harmonic_curr+1);
            res_dumb(n_dumb) = abs(sum(fil_dumb.*x(n_dumb+off-r_dumb:n_dumb+off+r_dumb)));
          end
          checkSanity(fastY,res1,r,off,funcType,'abs',extraStr);
        end
      end

    end
  end

end


%SOLVELIN Solve linear system Ax=b.
%
%   [ X, FLAG, T_SOLVE ] = SOLVELIN( A, B, TYPE, X0, VARARGIN ) Solves
%   the linear sparse system Ax = b with solver of TYPE (backslash,
%   mumps, gmres, bicgstab, or amg). X0 is an optional initial guess
%   for the iterative solver types (gmres/bicgstab/amg) and T_SOLVE is
%   the total time. FLAG returns 0 for success and ~0 otherwise.
%
%   See also SOLVESTAT, SOLVETIME

% Copyright 2013-2022 Precise Simulation, Ltd.


function [R] = F2R(F)
% Convert temperature from degrees Fahrenheit to Rankine.
R = F+459.67;


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
%
% function [y,dy] = translation3D(w,x,varargin)
%
% computes y = Q*w = and the derivative wrt. w.
% x = reshape(x,[],2);
% Q = [1 0 0; 0 1 0;0 0 1];  dy = Q:
% if no arguments are given, the parameters for the identity map are returned.
%
% see also transformations/contents.m, trafo.m
%==============================================================================

function [y,dy] = translation3D(w,x,varargin)

% the persistent variable Q stores the matrix
% Q(x) = kron( I_2 , [x(:,1),x(:,2),1] );
persistent Q

if nargin == 0,
  runMinimalExample;
  return;
else
  y = mfilename('fullfile');
  dy = [0;0;0];         % parameterization of identity
  if ischar(w),  Q  = []; w = []; end; % reset Q
  if isempty(w), return;          end;
end;

if isempty(w) || (size(Q,1) ~= numel(x)),
  n = length(x)/3;
  Q = sparse(kron(speye(3),ones(n,1)));
  if nargout == 0, return; end;
end;
y  = x + Q*w;
dy = Q;

%------------------------------------------------------------------------------
function runMinimalExample
help(mfilename);
fprintf('%s: minimal example\n',mfilename)

omega = [0,10,0,8,0,9]; m = [8,7,6];
c = (omega(2:2:end)-omega(1:2:end))'/2;
w = c/10
x = getCellCenteredGrid(omega,m);
z = feval(mfilename,w(:),x);
FAIRfigure(1); clf;
plotGrid(x,omega,m,'color','r'); axis image; hold on;
plotGrid(z,omega,m,'color','b'); axis image; hold off;

fctn = @(w) feval(mfilename,w,x);
w = w + randn(size(w));
checkDerivative(fctn,w,'fig',2);
%==============================================================================


clear all
close all
path(path,'..\..\FUZZCLUST')
colors={'r.' 'gx' 'b+' 'ys' 'md' 'cv' 'k.' 'r*' 'g*' 'b*' 'y*' 'm*' 'c*' 'k*' };

%the data
data.X=nDexample(5,250,2,1);
%normalization
data=clust_normalize(data,'range');

%parameters
param.c=3;
param.m=2;
param.val=1;
param.vis=1;
%Kmeans clustering
result=kmedoid(data,param);

%validation
result = validity(result,data,param);
%
result.validity


function i4_ceiling_test ( )

%*****************************************************************************80
%
%% I4_CEILING_TEST tests I4_CEILING.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 September 2014
%
%  Author:
%
%    John Burkardt
%
  r8_lo = -100.0;
  r8_hi =  100.0;
  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4_CEILING_TEST\n' );
  fprintf ( 1, '  I4_CEILING evaluates the "ceiling" of an R8.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '      R8    I4_CEILING(R8)\n' );
  fprintf ( 1, '\n' );

  for i = 1 : 10
    [ r8, seed ] = r8_uniform_ab ( r8_lo, r8_hi, seed );
    i4 = i4_ceiling ( r8 );
    fprintf ( 1, '  %8.4f            %4d\n', r8, i4 );
  end

  return
end


%MDL_PLANAR3 Create model of a simple planar 3-link mechanism
%
% MDL_PLANAR2 is a script that creates the workspace variable p3 which
% describes the kinematic characteristics of a simple redundant planar
% 3-link mechanism.
%
% Also defines the vector:
%   qz   corresponds to the zero joint angle configuration.
%
%
% Notes::
% - Moves in the XY plane.
% - No dynamics in this model.
%
% See also SerialLink, mdl_twolink, mdl_planar1, mdl_planar2.

% MODEL: generic, planar, 3DOF, standard_DH

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

a1 = 1;
a2 = 1;
a3 = 1;

p3 = SerialLink([
    Revolute('d', 0, 'a', a1, 'alpha', 0, 'standard')
    Revolute('d', 0, 'a', a2, 'alpha', 0, 'standard')
    Revolute('d', 0, 'a', a3, 'alpha', 0, 'standard')
    ], ...
    'name', 'three link');
qz = [0 0 0];


function pass = test_conj( pref )
% Test CONJ

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

tol = 100*pref.cheb2Prefs.chebfun2eps;

f = chebfun2(@(x,y) cos(x.*y));
g = conj( f );
pass(1) = ( norm( f - g ) < tol );

f = chebfun2(@(x,y) cos(x.*y));
g = conj( 1i*f );
pass(2) = ( norm( 1i*f + g ) < 100*tol );

f1 = chebfun2(@(x,y) cos(x.*y));
f2 = chebfun2(@(x,y) sin(x + y.^2));
g = conj( f1 + 1i*f2 );
pass(3) = ( norm( f1 - 1i*f2 - g ) < tol );

end


% Specification of Riemann problems

%  Shocktube problem of G.A. Sod, JCP 27:1, 1978
pleft = 1.0;  pright = 0.1; rholeft = 1.0;  rhoright = 0.125;
uleft = 0;  uright = 0; tend = 0.151; lambda = 0.45;	% lambda = dt/dx

% Lax test case: M. Arora and P.L. Roe: JCP 132:3-11,  1997
%pleft = 3.528;  pright = 0.571; rholeft = 0.445;  rhoright = 0.5;
%uleft = 0.698;  uright = 0; tend = 0.15; lambda = 0.3;	% lambda = dt/dx

% Mach = 3 test case: M. Arora and P.L. Roe: JCP 132:3-11,  1997
%pleft = 10.333;  pright = 1; rholeft = 3.857;  rhoright = 1;
%uleft = 0.92;  uright = 3.55; tend = 0.09; lambda = 0.3; % lambda = dt/dx

% Shocktube problem with supersonic zone
%pleft = 1;  pright = 0.02; rholeft = 1;  rhoright = 0.02;
%uleft = 0;  uright = 0; tend = 0.162; lambda = 0.4;	% lambda = dt/dx

% Contact discontinuity
%pleft = 0.5;  pright = 0.5; rholeft = 1.0;  rhoright = 0.6;
%uleft = 0;  uright = 0; tend = 1; lambda = 0.4; 	% lambda = dt/dx

% Stationary shock
%pleft = 1.0;  pright = 0.1; rholeft = 1.0;  rhoright = 0.125;
%uleft = -2;  uright = -2; tend = 0.1; lambda = 0.2; 	% lambda = dt/dx


function shoreline_test ( )

%*****************************************************************************80
%
%% SHORELINE_TEST tests the SHORELINE library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2012
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SHORELINE_TEST:\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the SHORELINE library.\n' );

  circle_centered_test ( );
  circle_offcenter_test ( );
  ellipse_centered_test ( );
  ellipse_slanted_test ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SHORELINE_TEST:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function circle_centered_test ( )

%*****************************************************************************80
%
%% CIRCLE_CENTERED_TEST uses a circle centered at the origin.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2012
%
%  Author:
%
%    John Burkardt
%
  global c
  global r

  fprintf ( 1, '\n' );
  fprintf ( 1, 'CIRCLE_CENTERED_TEST\n' );
%
%  C = [0,0],  R = 1.
%
  c = [ 0.0, 0.0 ];
  r = 1.0;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2 / 4.0;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  C = [0,0],  R = 1/2.
%
  c = [ 0.0, 0.0 ];
  r = 0.5;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2 / 4.0;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  C = [0,0],  R = 1/4.
%
  c = [ 0.0, 0.0 ];
  r = 0.25;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2 / 4.0;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  C = [0,0],  R = 1/8.
%
  c = [ 0.0, 0.0 ];
  r = 0.125;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2 / 4.0;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );

  return
end
function circle_offcenter_test ( )

%*****************************************************************************80
%
%% CIRCLE_OFFCENTER_TEST uses a circle not centered at the origin.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2012
%
%  Author:
%
%    John Burkardt
%
  global c
  global r

  fprintf ( 1, '\n' );
  fprintf ( 1, 'CIRCLE_OFFCENTER_TEST\n' );
%
%  C = [-1,0],  R = 1/2.
%
  c = [-1.0, 0.0 ];
  r = 0.50;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2 / 2.0;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1), c(2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  C = [0.5,0.5],  R = 1/4.
%
  c = [ 0.0, 0.0 ];
  r = 0.5;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  C = [0.75,0.50],  R = 1/4.
%
  c = [ 0.75, 0.50 ];
  r = 0.25;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );

  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  C = [1.0,1.0],  R = 1/2.
%
  c = [ 1.0, 1.0 ];
  r = 0.50;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r^2 / 4.0;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  R = %f, C = [%f,%f], Area = %f\n', r, c(1:2), area );
  shoreline ( @circle, m, n, x_min, x_max, y_min, y_max, step_num );

  return
end
function ellipse_centered_test ( )

%*****************************************************************************80
%
%% ELLIPSE_CENTERED_TEST uses an ellipse centered at the origin.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2012
%
%  Author:
%
%    John Burkardt
%
  global angle
  global c
  global r1
  global r2

  fprintf ( 1, '\n' );
  fprintf ( 1, 'ELLIPSE_CENTERED_TEST\n' );
%
%  Angle = 0.0, C = [0,0],  R1 = 0.75, R2 = 0.50;
%
  angle = 0.0;
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.50;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  Angle = 0.0, C = [0,0],  R1 = 0.75, R2 = 0.25
%
  angle = 0.0;
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.25;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  Angle = 0.0, C = [0,0],  R1 = 0.75, R2 = 0.125
%
  angle = 0.0;
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.125;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  Angle = 0.0, C = [0,0],  R1 = 0.75, R2 = 0.0625
%
  angle = 0.0;
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.0625;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );

  return
end
function ellipse_slanted_test ( )

%*****************************************************************************80
%
%% ELLIPSE_SLANTED_TEST uses a slanted ellipse centered at the origin.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2012
%
%  Author:
%
%    John Burkardt
%
  global angle
  global c
  global r1
  global r2

  fprintf ( 1, '\n' );
  fprintf ( 1, 'ELLIPSE_SLANTED_TEST\n' );
%
%  ANGLE = 0.0, C = [0,0],  R1 = 0.75, R2 = 0.25.
%
  angle = 0.0 * ( pi / 180.0 );
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.25;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  ANGLE = 30, C = [0,0],  R1 = 0.75, R2 = 0.25
%
  angle = 30.0 * ( pi / 180.0 );
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.25;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );
%
%  ANGLE = 45, C = [0,0],  R1 = 0.75, R2 = 0.125
%
  angle = 45.0 * ( pi / 180.0 );
  c = [ 0.0, 0.0 ];
  r1 = 0.75;
  r2 = 0.25;
  m = 11;
  n = 11;
  x_min = -1.0;
  x_max = +1.0;
  y_min = -1.0;
  y_max = +1.0;
  step_num = 4;

  area = pi * r1 * r2;
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Angle = %f, R = [%f,%f], C = [%f,%f], Area = %f\n', ...
    angle, r1, r2, c(1:2), area );
  shoreline ( @ellipse, m, n, x_min, x_max, y_min, y_max, step_num );

  return
end


function matrix_output=padded_cell2mat(cell_input,pad)
    % Convert a ragged cell array of arrays in a padded matrix
    % Pierre Morel 2015.

    %With cellfun
%     ticID=tic;
%     maxLength=max(cellfun(@numel,cell_input));
%     tempcell=cellfun(@(x)horzcat(2,x,NaN*zeros(1,maxLength-length(x))),cell_input,'UniformOutput',false);
%     matrix_output=cell2mat(tempcell);
%     disp(['padded matrix (cellfun) created in ' num2str(toc(ticID)) ' s'])

    if nargin<2
        pad=NaN;
    end

    %With for loop (faster than cellfun)
    %ticID=tic;
    lengths=cellfun(@numel,cell_input);
    maxLength=max(lengths);
    matrix_output=zeros(length(cell_input),maxLength)+pad;
    for k=1:length(cell_input)
        matrix_output(k,1:lengths(k))=cell_input{k};
    end
    %disp(['padded matrix (for loop)  created in ' num2str(toc(ticID)) ' s'])
end


function vexity = DeriveVexityFromInflection(properties,xL,xU)

% [point (changes to convex = 1/changes to concave = -1) ... ]
if isa(properties.inflection,'function_handle')
    data = properties.inflection(xL,xU);
    if isempty(data)
        vexity = 'none';
        return
    end
    data = [data inf];
else
    data = properties.inflection;
    data = [data inf];
end
convex = [data(2:2:end-1)];
points = data(1:2:end);
vexity = 'none';
for k = 1:length(points)-1
    if xL >= points(k) && xU <= points(k+1)
        if convex(k) == 1
            vexity = 'convex';
            return
        else
            vexity = 'concave';
            return
        end
    end
end


function [X,Y,Out] = TMac(data,known,Nway,coreNway,opts)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% tensor completion by parallel matrix factorization
% ==============================================================================
% solve
%  min_{X,Y} sum_{n=1}^N 0.5*alpha(n)*||Proj_{known}(Xn*Yn-Unfold_n(M))||_F^2
% ===============================================================================
%
% Input:
%       data: observed entries of the underlying tensor
%       known: indices of observed entries
%       Nway: the dimension of the underlying tensor
%       coreNway: estimated ranks of all mode matricizations
%       opts.
%           maxit: maximum number of iterations (default: 500)
%           tol: stopping tolerance (default: 1e-4)
%           maxT: maximum running time (sec) (default: 1e6)
%           alpha: weights in the model (default: alpha(n) = 1/N, any n)
%           alpha_adj: determine whether dynamically update alpha
%                       (default: 1 (yes))
%           rank_adj: determine rank-adjusting strategy
%                       (1: increase; -1: decrease; 0: fix)
%           rank_inc: rank increment if rank-increasing strategy is used
%           rank_min: minimum rank estimation
%           rank_max: maximum rank estimation
%
% Output:
%       X,Y: cell structs
%       Out.
%           iter: number of iterations
%           relerr1: relative change array of total fitting
%           relerr2: array of total fitting
%           alpha: final weights alpha (may be different from input)

N = length(Nway); coNway = zeros(1,N);
for n = 1:N
    coNway(n) = prod(Nway)/Nway(n);
end
nrmb = norm(data);
%% Parameters and defaults
if isfield(opts,'maxit')      maxit = opts.maxit;     else maxit = 500;             end
if isfield(opts,'tol')        tol = opts.tol;         else tol = 1e-4;              end
if isfield(opts,'maxT')       maxT = opts.maxT;       else maxT = 1e6;              end
if isfield(opts,'alpha')      alpha = opts.alpha;     else alpha = ones(1,N)/N;     end
if isfield(opts,'alpha_adj')
    alpha_adj = opts.alpha_adj;
else
    alpha_adj = 1;
end

if isfield(opts,'rank_adj') rank_adj = opts.rank_adj; else rank_adj = zeros(1,N);   end
if isfield(opts,'rank_inc') rank_inc = opts.rank_inc; else rank_inc = ones(1,N);    end
if isfield(opts,'rank_min') rank_min = opts.rank_min; else rank_min = ones(1,N);    end
if isfield(opts,'rank_max') rank_max = opts.rank_max; else rank_max = 50*ones(1,N); end

%% Data preprocessing and initialization
if isfield(opts,'X0')
    X = opts.X0;
else
    X = cell(1,N);
    for n = 1:N
        X{n} = randn(Nway(n),coreNway(n));
    end
end

if isfield(opts,'Y0')
    Y = opts.Y0;
else
    Y = cell(1,N);
    for n = 1:N
        Y{n} = randn(coreNway(n),coNway(n));
    end
end

% rescale the initial point based on number of elements
estMnrm = sqrt(nrmb^2*(prod(Nway)/length(known)));

for n = 1:N
    X{n} = X{n}/norm(X{n},'fro')*estMnrm^(Nway(n)/(Nway(n)+coNway(n)));
    Y{n} = Y{n}/norm(Y{n},'fro')*estMnrm^(coNway(n)/(Nway(n)+coNway(n)));
end

X0 = X; Y0 = Y;

[known,id] = sort(known); data = data(id);

M = zeros(Nway); M(known) = data;

sx = cell(1,N);
reschg = ones(1,N);
reschg_tol = max(1e-2,10*tol);
rank_inc_num = sum(rank_adj==1);

res0 = zeros(1,N); TotalRes = 0;
res = res0;
for n = 1:N
    Mn = Fold(X{n}*Y{n},Nway,n);
    res0(n) = norm(Mn(known)-data);
    TotalRes = TotalRes+res0(n);
end
solX = ones(1,N);
Xsq = cell(1,N); Yt = cell(1,N); spI = cell(1,N);
for n = 1:N
    Yt{n} = Y{n}';
end

Out.rank = coreNway;

start_time = tic;

alpha = alpha/sum(alpha);

fprintf('Iteration:     ');

for k = 1:maxit
    fprintf('\b\b\b\b\b%5i',k);

    % update (X,Y)
    for n = 1:N
        if alpha(n) > 0
            Mn = Unfold(M,Nway,n);
            if solX(n)
                X{n} = Mn*Yt{n};
            end
            solX(n) = 1;

            Xsq{n} = X{n}'*X{n};
            Y{n} = pinv(Xsq{n})*X{n}'*Mn;
            Yt{n} = Y{n}';

            if rank_adj(n) == -1
                %rank_dec_adaptive();
                rank_dec_adaptive(Xsq,n,coreNway,rank_min,rank_adj,X,X0,Y,Y0);
            end
        end
    end

    % update M
    Mn = Fold(X{1}*Y{1},Nway,1);
    res(1) = norm(Mn(known)-data);
    M = alpha(1)*Mn;
    for n = 2:N
        if alpha(n) > 0
        Mn = Fold(X{n}*Y{n},Nway,n);
        res(n) = norm(Mn(known)-data);
        M = M+alpha(n)*Mn;
        end
    end

    % pass the true tensor M for evaluation
    if isfield(opts,'Mtr')
        Out.truerel(k) = norm(M(:)-opts.Mtr(:))/norm(opts.Mtr(:));
    end

    M(known) = data;

    TotalRes0 = TotalRes;
    TotalRes = 0;
    for n = 1:N
        if alpha(n) > 0
            TotalRes = TotalRes+res(n)^2;
        end
    end
    ratio = res./res0;   reschg = abs(1-ratio);

    if rank_inc_num > 0
        for n = 1:N
            if alpha(n) > 0
            if coreNway(n) < rank_max(n) && reschg(n) < reschg_tol
                %rank_inc_adaptive();
                rank_inc_adaptive(M,Y,n,Yt,Y0,coreNway,rank_max,rank_inc,rank_inc_num,nstall,X0,solX,Nway,coNway);
            end
            end
        end
    end

    % adaptively update weight

    if alpha_adj ~= 0
        alpha = 1./(res.^2); alpha = alpha/sum(alpha);
    end

    % record how the rank estimates are updated
    Out.rank = [Out.rank; coreNway];

    % --- diagnostics, reporting, stopping checks ---
    relerr1 = abs(TotalRes-TotalRes0)/(TotalRes0+1);
    relerr2 = sum(alpha.*res)/nrmb;

    % reporting
    Out.hist_rel(1,k) = relerr1;
    Out.hist_rel(2,k) = relerr2;

    % check stopping criterion
    crit = relerr1<tol;
    if crit; nstall = nstall+1; else nstall = 0; end
    if nstall>=3 || relerr2<tol break; end
    if toc(start_time)>maxT; break; end;

    X0 = X; Y0 = Y; M0 = M;
    res0 = res;
end % main
fprintf('\n'); Out.iter = k;
Out.alpha = alpha;

end


function ue= f_ptos(signal1)
%  function to be used in the ptos program
% k1=100;%  N=1;
Na=signal1(1);
k1=signal1(2);
e=signal1(3);
k2=sqrt(2*k1/Na);
if  abs(e)<=1/k1
     ue=(k1/k2)*e;
else
    ue=sign(e)*(sqrt(2*Na*abs(e))- 1/k2);
end


function [C, sigma] = dataset3Params(X, y, Xval, yval)
%EX6PARAMS returns your choice of C and sigma for Part 3 of the exercise
%where you select the optimal (C, sigma) learning parameters to use for SVM
%with RBF kernel
%   [C, sigma] = EX6PARAMS(X, y, Xval, yval) returns your choice of C and
%   sigma. You should complete this function to return the optimal C and
%   sigma based on a cross-validation set.
%

% You need to return the following variables correctly.
C = 1;
sigma = 0.1;

param = [0.01 , 0.03, 0.1, 0.3, 1, 3, 10, 30];

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return the optimal C and sigma
%               learning parameters found using the cross validation set.
%               You can use svmPredict to predict the labels on the cross
%               validation set. For example,
%                   predictions = svmPredict(model, Xval);
%               will return the predictions on the cross validation set.
%
%  Note: You can compute the prediction error using
%        mean(double(predictions ~= yval))
%

minError = 10000.0;

%for CVal = param,
%	for sigmaVal = param,
%		model =  svmTrain(X, y, CVal, @(x1, x2) gaussianKernel(x1, x2, sigmaVal));
%		predictions = svmPredict(model , Xval);
%		error = mean(double(predictions ~= yval));
%		if minError > error,
%			minError = error;
%			C = CVal;
%			sigma = sigmaVal;
%		end
%	end
%end

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

end


function Y = vanherk(X,N,TYPE,varargin)
%  VANHERK    Fast max/min 1D filter
%
%    Y = VANHERK(X,N,TYPE) performs the 1D max/min filtering of the row
%    vector X using a N-length filter.
%    The filtering type is defined by TYPE = 'max' or 'min'. This function
%    uses the van Herk algorithm for min/max filters that demands only 3
%    min/max calculations per element, independently of the filter size.
%
%    If X is a 2D matrix, each row will be filtered separately.
%
%    Y = VANHERK(...,'col') performs the filtering on the columns of X.
%
%    Y = VANHERK(...,'shape') returns the subset of the filtering specified
%    by 'shape' :
%        'full'  - Returns the full filtering result,
%        'same'  - (default) Returns the central filter area that is the
%                   same size as X,
%        'valid' - Returns only the area where no filter elements are outside
%                  the image.
%
%    X can be uint8 or double. If X is uint8 the processing is quite faster, so
%    dont't use X as double, unless it is really necessary.
%

% Initialization
[direc, shape] = parse_inputs(varargin{:});
if strcmp(direc,'col')
   X = X';
end
if strcmp(TYPE,'max')
   maxfilt = 1;
elseif strcmp(TYPE,'min')
   maxfilt = 0;
else
   error([ 'TYPE must be ' char(39) 'max' char(39) ' or ' char(39) 'min' char(39) '.'])
end

% Correcting X size
fixsize = 0;
addel = 0;
if mod(size(X,2),N) ~= 0
   fixsize = 1;
   addel = N-mod(size(X,2),N);
   if maxfilt
      f = [ X zeros(size(X,1), addel) ];
   else
      f = [X repmat(X(:,end),1,addel)];
   end
else
   f = X;
end
lf = size(f,2);
lx = size(X,2);
clear X

% Declaring aux. mat.
g = f;
h = g;

% Filling g & h (aux. mat.)
ig = 1:N:size(f,2);
ih = ig + N - 1;

g(:,ig) = f(:,ig);
h(:,ih) = f(:,ih);

if maxfilt
   for i = 2 : N
      igold = ig;
      ihold = ih;

      ig = ig + 1;
      ih = ih - 1;

      g(:,ig) = max(f(:,ig),g(:,igold));
      h(:,ih) = max(f(:,ih),h(:,ihold));
   end
else
   for i = 2 : N
      igold = ig;
      ihold = ih;

      ig = ig + 1;
      ih = ih - 1;

      g(:,ig) = min(f(:,ig),g(:,igold));
      h(:,ih) = min(f(:,ih),h(:,ihold));
   end
end
clear f

% Comparing g & h
if strcmp(shape,'full')
   ig = [ N : 1 : lf ];
   ih = [ 1 : 1 : lf-N+1 ];
   if fixsize
      if maxfilt
         Y = [ g(:,1:N-1)  max(g(:,ig), h(:,ih))  h(:,end-N+2:end-addel) ];
      else
         Y = [ g(:,1:N-1)  min(g(:,ig), h(:,ih))  h(:,end-N+2:end-addel) ];
      end
   else
      if maxfilt
         Y = [ g(:,1:N-1)  max(g(:,ig), h(:,ih))  h(:,end-N+2:end) ];
      else
         Y = [ g(:,1:N-1)  min(g(:,ig), h(:,ih))  h(:,end-N+2:end) ];
      end
   end

elseif strcmp(shape,'same')
   if fixsize
      if addel > (N-1)/2
         %disp('hoi')
         ig = [ N : 1 : lf - addel + floor((N-1)/2) ];
         ih = [ 1 : 1 : lf-N+1 - addel + floor((N-1)/2)];
         if maxfilt
            Y = [ g(:,1+ceil((N-1)/2):N-1)  max(g(:,ig), h(:,ih)) ];
         else
            Y = [ g(:,1+ceil((N-1)/2):N-1)  min(g(:,ig), h(:,ih)) ];
         end
      else
         ig = [ N : 1 : lf ];
         ih = [ 1 : 1 : lf-N+1 ];
         if maxfilt
            Y = [ g(:,1+ceil((N-1)/2):N-1)  max(g(:,ig), h(:,ih))  h(:,lf-N+2:lf-N+1+floor((N-1)/2)-addel) ];
         else
            Y = [ g(:,1+ceil((N-1)/2):N-1)  min(g(:,ig), h(:,ih))  h(:,lf-N+2:lf-N+1+floor((N-1)/2)-addel) ];
         end
      end
   else % not fixsize (addel=0, lf=lx)
      ig = [ N : 1 : lx ];
      ih = [ 1 : 1 : lx-N+1 ];
      if maxfilt
         Y = [  g(:,N-ceil((N-1)/2):N-1) max( g(:,ig), h(:,ih) )  h(:,lx-N+2:lx-N+1+floor((N-1)/2)) ];
      else
         Y = [  g(:,N-ceil((N-1)/2):N-1) min( g(:,ig), h(:,ih) )  h(:,lx-N+2:lx-N+1+floor((N-1)/2)) ];
      end
   end

elseif strcmp(shape,'valid')
   ig = [ N : 1 : lx];
   ih = [ 1 : 1: lx-N+1];
   if maxfilt
      Y = [ max( g(:,ig), h(:,ih) ) ];
   else
      Y = [ min( g(:,ig), h(:,ih) ) ];
   end
end

if strcmp(direc,'col')
   Y = Y';
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [direc, shape] = parse_inputs(varargin)
direc = 'lin';
shape = 'same';
flag = [0 0]; % [dir shape]

for i = 1 : nargin
   t = varargin{i};
   if strcmp(t,'col') & flag(1) == 0
      direc = 'col';
      flag(1) = 1;
   elseif strcmp(t,'full') & flag(2) == 0
      shape = 'full';
      flag(2) = 1;
   elseif strcmp(t,'same') & flag(2) == 0
      shape = 'same';
      flag(2) = 1;
   elseif strcmp(t,'valid') & flag(2) == 0
      shape = 'valid';
      flag(2) = 1;
   else
      error(['Too many / Unkown parameter : ' t ])
   end
end


function [psi] = ftH2O2psi(ftH2O)
% Convert pressure from feet of water column at 4 degrees to pounds per
% square inch
% Chad Greene 2012
psi = ftH2O*0.433528;


function pz=v_lpcpp2pz(pp)
%V_LPCPP2PZ LPC: Convert power spectrum polynomial in cos(w) to power spectrum zeros PZ=(RP)
% pp is a polynomial such that |polyval(ra,e^jw)| = polyval(pp,cos(w))

%      Copyright (C) Mike Brookes 1998
%      Version: $Id: v_lpcpp2pz.m 10865 2018-09-21 17:22:45Z 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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

pz=roots(pp);


function C = curvature(DEM,ctype,varargin)

%CURVATURE 8-connected neighborhood curvature of a digital elevation model
%
% Syntax
%
%     C = curvature(DEM)
%     C = curvature(DEM,type)
%     C = curvature(DEM,type,pn,pv,...)
%
% Description
%
%     curvature returns the second numerical derivative (curvature) of a
%     digital elevation model. By default, curvature returns the profile
%     curvature (profc).
%
% Input arguments
%
%     DEM    digital elevation model (GRIDobj)
%     type   'profc' (default) : profile curvature [m^(-1)]
%            'planc' : planform curvature or contour curvature [m^(-1)]
%            'tangc' : tangential curvature [m^(-1)]
%            'meanc' : mean curvature [m^(-1)]
%            'total' : total curvature [m^(-2)]
%
%     Parameter name value/pairs
%
%     'useblockproc'    true or {false}: use block processing
%                       (see function blockproc)
%     'useparallel'     true or {false}: use parallel computing toolbox
%     'blocksize'       blocksize for blockproc (default: 5000)
%
% Output arguments
%
%     C      curvature (GRIDobj)
%
% Remarks
%
%     Please note that curvature is not defined for cells with zero
%     gradient. Here, curvature is set to zero.
%
%     All formulas are according to Schmidt et al. (2003) on page 800.
%
% Example
%
%     DEM = GRIDobj('srtm_bigtujunga30m_utm11.tif');
%     DEM = filter(DEM);
%     C = curvature(DEM,'planc');
%     imageschs(DEM,C,'percentclip',0.1)
%
% Reference
%
%     Schmidt, J., Evans, I.S., Brinkmann, J., 2003. Comparison of
%     polynomial models for land surface curvature calculation.
%     International Journal of Geographical Information Science 17,
%     797-814. doi:10.1080/13658810310001596058
%
% See also: GRIDobj/gradient8
%
% Author:  Wolfgang Schwanghart (w.schwanghart[at]geo.uni-potsdam.de)
% Date: 17. August, 2017

% check input arguments
narginchk(1,inf);
if nargin == 1
    ctype = 'profc';
else
    ctype = validatestring(ctype,{'profc','planc','tangc','meanc','total'});
end

p = inputParser;
p.FunctionName = 'GRIDobj/curvature';
addParamValue(p,'useblockproc',false,@(x) isscalar(x));
addParamValue(p,'blocksize',5000,@(x) isscalar(x));
addParamValue(p,'useparallel',false,@(x) isscalar(x));
parse(p,varargin{:});

% create a copy of the DEM instance
C = DEM;
c = class(DEM.Z);
switch c
    case 'double'
        C.Z = double.empty(0,0);
    otherwise
        C.Z = single.empty(0,0);
end

% Large matrix support. Break calculations in chunks using blockproc
% Parallisation for large grids using blockproc does in my experience with
% four cores hardly increase the speed.
if p.Results.useblockproc
    blksiz = bestblk(size(DEM.Z),p.Results.blocksize);
    cs  = C.cellsize;
    fun = @(x) curvaturesub(x,cs,ctype);
    C.Z = blockproc(DEM.Z,blksiz,fun,...
           'BorderSize',[1 1],...
           'Padmethod','symmetric',...
           'UseParallel',p.Results.useparallel);
else
    C.Z = curvaturesub(DEM.Z,C.cellsize,ctype);
end

C.name = ctype;

end
% subfunction

function curv = curvaturesub(dem,cs,ctype)

if isstruct(dem);
    dem = dem.data;
    % DEM has already been padded
    correctedges = false;
    shape = 'same';
else
    correctedges = true;
    shape = 'valid';
end

% First-order partial derivatives:
[fx,fy] = gradient(dem,cs);

if correctedges
    dem = padarray(dem,[1 1],'symmetric');
end
% Second order derivatives according to Evans method (see Olaya 2009)
%
% z1 z2 z3
% z4 z5 z6
% z7 z8 z9

% kernel for d2z/dx2
kernel = [1 -2 1; 1 -2 1; 1 -2 1]./(3*cs.^2);
fxx = conv2(dem,kernel,shape);
% kernel for d2z/dy2
kernel = kernel';
fyy = conv2(dem,kernel,shape);
% kernel for d2z/dxy
kernel = [-1 0 1; 0 0 0; 1 0 -1]./(4*cs.^2);
fxy = conv2(dem,kernel,shape);

%% Other options to calculate Second-order partial derivatives:
% r = gradient(p,cs);
% t = gradient(q',cs)';
% % Second-order mixed partial derivative:
% s = gradient(p',cs)';

switch ctype
    case 'profc'
        curv = - (fx.^2 .* fxx + 2*fx.*fy.*fxy + fy.^2.*fyy)./((fx.^2 + fy.^2).*(1 + fx.^2 + fy.^2).^(3/2));
    case 'tangc'
        curv = - (fy.^2 .* fxx + 2*fx.*fy.*fxy + fx.^2.*fyy)./((fx.^2 + fy.^2).*(1 + fx.^2 + fy.^2).^(1/2));
    case 'planc'
        curv = - (fy.^2 .* fxx + 2*fx.*fy.*fxy + fx.^2.*fyy)./((fx.^2 + fy.^2).^(3/2));
    case 'meanc'
        curv = - ((1+fy.^2).*fxx - 2.*fxy.*fx.*fy + (1+fx.^2).*fyy)./ ...
            (2.* (fx.^2+fy.^2+1).^(3/2));
%         curv = (fx.^2 .* fxx + 2*fx.*fy.*fxy + fy.^2.*fyy)./((fx.^2 + fy.^2).*(1 + fx.^2 + fy.^2)) ...
%             - ((1+fy).^2 .* fxx + 2*fx.*fy.*fxy + (1+fx).^2.*fyy)./(2.*(1 + fx.^2 + fy.^2).^(3/2));
    case 'total'
        curv = fxx.^2 + 2*fxy.^2+fyy.^2;
end

if correctedges
    dem = dem(2:end-1,2:end-1);
end
curv(isinf(curv) | isnan(curv)) = 0;
curv(isnan(dem)) = nan;
curv = reshape(curv,size(dem));

end


function probRuin = calcProbRuin(EquitySAVal)
% A helper function that calculates the probability of ruin given the
% account values.

probRuin = sum(min(EquitySAVal) == 0) / size(EquitySAVal, 2);
end


function G = Kernel_Integration_Approx(dt, para)

G = zeros(length(dt(:)), size(para.g,2));

M = size(para.g,1);
Nums = ceil(dt./para.dt);
for i = 1:length(dt(:))
    if Nums(i)<=M
        G(i,:) = sum(para.g(1:Nums(i),:)).*para.dt;
    else
        G(i,:) = sum(para.g).*para.dt;
    end
end


function out=asin(x)

out=-i.*log(i.*x+sqrt(1-x.^2));


function plotXY(x1, x2, y1, y2,h_newfig, fontsize)

% fontsize= 20;
if h_newfig
    figure;
    set(gcf,'position',[500,100,1000,650])
    set(gcf,'color','w');
end

mArrow2(x1,0,x2,0,{'color','k'});
mArrow2(0,y1,0,y2,{'color','k'});
xlim([x1,x2])
ylim([y1,y2])
set(gca,'visible','off');

% (x1+1):10:(x2-1)
for i = unique(round([linspace(x1*0.9, x2*0.9,7),0]))
    line([i i],[-(y2-y1)*0.005 (y2-y1)*0.005],'color','k')
    line([-(x2-x1)*0.005 (x2-x1)*0.005],[i i],'color','k')

    % xticks
    if i<=0
        t= text(i-(y2-y1)*0.03, -(x2-x1)*0.025,num2str(round(i)));
    else
        t= text(i-(y2-y1)*0.02, -(x2-x1)*0.025,num2str(round(i)));
    end
    t.FontSize=fontsize;

    % yticks
    if i<0
        t = text((y2-y1)*0.01, i, num2str(round(i)));
    elseif i>0
        t = text((y2-y1)*0.01, i, num2str(round(i)));
    end
    t.FontSize = fontsize;
end

t = text(x2*0.97,(y2-y1)*0.03,'$$x$$','Interpreter','latex');
t.FontSize = fontsize;
t = text(-(x2-x1)*0.03,y2*1,'$$y$$','Interpreter','latex');
t.FontSize = fontsize;
axis square

end

function [ h ] = mArrow2(x1,y1,x2,y2,props)

h = annotation('arrow');
set(h,'parent', gca, ...
    'position', [x1,y1,x2-x1,y2-y1], ...
    'HeadLength', 10, 'HeadWidth', 10, 'HeadStyle', 'cback1', ...
    props{:} );
end


function [ x, y ] = srot ( n, x, incx, y, incy, c, s )

%*****************************************************************************80
%
%% SROT applies a plane rotation.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 November 2006
%
%  Author:
%
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979.
%
%    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
%    Basic Linear Algebra Subprograms for Fortran Usage,
%    Algorithm 539,
%    ACM Transactions on Mathematical Software,
%    Volume 5, Number 3, September 1979, pages 308-323.
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vectors.
%
%    Input, real X(*), one of the vectors to be rotated.
%
%    Input, integer INCX, the increment between successive entries of X.
%
%    Input, real Y(*), one of the vectors to be rotated.
%
%    Input, integer INCY, the increment between successive elements of Y.
%
%    Input, real C, S, parameters (presumably the cosine and
%    sine of some angle) that define a plane rotation.
%
%    Output, real X(*), the rotated vector.
%
%    Output, real Y(*), the rotated vector.
%
  if ( n <= 0 )

    x = [];
    y = [];

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

    for i = 1 : n
      stemp = c * x(i) + s * y(i);
      y(i) =  c * y(i) - s * x(i);
      x(i) = stemp;
    end

  else

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

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

    for i = 1 : n
      stemp = c * x(ix) + s * y(iy);
      y(iy) = c * y(iy) - s * x(ix);
      x(ix) = stemp;
      ix = ix + incx;
      iy = iy + incy;
    end

  end

  return
end


function seq=seqa(a,b,c);
% PURPOSE: produce a sequence of values
% -----------------------------------------------------
% USAGE: y = seqa(a,b,c)
%  where    a = initial value in sequence
%           b = increment
%           c = number of values in the sequence
% -----------------------------------------------------
% RETURNS: a sequence, (a:b:(a+b*(c-1)))' in MATLAB notation
% -----------------------------------------------------
% NOTE: a Gauss compatability function
% -----------------------------------------------------

% written by:
% James P. LeSage, Dept of Economics
% University of Toledo
% 2801 W. Bancroft St,
% Toledo, OH 43606
% jpl@jpl.econ.utoledo.edu

% seqa Gauss eqivalent of seqa(a,b,c)
seq=(a:b:(a+b*(c-1)))';
return;


function prob_thin = probThin(BandCirrus)
%PROBCIRRUS
    prob_thin = BandCirrus./400;
    clear BandCirrus;
%     prob_thin(prob_thin>1)=1;
    prob_thin(prob_thin<0)=0;
end