function [node,elem,face]=s2m(v,f,keepratio,maxvol,method,regions,holes,varargin)
%
% [node,elem,face]=s2m(v,f,keepratio,maxvol,method)
% [node,elem,face]=s2m(v,f,keepratio,maxvol,'tetgen',regions,holes)
%
% volumetric mesh generation from a closed surface, shortcut for surf2mesh
%
% author: Qianqian Fang (q.fang at neu.edu)
%
% inputs and outputs are similar to those defined in surf2mesh
%
% if method='cgalpoly', s2m will call cgals2m and keepratio should be a
% structure (as the 'opt' input in cgals2m)
%
% input default values:
%       method: if ignored, iso2mesh uses surf2mesh ('tetgen') to do the
%               tetrahedral mesh generation
%       regions,holes: if ignored, iso2mesh assumes both are empty
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

if(nargin>=5 && strcmp(method,'cgalpoly'))
    [node,elem,face]=cgals2m(v,f,keepratio,maxvol);
    return;
end
if(nargin<=5)
    regions=[];
end
if(nargin<=6)
    holes=[];
end
if(nargin>=5)
    if(nargin>=8)
        [node,elem,face]=surf2mesh(v,f,[],[],keepratio,maxvol,regions,holes,0,method,varargin{:});
    else
        [node,elem,face]=surf2mesh(v,f,[],[],keepratio,maxvol,regions,holes,0,method);
    end
else
    [node,elem,face]=surf2mesh(v,f,[],[],keepratio,maxvol,regions,holes);
end


function is=lpcrf2is(rf)
%LPCRF2IS Convert reflection coefficients to inverse sines IS=(RF)

%      Copyright (C) Mike Brookes 1997
%      Version: $Id: lpcrf2is.m,v 1.4 2007/05/04 07:01:39 dmb Exp $
%
%   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.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

is=asin(rf)*2/pi;


function codeKeeper = syncPatternDetectNEV(NEVStruct)

% syncPatternDetectNEV
%
% Finds the code for the SYNC pattern on the SYNC output of Blackrock
% Microsystems Neural Signal Processor (NSP) recorded by analog input
% channel 16 and thresholded as extracted spikes and saved in the NEV file.
%
%   INPUT
%
%   NEVStruct:  The NEV structure containing the SYNC pulse.
%
%   OUTPUT
%
%   codeKeeper: A cell structure containing the unique code and their
%               respective timestamps.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   USAGE EXAMPLE:
%
%   codeKeeper = syncPatternDetectNEV(NEVStruct)
%
%   In the example above, the NEV structure, containing the continueus
%   signal from the SYNC pulse is passed to the function. The output will
%   contain the unique codes parsed from the signal file and their
%   respective timestamps.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Kian Torab
%   kian@blackrockmicro.com
%   Blackrock Microsystems
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Version History
%
% 1.0.0.0: July 7, 2014
%   - Initial release.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Setup
separationVar = 'D';

%% Detect the rising edges
edgeTS = NEVStruct.Data.Spikes.TimeStamp(NEVStruct.Data.Spikes.Electrode == 144);
differenceTS = double(diff(edgeTS));
pulseDifferenceLenght = mode(differenceTS);

convertedChar = [];
for idx = 1:length(differenceTS)
    if differenceTS(idx) < pulseDifferenceLenght*1.1;
        convertedChar = [convertedChar, '1'];
    elseif differenceTS(idx) < 9*pulseDifferenceLenght;
        convertedChar = [convertedChar, repmat('0', 1, round((differenceTS(idx) - pulseDifferenceLenght)/pulseDifferenceLenght)), '1'];
    else
        convertedChar = [convertedChar, separationVar];
    end
end

begTS = edgeTS(find(differenceTS > pulseDifferenceLenght * 12) + 1);
%%
begTS = [edgeTS(1) begTS];

codeKeeper{1} = bin2dec(regexp(convertedChar, separationVar, 'split'))';
codeKeeper{2} = begTS;


% LOTKA-VOLTERRA system

clear all, close all, clc
figpath = '../FIGURES/'; mkdir(figpath)
datapath = '../DATA/';
addpath('../utils');

%% Load Models
ModelCollection = {'DMDc','SINDYc', 'NARX'};
Nmodels = length(ModelCollection);
InputSignalType = 'sphs'; % prbs; chirp; noise; sine2; sphs; mixed
TrainAlg = 'trainbr'; %trainlm,trainbr
dep_trainlength = 1;
dep_noise = 0;

% Ntrain_vec = [5:15,20:5:95,100:100:1000];%,1500:500:3000];
% eta_vec = 0.0;
% Nr = 1;

Ntrain_vec = [5:15,20:5:95,100:100:1000,1250,1500,2000,3000];%,1500:500:3000];
eta_vec = 0.05;
Nr = 1;

N_LENGTHS = length(Ntrain_vec);

%% Load data
ResultsALL(N_LENGTHS,1:Nmodels) = struct('x', [], 'u', [], 't', [], 'xref', [], 'J', [], 'eval_time', []);

ModelName = 'DMDc';
datapath1 = [datapath,'EX_LOTKA_Dependencies/',ModelName,'/'];
load(fullfile(datapath1,['EX_LOTKA_MPC_',ModelName,'_',InputSignalType,'_TrainLength','.mat']))
ResultsALL(:,1) = Results;

ModelName = 'SINDYc';
datapath1 = [datapath,'EX_LOTKA_Dependencies/',ModelName,'/'];
load(fullfile(datapath1,['EX_LOTKA_MPC_',ModelName,'_',InputSignalType,'_TrainLength','.mat']))
ResultsALL(:,2) = Results;

ModelName = 'NARX';
datapath1 = [datapath,'EX_LOTKA_Dependencies/',ModelName,'/',TrainAlg,'/'];
load(fullfile(datapath1,['EX_LOTKA_MPC_',ModelName,'_',InputSignalType,'_TrainLength','.mat']))
ResultsALL(:,3) = Results;

%% Correct cost
Q = [1,1]; R = 0.5; Ru = 0.5;
for iM = 1:Nmodels
    for iL = 1:N_LENGTHS
        ResultsALL(iL,iM).J = evalObjectiveFCN(ResultsALL(iL,iM).u,ResultsALL(iL,iM).x,ResultsALL(iL,iM).xref,diag(Q),R,Ru);
    end
end

%% Show trajectories
cb_hrzntl = 1;

cmap = jet(N_LENGTHS);
for jModel = 1:Nmodels
    figure, hold on, box on
    for iM = 1:N_LENGTHS
        plot(ResultsALL(iM,jModel).x(1,:),ResultsALL(iM,jModel).x(2,:),'-','Color',cmap(iM,:),'LineWidth',1)
    end
    plot(ResultsALL(iM,jModel).xref(1,1),ResultsALL(iM,jModel).xref(2,1),'ok','MarkerFaceColor','k')
    %     axis equal
    ylim([-20 100]), xlim([0 200])
    colormap(cmap),
    ch = colorbar;
    ch.Limits = [0 1];
    ch.Ticks = [0,0.25,0.5,0.75,1];
    ch.TickLabels = num2str( Ntrain_vec( [1, (N_LENGTHS-1)/4, (N_LENGTHS-1)/2+1, 3*(N_LENGTHS-1)/4+1, 4*(N_LENGTHS-1)/4+1] )' );
    if cb_hrzntl == 0
        ch.Position = [ch.Position(1),ch.Position(2)+0.14,ch.Position(3)-0.01,ch.Position(4)-0.1];
        set(gca,'Position',[0.08 0.2753 0.775 0.6497])
    elseif cb_hrzntl == 1
        ch.Location = 'southoutside';
        ch.Position = [0.2,0.1,0.75,ch.Position(4)];
        set(gca,'Position',[0.2 0.4 0.75 0.55])
    end
    xlabel('x1');
    ylabel('x2')
    set(gca,'LineWidth',1, 'FontSize',14)
    set(gcf,'Position',[100 100 300 200])
    set(gcf,'PaperPositionMode','auto')
    print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_State_',ModelCollection{jModel},'.eps']);
end

%% Show cost trajectory
cb_hrzntl = 1;

cmap = jet(N_LENGTHS);
for jModel = 1:Nmodels
    figure, hold on, box on
    for iM = 1:N_LENGTHS
        plot(ResultsALL(end,jModel).t,cumsum(ResultsALL(iM,jModel).J),'-','Color',cmap(iM,:),'LineWidth',1)
    end
    plot(ResultsALL(end,2).t,cumsum(ResultsALL(end,2).J),'--','Color','k','LineWidth',2)
    ylim([-10 10^6]), xlim([200 max(ResultsALL(end,jModel).t)])
    colormap(cmap),
    ch = colorbar;
    ch.Limits = [0 1];
    ch.Ticks = [0,0.25,0.5,0.75,1];
    ch.TickLabels = num2str( Ntrain_vec( [1, (N_LENGTHS-1)/4, (N_LENGTHS-1)/2+1, 3*(N_LENGTHS-1)/4+1, 4*(N_LENGTHS-1)/4+1] )' );
    if cb_hrzntl == 0
        ch.Position = [ch.Position(1),ch.Position(2)+0.14,ch.Position(3)-0.01,ch.Position(4)-0.1];
        set(gca,'Position',[0.08 0.2753 0.775 0.6497])
    elseif cb_hrzntl == 1
        ch.Location = 'southoutside';
        ch.Position = [0.2,0.1,0.75,ch.Position(4)];
        set(gca,'Position',[0.2 0.4 0.75 0.55])
    end
    ylim([10^3 10^6])
    set(gca,'yscale','log')
    xlabel('Time');
    ylabel('Cost')
    set(gca,'LineWidth',1, 'FontSize',14)
    set(gcf,'Position',[100 100 300 200])
    set(gcf,'PaperPositionMode','auto')
    print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_Cost_',ModelCollection{jModel},'.eps']);
end

%% Show execution time
clear ph
ccolors = [1 0 0; 0 1 0; 0.7,0.7,1];
lstyles = {'-', '--', '-.'};
symbols = {'o', 'd', 's'};

Tx = zeros(length(N_LENGTHS),Nmodels);
for iM = 1:Nmodels
    for iL = 1:N_LENGTHS
        Tx(iL,iM) = ResultsALL(iL,iM).eval_time;
    end
end
figure, hold on, box on
for iM = 1:Nmodels
    plot(Ntrain_vec,Tx(:,iM)./60,symbols{iM},'Color',ccolors(iM,:),'MarkerFaceColor',ccolors(iM,:))
end
xlim([4 1001])
ylim([0.5*10^-5 10^2])
set(gca,'ytick',[10.^([-5:2:2])])
set(gca,'XScale','log','YScale','log')
xlabel('Length of Training Data');
ylabel('Time [m]')
legend(ModelCollection,'Location','SouthEast')
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 200])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_ExecTime','.eps']);
legend('off')
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_ExecTime','_noleg.eps']);

%% Add penalization
Q = 1*eye(2); %20
for iM = 1:Nmodels
    for iL = 1:N_LENGTHS
       if ResultsALL(iL,iM).t(end) == 0
           % Flag not converged / ended early
           ResultsALL(iL,iM).J(end) = 10^6;
       else
           % Flag if far from end state at end of time
           %ResultsALL(iL,iM).J(end) = ResultsALL(iL,iM).J(end) + abs(ResultsALL(iL,iM).xref(:,end) - ResultsALL(iL,iM).x(:,end))'*Q*abs(ResultsALL(iL,iM).xref(:,end) - ResultsALL(iL,iM).x(:,end));
       end
    end
end

%% Show Performance over training lengths
clear ph
ccolors = [1 0 0; 0 1 0; 0.7,0.7,1];
lstyles = {'-', '--', '-.'};
symbols = {'o', 'd', 's'};

Nstart = 20;
xx = Ntrain_vec(Nstart):2:1000;
yModel = zeros(length(xx),Nmodels);
JendAll = zeros(length(N_LENGTHS),Nmodels);
Jend = cell(Nmodels,1);
xJend = cell(Nmodels,1);

for iM = 1:Nmodels
%     Jend{iM} = zeros(length(N_LENGTHS),Nmodels);
    count = 0;
    for iL = 1:N_LENGTHS,
        tmp = cumsum(ResultsALL(iL,iM).J);
        if tmp(end)<10^10
            count = count + 1;
            xJend{iM}(count) = Ntrain_vec(iL);
            Jend{iM}(count) = tmp(end);
        end
        JendAll(iL,iM) = tmp(end);
    end
    yModel(:,iM) = spline(xJend{iM}(Nstart:end),Jend{iM}(Nstart:end),xx);
end

clear ph
figure, hold on, box on

if eta_vec == 0.05
    fillh1 = fill([4.5*10^0 2.85*10^3 2.85*10^3 4.5*10^0], [5.5*10^3 5.5*10^3 1.5*10^4 1.5*10^4],0.9*ones(1,3)); % /w noise, not performing well above
elseif  eta_vec == 0.0
    fillh1 = fill([4.5*10^0 2.85*10^3 2.85*10^3 4.5*10^0], [5.5*10^3 5.5*10^3 2.5*10^4 2.5*10^4],0.9*ones(1,3));
end
fillh1.EdgeColor = 0.9*ones(1,3); fillh1.FaceAlpha = 0.5;

[~,idx_best] = min(JendAll(:,2));
plot(Ntrain_vec,JendAll(idx_best,2)*ones(size(Ntrain_vec)),'-','Color',ccolors(2,:),'LineWidth',1)

for iM = 1:Nmodels
%     if iM <= Nmodels
%         plot(xx,yModel(:,iM),'-','Color',ccolors(iM,:), 'LineWidth',1, 'LineStyle',lstyles{iM}), hold on,
%     end
    ph(iM) = plot(Ntrain_vec,JendAll(:,iM),symbols{iM},'Color',ccolors(iM,:),'MarkerFaceColor',ccolors(iM,:),'MarkerSize',4);
end
if eta_vec == 0
    iM = 1; plot([6.5,6.5],[5*10^3 10^7],'Color',ccolors(iM,:),'LineStyle',lstyles{iM});
    iM = 2; plot([13.5,13.5],[5*10^3 10^7],'Color',ccolors(iM,:),'LineStyle',lstyles{iM});
    iM = 3; plot([100,100],[5*10^3 10^7],'Color',ccolors(iM,:),'LineStyle',lstyles{iM});
elseif eta_vec == 0.05
    iM = 1; plot([7.5,7.5],[5*10^3 10^7],'Color',ccolors(iM,:),'LineStyle',lstyles{iM});
    iM = 2; plot([70,70],[5*10^3 10^7],'Color',ccolors(iM,:),'LineStyle',lstyles{iM});
    iM = 3; plot([130,130],[5*10^3 10^7],'Color',ccolors(iM,:),'LineStyle',lstyles{iM});
end
xlim([4 3001])
% ylim([-100 5000])
% ylim([5*10^2 1.5*10^4])
% ylim([1*10^2 10^5])
ylim([5*10^3 10^7])
% set(gca,'YScale','log')
set(gca,'XScale','log','YScale','log', 'ytick', [10^3,10^4,10^5,10^6,10^7], 'xtick', [10^0,10^1,10^2,10^3]) %[10^3,5*10^3,10^4]
xlabel('Length of Training Data');
ylabel('Cost')
lh = legend(ph,ModelCollection,'Location','NorthEast');
lh.Position = [0.71 0.73 lh.Position(3)-0.05 lh.Position(4)];
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 200])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_Cost','.eps']);

lh.Location = 'NorthOutside';
lh.Orientation = 'horizontal';
lh.Box = 'off';
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_Cost','_legout.eps']);
legend('off')
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_Cost','_noleg.eps']);

%% Show best case for all models
% eta = 0.05: 8    38    21
% -->  Ntrain = 12        1250          65
% --> Jend = 9.0603e+03,  8.6549e+03, 2.0592e+04
% Jend for best eta==0: 8(12), 38(1250), 21(65)
% SINDY converged Ntrain = 200
% eta = 0.0: 12    25    37
% -->  Ntrain = 20          85        1000
% --> Jend = 9.0601e+03,  8.6595e+03, 8.9236e+03
% SINDY converged Ntrain = 200
BestModelIDX = zeros(1,Nmodels);
Jend = zeros(N_LENGTHS,Nmodels);
for iM = 1:Nmodels
   for iL = 1:N_LENGTHS
        tmp = cumsum(ResultsALL(iL,iM).J);
        Jend(iL,iM) = tmp(end);
   end
   [~,BestModelIDX(iM)] = min(Jend(:,iM));
end

% [val,idx1] = min(abs(Jend(:,1)-9.0601e+03))
% Ntrain_vec(idx1)
% [val,idx2] = min(abs(Jend(:,2)-8.6595e+03))
% Ntrain_vec(idx2)
% [val,idx3] = min(abs(Jend(:,3)-8.9236e+03))
% Ntrain_vec(idx3)

ccolors = [1 0 0; 0 1 0; 0.7,0.7,1];
lstyles = {'-', '--', '-.'};

figure,
hold on, box on
plot(ResultsALL(BestModelIDX(1),1).t,ResultsALL(1,1).xref(1,:),'-k')
for iM = 1:Nmodels
    plot(ResultsALL(BestModelIDX(iM),iM).t,ResultsALL(BestModelIDX(iM),iM).x(1,:),'Color',ccolors(iM,:),'LineStyle',lstyles{iM},'LineWidth',2)
end
ylim([65 110])
xlabel('Time'), ylabel('Prey')
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 100])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_BestModels_x1','.eps']);

figure,
hold on, box on
plot(ResultsALL(BestModelIDX(1),1).t,ResultsALL(1,1).xref(2,:),'-k')
for iM = 1:Nmodels
    plot(ResultsALL(BestModelIDX(iM),iM).t,ResultsALL(BestModelIDX(iM),iM).x(2,:),'Color',ccolors(iM,:),'LineStyle',lstyles{iM},'LineWidth',2)
end
ylim([7 27])
xlabel('Time'), ylabel('Predator')
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 100])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_BestModels_x2','.eps']);

figure,
hold on, box on
for iM = 1:Nmodels
    plot(ResultsALL(BestModelIDX(iM),iM).t,cumsum(ResultsALL(BestModelIDX(iM),iM).J),'Color',ccolors(iM,:),'LineStyle',lstyles{iM},'LineWidth',2)
end
if eta_vec == 0
    ylim([7*10^3 9.5*10^3])
elseif eta_vec == 0.05
    ylim([7*10^3 1*10^4])
end
set(gca,'yscale','linear','ytick',[7*10^3,8*10^3,9*10^3],'yticklabels',{'70','80','90'})
xlabel('Time'), ylabel('Cost')
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 100])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_BestModels_J','.eps']);

%% Show State Performance over training lengths
Q = 1*eye(2); %20
Jstate = zeros(length(ResultsALL(iL,iM).J),N_LENGTHS,Nmodels);
for iM = 1:Nmodels
    for iL = 1:N_LENGTHS
        for it = 1:length(ResultsALL(iL,iM).xref(1,:))
            Jstate(it,iL,iM) = abs(ResultsALL(iL,iM).xref(:,it) - ResultsALL(iL,iM).x(:,it))'*Q*abs(ResultsALL(iL,iM).xref(:,it) - ResultsALL(iL,iM).x(:,it));
        end
    end
end

clear ph
ccolors = [1 0 0; 0 1 0; 0.7,0.7,1];
lstyles = {'-', '--', '-.'};
symbols = {'o', 'd', 's'};

Nstart = 20;
xx = Ntrain_vec(Nstart):2:1000;
yModel = zeros(length(xx),Nmodels);
JendAll = zeros(length(N_LENGTHS),Nmodels);
Jend = cell(Nmodels,1);
xJend = cell(Nmodels,1);

for iM = 1:Nmodels
%     Jend{iM} = zeros(length(N_LENGTHS),Nmodels);
    count = 0;
    for iL = 1:N_LENGTHS,
        tmp = cumsum(Jstate(:,iL,iM));
        if tmp(end)<10^10
            count = count + 1;
            xJend{iM}(count) = Ntrain_vec(iL);
            Jend{iM}(count) = tmp(end);
        end
        JendAll(iL,iM) = tmp(end);
    end
    yModel(:,iM) = spline(xJend{iM}(Nstart:end),Jend{iM}(Nstart:end),xx);
end

figure, hold on, box on
for iM = 1:Nmodels
%     if iM < Nmodels
%         plot(xx,yModel(:,iM),'-','Color',ccolors(iM,:), 'LineWidth',1, 'LineStyle',lstyles{iM}), hold on,
%     end
    plot(Ntrain_vec,JendAll(:,iM),symbols{iM},'Color',ccolors(iM,:),'MarkerFaceColor',ccolors(iM,:),'MarkerSize',4)
end
xlim([4 1001])
ylim([5*10^3 5*10^6])
% set(gca,'YScale','log')
set(gca,'XScale','log','YScale','log', 'ytick', [10^4,10^5,10^6], 'xtick', [10^0,10^1,10^2,10^3])
xlabel('Length of Training Data');
ylabel('Cost')
lh = legend(ModelCollection,'Location','NorthEast');
lh.Position = [0.71 0.73 lh.Position(3)-0.05 lh.Position(4)];
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 200])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_CostState','.eps']);

lh.Location = 'NorthOutside';
lh.Orientation = 'horizontal';
lh.Box = 'off';
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_CostState','_legout.eps']);
legend('off')
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_CostState','_noleg.eps']);

return
%% Legend // Dummy plot
figure, hold on, box on
for iM = 1:Nmodels
    plot(Ntrain_vec,ones(size(Ntrain_vec)),'-','Marker',symbols{iM},'Color',ccolors(iM,:),'MarkerFaceColor',ccolors(iM,:))
end

% xlabel('Length of Training Data');
% ylabel('Cost')
axis off
lh = legend(ModelCollection,'Location','NorthEast');
lh.Location = 'NorthOutside';
lh.Orientation = 'horizontal';
lh.Box = 'off';
set(gca,'LineWidth',1, 'FontSize',14)
set(gcf,'Position',[100 100 300 100])
set(gcf,'PaperPositionMode','auto'),
print('-depsc2', '-painters', '-loose', '-cmyk', [figpath,'EX_LOTKA_CTRLPERF_',InputSignalType,'_Eta',sprintf('%03g',100*eta_vec),'_TrainingLength_Legend','.eps']);

return
%% TESTING

% [~,idx_best_DMDc] = min(JendAll(:,1));
% % plot(Ntrain_vec,JendAll(idx_best,2)*ones(size(Ntrain_vec)),'-','Color',ccolors(2,:),'LineWidth',1)
% iM = 1;
% iL = idx_best_DMDc;

%
iM = 3;
iL = find(Ntrain_vec == 85); % DMDc

% iM = 1;
% iL = find(Ntrain_vec == 10); % DMDc

% iM = 3;
% iL = find(Ntrain_vec == 3000); % NARX: 85, 100, 14

figure, hold on
plot(ResultsALL(end,2).x(1,:),ResultsALL(end,2).x(2,:),'-k','LineWidth',1)
plot(ResultsALL(iL,iM).x(1,:),ResultsALL(iL,iM).x(2,:),'--r','LineWidth',1)

figure, hold on
plot(ResultsALL(end,2).t,ResultsALL(end,2).x(2,:),'-k','LineWidth',1)
plot(ResultsALL(end,iM).t,ResultsALL(iL,iM).x(2,:),'--r','LineWidth',1)
plot(ResultsALL(end,2).t,ResultsALL(end,2).x(1,:),'-k','LineWidth',1)
plot(ResultsALL(end,iM).t,ResultsALL(iL,iM).x(1,:),'--r','LineWidth',1)

figure, hold on
plot(ResultsALL(end,2).t,cumsum(ResultsALL(end,2).J),'-k','LineWidth',1)
plot(ResultsALL(end,iM).t,cumsum(ResultsALL(iL,iM).J),'--r','LineWidth',1)

figure, hold on
plot(ResultsALL(end,2).t,ResultsALL(end,2).u,'-k','LineWidth',1)
plot(ResultsALL(end,iM).t,ResultsALL(iL,iM).u,'--r','LineWidth',1)

%% TESTING
figure,hold on
for iM = 1:Nmodels
    Jend = cumsum(ResultsALL(iM,1).J);
    semilogx(Ntrain_vec(iM),Jend(end),'or')
    Jend = cumsum(ResultsALL(iM,2).J);
    semilogx(Ntrain_vec(iM),Jend(end),'og')
    Jend = cumsum(ResultsALL(iM,3).J);
    semilogx(Ntrain_vec(iM),Jend(end),'ob')
end

%%
figure,hold on
for iM = 1:Nmodels
    Jend = cumsum(ResultsALL(iM,1).J);
    plot3(Ntrain_vec(iM).*ones(size(Jend)),ResultsALL(iM,1).t,Jend,'-r')
end

%%
Jend = zeros(Nmodels,1);
for iM = 1:Nmodels
    tmp = cumsum(ResultsALL(iM,1).J); Jend(iM) = tmp(end);
end

figure,plot(Jend)

figure,plot(ResultsALL(3,1).x(1,:))
figure,plot(ResultsALL(3,1).u)


function [gg h] = collapsegroup(g)
% [gg h] = collapsegroup(g)
% g: group values. col vec of ints, or col cellstr.
% gg: col vec of ints taking values in the interval [1,Ngroups].
% h: if g is a col int vec, h is an int col vec. if g is a col cellstr, h
% is a col cellstr. h is an Ngroups-by-1 vector.
%
% gg(i) is the new grouping value for g(i). h(gg(i)) is equal to g(i).
%
% This is similar to stats/grp2idx, but does something I prefer with nans.

assert(isnumeric(g)||iscellstr(g));
g = g(:);

h = unique(g);

% nans are not uniqued; if there is a nan, include one in h
if isnumeric(h) && any(isnan(h))
    h(isnan(h),:) = [];
    h(end+1,1) = nan;
end

[~,gg] = ismember(g,h);

% if there are nans in g/h, gg will have 0 values since a nan in g is not
% considered to match up with a nan in h.
if isnumeric(h) && any(isnan(h))
    gg(gg==0) = numel(h);
end


function [jc,ir,pr] = save_sparse(A)
% convert sparse matrix to jc, ir, pr
%
% Input
%  A - sparse matrix
% Output
%  jc -
%  ir -
%  pr -
%

[ir,j,pr] = find(A);
ir = ir - 1;

jc = zeros(1,size(A,2)+1);
for i = 1:numel(j), jc(j(i)+1) = jc(j(i)+1) + 1;end
jc = cumsum(jc);

%for i = 1:size(A,2)+1,	jc2(i) = sum(j < i);end
%plot([jc(100:200)',jc2(100:200)'])


function L = computeL(nu)
    L_tmp = cell(nu,1);

    for i=1:nu
       L_tmp{i,1} = eye(2);
    end

    L = cell2mat(L_tmp);
end


% The COBRAToolbox: testKLDis.m
%
% Purpose:
%     - test the functionality of KLDis
%
% Authors:
%     - Loic Marx
%

% save the current path
currentDir = pwd;

% initialize the test
cd(fileparts(which(mfilename)));

% set the tolerance
tol = 1e-6;

% Generate 2 matrix of the same size
P = [1 2; 2 1];
Q = [3 2; 2 3];

% run the function
KLD = KLDis(P,Q);

% compare the scaled matrix against the reference data
assert(norm(KLD - 0.12723233459191 * [1; 1]) < tol)

Q2 = [inf inf];
P2 = [inf inf];

% Test if KLDis throws an error
assert(verifyCobraFunctionError('KLDis','inputs', {P, Q(:,1)}, 'testMessage', 'the number of columns in P and Q should be the same'));
assert(verifyCobraFunctionError('KLDis','inputs', {P2, Q2}, 'testMessage', 'the inputs contain non-finite values!'));

% change the directory
cd(currentDir)


function [x,fval,exitflag,output,solutions] = multiStartCommonRun(waitBarStr, numIter, fun, x0, A, b, lb, ub, nonlcon, hUiProgDlg)
%multiStartCommonRun Summary of this function goes here
%   Detailed explanation goes here

    arguments
        waitBarStr (1,:) char
        numIter
        fun
        x0 double
        A double
        b double
        lb double
        ub double
        nonlcon
        hUiProgDlg = [];
    end

    ticID = tic;

    if(strcmpi('CustomStartPointSet', class(numIter)))
        numIterAct = numIter.NumStartPoints;
    else
        numIterAct = numIter;
    end

    if(not(isempty(hUiProgDlg)))
        hWaitBar = hUiProgDlg;
    else
        hWaitBar = waitbar(0, waitBarStr);
    end

    warning ('off','all');
    opts = optimoptions(@fmincon,'Algorithm','interior-point', 'TolFun', eps, 'TolX', eps, 'MaxIter', 300, 'FinDiffType', 'central', 'ScaleProblem', 'obj-and-constr');
    problem = createOptimProblem('fmincon','objective',fun,'x0',x0,'Aineq',A,'bineq',b,'lb',lb,'ub',ub,'nonlcon',nonlcon,'options',opts);
    ms = MultiStart('Display', 'iter', 'OutputFcns', @(optimValues, state) msOutFcn(optimValues, state, numIterAct, hWaitBar, waitBarStr, ticID));
    disp(waitBarStr);
    [x,fval,exitflag,output,solutions] = run(ms,problem,numIter);
    warning ('on','all');

    if(~isa(hWaitBar, 'matlab.ui.dialog.ProgressDialog'))
        close(hWaitBar);
    end
end


function [minVal, minPos] = min(f)
%MIN   Global minimum of a CLASSICFUN on [a,b].
%   MINVAL = MIN(F) returns the global minimum of the CLASSICFUN F on [a,b].  If F is
%   an array-valued CLASSICFUN, MINVAL is a row vector whose Kth entry is the global
%   minimum of the Kth column of F.
%
%   [MINVAL, MINPOS] = MIN(F) returns also a value such that MINVAL = F(MINPOS).
%
%   If F is complex-valued then absolute values are taken to determine maxima
%   but the output value corresponds to that of the original function. That
%   is, MINVAL = FEVAL(F, MINPOS) where [~, MINPOS] = MIN(ABS(F)).
%
% See also MAX, MINANDMAX.

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

% To avoid code duplication, we simply call MINANDMAX:
[minVal, minPos] = minandmax(f);
minVal = minVal(1,:);
minPos = minPos(1,:);

end


function Y=trapz(X,I,dummy)
%TRAPZ (overloaded)

try
    n = X.dim(1);
    m = X.dim(2);
    if nargin==1
        Y = X;
        if n==1 || m==1
            % Spezialized code...
            Y.basis = trapz(Y.basis,1);
            Y.dim(1) = 1;
            Y.dim(2) = 1;
            temp = 1;
        else
            % Standard case

            temp = trapz(reshape(X.basis(:,1),n,m));
            Y.basis =  kron(speye(m),ones(1,n))*X.basis;

        end
    else
        Y = X;
        temp = trapz(reshape(X.basis(:,1),n,m),I);
        Y.basis = temp(:);
        for i = 1:length(Y.lmi_variables)
            temp = trapz(reshape(X.basis(:,i+1),n,m),I);
            Y.basis(:,i+1) = temp(:);
        end
    end
catch
    error(lasterr)
end
Y.dim(1) = size(temp,1);
Y.dim(2) = size(temp,2);
% Reset info about conic terms
Y.conicinfo = [0 0];
Y.extra.opname = '';
Y = clean(Y);


%-------------------------------------------------------------------------------------------------------------------%
%
% IB2d is an Immersed Boundary Code (IB) for solving fully coupled non-linear
% 	fluid-structure interaction models. This version of the code is based off of
%	Peskin's Immersed Boundary Method Paper in Acta Numerica, 2002.
%
% Author: Nicholas A. Battista
% Email:  nick.battista@unc.edu
% Date Created: May 27th, 2015
% Institution: UNC-CH
%
% This code is capable of creating Lagrangian Structures using:
% 	1. Springs
% 	2. Beams (*torsional springs)
% 	3. Target Points
%	4. Muscle-Model (combined Force-Length-Velocity model, "HIll+(Length-Tension)")
%
% One is able to update those Lagrangian Structure parameters, e.g., spring constants, resting %%	lengths, etc
%
% There are a number of built in Examples, mostly used for teaching purposes.
%
% If you would like us %to add a specific muscle model, please let Nick (nick.battista@unc.edu) know.
%
%--------------------------------------------------------------------------------------------------------------------%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: creates the RUBBERBAND-EXAMPLE geometry and prints associated input files
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function Pulsing_Heart()

%
% Grid Parameters (MAKE SURE MATCHES IN input2d !!!)
%
Nx =  64;        % # of Eulerian Grid Pts. in x-Direction (MUST BE EVEN!!!)
Ny =  64;        % # of Eulerian Grid Pts. in y-Direction (MUST BE EVEN!!!)
Lx = 1.0;        % Length of Eulerian Grid in x-Direction
Ly = 1.0;        % Length of Eulerian Grid in y-Direction

% Immersed Structure Geometric / Dynamic Parameters %
N = 2.5*Nx;              % Number of Lagrangian Pts. (2x resolution of Eulerian grid)
struct_name = 'heart'; % Name for .vertex, .spring, etc files.

% Call function to construct geometry
frac1 = 0.0135; %0.022
[xA,yA] = give_Me_Immsersed_Boundary_Geometry_1(Lx,Nx,frac1);
Nb1 = length(xA);

% Call function to construct geometry
frac2 = 0.0085; %0.015
[xB,yB] = give_Me_Immsersed_Boundary_Geometry_2(Lx,Nx,frac2,Nb1);

% Plot Geometry to test BEFORE taking out pts.
figure(1)
plot(xA,yA,'r-'); hold on;
plot(xA,yA,'*'); hold on;
plot(xB,yB,'m-'); hold on;
plot(xB,yB,'g*'); hold on;
xlabel('x'); ylabel('y');
axis([0 Lx 0 Ly]);

% Cuts hole into heart geometry
n1 = 145; n2 = 180;
[xA,yA,xB,yB] = please_Take_Out_Points(xA,yA,xB,yB,n1,n2);

% Plot Geometry to test AFTER taking out pts.
figure(2)
plot(xA,yA,'r-'); hold on;
plot(xA,yA,'*'); hold on;
plot(xB,yB,'m-'); hold on;
plot(xB,yB,'g*'); hold on;
xlabel('x'); ylabel('y');
axis([0 Lx 0 Ly]);

% Print STATES A,B, and C:
print_States(xA,yA,'State_A');
print_States(xB,yB,'State_B');

% Print files to .txt files
%please_Print_Vertices_To_File(xA,yA,xB,yB)

% Prints .vertex file!
print_Lagrangian_Vertices(xA,yA,struct_name);

% Prints .spring file!
k_Spring = 1e3; ds_Rest = 0;
print_Lagrangian_Springs(xA,k_Spring,ds_Rest,struct_name,n1)

% Prints .target file!
k_Target = 2e10;
print_Lagrangian_Target_Pts(xA,k_Target,struct_name);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: prints VERTEX points to a file called State_<j>.pts
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function print_States(xA,yA,struct_name)

    N = length(xA);

    vertex_fid = fopen([struct_name '.pts'], 'w');

    %Loops over all Lagrangian Pts.
    for s = 1:N
        X_v = xA(s);
        Y_v = yA(s);
        fprintf(vertex_fid, '%1.16e %1.16e\n', X_v, Y_v);
    end

    fclose(vertex_fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: prints VERTEX points to a file called heart.vertex
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function print_Lagrangian_Vertices(xLag,yLag,struct_name)

    N = length(xLag);

    vertex_fid = fopen([struct_name '.vertex'], 'w');

    fprintf(vertex_fid, '%d\n', N );

    %Loops over all Lagrangian Pts.
    for s = 1:N
        X_v = xLag(s);
        Y_v = yLag(s);
        fprintf(vertex_fid, '%1.16e %1.16e\n', X_v, Y_v);
    end

    fclose(vertex_fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: prints Vertex points to a file called heart.target
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function print_Lagrangian_Target_Pts(xLag,k_Target,struct_name)

    N = length(xLag);

    target_fid = fopen([struct_name '.target'], 'w');

    fprintf(target_fid, '%d\n', N );

    %Loops over all Lagrangian Pts.
    for s = 1:N
        fprintf(target_fid, '%d %1.16e\n', s, k_Target);
    end

    fclose(target_fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: prints SPRING points to a file called rubberband.spring
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function print_Lagrangian_Springs(xLag,k_Spring,ds_Rest,struct_name,n1)

    N = length(xLag);

    spring_fid = fopen([struct_name '.spring'], 'w');

    fprintf(spring_fid, '%d\n', N );

    %spring_force = kappa_spring*ds/(ds^2);

    %SPRINGS BETWEEN VERTICES
    for s = 1:N
            if s < n1
                fprintf(spring_fid, '%d %d %1.16e %1.16e\n', s, s+1, k_Spring, ds_Rest);
            elseif ( (s>=n1+1) && (s<N) )
                fprintf(spring_fid, '%d %d %1.16e %1.16e\n', s, s+1, k_Spring, ds_Rest);
            elseif s == N
                fprintf(spring_fid, '%d %d %1.16e %1.16e\n', s, 1,   k_Spring, ds_Rest);
            end
    end
    fclose(spring_fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: creates the Lagrangian structure geometry for PHASE 1
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [xLag,yLag] = give_Me_Immsersed_Boundary_Geometry_1(Lx,Nx,frac)

% The immsersed structure is a heart %
tVec = 0:Lx/(2*Nx):2*pi;
for i=1:length(tVec)
    t = tVec(i);
    xLag(i)	=	16*sin(t)^3;
    yLag(i)	=	13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t);
end

xLag = frac*xLag + 0.5;
yLag = frac*yLag + 0.5;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: creates the Lagrangian structure geometry for PHASE 1
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [xLag,yLag] = give_Me_Immsersed_Boundary_Geometry_2(Lx,Nx,frac,Nb)

% The immsersed structure is a heart %
ds = 2*pi/(Nb-1);
tVec = 0:ds:2*pi;

for i=1:length(tVec)
    t = tVec(i);
    xLag(i)	=	16*sin(t)^3;
    yLag(i)	=	13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t);
end

xLag = frac*xLag + 0.5;
yLag = frac*yLag + 0.5;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: creates the Lagrangian structure geometry for PHASE 2
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [xLag,yLag] = give_Me_Immsersed_Boundary_Geometry_3(Lx,Nx,frac,Nb)

% The immsersed structure is a heart %
ds = 2*pi/(Nb-1);
tVec = 0:ds:2*pi;
for i=1:length(tVec)
    t = tVec(i);
    r(i) = 1 - sin(t);
    xLag(i)	=	r(i)*cos(t);
    yLag(i)	=	r(i)*sin(t);
end

xLag = frac*xLag;
yLag = frac*yLag;

minY = min(yLag);
yLag = yLag - 3*minY/8;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: take out Lagrangian Pts.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [x1,y1,x2,y2] = please_Take_Out_Points(x1,y1,x2,y2,n1,n2)

x1 = [x1(1:n1) x1(n2:end)];
y1 = [y1(1:n1) y1(n2:end)];

x2 = [x2(1:n1) x2(n2:end)];
y2 = [y2(1:n1) y2(n2:end)];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: prints all Vertices to File
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function please_Print_Vertices_To_File(X1,Y1,X2,Y2)

fileID = fopen('All_Positions.txt','w');
for j=1:length(X1)
    fprintf(fileID,'%1.16e %1.16e %1.16e %1.16e\n', X1(j),Y1(j),X2(j),Y2(j) );
end
fclose(fileID);


function [uOutput] = scecdcimp(nFunction, sFilename)
% import UW catalog

% Filter function switchyard
if nFunction == FilterOp.getDescription
    uOutput = 'UW catalog ';
elseif nFunction == FilterOp.importCatalog
    % Read formated data
    mData = textread(sFilename, '%s', 'delimiter', '\n', 'whitespace', '');
    % Create empty catalog
    uOutput = zeros(length(mData), 9);
    % Loop thru all lines of catalog and convert them
    for i = 1:length(mData)
        if rem(i,100) == 0 ; disp([ num2str(i) ' of ' num2str(length(mData)) ' events processed ']); end
        try
            l = find(mData{i} == ' ');
            mData{i}(l) = '0';
            uOutput(i,1) = -str2num(mData{i}(30:32)) - str2num(mData{i}(34:37))/6000 ;  % Longitude
            if mData{i}(33) == 'E' ; uOutput(i,1)  = -1*uOutput(i,1); end
            uOutput(i,2) =  str2num(mData{i}(22:23)) + str2num(mData{i}(25:28))/6000 ;  % Latitude
            if mData{i}(24) == 'S' ; uOutput(i,1)  = -1*uOutput(i,1); end
            uOutput(i,3) = str2num(mData{i}(3:6));    % Year
            uOutput(i,4) = str2num(mData{i}(7:8));    % Month
            uOutput(i,5) = str2num(mData{i}(9:10));   % Day
            uOutput(i,6) = str2num(mData{i}(45:48));  % Magnitude
            uOutput(i,7) = str2num(mData{i}(38:43));  % Depth
            uOutput(i,8) = str2num(mData{i}(11:12));  % Hour
            uOutput(i,9) = str2num(mData{i}(13:14));  % Minute

            %Create decimal year
            uOutput(i,3) = decyear([uOutput(i,3) uOutput(i,4) uOutput(i,5) uOutput(i,8) uOutput(i,9)]);

            if mData{i}(2) == 'P'  ||  mData{i}(2) == 'X'  ||  mData{i}(2) == 'L'
                uOutput(i,:)=nan;
            end

        catch
            msg.dbfprintf('Import: Problem in line %d of %s. Line ignored.\n',i, sFilename);  % eliminate explosions
            uOutput(i,:)=nan;
        end
    end
    l = isnan(uOutput(:,1));
    uOutput(l,:) = [];
end


function [inference] = tapas_vlinear_inference(inference, pars)
%%
%
% aponteeduardo@gmail.com
% copyright (C) 2016
%

if ~isfield(inference, 'estimate_method')
    inference.estimate_method = @tapas_mcmc_blocked_estimate;
end

if ~isfield(inference, 'initialize_states')
    inference.initialize_states = @tapas_linear_init_states;
end

if ~isfield(inference, 'initialize_state')
    inference.initialize_state = @tapas_vlinear_init_state;
end

if ~isfield(inference, 'sampling_methods')
    inference.sampling_methods = {
        @(d, m, i, s) tapas_mh_mc3_sample_node(d, m, i, s, 2), ...
        @(d, m, i, s) tapas_sampler_vlinear_gibbs_node(d, m, i, s, 3), ...
            @tapas_sampler_mc3};
end

if ~isfield(inference, 'metasampling_methods')
    inference.metasampling_methods = {@tapas_mcmc_meta_diagnostics, ...
        @tapas_mcmc_meta_adaptive};
end

if ~isfield(inference, 'get_stored_state')
    inference.get_stored_state = @tapas_vlinear_get_stored_state;
end

if ~isfield(inference, 'prepare_posterior')
    inference.prepare_posterior = @tapas_linear_prepare_posterior;
end

if ~isfield(inference, 'mh_sampler')
    inference.mh_sampler = cell(4, 1);
end

if ~isfield(inference.mh_sampler{2}, 'propose_sample')
    inference.mh_sampler{2}.propose_sample = ...
        @tapas_mh_mc3_propose_gaussian_sample;
    inference.mh_sampler{2}.ar_rule = ...
        @tapas_mh_mc3_arc;
end

if ~isfield(inference, 'niter')
    if isfield(pars, 'niter')
        inference.niter = pars.niter;
    else
        inference.niter = 5000;
    end
end

if ~isfield(inference, 'nburnin')
    if isfield(pars, 'nburnin')
        inference.nburnin = pars.nburnin;
    else
        inference.nburnin = 5000;
    end
end

if ~isfield(inference, 'mc3it')
    if isfield(pars, 'mc3it')
        inference.mc3it = pars.mc3it;
    else
        inference.mc3it = 10;
    end
end

if ~isfield(inference, 'thinning')
    if isfield(pars, 'thinning')
        inference.thinning = pars.thinning;
    else
        inference.thinning = 0;
    end
end

if ~isfield(inference, 'ndiag')
    if isfield(pars, 'ndiag')
        inference.ndiag = pars.ndiag;
    else
        inference.ndiag = 200;
    end
end

end


function img_f = GT_filter(img)
    % plug-in your favorite filter here
    % e.g. L0 smoothing filter
    img_f = L0Smoothing(img, 0.02);
end


function handle = imageModifyVargplvm(handle, imageValues, imageSize, transpose, negative, ...
		     scale,thresh)

% IMAGEMODIFY Helper code for visualisation of image data.
% FORMAT
% DESC is a helper function for visualising image data using latent
% variable models.
% ARG handle : the handle of the image data.
% ARG imageValues : the values to set the image data to.
% ARG imageSize : the size of the image.
% ARG transpose : whether the resized image needs to be transposed
% (default 1, which is yes).
% ARG negative : whether to display the negative of the image
% (default 0, which is no).
% ARG scale : dummy input, to maintain compatability with
% IMAGEVISUALISE.
% ARG thresh : An array, thresh = [minVal, threshDown, threshUp, maxVal]
% which gives value minVal to all image elements smaller than threshDown
% and value maxVal to all image elements larger than threshUp.
% RETURN handle : a the handle to the image data.
%
% COPYRIGHT : Neil D. Lawrence, 2003, 2004, 2006
%
% SEEALSO : imageVisualise, fgplvmResultsDynamic

% SHEFFIELDML

if nargin < 4 || isempty(transpose)
  transpose = 1;
end
if nargin< 5 || isempty(negative)
  negative = 0;
end
if nargin < 6
    thresh = [];
end
if negative
  imageValues = -imageValues;
end
if ~isempty(thresh)
    imageValues(imageValues < thresh(2)) = thresh(1);
    imageValues(imageValues >= thresh(3)) = thresh(4);
end
if transpose
  set(handle, 'CData', reshape(imageValues(1:imageSize(1)*imageSize(2)), imageSize(1), imageSize(2))');
else
  set(handle, 'CData', reshape(imageValues(1:imageSize(1)*imageSize(2)), imageSize(1), imageSize(2)));
end


function [nx] = tapas_ti_gen_state(y, x, u, theta, ptheta)
%% General method to generate state space.
%
% aponteeduardo@gmail.com
% copyright (C) 2016
%

gen_state = ptheta.method_state;

ns = size(theta, 1);
nc = size(theta, 2);

nx = cell(ns, nc);

for i = 1:ns
    for j = 1:nc
        nx{i, j} = gen_state(y{i, j}, [], u{i, j}, theta{i, j}, ptheta);
    end
end

end


function  SubPopulation = SelectPop(SubPopulation,Problem)

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    for i = 1 : length(SubPopulation)
        pop = SubPopulation{i};
        [~,rank] = sort(pop.objs);
        SubPopulation{i} = pop(rank(1:Problem.N/2));
    end
end


function [yData,signalData,signalIdx,signalAmps] = ...
                file_embeddingSubSampling(projectionFile,parameters)
%file_embeddingSubSampling finds the potential training set contributions
%from a single file (called by runEmbeddingSubSampling.m)
%
%   Input variables:
%
%       projectionFile -> file to be analyzed (should contain a variable
%                           called 'projections')
%       parameters -> struct containing non-default choices for parameters
%
%
%   Output variables:
%
%       yData -> Nx2 array containing t-SNE embedding
%       signalData -> wavelet data corresponding to yData
%       signalIdx -> idx used
%       signalAmps -> wavelet amplitudes of signalData
%
% (C) Gordon J. Berman, 2014
%     Princeton University

    rtol = parameters.training_relTol;
    perplexity = parameters.training_perplexity;
    numPoints = parameters.training_numPoints;

    fprintf(1,'\t Loading Projections\n');
    load(projectionFile,'projections');

    N = length(projections(:,1));
    numModes = parameters.pcaModes;
    skipLength = floor(N / numPoints);
    if skipLength == 0
        skipLength = 1;
        numPoints = N;
    end
    firstFrame = mod(N,numPoints) + 1;
    signalIdx = firstFrame:skipLength:(firstFrame + (numPoints-1)*skipLength);

    fprintf(1,'\t Calculating Wavelets\n');
    [data,~] = findWavelets(projections,numModes,parameters);
    amps = sum(data,2);

    signalData = bsxfun(@rdivide,data(signalIdx,:),amps(signalIdx));
    signalAmps = amps(signalIdx);

    clear data amps;

    fprintf(1,'\t Calculating Distances\n');
    [D,~] = findKLDivergences(signalData);

    fprintf(1,'\t Running t-SNE\n');
    parameters.relTol = rtol;
    parameters.perplexity = perplexity;
    [yData,~,~,~] = tsne_d(D,parameters);


function G = mldivide( a, F )
%\  DISKFUNV left divide.
%
%  a\F Divides each component of a DISKFUNV F by the scalar a.
%
%  One is only allowed to divide a DISKFUNV by a scalar.
%
% See also MRDIVIDE.

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

% Empty check:
if ( ( isempty(a) ) || ( isempty(F) ) )
    G = diskfunv();
    return
end

% Only allow a\F, where a is a scalar:
if ( ~isa(a, 'double') )
    error('DISKFUN:DISKFUNV:mldivide:nonScalar', ...
        'Division must be by a scalar.');
end

% Left divide:
G = F;
G.components{1} = mldivide( a, F.components{1} );
G.components{2} = mldivide( a, F.components{2} );

end


function [ panoLineImg ] = viewRegionHypothesis( img, AllCuboid, thres )
%VIEWREGIONHYPOTHESIS Summary of this function goes here
%   Detailed explanation goes here

AllLines = zeros(0,6);
for cid = 1:AllCuboid.count
    if AllCuboid.score(cid)<thres
        continue;
    end

    view = AllCuboid.views(cid,:);
    xyzBox = AllCuboid.xyzBox(cid,:);
    numRectangle = sum(view~=0);

    for rid = 1:numRectangle
        rect = reshape(xyzBox((rid*12-11):(rid*12)), 3, 4)';
        lines = lineFromTwoPoint(rect([1 2 3 4], :), rect([2 3 4 1], :));
        AllLines = [AllLines; lines];
    end
end

% img = imresize( im2double(img), [512 1024]);
% panoLineImg = paintParameterLine( AllLines, 1024, 512, img);
img = imresize( im2double(img), [1024 2048]);
panoLineImg = paintParameterLine( AllLines, 2048, 1024, img);

% imshow(panoLineImg);

end


function X = hlp_insertSingletonDim(X,dim)
% insert a singleton dimension into dimension 'dim' of matrix X
% author: Tim Mullen, 2011

    nd = ndims(X);
    X = permute(X,unique_bc([1:dim-1 nd+1 dim:nd]));


function output = callbaron(model)

% This sets up everything and more. Can be simplified significantly since
% baron handles its own computational tree etc
model = yalmip2nonlinearsolver(model);

% [Anonlinear*f(x) <= b;Anonlinear*f(x) == b]
cu = full([model.bnonlinineq;model.bnonlineq]);
cl = full([repmat(-inf,length(model.bnonlinineq),1);model.bnonlineq]);
Anonlinear = [ model.Anonlinineq; model.Anonlineq];

% Create string representing objective
obj = createmodelstring(model.c,model);
if nnz(model.Q)>0
    obj = [obj '+' createQstring(model.Q,model)];
end
if any(model.f) > 0
    obj = [obj '+' num2str(model.f)];
end
obj = baronify(obj);
if length(obj)>0
    obj = strrep(obj,'+-','-');
    obj = ['@(x) ' obj];
    obj = eval(obj);
else
    obj = @(x)0;
end

% Create string representing nonlinear consdbqtraints
if length(cu)>0
    con = '[';
    remove = [];
    for i = 1:length(cu)
        if isinf(cl(i)) & isinf(cu(i))
            remove = [remove;i];
        else
            con = [con createmodelstring(Anonlinear(i,:),model) ';'];
        end
    end
    cl(remove) = [];
    cu(remove) = [];
    con = [con ']'];
    con = baronify(con);
    con = ['@(x) ' con];
    con = eval(con);
else
    cu = [];
    cl = [];
    con = [];
end

% Linear constraints
ru = full([model.b;model.beq]);
rl = full([repmat(-inf,length(model.b),1);model.beq]);
A =  [model.A; model.Aeq];
if length(ru)>0
    remove = find(isinf(rl) & isinf(ru));
    A(remove,:)=[];
    rl(remove) = [];
    ru(remove) = [];
end

lb = model.lb;
ub = model.ub;

xtype = [];
xtype = repmat('C',length(lb),1);
xtype(model.binary_variables) = 'B';
xtype(model.integer_variables) = 'I';
x0 = model.x0;
opts = model.options.baron;
opts.prlevel = model.options.verbose;
if model.options.savedebug
    save barondebug obj con A ru rl cl cu lb ub x0 opts
end

solvertime = tic;
[x,fval,exitflag,info,allsol] = baron(obj,A,rl,ru,lb,ub,con,cl,cu,xtype,x0,opts);
solvertime = toc(solvertime);

% Check, currently not exhaustive...
switch exitflag
    case 1
        problem = 0;
    case 2
        problem = 1;
    case 3
        problem = 2;
    case 4
        problem = 3;
    case 5
        problem = 11;
    otherwise
        problem = 9;
end

% Save all data sent to solver?
if model.options.savesolverinput
    solverinput.obj = obj;
    solverinput.A = A;
    solverinput.rl = rl;
    solverinput.ru = ru;
    solverinput.lb = lb;
    solverinput.ub = ub;
    solverinput.con = con;
    solverinput.cl = cl;
    solverinput.cu = cu;
    solverinput.xtype = xtype;
    solverinput.opts = opts;
else
    solverinput = [];
end

% Save all data from the solver?
if model.options.savesolveroutput
    solveroutput.x = x;
    solveroutput.fval = fval;
    solveroutput.exitflag = exitflag;
    solveroutput.info=info;
    solveroutput.allsol=allsol;
else
    solveroutput = [];
end

if ~isempty(x)
    x = RecoverNonlinearSolverSolution(model,x);
end

% Standard interface
output = createOutputStructure(x,[],[],problem,'BARON',solverinput,solveroutput,solvertime);

function z = createOneterm(i,model)

[evalPos,pos] = ismember(i,model.evalVariables);
if pos
    % This is a nonlinear operator
    map = model.evalMap{pos};
    % We might hqave vectorized things to compute several expressions at the same time
    if strcmp(model.evalMap{pos}.fcn,'sum_square')
        z = ['('];
        for j = map.variableIndex
            jl = find(model.linearindicies == j);
            if isempty(jl)
                z =  [z '(' createmonomstring(model.monomtable(j,:),model) ')^2+'];
            else
                z =  [z 'x(' num2str(jl) ')^2+'];
            end
        end
        z = [z(1:end-1) ')'];
    elseif strcmp(model.evalMap{pos}.fcn,'slogfrac')
        j1 = find(model.linearindicies == map.variableIndex(1));
        j2 = find(model.linearindicies == map.variableIndex(2));
        z =  ['(log(1 + x(' num2str(j1) ')/x(' num2str(j2) ')))'];
    elseif strcmp(model.evalMap{pos}.fcn,'entropy')
        z = ['('];
        for j = map.variableIndex
            jl = find(model.linearindicies == j);
            if isempty(jl)
                z =  [z '(' createmonomstring(model.monomtable(j,:),model) ')^2+'];
            else
                z =  [z '-x(' num2str(jl) ')*log(x(' num2str(jl) '))+'];
            end
        end
        z = [z(1:end-1) ')'];
    elseif strcmp(model.evalMap{pos}.fcn,'logsumexp')
        z = ['('];
        for j = map.variableIndex
            jl = find(model.linearindicies == j);
            if isempty(jl)
                z =  [z '(' createmonomstring(model.monomtable(j,:),model) ')^2+'];
            else
                z =  [z 'exp(x(' num2str(jl) '))+'];
            end
        end
        z = ['log' z(1:end-1) ')'];
    elseif strcmp(model.evalMap{pos}.fcn,'power_internal1')
        j = find(map.computes == i);
        j = map.variableIndex(j);
        % we have f(x(j)), but have to map back to linear indicies
        jl = find(model.linearindicies == j);
        if isempty(jl)
            z =  [num2str(model.evalMap{pos}.arg{2}) '^(' createmonomstring(model.monomtable(j,:),model)  ')'];
        else
            z =  [num2str(model.evalMap{pos}.arg{2}) '^(x(' num2str(jl) '))'];
        end
    else
        j = find(map.computes == i);
        j = map.variableIndex(j);
        % we have f(x(j)), but have to map back to linear indicies
        jl = find(model.linearindicies == j);
        if isempty(jl)
            z =  [map.fcn '(' createmonomstring(model.monomtable(j,:),model)  ')'];
        else
            z =  [map.fcn '(x(' num2str(jl) '))'];
        end
    end
else
    i = find(model.linearindicies == i);
    z =  ['x(' num2str(i) ')'];
end

function monomstring = createmonomstring(v,model)

monomstring = '';
for i = find(v)
    z = createOneterm(i,model);
    if v(i)==1
        monomstring = [monomstring z '*'];
    else
        monomstring = [monomstring z '^' num2str(v(i),12) '*'];
    end
end
monomstring = monomstring(1:end-1);

function string = createmodelstring(row,model)
string = '';
index = find(row);
for i = index(:)'
    monomstring = createmonomstring(model.monomtable(i,:),model);
    string = [string  num2str(row(i),12) '*' monomstring '+'];
end
string = string(1:end-1);
string = strrep(string,'+-','-');
string = strrep(string,')-1*',')-');
string = strrep(string,')+1*',')+');

function string = createQstring(Q,model)
% Special code for the quadratic term
string = '';
[ii,jj,c]= find(triu(Q));
for i = 1:length(ii)
    if ii(i)==jj(i)
        % Quadratic term
        monomstring = createmonomstring(sparse(1,ii(i),1,1,size(Q,1)),model);
        string = [string  num2str(c(i),12) '*' monomstring '^2' '+'];
    else
        % Bilinear term
        monomstring1 = createmonomstring(sparse(1,ii(i),1,1,size(Q,1)),model);
        monomstring2 = createmonomstring(sparse(1,jj(i),1,1,size(Q,1)),model);
        string = [string  num2str(c(i),12) '*2*' monomstring1 '*' monomstring2 '+'];
    end
end
string = string(1:end-1);
string = strrep(string,'+-','-');
string = strrep(string,'-1*','-');
string = strrep(string,'+1*','+');

function s = baronify(s)
s = strrep(s,'+1*','+');
s = strrep(s,'-1*','-');
s = strrep(s,'sqrtm_internal','sqrt');
s = strrep(s,'cabs','abs');
% YALMIP catches log(1+z) and implements internal model slog(z)
% Replace with log
expression = 'slog((\w*)';
replace = 'log(1+$1';
s =  regexprep(s,expression,replace);
% YALMIP catches x^y and replaced with power1_internal
expression = 'slog((\w*)';
replace = 'log(1+$1';
s =  regexprep(s,expression,replace);


function p = addMultipliedEqualityCuts(p)

newRows = [];
for i =  p.linears
    for j = 1:p.K.f
        row = p.F_struc(j,:);
        used = find(row(2:end));
        if ~any(p.variabletype(used))
            % Linear constraint
            ok = 1;
            for k = 1:length(used)
                find1 = findrows(p.bilinears(:,2:end),[i used(k)]);
                find2 = findrows(p.bilinears(:,2:end),[used(k) i]);
                if (isempty(find1) & isempty(find2))
                    ok = 0;
                    break
                else
                    monom(k) = [find1 find2];
                end
            end
            if ok
                monom = p.bilinears(monom,1);
                row(1+monom) = row(1+used);
                row(1+used) = 0;
                row(i) = row(1);
                row(1)=0;
                newRows = [newRows;row];
            end
        end
    end
end
if ~isempty(newRows)
    p.F_struc = [newRows;p.F_struc];
    p.K.f = p.K.f + size(newRows,1);
end


function criterion = gbc_variants(ori,CS,Dl,Dr,delta,varargin)
errorcheck = all(length(ori)==length(delta) & all(floor(delta) == delta));
assert(errorcheck,'Provide a list of valid variant IDs to compute grains from variant Ids');
% variant grain criterion
% check whether the two ebsd measurements are seperated by a grain boundary
if size(delta,2)>1
    criterion = delta(Dl,1)-delta(Dr,1) + delta(Dl,2)-delta(Dr,2) == 0;
else
    criterion = delta(Dl,1)-delta(Dr,1) == 0;
end


% Focussed Detector in 3D Example
%
% This example shows how k-Wave can be used to model the output of a
% focussed bowl detector in 3D where the directionality arises from
% spatially averaging across the detector surface. It builds on the
% Focussed Detector in 2D example.
%
% author: Ben Cox
% date: 29th October 2010
% last update: 18th September 2012
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox

% This file is part of k-Wave. k-Wave 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.
%
% k-Wave 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 Lesser General Public License
% along with k-Wave. If not, see <http://www.gnu.org/licenses/>.

clear all;

% =========================================================================
% SIMULATION
% =========================================================================

% create the computational grid
Nx = 64;            % number of grid points in the x direction
Ny = 64;            % number of grid points in the y direction
Nz = 64;            % number of grid points in the z direction
dx = 100e-3/Nx;     % grid point spacing in the x direction [m]
dy = dx;            % grid point spacing in the y direction [m]
dz = dx;            % grid point spacing in the z direction [m]
kgrid = makeGrid(Nx, dx, Ny, dy, Nz, dz);

% define the properties of the propagation medium
medium.sound_speed = 1500;	% [m/s]

% create the time array
[kgrid.t_array, dt] = makeTime(kgrid, medium.sound_speed);
Nt = length(kgrid.t_array);

% create a concave sensor
radius = Nx/4-1;
height = 10;
ss = makeSphericalSection(radius, height);

% add it to a mask of the correct size
sensor.mask = zeros(Nx, Ny, Nz);
[a,b,c] = size(ss);
sphere_offset = 10;
sensor.mask(sphere_offset+(1:a),(Ny-b+1)/2+(1:b),(Nz-c+1)/2+(1:c)) = ss;

% define a time varying sinusoidal source
source_freq = 0.25e6;
source_mag = 1;
source.p = source_mag*sin(2*pi*source_freq*kgrid.t_array);
source.p = filterTimeSeries(kgrid, medium, source.p);

% place the first point source near the focus of the detector
source1 = zeros(Nx, Ny, Nz);
source1(sphere_offset+radius, Ny/2+1, Nz/2+1) = 1;

% place the second point source off axis
source2 = zeros(Nx, Ny, Nz);
source2(sphere_offset+radius, Ny/2+6, Nz/2+6) = 1;

% run the first simulation
source.p_mask = source1;
input_args = {'PMLSize', 10, 'DataCast', 'single', 'PlotSim', false};
sensor_data1 = kspaceFirstOrder3D(kgrid, medium, source, sensor, input_args{:});

% average the data recorded at each grid point to simulate the measured
% signal from a single element focussed detector
sensor_data1 = sum(sensor_data1, 1);

% run the second simulation
source.p_mask = source2;
sensor_data2 = kspaceFirstOrder3D(kgrid, medium, source, sensor, input_args{:});

% average the data recorded at each grid point to simulate the measured
% signal from a single element focussed detector
sensor_data2 = sum(sensor_data2, 1);

% =========================================================================
% VISUALISATION
% =========================================================================

% plot the detector and on-axis and off-axis point sources
voxelPlot(sensor.mask + source1 + source2);
view([99, 18]);

% plot the time series corresponding to the on-axis and off-axis sources
figure
[t_sc, t_scale, t_prefix] = scaleSI(kgrid.t_array(end));
plot(kgrid.t_array.*t_scale, sensor_data1, '-');
hold on
plot(kgrid.t_array.*t_scale, sensor_data2, 'r-');
xlabel(['Time [' t_prefix 's]']);
ylabel('Average Pressure Measured By Focussed Detector [Pa]');
legend('Source on axis', 'Source off axis');


function PlotFittedModel(protocol, MODELNAME, fittedpars, constants, h, style)
% Plots the normalized measurements predicted by the model with
% the fitted parameters against the absolute dot product of the
% gradient and fibre directions.
%
% PlotFittedModel(protocol, MODELNAME, fittedpars, h)
% adds the plot to figure handle h.
%
% protocol is the imaging protocol.
%
% MODELNAME is the name identifying the model.
%
% fittedpars and the model parameter values.
%
% constants is a structure containing fixed values required for the model.
%
% h is a figure handle to add the plot to.  If not specified, a new figure
% appears.
%
% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
%         Gary Hui Zhang (gary.zhang@ucl.ac.uk)
%

if(nargin<5)
    h = figure;
end

% Get estimated fibre direction and b=0 signal.
fibredir = GetFibreOrientation(MODELNAME, fittedpars);
b0est = GetB0(MODELNAME, fittedpars);

if(nargin<6)
    style = '-';
end

linedef{1} = ['r', style];
linedef{2} = ['b', style];
linedef{3} = ['g', style];
linedef{4} = ['m', style];
linedef{5} = ['c', style];
linedef{6} = ['k', style];
linedef{7} = ['y', style];

hold on;

scale = GetScalingFactors(MODELNAME);
xsc = fittedpars(1:(length(scale)-1))./scale(1:(end-1));
S_Meas = SynthMeas(MODELNAME, xsc, protocol, fibredir, constants);
Snormdw = S_Meas./b0est;
for j=1:length(protocol.uG)
    inds = find(protocol.G == protocol.uG(j) & protocol.delta == protocol.udelta(j) & protocol.smalldel == protocol.usmalldel(j));
    dps = abs(protocol.grad_dirs(inds,:)*fibredir);
    [t tinds] = sort(dps);
    plot(dps(tinds), Snormdw(inds(tinds)), linedef{j}, 'LineWidth', 2);
end
xlabel('|n.G|/|G|_{max}');
ylabel('S/S_0');


function testFinalModels_HN_OldExp(pathExperiments,nExp,fSetNames,paramCells,nameCells)
% - paramCells: One cell of parameters for each fSet
% - nameCells: One cell of names for each fSet

startpath = pwd;
nFset = numel(fSetNames);
for exp = 1:nExp
    cd(fullfile(pathExperiments,['Experiment',num2str(exp)])), pathExperiment = pwd;
    load('training'), load('testing')
    nameOutcomes = fieldnames(training); nOutcomes = numel(nameOutcomes);
    cd('FINAL_MODELS'), pathFinalModels = pwd;
    for o = 1:nOutcomes
        for f = 1:nFset
            results = []; results = struct;
            cd(fullfile(pathFinalModels,nameOutcomes{o},fSetNames{f}))
            load('finalModel'), load('coeff'), load('response'), model = struct;

            % OBTAINING MODEL CHARACTERISTIC
            order = numel(finalModel.Name);
            paramCell = paramCells{f}; nameCell = nameCells{f};
            nParam = numel(paramCell); scans = cell(1,order);
            for n = 1:order
                name = finalModel.Name{n};
                indA = strfind(name,'--'); indB = strfind(name,'-');
                if ~isempty(indA) % This is a texture
                    model.(['Feature',num2str(n)]).isTexture = true;
                    model.(['Feature',num2str(n)]).textType = name((indA(1)+2):(indB(3)-1));
                    model.(['Feature',num2str(n)]).textName = name((indB(3)+1):end);
                    indScan = strfind(name,'(');
                    scans{n} = name(1:indScan-1);
                    model.(['Feature',num2str(n)]).scan = scans{n};
                    indMat = zeros(1,nParam); sizeParam = zeros(1,nParam);
                    for p = 1:nParam
                        paramAll = paramCell{p}; nSpecParam = numel(paramAll); sizeParam(p) = nSpecParam;
                        nameParam = nameCell{p};
                        indP = strfind(name,nameParam);
                        for start = indP:numel(name)
                            if strcmp(name(start),'=')
                                break
                            end
                        end
                        for final = indP:numel(name)
                            if strcmp(name(final),',') | strcmp(name(final),')')
                                break
                            end
                        end
                        if iscell(paramCell{p})
                            param = name((start+1):(final-1));
                            for nsp = 1:nSpecParam
                                if strcmp(param,paramAll{nsp})
                                    indMat(p) = nsp;
                                    break
                                end
                            end
                        else
                            param = str2num(name((start+1):(final-1)));
                            for nsp = 1:nSpecParam
                                if param > (paramAll(nsp)-0.05) & param < (paramAll(nsp)+0.05)
                                    indMat(p) = nsp;
                                    break
                                end
                            end
                        end
                    end
                    if numel(sizeParam) == 2
                        model.(['Feature',num2str(n)]).indText = sub2ind(sizeParam,indMat(1),indMat(2));
                    elseif numel(sizeParam) == 3
                        model.(['Feature',num2str(n)]).indText = sub2ind(sizeParam,indMat(1),indMat(2),indMat(3));
                    elseif numel(sizeParam) == 4
                        model.(['Feature',num2str(n)]).indText = sub2ind(sizeParam,indMat(1),indMat(2),indMat(3),indMat(4));
                    elseif numel(sizeParam) == 5
                        model.(['Feature',num2str(n)]).indText = sub2ind(sizeParam,indMat(1),indMat(2),indMat(3),indMat(4),indMat(5));
                    elseif numel(sizeParam) == 6
                        model.(['Feature',num2str(n)]).indText = sub2ind(sizeParam,indMat(1),indMat(2),indMat(3),indMat(4),indMat(5),indMat(6));
                    end
                    model.(['Feature',num2str(n)]).FullName = name;
                else % This is a non-texture
                    scans{n} = 'nonText';
                    model.(['Feature',num2str(n)]).isTexture = false;
                    model.(['Feature',num2str(n)]).nonText = name;
                end
            end
            model.coeff = coeff;
            model.order = order;
            results.model = model;
            results.trainData.data = finalModel.Data; results.trainData.response = response; results.trainData.outcome = training.(nameOutcomes{o}).outcome;

            % TESTING MODEL
            text = testing.(nameOutcomes{o}).text; nonText = testing.(nameOutcomes{o}).nonText;
            outcome = testing.(nameOutcomes{o}).outcome;
            resp = zeros(numel(outcome),1);
            data = zeros(numel(outcome),order);
            for n = 1:order
                coeff = model.coeff(n);
                feat = ['Feature',num2str(n)];
                scan = scans{n};
                if model.(feat).isTexture
                    data(:,n) = text.(fSetNames{f}).(scan){model.(feat).indText}.(model.(feat).textType).(model.(feat).textName).Data;
                else
                    data(:,n) = nonText.(model.(feat).nonText).Data;
                end
                resp = resp + coeff*data(:,n);
            end
            resp = resp + model.coeff(end);
            results.testData.data = data; results.testData.response = resp; results.testData.outcome = outcome;
            [AUC,sensitivity,specificity,accuracy] = calcPerformMetrics(resp,outcome,0);
            results.AUC = AUC;
            results.Sensitivity = sensitivity;
            results.Specificity = specificity;
            results.Accuracy = accuracy;
            cd(pathExperiment), save(['testResultsModels_',fSetNames{f},'_',nameOutcomes{o}],'results')
        end
    end
end

cd(startpath)
end


function y = mytestNEW(B,X)

y = B - X*X;


% The COBRAToolbox: testROOM.m
%
% Purpose:
%     - Check the function ROOM
%
% Authors:
%     - Luis V. Valcarcel 2018-12-17
%

global CBTDIR

solversToUse = prepareTest('needsMILP', true, 'useSolversIfAvailable', {'tomlab_cplex', 'ibm_cplex', 'gurobi', 'glpk','cplex_direct'}, 'excludeSolvers', {'qpng'});
% Note: the solver QPNG cannot be used with this test

% save the current path
currentDir = pwd;

% initialize the test
testDir = fileparts(which('testROOM'));
cd(testDir);

% Create Toy example model
ReactionFormulas = {'A -> B', '2 B -> C + byp', '2 B + cof -> D + byp',...
'D -> E + cof', 'C + cof -> D', 'C -> E', ' -> A', 'E -> ', 'byp -> '};
ReactionNames = {'v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'b1', 'b2', 'b3'};
lowerbounds = [0 0 0 0 0 0 0 0 0];
upperbounds = [20, 20, 20, 20, 20, 20, 20, 20, 20];
model = createModel(ReactionNames, ReactionNames, ReactionFormulas,...
'lowerBoundList', lowerbounds, 'upperBoundList', upperbounds);

% Generate reference flux
WT_flux = [10, 5, 0, 0, 0, 5, 10, 5, 5];

% Check errors when missing argument
assert(verifyCobraFunctionError('ROOM', 'inputs', {model}))
assert(verifyCobraFunctionError('ROOM', 'inputs', {model, WT_flux}))
assert(verifyCobraFunctionError('ROOM', 'inputs', {model, WT_flux, 'a'}))

% define the solver packages to be used to run this test
solverPkgs = solversToUse.MILP;

predictedROOMsol = [10 5 0 5 5 0 10 5 5]';

% Test solving for different solvers
for k = 1:length(solverPkgs)
    fprintf(' -- Running testROOM using the solver interface: %s ... ', solverPkgs{k});

    solverOK = changeCobraSolver(solverPkgs{k}, 'all', 0);

    if solverOK
        % Calculate ROOM and check solutions
        fluxROOM = ROOM(model, WT_flux, {'v6'},'delta', 1e-5, 'epsilon', 1e-5);
        assert(norm(fluxROOM-predictedROOMsol)<1e-2)

        [fluxROOM, solutionROOM, totalFluxDiff] = ROOM(model, WT_flux, {'v6'},'delta',1e-6,'epsilon',1e-6);
        assert(norm(fluxROOM-predictedROOMsol)<1e-2)
        assert(abs(totalFluxDiff^2-75)<1e-2)

        [fluxROOM2, solutionROOM2, totalFluxDiff2] = linearROOM(model, WT_flux, {'v6'},'delta',1e-6,'epsilon',1e-6);
        assert(norm(fluxROOM-predictedROOMsol)<1e-2)
        assert(abs(totalFluxDiff^2-75)<1e-2)

    else
        warning('The test testROOM cannot run using the solver interface: %s. The solver interface is not installed or not configured properly.\n', solverPkgs{k});
    end

    % output a success message
    fprintf('Done.\n');
end

% remove the file created during the test
if exist('CobraLPSolver.log','file')
    delete('CobraLPSolver.log');
end

% Set seed to default value
rng('default')
% change the directory
cd(currentDir)


%% Simulation Data
simu = simulationClass();               % Initialize Simulation Class
simu.simMechanicsFile = 'RM3.slx';      % Specify Simulink Model File
simu.rampTime = 100;                    % Wave Ramp Time [s]
simu.endTime=200;                       % Simulation End Time [s]
simu.dt = 0.1;                          % Simulation Time-Step [s]
simu.explorer = 'off';

%% Wave Information
% Regular Waves
waves = waveClass('regular');           % Initialize Wave Class and Specify Type
waves.height = 2.5;                          % Wave Height [m]
waves.period = 8;                            % Wave Period [s]

%% Body Data
% Float
body(1) = bodyClass('../../../../examples/RM3/hydroData/rm3.h5');
body(1).geometryFile = '../../../../examples/RM3/geometry/float.stl';
body(1).mass = 'equilibrium';
body(1).inertia = [20907301 21306090.66 37085481.11];

% Spar/Plate
body(2) = bodyClass('../../../../examples/RM3/hydroData/rm3.h5');
body(2).geometryFile = '../../../../examples/RM3/geometry/plate.stl';
body(2).mass = 'equilibrium';
body(2).inertia = [94419614.57 94407091.24 28542224.82];

%% PTO and Constraint Parameters
% Floating (3DOF) Joint
constraint(1) = constraintClass('Constraint1'); % Initialize Constraint Class for Constraint1
constraint(1).location = [0 0 0];                    % Constraint Location [m]

% Translational PTO
pto(1) = ptoClass('PTO1');                      % Initialize PTO Class for PTO1
pto(1).stiffness = 0;                                   % PTO Stiffness [N/m]
pto(1).damping = 1200000;                             % PTO Damping [N/(m/s)]
pto(1).location = [0 0 0];                           % PTO Location [m]


function [res] = mne_transpose_named_matrix(mat)
%
% [res] = mne_transpose_named_matrix(mat)
%
% Transpose a named matrix
%

%
%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
%   Revision 1.2  2006/04/23 15:29:41  msh
%   Added MGH to the copyright
%
%   Revision 1.1  2006/04/18 23:21:22  msh
%   Added mne_transform_source_space_to and mne_transpose_named_matrix
%
%

res.nrow = mat.ncol;
res.ncol = mat.nrow;
res.row_names = mat.col_names;
res.col_names = mat.row_names;
res.data      = mat.data';

return;

end


function diagnostic = callkypd(F,h,options)

%F = constraint2kyp(F);
kyps = is(F,'kyp');
if all(kyps)
    kypConstraints = F;
    otherConstraints = lmi;
else
    kypConstraints   = F(find(kyps));
    otherConstraints = F(find(~kyps));
end

% Trivial case
if length(kypConstraints) == 0
    if ~isempty(options)
        options.solver = '';
    else
        options = sdpsettings;
    end
    diagnostic = solvesdp(F,h,options)
    return;
end

p_variables = [];
x_variables = [];
for i = 1:length(kypConstraints)
    [A{i},B{i},P{i},M{i},negated{i}] = extractkyp(sdpvar(kypConstraints(i)));
    if ~isa(P{i},'sdpvar') | ~isempty(intersect(p_variables,getvariables(P{i})))
        diagnostic.solvertime = 0;
        diagnostic.problem = -4;
        diagnostic.info = yalmiperror(-4);
        return;
    end
    P_base = getbase(P{i});
    [n,m] = size(P{i});
    if (n~=m) | (nnz(P_base)~=n*n) | (sum(sum(P_base))~=n*n)
        diagnostic.solvertime = 0;
        diagnostic.problem = -4;
        diagnostic.info = yalmiperror(-4);
        return;
    end
    p_variables = [p_variables getvariables(P{i})];
    x_variables = [x_variables getvariables(M{i})];
end

if intersect(p_variables,getvariables(h))
    diagnostic.solvertime = 0;
    diagnostic.problem = -4;
    diagnostic.info = yalmiperror(-4);
    return;
end

start = length(A);k = 1;
for i = 1:length(otherConstraints)
    if is(otherConstraints(i),'lmi')
        A{k+start}=[];
        B{k+start}=[];
        P{k+start}=[];
        M{k+start} = sdpvar(otherConstraints(i));
        x_variables = [x_variables getvariables(M{k+start})];
        k = k + 1;
    elseif is(otherConstraints(i),'elementwise')
        X = sdpvar(otherConstraints(i));
        for ii = 1:size(X,1)
            for jj = 1:size(X,2)
                A{k+start}=[];
                B{k+start}=[];
                P{k+start}=[];
                M{k+start} = X(ii,jj);
                x_variables = [x_variables getvariables(X(ii,jj))];
                k = k + 1;
            end
        end
    end
end

% Objective function variables
x_variables = unique([x_variables getvariables(h)]);

% Are P and x independent
if ~isempty(intersect(p_variables,x_variables))
    error
end

% Generate the M-matrices
for i = 1:length(M)
    m_variables = getvariables(M{i});
    n = length(M{i});
    M0{i} = getbasematrix(M{i},0);
    for j = 1:length(x_variables)
        Mi{i,j} = getbasematrix(M{i},x_variables(j));
    end
end

c = zeros(length(x_variables),1);
if ~isempty(h)
    for i = 1:length(x_variables)
        c(i) = getbasematrix(h,x_variables(i));
    end
end

for i = 1:length(M)
    matrixinfo.n(i) = length(A{i});
    matrixinfo.nm(i) = length(M{i});
end

matrixinfo.K  = length(x_variables);
matrixinfo.c  = c;
matrixinfo.N  = length(A);
matrixinfo.A  = A;
matrixinfo.B  = B;
matrixinfo.M0 = M0;
matrixinfo.M  = Mi;
matrixinfo.A  = A;

try
    solvertime = tic;
    [u,Popt,xopt,Zopt] = kypd_solver(matrixinfo,options);
    solvertime = toc(solvertime);

    % SAVE PRIMALS
    setsdpvar(recover(x_variables),xopt);
    for i = 1:length(kypConstraints)
        if negated{i}
            setsdpvar(P{i},-Popt{i});
        else
            setsdpvar(P{i},Popt{i});
        end
    end

    % SAVE DUALS
    lmi_index = [];
    j = 1;
    for i = 1:length(kypConstraints)
        %W = struct(kypConstraints(i));lmiid = W.LMIid;
        lmiid = getlmiid(kypConstraints(i));
        lmi_index = [lmi_index;lmiid];
        duals{j}=Zopt{j};j = j+1;
    end
    for i = 1:length(otherConstraints)
        %W = struct(otherConstraints(i));lmiid = W.LMIid;
        lmiid = getlmiid(otherConstraints(i));
        lmi_index = [lmi_index;lmiid];
        duals{j}=Zopt{j};j = j+1;
    end
    yalmip('setdual',lmi_index,duals);

    diagnostic.solvertime = solvertime;
    diagnostic.info = yalmiperror(0,'KYPD');
    diagnostic.problem = 0;
catch
    solvertime = etime(clock,solvertime);
    diagnostic.solvertime = solvertime;
    diagnostic.info = yalmiperror(9,'KYPD');
    diagnostic.problem = 9;
end

function Fout = constraint2kyp(F)
Fout = [];
for i = 1:length(F)
    if is(F(i),'lmi')
        [l,m,r] = factors(sdpvar(F(i)));
        [constants,general,singles,pairs] = classifyfactors(l,m,r);
        [constants,general,singles,pairs] = compressfactors2(constants,general,singles,pairs);
    else
        Fout = Foput + F(i);
    end
end


function plotRendezvous(hAxis, timeArr, bodyInfo, iniOrbit, finOrbit, xfrOrbit, dv1, dv2, celBodyData)
%plotRendezvous Summary of this function goes here
%   Detailed explanation goes here

    gmuXfr = bodyInfo.gm;

    cla(hAxis, 'reset');

    iniOrbBodyInfo = getBodyInfoStructFromOrbit(iniOrbit);
    finOrbBodyInfo = getBodyInfoStructFromOrbit(finOrbit);

    xfrOrbit2 = xfrOrbit;
    xfrOrbit2(7) = timeArr(1);
    xfrOrbit2(6) = computeMeanFromTrueAnom(xfrOrbit(6), xfrOrbit(2));
    xfrOrbBodyInfo = getBodyInfoStructFromOrbit(xfrOrbit2);

    axes(hAxis);
    hold on;
    axes(hAxis);
    set(hAxis,'XTickLabel',[]);
    set(hAxis,'YTickLabel',[]);
    set(hAxis,'ZTickLabel',[]);
    grid on;
    view(3);

%     dRad = bodyInfo.radius;
%     [X,Y,Z] = sphere(30);
%     surf(dRad*X,dRad*Y,dRad*Z);
%     colormap(bodyInfo.bodycolor);

    ma_initOrbPlot([], hAxis, bodyInfo);

    parentBodyInfo = bodyInfo.getParBodyInfo(celBodyData);

    [iniLB, iniUB, ~] = getOrbitTAPlotBnds(bodyInfo, parentBodyInfo, iniOrbit);
    [finLB, finUB, ~] = getOrbitTAPlotBnds(bodyInfo, parentBodyInfo, finOrbit);

    time1 = timeArr(1);
    time2 = timeArr(2);

    if(iniOrbit(2) >= 1)
        [rVect, vVect] = getStateAtTime(iniOrbBodyInfo, time1, iniOrbit(8));
        [~, ~, ~, ~, ~, iniTA1] = getKeplerFromState(rVect,vVect,iniOrbit(8));
        iniLB = min(iniLB,iniTA1);

        [rVect, vVect] = getStateAtTime(iniOrbBodyInfo, time2, finOrbit(8));
        [~, ~, ~, ~, ~, iniTA2] = getKeplerFromState(rVect,vVect,finOrbit(8));
        iniUB = max(iniUB,iniTA2);
    end

    if(finOrbit(2) >= 1)
        [rVect, vVect] = getStateAtTime(finOrbBodyInfo, time1, finOrbit(8));
        [~, ~, ~, ~, ~, finTA1] = getKeplerFromState(rVect,vVect,finOrbit(8));
        finLB = min(finLB,finTA1);

        [rVect, vVect] = getStateAtTime(finOrbBodyInfo, time2, finOrbit(8));
        [~, ~, ~, ~, ~, finTA2] = getKeplerFromState(rVect,vVect,finOrbit(8));
        finUB = max(finUB,finTA2);
    end

    plotOrbit('r', iniOrbit(1), iniOrbit(2), iniOrbit(3), iniOrbit(4), iniOrbit(5), iniLB, iniUB, gmuXfr);
    plotOrbit('b', finOrbit(1), finOrbit(2), finOrbit(3), finOrbit(4), finOrbit(5), finLB, finUB, gmuXfr);
    plotOrbit('k', xfrOrbit(1), xfrOrbit(2), xfrOrbit(3), xfrOrbit(4), xfrOrbit(5), xfrOrbit(6), xfrOrbit(7), gmuXfr,[],[],[],'--');

    [iniRVectT1, ~] = getStateAtTime(iniOrbBodyInfo, time1, gmuXfr);
    [iniRVectT2, ~] = getStateAtTime(iniOrbBodyInfo, time2, gmuXfr);
    [finRVectT1, ~] = getStateAtTime(finOrbBodyInfo, time1, gmuXfr);
    [finRVectT2, ~] = getStateAtTime(finOrbBodyInfo, time2, gmuXfr);

    hold on;
    plot3(iniRVectT1(1),iniRVectT1(2),iniRVectT1(3),...
                    '-ro',...
                    'LineWidth',1.0,...
                    'MarkerEdgeColor','k',...
                    'MarkerFaceColor','r',...
                    'MarkerSize',10);

    hold on;
    plot3(iniRVectT2(1),iniRVectT2(2),iniRVectT2(3),...
                    '-ro',...
                    'LineWidth',1.0,...
                    'MarkerEdgeColor','k',...
                    'MarkerFaceColor','r',...
                    'MarkerSize',10);

    hold on;
    plot3(finRVectT1(1),finRVectT1(2),finRVectT1(3),...
                    '-bo',...
                    'LineWidth',1.0,...
                    'MarkerEdgeColor','k',...
                    'MarkerFaceColor','b',...
                    'MarkerSize',10);

    hold on;
    plot3(finRVectT2(1),finRVectT2(2),finRVectT2(3),...
                    '-bo',...
                    'LineWidth',1.0,...
                    'MarkerEdgeColor','k',...
                    'MarkerFaceColor','b',...
                    'MarkerSize',10);

    hold off;
    axis equal;

    drawnow;
end


close all;
clear all;
clc;

data_file_path = 'bin/mmv_phase_transition_noiseless_s_2.mat';
options.export = true;
options.export_dir = 'bin';
options.export_name = 'mmv_noiseless_s_2';
options.chosen_ks = [2, 4, 8, 16, 32, 64];
options.subtitle = 'Noiseless, S = 2';
spx.pursuit.PhaseTransitionAnalysis.print_results(data_file_path, ...
    'CoSaMP', options);


function slope = calc_slope_grigsby(structNum,Thresholds)
%function slope = calc_slope_grigsby(structNum,Thresholds)
%
%This function returns shape features.
%
%IEN & APA, 07/06/2006

global planC stateS
indexS = planC{end};
for i=1:length(Thresholds)
    contourSUV(structNum,Thresholds(i));
    structVol(i) = getStructureVol(length(planC{indexS.structures}));
    %runCERRCommand('del','structure',length(planC{indexS.structures}))
    n = length(planC{indexS.structures});
    len = n;
    planC = delUniformStr(n, planC); %Update the uniform data.
    planC{indexS.structures}(n:len-1) = planC{indexS.structures}(n+1:len);
    planC{indexS.structures} = planC{indexS.structures}(1:len-1);
end
coeff = polyfit(Thresholds,structVol,1);
slope=coeff(1);
return;


% © Rahul Kala, IIIT Allahabad, Creative Commons Attribution-ShareAlike 4.0 International License.
% The use of this code, its parts and all the materials in the text; creation of derivatives and their publication; and sharing the code publically is permitted without permission.

% Please cite the work in all materials as: R. Kala (2014) Code for Robot Path Planning using Probabilistic Roadmap (Octave), Indian Institute of Information Technology Allahabad, Available at: http://rkala.in/codes.html

function h=historic(a,b)
h = sqrt(sum((a-b).^2));


function outputImage = times(this, otherImage)
% Multiplies data of other image with this one and writes output in new image
%
% NOTE: If voxel dimensions of 2nd image do not match - or a scalar is
% given as 2nd argument - data in the 2nd argument is automatically
% replicated to match this image geometry.
%
%
%   Y = MrImage()
%   outputImage = times(Y, otherImage, ...
%   functionHandle)
%
%   OR
%
%   outputImage = Y.*otherImage
%
% This is a method of class MrImage.
%
%
% IN
%   otherImage              image that will be multiplied with this one
%
% OUT
%   outputImage             new MrImage, product of this and otherImage
%
% EXAMPLE
%
%   % Compute difference of 2 images
%		Y = MrImage();
%		Z = MrImage();
%		X = Y.times(Z);
%
%   % OR (cool overload!):
%       X = Y.*Z
%
%   See also MrImage perform_binary_operation MrImage.plus

% Author:   Saskia Bollmann & Lars Kasper
% Created:  2014-11-13
% Copyright (C) 2014 Institute for Biomedical Engineering
%                    University of Zurich and ETH Zurich
%
% This file is part of the TAPAS UniQC Toolbox, which is released
% under the terms of the GNU General Public Licence (GPL), version 3.
% You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version).
% For further details, see the file COPYING or
%  <http://www.gnu.org/licenses/>.

outputImage = this.perform_binary_operation(otherImage, @times);


%########################################################################
%
%	- PPGI Toolbox -
%   A MATLAB toolbox for Photoplethysmography Imaging (PPGI)
%
% Author   : Christian S. Pilz
% Company  : The Nature of Space of Time
% Date     : 07.05.2019
%
% Contact  : cpi@partofthestars.com
% Web Page : www.partofthestars.com
%
% Version  : beta0.1
%
%########################################################################
%
%	skin.m:
%
% Description:
%
%   A static MATLAB class to extract skin pixels based upon
%   YCbCr color space thresholding
%

classdef skin

   methods(Static)
       function out = get(rgb)
           %convert the image from RGB to YCbCr
           img_ycbcr = rgb2ycbcr(rgb);
           Cb = img_ycbcr(:,:,2);
           Cr = img_ycbcr(:,:,3);

           %detect skin
           [r,c,v] = find(Cb>=98 & Cb<=142 & Cr>=133 & Cr<=177);
            numind = size(r,1);

            %extract skin Pixels
            for i=1:numind
                out(i,:)=double(rgb(r(i),c(i),:));
            end
       end
   end
end