%plugin_movepath()- Given a path to a plugin folder, this function will
%                     put the plugin at the bottom of the path.
%
% Usage:
%         plugin_movepath('x','begin');           % Put plugin 'x' at the top of the path
%         plugin_movepath('x','end');             % Put plugin 'x' at the bottom of the path
%         plugin_movepath('x','begin','warns',1); % Put plugin 'x' at the top of the path and show warnings
%
%  Inputs:
%         foldername   - [string] Plugin name or part of it
%         pluginpos    - {'begin','end'} Position to move the plugin in the path.
%                      To the top ('begin') or to the bottom ('end').
% Optional inputs:
%        warns        -[0,1] Allow isplay [1] or do not display [0] warnings.
%                      Warnings are restored at the end of the process. Default[0]
%  Outputs:
%        oldpath  - Original MATLAB path before entering this function
%        newpath  - MATLAB path after being modified by this function
%
% Author: Ramon Martinez-Cancino and Arnaud Delorme, SCCN, 2016
%
% Copyright (C) 2016  Ramon Martinez-Cancino,INC, SCCN
%
% 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 should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function[oldpath, newpath] = plugin_movepath(foldername,pluginpos, varargin)
oldpath = []; newpath = [];

try
    options = varargin;
    if ~isempty( varargin ),
        for i = 1:2:numel(options)
            g.(options{i}) = options{i+1};
        end
    else g = []; end;
catch
    disp('plugin_movepath() error: calling convention {''key'', value, ... } error'); return;
end;

try g.warns;   catch, g.warns  = 0;  end; % NO warnings by default

% Checking entries
if sum(strcmp(pluginpos,{'begin','end'})) ~= 1
    fprintf(2,'plugin_movepath error: Invalid function argument\n');
    return;
end

% Look in the plugin list for the plugin name provided
global PLUGINLIST
hitindx = find(~cellfun(@isempty,strfind(lower({PLUGINLIST.plugin}),lower(foldername))));
if isempty(hitindx)
    fprintf(2,'plugin_movepath error: Unidentified plugin folder\n')
    return;
else
    eeglabfolder = fileparts(which('eeglab.m'));
    pluginfolder = fullfile(eeglabfolder,'plugins',PLUGINLIST(hitindx).foldername );
end

% Backing up old path
if ismatlab
    oldpath = matlabpath;
else
    oldpath = path;
end;

% Retreiving path
comp = computer;
if strcmpi(comp(1:2), 'PC')
    newpathtest = [ pluginfolder ';' ];
else
    newpathtest = [ pluginfolder ':' ];
end;
ind = strfind(oldpath, newpathtest);

% Checking out if the work is already done
if strcmp(pluginpos,'begin') && ind == 1, return; end;
if strcmp(pluginpos,'end')   && strcmp(oldpath(end-length(pluginfolder):end),pluginfolder), return; end;

% Shooting down warnings
if ~g.warns
    tmpwarn = warning;
    warning off;
end

% Remove folder and subfolders from path
rmpath(genpath(pluginfolder));

% Add folder to the path again in the requested position
 if strcmp(pluginpos,'begin')
     addpath(genpath(pluginfolder),'-begin');
     fprintf(1,['EEGLAB warning: to avoid name conflict ' PLUGINLIST(hitindx).foldername ' functions relocated at the end of the path\n']);
 elseif strcmp(pluginpos,'end')
     addpath(genpath(pluginfolder),'-end');
     fprintf(1,['EEGLAB warning: to avoid name conflict ' PLUGINLIST(hitindx).foldername ' functions relocated at the end of the path\n']);
 end

 % Restoring warnings
 if ~g.warns
     warning(tmpwarn);
 end

 newpath = path; % Retreiving new path

 % required here because path not added yet
% to the admin folder
function res = ismatlab;

v = version;
if v(1) > '4'
    res = 1;
else
    res = 0;
end;


function bnet = bnet_from_engine(engine)
% BNET_FROM_ENGINE Return the bnet structure stored inside the engine (inf_engine)
% bnet = bnet_from_engine(engine)

bnet = engine.bnet;

% We cannot write 'engine.bnet' without writing a 'subsref' function,
% since engine is an object with private parts.
% The bnet field should be the only thing external users of the engine should need access to.
% We do not pass bnet as a separate argument, since it could get out of synch with the one
% encoded inside the engine.


function  write(freader,data,datatype)
%
%    write(freader,data,datatype) - writes data to a binary file opened with freader('filename')
%
fwrite(freader.fd,data,datatype);


function Callbacks_ideal_vocal_tract_GUI25(f,C)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
x=C{1,1};
y=C{1,2};
a=C{1,3};
b=C{1,4};
u=C{1,5};
v=C{1,6};
m=C{1,7};
n=C{1,8};
lengthbutton=C{1,9};
widthbutton=C{1,10};
enterType=C{1,11};
enterString=C{1,12};
enterLabel=C{1,13};
noPanels=C{1,14};
noGraphicPanels=C{1,15};
noButtons=C{1,16};
labelDist=C{1,17};%distance that the label is below the button
noTitles=C{1,18};
buttonTextSize=C{1,19};
labelTextSize=C{1,20};
textboxFont=C{1,21};
textboxString=C{1,22};
textboxWeight=C{1,23};
textboxAngle=C{1,24};
labelHeight=C{1,25};
fileName=C{1,26};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%PANELS
for j=0:noPanels-1
uipanel('Parent',f,...
'Units','Normalized',...
'Position',[x(1+4*j) y(1+4*j) x(2+4*j)-x(1+4*j) y(3+4*j)-y(2+4*j)]);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%GRAPHIC PANELS
for i=0:noGraphicPanels-1
switch (i+1)
case 1
graphicPanel1 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 2
graphicPanel2 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 3
graphicPanel3 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 4
graphicPanel4 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 5
graphicPanel5 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
case 6
graphicPanel6 = axes('parent',f,...
'Units','Normalized',...
'Position',[a(1+4*i) b(1+4*i) a(2+4*i)-a(1+4*i) b(3+4*i)-b(2+4*i)],...
'GridLineStyle','--');
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%TITLE BOXES
for k=0:noTitles-1
switch (k+1)
case 1
titleBox1 = uicontrol('parent',f,...
'Units','Normalized',...
'Position',[u(1+4*k) v(1+4*k) u(2+4*k)-u(1+4*k) v(3+4*k)-v(2+4*k)],...
'Style','text',...
'FontSize',textboxFont{k+1},...
'String',textboxString(k+1),...
'FontWeight',textboxWeight{k+1},...
'FontAngle',textboxAngle{k+1});
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%BUTTONS
for i=0:(noButtons-1)
enterColor='w';
if strcmp(enterType{i+1},'pushbutton')==1 ||strcmp(enterType{i+1},'text')==1
enterColor='default';
end
if (strcmp(enterLabel{1,(i+1)},'')==0 &&...
        strcmp(enterLabel{1,(i+1)},'...')==0) %i.e. there is a label
%creating a label for some buttons
uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i)-labelDist-labelHeight(i+1) ...
(m(2+2*i)-m(1+2*i)) labelHeight(i+1)],...
'Style','text',...
'String',enterLabel{i+1},...
'FontSize', labelTextSize(i+1),...
'HorizontalAlignment','center');
end
switch (i+1)
case 1
button1=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button1Callback);
case 2
button2=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button2Callback);
case 3
button3=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button3Callback);
case 4
button4=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button4Callback);
case 5
button5=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button5Callback);
case 6
button6=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button6Callback);
case 7
button7=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button7Callback);
case 8
button8=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button8Callback);
case 9
button9=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button9Callback);
case 10
button10=uicontrol('Parent',f,...
'Units','Normalized',...
'Position',[m(1+2*i) n(1+2*i) (m(2+2*i)-m(1+2*i)) (n(2+2*i)-n(1+2*i))],...
'Style',enterType{i+1},...
'String',enterString{i+1},...
'FontSize', buttonTextSize(1+i),...
'BackgroundColor',enterColor,...
'HorizontalAlignment','center',...
'Callback',@button10Callback);
end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%USER CODE FOR THE VARIABLES AND CALLBACKS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initialize Variables
vowel_index=1;
ipd=100;
Lm=40;
L=400;
ilog=1;
ftable=[270 2290 3010; 390 1990 2550; 530 1840 2480; 660 1720 2410;...
    520 1190 2390; 730 1090 2390; 570 840 2410; 490 1350 1690;...
    440 1020 2240; 300 870 2240; 300 870 2240; 500 1500 2500];
btable=[40 60 75];
fk=[270 2290 3010];
bk=[40 60 75];
M=3;
fs=10000;
hn=[];
g=[];
iglottal=0;
vowels=['IY'; 'IH'; 'EH'; 'AE'; 'AH'; 'AA'; 'AO'; 'ER'; 'UH'; 'UW'; 'OO'; 'Ne'];
filename=vowels(1,:);
alpha1=40;
alpha2=20;

% nfft: size of fft and ifft for conversion from time to frequency or
% frequency to time domain
    nfft=1000;

% Name GUI
    set(f,'Name','ideal_vocal_tract_GUI');

% CALLBACKS
% Callback for button1 -- vowel choice from popuplist
 function button1Callback(h,eventdata)
     vowel_index=get(button1,'val');
     fk=ftable(vowel_index,:);
     bk=btable;
     filename=vowels(vowel_index,:);
 end

% Callback for button2 -- ipd: pitch period in msec
 function button2Callback(h,eventdata)
     ipd=str2num(get(button2,'string'));
     if ipd < 2
         waitfor(msgbox('pitch period must lie between 2 and 15 msec'));
     elseif ipd > 15
         waitfor(msgbox('pitch period must lie between 2 and 15 msec'));
     end
     ipd=ipd*fs/1000;
 end

% Callback for button3 -- Lm: frame duration in msec, (editable)
 function button3Callback(h,eventdata)
     Lm=str2num(get(button3,'string'));
      if Lm < 0
         waitfor(msgbox('The frame duration cannot be negative'));
     end
     L=round(Lm*fs/1000);
 end

% Callback for button4 -- log/linear popuplist (1=log, 2=linear); option
% for plotting vowel and ideal frequency responses
 function button4Callback(h,eventdata)
     ilog=get(button4,'val');
 end

% Callback for button10 -- iglottal: use glottal puse (1) or skip glottal
% pulse (0)
    function button10Callback(h,eventdata)
        iglottal=get(button10,'val');
    end

% Callback for button8 -- alpha1 for glottal pulse
    function button8Callback(h,eventdata)
        alpha1=str2num(get(button8,'string'))/100;
        if alpha1 < 0
            waitfor(msgbox('alpha1 must lie between 0 and 100'));
        elseif alpha1 > 1
            waitfor(msgbox('alpha1 must lie between 0 and 100'));
        end
    end

% Callback for button9 -- alpha2 for glottal pulse
    function button9Callback(h,eventdata)
        alpha2=str2num(get(button9,'string'))/100;
    if alpha2 < 0
        waitfor(msgbox('alpha2 must lie between 0 and 100'));
    elseif alpha2 > 1
        waitfor(msgbox('alpha2 must lie between 0 and 100'));
     end
    end

% Callback for button5 -- Run ideal vocal tract responses
 function button5Callback(h,eventdata)

% eps: smallest spectral magnitude for plotting log magnitude spectra
    eps=1.e-3;

% form rosenberg glottal pulse, g; rise % from alpha1; fall % from alpha2
    button8Callback(h,eventdata);
    button9Callback(h,eventdata);
    button10Callback(h,eventdata);
    button2Callback(h,eventdata);
    button3Callback(h,eventdata);
    button4Callback(h,eventdata);

    n1=round(ipd*alpha1);
    n2=round(ipd*alpha2);
    g=[];
    x1=0:n1;
    g=[g 0.5*(1-cos(pi*x1/n1))];
    x2=1:n2;
    g=[g cos(pi*x2/(2*n2))];
    g=[g zeros(1,ipd-length(g))];

% create periodic voiced excitation
    e=zeros(1,nfft);
    e(1:ipd:nfft)=1;
    EM=zeros(1,nfft);
    EM(1:round(nfft/ipd):nfft)=1;

% glottal_pulse excitation based on iglottal (1: use glottal pulse, 0 skip
% glottal pulse
if (iglottal == 1)
    eg=conv(e,g);
else
    eg=e;
end
    ege(1:nfft)=0;
    ege(1:nfft)=eg(1:nfft);
    EGM=abs(fft(ege,nfft));

% convert to second order system format
    zk=exp(-2*pi*bk/fs);
    fkn=cos(2*pi*fk/fs);

% transform into frequency domain
    HR=[];
    HT=zeros(1,nfft);
    HP=(complex(ones(1,nfft),zeros(1,nfft)))';
    for k=1:M
        B=1-2*zk(k)*fkn(k)+zk(k)*zk(k);
        A=[1 -2*zk(k)*fkn(k) zk(k)*zk(k)];
        [H,W]=freqz(B,A,nfft,'whole',fs);
        HP=HP.*H;
        HL=(abs(H));
        HT=HT.*HL';
    end

% inverse transform to give vocal tract impulse response
    hn=ifft(HP,nfft);
    hmax=max(max(hn),-min(hn));
    for index=1:nfft
        if (max(max(hn(index:nfft)),-min(hn(index:nfft)))) < hmax/50
            nl=index;
            break;
        end
    end

% plot elements of composite response in the 6 graphics Panels
% plot ideal impulse excitation signal in graphics Panel 5 (top left panel)
    reset(graphicPanel5);
    axes(graphicPanel5);

    if (iglottal == 0)
        stem(0:nfft-1,e(1:nfft),'b','LineWidth',2),axis tight;
    else
        plot(0:nfft-1,eg(1:nfft),'b','LineWidth',2),axis tight;
    end
    xpp=['Time in Samples; fs=',num2str(fs),' samples/second'];
    xlabel(xpp),ylabel('Amplitude');grid on;legend('Excitation Pulses');

% plot vowel impulse response in graphics Panel 3 (middle left panel)
    reset(graphicPanel3);
    axes(graphicPanel3);

    plot(0:nl,hn(1:nl+1),'r','LineWidth',2);
    xlabel(xpp),ylabel('Amplitude');
    axis tight, grid on;legend('Vowel Vocal Tract Impulse Response');

% plot linear or log magnitude frequency response of ideal impulse
% excitation signal in graphics Panel 6 (top right panel); use lin/log
% option to decide whether to plot linear or log magnitude responses
    if (ilog == 1)
        reset(graphicPanel6);
        axes(graphicPanel6);
        plot(W(1:nfft/2+1),20*log10(EGM(1:nfft/2+1)+eps),'b','LineWidth',2);
        axis tight,xlabel('Frequency in Hz'),ylabel('Log Magnitude (dB)');
        legend('Excitation Pulses Log Spectrum');

% plot linear or log magnitude frequency response of ideal vocal tract
% impulse response in graphics Panel 4 (middle right panel); use lin/log
% option to decide whether to plot linear or log magnitude response
        reset(graphicPanel4);
        axes(graphicPanel4);
        plot(W(1:nfft/2+1),20*log10(abs(HP(1:nfft/2+1))),'r','LineWidth',2);
        axis tight,grid on, xlabel('Frequency in Hz');
        ylabel('Log Magnitude (dB)');legend('Vocal Tract Log Spectrum');
    else
        reset(graphicPanel6);
        axes(graphicPanel6);
        plot(W(1:nfft/2+1),EGM(1:nfft/2+1),'b','LineWidth',2);
        axis tight,xlabel('Frequency in Hz'),ylabel('Magnitude');
        legend('Excitation Pulses Linear Spectrum');

        reset(graphicPanel4);
        axes(graphicPanel4);
        plot(W(1:nfft/2+1),abs(HP(1:nfft/2+1)),'r','LineWidth',2);
        xlabel('Frequency in Hz'),ylabel('Magnitude'),axis tight,grid on;
        legend('Vocal Tract Linear Spectrum');
    end
    axis tight;

% take product of magnitudes, convolve time responses
    he=zeros(1,L+nfft-1);
    for index=1:ipd:L
        he(index:index+nfft-1)=he(index:index+nfft-1)+hn(1:nfft)';
    end
    EMV=EGM(1:nfft/2+1).*abs(HP(1:nfft/2+1))';

% plot ideal periodic vowel impulse response in graphics Panel 1 (lower
% left panel); note: no glottal pulse used in this simple ideal vocal tract
% model
    reset(graphicPanel1);
    axes(graphicPanel1);
    plot(0:L-1,he(1:L),'b','LineWidth',2);
    xlabel(xpp),ylabel('Amplitude');
    axis tight,grid on;legend('Vowel Waveform');

% plot linear or log magnitude frequency response of ideal synthetic vowel
% impulse response in graphics Panel 2 (bottom right panel); use lin/log
% option to decide whether to plot linear or log magnitude response
    if (ilog == 1)
        reset(graphicPanel2);
        axes(graphicPanel2);
        plot(W(1:nfft/2+1),20*log10(EMV(1:nfft/2+1)+eps),'r','LineWidth',2);
        xlabel('Frequency in Hz'),ylabel('Log Magnitude (dB)');
        axis tight,grid on;legend('Vowel Log Spectrum');
    else
        reset(graphicPanel2);
        axes(graphicPanel2);
        plot(W(1:nfft/2+1),EMV(1:nfft/2+1),'r','LineWidth',2);
        xlabel('Frequency in Hz'),ylabel('Magnitude');
        axis tight, grid on;legend('Vowel Linear Spectrum');
    end

% set titleBox1 information for display
    stitle=sprintf('Ideal Vocal Tract -- Vowel:%s, ipd:%d, L:%d, fs:%d, eps:%6.3f',filename,ipd,L,fs,eps);
    set(titleBox1,'String',stitle);
    set(titleBox1,'FontSize',20);
 end

% Callback for button7 -- Play Synthetic Vowel
    function button7Callback(h,eventdata)
% play back synthetic speech output
    e=zeros(1,fs);
    e(1:ipd:fs)=1;
    if (iglottal == 1)
        y1=conv(e,g);
        yout=conv(y1,hn);
    else
        yout=conv(e,hn);
    end
    % uiwait(msgbox('Play out synthetic speech','speech out'));
    soundsc(yout,fs);
    end

% Callback for button6 -- Close GUI
 function button6Callback(h,eventdata)
     close(gcf);
 end
end


function workbook=loadWorkbook(fileName,createEmpty)
% loadWorkbook
%   Loads an Excel file into a Workbook object using the Java library Apache POI
%
%   fileName    name of the Excel file. If it doesn't exist it will be
%               created
%   createEmpty true if an empty workbook should be created if the file
%               didn't exist (opt, default false)
%
%   workbook    Workbook object representing the Excel file
%
%   Usage: workbook=loadWorkbook(fileName,createEmpty)

if nargin<2
    createEmpty=false;
end

%Check if the user has MATLAB Text Analytics Toolbox installed, as it comes
%with its own conflicting version of the required Apache POI files
if exist('vaderSentimentScores.m')== 2
    error(['MATLAB Text Analytics Toolbox found. This should be uninstalled ' ...
           'if you want to read/write Excel files. See RAVEN GitHub Issues '...
           'page for instructions.'])
end

%Adds the required classes to the static Java path if not already added
addJavaPaths();

%Import required classes from Apache POI
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
import java.io.FileInputStream;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.xssf.usermodel.*;

%Check if the file exists
if ~isfile(fileName)
    if createEmpty==false
        EM='The Excel file could not be found';
        dispEM(EM);
    else
        %Create an empty workbook
        [~,~,I]=fileparts(fileName);
        if strcmpi(I,'.xls')
            workbook=HSSFWorkbook();
        else
            if strcmpi(I,'.xlsx')
                workbook=XSSFWorkbook();
            else
                EM='The file name must end in .xls or .xlsx';
                dispEM(EM);
            end
        end
    end
else
    %Opens the workbook. The input stream is needed since it will otherwise
    %keep the file open
    is=FileInputStream(getFullPath(fileName));
    workbook=WorkbookFactory.create(is);
    is.close();
end
end


% SCRIPT TEST TO LOAD ALL ROBOTS

% Copyright (C) 2012, by Arturo Gil Aparicio
%
% This file is part of ARTE (A Robotics Toolbox for Education).
%
% ARTE 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.
%
% ARTE is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with ARTE.  If not, see <http://www.gnu.org/licenses/>.

close all

fprintf('\nTHE DEMO LOADS ALL ROBOTS AND PLOTS THEM')

%there are eight possible solutions for the

%load robot parameters
% you can try different robots
robot=load_robot('ABB', 'IRB52');
robot=load_robot('ABB', 'IRB140');
robot=load_robot('ABB', 'IRB1600_6_120');
robot=load_robot('ABB', 'IRB1600_X145_M2004');
robot=load_robot('ABB', 'IRB1600ID');
robot=load_robot('ABB', 'IRB2400');
%robot=load_robot('ABB', 'IRB4400');
robot=load_robot('ABB', 'IRB4600');
robot=load_robot('ABB', 'IRB6620');
robot=load_robot('ABB', 'IRB6620LX');
robot=load_robot('ABB', 'IRB6650S_125_350');
robot=load_robot('ABB', 'IRB7600_150');
robot=load_robot('ABB', 'IRB7600_400_255_m2000');
robot=load_robot('ABB', 'IRB7600_500_230');
%ADEPT
robot=load_robot('ADEPT', 'Viper_s1700D');
%EPSON
robot=load_robot('EPSON', 'Prosix_C3_A601C');
%FANUC
robot=load_robot('FANUC', 'LR_MATE_200iC');
%KUKA
robot=load_robot('KUKA', 'KR5_2ARC_HW');
robot=load_robot('KUKA', 'KR5_arc');
robot=load_robot('KUKA', 'KR5_scara_R350_Z200');
robot=load_robot('KUKA', 'KR5_sixx_R650');
robot=load_robot('KUKA', 'KR5_sixx_R850');
robot=load_robot('KUKA', 'KR6_2');
robot=load_robot('KUKA', 'KR30_jet');
robot=load_robot('KUKA', 'KR90_R2700_pro');
robot=load_robot('KUKA', 'KR90_R3100_EXTRA');
robot=load_robot('KUKA', 'KR_16_arc_HW');
robot=load_robot('KUKA', 'KR_30_L16_2');
robot=load_robot('KUKA', 'KR_1000_1300_TITAN');
%MITSUBISHI
robot=load_robot('MITSUBISHI', 'pa-10');
robot=load_robot('MITSUBISHI', 'rv-6s');
%STANFORD ARM
robot=load_robot('example', 'stanford');
%STAUBLI
robot=load_robot('STAUBLI', 'RX160L');
%UNIMATE
robot=load_robot('UNIMATE', 'PUMA560');

%EXAMPLE ROBOTS
robot=load_robot('example', '2dofplanar');
robot=load_robot('example', '3dofplanar');
robot=load_robot('example', 'scara');
robot=load_robot('example', 'stanford');


function dotmfolders = findDotMFolders(subdir, exclList)
global MAXPATHLENGTH
MAXPATHLENGTH = 8;

dotmfolders = {};

if ~exist('subdir','var')
    subdir = pwd;
end
if ~exist('exclList','var')
    exclList = {};
end

if ~iscell(exclList)
    exclList = {exclList};
end

subdirFullpath = filesepStandard_startup(subdir,'full');

if ~ispathvalid_startup(subdirFullpath, 'dir')
    fprintf('Warning: folder %s doesn''t exist\n', subdirFullpath);
    return;
end

% If current subjdir is in the exclList then go back to curr dir and exit
if isExcluded(subdirFullpath, exclList)
    return;
end

dirs = dir([subdirFullpath, '*']);
if isempty(dirs)
    return;
end

if isdotmfolder(subdirFullpath)
    dotmfolders = {filesepStandard_startup(subdirFullpath, 'nameonly')};
end

for ii = 1:length(dirs)
    if ~dirs(ii).isdir
        continue;
    end
    if dirs(ii).name(1) == '.'
        continue;
    end
    dotmfolders = [dotmfolders; findDotMFolders([subdirFullpath, dirs(ii).name], exclList)]; %#ok<AGROW>
end

% -------------------------------------------------------------------------
function b = isdotmfolder(folder)
global MAXPATHLENGTH
b = false;
if ~ispathvalid_startup(folder, 'dir')
    return
end
if isempty(dir([folder,'/*.m']))
    % Exceptions to rule that 'dotm' folder must have at least one '.m' file:
    % it is a an executable folder (i.e. '/bin')
    if ~isempty(strfind(folder, '/bin/')) %#ok<*STREMP>
        b = true;
        return
    end
    return;
else
    rootdir = which('findDotMFolders');
    rootdir = fileparts(rootdir);
    rootdir = pathsubtract_startup(rootdir, 'Utils/submodules','nochange');
    p = pathsubtract_startup(folder, rootdir);
    if length(find(p=='/')) > MAXPATHLENGTH
        return
    end
end
b = true;

% -------------------------------------------------------------------------
function b = isExcluded(pname, exclList)
b = true;
if pname(end)=='/'
    pname(end) = '';
end
if ~ispathvalid_startup(pname,'dir')
    return;
end
[~,f,e] = fileparts(pname);
for ii = 1:length(exclList)
    [c,d] = str2cell_startup(exclList{ii},'*');
    if isempty(d) && strcmp(c{1}, [f,e])
        return;
    end

    % Get list of all folders matching exclList{ii} pattern, whether it be
    % a single folder name or a wildcard pattern
    for jj = 1:length(c)
        k = strfind(c{jj}, [f,e]);
        if isempty(k)
            break;
        end
    end
    if ~isempty(k)
        return;
    end
end
b = false;


function jsubs = cfg2jobsubs(item, subs)

% function jsubs = cfg2jobsubs(item, subs)
% Return the subscript into the job tree for a given subscript vector into
% the val part of the cfg tree. In a cfg_choice, this is a struct reference
% to a field with the name of the tag of the corresponding child node.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: cfg2jobsubs.m 4867 2012-08-30 13:04:51Z volkmar $

rev = '$Rev: 4867 $'; %#ok

% Only de-reference subscripts into .val{1} field
if isequal(subs(1:2), substruct('.','val','{}',{1}))
    % return possible indices into .val{1} field
    citem = subsref(item, subs(1:2));
    if numel(subs) > 2
        jsubs1 = cfg2jobsubs(citem, subs(3:end));
    else
        jsubs1 = [];
    end;
    jsubs = [substruct('.', gettag(citem)) jsubs1];
else
    cfg_message('matlabbatch:cfg2jobsubs:wrongsubs', 'Inappropriate subscript reference in item ''%s''.', item.tag);
    jsubs = struct('type',{},'subs',{});
end;


function d = cols(X)

warning('This function is deprecated')

d = size(X,2);


%%%%%%%%%%%%%%%%%%%% MRiLab setup%%%%%%%%%%%%%%%%%%%%%%
function MRiLab

    warning off; % disable warning

    [pathstr,name,ext]=fileparts(mfilename('fullpath'));
    addpath(genpath(pathstr));
    % Remove unnessary search path
    rmpath(genpath([pathstr filesep '.git']));
    rmpath(genpath([pathstr filesep 'Doc']));
    % Open MRiLab main panel
    SimuPanel(pathstr);
    clear pathstr name ext
end


classdef prtUiTableEditStructure < prtUiManagerPanel
    % prtUiTableEditStructure
    %

    properties

        enableRowDeletion = 'on';
        enableColumnCreation = 'on';
        dataStructure
        dataCell = {};

        tableFieldNames = {};
        handleStruct

        sortingInds

        fontSizeTable = 8;
        fontSizeEdit = 12;

        editableArray = [];
    end

    methods
        function self = prtUiTableEditStructure(varargin)

            self = prtUtilAssignStringValuePairs(self,varargin{:});

            if nargin == 0
                self.create();
            elseif nargin~=0 && ~self.hgIsValid
               self.create()
            end

            init(self);
        end

        function create(self)
            % Overload the default prtUiManagerPanel
            % This will "create" a bigger figure and turn off toolbars and
            % stuff.

            self.handleStruct.figure = gcf;

            set(self.handleStruct.figure,...
                'Toolbar','none',...
                'MenuBar','none',...
                'Name','prtDataSetSelector',...
                'NumberTitle','off',...
                'WindowStyle','Normal',...
                'DockControls','off');

            if isempty(self.parent)
                self.managedHandle = uipanel(self.handleStruct.figure,...
                    'BackgroundColor',get(0,'DefaultFigureColor'),...
                    'BorderType','none');
            else
                self.managedHandle = uipanel('Parent',self.parent,...
                    'BackgroundColor',get(0,'DefaultFigureColor'),...
                    'BorderType','none');
            end
        end
        function init(self)

            self.handleStruct.table = uitable('parent',self.managedHandle,...
                'units','normalized',...
                'position',[0.05 0.05 0.9 0.8],...
                'fontUnits','points',...
                'fontSize',self.fontSizeTable,...
                'visible','on');
            drawnow;
            self.handleStruct.jScrollPane = findjobj(self.handleStruct.table);
            if ~isempty(self.handleStruct.jScrollPane)
                self.handleStruct.jTable = self.handleStruct.jScrollPane(1).getViewport.getView;
            end
            set(self.handleStruct.table,'visible','on');

            self.handleStruct.tableContextMenu = uicontextmenu;
            self.handleStruct.tableContextMenuItemNewSelection = uimenu(self.handleStruct.tableContextMenu, 'Label', 'Sort By', 'Callback', @(myHandle,eventData)self.sortBy(myHandle,eventData));
            self.handleStruct.tableContextMenuItemAndSelection = uimenu(self.handleStruct.tableContextMenu, 'Label', 'Set Values', 'Callback', @(myHandle,eventData)self.setValues(myHandle,eventData));
            self.handleStruct.tableContextMenuItemOrSelection = uimenu(self.handleStruct.tableContextMenu, 'Label', 'String Search Sort', 'Callback', @(myHandle,eventData)self.sortByStringSearch(myHandle,eventData));
            self.handleStruct.tableContextMenuCreateColumn = uimenu(self.handleStruct.tableContextMenu, 'Label', 'Add Column', 'Callback', @(myHandle,eventData)self.createColumn(myHandle,eventData),'Enable',self.enableColumnCreation,'Separator','on');
            self.handleStruct.tableContextMenuDeleteSelection = uimenu(self.handleStruct.tableContextMenu, 'Label', 'Delete Current Rows', 'Callback', @(myHandle,eventData)self.deleteSelectedRows(myHandle,eventData),'Enable',self.enableRowDeletion);

            %             self.handleStruct.tableContextMenuItemNoSelection = uimenu(self.handleStruct.tableContextMenu, 'Label', 'Remove From Table', 'Callback', @(myHandle,eventData)self.uiMenuNoSelection(myHandle,eventData));
            self.updateDataStructure;
        end

        function updateDataStructureFromGui(self,h,e)

            cellData = get(self.handleStruct.table,'data');

            selected = get(self.handleStruct.table,'UserData');
            if isempty(selected)
                warndlg('No rows selected');
                return;
            end
            selectedRow = selected(1);
            selectedCol = selected(2);

            obsInfo = self.dataStructure;
            obsInfo(self.sortingInds(selectedRow)).(self.tableFieldNames{selectedCol}) = cellData{selectedRow,selectedCol};
            self.dataStructure = obsInfo;

            self.updateDataStructure(obsInfo);
            self.updateTableDisplay;

            jUIScrollPane = findjobj(self.handleStruct.table);
            jUITable = jUIScrollPane.getViewport.getView;
            jUITable.changeSelection(selectedRow,selectedCol-1, false, false);
        end

        function appendDataStructure(self,obsInfo)
            if ~isempty(self.dataStructure)
                self.updateDataStructure(cat(1,obsInfo(:),self.dataStructure(:)));
            else
                self.updateDataStructure(obsInfo(:));
            end
        end

        function updateDataStructure(self,obsInfo)
            if nargin > 1
                obsInfo = obsInfo(:);
                self.dataStructure = obsInfo;
            end
            if ~isempty(self.dataStructure)
                self.tableFieldNames = fieldnames(self.dataStructure(:));
                self.dataCell = struct2cell(self.dataStructure(:))';

                if isempty(self.editableArray)
                    self.editableArray = false(1,size(self.dataCell,2));
                end

                set(self.handleStruct.table,'data',self.dataCell,...
                    'ColumnName',self.tableFieldNames,...
                    'ColumnEditable',self.editableArray,...
                    'ColumnWidth','auto','RearrangeableColumns','off',...
                    'RowStriping','off','RowName',cellstr(num2str((1:size(self.dataCell,1))')),...
                    'uicontextmenu',self.handleStruct.tableContextMenu,...
                    'CellSelectionCallback',@(src,evnt)set(src,'UserData',evnt.Indices),...
                    'CellEditCallback',@(src,event)self.updateDataStructureFromGui(src,event));

                if length(self.sortingInds) ~= numel(self.dataStructure)
                    self.sortingInds = [];
                end
                % I do not think we have to do this
                if isempty(self.sortingInds)
                    self.sortingInds = (1:size(self.dataCell,1))';
                end

                set(self.managedHandle,'ResizeFcn',@self.resizeFunction);
                resizeFunction(self);
                set(self.handleStruct.table,'visible','on');
            else
                set(self.handleStruct.table,'data',[],...
                    'ColumnName',self.tableFieldNames,...
                    'ColumnEditable',self.editableArray,...
                    'ColumnWidth','auto','RearrangeableColumns','off',...
                    'RowStriping','off','RowName',cellstr(num2str((1:size(self.dataCell,1))')),...
                    'uicontextmenu',self.handleStruct.tableContextMenu,...
                    'CellSelectionCallback',@(src,evnt)set(src,'UserData',evnt.Indices),...
                    'CellEditCallback',@(src,event)error('Not implemented'));

                self.sortingInds = [];

                set(self.managedHandle,'ResizeFcn',@self.resizeFunction);
                resizeFunction(self);
                set(self.handleStruct.table,'visible','on');
            end
        end

        function setValues(self,e,s)

            selected = get(self.handleStruct.table,'UserData');
            if isempty(selected)
                warndlg('No rows selected');
                return;
            end
            selectedRows = selected(:,1);

            strs = fieldnames(self.dataStructure);
            strOut = prtUiListDlg(strs);
            selectedColInd = strOut.enteredSelection;
            if isempty(selectedColInd) || selectedColInd == 0;
                warndlg('No field selected');
                return;
            end
            selectedColData = self.dataCell(:,selectedColInd);
            answer = inputdlg(sprintf('Please input a new value for field "%s" in the selected cells',strs{selectedColInd}));
            answer = answer{1};
            if isempty(answer)
                warndlg('No value entered');
                return;
            end
            if isnumeric(selectedColData{1})
                answer = str2double(answer);
                if isempty(answer)
                    warndlg('Improper numeric value provided');
                    return;
                end
            elseif islogical(selectedColData{1})
                answer = logical(str2double(answer));
                if isempty(answer)
                    warndlg('Improper numeric value provided');
                    return;
                end
            elseif isa(selectedColData{1},'char')
                if ~isa(answer,'char');
                    answer = num2str(answer);
                end
            end
            relativeInds = self.sortingInds(selectedRows);
            if ~isempty(answer)
                self.dataCell(relativeInds,selectedColInd) = {answer};
                for i = 1:length(relativeInds)
                    self.dataStructure(relativeInds(i)).(strs{selectedColInd}) = answer;
                end
            end

            self.updateTableDisplay;
        end

        function sortByStringSearch(self,e,s)
            strs = fieldnames(self.dataStructure);
            strOut = prtUiListDlg(strs);
            selectedColInd = strOut.enteredSelection;
            if isempty(selectedColInd) || selectedColInd == 0;
                return;
            end
            sortVecData = self.dataCell(:,selectedColInd);
            if isnumeric(sortVecData{1}) || islogical(sortVecData{1});
                warndlg('Numeric or logical field specified');
                return;
            end
            str = inputdlg('Input a search string, use * for wildcards');
            regexpStr = strrep(lower(str),'*','.*');

            found = regexp(lower(sortVecData),regexpStr);
            sortVecBool = cellfun(@(x)~isempty(x),found);
            [~,inds] = sort(~sortVecBool);
            self.sort(inds);
        end

        function sortBy(self,e,s)
            strs = fieldnames(self.dataStructure);
            strOut = prtUiListDlg(strs);
            selectedColInd = strOut.enteredSelection;
            if isempty(selectedColInd) || selectedColInd == 0;
                return;
            end
            sortVec = self.dataCell(:,selectedColInd);
            if isnumeric(sortVec{1}) || islogical(sortVec{1});
                sortVec = cat(1,sortVec{:});
            end
            [~,inds] = sort(sortVec);
            self.sort(inds);
        end

        function createColumn(self,h,e)

            answer=inputdlg('Enter a name for the new column','New Column Name');
            if isempty(answer)
                return;
            end
            varName = genvarname(answer{1});
            obsInfo = self.dataStructure;
            if isfield(obsInfo,varName);
                h = errordlg('%s is already a field of the database');
                uiwait(h);
                return
            end

            ButtonName = questdlg('Add a numeric or character?', ...
                'Numeric or Character', ...
                'Numeric', 'Character','Numeric');

            switch ButtonName
                case 'Numeric'
                    vals = repmat({nan},size(obsInfo));
                otherwise
                    vals = repmat({''},size(obsInfo));
            end
            for i = 1:length(obsInfo)
                obsInfo(i).(varName) = vals{i};
            end

            self.editableArray = [self.editableArray,true];
            self.updateDataStructure(obsInfo);
            self.updateTableDisplay;
        end

        function deleteSelectedRows(self,h,e,force)

            if nargin < 4
                force = false;
            end
            if ~force
                ButtonName = questdlg('Remove selected rows from database?', ...
                    'Clear Current?', ...
                    'Yes, erase', 'No, go back','No, go back');
            else
                ButtonName = 'Yes, erase';
            end
            switch ButtonName
                case '';
                    return;
                case 'No, go back'
                    return;
                otherwise

                    selected = get(self.handleStruct.table,'UserData');
                    if isempty(selected)
                        warndlg('No rows selected');
                        return;
                    end
                    selectedRowsUnsorted = selected(:,1);
                    selectedRows = self.sortingInds(selectedRowsUnsorted);
                    selectedBool = false(size(self.dataStructure));
                    selectedBool(selectedRows) = true;
                    selectedBoolUnsorted = false(size(self.dataStructure));
                    selectedBoolUnsorted(selectedRowsUnsorted) = true;

                    obsInfo = self.dataStructure(~selectedBool);
                    [~,~,ic] = unique(self.sortingInds(~selectedBoolUnsorted));
                    self.sortingInds = ic;

                    self.updateDataStructure(obsInfo);
                    self.updateTableDisplay;
            end
        end

        function sort(self,inds)
            self.sortingInds = inds;
            self.updateTableDisplay;
        end

        function resizeFunction(self,varargin)

            rowHeightInPixels = self.fontSizeEdit*2; % A decent rule of thumb for edit boxes?
            %border = max(rowHeightInPixels/8,1); % A decent rule of thumb ?
            border = 0;

            parentPosPixels = getpixelposition(self.managedHandle);
            parentHeight = parentPosPixels(4);
            parentWidth = parentPosPixels(3);

            editPos = [1 parentHeight-rowHeightInPixels, parentWidth, rowHeightInPixels];

            % Re-adjust height of the uitable
            tableTopPixels = editPos(2)-border;
            tablePos = [1 1 parentWidth tableTopPixels-1];

            % Set everything
            set(self.handleStruct.table,'units','pixels'); % Reset below
            set(self.handleStruct.table,'position',tablePos);
            set(self.handleStruct.table,'units','normalized');
        end

        function updateTableDisplay(self)
            set(self.handleStruct.table,'Data',self.dataCell(self.sortingInds,:));
        end
    end
end


% UIGETFILE2 - same as uigetfile but remember folder location.
%
% Usage: >> uigetfile2(...)
%
% Inputs: Same as uigetfile
%
% Author: Arnaud Delorme & Hilit Serby, Scott Makeig, SCCN, UCSD, 2004
%         Thanks to input from Bas Kortmann
%
% Copyright (C) Arnaud Delorme & Hilit Serby, Scott Makeig, SCCN, UCSD, 2004

% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

function varargout = uigetfile2(varargin);
mlock
persistent tmp_fld

if nargin < 1
    help uigetfile2;
    return;
end;

% remember old folder
olddir = pwd;
try
    eeglab_options;
    if option_rememberfolder
        if isempty(tmp_fld)
            tmp_fld = getpref('eeglab','lastdir',olddir);
        end
        cd(tmp_fld);
    end
end

%% Show the open dialog and save the latest directory to the file
% ---------------------------------------------------------------
[varargout{1} varargout{2}] = uigetfile(varargin{:});
try
    if option_rememberfolder
        if ischar(varargout{1})
            tmp_fld = varargout{2};
            setpref('eeglab','lastdir',tmp_fld);
        end
    end
end
cd(olddir)


function files=cosmo_dir(varargin)
% list files recursively in a directory
%
% files=cosmo_dir([directory][,file_pattern])
%
% Inputs:
%   directory      optional parent directory to look for files. If omitted
%                  the current directory is used.
%   file_pattern   optional pattern to match file names. The wildcards '*'
%                  (zero or more of any character) and '?' (any single
%                  character) can be used. If omitted, '*' is used, meaning
%                  that all files are listed. A file pattern may be
%                  prefixed by a directory.
% Output:
%   files          Px1 struct (if P files were found in the directory or
%                  recursively in any (sub^X)-directorie) with fields
%                  .name, .date, .bytes, .isdir, .datenum. Unlike the
%                  built-in 'dir' function, .name contains the path and
%                  filename.
%
% Notes:
%  - the output is similar to built-in 'dir', except that .name contains
%    the path of the files as well.
%  - to list files in a directory but not those in its subdirectories, use
%    the built-in 'dir' function.
%  - this function does not return '.' (current directory) or '..' (parent
%    directory.
%
% Examples:
%  % list recursively all files in the current directory
%  d=cosmo_dir();
%
%  % Assuming that the directory 'my_dir' exists, list recursively all
%  % files the directory contains
%  d=cosmo_dir('my_dir');
%
%  % Assuming that the directory 'my_file' does not exist, return
%  % either a struct with a single entry (if a file named 'my_file'
%  % exists), or an emtpy struct (if no such file exists)
%  d=cosmo_dir('my_file');%
%
%  % list recursively all files in the current directory for which the name
%  % ends with '.jpg'
%  d=cosmo_dir('*.jpg')
%
%  % list recursively all files in the directory 'my_dir' with extension
%  % '.jpg'
%  d=cosmo_dir('my_dir', '*.jpg')
%
%  % as above but with a single argument; list recursively all files in
%  % the directory 'my_dir' with extension '.jpg'
%  d=cosmo_dir('my_dir/*.jpg')
%
%  % list recursively all files in my_dir that are two characters long,
%  % followed by the extension '.jpg'
%  d=cosmo_dir('my_dir', '??.jpg')
%
%  % list recursively all files in my_dir that start with 'a', followed by
%  % any character, followed by 'b', followed by any number of characters,
%  % followed by '.jpg'
%  d=cosmo_dir('my_dir', 'a?b*.jpg')
%
% See also: dir
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #

    [root_dir,file_pat]=process_arguments(varargin{:});

    file_re=['^' ... % start of the string
             regexptranslate('wildcard',file_pat) ...
             '$'];   % end of the string

    files=find_files_recursively(root_dir,file_re);

function [root_dir,file_pat]=process_arguments(varargin)
    narg=numel(varargin);
    if narg>2
        error('need at most two arguments');
    end

    if ~iscellstr(varargin)
        error('arguments must be strings');
    end

    root_dir='';
    file_pat='*';

    if narg>=1
        arg1=varargin{1};
        if isdir(arg1)
            root_dir=arg1;
            if narg>=2
                file_pat=varargin{2};
            end
        else
            if narg>=2
                error('Directory not found: ''%s''', arg1);
            end
            [root_dir,nm,ext]=fileparts(arg1);
            file_pat=[nm ext];
        end
    end

function res=find_files_recursively(root_dir,file_re)
    if isempty(root_dir)
        dir_arg={};
    else
        dir_arg={root_dir};
    end

    d=dir(dir_arg{:});
    n=numel(d);

    res_cell=cell(n,1);
    for k=1:n
        d_k=d(k);
        fn=d_k.name;

        % do not return current and parent directorys
        ignore_fn=strcmp(fn,'.') || strcmp(fn,'..');

        if ~ignore_fn
            path_fn=fullfile(root_dir, fn);

            if isdir(path_fn)
                % recursive call
                res=find_files_recursively(path_fn,file_re);

            elseif ~isempty(regexp(fn,file_re,'once'))
                % file matches the pattern
                d_k.name=path_fn;
                res=d_k;

            else
                % ignore file
                continue;
            end

            if ~isempty(res)
                res_cell{k}=res;
            end
        end
    end

    keep_msk=~cellfun(@isempty,res_cell);

    if any(keep_msk)
        % at least one file found
        res_keep=res_cell(keep_msk);
        res=cat(1,res_keep{:});
    else
        % no files found, return empty struct
        if cosmo_wtf('is_octave')
            labels={'name','date','bytes','isdir',...
                        'datenum','statinfo'};
        else
            labels={'name','date','bytes','isdir',...
                        'datenum'};
        end
        n_labels=numel(labels);
        res=cell2struct(cell(n_labels,0),labels);
    end


function tapas_physio_save_batch_mfile(matlabbatch, fileBatchM, ...
    doRemoveEmptyDefaults)
% Saves created matlabbatch variable to .m-file for later call of
% spm_jobman or run(fileBatchM)
%
%    tapas_physio_save_batch_mfile.m(matlabbatch, fileBatchM)
%
% IN
%   matlabbatch     variable from workspace
%   fileBatchM      m-file that we save to
%   doRemoveEmptyDefaults
%                   if true, all lines in the batch that have empty
%                   (default) values will be removed
%                   default: false
%
% OUT
%
% EXAMPLE
%   tapas_physio_save_batch_mfile.m
%
%   See also

% Author:   Lars Kasper
% Created:  2022-03-30
% Copyright (C) 2022 TNU, Institute for Biomedical Engineering,
%                    University of Zurich and ETH Zurich.
%
% This file is part of the TAPAS PhysIO Toolbox, which is released under
% the terms of the GNU General Public License (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/>.

if nargin < 3
    doRemoveEmptyDefaults = false;
end

str = gencode(matlabbatch)';

if doRemoveEmptyDefaults
    indLineRemove = tapas_physio_find_string(str, ...
        {'= \[\];', '= {};', '= {''''};', '= '''';'});
    indLineRemove = cell2mat(indLineRemove);
    str(indLineRemove) = [];
end

nLines = numel(str);
fid = fopen(fileBatchM, 'w+');

for iLine = 1:nLines
    fprintf(fid, '%s\n', str{iLine});
end
fclose(fid);


function addCOBRABinaryPathToSystemPath()
% Sets up the path to system executables shipped by the toolbox.
%
% USAGE:
%     addCOBRABinaryPathToSystemPath()
%

global CBTDIR

arch = computer('arch');

%Set thefolders
binaryDir = [CBTDIR filesep 'binary' filesep arch filesep 'bin'];
libDir = [CBTDIR filesep 'binary' filesep arch filesep 'lib'];

%get all Subfolders
bindirs = rdir([binaryDir filesep '**' filesep '*']);
libdirs = rdir([libDir filesep '**' filesep '*']);
binnames = {bindirs.name};
libnames = {libdirs.name};
bindirs = [{binaryDir},binnames([bindirs.isdir])]; %Add all subdirectories and the top level
libdirs = [{libDir},libnames([libdirs.isdir])];

if ispc
    setenv('Path', [getenv('Path') ';' strjoin(union(bindirs,libdirs),';')  ]);
else
    setenv('PATH', [getenv('PATH') ':' strjoin(bindirs,':')]);
    setenv('LD_LIBRARY_PATH', [getenv('LD_LIBRARY_PATH') ':' strjoin(libdirs,':')]);
end

end


function slwritetext(T, filename)
%SLWRITETEXT Writes a text to file
%
% $ Syntax $
%   - slwritetext(T, filename)
%
% $ Arguments $
%   - T             the cell array representing the text
%   - filename      the path of the file to write to
%
% $ Description $
%   - slwritetext(T, filename) Writes in a text file stored in a cell array
%   to a text file specified by filename.
%
% $ History $
%   Created by Dahua Lin, on 2005-06-02
%

if ~iscell(T)
    error('T should be a text cell array');
end
fid = fopen(filename, 'w');
if (fid <= 0)
    error(['Fail to open ', filename]);
end

n = length(T);
for i = 1 : n
    fprintf(fid, '%s\r\n', T{i});
end

fclose(fid);


%Save_Figure_Script

%Variables that must be defined in the workspace:
% P
% iterationNum
%

%Now, save the figure if desired:
if P.disp.saveIntermediatePlots
   BaseName = ['MS_Fig_Iter_' num2str(iterationNum)];
   FigureName = [BaseName '.pdf'];
   DirName = 'img/';  %Which subdirectory are the images in?

   % %Force Figure Location (Good for extracting figures -> LaTeX)
   set(gcf,'position',800*[0,0,2,1])

   %This is a magical function that I got on file exchange
   %This should not be so hard to do in Matlab...
   save2pdf(FigureName,gcf,400)

   %Now, create the latex code if desired:
   if P.disp.createTex
       FileName = P.disp.TexFileName;
       fid = fopen(FileName,'a');  %Open file for appending
        fprintf(fid,'\n');
        fprintf(fid,'\\begin{figure} \n');
        fprintf(fid,'    \\centering \n');
        fprintf(fid,['    \\includegraphics[width = \\columnwidth]{' DirName FigureName '}    \n']);
        fprintf(fid,'    \\caption{}     \n');
        fprintf(fid,['    \\label{fig: ' BaseName '}     \n']);
        fprintf(fid,'\\end{figure} \n');
        fclose(fid);
   end
end


function submitWithConfiguration(conf)
  addpath('./lib/jsonlab');

  parts = parts(conf);

  fprintf('== Submitting solutions | %s...\n', conf.itemName);

  tokenFile = 'token.mat';
  if exist(tokenFile, 'file')
    load(tokenFile);
    [email token] = promptToken(email, token, tokenFile);
  else
    [email token] = promptToken('', '', tokenFile);
  end

  if isempty(token)
    fprintf('!! Submission Cancelled\n');
    return
  end

  try
    response = submitParts(conf, email, token, parts);
  catch
    e = lasterror();
    fprintf( ...
      '!! Submission failed: unexpected error: %s\n', ...
      e.message);
    fprintf('!! Please try again later.\n');
    return
  end

  if isfield(response, 'errorMessage')
    fprintf('!! Submission failed: %s\n', response.errorMessage);
  else
    showFeedback(parts, response);
    save(tokenFile, 'email', 'token');
  end
end

function [email token] = promptToken(email, existingToken, tokenFile)
  if (~isempty(email) && ~isempty(existingToken))
    prompt = sprintf( ...
      'Use token from last successful submission (%s)? (Y/n): ', ...
      email);
    reenter = input(prompt, 's');

    if (isempty(reenter) || reenter(1) == 'Y' || reenter(1) == 'y')
      token = existingToken;
      return;
    else
      delete(tokenFile);
    end
  end
  email = input('Login (email address): ', 's');
  token = input('Token: ', 's');
end

function isValid = isValidPartOptionIndex(partOptions, i)
  isValid = (~isempty(i)) && (1 <= i) && (i <= numel(partOptions));
end

function response = submitParts(conf, email, token, parts)
  body = makePostBody(conf, email, token, parts);
  submissionUrl = submissionUrl();
  params = {'jsonBody', body};
  responseBody = urlread(submissionUrl, 'post', params);
  response = loadjson(responseBody);
end

function body = makePostBody(conf, email, token, parts)
  bodyStruct.assignmentSlug = conf.assignmentSlug;
  bodyStruct.submitterEmail = email;
  bodyStruct.secret = token;
  bodyStruct.parts = makePartsStruct(conf, parts);

  opt.Compact = 1;
  body = savejson('', bodyStruct, opt);
end

function partsStruct = makePartsStruct(conf, parts)
  for part = parts
    partId = part{:}.id;
    fieldName = makeValidFieldName(partId);
    outputStruct.output = conf.output(partId);
    partsStruct.(fieldName) = outputStruct;
  end
end

function [parts] = parts(conf)
  parts = {};
  for partArray = conf.partArrays
    part.id = partArray{:}{1};
    part.sourceFiles = partArray{:}{2};
    part.name = partArray{:}{3};
    parts{end + 1} = part;
  end
end

function showFeedback(parts, response)
  fprintf('== \n');
  fprintf('== %43s | %9s | %-s\n', 'Part Name', 'Score', 'Feedback');
  fprintf('== %43s | %9s | %-s\n', '---------', '-----', '--------');
  for part = parts
    score = '';
    partFeedback = '';
    partFeedback = response.partFeedbacks.(makeValidFieldName(part{:}.id));
    partEvaluation = response.partEvaluations.(makeValidFieldName(part{:}.id));
    score = sprintf('%d / %3d', partEvaluation.score, partEvaluation.maxScore);
    fprintf('== %43s | %9s | %-s\n', part{:}.name, score, partFeedback);
  end
  evaluation = response.evaluation;
  totalScore = sprintf('%d / %d', evaluation.score, evaluation.maxScore);
  fprintf('==                                   --------------------------------\n');
  fprintf('== %43s | %9s | %-s\n', '', totalScore, '');
  fprintf('== \n');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Service configuration
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function submissionUrl = submissionUrl()
  submissionUrl = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1';
end


function write_sicd_security_tags(obj)
%WRITE_SICD_SECURITY_TAGS Writes the NITF security tags
%
% It's not expected that the typical user would call this function, rather
% it is called as part of a bigger NITF/SICD writer.
%
% Inputs:
%       obj:       This is the 'hidden' object-specific handle.  It is
%                  similar to 'this' in Java.
%
% References:
%       MIL-STD-2500C, Department of Defense Interface Standard
%                      National Imagery Transmission Format version 2.1
%                      01 May 2006
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

% Security is limited in the SICD XML structure.  Without explicit tags
% passed, we make a guess from XML and fill in what we can.
if isfield(obj.sicdmeta,'CollectionInfo') && ...
        isfield(obj.sicdmeta.CollectionInfo,'Classification')&& ...
        ~isempty(obj.sicdmeta.CollectionInfo.Classification)
    classification = obj.sicdmeta.CollectionInfo.Classification;
else
    classification = ' ';
end
codes = strsplit(classification,'/');  % Cell array
codes = strjoin(cellfun(@(x) x(1:min(2,end)), codes(2:end), 'UniformOutput', false));

% Tag name, field length, default value
tag_info = { ...
    'CLAS', 1, classification(1); ...
    'CLSY', 2, 'US'; ...
    'CODE', 11, codes; ...
    'CTLH', 2, ''; ...
    'REL', 20, ''; ...
    'DCTP', 2, ''; ...
    'DCDT', 8, ''; ...
    'DCXM', 4, ''; ...
    'DG', 1, ''; ...
    'DGDT', 8, ''; ...
    'CLTX', 43, ''; ...
    'CATP', 1, ''; ...
    'CAUT', 40, ''; ...
    'CRSN', 1, ''; ...
    'SRDT', 8, ''; ...
    'CTLN', 15, ''};

if isfield(obj.sicdmeta,'NITF') && isfield(obj.sicdmeta.NITF,'security')
    sec_tags = obj.sicdmeta.NITF.security;
else
    sec_tags = struct();
end

for i=1:size(tag_info,1)
    if isfield(sec_tags, tag_info{i,1})
        fwriten(obj.FID, sec_tags.(tag_info{i,1}), tag_info{i,2});
    else
        fwriten(obj.FID, tag_info{i,3}, tag_info{i,2});
    end
end

end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////


function setup_paths()

% Add the neccesary paths

[pathstr, name, ext] = fileparts(mfilename('fullpath'));

% Tracker implementation
addpath(genpath([pathstr '/implementation/']));

% Runfiles
addpath([pathstr '/runfiles/']);

% Utilities
addpath([pathstr '/utils/']);

% The feature extraction
addpath(genpath([pathstr '/feature_extraction/']));

% Matconvnet
addpath([pathstr '/external_libs/matconvnet/matlab/mex/']);
addpath([pathstr '/external_libs/matconvnet/matlab']);
addpath([pathstr '/external_libs/matconvnet/matlab/simplenn']);

% PDollar toolbox
addpath(genpath([pathstr '/external_libs/pdollar_toolbox/channels']));

% Mtimesx
addpath([pathstr '/external_libs/mtimesx/']);

% mexResize
addpath([pathstr '/external_libs/mexResize/']);


% APM Input Measured Value
%
% response = apm_meas(server,app,name,value)
%
% Function apm_meas sends a measurement to the APM server
%   with the following arguments:
%
%   server = address of server
%      app = application name
%     name = parameter or variable name
%    value = measurement value
%
% A response is returned indicating whether the measurement
%   was successfully recorded
%
function response = apm_meas(server,app,name,value)

    % Web-server URL base
    app = lower(deblank(app));
    name = strcat(name,'.meas');
    params = ['?p=' urlencode(app) '&n=' urlencode(name) '&v=' urlencode(num2str(value))];
    url = [deblank(server) '/online/meas.php' params];

    % Send request to web-server
    response = urlread_apm(url);


function [filename, pathname] = myUiGetFile(browseDir, varargin)
%
% [filename, pathname] = myUiGetFile(browseDir, varargin)
%
% Wrapper for uigetfile. Will start browsing at 'browseDir' instead of pwd.
% The rest of the input args should be the normal arguments to uigetfile (see 'help uigetfile').
%
% HISTORY:
% 2002.03.05 RFD (bob@white.stanford.edu): wrote it.
% 2009.04.29 RAS: allows MultiSelect.
%
% Example:
%
% [fileName,inputGrayPath]=myUiGetFile(get(handles.inputGrayPath,'String'),'*.?ray','Get gray file');
% [fileName,inputGrayPath]=myUiGetFile(inputGrayPath,'*.?ray','Get gray file');
% [fileName,inputGrayPath]=myUiGetFile(inputGrayPath,{'*.?ray','.class'},'Gray or mesh file');
%

curDir = pwd;
if(~exist('browseDir','var')), browseDir = curDir; end

% We're slightly clever- if the browseDir is not a dir, go up one level.
% This lets us pass in a file, and browse the file's dir.
if(~exist(browseDir,'dir'))
    browseDir = fileparts(browseDir);
    if(~exist(browseDir,'dir')), browseDir = pwd; end
end

cd(browseDir);
if(~exist('varargin','var') || isempty(varargin))
    [filename, pathname] = uigetfile('multiselect', 'on');
else
    [filename, pathname] = uigetfile(varargin{:}, 'multiselect', 'on');
end
cd(curDir);

return;


function x = double( v ) %#ok
cvx_throw( 'Disciplined convex programming error:\n   Constraints may not appear in if/then statements.' );

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function CHECK_FILE_EXIST(filename)

if exist(filename, 'file') == 0
  error('%s does not exist', filename);
end

end


function pgs(hf)
ss2=get(hf,'UserData');
status=ss2(1);
status2=ss2(2);

ssz=get(0,'ScreenSize');

set(status,'FontUnits','points','FontSize',8*ssz(4)/768);
set(status2,'FontUnits','points','FontSize',8*ssz(4)/768);
drawnow;
pagesetupdlg(hf);

set(status,'FontUnits','points','FontSize',10*ssz(4)/768);
set(status2,'FontUnits','points','FontSize',10*ssz(4)/768);


function rts_retrieveNumDbls(~, ~,tcpipClient)
%UNTITLED Summary of this function goes here
%   Detailed explanation goes here

   	rts_retrieveDataAndStore(tcpipClient, 7, 'd');
end


function jsubs = cfg2jobsubs(item, subs)

% function jsubs = cfg2jobsubs(item, subs)
% Return the subscript into the job tree for a given subscript vector into
% the val part of the cfg tree. In a cfg_branch, this is a struct reference
% to a field with the name of the tag of the corresponding child node.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: cfg2jobsubs.m 1862 2008-06-30 14:12:49Z volkmar $

rev = '$Rev: 1862 $'; %#ok

% Only de-reference subscripts into .val{x} field
if isequal(subs(1), substruct('.','val')) && strcmp(subs(2).type, '{}')
    % return possible indices into .val{1} field
    citem = subsref(item, subs(1:2));
    if numel(subs) > 2
        jsubs1 = cfg2jobsubs(citem, subs(3:end));
    else
        jsubs1 = [];
    end;
    jsubs = [substruct('.', gettag(citem)) jsubs1];
else
    cfg_message('matlabbatch:cfg2jobsubs:wrongsubs', 'Inappropriate subscript reference in item ''%s''.', item.tag);
    jsubs = struct('type',{},'subs',{});
end;


% % This file is part of the project NILM-Eval (https://github.com/beckel/nilm-eval).
% % Licence: GPL 2.0 (http://www.gnu.org/licenses/gpl-2.0.html)
% % Copyright: ETH Zurich, 2014
% % Author: Romano Cicchetti
%
% function create_configuration()
%
%     algorithm = 'weiss';
%     configuration = 'initial';
%
%     % create a new default configuration
%
%     % load default values in yaml file
%     yaml_file = strcat('input/default_values/', algorithm, '.yaml');
%     default = ReadYaml(yaml_file);
%
%     % set default values
%     field_names = fieldnames(default);
%     for field_name = field_names'
%         default.(field_name{1}) = cell2mat(default.(field_name{1}));
%     end
%
%     % save default values in matlab file and a new yaml file
%     path_to_configuration = strcat('input/autogen/configurations/', algorithm, '_', configuration);
%     if ~exist(path_to_configuration, 'dir')
%         mkdir(path_to_configuration);
%     end
%     save(strcat(path_to_configuration, '/default_values.mat'), 'default');
%     copyfile(yaml_file, strcat(path_to_configuration, '/default_values.yaml'));
%
% end


function testFoobar
%testFoobar Passing M-file test

%   Steven L. Eddins
%   Copyright 2008 The MathWorks, Inc.


function planC = importDICOM(source,destn,recursiveFlag)
% function importDICOM(source,destn)
%
% Function to import DICOM from source and write CERR file to destn.
%
% APA, 8/14/2018

if ~exist('recursiveFlag','var')
    recursiveFlag = false;
end

zipFlag = 'No';

% % Define file and directory filter patterns
% fileFilterC = {'scout','corTmp','sag','report','_nac','mip',...
%     'coronal','sagittal','screen_save'};
% dirFilterC = {'ot'};

% Get all directories and files
tic,
[filesInCurDir,dirsInCurDir] = rdir(source);
toc

% Convert to lower case
dirsToImportC = lower({dirsInCurDir.fullpath});
if isempty(dirsToImportC)
    dirsToImportC = {source};
end

% filter directories containing no files
indV1 = false(1,length(dirsToImportC));
tic,
for dirNum = 1:length(dirsToImportC)
    dirS = dir(dirsToImportC{dirNum});
    if ~all([dirS.isdir])
        indV1(dirNum) = 1;
    end
end
toc
dirsToImportC = dirsToImportC(indV1);

%% Import DICOM to CERR
% Read options file
pathStr = getCERRPath;
optName = [pathStr,'CERROptions.json'];
optS = opts4Exe(optName);

% Import all the dirs
for dirNum = 1:length(dirsToImportC)
    try
        init_ML_DICOM
        %hWaitbar = waitbar(0,'Scanning Directory Please wait...');
        sourceDir = dirsToImportC{dirNum};
        %patient = scandir_mldcm_babs(sourceDir, hWaitbar, 1);
        excludePixelDataFlag = true;
        patient = scandir_mldcm(sourceDir, excludePixelDataFlag, recursiveFlag);
        %close(hWaitbar);
        dcmdirS = struct(['patient_' num2str(1)],patient.PATIENT(1));
        for j = 2:length(patient.PATIENT)
            dcmdirS.(['patient_' num2str(j)]) = patient.PATIENT(j);
        end
        patNameC = fieldnames(dcmdirS);
        mergeScansFlag = 'No';
        combinedDcmdirS = struct('STUDY',dcmdirS.(patNameC{1}).STUDY);
        combinedDcmdirS = struct('STUDY',dcmdirS.(patNameC{1}).STUDY,'info',dcmdirS.(patNameC{1}).info);
        for i = 2:length(patNameC)
            for j = 1:length(dcmdirS.(patNameC{i}).STUDY.SERIES)
                combinedDcmdirS.STUDY.SERIES(end+1) = ...
                    dcmdirS.(patNameC{i}).STUDY.SERIES(j);
            end
        end
        % Pass the java dicom structures to function to create CERR plan
        try
            planC = dcmdir2planC(combinedDcmdirS,mergeScansFlag,optS);
        end

        indexS = planC{end};

        % build the filename for storing planC
        if sourceDir(end) == filesep
            [~,folderNam] = fileparts(sourceDir(1:end-1));
        else
            [~,folderNam] = fileparts(sourceDir);
        end

        %mrn = planC{indexS.scan}(1).scanInfo(1).DICOMHeaders.PatientID;
        %studyDscr = planC{indexS.scan}(1).scanInfo(1).DICOMHeaders.StudyDescription;
        %seriesDscr = planC{indexS.scan}(1).scanInfo(1).DICOMHeaders.SeriesDescription;
        %modality = planC{indexS.scan}(1).scanInfo(1).DICOMHeaders.Modality;
        % outFileName = [mrn,'~',studyDscr,'~',seriesDscr,'~',modality];

        outFileName = folderNam;

        %outFileName = mrn;   % store file names as MRNs

        %[~,outFileName] = fileparts(sourceDir);  % store file names as DICOM directory names
        %fullOutFileName = fullfile(destn,fileName);

        %Check for duplicate name of fullOutFileName
        if exist('destn','var') && ~isempty(destn)
            dirOut = dir(destn);
            allOutNames = {dirOut.name};
            if any(strcmpi([outFileName,'.mat'],allOutNames))
                fullOutFileName = [outFileName,'_duplicate_',num2str(rand(1))];
            end
            if strcmpi(zipFlag,'Yes')
                saved_fullFileName = fullfile(destn,[outFileName,'.mat.bz2']);
            else
                saved_fullFileName = fullfile(destn,[outFileName,'.mat']);
            end

            if ~exist(fileparts(saved_fullFileName),'dir')
                mkdir(fileparts(saved_fullFileName))
            end
            save_planC(planC,[], 'passed', saved_fullFileName);
        end

    catch

        disp(['Cannot convert ',source])

    end
end


function jsubs = cfg2jobsubs(item, subs)

% function jsubs = cfg2jobsubs(item, subs)
% Return the subscript into the job tree for a given subscript vector into
% the val part of the cfg tree. In a cfg_choice, this is a struct reference
% to a field with the name of the tag of the corresponding child node.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: cfg2jobsubs.m 1862 2008-06-30 14:12:49Z volkmar $

rev = '$Rev: 1862 $'; %#ok

% Only de-reference subscripts into .val{1} field
if isequal(subs(1:2), substruct('.','val','{}',{1}))
    % return possible indices into .val{1} field
    citem = subsref(item, subs(1:2));
    if numel(subs) > 2
        jsubs1 = cfg2jobsubs(citem, subs(3:end));
    else
        jsubs1 = [];
    end;
    jsubs = [substruct('.', gettag(citem)) jsubs1];
else
    cfg_message('matlabbatch:cfg2jobsubs:wrongsubs', 'Inappropriate subscript reference in item ''%s''.', item.tag);
    jsubs = struct('type',{},'subs',{});
end;


function varargout = get(tpl,action,varargin)
%TEMPLATE/GET Access data stored in a Template object
%  TPL = GET(TPL,ACTION,VARARGIN)
%     ACTION 'var'
%     ACTION 'undefined'

%  Copyright (C) 2003 Guillaume Flandin <Guillaume@artefact.tk>
%  $Revision: 1.0 $Date: 2003/05/05 22:19:51 $

narginchk(2,3);

switch lower(action)
	case 'var'
		narginchk(2,3);
		if nargin == 2
			varargout{1} = tpl.varvals;
		elseif iscellstr(varargin{1})
			varargout{1} = {};
			for i=1:length(varargin{1})
				key = find(ismember(tpl.varkeys,varargin{1}{i}));
				if isempty(key)
					%error('[Template] No such variable name.');
					varargout{1}{end+1} = '';
				else
					varargout{1}{end+1} = tpl.varvals{key};
				end
			end
		elseif ischar(varargin{1})
			varargout{1} = char(get(tpl,'var',cellstr(varargin{1})));
		else
			varargout{1} = '';
		end
	case 'undefined'
    narginchk(3,3);
		tpl = loadtpl(tpl,varargin{1});
		str = get(tpl,'var',varargin{1});
		varargout{1} = {};

		%%%%%%%%%%%%%%%%%%%%%%%% WIH REGEXP ONLY %%%%%%%%%%%%%%%%%%%%
		% [b, e] = regexp(str,'{[^ \t\r\n}]+}');
		% for i=1:length(b)
		% 	if ~any(ismember(tpl.varkeys,str(b(i)+1:e(i)-1)))
		% 		varargout{1}{end+1} = str(b(i)+1:e(i)-1);
		%	end
		% end
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	otherwise
		varargout{1} = finish(get(tpl,'var',action),tpl.unknowns);
end


function writeFiberSelection (sel, filename)

% function writeFiberSelection (sel, filename)
% Author: DA

fid = fopen (filename, 'wb');

fwrite (fid, length(sel.selected), 'uint');
fwrite (fid, sel.selected, 'uint');

fclose(fid);


function [v, xml] = loadXML(filename)
%
% Reads a XML file and produces a struct array.
%
% filename = name of the XML file
% v = struct variable containing fields of type char or numeric
%
% filename can also be an URL containing XML

% Read file
if ~strcmp(filename(1:5), 'http:');
    [fid, message] = fopen(filename,'r');
    if fid == -1; error(message); end
    xml = fread(fid, 'uint8=>char');
    fclose(fid);
else
    filename = strrep(filename, '\', '/');
    status =0; trying=0;
    while status == 0
        [xml,status] = urlread(filename,'Timeout',5);
        if status == 0
            trying=1;
            disp(sprintf('Warning: Failure reading %s. Trying again...',filename))
            drawnow
        end
    end
    if trying==1
        disp(sprintf('Ok: Success reading %s',filename))
    end
end

% Remove 'new line' characters from the chain
xml = char(xml(:)');
xml = strrep(xml, char(10), '');
xml = strrep(xml, char(13), '');

%v = xml2struct(xml);
v = xmlparse(xml);


classdef ECGtask_heartbeat_classifier < ECGtask

% ECGtask for ECGwrapper (for Matlab)
% ---------------------------------
%
% Description:
%
% Abstract class for defining ECGtask interface
%
%
% Author: Mariano Llamedo Soria (llamedom at frba.utn.edu.ar)
% Version: 0.1 beta
% Birthdate  : 18/2/2013
% Last update: 18/2/2013

    properties(GetAccess = public, Constant)
        name = 'ECG_heartbeat_classifier';
        target_units = 'ADCu';
        doPayload = true;
    end

    properties( GetAccess = public, SetAccess = private)
        % if user = memory;
        % memory_constant is the fraction respect to user.MaxPossibleArrayBytes
        % which determines the maximum input data size.
        memory_constant = 0.3;

        started = false;

    end

    properties( Access = private, Constant)

        fig_hdl = 1;
        cKnownModesOfOperation = {'auto' 'slightly-assisted', 'assisted'};

    end

    properties( Access = private )

    end

    properties

        progress_handle
        payload
        mode
        tmp_path

        % minimum amount of heartbeats required
        min_heartbeats_required = 500;
        % maximum amount of heartbeats to process each iteration
        max_heartbeats_per_iter = 4000;

    end

    methods

        function obj = ECGtask_heartbeat_classifier(obj)

            if( isempty(obj.mode) )
                obj.mode = obj.cKnownModesOfOperation{1};
            end

        end

        function Start(obj, ECG_header, ECG_annotations)

            if( ECG_header.nsig == 1 )
                disp_string_framed(2, 'The classifier was not developed for single lead signals.');
                return
            end

            lead_idx = get_ECG_idx_from_header(ECG_header);

            if( length(lead_idx) <= 1 )
                disp_string_framed(2, 'The classifier was not developed for single lead signals.');
                return
            end

            if(( isfield(ECG_annotations, 'time') && ~isempty(ECG_annotations.time)) )
                obj.started = true;
            else

                % payload property is used in this task to input an external QRS
                % detector, or manually corrected detections.
                aux_val = get_QRS_from_payload(obj.payload);

                if(~isempty(aux_val) && length(aux_val.time) > obj.min_heartbeats_required )
                    obj.started = true;
                else
                    warning('ECGtask_HB_classifier:BadPayload', 'Not enough heartbeats to perform classification. Try decreasing "min_heartbeats_required" or increasing the amount of heartbeats.\n');
                end
            end

        end

        function payload_out = Process(obj, ECG, ECG_start_offset, ECG_sample_start_end_idx, ECG_header, ECG_annotations, ECG_annotations_start_end_idx )

            payload_out = [];

            if( ~obj.started )
                obj.Start(ECG_header);
                if( ~obj.started )
                    cprintf('*[1,0.5,0]', 'Task %s unable to be started for %s.\n', obj.name, ECG_header.recname);
                    return
                end
            end

            % payload property is used in this task to input an external QRS
            % detector, or manually corrected detections.
            aux_QRS_loc = get_QRS_from_payload(obj.payload, ECG_start_offset, ECG_sample_start_end_idx);

            if(isempty(aux_QRS_loc))
                annotations_used = ECG_annotations;
            else
                annotations_used = aux_QRS_loc;
            end

%             aux_val = ECG_sample_start_end_idx + ECG_start_offset - 1;
%             disp_string_title(1, sprintf( 'Classifying from %d to %d', aux_val(1), aux_val(2) ) );

            [lead_idx, ECG_header ] = get_ECG_idx_from_header(ECG_header);

            [aux_val, ~, lablist ] = a2hbc('ECG', ECG(:,lead_idx), ...
                            'ECG_header', ECG_header, ...
                            'ECG_annotations', annotations_used, ...
                            'op_mode', obj.mode );

            bAux = annotations_used.time > ECG_sample_start_end_idx(1) & annotations_used.time < ECG_sample_start_end_idx(2);
            payload_out.anntyp = lablist(colvec(aux_val(bAux)),1);
            payload_out.time = annotations_used.time(bAux) + ECG_start_offset - 1;
            payload_out.lablist = lablist;

        end

        function payload = Finish(obj, payload, ECG_header)

        end

        function payload = Concatenate(obj, plA, plB)

            if( isempty(plA) )

                payload = plB;

            else
                for fn = rowvec(fieldnames(plA))

                    if( isfield(plA, fn{1}) && isfield(plB, fn{1}) )
                        payload.(fn{1}) = [ plA.(fn{1}); plB.(fn{1}) ];
                    elseif( ~isfield(plA, fn{1}) && isfield(plB, fn{1}) )
                        payload.(fn{1}) = plB.(fn{1});
                    end

                end
            end

        end

        %% property restriction functions

        function set.mode(obj,x)
            if( ischar(x) && ~isempty(strcmpi(x, obj.cKnownModesOfOperation)) )
                obj.mode = x;
            else
                warning('ECGtask_HB_classifier:BadArg', 'Invalid mode.');
            end
        end

    end

    methods ( Access = private )

    end

end


function [success] = downloadGithubRepositories(varargin)
	% Downloads Github repositories repositories.
	% Biafra Ahanonu
	% started: 2019.01.14 [10:23:05]
	% changelog
		% 2020.04.03 [11:15:32] - Allow inputs to use getOptions. Also allow force updating of git repository.
		% 2020.04.03 [14:02:33] - Save downloaded compressed files (e.g. zips) to a sub-folder.
		% 2020.06.28 [13:08:16] - Final implementation of force update, to bring to most current version of all git directories.
		% 2021.01.22 [13:18:25] - Update to allow regexp backup to find name of downloaded Github repo folder after unzipping, e.g. in cases where a release or non-master branch is downloaded. - IGNORE
		% 2021.02.01 [15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions.
		% 2021.08.08 [19:30:20] - Updated to handle CIAtah v4.0 switch to all functions inside ciapkg package.
		% 2022.01.27 [08:49:09] - If multiple repos requested but one already downloaded, previously exited before downloading the other repos.

	import ciapkg.api.* % import CIAtah functions in ciapkg package API.

	%========================
	% 1 = force update of the git repository, 0 = skip if already downloaded
	options.forceUpdate = 0;
	% Str: directory of external download path.
	options.signalExtractionDir = ciapkg.getDirExternalPrograms();
	options.gitNameDisp = {'NoRMCorre'};
	options.gitRepos = {'https://github.com/flatironinstitute/NoRMCorre/archive/master.zip'};
	options.outputDir = {'normcorre'};
	options.gitName = {'NoRMCorre-master'};

	% get options
	options = getOptions(options,varargin);
	% display(options)
	% unpack options into current workspace
	% fn=fieldnames(options);
	% for i=1:length(fn)
	% 	eval([fn{i} '=options.' fn{i} ';']);
	% end
	%========================

	try
		signalExtractionDir = options.signalExtractionDir;

		gitNameDisp = options.gitNameDisp;
		gitRepos = options.gitRepos;
		outputDir = options.outputDir;
		gitName = options.gitName;
		nRepos = length(outputDir);

		% If forcing an update, make sure to remove all external programs from the path
		if options.forceUpdate==1
			ciapkg.download.updatePathCleanup(options.signalExtractionDir);
			pause(0.02)
		end

		for gitNo = 1:nRepos
			display(repmat('=',1,7))
			fprintf('%s\n',gitNameDisp{gitNo});

			outDirPath = [signalExtractionDir filesep outputDir{gitNo}];

			oldDir = [signalExtractionDir filesep gitName{gitNo}];
			newDir = [signalExtractionDir filesep outputDir{gitNo}];

			% If the new directory exist
			if exist(newDir,'dir')&options.forceUpdate==0
				fprintf('Package already exists (and no forced update), skipping: %s.\n',newDir)
				success = 1;
				continue;
			end

			% Make download directory
			rawSavePathDownload = [signalExtractionDir filesep '_downloads'];
			if ~exist(rawSavePathDownload,'dir');mkdir(rawSavePathDownload);fprintf('Made folder: %s',rawSavePathDownload);end
			% Download save path
			rawSavePathDownload = [rawSavePathDownload filesep outputDir{gitNo} '.zip'];

			% Remove directory and downloaded zip file if forcing an update.
			if options.forceUpdate==1
				if exist(outDirPath,'dir')
					fprintf('Removing directory to allow updates: %s\n', outDirPath);
					status = 0;
					tryCount = 1;
					% Try to delete several times else print out warning
					while status==0&tryCount<4
						[status,msg,msgID] = rmdir(outDirPath,'s');
						tryCount = tryCount + 1;
						pause(0.1);
					end
					if status==0
						warning('	Something went wrong removing the directory, check for proper permissions, etc.')
						warning(['	' msg])
						disp(['	' msgID])
					else
						disp('	Successfully removed directory!')
					end
				end
				if exist(rawSavePathDownload,'file')==2
					fprintf('Removing zip file to allow update: %s\n',rawSavePathDownload)
					delete(rawSavePathDownload)
				end
			else

			end

			% Download git repo zip
			if exist(rawSavePathDownload,'file')~=2
				fprintf('Downloading %s file to %s\n',gitRepos{gitNo},rawSavePathDownload)
				websave(rawSavePathDownload,gitRepos{gitNo});
			else
				fprintf('Already downloaded %s\n',rawSavePathDownload)
			end

			% To ensure do not have mixed extraction directories, still check directory is there before extracting even in case of forced update.
			if exist(outDirPath,'dir')
				fprintf('Already extracted %s\n', outDirPath);
				continue;
			end

			% Unzip the repo file
			fprintf('Unzipping file %s\n',rawSavePathDownload)
			filenames = unzip(rawSavePathDownload,signalExtractionDir);
			% cellfun(@disp,filenames,'UniformOutput',false)

			% Rename to proper folder for calciumImagingAnalysis
			fprintf('Renaming %s to %s \n',[signalExtractionDir filesep gitName{gitNo}],[signalExtractionDir filesep outputDir{gitNo}])
			if strcmp(oldDir,newDir)==1
				disp('Same directory, ignore name change!')
			else
				movefile(oldDir,newDir);
			end

			% fprintf('\n\n')
		end

		success = 1;
	catch err
		success = 0;
		disp('Check internet connection or download and unzip files manually, see:')
		try
			cellfun(@disp,gitRepos,'UniformOutput',false)
		catch err2
			display(repmat('@',1,7))
			disp(getReport(err2,'extended','hyperlinks','on'));
			display(repmat('@',1,7))
		end
		fprintf('\n\n')
		display(repmat('@',1,7))
		disp(getReport(err,'extended','hyperlinks','on'));
		display(repmat('@',1,7))
	end
end


classdef StatusState
    %STATUSSTATE Represent status selections
    %   Enumerates a list of choices

    % Copyright 2020-2021 The MathWorks Inc.

    %% Enumerations
    enumeration
        none
        complete
        running
        warning
        error
        info
        unknown
    end %enumeration

end %classdef


function out = cfg_run_runjobs(job)

% Initialise, fill, save and run a job with repeated inputs.
% To make use of possible parallel execution of independent jobs, all
% repeated jobs are filled first and (if successfully filled) run as one
% large job.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: cfg_run_runjobs.m 6514 2015-08-06 10:07:53Z volkmar $

rev = '$Rev: 6514 $'; %#ok

if isfield(job.save, 'savejobs')
    [p, n, e] = fileparts(job.save.savejobs.outstub);
    outfmt = strrep(fullfile(job.save.savejobs.outdir{1}, sprintf('%s_%%0%dd.m', n, ceil(log10(numel(job.inputs))+1))), '\', '\\');
end;
hjobs = cell(size(job.inputs));
sts = false(size(job.inputs));
out.jobfiles = {};
for cr = 1:numel(job.inputs)
    cjob = cfg_util('initjob', job.jobs);
    inp = cell(size(job.inputs{cr}));
    for ci = 1:numel(job.inputs{cr})
        fn = fieldnames(job.inputs{cr}{ci});
        inp{ci} = job.inputs{cr}{ci}.(fn{1});
    end;
    sts(cr) = cfg_util('filljob', cjob, inp{:});
    if sts(cr)
        [un, hjobs{cr}] = cfg_util('harvest', cjob);
    end;
    if isfield(job.save, 'savejobs')
        out.jobfiles{cr} = sprintf(outfmt, cr);
        cfg_util('savejob', cjob, out.jobfiles{cr});
    end;
    cfg_util('deljob', cjob);
end;
if all(sts)
    % keep all hjobs;
elseif any(sts) && strcmp(job.missing,'skip')
    hjobs = hjobs(sts);
else
    hjobs = {};
end
if ~isempty(hjobs)
    cjob = cfg_util('initjob', hjobs);
    cfg_util('run', cjob);
    out.jout = cfg_util('getalloutputs', cjob);
%    if isfield(job.save, 'savejobs')
%        [p n e] = fileparts(job.save.savejobs.outstub);
%        out.jobrun{1} = fullfile(p, [n '_run.m']);
%        cfg_util('saverun', cjob, out.jobrun{1});
%    end;
    cfg_util('deljob', cjob);
end;


function EnableDisableGuiPlotBttns(handles)
global maingui
if isempty(handles)
    return
end

if ~isempty(maingui.dataTree.currElem.GetRawData())
    set(handles.radiobuttonPlotRaw, 'enable','on')
else
    set(handles.radiobuttonPlotRaw, 'enable','off')
end
if ~isempty(maingui.dataTree.currElem.GetDod())
    set(handles.radiobuttonPlotOD, 'enable','on')
else
    set(handles.radiobuttonPlotOD, 'enable','off')
end
if ~isempty(maingui.dataTree.currElem.GetDc())
    set(handles.radiobuttonPlotConc, 'enable','on')
else
    set(handles.radiobuttonPlotConc, 'enable','off')
end

raw_checked  = get(handles.radiobuttonPlotRaw, 'value');
if strcmp(get(handles.radiobuttonPlotRaw, 'enable'), 'on')
    raw_enable  = true;
else
    raw_enable  = false;
end
if strcmp(get(handles.radiobuttonPlotOD, 'enable'), 'on')
    OD_enable  = true;
else
    OD_enable  = false;
end
if strcmp(get(handles.radiobuttonPlotConc, 'enable'), 'on')
    Conc_enable  = true;
else
    Conc_enable  = false;
end

if ~isempty(maingui.dataTree.groups(1).CondNames) > 0  % If there is stim
    iCondGrp = get(handles.popupmenuConditions, 'value');
    CondName = maingui.dataTree.groups(1).CondNames{iCondGrp};
    if ~isempty(maingui.dataTree.currElem.GetDodAvg(CondName)) || ~isempty(maingui.dataTree.currElem.GetDcAvg(CondName))
        set(handles.checkboxPlotHRF, 'enable','on');
        if ~isa(maingui.dataTree.currElem, 'RunClass')
            set(handles.checkboxPlotHRF, 'value',1);
            if ~isempty(maingui.dataTree.currElem.GetDcAvg())
                set(handles.radiobuttonPlotConc, 'value',1);
            elseif ~isempty(maingui.dataTree.currElem.GetDodAvg())
                set(handles.radiobuttonPlotOD, 'value',1);
            end
        end
    else
        set(handles.checkboxPlotHRF, 'enable','off');
        set(handles.checkboxPlotHRF, 'value',0);
    end
elseif raw_enable && raw_checked
    set(handles.checkboxPlotHRF, 'enable','off');
    set(handles.checkboxPlotHRF, 'value',0);
elseif ~OD_enable && ~Conc_enable
    set(handles.checkboxPlotHRF, 'enable','off');
    set(handles.checkboxPlotHRF, 'value',0);
else
    set(handles.checkboxPlotHRF, 'enable','off');
    set(handles.checkboxPlotHRF, 'value',0);
end

if isa(maingui.dataTree.currElem, 'RunClass')
    if ~OD_enable && ~Conc_enable
        set(handles.radiobuttonPlotRaw, 'value',1)
    end
end


function [result, result_raw] = par_evaluate(task__,noresult)
% Internal: Task processing function of the worker.
% Result = par_evaluate(Task)
%
% Both the task and the result are assumed to be in serialized form, and this function deserializes
% the task, evaluates it, and re-serializes the results.
%
% In:
%   Task : task record; A sequence of bytes which represents a cell array of the form:
%          {Number, Function, Arugment1, Arguments2, ...} where Number is an arbitrary task
%          number, Function is the function to evaluate, and ArgumentX are arguments to the function.
%
%   NoResult : Whether the task does not produce a result. (default: false)
%
% Out:
%   Result : result record; A sequence of bytes which represents a cell array of the form:
%            {Number, ResultData} where Number is the corresponding task number and ResultData is
%            the first output of the function.
%
%            If an exception happened during processing, result represents {Number, LastError} where
%            LastError is an error record as returned by lasterror.
%
% Notes:
%   Depending on the severity of the error (especially when the serialization itself fails), the
%   error record may contain an inaccurate number or just a string as error
%   record.
%
% See also:
%   par_worker
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2010-08-29

% Copyright (C) Christian Kothe, SCCN, 2010, christian@sccn.ucsd.edu
%
% 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 should have received a copy of the GNU General Public License along with this program; if not,
% write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
% USA

if nargin < 2
    noresult = false; end

result_raw = [];
try
    % deserialize the task (names mangled as the task may involve an "eval" call).
    task__ = hlp_deserialize(task__);
    % evaluate Function(Argument1,Argument2, ...) and construct the result record
    if noresult
        task__{2}(task__{3:end});
    else
        result_raw = {task__{1},task__{2}(task__{3:end})};
        % serialize the result record
        result = hlp_serialize(result_raw);
    end
catch e
    try
        % try to display and serialize the error
        fprintf('exception during task processing: %s\n',e.message);
        if exist('hlp_handleerror','file')
            hlp_handleerror(e);
        else
            for k = 1:length(e.stack)
                fprintf('  %s (%i)\n',e.stack(k).name,e.stack(k).line); end
        end
        if iscell(task__)
            result = hlp_serialize({task__{1},e});
        else
            result = hlp_serialize({NaN,e});
        end
    catch
        % fall back to minimal reporting
        try
            fprintf('exception during error serialization: %s\n',e.message);
            result = hlp_serialize({NaN,['Error during error serialization: ' e.message]});
        catch
            fprintf('serialization failed completely.\n');
            result = uint8(200);
        end
    end
end


classdef LvdPluginOptimVarSet < matlab.mixin.SetGet
    %LvdPluginOptimVarSet Summary of this class goes here
    %   Detailed explanation goes here

    properties
        pluginVars(1,:) LvdPluginOptimVarWrapper

        lvdData LvdData
    end

    methods
        function obj = LvdPluginOptimVarSet(lvdData)
            obj.lvdData = lvdData;
        end

        function addPluginVar(obj, newPluginVar)
            obj.pluginVars(end+1) = newPluginVar;
        end

        function removePluginVar(obj, pluginVar)
            obj.pluginVars([obj.pluginVars] == pluginVar) = [];
        end

        function [listBoxStr, pluginVars] = getListboxStr(obj)
            listBoxStr = {};

            for(i=1:length(obj.pluginVars)) %#ok<*NO4LP>
                if(obj.pluginVars(i).isVariableActive())
                    varStr = '* ';
                else
                    varStr = '';
                end

                listBoxStr{end+1} = sprintf('%u - %s%s', i, varStr, obj.pluginVars(i).name); %#ok<AGROW>
            end

            pluginVars = obj.pluginVars;
        end

        function pluginVars = getPluginVarsArray(obj)
            pluginVars = obj.pluginVars;
        end

        function inds = getIndsForPluginVars(obj, pluginVars)
            inds = find(ismember(obj.pluginVars, pluginVars));
        end

        function plugin = getPluginVarAtInd(obj, ind)
            if(ind > 0 && ind <= length(obj.pluginVars))
                plugin = obj.pluginVars(ind);
            else
                plugin = LvdPluginOptimVarWrapper.empty(1,0);
            end
        end

        function numPluginVars = getNumPluginVars(obj)
            numPluginVars = length(obj.pluginVar);
        end

        function varValues = getPluginVarValues(obj)
            varValues = [obj.pluginVars.value];
            varValues = varValues(:);
        end

        function tf = isVarAPluginVar(obj, var)
            if(not(isempty(obj)))
                if(isempty(obj.pluginVars))
                    tf = false;

                else
                    vars = [obj.pluginVars.optVar];
                    tf = any(var == vars);
                end

            else
                tf = true;
            end
        end
    end
end