function set_rotation_pointer(h)
    %set rotation pointer rotate
    zz=load('rotate.mat');
    val = sum(zz.cdata,3)+1;
    h.Pointer='custom';
    h.PointerShapeCData=[nan(1,16);val];
end


function ef(varargin)
% Command-style shortcut for exp_fullform(varargin)
%
% See also:
%   exp_fullform
%
% Example:
% >> ef var1 var2
%    var1 =
%      ...
%    var2 =
%      ...
%

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

if ~iscellstr(varargin)
    error('ef is to be used as a command, i.e. without brackets.'); end

for i=1:length(varargin)
    disp([varargin{i} ' = ']);
    disp(['  ' exp_fullform(evalin('caller',varargin{i}))]);
    disp('');
end


function [lineStyle] = getLineStyleStrFromText(lineStyleText)
%getLineStyleFromString Summary of this function goes here
%   Detailed explanation goes here

    switch lineStyleText
        case 'Solid Line'
            lineStyle = '-';
        case 'Dashed Line'
            lineStyle = '--';
        case 'Dotted Line'
            lineStyle = ':';
        case 'Dashed-dot Line'
            lineStyle = '-.';
        otherwise
            lineStyle = '-';
    end
end


%kScrollbar 'Scrollbar Object Menuform'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros Scrollbar.pane file
%
% Parameters:
%
% Example: kScrollbar( {})
%
% Khoros helpfile follows below:
%
% .begin tagged
%
% .item "The Scrollbar GUI Object"
% The Scrollbar object allows users to reposition data that is too large to
% fit in a viewing window.  The Scrollbar consists of a long, thin area called the
% scrollbar trough, within which is a smaller, movable button
% called the slider.  Scrollbars may be horizontal or vertical.
% Horizontal scrollbars have the minimum value at the top and
% the maximum value at the bottom; vertical scrollbars have the
% minimum value at the left and the maximum value at the right.
%
% With a horizontal scrollbar, clicking in the scrollbar trough
% to the right of the slider will cause the scrollbar to
% increment in value; clicking in the scrollbar trough to the
% left of the slider will cause the scrollbar to decrement in
% value.  Similarly with a vertical scrollbar, clicking above
% the slider will decrement the value while clicking below the
% slider will increment the value.  The slider itself can be
% dragged back and forth (with a horizontal scrollbar) or up and
% down (with a vertical scrollbar) to change the value.
%
% .item "Minimum Value"
% The minimum world coordinate value that is to be represented by the scrollbar.
%
% .item "Maximum Value"
% The maximum world coordinate value that is to be represented by the scrollbar.
%
% .item "Default Value"
% The default world coordinate value that is to be represented by the scrollbar.
%
% .item "Increment Value"
% The value by which the scrollbar slider will be incremented
% or decremented when the user clicks in the scrollbar trough.
%
% .item "Orientation"
% The scrollbar may be vertical or horizontal.
% .end tagged

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

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


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


function dt6 = dtiRawFixDt6File(dt6FileName,t1FileName)
% Fix the paths in a dt6 file.
% dt6 = dtiRawFixDt6File(dt6FileName,[t1FileName='t1/t1.nii.gz'])
%
% Note that this function enforces unix-style file seperators (/) because
% these work on all platforms (Windows prefers \, but will take /).
%
% Also note that if you catch the output argument, the fixed dt6 struct
% will NOT be saved.
%
% TODO: Allow t1 file to be outside the subject dir.
%
% 2007.08.01 RFD wrote it based on a script from Sherbondy.

if(~exist('dt6FileName','var')||isempty(dt6FileName))
    [f,p] = uigetfile({'*.mat';'*.*'},'Select a dt6 file to fix...');
    if(isnumeric(f)), disp('User canceled.'); return; end
    dt6FileName = fullfile(p,f);
end
if(~exist('t1FileName','var')||isempty(t1FileName))
    t1FileName='t1/t1.nii.gz';
end

[dt6Dir,fName,ext] = fileparts(dt6FileName);
if(isempty(dt6Dir)) dt6Dir = pwd; end
[subDir,dt6DirName] = fileparts(dt6Dir);
if(isempty(subDir)) subDir = pwd; end

dt6 = load(dt6FileName);
if isfield(dt6.files,'homeDir'); dt6.files = rmfield(dt6.files,'homeDir'); end
if isfield(dt6.files,'binDir'); dt6.files = rmfield(dt6.files,'binDir'); end
fieldList = fieldnames(dt6.files);
for ff=1:length(fieldList)
    [p,f,e] = fileparts(getfield(dt6.files,fieldList{ff}));
    f = [f e];
	dt6.files = setfield(dt6.files,fieldList{ff},[dt6DirName '/bin/',f]);
end
dt6.files.t1 = t1FileName;

if(~exist(fullfile(subDir,dt6.files.t1),'file'))
    [f,p] = uigetfile({'*.mat';'*.*'},'Select the associated t1 file (cancel for none)...');
    if(isnumeric(f))
        dt6.files.t1 = '';
    else
        dt6.files.t1 = [p '/' f];
    end
end
if(nargout==0)
    save(dt6FileName, '-struct', 'dt6');
end

return;

baseDir = '/teal/scr1/dti/probtrack_compare';
subjDirs = {'bg040719' 'md040714'  'mho040625'  'rfd040630'  'ss040804' 'db061209'};
ogDir = pwd;
for dd=1:length(subjDirs)
    disp(['Fixing dt6 for subject: ' subjDirs{dd} ' ...']);
    dt6FileName = fullfile(baseDir,subjDirs{dd},'dti06','dt6.mat');
    dtiRawFixDt6File(dt6FileName);
end
cd(ogDir);


function status = SetupRawDir(dirs,anatSeriesNames,makeIFileFlag)
% Set up the directories containing Pfiles, Anat files
%
%  status = SetupRawDir([dirs,anatSeriesNames,makeIFileFlag]);
%
% This routine is useful if you've dumped the Pfiles and DICOM files (using
% sftp and get11, respectively) in a single directory.
%
% dirs: specify the directory, or a cell specifying many directories.
% Default is current working directory.
%
% anatSeriesNames: a cell specifying the names of each
% anatomical series, e.g. {'3plane' 'Inplane' 'SS'}.
% Anatomical series are identified as directories with
% numeric names like '001' or '099'. The script
% will rename the series in numeric order according to the
% name. Leave empty to not rename that series. (E.g.,
% {'Inplane' '' '' 'SS'} ignores the 2 middle series.)
% enter the number 0 to get a default:
% {'Localizer' 'Inplane' 'SS'}
% leave blank and it will prompt for each series #.
%
% makeIFileFlag: if 1, use dcm2gen to convert DICOM images
% to genesis I-files for each anatomical subdir.
%
% Analogous to the old script simptrans3.sh [now defunct],
% set up the Raw directory for a session/sessions, with
% the appropriate subdirectories.
%
% ras 12/01/04.
status = 0;

if ~exist('dirs','var') || isempty(dirs)
    dirs = pwd;
end

if ~exist('makeIFileFlag','var') || isempty(makeIFileFlag)
    makeIFileFlag = 0;
end

if ~exist('anatSeriesNames','var') || isempty(anatSeriesNames)
    anatSeriesNames = []; % flag to check for each dir
elseif isequal(anatSeriesNames,0)
    anatSeriesNames = {'Localizer' 'Inplane' 'SS'};
end

if iscell(dirs)
    for i = 1:length(dirs)
        SetupRawDir(dirs{i},anatSeriesNames,makeIFileFlag);
    end
    return
end

callingDir = pwd;

cd(dirs);

% make the Raw dir and subdirs
if ~exist('Raw','dir') || ~exist('Raw/Anatomy','dir') ...
    || ~exist('Raw/Pfiles','dir')
    fprintf('Making Raw directory and subdirs...\n');
%     unix('mkdir Raw Raw/Anatomy Raw/Pfiles');
    mkdir('Raw');
    mkdir('Raw','Anatomy');
    mkdir('Raw','Pfiles');
end

% get list of anatomical series dirs
anatSeries = dir('0*');
if ~isempty(anatSeries)
    isdir = [anatSeries.isdir];
    names = {anatSeries.name};
    for i = 1:length(names)
        nums(i) = str2num(names{i});
    end
    isnum = ismember(nums,(1:99));
    nums = nums(isnum==1);
    names = names(isnum==1);
    anatSeries = anatSeries(isdir==1 & isnum==1);
end

% move anat series to Raw/Anatomy/
fprintf('Moving anatomical series dirs to Raw/Anatomy...\n');
for i = 1:length(anatSeries);
%     cmd = sprintf('mv %s Raw/Anatomy/',anatSeries(i).name);
%     unix(cmd);
    movefile(anatSeries(i).name, 'Raw/Anatomy');
end

% make sure we have a list of names for anat series
if isempty(anatSeriesNames)
    for i = 1:length(anatSeries);
        msg = sprintf('Enter name for series %i [enter to leave as is]: ',nums(i));
        anatSeriesNames{i} = input(msg,'s');
    end
elseif isequal(anatSeriesNames,0)
    anatSeriesNames = {'Localizer' 'Inplane' 'SS'};
    anatSeriesNames(end+1:length(anatSeries)) = '';
end

% rename anat series
for i = 1:length(anatSeries)
    if ~isempty(anatSeriesNames{i})
%         cmd = sprintf('mv Raw/Anatomy/%s Raw/Anatomy/%s',...
%                        anatSeries(i).name,anatSeriesNames{i});
%         unix(cmd);
        cd Raw/Anatomy
        movefile(anatSeries(i).name, anatSeriesNames{i});
        cd ../..
    end
end

% get list of Pfiles, move to Raw/Pfiles
pfiles = dir('P*.7*');
pnames = {pfiles.name};
fprintf('Moving Pfiles and Pmags to Raw/Pfiles...\n');
for i = 1:length(pnames)
%     cmd = sprintf('mv %s Raw/Pfiles/',pnames{i});
%     unix(cmd);
    movefile(pnames{i}, 'Raw/Pfiles/');
end

% move .img files (from rtfmri) to Raw/Pfiles/imgFiles
imgfiles = dir('P*.img');
if ~isempty(imgfiles)
    fprintf('Making Raw/Pfiles/imgFiles and moving .img files there...\n');
%     unix('mkdir Raw/Pfiles/imgFiles');
    mkdir('Raw/Pfiles', 'imgFiles');
    for i = 1:length(imgfiles)
%         cmd = sprintf('mv %s Raw/Pfiles/imgFiles/',imgfiles(i).name);
%         unix(cmd);
        movefile(imgfiles(i).name, 'Raw/Pfiles/imgFiles/');
    end
end

% get list of E-file headers, compare to pfile names
% (we want to store 'junk' e-files that lack corresponding
% p-files in Raw/Pfiles/extraEfiles
efiles = dir('E*.7');
if ~isempty(efiles)
    enames = {efiles.name};
    for i = 1:length(enames)
        enums(i) = str2num(enames{i}(12:16));
    end
    for i = 1:length(pnames)
        pnums(i) = str2num(pnames{i}(2:6));
    end
    pnums = unique(pnums);
    ind = ismember(enums,pnums);
    goodEfiles = find(ind==1);
    extraEfiles  = find(ind==0);

    % move 'good' efiles to Raw/Pfiles
    for i = goodEfiles
%         cmd = sprintf('mv %s Raw/Pfiles/',enames{i});
%         unix(cmd);
        movefile(enames{i}, 'Raw/Pfiles');
    end

    % move 'extra' efiles to Raw/Pfiles/extraEfiles
    for i = extraEfiles
          if ~exist('Raw/Pfiles/extraEfiles', 'dir')
              mkdir('Raw/Pfiles/', 'extraEfiles');
          end
%         cmd = sprintf('mv %s Raw/Pfiles/extraEfiles/',enames{i});
%         unix(cmd);
          movefile(enames{i}, 'Raw/Pfiles/extraEfiles');
    end
end

% read the first I-file found to get exam #
fprintf('Trying to get exam #...');
try
    tmp = dir('Raw/Anatomy');
    pth = fullfile('Raw','Anatomy',tmp(3).name);
    tmp = dir(fullfile(pth,'I*'));
    [img hdr] = ReadMRImage(fullfile(pth,tmp(1).name));
%     cmd = sprintf('echo %i >Raw/examNum.txt',...
%                    hdr.exam(1).ex_no);
%     unix(cmd);
    fid = fopen('Raw/examNum.txt', 'w');
    fprintf(fid, '%s', num2str(hdr.exam(1).ex_no));
    fclose(fid);
    fprintf('succeeded.\n');
catch
    fprintf('Couldn''t get exam #\n');
end

% convert DICOM to Genesis I-file, if selected
if makeIFileFlag==1 && isunix
    dcm2genPath = fullfile(RAID,'dataTools','dcm2gen');
    cd('Raw/Anatomy');
    subdirs = dir;
    subdirs = subdirs([subdirs.isdir]==1);
    for i = 1:length(subdirs)
        cmd = sprintf('%s %s/*',dcm2genPath,subdirs(i).name);
        unix(cmd);
    end
end

cd(callingDir);

status = 1;

return


classdef LaunchVehicleStopwatchState < matlab.mixin.SetGet & matlab.mixin.Copyable
    %LaunchVehicleStopwatchState Summary of this class goes here
    %   Detailed explanation goes here

    properties
        stopwatch LaunchVehicleStopwatch
        value(1,1) double = 0;
        running(1,1) StopwatchRunningEnum = StopwatchRunningEnum.NotRunning;
    end

    methods
        function obj = LaunchVehicleStopwatchState(stopwatch)
            obj.stopwatch = stopwatch;
        end
    end

    methods(Access=protected)
        function copyObj = copyElement(obj)
            copyObj = copyElement@matlab.mixin.Copyable(obj);
        end
    end
end


function string_maker(block)
% Level-2 MATLAB file S-Function for times two demo.
%   Copyright 1990-2009 The MathWorks, Inc.
%   $Revision: 1.1.6.2 $

  setup(block);

%endfunction

function setup(block)

  %% Register number of input and output ports
  block.NumDialogPrms  = 3;
  block.NumInputPorts  = 3;
  block.NumOutputPorts = 1;

  %% Setup functional port properties to dynamically
  %% inherited.
  block.SetPreCompInpPortInfoToDynamic;
  block.SetPreCompOutPortInfoToDynamic;

  block.InputPort(1).DirectFeedthrough = true;
  block.InputPort(1).DimensionsMode   = 'Fixed';
  block.InputPort(1).Dimensions       = 1;

  block.InputPort(2).DirectFeedthrough = true;
  block.InputPort(2).DimensionsMode   = 'Fixed';
  block.InputPort(2).Dimensions       = 1;

  block.InputPort(3).DirectFeedthrough = true;
  block.InputPort(3).DimensionsMode   = 'Fixed';
  block.InputPort(3).Dimensions       = 1;

  block.OutputPort(1).DimensionsMode   = 'Fixed';
  block.OutputPort(1).Dimensions       = 15;
  block.OutputPort(1).DatatypeID       = -1;
  %% Set block sample time to inherited
  block.SampleTimes = [-1 0];

  %% Set the block simStateCompliance to default (i.e., same as a built-in block)
  block.SimStateCompliance = 'DefaultSimState';

  %% Run accelerator on TLC
  block.SetAccelRunOnTLC(true);

  %% Register methods
  block.RegBlockMethod('Outputs',                 @SetOutPortDims);
  block.RegBlockMethod('Outputs',                 @Output);

%endfunction

function SetOutPortDims(block)   %% SetOutputPortDims - Check and set output port dimensions
    block.InputPort(1).Dimensions  = 1;
    block.InputPort(2).Dimensions  = 1;
    block.InputPort(3).Dimensions  = 1;

    block.OutputPort(1).Dimensions = 15;

%endfunction

  %% Output
function Output(block)
%out_temp = 'A0';
temp_str_1 = num2str(block.InputPort(1).Data);
temp_str_2 = num2str(block.InputPort(2).Data);
temp_str_3 = num2str(block.InputPort(3).Data);
%string1 = strcat(out_temp,temp_str);
  block.OutputPort(1).CurrentDimensions = 15;
  block.OutputPort(1).Data(1) = block.DialogPrm(1).Data;
  block.OutputPort(1).Data(2) = 48;
  block.OutputPort(1).Data(3) = temp_str_1(1);
  block.OutputPort(1).Data(4) = temp_str_1(2);
  block.OutputPort(1).Data(5) = temp_str_1(3);

  block.OutputPort(1).Data(6) = block.DialogPrm(2).Data;
  block.OutputPort(1).Data(7) = 48;
  block.OutputPort(1).Data(8) = temp_str_2(1);
  block.OutputPort(1).Data(9) = temp_str_2(2);
  block.OutputPort(1).Data(10) = temp_str_2(3);

  block.OutputPort(1).Data(11) = block.DialogPrm(3).Data;
  block.OutputPort(1).Data(12) = 48;
  block.OutputPort(1).Data(13) = temp_str_3(1);
  block.OutputPort(1).Data(14) = temp_str_3(2);
  block.OutputPort(1).Data(15) = temp_str_3(3);

%endfunction


function name = p13_name ( )

%*****************************************************************************80
%
%% P13_NAME returns the name of problem 13.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string NAME, the name of the problem.
%
  name = 'BFN03';

  return
end


function [ ] = make_dir( folderPath )
%
% Copyright Aditya Khosla http://mit.edu/khosla
%
% Please cite this paper if you use this code in your publication:
%   A. Khosla, J. Xiao, A. Torralba, A. Oliva
%   Memorability of Image Regions
%   Advances in Neural Information Processing Systems (NIPS) 2012
%

folder = fileparts(folderPath);

if(~isdir(folder))
    mkdir(folder);
end


function stringOut=upperFirstLowerRest(stringIn)

stringOut=lower(stringIn);
if ~isempty(stringOut)
  stringOut(1)=upper(stringIn(1));
end

end


function [VMHId] = generateVMHMetAbbr(met, metabolite_structure_rBioNet,metab,rxnDB,customMetAbbrList)
% This function generates VMH ID's based on a metabolites based on
% predefined rules, as we would generally do it manually
%
% INPUT
% met                           Metabolite name
% metabolite_structure_rBioNet  To save time provide rBioNet either as
%                               1) string to mat file to load, e.g.,: /path/to/metabolite_structure_rBioNet.mat
%                               2) structure already in memory: metabolite_structure_rBioNet
%
% metab                         To save time provide rBioNet (as
%                               metab.mat file)
% rxnDB                         To save time provide rBioNet (as
%                               rxn.mat file)
% customMetaboliteList          List of metabolite abbr against which
%                               uniqueness should also be checked
%
% OUTPUT
% VMHId                         New VMH ID
%
% Ines Thiele, 09/2021

% load rBioNet
if 0
    mkdir('data/');
    websave('data/MetaboliteDatabase.txt','https://raw.githubusercontent.com/opencobra/COBRA.papers/master/2021_demeter/input/MetaboliteDatabase.txt');
    websave('data/ReactionDatabase.txt','https://raw.githubusercontent.com/opencobra/COBRA.papers/master/2021_demeter/input/ReactionDatabase.txt');
    createRBioNetDBFromVMHDB('rBioNetDBFolder','data/');
end
if ~exist('metab','var')
    load('data/metab.mat');
    load('data/rxn.mat');
else
    rxn = rxnDB;
end
% load extended rBioNet
if exist('metabolite_structure_rBioNet','var')
    if ~isstruct(metabolite_structure_rBioNet)
        load(metabolite_structure_rBioNet);
    end
else
    load met_strc_rBioNet;
end

% convert input into lower case
VMHId = lower(met);

% remove unneeded parts from the input
[VMHId] = removeJunk(VMHId);
% keep the original but curated input name
[met_VMHId] = VMHId;

% replace metabolite name with known abbreviations from rBioNet
for i = 1 : size(metab,1)
    name = lower(metab(i,2));
    abbr = lower(metab(i,1));
    % clean up a bit names
    [name] = removeJunk(name);
    nameList_rBioNet(i,1) = name;
    % check that abbr does not contain HC#
    if isempty(regexp(abbr{1},'m\d\d\d\d\d')) && isempty(regexp(abbr{1},'hc\d\d\d\d\d'))  && isempty(regexp(abbr{1},'ce\d\d\d\d')) ...
            && isempty(regexp(abbr{1},'cn\d\d\d\d'))  && isempty(regexp(abbr{1},'c\d\d\d\d\d'))&& ~strcmp(abbr{1},'m') && contains(VMHId,name)

        if strcmp(name,'sulfate')
            abbr = 's'; % don't use so4
        else
            new = ['(' abbr{1} ')'];
            VMHId = regexprep(VMHId,name,new);
        end
    end
end

F = fieldnames(metabolite_structure_rBioNet);
for i= 1: length(F)
    name = metabolite_structure_rBioNet.(F{i}).metNames;
    abbr = metabolite_structure_rBioNet.(F{i}).VMHId;
    [name] = removeJunk(name);
    nameList_rBioNet_strc{i,1} = name;
    if isempty(regexp(abbr,'m\d\d\d\d\d')) && isempty(regexp(abbr,'hc\d\d\d\d\d'))  && isempty(regexp(abbr,'ce\d\d\d\d')) ...
            && isempty(regexp(abbr,'cn\d\d\d\d'))  && isempty(regexp(abbr,'c\d\d\d\d\d'))&& ~strcmp(abbr,'m') && contains(VMHId,name)

        if strcmp(name,'sulfate')
            abbr = 's'; % don't use so4
        else

            if ischar(abbr)
                new = ['(' abbr ')'];
            else
                new = ['(' abbr{1} ')'];
            end
            VMHId = regexprep(VMHId,name,new);
        end
    end
end

% these rules are defined as I would have manually implemented them based
% on a metabolite name.
transl = {
    'glucuronide'   '-g-'
    'monophosphate' '-mp-'
    'diphosphate'   '-dp-'
    'triphosphate'   '-tp-'
    'phosphate' '-p-'
    'methyl'    '-m-'
    'uridine'   '-u-'
    'deoxy' '-d-'
    'dehydro'   '-d-'
    'fluoro'    '-f-'
    'uracil'    '-ura-'
    'acetyl'    '-ac-'
    'glutathione'   '-gth-'
    'quinone'   '-q-'
    'thio'  '-t-'
    'pyridil'   'py'
    'amino' '-am-'
    'amine' '-am-'
    'amide' '-ad-'
    'hydroxy'   '-h-'
    'alpha' '-a-'
    'beta'  '-b-'
    'gamma' '-g-'
    'formyl'    '-f-'
    'oxide' '-o-'
    'carboxyl' '-ca-'
    'carboxy' '-ca-'
    'carboxide' '-ca-'
    'oxi'   '-o-'
    'oxy'   '-o-'
    'riboside'  '-rib-'
    'phospho'   '-p-'
    'tauro' '-t-'
    'cheno' '-c-'
    'deaminated'    '-da-'
    'deaminate' '-da-'
    'deamine' '-da-'
    'acid'  '-a-'
    'nicotinic' '-ni-'
    'tadine' 'td'
    'di'    '-d-'
    'carbaldehyde'  '-ca-'
    'carbaldh'  '-ca-'
    'aldehyde'  '-al-'
    'oxo'   '-o-'
    'hydro' '-h-'
    'azole' '-az-'
    'tri'   '-t-'
    'warfarin'  '-warf-'
    'sulphate' '-s-'
    'glucuronate'   '-glc-'
    'benzyl'    '-b-'
    'tetra'    '-t-'
    'enoyl' '-e-'
    'trans' 't'
    'cis' 'c'
    'mono' 'm'
    };
transl = lower(transl);
for i = 1 : size(transl,1)
    VMHId = regexprep(VMHId,transl{i,1},transl{i,2});
end

% no shortening happened
VMHIdO = VMHId;

% choose the first 4 letters
VMHId = regexprep(VMHId,'-([a-z])([a-z])([a-z])([a-z])([a-z]+)-','-$1$2$3$4-');
VMHId = regexprep(VMHId,'-([a-z])([a-z])([a-z])([a-z])([a-z]+)$','-$1$2$3$4-');
VMHId = regexprep(VMHId,'^([a-z])([a-z])([a-z])([a-z])([a-z]+)-','-$1$2$3$4-');
VMHId = regexprep(VMHId,'([a-z])([a-z])([a-z])([a-z])([a-z]+)','-$1$2$3$4-');
% remove numbers between two letters
VMHIdN = VMHId;
% not of the form of DG(15:0/18:2(9Z,12Z)/0:0)
if length(find(strfind(VMHId,'/')))==0
    VMHId = regexprep(VMHId,'([a-z])(\d\d+)([a-z])','$1$3');
else
    VMHId = regexprep(VMHId,'\/','_');
end
VMHId = regexprep(VMHId,'\s','');
VMHId = regexprep(VMHId,'-','');
VMHId = regexprep(VMHId,'\(','');
VMHId = regexprep(VMHId,'\)','');
VMHId = regexprep(VMHId,'\:','');
VMHId = regexprep(VMHId,',','');
VMHId = regexprep(VMHId,'+','_');
VMHId = regexprep(VMHId,'{','');
VMHId = regexprep(VMHId,'}','_');
VMHId = regexprep(VMHId,'__','_');
VMHId = regexprep(VMHId,'^_','');
VMHId = regexprep(VMHId,'!','');
VMHId = regexprep(VMHId,'‐','');

% check that this abbr does not exist yet
[VMH_existance,rBioNet_existance] = checkAbbrExists({VMHId},metab,rxn,metabolite_structure_rBioNet);
% if the abbr already exists, try the version with the internal numbers
if ~isempty(find(contains(VMH_existance(:,3),'1'))) ||  ~isempty(find(contains(rBioNet_existance(:,3),'1')))
    % check whether it is the same metabolite based on name match (not
    % more)
    if isempty(find(ismember(nameList_rBioNet_strc,met_VMHId))) &&  isempty(find(ismember(nameList_rBioNet,met_VMHId)))
        % choose a 5 letter abbr
        VMHId = VMHIdO;
        % add 1 to the end
        VMHId = [VMHId '1'];
        [VMH_existance,rBioNet_existance] = checkAbbrExists({VMHId},metab,rxn,metabolite_structure_rBioNet);
        if ~isempty(find(contains(VMH_existance(:,3),'1'))) ||  ~isempty(find(contains(rBioNet_existance(:,3),'1')))
            VMHId = VMHIdO;
            % add 1 to the end
            VMHId = [VMHId '2'];
            [VMH_existance,rBioNet_existance] = checkAbbrExists({VMHId},metab,rxn,metabolite_structure_rBioNet);
        end

        VMHId = regexprep(VMHId,'\s','');
        VMHId = regexprep(VMHId,'-','');
        VMHId = regexprep(VMHId,'\(','');
        VMHId = regexprep(VMHId,'\)','');
        VMHId = regexprep(VMHId,'\:','');
        VMHId = regexprep(VMHId,',','');
        VMHId = regexprep(VMHId,'+','_');
        VMHId = regexprep(VMHId,'{','');
        VMHId = regexprep(VMHId,'}','_');
VMHId = regexprep(VMHId,'‐','');

    end
end

% now check also against the costum metabolite abbr list
if exist('customMetAbbrList','var')
    if ~isempty(customMetAbbrList) &&  length(strmatch(VMHId,customMetAbbrList,'exact'))>0
        % choose a 5 letter abbr
        VMHId = VMHIdO;
        % add 1 to the end
        VMHId = [VMHId '1'];
        num = 2;
        [VMH_existance,rBioNet_existance] = checkAbbrExists({VMHId},metab,rxn,metabolite_structure_rBioNet);
        while ~isempty(find(contains(VMH_existance(:,3),'1'))) ||  ~isempty(find(contains(rBioNet_existance(:,3),'1')))
            VMHId = VMHIdO;
            % add 1 to the end
            VMHId = [VMHId num2str(num)];
            num = num+1;
            [VMH_existance,rBioNet_existance] = checkAbbrExists({VMHId},metab,rxn,metabolite_structure_rBioNet);
        end

        VMHId = regexprep(VMHId,'\s','');
        VMHId = regexprep(VMHId,'-','');
        VMHId = regexprep(VMHId,'\(','');
        VMHId = regexprep(VMHId,'\)','');
        VMHId = regexprep(VMHId,'\:','');
        VMHId = regexprep(VMHId,',','');
        VMHId = regexprep(VMHId,'+','_');
        VMHId = regexprep(VMHId,'{','');
        VMHId = regexprep(VMHId,'}','_');
        VMHId = regexprep(VMHId,'/','_');
        VMHId = regexprep(VMHId,'‐','');

        % Check here again if it is in customMetAbbrList (needs first
        % converted with regexprep)
         while ~isempty(find(ismember(customMetAbbrList,VMHId))>0)
            VMHId = [VMHId '1'];
         end
    end
end

function [name] = removeJunk(name)
% remove parts of the metabolite name (in input as well as in rBioNet) that
% is not informative but makes mapping more challenging

name = regexprep(name,'conjugate','');
name = regexprep(name,'acceptor','');
name = regexprep(name,'donor','');
name = regexprep(name,'intermediate','');
name = regexprep(name,'\(1\-\)','');
name = regexprep(name,'\(1\+\)','');
name = regexprep(name,'\(2\-\)','');
name = regexprep(name,'\(2\+\)','');
name = regexprep(name,'\(3\-\)','');
name = regexprep(name,'\(3\+\)','');
name = regexprep(name,'\(4\-\)','');
name = regexprep(name,'\(4\+\)','');
name = regexprep(name,'\(1\)','');
name = regexprep(name,'\(2\)','');
name = regexprep(name,'^ ','');
name = regexprep(name,' $','');
name = regexprep(name,'*','');
name = regexprep(name,'''','');
name = regexprep(name,'β','b');
name = regexprep(name,'α','a');
name = regexprep(name,'Δ','d');
name = regexprep(name,'δ','d');
name = regexprep(name,'γ','g');
name = regexprep(name,'ω','o');
name = regexprep(name,'\.','_');
% these edits are specific to the metabolon input file
name = regexprep(name,'\[1\]','');
name = regexprep(name,'\[2\]','');
name = regexprep(name,'′','');
name = regexprep(name,'\[cis or trans\]','');
% remove any square brackets but retain text
name = regexprep(name,'\[','');
name = regexprep(name,'\]','');
name = regexprep(name,';','_');
name = regexprep(name,'!','');
name = regexprep(name,'‐','');
name = regexprep(name,'â','a');


%% Copyright (C) 2022 Alex Vong
%%
%% 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 <https://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @defun  show_system_info ()
%% Show information about the current system.
%%
%% @seealso{computer, ver}
%% @end defun

function show_system_info ()
  [platform, array_maxsize, endian] = computer ();
  arch = computer ('arch');

  disp ('System info');
  disp ('-----------');
  disp ('');
  fprintf ('Platform: %s\n', platform);
  fprintf ('Array Maximum Size: %d\n', array_maxsize);
  fprintf ('Endianness: %s\n', endian);
  fprintf ('Architecture: %s\n', arch);
  ver ();
  disp ('');
end


function [ fileList, patientList ] = matRad_scanDicomImportFolder( patDir )
% matRad function to scan a folder for dicom data
%
% call
%   [ fileList, patientList ] = matRad_scanDicomImportFolder( patDir )
%
% input
%   patDir:         folder to be scanned
%
% output
%   fileList:       matlab struct with a list of dicom files including meta
%                   infomation (type, series number etc.)
%   patientList:    list of patients with dicom data in the folder
%
% References
%   -
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright 2015 the matRad development team.
%
% This file is part of the matRad project. It is subject to the license
% terms in the LICENSE file found in the top-level directory of this
% distribution and at https://github.com/e0404/matRad/LICENSES.txt. No part
% of the matRad project, including this file, may be copied, modified,
% propagated, or distributed except according to the terms contained in the
% LICENSE file.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

matRad_cfg = MatRad_Config.instance();

%% print current status of the import script
matRad_cfg.dispInfo('Dose series matched to the different plans are displayed and could be selected.\n');
matRad_cfg.dispInfo('Rechecking of correct matching procedure is recommended.\n');

global warnDlgDICOMtagShown;
warnDlgDICOMtagShown = false;

%% get all files in search directory

% dicom import needs image processing toolbox -> check if available
if ~license('checkout','image_toolbox')
    matRad_cfg.dispError('image processing toolbox and/or corresponding licence not available');
end

fileList = matRad_listAllFiles(patDir);

if ~isempty(fileList)
    %% check for dicom files and differentiate patients, types, and series
    numOfFiles = numel(fileList(:,1));
    h = waitbar(0,'Please wait...');
    %h.WindowStyle = 'Modal';
    steps = numOfFiles;
    for i = numOfFiles:-1:1
        waitbar((numOfFiles+1-i) / steps)
        try % try to get DicomInfo
            if verLessThan('matlab','9')
                info = dicominfo(fileList{i});
            else
                info = dicominfo(fileList{i},'UseDictionaryVR',true);
            end
        catch
            fileList(i,:) = [];
            matRad_progress(numOfFiles+1-i, numOfFiles);
            continue;
        end
        try
            fileList{i,2} = info.Modality;
        catch
            fileList{i,2} = NaN;
        end

        fileList = parseDicomTag(fileList,info,'PatientID',i,3);

        switch fileList{i,2}
            case 'CT'

               fileList = parseDicomTag(fileList,info,'SeriesInstanceUID',i,4);

            case {'RTPLAN','RTDOSE','RTSTRUCT'}

               fileList = parseDicomTag(fileList,info,'SOPInstanceUID',i,4);

           otherwise

              fileList = parseDicomTag(fileList,info,'SeriesInstanceUID',i,4);

        end

        fileList = parseDicomTag(fileList,info,'SeriesNumber',i,5,@seriesnum2str); %We want to make sure the series number is stored as string
        fileList = parseDicomTag(fileList,info,'FamilyName',i,6);
        fileList = parseDicomTag(fileList,info,'GivenName',i,7);
        fileList = parseDicomTag(fileList,info,'PatientBirthDate',i,8);

        try
            if strcmp(info.Modality,'CT')
                fileList{i,9} = num2str(info.PixelSpacing(1));
            else
                fileList{i,9} = NaN;
            end
        catch
            fileList{i,9} = NaN;
        end
        try
            if strcmp(info.Modality,'CT')
                fileList{i,10} = num2str(info.PixelSpacing(2));
            else
                fileList{i,10} = NaN;
            end
        catch
            fileList{i,10} = NaN;
        end
        try
            if strcmp(info.Modality,'CT')
                %usually the Attribute should be SliceThickness, but it
                %seems like some data uses "SpacingBetweenSlices" instead.
                if isfield(info,'SliceThickness') && ~isempty(info.SliceThickness)
                    fileList{i,11} = num2str(info.SliceThickness);
                elseif isfield(info,'SpacingBetweenSlices')
                    fileList{i,11} = num2str(info.SpacingBetweenSlices);
                else
                    matRad_cfg.dispError('Could not identify spacing between slices since neither ''SliceThickness'' nor ''SpacingBetweenSlices'' are specified');
                end
            else
                fileList{i,11} = NaN;
            end
        catch
            fileList{i,11} = NaN;
        end
        try
            if strcmp(info.Modality,'RTDOSE')
                dosetext_helper = strcat('Instance','_', num2str(info.InstanceNumber),'_', ...
                    info.DoseSummationType, '_', info.DoseType);
                fileList{i,12} = dosetext_helper;
            else
                fileList{i,12} = NaN;
            end
        catch
            fileList{i,12} = NaN;
        end
        % writing corresponding dose dist.
        try
            if strcmp(fileList{i,2},'RTPLAN')
                corrDose = [];
                numDose = length(fieldnames(info.ReferencedDoseSequence));
                for j = 1:numDose
                    fieldName = strcat('Item_',num2str(j));
                    corrDose{j} = info.ReferencedDoseSequence.(fieldName).ReferencedSOPInstanceUID;
                end
                fileList{i,13} = corrDose;
            else
                fileList{i,13} = {'NaN'};
            end

        catch
            fileList{i,13} = {'NaN'};
        end
        matRad_progress(numOfFiles+1-i, numOfFiles);

    end
    close(h)

    if ~isempty(fileList)
        patientList = unique(fileList(:,3));

        if isempty(patientList)
            msgbox('No patient found with DICOM CT _and_ RT structure set in patient directory!', 'Error','error');
        end
    else
        msgbox('No DICOM files found in patient directory!', 'Error','error');
        %h.WindowStyle = 'Modal';
        %error('No DICOM files found in patient directory');
    end
else
    msgbox('Search folder empty!', 'Error','error');

end

clear warnDlgDICOMtagShown;

end

function fileList = parseDicomTag(fileList,info,tag,row,column,parsefcn)

global warnDlgDICOMtagShown;

defaultPlaceHolder = '001';

if nargin < 6
    parsefcn = @(x) x;
end

try
   if isfield(info,tag)
      if ~isempty(info.(tag))
         fileList{row,column} = parsefcn(info.(tag));
      else
         fileList{row,column} = defaultPlaceHolder;
      end
   else
      fileList{row,column} = defaultPlaceHolder;
   end
catch
   fileList{row,column} = NaN;
end

if ~warnDlgDICOMtagShown && strcmp(fileList{row,column},defaultPlaceHolder) && (column == 3 || column == 4)

   dlgTitle    = 'Dicom Tag import';
   dlgQuestion = ['matRad_scanDicomImportFolder: Could not parse dicom tag: ' tag '. Using placeholder ' defaultPlaceHolder ' instead. Please check imported data carefully! Do you want to continue?'];
   answer      = questdlg(dlgQuestion,dlgTitle,'Yes','No', 'Yes');

   warnDlgDICOMtagShown = true;

   switch answer
      case 'No'
         matRad_cfg.dispError('Inconsistency in DICOM tags')
   end
end

end

function value = seriesnum2str(value)
    if isnumeric(value)
        value = num2str(value);
    end
end


function kegg2mol(cid,molfileDir,mets,takeMajorMS,pH,takeMajorTaut)
% Retreive molfiles from the KEGG Compound database.
%
% kegg2mol(cid,molfileDir,mets,takeMajorMS,pH,takeMajorTaut)
%
% INPUTS
% cid               m x 1 array of KEGG Compound identifiers.
%
% OPTIONAL INPUTS
% molfileDir        Path to directory where molfiles will be saved. Default
%                   is molfilesFromKegg.
% mets              m x 1 array of metabolite identifiers. Used to name
%                   molfiles. KEGG Compound ID will be used if mets is
%                   omitted.
% takeMajorMS       {(0),1}. If 0 (default), molfiles will be downloaded
%                   directly from KEGG. If 1, they will save as the major
%                   microspecies at the pH specified in input variable pH.
%                   Computing major microspecies requires ChemAxon's
%                   calculator plugins (cxcalc).
% pH                pH for computing major microspecies.
% takeMajorTaut     {0,(1)}. If 1 (default), molfiles will be saved as the
%                   major tautomers of the major microspecies at the
%                   specified pH.
%
% WRITTEN OUTPUTS
% One molfile for each metabolite with a KEGG Compound ID.

% If takeMajorMS == 1; approximately 2 seconds per kegg id
% If takeMajorMS == 0; approximately 0.3 seconds per kegg id

% Configure inputs
cid = reshape(cid,length(cid),1);
if ischar(cid)
    cid = strtrim(cellstr(cid));
end
if isnumeric(cid)
    eval(['cid = {' regexprep(sprintf('''C%05d''; ',cid),'(;\s)$','') '};']);
end

if ~exist('molfileDir','var')
    molfileDir = 'molfilesFromKegg';
elseif isempty(molfileDir)
    molfileDir = 'molfilesFromKegg';
end
[success,message] = mkdir(molfileDir);
if success ~= 1
    error(message)
end
if ~strcmp(molfileDir(end),filesep)
    molfileDir = [molfileDir filesep];
end

if ~exist('mets','var')
    mets = cid;
elseif isempty(mets)
    mets = cid;
end
mets = reshape(mets,length(mets),1);
if ischar(mets)
    mets = strtrim(cellstr(mets));
end
if isnumeric(mets)
    mets = strtrim(cellstr(num2str(mets)));
end
mets = regexprep(mets,'(\[\w\])$',''); % Remove compartment assignment

if ~exist('takeMajorMS','var')
    takeMajorMS = 0;
elseif isempty(takeMajorMS)
    takeMajorMS = 0;
end
if ~exist('pH','var')
    pH = 7;
elseif isempty(pH)
    pH = 7;
end
if ~exist('takeMajorMS','var')
    takeMajorTaut = 1;
elseif isempty(takeMajorMS)
    takeMajorTaut = 1;
end

% Only retreive molfiles for unique metabolites
bool = ~cellfun('isempty',cid);
umets = mets(bool);
ucid = cid(bool);
[umets,crossi] = unique(umets);
ucid = ucid(crossi);

% List all elements
elements = {'H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg', 'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca',...
    'Sc', 'Ti', 'V', 'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se', 'Br', 'Kr', 'Rb', 'Sr', 'Y',...
    'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh', 'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba', 'La', 'Ce',...
    'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho', 'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir',...
    'Pt', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac', 'Th', 'Pa', 'U', 'Np', 'Pu', 'Am', 'Cm',...
    'Bk', 'Cf', 'Es', 'Fm', 'Md', 'No', 'Lr', 'Rf', 'Db', 'Sg', 'Bh', 'Hs', 'Mt', 'Ds', 'Rg', 'Cn', 'Uut', 'Fl', 'Uup', 'Lv', 'Uus', 'Uuo'};

% Retreive molfiles
nomol = {};
for i = 1:length(umets)
    met = umets{i};
    id = ucid{i};
    [mol,success] = urlread(sprintf('http://rest.kegg.jp/get/cpd:%s/mol', id)); % API

    if success == 0
        nomol = [nomol; {met}];
        continue;
    end

    mol = regexprep(mol,'\r',''); % Remove carriage returns
    mol = regexprep(mol,'[^\n]*\n',[id '\n'],'once'); % Replace top line with KEGG ID
    mol = regexprep(mol,'M  END.*','M  END'); % Remove all lines after end of molfile

    % Identify variable structures containing R groups, repeat units etc.
    % ChemAxon's calculator plugins cannot compute major microspecies for
    % such structures.
    atoms = {};
    if takeMajorMS == 1
        % Get atom list
        lines = regexp(mol,'\n','split');
        atomCount = str2double(lines{4}(1:3));
        if atomCount > 0
            atomBlock = lines(5:5 + atomCount - 1);
            pat = '[^a-z_A-z]+(?<atom>[a-z_A-Z]+)[^a-z_A-z]+';
            atoms = regexp(atomBlock,pat,'names');
            atoms = [atoms{:}]';
            atoms = {atoms.atom}';
        end

        % Check for repeat units
        if ~isempty(strmatch('M  STY',lines))
            atoms = {};
        end
    end

    if takeMajorMS == 0 || ~all(ismember(atoms,elements)) || isempty(atoms) || (length(atoms) == 2 && all(strcmp(atoms,'H'))) % Write raw molfile from KEGG directly to file
        fid = fopen([molfileDir met '.mol'],'w+');
        fprintf(fid,'%s',mol);
        fclose(fid);
    else % Get major microspecies and write to file
        fid = fopen('tmp.mol','w+'); % Write raw molfile from KEGG to temporary file
        fprintf(fid,'%s',mol);
        fclose(fid);

        if takeMajorTaut == 1
            majorTautOption = 'true';
        else
            majorTautOption = 'false';
        end

        status = system(['cxcalc -o ' molfileDir met '.mol majorms -H ' num2str(pH) ' -f mol -M ' majorTautOption ' tmp.mol']); % Call ChemAxon's calculator plugin (cxcalc) to compute major microspecies

        if status ~= 0
            nomol = [nomol; {met}];
        end
    end
end

delete('tmp.mol'); % Delete temporary file

if ~isempty(nomol)
    fprintf(['Could not retreive molfiles from KEGG for metabolites:\n' sprintf('%s\n', nomol{:})]);
end


function z_callBack_virtualTeachPendant_J1_minus()
%% Soft realtime joints control Joint X button callback
% Copyright: Mohammad SAFEEA, 27th-July-2018
global virtual_smartPad_w_joints_command;
disp('Moving J1 in negative direction');
virtual_smartPad_w_joints_command(1)=-1;
end


function handles = configSettingsGUI(varargin)
handles = [];

% Parse args
[filenames, nParamsPerCol, lastpos, options] = ParseArgs(varargin);

InitializeGuiStruct(filenames, options);
hf = CreateGui();
ResetGui(hf);
ResizeGui(hf, nParamsPerCol, lastpos);
hBttnSave = DrawBttns(hf);
DrawConfigParams(hf, hBttnSave);
handles.figure = hf;

% ----------------------------------------------------------
function [filenames, nParamsPerCol, lastpos, options] = ParseArgs(args)
filenames = {};
nParamsPerCol = [];
lastpos = [];
options = '';
if ~isempty(args) && isnumeric(args{end}) && length(args{end})==4
    lastpos = args{end};
    args(end) = [];
end
if length(args)==1
    if iscell(args{1}) || ischar(args{1})
        filenames = args{1};
    else
        nParamsPerCol = args{1};
    end
elseif length(args)==2
    if iscell(args{1}) || ischar(args{1})
        filenames = args{1};
        nParamsPerCol = args{2};
    else
        filenames = args{2};
        nParamsPerCol = args{1};
    end
elseif length(args)==3
    if iscell(args{1}) || ischar(args{1})
        filenames = args{1};
        nParamsPerCol = args{2};
    else
        filenames = args{2};
        nParamsPerCol = args{1};
    end
    options = args{2};
end
if ~exist('filenames','var') || isempty(filenames)
    filenames = {};
end
if ~exist('nParamsPerCol','var') || isempty(nParamsPerCol)
    nParamsPerCol = 6;
end
if ~exist('options','var')
    options = '';
end
if nParamsPerCol<1
    nParamsPerCol = 1;
end
if nParamsPerCol>12
    nParamsPerCol = 12;
end

% -------------------------------------------------------------
function InitializeGuiStruct(filenames, options)
global cfgGui

if ~isempty(cfgGui)
    if ishandles(cfgGui.handle)
        return;
    end
end

cfgGui = struct(...
    'filedata',[], ...
    'ysizeParam',0, ...
    'xsizeParam',0, ...
    'ysizeBttn',0, ...
    'xsizeBttn',0, ...
    'ysizeGap',0, ...
    'xsizeGap',0, ...
    'nrows',0, ...
    'ncols',0, ...
    'ysizeTotal',0, ...
    'xsizeTotal',0, ...
    'ysizeParamsAll',0, ...
    'xsizeParamsAll',0, ...
    'nParamsPerCol',8, ...
    'handle',[], ...
    'pos',[] ...
    );

cfgGui.filedata = ConfigFileClass(filenames);

% char to pixel conversion
cfgGui.units = 'pixels';
[fx, fy] = guiUnitConversion('characters', cfgGui.units);

% Hardcode size of each parameter panel in char units
cfgGui.ysizeParam = 5*fy;
cfgGui.xsizeParam = 50*fx;

% Hardcode size of each buttons
cfgGui.ysizeBttn = 2.4*fy;
cfgGui.xsizeBttn = 25*fx;

% Gaps sizes between controls
cfgGui.ysizeGap = 1*fy;
cfgGui.xsizeGap = 2*fx;

cfgGui.fontsizes = [15, 11, 10, 9];
if ismac()
    cfgGui.fontsizes = cfgGui.fontsizes+4;
end
cfgGui.posParam     = [.10,.10,.80,.80];

cfgGui.options = options;

% -------------------------------------------------------------
function hf = CreateGui()
global cfgGui

if ~ishandles(cfgGui.handle)
    hf = figure('name', 'App Setting Config GUI', 'NumberTitle','off', 'MenuBar','none', 'ToolBar','none', ...
        'units',cfgGui.units);
else
    hf = cfgGui.handle;
end
cfgGui.handle = hf;

% -------------------------------------------------------------
function ResetGui(hf)
hc = get(hf, 'children');
for ii = 1:length(hc)
    if strcmpi(get(hc(ii), 'type'), 'uimenu')
        continue;
    end
    delete(hc(ii));
end

% -------------------------------------------------------------
function ResizeGui(hf, nParamsPerCol, ~)
global cfgGui

cfgGui.nParamsPerCol = nParamsPerCol;

p0 = get(hf, 'position');

% Calculate number of columns and rows needed to accomodate all the
% parameters
cfgGui.np = cfgGui.filedata.GetParamNum();
if floor(cfgGui.np/cfgGui.nParamsPerCol) == 0
    k = 1;
elseif floor(cfgGui.np/cfgGui.nParamsPerCol) == cfgGui.np/cfgGui.nParamsPerCol
    k = 0;
else
    k = 1;
end
cfgGui.ncols = floor(cfgGui.np/cfgGui.nParamsPerCol)+k;
cfgGui.nrows = cfgGui.nParamsPerCol;
cfgGui.ysizeParamsAll = cfgGui.nrows * (cfgGui.ysizeParam + cfgGui.ysizeGap) + 2*cfgGui.ysizeGap;
cfgGui.xsizeParamsAll = cfgGui.ncols * (cfgGui.xsizeParam + cfgGui.xsizeGap) + 2*cfgGui.xsizeGap;
cfgGui.ysizeTotal = cfgGui.ysizeParamsAll+cfgGui.ysizeBttn+4*cfgGui.ysizeGap;
cfgGui.xsizeTotal = cfgGui.xsizeParamsAll;
set(hf, 'position', [p0(1), p0(2), cfgGui.xsizeTotal, cfgGui.ysizeTotal])
rePositionGuiWithinScreen(hf);

% -------------------------------------------------------------
function hv = DrawConfigParams(hf, hBttnSave)
global cfgGui

np = cfgGui.filedata.GetParamNum();
hp = zeros(np,1);
hcm = setMouseClickAction();

for i = 1:cfgGui.ncols
    for j = 1:cfgGui.nrows
        % Figure out param panel position
        xpos    = (cfgGui.xsizeParam+cfgGui.xsizeGap)*(i-1) + cfgGui.xsizeGap;
        ypos    = cfgGui.ysizeTotal - 2*cfgGui.ysizeGap - (cfgGui.ysizeParam+cfgGui.ysizeGap)*j;
        posPanel = [xpos, ypos, cfgGui.xsizeParam, cfgGui.ysizeParam];

        ip = cfgGui.nParamsPerCol*(i-1) + j;
        if ip>np
            if np==0
                uicontrol(hf, 'Style','text', 'string','CONFIG FILE IS EMPTY', 'FontSize',cfgGui.fontsizes(2), ...
                          'fontweight','bold', 'units',cfgGui.units, 'Position',posPanel, 'foregroundcolor',[.6,.3,.1]);
            end
            break;
        end

        % Draw param panel
        hp(ip) = uipanel('parent',hf, 'Title',cfgGui.filedata.GetParamName(ip), 'FontSize',cfgGui.fontsizes(3), 'fontweight','bold', 'foregroundcolor',[.6,.3,.1], ...
            'units',cfgGui.units, 'Position',posPanel);

        % Draw param values control within panel. Note all controls have same relative position within panel
        pval = cfgGui.filedata.GetParamValue(ip);
        if isempty(pval)
            pval = '';
        end
        if isempty(cfgGui.filedata.GetParamValueOptions(ip))
            hv = uicontrol(hp(ip), 'Style','edit', 'string',pval, 'FontSize',cfgGui.fontsizes(4), 'fontweight','bold', 'Tag',cfgGui.filedata.GetParamName(ip), ...
                           'units','normalized', 'position',cfgGui.posParam);
        else
            hv = uicontrol(hp(ip), 'Style','popupmenu', 'string',cfgGui.filedata.GetParamValueOptions(ip), ...
                           'FontSize',cfgGui.fontsizes(4), 'fontweight','bold', 'Tag',cfgGui.filedata.GetParamName(ip), ...
                           'units','normalized', 'position',cfgGui.posParam);
            k = find(strcmp(cfgGui.filedata.GetParamValueOptions(ip), pval));
            if isempty(k)
                set(hv, 'string',[{''}; cfgGui.filedata.GetParamValueOptions(ip)]);
            else
                hv.Value = k;
            end
        end
        hv.Callback = {@setVal, hBttnSave};
    end

end

if verGreaterThanOrEqual('matlab','9.8')
    set(hp, 'ContextMenu',setMouseClickAction(hcm,hp));
else
    set(hp, 'ButtonDownFcn',{@mouseClickFcn_Callback,hp});
end
set(hf, 'ButtonDownFcn',{@mouseClickFcn_Callback,hp});

% -------------------------------------------------------------
function [hBttnSave, hBttnExit] = DrawBttns(hf)
global cfgGui

if cfgGui.ncols == 1
    k = 10;
else
    k = 5;
end
xoffset = cfgGui.xsizeTotal/k;
hBttnSave = uicontrol(hf, 'Style','pushbutton', 'FontSize',cfgGui.fontsizes(1), 'Units',cfgGui.units, 'String','SAVE', ...
    'Position', [xoffset, cfgGui.ysizeTotal-(cfgGui.ysizeParamsAll+cfgGui.ysizeParam), cfgGui.xsizeBttn, cfgGui.ysizeBttn]);
hBttnSave.Callback = @cfgSave;
hBttnExit = uicontrol(hf, 'Style','pushbutton', 'FontSize',cfgGui.fontsizes(1), 'Units',cfgGui.units, 'String','EXIT', ...
    'Position', [cfgGui.xsizeTotal-(cfgGui.xsizeBttn+xoffset), cfgGui.ysizeTotal-(cfgGui.ysizeParamsAll+cfgGui.ysizeParam), cfgGui.xsizeBttn, cfgGui.ysizeBttn]);
hBttnExit.Callback = @cfgExit;
setappdata(hBttnSave, 'backgroundcolororiginal',hBttnSave.BackgroundColor);
setappdata(hBttnSave, 'foregroundcolororiginal',hBttnSave.ForegroundColor);

% -------------------------------------------------------------
function setVal(hObject, ~, hBttnSave)
global cfgGui

if strcmp(hObject.Style, 'popupmenu')
    if hObject.Value>0
        s = hObject.String{hObject.Value};
    else
        s = {};
    end
else
    s = hObject.String;
end
if iscell(s) && ~isempty(s)
    s = s{1};
elseif isempty(s)
    s = '';
end

% Check if param value has changed
if cfgGui.filedata.ChangedValue(hObject.Tag, s)
    hBttnSave.BackgroundColor = [.90, .10, .05];
    hBttnSave.ForegroundColor = [.90, .80, .75];
end
cfgGui.filedata.SetValue(hObject.Tag, s);

% -------------------------------------------------------------
function cfgSave(hObject, ~) %#ok<*DEFNU>
global cfgGui
global cfg
cfgGui.filedata.Save();

% This is the only place in configSettingsGUI that we access global cfg.
% We only use it to update the global variable when we to save changes
if isa(cfg, 'ConfigFileClass')
    cfg.Update();
end

hObject.BackgroundColor = getappdata(hObject, 'backgroundcolororiginal');
hObject.ForegroundColor = getappdata(hObject, 'foregroundcolororiginal');
if optionExists(cfgGui.options, {'keepopen','stayopen'})
    return
end
close;

% -------------------------------------------------------------
function cfgExit(~,~)
close;

% -------------------------------------------------------------
function mouseClickFcn_Callback(hObject, ~, handles)
type = get(hObject, 'type');
if strcmp(type, 'figure')
    return;
end

hf = [];
while ~strcmp(type, 'root')
    hObject = get(hObject, 'parent');
    type = get(hObject, 'type');
    if strcmp(type, 'figure')
        hf = hObject;
        break;
    end
end
if isempty(hf)
    return;
end

me = get(hf,'selectiontype');
if ~strcmp(me, 'alt')
    return
end

mp = get(hf,'currentpoint');
if length(mp)<2
    return;
end
% fprintf('Mouse click position: [%0.1f, %0.1f]:\n\n', mp(1), mp(2));
paramNameClicked = '';
for ii = 1:length(handles)
    p = get(handles(ii), 'position');
    paramName = get(handles(ii), 'title');
    if (mp(1)>=p(1) && mp(1)<=p(1)+p(3)) && (mp(2)>=p(2) && mp(2)<=p(2)+p(4))
        % fprintf('**** Clicked on ''%s'': [%0.1f, %0.1f] ****\n', paramName, p(1), p(2));
        paramNameClicked = paramName;
    else
        % fprintf('Param ''%s'' position: [%0.1f, %0.1f]\n', paramName, p(1), p(2));
    end
end
if isempty(paramNameClicked)
    return;
end
clipboard('copy',paramNameClicked)
msg = sprintf('''%s''   copied to clipboard',paramNameClicked);
try
    MessageBox(msg, sprintf('Parameter: ''%s''', paramNameClicked), 'timelimit');
catch
    msgbox(msg);
end

% -------------------------------------------------------------
function hcm = setMouseClickAction(hcm, hp)
if nargin<2
    hcm = uicontextmenu();
    uimenu(hcm, 'text','Copy Param Name');
    return
end
hm = get(hcm, 'children');
hm.MenuSelectedFcn = {@mouseClickFcn_Callback,hp};


function n = type(d)

%tstoolbox/@description/type
%   return signal type (e.g. 'Correlation function', 'Spectrogram' etc.)
%
% Copyright 1997-2001 DPI Goettingen, License http://www.physik3.gwdg.de/tstool/gpl.txt

narginchk(1,1);

n = d.type;


function [config,fn]=cosmo_config(fn, config)
% return a struc with configuration settings, or store such settings
%
% Usages:
% - get the configuation (either default, or what is in '.cosmomvpa.cfg'):
%   >> config=cosmo_config();
%
% - read configuration from a specified file
%   >> config=cosmo_config(fn)
%
% - store configuration in a file
%   >> cosmo_config(fn, to_store)
%
% - related function (in CoSMoMVPA's 'examples/' directory):
%   >> cosmo_wizard_set_config
%
% Inputs:
%   fn          optional filename of a configuration file.
%               This can either be a path of a file, or (on Unix platforms)
%               a filename in the user's home directory.
%               If fn is omitted, then it defaults to '.cosmomvpa.cfg'
%               and will read the configuration from that file if it
%               exists in one of the aforementioned locations; see the
%               notes below for details.
%   to_store    optional struct with configuration to store.
%               If omitted then the configuration is not stored.
%
% Returns:
%   config      Struct with configurations
%
% Notes:
%  - the rationale for this function is to keep the example code fixed
%    (that is, without any paths hard-coded) and still allow each
%    user to store the example data in a directory of their choice.
%
%  - the format for a configuration file is of the form <key>=<value>,
%    where <key> cannot contain the '=' character and <value> cannot start
%    or end with a white-space character.

%  - if the .cosmomvpa.cfg file is in the same directory as this file
%   (presently, 'mvpa/'), it will be found there as well.
%
%  - an example configuration file (of three lines):
%
% # path for runnable examples
% tutorial_data_path=/Users/nick/organized/_datasets/CoSMoMVPA/tutorial_data
% output_data_path=/Users/nick/organized/_datasets/CoSMoMVPA/tutorial_data
%
%  - If a configuration file with the name '.cosmomvpa.cfg' is stored
%    in a directory that is in the matlab path, the user path, or (on Unix
%    platforms) the user's home directory, then calling this function with
%    no arguments will read that file and return the configuration stored
%    in it.
%
%  - The configuration can also be changed as follows:
%    >> % get default configuration
%    >> % If the following command gives an error, do: config=struct()
%    >> config=cosmo_config();
%    >>
%    >> % update settings
%    >> config.tutorial_data_path='/path/to/some/data';
%    >> config.output_data_path='/where/i/want/output';
%    >>
%    >> % get first directory in user path
%    >> matlab_path=cosmo_strsplit (userpath,':',1);
%    >>
%    >> % set configuration filename
%    >> config_fn=fullfile(matlab_path,'.cosmomvpa.cfg');
%    >> cosmo_config(config_fn, config);
%    >> fprintf('Configuration stored in %s\n', config_fn);
%    >>
%    >> % now check they are the same
%    >> loaded_config=cosmo_config();
%    >> assert(isequal(loaded_config,config));
%
%  - The configuration can be set using cosmo_wizard_set_config in
%    CoSMoMVPA's 'examples/' directory
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #

    default_config_fn='.cosmomvpa.cfg';

    if nargin==1 && ischar(fn)
        fn=find_config_file(fn);
        config=read_config(fn);
    elseif nargin==0
        % see if the configuration file can be found
        fn=find_config_file(default_config_fn);
        if isempty(fn)
            config=struct();
        else
            config=read_config(fn);
        end
    elseif nargin==2 && ischar(fn) && isstruct(config)
        write_config(fn,config);
    else
        error('Illegal input');
    end

    expected_fields={'tutorial_data_path','output_data_path'};
    missing_fields=setdiff(expected_fields,fieldnames(config));

    if numel(missing_fields)>0
        missing_fields_str=cosmo_strjoin(missing_fields,''', ''');
        cosmo_warning(['Using %s, fields ''%s'' are missing. This makes '...
                    'it more complicated to run CoSMoMVPA''s '...
                    'exercises and examples.\n'...
                    'To set the configuration, consider running\n\n'...
                    '    cosmo_wizard_set_config\n\n'...
                    'in the CoSMoMVPA ''examples/'' directory'],...
                    mfilename(),missing_fields_str);
    end

    validate_config(config);

function validate_config(config)
    % simple validation of config

    % poor-man version of OO
    path_exists=struct();
    path_exists.match=@(x)isempty(cosmo_strsplit(x,'_path',-1));
    path_exists.test=@(p) exist(p,'file');
    path_exists.msg=@(key, p) sprintf('%s: path "%s" not found. ',key,p);

    checks={path_exists};
    add_msg=sprintf('To set the configuration, run: help %s', mfilename());

    % perform checks on fieldnames present in 'checks'.

    fns=fieldnames(config);
    for k=1:numel(fns)
        fn=fns{k};
        for j=1:numel(checks)
            check=checks{j};
            if check.match(fn)
                test_func=check.test;
                value=config.(fn);

                if ~test_func(value)
                    msg_func=check.msg;
                    cosmo_warning('%s\n%s',msg_func(fn, value),add_msg);
                end
            end
        end
    end

function path_fn=find_config_file(fn, raise_)
% tries to find a configuration file by looking:
% - for the path of the file
% - in the matlab path
% - in the user's home directory (on Unix)
    if nargin<2, raise_=false; end

    exist_=@(fn_) exist(fn_,'file');

    path_fn=[];

    % simulate 'go-to' statement using a while loop with break at the end
    while true
        % does the file exist 'as is'?
        if exist_(fn)
            path_fn=fn;
            break
        end

        % is it in the mvpa directory?
        parent_dir=fileparts(mfilename('fullpath'));
        m_fn=fullfile(parent_dir,fn);
        if exist_(m_fn)
            path_fn=m_fn;
            break;
        end

        % is it in the user path?
        % (not supported on octave)
        if cosmo_wtf('is_matlab')
            upaths=cosmo_strsplit(userpath(),pathsep());

            for k=1:numel(upaths)
                u_fn=fullfile(upaths{k},fn);
                if exist_(u_fn)
                    path_fn=u_fn;
                    break;
                end
            end
            if ~isempty(path_fn)
                break;
            end
        end

        if isunix()
            % is it in the home directory?
            u_fn=fullfile(getenv('HOME'),fn);
            if exist_(u_fn)
                path_fn=u_fn;
                break;
            end
        end

        if raise_
            error('Cannot find config file "%s"', fn);
        end

        break;
    end

function config=read_config(fn)
% reads configuration from a file fn

    config=struct(); % space for output
    if isempty(fn)
        error('Input file not specified - cannot open')
    end

    fid=fopen(fn);
    if fid==-1
        error('Unable to open file %s',fn);
    end

    line_number=0;
    while true
        % read each line
        line=fgetl(fid);
        if ~ischar(line)
            % end of file
            break;
        end

        line_number=line_number+1;

        % ignore empty lines or lines starting with '#'
        if isempty(line) || line(1)=='#'
            continue
        end

        % look for lines of form '<key>=<value>'.
        % white spaces around key or value are ignored.
        m=regexp(line,'(?<key>[^=]+)\s*=\s*(?<value>.*)\s*','names');

        if isempty(m)
            cosmo_warning('Skipping non-recognized line "%s"', line);
            continue;
        end

        % get key and value
        key=m.key;
        value=m.value;

        verify_no_illegal_char(fn,line_number,[key value])

        % see if it can be converted to numeric
        value_num=str2double(value);
        if ~isnan(value_num)
            value=value_num;
        end

        config.(key)=value;
    end

    fclose(fid);

function verify_no_illegal_char(fn,line_number,s)
    illegal_chars=sprintf('"''');
    matching=bsxfun(@eq,s,illegal_chars(:));
    if any(matching(:))
        error(['File %s, line %d: found illegal character. '...
            'note that quote characters are not allowed '...
            'for keys or values'],fn,line_number)
    end

function write_config(fn, config)
% writes the config to a file fn
% no support for comments or empty lines

    fid=fopen(fn,'w');

    fns=fieldnames(config);
    for k=1:numel(fns)
        fn=fns{k};

        v=config.(fn);
        if isnumeric(v)
            % convert numeric to string
            v=sprintf('%d ',v);
        elseif ischar(v)
            % no converstion
        else
            cosmo_warning('Skipping unsupported data type for key "%s"',...
                                                fn);
        end
        fprintf(fid,'%s=%s\n',fn,v);
    end

    fclose(fid);


%kVRML 'visualizes threshhold images using vrwave '
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros VRML.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'First Input data object'
%
% Example: kVRML(i, {'i',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% VRML - visualizes threshhold images using vrwave
%
%  DESCRIPTION
%
%
%
%  EXAMPLES
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1996-2003, Rainer Heintzmann,  All rights reserved.
%

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

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


classdef AnnotationMarkerHandle < handle
    properties
        lineHandle;
        textHandle;
    end

    properties (Dependent)
        visible;
    end

    methods
        function set.visible(obj,visibleStr)
            obj.textHandle.Visible = visibleStr;
            obj.lineHandle.Visible = visibleStr;
        end
    end

    methods (Access = public)
        function obj = AnnotationMarkerHandle(lineHandle,textHandle)
            if nargin ~= 0
                obj.lineHandle = lineHandle;
                obj.textHandle = textHandle;
            end
        end
    end
end


function [min] = ns2min(ns)
% Convert time from nanoseconds to minutes.
% Chad Greene 2012
min = ns/60*1e-9 ;

% Dear Postmaster General,
%
% The following is a list of individuals who do not live in my house:
%
%     Current Resident
%     Smart Shopper
%     Valued Customer
%     Our Neighbor
%     Deal Seeker
%     Postal Patron
%     Thrifty Consumer
%     Box Holder
%     Home Owner
%     Tax Payer
%     Texas Voter
%     Pet Lover
%     Bargain Buyer
%     Sports Fan
%     Safe Driver
%     Future Client
%     Home Chef
%     Steak Lover
%     Darryl Jenkins
%
% Please refrain from delivering their mail to my address.


% GIfTI Class for MATLAB
%
% Geometry format under the Neuroimaging Informatics Technology Initiative
% (NIfTI):
%                 http://www.nitrc.org/projects/gifti/
%                      http://nifti.nimh.nih.gov/
%
% This MATLAB class is part of SPM:
%                  http://www.fil.ion.ucl.ac.uk/spm/
%
% It relies on external libraries:
%   Base64, by Peter J. Acklam:
%      http://home.online.no/~pjacklam/
%   miniz, by Rich Geldreich:
%      http://code.google.com/p/miniz/
%   XMLTree, by Guillaume Flandin:
%      http://www.artefact.tk/software/matlab/xml/
%__________________________________________________________________________
% Copyright (C) 2008-2015 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: Contents.m 6404 2015-04-13 14:29:53Z guillaume $

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


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

%%
clear; close all; clc;

%% Syntax
% |[t]=mat2strIntDouble(varargin);|

%% Description
% UNDOCUMENTED
%% Examples
%
%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.