function fh = GNSSspectrumgen
%==========================================================================
%GNSSspectrumgen Functions to generate GNSS analytical spectra.
%   fh = GNSSspectrumgen  returns the handlers of the local functions:
%
%   spectrumgen_call
%   [SI SQ] = spectrumgen_call(signal,F) returns the analytical complex
%   spectra of a GNSS signal with normalized complex power.
%
%       Inputs
%           signal --> GPS L1: L1CA, L1P, L1M, L1C, L1Cd, L1Cp, L1Cp1,L1Cp2
%                              L1, L1_new.
%                      GPS L2: L2C, L2P, L2M, L2, L2_new.
%                      GPS L5: L5I, L5Q, L5, L5_new
%                      Galileo E1: E1PRS/EA, E1OS.
%                      Galileo E6: E6PRS/E6OS.
%                      Galileo E5: E5, E5A, E5B.
%                      BeiDou-2 Current:
%                      	B1: B11, B12, B1
%                       B2: B2I, B2Q, B2
%                       B3: B3
%                      BeiDou-2 Future:
%                       B1: B1Cd, B1Cp, B1C, B1_new
%                       B2: B2_new
%                       B3: B3_new, B3A, B3composite
%           F --> Baseband frequency points.
%
%       Ouputs
%           SI/SQ --> Normalized complex spectrum.
%
%   spectrum_BPSK
%   S = spectrum_BPSK(fc,F) returns spectrum of a BPSK modulation with a
%   chipping rate fc.
%
%   spectrum_BOCs
%   S = spectrum_BOCs(n,m,F) returns spectrum of a sine-phased even BOC
%   modulation with a chipping rate fc=m*1.023e6 and sub-carrier rate
%   fs = n*1.023e6.
%
%   spectrum_BOCc
%   S = spectrum_BOCc(n,m,F) returns spectrum of a cosine-phased even BOC
%   modulation with a chipping  rate fc=m*1.023e6 and sub-carrier rate
%   fs = n*1.023e6.
%
%   spectrum_AltBOC returns spectrum of a sine-phased
%   modified even AltBOC modulation with a chipping rate fc=m*1.023e6 and
%   sub-carrier rate fs = n*1.023e6.
%
%   Observations
%       # I think that L2 can also transmit a C/A component, but that they
%       actually never do it.
%       # I am not sure if the future BeiDou signals will replace or
%       complement the former signals. Now I assume they will replace them.
%       # I cound't find the official transmitted powers of the BeiDou
%       signals anywhere. I have assumed they are -163dBm per component.
%
%   References
%       # L1CA/L2: GPS Interface Control Document IS-GPS-200
%       # L1C:  GPS Interface Control Document IS-GPS-800
%       # L5: GPS Interface Control Document IS-GPS-705
%       # Galileo: Galileo Open Service Signal In Space Interface Control
%       Document (OS SIS ICD)
%       # BeiDou: BeiDou Navigation Satellite System Signal In Space
%       Interface Control Document 2.0
%--------------------------------------------------------------------------
% Version log (main changes)
%   02/03/2017 --> Log started
%--------------------------------------------------------------------------
% Author: Daniel Pascual (daniel.pascual [at] protonmail.com)
% Copyright 2017 Daniel Pascual
% License: GNU GPLv3
%==========================================================================

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

    fh.spectrumgen_call = @spectrumgen_call;
    fh.spectrum_BPSK = @spectrum_BPSK;
    fh.spectrum_BOCs = @spectrum_BOCs;
    fh.spectrum_BOCc = @spectrum_BOCc;
    fh.spectrum_AltBOC = @spectrum_AltBOC;
end

function [SI, SQ] = spectrumgen_call(signal,F)
%==========================================================================
%
%--------------------------------------------------------------------------
% Author: Daniel Pascual (daniel.pascual [at] protonmail.com)
% Copyright 2017 Daniel Pascual
% License: GNU GPLv3
%==========================================================================

    switch(signal)
        %-------------------- All GNSS individual -------------------------
        % BPSK
        case {'L1CA', 'L2C'}
            SI = spectrum_BPSK(1.023e6,F);
            SQ = zeros(size(SI));

        case {'E6CS'}
            SI = spectrum_BPSK(5*1.023e6,F);
            SQ = zeros(size(SI));

        case {'L1P', 'L2P', 'L5I', 'L5Q'}
            SI = spectrum_BPSK(10.23e6,F);
            SQ = zeros(size(SI));

        % BOCs
        case{'L1Cd','L1Cp1'}
            SI = spectrum_BOCs(1,1,F);
            SQ = zeros(size(SI));

        case{'L1Cp2'}
            SI = spectrum_BOCs(6,1,F);
            SQ = zeros(size(SI));

        case {'L1M','L2M'}
            SI = spectrum_BOCs(10,5,F);
            SQ = zeros(size(SI));

        case{'L1Cp'}
            P_Cp1 = GNSS_POWERS.GPS_L1_Cp1/GNSS_POWERS.GPS_L1_Cp;
            P_Cp2 = GNSS_POWERS.GPS_L1_Cp2/GNSS_POWERS.GPS_L1_Cp;

            S_Cp1 = P_Cp1*spectrumgen_call('L1Cp1',F);
            S_Cp2 = P_Cp2*spectrumgen_call('L1Cp2',F);

            SI = S_Cp1 + S_Cp2;
            SQ = zeros(size(SI));

        case{'L1C'}
            P_Cd = GNSS_POWERS.GPS_L1_Cd/GNSS_POWERS.GPS_L1_C;
            P_Cp = GNSS_POWERS.GPS_L1_Cp/GNSS_POWERS.GPS_L1_C;

            S_Cd = P_Cd*spectrumgen_call('L1Cd',F);
            S_Cp = P_Cp*spectrumgen_call('L1Cp',F);

            SI = S_Cd;
            SQ = S_Cp;

        case 'E1OS'
            SI = (10/11)*spectrum_BOCs(1,1,F)+(1/11)*spectrum_BOCs(6,1,F);
            SQ = zeros(size(SI));

        % BOCc
        case {'E6A','E6PRS'}
            SI = spectrum_BOCc(10,5,F);
            SQ = zeros(size(SI));

        case {'E1A','E1PRS'}
            SI = spectrum_BOCc(15,2.5,F);
            SQ = zeros(size(SI));

        %-------------------- GPS L1  -------------------------------------
        % Prior to Block III
        case 'L1'
            P_M = GNSS_POWERS.GPS_L1_M/GNSS_POWERS.GPS_L1;
            P_P = GNSS_POWERS.GPS_L1_P/GNSS_POWERS.GPS_L1;
            P_CA =  GNSS_POWERS.GPS_L1_CA/GNSS_POWERS.GPS_L1;

            S_CA = P_CA*spectrumgen_call('L1CA',F);
            S_P = P_P*spectrumgen_call('L1P',F);
            S_M = P_M*spectrumgen_call('L1M',F);

            SI = S_P+S_M;
            SQ = S_CA;

        % Block III (includes L1C)
        case 'L1_new'

            P_M = GNSS_POWERS.GPS_L1_M/GNSS_POWERS.GPS_L1_new;
            P_P = GNSS_POWERS.GPS_L1_P/GNSS_POWERS.GPS_L1_new;
            P_CA = GNSS_POWERS.GPS_L1_CA/GNSS_POWERS.GPS_L1_new;
            P_C = GNSS_POWERS.GPS_L1_C/GNSS_POWERS.GPS_L1_new;

            S_CA = P_CA*spectrumgen_call('L1CA',F);
            S_P = P_P*spectrumgen_call('L1P',F);
            S_M = P_M*spectrumgen_call('L1M',F);
            [S_Cd, S_Cp] = spectrumgen_call('L1C',F);
            S_Cd = S_Cd*P_C;
            S_Cp = S_Cp*P_C;

            SI = S_P+S_M+S_Cd;
            SQ = S_CA+S_Cp;

        %-------------------- GPS L2  -------------------------------------
        case 'L2_new'

            P_P = GNSS_POWERS.GPS_L2_P_new/GNSS_POWERS.GPS_L2_new;
            P_C = GNSS_POWERS.GPS_L2_C/GNSS_POWERS.GPS_L2_new;
            P_M = GNSS_POWERS.GPS_L2_M/GNSS_POWERS.GPS_L2_new;

            S_P = P_P*spectrumgen_call('L2P',F);
            S_C = P_C*spectrumgen_call('L2C',F);
            S_M = P_M*spectrumgen_call('L2M',F);

            SI = S_P+S_M;
            SQ = S_C;

        case 'L2_new_2'

            P_P = GNSS_POWERS.GPS_L2_P_new/GNSS_POWERS.GPS_L2_new_2;
            P_C =  GNSS_POWERS.GPS_L2_C_new/GNSS_POWERS.GPS_L2_new_2;
            P_M =  GNSS_POWERS.GPS_L2_M/GNSS_POWERS.GPS_L2_new_2;

            S_P =   P_P*spectrumgen_call('L2P',F);
            S_C =   P_C*spectrumgen_call('L2C',F);
            S_M =   P_M*spectrumgen_call('L2M',F);

            SI = S_P+S_M;
            SQ = S_C;

        %-------------------- GPS L5  -------------------------------------
        case {'L5', 'L5_new'}
            SI = 0.5*spectrumgen_call('L5I',F);
            SQ = SI;

        %-------------------- Galileo E1 ----------------------------------
        case {'E1'}
            P_E1PRS = 0.5;
            P_E1OS = 0.5;

            S_E1PRS = P_E1PRS*spectrumgen_call('E1PRS',F);
            S_E1OS = P_E1OS*spectrumgen_call('E1OS',F);

            SI = S_E1OS;
            SQ = S_E1PRS;

        %-------------------- Galileo E6 ----------------------------------
        case 'E6'
            P_E6A = 0.5;
            P_E6B = 0.5;

            S_E6PRS = P_E6A*spectrumgen_call('E6PRS',F);
            S_E6CS = P_E6B*spectrumgen_call('E6CS',F);

            SI = S_E6CS;
            SQ = S_E6PRS;

        %-------------------- Galileo E5 ----------------------------------
       case 'E5'
            SI = 0.5*spectrum_AltBOC(15,10,F);
            SQ = SI;

        case {'E5A','E5B'}
            aux = spectrum_AltBOC(15,10,F);
            len = floor(length(aux)/2);
            aux2 = [aux(1:len+1) zeros(1,len)];
            len2 = floor(length(aux2)/2);
            [~, aux3] =  max(aux2);
            SI =  0.5*2*circshift(aux2',len2-aux3)';  % actually is not exactly multply by 2..
            SQ = SI;

        %-------------------- BeiDou-2 current ----------------------------
        % B1
        case {'B1','B11','B12'}
            SI = 0.5*spectrum_BPSK(2*1.023e6,F);
            SQ = 0.5*spectrum_BPSK(2*1.023e6,F);

        % B2
        case {'B2Q'}
            SI = spectrum_BPSK(10*1.023e6,F);
            SQ = zeros(size(SI));
        case {'B2I'}
            SI = spectrum_BPSK(2*1.023e6,F);
            SQ = zeros(size(SI));
        case{'B2'}
            P_B2Q = 0.5;
            P_B2I = 0.5;

            SQ = P_B2Q*spectrumgen_call('B2Q',F);
            SI = P_B2I*spectrumgen_call('B2I',F);

        % B3
        case{'B3'}
             SI = 0.5*spectrum_BPSK(10*1.023e6,F);
             SQ = SI;

        %-------------------- BeiDou-2 future -----------------------------
        % B1
        case {'B1Cd'}
            SI = spectrum_BOCs(1,1,F);
            SQ = zeros(size(SI));

        case {'B1Cp'}
            SI = spectrum_BOCs(6,1,F);
            SQ = zeros(size(SI));

        case {'B1C'}
            P_B1Cd = (10/11);
            P_B1Cp = (1/11);

            S_B1Cd = P_B1Cd*spectrumgen_call('B1Cd',F);
            S_B1Cp = P_B1Cp*spectrumgen_call('B1Cp',F);

            SI = S_B1Cd + S_B1Cp;
            SQ = zeros(size(SI));

        case {'B1_new'}
            SI = spectrum_BOCs(14,2,F);
            SQ = zeros(size(SI));

        case {'B1composite'}
            P_B1C = GNSS_POWERS.BEIDOU_B1C/GNSS_POWERS.BEIDOU_B1_composite;
            P_B1_new = GNSS_POWERS.BEIDOU_B1_new/GNSS_POWERS.BEIDOU_B1_composite;

            S_B1C = P_B1C*spectrumgen_call('B1C',F);
            S_B1_new = P_B1_new*spectrumgen_call('B1_new',F);

            SI = S_B1C+S_B1_new;
            SQ = zeros(size(SI));

        % B2
        case{'B2_new'}
            SI = 0.5*spectrum_AltBOC(15,10,F);
            SQ = 0.5*spectrum_AltBOC(15,10,F);

        % B3
        case{'B3_new'}
            SI = 0.5*spectrum_BPSK(10*1.023e6,F);
            SQ = 0.5*SI;
        case{'B3A'}
            S = spectrum_BOCs(15,2.5,F);
            SQ = zeros(size(SI));

        case {'B3composite'}
            P_B3_new = GNSS_POWERS.BEIDOU_B3_new/GNSS_POWERS.BEIDOU_B3_composite;
            P_B3A = GNSS_POWERS.BEIDOU_B3A/GNSS_POWERS.BEIDOU_B3_composite;

            S_B3_new = P_B3_new*spectrumgen_call('B3_new',F);
            S_B3A = P_B3A*spectrumgen_call('B3A',F);

            SI = S_B3_new;
            SQ = S_B3A;
    end
    end

function S = spectrum_BPSK(fc,F)
%==========================================================================
% BPSK of chipping rate fc.
%--------------------------------------------------------------------------
% Author: Daniel Pascual (daniel.pascual [at] protonmail.com)
% Copyright 2017 Daniel Pascual
% License: GNU GPLv3
%==========================================================================

    S = sinc((1/fc)*F);
    aux = sum(abs(S).^2)/length(S);
    S = S/sqrt(aux);
    S = abs(S).^2;
end

function S = spectrum_BOCs(n,m,F)
%==========================================================================
% sine-phased BOC even of a chipping rate fc=m*1.023e6 and sub-carrier rate
% of fs = n*1.023e6.
%--------------------------------------------------------------------------
% Author: Daniel Pascual (daniel.pascual [at] protonmail.com)
% Copyright 2017 Daniel Pascual
% License: GNU GPLv3
%==========================================================================

    fs = n*1.023e6;
    fc = m*1.023e6;

    S = sinc((1/fc)*F).*tan(pi*F/(2*fs));
    aux = sum(abs(S).^2)/length(S);
    S = S/sqrt(aux);
    S = abs(S).^2;
end

function S = spectrum_BOCc(n,m,F)
%==========================================================================
% cosine-phased BOC even of a chipping rate fc=m*1.023e6 and sub-carrier
% rate of fs = n*1.023e6.
%--------------------------------------------------------------------------
% Author: Daniel Pascual (daniel.pascual [at] protonmail.com)
% Copyright 2017 Daniel Pascual
% License: GNU GPLv3
%==========================================================================

    fs = n*1.023e6;
    fc = m*1.023e6;

    S = 2*sinc((1/fc)*F).*((sin(pi*F/(4*fs)).^2)./cos(pi*F/(2*fs)));
    aux = sum(abs(S).^2)/length(S);
    S = S/sqrt(aux);
    S = abs(S).^2;
end

function S = spectrum_AltBOC(n,m,F)
%==========================================================================
% sine-phased AltBOC even of a chipping rate fc=m*1.023e6 and sub-carrier
% rate of fs = n*1.023e6.
%--------------------------------------------------------------------------
% Author: Daniel Pascual (daniel.pascual [at] protonmail.com)
% Copyright 2017 Daniel Pascual
% License: GNU GPLv3
%==========================================================================

    fs = n*1.023e6;
    fc = m*1.023e6;

    S = (4*fc./((pi*F).^2)).* ((cos(pi*F/(fc))).^2).* (((cos(pi*F/(2*fs))).^2) - cos(pi*F/(2*fs)) - 2*cos(pi*F/(2*fs)).*cos(pi*F/(4*fs)) + 2 ) ./ ((cos(pi*F/(2*fs))).^2);
    S_ = S;
    S_(find(isnan(S))) = 0;
    aux = sum(abs(S_))/length(S);
    S = S/aux;
    S = abs(S);
end


function [p] = dot(qt1,qt2, do_qr)
%Dot product of two QTT-Tuckers
%   [PR]=DOT(TT1,TT2) -- dot product of two TT-tensors
%
%   [PR]=DOT(TT1,TT2, DO_QR) if DO_QR==true is specified, perform the
%   left-to-right QRs of TT1,TT2
%   before the scalar product. It increases the  accuracy in some cases.
%
% In general, returns a 4D tensor of sizes
% r0(tt1), r0(tt2), rd(tt1), rd(tt2)
% If r0(tt1) = r0(tt2) = 1 it returns a matrix of size rd(tt1) x rd(tt2)
%
%
% TT-Toolbox 2.2, 2009-2012
%
%This is TT Toolbox, written by Ivan Oseledets et al.
%Institute of Numerical Mathematics, Moscow, Russia
%webpage: http://spring.inm.ras.ru/osel
%
%For all questions, bugs and suggestions please mail
%ivan.oseledets@gmail.com
%---------------------------

if (nargin<3)||(isempty(do_qr))
    do_qr = false;
end;

d=qt1.dphys;
for i=1:d
    % dot product of factors gives rt1 times rt2 matrix, to be convolved
    % between cores
    % Make it more precise by QRs? <-- already inside @tt_tensor/dot
%     [qt1.tuck{i}, rv1]=qr(qt1.tuck{i}, 'lr');
%     [qt2.tuck{i}, rv2]=qr(qt2.tuck{i}, 'lr');
%     rv1 = eye(qt1.tuck{i}.r(end));
%     rv2 = eye(qt2.tuck{i}.r(end));
    Pfac = squeeze(dot(qt1.tuck{i}, qt2.tuck{i}, do_qr)); % size rt1,rt2
%     rt1 = size(rv1, 2); rt2 = size(rv2, 2);
%     rt1new = size(rv1,1); rt2new = size(rv2,1);
    % Now, merge Pfac to the core of qt1
    curcr = qt2.core{i};
    rc1 = size(curcr, 1); rt2 = size(curcr, 2); rc2 = size(curcr, 3);
    curcr = permute(curcr, [1, 3, 2]);
    curcr = reshape(curcr, rc1*rc2, rt2);
%     curcr = curcr*(rv1.');
    curcr = curcr*(Pfac.'); % Now, core2 has the tucker ranks of qt1
    curcr = reshape(curcr, rc1, rc2, qt1.core.n(i));
    qt2.core{i} = permute(curcr, [1, 3, 2]);

%     curcr = qt2.core{i};
%     rc1 = size(curcr, 1); rc2 = size(curcr, 3);
%     curcr = permute(curcr, [1, 3, 2]);
%     curcr = reshape(curcr, rc1*rc2, rt2);
%     curcr = curcr*(rv2.');
%     curcr = reshape(curcr, rc1, rc2, rt2new);
%     qt2.core{i} = permute(curcr, [1, 3, 2]);
end;
% Finaly, dot product of cores. It is consistent, since we merged Pfacs
p = dot(qt1.core, qt2.core, do_qr);
end


function plotData(X, y)
%PLOTDATA Plots the data points X and y into a new figure
%   PLOTDATA(x,y) plots the data points with + for the positive examples
%   and o for the negative examples. X is assumed to be a Mx2 matrix.

% Create New Figure
figure; hold on;

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the positive and negative examples on a
%               2D plot, using the option 'k+' for the positive
%               examples and 'ko' for the negative examples.
%

positive = find(y == 1);
negative = find(y == 0);

plot(X(positive, 1), X(positive, 2), 'k+', 'LineWidth', 2, 'MarkerSize', 7);
plot(X(negative, 1), X(negative, 2), 'ko', 'MarkerFaceColor', 'y', 'MarkerSize', 7);

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

hold off;

end


function [desc, f] = at_cnnfeat2vlfeat(x)

[u,v] = meshgrid(1:size(x,2),1:size(x,1));
f = [u(:)'; v(:)'];
desc1 = reshape(shiftdim(x(:)),size(x,1)*size(x,2),[])';

desc = yael_vecs_normalize(desc1);


function A = shiftAnglesFromMinusPIToPI(InA)
    %dont do anything to angles that are already in range
    %if we leave out this step, we get +180 shifted to -180
    idx = find(InA>pi | InA <-pi);
    if(isempty(idx))
        A = InA;
    else
        A = InA;
        A(idx) = mod(InA(idx)+pi,2*pi)-pi;  % input is in radians
    end
end


function Population = LCSA_NSGAIIIEnvironmentalSelection(Population,N,Z,Zmin)
% -----------------------------------------------------------------------
%  Copyright (C) 2020 Heiner Zille
%
%  This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0
%  International License. (CC BY-NC-SA 4.0). To view a copy of this license,
%  visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or see the
%  pdf-file "License-CC-BY-NC-SA-4.0.pdf" that came with this code.
%
%  You are free to:
%  * Share ? copy and redistribute the material in any medium or format
%  * Adapt ? remix, transform, and build upon the material
%  Under the following terms:
%  * Attribution ? You must give appropriate credit, provide a link to the
%     license, and indicate if changes were made. You may do so in any reasonable
%     manner, but not in any way that suggests the licensor endorses you or your use.
%  * NonCommercial ? You may not use the material for commercial purposes.
%  * ShareAlike ? If you remix, transform, or build upon the material, you must
%    distribute your contributions under the same license as the original.
%  * No additional restrictions ? You may not apply legal terms or technological
%    measures that legally restrict others from doing anything the license permits.
%
%  Author of this Code:
%   Heiner Zille <heiner.zille@ovgu.de> or <heiner.zille@gmail.com>
%
%  This code is based on the following publications:
%
%  1) Heiner Zille
%     "Large-scale Multi-objective Optimisation: New Approaches and a Classification of the State-of-the-Art"
%     PhD Thesis, Otto von Guericke University Magdeburg, 2019
%     http://dx.doi.org/10.25673/32063
%
%  2) Heiner Zille and Sanaz Mostaghim
%     "Linear Search Mechanism for Multi- and Many-Objective Optimisation"
%     10th International Conference on Evolutionary Multi-Criterion Optimization (EMO 2019),
%        Lecture Notes in Computer Science, vol 11411.
%        Deb K. et al. (eds), Springer, Cham, East Lansing, Michigan, USA, March 2019
%     https://doi.org/10.1007/978-3-030-12598-1_32.
%
%  This file is intended to work with the PlatEMO framework version 2.5.
%  Date of publication of this code: 06.04.2020
%  Last Update of this code: 06.04.2020
%  A newer version of this algorithm may be available. Please contact the author
%  or see http://www.ci.ovgu.de/Research/Codes.html.
%
% The files may have been modified in Feb 2021 by the authors of the Platemo framework to work with the Platemo 3.0 release.
% -----------------------------------------------------------------------
% This file is derived from its original version containied in the PlatEMO
% framework.
% -----------------------------------------------------------------------

    if isempty(Zmin)
        Zmin = ones(1,size(Z,2));
    end

    %% Non-dominated sorting
    [FrontNo,MaxFNo] = NDSort(Population.objs,Population.cons,N);
    Next = FrontNo < MaxFNo;

    %% Select the solutions in the last front
    Last   = find(FrontNo==MaxFNo);
    Choose = LastSelection(Population(Next).objs,Population(Last).objs,N-sum(Next),Z,Zmin);
    Next(Last(Choose)) = true;
    % Population for next generation
    Population = Population(Next);
end

function Choose = LastSelection(PopObj1,PopObj2,K,Z,Zmin)
% Select part of the solutions in the last front

    PopObj = [PopObj1;PopObj2] - repmat(Zmin,size(PopObj1,1)+size(PopObj2,1),1);
    [N,M]  = size(PopObj);
    N1     = size(PopObj1,1);
    N2     = size(PopObj2,1);
    NZ     = size(Z,1);

    %% Normalization
    % Detect the extreme points
    Extreme = zeros(1,M);
    w       = zeros(M)+1e-6+eye(M);
    for i = 1 : M
        [~,Extreme(i)] = min(max(PopObj./repmat(w(i,:),N,1),[],2));
    end
    % Calculate the intercepts of the hyperplane constructed by the extreme
    % points and the axes
    Hyperplane = PopObj(Extreme,:)\ones(M,1);
    a = 1./Hyperplane;
    if any(isnan(a))
        a = max(PopObj,[],1)';
    end
    % Normalization
    PopObj = PopObj./repmat(a',N,1);

    %% Associate each solution with one reference point
    % Calculate the distance of each solution to each reference vector
    Cosine   = 1 - pdist2(PopObj,Z,'cosine');
    Distance = repmat(sqrt(sum(PopObj.^2,2)),1,NZ).*sqrt(1-Cosine.^2);
    % Associate each solution with its nearest reference point
    [d,pi] = min(Distance',[],1);

    %% Calculate the number of associated solutions except for the last front of each reference point
    rho = hist(pi(1:N1),1:NZ);

    %% Environmental selection
    Choose  = false(1,N2);
    Zchoose = true(1,NZ);
    % Select K solutions one by one
    while sum(Choose) < K
        % Select the least crowded reference point
        Temp = find(Zchoose);
        Jmin = find(rho(Temp)==min(rho(Temp)));
        j    = Temp(Jmin(randi(length(Jmin))));
        I    = find(Choose==0 & pi(N1+1:end)==j);
        % Then select one solution associated with this reference point
        if ~isempty(I)
            if rho(j) == 0
                [~,s] = min(d(N1+I));
            else
                s = randi(length(I));
            end
            Choose(I(s)) = true;
            rho(j) = rho(j) + 1;
        else
            Zchoose(j) = false;
        end
    end
end


function beta=calcStarBetaskBest(A,K)
%%CALCSTARBETASKBEST Calculate target-measurement association probabilities,
%                    as in the JPDAFStar given an association matrix using
%                    only the k-best hypotheses for the computation of the
%                    target-measurement association probabilities rather
%                    than goign through all joint association events.
%
%INPUTS:   A  A numTar X numMeas matrix of all-positive likelihood
%              ratios for assigning the target specified by the row to the
%              measurement specified by the column.
%          K  The number of hypotheses to generate.
%
%OUTPUTS:  beta A numTar X (numMeas+1) matrix of probabilities of assigning
%               the target given by the row to the measurement given by the
%               column. The final column is a set of missed detection
%               probabilities.
%
%The general idea behind this function is the same as that of the function
%calcStarBetasBF. However, rather than generating all possible
%joint association events, only the k-best events are generated.
%
%To reformulate the problem such that a 2D assignment algorithm can be
%used, the logarithm of the likelihood ratios must be taken, then the cost
%values are exponentiated to get traditional probabilities.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%In order to be able to use the k-Best 2D assignment algorithm, the
%association matrix must be augmented with extra columns that represent
%missed detection events. When the likelihood ratios in A have been
%appropriately computed, the likelihood ratio of a missed detection event
%is equal to one.

numTar=size(A,1);
numMeas=size(A,2);

%Adjust the cost matrix so that 2D assignment can be use.
A=log(A);

%Alocate space for the results.
beta=zeros(numTar,numMeas+1);

%Augment the A matrix to handle missed detection hypotheses. These are
%supposed to have a likelihood ratio of 1, so  the logarithm should be
%zero.
AClut=1-eye(numTar);
AClut(AClut==1)=-inf;
[col4rowBest,row4ColBest,gainBest]=kBest2DAssignment([A,AClut],K,true);

%Undo the logarithm from before.
gainBest=exp(gainBest);

%Adjust K to reflect the fact that fewer than K hypotheses might have been
%present.
K=size(col4rowBest,2);

%For each hypothesis, determine the set of measurements that are
%target-originated and save them order in tarMeas. Also find the set of
%targets that are observed and save them in obsTar.
tarMeas=zeros(numTar,K);
obsTar=zeros(numMeas,K);
for curHyp=1:K
    tarMeas(:,curHyp)=col4rowBest(:,curHyp);

    %Remove elements that are missed detections.
    misSel=col4rowBest(:,curHyp)>numMeas;
    tarMeas(misSel,curHyp)=0;

    %Sort the result.
    tarMeas(:,curHyp)=sort(tarMeas(:,curHyp));
    obsTar(:,curHyp)=sort(row4ColBest(1:numMeas,curHyp));
end

%For each set of observed targets and measurements that are
%target-originated, go through and only keep the most likely hypothesis.
%Since everything is already ordered in decreasing gain, the first
%occurrence of each set of observed targets and target-originated
%measurements is the most likely.
validHyps=true(K,1);
for curHyp=1:K
    if(validHyps(curHyp)==false)
        continue;
    end
    validHyps(curHyp)=false;

    for HypS=(curHyp+1):K
        if(isequal(tarMeas(:,curHyp),tarMeas(:,HypS))&&isequal(obsTar(:,curHyp),obsTar(:,HypS)))
            validHyps(HypS)=false;
        end
    end

    %Add the ML hypothesis with the given set of observed targets and
    %target-originated measurements to the beta terms.
    for curTar=1:numTar
        curMeas=col4rowBest(curTar,curHyp);
        if(curMeas>numMeas)
            %If it is a missed detection.
             beta(curTar,end)=beta(curTar,end)+gainBest(curHyp);
        else
            beta(curTar,curMeas)=beta(curTar,curMeas)+gainBest(curHyp);
        end
    end
end

%Normalize the betas so that sum of the probabilities of each target being
%assigned to a measurement or a missed detection sums to one.
beta=bsxfun(@rdivide,beta,sum(beta,2));

end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function y = ga44(x)
    y = 1 - 0.1 * (sin(x(1)^2 + x(2)) - 0.1) / (x(1)^2 + x(2)^2);
end


function tests = PlanTest
  tests = functiontests(localfunctions);
end

function setupOnce(tc)
    clc
    load map1          % load map
    tc.TestData.map = map;
    tc.TestData.goal = [50 30];
    tc.TestData.start = [20 10];
end

function teardownOnce(tc)
    close all
end

function bug2_test(tc)

    nav = Bug2(tc.TestData.map);
    tc.verifyInstanceOf(nav, 'Bug2');
    s = nav.char();
    verifyTrue(tc, ischar(s) );

    nav.plot();

    p = nav.query(tc.TestData.start, tc.TestData.goal);

    tc.verifyTrue(size(p,2) == 2, 'plan must have 2 columns');
    tc.verifyEqual(p(1,:), tc.TestData.start, 'start point must be on path');
    tc.verifyEqual(p(end,:), tc.TestData.goal, 'goal point must be on path');
    tc.verifyFalse( any( nav.isoccupied(p') ), 'path must have no occupied cells');

    nav.plot()
    nav.plot(p);

    tc.assumeTrue(ispc || ismac);  % FILTER video generation for Travis
    fname = fullfile(tempdir, 'bug.mp4');
    p = nav.query(tc.TestData.start, tc.TestData.goal, 'animate', 'movie', fname);
    tc.verifyTrue(exist(fname, 'file') == 2);
    delete(fname);

    tc.verifyError( @() nav.plan(), 'RTB:Bug2:badcall');

    map = zeros(10,10);
    map(3:7,3:7) = 1;
    map(4:6,4:6) = 0;
    nav = Bug2(map);
    tc.verifyError( @() nav.query([5 5], [2 2]), 'RTB:bug2:noplan');

end

function dxform_test(tc)

    nav = DXform(tc.TestData.map);
    tc.verifyInstanceOf(nav, 'DXform');

    s = nav.char();
    verifyTrue(tc, ischar(s) );

    nav.plot();
    nav.plan(tc.TestData.goal);
    nav.plot();
    nav.plan(tc.TestData.goal, 'animate');

    p = nav.query(tc.TestData.start);

    tc.verifyTrue(size(p,2) == 2, 'plan must have 2 columns');
    tc.verifyEqual(p(1,:), tc.TestData.start, 'start point must be on path');
    tc.verifyEqual(p(end,:), tc.TestData.goal, 'goal point must be on path');
    tc.verifyFalse( any( nav.isoccupied(p') ), 'path must have no occupied cells');

    nav.query(tc.TestData.start, 'animate');

    nav.plot();
    nav.plot(p);

    nav.plot3d();
    nav.plot3d(p);
end

function distancexform_test(tc)
    map = zeros(10,10);
    map(4:6,4:6) =1;
    %args= {'verbose'}
    args = {};

    dx1 = distancexform(map, [5 8], 'fast', 'noipt', args{:});
    tc.verifyClass(dx1, 'double');
    tc.verifyEqual(dx1(8,5), 0);
    tc.verifyTrue(all(all(isnan(dx1(map==1)))));
    i=sub2ind(size(dx1), 8, 5);
    tc.verifyTrue(all(dx1(i+[-11 -10 -9 -1 1 11 10 9])) > 0);

    tc.verifySize(dx1, size(map));
    dx2 = distancexform(map, [5 8], 'nofast', 'ipt', args{:});
    tc.verifyClass(dx1, 'double');
    tc.verifySize(dx1, size(map));
    dx3 = distancexform(map, [5 8], 'nofast', 'noipt', args{:});
    tc.verifyClass(dx1, 'double');
    tc.verifySize(dx1, size(map));

    tc.verifyEqual(dx1, dx2, 'absTol', 1e-6, 'MEX ~= bwdist');
    tc.verifyEqual(dx1, dx3, 'MEX ~= MATLAB');

    dx1 = distancexform(map, [5 8], 'cityblock', 'fast', 'noipt', args{:});
    tc.verifyClass(dx1, 'double');
    tc.verifyTrue(all(all(isnan(dx1(map==1)))));
    i=sub2ind(size(dx1), 8, 5);
    tc.verifyTrue(all(dx1(i+[-11 -10 -9 -1 1 11 10 9])) > 0);
    tc.verifySize(dx1, size(map));
    dx2 = distancexform(map, [5 8], 'cityblock', 'nofast', 'ipt', args{:});
    tc.verifyClass(dx1, 'double');
    tc.verifySize(dx1, size(map));
    dx3 = distancexform(map, [5 8], 'cityblock', 'nofast', 'noipt', args{:});
    tc.verifyClass(dx1, 'double');
    tc.verifySize(dx1, size(map));

    tc.verifyEqual(dx1, dx2, 'absTol', 1e-6, 'MEX ~= bwdist');
    tc.verifyEqual(dx1, dx3, 'MEX ~= MATLAB');

    dx1 = distancexform(map, [5 8], 'cityblock', 'animate');
    dx1 = distancexform(map, [5 8], 'cityblock', 'animate', 'delay', 0.1);

    tc.assumeTrue(ispc || ismac);  % FILTER video generation for Travis
    fname = fullfile(tempdir, 'bug.mp4');
    dx1 = distancexform(map, [5 8], 'cityblock', 'animate', 'movie', fname);
    tc.verifyTrue(exist(fname, 'file') == 2);
    delete(fname)
end

function dstar_test(tc)

    % create a planner
    nav = Dstar(tc.TestData.map, 'quiet');
    tc.verifyInstanceOf(nav, 'Dstar');

    s = nav.char();
    verifyTrue(tc, ischar(s) );

    nav.plot();

    % plan path to goal
    nav.plan(tc.TestData.goal);
    nav.plan(tc.TestData.goal, 'animate');

    % execute it
    p = nav.query(tc.TestData.start);

        tc.verifyTrue(size(p,2) == 2, 'plan must have 2 columns');
    tc.verifyEqual(p(1,:), tc.TestData.start, 'start point must be on path');
    tc.verifyEqual(p(end,:), tc.TestData.goal, 'goal point must be on path');
    tc.verifyFalse( any( nav.isoccupied(p') ), 'path must have no occupied cells');

    nav.query(tc.TestData.start, 'animate');

    nav.plot();
    nav.plot(p);

    % add a swamp
    for r=78:85
        for c=12:45
            nav.modify_cost([c;r], 2);
        end
    end

    % replan
    nav.plan();

    % show new path
    nav.query(tc.TestData.start);

    p = nav.query(tc.TestData.start);
    tc.verifyTrue(size(p,2) == 2, 'plan must have 2 columns');
    tc.verifyEqual(p(1,:), tc.TestData.start, 'start point must be on path');
    tc.verifyEqual(p(end,:), tc.TestData.goal, 'goal point must be on path');
    tc.verifyFalse( any( nav.isoccupied(p') ), 'path must have no occupied cells');

    nav.plot(p);

    nav.modify_cost([12 45; 78 85], 2);
    nav.modify_cost([12 13 14; 78 79 80], [2 3 4]);
end

function prm_test(tc)

    randinit
    nav = PRM(tc.TestData.map);
        tc.verifyInstanceOf(nav, 'PRM');

    s = nav.char();
    verifyTrue(tc, ischar(s) );

    nav.plot();

    nav.plan();
    nav.plot();

    p = nav.query(tc.TestData.start, tc.TestData.goal);

    tc.verifyTrue(size(p,2) == 2, 'plan must have 2 columns');
    tc.verifyEqual(p(1,:), tc.TestData.start, 'start point must be on path');
    tc.verifyEqual(p(end,:), tc.TestData.goal, 'goal point must be on path');
    tc.verifyFalse( any( nav.isoccupied(p') ), 'path must have no occupied cells');

    nav.query(tc.TestData.start, tc.TestData.goal);
    nav.plot(p);
end

function lattice_test(tc)

    nav = Lattice();
    tc.verifyInstanceOf(nav, 'Lattice');

    nav.plan('iterations', 8);
    nav.plot()

    start = [1 2 pi/2]; goal = [2 -2 0];
    p = nav.query( start, goal );
    verifyEqual(tc, size(p,1), 7);
    tc.verifyTrue(size(p,2) == 3, 'plan must have 3 columns');
    tc.verifyEqual(p(1,:), start, 'AbsTol', 1e-10, 'start point must be on path');
    tc.verifyEqual(p(end,:), goal, 'AbsTol', 1e-10, 'goal point must be on path');

    nav.plot

    nav.plan('cost', [1 10 10])
    p = nav.query( start, goal );
    verifyEqual(tc, size(p,1), 9);
    tc.verifyTrue(size(p,2) == 3, 'plan must have 3 columns');
    tc.verifyEqual(p(1,:), start, 'AbsTol', 1e-10, 'start point must be on path');
    tc.verifyEqual(p(end,:), goal, 'AbsTol', 1e-10, 'goal point must be on path');

    load road
    nav = Lattice(road, 'grid', 5, 'root', [50 50 0])
    nav.plan();
    start = [30 45 0]; goal = [50 20 0];
    p = nav.query(start, goal);
    tc.verifyTrue(size(p,2) == 3, 'plan must have 3 columns');
    tc.verifyEqual(p(1,:), start, 'AbsTol', 1e-10, 'start point must be on path');
    tc.verifyEqual(p(end,:), goal, 'AbsTol', 1e-10, 'goal point must be on path');
    tc.verifyFalse( any( nav.isoccupied(p(:,1:2)') ), 'path must have no occupied cells');

end

function rrt_test(tc)
    randinit

    car = Bicycle('steermax', 0.5);
    %nav = RRT(car, 'goal', goal, 'range', 5);
    nav = RRT(car, 'npoints', 400);
    tc.verifyInstanceOf(nav, 'RRT');

    s = nav.char();

    nav.plan();
    nav.plot();

    start = [0 0 0]; goal = [0 2 0];
    p = nav.query(start, goal);

    tc.verifyTrue(size(p,2) == 3, 'plan must have 3 columns');
    tc.verifyFalse( any( nav.isoccupied(p(:,1:2)') ), 'path must have no occupied cells');

    % bigger example with obstacle
    load road

    randinit
    nav = RRT(car, road, 'npoints', 1000, 'root', [50 22 0], 'simtime', 4);
    nav.plan();
    p = nav.query([40 45 0], [50 22 0]);
    tc.verifyTrue(size(p,2) == 3, 'plan must have 3 columns');
    tc.verifyFalse( any( nav.isoccupied(p(:,1:2)') ), 'path must have no occupied cells');

end


function value = dzasum ( n, x, incx )

%*****************************************************************************80
%
%% DZASUM takes the sum of the absolute values of a complex vector.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 May 2006
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979.
%
%    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
%    Basic Linear Algebra Subprograms for FORTRAN usage,
%    ACM Transactions on Mathematical Software,
%    Volume 5, Number 3, pages 308-323, 1979.
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, complex X(*), the vector.
%
%    Input, integer INCX, the increment between successive entries of X.
%
%    Output, real VALUE, the sum of the absolute values.
%
  value = sum ( abs ( real ( x(1:incx:1+(n-1)*incx) ) ) ...
              + abs ( imag ( x(1:incx:1+(n-1)*incx) ) ) );

  return
end


function F = erf(F, varargin)
%ERF   Error function of a CHEBFUN.
%   ERF(X) is the error function of the real-valued CHEBFUN X.
%
%   The error function is defined as:
%       erf(X)(s) = 2/sqrt(pi) * integral from 0 to X(s) of exp(-t^2) dt.
%
% See also ERFC, ERFCX, ERFINV, ERFCINV.

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

% Input must be real:
if ( ~isreal(F) )
    error('CHEBFUN:CHEBFUN:erf:notreal', 'Input must be real.');
end

% Call the compose method:
F = compose(F, @erf, varargin{:});

end


function [dpixc, dpixc_ind, blinkmat] = generatedataMultiPSF(size_vec, x_vec,y_vec,intensity_vec,psf_tmp,offset,Nt, probtrans)
% generate points

if size(intensity_vec,2)>size(intensity_vec,1); intensity_vec = intensity_vec'; end
if size(x_vec,2)>size(x_vec,1); x_vec = x_vec'; end
if size(y_vec,2)>size(y_vec,1); y_vec = y_vec'; end

nx = size_vec(2)-size_vec(1);
ny = size_vec(4)-size_vec(3);
N = length(x_vec); %number of points
center = [nx ny]/2;
center_round = round(center);

%
% intensity_mat = repmat(intensity_vec, 1,Nt);
% changemat = rand(N,Nt)<probtrans;
% statemat = mod(cumsum(changemat,2),2);
% initvec = rand(N,1)>0.5; %initial state of the blinkmat
% ivt = ~(initvec == statemat(:,1));
% statematinit = mod(statemat+repmat(ivt,1,Nt),2);
%
% % blinkmat_equal = rand(N, Nt);
% % blinkmat = blinkmat_equal .* intensity_mat; %different intensities...
% blinkmat = statematinit .* intensity_mat; %different intensities...
blinkmat = blinkmat_markov(N,Nt, intensity_vec, probtrans);
center_im = pixelize(center_round, 1, size_vec, nx, ny, [],0);
dpixc_ind = newimar(N);

shift_vec = [x_vec-center(1), y_vec-center(2)];
for ii=1:N
    sp = size(psf_tmp{ii});
    psf_tmp2 = double(psf_tmp{ii}/sum(psf_tmp{ii}(:))); %normalize to 1
    psf_tmp3 = padimage(psf_tmp2,fliplr([nx, ny])+2*sp);
    psf = psf_tmp3;
    psf_im = clip(dip_image(conv2(center_im,psf,'same')), 0, Inf);
    dpixc_ind{ii} = clip(shift(psf_im, shift_vec(ii,:)), 0, Inf);
end

dpixc_nonoise = array2im(dpixc_ind'*blinkmat + offset);
dpixc_dip = noise(dpixc_nonoise,'poisson');
dpixc = double(dpixc_dip);


function surf = imJointSurfaceArea(img, L1, L2, varargin)
% Surface area of the interface between two labels.
%
%   S = imJointSurfaceArea(LBL, L1, L2)
%   Estimates the joint surface area between the two labels L1 and L2 in
%   the label image LBL.
%
%   S = imJointSurfaceArea(LBL, L1, L2, NDIRS)
%   Specifies the number of directions used for estimating surface area.
%   NDIRS can be either 3 or 13 (the default).
%
%   S = imJointSurfaceArea(..., RESOL)
%   Specifies image resolution. RESOL is a 1-by-3 row vector containing
%   resolution in the X, Y and Z direction (in that order).
%
%
%   Example
%     % generate a demo image
%     img = discreteBall(1:10, 1:100, 1:100, [50.12 50.23 50.34 40]);
%     % convert to image with two different labels
%     img2 = uint8(img + 1);
%     % compute joint surface area
%     imJointSurfaceArea(img2, 1, 2)
%     ans =
%         2.0102e+004
%
%   See also
%     imSurfaceArea

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2010-07-26,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

% check image dimension and type
if ndims(img) ~= 3 || islogical(img)
    error('first argument should be a 3D image');
end

%% Process input arguments

% default number of directions
ndir = 13;

% default image resolution
delta = [1 1 1];

% Process user input arguments
while ~isempty(varargin)
    var = varargin{1};
    if ~isnumeric(var)
        error('option should be numeric');
    end

    % option is either connectivity or resolution
    if isscalar(var)
        ndir = var;
    else
        delta = var;
    end
    varargin(1) = [];
end

%% Initialisations

% distances between a pixel and its neighbours.
d1  = delta(1);
d2  = delta(2);
d3  = delta(3);

% volume of a voxel (used for computing line densities)
vol = d1 * d2 * d3;

%% Main processing for 3 directions

% number of transitions along the 3 main directions
n1a = sum(sum(sum(img(:,1:end-1,:)==L1 & img(:,2:end,:)==L2)));
n1b = sum(sum(sum(img(:,1:end-1,:)==L2 & img(:,2:end,:)==L1)));
n2a = sum(sum(sum(img(1:end-1,:,:)==L1 & img(2:end,:,:)==L2)));
n2b = sum(sum(sum(img(1:end-1,:,:)==L2 & img(2:end,:,:)==L1)));
n3a = sum(sum(sum(img(:,:,1:end-1)==L1 & img(:,:,2:end)==L2)));
n3b = sum(sum(sum(img(:,:,1:end-1)==L2 & img(:,:,2:end)==L1)));

if ndir == 3
    % compute surface area by averaging over the 3 main directions
    surf = 4/3 * ((n1a+n1b)/d1 + (n2a+n2b)/d2 + (n3a+n3b)/d3) / 2 * vol;
    return;
end

%% Additional processing for 13 directions

% Number of connected components along diagonals contained in the three
% main planes
n4a = sum(sum(sum(img(2:end,1:end-1,:)==L1   & img(1:end-1,2:end,:)==L2)));
n4b = sum(sum(sum(img(2:end,1:end-1,:)==L2   & img(1:end-1,2:end,:)==L1)));
n5a = sum(sum(sum(img(1:end-1,1:end-1,:)==L1 & img(2:end,2:end,:)==L2)));
n5b = sum(sum(sum(img(1:end-1,1:end-1,:)==L2 & img(2:end,2:end,:)==L1)));
n6a = sum(sum(sum(img(:,2:end,1:end-1)==L1   & img(:,1:end-1,2:end)==L2)));
n6b = sum(sum(sum(img(:,2:end,1:end-1)==L2   & img(:,1:end-1,2:end)==L1)));
n7a = sum(sum(sum(img(:,1:end-1,1:end-1)==L1 & img(:,2:end,2:end)==L2)));
n7b = sum(sum(sum(img(:,1:end-1,1:end-1)==L2 & img(:,2:end,2:end)==L1)));
n8a = sum(sum(sum(img(2:end,:,1:end-1)==L1   & img(1:end-1,:,2:end)==L2)));
n8b = sum(sum(sum(img(2:end,:,1:end-1)==L2   & img(1:end-1,:,2:end)==L1)));
n9a = sum(sum(sum(img(1:end-1,:,1:end-1)==L1 & img(2:end,:,2:end)==L2)));
n9b = sum(sum(sum(img(1:end-1,:,1:end-1)==L2 & img(2:end,:,2:end)==L1)));

%TODO: add the case of 9 directions ?

% Number of connected components along lines corresponding to diagonals of
% the unit cube
n10a = sum(sum(sum(img(1:end-1,1:end-1,1:end-1)==L1 & img(2:end,2:end,2:end)==L2)));
n10b = sum(sum(sum(img(1:end-1,1:end-1,1:end-1)==L2 & img(2:end,2:end,2:end)==L1)));
n11a = sum(sum(sum(img(2:end,1:end-1,1:end-1)==L1 & img(1:end-1,2:end,2:end)==L2)));
n11b = sum(sum(sum(img(2:end,1:end-1,1:end-1)==L2 & img(1:end-1,2:end,2:end)==L1)));
n12a = sum(sum(sum(img(1:end-1,2:end,1:end-1)==L1 & img(2:end,1:end-1,2:end)==L2)));
n12b = sum(sum(sum(img(1:end-1,2:end,1:end-1)==L2 & img(2:end,1:end-1,2:end)==L1)));
n13a = sum(sum(sum(img(2:end,2:end,1:end-1)==L1 & img(1:end-1,1:end-1,2:end)==L2)));
n13b = sum(sum(sum(img(2:end,2:end,1:end-1)==L2 & img(1:end-1,1:end-1,2:end)==L1)));

% space between 2 voxels in each direction
d12  = hypot(d1, d2);
d13  = hypot(d1, d3);
d23  = hypot(d2, d3);
d123 = sqrt(d1^2 + d2^2 + d3^2);

% Compute weights corresponding to surface fraction of spherical caps
% For isotropic case, weights correspond to:
% c1 = 0.04577789120476 * 2;  % Ox
% c2 = 0.04577789120476 * 2;  % Oy
% c3 = 0.04577789120476 * 2;  % Oz
% c4 = 0.03698062787608 * 2;  % Oxy
% c6 = 0.03698062787608 * 2;  % Oxz
% c8 = 0.03698062787608 * 2;  % Oyz
% c10 = 0.03519563978232 * 2;  % Oxyz
c = computeDirectionWeights3d13(delta);

% compute the weighted sum of each direction
% intersection count * direction weight / line density
surf = 4 * vol * (...
    (n1a+n1b)*c(1)/d1 + (n2a+n2b)*c(2)/d2 + (n3a+n3b)*c(3)/d3 + ...
    (n4a+n4b+n5a+n5b)*c(4)/d12 + (n6a+n6b+n7a+n7b)*c(6)/d13 + ...
    (n8a+n8b+n9a+n9b)*c(8)/d23 + ...
    (n10a + n10b + n11a + n11b + n12a + n12b + n13a + n13b) * c(10) / d123) / 2;


function ker0_values_test ( )

%*****************************************************************************80
%
%% KER0_VALUES_TEST demonstrates the use of KER0_VALUES.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 February 2009
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'KER0_VALUES_TEST:\n' );
  fprintf ( 1, '  KER0_VALUES stores values of \n' );
  fprintf ( 1, '  the Kelvin function KER of order 0.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '      X           FX\n' );
  fprintf ( 1, '\n' );

  n_data = 0;

  while ( 1 )

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

    if ( n_data == 0 )
      break
    end

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

  end

  return
end


function ekg_filt(up)
%EKG_FILT extracts respiratory signals using various filtering techniques
% from the ECG signal as specified in PC's literature review.
%	            ekg_filt(option, up)
%
%	Inputs:
%		option          the option which has led to this function being used
%       up              universal parameters structure
%
%	Outputs:
%       ...
%

fprintf('\n--- Extracting Respiratory Signals from ECG using Filtering Techniques ');
log_int_respSig = 0;             % Has value 1 unless this is a final respiratory signal

for subj = up.paramSet.subj_list

    %% Cycle through each ecg signal
    for sig_no = 1 : length(up.paramSet.ekg_sigs)

        %% Cycle through each method
        for filt_no = 1 : length(up.al.options.ekg_filt)

            %% Skip if this processing has been done previously
            eval(['save_name = ''' up.paramSet.ekg_sigs{sig_no}, up.paths.filenames.filt '_' up.al.options.ekg_filt{filt_no} ''';']);
            iden_resp_sig_file_ending
            savepath = [up.paths.data_save_folder, num2str(subj), ending];
            exist_log = check_exists(savepath, save_name);
            if exist_log
                continue
            end

            %% Load relevant data
            if ~exist('data', 'var')
                load([up.paths.data_load_folder, up.paths.data_load_filename]);
            end
            % Extract EKG data
            eval(['rel_data = data(subj).' up.paramSet.ekg_sigs{sig_no} ';']);

            %% Filter the raw signal using this method
            respWave = feval(up.al.options.ekg_filt{filt_no}, rel_data, up);

            %% Band-pass filter
            filtered_data = bpf_signal_to_remove_non_resp_freqs(respWave, respWave.fs, up);
            eval([save_name ' = filtered_data;']);

            %% Save processed data
            save_or_append_data
        end

    end

end

end


function  bdiffma(newcat)
    %  This routine etsimates the b-value of a curve automatically
    %  The b-valkue curve is differenciated and the point
    %  of maximum curvature marked. The b-value will be calculated
    %  using this point and the point half way toward the high
    %  magnitude end of the b-value curve.

    %  Stefan Wiemer 1/95
    %
    think
    %zmap_message_center.set_info('  ','Calculating b-value...')
    global cluscat mess bfig backcat xt3 bvalsum3
    global  ttcat teb t0b cua b1 b2 n1 n2
    report_this_filefun(mfilename('fullpath'));

    [existFlag,figNumber]=figure_exists('frequency-magnitude distribution',1);
    if existFlag
        % figure_w_normalized_uicontrolunits(bfig);
        bfig = figNumber;
    else
        bfig=figure_w_normalized_uicontrolunits(...                  %build figure for plot
            'Units','normalized','NumberTitle','off',...
            'Name','frequency-magnitude distribution',...
            'MenuBar','none',...
            'visible','off',...
            'pos',[ 0.300  0.7 0.5 0.5]);

        uicontrol('Units','normal',...
            'Position',[.0 .85 .08 .06],'String','Info ',...
             'Callback','infoz(1)');
        uicontrol('Units','normal',...
            'Position',[.0 .55 .10 .06],'String','Manual ',...
             'Callback','bfitnew(newcat)');
        matdraw

        uicontrol('Units','normal',...
            'Position',[.0 .65 .08 .06],'String','Save ',...
             'Callback',{@calSave9,xt3, bvalsum3})

    end

    maxmag = max(newcat.Magnitude);
    mima = min(newcat.Magnitude);
    if mima > 0 ; mima = 0 ; end

    % number of mag units
    nmagu = (maxmag*10)+1;

    bval = zeros(1,nmagu);
    bvalsum = zeros(1,nmagu);
    bvalsum3 = zeros(1,nmagu);

    [bval,xt2] = hist(newcat.Magnitude,(mima:0.1:maxmag));
    bvalsum = cumsum(bval);                        % N for M <=
    bvalsum3 = cumsum(bval(length(bval):-1:1));    % N for M >= (counted backwards)
    xt3 = (maxmag:-0.1:mima);

    backg_be = log10(bvalsum);
    backg_ab = log10(bvalsum3);
    orient tall

    if hold_state
        axes(cua)
        hold on
    else
        figure_w_normalized_uicontrolunits(bfig);delete(gca);delete(gca);delete(gca);delete(gca)
        rect = [0.2,  0.3, 0.70, 0.6];           % plot Freq-Mag curves
        axes('position',rect);
    end

    pl =semilogy(xt3,bvalsum3,'b');
    set(pl,'LineWidth',2.0)
    hold on
    %semilogy(xt3,bvalsum3,'om')
    difb = [0 diff(bvalsum3) ];
    %pl =semilogy(xt3,difb,'g');
    %set(pl,'LineWidth',2.0)
    %semilogy(xt3,difb,'g')
    grid

    % Marks the point of maximum curvature
    %
    i = find(difb == max(difb));
    i = max(i);
    %te = semilogy(xt3(i),difb(i),'xk');
    %set(te,'LineWidth',2,'MarkerSize',ms10)
    %te = semilogy(xt3(i),bvalsum3(i),'xk');
    %set(te,'LineWidth',2,'MarkerSize',ms10)

    % Estimate the b-value
    %
    i2 = 1 ;
    %te = semilogy(xt3(i2),difb(i2),'xk');
    %set(te,'LineWidth',2,'MarkerSize',ms10)
    %te = semilogy(xt3(i2),bvalsum3(i2),'xk');
    %set(te,'LineWidth',2,'MarkerSize',ms10)

    xlabel('Magnitude','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)
    ylabel('Cumulative Number','FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)
    set(gca,'Color',color_bg)
    set(gca,'visible','on','FontSize',ZmapGlobal.Data.fontsz.m,'FontWeight','bold',...
        'FontWeight','bold','LineWidth',1.5,...
        'Box','on')

    cua = gca;

    par2 = 0.1 * max(bvalsum3);
    par3 = 0.12 * max(bvalsum3);
    M1b = [];
    M1b = [xt3(i) bvalsum3(i)];
    tt3=num2str(fix(100*M1b(1))/100);
    text( M1b(1),M1b(2),['|: M1=',tt3],'Fontweight','bold' )

    M2b = [];
    M2b =  [xt3(i2) bvalsum3(i2)];
    tt4=num2str(fix(100*M2b(1))/100);
    %text( M2b(1),M2b(2),['|: M2=',tt4],'Fontweight','bold' )

    ll = xt3 >= M1b(1) & xt3 <= M2b(1);
    x = xt3(ll);

    [ av,bv,si] = bmemag(newcat);

    pause(0.1)

    y = backg_ab(ll);
    %[p,s] = polyfit(x,y,1)                    % fit a line to background
    [aw bw,  ew] = wls(x',y');
    p = [bw aw];
    f = polyval(p,x);
    (teb-t0b)/(10.^ polyval(p,5))
    (teb-t0b)/(10.^ polyval(p,6))
    (teb-t0b)/(10.^ polyval(p,7))
    (teb-t0b)/(10.^ polyval(p,8))
    f = 10.^f;
    hold on
    ttm= semilogy(x,f,'r');                         % plot linear fit to backg
    set(ttm,'LineWidth',1)
    set(gca,'XLim',[min(newcat.Magnitude)-0.5  max(newcat.Magnitude)+1.0])
    r = corrcoef(x,y);
    r = r(1,2);
    std_backg = ew;      % standard deviation of fit

    p=-p(1,1);
    p=fix(100*p)/100;
    std_backg=fix(100*std_backg)/100;
    tt2=num2str(std_backg);
    tt1=num2str(p);
    tt4=num2str(bv,2);
    tt5=num2str(si,2);

    rect=[0 0 1 1];
    h2=axes('position',rect);
    set(h2,'visible','off');

    if ~ho
        txt1=text(.16, .18,['b-value (w LS, M  > ', num2str(M1b(1)) '): ',tt1, ' +/- ', tt2]);
        set(txt1,'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)
        txt1=text(.16, .12,['b-value (max lik, M > ', num2str(min(newcat.Magnitude)) '): ',tt4, ' +/- ', tt5]);
        set(txt1,'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)

    else
        txt1=text(.16, .06,['b-value (weighted least square): ',tt1, ' +/- ', tt2]);
        set(txt1,'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m,'Color','r')
    end
    set(gcf,'visible','on');
    zmap_message_center.set_info('  ','Done')
    done

    if hold_state
        % calculate the probability that the two distributins are differnt
        b2 = str2double(tt1); n2 = newcat.Count;
        n = n1+n2;
        da = -2*n*log(n) + 2*n1*log(n1+n2*b1/b2) + 2*n2*log(n1*b2/b1+n2) -2;
        pr = exp(-da/2-2);
        disp(['Probability: ',  num2str(pr)]);
        txt1=text(.65, .85,['Utsu Test: ', num2str(pr)]);
        set(txt1,'FontWeight','bold','FontSize',ZmapGlobal.Data.fontsz.m)
    else
        b1 = str2double(tt1); n1 = newcat.Count;
    end


function dlap_io_test01 ( )

%*****************************************************************************80
%
%% DLAP_IO_TEST01 tests DLAP_FILE_WRITE.
%
%  Discussion:
%
%    The matrix is:
%
%      11  12   0   0  15
%      21  22   0   0   0
%       0   0  33   0  35
%       0   0   0  44   0
%      51   0  53   0  55
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 January 2014
%
%  Author:
%
%    John Burkardt
%
  n = 5;
  nelt = 11;

  a = [ 51.0, 12.0, 11.0, 33.0, 15.0, ...
        53.0, 55.0, 22.0, 35.0, 44.0, ...
        21.0 ];
  ia = [ 5,  1,  1,  3,  1,  5,  5,  2,  3,  4,  2 ];
  irhs = 1;
  isoln = 1;
  isym = 0;
  output_filename = 'a5by5.dlap';
  ja = [ 1,  2,  1,  3,  5,  3,  5,  2,  5,  4,  1 ];
  rhs = [ 110.0, 65.0, 274.0, 176.0, 485.0 ];
  soln = [ 1.0, 2.0, 3.0, 4.0, 5.0 ];

  fprintf ( 1, '\n' );
  fprintf ( 1, 'DLAP_IO_TEST01\n' );
  fprintf ( 1, '  DLAP_FILE_WRITE writes a matrix in SLAP Triad format\n' );
  fprintf ( 1, '  to a DLAP sparse matrix file.\n' );

  dlap_file_print ( n, nelt, isym, irhs, isoln, ia, ja, a, rhs, ...
    soln, '  The DLAP data to be written to the file.' );

  output = fopen ( output_filename, 'wt' );

  dlap_file_write ( n, nelt, isym, irhs, isoln, ia, ja, a, rhs, soln, output );

  fclose ( output );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Wrote the matrix data to "%s"\n', output_filename );

  return
end


function [x, infos] = robust_online_mu_nmf(V, rank, in_options)
% Robust online non-negative matrix factorization (ONMF) with outliers (RONMF) algorithm.
%
% Inputs:
%       matrix      V
%       rank        rank
%       in_options  options
% Output:
%       w           solution of w
%       infos       information
%
% References:
%       R. Zhao and Y. F. Tan,
%       "Online nonnegative matrix factorization with outliers,"
%       ICASSP, 2016.
%
%
% This file is part of NMFLibrary.
%
% Created by H.Sakai and H.Kasai on Feb. 12, 2017
%
% Change log:
%
%       May. 20, 2019 (Hiroyuki Kasai): Added initialization module.
%
%       Jul. 12, 2022 (Hiroyuki Kasai): Modified code structures.
%

    % set dimensions and samples
    [m, n] = size(V);

    % set local options
    local_options = [];
    local_options.lambda        = 1;
    local_options.x_init_robust = true;

    % check input options
    if ~exist('in_options', 'var') || isempty(in_options)
        in_options = struct();
    end
    % merge options
    options = mergeOptions(get_nmf_default_options(), local_options);
    options = mergeOptions(options, in_options);

    % initialize factors
    init_options = options;
    [init_factors, ~] = generate_init_factors(V, rank, init_options);
    Wt = init_factors.W;
    H = init_factors.H;
    R = init_factors.R;

    % initialize
    method_name = 'Robust-Online-MU';
    epoch = 0;
    grad_calc_count = 0;
    l = zeros(m, options.batch_size) + options.lambda;

    if options.verbose > 0
        fprintf('# %s: started ...\n', method_name);
    end

    % store initial info
    clear infos;
    [infos, f_val, optgap] = store_nmf_info(V, Wt, H, R, options, [], epoch, grad_calc_count, 0);

    if options.verbose > 1
        fprintf('%s: Epoch = 0000, cost = %.16e, optgap = %.4e\n', method_name, f_val, optgap);
    end

    % set start time
    start_time = tic();

    % main outer loop
    while true

        % check stop condition
        [stop_flag, reason, max_reached_flag] = check_stop_condition(epoch, infos, options);
        if stop_flag
            display_stop_reason(epoch, infos, options, method_name, reason, max_reached_flag);
            break;
        end

        % Reset sufficient statistic
        At = zeros(m, rank);
        Bt = zeros(rank, rank);
        Ct = zeros(m, rank);

        % main inner loop
        for t = 1 : options.batch_size : n - 1

            % Retrieve vt, ht and rt
            vt = V(:, t:t+options.batch_size-1);
            ht = H(:, t:t+options.batch_size-1);
            rt = R(:, t:t+options.batch_size-1);

            % update ht/rt
            ht = ht .* (Wt.' * vt) ./ (Wt.' * (Wt * ht + rt));
            ht = ht + (ht<eps) .* eps;
            rt = rt .* vt ./ (Wt * ht + rt + l);

            % update sufficient statistics
            At = At + vt *  ht';
            Bt = Bt + ht *  ht';
            Ct = Ct + rt *  ht';

            % Update Wt
            Wt = Wt .* At ./ (Wt * Bt + Ct);
            Wt = Wt + (Wt<eps) .* eps;

            % Update H
            H(:,t:t+options.batch_size-1) = ht;

            % Update R
            R(:,t:t+options.batch_size-1) = rt;

            grad_calc_count = grad_calc_count + m * options.batch_size;
        end

        % measure elapsed time
        elapsed_time = toc(start_time);

        % update epoch
        epoch = epoch + 1;

        % store info
        infos = store_nmf_info(V, Wt, H, R, options, infos, epoch, grad_calc_count, elapsed_time);

        % display info
        display_info(method, epoch, infos, options);

    end

    x.W = Wt;
    x.H = H;
    x.R = R;

end


function fixed = p09_fixed_points ( m, fixed_num )

%*****************************************************************************80
%
%% P09_FIXED_POINTS returns the fixed points in problem 09.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer FIXED_NUM, the number of fixed points.
%
%    Output, real FIXED(M,FIXED_NUM), the fixed points.
%
  center1 = [ 0.50, 0.50 ];
  center2 = [ 0.25, 0.75 ];
  center3 = [ 0.60, 0.40 ];

  r1 = 0.5;
  r2 = 0.1;
  r3 = 0.1;

  fixed[1:2,1:4] = [ ...
    center1(1) - r1, center1(2) - r1; ...
    center1(1) + r1, center1(2) - r1; ...
    center1(1) + r1, center1(2) + r1; ...
    center1(1) - r1, center1(2) + r1 ]';

  for j = 1 : 6
    angle = ( ( j - 1 ) * 2 ) * pi / 6.0;
    fixed(1,4+j) = center2(1) + r2 * cos ( angle );
    fixed(2,4+j) = center2(2) + r2 * sin ( angle );
  end

  for j = 1 : 6
    angle = ( ( j - 1 ) * 2 ) * pi / 6.0;
    fixed(1,10+j) = center3(1) + r3 * cos ( angle );
    fixed(2,10+j) = center3(2) + r3 * sin ( angle );
  end

  return
end


function fmincon_test02 ( )

%*****************************************************************************80
%
%% FMINCON_TEST02 minimizes the Niederreiter-McCurley function 2.
%
%  Discussion:
%
%    The value determined by FMINCON seems highly sensitive to the
%    starting condition.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 September 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Harald Niederreiter, Kevin McCurley,
%    Optimization of functions by quasi-random search methods,
%    Computing,
%    Volume 22, Number 2, 1979, pages 119-123.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FMINCON_TEST02\n' );
  fprintf ( 1, '  Minimize the negative Niederreiter-McCurley #2 function\n' );

  n = 4;
  lb = [ 0, 0, 0, 0 ];
  ub = [ 1, 1, 1, 1 ];
  x0 = ( lb + ub ) / 2.0;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Initial data:\n' );
  fprintf ( 1, '\n' );
  for j = 1 : n
    fprintf ( 1, '  ---X(%d)---', j );
  end
  fprintf ( 1, '  ----F(X)----\n' );
  fprintf ( 1, '\n' );
  for j = 1 : n
    fprintf ( 1, '  %10f', x0(j) );
  end
  fprintf ( 1, '  %12e\n', - niederreiter_mccurley2 ( x0 ) );

  [ x, fval, exitflag, output ] = fmincon ( @niederreiter_mccurley2, x0, ...
    [], [], [], [], lb, ub );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Computed optimum after %d function evaluations:\n', ...
    output.funcCount );
  fprintf ( 1, '\n' );
  for j = 1 : n
    fprintf ( 1, '  ---X(%d)---', j );
  end
  fprintf ( 1, '  ----F(X)----\n' );
  fprintf ( 1, '\n' );
  for j = 1 : n
    fprintf ( 1, '  %10f', x(j) );
  end
  fprintf ( 1, '  %12e\n', - niederreiter_mccurley2 ( x ) );

  return
end


function [Gal] = nmps22Gal(nmps2)
% Convert acceleration from nanometers per square-second to galileos
% Chad A. Greene 2012
Gal = nmps2*1e-7;


%Program for Fusing 2 images

%Author : Athi Narayanan S
%M.E, Embedded Systems,
%K.S.R College of Engineering
%Erode, Tamil Nadu, India.
%http://sites.google.com/site/athisnarayanan/
%s_athi1983@yahoo.co.in

%Program Description
%This program is the main entry of the application.
%This program fuses/combines 2 images
%It supports both Gray & Color Images
%Alpha Factor can be varied to vary the proportion of mixing of each image.
%With Alpha Factor = 0.5, the two images mixed equally.
%With Alpha Facotr < 0.5, the contribution of background image will be more.
%With Alpha Facotr > 0.5, the contribution of foreground image will be more.

function fusedImg = FuseImages(bgImg, fgImg, alphaFactor)

bgImg = double(bgImg);
fgImg = double(fgImg);

fgImgAlpha = alphaFactor .* fgImg;
bgImgAlpha = (1 - alphaFactor) .* bgImg;

fusedImg = fgImgAlpha + bgImgAlpha;


function v = volume(SO3F,center,radius,varargin)
% ratio of orientations with a certain orientation
%
% Description
% The function 'volume' returns the ratio of an orientation that is close
% to an orientation (center) by a misorientation tolerance (radius) to the
% volume of the entire odf.
%
% Syntax
%   v = volume(odf,center,radius)
%   v = volume(odf,fibre,radius) % gives the volume with a fibre
%
% Input
%  odf    - @SO3Fun
%  center - @orientation
%  fibre  - @fibre
%  radius - double
%
% Options
%  resolution - resolution of discretization
%
% See also
% SO3Fun/fibreVolume SO3Fun/entropy SO3Fun/textureindex

if isa(center,'fibre')

  v = fibreVolume(SO3F,center.h,center.r,radius,varargin{:});

else

  % get resolution
  res = get_option(varargin,'RESOLUTION',min(1.25*degree,radius/30),'double');

  % discretisation
  if nargin > 3 && isa(varargin{1},'orientation')
    S3G = varargin{1};
  else
    S3G = equispacedSO3Grid(SO3F.CS,SO3F.SS,...
      'maxAngle',radius,'center',center,'resolution',res,varargin{:});
  end

  % estimate volume portion of odf space
  reference = 9897129 * 96 / numProper(SO3F.CS) / numProper(SO3F.SS);
  f = min(1,length(S3G) * (res / 0.25 / degree)^3 / reference);

  % eval odf
  if f == 0
    v = 0;
  else
    v = mean(eval(SO3F,S3G)) * f;
  end
end

end


% ENMF: Exact NMF (Gillis and Glineur, 2012)
% process_video('NMF', 'ENMF', 'dataset/demo.avi', 'output/demo_ENMF.avi');
rank = 1;
[H,W] = ExactNMF(M,rank,100);
L = (W' * H')';
S = M - L;


function [ Wopt ] =update_beam_v2( H,K,M,grt,Pt,beta,omega )
%     Hc=H*W_old;
%     He=abs(Hc).^2;
    %% update W
    A=zeros(M,M);
    for k0=1:K
        tmp=abs(beta(k0))^2*H(k0,:)'*H(k0,:);
        A=A+tmp;
    end
    %% init
    lambda_min=0;
    lambda_max=real(sum(sum(A)));
    flag=0;
    while(1)
        [Wn]=downbeam_lambda(A,H,K,M,grt,beta,lambda_max);
        power=power_W( Wn );
        if power>Pt
            lambda_min=lambda_max;
            lambda_max=lambda_max*2;
        elseif power==Pt
            flag=1;
            break
        else
            break
        end
    end
    if flag~=1
        rho=Pt/power;
        Wopt=Wn.*sqrt(rho);
        [ ~,~,f0 ] = update_SINR( H,Wopt,K,omega );
        while(1)
%             [ lambda ] = update_lambda( lambda_min,lambda_max,A,M );
%             lambda=(lambda_min+lambda_max)/2;
            [ lambda,lambda_min ] = update_lambda_v2( lambda_min,lambda_max,A,M );
            [Wn]=downbeam_lambda(A,H,K,M,grt,beta,lambda);
            power=power_W( Wn );
            rho=Pt/power;
            Wn=Wn.*sqrt(rho);
            [ ~,~,f1 ] = update_SINR( H,Wn,K,omega );
            %%
            if power>Pt
                lambda_min=lambda;
            else
                lambda_max=lambda;
            end
            if f1>f0
                Wopt=Wn;
            end
            f0=f1;
            if abs(lambda_max-lambda_min)<1e-3 && abs(power-Pt)<1e-5 && abs(f1-f0)<1e-5
                break
            elseif abs(lambda_max-lambda_min)<1e-7 && lambda_min==0
                break
            end
        end
    end
end


function values = fast_intersection(rows, cols, values, target, unknown_dist, far_dist)
%FAST_INTERSECTION Under the assumption of categorical distance for the
% intersecting simplicial set perform a fast intersection.
%
% values = FAST_INTERSECTION(rows, cols, values, target, unknown_dist, far_dist)
%
% Parameters
% ----------
% rows: array
%     An array of the row of each non-zero in the sparse matrix
%     representation.
%
% cols: array
%     An array of the column of each non-zero in the sparse matrix
%     representation.
%
% values: array
%     An array of the value of each non-zero in the sparse matrix
%     representation.
%
% target: array of shape (n_samples, 1)
%     The categorical labels to use in the intersection.
%
% unknown_dist: double (optional, default 1)
%     The distance an unknown label (-1) is assumed to be from any point.
%
% far_dist: double (optional, default 5)
%     The distance between unmatched labels.
%
% Returns
% -------
% values: array
%     The non-zero entries resulting from the intersection.
%
%   AUTHORSHIP
%   Math Lead & Primary Developer:  Connor Meehan <connor.gw.meehan@gmail.com>
%   Secondary Developer: Stephen Meehan <swmeehan@stanford.edu>
%   Bioinformatics Lead:  Wayne Moore <wmoore@stanford.edu>
%   Provided by the Herzenberg Lab at Stanford University
%   License: BSD 3 clause

    if nargin < 6
        far_dist = 5;
        if nargin < 5
            unknown_dist = 1;
        end
    end

    row_labels = target(rows);
    col_labels = target(cols);

    unknown = row_labels == -1 | col_labels == -1;
    far = (row_labels ~= col_labels) & ~unknown;

    values(unknown) = values(unknown)*exp(-unknown_dist);
    values(far) = values(far)*exp(-far_dist);

    end


classdef ProductComputerForTensor < ProductComputer

    properties
    end

    methods (Access = public)

        function obj = ProductComputerForTensor(C,e)
            obj.generate(C,e)
        end
    end

    methods (Access = protected)

        function computeProduct(obj)
            C = obj.fourthOrder.getValue();
            e = obj.secondOrder.getValue();
            d = obj.secondOrder.getDimension();
            s = zeros(size(e));
            for i = 1:d
                for j = 1:d
                    for k = 1:d
                        for l = 1:d
                            cijkl = C(i,j,k,l);
                            ekl = e(k,l);
                            s(i,j) = s(i,j) + cijkl*ekl;
                        end
                    end
                end
            end
            obj.secondOrderOut.setValue(s)
        end

    end

end


function [f, df] = mySparseFun(X0, x, y, xu, s, sn)
if nargin == 0
    clc; close all;
    x = [-20:0.1:60]';
    y = rand(length(x), 1);
    xu = [-20:0.1:60]';
    n = length(x);
    s = 1.0;
    sn = 0.1;
    X0 = [0.1 0.1 log([2.0 2.0])]';
end
a = X0(1);
b = X0(2);
l = exp(X0(3));
l2 = l*l;
sf = exp(X0(4));
sf2 = sf*sf;
sn2 = sn*sn;

m = length(xu);
n = length(x);
[Kuu, dKuu] = CalKFun(xu, xu, X0(3:4));
Kuu = Kuu + sf2*1e-2*eye(m);    % stablize.
save('./KInfo.mat', 'Kuu', 'X0', 'xu');
if rank(Kuu) < m
    Kuu = Kuu + 1e-6*eye(m);
end
L0 = chol(Kuu, 'lower');
iL0 = inv(L0);
iKuu = iL0'*iL0;
logDetKuu = 2*sum(log(diag(L0)));

[Kfu, dKfu] = CalKFun(x, xu, X0(3:4));
Kuf = Kfu';
dKuf = {dKfu{1}', dKfu{2}'};

Qff = Kfu*iKuu*Kuf;
DiagKff = sf2*eye(n);
Gama = sn2*eye(n) + s*(DiagKff - diag(diag(Qff)));
iGama = diag( 1.0 ./ diag(Gama) );
logDetGama = sum( log(diag(Gama)) );
ApxK = Gama + Qff;   % use Woodbury to calculate its inverse and determinants: Z = Gama, U = V = Kfu, W = iKuu.
S = Kuu + Kfu'*iGama*Kfu;
% S = S + 1e-10*eye(m);  % for numerical stabitity.
% if rank(S) < m
%     S = S + 1e-6*eye(m);
% end
L1 = chol(S, 'lower');
logDetS = 2*sum( log(diag(L1)) );
iL1 = inv(L1);
iS = iL1'*iL1;
iApxK = iGama - iGama*Kfu*iS*Kfu'*iGama;
tmp = iApxK*ApxK;
tt = diag(tmp);
% max(tt) - min(tt)

logDetK = logDetGama - logDetKuu + logDetS;   % use Woodbury equation.
mx = a*x + b;
f = -0.5*(y-mx)'*iApxK*(y-mx) - 0.5*logDetK-0.5*n*log(2*pi);
% ff = -0.5*(y-mx)'*pinv(ApxK)*(y-mx) - 0.5*log(det(ApxK)) - 0.5*n*log(2*pi);
% -0.5*(y-mx)'*pinv(ApxK)*(y-mx)+0.5*(y-mx)'*iApxK*(y-mx)
%%%%%%%%%% calculate gradient.
dQ = {};
dGama = {};
dDiagK = {zeros(n, n), 2*DiagKff};
dK = {};
Alpha = iApxK*(y-mx);
df2m = [x'; ones(1, n)] * Alpha;
A = Alpha * Alpha' - iApxK;
df2c = zeros(2, 1);
for i = 1 : 1 : 2
     dQ{i} = dKfu{i}*iKuu*Kuf + Kfu*iKuu*dKuf{i}+Kfu*(-iKuu*dKuu{i}*iKuu)*Kuf;
     dGama{i} = s*dDiagK{i} - s*diag(diag(dQ{i}));
     dK{i} = dQ{i} + dGama{i};
     nSum = 0;
     for id = 1 : 1 : n
         nSum = nSum + A(id, :) * dK{i}(:, id);
     end
     df2c(i) = 0.5*nSum;
end
% TestWoodFun(Gama, iKuu, Kfu, Kfu);
%%%%%%%%% Test dQ.
% Eps = 1e-2;
% for i = 1 : 1 : 2
%     v = zeros(2, 1);
%     v(i) = Eps;
%     XNew = X0(3:4) + v;
%     [KfuNew, ~] = CalKFun(x, xu, XNew);
%     [KuuNew, ~] = CalKFun(xu, xu, XNew);
%     QffNew = KfuNew*inv(KuuNew)*KfuNew';
%     dQ_Est = (QffNew - Qff) / Eps;
%     dKuuNew = (KuuNew - Kuu)/Eps;
%     tmpDiff = dQ{i} - dQ_Est;
%     norm(tmpDiff(:))
% end

df = [df2m; df2c];

f = -f;
df = -df;
bTest = 1;
end

function [K, dK] = CalKFun(x, y, p)
l = exp(p(1));
sf = exp(p(2));
l2 = l*l;
sf2 = sf*sf;
m = length(x);
n = length(y);
dK = {};
X = repmat(x, 1, n);
Y = repmat(y', m, 1);
R = (X - Y) .*(X - Y);
K = sf2*exp(-0.5/l2*R);
dK{1} = 1/l2 * R.*K;
dK{2} = 2*K;
% tmp = zeros(m,n);
% for i = 1 : 1 : m
%     for j = 1 : 1 : n
%         r = x(i) - y(j);
%         r2 = r*r;
%         tmp(i, j) = sf2*exp(-0.5*r2/l2);
%     end
% end
% bTest = 1;
end

function [K] = TestWoodFun(Z, W, U, V)
K = Z + U * W * V';
InvZ = pinv(Z);
InvW = pinv(W);
S = InvW+V'*InvZ*U;
InvK = InvZ - InvZ*U*pinv(S)*V'*InvZ;
detK = det(Z)*det(W)*det(InvW + V'*InvZ*U);

A = K*InvK;
figure;
tt = diag(A);
plot(tt, 'b.' );
max(tt) - min(tt)
bTest = 1;
end


function[varargout] = vmedian(varargin)
%VMEDIAN  Median over finite elements along a specified dimension.
%
%   Y=VMEDIAN(X,DIM) takes the median of all finite elements of X along
%   dimension DIM.
%
%   [Y1,Y2,...YN]=VMEDIAN(X1,X2,...XN,DIM) also works.
%
%   VMEDIAN(X1,X2,...XN,DIM); with no output arguments overwrites the
%   original input variables.
%
%   VMEDIAN, like MATLAB's MEDIAN, defines the median over an even
%   number of values to be the average of the two middle elements.
%
%   VMEDIAN uses a fast algorithm which can be several times faster
%   than MEDIAN, but unlike MEDIAN, excludes both INFs and NANs.
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2008--2015 J.M. Lilly --- type 'help jlab_license' for details

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

dim=varargin{end};

for i=1:length(varargin)-1
   if isreal(varargin{i})
       varargout{i}=vmedian1(varargin{i},dim);
   else
       varargout{i}=vmedian1(real(varargin{i}),dim)+sqrt(-1)*vmedian1(imag(varargin{i}),dim);
   end
end

eval(to_overwrite(nargin-1))

function[med]=vmedian1(data,dim)

numel=sum(isfinite(data),dim);
med=vzeros(size(numel),'nan');

temp=vswap(data,nan,inf);
temp=vswap(temp,-inf,inf);
sorted=sort(temp,dim,'ascend');
sorted=permute(sorted,[1:dim-1 dim+1:ndims(sorted) dim]);
sorted=reshape(sorted,[length(numel(:)),size(sorted,ndims(sorted))]);

ii=(1:length(numel(:)))';
ii=reshape(ii,size(numel));

boolodd=isodd(numel);
booleven=~boolodd&(numel~=0);

%ii(boolodd)

%(numel(boolodd)+1)./2

%looking to fix bug reported by Sandra
%indexodd=sub2ind(size(sorted),ii(boolodd),(numel(boolodd)+1)./2);
%indexeven1=sub2ind(size(sorted),ii(booleven),numel(booleven)./2);
%indexeven2=sub2ind(size(sorted),ii(booleven),numel(booleven)./2+1);

% vsize(sorted,ii,find(boolodd))
% anyany(~isfinite(boolodd))
% minmin(numel(boolodd))
% maxmax(numel(boolodd))
% median(vcolon(numel(boolodd)),1)
% minmin((numel(boolodd)+1)/2)
% maxmax((numel(boolodd)+1)/2)
% median((numel(boolodd)+1)/2,1)

if ~isempty(boolodd)
    indexodd=sub2ind(size(sorted),ii(boolodd),(numel(boolodd)+1)./2);
    med(boolodd)=sorted(indexodd);
end
if ~isempty(booleven)
    indexeven1=sub2ind(size(sorted),ii(booleven),numel(booleven)./2);
    indexeven2=sub2ind(size(sorted),ii(booleven),numel(booleven)./2+1);
    med(booleven)=sorted(indexeven1)./2+sorted(indexeven2)./2;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[]=vmedian_test

N=6;
x1=randn(N,N,N,N,N);
bool=false(5,1);
tol=1e-4;

etime1=0;
etime2=0;
for i=1:5
    tic;y1=vmedian(x1,i);etime1=etime1+toc;
    tic;z1=median(x1,i);etime2=etime2+toc;
    bool(i)=aresame(y1,z1,tol);
end
reporttest('VMEDIAN 5-D with no NANs versus MEDIAN', allall(bool))
disp(['VMEDIAN was ' num2str(etime2./etime1) ' faster than MEDIAN.'])

N=30;
x1=randn(N,N,N);
x1(2:7:end)=nan;

tic
y1=vmedian(x1,1);
y2=vmedian(x1,2);
y3=vmedian(x1,3);
etime1=toc;

z1=zeros(size(y1));
z2=zeros(size(y2));
z3=zeros(size(y3));

tic
for i=1:N
    for j=1:N
        z1(1,i,j)=median(x1(isfinite(x1(:,i,j)),i,j),1);
        z2(i,1,j)=median(x1(i,isfinite(x1(i,:,j)),j),2);
        z3(i,j)=median(x1(i,j,isfinite(x1(i,j,:))),3);
    end
end
etime2=toc;
tol=1e-4;
reporttest('VMEDIAN 3-D including NANs', aresame(y1,z1,tol) && aresame(y2,z2,tol)&&aresame(y3,z3,tol))
disp(['VMEDIAN was ' num2str(etime2./etime1) ' faster than loop with MEDIAN.'])

N=30;
x1=round(randn(N,N,N));
x1(2:7:end)=nan;
x1(1:9:end)=x1(1);

tic
y1=vmedian(x1,1);
y2=vmedian(x1,2);
y3=vmedian(x1,3);
etime1=toc;

z1=zeros(size(y1));
z2=zeros(size(y2));
z3=zeros(size(y3));

tic
for i=1:N
    for j=1:N
        z1(1,i,j)=median(x1(isfinite(x1(:,i,j)),i,j),1);
        z2(i,1,j)=median(x1(i,isfinite(x1(i,:,j)),j),2);
        z3(i,j)=median(x1(i,j,isfinite(x1(i,j,:))),3);
    end
end
etime2=toc;
tol=1e-4;
reporttest('VMEDIAN 3-D including NANs and repeated data', aresame(y1,z1,tol) && aresame(y2,z2,tol)&&aresame(y3,z3,tol))
disp(['VMEDIAN was ' num2str(etime2./etime1) ' faster than loop with MEDIAN.'])

reporttest('VMEDIAN NaNs with row median',aresame([1 nan],vmedian([1 nan; nan nan],1)));
reporttest('VMEDIAN NaNs with column median',aresame([1 nan]',vmedian([1 nan; nan nan],2)));


function F = fuzzysysfcn(inmf,outmf,vrange,op)
%FUZZYSYSFCN Fuzzy system function.
%   F = FUZZYSYSFCN(INMF,OUTMF,VRANGE,OP) creates a fuzzy system
%   function, F, corresponding to a set of rules and output membership
%   functions. INMF is an M-by-N matrix of input membership function
%   handles. M is the number of rules, and N is the number of fuzzy
%   system inputs. OUTMF is a cell array containing output membership
%   functions. numel(OUTMF) can be either M or M + 1. If it is M + 1,
%   then the "extra" output membership function is used for an
%   automatically computed "else rule." VRANGE is a two-element vector
%   specifying the valid range of input values for the output membership
%   functions. OP is a function handle specifying how to combine the
%   antecedents for each rule. OP can be either @min or @max. If OP is
%   omitted, then @min is used.
%
%  The output, F, is a function handle that computes the fuzzy system's
%  output, given a set of inputs, using the syntax:
%  out = F(Z1,Z2,Z3,...,ZN);
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

if nargin < 4
   op = @min;
end

% The lambda functions are independent of the inputs Z1,Z2,...,ZN, so
% they can be computed in advance.
L = lambdafcns(inmf,op);

F = @fuzzyOutput;

   %-------------------------------------------------------------------%
   function out = fuzzyOutput(varargin)
      Z = varargin;
      % The implication functions and aggregation functions have to be
      % computed separately for each input value.  Therefore we have to
      % loop over each input value to determine the corresponding output
      % value. Zk is a cell array that will be used to pass scalar
      % values for each input (Z1,Z2,...,ZN) to IMPLFCNS.
      Zk = cell(1,numel(Z));
      % Initialize the array of output values to be the same size as the
      % first input,Z{1}.
      out = zeros(size(Z{1}));
      for k = 1:numel(Z{1})
         for p = 1:numel(Zk)
            Zk{p} = Z{p}(k);
         end
         Q = implfcns(L,outmf,Zk{:});
         Qa = aggfcn(Q);
         out(k) = defuzzify(Qa,vrange);
      end
   end

end


function d = gsp_hop_distanz(G,i,j)
%GSP_HOP_DISTANZ Compute the hop distance between two node
%   Usage:  d = gsp_hop_distanz(G,i,j);
%
%   Input parameters:
%       G   : Graph
%       i   : node
%       j   : node
%   Output parameters:
%       d   : hop distanz
%
%   This code computes the hop distance between node i and node j. It uses
%   a naive greedy algorithm and has to be improved.
%

% Author: Nathanael Perraudin
% Date  : 15 septembre 2015
% Testing: test_gsp_hope_distanz

M = double(logical(G.W));
s = zeros(G.N,1);
s(i) = 1;
s = logical(s);
d = 0;
while s(j)==0 && d<=G.N+1
    d = d+1;
    s = logical(M*double(s)) +s;
end

if d == G.N+1
    d = inf;
end

end


function [k,sigma,mu] = myDistFit(Temperature)
%MYDISTFIT    Create plot of datasets and fits
%   MYDISTFIT(TEMPERATURE)
%   Creates a plot, similar to the plot in the main distribution fitting
%   window, using the data that you provide as input.  You can
%   apply this function to the same data you used with dfittool
%   or with different data.  You may want to edit the function to
%   customize the code and this help message.
%
%   Number of datasets:  1
%   Number of fits:  1

% This function was automatically generated on 04-Dec-2006 08:27:07

% Data from dataset "Temperature data":
%    Y = Temperature

% Force all inputs to be column vectors
Temperature = Temperature(:);

% Set up figure to receive datasets and fits
f_ = clf;
figure(f_);
set(f_,'Units','Pixels','Position',[654 334.5 680 468.45]);
legh_ = []; legt_ = {};   % handles and text for legend
ax_ = newplot;
set(ax_,'Box','on');
hold on;

% --- Plot data originally in dataset "Temperature data"
t_ = ~isnan(Temperature);
Data_ = Temperature(t_);
[F_,X_] = ecdf(Data_,'Function','cdf'...
              );  % compute empirical cdf
Bin_.rule = 1;
[C_,E_] = dfswitchyard('dfhistbins',Data_,[],[],Bin_,F_,X_);
[N_,C_] = ecdfhist(F_,X_,'edges',E_); % empirical pdf from cdf
h_ = bar(C_,N_,'hist');
set(h_,'FaceColor','none','EdgeColor',[0.333333 0 0.666667],...
       'LineStyle','-', 'LineWidth',1);
xlabel('Data');
ylabel('Density')
legh_(end+1) = h_;
legt_{end+1} = 'Temperature data';

% Nudge axis limits beyond data limits
xlim_ = get(ax_,'XLim');
if all(isfinite(xlim_))
   xlim_ = xlim_ + [-1 1] * 0.01 * diff(xlim_);
   set(ax_,'XLim',xlim_)
end

x_ = linspace(xlim_(1),xlim_(2),100);

% --- Create fit "Generalized Extreme Value Fit"

% Fit this distribution to get parameter values
t_ = ~isnan(Temperature);
Data_ = Temperature(t_);
% To use parameter estimates from the original fit:
%     p_ = [ -0.1140337456229, 30.99486601834, 23.95766494166];
p_ = gevfit(Data_, 0.05);
y_ = gevpdf(x_,p_(1), p_(2), p_(3));
h_ = plot(x_,y_,'Color',[1 0 0],...
          'LineStyle','-', 'LineWidth',2,...
          'Marker','none', 'MarkerSize',6);
legh_(end+1) = h_;
legt_{end+1} = 'Generalized Extreme Value Fit';

hold off;
leginfo_ = {'Orientation', 'vertical', 'Location', 'NorthEast'};
h_ = legend(ax_,legh_,legt_,leginfo_{:});  % create legend
set(h_,'Interpreter','none');

% ---- Added code after generation
k = p_(1);
sigma = p_(2);
mu = p_(3);


function sftpack_test ( )

%*****************************************************************************80
%
%% SFTPACK_TEST tests the SFTPACK library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 August 2010
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SFTPACK_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the SFTPACK library.\n' );

  sftpack_test01 ( );
  sftpack_test02 ( );
  sftpack_test03 ( );
  sftpack_test04 ( );
  sftpack_test05 ( );
  sftpack_test06 ( );
  sftpack_test07 ( );
  sftpack_test08 ( );

  sftpack_test11 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'SFTPACK_TEST\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function [fitness, class, Simil] = calcfitness(data, ideals, y, w)
[nc, v_dim] = size(ideals);
d_dim = size(data,1);

if nargin==3
   w=ones(1,v_dim);
end
[class, Simil] = classifier(data(:,1:v_dim), ideals, y, w);
fitness = length(find(class-data(:, v_dim +1) == 0))/d_dim;


% predicting numerical values using Discreminate Analysis

clear all;

disp('===REgress Tree===');
disp('Reading featur vector');

featurs = csvread('forWeka_featuresonly.csv');

num_data = 5000;
size_training = floor(.6*num_data);

trainingset = featurs(1:size_training,:);
testset = featurs((size_training+1):num_data,:);

disp('Splitting up data into training/test sets');
[num,txt,raw] = xlsread('C:\MatlabNLP\examples\gsa\data\final104.xls');

% reading the description of each shoe
descriptions = raw(2:size(raw,1),2);
style_ratings = num(1:size(num,1),1);
comfort_ratings = num(1:size(num,1),4);
overal_ratings = num(1:size(num,1),5);

% only take m data points
m=num_data;
descriptions = descriptions(1:m);
style_ratings = style_ratings(1:m);
comfort_ratings = comfort_ratings(1:m);
overal_ratings = overal_ratings(1:m);

responsevals = [style_ratings, comfort_ratings, overal_ratings];

responsevals_training = responsevals(1:size_training,:);
responsevals_test = responsevals((size_training+1):num_data,:);
disp('Multiple linear regression');
% http://www.mathworks.com/help/toolbox/stats/classregtree.html

tic;

a = responsevals_training(:,3)';
b = responsevals_test(:,3)';

class = classregtree(trainingset,a');
yfit = round(eval(class,testset));

cMat2 = confusionmat(yfit,b)
toc;