function el = export_structure_set_module_field(args)
%"export_structure_set_module_field"
%   Given a single scan, return a properly populated structure_set module
%   field for use with RT Structure set IODs.  See structure_set_module_tags.m.
%
%   For speed, tag must be a decimal representation of the 8 digit
%   hexidecimal DICOM tag desired, ie instead of '00100010', pass
%   hex2dec('00100010');
%
%   Arguments are passed in a structure, arg:
%       arg.tag         = decimal tag of field to fill
%       arg.data        = CERR structure(s) to fill from
%       arg.template    = an empty template of the module created by the
%                         function build_module_template.m
%
%   This function requires arg.data = {structureS};
%
%JRA 06/19/06
%
%Usage:
%   dcmobj = export_patient_module_field(args)
%
% 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/>.

%Init output element to empty.
el = [];

%Unpack input data.
tag         = args.tag;
structuresS = args.data{1};
scansS      = args.data{2};
template    = args.template;

switch tag
    %Class 1 Tags -- Required, must have data.
    case 805699586  %3006,0002 Structure Set Label.
        data = 'CERR Export';
        el = data2dcmElement(data, tag);

    %Class 2 Tags -- Must be present, can be NULL.
    case 805699592  %3006,0008 Structure Set Date
        data = datestr(now, 29);
        el = data2dcmElement(data, tag);

    case 805699593  %3006,0009 Structure Set Time
        data = datestr(now, 13);
        el = data2dcmElement(data, tag);

    %Class 3 Tags -- presence is optional, currently undefined.
    case 805699588  %3006,0004 Structure Set Name
        %Currently unsupported.

    case 805699590  %3006,0006 Structure Set Description
        %Currently unsupported.

    case   2097171  %3006,0013 Instance Number
        %Currently unsupported.

    case 805699600  %3006,0010 Referenced Frame of Reference Sequence
        templateEl = template.getValue(tag);

        fHandle = @export_referenced_frame_of_reference_sequence;

        tmp = javaObject('org.dcm4che3.data.Attributes');
        el = tmp.newSequence(tag, 0);

        %Get unique frame of reference UIDs used by structures.
        [FORs,indV]    = unique({structuresS.Frame_Of_Reference_UID});
        nFORs   = length(FORs);

        for i=1:nFORs
            dcmobj = export_sequence(fHandle, templateEl, {FORs(i), scansS, structuresS(indV(i))});
            %dcmobj = export_sequence(fHandle, templateEl, {FORs(i), scansS});
            el.add(i-1, dcmobj);
        end

        el = el.getParent();

    case 805699616  %3006,0020 Structure Set ROI Sequence
        templateEl = template.getValue(tag);
        fHandle = @export_structure_set_ROI_sequence;

        tmp = javaObject('org.dcm4che3.data.Attributes');
        el = tmp.newSequence(tag, 0);

        nStructures = length(structuresS);

        for i=1:nStructures
            dcmobj = export_sequence(fHandle, templateEl, {structuresS(i), i});
            %dcmobj = export_sequence(fHandle, tag, {structuresS(i), i});
            el.add(i-1, dcmobj);
        end

        el = el.getParent();
    %Class 1C Tags -- presence is required under special circumstances

    %Class 2C Tags.

    otherwise
        warning(['No methods exist to populate DICOM structure_set module field ' dec2hex(tag,8) '.']);
end


function dfdelgraphexclude
%DFDELGRAPHEXCLUDE Called when the exclusion dataset changes

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

% Find the exclusion graph's figure window, and delete it
t = get(0,'ShowHiddenHandles');
set(0,'ShowHiddenHandles','on');
c = get(0,'Child');
f = findobj(c,'flat','Type','figure','Tag','dfexcludegraph');
set(0,'ShowHiddenHandles',t);
delete(f);


function rts_updateConnStatusLbl(connected, hLbl, vesselName)
%rts_updateConnStatusLbl Summary of this function goes here
%   Detailed explanation goes here

    connStr = 'CONNECTED';
    disconnStr = 'DISCONNECTED';
    if(connected)
        preposition = ' to ';
        statusStr = formConnectedStatusString(connStr, vesselName, preposition);
        statusColor = 'green';
    else
        statusStr = formDisconnectedStatusString(disconnStr);
        statusColor = 'red';
    end

    if(ishandle(hLbl))
        set(hLbl, 'String', statusStr);
        set(hLbl, 'ForegroundColor', statusColor);
    end
end

function statusStr = formConnectedStatusString(status, vesselName, preposition)
%     statusStr = [status, preposition, vesselName];
    statusStr = status;
end

function statusStr = formDisconnectedStatusString(status)
    statusStr = status;
end


function ui = mrViewMeshPanel(ui, dockFlag, vis);
%
% ui = mrViewMeshPanel(ui, [dockFlag], [vis=0]);
%
% Adds a panel to the mrViewer UI with
% controls for displaying data onto 3D meshes.
%
% dockFlag: if 1,  will attach panel to the
% mrViewer figure. Otherwise,  will make a
% separate figure for the panel.
%
% vis: if 0, will initialize the panel to be hidden (default when
% starting up mrViewer); otherwise, leave it visible (as when
% docking/undocking the panel).
%
% ras,  07/13/06.
if ~exist('ui','var') | isempty(ui),   ui = mrViewGet; end
if ~exist('dockFlag','var') | isempty(dockFlag),   dockFlag = 1; end
if ~exist('vis','var') | isempty(vis),   vis = 0; end

mrGlobals2;

bgColor = [.9 .9 .9];

if dockFlag==1
    ui.panels.mesh = mrvPanel('right',   0.2,  ui.fig,  'normalized');
else
    hfig = figure('Name',   sprintf('Info [%s]', ui.tag),   ...
                  'Units',   'normalized',   ...
                  'Position',  [.88 .5 .12 .5],   ...
                  'MenuBar',   'none',   ...
                  'NumberTitle',   'off',   ...
                  'UserData', ui.tag);
    ui.panels.mesh = uipanel('Parent', hfig, 'Units',   'normalized',   ...
                               'Position',  [0 0 1 1]);
	% close request function for this figure: just toggle visibility
    crf = 'tmp = findobj(''Parent'', gcf, ''Type'', ''uipanel''); ';
    crf = [crf 'mrvPanelToggle(tmp); clear tmp;'];
    set(hfig, 'CloseRequestFcn', crf);
end

set(ui.panels.mesh, 'BackgroundColor', bgColor, 'Title', 'Mesh', ...
    'ShadowColor', bgColor, 'UIContextMenu', meshPanelContextMenu(ui));

% add a popup showing the selected segmentation
uicontrol('Parent', ui.panels.mesh, 'Style', 'text', 'String', 'Selected Segmentation', ...
    'Units', 'normalized', 'Position', [.1 .95 .8 .03], ...
    'HorizontalAlignment', 'left', 'BackgroundColor', [.9 .9 .9]);

ui.controls.segSelect = uicontrol('Parent', ui.panels.mesh, 'Style', 'popup',...
	'String', {'(none loaded)'}, 'Value', 1, ...
    'Units', 'normalized', 'Position', [.1 .91 .8 .04], ...
    'HorizontalAlignment', 'left', 'BackgroundColor', [1 1 1], ...
	'Callback', 'mrViewSet(gcf, ''SegmentationNum'', get(gcbo, ''Value''));');

% add a popup menu showing all meshes loaded (across all segmentations)
uicontrol('Parent', ui.panels.mesh, 'Style', 'text', 'String', 'Selected Mesh', ...
    'Units', 'normalized', 'Position', [.1 .86 .8 .03], ...
    'HorizontalAlignment', 'left', 'BackgroundColor', [.9 .9 .9]);

ui.controls.meshSelect = uicontrol('Parent', ui.panels.mesh, 'Style', 'popup',...
	'String', {'(none loaded)'}, 'Value', 1, ...
    'Units', 'normalized', 'Position', [.1 .82 .8 .04], ...
    'HorizontalAlignment', 'left', 'BackgroundColor', [1 1 1], ...
	'Callback', 'mrViewSelectMesh(gcf, get(gcbo, ''Value''));');

% update all meshes button
ui.controls.meshUpdateAll = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Update All', ...
    'BackgroundColor', [.9 .8 .9], ...
    'Units', 'normalized', 'Position', [.1 .78 .8 .04],   ...
    'Callback', 'mrViewUpdateAllMeshes; ');

% mesh update button
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Update', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.1 .7 .8 .04],   ...
    'Callback', 'mrViewMesh; ');

% mesh open button
cb = 'mrViewLoad(gcf, [], ''Mesh''); mrViewDisplayMesh; ';
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Open', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.1 .65 .4 .04],   ...
    'Callback', cb);

% mesh close button
cb = ['segCloseMesh( mrViewGet(gcf, ''Segmentation'') );'];
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Close', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.5 .65 .4 .04],   ...
    'Callback', cb);

% mesh get ROI button
cb = ['mrViewROI(''mesh''); '];
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Get ROI', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.1 .6 .4 .04],   ...
    'Callback', cb);

% mesh get Disk button (N.Y.I.; just does mesh ROI layer 1 xform now)
cb = ['mrViewROI(''meshgrow''); '];
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Grow ROI', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.5 .6 .4 .04],   ...
    'Callback', cb);

% toggle cursor button
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Cursor', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.1 .55 .4 .04],   ...
    'Callback', 'meshToggleCursor(mrViewGet(gcf, ''mesh''));'); % 'mrViewSetCursorFromMesh;'

% mesh prefs button
ui.controls.meshUpdate = uicontrol('Parent', ui.panels.mesh,  ...
    'Style', 'pushbutton',  'String', 'Prefs', ...
    'BackgroundColor', [.9 .8 .8], ...
    'Units', 'normalized', 'Position', [.5 .55 .4 .04],   ...
    'Callback', 'mrmPreferences; ');

%%%%%%%%%%%%%%%%%%%
%% Mesh Settings %%
%%%%%%%%%%%%%%%%%%%
% listbox w/ settings
mrGlobals2;
names = {''};
uicontrol('Parent', ui.panels.mesh, 'Style', 'text', 'String', 'Settings', ...
    'Units', 'normalized', 'Position', [.1 .45 .8 .05], 'FontSize', 12, ...
    'HorizontalAlignment', 'left', 'BackgroundColor', [.9 .9 .9]);

h.settingsList = uicontrol('Parent', ui.panels.mesh, 'Style', 'listbox', ...
                   'Units', 'normalized', 'Position', [.1 .2 .8 .25], ...
                   'String', names, 'Tag', 'MeshSettingsList');

% store settings button
callback = 'meshStoreSettings(mrViewGet(gcf, ''CurMesh'')); ';
h.store = uicontrol('Parent', ui.panels.mesh, 'Style', 'pushbutton', ...
            'Units', 'normalized', 'Position', [.1 .15 .4 .04], ...
            'String', 'Store', 'Callback', callback);

% retrieve settings button
callback = 'meshRetrieveSettings(mrViewGet(gcf, ''CurMesh'')); ';
h.retrieve = uicontrol('Parent', ui.panels.mesh, 'Style', 'pushbutton', ...
            'Units', 'normalized', 'Position', [.1 .1 .4 .04], ...
            'String', 'Retrieve', 'Callback', callback);

% rename settings button
callback = 'meshRenameSettings(mrViewGet(gcf, ''CurMesh'')); ';
h.rename = uicontrol('Parent', ui.panels.mesh, 'Style', 'pushbutton', ...
            'Units', 'normalized', 'Position', [.5 .15 .4 .04], ...
            'String', 'Rename', 'Callback', callback);

% delete settings button
callback = 'meshDeleteSettings(mrViewGet(gcf, ''CurMesh'')); ';
h.delete = uicontrol('Parent', ui.panels.mesh, 'Style', 'pushbutton', ...
            'Units', 'normalized', 'Position', [.5 .1 .4 .04], ...
            'String', 'Delete', 'Callback', callback);

% % manual zoom slider
% cb = ['MSH = mrViewGet(gcf, ''SelectedMesh''); ' ...
%       'TMP = mrmGet(MSH,''Camera''); TMP.actor = 0; ' ...
%       'TMP.frustum(2) = 600 - get(gcbo, ''Value''); ' ...
%       'mrMesh(MSH.host, MSH.id, ''set'', TMP); clear TMP MSH;'];
% h.zoom = uicontrol('Parent', ui.panels.mesh, 'Style', 'slider', ...
%             'Min', 0, 'Max', 600, ...
%             'Units', 'normalized', 'Position', [.1 .05 .8 .04], ...
%             'String', 'Zoom', 'Callback', cb);
% uicontrol('Parent', ui.panels.mesh, 'Style', 'text', 'Units', 'normalized', ...
%     'Position', [.1 .1 .8 .04], 'String', 'Manual Zoom', ...
%     'HorizontalAlignment', 'left');

ui.meshHandles = h;

%%%%%hide the panel if requested
if vis==0
	mrvPanelToggle(ui.panels.mesh, 'off');
end

return

function h = meshPanelContextMenu(ui);
% creates a UI Context menu for the mesh panel. This initially has a single
% option, allowing you to set the mesh width (in case it gets screwed up).
% In the future, I may add more context-specific operations.
h = uicontextmenu;

cb = ['UI = mrViewGet;  TMP_POS = get(UI.panels.mesh, ''Position''); ' ...
	  'PROMPT = {''Enter New Panel Width: ''}; ' ...
	  'DEF = {num2str(TMP_POS(3))}; ' ...
	  'TMP_RESP = inputdlg(PROMPT, ''Mesh Panel'', 1, DEF); ' ...
	  'TMP_POS(3) = str2num( TMP_RESP{1} ); ' ...
	  'set(ui.panels.mesh, ''Position'', TMP_POS); ' ...
	  'clear UI TMP_POS PROMPT DEF TMP_RESP TMP_POS; '];
uimenu(h, 'Label', 'Set Panel Width');

return


%%%
%{
Copyright (c) 2010, Jake Hughey
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

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

function [sortedStruct index] = nestedSortStruct(aStruct, fieldNamesCell, directions)
% [sortedStruct index] = nestedSortStruct(aStruct, fieldNamesCell, directions)
% nestedSortStruct returns a nested sort of a (one-dimensional) struct array
% (aStruct), and can also return an index vector. The fields by which to sort are
% specified in a cell array of strings fieldNamesCell. Fields must be single numbers or
% logicals, or chars (usually simple strings).
%
% fieldNamesCell can also be a simple string of one fieldname, in which case
% nestedSortStruct will simply call sortStruct. This will be faster than putting the
% single fieldname in a cell array.
%
% directions is an optional argument to specify whether the struct array should be sorted
% in ascending or descending order for the fields. By default, the struct array will be
% sorted in ascending order for each field. If supplied, directions must be
%       1) a single 1 to sort in ascending order for all fields, or
%       2) a single -1 to sort in descending order for all fields, or
%       3) a vector of 1's and -1's, the same length as fieldNamesCell, where the struct
%          array will be sorted in the order specified by directions(ii) for
%          fieldNamesCell(ii).
%
% nestedSortStruct basically converts the struct array to a cell array, then converts
% relevants parts of the cell array to a matrix, on which sortrows is run.
%
% nestedSortStruct will usually be faster than nestedSortStruct2. For nestedSortStruct,
% the speed of sorting is mostly independent of the order of the fieldnames in fieldNamesCell.
%
% For nestedSortStruct2, the order of the fields in fieldNamesCell affects the speed. The
% sooner a field for which most entries in the struct array have unique values will be
% used to sort the struct array (i.e., the earlier that field's location in
% fieldNamesCell), the faster nestedSortStruct2 will be. If a field with mostly unique
% entries is the first field by which the struct array will be sorted, nestedSortStruct2
% could be faster than nestedSortStruct.

%% check struct
if ~isstruct(aStruct)
    error('first input supplied is not a struct.')
end % if

if sum(size(aStruct)>1)>1 % if more than one non-singleton dimension
    error('I don''t want to sort your multidimensional struct array.')
end % if

%% check fieldnames
if ~iscell(fieldNamesCell)
    if isfield(aStruct, fieldNamesCell) % if fieldNamesCell is a simple string of a valid fieldname
        [sortedStruct index] = sortStruct(aStruct, fieldNamesCell);
        return
    else
        error('second input supplied is not a cell array or simple string of a fieldname.')
    end % if isfield
end % if ~iscell

if ~isfield(aStruct, fieldNamesCell)
    for ii=find(~isfield(aStruct, fieldNamesCell))
        fprintf('%s is not a fieldname in the struct.\n', fieldNamesCell{ii})
    end % for
    error('at least one entry in fieldNamesCell is not a fieldname in the struct.')
end % if

%% check classes of fieldnames
fieldFlag = 0;
for ii=1:length(fieldNamesCell)
    fieldEntry = aStruct(1).(fieldNamesCell{ii});
    if ~( ((isnumeric(fieldEntry) || islogical(fieldEntry)) && numel(fieldEntry)==1) || ischar(fieldEntry) )
        fprintf('%s is not a valid fieldname by which to sort.\n', fieldNamesCell{ii})
        fieldFlag = 1;
    end % if
end % for ii

if fieldFlag
    error('at least one fieldname is not a valid one by which to sort.')
end

%% check directions, create if necessary (1 for ascending, -1 for descending)
if nargin < 3 % if directions doesn't exist
    directions = ones(1, length(fieldNamesCell));
else % check directions if it does exist
    if ~(isnumeric(directions) && all(ismember(directions, [-1 1])))
        error('directions, if given, must be a single number or a vector with 1 (ascending) and -1 (descending).')
    end % if ~(...

    if numel(directions)==1
        directions = directions * ones(1, length(fieldNamesCell)); % create vector from single element
    elseif length(fieldNamesCell)~=length(directions)
        error('fieldNamesCell and directions vector are different lengths.')
    end % if numel...
end % if exist...

%% fieldNamesIdx is a vector of the indices of the fields by which to sort
[dummy fieldNamesIdx] = ismember(fieldNamesCell, fieldnames(aStruct));

%% convert the struct to a cell, squeeze makes sure both row and column arrays are sorted properly, transpose for sortrows
aCell = squeeze(struct2cell(aStruct))';

%% sortrows of aCell, using indices from fieldNamesIdx and directions
[sortedCell index] = sortrows(aCell, fieldNamesIdx .* directions);

sortedStruct = aStruct(index); % apply the index to the struct array


function str = encodevarname(str,varargin)
%
%    newname = encodevarname(name)
%
%    Encode an invalid variable name using a hex-format for bi-directional
%    conversions.

%    This function is sensitive to the default charset
%    settings in MATLAB, please call feature('DefaultCharacterSet','utf8')
%    to set the encoding to UTF-8 before calling this function.
%
%    author: Qianqian Fang (q.fang <at> neu.edu)
%
%    input:
%        name: a string, can be either a valid or invalid variable name
%
%    output:
%        newname: a valid variable name by converting the leading non-ascii
%              letter into "x0xHH_" and non-ascii letters into "_0xHH_"
%              format, where HH is the ascii (or Unicode) value of the
%              character.
%
%              if the encoded variable name CAN NOT be longer than 63, i.e.
%              the maximum variable name specified by namelengthmax, and
%              one uses the output of this function as a struct or variable
%              name, the name will be trucated at 63. Please consider using
%              the name as a containers.Map key, which does not have such
%              limit.
%
%    example:
%        encodevarname('_a')   % returns x0x5F_a
%        encodevarname('a_')   % returns a_ as it is a valid variable name
%        encodevarname('变量')  % returns 'x0xE58F98__0xE9878F_'
%
%    this file is part of EasyH5 Toolbox: https://github.com/fangq/easyh5
%
%    License: GPLv3 or 3-clause BSD license, see https://github.com/fangq/easyh5 for details
%

    if(~isvarname(str(1)))
        if(exist('unicode2native','builtin'))
            str=regexprep(str,'^([^A-Za-z])','x0x${sprintf(''%X'',unicode2native($1))}_','once');
        else
            str=sprintf('x0x%X_%s',char(str(1))+0,str(2:end));
        end
    end
    if(isvarname(str))
        return;
    end
    if(exist('unicode2native','builtin'))
        str=regexprep(str,'([^0-9A-Za-z_])','_0x${sprintf(''%X'',unicode2native($1))}_');
    else
        cpos=regexp(str,'[^0-9A-Za-z_]');
        if(isempty(cpos))
            return;
        end
        str0=str;
        pos0=[0 cpos(:)' length(str)];
        str='';
        for i=1:length(cpos)
            str=[str str0(pos0(i)+1:cpos(i)-1) sprintf('_0x%X_',str0(cpos(i))+0)];
        end
        if(cpos(end)~=length(str))
            str=[str str0(pos0(end-1)+1:pos0(end))];
        end
    end
end


function format_string = guess_nitf_format(imagesubhdr)
% GUESS_NITF_FORMAT Given a NITF image subheader structure, this functions
% tries to determine which set of sensor specific adjustments might need to
% be applied
%
% Assumes a set of test functions (all of the format isnitf*.m) are in the
% same directory.  If format is unrecognized, an empty string is returned.
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

fullname=which(mfilename('fullpath'));
path=fileparts(fullname);
filelist=dir([path filesep 'isnitf*.m']);

format_string=[];
for i=1:length(filelist)
    str_ind=strfind(filelist(i).name,'.m');
    if ~isempty(str_ind)&&(str_ind(end)>1)
        test_format=filelist(i).name(1:(str_ind(end)-1)); % Strip off .m extension
        if(feval(test_format, imagesubhdr))
            format_string=test_format(7:end);
            return
        end
    end
end

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


% eegplugin_ascinstep() - EEGLAB plugin for importing ASC INStep files.
%
% Usage:
%   >> eegplugin_ascinstep(menu);
%   >> eegplugin_ascinstep(menu, trystrs, catchstrs);
%
% Inputs:
%   menu       - [float]  EEGLAB menu handle
%   trystrs    - [struct] "try" strings for menu callbacks. See notes on EEGLab plugins.
%                (http://www.sccn.ucsd.edu/eeglab/contrib.html)
%   catchstrs  - [struct] "catch" strings for menu callbacks. See notes on EEGLab plugins.
%                (http://www.sccn.ucsd.edu/eeglab/contrib.html)
%
%
% Notes:
%   This plugins consist of the following Matlab files:
%   pop_loadeep.m           pop_loadeep_avg.m
%   loadeep.m               loadeep_avg.m
%   read_eep_cnt.m          read_eep_avr.m
%   read_eep_cnt.mexglx     read_eep_avr.mexglx
%   read_eep_cnt.dll        read_eep_avr.dll
%
% Authors: Arnaud Delorme, SCCN, INC, UCSD, 2006

% Copyright (C) 2006 Arnaud Delorme
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

function vers = eegplugin_ascinstep(fig, trystrs, catchstrs)

    vers = 'eepimport1.02';

    if nargin < 3
        error('eegplugin_ascinstep requires 3 arguments');
    end;

    % add folder to path
    % ------------------
    if ~exist('pop_loadeep')
        p = which('eegplugin_ascinstep.m');
        p = p(1:findstr(p,'eegplugin_ascinstep.m')-1);
        addpath( p );
    end;

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

    % menu callbacks
    % --------------
    comcnt = [ trystrs.no_check '[EEG LASTCOM] = pop_loadascinstep;' catchstrs.new_and_hist ];

    uimenu( menu, 'label', 'From INStep .ASC file', 'callback', comcnt, 'separator', 'on' );


function copyDependenciesForCERRCompile(compiled_path)

% function copyDependenciesForCERRCompile(compiled_path)
%
% This function creates bin, doc, pics directories and copies files to
% them.
%
% APA, 03/26/2012
% RKP, 8/13/2019 - Updated to use dcm4che-5.17.0

CERRPath = getCERRPath;
CERRPathSlashes = strfind(getCERRPath,filesep);
topLevelCERRDir = CERRPath(1:CERRPathSlashes(end-1));

% Create bin, doc and pics directories
mkdir(fullfile(compiled_path,'bin'));
mkdir(fullfile(compiled_path,'doc'));
mkdir(fullfile(compiled_path,'pics'));
copyfile(fullfile(topLevelCERRDir,'CERR_core','CERROptions.m'),compiled_path);
copyfile(fullfile(topLevelCERRDir,'CERR_core','CERROptions.json'),compiled_path);

% Fill-in the bin directory
destin = fullfile(compiled_path,'bin');
mkdir(fullfile(destin,'Compression'));
mkdir(fullfile(destin,'Importing'));
mkdir(fullfile(destin,'IMRTP'));
mkdir(fullfile(destin,'mat_files'));
mkdir(fullfile(destin,'MeshInterp'));
copyfile(fullfile(topLevelCERRDir,'ML_Dicom','dcm4che-5.17.0'),fullfile(destin,'dcm4che-5.17.0'));
copyfile(fullfile(topLevelCERRDir,'CERR_core','Mex'),fullfile(destin,'Mex'));

destin_compression = fullfile(compiled_path,'bin','Compression');
copyfile(fullfile(topLevelCERRDir,'CERR_core','Compression','7z.dll'),destin_compression);
copyfile(fullfile(topLevelCERRDir,'CERR_core','Compression','7z.exe'),destin_compression);
copyfile(fullfile(topLevelCERRDir,'CERR_core','Compression','7z.sfx'),destin_compression);
copyfile(fullfile(topLevelCERRDir,'CERR_core','Compression','7z_License.txt'),destin_compression);
copyfile(fullfile(topLevelCERRDir,'CERR_core','Compression','tar.exe'),destin_compression);

destin_importing = fullfile(compiled_path,'bin','Importing');
copyfile(fullfile(topLevelCERRDir,'CERR_core','Importing','readASCIIDose.exe'),destin_importing);
copyfile(fullfile(topLevelCERRDir,'CERR_core','Importing','ES - IPT4.1CompatibleDictionary.mat'),destin_importing);

destin_IMRTP = fullfile(compiled_path,'bin','IMRTP');
copyfile(fullfile(topLevelCERRDir,'IMRTP','QIBData'),fullfile(destin_IMRTP,'QIBData'),'f');
copyfile(fullfile(topLevelCERRDir,'IMRTP','vmc++'),fullfile(destin_IMRTP,'vmc++'),'f');

copyfile(fullfile(topLevelCERRDir,'CERR_core','Icons','copperColorMap.mat'),fullfile(compiled_path,'bin','mat_files'));

destin_MeshInterp = fullfile(compiled_path,'bin','MeshInterp');
copyfile(fullfile(topLevelCERRDir,'CERR_core','MeshBasedInterp','libMeshContour.dll'),destin_MeshInterp);
copyfile(fullfile(topLevelCERRDir,'CERR_core','MeshBasedInterp','MeshContour.h'),destin_MeshInterp);
copyfile(fullfile(topLevelCERRDir,'CERR_core','MeshBasedInterp','pretriang_4.txt'),destin_MeshInterp);
copyfile(fullfile(topLevelCERRDir,'CERR_core','MeshBasedInterp','pretriang_5.txt'),destin_MeshInterp);
copyfile(fullfile(topLevelCERRDir,'CERR_core','MeshBasedInterp','pretriang_6.txt'),destin_MeshInterp);

% Fill-in the pics directory
destin = fullfile(compiled_path,'pics');
copyfile(fullfile(topLevelCERRDir,'CERR_core','Icons'),fullfile(destin,'Icons'));
copyfile(fullfile(topLevelCERRDir,'CERR_core','CERR.png'),destin);
copyfile(fullfile(topLevelCERRDir,'CERR_core','Contouring','structureFusionBackground.png'),destin);

% Fill-in the docs directory
destin = fullfile(compiled_path,'doc');
mkdir(fullfile(destin,'html'));
copyfile(fullfile(topLevelCERRDir,'CERR_core','CommandLine','CERRCommandLinehelp.html'),fullfile(destin,'html'));

%  Copy JSON configuration files for Segmentation and Dosimetric models
destin_modelConfig = fullfile(compiled_path,'ModelImplementationLibrary','SegmentationModels', 'ModelConfigurations');
mkdir(destin_modelConfig)
copyfile(fullfile(topLevelCERRDir,'CERR_core','ModelImplementationLibrary','SegmentationModels', 'ModelConfigurations'),destin_modelConfig);
destin_modelConfig = fullfile(compiled_path,'ModelImplementationLibrary','DosimetricModels', 'Models');
mkdir(destin_modelConfig)
copyfile(fullfile(topLevelCERRDir,'CERR_core','ModelImplementationLibrary','DosimetricModels', 'Models'),destin_modelConfig);

return;


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

% Always writing version 2.1 NITF

fwriten(obj.FID, 'DE', 2);   % DE
fwriten(obj.FID, 'XML_DATA_CONTENT', 25);  % DESID
fwriten(obj.FID, '01', 2);   % DESVER
obj.write_nitf_security_tags(); % Security tags go here
%fwriten(obj.FID, '0000', 4);   % DESSHL - Complete inclusion of all User-defined Subheader Subfield was not required prior to SICD version 1.0
fwriten(obj.FID, '0773', 4);   % DESSHL
fwriten(obj.FID, '99999', 5); % DESCRC - CRC not computed
fwriten(obj.FID, 'XML', 8); % DESSHFT
if isfield(obj.sicdmeta,'ImageCreation') && isfield(obj.sicdmeta.ImageCreation, 'DateTime')
    fwriten(obj.FID, datestr(obj.sicdmeta.ImageCreation.DateTime,'yyyy-mm-ddTHH:MM:SSZ'), 20); % DESSHDT
else
    fwriten(obj.FID, '', 20); % DESSHDT
end
fwriten(obj.FID, '', 40); % DESSHRP
fwriten(obj.FID, 'SICD Volume 1 Design & Implementation Description Document', 60); % DESSHSI
fwriten(obj.FID, '1.0', 10); % DESSHSV
fwriten(obj.FID, '2011-09-28T00:00:00Z', 20); % DESSHSD
fwriten(obj.FID, 'urn:SICD:1.0.0', 120); % DESSHTN
if isfield(obj.sicdmeta,'GeoData') && isfield(obj.sicdmeta.GeoData,'ImageCorners') && ...
    isfield(obj.sicdmeta.GeoData.ImageCorners,'ICP')
    DESSHLPG = sprintf('%+012.8f%+013.8f%+012.8f%+013.8f%+012.8f%+013.8f%+012.8f%+013.8f',...
        obj.sicdmeta.GeoData.ImageCorners.ICP.FRFC.Lat,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.FRFC.Lon,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.FRLC.Lat,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.FRLC.Lon,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.LRLC.Lat,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.LRLC.Lon,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.LRFC.Lat,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.LRFC.Lon,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.FRFC.Lat,...
        obj.sicdmeta.GeoData.ImageCorners.ICP.FRFC.Lon);
else
    DESSHLPG = '';
end
fwriten(obj.FID, DESSHLPG, 125); % DESSHLPG
fwriten(obj.FID, '', 25); % DESSHLPT
fwriten(obj.FID, '', 20); % DESSHLI
fwriten(obj.FID, '', 120); % DESSHLIN
fwriten(obj.FID, '', 200); % DESSHABS

end

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


% Initialize path
M_ROOT = fileparts(which(mfilename));
addpath([M_ROOT '/vgg']);
addpath([M_ROOT '/ojw']);
clear M_ROOT


%% OpenMAS Object Class Diagnotistic tool (OMAS_objectDiagnostics.m) %%%%%%
% This function is designed to preform a batch analysis of the complete
% class library to verify their development status for simulation.

function [issueCount] = OMAS_objectDiagnostics(varargin)

% Input sanity check
assert(numel(varargin) <= 2,'Please provide an object to test, or nothing to test all objects in the "objects" directory.');

% Generate the path to the model directory
phaseStr = 'DIAGNOSTICS';
outputFileName = 'object-diagnostics.xlsx';

repoPath = mfilename('fullpath');           % Get the system paths
ind = strfind(repoPath,'env');
repoPath = repoPath(1:(ind-1));

objectsDir = [repoPath,'objects'];
outputFile = [repoPath,outputFileName];
tempDir = OMAS_system.GetOSPathString([repoPath,'temp']);

% DETERMINE THE INPUTS
switch numel(varargin)
    case 1
        % Assume named model
        targetFiles = varargin(1);
    case 0
        % Assume all models
        targetFiles = dir([objectsDir,'\*.m']);
        targetFiles = {targetFiles.name}';
    otherwise
        error('Please provide a model name, or no input.');
end

fprintf('[%s]\t%d object behaviours found, evaluating...\n',phaseStr,numel(targetFiles));

% Handle file I/O
fclose('all');                                                 % Release any file handle
if exist(outputFile,'file')
    delete(outputFile);                              % Delete output file
end

% Prepare the diagnostic header
headerArray = {'model #','file name','class',...
    'build status','build message',...
    'OMAS status','OMAS message',...
    'notes'};

% Check if file is active
try
    % Try to write the header to the file
    xlswrite(outputFile,headerArray);
catch writeError
    warning('Unable to write to diagnostic file, is it open?');
    rethrow(writeError);
end

% Container for model error status
statusArray  = false(numel(targetFiles),1);
summaryArray = cell(numel(targetFiles),numel(headerArray));

% ///////////////// MOVE THROUGH THE MODELS ///////////////////
for i = 1:numel(targetFiles)
    % For clarity
    fprintf('[%s]\tEvaluating model "%s"...\n',phaseStr,targetFiles{i});
    % Preform diagnostic routine on selected model
    [entry,statusArray(i)] = GetObjectEvaluation(phaseStr,tempDir,targetFiles{i});
    % For clarity
    fprintf('[%s]\tEvaluation for model "%s" complete.\n\n',phaseStr,targetFiles{i});

    close all; % Terminate all open figures

    summaryArray(i,:) = [num2str(i),entry];                    % Append the test number
end
% /////////////////////////////////////////////////////////////
issueCount = sum(statusArray);                                 % Simply confirm if there are any issues

% Write data to the output .xlsx file
xlswrite(outputFile,[headerArray;summaryArray]);
fclose('all');                                                 % Release any file handle

% Delete temporary directory
try
    rmdir(tempDir,'s');
catch
    warning('There was a problem deleting the temporary file.');
end

% Pass statistics
errorNumber   = sum(statusArray == 0);
successNumber = sum(statusArray == 1);

% Summary string
fprintf('[%s]\tDiagnostics complete, %d object errors, %d objects working correctly.\n',phaseStr,errorNumber,successNumber);
end

% Compute the evaluation of the provided object file
function [entryArray,isSuccessful] = GetObjectEvaluation(phaseStr,tempDir,fileName)

% Input sanity check
assert(ischar(fileName),'The model name must be given as a string.');

% Remove the .m from the file-name for evaluation
if contains(fileName,'.m')
    fileName = strrep(fileName,'.m',''); % Remove extension if necessary
end

% Containers
sim_steps   = 5;
sim_dt      = 0.25;
failString = 'FAILED';
passString = 'PASSED';
importStatus = 0;
simStatus = 0;
isSuccessful = 0;

% Create row for output .csv
entryArray = repmat({'-'},1,7);
entryArray{1} = fileName;
entryArray{2} = 'N/a';

% //////////// ATTEMPT TO INSTANTIATE THE MODEL ///////////////
% CREATE THE OBJECT SET
objectNumber = 2;
objectIndex = cell(objectNumber,1);
try
    for j = 1:objectNumber
        objectIndex{j} = eval(fileName);                                % Attempt to construct the object
    end
    importStatus = 1;
catch instantiationError
    warning(instantiationError.message);
    entryArray{3} = failString;
    entryArray{4} = instantiationError.message;
end
% /////////////////////////////////////////////////////////////

% Check instantiation was successful
if ~importStatus
    fprintf('[%s]\t%s(1) - Object "%s" failed to be instantiated.\n',phaseStr,failString,fileName);
    return
end
fprintf('[%s]\t%s(1) - Object "%s" instantiated.\n',phaseStr,passString,fileName);

% Lift basic model parameters
entryArray{2} = class(objectIndex{1});
entryArray{3} = passString;

% ////////// IF THE OBJECT CAN BE SIMULATED, ATTEMPT SIMULATION ///////////
fprintf('[%s]\tSimulating object "%s"\n',phaseStr,fileName);
try
    OMAS_initialise(...
        'objects',objectIndex,...
        'duration',sim_steps*sim_dt,...
        'dt',sim_dt,...
        'idleTimeOut',0.5,...
        'figures','None',...
        'verbosity',0,...
        'outputPath',tempDir);
    simStatus = 1;
catch simError
    warning(simError.message);
    entryArray{5} = failString;
    entryArray{6} = simError.message;
    notes = strcat('[function] -> ',simError.stack(1).name);
    entryArray{7} = strcat(notes,' [line] -> ',num2str(simError.stack(1).line));
end
% /////////////////////////////////////////////////////////////////////////

% Check simulation was successful
if ~simStatus
	fprintf('[%s]\t%s(2) - Model "%s" failed simulation test\n.',phaseStr,failString,fileName);
    return
end
fprintf('[%s]\t%s(2) - Model "%s" simulated successfully.\n',phaseStr,passString,fileName);

% Indicate simulation was successful
entryArray{5} = passString;

% Indicate that if there where no errors
isSuccessful = 1;
end


classdef Compartment < handle
    properties
        count             %number of compartments
        wholeCellModelIDs %ids of compartments
        names             %names of compartments
    end

    %indices
    properties
        cytosolIndexs                   %index within compartments
        chromosomeIndexs                %index within compartments
        membraneIndexs                  %index within compartments
        terminalOrganelleCytosolIndexs  %index within compartments
        terminalOrganelleMembraneIndexs %index within compartments
        extracellularIndexs             %index within compartments
        cellularIndexs                  %index within compartments
    end

    methods
        function this = Compartment()
        end

        function initializeConstants(this, knowledgeBase, ~)
            this.count             = knowledgeBase.numCompartments;
            this.wholeCellModelIDs = {knowledgeBase.compartments.wholeCellModelID}';
            this.names             = {knowledgeBase.compartments.name}';

            this.cytosolIndexs                   = knowledgeBase.cytosolCompartmentIndexs;
            this.chromosomeIndexs                = knowledgeBase.chromosomeCompartmentIndexs;
            this.membraneIndexs                  = knowledgeBase.membraneCompartmentIndexs;
            this.terminalOrganelleCytosolIndexs  = knowledgeBase.terminalOrganelleCytosolCompartmentIndexs;
            this.terminalOrganelleMembraneIndexs = knowledgeBase.terminalOrganelleMembraneCompartmentIndexs;
            this.extracellularIndexs             = knowledgeBase.extracellularCompartmentIndexs;
            this.cellularIndexs                  = knowledgeBase.cellularCompartmentIndexs;
        end

        function index = getIndexs(this, wholeCellModelIDs)
            [~, index] = ismember(wholeCellModelIDs, this.wholeCellModelIDs);
        end
    end
end


function varargout = subsref(f,s)
%overloads subsref

switch s(1).type
  case '()'

    f.h = subsref(f.h,s(1));
    f.o1 = subsref(f.o1,s(1));
    f.o2 = subsref(f.o2,s(1));

    if numel(s)>1
      [varargout{1:nargout}] = builtin('subsref',f,s(2:end));
    else
      varargout{1} = f;
    end
  otherwise

    [varargout{1:nargout}] = builtin('subsref',f,s);

end
end


function [varargout] = funname(varargin)

% WRITE_CTF_SHM writes metainformation and data as a packet to shared memory.
% This function can be used for real-time processing of data while it is
% being acquired.
%
% Use as
%   write_ctf_shm(msgType, msgId, sampleNumber, numSamples, numChannels, data);
%
% See also READ_CTF_SHM

% Copyright (C) 2007, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
% for the documentation and details.
%
%    FieldTrip is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    FieldTrip is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id: write_ctf_shm.m 2885 2011-02-16 09:41:58Z roboos $

% remember the original working directory
pwdir = pwd;

% determine the name and full path of this function
funname = mfilename('fullpath');
mexsrc  = [funname '.c'];
[mexdir, mexname] = fileparts(funname);

try
  % try to compile the mex file on the fly
  warning('trying to compile MEX file from %s', mexsrc);
  cd(mexdir);
  mex(mexsrc);
  cd(pwdir);
  success = true;

catch
  % compilation failed
  disp(lasterr);
  error('could not locate MEX file for %s', mexname);
  cd(pwdir);
  success = false;
end

if success
  % execute the mex file that was juist created
  funname   = mfilename;
  funhandle = str2func(funname);
  [varargout{1:nargout}] = funhandle(varargin{:});
end


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

    % Last Modified by GUIDE v2.5 25-Jan-2020 16:16:14

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

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

    centerUIFigure(hObject);

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

    handles = populateGUI(lvdData, handles);

    % Update handles structure
    guidata(hObject, handles);

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

function handles = populateGUI(lvdData, handles)
    lvdOpt = lvdData.optimizer;
    optAlgoStrs = LvdOptimizerAlgoEnum.getListBoxStr();
    gradAlgoStrs = LvdOptimizerGradientCalculationAlgoEnum.getListBoxStr();

    handles.gradientSelCombo.String = gradAlgoStrs;
    handles.gradientSelCombo.Value = LvdOptimizerGradientCalculationAlgoEnum.getIndForName(lvdOpt.gradAlgo.name);
    gradientSelCombo_Callback(handles.gradientSelCombo, [], handles);

    handles.optimizerSelectionCombo.String = optAlgoStrs;
    handles.optimizerSelectionCombo.Value = LvdOptimizerAlgoEnum.getIndForName(lvdOpt.optAlgo.name);
    optimizerSelectionCombo_Callback(handles.optimizerSelectionCombo, [], handles);

    % --- Outputs from this function are returned to the command line.
function varargout = lvd_OptimizerSelectionGUI_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
        lvdData = getappdata(handles.lvd_OptimizerSelectionGUI, 'lvdData');
        lvdOpt = lvdData.optimizer;

        gradAlgoStrs = LvdOptimizerGradientCalculationAlgoEnum.getListBoxStr();
        optGradInd = handles.gradientSelCombo.Value;
        gradAlgoEnum = LvdOptimizerGradientCalculationAlgoEnum.getEnumForListboxStr(gradAlgoStrs{optGradInd});
        lvdOpt.gradAlgo = gradAlgoEnum;

        optAlgoStrs = LvdOptimizerAlgoEnum.getListBoxStr();
        optAlgoInd = handles.optimizerSelectionCombo.Value;
        optAlgoEnum = LvdOptimizerAlgoEnum.getEnumForListboxStr(optAlgoStrs{optAlgoInd});
        lvdOpt.optAlgo = optAlgoEnum;

        varargout{1} = [];
        close(handles.lvd_OptimizerSelectionGUI);
    end

    % --- Executes on selection change in optimizerSelectionCombo.
function optimizerSelectionCombo_Callback(hObject, eventdata, handles)
    % hObject    handle to optimizerSelectionCombo (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 optimizerSelectionCombo contents as cell array
    %        contents{get(hObject,'Value')} returns selected item from optimizerSelectionCombo
    optAlgoStrs = LvdOptimizerAlgoEnum.getListBoxStr();
    enum = LvdOptimizerAlgoEnum.getEnumForListboxStr(optAlgoStrs{get(hObject,'Value')});
    handles.optimAlgDescTextLbl.String = enum.desc;

    if(enum.reqGrad)
        handles.gradientSelCombo.Enable = 'on';
        handles.editSelectedGradAlgoOptions.Enable = 'on';
        gradientSelCombo_Callback(handles.gradientSelCombo, [], handles);
    else
        handles.gradientSelCombo.Enable = 'off';
        handles.editSelectedGradAlgoOptions.Enable = 'off';
    end

    % --- Executes during object creation, after setting all properties.
function optimizerSelectionCombo_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to optimizerSelectionCombo (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 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)
    uiresume(handles.lvd_OptimizerSelectionGUI);

    % --- Executes on selection change in gradientSelCombo.
function gradientSelCombo_Callback(hObject, eventdata, handles)
    % hObject    handle to gradientSelCombo (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 gradientSelCombo contents as cell array
    %        contents{get(hObject,'Value')} returns selected item from gradientSelCombo
    gradAlgoStrs = LvdOptimizerGradientCalculationAlgoEnum.getListBoxStr();
    enum = LvdOptimizerGradientCalculationAlgoEnum.getEnumForListboxStr(gradAlgoStrs{get(hObject,'Value')});
    handles.optimGradAlgDescTextLbl.String = enum.desc;

    if(enum.disableOptions)
        handles.editSelectedGradAlgoOptions.Enable = 'off';
    else
        handles.editSelectedGradAlgoOptions.Enable = 'on';
    end

    % --- Executes during object creation, after setting all properties.
function gradientSelCombo_CreateFcn(hObject, eventdata, handles)
    % hObject    handle to gradientSelCombo (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 editSelectedGradAlgoOptions.
function editSelectedGradAlgoOptions_Callback(hObject, eventdata, handles)
    % hObject    handle to editSelectedGradAlgoOptions (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_OptimizerSelectionGUI, 'lvdData');

    gradAlgoStrs = LvdOptimizerGradientCalculationAlgoEnum.getListBoxStr();
    gradAlgoInd = handles.gradientSelCombo.Value;
    gradAlgoEnum = LvdOptimizerGradientCalculationAlgoEnum.getEnumForListboxStr(gradAlgoStrs{gradAlgoInd});

    lvdOpt = lvdData.optimizer;
    gradAlgo = lvdOpt.getGradAlgoForEnum(gradAlgoEnum);
    gradAlgo.openOptionsDialog();

    % --- Executes on button press in editSelectedOptimizerOptionsButton.
function editSelectedOptimizerOptionsButton_Callback(hObject, eventdata, handles)
    % hObject    handle to editSelectedOptimizerOptionsButton (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_OptimizerSelectionGUI, 'lvdData');

    optAlgoStrs = LvdOptimizerAlgoEnum.getListBoxStr();
    optAlgoInd = handles.optimizerSelectionCombo.Value;
    optAlgoEnum = LvdOptimizerAlgoEnum.getEnumForListboxStr(optAlgoStrs{optAlgoInd});

    lvdOpt = lvdData.optimizer;
    optimizer = lvdOpt.getOptimizerForEnum(optAlgoEnum);
    optimizer.openOptionsDialog();


function [ status ] = testGraphical( varargin )
%TESTGRAPHICAL Runs the M2T test suite to produce graphical output
%
% This is quite a thin wrapper around testMatlab2tikz to run the test suite to
% produce a PDF side-by-side report.
%
% Its allowed arguments are the same as those of testMatlab2tikz.
%
% Usage:
%
%     status = testGraphical(...) % gives programmatical access to the data
%
%     testGraphical(...); % automatically invokes makeLatexReport afterwards
%
% See also: testMatlab2tikz, testHeadless, makeLatexReport

    [state] = initializeGlobalState();
    finally_restore_state = onCleanup(@() restoreGlobalState(state));

    [status, args] = testMatlab2tikz('actionsToExecute', @actionsToExecute, ...
                                     varargin{:});

    if nargout == 0
        makeLatexReport(status, args.output);
    end
end
% ==============================================================================
function status = actionsToExecute(status, ipp)
    status = execute_plot_stage(status, ipp);

    if status.skip
        return
    end

    status = execute_save_stage(status, ipp);
    status = execute_tikz_stage(status, ipp);
    %status = execute_hash_stage(status, ipp); %cannot work with files in
    %standalone mode!
    status = execute_type_stage(status, ipp);

    if ~status.closeall && ~isempty(status.plotStage.fig_handle)
        close(status.plotStage.fig_handle);
    else
        close all;
    end
end
% ==============================================================================


function ax = setAxis(fh, axis_id)
% Enabled a certain axis in the figure, update MATLAB curfigure status
% useful to reset the current axis in case of new plotting
%
% INPUT
%   fh       figurehandle
%   axis_id  number of the axis (1 is the first inserted)
%
% SYNTAX
%   setAxis(fh, axis_id)

%--- * --. --- --. .--. ... * ---------------------------------------------
%               ___ ___ ___
%     __ _ ___ / __| _ | __|
%    / _` / _ \ (_ |  _|__ \
%    \__, \___/\___|_| |___/
%    |___/                    v 1.0RC1
%
%--------------------------------------------------------------------------
%  Copyright (C) 2021 Geomatics Research & Development srl (GReD)
%  Written by: Giulio Tagliaferro
%  Contributors:     ...
%  A list of all the historical goGPS contributors is in CREDITS.nfo
%--------------------------------------------------------------------------
%
%   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/>.
%
%--------------------------------------------------------------------------
% 01100111 01101111 01000111 01010000 01010011
%--------------------------------------------------------------------------

    if not(isa(fh, 'matlab.ui.Figure'))
        axis_id = fh;
        fh = gcf;
    end
    set(0, 'CurrentFigure', fh);
    try
        ax = fh.Children(max(1, end + 1 - axis_id));
        subplot(ax);
    catch
        ax = axes();
    end
end


function varargout = legcoeffs(varargin) %#ok<STOUT>
%LEGCOEFFS   LEGCOEFFS does not support TRIGTECH objects.
%
% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% TODO: Add support for this.

error('CHEBFUN:TRIGTECH:legcoeffs:nosupport', ...
      'LEGCOEFFS does not support TRIGTECH objects.')

end


% OtTableBof Check whether the first record was read.
%
% Usage:
%    bof = OtTableBof(htable)

% 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-04-11 Created (Johan Meijdam, VORtech)

function bof = OtTableBof(htable)
   bof = Ot('table.bof', htable);
end


function planC = CERRImport_newplan(optName, archiveDir, saveFile)
%function planC = CERRImport_newplan(optName,archiveDir,saveDir)
%
%27 Oct 2006    KU   Modified CERRImport.m for import of plans to an existing study.
%
%
% 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/>.

global planC
global stateS

fname1 = '';

[fname1, pathname] = uigetfile('*.*','Select 0000 file to begin importing.');
if fname1==0;
    disp('RTOG scan aborted.');
    return
else
    archiveDir = pathname;
    if exist('optName')==0
        optName='CERROptions.m';
    end
   optS = opts4Exe(optName);
end

%Start diary and timer for import log.
startTime = now;
tmpFileName = tempname;
diary(tmpFileName);

%%%%Call the import tool: IMPORT occurs here.
    temp_planC = importRTOGDir_newplan(optS, archiveDir, fname1);
%%%%

%Check that there are plans in temp_planC.
if isempty(temp_planC{temp_planC{end}.dose}) ||...
        (isempty(temp_planC{temp_planC{end}.dose}(1).doseArray) && isempty(temp_planC{temp_planC{end}.dose}(1,end).doseArray))
    disp('No plans to import.');
    sentence1 = 'There are no plans to be imported.';
    Zmsgbox=msgbox(sentence1, 'modal');
    waitfor(Zmsgbox);
    clear temp_planC;
    return
end

nplans = 0;
for j = 1:length(temp_planC{temp_planC{end}.dose})
    nplans = nplans + 1;
    if ischar(temp_planC{temp_planC{end}.dose}(1,j).fractionGroupID)
        ID = temp_planC{temp_planC{end}.dose}(1,j).fractionGroupID;
    else
        ID = num2str(temp_planC{temp_planC{end}.dose}(1,j).fractionGroupID);
    end
    newPlanName = ID;

    %Check if plan is already in current study.
    match = 0;
    if length(planC{planC{end}.dose}) >=1
        for k=1:length(planC{planC{end}.dose})
            if isequal(temp_planC{temp_planC{end}.dose}(1,j).doseArray, planC{planC{end}.dose}(1,k).doseArray)
                match = 1;
                nplans = nplans - 1;
                disp(['Plan "', ID, '" already exists in the current study.']);
                disp(['Skipping import of plan "',  ID, '".']);
                sentence1 = (['Plan "', ID, '" is already in the current study. ',...
                    'It will not be imported.']);
                Zmsgbox=msgbox(sentence1, 'modal');
                waitfor(Zmsgbox);
            end
        end
    end

    if match ~= 1   %plan is not yet in current study
        % Check dose for duplicate fractionGroupID names.
        if length(planC{planC{end}.dose}) >=1
            n = 0;
            match = 1;
            while match == 1
                match = 0;
                for k=1:length(planC{planC{end}.dose})
                    if ischar(planC{planC{end}.dose}(1,k).fractionGroupID)
                        idString = planC{planC{end}.dose}(1,k).fractionGroupID;
                    else
                        idString = num2str(planC{planC{end}.dose}(1,k).fractionGroupID);
                    end

                    if strcmpi(idString, newPlanName)
                        match = 1;
                        n=n+1;
                        newPlanName = [ID,' (',num2str(n),')'];
                    end
                end
            end
            temp_planC{temp_planC{end}.dose}(1,j).fractionGroupID = newPlanName;
            if n >= 1
                disp(['A plan with the name "', ID, '" already exists in the current study.']);
                disp(['Changing new plan name to "',  newPlanName, '".']);
                sentence1 = (['A plan with the name "', ID, '" already exists in the current study. ',...
                            'Changing new plan name to "',  newPlanName, '".']);
                Zmsgbox=msgbox(sentence1, 'modal');
                beep
                waitfor(Zmsgbox);
            end

            % Check beam geometry for duplicate fractionGroupID names.
            if ~strcmpi(ID, newPlanName)
                for i=1:length(temp_planC{temp_planC{end}.beamGeometry})
                    if ischar(temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID)
                        tempID = temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID;
                    else
                        tempID = num2str(temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID);
                    end
                    if strcmpi(tempID, ID)
                        temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID = newPlanName;
                    end
                end
            end

            % Check DVH's for duplicate fractionIDOfOrigin names.
            if ~strcmpi(ID, newPlanName)
                for i=1:length(temp_planC{temp_planC{end}.DVH})
                    if ischar(temp_planC{temp_planC{end}.DVH}(1,i).fractionIDOfOrigin)
                        tempID = temp_planC{temp_planC{end}.DVH}(1,i).fractionIDOfOrigin;
                    else
                        tempID = num2str(temp_planC{temp_planC{end}.DVH}(1,i).fractionIDOfOrigin);
                    end
                    if strcmpi(tempID, ID)
                        temp_planC{temp_planC{end}.DVH}(1,i).fractionIDOfOrigin = newPlanName;
                    end
                end
            end
        end

        % Add associated scan and dose UID's to dose UID fields.
        scanUID = planC{planC{end}.scan}(1).scanUID;
        temp_planC{temp_planC{end}.dose}(1,j).assocScanUID = scanUID;
        temp_planC{temp_planC{end}.dose}(1,j).doseUID = createUID('dose');

        % Add new plan to planC.
        if isempty(planC{planC{end}.dose}) || isempty(planC{planC{end}.dose}(1,end).doseArray)
            planC{planC{end}.dose} = temp_planC{temp_planC{end}.dose}(1,j);
            ok = 0;
            for i=1:length(temp_planC{temp_planC{end}.beamGeometry})     %add beams
                if ischar(temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID)
                    tempID = temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID;
                else
                    tempID = num2str(temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID);
                end
                if strcmpi(tempID, newPlanName)
                    ok = ok+1;
                    if ok == 1
                        planC{planC{end}.beamGeometry} = temp_planC{temp_planC{end}.beamGeometry}(1,i);
                    else
                        planC{planC{end}.beamGeometry} = [planC{planC{end}.beamGeometry}, temp_planC{temp_planC{end}.beamGeometry}(1,i)];
                    end
                end
            end
        else
            if isfield(planC{planC{end}.dose}(1),'cachedMask')
                temp_planC{temp_planC{end}.dose}(1,j).cachedMask = [];
            end
            planC{planC{end}.dose} = dissimilarInsert(planC{planC{end}.dose}, temp_planC{temp_planC{end}.dose}(1,j));

            for i=1:length(temp_planC{temp_planC{end}.beamGeometry})
                if ischar(temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID)
                    tempID = temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID;
                else
                    tempID = num2str(temp_planC{temp_planC{end}.beamGeometry}(1,i).fractionGroupID);
                end
                if strcmpi(tempID, newPlanName)
                    planC{planC{end}.beamGeometry} = dissimilarInsert(planC{planC{end}.beamGeometry}, temp_planC{temp_planC{end}.beamGeometry}(1,i));
                end
            end
        end

    end
end

if nplans == 0
    disp('No plans to import.');
    sentence1 = 'No plans were found to import!';
    Zmsgbox=msgbox(sentence1, 'modal');
    beep
    waitfor(Zmsgbox);
    return
elseif length(planC{planC{end}.dose})>=1 && ~isempty(planC{planC{end}.dose}(1).doseArray)
    planC{planC{end}.dose}(1,end).doseNumber = length(planC{planC{end}.dose});

    %switch to new dose after a short pause.
    pause(.1);
    sliceCallBack('selectDose', num2str(planC{planC{end}.dose}(1,end).doseNumber));

    %switch to scan #1 if not already selected.
    sliceCallBack('selectScan', num2str(1));

    %Turn on dose and switch to colorwash if not already on.
    if stateS.doseToggle == -1
        stateS.doseToggle = - stateS.doseToggle;
        set(findobj('tag', 'doseToggle'), 'checked', 'on');
    end
    stateS.optS.dosePlotType = 'colorwash';
    stateS.doseChanged = 1;
    stateS.doseSetChanged = 1;
    stateS.doseDisplayChanged = 1;
    stateS.structsChanged = 1;
    sliceCallBack('refresh')

    sentence1 = horzcat('The current study has been updated with the new plan(s). ',...
        'The changes have not been saved.  Please remember to save changes ',...
        'before closing the study.');
    Zmsgbox=msgbox(sentence1, 'modal');
    beep
    waitfor(Zmsgbox);
end

%Stop diary and write it to planC.
diary off;
endTime = now;
logC = file2cell(tmpFileName);
delete(tmpFileName);
indexS = planC{end};

temp_planC{temp_planC{end}.importLog} = [];
temp_planC{temp_planC{end}.importLog}.importLog = logC;
temp_planC{temp_planC{end}.importLog}.startTime = datestr(startTime);
temp_planC{temp_planC{end}.importLog}.endTime = datestr(endTime);

planC{indexS.importLog} = [planC{indexS.importLog}, temp_planC{temp_planC{end}.importLog}];


function x = utl_prune_handles(x)
% Prune unreferenced workspace variables from anonymous functions in the given argument.
%
% In:
%   Data : an arbitrary data structure
%
% Out:
%   Data : the data structure with hidden references in anonymous functions removed
%
%                                Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                                2011-11-23

if iscell(x)
    % recurse into cell arrays...
    for k=1:numel(x)
        x{k} = utl_prune_handles(x{k}); end
elseif isstruct(x)
    % recurse into structs...
    for f=fieldnames(x)'
        if ~isempty(x)
            [x.(f{1})] = celldeal(utl_prune_handles({x.(f{1})})); end
    end
elseif isa(x,'function_handle')
    % inspect function handles
    f = char(x);
    if f(1) == '@'
        % anonymous function: take apart...
        parts = functions(x);
        % ... and put back together
        x = make_function(f,parts.workspace{1});
    end
end

% create a function handle
function f = make_function(decl__,workspace__)
% create workspace
for fn__=fieldnames(workspace__)'
    eval([fn__{1} ' = workspace__.(fn__{1}) ;']); end
clear workspace__ fn__;
% evaluate declaration
f = eval(decl__);


%MTIMES Datafile overload


function my_call(value)
fprintf('%d \n', value); % might check here whether this is a label at all
                         % since we get here by clicking on ANY text in figure


function plugin = plugin_getweb(type, pluginOri, mode)

if nargin < 1, help plugin_getweb; return; end;
if nargin < 2, pluginOri = []; end;
if nargin < 3, mode = 'merge'; end; % 'merge' or 'newlist'

% convert plugin list format if necessary
if isfield(pluginOri, 'plugin'), pluginOri = plugin_convert(pluginOri); end;

try
    disp( [ 'Retreiving URL with ' type ' extensions...' ] );
    if strcmpi(type, 'import')
        [tmp status] = plugin_urlread('http://sccn.ucsd.edu/wiki/Plugin_list_import');
    else
        [tmp status] = plugin_urlread('http://sccn.ucsd.edu/wiki/Plugin_list_process');
    end;
catch,
    error('Cannot connect to the Internet to retrieve extension list');
end;

% retreiving download statistics
try
    disp( [ 'Retreiving download statistics...' ] );
    [stats status] = plugin_urlread('http://sccn.ucsd.edu/eeglab/plugin_uploader/plugin_getcountall.php');
    stats = textscan(stats, '%s%d%s%s');
catch,
    stats = {};
    disp('Cannot connect to the Internet to retrieve statistics for extensions');
end;

if status == 0
    error('Cannot connect to the Internet to retrieve extension list');
end;

% parse the web page
% ------------------
try
    plugin = parseTable(tmp);
catch
    error('Cannot parse extension list - please contact eeglab@sccn.ucsd.edu');
end;

% find correspondance with plugin list
% ------------------------------------
if ~isempty(pluginOri)
     currentNames = lower({ pluginOri.name });
else currentNames = {};
end;
allMatch = [];
for iRow = 1:length(plugin)
    % fix links
    if isfield(plugin, 'zip'), plugin(iRow).zip = strrep(plugin(iRow).zip, '&', '&'); end;

    % get number of downloads
    if ~isempty(stats)
        indMatch = strmatch(plugin(iRow).name, stats{1}, 'exact');
        if ~isempty(indMatch)
             plugin(iRow).downloads = stats{2}(indMatch(1));
             if length(stats) > 2 && ~isempty(stats{3}{indMatch(1)})
                 plugin(iRow).version   = stats{3}{indMatch(1)};
                 plugin(iRow).zip       = stats{4}{indMatch(1)};
             end;
        else plugin(iRow).downloads = 0;
        end;
    else plugin(iRow).downloads = 0;
    end;

    % match with existiting plugins
    indMatch = strmatch(lower(plugin(iRow).name), currentNames, 'exact');
    if isempty(indMatch)
        plugin(iRow).currentversion  = '-';
        plugin(iRow).installed       = 0;
        plugin(iRow).installorupdate = 1;
        plugin(iRow).status          = 'notinstalled';
    else
        if length(indMatch) > 1
            disp([ 'Warning: duplicate extension ' plugin(iRow).name ' instaled' ]);
        end;
        plugin(iRow).currentversion = pluginOri(indMatch).currentversion;
        plugin(iRow).foldername     = pluginOri(indMatch).foldername;
        plugin(iRow).status         = pluginOri(indMatch).status;
        plugin(iRow).installed      = 1;
        if strcmpi(plugin(iRow).currentversion, plugin(iRow).version)
            plugin(iRow).installorupdate = 0;
        else
            plugin(iRow).installorupdate = 1;
        end;
        allMatch = [ allMatch indMatch(:)' ];
    end;

end;

% put all the installed plugins first
% -----------------------------------
if ~isempty(plugin)
    [tmp reorder] = sort([plugin.installed], 'descend');
    plugin = plugin(reorder);
%     plugin(1).currentversion  = '0.9';
%     plugin(1).version         = '1';
%     plugin(1).foldername      = 'test';
%     plugin(1).installed       = 1;
%     plugin(1).installorupdate = 1;
%     plugin(1).description     = 'test';
%     plugin(1).webdoc          = 'test';
%     plugin(1).name            = 'test';
end;

if strcmpi(mode, 'merge') && ~isempty(pluginOri)
    indices = setdiff([1:length(pluginOri)], allMatch);
    fields  = fieldnames(pluginOri);
    lenPlugin = length(plugin);

    for indPlugin = 1:length(indices)
        for indField = 1:length(fields)
            value  = getfield(pluginOri, { indices(indPlugin)  }, fields{ indField });
            plugin = setfield(plugin   , { lenPlugin+indPlugin }, fields{ indField }, value);
        end;
    end;
end;

% parse the web table
% ===================
function plugin = parseTable(tmp);

plugin = [];
if isempty(tmp), return; end;

% get table content
% -----------------
tableBeg = findstr('Plug-in name', tmp);
tableEnd = findstr('
', tmp(tableBeg:end));
tableContent = tmp(tableBeg:tableBeg+tableEnd-2);
endFirstLine = findstr('
', tableContent);
tableContent = tableContent(endFirstLine(1)+5:end);

% parse table entries
% -------------------
posBegRow = findstr('
' , tableContent);
posEndRow = findstr('
', tableContent);
if length(posBegRow) ~= length(posEndRow) || isempty(posBegRow)
    error('Cannot connect to the Internet to retrieve plugin list');
end;
for iRow = 1:length(posBegRow)
    rowContent = tableContent(posBegRow(iRow)+4:posEndRow(iRow)-1);
    posBegCol = findstr('' , rowContent);
    posEndCol = findstr('	', rowContent);
    for iCol = 1:length(posBegCol)
        table{iRow,iCol} = rowContent(posBegCol(iCol)+4:posEndCol(iCol)-1);
    end;
end;

%% extract zip link and plugin name from first column
% --------------------------------------------------
%href="http://www.unicog.org/pm/uploads/MEG/ADJUST_PLUGIN.zip" class="external text" title="http://www.unicog.org/pm/uploads/MEG/ADJUST_PLUGIN.zip" rel="nofollow">ADJUST PLUGIN</td
for iRow = 1:size(table,1)

    % get link
    [plugin(iRow).name plugin(iRow).webdoc] = parsehttplink(table{iRow,1});
    plugin(iRow).version = table{iRow,2};
    tmp = deblank(table{iRow,3}(end:-1:1));
    plugin(iRow).description = deblank(tmp(end:-1:1));
    [tmp plugin(iRow).zip] = parsehttplink(table{iRow,4});

end;

function [txt link] = parsehttplink(currentRow)
    openTag  = find(currentRow == '<');
    closeTag = find(currentRow == '>');
    if isempty(openTag)
        link = '';
        txt = currentRow;
    else
        % parse link
        link = currentRow(openTag(1)+1:closeTag(1)-1);
        hrefpos = findstr('href', link);
        link = link(hrefpos:end);
        quoteInd = find(link == '"');
        link = link(quoteInd(1)+1:quoteInd(2)-1);

        for iTag = length(openTag):-1:1
            currentRow(openTag(iTag):closeTag(iTag)) = [];
        end;
        txt = currentRow;
    end;


function Z=setoperatorname(Z,name)

Z.extra.opname=name;


classdef GemPanel < GemUserInterfaceObject
    % GemPanel GEM class for a panel
    %
    %     Licence
    %     -------
    %     Part of GEM. https://github.com/tomdoel/gem
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties (Access = protected)
        BorderAxes
        InnerPosition
    end

    properties
        BackgroundColour
    end

    properties (SetObservable)
        BorderColour
    end

    properties (Dependent)
        LeftBorder
        RightBorder
        TopBorder
        BottomBorder
    end

    methods
        function obj = GemPanel(parent_handle)
            obj = obj@GemUserInterfaceObject(parent_handle);
            obj.BackgroundColour = obj.StyleSheet.BackgroundColour;
            obj.AddPostSetListener(obj, 'BorderColour', @obj.BorderColourChangedCallback);
        end

        function CreateGuiComponent(obj, position)
            obj.GraphicalComponentHandle = uipanel('Parent', obj.Parent.GetContainerHandle, 'BorderType', 'none', 'Units', 'pixels', ...
                'BackgroundColor', obj.BackgroundColour, 'ForegroundColor', obj.StyleSheet.TextPrimaryColour, 'ResizeFcn', '', 'Position', position);
        end

        function Resize(obj, position)
            Resize@GemUserInterfaceObject(obj, position);

            if ~isempty(obj.BorderAxes)
                obj.BorderAxes.Resize([1, 1, position(3), position(4)]);
            end

            inner_position = [1, 1, position(3), position(4)];

            if obj.LeftBorder
                inner_position(1) = inner_position(1) + 1;
                inner_position(3) = inner_position(3) - 1;
            end
            if obj.RightBorder
                inner_position(3) = inner_position(3) - 1;
            end
            if obj.TopBorder
                % FIXME: -2 instead of -1 to ensure top line is visible
                inner_position(4) = inner_position(4) - 2;
            end
            if obj.BottomBorder
                inner_position(2) = inner_position(2) + 1;
                inner_position(4) = inner_position(4) - 1;
            end

            obj.InnerPosition = inner_position;
        end

        function inner_position = GetInnerPosition(obj, inner_position)
            % Gets the position minus any borders
            if obj.LeftBorder
                inner_position(1) = inner_position(1) + 1;
                inner_position(3) = inner_position(3) - 1;
            end
            if obj.RightBorder
                inner_position(3) = inner_position(3) - 1;
            end
            if obj.TopBorder
                % FIXME: -2 instead of -1 to ensure top line is visible
                inner_position(4) = inner_position(4) - 2;
            end
            if obj.BottomBorder
                inner_position(2) = inner_position(2) + 1;
                inner_position(4) = inner_position(4) - 1;
            end
        end

        function set.LeftBorder(obj, border)
            if border
                obj.lazyCreateBorderAxes();
            end
            if ~isempty(obj.BorderAxes)
                obj.BorderAxes.LeftLine = border;
            end
        end

        function border = get.LeftBorder(obj)
            if isempty(obj.BorderAxes)
                border = false;
            else
                border = obj.BorderAxes.LeftLine;
            end
        end
        function set.RightBorder(obj, border)
            if border
                obj.lazyCreateBorderAxes();
            end
            if ~isempty(obj.BorderAxes)
                obj.BorderAxes.RightLine = border;
            end
        end

        function border = get.RightBorder(obj)
            if isempty(obj.BorderAxes)
                border = false;
            else
                border = obj.BorderAxes.RightLine;
            end
        end
        function set.TopBorder(obj, border)
            if border
                obj.lazyCreateBorderAxes();
            end
            if ~isempty(obj.BorderAxes)
                obj.BorderAxes.TopLine = border;
            end
        end

        function border = get.TopBorder(obj)
            if isempty(obj.BorderAxes)
                border = false;
            else
                border = obj.BorderAxes.TopLine;
            end
        end
        function set.BottomBorder(obj, border)
            if border
                obj.lazyCreateBorderAxes();
            end
            if ~isempty(obj.BorderAxes)
                obj.BorderAxes.BottomLine = border;
            end
        end

        function border = get.BottomBorder(obj)
            if isempty(obj.BorderAxes)
                border = false;
            else
                border = obj.BorderAxes.BottomLine;
            end
        end
    end

    methods (Access = protected)
        function BorderColourChangedCallback(obj, ~, ~, ~)
            if ~isempty(obj.BorderAxes)
                obj.BorderAxes.LineColour = obj.BorderColour;
            end
        end

        function lazyCreateBorderAxes(obj)
            if isempty(obj.BorderAxes)
                obj.BorderAxes = GemLineAxes(obj);
                if ~isempty(obj.BorderColour)
                    obj.BorderAxes.LineColour = obj.BorderColour;
                end
                obj.AddChild(obj.BorderAxes);
            end
        end

    end

end


% OtTableLast Move to the last record of the table.
%
% Usage:
%    OtTableLast(htable)

% 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-04-11 Created (Johan Meijdam, VORtech)

function iret = OtTableLast(htable)
   iret = Ot('table.last', htable);
end


function display(sVF,varargin)
% standard output

displayClass(sVF,inputname(1),varargin{:});

if length(sVF) > 1, disp([' size: ' size2str(sVF)]); end

end