function [matVar] = jsonRead(inputVar,varargin)
	% Decode a json string.
	% Biafra Ahanonu
	% started: 2020.06.09 [12:19:01]
	% inputs
		% inputVar - JSON string or path to a HDF5 file containing dataset that is a JSON string.
	% outputs
		%

	% changelog
		% 2021.08.08 [19:30:20] - Updated to handle CIAtah v4.0 switch to all functions inside ciapkg package.
        % 2022.01.25 [15:52:31] - Edge case where the end of the imported string is a space, causing jsondecode to fail.
	% TODO
		%

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

	%========================
	% Str: hierarchy name in hdf5 where JSON data is located.
	options.inputDatasetName = '/movie/preprocessingSettingsAll';
	% get options
	options = getOptions(options,varargin);
	% display(options)
	% unpack options into current workspace
	% fn=fieldnames(options);
	% for i=1:length(fn)
	% 	eval([fn{i} '=options.' fn{i} ';']);
	% end
	%========================

	try
		if ischar(inputVar)
			% Determine if it is a file
			if exist(inputVar,'file')==2
				% Read in the JSON string
				inputVar = h5read(inputVar,options.inputDatasetName);
				if iscell(inputVar)
					inputVar = inputVar{1};
				end
				try
					jsondecode(inputVar);
                catch
                    % Edge case where the end of the imported string is a space, causing jsondecode to fail.
                    inputVar = char(inputVar);
					inputVar = inputVar(1:end-1);
				end
				if ~ischar(inputVar)
					fprintf('HDF5 dataset %s does NOT contain a json string.\n',options.inputDatasetName);
				end
			else
			end

			% Encode the input variable as a JSON string
			matVar = jsondecode(inputVar);
		end

		if nargout==0
			disp(matVar)
		end

	catch err
		disp(repmat('@',1,7))
		disp(getReport(err,'extended','hyperlinks','on'));
		disp(repmat('@',1,7))
	end
end
function [jsonStr] = subfxnHumanReadable(jsonStr)
	% Make human readable
	jsonStr = strrep(jsonStr, ',', sprintf(',\r'));
	jsonStr = strrep(jsonStr, '[{', sprintf('[\r{\r'));
	jsonStr = strrep(jsonStr, '}]', sprintf('\r}\r]'));
end


%% HELLO_SCRIPT is a script to call HELLO_FUN.
%
%  Discussion:
%
%    The BATCH command runs scripts, not functions.  So we have to write
%    this short script if we want to work with BATCH!
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 May 2012
%
%  Author:
%
%    John Burkardt
%
  n = 10;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'HELLO_SCRIPT\n' );
  fprintf ( 1, '  Call HELLO_FUN to say hello %d times\n', n );

  tic
  hello_fun ( n );
  toc


function clearStructMeshes(varargin)
%function clearStructMeshes()
%This function clears the surface meshes for passed structure uidC.
%
%APA, 06/21/07
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

global planC
indexS = planC{end};

if isempty(varargin)
    structNumToClear = 1:length(planC{indexS.structures});
else
    uidC = varargin{1};
    structNumToClear = getAssociatedStr(uidC);
end

%Set Matlab path to directory containing the library
currDir = cd;

if ispc
    meshDir = fileparts(which('libMeshContour.dll'));
    cd(meshDir);
    loadlibrary('libMeshContour','MeshContour.h');
elseif isunix
    meshDir = fileparts(which('libMeshContour.so'));
    cd(meshDir);
    loadlibrary('libMeshContour.so','MeshContour.h');
end
%Clear existing structure meshes
waitbarH = waitbar(0,'Clearing surface meshes for structures...');
try
    for structNum = structNumToClear
        structUID = planC{indexS.structures}(structNum).strUID;
        calllib('libMeshContour','clear',structUID)
        planC{indexS.structures}(structNum).meshRep = 0;
        planC{indexS.structures}(structNum).meshS   = [];
        waitbar(structNum/length(planC{indexS.structures}),waitbarH)
    end
end
close(waitbarH)
%switch back the current irectory
cd(currDir)


function [metabolite_structure] = queryExposomeExplorer(metabolite_structure)
%
% the function will search for metabolite names
% http://exposome-explorer.iarc.fr/search?utf8=%E2%9C%93&query=2-aminophenol+sulfate&button=
%
%
% INPUT
% metabolite_structure  metabolite structure
% startSearch           specify where the search should start in the
%                       metabolite structure. Must be numeric (optional, default: all metabolites
%                       in the structure will be search for)
% endSearch             specify where the search should end in the
%                       metabolite structure. Must be numeric (optional, default: all metabolites
%                       in the structure will be search for)
%
% OUTPUT
% metabolite_structure  updated metabolite structure
%
%
% Ines Thiele, 09/2021

Mets = fieldnames(metabolite_structure);

if ~exist('startSearch','var')
    startSearch = 1;
end
if ~exist('endSearch','var')
    endSearch = length(Mets);
end

annotationSource = 'Exposome Explorer website by name search';
annotationType = 'automatic';

for i = startSearch : endSearch
    if isempty(metabolite_structure.(Mets{i}).lipidmaps) || length(find(isnan(metabolite_structure.(Mets{i}).lipidmaps)))>0
        metN = metabolite_structure.(Mets{i}).metNames;
        % make name fit for internet
        metN = regexprep(metN,'"','');
        metInt = regexprep(metN,' ','+') ;
       % http://exposome-explorer.iarc.fr/search?utf8=%E2%9C%93&query=2-aminophenol+sulfate&button=
        url=['http://exposome-explorer.iarc.fr/search?utf8=%E2%9C%93&query=' metInt];
        syst = urlread(url);
        exposomeExplorer = '';
        if exist('syst','var') && ~isempty(strfind(syst,'returned 1 result'))
            tok = split(syst,'a href="/compounds/');
            tok2 = split(tok{2},'>');
            tok3 = regexprep(tok2{1},'"','');
            exposomeExplorer = tok3;
            % no real information on there - could be useful for getting mol
            % files
            if ~isempty(exposomeExplorer)
                metabolite_structure.(Mets{i}).exposomeExplorer = exposomeExplorer;
                metabolite_structure.(Mets{i}).exposomeExplorer_source = [annotationSource,':',annotationType,':',':',datestr(now)];
            end
        end
    end
end


%HORZCAT Datafile overload: horizontal concatenation


function v = cvx_value( x )
warning( 'CVX:IllegalUse', ...
    'CVX error: illegal use of a cvx problem object has been detected.\n   Please do not copy or manipulate the value of ''cvx_problem'' in any way.', 1 ); %#ok
v = [];

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function varargout = panel_options(varargin)
% PANEL_OPTIONS:  Set general Brainstorm configuration.
%
% USAGE:  [bstPanelNew, panelName] = panel_options('CreatePanel')
%                                    panel_options('SystemPathRemove', rmPath)          % Update system path
%                             PATH = panel_options('SystemPathRemove', rmPath, PATH)    % Update user defined path (do not change system path)

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

eval(macro_method);
end

%% ===== CREATE PANEL =====
function [bstPanelNew, panelName] = CreatePanel() %#ok<DEFNU>
    % Java initializations
    import java.awt.*;
    import javax.swing.*;
    global GlobalData;
    % Constants
    panelName = 'Preferences';

    % Create main main panel
    jPanelNew = gui_river();

    % ===== LEFT =====
    jPanelLeft = gui_river();
    jPanelNew.add('vtop', jPanelLeft);
    % ===== LEFT: SYSTEM =====
    jPanelSystem = gui_river([5 2], [0 15 8 15], 'System');
        jCheckUpdates    = gui_component('CheckBox', jPanelSystem, 'br', 'Automatic updates', [], [], []);
        if (bst_get('MatlabVersion') >= 804)
            jCheckSmooth = gui_component('CheckBox', jPanelSystem, 'br', 'Use smooth Matlab graphics', [], [], []);
        else
            jCheckSmooth = [];
        end
        jCheckDownsample = gui_component('CheckBox', jPanelSystem, 'br', 'Downsample recordings for faster display', [], [], []);
        jCheckGfp        = gui_component('CheckBox', jPanelSystem, 'br', 'Display GFP over time series', [], [], []);
        jCheckForceComp  = gui_component('CheckBox', jPanelSystem, 'br', 'Force mat-files compression (slower)', [], [], []);
        jCheckIgnoreMem  = gui_component('CheckBox', jPanelSystem, 'br', 'Ignore memory warnings', [], [], []);
        if ~ispc
            jCheckSystemCopy  = gui_component('CheckBox', jPanelSystem, 'br', 'Use system calls to copy/move files', [], [], []);
        else
            jCheckSystemCopy = [];
        end
    jPanelLeft.add('hfill', jPanelSystem);
    % ===== LEFT: OPEN GL =====
    jPanelOpengl = gui_river([5 2], [0 15 8 15], 'OpenGL rendering');
        jRadioOpenNone = gui_component('Radio', jPanelOpengl, '',   'OpenGL: Disabled (no transparency)', [], [], []);
        jRadioOpenSoft = gui_component('Radio', jPanelOpengl, 'br', 'OpenGL: Software (slow)', [], [], []);
        jRadioOpenHard = gui_component('Radio', jPanelOpengl, 'br', 'OpenGL: Hardware (accelerated)', [], [], []);
        % Group buttons
        jButtonGroup = ButtonGroup();
        jButtonGroup.add(jRadioOpenNone);
        jButtonGroup.add(jRadioOpenSoft);
        jButtonGroup.add(jRadioOpenHard);
        % On mac systems: opengl software is not supported
        if strncmp(computer,'MAC',3)
            jRadioOpenSoft.setEnabled(0);
        end
    jPanelLeft.add('br hfill', jPanelOpengl);
    % ===== LEFT: INTERFACE SCALING =====
    jPanelScaling = gui_river([5 2], [0 0 5 0], 'Interface scaling (%)');
        % Slider labels
        labelTable = java.util.Hashtable();
        labelTable.put(uint32(1), gui_component('label',[],'','100'));
        labelTable.put(uint32(2), gui_component('label',[],'','125'));
        labelTable.put(uint32(3), gui_component('label',[],'','150'));
        labelTable.put(uint32(4), gui_component('label',[],'','200'));
        labelTable.put(uint32(5), gui_component('label',[],'','250'));
        labelTable.put(uint32(6), gui_component('label',[],'','300'));
        labelTable.put(uint32(7), gui_component('label',[],'','400'));
        % Slider config
        jSliderScaling = JSlider(1,7,1);
        jSliderScaling.setLabelTable(labelTable);
        jSliderScaling.setPaintTicks(1);
        jSliderScaling.setMajorTickSpacing(1);
        jSliderScaling.setPaintLabels(1);
        jPanelScaling.add('hfill', jSliderScaling);
    jPanelLeft.add('br hfill', jPanelScaling);

    % ===== RIGHT =====
    jPanelRight = gui_river();
    jPanelNew.add(jPanelRight);
    % ===== RIGHT: FOLDERS =====
    jPanelFolders = gui_river([5 5], [0 15 15 15], 'Installation folders');
        % Temporary directory
        gui_component('Label', jPanelFolders, '', 'Brainstorm temporary directory: ', [], [], []);
        jTextTempDir   = gui_component('Text', jPanelFolders, 'br hfill', '', [], [], []);
        jButtonTempDir = gui_component('Button', jPanelFolders, [], '...', [], [], @TempDirectory_Callback);
        jButtonTempDir.setMargin(Insets(2,2,2,2));
        jButtonTempDir.setFocusable(0);
        % BrainSuite folder
        gui_component('Label', jPanelFolders, 'br', 'BrainSuite installation folder: ', [], [], []);
        jTextBsDir   = gui_component('Text', jPanelFolders, 'br hfill', '', [], [], []);
        jButtonBsDir = gui_component('Button', jPanelFolders, [], '...', [], [], @BsDirectory_Callback);
        jButtonBsDir.setMargin(Insets(2,2,2,2));
        jButtonBsDir.setFocusable(0);
        % Python executable
        jLabelPythonExe  = gui_component('Label', jPanelFolders, 'br', 'Python executable: ', [], [], []);
        jTextPythonExe   = gui_component('Text', jPanelFolders, 'br hfill', '', [], [], []);
        jButtonPythonExe = gui_component('Button', jPanelFolders, [], '...', [], [], @PythonExe_Callback);
        jButtonPythonExe.setMargin(Insets(2,2,2,2));
        jButtonPythonExe.setFocusable(0);
        if ~exist('pyenv', 'builtin') && ~exist('pyversion', 'builtin')
            jLabelPythonExe.setEnabled(0);
            jTextPythonExe.setEnabled(0);
            jButtonPythonExe.setEnabled(0);
        end
    jPanelRight.add('br hfill', jPanelFolders);

    % ===== RIGHT: SIGNAL PROCESSING =====
    jPanelProc = gui_river([5 5], [0 15 15 15], 'Processing');
        jCheckUseSigProc = gui_component('CheckBox', jPanelProc, 'br', 'Use Signal Processing Toolbox (Matlab)',    [], 'If selected, some processes will use the Matlab''s Signal Processing Toolbox functions.
Else, use only the basic Matlab function.', []);
        jBlockSizeLabel = gui_component('Label',  jPanelProc, 'br', 'Memory block size in Mb (default: 100Mb): ', [], [], []);
        blockSizeTooltip = 'Maximum size of data blocks to be read in memory, in megabytes.
Ensure this does not exceed the available RAM in your computer.';
        jBlockSize = gui_component('Text',  jPanelProc, [], '', [], [], []);
        jBlockSizeLabel.setToolTipText(blockSizeTooltip);
        jBlockSize.setToolTipText(blockSizeTooltip);
    jPanelRight.add('br hfill', jPanelProc);

    % ===== RIGHT: RESET =====
    if (GlobalData.Program.GuiLevel == 1)
        jPanelReset = gui_river([5 5], [0 15 15 15], 'Reset Brainstorm');
            gui_component('Label',  jPanelReset, [], 'Reset database and options to defaults: ', [], [], []);
            gui_component('Button', jPanelReset, [], 'Reset', [], [], @ButtonReset_Callback);
            gui_component('Label',  jPanelReset, 'br', 'Empty temporary directory: ', [], [], []);
            gui_component('Button', jPanelReset, [], 'Empty', [], [], @(h,ev)gui_brainstorm('EmptyTempFolder', 1));
        jPanelRight.add('br hfill', jPanelReset);
    end

    % ===== BOTTOM =====
    jPanelBottom = gui_river();
    jPanelNew.add('br hfill', jPanelBottom);
    % MEMORY
    [MaxVar, TotalMem] = bst_get('SystemMemory');
    if ~isempty(MaxVar) && ~isempty(TotalMem)
        % Display memory info
        jPanelMem = gui_river([0 0], [0 15 8 15]);
        labelBottom = sprintf('Max variable size: %d Mb       Memory available: %d Mb', MaxVar, TotalMem);
        jPanelLeft.add('br hfill', jPanelMem);
    else
        labelBottom = '';
    end

    % ===== VALIDATION BUTTONS =====
    gui_component('Label', jPanelBottom, '', labelBottom, [], [], []);
    gui_component('Label', jPanelBottom, 'hfill', ' ');
    gui_component('Button', jPanelBottom, 'right', 'Cancel', [], [], @ButtonCancel_Callback);
    gui_component('Button', jPanelBottom, [], 'Save', [], [], @ButtonSave_Callback);

    % ===== LOAD OPTIONS =====
    LoadOptions();

    % ===== CREATE PANEL =====
    bstPanelNew = BstPanel(panelName, ...
                           jPanelNew, ...
                           struct());

%% =================================================================================
%  === CONTROLS CALLBACKS  =========================================================
%  =================================================================================
%% ===== LOAD OPTIONS =====
    function LoadOptions()
        % GUI
        jCheckForceComp.setSelected(bst_get('ForceMatCompression'));
        jCheckUpdates.setSelected(bst_get('AutoUpdates'));
        jCheckGfp.setSelected(bst_get('DisplayGFP'));
        jCheckDownsample.setSelected(bst_get('DownsampleTimeSeries') > 0);
        jCheckIgnoreMem.setSelected(bst_get('IgnoreMemoryWarnings'));
        if ~isempty(jCheckSmooth)
            jCheckSmooth.setSelected(bst_get('GraphicsSmoothing') > 0);
        end
        if ~isempty(jCheckSystemCopy)
            jCheckSystemCopy.setSelected(bst_get('SystemCopy'));
        end
        switch bst_get('DisableOpenGL')
            case 0
                jRadioOpenHard.setSelected(1);
            case 1
                jRadioOpenNone.setSelected(1);
            case 2
                if strncmp(computer,'MAC',3)
                    jRadioOpenHard.setSelected(1);
                else
                    jRadioOpenSoft.setSelected(1);
                end
        end
        % Interface scaling
        switch (bst_get('InterfaceScaling'))
            case 100,       jSliderScaling.setValue(1);
            case 125,       jSliderScaling.setValue(2);
            case 150,       jSliderScaling.setValue(3);
            case {175,200}, jSliderScaling.setValue(4);
            case 250,       jSliderScaling.setValue(5);
            case 300,       jSliderScaling.setValue(6);
            case 400,       jSliderScaling.setValue(7);
        end
        % Temporary folder
        jTextTempDir.setText(bst_get('BrainstormTmpDir'));
        % BrainSuite folder
        jTextBsDir.setText(bst_get('BrainSuiteDir'));
        % Python config
        jTextPythonExe.setText(bst_get('PythonExe'));
        % Use signal processing toolbox
        isToolboxInstalled = (exist('kaiserord', 'file') > 0);
        jCheckUseSigProc.setEnabled(isToolboxInstalled);
        jCheckUseSigProc.setSelected(bst_get('UseSigProcToolbox'));
        processOptions = bst_get('ProcessOptions');
        jBlockSize.setText(num2str(processOptions.MaxBlockSize * 8 / 1024 / 1024));
    end

%% ===== SAVE OPTIONS =====
    function SaveOptions()
        bst_progress('start', 'Brainstorm preferences', 'Applying preferences...');
        % ===== GUI =====
        bst_set('ForceMatCompression', jCheckForceComp.isSelected());
        bst_set('AutoUpdates', jCheckUpdates.isSelected());
        bst_set('DisplayGFP',  jCheckGfp.isSelected());
        bst_set('IgnoreMemoryWarnings',  jCheckIgnoreMem.isSelected());
        if jCheckDownsample.isSelected()
            bst_set('DownsampleTimeSeries', 5);
        else
            bst_set('DownsampleTimeSeries', 0);
        end
        if ~isempty(jCheckSystemCopy)
            bst_set('SystemCopy', jCheckSystemCopy.isSelected());
        end
        if ~isempty(jCheckSmooth)
            % Update value
            isSmoothing = jCheckSmooth.isSelected();
            isChangedSmoothing = (bst_get('GraphicsSmoothing') ~= isSmoothing);
            bst_set('GraphicsSmoothing', isSmoothing);
            % Update open figures
            if isChangedSmoothing
                % Get all figures
                hFigAll = bst_figures('GetFiguresByType', {'DataTimeSeries', 'ResultsTimeSeries', '3DViz', 'Topography', 'MriViewer', 'Timefreq', 'Spectrum', 'Pac', 'Image'});
                % Set figurs properties
                if ~isempty(hFigAll)
                    if isSmoothing
                        set(hFigAll, 'GraphicsSmoothing', 'on');
                    else
                        set(hFigAll, 'GraphicsSmoothing', 'off');
                    end
                end
            end
        end

        % === OPENGL ===
        % Get selected status
        if jRadioOpenHard.isSelected()
            DisableOpenGL = 0;
        elseif jRadioOpenNone.isSelected()
            DisableOpenGL = 1;
        else
            DisableOpenGL = 2;
        end
        % Apply changes
        if (DisableOpenGL ~= bst_get('DisableOpenGL'))
            bst_set('DisableOpenGL', DisableOpenGL);
            StartOpenGL();
        end

        % ===== INTERFACE SCALING =====
        previousScaling = bst_get('InterfaceScaling');
        switch (jSliderScaling.getValue())
            case 1,  InterfaceScaling = 100;
            case 2,  InterfaceScaling = 125;
            case 3,  InterfaceScaling = 150;
            case 4,  InterfaceScaling = 200;
            case 5,  InterfaceScaling = 250;
            case 6,  InterfaceScaling = 300;
            case 7,  InterfaceScaling = 400;
        end
        bst_set('InterfaceScaling', InterfaceScaling);

        % ===== DATA IMPORT =====
        % Temporary directory
        oldTmpDir = bst_get('BrainstormTmpDir');
        newTmpDir = char(jTextTempDir.getText());
        if ~file_compare(oldTmpDir, newTmpDir)
            % Make sure it is different from and does not contain the database directory
            dbDir = bst_get('BrainstormDbDir');
            if file_compare(newTmpDir, dbDir)
                java_dialog('warning', 'Your temporary and database directories must be different.');
            elseif dir_contains(newTmpDir, dbDir)
                java_dialog('warning', 'Your temporary directory cannot contain your database directory.');
            else
                % If resetting tmp directory with an empty value
                if isempty(newTmpDir)
                    bst_set('BrainstormTmpDir', '');
                % If temp directory changed: create directory if it doesn't exist
                elseif file_exist(newTmpDir) || mkdir(newTmpDir)
                    bst_set('BrainstormTmpDir', newTmpDir);
                else
                    java_dialog('warning', 'Could not create temporary directory.');
                end
            end
        end
        % BrainSuite directory
        oldBsDir = bst_get('BrainSuiteDir');
        newBsDir = char(jTextBsDir.getText());
        if ~file_compare(oldBsDir, newBsDir)
            % Folder doesn't exist
            if ~isempty(newBsDir) && ~file_exist(newBsDir)
                java_dialog('warning', 'Selected BrainSuite folder doesn''t exist. Ignoring...');
            elseif ~isempty(newBsDir) && ~file_exist(bst_fullfile(newBsDir, 'bdp'))
                java_dialog('warning', 'Selected folder does not contain a valid BrainSuite install (missing "bdp" folder). Ignoring...');
            else
                bst_set('BrainSuiteDir', newBsDir);
            end
        end

        % ===== PYTHON =====
        % Get saved configuration
        oldPythonExe = bst_get('PythonExe');
        % Get new configuration
        newPythonExe = char(jTextPythonExe.getText());
        % If something changed
        if ~isequal(newPythonExe, oldPythonExe)
            % Save new values in user preferences
            bst_set('PythonExe', newPythonExe);
            % Set the new version of Python in Matlab
            try
                [pyVer, newPythonExe, isLoaded] = bst_python_ver(newPythonExe);
            catch
                bst_error('You must close and restart Matlab for this change to take effect.', 'Python exectutable', 0);
            end
            % Initialize Python if possible
            bst_python_init('Initialize', 1);
        end

        % ===== PROCESSING OPTIONS =====
        % Use signal processing toolbox
        bst_set('UseSigProcToolbox', jCheckUseSigProc.isSelected());
        % Memory block size (Valid values: between 1MB and 1TB)
        blockSize = str2num(jBlockSize.getText());
        if ~isempty(blockSize) && blockSize >= 1 && blockSize <= 1e6
            processOptions = bst_get('ProcessOptions');
            processOptions.MaxBlockSize = blockSize * 1024 * 1024 / 8; % Mb to bytes
            bst_set('ProcessOptions', processOptions);
        end
        bst_progress('stop');

        % If the scaling was changed: Restart brainstorm
        if (previousScaling ~= InterfaceScaling)
            brainstorm stop;
            brainstorm;
        end
    end

%% ===== SAVE OPTIONS =====
    function ButtonSave_Callback(varargin)
        % Save options
        SaveOptions()
        % Hide panel
        gui_hide(panelName);
    end

%% ===== CANCEL BUTTON =====
    function ButtonCancel_Callback(varargin)
        % Hide panel
        gui_hide(panelName);
    end

%% ===== TEMP DIRECTORY SELECTION =====
    % Callback for '...' button
    function TempDirectory_Callback(varargin)
        % Get the initial path
        initDir = bst_get('BrainstormTmpDir', 1);
        % Open 'Select directory' dialog
        tempDir = uigetdir(initDir, 'Select temporary directory.');
        % If no directory was selected : return without doing anything
        if (isempty(tempDir) || (tempDir(1) == 0))
            return
        end
        % Else : update control text
        jTextTempDir.setText(tempDir);
        % Focus main brainstorm figure
        jBstFrame = bst_get('BstFrame');
        jBstFrame.setVisible(1);
    end

%% ===== BRAINSUITE DIRECTORY SELECTION =====
    % Callback for '...' button
    function BsDirectory_Callback(varargin)
        % Get the initial path
        initDir = bst_get('BrainSuiteDir', 1);
        % Open 'Select directory' dialog
        bsDir = uigetdir(initDir, 'Select BrainSuite directory.');
        % If no directory was selected : return without doing anything
        if (isempty(bsDir) || (bsDir(1) == 0) || (~isempty(initDir) && file_compare(initDir, bsDir)))
            return;
        % Directory is not a valid folder
        elseif ~file_exist(bst_fullfile(bsDir, 'bdp'))
            java_dialog('warning', 'Selected folder does not contain a valid BrainSuite install (missing folder "bdp").');
            return;
        end
        % Else : update control text
        jTextBsDir.setText(bsDir);
        % Focus main brainstorm figure
        jBstFrame = bst_get('BstFrame');
        jBstFrame.setVisible(1);
    end

%% ===== PYTHON EXECUTABLE =====
    % Callback for '...' button
    function PythonExe_Callback(varargin)
        % Get the initial path
        initExe = bst_get('PythonExe');
        % Ask for python path
        newExe = java_getfile( 'open', ...
            'Select Python executable', ...  % Window title
            bst_fileparts(initExe), 'single', 'files', ...     % Default directory, Selection mode
            {{'*'}, 'Python executable (version 3.5 or higher)', 'Python'}, 'Python');
        if isempty(newExe) || isequal(initExe, newExe)
            return;
        end
        % Else : update control text
        jTextPythonExe.setText(newExe);
        % Focus main brainstorm figure
        jBstFrame = bst_get('BstFrame');
        jBstFrame.setVisible(1);
    end

% %% ===== QT DIRECTORY SELECTION =====
%     % Callback for '...' button
%     function QtDirectory_Callback(varargin)
%         % Get the initial path
%         PythonConfig = bst_get('PythonConfig', 1);
%         initDir = PythonConfig.QtDir;
%         % Open 'Select directory' dialog
%         qtDir = uigetdir(initDir, 'Select Qt plugin directory.');
%         % If no directory was selected : return without doing anything
%         if (isempty(qtDir) || (qtDir(1) == 0) || (~isempty(initDir) && file_compare(initDir, qtDir)))
%             return;
%         % Directory is not avalid Qt folder (test on windows only)
%         elseif ispc && ~file_exist(bst_fullfile(qtDir, 'qwindows.dll'))
%             java_dialog('warning', 'Selected folder does not contain a valid Qt plugin install (qwindows.dll missing).');
%             return;
%         end
%         % Else : update control text
%         jTextQtDir.setText(qtDir);
%         % Focus main brainstorm figure
%         jBstFrame = bst_get('BstFrame');
%         jBstFrame.setVisible(1);
%     end
%
% %% ===== ADD PYTHON PATH =====
%     % Callback for '+' button
%     function AddPath_Callback(varargin)
%         % Get the initial path
%         PythonConfig = bst_get('PythonConfig', 1);
%         if ~isempty(PythonConfig.PythonPath)
%             initPath = str_split(PythonConfig.PythonPath);
%             initDir = initPath{1};
%         else
%             initPath = {};
%             initDir = [];
%         end
%         % Open 'Select directory' dialog
%         addDir = uigetdir(initDir, 'Add folder to system path');
%         % If no directory was selected : return without doing anything
%         if (isempty(addDir) || (addDir(1) == 0) || ismember(addDir, initPath))
%             return;
%         end
%         % New python path
%         if ~isempty(PythonConfig.PythonPath)
%             newPath = [PythonConfig.PythonPath, pathsep, addDir];
%         else
%             newPath = addDir;
%         end
%         % Else : update control text
%         jTextPythonPath.setText(newPath);
%         % Focus main brainstorm figure
%         jBstFrame = bst_get('BstFrame');
%         jBstFrame.setVisible(1);
%     end
end

%% ===== START OPENGL =====
function [isOpenGL, DisableOpenGL] = StartOpenGL()
    global GlobalOpenGLStatus;
    % Get configuration
    DisableOpenGL = bst_get('DisableOpenGL');
    isOpenGL = 1;
    isUnixWarning = 0;

    % ===== MATLAB < 2014b =====
    if (bst_get('MatlabVersion') < 804)
        % Define OpenGL options
        switch DisableOpenGL
            case 0
                if strncmp(computer,'MAC',3)
                    OpenGLMode = 'autoselect';
                elseif isunix && ~isempty(GlobalOpenGLStatus)
                    OpenGLMode = 'autoselect';
                    disp('BST> Warning: You have to restart Matlab to switch between software and hardware OpenGL.');
                else
                    OpenGLMode = 'hardware';
                end
                FigureRenderer = 'opengl';
            case 1
                OpenGLMode = 'neverselect';
                FigureRenderer = 'zbuffer';
            case 2
                if strncmp(computer,'MAC',3)
                    OpenGLMode = 'autoselect';
                elseif isunix && ~isempty(GlobalOpenGLStatus)
                    OpenGLMode = 'autoselect';
                    disp('BST> Warning: You have to restart Matlab to switch between software and hardware OpenGL.');
                else
                    OpenGLMode = 'software';
                end
                FigureRenderer = 'opengl';
        end
        % Configure OpenGL
        try
            opengl(OpenGLMode);
        catch
            isOpenGL = 0;
        end
        % Check that OpenGL is running
        s = opengl('data');
        if isempty(s) || isempty(s.Version)
            isOpenGL = 0;
        end
        % Figure types for which the OpenGL renderer is used
        figTypes = {'3DViz', 'Topography', 'MriViewer', 'Timefreq', 'Pac', 'Image'};

    % ===== MATLAB >= 2014b =====
    else
        % Start OpenGL
        s = opengl('data');
        if isempty(s) || isempty(s.Version)
            isOpenGL = 0;
        end
        % Linux: Cannot change the OpenGL mode at runtime
        if isunix
            if ~isOpenGL
                DisableOpenGL = 1;
            % If the requested configuration is not the current OpenGL status: Error
            elseif (DisableOpenGL == 0) && (s.Software == 1)
                isUnixWarning = 1;
                DisableOpenGL = 2;
                bst_set('DisableOpenGL', DisableOpenGL);
            elseif (DisableOpenGL == 2) && (s.Software == 0)
                isUnixWarning = 1;
                DisableOpenGL = 0;
                bst_set('DisableOpenGL', DisableOpenGL);
            end
        % MacOSX: No software OpenGL
        elseif strncmp(computer,'MAC',3)
            % Nothing to do
        % Windows: Try to change the current status hardware/software
        else
            try
                if (DisableOpenGL == 0)
                    opengl('hardware');
                elseif (DisableOpenGL == 2)
                    opengl('software');
                end
                s = opengl('data');
            catch
                isOpenGL = 0;
            end
        end
        % Configure OpenGL
        switch DisableOpenGL
            case 0,  FigureRenderer = 'opengl';
            case 1,  FigureRenderer = 'painters';
            case 2,  FigureRenderer = 'opengl';
        end
        % Figure types for which the OpenGL renderer is used
        figTypes = {'DataTimeSeries', 'ResultsTimeSeries', 'Spectrum', '3DViz', 'Topography', 'MriViewer', 'Timefreq', 'Pac', 'Image'};
    end

    % Add comment if not running Brainstorm
    if isappdata(0, 'BrainstormRunning')
        fprintf(1, 'BST> OpenGL status: ');
    end
    % If OpenGL is running: save status
    if isOpenGL
        GlobalOpenGLStatus = DisableOpenGL;
        if (DisableOpenGL == 1)
            disp('disabled');
        elseif s.Software
            disp('software');
        else
            disp('hardware');
        end
    else
        GlobalOpenGLStatus = -1;
        FigureRenderer = 'painters';
        disp('failed');
    end

    % Display warning
    if isUnixWarning
        disp('BST> Warning: Switching between hardware and software at runtime is not possible on Linux systems.');
        disp('BST> To force Matlab to use the software OpenGL: matlab -softwareopengl');
        disp('BST> To force Matlab to use the hardware OpenGL: matlab -nosoftwareopengl');
    end

    % ===== UPDATE FIGURES =====
    % Get all figures
    hFigAll = bst_figures('GetFiguresByType', figTypes);
    % Set figures renderers
    if ~isempty(hFigAll)
        bst_progress('start', 'OpenGL configuration', 'Updating figures...');
        set(hFigAll, 'Renderer', FigureRenderer);
        drawnow;
        bst_progress('stop');
    end
end

%% ===== BUTTON: RESET =====
function ButtonReset_Callback(varargin)
    % Ask user confirmation
    isConfirm = java_dialog('confirm', ...
        ['You are about to reinitialize your Brainstorm installation, this will:' 10 10 ...
         ' - Detach all the protocols from the database (without deleting any file)' 10 ...
         ' - Reset all the Brainstorm and processes preferences' 10 ...
         ' - Restart Brainstorm as if it was the first time on this computer' 10 10 ...
         'Reset Brainstorm now?' 10 10], ...
        'Reset Brainstorm');
    if ~isConfirm
        return;
    end
    % Close panel
    gui_hide('Preferences');
    % Reset and restart brainstorm
    brainstorm stop;
    brainstorm reset;
    brainstorm;
end

%% ===== SYSTEM PATH: REMOVE DIR =====
% USAGE:         panel_options('SystemPathRemove', rmPath)          % Update system path
%         PATH = panel_options('SystemPathRemove', rmPath, PATH)    % Update user defined path (do not change system path)
function PATH = SystemPathRemove(rmPath, PATH)
    % Parse inputs
    if (nargin < 2)
        PATH = getenv('PATH');
        isSystemPath = 1;
    else
        isSystemPath = 0;
    end
    % Get system path
    PATH = getenv('PATH');
    PATH_split = str_split(PATH, pathsep);
    % Find elements to remove
    rm_split = str_split(rmPath, pathsep);
    iRm = find(ismember(PATH_split, rm_split));
    if isempty(iRm)
        return;
    end
    % Display removed path
    for i = 1:length(iRm)
        disp(['BST> Removed from system path:  ' PATH_split{iRm(i)}]);
    end
    % Remove elements from path string
    PATH_split(iRm) = [];
    PATH = '';
    for i = 1:length(PATH_split)
        if (i == 1)
            PATH = PATH_split{i};
        else
            PATH = [PATH, pathsep, PATH_split{i}];
        end
    end
    % Update system path
    if isSystemPath
        setenv('PATH', PATH);
    end
end

%% ===== SYSTEM PATH: ADD DIR =====
% USAGE:         panel_options('SystemPathAdd', rmPath)          % Update system path
%         PATH = panel_options('SystemPathAdd', rmPath, PATH)    % Update user defined path (do not change system path)
function PATH = SystemPathAdd(addPath, PATH)
    % Parse inputs
    if (nargin < 2)
        PATH = getenv('PATH');
        isSystemPath = 1;
    else
        isSystemPath = 0;
    end
    % Get system path
    PATH_split = str_split(PATH, pathsep);
    % Check which folders are not yet in the system path
    add_split = str_split(addPath, pathsep);
    for iPath = 1:length(add_split)
        if isdir(add_split{iPath}) && ~ismember(add_split{iPath}, PATH_split)
            PATH = [PATH, pathsep, add_split{iPath}];
            disp(['BST> Added to system path: ' add_split{iPath}]);
        end
    end
    % Update system path
    if isSystemPath
        setenv('PATH', PATH);
    end
end


classdef ImprovedInputParser < inputParser
    %

    % This file is part of the Matlab Toolbox TENSALG for Tensor Algebra,
    % developed under the BSD Licence.
    % See the LICENSE file for conditions.

    properties
        unmatchedArgs
    end

    methods
        function p = ImprovedInputParser()
            p@inputParser();
            p.KeepUnmatched = true;
        end
        function parse(p,varargin)
            parse@inputParser(p,varargin{:});
            makeUnmatchedArgs(p);
        end

        function makeUnmatchedArgs(p)
            tmp = [fieldnames(p.Unmatched), ...
                struct2cell(p.Unmatched)];
            p.unmatchedArgs = reshape(tmp',[],1)';
        end

        function obj = passMatchedArgsToProperties(p,obj)
            fNames = fieldnames(p.Results);
            for k = 1:numel(fNames)
                obj.(fNames{k}) = p.Results.(fNames{k});
            end
        end
    end
end


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

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @deftypefn  {Function File} {} print_usage ()
%% Wrapper for print_usage on Matlab.
%%
%% Matlab has no print_usage function.  Preparing
%% the Matlab package should rename this from
%% "my_print_usage.m" to "print_usage.m".
%%
%% @seealso{error}
%% @end deftypefn

function print_usage ()

  % if we are on Octave
  if (exist ('OCTAVE_VERSION', 'builtin'))
    %evalin ('caller', 'print_usage ();' );
    %return
  end

  H = dbstack;
  name = H(2).name;

  msgid = sprintf('%s:invalidCall', name);
  errmsg = sprintf('Invalid call to "%s": see documentation', name);

  %error('Invalid call to "%s": see documentation', name)
  ME = MException(msgid, errmsg);
  ME.throwAsCaller();

end


function outputWaveforms = load_antelope(obj, specificDatabase)
   % load a waveform from antelope
   %  w = obj.load_antelope(specificDatabase)
   %   database is the antelope database

   % AUTHOR: Celso Reyes
   % MODIFICATIONS: Glenn Thompson, Carl Tape

   %TODO: maybe order of operations can be changed to avoid unpacking
   %request when unnecessary.

   %call this routine for each database, then return the waveforms.
   if exist('specificDatabase','var')
      obj.dbname = specificDatabase;
      outputWaveforms = emptyWaveform();

      %convert each channeltag into
      obj = obj.buildSearchCriteria();
      for i = 1:numel(obj.searchcriteria)
         %if multiple traces will result, then there may be multiple records for tr
         [tr, dbname, fdb] = get_antelope_traces(obj, obj.searchcriteria{i});
         w = cycleThroughTraces(tr, obj.combinetraces);
         outputWaveforms = [outputWaveforms; w]; %#ok<AGROW>
      end
      dbclose(fdb);
   else
      outputWaveforms = RecursivelyLoadFromEachDatabase(obj);
   end
end


function so = streamFilter(si,filter,varargin)
% STREAMFILTER  Filtered stream
while ~builtin('feval',filter,head(si),varargin{:})
    si = tail(si);
end
so = {head(si),delayEval(@streamFilter,{tail(si),filter,varargin{:}})};


function nocancel = cinchGenerateData (dt6file, datapath)
nocancel = true;
if ~exist(datapath, 'dir')
        r = questdlg ('CINCH data has not yet been created for this subject. Do this now? (Warning: This could take a minute or two!)');
        if (~strcmp (r,'Yes'))
            nocancel = false;
            return;
        end;
    h = mrvWaitbar(0,'Please wait...');
    dtiConvertDT6ToBinaries (dt6file, datapath);
    close(h);
end;
return;


function [ state ] = getPin13State( t )
%% This function is used to get the state of the input pin 13
%     on the media flange, of the KUKA iiwa 7 R 800.

%% Syntax:
% [ state ] = getPin13State( t )

%% About:
% This function is used to get the state of the input pin number 13
%  on the media flange, of the KUKA iiwa 7 R 800.

%% Arreguments:
% t: is the TCP/IP connection.
% state:  represents the state of the input-pin. It is an integer equal to
% 1 when the pin state is true, or it is an integer equal to 0 when the
% pin state is false. Otherwise, if the pin is not connected the return
% value is empty.

% Copyright, Mohammad SAFEEA, 9th of May 2017

theCommand='getPin13';
fprintf(t, theCommand);
message=fgets(t);
state=str2num(message);
end


%GETPREPROC Get datafile PREPROC field
%
%	   PREPROC = GETPREPROC(A)
%
% Retrieves the PREPROC field of the datafile A. This is a
% structure array with two fields:
% - preproc: a string with a command name
% - pars:    a cell array with parameters
%
%    [COMMAND,PARS]  = GETPREPROC(A,N)
%
% In this case just the command name and the parameter cell array of
% the N-th preprocessing command are returned.
%
% or just the name of the N-th file.
% If N larger than the number of stored commands, COMMAND and PARS
% will be empty.


function results = spm_tests(varargin)
% Unit Testing Framework
% FORMAT results = spm_tests(name,value,...)
% name,value  - pairs of optional parameter names and values:
%     verbose:   verbosity level of test run progress report [default: 2]
%     display:   display test results [default: false]
%     coverage:  display code coverage [default: false]
%     cobertura: save code coverage results in the Cobertura XML format [default: false]
%     tag:       test tag selector [default: '', ie all tests]
%     tap:       save a Test Anything Protocol (TAP) file [default: false]
%     test:      name of function to test [default: '', ie all tests]
%
% results     - TestResult array containing information describing the
%               result of running the test suite.
%__________________________________________________________________________
% Copyright (C) 2015-2019 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_tests.m 7548 2019-03-20 10:08:49Z guillaume $

if spm_check_version('matlab','8.3') < 0
    error('Unit Tests require MATLAB R2014a or above.');
end

SVNid = '$Rev: 7548 $';
SPMid = spm('FnBanner',mfilename,SVNid);

%-Input parameters
%--------------------------------------------------------------------------
options = struct('verbose',2, 'display',false, 'coverage',false, ...
                 'cobertura',false, 'tag', '', 'tap',false, 'test','');
if nargin
    if isstruct(varargin{1})
        fn = fieldnames(varargin{1});
        for i=1:numel(fn)
            options.(fn{i}) = varargin{1}.(fn{i});
        end
    else
        for i=1:2:numel(varargin)
            options.(varargin{i}) = varargin{i+1};
        end
    end
end

%-Unit tests
%==========================================================================

%-Create a TestSuite
%--------------------------------------------------------------------------
import matlab.unittest.TestSuite;
import matlab.unittest.selectors.*;
tests = fullfile(spm('Dir'),'tests');
if isempty(options.test)
    suite = TestSuite.fromFolder(tests, 'IncludingSubfolders', true);
else
    suite = [];
    options.test = cellstr(options.test);
    for i=1:numel(options.test)
        prefix = 'test_';
        if strncmp(options.test{i},prefix,length(prefix))
            prefix = '';
        end
        mtest = fullfile(tests,[prefix spm_file(options.test{i},'ext','.m')]);
        if ~spm_existfile(mtest)
            warning('SPM:tests:fileNotFound',...
                'No tests found for %s',options.test{i});
            continue
        end
        suite = [suite, TestSuite.fromFile(mtest)];
        % if i==1
        %     suite = TestSuite.fromFile(mtest);
        % else
        %     suite(i) = TestSuite.fromFile(mtest);
        % end
    end
end
if ~isempty(options.tag)
    suite = suite.selectIf(~HasTag | HasTag(options.tag));
end

%-Create a TestRunner
%--------------------------------------------------------------------------
import matlab.unittest.TestRunner;
import matlab.unittest.plugins.*
if ~options.verbose
    runner = TestRunner.withNoPlugins;
else
    runner = TestRunner.withTextOutput('Verbosity',options.verbose);
end

if options.coverage
    plugin = CodeCoveragePlugin.forFolder(spm('Dir'));
    runner.addPlugin(plugin);
end

if options.cobertura
    d = getenv('WORKSPACE');
    if isempty(d), d = spm('Dir'); end
    coberturaFile = fullfile(d,'spm_CoverageResults.xml');
    plugin = CodeCoveragePlugin.forFolder(spm('Dir'),...
        'Producing',codecoverage.CoberturaFormat(coberturaFile));
    runner.addPlugin(plugin);
end

if options.tap
    d = getenv('WORKSPACE');
    if isempty(d), d = spm('Dir'); end
    tapFile = fullfile(d,'spm_tests.tap');
    plugin = TAPPlugin.producingVersion13(ToFile(tapFile));
    runner.addPlugin(plugin);
end

%-Run tests
%--------------------------------------------------------------------------
if ~isempty(suite)
    results = runner.run(suite);
else
    results = struct('Passed',{},'Failed',{},'Incomplete',{},'Duration',{});
end

%-Display test results
%--------------------------------------------------------------------------
if options.display
    fprintf(['Totals (%d tests):\n\t%d Passed, %d Failed, %d Incomplete.\n' ...
        '\t%f seconds testing time.\n\n'],numel(results),nnz([results.Passed]),...
        nnz([results.Failed]),nnz([results.Incomplete]),sum([results.Duration]));

    disp(table(results));
end


% Downloaded from MatLab FileExchange as part of the findjobj submission by
% Yair M Altman at
%   https://www.mathworks.com/matlabcentral/fileexchange/14317-findjobj-find-java-handles-of-matlab-graphic-objects
% Thus this falls under the same open license as described by Yair in
% license.txt of his download.
% Programmed and Copyright by Yair M. Altman: altmany(at)gmail.com
% $Revision: 1.1 $  $Date: 2020/02/07 07:00:36 $
function jControl = findjobj_fast(hControl, jContainer)
    try jControl = hControl.getTable; return, catch, end  % fast bail-out for old uitables
    try jControl = hControl.JavaFrame.getGUIDEView; return, catch, end  % bail-out for HG2 matlab.ui.container.Panel
    oldWarn = warning('off','MATLAB:HandleGraphics:ObsoletedProperty:JavaFrame');
    if nargin < 2 || isempty(jContainer)
        % Use a HG2 matlab.ui.container.Panel jContainer if the control's parent is a uipanel
        try
            hParent = get(hControl,'Parent');
        catch
            % Probably indicates an invalid/deleted/empty handle
            jControl = [];
            return
        end
        try jContainer = hParent.JavaFrame.getGUIDEView; catch, jContainer = []; end
    end
    if isempty(jContainer)
        hFig = ancestor(hControl,'figure');
        jf = get(hFig, 'JavaFrame');
        jContainer = jf.getFigurePanelContainer.getComponent(0);
    end
    warning(oldWarn);
    jControl = [];
    counter = 20;  % 2018-09-21 speedup (100 x 0.001 => 20 x 0.005) - Martin Lehmann suggestion on FEX 2016-06-07
    specialTooltipStr = '!@#$%^&*';
    try  % Fix for R2018b suggested by Eddie (FEX comment 2018-09-19)
        tooltipPropName = 'TooltipString';
        oldTooltip = get(hControl,tooltipPropName);
        set(hControl,tooltipPropName,specialTooltipStr);
    catch
        tooltipPropName = 'Tooltip';
        oldTooltip = get(hControl,tooltipPropName);
        set(hControl,tooltipPropName,specialTooltipStr);
    end
    while isempty(jControl) && counter>0
        counter = counter - 1;
        pause(0.005);
        jControl = findTooltipIn(jContainer, specialTooltipStr);
    end
    set(hControl,tooltipPropName,oldTooltip);
    try jControl.setToolTipText(oldTooltip); catch, end
    try jControl = jControl.getParent.getView.getParent.getParent; catch, end  % return JScrollPane if exists
end

function jControl = findTooltipIn(jContainer, specialTooltipStr)
    try
        jControl = [];  % Fix suggested by H. Koch 11/4/2017
        tooltipStr = jContainer.getToolTipText;
        %if strcmp(char(tooltipStr),specialTooltipStr)
        if ~isempty(tooltipStr) && tooltipStr.startsWith(specialTooltipStr)  % a bit faster
            jControl = jContainer;
        else
            for idx = 1 : jContainer.getComponentCount
                jControl = findTooltipIn(jContainer.getComponent(idx-1), specialTooltipStr);
                if ~isempty(jControl), return; end
            end
        end
    catch
        % ignore
    end
end


function cleanVolume()
%
% function cleanVolume()
%
% Deletes:
%   Volume/coords.mat
%   Volume/dataType/corAnal.mat (for each dataType)
%   Volume/dataType/*.mat (all other parameter maps)
%
% If you change this function make parallel changes in:
%     cleanFlat, cleanDataType
%
% djh, 2/2001

global HOMEDIR

curVolumeDir = fullfile(HOMEDIR,'Volume');
backupVolumeDir = fullfile(HOMEDIR,sprintf('deletedVolume_%s', ...
    datestr(now, 'yyyy-dd-mm-hh_MM-ss')));

if exist(curVolumeDir, 'dir')
    movefile(curVolumeDir, backupVolumeDir);
end


function newName = rename(oldName , format, varargin)
% rename(fileTest, '%s/<name>--DRIM.png', dirDrimResult)

[path, name, ext] = fileparts(oldName);
if numel(varargin) ~= 0
    format = sprintf(format, varargin{:});
end
newName = strrep(format, '<path>', path);
newName = strrep(newName, '<name>', name);
newName = strrep(newName, '<ext>', ext(2:end)); % no . mark
end


function viewGetDict = mrViewGetDictionarySetup(viewGetDict)
%
%
% USAGE:
%   This function is called upon initialization / first use to create
%   create the dictionary hash map for viewGet. This dictionary maps all of
%   the possible input combinations to the unique key that pertains to that
%   value.
%
% INPUT:
%   valueToTranslate - the orientation string, e.g. 'RAS'
%   searchString - the one character string to search for, e.g. 'S'
%   Note: the search string needs to be one of 'L','R','A','P','I','S'
%
% OUTPUT:
%   Number such that vectorString[number] = searchString
%   Note: if there are multiple occurences, then only the first one is
%   returned, along with a warning
%


function el = export_graphic_layer_module_field(args)
%"export_graphic_layer_module_field"
%   Returns a properly populated and formatted instance of tags in
%   graphic layer sequence.
%
%   For speed, tag must be a decimal representation of the 8 digit
%   hexidecimal DICOM tag desired, ie instead of '00100010', pass
%   hex2dec('00100010');
%
%   Arguments are passed in a structure, arg:
%       arg.tag         = decimal tag of field to fill
%       arg.data        = CERR structure(s) to fill from
%       arg.template    = an empty template of the module created by the
%                         function build_module_template.m
%
%   This function requires arg.data is a single doseS.
%
%APA 07/26/2019
%
%Usage:
%   dcmobj = export_rt_dose_module_field(args)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

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

%Unpack input data.
tag         = args.tag;
template    = args.template;

switch tag
    case 7340128   % 0070,0060
        templateEl  = template.getValue(tag);
        fHandle = @export_graphic_layer_sequence;

        %New null sequence
        tmp = org.dcm4che3.data.Attributes;
        el = tmp.newSequence(tag, 0);

        i = 1; % only one layer
        dcmobj = export_sequence(fHandle, templateEl, gspsS);
        %dcmobj = export_sequence(fHandle, tag, {structS(i), i});
        el.add(i-1, dcmobj);

        %get attribute to return
        el = el.getParent();

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


function fh = isolate_axes(ah, vis)
%ISOLATE_AXES Isolate the specified axes in a figure on their own
%
% Examples:
%   fh = isolate_axes(ah)
%   fh = isolate_axes(ah, vis)
%
% This function will create a new figure containing the axes/uipanels
% specified, and also their associated legends and colorbars. The objects
% specified must all be in the same figure, but they will generally only be
% a subset of the objects in the figure.
%
% IN:
%    ah - An array of axes and uipanel handles, which must come from the
%         same figure.
%    vis - A boolean indicating whether the new figure should be visible.
%          Default: false.
%
% OUT:
%    fh - The handle of the created figure.

% Copyright (C) Oliver Woodford 2011-2014, Yair Altman 2015-
%{
% Thank you to Rosella Blatt for reporting a bug to do with axes in GUIs
% 16/03/12: Moved copyfig to its own function. Thanks to Bob Fratantonio
%           for pointing out that the function is also used in export_fig.m
% 12/12/12: Add support for isolating uipanels. Thanks to michael for suggesting it
% 08/10/13: Bug fix to allchildren suggested by Will Grant (many thanks!)
% 05/12/13: Bug fix to axes having different units. Thanks to Remington Reid for reporting
% 21/04/15: Bug fix for exporting uipanels with legend/colorbar on HG1 (reported by Alvaro
%           on FEX page as a comment on 24-Apr-2014); standardized indentation & help section
% 22/04/15: Bug fix: legends and colorbars were not exported when exporting axes handle in HG2
% 02/02/21: Fix axes, figure size to preserve input axes image resolution (thanks @Optecks)
% 25/10/21: Bug fix: subplots were not isolated properly leading to print error (issue #347)
% 24/03/23: Remove any non-legendable objects from the legend (workaround for copyobj bug)
%}

    % Make sure we have an array of handles
    if ~all(ishandle(ah))
        error('ah must be an array of handles');
    end

    % Check that the handles are all for axes or uipanels, and are all in the same figure
    fh = ancestor(ah(1), 'figure');
    nAx = numel(ah);
    for a = 1:nAx
        if ~ismember(get(ah(a), 'Type'), {'axes', 'uipanel'})
            error('All handles must be axes or uipanel handles.');
        end
        if ~isequal(ancestor(ah(a), 'figure'), fh)
            error('Axes must all come from the same figure.');
        end
    end

    % Tag the objects so we can find them in the copy
    old_tag = get(ah, 'Tag');
    if nAx == 1
        old_tag = {old_tag};
    end
    set(ah, 'Tag', 'ObjectToCopy');

    % Mark all non-legendable objects in the original figure (if any legend shown)
    % a workaround to the copyobj bug of not copying the ApplicationData property
    lh = findall(fh, 'Tag','legend');
    if ~isempty(lh)
        ax = arrayfun(@(h) get(h,'Axes'), lh);
        c = findall(ax);
        hb = ~arrayfun(@(h)hasbehavior(h,'legend'), c);
        c = c(hb);
        oldTags = get(c,'Tag');
        set(c,'Tag','non-legendable!')
    end

    % Create a new figure exactly the same as the old one
    fh = copyfig(fh); %copyobj(fh, 0);

    % Fix Axes & Figure size for image catpuring to have almost exact resolution
    % of the Input Axes (thanks @Optecks)
    allaxes = findall(fh, 'type', 'axes');
    if ~isempty(ah)
        sz = get(ah(1), 'OuterPosition');
        un = get(ah(1), 'Units');
        set(allaxes(1), 'Units',un, 'OuterPosition', [0 0 sz(3) sz(4)]);
        set(allaxes(1), 'Units','pixels');
        sz = get(allaxes(1), 'OuterPosition');
        set(fh, 'Units','pixels', 'Position',[0 0 sz(3) sz(4)]+1);
    end

    if nargin < 2 || ~vis
        set(fh, 'Visible', 'off');
    end

    % Restore the axes tags in the original figure back to their original values
    for a = 1:nAx
        set(ah(a), 'Tag', old_tag{a});
    end

    % Find the objects to save
    ah = findall(fh, 'Tag', 'ObjectToCopy');
    if numel(ah) ~= nAx
        close(fh);
        error('Incorrect number of objects found.');
    end

    % Set the axes tags in the new figure to what they should be
    for a = 1:nAx
        set(ah(a), 'Tag', old_tag{a});
    end

    % Keep any legends and colorbars which overlap the subplots
    % Note: in HG1 these are axes objects; in HG2 they are separate objects, therefore we
    %       don't test for the type, only the tag (hopefully nobody but Matlab uses them!)
    lh = findall(fh, 'Tag','legend', '-or', 'Tag','Colorbar');
    nLeg = numel(lh);
    if nLeg > 0
        % Remove any non-legendable objects from the legend (if previously set)
        c2 = findall(ah,'Tag','non-legendable!');
        if ~isempty(c2)
            arrayfun(@(h)hasbehavior(h,'legend',false), c2);
            arrayfun(@(h,t)set(h,'Tag',t{1}),c,oldTags);  %restore object tags to orig values
        end

        set([ah(:); lh(:)], 'Units', 'normalized');
        try
            ax_pos = get(ah, 'OuterPosition'); % axes and figures have the OuterPosition property
        catch
            ax_pos = get(ah, 'Position'); % uipanels only have Position, not OuterPosition
        end
        if nAx > 1
            ax_pos = cell2mat(ax_pos(:));
        end
        ax_pos(:,3:4) = ax_pos(:,3:4) + ax_pos(:,1:2);
        try
            leg_pos = get(lh, 'OuterPosition');
        catch
            leg_pos = get(lh, 'Position');  % No OuterPosition in HG2, only in HG1
        end
        if nLeg > 1
            leg_pos = cell2mat(leg_pos);
        end
        leg_pos(:,3:4) = leg_pos(:,3:4) + leg_pos(:,1:2);
        ax_pos = shiftdim(ax_pos, -1);
        % Overlap test
        M = bsxfun(@lt, leg_pos(:,1), ax_pos(:,:,3)) & ...
            bsxfun(@lt, leg_pos(:,2), ax_pos(:,:,4)) & ...
            bsxfun(@gt, leg_pos(:,3), ax_pos(:,:,1)) & ...
            bsxfun(@gt, leg_pos(:,4), ax_pos(:,:,2));
        ah = [ah; lh(any(M, 2))];
    end

    % Get all the objects in the figure
    axs = findall(fh);

    % Delete everything except for the input objects and associated items
    delete(axs(~ismember(axs, [ah; allchildren(ah); allancestors(ah)])));
end

function ah = allchildren(ah)
    ah = findall(ah);
    if iscell(ah)
        ah = cell2mat(ah);
    end
    ah = ah(:);
end

function ph = allancestors(ah)
    ph = [];
    for a = 1:numel(ah)
        h = get(ah(a), 'parent');
        while h ~= 0
            ph = [ph; h]; %#ok<AGROW>
            h = get(h, 'parent');
        end
    end
end


function write_lines_with_prefix(obj, fn, decorator)
% write lines in mfile with prefix
%
% write_lines_with_prefix(obj, fn, decorator)
%
% Inputs:
%   obj                 MOcovMFile instance
%   fn                  output filename
%   decorator           function handle which takes a single argument with
%                       a line number, and returns a prefix string that
%                       forms an expression that can be evaluated. When
%                       called, each executable line is prefixed with its
%                       corresponding prefix expression and the results are
%                       written to the output file fn.
%
% Notes:
%   - the typical value for decorator is a function that returns
%       mocov_line_covered(fn,k)
%     with k the input line number. This provides functionality to keep
%     track of which lines are covered.

    orig_lines=get_lines(obj);
    n=numel(orig_lines);

    executable=get_lines_executable(obj);

    new_lines=cell(1,n);
    for k=1:n
        line=orig_lines{k};

        if executable(k)
            prefix=decorator(k);
        else
            prefix='';
        end

        new_lines{k}=sprintf('%s%s\n',prefix,line);
    end

    pth=fileparts(fn);
    mkdir_recursively(pth);

    fid=fopen(fn,'w');
    cleaner=onCleanup(@()fclose(fid));
    fprintf(fid,'%s',new_lines{:});

function mkdir_recursively(pth)
    if ~isempty(pth) && ~mocov_util_isfolder(pth)
        parent=fileparts(pth);
        mkdir_recursively(parent);
        mkdir(pth);
    end


ind_active = 1;
n_ima = 1;
active_images = 1;


function opt = opt_proplistToStruct(varargin)
% OPT_PROPLISTTOSTRUCT - Make options struct from parameter/value list
%
%Synopsis:
%  OPT= opt_proplistToStruct(<'Param1', VALUE1, 'Param2', VALUE2, ...>)
%  OPT= opt_proplistToStruct(OPT_IN, <'Param1', VALUE1, 'Param2', VALUE2, ...>)
%
%Arguments:
%  OPT_IN:      STRUCT of optional properties
%  'Param1', VALUE1, ...: Property/value list
%
%Returns:
%  OPT:  STRUCT with (new) fields created from the property/value list
%
%Description:
%  Generates a struct OPT (or updates a given struct OPT_IN) with field
%  'Param1' set to value VALUE1, field 'Param2' set to value VALUE2, and
%  so forth (property/value list).
%
%See also opt_setDefaults opt_structToProplist

% 06-2012 Benjamin Blankertz

opt= [];
if nargin==0,
  return;
end

if isstruct(varargin{1}),
  % First input argument is already a structure: Start with that, write
  % the additional fields
  opt= varargin{1};
  iListOffset= 1;
elseif isempty(varargin{1}),
  % First input argument is empty, which can happen under some
  % circumstances. This is not an opt, but also not part of the list
  iListOffset = 1;
else
  % First argument is not a structure: Assume this is the start of the
  % parameter/value list
  iListOffset = 0;
end

nFields= (nargin-iListOffset)/2;
if nFields~=round(nFields),
  error('Invalid parameter/value list');
end

for ff= 1:nFields,
  fld = varargin{iListOffset+2*ff-1};
  if ~ischar(fld),
    error('Invalid parameter/value list');
  end
  opt.(fld)= varargin{iListOffset+2*ff};
end


function AConstraint = assignschur(AConstraint,thecompiler,varargin)
AConstraint = flatten(AConstraint);
AConstraint.clauses{1}.schurfun  = thecompiler;
AConstraint.clauses{1}.schurdata = varargin;


function g = robOneDynamicsLogLikeGradients(model)

% ROBONEDYNAMICSLOGLIKEGRADIENTS Gradients of the robot one dynamics wrt parameters.

% FGPLVM

g = [];


function linkText = varlink(var,name)
% link to a variable

if getMTEXpref('generatingHelpMode')
  linkText = name;
else
  %linkText = ['' name ''];
  linkText = ['' name ''];
end


classdef Panel < matlab.ui.container.Panel & uix.mixin.Panel
    %uix.Panel  Standard panel
    %
    %  b = uix.Panel(p1,v1,p2,v2,...) constructs a standard panel and sets
    %  parameter p1 to value v1, etc.
    %
    %  A card panel is a standard panel (uipanel) that shows one its
    %  contents and hides the others.
    %
    %  See also: uix.CardPanel, uix.BoxPanel, uipanel

    %  Copyright 2009-2016 The MathWorks, Inc.
    %  $Revision: 1480 $ $Date: 2017-02-15 16:56:13 +0100 (Wed, 15 Feb 2017) $

    methods

        function obj = Panel( varargin )
            %uix.Panel  Standard panel constructor
            %
            %  p = uix.Panel() constructs a standard panel.
            %
            %  p = uix.Panel(p1,v1,p2,v2,...) sets parameter p1 to value
            %  v1, etc.

            % Set properties
            try
                uix.set( obj, varargin{:} )
            catch e
                delete( obj )
                e.throwAsCaller()
            end

        end % constructor

    end % structors

    methods( Access = protected )

        function redraw( obj )

            % Compute positions
            bounds = hgconvertunits( ancestor( obj, 'figure' ), ...
                [0 0 1 1], 'normalized', 'pixels', obj );
            padding = obj.Padding_;
            xSizes = uix.calcPixelSizes( bounds(3), -1, 1, padding, 0 );
            ySizes = uix.calcPixelSizes( bounds(4), -1, 1, padding, 0 );
            position = [padding+1 padding+1 xSizes ySizes];

            % Redraw contents
            selection = obj.Selection_;
            if selection ~= 0
                uix.setPosition( obj.Contents_(selection), position, 'pixels' )
            end

        end % redraw

    end % template methods

end % classdef


function tagS = general_equipment_module_tags
%"general_equipment_module_tags"
%   Return the tags used to represent a general equipment module as
%   specified by C.7.5.1 in PS3.3 of 2006 DICOM specification.
%
%   Tags are returned in a struct array with 3 fields:
%
%   Tag: String containing hex DICOM tag of a field.
%  Type: String describing type of field, with 5 options:
%         '1' Field must exist, data must exist and be valid.
%         '2' Field must exist, data can exist and be valid, or be NULL.
%         '3' Field is optional, if the field exists data can exist and be
%             valid or be NULL.
%         '1C' Field must exist under certain conditions and contain valid
%             data.
%         '2C' Field must exist under certain conditions and can contain
%             valid data or be NULL.
%Children: For sequences, a tagS with the same format as this struct array.
%
%JRA 06/06/06
%
%Usage:
%   tagS = general_equipment_module_tags
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

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

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

%Add tags based on PS3.3 attribute lists.

%Manufacturer
tagS(end+1) = struct('tag', '00080070', 'tagdec', 524400, 'type', '2', 'children', []);

%Institution Name
tagS(end+1) = struct('tag', '00080080', 'tagdec', 524416, 'type', '2', 'children', []);

%Institution Address
tagS(end+1) = struct('tag', '00080081', 'tagdec', 524417, 'type', '3', 'children', []);

%Station Name
tagS(end+1) = struct('tag', '00081010', 'tagdec', 528400, 'type', '3', 'children', []);

%Institutional Department Name
tagS(end+1) = struct('tag', '00081040', 'tagdec', 528448, 'type', '3', 'children', []);

%Manufacturer's Model Name
tagS(end+1) = struct('tag', '00081090', 'tagdec', 528528, 'type', '3', 'children', []);

%Device Serial Number
tagS(end+1) = struct('tag', '00181000', 'tagdec', 1576960, 'type', '3', 'children', []);

%Software Versions
tagS(end+1) = struct('tag', '00181020', 'tagdec', 1576992, 'type', '3', 'children', []);

%Spatial Resolution
tagS(end+1) = struct('tag', '00181050', 'tagdec', 1577040, 'type', '3', 'children', []);

%Date of Last Calibration
tagS(end+1) = struct('tag', '00181200', 'tagdec', 1577472, 'type', '3', 'children', []);

%Time of Last Calibration
tagS(end+1) = struct('tag', '00181201', 'tagdec', 1577473, 'type', '3', 'children', []);

%Pixel Padding Value
tagS(end+1) = struct('tag', '00280120', 'tagdec', 2621728, 'type', '3', 'children', []);


function obj = updateLegendMultipleAxes(obj, legIndex)

% x: ...[DONE]
% y: ...[DONE]
% traceorder: ...[DONE]
% font: ...[DONE]
% bgcolor: ...[DONE]
% bordercolor: ...[DONE]
% borderwidth: ...[DONE]
% xref: ...[DONE]
% yref: ...[DONE]
% xanchor: ...[DONE]
% yanchor: ...[DONE]

%=========================================================================%
%
%-GET NECESSARY INFO FOR MULTIPLE LEGENDS-%
%
%=========================================================================%

for traceIndex = 1:obj.State.Figure.NumPlots
    allNames{traceIndex} = obj.data{traceIndex}.name;
    allShowLegens(traceIndex) = obj.data{traceIndex}.showlegend;
    obj.data{traceIndex}.showlegend = false;
    obj.data{traceIndex}.legendgroup = obj.data{traceIndex}.name;

    axIndex = obj.getAxisIndex(obj.State.Plot(traceIndex).AssociatedAxis);
    [xSource, ySource] = findSourceAxis(obj, axIndex);
    xAxis = eval(sprintf('obj.layout.xaxis%d', xSource));
    yAxis = eval(sprintf('obj.layout.yaxis%d', xSource));

    allDomain(traceIndex, 1) = max(xAxis.domain);
    allDomain(traceIndex, 2) = max(yAxis.domain);
end

[~, groupIndex] = unique(allNames);

for traceIndex = groupIndex'
   obj.data{traceIndex}.showlegend = allShowLegens(traceIndex);
end

%-------------------------------------------------------------------------%

%-STANDARDIZE UNITS-%
legendUnits = get(obj.State.Legend(legIndex).Handle,'Units');
fontUnits = get(obj.State.Legend(legIndex).Handle,'FontUnits');
set(obj.State.Legend(legIndex).Handle,'Units','normalized');
set(obj.State.Legend(legIndex).Handle,'FontUnits','points');

%-------------------------------------------------------------------------%

%-LEGEND DATA STRUCTURE-%
legendData = get(obj.State.Legend(legIndex).Handle);

% only displays last legend as global Plotly legend
obj.layout.legend = struct();

%-------------------------------------------------------------------------%

%-layout showlegend-%
obj.layout.showlegend = strcmpi(legendData.Visible,'on');

%-------------------------------------------------------------------------%

%-legend (x,y) coordenates-%
obj.layout.legend.x = 1.005 * max(allDomain(:,1));
obj.layout.legend.y = 1.001 * max(allDomain(:,2));;

%-legend (x,y) refs-%
obj.layout.legend.xref = 'paper';
obj.layout.legend.yref = 'paper';

%-legend (x,y) anchors-%
obj.layout.legend.xanchor = 'left';
obj.layout.legend.yanchor = 'top';

%-------------------------------------------------------------------------%

if (strcmp(legendData.Box,'on') && strcmp(legendData.Visible, 'on'))

    %---------------------------------------------------------------------%

    %-legend traceorder-%
    obj.layout.legend.traceorder = 'normal';

    %---------------------------------------------------------------------%

    %-legend borderwidth-%
    obj.layout.legend.borderwidth = legendData.LineWidth;

    %---------------------------------------------------------------------%

    %-legend bordercolor-%
    col = 255*legendData.EdgeColor;
    obj.layout.legend.bordercolor = sprintf('rgb(%f,%f,%f)', col);

    %---------------------------------------------------------------------%

    %-legend bgcolor-%
    col = 255*legendData.Color;
    obj.layout.legend.bgcolor = sprintf('rgb(%f,%f,%f)', col);

    %---------------------------------------------------------------------%

    %-legend font size-%
    obj.layout.legend.font.size = legendData.FontSize;

    %---------------------------------------------------------------------%

    %-legend font family-%
    obj.layout.legend.font.family = matlab2plotlyfont(legendData.FontName);

    %---------------------------------------------------------------------%

    %-legend font colour-%
    col = 255*legendData.TextColor;
    obj.layout.legend.font.color = sprintf('rgb(%f,%f,%f)', col);

end

%-------------------------------------------------------------------------%

%-REVERT UNITS-%
set(obj.State.Legend(legIndex).Handle,'Units',legendUnits);
set(obj.State.Legend(legIndex).Handle,'FontUnits',fontUnits);

end


function structColorGUI(command,varargin)
%function structColorGUI(command,varargin)
%GUI to change structure color
%
%APA, 01/25/08, based on structColorGUI
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

global planC stateS

indexS = planC{end};

switch upper(command)

    case 'INIT'

        units = 'pixels';

        x = 340; y = 700;

        hFig = figure('Menu','None','Position',[100,100,x,y],'Name','Reassign Color', 'units', 'pixels',...
            'NumberTitle', 'off', 'resize', 'off', 'Tag', 'structColorGUI','WindowButtonDownFcn','structColorGUI(''BTDWN'')',...
            'WindowButtonUpFcn','structColorGUI(''BTUP'')');

        statusFrame = uicontrol(hFig, 'units',units ,'Position', [10 10 x-18 y-18], 'style', 'frame','HitTest','off');
        frameColor = get(statusFrame,'backgroundcolor');
        ud.frameColor = frameColor;

        %frameColor = [0.9 0.9 0.9];

        uicontrol(hFig, 'units',units,'Position',[x/2-100,670,200,20], 'style', 'text', 'String', 'Reassign Structure Color',...
            'backgroundcolor', frameColor,'fontweight', 'bold','fontsize',10);

        uicontrol(hFig, 'units',units,'Position',[12,650,300,20], 'style', 'text', 'String', '(Hold color, Drag, Drop over another to swap)',...
            'backgroundcolor', frameColor,'fontweight', 'normal','fontsize',8);

        uicontrol(hFig, 'units',units,'Position',[10+40,630,150,20], 'style', 'text', 'String', 'Current Color',...
            'backgroundcolor', frameColor,'fontweight', 'bold','fontsize',9);

        uicontrol(hFig, 'units',units,'Position',[10+180,630,90,20], 'style', 'text', 'String', 'New Color',...
            'backgroundcolor', frameColor,'fontweight', 'bold','fontsize',9);

        numRows = 28;

        for i=1:numRows
            ud.handles.strNum(i) = uicontrol(hFig, 'units',units,'Position',[10+3    y-18-50-i*20   20   15], 'style', 'text',...
                'String', num2str(i), 'backgroundcolor', frameColor,'Visible','Off');
            ud.handles.strName(i)  = uicontrol(hFig, 'units',units,'Position',[10+40   y-18-50-i*20   150  15], 'style', 'text',...
                'String', 'struct Name', 'backgroundcolor', frameColor,'Visible','Off');
            ud.handles.strSelectColor(i)  = uicontrol(hFig, 'units',units,'Position',[10+240   y-18-50-i*20   40  15], 'style', 'push',...
                'String', 'Pick', 'backgroundcolor', frameColor,'Visible','Off', 'callback',['structColorGUI(''pickColor'',''' num2str(i) ''')']);
            ud.handles.newName(i) = uicontrol(hFig, 'units',units,'Position',[10+210  y-18-50-i*20   20  15], 'style', 'text', 'backgroundcolor', stateS.optS.colorOrder(i,:),...
                'horizontalAlignment', 'center', 'userdata', i, 'Tag', 'newStructName','Visible','Off','enable','off');
            ud.handles.newNamePos{i} = get(ud.handles.newName(i),'position');
        end

        ud.numStructRows = numRows;

        %Get structure numbers associated with the passed scan
        scanNum = str2num(varargin{1});
        [assocScansV, relStructNumV] = getStructureAssociatedScan(1:length(planC{indexS.structures}), planC);
        assocStructs = find(assocScansV == scanNum);
        ud.assocStructs = assocStructs;

        for j =  1:length(ud.assocStructs)
            ud.struct(j).newName = '';
        end

        ud.handles.structsSlider = uicontrol(hFig, 'units',units,'Position',[x-18-10 65 20 y-10-125], 'style', 'slider',...
            'enable', 'off','tag','structSlider','callback','structColorGUI(''sliderRefresh'')','backgroundcolor', ud.frameColor);

%         ud.handles.undo = uicontrol(hFig, 'units',units, 'Position', [30 15 60 20], 'style', 'pushbutton', ...
%             'string', 'Undo', 'callback', 'structColorGUI(''undo'')');

        ud.handles.reset = uicontrol(hFig, 'units',units, 'Position', [100 15 60 20], 'style', 'pushbutton', ...
            'string', 'Reset', 'callback', 'structColorGUI(''reset'')');

        ud.handles.save = uicontrol(hFig, 'units',units, 'Position', [170 15 60 20], 'style', 'pushbutton', ...
            'string', 'Save', 'callback', 'structColorGUI(''save'')');

        ud.handles.exit = uicontrol(hFig, 'units',units, 'Position', [240 15 60 20], 'style', 'pushbutton', ...
            'string', 'Exit', 'callback', 'structColorGUI(''exit'')');

        %Store structure colors in ud
        strColorM = stateS.optS.colorOrder;
        numRepeat = ceil(length(ud.assocStructs)/size(strColorM,1));
        strColorM = repmat(strColorM,[numRepeat 1]);
        for j =  1:length(ud.assocStructs)
            strColorM(j,:) = planC{indexS.structures}(ud.assocStructs(j)).structureColor;
        end
        ud.strColorM = strColorM;
        ud.strColorOldM = strColorM;

        ud.handles.currentColor = [];

        structLen = length(ud.assocStructs);
        if (structLen/28) < 2
            max = 2;
        elseif (structLen/28) > 2
            max = 3;
        elseif (structLen/28) > 3
            max = 4;
        end

        try
            value = ud.sliderValue;
        catch
            value = max;
            ud.slider.oldValue = value;
        end
        if max == 2
            sliderstep = 1;
        else
            sliderstep = 1/max;
        end
        set(ud.handles.structsSlider,'min',1,'max',max,'value',max,'sliderstep',[sliderstep sliderstep]);

        %Log
        ud.swapHistory = [];

        set(hFig,'Userdata',ud);

        structColorGUI('refresh')

    case 'REFRESH'

        hFig = findobj('Tag','structColorGUI');

        ud = get(hFig,'Userdata');

        %structLen = length(planC{indexS.structures});
        structLen = length(ud.assocStructs);

        if structLen > ud.numStructRows
            % Enable Slider
            set(ud.handles.structsSlider,'Enable','On');
        end

        if structLen > 28
            set(ud.handles.structsSlider,'enable', 'on');

            % initialize structure slider
            set(hFig,'Userdata',ud);

            structColorGUI('sliderRefresh','init');

        else
            if length(ud.assocStructs)> 28
                numStruct = 28;
            else
                numStruct = length(ud.assocStructs);
            end

            for i=1:numStruct
                structNum  = i;
                structName = planC{indexS.structures}(ud.assocStructs(structNum)).structureName;
                set(ud.handles.strName(structNum), 'string', structName, 'visible', 'on','foregroundcolor',ud.strColorOldM(i,:));
                set(ud.handles.strSelectColor(structNum),'visible', 'on')
                set(ud.handles.strNum(structNum) , 'visible','on');
                set(ud.handles.newName(structNum) , 'visible','on','backgroundcolor',ud.strColorM(i,:));
            end

            %Provide Additional color-Selections
            if numStruct<28
                for i=numStruct+1:28
                    set(ud.handles.newName(i) , 'visible','on','backgroundcolor',ud.strColorM(i,:));
                end
            end

        end

    case 'SLIDERREFRESH'
        ud = get(findobj('Tag','structColorGUI'),'Userdata');

        value = round(get(ud.handles.structsSlider,'value'));
        set(ud.handles.structsSlider,'value',value)
        ud.slider.oldValue = value;
        set(findobj('Tag','structColorGUI'),'Userdata',ud);
        assocStructs = ud.assocStructs;

        numStruct = getStructDispLen(value,assocStructs);

        for i = 1:length(numStruct)
            structNum  = assocStructs(numStruct(i));
            structName = planC{indexS.structures}(structNum).structureName;
            set(ud.handles.strName(i), 'string', structName, 'visible', 'on','foregroundcolor',ud.strColorOldM(numStruct(i),:));
            set(ud.handles.strSelectColor(i),'visible', 'on')
            set(ud.handles.strNum(i) , 'visible','on','String',structNum);
            set(ud.handles.newName(i) ,'visible','on','backgroundcolor',ud.strColorM(numStruct(i),:));
        end

        for j = length(numStruct)+1:28
            set(ud.handles.strName(j), 'visible','off');
            set(ud.handles.strSelectColor(j),'visible', 'off')
            set(ud.handles.strNum(j) , 'visible','off');
            set(ud.handles.newName(j), 'visible','off');
        end

        %Provide Additional color-Selections
        for i = length(numStruct)+1:28
            set(ud.handles.newName(i) , 'visible','on','backgroundcolor',stateS.optS.colorOrder(i,:));
        end

    case 'BTDWN'
        % hFig = findobj('Tag','structColorGUI');
        hFig = gcf;
        ud = get(hFig,'Userdata');
        %Get the color object (static text) clicked
        currentPt = get(hFig,'currentPoint');
        hObject = [];
        for i=1:length(ud.handles.newName)
            pos = get(ud.handles.newName(i),'position');
            if currentPt(1)>=pos(1) && currentPt(1)<=pos(1)+pos(3) && currentPt(2)>=pos(2) && currentPt(2)<=pos(2)+pos(4)
                hObject = ud.handles.newName(i);
                break
            end
        end
        if ~isempty(hObject)
            ud.handles.currentColor = hObject;
            ud.handles.currentColorPos = get(hObject,'position');
            indColor = find(ud.handles.newName==hObject);
            set(ud.handles.strName,'FontWeight','normal')
            set(ud.handles.strName(indColor),'FontWeight','bold')
            set(ud.handles.strName(indColor),'backgroundcolor', 'y')
            set(hFig,'Userdata',ud);
            set(hFig,'WindowButtonMotionFcn','structColorGUI(''BTMTN'')')
        end

        %Set the structure name string font to boldface

    case 'BTMTN'
        hFig = gcf;
        ud = get(hFig,'Userdata');
        set(ud.handles.strName,'fontWeight','normal')
        set(ud.handles.strName,'backgroundcolor', ud.frameColor)
        movingColorInd = find(ud.handles.newName == ud.handles.currentColor);
        set(ud.handles.strName(movingColorInd),'fontWeight','bold')
        set(ud.handles.strName(movingColorInd),'backgroundcolor', 'y')
        %Get the structure object under cursor
        %         hFig = findobj('Tag','structColorGUI');
        currentPt = get(hFig,'currentPoint');
        set(ud.handles.currentColor,'position',[currentPt 20 15])
        %Set the structure name string font to boldface
        %Get the structure object under cursor
        for i=1:length(ud.handles.newName)
            colorPos = ud.handles.newNamePos{i};
            if (currentPt(1) >= colorPos(1)) && (currentPt(1) <= colorPos(1)+colorPos(3)) && (currentPt(2) >= colorPos(2)) && (currentPt(2) <= colorPos(2)+colorPos(4))
                baseColorInd = i;
                set(ud.handles.strName(baseColorInd),'fontWeight','bold')
                set(ud.handles.strName(baseColorInd),'backgroundcolor', 'y')
                drawnow
                break
            end
        end

    case 'BTUP'
        % hFig = findobj('Tag','structColorGUI');
        hFig = gcf;
        ud = get(hFig,'Userdata');
        set(ud.handles.strName,'fontWeight','normal')
        set(ud.handles.strName,'backgroundcolor', ud.frameColor)
        if isempty(ud.handles.currentColor)
            return;
        end
        %Get the structure object under cursor
        movingColorInd = find(ud.handles.newName == ud.handles.currentColor);
        currentPt = get(hFig,'currentPoint');
        if strcmpi(get(ud.handles.structsSlider ,'enable'),'off')
            sliderVal = 1;
            sliderMax = 1;
        else
            sliderVal = get(ud.handles.structsSlider ,'value');
            sliderMax = get(ud.handles.structsSlider ,'max');
        end
        val = sliderMax - sliderVal + 1;
        movingColorInd = (val-1)*ud.numStructRows + movingColorInd;
        baseColorInd = [];
        for i=1:length(ud.handles.newName)
            colorPos = ud.handles.newNamePos{i};
            if (currentPt(1) >= colorPos(1)) && (currentPt(1) <= colorPos(1)+colorPos(3)) && (currentPt(2) >= colorPos(2)) && (currentPt(2) <= colorPos(2)+colorPos(4))
                baseColorInd = (val-1)*ud.numStructRows + i;
                break
            end
        end

        %Swap the structure colors
        if ~isempty(baseColorInd)
            baseColorTmp = ud.strColorM(baseColorInd,:);
            ud.strColorM(baseColorInd,:) = ud.strColorM(movingColorInd,:);
            ud.strColorM(movingColorInd,:) = baseColorTmp;
            ud.swapHistory = [ud.swapHistory; movingColorInd baseColorInd];
        end

        set(ud.handles.currentColor,'position',ud.handles.currentColorPos)
        set(hFig,'WindowButtonMotionFcn','');

        set(hFig,'Userdata',ud);
        if strcmp(get(ud.handles.structsSlider,'Enable'),'on')
            structColorGUI('sliderrefresh')
        else
            structColorGUI('refresh')
        end

    case 'PICKCOLOR'
        % hFig = findobj('Tag','structColorGUI');
        hFig = gcf;
        ud = get(hFig,'Userdata');
        %Get structure index
        if strcmpi(get(ud.handles.structsSlider ,'enable'),'off')
            sliderVal = 1;
            sliderMax = 1;
        else
            sliderVal = get(ud.handles.structsSlider ,'value');
            sliderMax = get(ud.handles.structsSlider ,'max');
        end
        val = sliderMax - sliderVal + 1;
        structIndex = (val-1)*ud.numStructRows + str2num(varargin{1});
        drawnow;
        newColorVal = uisetcolor;
        drawnow;
        prevColorVal = ud.strColorM(structIndex,:);
        ud.strColorM(structIndex,:) = newColorVal;
        set(hFig,'Userdata',ud);
        if strcmp(get(ud.handles.structsSlider,'Enable'),'on')
            structColorGUI('sliderrefresh')
        else
            structColorGUI('refresh')
        end

    case 'UNDO'
        hFig = findobj('Tag','structColorGUI');
        ud = get(hFig,'Userdata');
        if ~isempty(ud.swapHistory)
            baseColorInd = ud.swapHistory(end,1);
            movingColorInd = ud.swapHistory(end,2);
            %Swap the structure colors
            baseColorTmp = ud.strColorM(baseColorInd,:);
            ud.strColorM(baseColorInd,:) = ud.strColorM(movingColorInd,:);
            ud.strColorM(movingColorInd,:) = baseColorTmp;
            ud.swapHistory(end,:) = [];
            set(hFig,'Userdata',ud);
            structColorGUI('refresh')
        end

    case 'RESET'
        hFig = findobj('Tag','structColorGUI');
        ud = get(hFig,'Userdata');

        ud.strColorM = ud.strColorOldM;

        %Clear Log
        ud.swapHistory = [];

        set(hFig,'Userdata',ud);

        structColorGUI('refresh')

    case 'SAVE'
        hFig = findobj('Tag','structColorGUI');
        ud = get(hFig,'Userdata');

        sliderVis = get(ud.handles.structsSlider,'enable');

        if strcmpi(sliderVis,'off')

            %Store color in planC
            for j =  1:length(ud.assocStructs)
                planC{indexS.structures}(ud.assocStructs(j)).structureColor = ud.strColorM(j,:);
            end
        else
            oldValue = ud.slider.oldValue;
            oldStructNum = getStructDispLen(oldValue,ud.assocStructs);

            for jj = 1: length(oldStructNum)
                planC{indexS.structures}(ud.assocStructs(oldStructNum(jj))).structureColor = ud.strColorM(oldStructNum(jj),:);
            end
        end
        ud.strColorOldM = ud.strColorM;

        stateS.structsChanged = 1;
        CERRRefresh

    case 'EXIT'
        hFig = findobj('Tag','structColorGUI');
        delete(hFig)

end

function numStruct = getStructDispLen(value,structsV)
global planC

indexS = planC{end};

ud = get(findobj('Tag','structColorGUI'),'Userdata');
max = get(ud.handles.structsSlider,'max');

if max == 2
    if value == 2
        numStruct = 1:28;
    elseif value == 1
        numStruct = 29:length(structsV);
    end
elseif max == 3
    if value == 3
        numStruct = 1:28;
    elseif value == 2
        numStruct = 29:56;
    elseif value == 1
        numStruct = 57:length(structsV);
    end
end


 function ob = subsasgn(ob, sub, arg)
%function ob = subsasgn(ob, sub, arg)
% method for "ob.sub = arg" etc.

% trick: for struct.sub = object
% e.g., ob.arg.field = ob;
if isstruct(ob)
%	ob = subsasgn(ob, sub, arg); % no, causes recursion
%	ob = builtin('subsasgn', ob, sub, arg);	% samit basu dislikes this

	% recurse a.b.c.d... to avoid builtin:
	if streq(sub(1).type, '.')
		if length(sub) > 1
%			printf('descending to %s', sub(1).subs)
			ob.(sub(1).subs) = subsasgn(ob.(sub(1).subs), sub(2:end), arg);
		else
			ob.(sub(1).subs) = arg;
		end
	else
		error 'not done'
	end

% trick: just convert it to a structure and then back!
else
	cl = class(ob);
	ob = struct(ob);
	name = sub.subs;
	if isfield(ob.data, name)
%		ob.data.(name) = arg;
		% 2011-03-12 changed to handle ig.mask(1)=0
		ob.data = subsasgn(ob.data, sub, arg);
	elseif isfield(ob.meth, name)
		ob.meth.(name) = arg;
	else
		error(['"' name '"is not in data or meth'])
	end
%	ob = subsasgn(ob, sub, arg);
	ob = class(ob, cl);
end


% Ot Matlab interface to OmniTRANS.
%
% Commands:
%    OtStart                     Initialize the Ot-interface.
%    OtStop                      Stop using the Ot-interface.
%
%    OtTableNew,OtQueryNew       Create a table/query handle.
%    OtTableFree,OtQueryFree     Release a table handle.
%
%    OtTableSetName              Set the path to a .db file.
%    OtQuerySetSql               Set an SQL statement for a query.
%
%    OtTableOpen,OtQueryOpen     Open an OmniTRANS table/SELECT-query.
%    OtTableClose,OtQueryClose   Close an OmniTRANS table/SELECT-query.
%    OtQueryExecute              Execute a non-SELECT SQL query.
%
%    OtTableFields,OtQueryFields             Get an array field names.
%    OtTableEmpty,OtQueryEmpty               Is the record set empty?
%    OtTableRecordCount,OtQueryRecordCount   Return the number of records.
%
%    OtTableFirst,OtQueryFirst   Move to the first record.
%    OtTableNext,OtQueryNext     Move to the next record.
%    OtTableEof,OtQueryEof       Check whether the last record was read.
%
%    OtTableLast,OtQueryLast     Move to the last record.
%    OtTablePrior,OtQueryPrior   Move to the previous record.
%    OtTableBof,OtQueryBof       Check whether the first record was read.
%
%    OtTableGet,OtQueryGet       Get contents of a field at the current record.
%    OtTableGetAll,OtQueryGetAll Get contents of all fields at the
%                                current record in a string array.
%
%    OtTableAppend               Put the table into append mode.
%    OtTableEdit                 Put the table into edit mode.
%    OtTableSet                  Modify the current record.
%    OtTableDelete               Delete the current record.
%    OtTablePost                 Post changes to the database table.
%
%    OtPmtu,OtPmturi                      Create a PMTU or PMTURI structure.
%    OtMatrixCubeNew,OtSkimCubeNew        Create a new matrix/skim cube handle.
%    OtMatrixCubeFree,OtSkimCubeFree      Release a matrix/skim cube handle.
%    OtMatrixCubeGet,OtSkimCubeGet        Obtain a matrix from a matrix/skim cube.
%    OtMatrixCubeSet,OtSkimCubeSet        Store a matrix in a matrix/skim cube.
%    OtMatrixCubeDelete,OtSkimCubeDelete  Delete a matrix in a matrix/skim cube.
%
% To be able to use this interface, ensure the OmniTRANS directory
% (with OtInterface.dll and all those BPL files) is on the system path.
%

% OtMatlab: Matlab interface to the Omnitrans transport planning software

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

% All rights reserved.

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

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

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

% 2006-02-28 Created (Johan Meijdam, VORtech)
% 2010-01-22 Updated by Feike Brandt, OmniTRANS International B.V.

% Implementation: Ot.cpp

function [result] = Ot(command, arguments)
    error(['This is Ot.m. In case you read this error message,' ...
           'check whether there is an Ot.dll file in the same directory.']);