function varargout = metCompareGUI(varargin)
% Creates a comparison GUI for deciding which metabolite are
% in a new or existing reaction.
% Called by `metCompare`, calls `findMetMatch`, `colText`, `addMetInfo`.
%
% USAGE:
%
%    [RxnInfo, stopFlag] = metCompareGUI(RxnInfo)
%
% INPUTS
%    RxnInfo:     Structure containing relevent info. See `metCompare` function
%                 `fillRxnInfo`.
%
% OPTIONAL OUTPUTS:
%    RxnInfo:     Update structure.
%    stopFlag:    Indicates if more metabolites need to be reviewed
%    CMODEL:      global input
%    TMODEL:      global input
%
% Please cite:
% `Sauls, J. T., & Buescher, J. M. (2014). Assimilating genome-scale
% metabolic reconstructions with modelBorgifier. Bioinformatics
% (Oxford, England), 30(7), 1036?8`. http://doi.org/10.1093/bioinformatics/btt747
%
% ..
%    Edit the above text to modify the response to help addMetInfo
%    Last Modified by GUIDE v2.5 06-Dec-2013 14:19:28
%    This file is published under Creative Commons BY-NC-SA.
%
%    Correspondance:
%    johntsauls@gmail.com
%
%    Developed at:
%    BRAIN Aktiengesellschaft
%    Microbial Production Technologies Unit
%    Quantitative Biology and Sequencing Platform
%    Darmstaeter Str. 34-36
%    64673 Zwingenberg, Germany
%    www.brain-biotech.de

gui_Singleton = 1; % Begin initialization code - DO NOT EDIT
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @metCompareGUI_OpeningFcn, ...
                   'gui_OutputFcn',  @metCompareGUI_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
% End initialization code - DO NOT EDIT

% --- Executes just before metCompareGUI is made visible.
function metCompareGUI_OpeningFcn(hObject, eventdata, handles, varargin)

% Declare globals
global CMODEL TMODEL

% workaround to enable java handles
axes(handles.axes1)
set(handles.axes1, 'Visible', 'off')

% Choose default command line output for metCompareGUI
handles.output = hObject;

% Load rxn, metabolite, and match data.
handles.RxnInfo = varargin{1};

% Populate reaction info.
cModelName = CMODEL.description ;
set(handles.staticCmodel, 'String', cModelName) ;
Tmodels = fieldnames(TMODEL.Models) ;
if length(Tmodels) == 1
    set(handles.staticTmodel, 'String', Tmodels{1})
end
rxnNum = num2str(handles.RxnInfo.rxnIndex) ;

% Set the reaction number if the metabolites all come from a reaction.
if handles.RxnInfo.rxnIndex
    set(handles.CRxnNumField, 'String', rxnNum) ;
else
    % Otherwise change how GUI appears.
    set(handles.staticCRxnNum, 'String', 'Met Number:') ;
    set(handles.staticRxnName, 'String', 'In Crxn(s):') ;
    set(handles.staticRxnEquation, 'String', 'In Trxn(s):') ;
    set(handles.staticTRxnNum, 'String', 'Current match in T.') ;
    set(handles.staticNewRxnEquation, 'Visible', 'Off') ;
    set(handles.newRxnEquationField, 'Visible', 'Off') ;
    % And disable the ability to skip checking the mets.
    set(handles.buttonSkip, 'Enable', 'off') ;
end
rxnName = handles.RxnInfo.rxnName ;
set(handles.rxnNameField, 'String', rxnName) ;
rxnEq = handles.RxnInfo.matchRxnEquation ;
set(handles.rxnEquationField, 'String', rxnEq) ;

rxnMatch = handles.RxnInfo.rxnMatch ;

% Indicate if the reaction is new, has already been matched, or N/A.
if ~rxnMatch && handles.RxnInfo.rxnIndex
    set(handles.TRxnNumField, 'String', 'New Rxn') ;
elseif ~rxnMatch && ~handles.RxnInfo.rxnIndex
    set(handles.TRxnNumField, 'String', 'N/A') ;
else
    set(handles.TRxnNumField, 'String', num2str(rxnMatch)) ;
    % You cannot choose new metabolite for reactions with matches.
    set(handles.chooseNew, 'Enable', 'off') ;
end

% List unseen metabolites.
if handles.RxnInfo.rxnIndex
  handles.RxnInfo.unseen = ~handles.RxnInfo.goodMatch ;
else
    % If just comparing metabolites, do not mark any as seen.
    handles.RxnInfo.unseen = ones(handles.RxnInfo.nMets, 1) ;
end

% Put metabolite names in the popup menu.
set(handles.popup_met, 'String', handles.RxnInfo.metData(1, :)) ;

% Populate first metabolite info and matches
% nowMet is the index of the metabolite in RxnInfo. It is selected for by
% the first metabolite that has not been seen.
handles.RxnInfo.nowMet = find(handles.RxnInfo.unseen == 1, 1) ;
if isempty(handles.RxnInfo.nowMet)
    handles.RxnInfo.nowMet = 1 ;
end
set(handles.popup_met, 'Value', handles.RxnInfo.nowMet) ;
popup_met_Callback(handles.popup_met, eventdata, handles)

% Create reaction equation based of best match suggestions.
handles = metMatchRxnEquation(hObject, handles) ;

% Update stats
fillStats(handles)

% Sets the cell selection callback feature for the uitables.
set(handles.uitable_matches, 'CellSelectionCallback', {@matchMetCallback, ...
                                                     handles})
set(handles.uitable_met, 'CellSelectionCallback', {@metTableCallback, ...
                                                 handles})

% Update handles structure ;
guidata(hObject, handles) ;

% UIWAIT makes metCompareGUI wait for user response (see UIRESUME)
uiwait(handles.figure1);
end

% --- Outputs from this function are returned to the command line.
function varargout = metCompareGUI_OutputFcn(hObject, eventdata, handles)
% Get default command line output from handles structure
handles.output = handles.RxnInfo ;
varargout{1} = handles.output ;
varargout{2} = handles.stopFlag ;
close
end

%% Button and Input Change Functions
% --- Executes on button press in buttonChoose.
function handles = buttonChoose_Callback(hObject, eventdata, handles)
global CMODEL
RxnInfo = handles.RxnInfo ;
% nowMetIndex is the index of the metabolite in CMODEL
nowMetIndex = RxnInfo.metIndex(RxnInfo.nowMet) ;

choice = get(get(handles.chooseMatch, 'SelectedObject'), 'Tag') ;

matchScores = RxnInfo.matchScores{RxnInfo.nowMet} ;
matchIndex  = RxnInfo.matchIndex{RxnInfo.nowMet} ;
% [matchScores, matchIndex] = findMetMatch(nowMetIndex,RxnInfo.rxnMatch) ;

switch choice
    case 'choose1'
        RxnInfo.matches(RxnInfo.nowMet) = matchIndex(1) ;
    case 'choose2'
        RxnInfo.matches(RxnInfo.nowMet) = matchIndex(2) ;
    case 'choose3'
        RxnInfo.matches(RxnInfo.nowMet) = matchIndex(3) ;
    case 'choose4'
        RxnInfo.matches(RxnInfo.nowMet) = matchIndex(4) ;
    case 'choose5'
        RxnInfo.matches(RxnInfo.nowMet) = matchIndex(5) ;
    case 'chooseNew'
        % if metabolite has been declared new, ensure that all reactions it is
        % involved in are also declared new.
        nowRxnIndex = find(CMODEL.S(nowMetIndex,:) ~= 0) ;
        if sum(RxnInfo.rxnList(nowRxnIndex) > 0) > 0

            set(handles.errorField, 'String',...
                [CMODEL.mets{nowMetIndex} 'Cannot be new, it is in matched Rxns.' ...
                num2str(nowRxnIndex(RxnInfo.rxnList(nowRxnIndex) > 0)) ])
            return
        end
        RxnInfo.matches(RxnInfo.nowMet) = 0 ;
    case 'chooseOther'
         newRxnIndex = str2double(get(handles.chooseOtherNo, 'String')) ;
         if newRxnIndex > 0
             RxnInfo.matches(RxnInfo.nowMet)
         else
             set(handles.errorField, 'String',...
                'Please enter a valid Rxn number.')
             return
         end
    otherwise
end

% Add data back to handle.
RxnInfo.matches = RxnInfo.matches ;

% Indicate the user has reviewed this match.
RxnInfo.goodMatch(RxnInfo.nowMet) = 1 ;

% Update metabolite as seen.
RxnInfo.unseen(RxnInfo.nowMet) = 0 ;

% Go to next metabolite in the list that has not been seen.
val = find(RxnInfo.unseen == 1, 1) ;
% If all matches are good then just go to the first metabolites.
if isempty(val)
    val = 1 ;
end
set(handles.popup_met, 'Value', val) ;

% Update handles.
handles.RxnInfo = RxnInfo ;
guidata(hObject, handles) ;

% Update new reaction equation. This also checks if the decision was good.
handles = metMatchRxnEquation(hObject, handles) ;

% Go to next met.
popup_met_Callback(handles.popup_met, eventdata, handles)
end

% --- Executes on selection change in popup_met.
function popup_met_Callback(hObject, eventdata, handles)
% Get index of choice and associate with met, save to handles.
val = get(hObject, 'Value') ;
handles.RxnInfo.nowMet = val ;
guidata(hObject, handles) ;
% Populate table with met and match information.
populateMetTables(handles) ;
end

% --- Executes on selection of item in uitable_matches
function matchMetCallback(hObject, eventdata, handles)
global TMODEL
if ~isempty(eventdata.Indices)
    % Declare variables
    RxnInfo = handles.RxnInfo ; % For convenience.
    RxnInfo.nowMet = get(handles.popup_met, 'Value') ;
    nowMetIndex = RxnInfo.metIndex(RxnInfo.nowMet) ;
    matchScores = RxnInfo.matchScores{RxnInfo.nowMet} ;
    matchIndex  = RxnInfo.matchIndex{RxnInfo.nowMet} ;
%     [matchScores,matchIndex] = findMetMatch(nowMetIndex,RxnInfo.rxnMatch) ;

    % Set match reaction number based on column clicked.
    set(handles.chooseOtherNo,'String', 'Met #')
    matchCol = eventdata.Indices(2) ;
    if matchCol == 1
        set(handles.chooseMatch, 'SelectedObject', handles.choose1) ;
    elseif matchCol == 2
        set(handles.chooseMatch, 'SelectedObject', handles.choose2) ;
    elseif matchCol == 3
        set(handles.chooseMatch, 'SelectedObject', handles.choose3) ;
    elseif matchCol == 4
        set(handles.chooseMatch, 'SelectedObject', handles.choose4) ;
    elseif matchCol == 5
        set(handles.chooseMatch, 'SelectedObject', handles.choose5) ;
    else
        set(handles.chooseMatch, 'SelectedObject', handles.chooseOther) ;
        set(handles.chooseOtherNo, 'String', num2str(matchIndex(matchCol)))
    end

    % Opens up KEGG ID site if KEGGID is selected
    matchRow = eventdata.Indices(1) ;
    % If we are in the right row
    if matchRow == 7
       % Grab the ID.
       cID = TMODEL.metKEGGID{matchIndex(matchCol)} ;
       if ~isempty(cID)
           % Enforce the cID is the right length.
           cID = cID(1:6) ;
           % Launch website.
           KEGGIDurl = ['http://www.genome.jp/dbget-bin/www_bget?' cID] ;
           web(KEGGIDurl, '-new', '-noaddressbox', '-notoolbar')
       end
    end
end
end

% --- Executes on selection of item in uitable_met
function metTableCallback(hObject, eventdata, handles)
if ~isempty(eventdata.Indices)
    RxnInfo.nowMet = get(handles.popup_met, 'Value') ;
    % Opens up KEGG ID site if KEGGID is selected
    matchRow = eventdata.Indices(1) ;
    % If we are in the right row.
    if matchRow == 7
       % Grab the ID.
       cID = handles.RxnInfo.metData{5, RxnInfo.nowMet} ;
       if ~isempty(cID)
           % Enforce the cID is the right length.
           cID = cID(1:6) ;
           % Launch browser.
           KEGGIDurl = ['http://www.genome.jp/dbget-bin/www_bget?' cID] ;
           web(KEGGIDurl, '-new', '-noaddressbox', '-notoolbar')
       end
    end
end
end

% --- Executes on button press in buttonAddMets.
function buttonAddMets_Callback(hObject, eventdata, handles)
% Do not stop the next iteration of calling metCompare.
handles.stopFlag = 0 ;
guidata(hObject, handles) ;
% Allows the wait command to be suspended, closing the GUI.
uiresume(handles.figure1)
end

% --- Executes on button press in buttonSkip.
function buttonSkip_Callback(hObject, eventdata, handles)
% Stop the next iteration of calling metCompare.
handles.stopFlag = 1 ;
guidata(hObject, handles) ;
% Allows the wait command to be suspended, closing the GUI.
uiresume(handles.figure1)
end

% --- Executes when selected object is changed in chooseMatch. NOT USED.
function chooseMatch_SelectionChangeFcn(hObject, eventdata, handles)
% hObject    handle to the selected object in chooseMatch
% eventdata  structure with the following fields (see UIBUTTONGROUP)
%	EventName: string 'SelectionChanged' (read only)
%	OldValue: handle of the previously selected object or empty if none was selected
%	NewValue: handle of the currently selected object
% handles    structure with handles and user data (see GUIDATA)
end

% --- Executes on change in buttonChoose. NOT USED.
function chooseOtherNo_Callback(hObject, eventdata, handles)
% hObject    handle to chooseOtherNo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
end

% --- Executes on change in editNMatches. NOT USED.
function editNMatches_Callback(hObject, eventdata, handles)
% hObject    handle to editNMatches (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
end

%% Subfunctions
% Populates both met and match tables.
function populateMetTables(handles)
% Pull out variables for easier referencing. Declare globals.
RxnInfo = handles.RxnInfo ;
global CMODEL TMODEL

% resize Row headers uitable_met
jscroll = findjobj(handles.uitable_met) ;
rowHeaderViewport = jscroll.getComponent(4) ;
rowHeader = rowHeaderViewport.getComponent(0);
newWidth = 125 ;
rowHeaderViewport.setPreferredSize(java.awt.Dimension(newWidth, 0));
height = rowHeader.getHeight;
rowHeader.setPreferredSize(java.awt.Dimension(newWidth, height));
rowHeader.setSize(newWidth,height);
% format left
rend = rowHeader.getCellRenderer(1, 0);
rend.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
jscroll.repaint %apply changes

nowMetIndex = RxnInfo.metIndex(RxnInfo.nowMet) ;
metDataTable = RxnInfo.metData(:, RxnInfo.nowMet) ;
nowMetDataTable = [ {''} ; ...
                     metDataTable{1} ; ...
                     CMODEL.mets{nowMetIndex}(end-1) ; ...
                     metDataTable(2:end)] ;

% Index of the met in CMODEL.
nMatches = str2double(get(handles.editNMatches, 'String')) ;
metMatchTable = cell(7, nMatches) ;
if nMatches <= RxnInfo.nMets
    matchScores = RxnInfo.matchScores{RxnInfo.nowMet} ;
    matchIndex  = RxnInfo.matchIndex{RxnInfo.nowMet} ;
else
    [matchScores, matchIndex] = findMetMatch(nowMetIndex, RxnInfo.rxnMatch) ;
end
for iMatch = 1:nMatches
    metMatchTable{1, iMatch} = num2str(matchScores(iMatch) / ...
                                      sum(matchScores(1:nMatches)) ) ;
    metMatchTable{2, iMatch} = [TMODEL.mets{matchIndex(iMatch)}, ', ', ...
                               num2str(matchIndex(iMatch))] ;
    metMatchTable{3, iMatch} = TMODEL.mets{matchIndex(iMatch)}(end-1) ;
    metMatchTable{4, iMatch} = TMODEL.metNames{matchIndex(iMatch)} ;
    metMatchTable{5, iMatch} = TMODEL.metFormulas{matchIndex(iMatch)} ;
    metMatchTable{6, iMatch} = num2str(TMODEL.metCharge(matchIndex(iMatch))) ;
    metMatchTable{7, iMatch} = TMODEL.metKEGGID{matchIndex(iMatch)} ;
    metMatchTable{8, iMatch} = TMODEL.metSEEDID{matchIndex(iMatch)} ;
    metMatchTable{9, iMatch} = TMODEL.metID{matchIndex(iMatch)} ;
end

% weed out accidently remaining cells in cells
for iac = 1:numel(nowMetDataTable)
    if iscell(nowMetDataTable{iac})
        nowMetDataTable{iac} = [nowMetDataTable{iac}{:}] ;
    end
end
for iac = 1:numel(metMatchTable)
    if iscell(metMatchTable{iac})
        metMatchTable{iac} = [metMatchTable{iac}{:}] ;
    end
end

% If compartment doesn't match or if score is below 0.3
if ~strcmpi(metMatchTable{3, 1}, nowMetDataTable{3}) ...
        || str2double(metMatchTable{1, 1}) < 0.3
    set(handles.chooseNew, 'Value', 1)
else
    set(handles.choose1, 'Value', 1)
end

% Set color of good and bad correspondence in table.
colOptions = {'blue', 'red'} ;
for ic = 1:size(metMatchTable, 2)
    metMatchTable{1, ic} = ['<text>  ' metMatchTable{1,ic} ...
        '</text>             '] ;
    metMatchTable{2, ic} = colText(['  ' metMatchTable{2, ic}], colOptions{ ...
        2 - strcmpi(metMatchTable{2, ic}(1:strfind(metMatchTable{2, ic}, ...
                                                ', ')-1), ...
        nowMetDataTable{2, 1}(1:strfind(nowMetDataTable{2, 1}, ',') - 1))}) ;
    for ir = 3:size(metMatchTable, 1)
        if ~isempty(metMatchTable{ir, ic}) && ...
                ~isempty(nowMetDataTable{ir, 1})
            metMatchTable{ir, ic} = colText(['  ' metMatchTable{ir, ic}], ...
                colOptions{1 + isempty(strfind(metMatchTable{ir, ic}, nowMetDataTable{ir, 1}))}) ;
        else
            metMatchTable{ir, ic} = ['  ' metMatchTable{ir, ic}] ;
        end
    end
end

% If we are just comparing metabolites, put in information about what
% reactions that metabolite is involved in.
if ~RxnInfo.rxnIndex
    % Metabolite number in C.
    set(handles.CRxnNumField, 'String', nowMetIndex)
    % Current match in T.
    set(handles.TRxnNumField, 'String', RxnInfo.metList(nowMetIndex)) ;
    % Reactions it is involved in C.
    involvedRxns = find(CMODEL.S(nowMetIndex, :)) ;
    set(handles.rxnNameField, 'String', involvedRxns)
    % Reactions that it is matched to in T.
    set(handles.rxnEquationField, 'String', ...
        num2str(RxnInfo.rxnList(involvedRxns))) ;

    % Also give a hint as how best to proceed.
    if isempty(involvedRxns)
        hintString = 'Metabolite not in C, trivial problem, declare new.' ;
        set(handles.chooseNew, 'Value', 1)
    elseif ~RxnInfo.rxnList(involvedRxns)
    	hintString = ...
            'Metabolite not in a reaction matched to T, declare new' ;
        set(handles.chooseNew, 'Value', 1)
    else
        hintString = ...
            'Metabolite matched to a reaction in T. Best to keep match.' ;
        set(handles.choose1, 'Value', 1)
    end
    set(handles.errorField, 'String', hintString)
end

set(handles.uitable_matches, 'Data', metMatchTable, 'Fontsize', 10) ;

for ic = 1:size(nowMetDataTable, 2)
    for ir = 1:size(nowMetDataTable, 1)
        % add leading whitespace to all cells
        nowMetDataTable{ir, ic} = ['  ' nowMetDataTable{ir, ic}] ;
    end
end
set(handles.uitable_met, 'Data', nowMetDataTable, 'Fontsize', 10) ;

% Update unseen mets field
unseenMets = '' ;
for iMet = 1:RxnInfo.nMets
    if handles.RxnInfo.unseen(iMet) == 1
        unseenMets = [unseenMets RxnInfo.metData{1, iMet} '; '] ;
    end
end
set(handles.unseenMetsField, 'String', unseenMets) ;

end

% Makes reaction equation based on current best matches and checks the
% validity of the choices.
function handles = metMatchRxnEquation(hObject, handles)
% Declare some variables just to not have to type handles so much.
global CMODEL TMODEL
RxnInfo = handles.RxnInfo ;

% If metabolites come from a reaction, make the new equation.
% Disable choosing mets until checks have passed.
set(handles.buttonAddMets, 'Enable', 'off') ;
if RxnInfo.rxnIndex
    % Build the equation.
    reactants = cell(1, 1) ;
    products = cell(1, 1) ;
    for iMet = 1:RxnInfo.nMets
        % Reactants
        if RxnInfo.metStoichs(iMet) < 0
            % First reactant.
            if isempty(reactants{1})
               % Add Stoich
               reactants{1} = num2str(abs(RxnInfo.metStoichs(iMet))) ;
               % If a match has been found in TMODEL, choose that name.
               if RxnInfo.matches(iMet) ~= 0 && ...
                       (RxnInfo.matches(iMet) < length(TMODEL.mets))
                   reactants{2} = [' ' ...
                       TMODEL.mets{RxnInfo.matches(iMet)} ' '];
               else % Add met name from CMODEL.
                   reactants{2} = [' ' ...
                       CMODEL.mets{RxnInfo.metIndex(iMet)} ' '] ;
               end
            % nth reactants.
            else
               reactants{end + 1} = ' + ' ;
               reactants{end + 1} = num2str(abs(RxnInfo.metStoichs(iMet))) ;
               if RxnInfo.matches(iMet) ~= 0 && ...
                       (RxnInfo.matches(iMet) < length(TMODEL.mets))
                   reactants{end + 1} = [' ' ...
                                   TMODEL.mets{RxnInfo.matches(iMet)} ' '];
               else
                   reactants{end + 1} = [' ' ...
                             CMODEL.mets{RxnInfo.metIndex(iMet)} ' '] ;
               end
            end
        % Products
        else
            % First product
            if isempty(products{1})
                if RxnInfo.rev == 1
                    products{1} = '<==> ' ;
                else
                    products{1} = '--> ' ;
                end
                % Add stoich.
                products{2} = num2str(abs(RxnInfo.metStoichs(iMet))) ;
                % Add name.
                if RxnInfo.matches(iMet) ~= 0 && ...
                        (RxnInfo.matches(iMet) < length(TMODEL.mets))
                   products{3} = [' ' TMODEL.mets{RxnInfo.matches(iMet)}] ;
                else
                   products{3} = [' ' ...
                             CMODEL.mets{RxnInfo.metIndex(iMet)} ' '] ;
                end
            else % nth product.
                products{end + 1} = ' + ' ;
                products{end + 1} = num2str(abs(RxnInfo.metStoichs(iMet))) ;
                if RxnInfo.matches(iMet) ~= 0 && ...
                       (RxnInfo.matches(iMet) < length(TMODEL.mets))
                   products{end + 1} = [' ' ...
                                  TMODEL.mets{RxnInfo.matches(iMet)} ' '] ;
                else
                   products{end + 1} = [' ' ...
                             CMODEL.mets{RxnInfo.metIndex(iMet)} ' '] ;
                end
            end
        end
    end
    % If there were no products, must be exchange reaction.
    if isempty(products{1})
        products{1} = '-->' ;
    end
    % Combine both halves of the equation and print to field.
    matchRxnEquation = [reactants{1, :} products{1, :} ] ;
    set(handles.newRxnEquationField, 'String', matchRxnEquation) ;
    handles.RxnInfo.matchRxnEquation = matchRxnEquation ;

    % NaN in metList create problem, so remove them (really, they shouldn't
    % be there in the first place)
    RxnInfo.metList(isnan(RxnInfo.metList)) = 0 ;

    % Set addReaction button off, then check if all the mets in the
    % reaction have good matches, then allowing the user to add the
    % reaction. Also, check for errors.
    errorString = 'Review required.' ;
    bgcolor = [0.7 0.7 0.7] ;
    % All metabolites must be good matches and new metabolites must be
    % reviewed.
    if ~ismember(1, RxnInfo.unseen) && ~ismember(0, RxnInfo.goodMatch)
        errorString = 'All clear.' ;
        set(handles.buttonAddMets, 'Enable', 'on') ;
    else
        for iMet = 1:RxnInfo.nMets
            if RxnInfo.metList(RxnInfo.metIndex(iMet)) ~= ...
                    RxnInfo.matches(iMet) && ...
                    RxnInfo.metList(RxnInfo.metIndex(iMet))
                errorString = ['ERROR: cMet ' ...
                    num2str(RxnInfo.metIndex(iMet)) ...
                    ' already assigned to tMet ' ...
                    num2str(RxnInfo.metList(RxnInfo.metIndex(iMet))) ...
                    '.'] ;
                bgcolor = [1 0 0] ;
                set(handles.buttonAddMets, 'Enable', 'off') ;
            elseif ~RxnInfo.metList(RxnInfo.metIndex(iMet)) ...
                    && ~isempty(find(RxnInfo.metList ...
                    == RxnInfo.matches(iMet), 1)) ...
                    && RxnInfo.matches(iMet) ~= 0
                errorString = ['ERROR: Metabolite ' ...
                    num2str(RxnInfo.metIndex(iMet)) ...
                    's match (tMet ' ...
                    num2str(RxnInfo.matches(iMet)) ...
                    ') already matched to cMet ' ...
                    num2str(find(RxnInfo.metList ...
                    == RxnInfo.matches(iMet), 1)) ...
                    '.'] ;
                bgcolor = [1 0 0] ;
                set(handles.buttonAddMets, 'Enable', 'off') ;
            end
        end
    end
% Set the error bar color to indicate an error or not.
set(handles.errorField, 'String', errorString, 'BackgroundColor', bgcolor) ;
else
    if ~RxnInfo.unseen
        set(handles.buttonAddMets, 'Enable', 'on') ;
    end
end

guidata(hObject, handles) ;
end

% Update stats.
function fillStats(handles)
RxnInfo = handles.RxnInfo ;
rxnString = [num2str(length(find(RxnInfo.rxnList >= 0))) ' / ' ...
             num2str(length(RxnInfo.rxnList))] ;
metString = [num2str(length(find(RxnInfo.metList))) ' / ' ...
             num2str(length(RxnInfo.metList))] ;
set(handles.text_metsDeclared, 'String', metString)
set(handles.text_rxnsAdded, 'String', rxnString)
end

%% Object Creation Functions
function popup_met_CreateFcn(hObject, eventdata, handles)
% hObject    handle to popup_met (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

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

function chooseOtherNo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to chooseOtherNo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

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

function editNMatches_CreateFcn(hObject, eventdata, handles)
% hObject    handle to editNMatches (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

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

function pushbutton_addinfo_Callback(hObject, eventdata, handles)
nowmet = get(handles.popup_met, 'String') ;
nowmet = nowmet{get(handles.popup_met, 'Value')} ;
nowmet = regexp(nowmet, ',', 'split') ;
nowmet = str2double(nowmet{end}) ;
addMetInfo(nowmet)

popup_met_Callback(handles.popup_met, [], handles)

end


function GUI = sessionGUI_addSession(session);
%
% Add a new session to the current mrVista study.
%
%  GUI = sessionGUI_addSession(<session=dialog>);
%
% ras, 07/2006.
mrGlobals2;

if notDefined('session')            % dialog
    p = 'Select a first session to add to this study ';
    session = sessionSelectDialog(1, p);
end

% evaluate relative to the current study's parent dir, if specified
n = GUI.settings.study;
if ~isempty(GUI.studies(n).studyDir)
    session = fullfile(eval(GUI.studies(n).studyDir), session);
else
    session = fullpath(session);
end

%%%%% add to sepcified study list:
otherSessions = GUI.studies(n).sessions;
if ~isempty(cellfind(otherSessions, session))
	ok = setdiff(1:length(otherSessions), cellfind(otherSessions,session));
	otherSessions = otherSessions(ok);
end
GUI.studies(n).sessions = [session otherSessions];

if n ~= 1
    %%%%% also add to recent sessions list:
    % first, if this session was already there, remove it:
    GUI.studies(1).sessions = setdiff(GUI.studies(1).sessions, session);

    % now, add to top of the list:
	otherSessions = GUI.studies(1).sessions;
	if ~isempty(cellfind(otherSessions, session))
		ok = setdiff(1:length(otherSessions), cellfind(otherSessions,session));
		otherSessions = otherSessions(ok);
	end

    GUI.studies(1).sessions = [session otherSessions];
end

% restrict to a max # of recent sessions
maxRecentSessions = 50;
if length(GUI.studies(1).sessions) > maxRecentSessions
    GUI.studies(1).sessions = GUI.studies(1).sessions(1:maxRecentSessions);
end

studySave(GUI.studies);

% select the new session
GUI = sessionGUI_selectSession(session);

return


function set_debug(debuglevel)
    % SET_DEBUG set the debug level.
    %
    %    SET_DEBUG is used in conjunction with PRINT_DEBUG to control the verboseness of MATLAB output.
    %    You use it to specify the debug level (an integer) at which to display a certain message.
    %
    %    EXAMPLE:
    %    Set the debug level to 1:
    %        debug.set_debug(1)
    %
    %    See also debug.get_debug, debug.print_debug, setpref.

    % AUTHOR: Ronni Grapenthin and Glenn Thompson, UAF-GI
    % $Date$
    % $Revision$
    % Modified by Glenn Thompson: 2010-03-10: To use multiple levels of debug (0 = none, 1 = some, 2 = higher)
    % GT 20150916: the setpref doesn't seem to work now print_debug is
    % using persistent variable. ANd now print_debug(level) without a text
    % message sets level. So replace this:

        %setpref('runmode', 'debug', debuglevel);

    % with
        debug.print_debug(debuglevel);

end


function kern = ndsimKernExpandParamTransformSettings(kern, paramtransformsettings)

% NDSIMKERNEXPANDPARAMTRANSFORMSETTINGS Create kernel structure from SIM kernel's parameters' transform settings.
% FORMAT
% DESC returns a single input motif kernel structure filled with the
% parameters in the given vector. This is used as a helper function to
% enable parameters to be optimised in, for example, the NETLAB
% optimisation functions.
% ARG kern : the kernel structure in which the parameters are to be
% placed.
% ARG param : vector of parameters which are to be placed in the
% kernel structure.
% RETURN kern : kernel structure with the given parameters in the
% relevant locations.
%
% SEEALSO : simKernParamInit, simKernExtractParam, kernExpandParam
%
% COPYRIGHT : Neil D. Lawrence, 2006
%
% COPYRIGHT : Jaakko Peltonen, 2011

% KERN

%fprintf(1,'expanding SIM kernel param-transforms settings:\n');
%paramtransformsettings
%for k=1:length(paramtransformsettings),
%  paramtransformsettings{k}
%end;
%pause

if isfield(kern, 'options') ...
      && isfield(kern.options, 'isNegativeS') ...
      && kern.options.isNegativeS,
  if isfield(kern, 'gaussianInitial') && kern.gaussianInitial,
    % positive transformations for: inversewidth, initial variance
    for k=1:2,
      kern.transforms(k).transformsettings = paramtransformsettings{k};
    end;
  else
    % positive transformations for: inversewidth
    for k=1:1,
      kern.transforms(k).transformsettings = paramtransformsettings{k};
    end;
  end;

else
  if isfield(kern, 'gaussianInitial') && kern.gaussianInitial,
    % positive transformations for: inversewidth, kernel-variance,
    % initial variance
    for k=1:3,
      kern.transforms(k).transformsettings = paramtransformsettings{k};
    end;
  else
    % positive transformations for: inversewidth, kernel-variance
    for k=1:2,
      kern.transforms(k).transformsettings = paramtransformsettings{k};
    end;
  end;
end;


function [flag] = iswithin (X, bounds)
% legacy code
s = warning ('on');
warning ('*** The function `iswithin` is now deprecated and has been renamed `VBA_isInRange` (same syntax).')
warning (s);

% fallback
flag = VBA_isInRange (X, bounds);


function val = file2mat(a,varargin)
% Function for reading from file_array objects.
% FORMAT val = file2mat(a,ind1,ind2,ind3,...)
% a      - file_array object
% indx   - indices for dimension x (int32)
% val    - the read values
%
% This function is normally called by file_array/subsref
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: file2mat.m 1530 2008-04-30 19:28:22Z guillaume $

%-This is merely the help file for the compiled routine
error('file2mat.c not compiled - see Makefile');


i = 0;

i = i+1;
db(i).mouse_name    = 'M150329_MP009';
db(i).date          = '2015-04-29';
db(i).expts         = [4 5 6];
db(i).expred        = 3;
db(i).nchannels_red = 2;
db(i).nchannels     = 1;
db(i).gchannel      = 1;
db(i).nplanes       = 1;
db(i).planesToProcess = [1];
%
i = i+1;
db(i).mouse_name    = 'M150329_MP009';
db(i).date          = '2015-04-10';
db(i).expred        = 3;
db(i).expts         = [5 6 7 8 9 10 11];
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150326_MP008';
db(i).date          = '2015-04-09';
db(i).expred        = 2;
db(i).expts         = [3 4 6 8];
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150423_MP014';
db(i).date          = '2015-06-16';
db(i).expts         = [8];
db(i).expred        = 4;
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    =  'M150303_MP007';
db(i).date          = '2015-04-05';
db(i).expts         = [1 7 9 10 11 12 13 14];
db(i).expred        = 6;
db(i).nchannels_red = 2;
db(i).comments      = 'singleORIsat different pause lengths';
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    =  'M150303_MP007';
db(i).date          = '2015-04-04';
db(i).expts         = [3 5 6 10];
db(i).expred        = 4;
db(i).comments      = 'multiGRAT slow, fast and textures';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    =  'M150326_MP008';
db(i).date          = '2015-04-11';
db(i).expts         = [4 6 7 9 10 11 12 14];
db(i).expred        = 5;
db(i).comments      = 'all sorts of crazy stims with SAT';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150326_MP008';
db(i).date          = '2015-04-16';
db(i).expts         = [1 3 5];
db(i).expred        = 2;
db(i).comments      = 'stimGRATfast not biased / biased';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150329_MP009';
db(i).date          = '2015-04-09';
db(i).expts         = [1 3];
db(i).expred        = 2;
db(i).comments      = 'multiGRAT, have not validated the channels';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150329_MP009';
db(i).date          = '2015-04-25';
db(i).expts         = [1 3 4];
db(i).expred        = 2;
db(i).comments      = 'fastgratings2';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150329_MP009';
db(i).date          = '2015-04-27';
db(i).expts         = [3 5 6];
db(i).expred        = 4;
db(i).comments      = 'fast gratings unbiased / biased';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;

i = i+1;
db(i).mouse_name    = 'M150422_MP012';
db(i).date          = '2015-05-20';
db(i).expts         = [4];
db(i).expred        = 4;
db(i).comments      = 'test registration types';
db(i).nchannels_red = 2;
db(i).nchannels = 1;
db(i).gchannel = 1;
db(i).nplanes = 1;


function [] = ReqName_callback(block)

% Callback processing function for mask parameter
% - number of Preconditions used in the Requirment Name Set
set_param(block, 'LinkStatus', 'none');
load_system('Simulink'); % Load Simulink library (background)
load_system('MIL_Test');

No = str2double(get_param(block,'No')); % Get # of Reqs
OldNo = length(find_system(block, 'regexp', 'on','LookUnderMasks','all','Name','<Precondition name>'));

% Add or remove model items
for i = 1:max(No,OldNo)
    if OldNo > No && i > No && i <= OldNo % Remove
        % Remove lines
        set_param([block '/switch <signal1>'], 'Inputs', num2str(No+1));
        PreLines = get_param([block '/<Precondition name>' num2str(i)],'LineHandles');

        delete_line(PreLines.Inport(1));
        delete_line(PreLines.Outport(2));

        % Remove blocks
        delete_block([block '/<Precondition name>' num2str(i)]);

    elseif No > OldNo && i > OldNo && i <= No % Add
        % Add blocks
        add_block('MIL_Test/Test Data/Test Data Architecture/<Test data generator>/<Requirement name>/<Precondition name>',[block '/<Precondition name>' num2str(i)]);
        set_param([block '/<Precondition name>' num2str(i)], 'LinkStatus', 'none');
        if i == 2
             pos = get_param([block '/<Precondition name>'], 'Position');
        else pos = get_param([block '/<Precondition name>' num2str(i-1)], 'Position');
        end
        pos1 = pos(1);
        pos3 = pos(3);
        pos2 = pos(2)+100;
        pos4 = pos(4)+100;
        set_param([block '/<Precondition name>' num2str(i)], 'Position', [pos1 pos2 pos3 pos4]);
        set_param([block '/switch <signal1>'], 'Inputs', num2str(i+1));
        % Add lines

        add_line(block,['Out Bus/1'],['<Precondition name>' num2str(i) '/1'],'autorouting','on');
        add_line(block,['<Precondition name>' num2str(i) '/2'],['switch <signal1>/' num2str(i+2)],'autorouting','on');

    end

end
if No == 1
        InPos = get_param([block '/<Precondition name>'], 'Position');
else
        InPos = get_param([block '/<Precondition name>' num2str(No)], 'Position');
end
       InP1 = InPos(1)+130;
       InP3 = InPos(3)+120;
       InP2 = InPos(2)+80;
       InP4 = InPos(4)+70;
       set_param([block '/Initialisation & Stabilisation'], 'Position',[InP1 InP2 InP3 InP4]);
parentOfReq = get_param(block, 'Parent');
system_name1(parentOfReq);


function bvhModify(handle, channels, skel, padding)

% BVHMODIFY Helper code for visualisation of bvh data.
% FORMAT
% DESC updates a bvh representation in a 3-D plot.
% ARG handle : a vector of handles to the structure to be updated.
% ARG channels : the channels to update the skeleton with.
% ARG skel : the skeleton structure.
%
% SEEALSO : skelModify, bvhVisualise
%
% COPYRIGHT : Neil D. Lawrence, 2005, 2006

% MOCAP

if nargin<4
  padding = 0;
end

skelModify(handle, channels, skel, padding);


function c=samplebase
% samplebase constructor

c=class(struct('dummy',[]),'samplebase');


function pBar = bst_progress(varargin)
% bst_progress: Manage the Brainstorm progress bar
%
% USAGE : pBar = bst_progress('start', title, msg, valStart, valStop) : Create a progress bar with start and stop bounds
%         pBar = bst_progress('start', title, msg)                    : Create a progress bar (unlimited)
%         pBar = bst_progress('stop')        : stop and hide progress bar
%         pBar = bst_progress('inc', valInc) : increment of 'valInc' the position of the progress bar
%         pBar = bst_progress('set', pos)    : set the position
%          pos = bst_progress('get')         : get the position
%         pBar = bst_progress('text', txt)   : set the text
%    isVisible = bst_progress('isvisible')   : return 1 if progress bar is visible, 0 else
%         pBar = bst_progress('show')        : display previously defined progress bar
%         pBar = bst_progress('hide')        : hide progress bar
%         pBar = bst_progress('setimage', imagefile) : display an image in the wait bar
%         pBar = bst_progress('setlink', url)        : clicking on the image opens a browser to display the url
%         pBar = bst_progress('removeimage')         : Remove the image from the wait bar

% NOTES : The window is created once, and then never deleted, just hidden.
%         Progress bar is represented by a structure:
%            |- jWindow
%            |- jLabel
%            |- jProgressBar
%
% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2008-2013

% JAVA imports
import org.brainstorm.icon.*;
import java.awt.Dimension;

global GlobalData;

%% ===== PARSE INPUTS =====
if ((nargin >= 1) && ischar(varargin{1}))
    commandName = varargin{1};
else
    error('Usage : bst_progress(commandName, parameters)');
end

%% ===== GET OR CREATE PROGRESS BAR =====
% Do nothing in case of server mode
if ~isempty(GlobalData) && ~isempty(GlobalData.Program) && isfield(GlobalData.Program, 'GuiLevel') && (GlobalData.Program.GuiLevel == -1)
    if ismember(lower(commandName), {'pos','isvisible'})
        pBar = 0;
    else
        pBar = [];
    end
    return;
end
% If running in NOGUI mode: just display the message in the command window
if ~bst_get('isGUI')
    switch lower(commandName)
        case 'start',     disp(['PROGRESS> ' varargin{2} ': ' varargin{3}]); pBar = [];
        case 'text',      disp(['PROGRESS> ' varargin{2}]); pBar = [];
        case 'get',       pBar = 1;
        case 'isvisible', pBar = 0;
    end
    return;
end
% Get progress bar
if ~isempty(GlobalData) && ~isempty(GlobalData.Program) && isfield(GlobalData.Program, 'ProgressBar') && ~isempty(GlobalData.Program.ProgressBar)
    pBar = GlobalData.Program.ProgressBar;
else
    pBar = [];
end
% Get Brainstorm GUI context
jBstFrame = bst_get('BstFrame');
if isempty(jBstFrame)
    return
end

% Default window size
if isempty(pBar) || strcmpi(commandName, 'removeimage') || (strcmpi(commandName, 'stop') && pBar.isImage)
    DefaultSize = java_scaled('dimension', 350, 130);
end

% If progress bar was not created yet : create it
if isempty(pBar)
    % If action=isvisible: no need to create the progress bar
    if strcmpi(commandName, 'isvisible')
        pBar = 0;
        return
    end
    % Create a JDialog, if possible dependent of the main Brainstorm JFrame
    pBar.jWindow = java_create('javax.swing.JDialog');
    % Set icon
    try
        pBar.jWindow.setIconImage(IconLoader.ICON_APP.getImage());
    catch
        % Old matlab... just ignore...
    end
    % Set as always-on-top / non-focusable
    pBar.jWindow.setAlwaysOnTop(1);
    pBar.jWindow.setFocusable(0);
    pBar.jWindow.setFocusableWindowState(0);
    % Non-modal
    pBar.jWindow.setModal(0);

    % Closing callback
%     if bst_iscompiled()
        pBar.jWindow.setDefaultCloseOperation(pBar.jWindow.HIDE_ON_CLOSE);
%     else
%         pBar.jWindow.setDefaultCloseOperation(pBar.jWindow.DO_NOTHING_ON_CLOSE);
%         java_setcb(pBar.jWindow, 'WindowClosingCallback', @(h,ev)CloseCallback);
%     end

    % Configure window
    pBar.jWindow.setPreferredSize(DefaultSize);
    % Main panel
    pBar.jPanel = java_create('javax.swing.JPanel');
    pBar.jPanel.setLayout(java_create('java.awt.GridBagLayout'));

    % Create objects
    pBar.isImage = 0;
    pBar.jImage = java_create('javax.swing.JLabel');
    pBar.jLabel = java_create('javax.swing.JLabel', 'Ljava.lang.String;', '...');
    pBar.jLabel.setFont(bst_get('Font'));
    pBar.jProgressBar = java_create('javax.swing.JProgressBar', 'II', 0, 99);
    % Update constraints
    UpdateConstraints(0);

    % Add the main Panel
    pBar.jWindow.getContentPane.add(pBar.jPanel);
    pBar.jWindow.pack();
    % Set window size and location
    %pBar.jWindow.setLocationRelativeTo(pBar.jWindow.getParent());
    jLoc = jBstFrame.getLocation();
    jSize = jBstFrame.getSize();
    pos = [jLoc.getX() + ((jSize.getWidth() - DefaultSize.getWidth()) / 2), ...
           jLoc.getY() + ((jSize.getHeight() - DefaultSize.getHeight()) / 2)];
    pBar.jWindow.setLocation(pos(1), pos(2));
    % Save progress bar
    GlobalData.Program.ProgressBar = pBar;
end

% Linux: need to print something on the command window (don't know why...)
if strcmpi(commandName, 'stop') && ismember(computer('arch'), {'glnx86', 'glnxa64'})
    drawnow();
    fprintf(' ');
    fprintf('\b');
    drawnow();
    % The dialog needs to be displayed for a short period before being hidden
    pause(0.05);
end

%% ===== SWITCH BETWEEN COMMANDS =====
switch (lower(commandName))
    % ==== START ====
    case 'start'
        % Set as "always on top"
        java_call(pBar.jWindow, 'setAlwaysOnTop', 'Z', 1);
        java_call(pBar.jWindow, 'setFocusable',   'Z', 0);
        java_call(pBar.jWindow, 'setFocusableWindowState', 'Z', 0);
        % Call: bst_progress(''start'', title, msg)
        if (nargin == 3) && ischar(varargin{3}) && ischar(varargin{2})
            % Get window title and comment
            wndTitle    = varargin{2};
            msg = varargin{3};
            % Set Progress bar in inderminate mode
            pBar.jProgressBar.setIndeterminate(1);
            pBar.jProgressBar.setStringPainted(0);
            % Set progress bar bounds
            pBar.jProgressBar.setMinimum(0);
            pBar.jProgressBar.setMaximum(100);
            % Set initial value to start
            pBar.jProgressBar.setValue(0);

        % Call: bst_progress(''start'', title, msg, start, stop)
        elseif ((nargin == 5) && ischar(varargin{2}) && ischar(varargin{3}) && isnumeric(varargin{4}) && isnumeric(varargin{5}))
            % Get window title and comment
            wndTitle = varargin{2};
            msg = varargin{3};
            % Set Progress bar in derminate mode
            pBar.jProgressBar.setIndeterminate(0);
            pBar.jProgressBar.setStringPainted(1);
            % Get progress bar bounds
            valStart = varargin{4};
            valStop  = varargin{5};
            % Test bounds
            if ( (valStart >= valStop) || (valStop <= 0) )
                % Set indeterminate bounds
                pBar.jProgressBar.setIndeterminate(1);
                pBar.jProgressBar.setStringPainted(0);
                valStart = 0;
                valStop  = 100;
            end
            % Set progress bar bounds
            pBar.jProgressBar.setMinimum(valStart);
            pBar.jProgressBar.setMaximum(valStop);
            % Set initial value to start
            pBar.jProgressBar.setValue(valStart);

        else
            error(['Usage : bst_progress(''start'', title, comment) ' 10 '        bst_progress(''start'', title, comment, valStart, valStop)']);
        end
        % Set window title
        pBar.jWindow.setTitle(wndTitle);
        % Set window comment (central label)
        pBar.jLabel.setText(msg);
        % Show window
        java_call(pBar.jWindow, 'setVisible', 'Z', 1);
        % Set watch cursor
        jBstFrame.setCursor(java_create('java.awt.Cursor', 'I', java.awt.Cursor.WAIT_CURSOR));

    % ==== STOP ====
    case 'stop'
        % Remove the "always on top" status
        java_call(pBar.jWindow, 'setAlwaysOnTop', 'Z', 0);
        java_call(pBar.jWindow, 'setFocusable',   'Z', 1);
        java_call(pBar.jWindow, 'setFocusableWindowState', 'Z', 1);
        % Hide window
        java_call(pBar.jWindow, 'setVisible', 'Z', 0);
        % Restore cursor
        jBstFrame.setCursor([]);
        % Remove image
        if pBar.isImage
            GlobalData.Program.ProgressBar.isImage = 0;
            pBar.jImage.setIcon([]);
            java_setcb(pBar.jImage, 'MouseClickedCallback', []);
            UpdateConstraints(0);
            pBar.jWindow.setPreferredSize(DefaultSize);
            pBar.jWindow.pack();
        end

    % ==== INCREMENT ====
    case 'inc'
        % Parse arguments
        if ((nargin == 2) && isnumeric(varargin{2}))
            valInc = varargin{2};
        else
            error('Usage : bst_progress(''inc'', valInc)');
        end
        % Get current value
        curValue = pBar.jProgressBar.getValue();
        % Get the incremented progress bar position
        newVal = min(curValue + valInc, pBar.jProgressBar.getMaximum());
        pBar.jProgressBar.setValue(newVal);

    % ==== SET POSITION ====
    case 'set'
        % Parse arguments
        if ((nargin == 2) && isnumeric(varargin{2}))
            newVal = varargin{2};
        else
            error('Usage : bst_progress(''set'', pos)');
        end
        % Get current value
        curValue = pBar.jProgressBar.getValue();
        % Get the incremented progress bar position
        if (curValue ~= newVal)
            newVal = min(newVal, pBar.jProgressBar.getMaximum());
            pBar.jProgressBar.setValue(newVal);
        end

    % ==== GET POSITION ====
    case 'get'
        % Get the incremented progress bar position
        pBar = pBar.jProgressBar.getValue();

    % ==== SET TEXT ====
    case 'text'
        % Parse arguments
        if ((nargin == 2) && ischar(varargin{2}))
            % Set new label
            pBar.jLabel.setText(varargin{2});
        else
            % Get label
            pBar.jLabel.getText();
        end

    % ==== IS VISIBLE ====
    case 'isvisible'
        pBar = pBar.jWindow.isVisible();

    % ==== SHOW ====
    case 'show'
        % Set as "always on top"
        java_call(pBar.jWindow, 'setAlwaysOnTop', 'Z', 1);
        java_call(pBar.jWindow, 'setFocusable',   'Z', 0);
        java_call(pBar.jWindow, 'setFocusableWindowState', 'Z', 0);
        % Show window
        java_call(pBar.jWindow, 'setVisible', 'Z', 1);
        % Set watch cursor
        jBstFrame.setCursor(java_create('java.awt.Cursor', 'I', java.awt.Cursor.WAIT_CURSOR));

    % ==== HIDE ====
    case 'hide'
        % Remove the "always on top" status
        java_call(pBar.jWindow, 'setAlwaysOnTop', 'Z', 0);
        java_call(pBar.jWindow, 'setFocusable',   'Z', 1);
        java_call(pBar.jWindow, 'setFocusableWindowState', 'Z', 1);
        % Hide window
        java_call(pBar.jWindow, 'setVisible', 'Z', 0);
        % Restore cursor
        jBstFrame.setCursor([]);

    % ==== SET IMAGE ====
    case 'setimage'
        % Get image path
        imagefile = varargin{2};
        if ~file_exist(imagefile)
            imagefile = bst_fullfile(bst_get('BrainstormDocDir'), imagefile);
        end
        if ~file_exist(imagefile)
            warning(['Image not found: ' imagefile]);
            return
        end
        % Image in label
        pBar.jImage.setIcon(javax.swing.ImageIcon(imagefile));
        GlobalData.Program.ProgressBar.isImage = 1;
        % Extend size of the frame
        UpdateConstraints(1);
        pBar.jWindow.setPreferredSize([]);
        pBar.jWindow.pack();

    % ==== SET LINK ====
    case 'setlink'
        url = varargin{2};
        java_setcb(pBar.jImage, 'MouseClickedCallback', @(h,ev)web(url, '-browser'));

    % ==== REMOVE IMAGE ====
    case 'removeimage'
        % Remove image
        GlobalData.Program.ProgressBar.isImage = 0;
        pBar.jImage.setIcon([]);
        java_setcb(pBar.jImage, 'MouseClickedCallback', []);
        UpdateConstraints(0);
        pBar.jWindow.setPreferredSize(DefaultSize);
        pBar.jWindow.pack();
end

%% ===== ADD COMPONENTS =====
    function UpdateConstraints(isImage)
        import java.awt.GridBagConstraints;
        import java.awt.Insets;
        % Remove all components
        pBar.jPanel.removeAll();
        % Generic constraints
        c = GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;
        c.gridx = 1;
        c.weightx = 1;
        % IMAGE
        c.gridy = 1;
        c.weighty = isImage;
        c.insets = Insets(0,0,0,0);
        pBar.jPanel.add(pBar.jImage, c);
        % TEXT
        c.gridy = 2;
        c.weighty = ~isImage;
        c.insets = Insets(5,12,5,12);
        pBar.jPanel.add(pBar.jLabel, c);
        % PROGRESS BAR
        c.gridy = 3;
        c.weighty = 0;
        c.insets = Insets(0,12,9,12);
        pBar.jPanel.add(pBar.jProgressBar, c);
%         % CANCEL BUTTON
%         c.gridy = 4;
%         c.weighty = 0;
%         c.insets = Insets(0,12,9,12);
%         c.weightx = 0;
%         pBar.jPanel.add(pBar.jButtonCancel, c);
    end

%     %% ===== CLOSE CALLBACK =====
%     function CloseCallback()
%         % Hide progress bar
%         %java_call(pBar.jWindow, 'setVisible', 'Z', 0);
%         bst_progress('stop');
%
%         if bst_iscompiled()
%             try
%                 % Get command window
%                 cmdWindow = com.mathworks.mde.cmdwin.CmdWin.getInstance();
%                 cmdWindow.grabFocus();
%                 %2) Wait for focus transfer to complete (up to 2 seconds)
%                 focustransferTimer = tic;
%                 while ~cmdWindow.isFocusOwner
%                     pause(0.1);  %Pause some small interval
%                     if (toc(focustransferTimer) > 2)
%                         error('Error transferring focus for CTRL+C press.')
%                     end
%                 end
%
%                 %3) Use Java robot to execute a CTRL+C in the (now focused) command window.
%
%                 %3.1)  Setup a timer to relase CTRL + C in 0.3 second
%                 %  Try to reuse an existing timer if possible (this would be a holdover
%                 %  from a previous execution)
%                 t_all = timerfindall;
%                 releaseTimer = [];
%                 ix_timer = 1;
%                 while isempty(releaseTimer) && (ix_timer<= length(t_all))
%                     if isequal(t_all(ix_timer).TimerFcn, @releaseCtrl_C)
%                         releaseTimer = t_all(ix_timer);
%                     end
%                     ix_timer = ix_timer+1;
%                 end
%                 if isempty(releaseTimer)
%                     releaseTimer = timer;
%                     releaseTimer.TimerFcn = @(h,ev)releaseCtrl_C;
%                 end
%                 releaseTimer.StartDelay = 0.3;
%                 start(releaseTimer);
%
%                 %3.2)  Press press CTRL+C
%                 pressCtrl_C();
%             catch
%                 disp('BST> Could not post a CTRL+C signal in the command window.');
%             end
%         end
%     end
%
%     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%     function pressCtrl_C()
%         SimKey = java.awt.Robot;
%         SimKey.keyPress(java.awt.event.KeyEvent.VK_CONTROL);
%         SimKey.keyPress(java.awt.event.KeyEvent.VK_C);
%     end
%
%     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%     function releaseCtrl_C()
%         SimKey = java.awt.Robot;
%         SimKey.keyRelease(java.awt.event.KeyEvent.VK_CONTROL);
%         SimKey.keyRelease(java.awt.event.KeyEvent.VK_C);
%         jBstFrame.setVisible(1);
%     end

end


function [metList,noMolMetList] = mol2sdf(mets,molfileDir,sdfFileName,includeRs)
% Concatenates molfiles in molfileDir into one SDF file.
%
% metList = mol2sdf(mets,molfileDir,sdfFileName)
%
% INPUTS
% mets              mx1 cell array of metabolite identifiers (e.g., BiGG
%                   abbreviations)
% molfileDir        Path to directory containing molfiles for metabolites
%                   in mets. Molfile names should match the metabolite
%                   identifiers in mets without compartment assignments.
%
% OPTIONAL INPUTS
% sdfFileName       Name of SDF file. Default is MetStructures.sdf.
% includeRs         {0,(1)}. If 0, variable structures such as R groups and
%                   repeat units will not be included in SDF.
%
% OUTPUTS
% metList           Cell array listing metabolites in SDF.
% noMolMetList      Cell array listing metabolites without mol file.
%
% WRITTEN OUTPUTS
% sdfFileName.sdf   SDF with metabolite structures in same order as in
%                   metList. Metabolite identifiers in the SDF are the same
%                   as in MetList.
%
% Ronan M.T. Fleming
% Hulda SH, Nov. 2012   Changed output format from CDF to SDF. Renamed
%                       function. Simplified code.

% Format inputs
if ~strcmp(molfileDir(end),filesep)
    molfileDir = [molfileDir filesep];
end

if ~exist('sdfFileName','var')
    sdfFileName = 'MetStructures.sdf';
end
if isempty(sdfFileName)
    sdfFileName = 'MetStructures.sdf';
end
if ~strcmp(sdfFileName(end-3:end),'.sdf')
    sdfFileName = [sdfFileName '.sdf'];
end

mets = reshape(mets,length(mets),1);
omets = mets; % store original metabolite identifiers
if ischar(mets)
    mets = strtrim(cellstr(mets));
end
if isnumeric(mets)
    mets = strtrim(cellstr(num2str(mets)));
end
mets = regexprep(mets,'(\[\w\])$',''); % Remove compartment assignment

if ~exist('includeRs','var')
    includeRs = 1;
end

% List all molfiles in molfile directory
d = dir(molfileDir);
dirbool = cat(1,d.isdir);
d = d(~dirbool);
molfileNames = {d.name};
molfileNames = regexprep(molfileNames,'(\.mol)$','');

molfileNames = molfileNames(ismember(molfileNames,mets)); % Only include molfiles for metabolites in mets

noMolMetList = unique(mets(ismember(mets,molfileNames)));
noMolMetList = reshape(noMolMetList,length(noMolMetList),1);

metList = molfileNames;

% List all elements
elements = {'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca',...
            'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y',...
            'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce',...
            'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir',...
            'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm',...
            'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Uut', 'Fl', 'Uup', 'Lv', 'Uus', 'Uuo'};

% Concatenate molfiles into single SDF file
fid = fopen(sdfFileName,'w+'); % Create SDF
first = true;
for m = 1:length(molfileNames)
    molfile = fileread([molfileDir molfileNames{m} '.mol']); % Read in molfile
    molfile = reshape(molfile, 1, length(molfile)); % for compatibility with Octave (where fileread returns a column vector of chars)
    molfile = regexprep(molfile,'\r',''); % Remove carriage returns
    molfile = regexprep(molfile,'[^\n]*\n',sprintf('%s\n',molfileNames{m}),'once'); % Replace top line with metabolite identifier
    molfile = regexprep(molfile,'\n+$',''); % Ensure there is only one newline caracter at end of each molfile in the SDF

    if includeRs == 0
        % Get atom list
        lines = regexp(molfile,'\n','split');
        try
            atomCount = str2double(lines{4}(1:3));
        catch
            disp(lines)
        end
        if atomCount > 0
            atomBlock = lines(5:5 + atomCount - 1);
            pat = '[^a-z_A-z\*]+(?<atom>[a-z_A-Z\*]+)[^a-z_A-z\*]+';
            atoms = regexp(atomBlock,pat,'names');
            atoms = [atoms{:}]';
            atoms = {atoms.atom}';

            % If structure contains a non-elemental atom or repeat units it
            % will not be appended to SDF
            if ~all(ismember(atoms,elements)) || ~isempty(strmatch('M  STY',lines))
                metList = setdiff(metList,molfileNames{m});
                continue;
            end
        end
    end

    % Add molfile to SDF
    if first
        fprintf(fid,'%s\n',molfile);
        first = false;
    else
        fprintf(fid,'%s\n','$$$$');
        fprintf(fid,'%s\n',molfile);
    end
end
fclose(fid);

noMolFileCount = sum(~ismember(mets,molfileNames));
fprintf('Percentage of metabolites without mol files: %.1f%%\n', 100*noMolFileCount/length(mets));

metList = reshape(metList,length(metList),1);
if isnumeric(omets)
    metList = str2double(metList);
end


%IMREAD  Loads an image from a file
%
%     img = cv.imread(filename)
%     img = cv.imread(filename, 'OptionName',optionValue, ...)
%
% ## Input
% * __filename__ Name of a file to be loaded.
%
% ## Output
% * __img__ Loaded image, whose depth and number of channels depend on options.
%
% ## Options
% * __Unchanged__ If set, return the loaded image as is (with alpha channel,
%   otherwise it gets cropped). Both the depth and number of channels are
%   unchanged as determined by the decoder. default false
% * __AnyDepth__ If set, return 16-bit/32-bit image when the input has the
%   corresponding depth, otherwise convert it to 8-bit. default false
% * __AnyColor__ If set, the image is read in any possible color format.
%   default false
% * __Color__ If set, always convert image to the 3 channel BGR color image.
%   default true
% * __Grayscale__ If set, always convert image to the single channel grayscale
%   image. default false
% * __GDAL__ If set, use the gdal driver for loading the image. default false
% * __ReduceScale__ Loads the image reduced by a scale factor (JPEG library
%   natively supports direct image scaling, other formats are resized after
%   loading). One of:
%   * `1`: no scaling (default).
%   * `2`: image scaled by 1/2 factor.
%   * `4`: image scaled by 1/4 factor.
%   * `8`: image scaled by 1/8 factor.
% * __IgnoreOrientation__ If set, do not rotate the image according to EXIF's
%   orientation flag. default false
% * __Flags__ Advanced option to directly set the flag specifying the depth
%   and color type of a loaded image. Note that setting this integer flag
%   overrides all the other flag options. Not set by default:
%   * `>0`: Return a 3-channel color image. Note that in the current
%           implementation the alpha channel, if any, is stripped from the
%           output image. For example, a 4-channel RGBA image is loaded as
%           RGB if `Flags >= 0`.
%   * `=0`: Return a grayscale image
%   * `<0`: Return the loaded image as is (with alpha channel if present).
% * __FlipChannels__ in case the output is color image, flips the color order
%   from OpenCV's BGR/BGRA to MATLAB's RGB/RGBA order. default true
%
% The function cv.imread loads an image from the specified file and returns
% it. If the image cannot be read (because of missing file, improper
% permissions, unsupported or invalid format), the function issues an error.
%
% Currently, the following file formats are supported:
%
% * Windows bitmaps - `*.bmp`, `*.dib` (always supported)
% * JPEG files - `*.jpeg`, `*.jpg`, `*.jpe` (see the Notes section)
% * JPEG 2000 files - `*.jp2` (see the Notes section)
% * Portable Network Graphics - `*.png` (see the Notes section)
% * WebP - `*.webp` (see the Notes section)
% * Portable image format - `*.pbm`, `*.pgm`, `*.ppm`, `*.pxm`, `*.pnm`,
%   `*.pam` (always supported)
% * Sun rasters - `*.sr`, `*.ras` (always supported)
% * TIFF files - `*.tiff`, `*.tif` (see the Notes section)
% * OpenEXR Image files - `*.exr` (see the Notes section)
% * Radiance HDR - `*.hdr`, `*.pic` (always supported)
% * Raster and Vector geospatial data supported by Gdal (see the Notes section)
% * DICOM medical images - `*.dcm` (see the Notes section)
%
% ### Notes
% * The function determines the type of an image by the content, not by the
%   file extension.
% * In the case of color images, the decoded images will have the channels
%   stored in BGR order. If `FlipChannels` is set, the channels are flipped to
%   RGB order.
% * On Microsoft Windows OS and MacOSX, the codecs shipped with an OpenCV
%   image (libjpeg, libpng, libtiff, and libjasper) are used by default. So,
%   OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an
%   option to use native MacOSX image readers. But beware that currently these
%   native image loaders give images with different pixel values because of
%   the color management embedded into MacOSX.
% * On Linux, BSD flavors and other Unix-like open-source operating systems,
%   OpenCV looks for codecs supplied with an OS image. Install the relevant
%   packages (do not forget the development files, for example, "libjpeg-dev",
%   in Debian and Ubuntu) to get the codec support or turn on the
%   `OPENCV_BUILD_3RDPARTY_LIBS` flag in CMake.
% * In the case you set `WITH_GDAL` flag to true in CMake and `GDAL` option to
%   load the image, then [GDAL driver](http://www.gdal.org) will be used in
%   order to decode the image by supporting the following formats:
%   * [Raster](http://www.gdal.org/formats_list.html),
%   * [Vector](http://www.gdal.org/ogr_formats.html).
% * If EXIF information are embedded in the image file, the EXIF orientation
%   will be taken into account and thus the image will be rotated accordingly
%   except if the option `IgnoreOrientation` is passed.
%
% See also: cv.imwrite, cv.imdecode, imread, imfinfo, imformats, dicomread,
%  hdrread, Tiff
%


function r = zerofh()
r = @(varargin)0;


function varargout = Blister_GUI(varargin)
% BLISTER_GUI M-file for Blister_GUI.fig
%      BLISTER_GUI, by itself, creates a new BLISTER_GUI or raises the existing
%      singleton*.
%
%      H = BLISTER_GUI returns the handle to a new BLISTER_GUI or the handle to
%      the existing singleton*.
%
%      BLISTER_GUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in BLISTER_GUI.M with the given input arguments.
%
%      BLISTER_GUI('Property','Value',...) creates a new BLISTER_GUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before Blister_GUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to Blister_GUI_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help Blister_GUI

% Last Modified by GUIDE v2.5 24-Nov-2008 12:22:09

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @Blister_GUI_OpeningFcn, ...
                   'gui_OutputFcn',  @Blister_GUI_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

% --- Executes just before Blister_GUI is made visible.
function Blister_GUI_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to Blister_GUI (see VARARGIN)

% Choose default command line output for Blister_GUI
handles.output = hObject;
axes(handles.axes1);
imshow('sample 01.jpg');  % Show a default sample image

% Create video input objects
handles.vid_obj = videoinput('winvideo');
handles.obj_src= get(handles.vid_obj,'Source');

% Set device parameters
set(handles.obj_src,'Brightness',160);
set(handles.obj_src,'Saturation',160);
set(handles.vid_obj,'FramesPerTrigger',1);
triggerconfig(handles.vid_obj,'manual');
set(handles.vid_obj,'TriggerRepeat',inf);
start(handles.vid_obj);

handles.vidRes = get(handles.vid_obj, 'VideoResolution');
handles.nBands = get(handles.vid_obj, 'NumberOfBands');

axes(handles.axes2);
himage = image( zeros(handles.vidRes(2), handles.vidRes(1), handles.nBands) );
preview(handles.vid_obj,himage);
% Update handles structure
guidata(hObject, handles);

% UIWAIT makes Blister_GUI wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = Blister_GUI_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

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

% Update the status messages
set(handles.text9,'string','Status:  Taking a snapshot...');

% Send a manual trigger to the camera
trigger(handles.vid_obj);

% Get data from the buffer and display
imdata = getdata(handles.vid_obj);
axes(handles.axes1);
imshow(imdata);
axes(handles.axes1);
set(handles.text9,'string','Status:  Searching for broken pills...');
drawnow

% Call our code in Blister Read
[numPills, numBroken] = BlisterRead(imdata);

% Display information regarding broken and full pills
set(handles.text7,'string',num2str(numPills));
set(handles.text8,'string',num2str(numBroken));
set(handles.text9,'string','Status:  Estimated broken pills.');
hold off;

% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
stop(handles.vid_obj);
% Hint: delete(hObject) closes the figure
delete(hObject);


% Unpacks an object of any complexity (structure, cell array ect.)
% from a  serialized form.
%
% mex-function, written by Dima Mihaylov (dmih@in-solve.ru)
%
% See also SERIALIZE


function template = PTKCreateTemplateForSegment(segment_mask, context, reporting)
    % PTKCreateTemplateForSegment. Function for creating a template image
    %     for a pulmonary segment regon
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    template = segment_mask.Copy;
end


function dftoggleaxlimctrl(dffig)
%DFTOGGLEAXLIMCTRL Toggle x and y axis limit controls on or off

%   $Revision: 1.1.6.2 $  $Date: 2004/01/24 09:35:53 $
%   Copyright 2003-2004 The MathWorks, Inc.

% Get handle to menu item, may be current object or may not
h = gcbo;
if ~isequal(get(h,'Tag'),'showaxlimctrl')
   h = findall(dffig,'Tag','showaxlimctrl');
end

% Get new state
onoff = on2off(get(h,'Checked'));
dfgetset('showaxlimctrl',onoff);

% Add or remove controls
dfaxlimctrl(dffig,onoff)

% Remove effects of controls on layout
if isequal(onoff,'off')
   dfadjustlayout(dffig);
end

% Change menu state
set(h,'Checked',onoff);


function csv = readCSV(filename)
FID = fopen(filename);
currLine = fgetl(FID);
idx = find(currLine==',');
field{1} = currLine(1:idx(1)-1);
csv.(field{1}) = {};
for i=2:length(idx)
    field{end+1} = regexprep(currLine(idx(i-1)+1:idx(i)-1), ' ', '_');
    csv.(field{end}) = {};
end
field{end+1} = regexprep(currLine(idx(end)+1:end), ' ', '_');
csv.(field{end}) = {};
nField = length(field);

line_cnt = 0;
while 1
    currLine = fgetl(FID);
    line_cnt = line_cnt + 1;
    PrintProgress(line_cnt, 1e5, 5000);

    if currLine == -1
        break;
    end

    idx = find(currLine==',');
    for i=1:nField
        if i==1
            idx1 = 1;
        else
            idx1 = idx(i-1)+1;
        end
        if i==nField
            idx2 = length(currLine);
        else
            idx2 = idx(i)-1;
        end

        csv.(field{i}){end+1} = currLine(idx1:idx2);
    end
end

fclose(FID);


function [optExists, value, vargs] = peel_option(vargs, searchValue, searchClass, minPos)
   optExists = false; value = [];
   if minPos > numel(vargs)
      return
   end
   switch searchClass
      case 'char'
         for n = minPos:numel(vargs)
            if ischar(vargs{n})
               if isempty(searchValue) || strcmp(searchValue,vargs{n})
                  optExists = true; value = vargs{n}; vargs(n) = [];
                  return
               end
            end
         end
      otherwise
         for n = minPos: numel(vargs)
            if isa(vargs{n},searchClass)
               if isempty(searchValue) || vargs{n} == searchValue
                  optExists = true; value = vargs{n}; vargs(n) = [];
                  return
               end
            end
         end
   end
end


function handle = vectorModify(handle, values)

% VECTORMODIFY Helper code for visualisation of vectorial data.

% MLTOOLS

set(handle, 'YData', values);


function fieldName = GetFieldNameFromFilePath(filepath, nStage)
if nargin<2
    nStage = 1;
end

orig_filepath = filepath;
[filepath, uttID] = fileparts(filepath);
fieldName = uttID;
for i=2:nStage
    [filepath, uttID] = fileparts(filepath);
    fieldName = [uttID '_' fieldName];
    if isempty(filepath)
        break;
    end
end
fieldName = ['U_' fieldName];
fieldName = regexprep(fieldName, '-', '_');

end


function [results, unmatched] = parse_params(args, defaults, varargin)
%PARSE_PARAMS Parses a set of name-value pairs.
% Usage:
%   parsed = parse_params(args, defaults)
%   parsed = parse_params(args, defaults, 'Name', Val, ...)
%   [parsed, unmatched] = parse_params(...)
%
% Args:
%   args: a cell array or structure of name-value pairs
%   defaults: a cell array or structure of name-value pairs
%
% Params:
%   This function takes any public properties of inputParser as parameters,
%   e.g., 'StructExpand'.
%
% Returns:
%   results: a structure containing the parsed results
%   unmatched: a structure containing any args that did not have a default
%
% See also: inputParser, struct2nameval, nameval2struct

% Make sure args are name-val cells
if isstruct(args); args = struct2nameval(args); end

% Make sure defaults are structs
if iscell(defaults); defaults = nameval2struct(defaults); end

% Default inputParser parameters
caller = get_caller_name();
parser_defaults.CaseSensitive = false;
parser_defaults.FunctionName = caller;
parser_defaults.KeepUnmatched = true;
parser_defaults.PartialMatching = true;
parser_defaults.StructExpand = true;

% Parse inputParser parameters
p = inputParser();
p.FunctionName = mfilename;
p = add_params(p, parser_defaults);
p.parse(varargin{:});
parser_params = p.Results;

% Create new inputParser instance
p = inputParser;

% Set inputParser properties from parsed parameters
param_names = fieldnames(parser_params);
for i = 1:numel(param_names)
    p.(param_names{i}) = parser_params.(param_names{i});
end

% Add parameters
p = add_params(p, defaults);

% Parse
p.parse(args{:});

% Return results of parsing
results = p.Results;
unmatched = p.Unmatched;

end

function p = add_params(p, defaults)

% Add defaults as parameters
names = fieldnames(defaults);
for i = 1:numel(names)
    p.addParameter(names{i}, defaults.(names{i}));
end

end


function transferModel(modelFile, srcVocabFile_new, tgtVocabFile_new, srcCharPrefix_new, tgtCharPrefix_new, outModelFile, varargin)
  addpath(genpath(sprintf('%s/../..', pwd)));

  %% Argument Parser
  p = inputParser;
  % required
  addRequired(p,'modelFile',@ischar);
  addRequired(p,'srcVocabFile_new',@ischar);
  addRequired(p,'tgtVocabFile_new',@ischar);
  addRequired(p,'srcCharPrefix_new',@ischar);
  addRequired(p,'tgtCharPrefix_new',@ischar);
  addRequired(p,'outModelFile',@ischar);

  % optional
  addOptional(p,'gpuDevice', 0, @isnumeric); % choose the gpuDevice to use: 0 -- no GPU

  p.KeepUnmatched = true;
  parse(p, modelFile, srcVocabFile_new, tgtVocabFile_new, srcCharPrefix_new, tgtCharPrefix_new, outModelFile, varargin{:})
  transferParams = p.Results;

  % GPU settings
  transferParams.isGPU = 0;
  if transferParams.gpuDevice
    n = gpuDeviceCount;
    if n>0 % GPU exists
      fprintf(2, '# %d GPUs exist. So, we will use GPUs.\n', n);
      transferParams.isGPU = 1;
      gpuDevice(transferParams.gpuDevice)
      transferParams.dataType = 'single';
    else
      transferParams.dataType = 'double';
    end
  else
    transferParams.dataType = 'double';
  end
  printParams(2, transferParams);

  modelFile = transferParams.modelFile;
  srcVocabFile_new = transferParams.srcVocabFile_new;
  tgtVocabFile_new = transferParams.tgtVocabFile_new;
  srcCharPrefix_new = transferParams.srcCharPrefix_new;
  tgtCharPrefix_new = transferParams.tgtCharPrefix_new;
  outModelFile = transferParams.outModelFile;

  %% Transfer
  % load current data
  fprintf(2, '# Loading %s\n', modelFile);
  savedData = load(modelFile);
  model = savedData.model;
  params = savedData.params;

  % src word
  fprintf(2, '# Transfering src word\n');
  [model.W_emb_src, params.srcVocab, ~, params.srcVocabFile] = transferMatrix(model.W_emb_src, params.srcVocab, params.srcCharShortList, ...
    srcVocabFile_new, params, 1, 0);

  % tgt word
  fprintf(2, '# Transfering tgt word\n');
  [model.W_emb_tgt, ~, ~, ~] = transferMatrix(model.W_emb_tgt, params.tgtVocab, params.tgtCharShortList, ...
    tgtVocabFile_new, params, 1, 0);

  % tgt word soft
  fprintf(2, '# Transfering tgt word soft\n');
  [model.W_soft, params.tgtVocab, ~, params.tgtVocabFile] = transferMatrix(model.W_soft, params.tgtVocab, params.tgtCharShortList, ...
    tgtVocabFile_new, params, 0, 0);
  % IMPORTANT: only update tgtVocab in the last call

  % src char
  if isfield(params, 'charOpt') && params.charOpt == 1
    fprintf(2, '# Transfering src char\n');
    [model.W_emb_src_char, params.srcCharVocab, params.srcCharVocabSize, params.srcCharVocabFile] = transferMatrix(model.W_emb_src_char, params.srcCharVocab, ...
      params.srcCharVocabSize, [srcCharPrefix_new '.char.vocab'], params, 1, 1);
    params.srcCharMapFile = [srcCharPrefix_new '.char.map'];
    params.srcCharMap = loadWord2CharMap(params.srcCharMapFile, params.charMaxLen);
  end

  if isfield(params, 'charOpt') && (params.charOpt == 2 || params.charOpt == 3)
    % tgt char
    fprintf(2, '# Transfering tgt char\n');
    [model.W_emb_tgt_char, ~, ~, ~] = transferMatrix(model.W_emb_tgt_char, params.tgtCharVocab, ...
      params.tgtCharVocabSize, [tgtCharPrefix_new '.char.vocab'], params, 1, 1);
    params.tgtCharMapFile = [tgtCharPrefix_new '.char.map'];
    params.tgtCharMap = loadWord2CharMap(params.tgtCharMapFile, params.charMaxLen);

    % tgt char soft
    fprintf(2, '# Transfering tgt char soft\n');
    [model.W_soft_char, params.tgtCharVocab, params.tgtCharVocabSize, params.tgtCharVocabFile] = transferMatrix(model.W_soft_char, params.tgtCharVocab, ...
      params.tgtCharVocabSize, [tgtCharPrefix_new '.char.vocab'], params, 0, 1);
    % IMPORTANT: only update tgtCharVocab in the last call
  end

  % save model
  save(outModelFile, 'model', 'params');
  model
  fprintf(2, '# Done saving to %s\n', outModelFile);
end

function [W_new, vocab_new, vocabSize_new, vocabFile_new] = transferMatrix(W, vocab, shortList, vocabFile_new, params, isCol, isChar)
  fprintf(2, '  W [%s], isCol=%d, isChar=%d, original vocab size %d, short list %d\n', num2str(size(W)), isCol, isChar, length(vocab), shortList);
  [vocab_new] = loadVocab(vocabFile_new);
  if isChar % for chars, we learn for the entire char vocab, so shortList is NOT used
    vocab_new{end+1} = '<c_s>'; % not learn
    vocab_new{end+1} = '</c_s>';

    if isCol
      W_new = initMatrixRange(params.initRange, [params.lstmSize, length(vocab_new)], params.isGPU, params.dataType);
    else
      W_new = initMatrixRange(params.initRange, [length(vocab_new), params.lstmSize], params.isGPU, params.dataType);
    end
    learnedVocab_new = vocab_new;
    vocabMap = cell2map(vocab);
  else % for words, we only learn embeddings for a small shortlist
    assert(shortList < length(vocab));
    if isCol
      W_new = initMatrixRange(params.initRange, [params.lstmSize, shortList], params.isGPU, params.dataType);
    else
      W_new = initMatrixRange(params.initRange, [shortList, params.lstmSize], params.isGPU, params.dataType);
    end
    learnedVocab_new = vocab_new(1:shortList);
    vocabMap = cell2map(vocab(1:shortList));
  end
  vocabSize_new = length(vocab_new);

  % mapping
  flags = isKey(vocabMap, learnedVocab_new);
  indices = values(vocabMap, learnedVocab_new(flags));
  indices = [indices{:}];
  if isCol
    W_new(:, flags) = W(:, indices);
  else
    W_new(flags, :) = W(indices, :);
  end

  fprintf(2, '  vocabSize_new %d, num overlap %d\n  new words:', vocabSize_new, sum(flags));
  fprintf(2, ' %s', learnedVocab_new{~flags});
  fprintf(2, '\n');
end


function [] = createnewblocklibrary(CGen)
%CodeGenerator.createnewblocklibrary
%
% Creates a new Simulink library file along with its slblocks.m.
%
% Authors::
%  Joern Malzahn, (joern.malzahn@tu-dortmund.de)
%
% See also SerialLink, Link.

% Copyright (C) 1993-2012, by Peter I. Corke
% Copyright (C) 2012-2013, by Joern Malzahn
%
% This file is part of The Robotics Toolbox for Matlab (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
%
% The code generation module emerged during the work on a project funded by
% the German Research Foundation (DFG, BE1569/7-1). The authors gratefully
% acknowledge the financial support.

warning off;
CGen.rmpath;
warning on;

%% Create Simulink library file
new_system(CGen.slib,'Library', 'ErrorIfShadowed');
open_system(CGen.slib);
save_system(CGen.slib,CGen.slibpath);

%% Create slblock.m

fid = fopen(fullfile(CGen.basepath,'slblocks.m'),'w+');

fprintf(fid,'%s\n',['% This file is the slblocks file for the ', CGen.getrobfname,' Simulink library.']);
fprintf(fid,'%s\n',['% It has been automatically generated using The Robotics Toolbox for Matlab (RTB).']);
fprintf(fid,'%s\n',' ');
fprintf(fid,'%s\n\n',CGen.generatecopyrightnote);

fprintf(fid,'%s\n','function blkStruct = slblocks');
fprintf(fid,'%s\n',' ');
fprintf(fid,'%s\n', ['Browser.Library = ''',CGen.slib,''';']);
fprintf(fid,'%s\n', ['Browser.Name = ''',CGen.getrobfname,''';']);
fprintf(fid,'%s\n', ['Browser.IsFlat = 1;']);
fprintf(fid,'%s\n',' ');

fprintf(fid,'%s\n', ['blkStruct.Name = [''',CGen.getrobfname,''', sprintf(''\n''), ''Library''];']);
fprintf(fid,'%s\n', ['blkStruct.OpenFcn= ''',CGen.slib,''';']);
fprintf(fid,'%s\n', ['blkStruct.MaskDisplay = ''''',';']);
fprintf(fid,'%s\n', ['blkStruct.Bworser = Browser;']);
fprintf(fid,'%s\n',' ');

fclose(fid);


function febio(varargin)

% function febio(febFileName)
% ------------------------------------------------------------------------
% This function calls FEBio from MATLAB and runs it in the command window.
% If no input is provided this commend simply triggers FEBio to run without
% an input file.
% If the input is a valid FEBio model input file path then FEBio will run
% the analysis for that file.
% The input may also be a structure with the following default fields:
%   defaultOptionStruct.FEBioPath=getFEBioPath; %The FEBio path
%   defaultOptionStruct.run_filename=[]; %The .feb file name
%   defaultOptionStruct.run_logname=[]; %The log file name
%   defaultOptionStruct.runMode='internal'; %Running internally
%
%
% 2020/11/24 Created
% ------------------------------------------------------------------------

%% Parse input

%Create default structure
defaultOptionStruct.FEBioPath=getFEBioPath; %Get FEBio path
defaultOptionStruct.run_filename=[];
defaultOptionStruct.run_logname=[];
defaultOptionStruct.runMode='internal';

switch nargin
    case 0
        inputVar=[];
    case 1
        inputVar=varargin{1};
end

if ~isempty(inputVar)
    if ~isstruct(inputVar) %Assume a feb file name was provided
        FEBioRunStruct.run_filename=inputVar;
        [filePath,fileName,~]=fileparts(inputVar);
        logFileName=fullfile(filePath,[fileName,'.txt']);
        FEBioRunStruct.run_logname=logFileName;
    else
        FEBioRunStruct=inputVar;
    end
    %Complete struct if there are missing fields
    FEBioRunStruct=structComplete(FEBioRunStruct,defaultOptionStruct,0);
else
    FEBioRunStruct=[];
end

%% Run FEBio

if isstruct(FEBioRunStruct) && ~isfield(FEBioRunStruct,'run_string')
    switch FEBioRunStruct.runMode
        case 'external_old'
            FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'" &'];
        case 'external'
            if ismac % Code to run on Mac plaform
                %TO DO IMPROVE THIS LINE FOR MAC
                FEBioRunStruct.run_string=['nice "',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'" &'];
            elseif isunix && ~ismac % Code to run on Linux plaform
                FEBioRunStruct.run_string=['nice "',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'" &'];
            elseif ispc % Code to run on Windows platform
                FEBioRunStruct.run_string=['start /min "GIBBON - FEBio" "',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'"'];
            else
                warning('Unknown operational system, run command might be inappropriate');
                FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'" &'];
            end
        case 'internal'
            if ispc
                FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'"'];
            elseif isunix
                FEBioRunStruct.run_string=['nice "',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'"'];
            else
                FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" "',FEBioRunStruct.run_filename,'"'];
            end
    end
elseif isempty(FEBioRunStruct)
    FEBioRunStruct.run_string=['"',defaultOptionStruct.FEBioPath,'"'];
end

% if isstruct(FEBioRunStruct) && ~isfield(FEBioRunStruct,'run_string')
%     switch FEBioRunStruct.runMode
%         case 'external_old'
%             FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'" &'];
%         case 'external'
%             if ismac % Code to run on Mac plaform
%                 %TO DO IMPROVE THIS LINE FOR MAC
%                 FEBioRunStruct.run_string=['nice "',FEBioRunStruct.FEBioPath,'"',' -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'" &'];
%             elseif isunix && ~ismac % Code to run on Linux plaform
%                 FEBioRunStruct.run_string=['nice "',FEBioRunStruct.FEBioPath,'"',' -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'" &'];
%             elseif ispc % Code to run on Windows platform
%                 FEBioRunStruct.run_string=['start /min "GIBBON - FEBio" "',FEBioRunStruct.FEBioPath,'"',' -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'"'];
%             else
%                 warning('Unknown operational system, run command might be inappropriate');
%                 FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'"',' -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'" &'];
%             end
%         case 'internal'
%             if ispc
%                 FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'"'];
%             elseif isunix
%                 FEBioRunStruct.run_string=['nice "',FEBioRunStruct.FEBioPath,'" -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'"'];
%             else
%                 FEBioRunStruct.run_string=['"',FEBioRunStruct.FEBioPath,'" -i "',FEBioRunStruct.run_filename,'" -o "',FEBioRunStruct.run_logname,'"'];
%             end
%     end
% elseif isempty(FEBioRunStruct)
%     FEBioRunStruct.run_string=['"',defaultOptionStruct.FEBioPath,'"'];
% end

% FEBioRunStruct.run_string

system(FEBioRunStruct.run_string); %START FEBio NOW!!!!!!!!

end
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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/>.


% ----------------------------------------------------------------------------
% function hfssSaveProject(fid, projectFile, [Overwrite = false])
%
% Description :
% -------------
% This function creates the necessary VB script to save the active HFSS
% project onto a disk file.
%
% Parameters :
% ------------
% fid         - file identifier of the HFSS script file.
% projectFile - full file name of the project file into which the active HFSS
%               project will be saved.
% [Overwrite] - (boolean) if set to true will overwrite any existing file with
%               the same name as that specified by projectFile.
%
%
% Note :
% ------
% The active HFSS project MUST be saved prior to solving it. This is slightly
% disadvantageous because we cannot create and solve projects "on-the-fly" -
% i.e., in memory without creating a project file on the disk. One workaround
% is to write the project to a temporary file and then delete the temporary
% file after the required solution is obtained.
%
% Example :
% ---------
% fid = fopen('myantenna.vbs', 'wt');
% ...
%
% ----------------------------------------------------------------------------

% ----------------------------------------------------------------------------
% This file is part of HFSS-MATLAB-API.
%
% HFSS-MATLAB-API 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.
%
% HFSS-MATLAB-API 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
% Foobar; if not, write to the Free Software Foundation, Inc., 59 Temple
% Place, Suite 330, Boston, MA  02111-1307  USA
%
% Copyright 2004, Vijay Ramasami (rvc@ku.edu)
% ----------------------------------------------------------------------------

function hfssSaveProject(fid, projectFile, Overwrite)

% arguments processor.
if (nargin < 2)
	error('Insufficient # of arguments !');
elseif (nargin < 3)
	Overwrite = [];
end

% default arguments.
if isempty(Overwrite)
	Overwrite = false;
end

% create the script.
fprintf(fid, '\n');
fprintf(fid, 'oProject.SaveAs _\n');
fprintf(fid, '    "%s", _\n', projectFile);
if (Overwrite)
    fprintf(fid, '    true\n');
else
    fprintf(fid, '    false\n');
end


function  ACFTA  = readACFTA(fid)
%
% <<<<<<<<<< CLASSIFICATION: UNCLASSIFIED >>>>>>>>>>
%
% READACFTA Create structure for metadata fields.
%   ACFTA = READACFTA(FID) returns a structure of fields and their
%   associated values.

% Written by Matt Donath, NGA, matthew.b.donath@nga.ic.gov
% References:
%  > MIL-STD-2500A, NATIONAL IMAGERY TRANSMISSION FORMAT VERSION 2.0
%  > MIL-STD-2500C, NATIONAL IMAGERY TRANSMISSION FORMAT VERSION 2.1
%  > STDI-0001,     NATIONAL SUPPORT DATA EXTENSIONS (SDE)(VERSION 1.3/CN2)
%                   FOR THE NATIONAL IMAGERY TRANSMISSION FORMAT (NITF)
%  > STDI-0002,     THE COMPENDIUM OF CONTROLLED EXTENSIONS (CE) FOR THE
%                   NATIONAL IMAGERY TRANSMISSION FORMAT (NITF) VERSION 2.1
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

%%  Create the metadata structure for ACFTA.

ACFTA.CETAG = fread(fid,6,'uint8=>char')';
ACFTA.CEL = str2double(fread(fid,5,'uint8=>char')');

ACFTA.AC_MSN_ID = fread(fid,10,'uint8=>char')';
ACFTA.SCTYPE = fread(fid,1,'uint8=>char')';
ACFTA.SCNUM = fread(fid,4,'uint8=>char')';
ACFTA.SENSOR_ID = fread(fid,3,'uint8=>char')';
ACFTA.PATCH_TOT = str2double(fread(fid,4,'uint8=>char')');
ACFTA.MTI_TOT = str2double(fread(fid,3,'uint8=>char')');
ACFTA.PDATE = fread(fid,7,'uint8=>char')';
ACFTA.IMHOSTNO = str2double(fread(fid,3,'uint8=>char')');
ACFTA.IMREQID = str2double(fread(fid,5,'uint8=>char')');
ACFTA.SCENE_SOURCE = fread(fid,1,'uint8=>char')';
ACFTA.MPLAN = fread(fid,2,'uint8=>char')';
ACFTA.ENTLOC = fread(fid,21,'uint8=>char')';
ACFTA.ENTELV = str2double(fread(fid,6,'uint8=>char')');
ACFTA.EXITLOC = fread(fid,21,'uint8=>char')';
ACFTA.EXITELV = str2double(fread(fid,6,'uint8=>char')');
ACFTA.TMAP = str2double(fread(fid,7,'uint8=>char')');
ACFTA.RCS = str2double(fread(fid,3,'uint8=>char')');
ACFTA.ROW_SPACING = str2double(fread(fid,7,'uint8=>char')');
ACFTA.COL_SPACING = str2double(fread(fid,7,'uint8=>char')');
ACFTA.SENSERIAL = fread(fid,4,'uint8=>char')';
ACFTA.ABSWVER = fread(fid,7,'uint8=>char')';

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


function [id,wasOpen] = mrmCheckMeshServer(id, host)
%
%     [id,wasOpen] = mrmCheckMeshServer(id, [host='localhohst']);
%
% Author: Ress
% Purpose:
%   Test whether a window with id is open on the host (defaults to
%   localhost). If not, start a new window is opened and its id is
%   returned. If id is set to -1, no possible window could be open so a new
%   window is opened and its value is returned in id.
%
%   The (boolean) variable wasOpen specifies that the window numbered id
%   was open (or not).
%
% Examples:
%    [id,wasOpen] = mrmCheckMeshServer(5);   % Checks for window 5
%
% Notes:
%    It would be nice to really just test, and not to test and open a new
%    one.  Also, I am not sure why the pauses are there.  Must be some
%    mrMesh bogosity. (BW)

warndlg('Obsolete.  mrmCheckMeshServer')

wasOpen = 0;
if ieNotDefined('id'), id = -1; end
if ieNotDefined('host') host = 'localhost'; end
oldId = id;

% Refreshing the window with this idea gives us the status.
[id,stat,res] = mrMesh(host, id, 'refresh');

if(id<-1)
    % If the server isn't up, id should be -1000.
    wasOpen = 0;
    switch computer
        case 'PCWIN'
            srvPath = which('mrMeshSrv.exe');
            dos([srvPath ' &']);
        case 'GLNX86'
            srvPath = which('mrMeshSrv.glx');
            eval(['! ' srvPath ' &']);
        otherwise
            error(['Platform "' computer '" is currently not supported!']);
        end
        % Some annoying inter-process communication pause.  Do not remove.
    pause(2); id = mrMesh(host, -1, 'refresh'); pause(1);
elseif(stat<0)
    % this means the server is up, but the specified ID doesn't exist (user
    % probably closed the window). So, we get a new window and return that
    % new id.
    id = mrMesh(host, -1, 'refresh');
    pause(1);
else
    if(oldId>=0)
        wasOpen = 1;
    end
end

return;


classdef MimBrushColourEditBox < MimGuiPluginEditBox
    % MimBrushColourEditBox. Gui Plugin for changing the size of the edit brush
    %
    %     You should not use this class within your own code. It is intended to
    %     be used by the gui of the TD MIM Toolkit.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties
        ButtonText = 'Custom'
        SelectedText = 'Custom'

        ToolTip = 'Change the colour of the editing paint brush'
        Category = 'Segmentation label'
        Visibility = 'Dataset'
        Mode = 'Edit'

        HidePluginInDisplay = false
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 1
        Location = 40

        MinValue = 0
        MaxValue = 255
        DefaultValue = 1

        EditBoxPosition = 90
        EditBoxWidth = 25

        StackVertically = false
    end

    methods (Static)
        function RunGuiPlugin(gui_app)
        end

        function enabled = IsEnabled(gui_app)
            enabled = gui_app.IsDatasetLoaded && gui_app.ImagePanel.OverlayImage.ImageExists && ...
                isequal(gui_app.ImagePanel.SelectedControl, 'Paint');
        end

        function is_selected = IsSelected(gui_app)
            is_selected = true;
        end

        function [value_instance_handle, value_property_name, limits_instance_handle, limits_property_name] = GetHandleAndProperty(gui_app)
            value_instance_handle = gui_app.ImagePanel;
            value_property_name = 'PaintBrushColour';
            limits_instance_handle = [];
            limits_property_name = [];
        end

    end
end


function seg = segCloseMesh(seg);
% seg = segCloseMesh(seg);
%
% Close a mesh in a segmentation. Also closes any display windows.
%
% ras, 10/2006.
m = seg.settings.mesh;
if meshGet(seg.mesh{m}, 'id') > 0
    % close mesh display window
    mrmSet(seg.mesh{m}, 'Close');
end
ok = setdiff(1:length(seg.mesh), m);
seg.mesh = seg.mesh(ok);
if isempty(ok)
	seg.settings.mesh = 0;
else
	seg.settings.mesh = max(m-1, 1); % either prev. mesh in list, or mesh 1
end

return


function ConvLDRvtoLDRi(filename, outputname, format)
%
%        ConvLDRvtoLDRi(filename, outputname, format)
%
%
%        Input:
%           -filename: video filename
%           -outputname: output name
%           -format: image file format
%
%        This function converts an LDR video into LDR images
%
%     Copyright (C) 2015  Francesco Banterle
%
%     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/>.
%

ldrv = ldrvread(filename);

for i=1:ldrv.totalFrames
    [frame, ldrv] = ldrvGetFrame(ldrv, i);
    imwrite(frame, [outputname, sprintf('_%07d.', i), format]);
end

end