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

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

% Last Modified by GUIDE v2.5 04-Jan-2008 12:38:42

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

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

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

guidata(handles.guifig,handles);
% Choose default command line output for selection_gui
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

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

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

% Get default command line output from handles structure
set(handles.guifig,'WindowStyle','Modal'); %make figure modal

uiwait; %wait till the figure is destroyed  or asked to resume

try %this statement is necessary if figure is destroyed , then output argument will be empty by default
    handles = guidata(handles.guifig);
    varargout{1} = handles.selection;
    closereq; % close the gui if OK is pressed
catch
    varargout{1} = [];
end

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

if isfield(handles,'value');%if there is no selection of radio button and OK is pressed then the selection is Radio Button1 by default
    handles.selection = handles.value;
else
    handles.selection = 'Radio Button1';
end

guidata(hObject, handles);
guidata(handles.guifig, handles);

uiresume;

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

switch get(hObject,'Tag')   % Get Tag of selected object
    case 'radio1'
        handles.value = 'Radio Button1'; %if Radio Button1 is selected then update handles.value
    case 'radio2'
        handles.value = 'Radio Button2';%if Radio Button2 is selected then update handles.value
end
guidata(hObject, handles);

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

% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: delete(hObject) closes the figure
delete(hObject);


function sys = flatten(sys)

% Go from an internal format which is hierarchical and performs better
% when adding many constraint objects.
if length(sys.clauses)>0
    if isa(sys.clauses{1},'cell')
        sys.clauses = [sys.clauses{:}];
    end
end


function obj = runPipeline(obj,varargin)
	% DESCRIPTION
	% Biafra Ahanonu
	% started: 2014.07.31 - branch from calciumImagingAnalysis 2020.05.07 [15:47:29]
	% inputs
		%
	% outputs
		%

	% changelog
		% 2020.05.09 [18:36:01] - Added a check to make sure certain directories are unloaded after running a module if they are not needed.
		% 2021.08.10 [09:57:36] - Updated to handle CIAtah v4.0 switch to all functions inside ciapkg package.
		% 2022.02.25 [09:54:56] - Eliminate the close all figure when initializing the main GUI. Unexpected for some users and undesirable in certain cases. Instead close all figures if a method is selected, this avoids user not getting feedback if figures are re-used and focus is not shifted.
	% TODO
		%

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

	try
		setFigureDefaults();
	catch err
		disp(repmat('@',1,7))
		disp(getReport(err,'extended','hyperlinks','on'));
		disp(repmat('@',1,7))
		obj.loadBatchFunctionFolders();
	end
	try
		set(0, 'DefaultUICOntrolFontSize', obj.fontSizeGui)
	catch
		set(0, 'DefaultUICOntrolFontSize', 11)
	end
	% close all;
	clc;

	fxnsToRun = obj.methodsList;
	%========================
	options.fxnsToRun = fxnsToRun;
	% get options
	options = getOptions(options,varargin);
	% disp(options)
	% unpack options into current workspace
	% fn=fieldnames(options);
	% for i=1:length(fn)
	%	eval([fn{i} '=options.' fn{i} ';']);
	% end
	%========================
	fxnsToRun = options.fxnsToRun;
	% initialDir = pwd;
	% set back to initial directory in case exited early
	% restoredefaultpath;
	% loadBatchFxns();
	if strcmp(obj.defaultObjDir,pwd)~=1
		cd(obj.defaultObjDir);
	end

	if ischar(obj.videoDir)
		obj.videoDir = {obj.videoDir};
	end

	% ensure private folders are set
	if ~exist(obj.picsSavePath,'dir');mkdir(obj.picsSavePath);end
	if ~exist(obj.dataSavePath,'dir');mkdir(obj.dataSavePath);end
	if ~exist(obj.logSavePath,'dir');mkdir(obj.logSavePath);end

	props = properties(obj);
	totSize = 0;
	% for ii=1:length(props)
	%	  currentProperty = getfield(obj, char(props(ii)));
	%	  s = whos('currentProperty');
	%	  totSize = totSize + s.bytes;
	% end
	% sprintf('%.f',totSize*1.0e-6)
	% fprintf(1, '%d bytes\n', totSize*1.0e-6);
	% runs all currently implemented view functions

	scnsize = get(0,'ScreenSize');
	dlgSize = [scnsize(3)*0.4 scnsize(4)*0.6];

	currentIdx = find(strcmp(fxnsToRun,obj.currentMethod));
	% Only keep the 1st method if it is twice in the function list.
	[~,duplicateIdx] = unique(fxnsToRun,'stable');
	currentIdx = intersect(currentIdx,duplicateIdx);
	% [idNumIdxArray, ok] = listdlg('ListString',fxnsToRun,'InitialValue',currentIdx(1),'ListSize',dlgSize,'Name','Sir! I have a plan! Select a calcium imaging analysis method or procedure to run:');

	[idNumIdxArray, fileIdxArray, ok] = obj.ciatahMainGui(fxnsToRun,['"Sir! I have a plan!" Hover over ' ciapkg.pkgName ' methods for tooltips.'],currentIdx);
	obj.foldersToAnalyze = fileIdxArray;
	bypassUI = 1;

	% [idNumIdxArray, ok] = obj.pipelineListBox(fxnsToRun,['"Sir! I have a plan!" Select a calciumImagingAnalysis method or procedure to run. Hover over items for tooltip descriptions.'],currentIdx);
	if ok==0;
		subfxnCheckDirs();
		return;
	end

	% excludeList = {'showVars','showFolders','setMainSettings','modelAddNewFolders','loadDependencies','saveObj','setStimulusSettings','modelDownsampleRawMovies'};
	% excludeListVer2 = {'modelEditStimTable','behaviorProtocolLoad','modelPreprocessMovie','modelModifyMovies','removeConcurrentAnalysisFiles'};
	% excludeListStimuli = {'modelVarsFromFiles'};
	excludeList = obj.methodExcludeList;
	excludeListVer2 = obj.methodExcludeListVer2;
	excludeListStimuli = obj.methodExcludeListStimuli;

	if isempty(intersect(fxnsToRun,excludeList))&isempty(intersect(fxnsToRun,excludeListVer2))
		% [guiIdx, ok] = listdlg('ListString',{'Yes','No'},'InitialValue',1,'ListSize',dlgSize,'Name','GUI Enabled?');
		[guiIdx, ok] = obj.pipelineListBox({'Yes','No'},['GUI Enabled?'],1);
		if ok==0; return; end
		% idNumIdxArray
		% turn off gui elements, run in batch
		obj.guiEnabled = guiIdx==1;
	end

	fxnsToRun = {fxnsToRun{idNumIdxArray}};
	obj.currentMethod = fxnsToRun{1};

	if bypassUI==0&isempty(intersect(fxnsToRun,excludeList))
		scnsize = get(0,'ScreenSize');
		usrIdxChoiceStr = obj.usrIdxChoiceStr;
		usrIdxChoiceDisplay = obj.usrIdxChoiceDisplay;
		% use current string as default
		currentIdx = find(strcmp(usrIdxChoiceStr,obj.signalExtractionMethod));
		% [sel, ok] = listdlg('ListString',usrIdxChoiceDisplay,'InitialValue',currentIdx,'ListSize',dlgSize,'Name','Get to the data! Cell extraction algorithm to use for analysis?');
		[sel, ok] = obj.pipelineListBox(usrIdxChoiceDisplay,['"Get to the data!" Cell extraction algorithm to use for analysis?'],currentIdx);

		if ok==0; return; end
		% (Americans love a winner)
		usrIdxChoiceList = {2,1};
		obj.signalExtractionMethod = usrIdxChoiceStr{sel};
	end
	if bypassUI==0&~isempty(obj.inputFolders)&isempty(intersect(fxnsToRun,excludeList))&isempty(intersect(fxnsToRun,excludeListVer2))
		if isempty(obj.protocol)
			obj.modelGetFileInfo();
		end
		folderNumList = strsplit(num2str(1:length(obj.inputFolders)),' ');
		selectList = strcat(folderNumList(:),'/',num2str(length(obj.inputFolders)),' | ',obj.date(:),' _ ',obj.protocol(:),' _ ',obj.fileIDArray(:),' | ',obj.inputFolders(:));
		% set(0, 'DefaultUICOntrolFontSize', 16)
		% select subjects to analyze
		subjectStrUnique = unique(obj.subjectStr);
		% [subjIdxArray, ok] = listdlg('ListString',subjectStrUnique,'ListSize',dlgSize,'Name','Which subjects to analyze?');
		[subjIdxArray, ok] = obj.pipelineListBox(subjectStrUnique,['Which subjects to analyze?'],1);
		if ok==0; return; end
		subjToAnalyze = subjectStrUnique(subjIdxArray);
		subjToAnalyze = find(ismember(obj.subjectStr,subjToAnalyze));
		% get assays to analyze
		assayStrUnique = unique(obj.assay(subjToAnalyze));
		% [assayIdxArray, ok] = listdlg('ListString',assayStrUnique,'ListSize',dlgSize,'Name','Which assays to analyze?');
		[assayIdxArray, ok] = obj.pipelineListBox(assayStrUnique,['Which assays to analyze?'],1);
		if ok==0; return; end
		assayToAnalyze = assayStrUnique(assayIdxArray);
		assayToAnalyze = find(ismember(obj.assay,assayToAnalyze));
		% filter for folders chosen by the user
		validFoldersIdx = intersect(subjToAnalyze,assayToAnalyze);
		% if isempty(validFoldersIdx)
		%	  continue;
		% end
		useAltValid = {'no additional filter','manual index entry','manually sorted folders','not manually sorted folders','manual classification already in obj',['has ' obj.signalExtractionMethod ' extracted cells'],['missing ' obj.signalExtractionMethod ' extracted cells'],'fileFilterRegexp','valid auto',['has ' obj.fileFilterRegexp ' movie file']};
		useAltValidStr = {'no additional filter','manual index entry','manually sorted folders','not manually sorted folders','manual classification already in obj',['has extracted cells'],'missing extracted cells','fileFilterRegexp','valid auto','movie file'};
		% [choiceIdx, ok] = listdlg('ListString',useAltValid,'ListSize',dlgSize,'Name','Choose additional folder sorting filters');
		[choiceIdx, ok] = obj.pipelineListBox(useAltValid,['Choose additional folder sorting filters'],1);
		if ok==0; return; end

		if ok==1
			useAltValid = useAltValidStr{choiceIdx};
		else
			useAltValid = 0;
		end
		% useAltValid = 0;
		[validFoldersIdx] = pipelineFolderFilter(obj,useAltValid,validFoldersIdx);

		% [fileIdxArray, ok] = listdlg('ListString',selectList,'ListSize',dlgSize,'Name','Which folders to analyze?','InitialValue',validFoldersIdx);
		[fileIdxArray, ok] = obj.pipelineListBox(selectList,['Which folders to analyze?'],validFoldersIdx);
		if ok==0; return; end

		obj.foldersToAnalyze = fileIdxArray;
		if isempty(obj.stimulusNameArray)|~isempty(intersect(fxnsToRun,excludeListVer2))|~isempty(intersect(fxnsToRun,excludeListStimuli))
			obj.discreteStimuliToAnalyze = [];
		else
			% [idNumIdxArray, ok] = listdlg('ListString',obj.stimulusNameArray,'ListSize',dlgSize,'Name','which stimuli to analyze?');
			[idNumIdxArray, ok] = obj.pipelineListBox(obj.stimulusNameArray,['Which stimuli to analyze?'],1);
			if ok==0; return; end

			obj.discreteStimuliToAnalyze = idNumIdxArray;
		end
	elseif bypassUI==0&~isempty(intersect(fxnsToRun,excludeListVer2))
		folderNumList = strsplit(num2str(1:length(obj.inputFolders)),' ');
		selectList = strcat(folderNumList(:),'/',num2str(length(obj.inputFolders)),' | ',obj.date(:),' _ ',obj.protocol(:),' _ ',obj.fileIDArray(:),' | ',obj.inputFolders(:));
		% [fileIdxArray, ok] = listdlg('ListString',selectList,'ListSize',dlgSize,'Name','Which folders to analyze?','InitialValue',1);
		[fileIdxArray, ok] = obj.pipelineListBox(selectList,['Which folders to analyze?'],1);
		if ok==0; return; end

		obj.foldersToAnalyze = fileIdxArray;
	else
		if isempty(obj.stimulusNameArray)|~isempty(intersect(fxnsToRun,excludeListVer2))|~isempty(intersect(fxnsToRun,excludeListStimuli))
			obj.discreteStimuliToAnalyze = [];
		else
			% [idNumIdxArray, ok] = listdlg('ListString',obj.stimulusNameArray,'ListSize',dlgSize,'Name','which stimuli to analyze?');
			[idNumIdxArray, ok] = obj.pipelineListBox(obj.stimulusNameArray,['Which stimuli to analyze?'],1);
			if ok==0; return; end

			obj.discreteStimuliToAnalyze = idNumIdxArray;
		end
	end

	for thisFxn = fxnsToRun
		try
			disp(repmat('!',1,21))
			close all;
			if ismethod(obj,thisFxn)
				disp(['Running: obj.' thisFxn{1}]);
				obj.(thisFxn{1});
			else
				disp(['Method not supported, skipping: obj.' thisFxn{1}]);
			end
		catch err
			disp(repmat('@',1,7))
			disp(getReport(err,'extended','hyperlinks','on'));
			disp(repmat('@',1,7))
			if strcmp(obj.defaultObjDir,pwd)~=1
				restoredefaultpath;
				cd(obj.defaultObjDir);
				ciapkg.loadBatchFxns();
				% cnmfVersionDirLoad('current','displayOutput',0);
			end
		end
	end
	obj.guiEnabled = 1;
	obj.foldersToAnalyze = [];
	% set back to initial directory in case exited early
	% restoredefaultpath;
	% loadBatchFxns();
	if strcmp(obj.defaultObjDir,pwd)~=1
		cd(obj.defaultObjDir);
	end

	subfxnCheckDirs();

	% Force back to command window.
	commandwindow

	disp([10 10 ...
	'Run processing pipeline by typing below (or clicking link) into command window (no semi-colon!):' 10 ...
	'obj'])
end
function subfxnCheckDirs()
	% Re-run load folders if certain functions are still present in the path
	fxnCheckList = {'CELLMax_Wrapper.m','extractor.m','normcorre.m'};
	if any(cellfun(@(x) ~isempty(which(x)),fxnCheckList))==1
		ciapkg.loadBatchFxns;
	end
end


function files_out = read_folder_structure(root,files_in)

[curr_files,isdir] = my_dir(root);

files_out = files_in;
for i=1:length(curr_files)
    if isdir(i) == 1
        files_out = read_folder_structure([root '\' curr_files{i}],files_out);
    else
        files_out{length(files_out)+1} = [root '\' curr_files{i}];
    end
end


function [filename, pathname] = getFilename(varargin)
% DESCRIPTION:
%       Function to automate collecting a single filename input using the
%       built in uigetfile gui.
%
% USAGE:
%       [filename pathname] = getFilename(start_dir)
%       [filename pathname] = getFilename()
%
% INPUTS:
%       start_dir   - the directory to start in
%
% OUTPUTS:
%       filename / pathname of selected file
%
% ABOUT:
%       author          - Bradley Treeby
%       date            - 5th November 2008
%       last update     - 30th June 2009
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox

% This file is part of k-Wave. k-Wave is free software: you can
% redistribute it and/or modify it under the terms of the GNU Lesser
% General Public License as published by the Free Software Foundation,
% either version 3 of the License, or (at your option) any later version.
%
% k-Wave is distributed in the hope that it will be useful, but WITHOUT ANY
% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
% FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
% more details.
%
% You should have received a copy of the GNU Lesser General Public License
% along with k-Wave. If not, see <http://www.gnu.org/licenses/>.

% get the filename
if nargin == 1
    start_dir = varargin{1};
    [filename, pathname, filterindex] = uigetfile({'*.jpg; *.gif; *.bmp; *.png', 'Image Files (*.jpg, *.gif, *.bmp, *.png)'; '*.*',...
        'All Files (*.*)'}, 'Select data file', 'MultiSelect', 'off', start_dir);
else
    [filename, pathname, filterindex] = uigetfile({'*.jpg; *.gif; *.bmp; *.png', 'Image Files (*.jpg, *.gif, *.bmp, *.png)'; '*.*',...
        'All Files (*.*)'}, 'Select data file', 'MultiSelect', 'off');
end

% check and end with an error if no file has been selected
if filterindex == 0
    error('Please select a data file');
end


function Header = spm_dicom_header(DicomFilename, DicomDictionary, Options)
% Read header information from a DICOM file
% FORMAT Header = spm_dicom_header(DicomFilename, DicomDictionary, Options)
% DicomFilename   - DICOM filename
% DicomDictionary - DICOM dictionary (see spm_dicom_headers)
% Options         - an (optional) structure containing fields
%                   abort      - if this is a function handle, it will
%                                be called with field name and value
%                                arguments.  If this function returns true,
%                                then reading the header will be aborted.
%                                [Default: false]
%                   all_fields - binary true/false, indicating what to do
%                                with fields that are not included in the
%                                DICOM dictionary.
%                                [Default: true]
%
% Header          - Contents of DICOM header
%
% Contents of headers are approximately explained in:
% http://medical.nema.org/standard.html
%
% This code may not work for all cases of DICOM data, as DICOM is an
% extremely complicated "standard".
%__________________________________________________________________________
% Copyright (C) 2002-2018 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_dicom_header.m 7374 2018-07-09 17:09:46Z guillaume $

if nargin < 3
    Options = struct('abort',false, 'all_fields',true);
end

Header = [];
DicomFilename = deblank(DicomFilename);
FID  = fopen(DicomFilename,'r','ieee-le');
if FID == -1
    warning('spm:dicom','%s: Cant open file.', DicomFilename);
    return;
end

fseek(FID,128,'bof');
dcm = char(fread(FID,4,'uint8')');
if ~strcmp(dcm,'DICM')
    % Try truncated DICOM file fomat
    fseek(FID,0,'bof');
    Tag.Group   = fread(FID,1,'ushort');
    Tag.Element = fread(FID,1,'ushort');
    if isempty(Tag.Group) || isempty(Tag.Element)
        fclose(FID);
        warning('spm:dicom','%s: Truncated file.', DicomFilename);
        return;
    end
    if isempty(find(DicomDictionary.group==Tag.Group & DicomDictionary.element==Tag.Element,1)) && ~(Tag.Group==8 && Tag.Element==0)
        % Entry not found in DICOM dictionary and not from a GE Twin+excite
        % that starts with with an 8/0 Tag that I can't find any
        % documentation for.
        fclose(FID);
        warning('spm:dicom','%s: Not a DICOM file.', DicomFilename);
        return;
    else
        fseek(FID,0,'bof');
    end
end

try
    Header = ReadDicom(FID, 'il', DicomDictionary, Options);
    if isempty(Header)
        fclose(FID);
        return;
    end
    Header.Filename = fopen(FID);
catch
    le = lasterror;
    fprintf('%s: Trouble reading DICOM file (%s), skipping.\n', fopen(FID), le.message);
end

fclose(FID);

%==========================================================================
% function [Header, BytesRead] = ReadDicom(FID, TransferSyntax, DicomDictionary, Options, NumBytes)
%==========================================================================
function [Header, BytesRead] = ReadDicom(FID, TransferSyntax, DicomDictionary, Options, NumBytes)
if nargin<5, NumBytes = 4294967295; end % FFFFFFFF
BytesRead = 0;
Header    = [];
while BytesRead < NumBytes
    Tag = ReadTag(FID, TransferSyntax, DicomDictionary, Options);
    if isempty(Tag), break; end

    %fprintf('(%.4X,%.4X) "%s" %d %d %s\n', Tag.Group, Tag.Element, Tag.VR, Tag.Length, Tag.ExtraBytes, Tag.Name);

    if Tag.Group==65534 && Tag.Element==57357 % FFFE,E00D ItemDelimitationItem
        break;
    end
    if Tag.Length>0
        % Handle particular fields as special cases, otherwise just use default treatment
        switch Tag.Name
            case {'GroupLength'}
                % Ignore it
                fseek(FID,Tag.Length,'cof');
            case {'PixelData'}
                Header.StartOfPixelData = ftell(FID);
                Header.SizeOfPixelData  = Tag.Length;
                Header.VROfPixelData    = Tag.VR;
                fseek(FID,Tag.Length,'cof');
            case {'CSAData'} % raw data
                Header.StartOfCSAData = ftell(FID);
                Header.SizeOfCSAData  = Tag.Length;
                fseek(FID,Tag.Length,'cof');
            case {'CSAImageHeaderInfo', 'CSASeriesHeaderInfo','CSANonImageHeaderInfoVA',...
                  'CSAMiscProtocolHeaderInfoVA','CSANonImageHeaderInfoVB','CSAMiscProtocolHeaderInfoVB'}
                Content  = DecodeCSA(FID,Tag.Length);
                Header.(Tag.Name) = Content;
            case {'TransferSyntaxUID'}
                Content = deblank(char(fread(FID,Tag.Length,'uint8')'));
                Header.(Tag.Name) = Content;
                switch Content
                    case {'1.2.840.10008.1.2'}      % Implicit VR Little Endian
                        TransferSyntax = 'il';
                    case {'1.2.840.10008.1.2.1'}    % Explicit VR Little Endian
                        TransferSyntax = 'el';
                    case {'1.2.840.10008.1.2.1.99'} % Deflated Explicit VR Little Endian
                        warning('spm:dicom','%s: Cant read Deflated Explicit VR Little Endian file.', fopen(FID));
                       %TransferSyntax = 'dl';
                        return;
                    case {'1.2.840.10008.1.2.2'}    % Explicit VR Big Endian
                        %warning('spm:dicom','%s: Cant read Explicit VR Big Endian file',fopen(FID));
                        TransferSyntax = 'eb'; % Unused
                    case {'1.2.840.10008.1.2.4.50','1.2.840.10008.1.2.4.51','1.2.840.10008.1.2.4.70',...
                          '1.2.840.10008.1.2.4.80','1.2.840.10008.1.2.4.90','1.2.840.10008.1.2.4.91'} % JPEG Explicit VR
                        TransferSyntax = 'el';
                        %warning('spm:dicom',['Cant read JPEG Encoded file "' fopen(FID) '".']);
                    otherwise
                       %TransferSyntax = 'el';
                        warning('spm:dicom','%s: Unknown Transfer Syntax UID (%s).',fopen(FID), Content);
                        return;
                end
            otherwise
                % Default treatment
                switch Tag.VR
                    case {'UN'}
                        % Unknown - read as char
                        Content = fread(FID,Tag.Length,'uint8')';
                    case {'AE', 'AS', 'CS', 'DA', 'DS', 'DT', 'IS', 'LO', 'LT',...
                            'PN', 'SH', 'ST', 'TM', 'UI', 'UT'}
                        % Character strings
                        Content = char(fread(FID,Tag.Length,'uint8')');

                        switch Tag.VR
                            case {'UI','ST'}
                                Content = deblank(Content);
                            case {'DS'}
                                try
                                    Content = textscan(Content,'%f','delimiter','\\')';
                                    Content = Content{1};
                                catch
                                    Content = textscan(Content,'%f','delimiter','/')';
                                    Content = Content{1};
                                end
                            case {'IS'}
                                Content = textscan(Content,'%d','delimiter','\\')';
                                Content = double(Content{1});
                            case {'DA'}
                                Content = strrep(Content,'.',' ');
                                Content = textscan(Content,'%4d%2d%2d');
                                [y,m,d] = deal(Content{:});
                                Content = datenum(double(y),double(m),double(d));
                            case {'TM'}
                                if any(Content==':')
                                    Content = textscan(Content,'%d:%d:%f');
                                    [h,m,s] = deal(Content{:});
                                    h       = double(h);
                                    m       = double(m);
                                else
                                    Content = textscan(Content,'%2d%2d%f');
                                    [h,m,s] = deal(Content{:});
                                    h       = double(h);
                                    m       = double(m);
                                end
                                if isempty(h), h = 0; end
                                if isempty(m), m = 0; end
                                if isempty(s), s = 0; end
                                Content = s+60*(m+60*h);
                            case {'LO'}
                                Content = strrep(Content,'+AF8-','_');
                            otherwise
                        end
                    case {'OB'}
                        % dont know if this should be signed or unsigned
                        Content = fread(FID,Tag.Length,'uint8')';
                    case {'US', 'AT', 'OW'}
                        Content = fread(FID,Tag.Length/2,'uint16')';
                    case {'SS'}
                        Content = fread(FID,Tag.Length/2,'int16')';
                    case {'UL'}
                        Content = fread(FID,Tag.Length/4,'uint32')';
                    case {'SL'}
                        Content = fread(FID,Tag.Length/4,'int32')';
                    case {'FL','OF'}
                        Content = fread(FID,Tag.Length/4,'float')';
                    case {'FD','OD'}
                        Content = fread(FID,Tag.Length/8,'double')';
                    case {'SQ'}
                        [Content, BytesJustRead] = ReadSQ(FID, TransferSyntax, DicomDictionary, Options, Tag.Length);
                        if BytesJustRead==-1 && isempty(Content)
                            Header    = [];
                            BytesRead = -1;
                            return;
                        end
                        Tag.Length = BytesJustRead;
                    otherwise
                        Content = fread(FID,Tag.Length,'uint8')';
                end
                if ~isempty(Tag.Name)
                    if isa(Options.abort, 'function_handle') && feval(Options.abort, Tag.Name, Content)
                        Header    = [];
                        BytesRead = -1;
                        return;
                    end
                    Header.(Tag.Name) = Content;
                end
        end
    end
    BytesRead = BytesRead + Tag.ExtraBytes + Tag.Length;
end

%==========================================================================
% function [Header, BytesRead] = ReadSQ(FID, TransferSyntax, DicomDictionary, Options, NumBytes)
%==========================================================================
function [Header, BytesRead] = ReadSQ(FID, TransferSyntax, DicomDictionary, Options, NumBytes)
Header = {};
n      = 0;
BytesRead = 0;
while BytesRead<NumBytes
    Tag.Group   = fread(FID,1,'ushort');
    Tag.Element = fread(FID,1,'ushort');
    Tag.Length  = fread(FID,1,'uint');
    if isempty(Tag.Length), return; end % End of file
    BytesRead   = BytesRead + 8;
    if (Tag.Group == 65534) && (Tag.Element == 57344)   % FFFE/E000 Item
        [Item, BytesJustRead] = ReadDicom(FID, TransferSyntax, DicomDictionary, Options, Tag.Length);
        if BytesJustRead==-1 && isempty(Item)
            Header    = [];
            BytesRead = -1;
            return;
        end

        BytesRead    = BytesRead + BytesJustRead;
        if ~isempty(Item)
            n         = n + 1;
            Header{n} = Item;
        end
    elseif (Tag.Group == 65279) && (Tag.Element == 224) % FEFF/00E0 Item (Byte-swapped)
        % Byte-swapped
        [Filename,Permission,MachineFormat]      = fopen(FID);
        TransferSyntaxSwapped = TransferSyntax;
        if TransferSyntax(2)=='b'
            TransferSyntaxSwapped(2) = 'l';
        else
            TransferSyntaxSwapped(2) = 'b';
        end
        [Item, BytesJustRead] = ReadDicom(FID, TransferSyntaxSwapped, DicomDictionary, Options, Tag.Length);
        if BytesJustRead==-1 && isempty(Item)
            BytesRead = -1;
            return;
        end

        BytesRead = BytesRead + BytesJustRead;
        n         = n + 1;
        Header{n} = Item;
        Position  = ftell(FID);
        fclose(FID);
        FID     = fopen(Filename, Permission, MachineFormat);
        fseek(FID, Position, 'bof');
    elseif (Tag.Group == 65534) && (Tag.Element == 57565) % FFFE/E0DD SequenceDelimitationItem
        break;
    elseif (Tag.Group == 65279) && (Tag.Element == 56800) % FEFF/DDE0 SequenceDelimitationItem (Byte-swapped)
        % Byte-swapped
        break;
    else
        warning('spm:dicom','%s: Tag (%.4X,%.4X) is unexpected in sequence.', fopen(FID), Tag.Group, Tag.Element);
    end
end

%==========================================================================
% function Tag = ReadTag(FID,TransferSyntax,DicomDictionary, Options)
%==========================================================================
function Tag = ReadTag(FID, TransferSyntax, DicomDictionary, Options)
[GroupElement, Bytesread] = fread(FID,2,'ushort');
if Bytesread < 2, Tag = []; return; end
Tag.Group   = GroupElement(1);
Tag.Element = GroupElement(2);
if Tag.Group == 2, TransferSyntax = 'el'; end
t           = find(DicomDictionary.group==Tag.Group & DicomDictionary.element==Tag.Element);
if ~isempty(t)
    Tag.Name = DicomDictionary.values(t).name;
    Tag.VR   = DicomDictionary.values(t).vr{1};
else
    if ~Options.all_fields
        % With a reduced DicomDictionary, this can speed things up considerably.
        Tag.Name = '';
    else
        if Tag.Element~=0
            % Odd Group numbers indicate private (manufacturer-specific) fields
            if rem(Tag.Group,2)
                % Shadow Group
                Tag.Name = sprintf('Private_%.4x_%.4x',Tag.Group,Tag.Element);
            else
                Tag.Name = sprintf('Tag_%.4x_%.4x',Tag.Group,Tag.Element);
            end
            Tag.VR   = 'UN';
        else
            Tag.Name = '';
            Tag.VR   = 'UN';
        end
    end
end

if TransferSyntax(2) == 'b'
    [Filename,Permission,MachineFormat] = fopen(FID);
    if strcmp(MachineFormat,'ieee-le') || strcmp(MachineFormat,'ieee-le.l64')
        Position = ftell(FID);
        fclose(FID);
        FID      = fopen(Filename,Permission,'ieee-be');
        fseek(FID,Position,'bof');
    end
end

Tag.ExtraBytes = 4; % Two shorts read so far

if TransferSyntax(1) =='e'
    Tag.VR         = char(fread(FID,2,'uint8')');
    Tag.ExtraBytes = Tag.ExtraBytes + 2;
    switch Tag.VR
        case {'OB','OW','OF','OD','SQ','UN','UT'}
            if ~strcmp(Tag.VR,'UN') || Tag.Group~=65534
                fread(FID,1,'ushort');
                Tag.ExtraBytes = Tag.ExtraBytes + 2;
            else
                warning('spm:dicom','%s: Possible problem with %s Tag (VR="%s").', fopen(FID), Tag.Name, Tag.VR);
            end
            Tag.Length     = double(fread(FID,1,'uint'));
            Tag.ExtraBytes = Tag.ExtraBytes + 4;

        case {'AE','AS','AT','CS','DA','DS','DT','FD','FL','IS','LO','LT','PN','SH','SL','SS','ST','TM','UI','UL','US'}
            Tag.Length     = double(fread(FID,1,'ushort'));
            Tag.ExtraBytes = Tag.ExtraBytes + 2;

        case char([0 0])
            if (Tag.Group == 65534) && (Tag.Element == 57357)    % ItemDeliminationItem
                % at least on GE, ItemDeliminationItem does not have a
                % VR, but 4 bytes zeroes as Length
                Tag.VR         = 'UN';
                fread(FID,1,'ushort'); % Should be zero
                Tag.Length     = 0;
                Tag.ExtraBytes = Tag.ExtraBytes + 2;

            elseif (Tag.Group == 65534) && (Tag.Element == 57565) % SequenceDelimitationItem
                Tag.VR         = 'UN';
                Tag.Length     = 0;
                fread(FID,1,'ushort'); % Should be zero
                Tag.ExtraBytes = Tag.ExtraBytes + 2;

            else
                warning('spm:dicom','%s: Don''t know how to handle VR of "\0\0" in %s.',fopen(FID),Tag.Name);
            end
        otherwise
            warning('spm:dicom','%s: Possible problem with %s Tag (VR="%s")\n', fopen(FID), Tag.Name, Tag.VR);
            fread(FID,1,'ushort');
            Tag.Length     = double(fread(FID,1,'uint'));
            Tag.ExtraBytes = Tag.ExtraBytes + 2+4;
    end
else
    Tag.Length     = double(fread(FID,1,'uint'));
    Tag.ExtraBytes = Tag.ExtraBytes + 4;
end

if isempty(Tag.VR) || isempty(Tag.Length)
    Tag = [];
    return;
end

if rem(Tag.Length,2)
    if Tag.Length==4294967295 % FFFFFFFF
        if strcmp(Tag.VR,'UN')
            warning('spm:dicom','%s: Unknown Value Representation of %s Tag, assuming ''SQ''.', fopen(FID), Tag.Name);
            Tag.VR = 'SQ';
        end
        return;
    else
        warning('spm:dicom','%s: Odd numbered Value Length in %s Tag (%X).', fopen(FID), Tag.Name, Tag.Length);
        Tag = [];
    end
end

%==========================================================================
% function t = DecodeCSA(FID,NumBytes)
%==========================================================================
function t = DecodeCSA(FID,NumBytes)
% Decode shadow information (0029,1010) and (0029,1020) from Siemens files
[Filename,Permission,MachineFormat] = fopen(FID);
Position = ftell(FID);
if strcmp(MachineFormat,'ieee-be') || strcmp(MachineFormat,'ieee-be.l64')
    fclose(FID);
    FID  = fopen(Filename,Permission,'ieee-le');
    fseek(FID,Position,'bof');
end

c   = fread(FID,4,'uint8');
fseek(FID,Position,'bof');

if all(c'==[83 86 49 48]) % "SV10"
    t = DecodeCSA2(FID,NumBytes);
else
    t = DecodeCSA1(FID,NumBytes);
end

if strcmp(MachineFormat,'ieee-be') || strcmp(MachineFormat,'ieee-be.l64')
    fclose(FID);
    FID  = fopen(Filename, Permission, MachineFormat);
end
fseek(FID, Position+NumBytes, 'bof');

%==========================================================================
% function t = DecodeCSA1(FID,NumBytes)
%==========================================================================
function t = DecodeCSA1(FID,NumBytes)
n   = fread(FID,1,'uint32');
if isempty(n) || n>1024 || n <= 0
    fseek(FID,NumBytes-4,'cof');
    t = struct('name','JUNK: Don''t know how to read this damned file format');
    return;
end
fread(FID,1,'uint32'); % Unused "M" or 77 for some reason
BytesRead = 2*4;
t(n)      = struct('name','', 'vm',[], 'vr','', 'syngodt',[], 'nitems',[], 'xx',[], 'item',struct('xx',{},'val',{}));
for i=1:n
    t(i).name = fread(FID,64,'uint8')';
    msk       = find(~t(i).name)-1;
    if ~isempty(msk)
        t(i).name = char(t(i).name(1:msk(1)));
    else
        t(i).name = char(t(i).name);
    end
    t(i).vm      = fread(FID,1,'int32')';
    t(i).vr      = fread(FID,4,'uint8')';
    t(i).vr      = char(t(i).vr(1:3));
    t(i).syngodt = fread(FID,1,'int32')';
    t(i).nitems  = fread(FID,1,'int32')';
    t(i).xx      = fread(FID,1,'int32')'; % 77 or 205
    BytesRead    = BytesRead + 64+4+4+4+4+4;
    if t(i).nitems > 0
        t(i).item(t(i).nitems) = struct('xx',[], 'val',[]);
    end
    for j=1:t(i).nitems
        % This bit is just wierd
        t(i).item(j).xx  = fread(FID,4,'int32')'; % [x x 77 x]
        BytesToRead      = t(i).item(j).xx(1)-t(1).nitems;
        if BytesToRead<0 || BytesToRead+Bytesread+4*4>NumBytes
            t(i).item(j).val = '';
            t(i).item        = t(i).item(1:j);
            BytesRead        = BytesRead + 4*4;
            break;
        end
        t(i).item(j).val = char(fread(FID,BytesToRead,'uint8')');
        fread(FID,4-rem(BytesToRead,4),'uint8');
        BytesRead        = BytesRead + 4*4+BytesToRead+(4-rem(BytesToRead,4));
    end
end

%==========================================================================
% function t = DecodeCSA2(FID, NumBytes)
%==========================================================================
function t = DecodeCSA2(FID, NumBytes)
fread(FID, 8, 'uint8'); % Unused
n        = fread(FID, 1, 'uint32');
if isempty(n) || n>1024 || n < 0
    fseek(FID, NumBytes-4, 'cof');
    t = struct('name','Don''t know how to read this damned file format');
    return;
end
fread(FID, 1, 'uint32'); % Unused "M" or 77 for some reason
Position = 16;
t(n)     = struct('name','', 'vm',[], 'vr','', 'syngodt',[], 'nitems',[], 'xx',[], 'item',struct('xx',{},'val',{}));
for i=1:n
    t(i).name = fread(FID, 64, 'uint8')';
    Position  = Position + 64;
    msk       = find(~t(i).name)-1;
    if ~isempty(msk)
        t(i).name = char(t(i).name(1:msk(1)));
    else
        t(i).name = char(t(i).name);
    end
    t(i).vm      = fread(FID, 1, 'int32')';
    t(i).vr      = fread(FID, 4, 'uint8')';
    t(i).vr      = char(t(i).vr(1:3));
    t(i).syngodt = fread(FID, 1, 'int32')';
    t(i).nitems  = fread(FID, 1, 'int32')';
    t(i).xx      = fread(FID, 1, 'int32')'; % 77 or 205
    Position     = Position + 20;
    if t(i).nitems > 0
        t(i).item(t(i).nitems) = struct('xx',[], 'val',[]);
    end
    for j=1:t(i).nitems
        t(i).item(j).xx  = fread(FID,4,'int32')'; % [x x 77 x]
        Position         = Position + 16;
        BytesToRead      = t(i).item(j).xx(2);
        if BytesToRead > NumBytes-Position
            BytesToRead      = NumBytes-Position;
            t(i).item(j).val = char(fread(FID, BytesToRead, 'uint8')');
            fread(FID,rem(4-rem(BytesToRead, 4), 4), 'uint8');
            t(i).item        = t(i).item(1:j);
            warning('spm:dicom','%s: Problem reading Siemens CSA field.', fopen(FID));
            return;
        end
        t(i).item(j).val = char(fread(FID, BytesToRead, 'uint8')');
        fread(FID,rem(4-rem(BytesToRead, 4), 4), 'uint8');
    end
end


function x = subsref( x, S, cheat )
error( 'Subscripts not allowed for this object.' );

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


% Defines a note
%
% Author: Jonathan Karr
% Affilitation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 5/7/2009
classdef Note < edu.stanford.covert.cell.kb.KnowledgeBaseObject
    properties
    end

    methods
        function this = Note(knowledgeBase, wid, wholeCellModelID, name, ...
                comments, crossReferences)

            if nargin == 0; return; end;

            this = edu.stanford.covert.cell.kb.Note.empty(size(wid,1),0);
            this(size(wid,1),1) = edu.stanford.covert.cell.kb.Note;
            for i = 1:size(wid,1)
                this(i,1).idx = i;
                this(i,1).knowledgeBase = knowledgeBase;
                this(i,1).wid = wid(i);
                this(i,1).wholeCellModelID = wholeCellModelID{i};
                if ~isempty(name); this(i,1).name = name{i}; end;
                if exist('comments','var') && ~isempty(comments); this(i,1).comments = comments{i}; end;
                if exist('crossReferences','var')
                    if size(crossReferences,1)>1
                        this(i,1).crossReferences = crossReferences(i);
                    else
                        this(i,1).crossReferences = struct;
                        fields = fieldnames(crossReferences);
                        for j = 1:size(fields,1)
                            values = crossReferences.(fields{j});
                            this(i,1).crossReferences.(fields{j}) = values(i);
                        end
                    end
                end
            end
        end
    end
end


% OtStop Stop using the Omnitrans interface.
%
% Usage:
%    OtStop
%
% Releases the Omnitrans resources allocated with a call to OtStart().

% OtMatlab: Matlab interface to the Omnitrans transport planning software

% Copyright (c) 2008, VORtech Computing
% Copyright (c) 2010, Omnitrans International

% All rights reserved.

% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:

%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * Redistributions in binary form must reproduce the above copyright
%       notice, this list of conditions and the following disclaimer in
%       the documentation and/or other materials provided with the distribution
%     * Neither the name of VORtech Computing and Omnitrans International nor the names
%       of its contributors may be used to endorse or promote products derived
%       from this software without specific prior written permission.

% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.

% 2006-02-28 Created (Johan Meijdam, VORtech)

function OtStop()
   Ot('stop');
end


%% mff_valid.m
%  Matlab File
%  author Colin Davey
%  date 12/3/2013
%  Copyright 2013 EGI. All rights reserved.
%  Support routine for MFF Matlab code. Not intended to be called directly.
%
%  Tests whether a file is valid, and throws an exception if not. Gives an
%  informational warning if filename doesn't end in '.mff'.
%%
function mff_valid(filePath)
valid = false;
filePathExist = exist(filePath);
% Check that filePath exists.
if filePathExist == 0
    theException = MException('EGI_MFF:MFF_NO_EXIST', 'MFF does not exist.');
% Check that filePath isn't a regular file.
elseif filePathExist == 2
    theException = MException('EGI_MFF:MFF_NOT_DIR', 'MFF is not a folder or package.');
% Check that filePath is a directory.
elseif filePathExist ~= 7
    theException = MException('EGI_MFF:MFF_NOT_DIR_OR_FILE', 'MFF is not a folder, package or file.');
else
    % Check that filePath/info.xml exists and is a file.
    if exist([filePath filesep 'info.xml']) ~= 2
        theException = MException('EGI_MFF:INVALID_NO_INFO', 'MFF is not valid. There is no info.xml file.');
    % Check that filePath/info1.xml exists and is a file.
    elseif exist([filePath filesep 'info1.xml']) ~= 2
        theException = MException('EGI_MFF:INVALID_NO_INFO1', 'MFF is not valid. There is no info1.xml file.');
    % Check that filePath/signal1.bin exists and is a file.
    elseif exist([filePath filesep 'signal1.bin']) ~= 2
        theException = MException('EGI_MFF:INVALID_NO_SIGNAL1', 'MFF is not valid. There is no signal1.bin file.');
    % Check the version.
    else
        infoObj = mff_getObject(com.egi.services.mff.api.MFFResourceType.kMFF_RT_Info, 'info.xml', filePath);
        ver = infoObj.getMFFVersion;
        if ver ~= 3;
            theException = MException('EGI_MFF:WRONG_VER', 'MFF is not version 3. Please convert using EGI''s MFF File Converter. Contact supportteam@egi.com form more information.');
        else
            valid = true;
        end
    end
end
if ~valid
    throw(theException);
end
% Delete DS_Store file that gets generated when moving to a PC.
fullDS_StorePath = [filePath filesep '._.DSStore'];
if exist(fullDS_StorePath, 'file') == 2
    delete(fullDS_StorePath);
end

% Give a warning if name doesn't end in '.mff'.
mff_warning = '*** Filename does not end in ''.mff''. This can cause a problem for some versions of NetStation. ***';
if size(filePath,2) < size('.mff',2) + 1
%     warning('EGI_MFF:EXT_WARNING', mff_warning);
    fprintf('%s\n', mff_warning);
elseif ~(strcmp(lower(filePath(end-3:end)), '.mff'))
%     warning('EGI_MFF:EXT_WARNING', mff_warning);
    fprintf('%s\n', mff_warning);
end


function tagS = gsps_module_tags
%"gsps_module_tags"
%   Return the tags used to represent a ROI contour specified by
%   A.33 in PS3.3 of 2006 DICOM specification. Tags are returned in a
%   struct array with 3 fields:
%
%   Tag: String containing hex DICOM tag of a field.
%  Type: String describing type of field, with 5 options:
%         '1' Field must exist, data must exist and be valid.
%         '2' Field must exist, data can exist and be valid, or be NULL.
%         '3' Field is optional, if the field exists data can exist and be
%             valid or be NULL.
%         '1C' Field must exist under certain conditions and contain valid
%             data.
%         '2C' Field must exist under certain conditions and can contain
%             valid data or be NULL.
%Children: For sequences, a tagS with the same format as this struct array
%          containing the tags of child fields.
%
%APA 07/12/2019
%
%Usage:
%   tagS = ROI_contour_module_tags
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR 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.
%
% CERR 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 CERR.  If not, see <http://www.gnu.org/licenses/>.

%Initialize the tagS structure.
tagS = struct('tag', {}, 'tagdec', {}, 'type', {}, 'children', {});

%Create an empty tagS template for sequence creation.
template = tagS;

%Add tags based on PS3.3 attribute lists

% Presentation Creation Date
tagS(end+1) = struct('tag', '00700082', 'tagdec', 7340162, 'type', '1', 'children', []);

% Presentation Creation Time
tagS(end+1) = struct('tag', '00700083', 'tagdec', 7340163, 'type', '1', 'children', []);

% Presentation LUT Shape
tagS(end+1) = struct('tag', '20500020', 'tagdec', 542113824, 'type', '1C', 'children', []);

% Displayed Area Selection Sequence
tagS(end+1) = struct('tag', '0070005A', 'tagdec', 7340122, 'type', '1', 'children', []);

    child_0 = template;
    %Referenced Image Sequence
    child_0(end+1) = struct('tag', '00081140', 'tagdec', 528704, 'type', '1C', 'children', image_SOP_instance_reference_macro_tags);
    % Displayed Area Top Left Hand Corner
    child_0(end+1) = struct('tag', '00700052', 'tagdec', 7340114, 'type', '1', 'children', []);
    % Displayed Area Bottom Right Hand Corner
    child_0(end+1) = struct('tag', '00700053', 'tagdec', 7340115, 'type', '1', 'children', []);
    % Presentation Size Mode
    child_0(end+1) = struct('tag', '00700100', 'tagdec', 7340288, 'type', '1', 'children', []);
    % Presentation Pixel Spacing
    child_0(end+1) = struct('tag', '00700101', 'tagdec', 7340289, 'type', '1C', 'children', []);
    % Presentation Pixel Aspect Ratio
    child_0(end+1) = struct('tag', '00700102', 'tagdec', 7340290, 'type', '1C', 'children', []);
    % Presentation Pixel Magnification Ratio
    child_0(end+1) = struct('tag', '00700103', 'tagdec', 7340291, 'type', '1C', 'children', []);

tagS(end).children = child_0;

% Referenced Series Sequence
tagS(end+1) = struct('tag', '00081115', 'tagdec', 528661, 'type', '1', 'children', []);
    child_0 = template;
    % Series Instance UID
    child_0(end+1) = struct('tag', '0020000E', 'tagdec', 2097166, 'type', '1', 'children', []);
    % Referenced Image Sequence
    child_0(end+1) = struct('tag', '00081140', 'tagdec', 528704, 'type', '1', 'children', image_SOP_instance_reference_macro_tags);

tagS(end).children = child_0;

% Referenced Study Sequence

%Graphic Annotation Sequence
tagS(end+1) = struct('tag', '00700001', 'tagdec', 7340033, 'type', '1', 'children', []);

child_0 = template;

%Referenced Image Sequence
child_0(end+1) = struct('tag', '00081140', 'tagdec', 528704, 'type', '1C', 'children', image_SOP_instance_reference_macro_tags);

%Graphic layer
child_0(end+1) = struct('tag', '00700002', 'tagdec', 7340034, 'type', '1', 'children', []);

%Text object sequence
child_0(end+1) = struct('tag', '00700008', 'tagdec', 7340040, 'type', '1C', 'children', []);

        child_1 = template;

        %Bounding Box Annotation Units
        %child_1(end+1) = struct('tag', '00700003', 'tagdec',  , 'type', '1C', 'children', []);

        %Anchor Point Annotation Units
        child_1(end+1) = struct('tag', '00700004', 'tagdec', 7340036, 'type', '1C', 'children', []);

        %Unformatted Text Value
        child_1(end+1) = struct('tag', '00700006', 'tagdec', 7340038 , 'type', '1', 'children', []);

        %Bounding Box Top Left Hand Corner
        %child_1(end+1) = struct('tag', '00700010', 'tagdec', 7340048, 'type', '1C', 'children', []);

        %Bounding Box Bottom Right Hand Corner
        %child_1(end+1) = struct('tag', '00700011', 'tagdec', 7340049, 'type', '1C', 'children', []);

        %Bounding Box Text Horizontal Justification
        %child_1(end+1) = struct('tag', '00700012', 'tagdec', 7340050, 'type', '1C', 'children', []);

        %Anchor Point
        child_1(end+1) = struct('tag', '00700014', 'tagdec', 7340052, 'type', '1C', 'children', []);

        %Anchor Point Visibility
        child_1(end+1) = struct('tag', '00700015', 'tagdec', 7340053, 'type', '1C', 'children', []);

child_0(end).children = child_1;

%Graphic object sequence
child_0(end+1) = struct('tag', '00700009', 'tagdec', 7340041, 'type', '1', 'children', []);

        child_2 = template;

        %Graphic Annotation Units
        child_2(end+1) = struct('tag', '00700005', 'tagdec', 7340037, 'type', '1', 'children', []);

        %Graphic Dimensions
        child_2(end+1) = struct('tag', '00700020', 'tagdec', 7340064, 'type', '1', 'children', []);

        %Number of Graphic Points
        child_2(end+1) = struct('tag', '00700021', 'tagdec', 7340065, 'type', '1', 'children', []);

        %Graphic Data
        child_2(end+1) = struct('tag', '00700022', 'tagdec', 7340066, 'type', '1', 'children', []);

        %Graphic Type
        child_2(end+1) = struct('tag', '00700023', 'tagdec', 7340067, 'type', '1', 'children', []);

        %Graphic Filled
        child_2(end+1) = struct('tag', '00700024', 'tagdec', 7340068, 'type', '1C', 'children', []);

child_0(end).children = child_2;

tagS(end).children = child_0;

%Graphic Layer Sequence
tagS(end+1) = struct('tag', '00700060', 'tagdec', 7340128, 'type', '1', 'children', []);
        child_1 = template;

        %0070,0002  Graphic Layer
        child_1(end+1) = struct('tag', '00700002', 'tagdec', 7340034, 'type', '1', 'children', []);

        %0070,0062  Graphic Layer Order
        child_1(end+1) = struct('tag', '00700062', 'tagdec', 7340130, 'type', '1', 'children', []);

        %0070,0066  Graphic Layer Recommended Display Grayscale Value
        child_1(end+1) = struct('tag', '00700066', 'tagdec', 7340134, 'type', '3', 'children', []);

        %0070,0401  Graphic Layer Recommended Display CIELab Value
        child_1(end+1) = struct('tag', '00700401', 'tagdec', 7341057, 'type', '3', 'children', []);

        %0070,0068  Graphic Layer Description
        child_1(end+1) = struct('tag', '00700068', 'tagdec', 7340136, 'type', '3', 'children', []);

tagS(end).children = child_1;


%% Texture Evolution
%
%%


function x = subsasgn( x, S, y )
error( 'Subscripted assignment not allowed for these objects.' );

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


% SERVER Write a message over the specified port
%
% Usage - server(message, output_port, number_of_retries)
function server(message, output_port, number_of_retries)

    import java.net.ServerSocket
    import java.io.*

    if (nargin < 3)
        number_of_retries = 20; % set to -1 for infinite
    end
    retry             = 0;

    server_socket  = [];
    output_socket  = [];

    while true

        retry = retry + 1;

        try
            if ((number_of_retries > 0) && (retry > number_of_retries))
                fprintf(1, 'Too many retries\n');
                break;
            end

            fprintf(1, ['Try %d waiting for client to connect to this ' ...
                        'host on port : %d\n'], retry, output_port);

            % wait for 1 second for client to connect server socket
            server_socket = ServerSocket(output_port);
            server_socket.setSoTimeout(1000);

            output_socket = server_socket.accept;

            fprintf(1, 'Client connected\n');

            output_stream   = output_socket.getOutputStream;
            d_output_stream = DataOutputStream(output_stream);

            % output the data over the DataOutputStream
            % Convert to stream of bytes
            fprintf(1, 'Writing %d bytes\n', length(message))
            d_output_stream.writeBytes(char(message));
            d_output_stream.flush;

            % clean up
            server_socket.close;
            output_socket.close;
            break;

        catch
            if ~isempty(server_socket)
                server_socket.close
            end

            if ~isempty(output_socket)
                output_socket.close
            end

            % pause before retrying
            pause(1);
        end
    end
end


% SHELLGUI
%
% Files
%   shellgui - GUI interface for seashell function
%   seashell - draws a pretty Florida seashell, using a 3D parametric surface.
%

% Example
%   shellgui


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

%%
clear; close all; clc;

%% Syntax
% |S=nowStr(f);|

%% 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/>.


%kMenuButton 'MenuButton Object Menuform'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros MenuButton.pane file
%
% Parameters:
% String: label 'Label ', default: ' ': 'label for menubutton'
%
% Example: kMenuButton( {'label',' '})
%
% Khoros helpfile follows below:
%
% .begin tagged
%
% .item "The Menubutton GUI Object"
% The Khoros menubutton object is used on Khoros graphical user interfaces
% whenever a pulldown menu is needed;  clicking on the menubutton will display
% the pulldown menu.
%
% .item "Label"
% The (optional) text that is displayed by the menubutton object.  A menubutton
% object will a pixmap to the right of the label.  This pixmap indicates that it
% is a menubutton, and whether clicking on it will display a pulldown menu
% (indicated by an arrow that points down) or a walking menu (indicated by
% an arrow that points to the right).
%
% .item "Font"
% The font in which the label for the menubutton will appear.
%
% .item "Foreground Color"
% The color in which the text for the label will appear.
%
% .item "Background Color"
% The color in which the background of the menubutton will appear.
% .end tagged

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

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


classdef Preferences < wt.model.BaseModel
    % Base class for managing app preferences
    %
    % Notes:
    %   The preferences may be set to automatically load upon creating an
    %   instance, and save upon destruction of an instance of this class.

    % Copyright 2020-2021 The MathWorks Inc.

    %% Preference Properties
    properties (AbortSet)

        % Starting window position
        Position (1,4) double = [100 100 1000 700]

        % Last folder that was used when opening a file
        LastFolder (1,1) string {mustBeFolder} = pwd

        % List of recent session files
        RecentSessionPaths (:,1) string {mustBeFile}

    end %properties

    %% Saving and Loading Preferences
    methods (Sealed)

        function load(obj,prefGroup)
            % Load stored preferences

            % Get a list of preference properties
            propList = getPreferenceProperties(obj);

            % Get the preference values
            if ispref(prefGroup)
                prefValues = getpref(prefGroup);
            else
                prefValues = struct();
            end

            % Loop on each preference field
            for idx = 1:numel(propList)

                % Get the current preference
                thisProp = propList(idx).Name;
                thisDefault = propList(idx).DefaultValue;
                if isfield(prefValues,thisProp)
                    thisValue = prefValues.(thisProp);
                else
                    thisValue = thisDefault;
                end

                % Get the preference
                try
                    obj.(thisProp) = thisValue;
                catch err
                    warning('wt:Preferences:LoadFailure',...
                        ['Unable to load stored preference for %s:%s. '...
                        'Reverting to default value.\n%s'],...
                        prefGroup,thisProp,err.message);
                    obj.(thisProp) = thisDefault;
                end

            end %for idx = 1:numel(propList)

        end %function

        function save(obj,prefGroup)
            % Save preferences

            % Get a list of preference properties
            propList = getPreferenceProperties(obj);

            % Remove existing preferences first (in case the props changed)
            if ispref(prefGroup)
                rmpref(prefGroup);
            end

            % Loop on each preference field
            if ~isempty(prefGroup)
                for idx = 1:numel(propList)

                    % Get the current preference
                    thisProp = propList(idx).Name;
                    thisValue = obj.(thisProp);

                    % Set the preference
                    setpref(prefGroup,thisProp,thisValue);

                end %for idx = 1:numel(propList)
            end %if ~isempty(prefGroup)

        end %function

    end %methods

    %% Private methods
    methods (Access=private)

        function propList = getPreferenceProperties(obj)
            % Get the info for preference properties

            %mc = metaclass(obj);
            %propList = mc.PropertyList;
            propNames = properties(obj);
            for idx = numel(propNames):-1:1
                propList(idx) = findprop(obj,propNames{idx});
            end
            propsToKeep = ~[propList.Constant] & ...
                ~[propList.Transient] & ...
                ~[propList.Hidden] & ...
                [propList.HasDefault] & ...
                strcmp({propList.GetAccess},'public') & ...
                strcmp({propList.SetAccess},'public');
            propList(~propsToKeep) = [];

        end %function

    end %methods

end % classdef


%% UNIX_HEAD_TEST tests the UNIX facility for issuing operating system commands.
%
%  Discussion:
%
%    HEAD is a legal command on UNIX systems, which returns the first
%    lines of a file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 July 2006
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'UNIX_HEAD_TEST\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Demonstrate a simple use of the "unix" command,\n' );
  fprintf ( 1, '  which allows MATLAB to invoke UNIX operating system commands.\n' );

  [ status, string ] = unix ( 'head unix_head_test.m' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Command status was %d\n', status );
  fprintf ( 1, '  Command output was %s\n', string );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Repeat the command, but add the -5 option.\n' );

  [ status, string ] = unix ( 'head -5 unix_head_test.m' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Command status was %d\n', status );
  fprintf ( 1, '  Command output was %s\n', string );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'UNIX_HEAD_TEST:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );


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

% Last Modified by GUIDE v2.5 17-Dec-2018 16:42:03

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

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

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

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

	populateGUI(handles, action, lvdData);

    % Update handles structure
    guidata(hObject, handles);

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

function populateGUI(handles, action, lvdData)
    [tanksListStr, tanks] = lvdData.launchVehicle.getTanksListBoxStr();

    if(isempty(action.tank))
        indVal = 1;
    else
        indVal = find(tanks == action.tank, 1);
        if(isempty(indVal))
            indVal = 1;
        end
    end

    handles.tankCombo.String = tanksListStr;
    handles.tankCombo.Value = indVal;

    handles.massToAddText.String = fullAccNum2Str(action.massToAdd);

    optVar = action.optVar;
	if(isempty(optVar))
        optVar = AddMassToTankActionOptimVar(action);
	end

    handles.optCheckbox.Value = double(optVar.getUseTfForVariable());

    [lb, ub] = optVar.getAllBndsForVariable();
    handles.lbText.String = fullAccNum2Str(lb);
    handles.ubText.String = fullAccNum2Str(ub);

    optCheckbox_Callback(handles.optCheckbox, [], handles);

% --- Outputs from this function are returned to the command line.
function varargout = lvd_AddMassToTankActionGUI_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} = false;
    else
        action = getappdata(handles.lvd_AddMassToTankActionGUI, 'action');
        lvdData = getappdata(handles.lvd_AddMassToTankActionGUI, 'lvdData');

        [~, tanks] = lvdData.launchVehicle.getTanksListBoxStr();

        action.massToAdd = str2double(handles.massToAddText.String);
        action.tank = tanks(handles.tankCombo.Value);

        optVar = action.optVar;
        if(not(isempty(optVar))) %need to remove existing var if it exists
            lvdData.optimizer.vars.removeVariable(optVar);
        end

        %Set Opt T/F
        useTf = get(handles.optCheckbox,'Value');

        if(isempty(optVar))
            optVar = AddMassToTankActionOptimVar(action);
        end

        optVar.setUseTfForVariable(useTf);

        %Bnds
        lb = str2double(get(handles.lbText,'String'));
        ub = str2double(get(handles.ubText,'String'));

        optVar.setUseTfForVariable(true(size(lb))); %need this to get the full lb/set in there
        optVar.setBndsForVariable(lb, ub);
        optVar.setUseTfForVariable(useTf);

        lvdData.optimizer.vars.addVariable(optVar);

        varargout{1} = true;
        close(handles.lvd_AddMassToTankActionGUI);
    end

% --- Executes on button press in saveAndCloseButton.
function saveAndCloseButton_Callback(hObject, eventdata, handles)
% hObject    handle to saveAndCloseButton (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))
        uiresume(handles.lvd_AddMassToTankActionGUI);
    else
        msgbox(errMsg,'Invalid Tank Inputs','error');
    end

function errMsg = validateInputs(handles)
    errMsg = {};

    val = str2double(get(handles.massToAddText,'String'));
    enteredStr = get(handles.massToAddText,'String');
    numberName = 'Mass to Add';
    lb = -Inf;
    ub = Inf;
    isInt = false;
    errMsg = validateNumber(val, numberName, lb, ub, isInt, errMsg, enteredStr);

    lwrBnd = str2double(get(handles.lbText,'String'));
    enteredStr = get(handles.lbText,'String');
    numberName = 'Mass to Add (Lower Bound)';
    lb = -Inf;
    ub = Inf;
    isInt = false;
    errMsg = validateNumber(lwrBnd, numberName, lb, ub, isInt, errMsg, enteredStr);

    uprBnd = str2double(get(handles.ubText,'String'));
    enteredStr = get(handles.ubText,'String');
    numberName = 'Mass to Add (Upper Bound)';
    lb = -Inf;
    ub = Inf;
    isInt = false;
    errMsg = validateNumber(uprBnd, numberName, lb, ub, isInt, errMsg, enteredStr);

    if(isempty(errMsg))
        uprBnd = str2double(get(handles.ubText,'String'));
        enteredStr = get(handles.ubText,'String');
        numberName = 'Mass to Add (Upper Bound)';
        lb = lwrBnd;
        ub = Inf;
        isInt = false;
        errMsg = validateNumber(uprBnd, numberName, lb, ub, isInt, errMsg, enteredStr);
    end

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

function massToAddText_Callback(hObject, eventdata, handles)
% hObject    handle to massToAddText (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 massToAddText as text
%        str2double(get(hObject,'String')) returns contents of massToAddText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

% --- Executes during object creation, after setting all properties.
function massToAddText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to massToAddText (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 tankCombo.
function tankCombo_Callback(hObject, eventdata, handles)
% hObject    handle to tankCombo (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 tankCombo contents as cell array
%        contents{get(hObject,'Value')} returns selected item from tankCombo

% --- Executes during object creation, after setting all properties.
function tankCombo_CreateFcn(hObject, eventdata, handles)
% hObject    handle to tankCombo (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 optCheckbox.
function optCheckbox_Callback(hObject, eventdata, handles)
% hObject    handle to optCheckbox (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 optCheckbox
    if(get(hObject,'Value'))
        handles.lbText.Enable = 'on';
        handles.ubText.Enable = 'on';
    else
        handles.lbText.Enable = 'off';
        handles.ubText.Enable = 'off';
    end

function lbText_Callback(hObject, eventdata, handles)
% hObject    handle to lbText (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 lbText as text
%        str2double(get(hObject,'String')) returns contents of lbText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

% --- Executes during object creation, after setting all properties.
function lbText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to lbText (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 ubText_Callback(hObject, eventdata, handles)
% hObject    handle to ubText (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 ubText as text
%        str2double(get(hObject,'String')) returns contents of ubText as a double
    newInput = get(hObject,'String');
    newInput = attemptStrEval(newInput);
    set(hObject,'String', newInput);

% --- Executes during object creation, after setting all properties.
function ubText_CreateFcn(hObject, eventdata, handles)
% hObject    handle to ubText (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 key press with focus on lvd_AddMassToTankActionGUI or any of its controls.
function lvd_AddMassToTankActionGUI_WindowKeyPressFcn(hObject, eventdata, handles)
% hObject    handle to lvd_AddMassToTankActionGUI (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'
            saveAndCloseButton_Callback(handles.saveAndCloseButton, [], handles);
        case 'enter'
            saveAndCloseButton_Callback(handles.saveAndCloseButton, [], handles);
        case 'escape'
            close(handles.lvd_AddMassToTankActionGUI);
    end