% Begin initialization code - DO NOT EDIT
function varargout = chanoperGUI(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
        'gui_Singleton',  gui_Singleton, ...
        'gui_OpeningFcn', @chanoperGUI_OpeningFcn, ...
        'gui_OutputFcn',  @chanoperGUI_OutputFcn, ...
        'gui_LayoutFcn',  [] , ...
        'gui_Callback',   []);
if nargin && ischar(varargin{1})
        gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
        [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
        gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

%--------------------------------------------------------------------------
function chanoperGUI_OpeningFcn(hObject, eventdata, handles, varargin)

handles.output = [];
example{1}  = 'ch@ = ch6 - ch5 label HEOG';
example{2}  = 'chan@ = ch6 - ch5 label = HEOG';
example{3}  = 'ch@ = 0.5*chan7 + 0.5*chan9 label LINKM';
example{4}  = 'ch@ = mahaleeg(ch1,ch2) label MAHAL01';
example{5}  = 'CH@ = mahaleeg(ch40) label SELFMAHAL';
example{6}  = 'ch@ = (ch11+ch12+ch13)/3 label = ROI temporal';
example{7}  = 'CHAN@ = (ch11 + ch12 + ch13)/3 label ROI temporal';
example{8}  = 'ch@ = abs(ch110) label E110 rectified ';

try
        ERPLAB = varargin{1};

        if iserpstruct(ERPLAB)
                nchan      = ERPLAB.nchan; % Total number of channels
                typedata   = 'ERP';
                datastr    = 'ERPset';
                formtype   = 'erpchanformulas';
                example{5} = 'ch@ = mgfperp(ERP) label MGFPower';
        else
                example{3} = 'ch@ = chinterpol';
                nchan    = ERPLAB.nbchan; % Total number of channels
                typedata = 'EEG';
                datastr  = 'dataset';
                formtype = 'eegchanformulas';
        end
catch
        ERPLAB.chanlocs = [];
        listch   = '';
        nchan    = 1;
        formtype = [];
        typedata = 'unspecific data';
        datastr  = 'who-knows-what';
end
try
        def = varargin{2};
        formulas = def{1};
        wchmsgon = def{2};
catch
        formulas = [];
        wchmsgon = 1;
end

handles.nchan    = nchan;
% handles.listname = [];
handles.example  = example;
handles.exacounter = 0;
handles.typedata = typedata;
handles.formtype = formtype;

%
% Name & version
%
version = geterplabversion;
set(handles.gui_chassis,'Name', ['ERPLAB ' version '   -   Channel Operation GUI for ' typedata])

% formulas = erpworkingmemory(formtype);

if isempty(formulas)
        set(handles.editor,'String','');
else
        set(handles.editor, 'String', formulas)
end

% For undo & redo
% handles.formulas{1} = get(handles.editor, 'String');
% handles.undocount = 1;
% set(handles.pushbutton_undo,'Enable','off')
% set(handles.pushbutton_redo,'Enable','off')

%
% Prepare List of current Channels
%
listch=[];
if isempty(ERPLAB.chanlocs)
        for e=1:nchan
                ERPLAB.chanlocs(e).labels = ['Ch' num2str(e)];
        end
end
listch = cell(1,nchan);
for ch =1:nchan
        listch{ch} = [num2str(ch) ' = ' ERPLAB.chanlocs(ch).labels ];
end

set(handles.listboxchan1,'String', listch)
label1 = '<left>Send file rather than individual equations';
label2 = '<left>(creates compact history)';
set(handles.checkbox_sendfile2history, 'string',[label1 '
' label2])
handles.listch = listch;

%
% Mode buttons
%
set(handles.button_recursive, 'String', sprintf('Modify existing %s (recursive updating)', datastr));
set(handles.button_no_recu, 'String', sprintf('Create new %s (independent transformations)',datastr));

%
% Gui memory
%
chanopGUI = erpworkingmemory('chanopGUI');

if isempty(chanopGUI)
        set(handles.button_recursive,'Value', 1); % default is Modify existing ERPset (recursive updating)
        set(handles.button_savelist, 'Enable','off')
        set(handles.chkeeplocs,'Value', 1) %default is Preserve Channel locations

        %
        % File List
        %
        set(handles.edit_filelist,'String','');
        set(handles.checkbox_sendfile2history,'Value',0)
        handles.listname = [];
else
        if chanopGUI.emode==0
                set(handles.button_recursive,'Value', 1);
                set(handles.button_no_recu,'Value', 0);
        else
                set(handles.button_recursive,'Value', 0);
                set(handles.button_no_recu,'Value', 1);
        end
        if chanopGUI.hmode==0
                set(handles.checkbox_sendfile2history,'Value', 0);
        else
                set(handles.checkbox_sendfile2history,'Value', 1);
        end
        if chanopGUI.keeplocs ==1
            set(handles.chkeeplocs,'Value',1);
        else
            set(handles.chkeeplocs,'Value',0);
        end
        listname = chanopGUI.listname;
        set(handles.edit_filelist,'String', listname );
        handles.listname = listname; % JLC Sept 1, 2012
end

% wchmsgon = erpworkingmemory('wchmsgon');

if isempty(wchmsgon) || wchmsgon==0
        set(handles.chwarning,'Value', 0)
elseif wchmsgon==1
        set(handles.chwarning,'Value', 1)
else
        error('Oops...checkbox_warning memory failed')
end

handles.locs = ERPLAB.chanlocs;

%
% Color GUI
%
handles = painterplab(handles);

%
% Set font size
%
handles = setfonterplab(handles);

% Update handles structure
guidata(hObject, handles);

% help
helpbutton

drawnow
uiwait(handles.gui_chassis);

%--------------------------------------------------------------------------
function varargout = chanoperGUI_OutputFcn(hObject, eventdata, handles)
% Get default command line output from handles structure

varargout{1} = handles.output;

% The figure can be deleted now
delete(handles.gui_chassis);
pause(0.1)

%--------------------------------------------------------------------------
function editor_Callback(hObject, eventdata, handles)

set(handles.edit_filelist, 'String','');
compacteditor(hObject, eventdata, handles);

% handles = editorbackup(hObject, eventdata, handles);
% formulas  = get(handles.editor, 'String');
% undocount = handles.undocount;
% undocount = undocount + 1;
% handles.formulas{undocount} = formulas;
% handles.undocount = undocount;

handles.listname  = [];

% Update handles structure
guidata(hObject, handles);

%--------------------------------------------------------------------------
function editor_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
        set(hObject,'BackgroundColor','white');
end

%--------------------------------------------------------------------------
function pushbutton_help_Callback(hObject, eventdata, handles)
% doc pop_eegchanoperator
web https://github.com/lucklab/erplab/wiki/EEG-and-ERP-Channel-Operations -browser

%--------------------------------------------------------------------------
function pushbutton_RUN_Callback(hObject, eventdata, handles)
listname    = handles.listname;
compacteditor(hObject, eventdata, handles);
formulalist = get(handles.editor,'String');
wchmsgon    = get(handles.chwarning,'Value');
keeplocs    = get(handles.chkeeplocs,'Value');

if strcmp(formulalist,'')
        msgboxText =  'You have not written any formula!';
        title = 'ERPLAB: chanoperGUI few inputs';
        errorfound(msgboxText, title);
        return
end
if size(formulalist,2)>256
        msgboxText = ['Formulas length exceed 256 characters.\n\n'...
                'Be sure to press [Enter] after you have entered each formula.'];
        title = 'ERPLAB: chanoperGUI few inputs';
        errorfound(sprintf(msgboxText), title);
        return
end

%
% Check formulas
%
if get(handles.button_recursive,'Value')
        editormode = 0;
else
        editormode = 1;
end

typedata = lower(handles.typedata);
[option, recall, goeson] = checkformulas(cellstr(formulalist), [typedata 'chanoperGUI'], editormode);

if goeson==0
        return
end
if isempty(listname) && get(handles.checkbox_sendfile2history,'Value')==1
        BackERPLABcolor = [1 0.9 0.3];    % yellow
        question = ['Equations at editor window have not been saved yet.\n\n'...
                'What would you like to do?'];
        title = 'WARNING: Save List of edited chans';
        oldcolor = get(0,'DefaultUicontrolBackgroundColor');
        set(0,'DefaultUicontrolBackgroundColor',BackERPLABcolor)
        button = questdlg(sprintf(question), title,'Save and run','Run without saving', 'Cancel','Run without saving');
        set(0,'DefaultUicontrolBackgroundColor',oldcolor)

        if strcmpi(button,'Save and run')
                fullname = savelist(hObject, eventdata, handles);
                listname = fullname;
                handles.output = {listname, wchmsgon}; % sent filenam string)
        elseif strcmpi(button,'Run without saving')
                handles.output = {cellstr(formulalist), wchmsgon}; % sent like a cell string (with formulas)
        elseif strcmpi(button,'Cancel') || strcmpi(button,'')
                handles.output   = [];
                handles.listname = [];
                % Update handles structure
                guidata(hObject, handles);
                return
        end
elseif isempty(listname) && get(handles.checkbox_sendfile2history,'Value')==0
        handles.output = {cellstr(formulalist), wchmsgon}; % sent like a cell string (with formulas)

elseif ~isempty(listname) && get(handles.checkbox_sendfile2history,'Value')==1
        handles.output = {listname, wchmsgon}; % sent filename string

elseif ~isempty(listname) && get(handles.checkbox_sendfile2history,'Value')==0
        handles.output = {cellstr(formulalist), wchmsgon}; % sent like a cell string (with formulas)
end

% handles.output
% formtype = handles.formtype;
% erpworkingmemory(formtype, formulalist);

%
% memory for Gui
%
chanopGUI.emode = editormode;
chanopGUI.hmode = get(handles.checkbox_sendfile2history,'Value');
chanopGUI.listname  = listname;
chanopGUI.keeplocs = keeplocs;
chanopGUI.chanlocs = handles.locs;
disp(chanopGUI.chanlocs)
erpworkingmemory('chanopGUI', chanopGUI);

try
    handles.output{3} = keeplocs;
catch
        disp('Problem setting location preference')
end

% Update handles structure
guidata(hObject, handles);
uiresume(handles.gui_chassis);

%--------------------------------------------------------------------------
function cancel_Callback(hObject, eventdata, handles)

handles.output = [];
% Update handles structure
guidata(hObject, handles);
uiresume(handles.gui_chassis);

%--------------------------------------------------------------------------
function eraser_Callback(hObject, eventdata, handles)
% %
% % for undo
% %
% formulas  = get(handles.editor, 'String');
% undocount = handles.undocount;
% handles.formulas{undocount} = formulas;
% undocount = undocount + 1;
% handles.undocount = undocount;
formulas  = get(handles.editor, 'String');
if isempty(formulas)
        return
end

% handles = editorbackup(hObject, eventdata, handles);
set(handles.editor, 'String','')
handles.output = [];
disp('Formulas were erased.')
set(handles.button_savelist, 'Enable','off')
handles.listname = [];
% Update handles structure
guidata(hObject, handles);

%--------------------------------------------------------------------------
function help_Callback(hObject, eventdata, handles)

fprintf('\n\n\n\n\n')
help pop_chanoperator

%--------------------------------------------------------------------------
function button_saveaslist_Callback(hObject, eventdata, handles)

compacteditor(hObject, eventdata, handles);
fulltext = strtrim(get(handles.editor,'String'));

if size(fulltext,2)>256
        msgboxText =  ['Formulas length exceed 256 characters.\n\n'...
                'Be sure to press [Enter] after you have entered each formula.'];
        title = 'ERPLAB: chanoperGUI few inputs';
        errorfound(sprintf(msgboxText), title);
        return
end
if ~strcmp(fulltext,'')
        fullname = savelist(hObject, eventdata, handles);
        if isempty(fullname)
                return
        end
        set(handles.edit_filelist, 'String', fullname )
        set(handles.button_savelist, 'Enable', 'on')
        handles.listname = fullname;
        % Update handles structure
        guidata(hObject, handles);
else
        set(handles.button_saveaslist,'Enable','off')
        msgboxText =  'You have not written any formula yet!';
        title = 'ERPLAB: chanoperGUI few inputs';
        errorfound(msgboxText, title);
        set(handles.button_saveaslist,'Enable','on')
        return
end

%--------------------------------------------------------------------------
function button_loadlist_Callback(hObject, eventdata, handles)
[filename, filepath] = uigetfile({'*.txt';'*.*'},'Select a formulas-file');

if isequal(filename,0)
        disp('User selected Cancel')
        return
else
        fullname = fullfile(filepath, filename);
        disp(['pop_chanoperation(): For formulas-file, user selected ', fullname])
end

set(handles.edit_filelist,'String',fullname);
fid_formula = fopen( fullname );

try
        formcell    = textscan(fid_formula, '%s','delimiter', '\r');
        formulas    = char(formcell{:});
catch
        serr = lasterror;
        msgboxText =  ['Please, check your file: \n';
                fullname '\n'...
                serr.message];
        title = 'ERPLAB: pop_chanoperation() error:';
        errorfound(sprintf(msgboxText), title);
        return
end
if size(formulas,2)>256
        msgboxText =  ['Formulas length exceed 256 characters.\n\n'...
                'Be sure to press [Enter] after you have entered each formula.'];
        title = 'ERPLAB: chanoperGUI few inputs';
        errorfound(sprintf(msgboxText), title);
        return
end

compacteditor(hObject, eventdata, handles);
set(handles.editor,'String',formulas);
fclose(fid_formula);
set(handles.button_savelist, 'Enable','on')
handles.listname = fullname;

% Update handles structure
guidata(hObject, handles);

%--------------------------------------------------------------------------
function listboxchan1_Callback(hObject, eventdata, handles)

numchan   = get(hObject, 'Value');
if isempty(numchan)
        return
end

linet    = get(handles.editor, 'Value');

if nnz(linet) == 0
        linet = 1;
end

formulas = cellstr(get(handles.editor, 'String'));
formulas{linet} = [formulas{linet} 'ch' num2str(numchan)];
set(handles.editor, 'String', char(formulas));

%--------------------------------------------------------------------------
function listboxchan1_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
        set(hObject,'BackgroundColor','white');
end

%--------------------------------------------------------------------------
function button_example_Callback(hObject, eventdata, handles)

% %
% % for undo
% %
% formulas  = get(handles.editor, 'String');
% undocount = handles.undocount;
% handles.formulas{undocount} = formulas;
% undocount = undocount + 1;
% handles.undocount = undocount;

nchan      = handles.nchan;
example    = handles.example;
exacounter = handles.exacounter;
exacounter = exacounter + 1;
text       = cellstr(get(handles.editor, 'String'));

if get(handles.button_no_recu,'Value')
        prechar = 'n';
else
        prechar = '';
end
if isempty([text{:}]) || exacounter>length(example)
        exacounter = 1;
end
if length(text)==1 && strcmp(text{1}, '')
        exacurr = char(regexprep(example{exacounter},'@',num2str(nchan+exacounter)));
        text{1} = [prechar exacurr];
else
        exacurr = char(regexprep(example{exacounter},'@',num2str(nchan+exacounter)));
        text{end+1} = [prechar exacurr];
end

set(handles.editor, 'String', char(text));
% handles    = editorbackup(hObject, eventdata, handles);
handles.exacounter = exacounter;
% Update handles structure
guidata(hObject, handles);

%--------------------------------------------------------------------------
function fullname = savelist(hObject, eventdata, handles)
fulltext = char(get(handles.editor,'String'));

if isempty(fulltext)
        return
end

fullnamepre = get(handles.edit_filelist,'String');

%
% Save OUTPUT file
%
[filename, filepath, filterindex] = uiputfile({'*.txt';'*.dat';'*.*'},'Save formulas-file as', fullnamepre);

if isequal(filename,0)
        disp('User selected Cancel')
        fullname = [];
        return
else
        [px, fname, ext] = fileparts(filename);

        if strcmp(ext,'')
                if filterindex==1 || filterindex==3
                        ext   = '.txt';
                else
                        ext   = '.dat';
                end
        end

        fname = [ fname ext];
        fullname = fullfile(filepath, fname);

        fid_list   = fopen( fullname , 'w');

        for i=1:size(fulltext,1)
                fprintf(fid_list,'%s\n', fulltext(i,:));
        end

        fclose(fid_list);
        set(handles.button_savelist, 'Enable','on')
end

%--------------------------------------------------------------------------
function compacteditor(hObject, eventdata, handles)
texteditor = strtrim(get(handles.editor,'String'));

if isempty(texteditor)
        return
end

formul = cellstr(texteditor);
nfl    = length(formul);
k = 1;
formulalist = cell(1);

% removes blank lines
for i=1:nfl
        if ~strcmp(formul{i},'')
                % removes blank lines
                formulalist{k} = regexprep(formul{i},'[^\s](label)[^\s]',' $1 ', 'ignorecase');
                k = k+1;
        end
end

formulalist = strtrimx(formulalist); % special white space removing
set(handles.editor,'String', char(formulalist));
drawnow

%--------------------------------------------------------------------------
function check_aoperations(hObject, eventdata, handles)
texteditor = strtrim(get(handles.editor,'String'));
if isempty(texteditor)
        return
end

formul = cellstr(texteditor);
nfl = length(formul);
k   = 1;
formulalist = cell(1);

for i=1:nfl
        if ~strcmp(formul{i},'')
                formulalist{k} = formul{i};
                k = k+1;
        end
end

formulalist = strtrimx(formulalist);
set(handles.editor,'String', char(formulalist));

%--------------------------------------------------------------------------
function button_savelist_Callback(hObject, eventdata, handles)
compacteditor(hObject, eventdata, handles);
fulltext = strtrim(get(handles.editor,'String'));

if size(fulltext,2)>256
        msgboxText = ['Formulas length exceed 256 characters.\n\n'...
                'Be sure to press [Enter] after you have entered each formula.'];
        title = 'ERPLAB: chanoperGUI few inputs';
        errorfound(sprintf(msgboxText), title);
        return
end
if ~isempty(fulltext)

        fullname = get(handles.edit_filelist, 'String');

        if ~strcmp(fullname,'')
                fid_list   = fopen( fullname , 'w');

                for i=1:size(fulltext,1)
                        fprintf(fid_list,'%s\n', fulltext(i,:));
                end

                fclose(fid_list);
                handles.listname = fullname;
                % Update handles structure
                guidata(hObject, handles);
                disp(['Saving equation list at ' fullname ''])
        else
                button_saveaslist_Callback(hObject, eventdata, handles)
                return
        end
else
        set(handles.button_saveaslist,'Enable','off')
        msgboxText =  'You have not written any formula yet!';
        title      = 'ERPLAB: chanoperGUI few inputs';
        errorfound(msgboxText, title);
        set(handles.button_saveaslist,'Enable','on')
        return
end

%--------------------------------------------------------------------------
function checkbox_sendfile2history_Callback(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function edit_filelist_Callback(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function edit_filelist_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
        set(hObject,'BackgroundColor','white');
end

%--------------------------------------------------------------------------
function button_clearfile_Callback(hObject, eventdata, handles)
set(handles.edit_filelist,'String','');
set(handles.button_savelist, 'Enable', 'off')

%--------------------------------------------------------------------------
function button_recursive_Callback(hObject, eventdata, handles)
if get(hObject,'Value')
        set(handles.button_no_recu,'Value',0)
        val = testsyntaxtype(hObject, eventdata, handles, 'recu');

        if val==0;
                set(handles.button_recursive, 'Value', 0)
                set(handles.button_no_recu, 'Value', 1)
        end

        %%%       handles = editorbackup(hObject, eventdata, handles);
        %%% Update handles structure
        %%guidata(hObject, handles);
else
        set(hObject,'Value',1)
end

%--------------------------------------------------------------------------
function button_no_recu_Callback(hObject, eventdata, handles)
if get(hObject,'Value')
        set(handles.button_recursive,'Value',0)
        val = testsyntaxtype(hObject, eventdata, handles, 'norecu');
        if val==0
                set(handles.button_recursive, 'Value', 1)
                set(handles.button_no_recu, 'Value', 0)
        end
        %%%       handles = editorbackup(hObject, eventdata, handles);
        %%% Update handles structure
        %%%guidata(hObject, handles);
else
        set(hObject,'Value',1)
end

%--------------------------------------------------------------------------
function val = testsyntaxtype(hObject, eventdata, handles, whocall)
val = 1;
formulaArray = get(handles.editor,'String');

if isempty(formulaArray)
        return
else
        formulaArray = strtrim(cellstr(formulaArray));
end
nformulas = length(formulaArray);

[expspliter parts] = regexp(formulaArray, '=','match','split');
ask4fix = 1;
wantfix = 0;
newnumchan = 1;

for t=1:nformulas
        fcomm = formulaArray{t};
        tokcommentb  = regexpi(fcomm, '^#', 'match');  % comment symbol (June 3, 2013)

        if isempty(tokcommentb) % skip comment symbol
                pleft  = regexpi(parts{t}{1}, '(\s*nch[an]*\d+)', 'tokens');
                plcom  = regexpi(parts{t}{1}, '(\s*ch[an]*\d+)', 'tokens');

                if isempty(pleft) &&  ~isempty(plcom) && strcmpi(whocall,'norecu')
                        if ask4fix
                                BackERPLABcolor = [1 0.9 0.3];    % yellow
                                question = ['For non recursive mode, left side of equation\nmust be define as a new channel.\n'...
                                            'For instance, nchan1 = ...\n\n'...
                                            'Do you want that ERPLAB corrects the syntax for you?'];
                                title = 'WARNING: Syntax is not proper for non recursive mode';
                                oldcolor = get(0,'DefaultUicontrolBackgroundColor');
                                set(0,'DefaultUicontrolBackgroundColor',BackERPLABcolor)
                                button = questdlg(sprintf(question), title,'Cancel','No', 'Yes','Yes');
                                set(0,'DefaultUicontrolBackgroundColor',oldcolor)

                                if strcmpi(button,'Yes')
                                        ask4fix = 0;
                                        wantfix = 1;
                                elseif strcmpi(button,'Cancel')
                                        val = 0; % cancel
                                        break
                                else
                                        ask4fix = 0;
                                        wantfix = 0;
                                end
                                %else
                                %      wantfix =1;
                        end
                elseif ~isempty(pleft) && strcmpi(whocall,'recu')
                        if ask4fix
                                BackERPLABcolor = [1 0.9 0.3];    % yellow
                                question = ['For recursive mode, left side of equation cannot\nbe define as a new channel.\n'...
                                            'For instance, you must write chan1 = ...\n\n'...
                                            'Do you want that ERPLAB corrects the syntax for you?'];
                                title = 'WARNING: Syntax is not proper for recursive mode';
                                oldcolor = get(0,'DefaultUicontrolBackgroundColor');
                                set(0,'DefaultUicontrolBackgroundColor',BackERPLABcolor)
                                button = questdlg(sprintf(question), title,'Cancel','No', 'Yes','Yes');
                                set(0,'DefaultUicontrolBackgroundColor',oldcolor)

                                if strcmpi(button,'Yes')
                                        ask4fix = 0;
                                        wantfix =1;
                                elseif strcmpi(button,'Cancel')
                                        val = 0; % cancel
                                        break
                                else
                                        ask4fix = 0;
                                        wantfix = 0;
                                end
                                %else
                                %      wantfix =1;
                        end
                        %else
                        %      wantfix = 0;
                end
                if wantfix && (~isempty(pleft) || ~isempty(plcom))% fixed  (June 3, 2013): JLC
                        fprintf('WARNING: equation %s ', formulaArray{t})
                        if strcmpi(whocall,'recu') % for recursive mode delete the n in nch
                                formulaArray{t} = sprintf('%s = %s', strtrim(regexprep(parts{t}{1}, '^n*','','ignorecase')), strtrim(parts{t}{2}));
                        else
                                formulaArray{t} = sprintf('%s = %s', strtrim(regexprep(parts{t}{1}, '^n*ch(\D*)(\d*)',['nch$1' num2str(newnumchan)],'ignorecase')), strtrim(parts{t}{2}));
                                newnumchan = newnumchan+1;
                        end
                        fprintf('was changed to equation %s \n', formulaArray{t})
                end
        end
end
if val==1
        set(handles.editor,'String', char(formulaArray));
end

%--------------------------------------------------------------------------
function chwarning_Callback(hObject, eventdata, handles)
%
% if get(hObject,'Value')
%       %
%       % Gui memory
%       %
%       erpworkingmemory('wchmsgon', 1);
% else
%       %
%       % Gui memory
%       %
%       erpworkingmemory('wchmsgon', 0);
% end

%--------------------------------------------------------------------------
function pushbutton_export_chan_list_Callback(hObject, eventdata, handles)
list_of_chans = get(handles.listboxchan1,'String');
nloch = length(list_of_chans);

for i=1:nloch
        fprintf('%s\n',list_of_chans{i});
end

fprintf('\n\nEnd of list.\n\n')

%--------------------------------------------------------------------------
function pushbutton_removechan_Callback(hObject, eventdata, handles)
typedata = handles.typedata;
chan2del = deletechanGUI(typedata);
nchan    = handles.nchan;
keeplocs = get(handles.chkeeplocs,'Value');

if ~isempty(chan2del)
        chan2del = unique_bc2(cell2mat(chan2del));
        if max(chan2del)>nchan && nnz(isinf(chan2del))==0
                msgboxText = 'You are specifying non-existing channels!';
                title = 'ERPLAB: chanoperGUI  remove channels';
                errorfound(sprintf(msgboxText), title);
                return
        end
        if min(chan2del)<1 && nnz(isinf(chan2del))==0
                msgboxText = 'You are specifying freaky non-existing channels!';
                title = 'ERPLAB: chanoperGUI  remove channels';
                errorfound(sprintf(msgboxText), title);
                return
        end
        if nnz(isnan(chan2del))>0  || nnz(isinf(chan2del))>0
                msgboxText = ['Channel problem\n'...
                        'You are specifying freaky non-existing channels!'];
                title = 'ERPLAB: chanoperGUI  remove channels';
                errorfound(sprintf(msgboxText), title);
                return
        end
        if strcmpi(typedata, 'EEG')
                eqtn = sprintf('deletechan(%s)', vect2colon(chan2del, 'Delimiter','off'));
        else
                eqtn = sprintf('delerpchan(%s)', vect2colon(chan2del, 'Delimiter','off'));
        end

        wchmsgon    = get(handles.chwarning,'Value');
        handles.output = {{eqtn}, wchmsgon}; % sent like a cell string (with formulas)
        try
            handles.output{3} = keeplocs;
        catch
            disp('Problem setting location preference')
        end
        % Update handles structure
        guidata(hObject, handles);
        uiresume(handles.gui_chassis);
else
        return
end

%--------------------------------------------------------------------------
function pushbutton_rerefwizard_Callback(hObject, eventdata, handles)
% set to non-recursive mode
set(handles.button_recursive, 'Value', 0)
set(handles.button_no_recu, 'Value', 1)

% open reference wizard
formulalist = rerefassistantGUI(handles.nchan, handles.listch);
if isempty(formulalist)
        return
end

compacteditor(hObject, eventdata, handles);
formulas  = get(handles.editor, 'String');

if get(handles.button_no_recu,'Value')
        formulalist = cellstr([formulalist{:}]);
        for t=1:length(formulalist)
                [expspliter parts] = regexp(formulalist, '=','match','split');
                formulalist{t} = sprintf('%s = %s', strtrim(regexprep(parts{t}{1}, '[^n]*ch','nch','ignorecase')), strtrim(parts{t}{2}));
        end
        formulalist = char(formulalist);
end

if isempty(formulas)
        set(handles.editor,'String',formulalist);
else
        formulalist = cellstr(formulalist);
        formulas = cellstr(formulas);
        formt = [formulas ;formulalist];
        formt = char(formt);
        set(handles.editor,'String',formt);
end

% %--------------------------------------------------------------------------
% function pushbutton_undo_Callback(hObject, eventdata, handles)
%
% undocount = handles.undocount;
% if undocount>1
%       undocount = undocount - 1;
%       formulas  = handles.formulas{undocount};
%       handles.undocount = undocount;
%       set(handles.editor, 'String',char(formulas));
%       set(handles.pushbutton_redo,'Enable','on')
%
%       % formulas = get(handles.edit_filelist, 'String');
%       % Update handles structure
%       guidata(hObject, handles);
% end
% if undocount==1
%       set(handles.pushbutton_undo,'Enable','off')
%       set(handles.pushbutton_redo,'Enable','on')
% end

%--------------------------------------------------------------------------
% function pushbutton_redo_Callback(hObject, eventdata, handles)
%
% nformu    = length(handles.formulas);
% undocount = handles.undocount;
% if undocount<nformu
%       undocount = undocount + 1;
%       formulas  = handles.formulas{undocount};
%       handles.undocount = undocount;
%       set(handles.editor, 'String',char(formulas));
%       % formulas = get(handles.edit_filelist, 'String');
%       % Update handles structure
%       guidata(hObject, handles);
% end
% if undocount==nformu
%       set(handles.pushbutton_redo,'Enable','off')
%       set(handles.pushbutton_undo,'Enable','on')
% end

%--------------------------------------------------------------------------
% function handles = editorbackup(hObject, eventdata, handles)
%
% %
% % for undo
% %
% formulas = get(handles.editor, 'String');
% if isempty(formulas)
%       return
% end
%
% lastform = handles.formulas(end);
%
% if strcmp(char(formulas),char(lastform))
%       return
% end
%
% undocount = length(handles.formulas);
% undocount = undocount + 1;
% handles.formulas{undocount} = formulas;
% set(handles.pushbutton_undo,'Enable','on')
% set(handles.pushbutton_redo,'Enable','off')
%
% handles.undocount = undocount;
% % Update handles structure
% %guidata(hObject, handles);
% return

%--------------------------------------------------------------------------
function pushbutton_RUN_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_loadlist_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_savelist_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_saveaslist_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_clearfile_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function checkbox_sendfile2history_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function eraser_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_example_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function help_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_recursive_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function button_no_recu_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function cancel_CreateFcn(hObject, eventdata, handles)

%--------------------------------------------------------------------------
function gui_chassis_CloseRequestFcn(hObject, eventdata, handles)

if isequal(get(handles.gui_chassis, 'waitstatus'), 'waiting')
        % The GUI is still in UIWAIT, us UIRESUME
        uiresume(handles.gui_chassis);
else
        % The GUI is no longer waiting, just close it
        delete(handles.gui_chassis);
end

% --- Executes on button press in chkeeplocs.
function chkeeplocs_Callback(hObject, eventdata, handles)
% hObject    handle to chkeeplocs (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of chkeeplocs

% --- Executes during object creation, after setting all properties.
function chwarning_CreateFcn(hObject, eventdata, handles)
% hObject    handle to chwarning (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called


function write_serial_event(filename, event)

% WRITE_SERIAL_EVENT
%
% changed A.Hadjipapas 2010
%
% write to phyiscal serial port
% serial port on windows or linux platform

% Copyright (C) 2007, Christian Hesse
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: write_serial_event.m 945 2010-04-21 17:41:20Z roboos $

[port, opt] = filetype_check_uri(filename);
temp=instrfind; %% find isntruments including serial ports

%% check if a serial port with the specified name is already available
if isempty(temp)||~any(strcmpi(temp.Port,port))
  %% if not make one
  s=serial(port);
  %% if user has specified Baudrate, apply that, %%  FIX THIS: currently no
  %% automatic implementation for more options
  if ~isempty(opt)
    s.Baudrate =str2double(opt{2}); %% set Baudrate using optional parameters
  end
  fopen(s); %% open serial port
end

%% write the contents of the field event.value to the serial port as a string
if isfield(event,'value') && ~isempty(event.value)
  msg = event.value;
else
  msg = [];
end

%% write the message to the serial port if it is open
if strcmp(s.Status,'open')
  %% if numeric use fwrite otherwise fprintf
  if isnumeric(msg)
    fwrite(s,msg);
  end

  if ischar(msg)
    fprintf(s,'%s',msg);
  end
else
  error('could not write event to serial port');
end

%% this is the old code
%
%     % serial port on windows or linux platform
%     s = [];
%     [port, opt] = filetype_check_uri(filename);
%
%     % determine whether any serial port objects are already associated with the target serial port
%     temp = instrfind;
%     if isa(temp,'instrument')
%       % find all serial ports
%       i1 = strcmp('serial',{temp(:).Type});
%       if any(i1)
%         % find all serial ports whose name matches that of the specified port
%         i2 = strmatch(lower(['Serial-',port]),lower({temp(find(i1)==1).Name}));
%         % set s to the (first) matching port if present (and open if necessary)
%         if ~isempty(i2)
%           s = temp(i2(1));
%           if ~strcmp(s.Status,'open'), fopen(s); end;
%         end
%       end
%     end
%
%     % create, configure a serial port object if necessary and open the port
%     if ~isa(s,'serial')
%       s = serial(port);
%       if ~isempty(opt) && iscell(opt), s = set(s,opt); end;
%       fopen(s);
%     end
%
%     %     % convert the event structure into an appropriate message
%     %     if isfield(event,'type') && strcmp(event.type,'ctrlchar')
%     %       % use only a single control character
%     %       msg = char(event.value(1));
%     %     else
%     %       % convert the entire event structure into a message
%     %       msg = struct2msg(event);
%     %     end
%
%     % write the message to the serial port
%     if isa(s,'serial') && strcmp(s.Status,'open')
%       fwrite(s,char(event.value));
%     else
%       error('could not write event to serial port');
%     end


function name = removestopwords(name, stopwords)
% remove stop of words. The returned sequence is also parsed into words:
%
% removestopwords('carFrontal')
% ans =
%   'car'
%
% You can also pass a cell array of strings with a list of words to be
% removed.
%
% If called without input arguments, it returs a cell array with the list
% of stopwords given by default.
%
% stopwords = removestopwords;
%
% You can change the list of stopwords by modifiying the file
% stopwords.txt.  (one stopword per line).
%
% Also, this function can be used to remove the stopwords from the LabelMe
% index. This might remove also useful information. For instance, the words
% 'blue', 'frontal', ... will disapear.
%
% D = removestopwords(D)
%

if nargin < 2
    % load list of stop words
    fid = fopen('stopwords.txt');
    C = textscan(fid,'%s');
    fclose(fid);
    stopwords = C{1};
end

if nargin > 0
    if isstruct(name)
        for i = 1:length(name)
            if isfield(name(i).annotation, 'object')
                N = length(name(i).annotation.object);
                for j = 1:N
                    nameobj = name(i).annotation.object(j).name;

                    % we avoid recursive call for speed.
                    w = lower(getwords(nameobj));
                    k = ismember(w, stopwords);
                    w = w(~k);
                    nameobj = strtrim(sprintf('%s ', w{:}));

                    name(i).annotation.object(j).name = nameobj;
                end
            end
        end
    else
        w = lower(getwords(name));
        j = ismember(w, stopwords);
        w = w(~j);
        name = strtrim(sprintf('%s ', w{:}));
    end
else
    name = stopwords;
end


% This file contains lists of ograns as they are used in the whole-body
% metabolic model.
% Please note that the desired sex has to be specified ('male' or 'female')
%
% Ines Thiele 2016 - 2017

OrgansListShort={ 'Heart'; 'Muscle'; 'Lung';'Skin'; 'Stomach'; 'sIEC'; 'Colon';...
    'Urinarybladder'; 'Retina'; 'Scord';'Brain';'Adipocytes'; ...
    'Liver';'Gall'; 'Kidney';'Pancreas'; 'Spleen';'Agland';'Thyroidgland';'Pthyroidgland';  ...
    'Ovary';'Uterus';...
    'Breast';'Cervix';...
    'Testis';'Prostate';...
    'Bcells';'CD4Tcells'; ...
    'Nkcells';'Monocyte';'Platelet'; 'RBC';%'Salvgland';
    %'Esophagus';'CD8Tcells';'Rectum';
    };
if strcmp(lower(sex),'female')
    OrgansListExt={'Heart'; 'Muscle'; 'Lung';'Skin'; 'Stomach'; 'sIEC'; 'Colon';...
        'Urinarybladder'; 'Retina'; 'Scord';'Brain';'Adipocytes'; ...
        'Liver';'Gall'; 'Kidney';'Pancreas'; 'Spleen';'Agland';'Thyroidgland';'Pthyroidgland';  ...
        'Ovary';'Uterus';...
        'Breast';'Cervix';...
        'Bcells';'CD4Tcells'; ...
        'Nkcells';'Monocyte';'Platelet'; 'RBC';...% 'Salvgland';
        'BBB';'Diet';'SI';'GI';'LI';'BileDuct';'Excretion'
        % 'Rectum';'CD8Tcells';'Esophagus';
        };
    OrgansList={'Heart'; 'Muscle'; 'Lung';'Skin'; 'Stomach'; 'sIEC'; 'Colon';...
        'Urinarybladder'; 'Retina'; 'Scord';'Brain';'Adipocytes'; ...
        'Liver';'Gall'; 'Kidney';'Pancreas'; 'Spleen';'Agland';'Thyroidgland';'Pthyroidgland';  ...
        'Ovary';'Uterus';...
        'Breast';'Cervix';...
        'Bcells';'CD4Tcells';...
        'Nkcells';'Monocyte';'Platelet'; 'RBC';...% 'Salvgland';
        %'Esophagus'; 'CD8Tcells';'Rectum';
        };% without 'BBB';'Diet';'SI';'GI';'LI';'BileDuct';'Excretion'
elseif strcmp(lower(sex),'male')
    OrgansListExt={'Heart'; 'Muscle'; 'Lung';'Skin'; 'Stomach'; 'sIEC'; 'Colon';...
        'Urinarybladder'; 'Retina'; 'Scord';'Brain';'Adipocytes'; ...
        'Liver';'Gall'; 'Kidney';'Pancreas'; 'Spleen';'Agland';'Thyroidgland';'Pthyroidgland';  ...
        'Testis';'Prostate';...
        'Bcells';'CD4Tcells'; ...
        'Nkcells';'Monocyte';'Platelet'; 'RBC';...% 'Salvgland';
        'BBB';'Diet';'SI';'GI';'LI';'BileDuct';'Excretion'
        %'Esophagus';'Rectum';'CD8Tcells';
        };
    OrgansList={'Heart'; 'Muscle'; 'Lung';'Skin'; 'Stomach'; 'sIEC'; 'Colon';...
        'Urinarybladder'; 'Retina'; 'Scord';'Brain';'Adipocytes'; ...
        'Liver';'Gall'; 'Kidney';'Pancreas'; 'Spleen';'Agland';'Thyroidgland';'Pthyroidgland';  ...
        'Testis';'Prostate';...
        'Bcells';'CD4Tcells'; ...
        'Nkcells';'Monocyte';'Platelet'; 'RBC';...% 'Salvgland';
        %'Esophagus';'Rectum'; 'CD8Tcells';
        };
end


function params = retinoCheckParams(view, dt, scans);
% Check if visual field mapping ("retinotopy", though it doesn't
% need to be retinotopic) parameters have been set for the specified
% scans, giving the user an option to set them if they haven't been
% assigned yet.
%
% params = retinoCheckParams(view, <dt, scans>);
%
% Returns the parameters as a struct array of length(nScans).
% Will prompt the user to set any scans that haven't been set yet
% in the scan list.
%
% ras, 01/06: testing the waters if this code is needed. I see many
% other places where similar parameters are set, but none of them
% seem immediately useable to me.
if notDefined('view'), view = getCurView;                   end
if notDefined('dt'), dt = viewGet(view, 'curdt');           end
if notDefined('scans'), scans = viewGet(view, 'curscan');   end

mrGlobals;
params = [];

if isnumeric(dt)
    dtNum = dt;
    dt = dataTYPES(dtNum).name;
else
    dtNum = existDataType(dt);
end

for i = 1:length(scans)
    check = retinoGetParams(view, dt, scans(i));

    if isempty(check)
        % not assigned: ask user if he/she wants to assign now
        annotation = dataTYPES(dtNum).scanParams(scans(i)).annotation;
        q = [sprintf('%s, scan %i (%s): ', dt, scans(i), annotation) ...
            'This scan doesn''t have any visual field-mapping ' ...
            'parameters assigned yet. Do you want to assign them now?'];
        resp = questdlg(q, mfilename, 'Yes', 'No', 'Yes');

        if isequal(resp, 'Yes')
            check = retinoSetParams(view, dt, scans(i));
        else
            error('No visual field map parameters set -- user aborted.');
        end
    end

    % at this point, check should be assigned, or we would have aborted
    if isempty(params)  % first scan
        params = check;
    else
        % add the current params to the struct array: copy a field
        % at a time, since the params for different scans may have
        % different fields (different design types)
        for f = fieldnames(check)'
            params(i).(f{1}) = check.(f{1});
        end
    end
end

return


function excelrecord6fcn(identified, IRFperiods, endo, fevd_estimates, n, pref)
% script excelrecord6
% records the information contained in the worksheet 'FEVD' of the excel spreadsheet 'results.xls'

% create the cell that will be saved on excel
fevdcell={};

% build preliminary elements: space between the tables
horzspace=repmat({''},2,5*identified);
vertspace=repmat({''},IRFperiods+3,1);

% loop over variables (vertical dimension)
for ii=1:n
    tempcell={};
    % loop over shocks (horizontal dimension)
    for jj=1:identified
        % create cell of fevd record for variable ii in response to shock jj
        temp=['part of ' endo{ii,1} ' fluctuation due to ' endo{jj,1} ' shocks'];
        fevd_ij=[temp {''} {''} {''};{''} {''} {''} {''};{''} {'lw. bound'} {'median'} {'up. bound'};num2cell((1:IRFperiods)') num2cell((fevd_estimates{ii,jj})')];
        tempcell=[tempcell fevd_ij vertspace];
    end
    fevdcell=[fevdcell;horzspace;tempcell];
end

% trim
fevdcell=fevdcell(3:end,1:end-1);

% write in excel
bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),fevdcell,'FEVD','B2');


function model = setupComponentContribution(model,molFileDir,cid,printLevel)
% Estimates standard transformed reaction Gibbs energy and directionality
% at in vivo conditions in multicompartmental metabolic reconstructions.
% Has external dependencies on the COBRA toolbox, the component
% contribution method, Python (with numpy and Open Babel bindings),
% ChemAxon's Calculator Plugins, and Open Babel. See details on
% availability at the end of help text.
%
% modelT = setupThermoModel(model,molfileDir,cid,T,cellCompartments,ph,...
%                           is,chi,concMin,concMax,confidenceLevel)
%
% INPUTS
% model             Model structure with following fields:
% .S                m x n stoichiometric matrix.
% .mets             m x 1 array of metabolite identifiers.
% .rxns             n x 1 array of reaction identifiers.
% .metFormulas      m x 1 cell array of metabolite formulas. Formulas for
%                   protons should be H, and formulas for water should be
%                   H2O.
% .metCharges       m x 1 numerical array of metabolite charges.
%
% OPTIONAL INPUTS
% molFileDir                Path to a directory containing molfiles for the
%                           major tautomer of the major microspecies of
%                           each metabolite at pH 7. Molfiles should be
%                           named with the metabolite identifiers in
%                           model.mets (without compartment assignments).
%                           Not required if cid are specified.
% cid                       m x 1 cell array of KEGG Compound identifiers.
%                           Not required if molfiledir is specified.
% model.metCompartments     m x 1 array of metabolite compartment
%                           assignments. Not required if metabolite
%                           identifiers are strings of the format ID[*]
%                           where * is the appropriate compartment
%                           identifier.
%
% OUTPUTS
% model                 Model structure with following additional fields:
% .inchi                Structure containing four m x 1 cell array's of
%                       IUPAC InChI strings for metabolites, with varying
%                       levels of structural detail.
% .pKa                  m x 1 structure containing metabolite pKa values
%                       estimated with ChemAxon's Calculator Plugins.
% .pseudoisomers        p x 4 matrix with the following columns:
%                       1. Metabolite index.
%                       2. Estimated pseudoisomer standard Gibbs energy.
%                       3. Number of hydrogen atoms in pseudoisomer
%                       chemical formula.
%                       4. Charge on pseudoisomer.
%
% WRITTEN OUTPUTS
% MetStructures.sdf     An SDF containing all structures input to the
%                       component contribution method for estimation of
%                       standard Gibbs energies.
%
%
% Ronan M. T. Fleming, Sept. 2012   Version 1.0
% Hulda S. H., Dec. 2012            Version 2.0

%% Configure inputs
% Retreive molfiles from KEGG if KEGG ID are given. Otherwise use molfiles
% in molfileDir.
if ~exist('cid','var')
    cid = [];
end
if ~exist('printLevel','var')
    printLevel = 1;
end
%% Get metabolite structures
if ~isempty(cid)
    molFileDir = 'molfilesFromKegg';
    fprintf('\nRetreiving molfiles from KEGG.\n');
    takeMajorMS = true; % Convert molfile from KEGG to major tautomer of major microspecies at pH 7
    pH = 7;
    takeMajorTaut = true;
    kegg2mol(cid,molFileDir,model.mets,takeMajorMS,pH,takeMajorTaut); % Retreive mol files
end

if printLevel>0
fprintf('Creating MetStructures.sdf from molfiles.\n')
end

sdfFileName = 'MetStructures.sdf';
includeRs = 0; % Do not include structures with R groups in SDF
[sdfMetList,noMolMetList] = mol2sdf(model.mets,molFileDir,sdfFileName,includeRs);

if printLevel>0
fprintf('Converting SDF to InChI strings.\n')
end
model.inchi = createInChIStruct(model.mets,sdfFileName);
compositeBool = ~cellfun('isempty',regexp(model.inchi.nonstandard,'\.')); % Remove InChI for composite compounds as they cause problems later.
model.inchi.standard(compositeBool) = cell(sum(compositeBool),1);
model.inchi.standardWithStereo(compositeBool) = cell(sum(compositeBool),1);
model.inchi.standardWithStereoAndCharge(compositeBool) = cell(sum(compositeBool),1);
model.inchi.nonstandard(compositeBool) = cell(sum(compositeBool),1);

%% Estimate metabolite pKa values with ChemAxon calculator plugins and determine all relevant pseudoisomers.
if printLevel>0
fprintf('Estimating metabolite pKa values.\n');
end
npKas = 20; % Number of acidic and basic pKa values to estimate
takeMajorTaut = false; % Estimate pKa for input tautomer. Input tautomer is assumed to be the major tautomer for the major microspecies at pH 7.
model.pseudoisomers = estimate_pKa(model.mets,model.inchi.nonstandard,npKas,takeMajorTaut); % Estimate pKa and determine pseudoisomers
model.pseudoisomers = rmfield(model.pseudoisomers,'met');

% Add number of hydrogens and charge for metabolites with no InChI
if any(~[model.pseudoisomers.success]) && printLevel>0
    fprintf('Assuming that metabolite species in model.metFormulas are representative for metabolites where pKa could not be estimated.\n');
end
nonphysicalMetSpecies = {};
for i = 1:length(model.mets)
    model_z = model.metCharges(i); % Get charge from model
    model_nH = numAtomsOfElementInFormula(model.metFormulas{i},'H'); % Get number of hydrogens from metabolite formula in model
    if ~model.pseudoisomers(i).success
        model.pseudoisomers(i).zs = model_z;
        model.pseudoisomers(i).nHs = model_nH;
        model.pseudoisomers(i).majorMSpH7 = true; % Assume species in model is the major (and only) metabolite species %RF: this seems dubious
    end
    if ~any(model.pseudoisomers(i).nHs == model_nH)
        nonphysicalMetSpecies = [nonphysicalMetSpecies; model.mets(i)];
    end
end
if ~isempty(nonphysicalMetSpecies)
    nonphysicalMetSpecies = unique(regexprep(nonphysicalMetSpecies,'\[\w\]',''));
    if printLevel>1
        fprintf('%s\n','#H in model.metFormulas does not match any of the species calculated mol file for metabolites:')
        for n=1:length(nonphysicalMetSpecies)
            fprintf('%s\n',nonphysicalMetSpecies{n});%,model.metFormulas{m});
        end
    end
end


function view = update3ViewLoc(view);
% view = update3ViewLoc(view);
%
% Updates the location of a volume 3-view window
% based on the settings of the slice view/orientation
% fields at the bottom of the window.

% 03/07/03 by ras

axiSlice=str2num(get(view.ui.sliceNumFields(1),'String'));
corSlice=str2num(get(view.ui.sliceNumFields(2),'String'));
sagSlice=str2num(get(view.ui.sliceNumFields(3),'String'));

loc = [axiSlice corSlice sagSlice];

view = refreshScreen(view,loc);

return


function [f] = ma_MinimizeMissionDuration(stateLog, eventID, celBodyData, maData)
%ma_maxTotalPropMass Summary of this function goes here
%   Detailed explanation goes here

    f = stateLog(end,1) - stateLog(1,1);
end


function write_html_dir(obj, output_dir)
% Write HTML coverage report for m-file collection
%
% write_html_dir(obj, output_dir)
%
% Inputs:
%   obj                 MOcovMFileCollection instance
%   output_dir          HTML output directory
%
% Notes:
%   - this function writes a file index.html, as well as node*.html files
%     for each individual MOcovMFile.

    if ~mocov_util_isfolder(output_dir)
        mkdir(output_dir);
    end

    monitor=obj.monitor;

    index_rel_fn='index.html';
    index_fn=fullfile(output_dir, index_rel_fn);

    mfiles=obj.mfiles;
    n=numel(mfiles);
    mfile_node_fns=cell(n,1);

    % write single HTML file for each m-file
    notify(monitor,sprintf('Writing html files in %s', output_dir));

    for k=1:n
        node_rel_fn=sprintf('node%d.html',k);
        mfile_node_fns{k}=node_rel_fn;

        mfile=mfiles{k};
        node_fn=fullfile(output_dir, node_rel_fn);
        write_html(mfile, node_fn, index_rel_fn);

        msg=sprintf('Written to %s', node_fn);
        notify(monitor,'.',msg);
    end

    % write index HTML file
    write_index_html(index_fn, mfiles, mfile_node_fns);
    msg=sprintf('Index written to %s\n', index_fn);
    notify(monitor,msg);

function write_index_html(output_fn, mfiles, mfile_node_fns)
    % build an index html file

    fid=fopen(output_fn,'w');
    cleaner=onCleanup(@()fclose(fid));

    fprintf(fid,['<!DOCTYPE html>\n'...
                        '<title>Coverage</title>'...
                        '
\n']);
    fprintf(fid,['
Lines	Executable	'...
                    'Executed	Coverage	'...
                    'File
\n']);

    stats=get_stats(mfiles);

    [unused,i]=sort(stats(:,4));

    n_files=numel(mfiles);

    % pattern with placeholders for:
    % - number of lines
    % - number of executable lines
    % - number of executed lines
    % - string describing the row
    row_pat=['
%d	'...
                        '%d	'...
                        '%d	'...
                        '%.1f%%	'...
                        '%s
\n'];

    % add summary line at top
    overall_stats=sum(stats,1);
    overall_stats(4)=100*overall_stats(3)/overall_stats(2);
    summary_str=sprintf('%d files',n_files);

    fprintf(fid,row_pat,overall_stats,summary_str);

    % add row for each file
    for k=1:numel(mfiles)
        mfile=mfiles{i(k)};
        stat=stats(i(k),:);
        node_fn=mfile_node_fns{i(k)};

        mfile_name=get_filename(mfile);
        mfile_anchor=sprintf('%s',node_fn,mfile_name);

        fprintf(fid,row_pat,stat,mfile_anchor);
    end

    % add summary line at bottom
    fprintf(fid,row_pat,overall_stats,summary_str);

    fprintf(fid,'
');

function stats=get_stats(mfiles)
    n=numel(mfiles);
    stats=zeros(n,4);
    for k=1:n
        mfile=mfiles{k};

        executable=get_lines_executable(mfile);
        executed=get_lines_executed(mfile);

        executed(~executable)=false;

        if sum(executable)==0
            coverage=100;
        else
            coverage=100*sum(executed)/sum(executable);
        end

        stat=[numel(executable),...
                     sum(executable),...
                     sum(executed),...
                     coverage];
        stats(k,:)=stat;
    end


%kcpRGBNTSCtoI1I2I3 'converts an image from RGB NTSC to I1I2I3 '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros cpRGBNTSCtoI1I2I3.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'First Input data object'
% OutputFile: o 'Output', required: 'Resulting output data object'
%
% Example: o = kcpRGBNTSCtoI1I2I3(i, {'i','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% cpRGBNTSCtoI1I2I3 - converts an image from RGB NTSC to I1I2I3
%
%  DESCRIPTION
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1997 Rafael Santos. Khoros (C) Khoral Research, Inc.
%

function varargout = kcpRGBNTSCtoI1I2I3(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kcpRGBNTSCtoI1I2I3(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'o', '__output'};
maxval={0,0};
minval={0,0};
istoggle=[0,0];
was_set=istoggle * 0;
paramtype={'InputFile','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'ckfromRGBNTSC"  -i1i2i3'],Inputs,narglist);


function [s,it]=display(a,tab,it)

  global display_tree_depth;
  if isempty(display_tree_depth) display_tree_depth=100; end;
  global display_tree_tab_step;
  if isempty(display_tree_tab_step) display_tree_tab_step=3; end;
  global display_tree_show_brackets;
  if isempty(display_tree_show_brackets) display_tree_show_brackets=1; end;

  % ----- tabulation stuff ----------
  print=0;  if nargin==1  tab=0; print=1; it=[]; end;
  tab_step=display_tree_tab_step;
  % ------ display tree ------------
  [s,it]=display(a.algorithm,tab,it);
  if  display_tree_show_brackets
    s=[s ones(1,tab+min(2,tab_step))*32 '{\n' ];
  end
  tab=tab+tab_step;
  i=length(it); v=it{i}; v=[v 1]; it{i}=v; %% add 1 to last row
  for i=1:length(a.child)
     [st it]=display(a.child{i},tab,it);
     if length(it{length(it)})<display_tree_depth
      s =[s ones(1,tab)*32 st];
     end

     j=length(it); v=it{j}; v(length(v))=v(length(v))+1;
     it{j}=v; %% increment last row
  end
  if  display_tree_show_brackets
    if  length(it{length(it)})>=display_tree_depth
     s=[s ones(1,tab)*32 '...\n'];
    end
    s =[s ones(1,tab-tab_step+min(2,tab_step))*32 '}\n' ];
  end
  tab=tab-tab_step;
  %% pop index of last item
  i=length(it); v=it{length(it)}; v=v(1:length(v)-1); it{i}=v;
  if print
   s=s(1:length(s)-2); % remove last carriage return
   it=deal(it(1:length(it)-1)); % remove last index to tree
   disp(sprintf(char(s)));
  end


function clim_positive(hax)

if nargin < 1
  hax = gca;
end

cl = get(hax, 'clim');
cl = max(cl);
set(hax, 'clim', [0 cl]);


function save_vt_history_data(fileName, data)
%     NeuroSLAM System Copyright (C) 2018-2019
%     NeuroSLAM: A Brain inspired SLAM System for 3D Environments
%
%     Fangwen Yu (www.yufangwen.com), Jianga Shang, Youjian Hu, Michael Milford(www.michaelmilford.com)
%
%     The NeuroSLAM V1.0 (MATLAB) was developed based on the OpenRatSLAM (David et al. 2013).
%     The RatSLAM V0.3 (MATLAB) developed by David Ball, Michael Milford and Gordon Wyeth in 2008.
%
%     Reference:
%     Ball, David, Scott Heath, Janet Wiles, Gordon Wyeth, Peter Corke, and Michael Milford.
%     "OpenRatSLAM: an open source brain-based SLAM system." Autonomous Robots 34, no. 3 (2013): 149-176.
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.

    fileID = fopen(fileName,'w');
    len = length(data(:,1));
    for ind = 1 : len
        fprintf(fileID,'%d %d \r\n',ind,data(ind, :));
    end
    fclose(fileID);
end


function res = hlp_varargin2struct(args, varargin)
% struct = hlp_varargin2struct(varargin, defaults)
% converts a list of name-value pairs into a struct with values assigned to names
%
% In:
%   varargin: cell array of alternating names and values
%             instead of any name-value pair, a struct can be given, which is substituted in-place into the argument list
%   defaults: optional name-value list of defaults; if a default value is '<mandatory>', an error
%             is raised when no value is specified in varargin
%             instead of any name-value pair, a struct can be specified, which is substituted in-place into the argument list
%
% Notes:
%   some parameters may have multiple alternative names, which shall be remapped to the
%   standard name within opts; alternative names are given together with the defaults,
%   by specifying a cell array of names instead of the name, as in the following example:
%   ... ,{'standard_name','alt_name_x','alt_name_y'}, default_value, ...
%
% Out:
%   struct: structure with values assigned to names
%
%                               Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                               2010-04-05

res = struct();
% it is allowed to specify just a struct in place of the varargin clause... (for further convenience)
if isstruct(args)
    args = {args}; end
% splice all substructs into the name-value lists
args = flatten_structs(args);
varargin = flatten_structs(varargin);

% go through the defaults (varargin) and apply them (also, build a remapping table for additional names along the way)
default_name_for = struct();
for i=1:2:length(varargin)
    if iscell(varargin{i})
        % alternative names were specified, remember them
        for j=2:length(varargin{i})
            default_name_for.(varargin{i}{j}) = varargin{i}{1}; end
        varargin{i} = varargin{i}{1};
    end
    try
        res.(varargin{i}) = varargin{i+1};
    catch
        error(['invalid field name specified in defaults: ' exp_fullform(varargin{i})]);
    end
end

% go through the arguments and override
for i=1:2:length(args)
    if isfield(default_name_for,args{i})
        % rewrite alternative names
        args{i} = default_name_for.(args{i}); end
    try
        res.(args{i}) = args{i+1};
    catch
        error(['invalid field name specified in args: ' exp_fullform(args{i})]);
    end
end

% check for missing but mandatory args
for fn = fieldnames(res)'
    if strcmp(res.(fn{1}), '<mandatory>')
        error(['the parameter ' fn{1} ' was unspecified but is mandatory']); end
end

% substitute any structs in place of a name-value pair into the name-value list
function outargs = flatten_structs(inargs)
outargs = {};
k=1;
while k <= length(inargs)
    if isstruct(inargs{k})
        for fn=fieldnames(inargs{k})'
            outargs([end+1 end+2]) = {fn{1} inargs{k}.(fn{1})}; end
        k = k+1;
    else
        outargs([end+1 end+2]) = inargs([k k+1]);
        k = k+2;
    end
end
if mod(length(outargs),2)
    error('a non-matching number of names and values was specified.'); end


function sys = double(X)
%double           Overloaded.

X = flatten(X);
nlmi = length(X.LMIid);

if (nlmi == 0)
 sys = NaN;
end

if nlmi>1
 error('Double not applicable on list of constraints')
end

sys = double(X.clauses{1}.data);