function iStudies = db_add_condition(SubjectName, ConditionName, isRefresh, DateOfStudy)
% DB_ADD_CONDITION: Add a subdirectory with a default study file to one or all subjects (current protocol)
%
% USAGE:  iStudies = db_add_condition(SubjectName, ConditionName, isRefresh)
%         iStudies = db_add_condition(SubjectName, ConditionName)  : Refresh display by default
%         iStudies = db_add_condition(SubjectName)                 : Ask ConditionName to the user
%         iStudies = db_add_condition(iSubject, ...)               : Indicated subject's index instead of name
% INPUT:
%     - SubjectName   : String, name of the target subject.
%                       Use '*' to specify all the subjects
%     - ConditionName : String, name of the condition to add.
%                       If empty or ommitted, asked to the user
%     - isRefresh     : If 0, tree is not refreshed after adding condition
%                       If 1, tree is refreshed
%     - DateOfStudy   : String 'dd-MMM-yyyy', force Study entries created in the database to use this acquisition date
% OUTPUT:
%     - iStudies : Indices of the studies that were created.
%                  Returns [] if an error occurs

% @=============================================================================
% 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-2018

%% ===== PARSE INPUTS =====
if (nargin < 4) || isempty(DateOfStudy)
    DateOfStudy = date;
end
if (nargin < 3) || isempty(isRefresh)
    isRefresh = 1;
end
if (nargin < 2)
    ConditionName = java_dialog('input', 'New folder name: ', 'Add folder', [], 'NewCondition');
    if isempty(ConditionName)
        return
    end
end
if (nargin < 1) || isempty(SubjectName)
    error('You must define the first argument "SubjectName".');
end
% Normalize names (in order to create a directory out of it)
ConditionName = file_standardize(ConditionName, 1);
% Get protocol subjects database
ProtocolInfo     = bst_get('ProtocolInfo');
ProtocolSubjects = bst_get('ProtocolSubjects');
ProtocolStudies  = bst_get('ProtocolStudies');
% Returned value
iStudies = [];
isModified = 0;

%% ===== GET SUBJECTS =====
% If SubjectDir starts with '*' : get all subjects
if ischar(SubjectName) && (SubjectName(1) == '*')
    iSubjectsList = 1:length(ProtocolSubjects.Subject);
% Else: Look for subject
elseif ischar(SubjectName)
    [tmp__, iSubjectsList] = bst_get('Subject', SubjectName, 1);
elseif isnumeric(SubjectName)
    [tmp__, iSubjectsList] = bst_get('Subject', SubjectName, 1);
end
% No subject found
if isempty(iSubjectsList)
    bst_error('Invalid subject.', 'Add condition', 0);
    return;
end

%% ===== CREATE STUDIES =====
for iSubject = iSubjectsList
    % Cannot add study to default anatomy
    if (iSubject == 0)
        error('Cannot add folders to the default anatomy.');
    end
    % Get subject definition
    SubjectFile = ProtocolSubjects.Subject(iSubject).FileName;
    SubjectName = ProtocolSubjects.Subject(iSubject).Name;
    % Get conditions for this subject
    [sSubjStudies, iSubjStudies] = bst_get('StudyWithSubject', SubjectFile,'intra_subject', 'default_study');

    % If condition already exists for this subject: return it
    iExistStudy = find(strcmpi([sSubjStudies.Condition], ConditionName));
    if ~isempty(iExistStudy)
        disp(['BST> Condition "' ConditionName '" already exists for subject "' SubjectName '".']);
        iStudies(end+1) = iSubjStudies(iExistStudy);
        continue
    end

    % === Create study file ===
    % Create structure
    StudyMat = db_template('studymat');
    StudyMat.Name = ConditionName;
    StudyMat.DateOfStudy = DateOfStudy;
    % Filename : STUDIES/dirSubject/ConditionName/brainstormstudy.mat
    StudyFile = bst_fullfile(bst_fileparts(SubjectFile), ConditionName, 'brainstormstudy.mat');
    StudyFileFull = bst_fullfile(ProtocolInfo.STUDIES, StudyFile);
    % Create folder
    if ~file_exist(bst_fileparts(StudyFileFull))
        mkdir(bst_fileparts(StudyFileFull));
    end
    % Save brainstormstudy.mat file
    bst_save(StudyFileFull, StudyMat, 'v7');

    % === Create Study db structure ===
    sNewStudy = db_template('Study');
    sNewStudy.Name              = StudyMat.Name;
    sNewStudy.FileName          = file_win2unix(StudyFile);
    sNewStudy.DateOfStudy       = StudyMat.DateOfStudy;
    sNewStudy.BrainStormSubject = SubjectFile;
    sNewStudy.Condition         = str_split(ConditionName);
    % Add study to Brainstorm database
    iNewStudy = length(ProtocolStudies.Study) + 1;
    ProtocolStudies.Study(iNewStudy) = sNewStudy;
    % Add to returned indices list
    iStudies = [iStudies iNewStudy];
    isModified = 1;
end

%% ===== REFRESH DISPLAY =====
if isModified
    % Save modifications to Brainstorm database
    bst_set('ProtocolStudies', ProtocolStudies);
    % Set default study to the last added study
    ProtocolInfo.iStudy = iStudies(end);
    bst_set('ProtocolInfo', ProtocolInfo);
    % GUI update
    if isRefresh
        % Redraw tree
        panel_protocols('UpdateTree');
    end
    % Save database
    db_save();
end

end


function model = addInchiToModel(model, molFileDir,  method, printLevel)
% Assigns Inchi to model.inchi structure given set of mol files for each
% metabolite
%
% USAGE:
%
%    model = assignInchiToModel(model, molFileDir, printLevel)
%
% INPUT:
%    model          Model structure with following fields:
%
%                     * .S - `m x n` stoichiometric matrix.
%                     * .mets - `m x 1` array of metabolite identifiers.
%                     * .rxns - `n x 1` array of reaction identifiers.
%                     * .metFormulas - `m x 1` cell array of metabolite formulas. Formulas for
%                       protons should be H, and formulas for water should be H2O.
%                     * .metCharges - `m x 1` numerical array of metabolite charges.
%                     * .metCompartments - optional `m x 1` array of metabolite compartment
%                       assignments. Not required if metabolite
%                       identifiers are strings of the format `ID[*]`
%                       where * is the appropriate compartment identifier.
%
%    molFileDir:    Path to a directory containing molfiles for the
%                   major tautomer of the major microspecies of
%                   each metabolite at pH 7. Molfiles should be
%                   named with the metabolite identifiers in
%                   model.mets (without compartment assignments).
%
% OPTIONAL INPUTS:
%    printLevel:    Verbose level
%
% OUTPUTS:
%    model:          Model structure with following additional fields:
%
%                   * .inchi - Structure containing four `m x 1` cell array's of
%                     IUPAC InChI strings for metabolites, with varying
%                     levels of structural detail.
%
%                   * .inchi.standard: m x 1 cell array of standard inchi
%                   * .inchi.standardWithStereo: m x 1 cell array of standard inchi with stereo
%                   * .inchi.standardWithStereoAndCharge: m x 1 cell array of standard inchi with stereo and charge
%                   * .inchi.nonstandard: m x 1 cell array of non-standard inchi
%
%   inchiBool           m x 1 true if inchi exists
%   molBool             m x 1 true if mol file exists
%   compositeInchiBool  m x 1 true if inchi is composite

% Written output - MetStructures.sdf - An SDF containing all structures input to the
% component contribution method for estimation of standard Gibbs energies.

if ~exist('printLevel','var')
    printLevel = 1;
end
if ~exist('method','var')
    method = 'sdf';
end

switch method
    case 'sdf'
        % Get metabolite structures in molfileDir.
        if printLevel>0
            fprintf('Creating MetStructures.sdf from molfiles.\n')
        end
        sdfFileName = 'MetStructures.sdf';
        includeRs = 0; % Do not include structures with R groups in SDF
        [sdfMetList,noMolMetList] = mol2sdf(model.mets,molFileDir,sdfFileName,includeRs);

        sdfBool = ismember(model.mets,sdfMetList);

        model.molBool = ~ismember(model.mets,noMolMetList);

        if printLevel>0
            fprintf('Converting SDF to InChI strings.\n')
        end
        model.inchi = createInChIStruct(model.mets,[molFileDir filesep sdfFileName]);
    case 'mol'
        %assumes that model.mets without compartment info provides the name of
        %the mol files in molFileDir
        [model.inchi,model.molBool] = createInChIStruct(model.mets,[],molFileDir);
    otherwise
        error('unrecognised method')
end

%identify the metabolites without inchi
model.inchiBool = ~cellfun('isempty',model.inchi.nonstandard);

% Remove InChI for composite compounds as they cause problems later.
model.compositeInchiBool = ~cellfun('isempty',regexp(model.inchi.nonstandard,'\.'));
model.inchi.standard(model.compositeInchiBool) = cell(sum(model.compositeInchiBool),1);
model.inchi.standardWithStereo(model.compositeInchiBool) = cell(sum(model.compositeInchiBool),1);
model.inchi.standardWithStereoAndCharge(model.compositeInchiBool) = cell(sum(model.compositeInchiBool),1);
model.inchi.nonstandard(model.compositeInchiBool) = cell(sum(model.compositeInchiBool),1);

if printLevel>0
    fprintf('%u%s\n',length(model.mets),' = number of model metabolites')
    fprintf('%u%s\n',nnz(model.molBool),' ... with mol files')
    fprintf('%u%s\n',nnz(~model.molBool),' ... without mol files')
    fprintf('%u%s\n',nnz(model.inchiBool),' ... with nonstandard inchi')
    fprintf('%u%s\n',nnz(~model.inchiBool),' ... without nonstandard inchi')
    fprintf('%u%s\n',nnz(model.compositeInchiBool),' ... compositie inchi removed')
end


% eegplugin_4dneuroimaging() - EEGLAB plugin for importing 4D neuroimaging PDF files.
%
% Usage:
%   >> eegplugin_4dneuroimaging(fig, trystrs, catchstrs);
%
% Inputs:
%   fig        - [integer]  EEGLAB figure
%   trystrs    - [struct] "try" strings for menu callbacks.
%   catchstrs  - [struct] "catch" strings for menu callbacks.
%
% Create a plugin:
%   For more information on how to create an EEGLAB plugin see the
%   help message of eegplugin_besa() or visit http://www.sccn.ucsd.edu/eeglab/contrib.html
%
% Author: Christian Wienbruch, University of Konstanz, Clinical Psychology, 2005
%         (plugin interface: Arnaud Delorme, SCCN, INC, UCSD)

% Copyright (C) 2005 Christian Wienbruch, University of Konstanz, Clinical Psychology
%

function vers = eegplugin_4dneuroimaging(fig, trystrs, catchstrs)

  vers = '4dneuroimaging1.00';
  if nargin < 3
      error('eegplugin_4dneuroimaging requires 3 arguments');
  end;

  % add folder to path
  % ------------------
  if ~exist('pop_read4d')
      p = which('eegplugin_4dneuroimaging.m');
      p = p(1:findstr(p,'eegplugin_4dneuroimaging.m')-1);
      addpath([ p vers ] );
  end;

  % find import data menu
  % ---------------------
  menu = findobj(fig, 'tag', 'import data');

  % menu callbacks
  % --------------
  com = [ trystrs.no_check '[EEGTMP LASTCOM]= pop_read4d;' catchstrs.new_non_empty ];

  % create menus
  % ------------
  uimenu( menu, 'label',  'From 4D .m4d pdf file', 'callback', com, 'separator', 'on' );


% minFunc
fprintf('Compiling minFunc files...\n');
mex -outdir minFunc/compiled minFunc/mex/mcholC.c
mex -outdir minFunc/compiled minFunc/mex/lbfgsC.c
mex -outdir minFunc/compiled minFunc/mex/lbfgsAddC.c
% mex -outdir minFunc/compiled CXX='g++' CXXFLAGS='\$CXXFLAGS -O3 -funroll-loops -fopenmp' LDFLAGS="\$LDFLAGS -fopenmp" minFunc/mex/lbfgsProdC.cpp
if ismac()
    mex -v -outdir minFunc/compiled CXX='g++' CXXFLAGS='\$CXXFLAGS -O3' LDFLAGS="\$LDFLAGS" CXXOPTIMFLAGS='-O3' minFunc/mex/lbfgsProdC.cpp
elseif isunix()
    mex -v -outdir minFunc/compiled CXX='g++' CXXFLAGS='\$CXXFLAGS -O3 -fopenmp -funroll-loops' LDFLAGS="\$LDFLAGS -fopenmp" CXXOPTIMFLAGS='-O3' minFunc/mex/lbfgsProdC.cpp
%     mex -v -outdir minFunc/compiled CXX='g++' CXXFLAGS='\$CXXFLAGS -O0 ' LDFLAGS="\$LDFLAGS " CXXOPTIMFLAGS='-O0' minFunc/mex/lbfgsProdC.cpp
%     mex -outdir minFunc/compiled minFunc/mex/lbfgsProdC.cpp
elseif ispc()
    mex -v -outdir minFunc/compiled COMPFLAGS="-DUSE_WINDOWS /openmp /O3 $COMPFLAGS"  minFunc/mex/lbfgsProdC.cpp
end
% mex -v -outdir minFunc/compiled -fopenmp -O3 minFunc/mex/lbfgsProdC.cpp
% mex -v -outdir minFunc/compiled CXX='g++' CXXFLAGS='\$CXXFLAGS -O3 -msse4 -ftree-vectorize -ftree-vectorizer-verbose=5 -ftree-loop-distribution -funroll-all-loops -ftracer -funroll-loops -fopenmp' LDFLAGS="\$LDFLAGS -fopenmp" minFunc/mex/lbfgsProdC.cpp
% mex -outdir minFunc/compiled CXX='g++' CFLAGS='\$CFLAGS -O3 -msse4 -ftree-vectorize -ftree-vectorizer-verbose=5 -ftree-loop-distribution -funroll-all-loops -ftracer -funroll-loops -fopenmp' LDFLAGS="\$LDFLAGS -fopenmp" minFunc/mex/lbfgsProdC.c

%%
% mex -v -outdir minFunc/compiled COMPFLAGS="-DUSE_WINDOWS /openmp /O3 $COMPFLAGS"  minFunc/mex/lbfgsProdC.cpp


function [pkg, filenames] = MavenDownload(varargin)
    %MAVENDOWNLOAD  Downloads JAR artifacts from Maven Central
    %
    %     pkg = MavenDownload(groupId, artifactId)
    %     pkg = MavenDownload(..., 'OptionName',optionValue, ...)
    %     [pkg, filenames] = MavenDownload(...)
    %
    % ## Input
    % * __groupId__ group Id (organization name), may be empty if there is no
    %   ambiguity.
    % * __artifactId__ artifact Id (module name).
    %
    % ## Options
    % * __Version__ (optional) package version. If not specified, the
    %   latest version is requested.
    % * __SkipDependencies__ Decide if dependencies should not be processed.
    %   Default false.
    % * __Download__ Decide if packages should be downloaded. Default true.
    % * __Verbose__ Verbosity messages. Default true.
    % * __OutDir__ Directory where to place downloaded JAR files. By default,
    %   the current directory is used.
    %
    % ## Output
    % * __pkg__ struct describing the package and its dependencies
    % * __filenames__ Full paths to downloaded JAR files.
    %
    % This is a poor man's implementation of a Java package manager.
    % It searches the [Maven Central Repository](http://search.maven.org/)
    % and downloads a package JAR file and its dependencies.
    %
    % The Maven REST API is documented [here](http://search.maven.org/#api).
    %
    % ## Example
    %
    %     MavenDownload('org.jsoup', 'jsoup', 'OutDir','jsoup')
    %     MavenDownload('org.commonjava.googlecode.markdown4j', 'markdown4j', 'OutDir','markdown4j')
    %     MavenDownload('org.markdownj', 'markdownj-core', 'OutDir','markdownj')
    %     MavenDownload('org.tautua.markdownpapers', 'markdownpapers-core', 'OutDir','markdownpapers')
    %     MavenDownload('org.pegdown', 'pegdown', 'OutDir','pegdown')
    %     MavenDownload('com.github.rjeschke', 'txtmark', 'OutDir','txtmark')
    %     MavenDownload('com.atlassian.commonmark', 'commonmark', 'OutDir','commonmark-java')
    %     MavenDownload('com.atlassian.commonmark', 'commonmark-ext-gfm-tables', 'OutDir','commonmark-java')
    %
    % See also: webread, websave, urlencode, jsondecode
    %

    % parse inputs
    nargoutchk(0,2);
    opts = parse_options(varargin{:});

    % find requested package
    pkg = struct();
    pkg.groupId = opts.groupId;
    pkg.artifactId = opts.artifactId;
    pkg.version = opts.version;

    % search for latest version if none specified
    if isempty(pkg.groupId) || isempty(pkg.version)
        pkg = package_search(pkg, opts);
    end

    % find dependencies
    if ~opts.SkipDependencies
        pkg = package_dependencies(pkg, opts);
    end

    % download JAR files (including all dependencies)
    if opts.Download
        filenames = package_download(pkg, opts);
    end
end

function opts = parse_options(varargin)
    %PARSE_OPTIONS  Help function to parse function inputs

    % helper function to validate true/false arguments
    isbool = @(x) isscalar(x) && (islogical(x) || isnumeric(x));

    p = inputParser();
    p.addRequired('groupId', @ischar);
    p.addRequired('artifactId', @(x) ischar(x) && ~isempty(x));
    p.addParameter('version', '', @ischar);
    p.addParameter('SkipDependencies', false, isbool);
    p.addParameter('Download', true, isbool);
    p.addParameter('Verbose', true, isbool);
    p.addParameter('OutDir', '', @ischar);
    p.parse(varargin{:});

    opts = p.Results;
    opts.SkipDependencies = logical(opts.SkipDependencies);
    opts.Download = logical(opts.Download);
    opts.Verbose = logical(opts.Verbose);
end

function pkg = package_search(pkg, opts)
    %PACKAGE_SEARCH  Search for package from Maven by artifact Id

    % search by artifact id
    if opts.Verbose, disp(['Searching... ' pkg.artifactId]); end
    url = 'http://search.maven.org/solrsearch/select';
    query = {'q',sprintf('a:"%s"',pkg.artifactId), 'rows',5, 'wt','json'};
    data = webread(url, query{:}, weboptions('ContentType','json'));

    % check number of results
    assert(~isempty(data), 'No data received');
    res = data.response;
    if res.numFound == 0
        error('mexopencv:err', ...
            'artifactId = "%s" was not found', pkg.artifactId);
    elseif res.numFound > 1 && isempty(pkg.groupId)
        %disp({res.docs.g})
        error('mexopencv:err', ...
            'Ambiguous artifactId = "%s", specify groupId', pkg.artifactId);
    end

    % match groupId if specified
    idx = 1;
    if ~isempty(pkg.groupId)
        g = {res.docs.g};
        if res.numFound > 1
            [~,idx] = ismember(validatestring(pkg.groupId, g), g);
        else
            assert(strcmp(pkg.groupId, g{1}), ...
                'groupId = "%s" does not match "%s"', pkg.groupId, g{1});
        end
    end

    % unique project name
    pkg.groupId = res.docs(idx).g;
    pkg.artifactId = res.docs(idx).a;
    if isempty(pkg.version)
        pkg.version = res.docs(idx).latestVersion;
    end
end

function pkg = package_dependencies(pkg, opts)
    %PACKAGE_DEPENDENCIES  Fill package dependencies

    %TODO: cache dependencies to avoid fetching same POM multiple times
    %TODO: cyclic dependencies

    % fetch POM XML file
    fpath = package_filepath(pkg, '.pom');
    if opts.Verbose, disp(['Fetching... ' fpath]); end
    url = 'http://search.maven.org/remotecontent';
    query = {'filepath',fpath};
    pom = webread(url, query{:}, weboptions('ContentType','xmldom'));

    % parse it for dependencies (and transitive dependencies)
    pkg.deps = parse_pom(pom);
    for i=1:numel(pkg.deps)
        pkg.deps(i) = package_dependencies(pkg.deps(i), opts);
    end
end

function filenames = package_download(pkg, opts)
    %PACKAGE_DOWNLOAD  Download JAR package and its dependencies

    % fetch JAR file
    [fpath, filename] = package_filepath(pkg, '.jar');
    if ~isempty(opts.OutDir)
        filename = fullfile(opts.OutDir, filename);
        if ~isdir(opts.OutDir)
            mkdir(opts.OutDir);
        end
    end
    if exist(filename, 'file') ~= 2
        if opts.Verbose, disp(['Downloading... ' fpath]); end
        url = 'http://search.maven.org/remotecontent';
        query = {'filepath',fpath};
        filename = websave(filename, url, query{:});
    else
        if opts.Verbose, disp(['Skipped ' fpath]); end
    end
    filenames = filename;

    % download dependencies
    if ~opts.SkipDependencies
        fnames = cell(size(pkg.deps));
        for i=1:numel(pkg.deps)
            fnames{i} = package_download(pkg.deps(i), opts);
        end

        % combine and flatten names
        filenames = [filenames fnames];
        while any(cellfun(@iscell, filenames))
            filenames = [filenames{:}];
        end
        filenames = unique(filenames, 'stable');
    end
end

function [fpath, filename] = package_filepath(pkg, packaging)
    %PACKAGE_FILEPATH  Construct path to fetch package from Maven Central

    % fpath = org/github/com/my-project/1.0.0/my-project-1.0.0.jar
    assert(~isempty(pkg.groupId));
    assert(~isempty(pkg.artifactId));
    assert(~isempty(pkg.version));
    packaging = validatestring(packaging, ...
        {'.pom', '.jar', '-sources.jar', '-javadoc.jar'});
    filename = sprintf('%s-%s%s', pkg.artifactId, pkg.version, packaging);
    fpath = sprintf('%s/%s/%s/%s', ...
        strrep(pkg.groupId,'.','/'), pkg.artifactId, pkg.version, filename);
end

function deps = parse_pom(pom)
    %PARSE_POM  Extract dependencies from POM document DOM
    %
    % See also: xmlread
    %

    % output structure-array of dependencies
    deps = struct('groupId',{}, 'artifactId',{}, 'version',{}, 'deps',{});
    k = 1;  % insertion index

    % debug
    %{
    disp(pom.saveXML([]));
    keyboard
    %}

    % get <dependencies> tag
    nodes = pom.getElementsByTagName('dependencies').item(0);
    if isempty(nodes)
        return;  % no dependencies
    end

    % check if contains a <parent> tag
    node = pom.getElementsByTagName('parent').item(0);
    if ~isempty(node)
        p_groupId = getElementTextByTagName(node, 'groupId');
        p_artifactId = getElementTextByTagName(node, 'artifactId');
        p_version = getElementTextByTagName(node, 'version');
    else
        p_groupId = '';
        p_artifactId = '';
        p_version = '';
    end

    % loop over child <dependency> tags
    for i=1:nodes.getLength()
        node = nodes.item(i-1);

        % skip anything other than <dependency> (text/comments/etc. nodes)
        if node.getNodeType() ~= 1 || ~strcmp(node.getNodeName(), 'dependency')
            continue;
        end

        % check dependency <scope> and ignore test dependencies
        scope = getElementTextByTagName(node, 'scope');
        if ~isempty(scope) && strcmp(scope, 'test')
            continue;
        end

        % get dependency <groupId>, <artifactId>, <version>
        deps(k).groupId = getElementTextByTagName(node, 'groupId');
        deps(k).artifactId = getElementTextByTagName(node, 'artifactId');
        deps(k).version = getElementTextByTagName(node, 'version');

        %HACK: fill empty fields with parent fields
        if isempty(deps(k).groupId)
            deps(k).groupId = p_groupId;
        end
        if isempty(deps(k).artifactId)
            deps(k).artifactId = p_artifactId;
        end
        if isempty(deps(k).version)
            deps(k).version = p_version;
        end

        % prepare for next entry
        k = k + 1;
    end
end

function txt = getElementTextByTagName(node, tag)
    %GETELEMENTTEXTBYTAGNAME  Helper function to get text content of tag node

    % equivalent to: txt = node.select('tag').first().text()
    nodeTAG = node.getElementsByTagName(tag).item(0);
    if ~isempty(nodeTAG)
        txt = char(nodeTAG.getFirstChild().getTextContent());
    else
        txt = '';
    end
end


function vl_xmkdir(path, varargin)
% VL_XMKDIR  Create a directory recursively.
%   VL_XMKDIR(PATH) creates all directory specified by PATH if they
%   do not exist (existing directories are skipped).
%
%   The function accepts the following options:
%
%   Pretend:: [false]
%     Set to true to avoid creating any directory but print which
%     directories would be created (implies 'Verbose',true).
%
%   Verbose:: [false]
%     Set to true to print the operations performed.
%
%   See also: VL_HELP().

% Authors: Andrea Vedaldi

% Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

pretend = false ;
verbose = false ;

for ai=1:2:length(varargin)
  opt = varargin{ai} ;
  arg = varargin{ai+1} ;
  switch lower(opt)
    case 'pretend'
      pretend = arg ;
    case 'verbose'
      verbose = arg ;
    otherwise
      error('Unknown option ''%s''.', opt) ;
  end
end

verbose = verbose | pretend ;

if isempty(path)
  return ;
end

[subPath, name, ext] = fileparts(path) ;
name = [name ext] ;

% subPath is equal to path if path = '/'
if ~strcmp(subPath, path)
  vl_xmkdir(subPath, varargin{:}) ;
end

% name is empty if path = '*/'
if isempty(name)
  return ;
end

if verbose
  fprintf('%s: directory ''%s'' in ''%s''', mfilename, name, subPath) ;
end

if ~exist(path, 'dir')
  if pretend && verbose
    fprintf(' does not exist, would create.\n') ;
  else
    mkdir(subPath, name) ;
    if verbose
      fprintf(' did not exist, created.\n') ;
    end
  end
else
  if verbose
    if pretend
      fprintf(' exists, would not create.\n') ;
    else
      fprintf(' exists, not creating.\n') ;
    end
  end
end


function name = PTKGetUserVisibleNameForContext(context)
    % PTKGetUserVisibleNameForContext.
    %
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2014.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    context = char(context);

    if strcmp(context, 'Lungs')
        name = 'Both lungs';
    elseif strcmp(context, 'LeftLung')
        name = 'Left lung';
    elseif strcmp(context, 'RightLung')
        name = 'Right lung';
    elseif strcmp(context, 'LeftUpperLobe')
        name = 'Left upper lobe';
    elseif strcmp(context, 'LeftLowerLobe')
        name = 'Left lower lobe';
    elseif strcmp(context, 'RightUpperLobe')
        name = 'Right upper lobe';
    elseif strcmp(context, 'RightLowerLobe')
        name = 'Right lower lobe';
    elseif strcmp(context, 'RightMiddleLobe')
        name = 'Right middle lobe';
    else
        name = context;
    end
end


%% runGmsh
% Below is a demonstration of the features of the |runGmsh| function

%%
clear; close all; clc;

%% Syntax
% |;|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*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 [filename ok] = getROIfilename(vw, local)
% gets file names of ROIs to load
%
%     filename = getROIfilename(vw, [local])
%
% INPUTS:
%	vw: mrVista view.
%
%	local: flag indicating whether to use the local ROI directory (e.g.,
%	'Gray/ROIs/') or the shared ROI directory (e.g., '3DAnatomy/ROIs').
%	[default: 1, local]
%
% ras, 2009: now this calls a much-improved dialog in roiDialog.
if notDefined('vw'),    vw = getCurView; end
if notDefined('local')
    local = 1; %isequal(vw.viewType, 'Inplane');
else
    % if local is defined AND if local ~=1
    if ~local,
        if ispref('VISTA', 'verbose') && getpref('VISTA', 'verbose')==1
            disp('Loading from shared ROI directory');
        end
    end
end

switch vw.viewType
    case 'Inplane'
        initDir = 'Inplane/ROIs';
        dirList = {'Inplane/ROIs'};

    case 'Volume'
        sharedDir = fullfile(getAnatomyPath, 'ROIs');
        if local==1
            initDir = 'Volume/ROIs';
        else
            initDir = sharedDir;
        end
        dirList = {sharedDir 'Volume/ROIs' 'Gray/ROIs'};

    case 'Gray'
        if (ispref('VISTA','defaultROIPath'))

            sharedDir = fullfile(getAnatomyPath, getpref('VISTA','defaultROIPath'));
        else
            sharedDir = fullfile(getAnatomyPath, 'ROIs');
        end
        if local==1
            initDir = 'Gray/ROIs';
        else
            initDir = sharedDir;
        end
        dirList = {sharedDir 'Volume/ROIs' 'Gray/ROIs'};

    case 'Flat'
        initDir = fullfile(vw.subdir, 'ROIs');
        dirList = {initDir};

    otherwise
        initDir = '';
        dirList = {};
end

[filename ok] = roiDialog(initDir, dirList);
if ~ok, filename = ''; end

return


function Out = LimitFigSize(FigH, Prop, Ext)
    % LimitFigSize - Set and get minimum or maximum figure size
    % Out = LimitFigSize(FigH, Prop, Ext)
    % INPUT:
    %   FigH: Handle of a Matlab figure.
    %         Optional, default: current figure.
    %   Prop: String, command:
    %         'min': Set minimum extent.
    %         'max': Set maximum extent.
    %         'get': Reply a struct with fields MinSize and MaxSize. If not limited,
    %                the empty matrix [] is replied.
    %         'clear': Clear the min and max limits.
    %         Optional, default: 'min'
    %   Ext:  [width, height] vector to determing the extent of the inner position
    %         in pixels. Optional, default: Current extent.
    %
    % OUTPUT:
    %   Out:  Output for the 'get' command.
    %
    % EXAMPLES:
    %   FigH = figure;
    %   LimitFigSize(FigH, 'min', [200, 200])
    %   LimitFigSize('max', [400, 400])        % Current figure as default
    %   LimitFigSize('min')                    % Current figure, current extent
    %   Limit = LimitFigSize(FigH, 'get')
    %
    % NOTE: This function is based on undocumented functions, such that it might
    % fail in future versions.
    %
    % Tested: Matlab 7.7, 7.8, 7.13, 8.6, WinXP/32, Win7/64
    %         Not compatible to Matlab 6.5.
    % Author: Jan Simon, Heidelberg, (C) 2012-2015 matlab.2010(a)n(MINUS)simon.de
    %
    % See also MaximizeFig, AlphaFig, ClipFig, TopFig, ToMonitorFig, WindowAPI.
    % $JRev: R-i V:008 Sum:6o/8OiL6gm/Z Date:20-Dec-2015 17:20:36 $
    % $License: BSD (use/copy/change/redistribute on own risk, mention the author) $
    % $UnitTest: uTest_LimitFigSize $
    % $File: Tools\GLGui\LimitFigSize.m $
    % History:
    % 001: 07-Oct-2012 15:02, First version.
    % 005: 02-Nov-2014 02:31, Consider HG2 client.
    %      BUGFIX: Replies empty matrix for 'get' if size has not been limited.
    % Initialize: ==================================================================
    % Global Interface: ------------------------------------------------------------
    % Consider dependencies to Matlab versions:
    MatlabVer = [100, 1] * sscanf(version, '%d.', 2);
    hasHG2    = (MatlabVer >= 804);
    hasHG1    = (MatlabVer >= 706);
    % hasHG2 = isa(FigH, 'matlab.ui.Figure');
    % hasHG2 = ~isnumeric(FigH);
    if ~usejava('jvm') || MatlabVer < 700
        % Should this be an error, a warning or a message??
        warning(['JSimon:', mfilename, ':NeedJava'], ...
            '*** %s: Require java and Matlab >= R14.', mfilename);
        return;
    end
    % Initial values: --------------------------------------------------------------
    % Program Interface: -----------------------------------------------------------
    % Parse the inputs:
    switch nargin
        case 0
            FigH = gcf;
            Prop = 'min';
            Ext  = [];
        case 1
            if numel(FigH) == 1 && ishandle(FigH)  % LimitFigSize(FigH)
                Prop = 'min';
                Ext  = [];
            elseif ischar(FigH)                    % LimitFigSize('string')
                Prop = FigH;
                Ext  = [];
                FigH = GetCurrentFigure(hasHG2);
            else                                   % LimitFigSize([W, H])
                Prop = 'min';
                Ext  = FigH;
                FigH = GetCurrentFigure(hasHG2);
            end
        case 2
            if ischar(FigH)                        % LimitFigSize('string', [W, H])
                Ext  = Prop;
                Prop = FigH;
                FigH = GetCurrentFigure(hasHG2);
            elseif numel(FigH) == 1 && ishandle(FigH)
                if ischar(Prop)                     % LimitFigSize(FigH, 'string')
                    Ext  = [];
                else                                % LimitFigSize(FigH, [W, H])
                    Ext  = Prop;
                    Prop = 'min';
                end
            else
                error(['JSimon:', mfilename, ':BadHandle'], ...
                    '*** %s: 1st input is not a figure handle or string.', mfilename);
            end
        case 3
            % Nothing to do
        otherwise
    end
    % Check if input is a figure handle:
    if numel(FigH) ~= 1 || ~ishandle(FigH) || ...     % Short-circuit
            ~strcmpi(get(FigH, 'Type'), 'figure')
        error(['JSimon:', mfilename, ':BadHandle'], ...
            '*** %s: 1st input is not a figure handle.', mfilename);
    end
    % User Interface: --------------------------------------------------------------
    % Do the work: =================================================================
    % Get the Java frame:
    if hasHG2
        % Suppress warnings:
        bakWarn = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
        jFrame  = get(handle(FigH), 'JavaFrame');  % Fails in Matlab < 7.0
        warning(bakWarn);
    else
        jFrame = get(handle(FigH), 'JavaFrame');  % Fails in Matlab < 7.0
    end
    try
        if hasHG2      % HG2 since R2014b:
            jClient = jFrame.fHG2Client;
        elseif hasHG1  % R2008a up to 2014a:
            jClient = jFrame.fHG1Client;
        else           % R14 (7.0) to R2011a:
            jClient = jFrame.fFigureClient;
        end
    catch ME          % Getting the client is not documented and subject to changes:
        error(['JSimon:', mfilename, ':NoJClient'], ...
            'Cannot get Java Figure Client: %s', ME.message);
    end
    % The com.mathworks.hg.peer.FigureFrameProxy is empty, if no DRAWNOW allowed to
    % update the figure since its creation:
    jWindow = jClient.getWindow;
    if isempty(jWindow)
        drawnow;
        pause(0.2);
        jWindow = jClient.getWindow;
    end
    % Apply, clear or get the limits:
    if strncmpi(Prop, 'min', 3)
        Ext = GetExtent(FigH, Ext);
        jWindow.setMinimumSize(java.awt.Dimension(Ext(1), Ext(2)));
    elseif strncmpi(Prop, 'max', 3)
        Ext = GetExtent(FigH, Ext);
        jWindow.setMaximumSize(java.awt.Dimension(Ext(1), Ext(2)));
    elseif strcmpi(Prop, 'clear')
        jWindow.setMinimumSize([]);
        jWindow.setMaximumSize([]);
    elseif strcmpi(Prop, 'get')
        % Get difference to outer limits:
        bakUnits = get(FigH, 'Units');
        set(FigH, 'Units', 'pixels');
        DiffPos = get(FigH, 'OuterPosition') - get(FigH, 'Position');
        set(FigH, 'Units', bakUnits);
        jDim = jWindow.getMinimumSize;
        if isempty(jDim)  % Size has not been limited before:
            Out.MinSize = [];
        else
            Out.MinSize = [jDim.getWidth, jDim.getHeight] - DiffPos(3:4);
        end

        jDim = jWindow.getMaximumSize;
        if isempty(jDim)
            Out.MaxSize = [];
        else
            Out.MaxSize = [jDim.getWidth, jDim.getHeight] - DiffPos(3:4);
        end
    end
    % return;
    % ******************************************************************************
function FigH = GetCurrentFigure(hasHG2)
    % A DRAWNOW is required when the figure is created to update the Java handle.
    % See GCF.
    if hasHG2
        FigH = get(groot,'CurrentFigure');
    else
        FigH = get(0, 'CurrentFigure');
    end
    if isempty(FigH)
        FigH = figure;
        drawnow;
    end
    % return;
    % ******************************************************************************
function Ext = GetExtent(FigH, Ext)
    % Get or convert extent to outer position.
    bakUnits = get(FigH, 'Units');
    set(FigH, 'Units', 'pixels');
    OuterPos = get(FigH, 'OuterPosition');
    if isempty(Ext)
        Ext = OuterPos(3:4);
    elseif isnumeric(Ext) && numel(Ext) == 2 && all(Ext >= 0)
        InnerPos = get(FigH, 'Position');
        Ext      = [Ext(1) + OuterPos(3) - InnerPos(3), ...
            Ext(2) + OuterPos(4) - InnerPos(4)];
    else
        error(['JSimon:', mfilename, ':BadSize'], ...
            '*** %s: Extent must be a positive [1 x 2] vector.', mfilename);
    end
    set(FigH, 'Units', bakUnits);
    % return;


function varargout = lvd_EditGeometricRefFramesGUI(varargin)
% LVD_EDITGEOMETRICREFFRAMESGUI MATLAB code for lvd_EditGeometricRefFramesGUI.fig
%      LVD_EDITGEOMETRICREFFRAMESGUI, by itself, creates a new LVD_EDITGEOMETRICREFFRAMESGUI or raises the existing
%      singleton*.
%
%      H = LVD_EDITGEOMETRICREFFRAMESGUI returns the handle to a new LVD_EDITGEOMETRICREFFRAMESGUI or the handle to
%      the existing singleton*.
%
%      LVD_EDITGEOMETRICREFFRAMESGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in LVD_EDITGEOMETRICREFFRAMESGUI.M with the given input arguments.
%
%      LVD_EDITGEOMETRICREFFRAMESGUI('Property','Value',...) creates a new LVD_EDITGEOMETRICREFFRAMESGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before lvd_EditGeometricRefFramesGUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to lvd_EditGeometricRefFramesGUI_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 lvd_EditGeometricRefFramesGUI

% Last Modified by GUIDE v2.5 11-Jan-2021 18:38:54

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @lvd_EditGeometricRefFramesGUI_OpeningFcn, ...
                   'gui_OutputFcn',  @lvd_EditGeometricRefFramesGUI_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 lvd_EditGeometricRefFramesGUI is made visible.
function lvd_EditGeometricRefFramesGUI_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 lvd_EditGeometricRefFramesGUI (see VARARGIN)

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

    lvdData = varargin{1};
    setappdata(hObject,'lvdData',lvdData);

    populateGUI(handles, lvdData);

    % Update handles structure
    guidata(hObject, handles);

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

function populateGUI(handles, lvdData)
    set(handles.refFrameListBox,'String',lvdData.geometry.refFrames.getListboxStr());

    numRefFrames = length(get(handles.refFrameListBox,'String'));

    if(handles.refFrameListBox.Value < 1)
        handles.refFrameListBox.Value = 1;
    elseif(handles.refFrameListBox.Value > numRefFrames)
        handles.refFrameListBox.Value = numRefFrames;
    end

    if(numRefFrames <= 0)
        handles.removeRefFrameButton.Enable = 'off';
    else
        handles.removeRefFrameButton.Enable = 'on';
    end

% --- Outputs from this function are returned to the command line.
function varargout = lvd_EditGeometricRefFramesGUI_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
    if(isempty(handles))
        varargout{1} = [];
    else
        close(handles.lvd_EditGeometricRefFramesGUI);
    end

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

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

% Hints: contents = cellstr(get(hObject,'String')) returns refFrameListBox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from refFrameListBox
    lvdData = getappdata(handles.lvd_EditGeometricRefFramesGUI,'lvdData');
    if(strcmpi(get(handles.lvd_EditGeometricRefFramesGUI,'SelectionType'),'open') && ...
       lvdData.geometry.refFrames.getNumRefFrames() > 0)
        selRefFrameInd = hObject.Value;
        selRefFrame = lvdData.geometry.refFrames.getRefFrameAtInd(selRefFrameInd);

        selRefFrame.openEditDialog();

        populateGUI(handles, lvdData);
    end

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

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --- Executes on button press in addRefFrameButton.
function addRefFrameButton_Callback(hObject, eventdata, handles)
% hObject    handle to addRefFrameButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    lvdData = getappdata(handles.lvd_EditGeometricRefFramesGUI,'lvdData');

    listboxStr = GeometricRefFrameEnum.getListBoxStr();
    [Selection,ok] = listdlgARH('ListString', listboxStr, ...
                                'SelectionMode', 'single', ...
                                'ListSize', [300 300], ...
                                'InitialValue',1, ...
                                'Name', 'Select New Reference Frame Type', ...
                                'PromptString', 'Select the type of the reference frame to be created:');

    if(ok)
        enum = GeometricRefFrameEnum.getEnumForListboxStr(listboxStr{Selection});

        switch enum
            case GeometricRefFrameEnum.CoordSystemOrigin
                numPoints = lvdData.geometry.points.getNumPoints();
                numCoordSystems = lvdData.geometry.coordSyses.getNumCoordSyses();
                if(numPoints >= 1 && numCoordSystems >= 1)
                    origin = lvdData.geometry.points.getPointAtInd(1);
                    coordSys = lvdData.geometry.coordSyses.getCoordSysAtInd(1);
                    newRefFrame = CoordSysPointRefFrame(coordSys, origin, 'New Reference Frame', lvdData);

                else
                    errordlg('Cannot create Coordinate System at Origin Reference Frame: There must be at least one geometric point and one coordinate system available.','Cannot Create Reference Frame');
                    return;
                end

            otherwise
                error('Unknown Reference Frame Type: %s', enum.name)
        end

        useTF = newRefFrame.openEditDialog();

        if(useTF)
            lvdData.geometry.refFrames.addRefFrame(newRefFrame);

            populateGUI(handles, lvdData);
        end
    end

% --- Executes on button press in removeRefFrameButton.
function removeRefFrameButton_Callback(hObject, eventdata, handles)
% hObject    handle to removeRefFrameButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    lvdData = getappdata(handles.lvd_EditGeometricRefFramesGUI,'lvdData');

    selRefFrameInd = handles.refFrameListBox.Value;
    selRefFrame = lvdData.geometry.refFrames.getRefFrameAtInd(selRefFrameInd);

	tf = selRefFrame.isInUse(lvdData);

    if(tf == false)
        lvdData.geometry.refFrames.removeRefFrame(selRefFrame);

        lvdData.viewSettings.removeGeoRefFrameFromViewProfiles(selRefFrame);

        populateGUI(handles, lvdData);

        numRefFrames = lvdData.geometry.refFrames.getNumRefFrames();
        if(handles.refFrameListBox.Value > numRefFrames)
            set(handles.refFrameListBox,'Value',numRefFrames);
        end
    else
        warndlg(sprintf('Could not delete the geometric reference frame "%s" because it is in use elsewhere.  Remove the reference frame dependencies before attempting to delete the reference frame.', selRefFrame.getName()),'Cannot Delete Reference Frame','modal');
    end

% --- Executes on key press with focus on lvd_EditGeometricRefFramesGUI or any of its controls.
function lvd_EditGeometricRefFramesGUI_WindowKeyPressFcn(hObject, eventdata, handles)
% hObject    handle to lvd_EditGeometricRefFramesGUI (see GCBO)
% eventdata  structure with the following fields (see MATLAB.UI.FIGURE)
%	Key: name of the key that was pressed, in lower case
%	Character: character interpretation of the key(s) that was pressed
%	Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles    structure with handles and user data (see GUIDATA)
    switch(eventdata.Key)
        case 'return'
            uiresume(handles.lvd_EditGeometricRefFramesGUI);
        case 'enter'
            uiresume(handles.lvd_EditGeometricRefFramesGUI);
        case 'escape'
            uiresume(handles.lvd_EditGeometricRefFramesGUI);
    end


function varargout = lvd_GraphicalAnalysisGUI(varargin)
% LVD_GRAPHICALANALYSISGUI MATLAB code for lvd_GraphicalAnalysisGUI.fig
%      LVD_GRAPHICALANALYSISGUI, by itself, creates a new LVD_GRAPHICALANALYSISGUI or raises the existing
%      singleton*.
%
%      H = LVD_GRAPHICALANALYSISGUI returns the handle to a new LVD_GRAPHICALANALYSISGUI or the handle to
%      the existing singleton*.
%
%      LVD_GRAPHICALANALYSISGUI('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in LVD_GRAPHICALANALYSISGUI.M with the given input arguments.
%
%      LVD_GRAPHICALANALYSISGUI('Property','Value',...) creates a new LVD_GRAPHICALANALYSISGUI or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before lvd_GraphicalAnalysisGUI_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to lvd_GraphicalAnalysisGUI_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 lvd_GraphicalAnalysisGUI

% Last Modified by GUIDE v2.5 09-Aug-2020 18:29:26

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @lvd_GraphicalAnalysisGUI_OpeningFcn, ...
                   'gui_OutputFcn',  @lvd_GraphicalAnalysisGUI_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 lvd_GraphicalAnalysisGUI is made visible.
function lvd_GraphicalAnalysisGUI_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 lvd_GraphicalAnalysisGUI (see VARARGIN)

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

    % Set up GUI
    lvdData = varargin{1};
    setappdata(hObject,'lvdData',lvdData);

    handles.ma_LvdMainGUI = varargin{2};

    exclude = getLvdGAExcludeList();

    taskList = lvd_getGraphAnalysisTaskList(lvdData, exclude);
    set(handles.depVarListbox,'String',taskList);

    maStateLog = lvdData.stateLog.getMAFormattedStateLogMatrix(true);

%     propNames = {'Liquid Fuel/Ox','Monopropellant','Xenon'};
    propNames = lvdData.launchVehicle.tankTypes.getFirstThreeTypesCellArr();
    substituteDefaultPropNamesWithCustomNamesInDepVarListbox(handles.depVarListbox, propNames);
    useSubplotCheckbox_Callback(handles.useSubplotCheckbox, [], handles);
    set(handles.startTimeText,'String',fullAccNum2Str(min(maStateLog(:,1))));
    set(handles.endTimeText,'String',fullAccNum2Str(max(maStateLog(:,1))));
    populateBodiesCombo(lvdData.celBodyData, handles.refBodyCombo);
    % populateOtherSCCombo(handles, handles.refSpacecraftCombo);
    % populateStationsCombo(handles, handles.refStationCombo);
    indepVarCombo_Callback(handles.indepVarCombo, [], handles);

    setappdata(hObject,'xLineValue',[]);
    setappdata(hObject,'yLineValue',[]);

    % Update handles structure
    guidata(hObject, handles);

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

% --- Outputs from this function are returned to the command line.
function varargout = lvd_GraphicalAnalysisGUI_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 selection change in indepVarCombo.
function indepVarCombo_Callback(hObject, eventdata, handles)
% hObject    handle to indepVarCombo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = cellstr(get(hObject,'String')) returns indepVarCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from indepVarCombo
    contents = cellstr(get(hObject,'String'));
    selected = deblank(contents{get(hObject,'Value')});

    if(strcmpi(selected,'Time') || strcmpi(selected,'Mission Elapsed Time'))
        set(handles.showEventTerminationCheckbox,'Enable','on');
%         set(handles.showSoITransCheckbox,'Enable','on');
        set(handles.showPeriCheckbox,'Enable','on');
        set(handles.showApoCheckbox,'Enable','on');
    else
        set(handles.showEventTerminationCheckbox,'Enable','off');
%         set(handles.showSoITransCheckbox,'Enable','off');
        set(handles.showPeriCheckbox,'Enable','off');
        set(handles.showApoCheckbox,'Enable','off');
    end

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

% Hint: get(hObject,'Value') returns toggle state of useSubplotCheckbox
    if(get(hObject,'Value'))
        set(handles.subPlotSizeXText,'Enable','on');
        set(handles.subPlotSizeYText,'Enable','on');
    else
        set(handles.subPlotSizeXText,'Enable','off');
        set(handles.subPlotSizeYText,'Enable','off');
    end

function subPlotSizeXText_Callback(hObject, eventdata, handles)
% hObject    handle to subPlotSizeXText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of subPlotSizeXText as text
%        str2double(get(hObject,'String')) returns contents of subPlotSizeXText as a double

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

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function subPlotSizeYText_Callback(hObject, eventdata, handles)
% hObject    handle to subPlotSizeYText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of subPlotSizeYText as text
%        str2double(get(hObject,'String')) returns contents of subPlotSizeYText as a double

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

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function lineWidthText_Callback(hObject, eventdata, handles)
% hObject    handle to lineWidthText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of lineWidthText as text
%        str2double(get(hObject,'String')) returns contents of lineWidthText as a double

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

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

% Hints: contents = cellstr(get(hObject,'String')) returns lineColorCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from lineColorCombo

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

% Hints: contents = cellstr(get(hObject,'String')) returns backgndColorCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from backgndColorCombo

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

% Hints: contents = cellstr(get(hObject,'String')) returns lineSpecCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from lineSpecCombo

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

    if(~isempty(errMsg))
        msgbox(errMsg,'Errors were found while validating your split value.  Please sure value is between the given bounds.','error');
        return;
    end

    lvdData = getappdata(handles.lvd_GraphicalAnalysisGUI,'lvdData');
    celBodyData = lvdData.celBodyData;
    maStateLog = lvdData.stateLog.getMAFormattedStateLogMatrix(true);

    taskInds = get(handles.depVarListbox,'Value');
    if(isempty(taskInds))
        errordlg('Error: No valid dependent variables selected.');
        return;
    end

    startTimeUT = str2double(get(handles.startTimeText,'String'));
    endTimeUT = str2double(get(handles.endTimeText,'String'));

    lineWidth = str2double(get(handles.lineWidthText,'String'));

    contents = cellstr(get(handles.lineColorCombo,'String'));
    lineColorStr = contents{get(handles.lineColorCombo,'Value')};
    lineColor = getLineSpecColorFromString(lineColorStr);

    contents = cellstr(get(handles.backgndColorCombo,'String'));
    bgColorStr = contents{get(handles.backgndColorCombo,'Value')};
    bgColor = getLineSpecColorFromString(bgColorStr);

    contents = cellstr(get(handles.lineSpecCombo,'String'));
    lineTypeStr = contents{get(handles.lineSpecCombo,'Value')};
    switch lineTypeStr
        case 'Solid Line'
            lineType = '-';
        case 'Dashed Line'
            lineType = '--';
        case 'Dotted Line'
            lineType = ':';
        case 'Dash-dot Line'
            lineType = '-.';
        otherwise
            lineType = '-';
    end

    propNames = lvdData.launchVehicle.tankTypes.getFirstThreeTypesCellArr();

    lvdSubLog = lvdData.stateLog.getStateLogEntriesBetweenTimes(startTimeUT, endTimeUT);
    maSubLog = maStateLog(maStateLog(:,1) >= startTimeUT & maStateLog(:,1) <= endTimeUT,:);

    contentsIndep = cellstr(get(handles.indepVarCombo,'String'));
    indepVarValues = zeros(size(maSubLog,1), 2);
    indepVarStr = deblank(contentsIndep{get(handles.indepVarCombo,'Value')});

    contentsIndepUnit = cellstr(get(handles.indepVarTimeUnit,'String'));
    indepVarUnitStr = deblank(contentsIndepUnit{get(handles.indepVarTimeUnit,'Value')});

    [secInMin, secInHr, secInDay, secInYear] = getSecondsInVariousTimeUnits();
    switch indepVarUnitStr
        case 'Seconds'
            indepTimeUnit = 'sec';
            indepTimeUnitMult = 1;
        case 'Minutes'
            indepTimeUnit = 'min';
            indepTimeUnitMult = 1/secInMin;
        case 'Hours'
            indepTimeUnit = 'hr';
            indepTimeUnitMult = 1/secInHr;
        case 'Days'
            indepTimeUnit = 'day';
            indepTimeUnitMult = 1/secInDay;
        case 'Years'
            indepTimeUnit = 'year';
            indepTimeUnitMult = 1/secInYear;
    end

    switch indepVarStr
        case 'Time'
            indepVarValues = indepTimeUnitMult*[maSubLog(:,1), maSubLog(:,1)];
            indepVarUnits = indepTimeUnit;

        case 'Mission Elapsed Time'
            indepVarValues = indepTimeUnitMult*[maSubLog(:,1) - maStateLog(1,1), maSubLog(:,1)];
            indepVarUnits = indepTimeUnit;

        case 'True Anomaly'
            for(i=1:size(maSubLog,1))
                indepVarValues(i,:) = [ma_GAKeplerElementsTask(maSubLog(i,:), 'tru', celBodyData), maSubLog(i,1)];
            end
            indepVarUnits = 'deg';

        case 'Longitude'
            for(i=1:size(maSubLog,1))
                indepVarValues(i,:) = [ma_GALongLatAltTasks(maSubLog(i,:), 'long', celBodyData), maSubLog(i,1)];
            end
            indepVarUnits = 'degE';

        case 'Altitude'
            for(i=1:size(maSubLog,1))
                indepVarValues(i,:) = [ma_GALongLatAltTasks(maSubLog(i,:), 'alt', celBodyData), maSubLog(i,1)];
            end
            indepVarUnits = 'km';
    end

    hWaitBar = waitbar(0,'Computing Dependent Variables...','WindowStyle','modal');
    depVarValues = zeros(size(maSubLog,1), length(taskInds));
    depVarUnits = cell(1,length(taskInds));
    contentsDep = strtrim(cellstr(get(handles.depVarListbox,'String')));
    prevDistTraveled = 0;

    hRefBodyCombo = handles.refBodyCombo;
    contents = cellstr(get(hRefBodyCombo,'String'));
    refBodyStr = contents{get(hRefBodyCombo,'Value')};
    refBodyInfo = celBodyData.(strtrim(lower(refBodyStr)));
    refBodyId = refBodyInfo.id;

    hRefSCCombo = handles.refSpacecraftCombo;
    if(strcmpi(get(hRefSCCombo,'Enable'),'off'))
        otherSCId = [];
    else
        try
            refSCInd = get(hRefSCCombo,'Value');
            otherSCs = maData.spacecraft.otherSC;
            otherSCId = otherSCs{refSCInd}.id;
        catch
            otherSCId = [];
        end
    end

%     hRefStnCombo = handles.refStationCombo;
%     if(strcmpi(get(hRefStnCombo,'Enable'),'off'))
%         stationID = [];
%     else
%         try
%             refSCInd = get(hRefStnCombo,'Value');
%             stations = maData.spacecraft.stations;
%             stationID = stations{refSCInd}.id;
%         catch
%
%         end
%     end

    stationID = [];

    dataEvtNums = [];
    maTaskList = ma_getGraphAnalysisTaskList({});
    for(i=1:size(maSubLog,1))
        for(j=1:length(taskInds))
            taskInd = taskInds(j);
            taskStr = contentsDep{taskInd};

            if(isvalid(hWaitBar))
                waitbar(i/size(maSubLog,1), hWaitBar, sprintf('Computing Dependent Variables...\n[%u of %u]', i, size(maSubLog,1)));
            end

            if(ismember(taskStr,maTaskList))
                [depVarValues(i,j), depVarUnits{j}, prevDistTraveled] = ma_getDepVarValueUnit(i, maSubLog, taskStr, prevDistTraveled, refBodyId, otherSCId, stationID, propNames, [], celBodyData, false);
            else
                [depVarValues(i,j), depVarUnits{j}] = lvd_getDepVarValueUnit(i, lvdSubLog, taskStr, refBodyId, celBodyData, false);
            end
        end

        dataEvtNums(i) = maSubLog(i,13);
    end
    close(hWaitBar);

    plotMethods = [lvdData.script.evts.plotMethod];
    if(any(plotMethods == EventPlottingMethodEnum.SkipFirstState))
        evtIndsToInsertNaNBetween = find(plotMethods == EventPlottingMethodEnum.SkipFirstState);

        stateInds = [];
        for(i=1:length(evtIndsToInsertNaNBetween))
            evtInd = evtIndsToInsertNaNBetween(i);
            stateInd = find(maSubLog(:,13) == evtInd,1,'first');
            if(stateInd > 1)
                stateInds(end+1) = stateInd;
            end
        end

        numIndepVars = size(indepVarValues,2);
        numDepVars = size(depVarValues,2);
        for(i=1:length(stateInds))
            indepVarValues = [indepVarValues(1:stateInds(i)-1,:); NaN(1,numIndepVars); indepVarValues(stateInds(i)+1:end,:)];
            depVarValues = [depVarValues(1:stateInds(i)-1,:); NaN(1,numDepVars); depVarValues(stateInds(i)+1:end,:)];

%             if(i < length(stateInds))
%                 stateInds(i+1:end) = stateInds(i+1:end)+1;  %accounts for the fact that we're inserting data
%             end
        end
    end

    useEvtLineColor = logical(handles.useEvtLineColorsCheckbox.Value);
    evts = [lvdData.script.evts];

    figNum = 100;
    if(get(handles.useSubplotCheckbox,'Value'))
        subPlotMaxX = str2double(get(handles.subPlotSizeXText,'String'));
        subPlotMaxY = str2double(get(handles.subPlotSizeYText,'String'));

        hFig = figure(figNum);
        whitebg(hFig, bgColor);
        plotNum = 0;
        for(i = 1:size(depVarValues,2))
            plotNum = plotNum  +1;
            if(plotNum > subPlotMaxX*subPlotMaxY)
                figNum = figNum + 1;
                hFig = figure(figNum);
                plotNum = 1;
            end

            data = depVarValues(:,i);

            taskInd = taskInds(i);
            taskStr = contentsDep{taskInd};

            subplot(subPlotMaxX,subPlotMaxY,plotNum);
            plotData(hFig, indepVarValues, data, lineColor, useEvtLineColor, evts, dataEvtNums, lineType, lineWidth, indepVarStr, taskStr, bgColor, indepVarUnits, indepTimeUnitMult, depVarUnits{i}, maStateLog, startTimeUT, endTimeUT, celBodyData, handles.lvd_GraphicalAnalysisGUI);
        end
    else
        for(i = 1:size(depVarValues,2)) %#ok<*NO4LP>
            data = depVarValues(:,i);

            taskInd = taskInds(i);
            taskStr = contentsDep{taskInd};

            hFig = figure(figNum+i);
            whitebg(hFig, bgColor);
            plotData(hFig, indepVarValues, data, lineColor, useEvtLineColor, evts, dataEvtNums, lineType, lineWidth, indepVarStr, taskStr, bgColor, indepVarUnits, indepTimeUnitMult, depVarUnits{i}, maStateLog, startTimeUT, endTimeUT, celBodyData, handles.lvd_GraphicalAnalysisGUI);
        end
    end

    if(get(handles.generateTextOutputCheckbox,'Value'))
        matSave = getappdata(handles.ma_LvdMainGUI,'current_save_location');
        [pathstr,name,~] = fileparts(matSave);
        if(isempty(pathstr))
            pathstr = uigetdir(pwd,'Select folder to save tabular text output');
            name = 'UntitledMission';
        end
        csvFilename = [pathstr,'\',name,'_GraphicalAnalysis_',datestr(now,'yyyymmdd_HHMMSS'),'.csv'];

        indepVarUnitStr = indepVarUnits;
        if(~isempty(indepVarUnitStr))
            indepVarUnitStr = [' [',indepVarUnitStr,']'];
        else
            indepVarUnitStr = '';
        end

        taskStrs = [indepVarStr,indepVarUnitStr,','];
        for(i = 1:length(taskInds)) %#ok<*NO4LP>
            taskInd = taskInds(i);
            taskStr = contentsDep{taskInd};

                depVarUnitStr = depVarUnits{i};
                if(~isempty(depVarUnitStr))
                    depVarUnitStr = [' [',depVarUnitStr,']']; %#ok<*AGROW>
                else
                    depVarUnitStr = '';
                end

                taskStr = [taskStr,depVarUnitStr];

            taskStrs = [taskStrs,taskStr,','];
        end
        taskStrs = [taskStrs,'\n'];
        if(pathstr ~= 0)
            fid = fopen(csvFilename,'wt+');
            fprintf(fid,taskStrs);
            fclose(fid);

            M = [indepVarValues(:,1),depVarValues];
            dlmwrite(csvFilename, M, '-append','precision', 15);

            msgbox(sprintf('Tabular output written to file: \n%s',csvFilename), 'Tabular Output', 'help');
        end
    end

function plotData(hFig, indepVarValues, data, lineColor, useEvtLineColor, evts, dataEvtNums, lineType, lineWidth, indepVarStr, taskStr, bgColor, indepVarUnitStr, indepTimeUnitMult, depVarUnitStr, maStateLog, startTimeUT, endTimeUT, celBodyData, hGAFig)
    xLineValue = getappdata(hGAFig,'xLineValue');
    yLineValue = getappdata(hGAFig,'yLineValue');

    hold on;
    for(i=1:length(evts))
        evt = evts(i);
        eventNum = evt.getEventNum();

        bool = dataEvtNums == eventNum;

        subIndVal = indepVarValues(bool,1);
        subData = data(bool);

        switch(evt.plotMethod)
            case EventPlottingMethodEnum.PlotContinuous
                %nothing

            case EventPlottingMethodEnum.SkipFirstState
                subIndVal = subIndVal(2:end);
                subData = subData(2:end);

%                 maStateLog =

            case EventPlottingMethodEnum.DoNotPlot
                maStateLog(maStateLog(:,13) == eventNum,:) = [];

                continue;

            otherwise
                error('Unknown event plotting method: %s', EventPlottingMethodEnum.DoNotPlot.name);
        end

        if(useEvtLineColor)
            lineColor = evt.colorLineSpec.color.color;
            plot(subIndVal, subData, 'Color',lineColor, 'LineStyle',lineType, 'LineWidth',lineWidth);
        else
            plot(subIndVal, subData, 'Color',lineColor, 'LineStyle',lineType, 'LineWidth',lineWidth);
        end
    end

    minData = min(data);
    maxData = max(data);
    if(minData == maxData)
        minData = minData - 0.75;
        maxData = maxData + 0.75;
    end
    onePercData = (maxData-minData)/100;

    if(~isempty(xLineValue))
        if(xLineValue >= min(indepVarValues(:,1)) && xLineValue <= max(indepVarValues(:,1)))
            if(strcmpi(bgColor,'c'))
                markerLineColor = 'w';
            else
                markerLineColor = 'c';
            end
            plot([xLineValue xLineValue], [minData maxData],markerLineColor,'LineWidth',0.25);
        end
    end

    if(~isempty(yLineValue))
        if(yLineValue >= min(data) && yLineValue <= max(data))
            if(strcmpi(bgColor,'c'))
                markerLineColor = 'w';
            else
                markerLineColor = 'c';
            end
            plot([min(indepVarValues(:,1)) max(indepVarValues(:,1))], [yLineValue yLineValue],markerLineColor,'LineWidth',0.25);
        end
    end

    subLog = maStateLog(maStateLog(:,1) >= startTimeUT & maStateLog(:,1) <= endTimeUT,:);
    subLogUnsorted = subLog;
    subLog = sortrows(subLog,[1]);
    subLog = unique(subLog,'rows');

    hShowMan = findobj('Tag','showEventTerminationCheckbox');
    if(get(hShowMan,'Value') && strcmpi(get(hShowMan,'Enable'), 'on'))
        if(strcmpi(bgColor,'r'))
            evtEndLineColor = 'w';
        else
            evtEndLineColor = 'r';
        end

        allEventNums = subLogUnsorted(:,13);
        x = diff(allEventNums)~=0;
        inds = find(x);
        inds = [inds; length(allEventNums)];

        minData = min(data);
        maxData = max(data);
        if(minData == maxData)
            minData = minData - 0.75;
            maxData = maxData + 0.75;
        end

        for(i=1:length(inds))
            ind = inds(i);

            eventTime = subLogUnsorted(ind,1)*indepTimeUnitMult;
            indepVarEventLoc = indepVarValues(indepVarValues(:,2)==eventTime,1);
            indepVarEventLoc = indepVarEventLoc(1);

            evtNum = subLogUnsorted(ind,13);

            plot([indepVarEventLoc indepVarEventLoc], [minData, maxData],evtEndLineColor,'LineWidth',0.25);
            text(indepVarEventLoc,maxData-8*onePercData,sprintf(' Event %u End ',evtNum),'Color',evtEndLineColor);

        end
    end

    hShowSoI = findobj('Tag','showSoITransCheckbox');
    if(get(hShowSoI,'Value') && strcmpi(get(hShowSoI,'Enable'), 'on'))
        if(strcmpi(bgColor,'m'))
            soiLineColor = 'w';
        else
            soiLineColor = 'm';
        end

        allBodyIDs = subLog(:,8);
        x = diff(allBodyIDs)~=0;
        inds = find(x);
        for(i=1:length(inds))
            ind = inds(i)+1;

            bodyLog = subLog(ind,:);
            bodyID = bodyLog(1,8);
            bodyInfo = getBodyInfoByNumber(bodyID, celBodyData);

            if(bodyLog(1,1) == startTimeUT)
                continue;
            end
            eventTime = bodyLog(1,1)*indepTimeUnitMult;
            indepVarEventLoc = indepVarValues(indepVarValues(:,2)==eventTime,1);
            indepVarEventLoc = indepVarEventLoc(1);

            minData = min(data);
            maxData = max(data);
            if(minData == maxData)
                minData = minData - 0.75;
                maxData = maxData + 0.75;
            end

            plot([indepVarEventLoc indepVarEventLoc], [minData, maxData],soiLineColor,'LineWidth',0.25);
            text(indepVarEventLoc,maxData-2*onePercData,[' To ',bodyInfo.name],'Color',soiLineColor);
        end
    end

    hShowPeri = findobj('Tag','showPeriCheckbox');
    if(get(hShowPeri,'Value') && strcmpi(get(hShowPeri,'Enable'), 'on'))
        if(strcmpi(bgColor,'g'))
            periLineColor = 'w';
        else
            periLineColor = 'g';
        end

        periCnt = 1;
        allBodyIDs = subLog(:,8);
        x = diff(allBodyIDs)~=0;
        inds = find(x)+1;
        inds = [1 inds' length(allBodyIDs)+1];
        for(i=1:length(inds)-1)
            ind = inds(i);
            nextInd = inds(i+1)-1;

            bodyLog = subLog(ind:nextInd,:);
            bodyID = bodyLog(1,8);
            bodyInfo = getBodyInfoByNumber(bodyID, celBodyData);

            [~, ~, ~, ~, ~, tru] = vect_getKeplerFromState(bodyLog(:,2:4)',bodyLog(:,5:7)',bodyInfo.gm);
            tru = angleNegPiToPi(tru);

            for(j=2:length(tru))
                tru1 = tru(j-1);
                tru2 = tru(j);

%                 if(((tru1 > tru2 && abs(tru1-tru2)>pi) || (tru1 < 0 && tru2 >= 0)) && bodyLog(j-1,8)==bodyLog(j,8))
                if(((tru1 < 0 && tru2 >= 0)) && bodyLog(j-1,8)==bodyLog(j,8))
                    eventTime = bodyLog(j,1)*indepTimeUnitMult;
                    indepVarEventLoc = indepVarValues(indepVarValues(:,2)==eventTime,1);
                    indepVarEventLoc = indepVarEventLoc(1);

                    minData = min(data);
                    maxData = max(data);
                    if(minData == maxData)
                        minData = minData - 0.75;
                        maxData = maxData + 0.75;
                    end

                    plot([indepVarEventLoc indepVarEventLoc], [minData, maxData],periLineColor,'LineWidth',0.25);
                    text(indepVarEventLoc,maxData-4*onePercData,[' P',num2str(periCnt)],'Color',periLineColor);
                    periCnt = periCnt + 1;
                end
            end
        end
    end

	hShowApo = findobj('Tag','showApoCheckbox');
    if(get(hShowApo,'Value') && strcmpi(get(hShowApo,'Enable'), 'on'))
        if(strcmpi(bgColor,'b'))
            apoLineColor = 'w';
        else
            apoLineColor = 'b';
        end

        apoCnt = 1;
        allBodyIDs = subLog(:,8);
        x = diff(allBodyIDs)~=0;
        inds = find(x)+1;
        inds = [1 inds' length(allBodyIDs)+1];
        for(i=1:length(inds)-1)
            ind = inds(i);
            nextInd = inds(i+1)-1;

            bodyLog = subLog(ind:nextInd,:);
            bodyID = bodyLog(1,8);
            bodyInfo = getBodyInfoByNumber(bodyID, celBodyData);

            [~, ~, ~, ~, ~, tru] = vect_getKeplerFromState(bodyLog(:,2:4)',bodyLog(:,5:7)',bodyInfo.gm);

            for(j=2:length(tru))
                tru1 = tru(j-1);
                tru2 = tru(j);

                if(tru1 < pi && tru2 >= pi && bodyLog(j-1,8)==bodyLog(j,8))
                    eventTime = bodyLog(j,1)*indepTimeUnitMult;
                    indepVarEventLoc = indepVarValues(indepVarValues(:,2)==eventTime,1);
                    indepVarEventLoc = indepVarEventLoc(1);

                    minData = min(data);
                    maxData = max(data);
                    if(minData == maxData)
                        minData = minData - 0.75;
                        maxData = maxData + 0.75;
                    end

                    plot([indepVarEventLoc indepVarEventLoc], [minData, maxData],apoLineColor,'LineWidth',0.25);
                    text(indepVarEventLoc,maxData-6*onePercData,[' A',num2str(apoCnt)],'Color',apoLineColor);
                    apoCnt = apoCnt + 1;
                end
            end
        end
    end

    hGridOn = findobj('Tag','showGridCheckboxGA');
    if(get(hGridOn,'Value'))
        grid on;
    else
        grid off;
    end

    if(~isempty(indepVarUnitStr))
        indepVarUnitStr = [' [',indepVarUnitStr,']'];
    else
        indepVarUnitStr = '';
    end

    if(~isempty(depVarUnitStr))
        depVarUnitStr = [' [',depVarUnitStr,']'];
    else
        depVarUnitStr = '';
    end

    xlabel([indepVarStr,indepVarUnitStr]);
    ylabel([taskStr,depVarUnitStr]);

    hold off;

    dcmObj = datacursormode;
    set(dcmObj,'UpdateFcn',@dataTipFormatFunc,'Enable','on');

function errMsg = validateInputs(handles)
%     maData = getappdata(handles.ma_MainGUI,'ma_data');
%     celBodyData = getappdata(handles.ma_MainGUI,'celBodyData');
    lvdData = getappdata(handles.lvd_GraphicalAnalysisGUI,'lvdData');
    celBodyData = lvdData.celBodyData;
    stateLog = lvdData.stateLog.getMAFormattedStateLogMatrix(true);

    errMsg = {};

    stateLogMinUT = floor(min(stateLog(:,1))*10000)/10000;
    stateLogMaxUT = ceil(max(stateLog(:,1))*10000)/10000;

    value = str2double(get(handles.startTimeText,'String'));
    enteredStr = get(handles.startTimeText,'String');
    numberName = 'Start Time (UT)';
    lb = stateLogMinUT;
    ub = stateLogMaxUT;
    isInt = false;
    errMsg = validateNumber(value, numberName, lb, ub, isInt, errMsg, enteredStr);

    value = str2double(get(handles.endTimeText,'String'));
    enteredStr = get(handles.endTimeText,'String');
    numberName = 'End Time (UT)';
    lb = stateLogMinUT;
    ub = stateLogMaxUT;
    isInt = false;
    errMsg = validateNumber(value, numberName, lb, ub, isInt, errMsg, enteredStr);

    if(isempty(errMsg))
        startUTEntered = str2double(get(handles.startTimeText,'String'));

        value = str2double(get(handles.endTimeText,'String'));
        enteredStr = get(handles.endTimeText,'String');
        numberName = 'End Time (UT)';
        lb = startUTEntered;
        ub = stateLogMaxUT;
        isInt = false;
        errMsg = validateNumber(value, numberName, lb, ub, isInt, errMsg, enteredStr);
    end

    if(get(handles.useSubplotCheckbox,'Value'))
        value = str2double(get(handles.subPlotSizeXText,'String'));
        enteredStr = get(handles.subPlotSizeXText,'String');
        numberName = 'Sub Plot X Size';
        lb = 1;
        ub = 10;
        isInt = true;
        errMsg = validateNumber(value, numberName, lb, ub, isInt, errMsg, enteredStr);

        value = str2double(get(handles.subPlotSizeYText,'String'));
        enteredStr = get(handles.subPlotSizeYText,'String');
        numberName = 'Sub Plot Y Size';
        lb = 1;
        ub = 10;
        isInt = true;
        errMsg = validateNumber(value, numberName, lb, ub, isInt, errMsg, enteredStr);
    end

    value = str2double(get(handles.lineWidthText,'String'));
    enteredStr = get(handles.lineWidthText,'String');
    numberName = 'Line Width';
    lb = 0.25;
    ub = 5;
    isInt = false;
    errMsg = validateNumber(value, numberName, lb, ub, isInt, errMsg, enteredStr);

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

% Hints: contents = cellstr(get(hObject,'String')) returns depVarListbox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from depVarListbox

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

% Hint: listbox controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function startTimeText_Callback(hObject, eventdata, handles)
% hObject    handle to startTimeText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of startTimeText as text
%        str2double(get(hObject,'String')) returns contents of startTimeText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

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

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function endTimeText_Callback(hObject, eventdata, handles)
% hObject    handle to endTimeText (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of endTimeText as text
%        str2double(get(hObject,'String')) returns contents of endTimeText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

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

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --------------------------------------------------------------------
function enterUTAsDateTime_Callback(hObject, eventdata, handles)
% hObject    handle to enterUTAsDateTime (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    secUT = enterUTAsDateTimeGUI(str2double(get(gco, 'String')));
    if(secUT >= 0)
        set(gco, 'String', num2str(secUT));
    end

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

% Hints: contents = cellstr(get(hObject,'String')) returns refBodyCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from refBodyCombo

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

% Hints: contents = cellstr(get(hObject,'String')) returns refSpacecraftCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from refSpacecraftCombo

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

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

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

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

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

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

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

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

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

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

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

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

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

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

% Hints: contents = cellstr(get(hObject,'String')) returns refStationCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from refStationCombo

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

function output_txt = dataTipFormatFunc(obj,event_obj)
% Display the position of the data cursor
% obj          Currently not used (empty)
% event_obj    Handle to event object
% output_txt   Data cursor text string (string or cell array of strings).
    pos = get(event_obj,'Position');
    output_txt = {['X: ',num2str(pos(1),'%12.5f')],...
        ['Y: ',num2str(pos(2),'%12.5f')]};

    % If there is a Z-coordinate in the position, display it as well
    if length(pos) > 2
        output_txt{end+1} = ['Z: ',num2str(pos(3),'%12.5f')];
    end

% --- Executes on button press in markerLinesButton.
function markerLinesButton_Callback(hObject, eventdata, handles)
% hObject    handle to markerLinesButton (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    xLineValue = getappdata(handles.lvd_GraphicalAnalysisGUI,'xLineValue');
    yLineValue = getappdata(handles.lvd_GraphicalAnalysisGUI,'yLineValue');

    defAns = cell(1,2);
    if(~isempty(xLineValue))
        defAns{1} = num2str(xLineValue);
    else
        defAns{1} = '';
    end
    if(~isempty(yLineValue))
        defAns{2} = num2str(yLineValue);
    else
        defAns{2} = '';
    end

    answer = inputdlg({'Draw a vertical line at X=? (Blank to clear)';
                       'Draw a horizontal line at Y=? (Blank to clear)'},...
                       'Marker Lines',...
                        1,...
                        defAns);
	answer = strtrim(answer);
    if(isempty(answer))
        return;
    end

    newX = str2double(answer{1});
    if(isnan(newX))
        newXStr = [];
    else
        newXStr = newX;
    end

    newY = str2double(answer{2});
    if(isnan(newY))
        newYStr = [];
    else
        newYStr = newY;
    end

    setappdata(handles.lvd_GraphicalAnalysisGUI,'xLineValue',newXStr);
    setappdata(handles.lvd_GraphicalAnalysisGUI,'yLineValue',newYStr);

% --- Executes on key press with focus on lvd_GraphicalAnalysisGUI or any of its controls.
function lvd_GraphicalAnalysisGUI_WindowKeyPressFcn(hObject, eventdata, handles)
% hObject    handle to lvd_GraphicalAnalysisGUI (see GCBO)
% eventdata  structure with the following fields (see MATLAB.UI.FIGURE)
%	Key: name of the key that was pressed, in lower case
%	Character: character interpretation of the key(s) that was pressed
%	Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles    structure with handles and user data (see GUIDATA)
    switch(eventdata.Key)
        case 'escape'
            close(handles.lvd_GraphicalAnalysisGUI);
    end

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

% Hints: contents = cellstr(get(hObject,'String')) returns indepVarTimeUnit contents as cell array
%        contents{get(hObject,'Value')} returns selected item from indepVarTimeUnit

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

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

% --------------------------------------------------------------------
function setTimeFromScriptMenu_Callback(hObject, eventdata, handles)
% hObject    handle to setTimeFromScriptMenu (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
    lvdData = getappdata(handles.lvd_GraphicalAnalysisGUI,'lvdData');
    stateLog = lvdData.stateLog.getMAFormattedStateLogMatrix(false);

    h = gco;
    if(strcmpi(h.Tag,'startTimeText'))
        set(gco,'String', num2str(min(stateLog(:,1)), '%1.15f'));
    elseif(strcmpi(h.Tag,'endTimeText'))
        set(gco,'String', num2str(max(stateLog(:,1)), '%1.15f'));
    else
        return;
    end

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

% Hint: get(hObject,'Value') returns toggle state of useEvtLineColorsCheckbox
    if(hObject.Value)
        handles.lineColorCombo.Enable = 'off';
    else
        handles.lineColorCombo.Enable = 'on';
    end