classdef plotlyfig < handle

    %----CLASS PROPERTIES----%
    properties
        data; % data of the plot
        layout;  % layout of the plot
        url; % url response of making post request
        error; % error response of making post request
        warning; % warning response of making post request
        message; % message response of making post request

    end

    properties (SetObservable)
        UserData;% credentials/configuration/verbose
        PlotOptions; % filename,fileopt,world_readable
    end

    properties (Hidden = true)
        PlotlyDefaults; % plotly specific conversion defualts
        State; % state of plot (FIGURE/AXIS/PLOTS)
    end

    properties (Access = private)
        PlotlyReference; % load the plotly reference
        InitialState; % inital userdata
    end

    %----CLASS METHODS----%
    methods

        %----CONSTRUCTOR---%
        function obj = plotlyfig(varargin)

            %-Core-%
            obj.data = {};
            obj.layout = struct();
            obj.url = '';

            %-UserData-%
            try
                [obj.UserData.Username,...
                    obj.UserData.ApiKey,...
                    obj.UserData.PlotlyDomain] = signin;
            catch
                errkey = 'plotlyfigConstructor:notSignedIn';
                error(errkey, plotlymsg(errkey));
            end

            obj.UserData.Verbose = true;

            %-PlotOptions-%
            obj.PlotOptions.CleanFeedTitle = true;
            obj.PlotOptions.FileName = '';
            obj.PlotOptions.FileOpt = 'new';
            obj.PlotOptions.WorldReadable = true;
            obj.PlotOptions.ShowURL = true;
            obj.PlotOptions.OpenURL = true;
            obj.PlotOptions.Strip = true;
            obj.PlotOptions.Visible = 'on';
            obj.PlotOptions.TriangulatePatch = false;

            % offline options
            obj.PlotOptions.Offline = false;
            obj.PlotOptions.ShowLinkText = true;
            obj.PlotOptions.LinkText = obj.get_link_text;
            obj.PlotOptions.IncludePlotlyjs = true;

            %-PlotlyDefaults-%
            obj.PlotlyDefaults.MinTitleMargin = 80;
            obj.PlotlyDefaults.TitleHeight = 0.01;
            obj.PlotlyDefaults.TitleFontSizeIncrease = 40;
            obj.PlotlyDefaults.FigureIncreaseFactor = 1.5;
            obj.PlotlyDefaults.AxisLineIncreaseFactor = 1.5;
            obj.PlotlyDefaults.MarginPad = 0;
            obj.PlotlyDefaults.MaxTickLength = 20;
            obj.PlotlyDefaults.ExponentFormat = 'none';
            obj.PlotlyDefaults.ErrorbarWidth = 6;
            obj.PlotlyDefaults.ShowBaselineLegend = false;
            obj.PlotlyDefaults.Bargap = 0;
            obj.PlotlyDefaults.CaptionMarginIncreaseFactor = 1.2;
            obj.PlotlyDefaults.MinCaptionMargin = 80;

            %-State-%
            obj.State.Figure = [];
            obj.State.Axis = [];
            obj.State.Plot = [];
            obj.State.Text = [];
            obj.State.Legend = [];
            obj.State.Colorbar = [];

            % figure object management
            obj.State.Figure.NumAxes = 0;
            obj.State.Figure.NumPlots = 0;
            obj.State.Figure.NumLegends = 0;
            obj.State.Figure.NumColorbars = 0;
            obj.State.Figure.NumTexts = 0;

            %-PlotlyReference-%
            obj.PlotlyReference = [];

            %-InitialState-%
            obj.InitialState.Username = obj.UserData.Username;
            obj.InitialState.ApiKey = obj.UserData.ApiKey;
            obj.InitialState.PlotlyDomain = obj.UserData.PlotlyDomain;

            % initialize figure handle
            fig_han = [];

            % initialize autoupdate key
            updatekey = false;

            % parse inputs
            switch nargin

                case 0
                case 1
                    % check for figure handle
                    if ishandle(varargin{1})
                        if strcmp(get(varargin{1},'type'),'figure')
                            fig_han = varargin{1};
                            updatekey = true;
                        end
                    else
                        errkey = 'plotlyfigConstructor:invalidInputs';
                        error(errkey , plotlymsg(errkey));
                    end

                otherwise

                    % check for figure handle
                    if ishandle(varargin{1})
                        if strcmp(get(varargin{1},'type'),'figure')
                            fig_han = varargin{1};
                            updatekey = true;
                            parseinit = 2;
                        end
                    else
                        parseinit = 1;
                    end

                    % check for proper property/value structure
                    if mod(length(parseinit:nargin),2) ~= 0
                        errkey = 'plotlyfigConstructor:invalidInputs';
                        error(errkey , plotlymsg(errkey));
                    end

                    % parse property/values
                    for a = parseinit:2:nargin
                        if(strcmpi(varargin{a},'filename'))
                            obj.PlotOptions.FileName = varargin{a+1};
                            % overwrite if filename provided
                            obj.PlotOptions.FileOpt = 'overwrite';
                        end
                        if(strcmpi(varargin{a},'fileopt'))
                            obj.PlotOptions.FileOpt = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'world_readable'))
                            obj.PlotOptions.WorldReadable = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'link'))
                            obj.PlotOptions.ShowURL = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'open'))
                            obj.PlotOptions.OpenURL = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'strip'))
                            obj.PlotOptions.Strip = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'visible'))
                            obj.PlotOptions.Visible = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'offline'))
                            obj.PlotOptions.Offline = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'showlink'))
                            obj.PlotOptions.ShowLinkText = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'linktext'))
                            obj.PlotOptions.LinkText = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'include_plotlyjs'))
                            obj.PlotOptions.IncludePlotlyjs = varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'layout'))
                            obj.layout= varargin{a+1};
                        end
                        if(strcmpi(varargin{a},'data'))
                            obj.data = varargin{a+1};
                        end
                    end
            end

            % create figure/axes if empty
            if isempty(fig_han)
                fig_han = figure;
                axes;
            end

            % plotly figure default style
            set(fig_han,'Name',obj.PlotOptions.FileName,'Color',[1 1 1],'NumberTitle','off', 'Visible', obj.PlotOptions.Visible);

            % figure state
            obj.State.Figure.Handle = fig_han;

            % update
            if updatekey
                obj.update;
            end

            % add figure listeners
            addlistener(obj.State.Figure.Handle,'Visible','PostSet',@(src,event)updateFigureVisible(obj,src,event));
            addlistener(obj.State.Figure.Handle,'Name','PostSet',@(src,event)updateFigureName(obj,src,event));

            % add plot options listeners
            addlistener(obj,'PlotOptions','PostSet',@(src,event)updatePlotOptions(obj,src,event));

            % add user data listeners
            addlistener(obj,'UserData','PostSet',@(src,event)updateUserData(obj,src,event));
        end

        %-------------------------USER METHODS----------------------------%

        %----GET OBJ.STATE.FIGURE.HANDLE ----%
        function plotlyFigureHandle = gpf(obj)
            plotlyFigureHandle = obj.State.Figure.Handle;
            set(0,'CurrentFigure', plotlyFigureHandle);
        end

        %----LOAD PLOTLY REFERENCE-----%
        function obj = loadplotlyref(obj)
            if isempty(obj.PlotlyReference)

                % plotly reference
                plotlyref = load('plotly_reference.mat');

                % update the PlotlyRef property
                obj.PlotlyReference = plotlyref.pr;
            end
        end

        %----KEEP THE MATLAB STYLE DEFAULTS----%
        function obj = revert(obj)

            % set the PlotOptions.Strip property
            obj.PlotOptions.Strip = false;

            % update the object
            obj.update;

        end

        %----STRIP THE STYLE DEFAULTS----%
        function obj = strip(obj)

            % set the PlotOptions.Strip property
            obj.PlotOptions.Strip = true;

            % load plotly reference
            obj.loadplotlyref;

            % strip the style keys from data
            for d = 1:length(obj.data)
                obj.data{d} = obj.stripkeys(obj.data{d}, obj.data{d}.type, 'style');
            end

            % strip the style keys from layout
            obj.layout = obj.stripkeys(obj.layout, 'layout', 'style');

        end

        %----GET THE FIELDS OF TYPE DATA----%
        function data = getdata(obj)

            % load plotly reference
            obj.loadplotlyref;

            % initialize output
            data = cell(1,length(obj.data));

            % remove style / plot_info types in data
            for d = 1:length(obj.data)
                data{d} = obj.stripkeys(obj.data{d}, obj.data{d}.type, {'style','plot_info'});
            end

        end

        %----VALIDATE THE DATA/LAYOUT KEYS----%
        function validate(obj)

            % load plotly reference
            obj.loadplotlyref;

            % validate data fields
            for d = 1:length(obj.data)
                obj.stripkeys(obj.data{d}, obj.data{d}.type, {'style','plot_info'});
            end

            % validate layout fields
            obj.stripkeys(obj.layout, 'layout', 'style');

        end

        %----GET PLOTLY FIGURE-----%
        function obj = download(obj, file_owner, file_id)
            plotlyfig = plotlygetfile(file_owner, file_id);
            obj.data = plotlyfig.data;
            obj.layout = plotlyfig.layout;
        end

        %---------------------STATIC IMAGE METHODS------------------------%

        %----SAVE STATIC PLOTLY IMAGE-----%
        function obj = saveas(obj, filename, varargin)

            % strip keys
            if obj.PlotOptions.Strip
                obj.strip;
            end

            % handle title
            if isempty(filename)
                handleFileName(obj);
                filename = obj.PlotOptions.FileName;
            end

            % create image figure
            imgfig.data = obj.data;
            imgfig.layout = obj.layout;

            % save image
            plotlygenimage(imgfig, filename, varargin{:});
        end

        %----SAVE STATIC JPEG IMAGE-----%
        function obj = jpeg(obj, filename)
            if nargin > 1
                obj.saveas(filename,'jpeg');
            else
                obj.saveas(obj.PlotOptions.FileName,'jpeg');
            end
        end

        %----SAVE STATIC PDF IMAGE-----%
        function obj = pdf(obj, filename)
            if nargin > 1
                obj.saveas(filename,'pdf');
            else
                obj.saveas(obj.PlotOptions.FileName,'pdf');
            end
        end

        %----SAVE STATIC PNG IMAGE-----%
        function obj = png(obj, filename)
            if nargin > 1
                obj.saveas(filename,'png');
            else
                obj.saveas(obj.PlotOptions.FileName,'png');
            end
        end

        %----SAVE STATIC SVG IMAGE-----%
        function obj = svg(obj, filename)
            if nargin > 1
                obj.saveas(filename,'svg');
            else
                obj.saveas(obj.PlotOptions.FileName,'svg');
            end
        end

        %----ADD A CUSTOM CAPTION-----%
        function obj = add_caption(obj, caption_string, varargin)

            caption.text = caption_string;

            % defaults
            caption.xref = 'paper';
            caption.yref = 'paper';
            caption.xanchor = 'left';
            caption.yanchor = 'top';
            caption.x = 0.1;
            caption.y = -0.05;
            caption.showarrow = false;

            % inject any custom annotation specs
            for n = 1:2:length(varargin)
                caption = setfield(caption, varargin{n}, varargin{n+1});
            end

            % adjust the bottom margin
            obj.layout.margin.b = max(obj.layout.margin.b, ...
                    obj.PlotlyDefaults.MinCaptionMargin);

            % add the new caption to the figure
            obj.State.Figure.NumTexts = obj.State.Figure.NumTexts + 1;
            obj.layout.annotations{obj.State.Figure.NumTexts} = caption;

            % update the figure state
            obj.State.Text(obj.State.Figure.NumTexts).Handle = NaN;
            obj.State.Text(obj.State.Figure.NumTexts).AssociatedAxis = gca;
            obj.State.Text(obj.State.Figure.NumTexts).Title = false;

        end

        %------------------------REST API CALL----------------------------%

        %----SEND PLOT REQUEST (NO UPDATE)----%
        function obj = plotly(obj)

            % strip keys
            if obj.PlotOptions.Strip
                obj.strip;
            end

            % validate keys
            validate(obj);

            % handle filename
            handleFileName(obj);

            % handle title (for feed)
            if obj.PlotOptions.CleanFeedTitle
                cleanFeedTitle(obj);
            end

            %args
            args.filename = obj.PlotOptions.FileName;
            args.fileopt = obj.PlotOptions.FileOpt;
            args.world_readable = obj.PlotOptions.WorldReadable;

            %layout
            args.layout = obj.layout;

            %send to plotly
            if ~obj.PlotOptions.Offline
                response = plotly(obj.data, args);

                %update response
                obj.url = response.url;
                obj.error = response.error;
                obj.warning = response.warning;
                obj.message = response.message;

                %open url in browser
                if obj.PlotOptions.OpenURL
                    web(response.url, '-browser');
                end
            else
                obj.url = plotlyoffline(obj);
                if obj.PlotOptions.OpenURL
                    web(obj.url, '-browser');
                end
            end

        end

        %-----------------------FIGURE CONVERSION-------------------------%

        %automatic figure conversion
        function obj = update(obj)

            % reset figure object count
            obj.State.Figure.NumAxes = 0;
            obj.State.Figure.NumPlots = 0;
            obj.State.Figure.NumLegends = 0;
            obj.State.Figure.NumColorbars = 0;
            obj.State.Figure.NumTexts = 0;

            % find axes of figure
            ax = findobj(obj.State.Figure.Handle,'Type','axes','-and',{'Tag','','-or','Tag','PlotMatrixBigAx','-or','Tag','PlotMatrixScatterAx'});
            obj.State.Figure.NumAxes = length(ax);

            % update number of annotations (one title per axis)
            obj.State.Figure.NumTexts = length(ax);

            % find children of figure axes
            for a = 1:length(ax)

                % reverse axes
                axrev = length(ax) - a + 1;

                % set axis handle field
                obj.State.Axis(a).Handle = ax(axrev);

                % add title
                obj.State.Text(a).Handle = get(ax(axrev),'Title');
                obj.State.Text(a).AssociatedAxis = handle(ax(axrev));
                obj.State.Text(a).Title = true;

                % find plots of figure
                plots = findobj(ax(axrev),'-not','Type','Text','-not','Type','axes','-depth',1);

                % add baseline objects
                baselines = findobj(ax(axrev),'-property','BaseLine');

                for np = 1:length(plots)

                    % reverse plots
                    nprev = length(plots) - np + 1;

                    % update the plot fields
                    obj.State.Figure.NumPlots = obj.State.Figure.NumPlots + 1;
                    obj.State.Plot(obj.State.Figure.NumPlots).Handle = handle(plots(nprev));
                    obj.State.Plot(obj.State.Figure.NumPlots).AssociatedAxis = handle(ax(axrev));
                    obj.State.Plot(obj.State.Figure.NumPlots).Class = getGraphClass(plots(nprev));
                end

                % find text of figure
                texts = findobj(ax(axrev),'Type','text','-depth',1);

                for t = 1:length(texts)
                    obj.State.Text(obj.State.Figure.NumTexts + t).Handle = handle(texts(t));
                    obj.State.Text(obj.State.Figure.NumTexts + t).Title = false;
                    obj.State.Text(obj.State.Figure.NumTexts + t).AssociatedAxis = handle(ax(axrev));
                end

                % update number of annotations
                obj.State.Figure.NumTexts = obj.State.Figure.NumTexts + length(texts);

            end

            % find legends of figure
            if isHG2
                legs = findobj(obj.State.Figure.Handle,'Type','Legend');
            else
                legs = findobj(obj.State.Figure.Handle,'Type','axes','-and','Tag','legend');
            end

            obj.State.Figure.NumLegends = length(legs);

            for g = 1:length(legs)
                obj.State.Legend(g).Handle = handle(legs(g));

                % find associated axis
                legendAxis = findLegendAxis(obj, handle(legs(g)));

                % update colorbar associated axis
                obj.State.Legend(g).AssociatedAxis = legendAxis;
            end

            % find colorbar of figure
            if isHG2
                cols = findobj(obj.State.Figure.Handle,'Type','Colorbar');
            else
                cols = findobj(obj.State.Figure.Handle,'Type','axes','-and','Tag','Colorbar');
            end

            obj.State.Figure.NumColorbars = length(cols);

            for c = 1:length(cols)

                % update colorbar handle
                obj.State.Colorbar(c).Handle = handle(cols(c));

                % find associated axis
                colorbarAxis = findColorbarAxis(obj, handle(cols(c)));

                % update colorbar associated axis
                obj.State.Colorbar(c).AssociatedAxis = colorbarAxis;

            end

            %--------------------UPDATE PLOTLY FIGURE---------------------%

            % reset dataget(obj.State.Figure.Handle,'Children')
            obj.data = {};

            % reset layout
            obj.layout = struct();

            % update figure
            updateFigure(obj);

            % update axes
            for n = 1:obj.State.Figure.NumAxes
                updateAxis(obj,n);
            end

            % update plots
            for n = 1:obj.State.Figure.NumPlots
                updateData(obj,n);
            end

            % update annotations
            for n = 1:obj.State.Figure.NumTexts
                updateAnnotation(obj,n);
            end

            % update legends
            for n = 1:obj.State.Figure.NumLegends
                updateLegend(obj,n);
            end

            % update colorbars
            for n = 1:obj.State.Figure.NumColorbars
                updateColorbar(obj,n);
            end

        end

        %----------------------EXTRACT PLOTLY INDICES---------------------%

        %----GET CURRENT AXIS INDEX ----%
        function currentAxisIndex = getAxisIndex(obj,axishan)
            currentAxisIndex = find(arrayfun(@(x)(eq(x.Handle,axishan)),obj.State.Axis));
        end

        %----GET CURRENT DATA INDEX ----%
        function currentDataIndex = getDataIndex(obj,plothan)
            currentDataIndex = find(arrayfun(@(x)(eq(x.Handle,plothan)),obj.State.Plot));
        end

        %----GET CURRENT ANNOTATION INDEX ----%
        function currentAnnotationIndex = getAnnotationIndex(obj,annothan)
            currentAnnotationIndex = find(arrayfun(@(x)(eq(x.Handle,annothan)),obj.State.Text));
        end

        %-------------------CALLBACK FUNCTIONS--------------------------%

        %----UPDATE FIGURE OPTIONS----%
        function obj = updateFigureVisible(obj,src,event)
            % update PlotOptions.Visible
            obj.PlotOptions.Visible = get(obj.State.Figure.Handle,'Visible');
        end

        function obj = updateFigureName(obj,src,event)
            % update PlotOptions.Name
            obj.PlotOptions.FileName = get(obj.State.Figure.Handle,'Name');
        end

        %----UPDATE PLOT OPTIONS----%
        function obj = updatePlotOptions(obj,src,event)
            if iscell(obj.PlotOptions.FileName)
                for i = 1 : numel(obj.PlotOptions.FileName)
                    obj.PlotOptions.FileName{i} = [obj.PlotOptions.FileName{i} ' - '];
                end
                obj.PlotOptions.FileName = cell2mat(obj.PlotOptions.FileName');
            end
            set(obj.State.Figure.Handle, 'Name', obj.PlotOptions.FileName, 'Visible', obj.PlotOptions.Visible);
        end

        %----UPDATE USER DATA----%
        function obj = updateUserData(obj,src,event)
            signin(obj.UserData.Username,...
                obj.UserData.ApiKey,...
                obj.UserData.PlotlyDomain);
        end

        %-------------------OVERLOADED FUNCTIONS--------------------------%

        %----PLOT FUNCTIONS----%
        function han = image(obj, varargin)
            %call image
            han = image(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = imagesc(obj, varargin)
            %call imagesc
            han = imagesc(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = line(obj, varargin)
            %call line
            han = line(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = patch(obj, varargin)
            %call patch
            han = patch(varargin{:});
            %update object
            obj.update;
        end

        function han = rectangle(obj, varargin)
            %call rectangle
            han = rectangle(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = area(obj,varargin)
            %call area
            han = area(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = bar(obj,varargin)
            %call bar
            han = bar(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = contour(obj,varargin)
            %call contour
            han = contour(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = plot(obj,varargin)
            %call plot
            han = plot(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = errorbar(obj,varargin)
            %call errorbar
            han = errorbar(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = quiver(obj,varargin)
            %call quiver
            han = quiver(varargin{:});
            %update object
            obj.update;
        end

        function han = scatter(obj, varargin)
            %call bar
            han = scatter(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = stairs(obj,varargin)
            %call stairs
            han = stairs(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = stem(obj,varargin)
            %call stem
            han = stem(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = boxplot(obj,varargin)
            %call boxplot
            han = boxplot(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function han = mesh(obj,varargin)
            %call mesh
            han = mesh(varargin{:});
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        function [y,t,x] = initial(obj,varargin)
            % plot initial
            initial(varargin{:});
            % call initial
            [y,t,x] = initial(varargin{:});
            % fake output by calling plot
            plot(t,y);
            %update object
            obj.update;
            %send to plotly
            obj.plotly;
        end

        %----OTHER----%
        function delete(obj)
            % reset persistent USERNAME, KEY, and DOMAIN
            % of signin to original state
            if isfield(obj.InitialState,'Username')
                signin(obj.InitialState.Username, ...
                    obj.InitialState.ApiKey,...
                    obj.InitialState.PlotlyDomain);
            end
        end
    end

    methods (Access=private)
        %----STRIP THE FIELDS OF A SPECIFIED KEY-----%
        function stripped = stripkeys(obj, fields, fieldname, key)

            %plorlt reference
            pr = obj.PlotlyReference;

            % initialize output
            stripped = fields;

            % get fieldnames
            fn = fieldnames(stripped);
            fnmod = fn;

            try
                for d = 1:length(fn);

                    % clean up axis keys
                    if any(strfind(fn{d},'xaxis')) || any(strfind(fn{d},'yaxis'))
                        fnmod{d} = fn{d}(1:length('_axis'));
                    end

                    % keys:(object, style, plot_info, data)
                    keytype = getfield(pr,fieldname,fnmod{d},'key_type');

                    % check for objects
                    if strcmp(keytype,'object')

                        % clean up font keys
                        if any(strfind(fn{d},'font'))
                            fnmod{d} = 'font';
                        end

                        % handle annotations
                        if strcmp(fn{d},'annotations')
                            annot = stripped.(fn{d});
                            fnmod{d} = 'annotation';
                            for a = 1:length(annot)
                                %recursive call to stripkeys
                                stripped.annotations{a} = obj.stripkeys(annot{a}, fnmod{d}, key);
                            end
                        else
                            %recursive call to stripkeys
                            stripped.(fn{d}) = obj.stripkeys(stripped.(fn{d}), fnmod{d}, key);
                        end

                        % look for desired key and strip if not an exception
                    elseif any(strcmp(keytype, key))
                        if ~isExceptionStrip(stripped,fn{d})
                            stripped = rmfield(stripped, fn{d});
                        end
                    end

                end

                %----CLEAN UP----%
                remfn = fieldnames(stripped);

                for n = 1:length(remfn)
                    if isstruct(stripped.(remfn{n}))
                        if isempty(fieldnames(stripped.(remfn{n})))
                            stripped = rmfield(stripped,remfn{n});
                        end
                    elseif isempty(stripped.(remfn{n}))
                        stripped = rmfield(stripped,remfn{n});
                    end
                end

                %---HANDLE ERRORS---%
            catch exception
                if obj.UserData.Verbose
                    % catch 3D output until integrated into graphref
                    if ~(strcmpi(fieldname,'surface') || strcmpi(fieldname,'scatter3d'))
                        fprintf(['\nWhoops! ' exception.message(1:end-1) ' in ' fieldname '\n\n']);
                    end
                end
            end
        end

        function link_text = get_link_text(obj)
           plotly_domain = obj.UserData.PlotlyDomain;
           link_domain = strrep(plotly_domain, 'https://', '');
           link_domain = strrep(link_domain, 'http://', '');
           link_text = ['Export to ' link_domain];
        end
    end
end


classdef PTKGui < MimGuiBase
    % PTKGui. The user interface for the TD Pulmonary Toolkit.
    %
    %     To start the user interface, run ptk.m.
    %
    %     You do not need to modify this file. To add new functionality, create
    %     new plguins in the Plugins and GuiPlugins folders.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2012.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    methods
        function obj = PTKGui(splash_screen)
            obj = obj@MimGuiBase(PTKAppDef, splash_screen);
        end
    end
end


function varargout = getpid(varargin)
% VL_GETPID Get MATLAB process ID
%   VL_GETPID() returns MATLAB process ID.
%
%   Algorithm::
%     VL_GETPID() returns the result of the getpid() system call on
%     UNIX-like operating systems and of GetCurrentProcessID() on
%     Windows.
%
%   See also: VL_HELP().
[varargout{1:nargout}] = vl_getpid(varargin{:});


function [success] = setupNwb(varargin)
	% Checks that NWB code is present and setup correctly.
	% Biafra Ahanonu
	% started: 2021.01.24 [14:31:24]
	% inputs
		%
	% outputs
		%

	% changelog
		% 2021.02.01 [15:19:40] - Update `_external_programs` to call ciapkg.getDirExternalPrograms() to standardize call across all functions.
		% 2021.03.26 [06:27:48] - Fix for options.defaultObjDir leading to incorrect NWB folder and cores not being generated.
	% TODO
		%

	[success] = ciapkg.nwb.setupNwb('passArgs', varargin);
end


function displayClass(obj,vName,varargin)

if check_option(varargin,'skipHeader'), return; end

disp(' ');

vName = get_option(varargin,'variableName',vName);
className = class(obj);
altName = get_option(varargin,'className',className);
scopes = get_option(varargin,'moreInfo');

str = [vName ' = ' doclink([className '.' className],altName)];
%str = [vName ' = <strong>' altName '</strong>'];

if ~isempty(scopes), str = [str,' (',scopes,')']; end

disp(str);

end


function output = base64decode(input)
%BASE64DECODE Decode Base64 string to a byte array.
%
%    output = base64decode(input)
%
% The function takes a Base64 string INPUT and returns a uint8 array
% OUTPUT. JAVA must be running to use this function. The result is always
% given as a 1-by-N array, and doesn't retrieve the original dimensions.
%
% See also base64encode

error(nargchk(1, 1, nargin));
error(javachk('jvm'));
if ischar(input), input = uint8(input); end

output = typecast(org.apache.commons.codec.binary.Base64.decodeBase64(input), 'uint8')';

end


function res = cache(this, stuff)
% Method for retrieving/putting stuff from/into the temporary cache
% FORMAT res = cache(obj, name)
% _______________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Stefan Kiebel
% $Id: cache.m 1373 2008-04-11 14:24:03Z spm $

if ischar(stuff)
    % assume this is a retrieval
        res = getcache(this, stuff);
else
    % assume this is a put
    name = inputname(2);
        res = setcache(this, name, stuff);
end

function res = getcache(this, stuff)
if isfield(this.cache, stuff)
    eval(['res = this.cache.' stuff ';']);
else
    res = [];
end

function this = setcache(this, name, stuff)
eval(['this.cache(1).' name ' = stuff;']);


function setL(OCP,L)
    OCP.L = L;
end


function GenerateSNIRFReaderWriter()

dirnameApp = [getAppDir(), 'DataTree/AcquiredData/'];
dirnameUtils = [getAppDir(), 'Utils/'];
dirnameInstall = fileparts(which('GenerateSNIRFReaderWriter.m'));
dirnameInstall(dirnameInstall=='\') = '/';
dirnameInstall(end+1)='/';

if exist([dirnameInstall, '/snirf_homer3'], 'dir')
    rmdir([dirnameInstall, '/snirf_homer3'], 's');
end
mkdir([dirnameInstall, '/snirf_homer3']);
mkdir([dirnameInstall, '/snirf_homer3/Utils']);

copyFiles([dirnameApp, 'DataFiles'],           [dirnameInstall, 'snirf_homer3/DataFiles']);
copyFiles([dirnameApp, 'Nirs'],                [dirnameInstall, 'snirf_homer3/Nirs']);
copyFiles([dirnameApp, 'Snirf'],               [dirnameInstall, 'snirf_homer3/Snirf']);
copyFiles([dirnameUtils, 'pretty_print_struct.m'], [dirnameInstall, 'snirf_homer3']);
copyFiles([dirnameUtils, 'isproperty.m'],      [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameUtils, 'iswholenum.m'],      [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameUtils, 'propnames.m'],       [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameUtils, 'CopyHandles.m'],     [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameUtils, 'strtrim_improve.m'], [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameUtils, 'fullpath.m'],        [dirnameInstall, 'snirf_homer3']);
copyFiles([dirnameUtils, 'filesepStandard.m'], [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameUtils, 'cell2str_new.m'], [dirnameInstall, 'snirf_homer3/Utils']);
copyFiles([dirnameApp, 'AcqDataClass.m'],      [dirnameInstall, 'snirf_homer3']);
copyFiles([dirnameApp, 'README.md'],           [dirnameInstall, 'snirf_homer3']);
copyFiles([dirnameUtils, 'cd_safe.m'],          [dirnameInstall, 'snirf_homer3']);
copyFiles([getAppDir(), 'str2cell.m'],          [dirnameInstall, 'snirf_homer3/Utils']);

% -------------------------------------------------------------------
function copyFiles(src, dst, type)

if ~exist('type', 'var')
    type = 'file';
end
if ~exist('errtype', 'var')
    errtype = 'Error';
end

try
    % If src is one of several possible filenames, then src to any one of
    % the existing files.
    if iscell(src)
        for ii=1:length(src)
            if ~isempty(dir(src{ii}))
                src = src{ii};
                break;
            end
        end
    end

    assert(logical(exist(src, type)));

    % Check if we need to untar the file
    k = findstr(src,'.tar.gz');
    if ~isempty(k)
        untar(src,fileparts(src));
        src = src(1:k-1);
    end

    % Copy file from source to destination folder
    fprintf('Copying %s to %s\n', src, dst);
    copyfile(src, dst);

catch ME

    printStack();
    if iscell(src)
        src = src{1};
    end
    MenuBox(sprintf('Error: Could not copy %s to installation folder.', src), {'OK'});
    pause(5);
    rethrow(ME);

end


function mff_setup

% MFF_SETUP ensures that the JVM is available and that the MFF java
% implementation is on the java classpath.

% this toolbox requires JAVA to be running and properly configured
if ~usejava('jvm')
  error('the EGI_MFF format requires that the java virtual machine is available, see http://www.fieldtriptoolbox.org/getting_started/egi')
end

% check that the java archive (jar file) is on the path
% the user can add it to the static path using classpath.txt
if ~(exist('com.egi.services.mff.api.MFFFactory', 'class')==8)
    jarpath = fullfile(fileparts(mfilename('fullpath')), 'java', 'M*.jar');
    jarlist = dir(jarpath);
    if size(jarlist, 1) == 1

        % Some MATLAB versions have a bug in javaclasspath that causes global
        % variables to be erased. Hence we keep a local copy and restore it afterwards.
        % See http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=2133

        var = whos('global');
        glob = [var.global];
        name = {var.name};
        name = name(glob);
        for i=1:length(name)
        eval(sprintf('global %s', name{i}));
        eval(sprintf('localcopy.%s = %s;', name{i}, name{i}));
        end

        % try to add it to the dynamic classpath
        jarpath = fullfile(fileparts(jarpath), jarlist(1).name);
        warning('adding %s to your Java path', jarpath);
        javaclasspath(jarpath);

        % The following pertains to http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=2133
        % also available as http://bit.ly/1o7QlRk, for which we cannot provide a solution.
        warning('In some versions of Matlab, javaclasspath clears all global variables due to a bug in MATLAB. Please execute %s.m immediately after starting MATLAB. See http://bit.ly/1o7QlRk', mfilename('fullpath'));

        % restore the global variables
        for i=1:length(name)
        eval(sprintf('global %s', name{i}));
        eval(sprintf('%s = localcopy.%s;', name{i}, name{i}));
        end
        clear localcopy

    else
        error('the EGI_MFF format requires one MFF .jar file on your classpath, see http://www.fieldtriptoolbox.org//getting_started/egi')
    end
end

% check once more, give an error if it still does not exist
if ~(exist('com.egi.services.mff.api.MFFFactory', 'class')==8)
  error('the EGI_MFF format requires one MFF .jar file on your classpath, see http://www.fieldtriptoolbox.org/getting_started/egi')
end


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

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

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

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

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

    populateGUI(handles, lvdData);

    % Update handles structure
    guidata(hObject, handles);

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

function populateGUI(handles, lvdData)
    set(handles.moveStageUpButton,'String','<html>↑');
    set(handles.moveStageDownButton,'String','<html>↓');
    set(handles.stagesListbox,'String',lvdData.launchVehicle.getStagesListBoxStr());

    numStages = length(get(handles.stagesListbox,'String'));
    if(numStages <= 1)
        handles.removeStageButton.Enable = 'off';
    end

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

% Get default command line output from handles structure
    if(isempty(handles))
        varargout{1} = [];
    else
        close(handles.lvd_EditStagesGUI);
    end

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

% --- Executes on selection change in stagesListbox.
function stagesListbox_Callback(hObject, eventdata, handles)
% hObject    handle to stagesListbox (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 stagesListbox contents as cell array
%        contents{get(hObject,'Value')} returns selected item from stagesListbox
    if(strcmpi(get(handles.lvd_EditStagesGUI,'SelectionType'),'open'))
        lvdData = getappdata(handles.lvd_EditStagesGUI,'lvdData');
        lv = lvdData.launchVehicle;

        selStage = get(handles.stagesListbox,'Value');
        stage = lv.getStageForInd(selStage);

        lvd_EditStageGUI(stage);
        set(handles.stagesListbox,'String',lvdData.launchVehicle.getStagesListBoxStr());
    end

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

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

% --- Executes on button press in addStageButton.
function addStageButton_Callback(hObject, eventdata, handles)
% hObject    handle to addStageButton (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_EditStagesGUI,'lvdData');
    lv = lvdData.launchVehicle;

    stage = LaunchVehicleStage(lv);
    useStage = lvd_EditStageGUI(stage);

    if(useStage)
        lv.addStage(stage);

        stageState = LaunchVehicleStageState(stage);
        lvdData.initStateModel.addStageState(stageState);

        set(handles.stagesListbox,'String',lvdData.launchVehicle.getStagesListBoxStr());

        handles.removeStageButton.Enable = 'on';
    end

% --- Executes on button press in removeStageButton.
function removeStageButton_Callback(hObject, eventdata, handles)
% hObject    handle to removeStageButton (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_EditStagesGUI,'lvdData');
    lv = lvdData.launchVehicle;

    selStage = get(handles.stagesListbox,'Value');
    stage = lv.getStageForInd(selStage);

    tf = stage.isStageAndChildrenInUse();

    if(tf == false)
        lvdData.initStateModel.removeStageStateForStage(stage);
        lv.removeStage(stage);

        set(handles.stagesListbox,'String',lvdData.launchVehicle.getStagesListBoxStr());

        numStages = lv.getNumStages();
        if(selStage > numStages)
            set(handles.stagesListbox,'Value',numStages);
        end

        if(numStages <= 1)
            handles.removeStageButton.Enable = 'off';
        end
    else
        warndlg(sprintf('Could not delete the stage "%s" because it (or an associated engine or tank) is in use as part of an event termination condition, event action, objective function, or constraint.  Remove all tanks and engines from the stage and remove the stage dependencies before attempting to delete the stage.', stage.name),'Cannot Delete Stage','modal');
    end

% --- Executes on button press in moveStageUpButton.
function moveStageUpButton_Callback(hObject, eventdata, handles)
% hObject    handle to moveStageUpButton (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_EditStagesGUI,'lvdData');
    lv = lvdData.launchVehicle;

    selStage = get(handles.stagesListbox,'Value');
    stage = lv.getStageForInd(selStage);

    lv.moveStageUp(stage);

    if(selStage>1)
        set(handles.stagesListbox,'Value',selStage-1);
    end

    set(handles.stagesListbox,'String',lvdData.launchVehicle.getStagesListBoxStr());

% --- Executes on button press in moveStageDownButton.
function moveStageDownButton_Callback(hObject, eventdata, handles)
% hObject    handle to moveStageDownButton (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_EditStagesGUI,'lvdData');
    lv = lvdData.launchVehicle;

    selStage = get(handles.stagesListbox,'Value');
    stage = lv.getStageForInd(selStage);

    lv.moveStageDown(stage);

    numStages = lv.getNumStages();
    if(selStage<numStages)
        set(handles.stagesListbox,'Value',selStage+1);
    end

    set(handles.stagesListbox,'String',lvdData.launchVehicle.getStagesListBoxStr());

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


classdef ( Hidden, Sealed ) PointerManager < handle
    %uix.PointerManager  Pointer manager

    %  Copyright 2016 The MathWorks, Inc.
    %  $Revision: 1435 $ $Date: 2016-11-17 17:50:34 +0000 (Thu, 17 Nov 2016) $

    properties( SetAccess = private )
        Figure % figure
    end

    properties( Access = private )
        Tokens % tokens
        Pointers % pointers
        NextToken % next token
        PointerListener % listener
    end

    methods( Access = private )

        function obj = PointerManager( figure )
            %uix.PointerManager  Create pointer manager
            %
            %  m = uix.PointerManager(f) creates a pointer manager for the
            %  figure f.

            obj.Figure = figure;
            obj.Tokens = 0;
            obj.Pointers = {figure.Pointer};
            obj.NextToken = 1;
            obj.PointerListener = event.proplistener( figure, ...
                findprop( figure, 'Pointer' ), 'PostSet', ...
                @obj.onPointerChanged );

        end % constructor

    end % structors

    methods( Access = private )

        function doSetPointer( obj, token, pointer )
            %doSetPointer  Set pointer
            %
            %  m.doSetPointer(t,p) sets the pointer to p with the token t.

            % Remove old entry
            tf = obj.Tokens == token;
            obj.Tokens(tf) = [];
            obj.Pointers(tf) = [];

            % Add new entry
            obj.Tokens(end+1) = token;
            obj.Pointers{end+1} = pointer;

            % Set pointer
            obj.PointerListener.Enabled = false;
            obj.Figure.Pointer = pointer;
            obj.PointerListener.Enabled = true;

        end % doSetPointer

        function doUnsetPointer( obj, token )
            %doUnsetPointer  Unset pointer
            %
            %  m.doUnsetPointer(s) unsets the pointer with the token t.

            % Remove old entry
            tf = obj.Tokens == token;
            obj.Tokens(tf) = [];
            obj.Pointers(tf) = [];

            % Update pointer
            obj.PointerListener.Enabled = false;
            obj.Figure.Pointer = obj.Pointers{end};
            obj.PointerListener.Enabled = true;

        end % doUnsetPointer

    end % private methods

    methods

        function onPointerChanged( obj, ~, ~ )
            %onPointerChanged  Event handler

            % Log as unknown setter
            obj.doSetPointer( 0, obj.Figure.Pointer )

        end % onPointerChanged

    end % event handlers

    methods( Static )

        function token = setPointer( figure, pointer )
            %setPointer  Set pointer
            %
            %  t = uix.PointerManager.setPointer(f,p) sets the pointer of
            %  the figure f to p.  The returned token t can be used
            %  subsequently to unset the pointer.

            % Get pointer manager
            obj = uix.PointerManager.getInstance( figure );

            % Retrieve token
            token = obj.NextToken;

            % Set
            obj.doSetPointer( token, pointer )

            % Increment token
            obj.NextToken = token + 1;

        end % setPointer

        function unsetPointer( figure, token )
            %unsetPointer  Unset pointer
            %
            %  uix.PointerManager.unsetPointer(f,t) unsets the pointer of
            %  the figure f using the token t.

            % Check ID
            validateattributes( token, {'numeric'}, {'scalar','integer','>',0} )

            % Get pointer manager
            obj = uix.PointerManager.getInstance( figure );

            % Unset
            obj.doUnsetPointer( token )

        end % unsetPointer

        function obj = getInstance( figure )
            %getInstance  Get pointer manager
            %
            %  m = uix.PointerManager.getInstance(f) gets the pointer
            %  manager for the figure f.

            % Get pointer manager
            name = 'UIxPointerManager';
            if isprop( figure, name ) % existing, retrieve
                obj = figure.( name );
            else % new, create and store
                obj = uix.PointerManager( figure );
                p = addprop( figure, name );
                p.Hidden = true;
                figure.( name ) = obj;
            end

        end % getInstance

    end % static methods

end % classdef


function compiler = mexcompiler
% mexcompiler returns the name of the compiler used by mex.

% Written by Tom Minka

mexopts = fullfile(prefdir,'mexopts.bat');
if ~exist(mexopts,'file')
  compiler = '';
  return
end
fid = fopen(mexopts);
while 1
  txt = fgetl(fid);
  if ~ischar(txt), break, end
  if strmatch('set COMPILER=',txt)
    compiler = txt(14:end);
    break
  end
end
fclose(fid);


function item = clearval(item, dflag)

% function item = clearval(item, dflag)
% This is a generic function to clear the contents of the val field of a
% cfg_item. It is usable for all leaf cfg_item classes (cfg_entry,
% cfg_files, cfg_menu).
% dflag is ignored for leaf entries - the val field is cleared
% unconditionally.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: clearval.m 1716 2008-05-23 08:18:45Z volkmar $

rev = '$Rev: 1716 $'; %#ok

item.val = {};


function [h]=disp_console(h,m)
%
%
%

mm = get(h,'string');
mm{end+1} = m;
set(h,'string',mm);


function s = setfield(s,field,v)
%SETFIELD Set mutable structure field contents.
% setfield(s,'field',v) sets the contents of the specified field to the
% value V.  This is equivalent to the syntax S.field = V.
%
% See also GETFIELD, RMFIELD, ISFIELD, FIELDNAMES.

% Written by Tom Minka
% (c) Microsoft Corporation. All rights reserved.

jv = s.obj;
if ~jv.containsKey(field)
  % add a new field
  jv.get('_fields').addElement(field);
end
jv.put(field,asJava(v));


function folder = layoutRoot()
%layoutRoot  Folder containing the GUI Layout Toolbox
%
%   folder = layoutRoot() returns the full path to the folder containing
%   the GUI Layout Toolbox.
%
%   Examples:
%   >> folder = layoutRoot()
%   folder = 'C:\tools\layouts2\layout'
%
%   See also: layoutVersion

%  Copyright 2009-2014 The MathWorks, Inc.
%  $Revision: 980 $ $Date: 2014-09-28 14:27:26 -0400 (Sun, 28 Sep 2014) $

folder = fileparts( mfilename( 'fullpath' ) );

end % layoutRoot


%> @brief Catkin-style basic dependencies from matlab_utilities
%> @param vararigin List of subdirectories to add to the Matlab path
%> Each dependency must be a subdirectory under this one.
function [] = addpath_thirdparty_packages(varargin)

% Get path of this file
base_path = fileparts(mfilename('fullpath'));

for i = 1:nargin
    dep = varargin{i};

%     if strcmp(dep,'yaml')
%         jcp = fullfile(prefdir,'javaclasspath.txt');
%         jcpID = fopen(jcp,'a');
%         fprintf(jcpID,...
%             [fullfile(pwd,'third','yaml','snakeyaml-1.10.jar')]...
%             );
%         fclose(jcpID);
%     end
    % Check then add path
    dep_path = fullfile(base_path, dep);
    assert(isfolder(dep_path), 'Invalid dependency (directory does not exist): %s', dep_path);
    addpath(dep_path);

    % Check for specific initialization
    %     init_path = fullfile(dep_path, [dep, '_init.m']);
    %     if exist(init_path, 'file')
    %         % Invoke initialization function
    %         feval([dep, '_init']);
    %     end
end

end


function vdisp(s,varargin)

global prevCharCnt;
if isempty(prevCharCnt), prevCharCnt = 0; end

if ~check_option(varargin,'silent') && ~getMTEXpref('generatingHelpMode')
  fprintf(repmat('\b',1, prevCharCnt));
  prevCharCnt = 0;
  disp(s);
end


function [strCell,IND,aIND] = prtUtilRemoveStrCell(strCell,str)
%[strCell,IND] = prtUtilRemoveStrCell(strCell,str);
%
%   Returns a cell array of strings NOT containing the character arrays in strCell
%   which contain the string str.  IND is the locations of the cells kept.
%
%   see also: prtUtilKeepStrCell
%
% xxx Need Help xxx

[garbage,aIND] = prtUtilKeepStrCell(strCell,str);

IND = setdiff(1:length(strCell),aIND);
strCell = {strCell{IND}};


function Fmenu = spm_Menu(action, varargin)
% SPM Menu window
% FORMAT Fmenu = spm_Menu('Create',Vis)
% Create the SPM Menu window (tag property set to 'Menu')
% Vis    - visibility: {'on'} or 'off'
% Fmenu  - handle of figure created
%
% FORMAT Fmenu = spm_Menu('Switch',Modality)
% Switch the SPM Menu window to the specified modality
%
% FORMAT spm_Menu('Close')
% Close the SPM Menu window
%__________________________________________________________________________
% Copyright (C) 2018-2019 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_Menu.m 7755 2019-12-16 13:19:28Z spm $

if nargin < 1, action = 'Create'; end

switch lower(action)
    case 'create'
        spm_Menu('Close');
        Fmenu = create_menu(varargin{1:end});

    case 'switch'
        Fmenu = spm_figure('FindWin','Menu');
        [Modality,ModNum] = spm('CheckModality',varargin{1});
        if ~isempty(Fmenu)
            if strcmpi(Modality,'PET')
                set(findobj(Fmenu, '-regexp', 'Tag', 'FMRI'), 'Visible', 'off');
                set(findobj(Fmenu, '-regexp', 'Tag', 'EEG'),  'Visible', 'off');
                set(findobj(Fmenu, '-regexp', 'Tag', 'PET'),  'Visible', 'on' );
            elseif strcmpi(Modality,'FMRI')
                set(findobj(Fmenu, '-regexp', 'Tag', 'EEG'),  'Visible', 'off');
                set(findobj(Fmenu, '-regexp', 'Tag', 'PET'),  'Visible', 'off');
                set(findobj(Fmenu, '-regexp', 'Tag', 'FMRI'), 'Visible', 'on' );
            else
                set(findobj(Fmenu, '-regexp', 'Tag', 'PET'),  'Visible', 'off');
                set(findobj(Fmenu, '-regexp', 'Tag', 'FMRI'), 'Visible', 'off');
                set(findobj(Fmenu, '-regexp', 'Tag', 'EEG'),  'Visible', 'on' );
            end
            set(findobj(Fmenu,'Tag','Modality'),'Value',ModNum,'UserData',ModNum);
        else
            warning('SPM Menu window not found.');
        end

    case 'close'
        Fmenu = spm_figure('FindWin','Menu');
        delete(Fmenu);

    otherwise
        error('Unknown action ''%s''.',action);
end

%==========================================================================
%-function Fmenu = create_menu(Vis)
%==========================================================================
function Fmenu = create_menu(Vis)

if ~nargin, Vis = 'on'; end

%-Get size and scalings
%--------------------------------------------------------------------------
PF    = spm_platform('fonts');             %-Font names (for this platform)
FS    = spm('FontSizes');                  %-Scaled font sizes

WS    = spm('WinScale');                   %-Window scaling factors
Rect0 = spm('WinSize','0',1);
RectM = spm('WinSize','Menu',1).*WS;       %-Menu window rectangle: 400x445
Pos   = [Rect0(1) Rect0(2) 0 0] + RectM;

%-Create Menu window
%--------------------------------------------------------------------------
if ~isempty(which('openfig'))
    Fmenu = openfig(fullfile(spm('Dir'),'spm_Menu.fig'),'new','invisible');
else
    fprintf('\nFunction openfig.m is missing. Download it from:\n');
    fprintf(' https://savannah.gnu.org/bugs/download.php?file_id=33499\n');
    Fmenu = [];
end

set(Fmenu,'Name',[spm('Version') ': Menu']);
set(Fmenu,'Units','pixels', 'Position',Pos);
set(Fmenu,'Color',[1 1 1]*.8);

% Fmenu = figure('Tag','Menu',...
%     'Name',[spm('Version') ': Menu'],...
%     'IntegerHandle','off',...
%     'NumberTitle','off',...
%     'Units','pixels',...
%     'Position',Pos,...
%     'Resize','on',...
%     'Pointer','arrow',...
%     'Color',[1 1 1]*.8,...
%     'MenuBar','none',...
%     'DockControls','off',...
%     'CloseRequestFcn','spm(''Quit'')',...
%     'HandleVisibility','off',...
%     'DefaultUicontrolFontName',PF.helvetica,...
%     'Visible','off');

%-Set SPM colour
%--------------------------------------------------------------------------
set(findobj(Fmenu,'Tag', 'frame'),'BackgroundColor',spm('colour'));
if ispc && strcmpi(spm_check_version,'matlab')
    try
        %M   = getframe(Fmenu);
        %col = double(M.cdata(floor(size(M.cdata,1)/3),floor(size(M.cdata,2)/2),:));
        col = [204 204 204];
        set(findobj(Fmenu,'UserData','LABEL'),'BackgroundColor',col/255);
    end
elseif ismac
    set(findobj(Fmenu,'UserData','LABEL'),'Visible','off','Tag','');
end

%-Set Utils
%--------------------------------------------------------------------------
set(findobj(Fmenu,'Tag', 'Utils'), 'String',{'Utils...',...
    'CD',...
    'PWD',...
    'Run M-file',...
    'Load MAT-file',...
    'Save MAT-file',...
    'Delete files',...
    'Show SPM',...
    'Show MATLAB'});
set(findobj(Fmenu,'Tag', 'Utils'), 'UserData',{...
    ['spm(''FnBanner'',''CD'');' ...
     'cd(spm_select(1,''dir'',''Select new working directory''));' ...
     'spm(''alert"'',{''New working directory:'',[''    '',pwd]},''CD'',1);'],...
    ['spm(''FnBanner'',''PWD'');' ...
     'spm(''alert"'',{''Present working directory:'',[''    '',pwd]},''PWD'',1);'],...
    ['spm(''FnBanner'',''Run M-file'');' ...
     'spm(''Run'');' ...
     'fprintf(''%-40s: %30s\n'',''Completed'',spm(''time''));'],...
    ['spm(''FnBanner'',''Load MAT-file'');' ...
     'load(spm_select(1,''mat'',''Select MAT-file''));'],...
    ['spm(''FnBanner'',''Save MAT-file'');' ...
     'save(spm_input(''Output filename'',1,''s''), spm_get_defaults(''mat.format''));'],...
    ['spm(''FnBanner'',''Delete files'');' ...
     'spm(''Delete'');'],...
    ['spm(''FnBanner'',''Show SPM'');' ...
     'spm(''Show'');'],...
    ['spm(''FnBanner'',''Show Command Window'');' ...
     'commandwindow;']});

%-Set Toolboxes
%--------------------------------------------------------------------------
xTB       = spm('tbs');
if ~isempty(xTB)
    set(findobj(Fmenu,'Tag', 'Toolbox'),'String',{'Toolbox:' xTB.name });
    set(findobj(Fmenu,'Tag', 'Toolbox'),'UserData',xTB);
else
    set(findobj(Fmenu,'Tag', 'Toolbox'),'Enable','off');
end
set(Fmenu,'Visible',Vis);


function hFig = JTattooDemo()
% JTattooDemo - demonstrates effects of Look-and-Feel changes (including JTattoo L&F)
%
% JTattooDemo displays a figure with Matlab uicontrols and Java components,
% and allows the user to modify the figure's look-and-feel (L&F) to any of
% the standard L&Fs installed on the system, as well to the JTattoo L&Fs.
%
% Syntax:
%    hFig = JTattooDemo()
%
% Input Parameters:
%    None.
%
% Output parameters:
%    hFig - handle of the created figure
%
% Technical description:
%    http://UndocumentedMatlab.com/blog/jtattoo-look-and-feel-demo/
%    http://www.jtattoo.net
%
% Bugs and suggestions:
%    Please send to Yair Altman (altmany at gmail dot com)
%
% Release history:
%    1.1 2013-03-19: Fixed JTattoo's name; restored original L&F for other GUI; removed slider Java control; added current L&F title
%    1.0 2013-03-19: First version posted on MathWorks File Exchange

% License to use and modify this code is granted freely to all interested, as long as the original author is
% referenced and attributed as such. The original author maintains the right to be solely associated with this work.

% Programmed and Copyright by Yair M. Altman: altmany(at)gmail.com
% $Revision: 1.0 $  $Date: 2013/03/19 23:22:38 $

    % Add the JTatto java library
    folder = fileparts(mfilename('fullpath'));
    javaclasspath( {folder, [folder '\JTattoo.jar']} );

    % The main figure can't be moved or resized with setting the default Windows L&F
    %originalLnF = javax.swing.UIManager.getLookAndFeel;
    %javax.swing.UIManager.setLookAndFeel(originalLnF); %'com.sun.java.swing.plaf.windows.WindowsLookAndFeel');

    % Create MATLAB figure
    hFig = figure( 'Name', 'JTattoo Look-and-Feel Demo', ...
                   'NumberTitle', 'off', ...
                   'MenuBar', 'none', ...
                   'Toolbar', 'none', ...
                   'CloseRequestFcn',@onExit);

    % Get the MATLAB figure's underlying Java frame
    javaWindow = getJavaFrame( hFig );
    setappdata( hFig, 'javaWindow', javaWindow );

    % Add the figure's main menus
    addMainMenus( hFig );

    % Add the figure's controls
    addControls( hFig );

end  % JTattooDemo

% Add the main menus to the figure
function addMainMenus( hFig )
    % File main menu
    FileMenu = uimenu( hFig, 'Label', 'File' );
    uimenu( FileMenu, 'Label', 'Exit', 'Callback', @onExit );

    % System main menu
    SystemMenu = uimenu( hFig, 'Label', 'System' );
    lnfs = javax.swing.UIManager.getInstalledLookAndFeels();
    for idx = 1 : length( lnfs )
        uimenu( SystemMenu, 'Label',char(lnfs(idx).getName), 'Callback',@(h,e)updateInterface(char(lnfs(idx).getClassName)));
    end

    % JTattoo look and feel object names
    jt_lnf =   {
        'Default'     ''
        'Smart'       'com.jtattoo.plaf.smart.SmartLookAndFeel'
        'Aluminium'   'com.jtattoo.plaf.aluminium.AluminiumLookAndFeel'
        'Acryl'       'com.jtattoo.plaf.acryl.AcrylLookAndFeel'
        'Aero'        'com.jtattoo.plaf.aero.AeroLookAndFeel'
        'Bernstein'   'com.jtattoo.plaf.bernstein.BernsteinLookAndFeel'
        'Graphite'    'com.jtattoo.plaf.graphite.GraphiteLookAndFeel'
        'Fast'        'com.jtattoo.plaf.fast.FastLookAndFeel'
        'Hifi'        'com.jtattoo.plaf.hifi.HiFiLookAndFeel'
        'Luna'        'com.jtattoo.plaf.luna.LunaLookAndFeel'
        'McWin'       'com.jtattoo.plaf.mcwin.McWinLookAndFeel'
        'Mint'        'com.jtattoo.plaf.mint.MintLookAndFeel'
        'Noire'       'com.jtattoo.plaf.noire.NoireLookAndFeel'
        };

    % JTattoo main menu
    JTattooMenu = uimenu( hFig, 'Label', 'JTattoo' );
    for idx = 1 : length( jt_lnf )
        uimenu( JTattooMenu, 'Label',jt_lnf{idx,1}, 'Callback',@(h,e)updateInterface(jt_lnf{idx,2})) ;
    end
end  % addMainMenus

% Add the figure's controls
function addControls( hFig )
    % Example MATLAB controls
    matlabPanel = uipanel(hFig, 'units','norm', 'pos',[0.05,0.05,0.4,0.9], 'title','Matlab controls');
    controlLayout = uiflowcontainer( 'v0', matlabPanel );
    uicontrol(controlLayout, 'Style','list', 'BackgroundColor', 'w', 'String',{'Listbox item #1','Listbox item #2','Listbox item #3'}, 'Parent', controlLayout);
    uicontrol(controlLayout, 'Style','Pushbutton',  'String', 'Button ');
    uicontrol(controlLayout, 'Style','edit',        'String', 'Edit Box');
    uicontrol(controlLayout, 'Style','text',        'String', 'Static Text');
    uicontrol(controlLayout, 'Style','slider',      'String', 'Slider');
    uicontrol(controlLayout, 'Style','radiobutton', 'String', 'Radio Button');
    uicontrol(controlLayout, 'Style','checkbox',    'String', 'Check Box');
    uicontrol(controlLayout, 'Style','popupmenu',   'String', {'Option 1','Option 2', 'Option 3'});

    % Example Java components
    javaPanel = uipanel(hFig, 'units','norm', 'pos',[0.5,0.05,0.4,0.9], 'title','Java controls');
    jspinner     = javax.swing.JSpinner();
    jspinner.setValue(25);
    jbutton      = javax.swing.JButton('Java Button');
    jtextfield   = javax.swing.JTextField('Java TextField');
    jprogressbar = javax.swing.JProgressBar(0,100);
    jprogressbar.setStringPainted(true);
    jprogressbar.setValue(65);
    jslider      = javax.swing.JSlider(0,100,35);
    jslider.setPaintLabels(true);
    jslider.setMajorTickSpacing(20);
    jscrollbar = javax.swing.JScrollBar();
    jscrollbar.setValue(40);
    jscrollbar.setOrientation(jscrollbar.HORIZONTAL);
    jradiobutton = javax.swing.JRadioButton('Java RadioButton');
    jcheckbox    = javax.swing.JCheckBox('Java CheckBox');
    jcombobox    = javax.swing.JComboBox({'Option #1','Option #2','Option #3'});
    placeJavaComponent(jspinner,     [0.1 0.9  0.8 0.07], javaPanel);
    placeJavaComponent(jbutton,      [0.1 0.8  0.8 0.07], javaPanel);
    placeJavaComponent(jtextfield,   [0.1 0.7  0.8 0.07], javaPanel);
    placeJavaComponent(jprogressbar, [0.1 0.60 0.8 0.07], javaPanel);
   %placeJavaComponent(jslider,      [0.1 0.45 0.8 0.10], javaPanel);  % buggy in JTattoo, so leave out
    placeJavaComponent(jscrollbar,   [0.1 0.35 0.8 0.07], javaPanel);
    placeJavaComponent(jradiobutton, [0.1 0.25 0.8 0.07], javaPanel);
    placeJavaComponent(jcheckbox,    [0.1 0.15 0.8 0.07], javaPanel);
    placeJavaComponent(jcombobox,    [0.1 0.05 0.8 0.07], javaPanel);

    % Display the current L&F name
    bgcolor = get(hFig,'color');
    lnfName = char(javax.swing.UIManager.getLookAndFeel.getName);
    uicontrol(hFig, 'Style','text', 'FontWeight','bold', 'units','norm', 'pos',[0.02,0.95,0.9,0.04], 'string',lnfName, 'Background',bgcolor, 'tag','L&F title');
end  % addControls

% Place a Java component within a panel in a specified normalized position
function placeJavaComponent ( jcomponent, position, parent )
    jcomponent = javaObjectEDT( jcomponent );  % ensure component is auto-delegated to EDT
    jcomponent.setOpaque(false);  % useful to demonstrate L&F backgrounds
    [jc,hContainer] = javacomponent( jcomponent, [], parent ); %#ok<ASGLU>
    set(hContainer, 'Units','Normalized', 'Position',position);
end  % placeJavaComponent

% User wants to exit the application
function onExit( h, e ) %#ok<INUSD>
    hFig = gcbf;
    try
        javaWindow = getappdata( hFig, 'javaWindow' );
        SetDefaultLookAndFeel( javaWindow );
    catch
        % ignore...
    end
    delete( hFig );
    drawnow;
end % onExit

% User requested to change the L&F
function updateInterface( lookandfeel )
    originalLnF = javax.swing.UIManager.getLookAndFeel;
    javaWindow = getappdata( gcbf, 'javaWindow' );
    if isempty( lookandfeel )
        javax.swing.UIManager.setLookAndFeel(...
            'com.sun.java.swing.plaf.windows.WindowsLookAndFeel');
    else
        jTattoo = javaObjectEDT( 'UpdateJTattooInterface' );
        javaMethodEDT('setLookAndFeel', jTattoo, lookandfeel, 'Default', javaWindow);
    end
    container = javaMethodEDT('getContentPane', javaWindow);
    javaMethodEDT('updateComponentTreeUI', 'javax.swing.SwingUtilities', container);

    % Update the title
    hTitle = findall(gcbf, 'tag','L&F title');
    lnfName = char(javax.swing.UIManager.getLookAndFeel.getName);
    set(hTitle, 'String',lnfName);
    drawnow;

    % Restore original L&F for other GUI
    javax.swing.UIManager.setLookAndFeel(originalLnF)
end % updateInterface

% Get a Matlab figure's underlying Java Frame (RootPane) reference handle
function JavaFrame = getJavaFrame( hFig )
    try
        %  contentSize = [0,0];  % initialize
        JavaFrame = hFig;
        figName = get(hFig,'name');
        if strcmpi(get(hFig,'number'),'on')
            figName = regexprep(['Figure ' num2str(hFig) ': ' figName],': $','');
        end
        mde = com.mathworks.mde.desk.MLDesktop.getInstance;
        jFigPanel = mde.getClient(figName);
        JavaFrame = jFigPanel;
        JavaFrame = jFigPanel.getRootPane;
    catch
        try
            jFrame = get(handle(hFig),'JavaFrame');
            jFigPanel = get(jFrame,'FigurePanelContainer');
            JavaFrame = jFigPanel;
            JavaFrame = jFigPanel.getComponent(0).getRootPane;
        catch
            % Never mind
        end

    end
    try
        % If invalid RootPane, retry up to N times
        tries = 10;
        while isempty(JavaFrame) && tries>0  % might happen if figure is still undergoing rendering...
            drawnow; pause(0.001);
            tries = tries - 1;
            JavaFrame = jFigPanel.getComponent(0).getRootPane;
        end

        % If still invalid, use FigurePanelContainer which is good enough in 99% of cases... (menu/tool bars won't be accessible, though)
        if isempty(JavaFrame)
            JavaFrame = jFigPanel;
        end
        % contentSize = [JavaFrame.getWidth, JavaFrame.getHeight];

        % Try to get the ancestor FigureFrame
        JavaFrame = JavaFrame.getTopLevelAncestor;
    catch
        % Never mind - FigurePanelContainer is good enough in 99% of cases... (menu/tool bars won't be accessible, though)
    end
end  % getJavaFrame


function LabBookEmail(varargin)
%"LabbookEmail"
%   GUI to handle emailing CERR Labbook image captures.
%
%JRA 5/31/05
%
%Usage:
%   LabBookEmail('init', image, annotation);
%
% 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/>.

screenSize = get(0,'ScreenSize');
y = 300;
x = 519;
units = 'normalized';

%If no arguments default to init.
if(nargin == 0)
    varargin{1} = 'init';
end

%Command for callback switch statement.
command = varargin{1};

hFig = findobj('tag', 'CERR_LabBookEmail');

%If asking for INIT, and already initialized, return.
if ~isempty(hFig) & strcmpi(command, 'init');
    figure(hFig);
    return;
end

switch upper(command)
    case 'INIT'
        hFig = figure('visible', 'on', 'Name','Email Dialogue', 'units', 'pixels', 'position',[(screenSize(3)-x)/2 (screenSize(4)-y)/2 x y], 'MenuBar', 'none', 'NumberTitle', 'off', 'resize', 'off', 'Tag', 'CERR_LabBookEmail');
        uicontrol('units',units,'Position',[.01 .03 .54 .94],'style', 'frame');
        uicontrol('units',units,'Position',[.56 .82 .43 .15],'style', 'frame');
        uicontrol('units',units,'Position',[.56 .03 .43 .76],'style', 'frame');

        uicontrol('units',units,'Position',[.03 .9 .5 .05],'String','To:', 'style', 'text', 'HorizontalAlignment', 'left');
        uicontrol('units',units,'Position',[.03 .76 .5 .14],'String','', 'style', 'edit','HorizontalAlignment', 'left', 'Tag', 'LabBookEmailToField');

        uicontrol('units',units,'Position',[.03 .69 .5 .05],'String','Subject:', 'style', 'text', 'HorizontalAlignment', 'left');
        uicontrol('units',units,'Position',[.03 .62 .5 .07],'String','', 'style', 'edit','HorizontalAlignment', 'left', 'Tag', 'LabBookEmailSubjectField');

        uicontrol('units',units,'Position',[.03 .55 .5 .05],'String','Body:', 'style', 'text', 'HorizontalAlignment', 'left');
        uicontrol('units',units,'Position',[.03 .05 .5 .5],'String','', 'style', 'edit','HorizontalAlignment', 'left', 'Tag', 'LabBookEmailBodyField');

        uicontrol('units',units,'Position',[.59 .85 .17 .08],'String','Send', 'callback','LabBookEmail(''SEND'');', 'Tag', 'LabBookEmailSend');
        uicontrol('units',units,'Position',[.8 .85 .17 .08],'String','Cancel', 'callback','LabBookEmail(''CANCEL'');', 'Tag', 'LabBookEmailCancel');

        addresses = getEmailAddresses;
        optEmails = addresses.optionsEmails;
        cachedEmails = addresses.cachedEmails;

        uicontrol('units',units,'Position',[.57 .04 .41 .74],'style', 'listbox', 'string', {optEmails{:}, cachedEmails{:}}, 'callback', 'LabBookEmail(''ADDRESSCLICKED'')');

    case 'MESSAGE'
        saveFile = varargin{2};
        annotation = varargin{3};

        subjectField = findobj(hFig, 'Tag', 'LabBookEmailSubjectField');
        bodyField    = findobj(hFig, 'Tag', 'LabBookEmailBodyField');

        [pathstr,name,ext] = fileparts(saveFile);

        set(subjectField, 'String', [name ext]);
        set(bodyField, 'string', annotation);

        set(hFig, 'userdata', saveFile);

    case 'ADDRESSCLICKED'
        emails = get(gcbo, 'string');
        value  = get(gcbo, 'value');
        emailToAdd = emails{value};

        toBox = findobj(hFig, 'Tag', 'LabBookEmailToField');

        oldEmails = get(toBox, 'string');

        if ~isempty(oldEmails)
            set(toBox, 'string', [oldEmails emailToAdd ';']);
        else
            set(toBox, 'string', [emailToAdd ';']);
        end

    case 'CANCEL'
        delete(hFig);

    case 'SEND'
        optS = opts4Exe([getCERRPath,'CERROptions.json']);
        toField = findobj(hFig, 'Tag', 'LabBookEmailToField');
        subjectField = findobj(hFig, 'Tag', 'LabBookEmailSubjectField');
        bodyField    = findobj(hFig, 'Tag', 'LabBookEmailBodyField');

        subject = get(subjectField, 'string');
        toAddys = get(toField, 'string');
        saveFile = get(hFig, 'userdata');
        body = get(bodyField, 'string');

        toAddys = parseEmailString(toAddys);

        delete(hFig);
        pause(.1);
        sendmail(toAddys, subject, body, {saveFile});
        setEmailAddresses(toAddys);

end

function addresses = getEmailAddresses
%"getEmailAddresses"
%   Returns a list of stored and cached email addresses.

	optS = CERROptions;
	optionsEmails = optS.emailAddresses;

	try
        cachedEmails  = load(fullfile(getCERRPath, 'Labbook', 'cachedEmails'));
        cachedEmails = cachedEmails.cachedEmails;
	catch
        cachedEmails = {};
	end

	cachedEmails = setdiff(cachedEmails, optionsEmails);
	addresses.optionsEmails = optionsEmails;
	addresses.cachedEmails  = cachedEmails;

function setEmailAddresses(newAddresses)
%"setEmailAddresses"
%   Adds the passed addresses to the email cache.

	optS = CERROptions;
	optionsEmails = optS.emailAddresses;

	try
        cachedEmails  = load(fullfile(getCERRPath, 'Labbook', 'cachedEmails'));
	catch
        cachedEmails = [];
	end

	cachedEmails = union(cachedEmails, newAddresses);
	cachedEmails = setdiff(cachedEmails, optionsEmails);
    saveOpt = getSaveInfo;
    try
        if ~isempty(saveOpt);
        	save(fullfile(getCERRPath, 'Labbook', 'cachedEmails'), 'cachedEmails', saveOpt);
        else
        	save(fullfile(getCERRPath, 'Labbook', 'cachedEmails'), 'cachedEmails');
        end
    catch
        warning('Could not save cached email addresses.');
    end

function strings = parseEmailString(emailString)
%"parseEmailString"
%   Convert from a string of emails seperated by ; , and blanks to a cell
%   array of email addresses.

dividers = [0 length(emailString)+1];
dividers = union(dividers, strfind(emailString, ','));
dividers = union(dividers, strfind(emailString, ' '));
dividers = union(dividers, strfind(emailString, ';'));
dividers = unique(dividers);

dividerEnd = dividers(2:end) - 1;
dividers = dividers(1:end-1);

for i=1:length(dividers)
    strings{i} = emailString(dividers(i)+1:dividerEnd(i));
end


function hRD = plugin_rd
% Reference design definition

%   Copyright 2014-2015 The MathWorks, Inc.

% Call the common reference design definition function
hRD = AnalogDevicesAGCDemo.adrv9361z7035.common.plugin_rd('fmc lvds agc', 'Rx');
AnalogDevicesAGCDemo.adrv9361z7035.ccfmc_lvds_agc.rx.add_rx_io(hRD);


function datapath = metoffice_get_path()

os = system_dependent('getos');
if ~isempty(strfind(os,'Ubuntu'))
  % Finland
  datapath = '/share/climate/data/UK_Met_Office/RecTest/DATASETS/';
elseif ~isempty(strfind(os,'Linux'))
  % ICS GridEngine
  datapath = '/share/climate/data/UK_Met_Office/RecTest/DATASETS/';
else
  % MetOffice
  datapath = '/net/home/h03/hadia/data/RecTest/';
end


function creds = loadplotlycredentials()

userhome = getuserdir();

plotly_credentials_file = fullfile(userhome,'.plotly','.credentials');

% check if credentials exist
if ~exist(plotly_credentials_file, 'file')
    error('Plotly:CredentialsNotFound',...
        ['It looks like you haven''t set up your plotly '...
        'account credentials yet.\nTo get started, save your '...
        'plotly username and API key by calling:\n'...
        '>>> saveplotlycredentials(username, api_key)\n\n'...
        'For more help, see https://plot.ly/MATLAB or contact '...
        'chris@plot.ly.']);
end

fileIDCred = fopen(plotly_credentials_file, 'r');

if(fileIDCred == -1)
    error('plotly:loadcredentials', ...
        ['There was an error reading your credentials file at '...
        plotly_credentials_file '. Contact chris@plot.ly for support.']);
end

creds_string_array = fread(fileIDCred, '*char');
creds_string = sprintf('%s',creds_string_array);
creds = loadjson(creds_string);

end


classdef HandleObj < handle
  properties
    data
  end
end


function data = readfile(path, varargin)
opts.asString = false;
opts = vl_argparse(opts, varargin);

assert(exist(path, 'file') == 2, 'File %s does not exist.', path);

fd = fopen(path, 'r');
data = textscan(fd, '%s', 'delimiter', '\n');
fclose(fd);

data = data{1};
data = cellfun(@strtrim, data, 'UniformOutput', false);
isNonAscii = cellfun(@(s) all(s < 128), data);
assert(all(isNonAscii), 'File %s contains non ascii characters.', path);
if opts.asString
  data = strjoin(data, '\n');
end


%MINUS Dataset overload


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Reset:
%   Set the specified variable to zero.
%   Example: robot = Reset(robot, do1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright (C) 2012, by Arturo Gil Aparicio
%
% This file is part of ARTE (A Robotics Toolbox for Education).
%
% ARTE 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.
%
% ARTE is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with ARTE.  If not, see <http://www.gnu.org/licenses/>.
function [robot] = Reset(robot, variable)

global configuration

robot.variable = 0;


function out = cfg_run_named_input(job)

% Return evaluated input.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: cfg_run_named_input.m 1716 2008-05-23 08:18:45Z volkmar $

rev = '$Rev: 1716 $'; %#ok

out.input = job.input;


function [bOK, sFilePath] = ex_PutFile(vFilterSpec, sDialogTitle, nXPos, nYPos)
% function [bOK, sFilePath] = ex_PutFile(vFilterSpec, sDialogTitle, nXPos, nYPos)
% -------------------------------------------------------------------------------
% Wrapper for the uiputfile function of Matlab. Simplifies the output parameter analysis
%
% Input parameter:
%   vFilterSpec   Filter rules for selection, e. g. '*.mat'
%   sDialogTitle  String to appear in the titlebar
%   nXPos         X-position of dialog
%   nYPos         Y-position of dialog
%
% Output parameters:
%   bOK         Result of user interaction: 1: OK pressed, 0: Cancel pressed
%   sFilePath   Complete filepath of selected file
%
% Danijel Schorlemmer
% December 18, 2001

% Init return values
bOK = 0;
sFilePath = '';
% Invoke Matlab's original function
if ~exist('vFilterSpec')
  vFilterSpec = '';
end
if ~exist('sDialogTitle')
  sDialogTitle = '';
end
if (exist('nXPos') & exist('nYPos'))
  [sFile, sPath] = uiputfile(vFilterSpec, sDialogTitle, nXPos, nYPos);
else
  [sFile, sPath] = uiputfile(vFilterSpec, sDialogTitle);
end
% Cancel pressed?
if isequal(sFile, 0)  ||  isequal(sPath, 0)
  return;
end
% Everything ok?
sFilePath = [sPath sFile];
if length(sFilePath) > 1
  % We got everything
  bOK = 1;
end


function varargout=voicebox(varargin)
%
% For calling details please see v_voicebox.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_voicebox.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: voicebox.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_voicebox(varargin{:});
else
    v_voicebox(varargin{:});
end


function mv = mv_helpMenu(mv, hfig);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% add menus (5): help menu
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mv.ui.helpMenu = uimenu(hfig, 'ForegroundColor', [.6 .2 0], 'Label', 'Help', ...
                              'Separator', 'on');

% web page callback:
% web http://white.stanford.edu/newlm/index.php/Multi_Voxel_UI
cb = 'web http://white.stanford.edu/newlm/index.php/Multi_Voxel_UI';
mv.ui.webHelp = uimenu(mv.ui.helpMenu, 'Label', 'Time Course UI page', 'Separator', 'off', ...
    'CallBack', cb);

% web page (external browser) callback:
% web http://white.stanford.edu/newlm/index.php/Multi_Voxel_UI -browser
cb = 'web http://white.stanford.edu/newlm/index.php/Multi_Voxel_UI -browser';
cb = 'web http://white/newlm/index.php/Main_Page -browser';
mv.ui.webHelp2 = uimenu(mv.ui.helpMenu, 'Label', 'Time Course UI page (external browser)', 'Separator', 'off', ...
    'CallBack', cb);

% mrVista web page callback:
% web web http://white.stanford.edu/newlm/index.php/Main_Page
cb = 'web http://white.stanford.edu/newlm/index.php/Main_Page';
mv.ui.webWiki = uimenu(mv.ui.helpMenu,  'Label',  'mrVista wiki',  ...
    'Separator',  'off',  'Callback',  cb);

% mrVista web page (external browser) callback:
% web web http://white.stanford.edu/newlm/index.php/Main_Page
% -browser
mv.ui.webWiki2 = uimenu(mv.ui.helpMenu,  'Label',  'mrVista wiki (external browser)',  ...
    'Separator',  'off',  'Callback',  cb);

% identify callback for menu item
cb = 'helpFindCallback; ';
uimenu(mv.ui.helpMenu,  'Label',  'Identify Callback for a menu item',  ...
        'Separator',  'on',  'Callback',  cb);

return


function st = makecall(args, origin, structargs)

    % check if signed in and grab username, key, domain
    [un, key, domain] = signin;
    if isempty(un) || isempty(key)
        error('Plotly:CredentialsNotFound',...
             ['It looks like you haven''t set up your plotly '...
              'account credentials yet.\nTo get started, save your '...
              'plotly username and API key by calling:\n'...
              '>>> saveplotlycredentials(username, api_key)\n\n'...
              'For more help, see https://plot.ly/MATLAB or contact '...
              'chris@plot.ly.']);
    end

    platform = 'MATLAB';

    args = m2json(args);
    kwargs = m2json(structargs);
    url = [domain '/clientresp'];
    payload = {'platform', platform, 'version', plotly_version, 'args', args, 'un', un, 'key', key, 'origin', origin, 'kwargs', kwargs};

    if (is_octave)
        % use octave super_powers
        resp = urlread(url, 'post', payload);
    else
        % do it matlab way
        resp = urlread(url, 'Post', payload);
    end

    st = loadjson(resp);

    response_handler(resp);

end


classdef Rx < adi.AD9361.Rx

    methods
        %% Constructor
        function obj = Rx(varargin)
            % Returns the matlabshared.libiio.base object
            coder.allowpcode('plain');
            obj = obj@adi.AD9361.Rx(varargin{:});
        end
    end

end


function sout = cvx_profile( flag )

% CVX_PROFILE	CVX-specific profiler control.
%    This is a function used for internal CVX development to help determine
%    performance limits within the CVX code itself, by turning off the profiler
%    when the solver is being called. End users will likely not find this
%    function to be useful.

global cvx___
cvx_global
s = cvx___.profile;
if nargin == 1,
    if isnumeric(flag) || islogical(flag),
        ns = double(flag) ~= 0;
    elseif ischar(flag) && size(flag,1) == 1,
        switch lower(flag),
            case { 'true', 'on' },
                ns = true;
            case { 'false', 'off' },
                ns = false;
            otherwise,
                cvx_throw( 'String arugment must be ''true''/''on'' or ''false''/''off''.' );
        end
    else
        cvx_throw( 'Argument must be a numeric scalar or a string.' );
    end
    if cvx___.profile ~= ns,
        cvx___.profile = ns;
        stat = profile('status');
        if ns && ~isempty( cvx___.problems ) && ~isequal( stat.ProfilerStatus, 'on' ),
            profile on
        elseif ~ns && isequal( stat.ProfilerStatus, 'on' ),
            profile off
        end
    end
end
if nargin == 0 || nargout > 0,
    sout = s;
end

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


cd lib/mex_files;
make_linux
cd ../..
addpath ./demo
addpath ./lib/m_files
addpath ./lib/mex_files


function hRD = plugin_rd_rx
% Reference design definition

% Call the common reference design definition function
hRD = AnalogDevices.adrv9361z7035.common.plugin_rd('ccbob_lvds','Rx & Tx');
AnalogDevices.adrv9361z7035.common.add_io(hRD, 'Rx & Tx', 'ccbob_lvds');


if isoctave
  status=2;
else
  status=0;
end;


% RICOH MEG Reader toolbox for MATLAB
% Version 1.0.3 13-Sep-2018
%
% Files
%   getRData          - Get measured data
%   getRHdrSystem     - Get header of the system information
%   getRHdrChannel    - Get header of the system information
%   getRHdrAcqCond    - Get header of the system information
%   getRHdrEvent      - Get header of the trigger event
%   getRHdrCoregist   - Get header of the system information
%   getRHdrDigitize   - Get header of the digitization information
%   getRHdrSubject    - Get header of the subject information
%   getRHdrAnnotation - Get header of annotation
%   getRHdrSource     - Get header of the source information
%   getRMriHdr        - Get header of mri
%   getRVersion       - Get toolbox version
%
%------------------------------------------------------------
%                          History
%------------------------------------------------------------
% R1.0.3 : 2018.09.13 - support Axial2ndOrderGradiometer
% R1.0.2 : 2018.06.04 - modify comment(fear of misinterpretation)
% R1.0.1 : 2018.03.14 - modify conflict 3rd party file
% R1.0.0 : 2017.09.27 - First release
%
%-----------------------------------------------------------------------
% Copyright (C) 2017-2018     Ricoh Company Ltd. All Rights Reserved.
% All rights reserved.


classdef PTKEditedResultPatch < PTKPatch
% PTKPatch. Class for sharing image edits with other PTK clients
    %
    %     You should not use this class within your own code. It is intended to
    %     be used by the gui of the TD MIM Toolkit.
    %
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties
        Schema = 1
        PatchType = 'EditedResult'
        SeriesUid
        PluginName
        EditedResult
    end

end


%SUM Datafile overload


function a=screensnap(b)
%   screensnap is a mex file to snap the screen
%   the input b is double data
%   when b=0,the snapped screen excluding the matlab window
%   else, the snapped screen including the matlab window
%    compile to use>> mex screensnap.c user32.lib gdi32.lib
%   usage:1, >>a=screensnap(0)     %exclude the matlab window
%            >>imshow(a);
%         2, >>a=screensnap(1);    %include the matlab window
%            >> imshow(a);
%   designed by darnshong
%   chenzushang@sina.com  http://darnshong.52blog.net
%   2005-12-18


% function to overwrite ops1 fields with ops0 fields if settings have
% changed for new runs
function ops = opsChanges(ops1, ops0)

ops = ops1;
f = fieldnames(ops0);

for j = 1:length(f)
    ops.(f{j}) = ops0.(f{j});
end


function clean = escapechars(dirty)
    % escape \ and % chars for sprintf
    clean = strrep(dirty,'\', '\\');
    clean = strrep(clean,'%', '%%');
end


%  PARSE_ARGUMENTS -- arguments parser
%
%  More About
%  ------------
%
%  - This function is an alias for utils.miscellaneous.parse_arguments.
%  Check it out for more explanations
%
%  Examples
%  ---------
%
%  See also: UTILS.MISCELLANEOUS.PARSE_ARGUMENTS
%


function d = setoptparams(d, varargin)

%tstoolbox/@description/setoptparams
%   Syntax:
%     * d = setoptparams(d, nr, param)
%
%   set optional parameter number nr
%
% Copyright 1997-2001 DPI Goettingen, License http://www.physik3.gwdg.de/tstool/gpl.txt

narginchk(2,3);

if nargin < 3
	nr = 1;
	param = varargin{1};
else
	nr = varargin{1};
	param = varargin{2};
end

d.optparam{nr} = param;


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

test = which('commons-cli-1.0.jar');
path =  fileparts(test);

allFiles = dir(path);
dpath = [];

for i = 1:length(allFiles)
    if ~ allFiles(i).isdir
        if i == 1
            dpath = {[path '\' allFiles(i).name]};
        else
            file = {[path '\' allFiles(i).name]};
            dpath = vertcat(dpath, file);
        end
    end
end
javaclasspath(dpath)


classdef MimSaveImage < MimGuiPlugin
    % MimSaveImage. Gui Plugin for exporting the image currently in the
    % visualisation window to a file
    %
    %     You should not use this class within your own code. It is intended to
    %     be used by the gui of the TD MIM Toolkit.
    %
    %     MimSaveImage is a Gui Plugin for the MIM Toolkit.
    %     The gui will create a button for the user to run this plugin.
    %     Running this plugin will raise a Save dialog allowing the user to
    %     choose a filename and format, and then save the image currently in the
    %     visualisation panel.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties
        ButtonText = 'Export Image'
        SelectedText = 'Export Image'
        ToolTip = 'Save the current image to files'
        Category = 'Export'
        Visibility = 'Dataset'
        Mode = 'Toolbar'

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

        Icon = 'export_image.png'
        Location = 20
    end

    methods (Static)
        function RunGuiPlugin(gui_app)
            gui_app.SaveBackgroundImage();
        end

        function enabled = IsEnabled(gui_app)
            enabled = gui_app.IsDatasetLoaded();
        end

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


classdef MimMatNatDatabaseSeries < handle
    % MimMatNatDatabaseSeries.
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    properties (SetAccess = private)
        Name
        StudyName
        Modality
        Date
        Time
        SeriesUid
        StudyUid
        NumberOfImages
    end

    methods
        function obj = MimMatNatDatabaseSeries(series_id, single_image_metainfo, number_of_images)
            if nargin > 0
                obj.Name = single_image_metainfo.SeriesDescription;
                obj.StudyName = single_image_metainfo.StudyDescription;
                obj.Modality = single_image_metainfo.Modality;
                obj.Date = single_image_metainfo.Date;
                obj.Time = single_image_metainfo.Time;
                obj.SeriesUid = series_id;
                obj.StudyUid = single_image_metainfo.StudyUid;
                obj.NumberOfImages = number_of_images;
            end
        end
    end
end


classdef testTopOptLevelSetPrinting < testTopOptPrinting

    properties (Access = protected)
        fileOutputName = 'testTopOptLevelSetPrinting';
        printMode = 'DesignVariable';
    end

end