function [metabolite_structure,IDsAdded] = parseKeggWebpage(metabolite_structure,startSearch,endSearch)

annotationSource = 'Kegg website';
annotationType = 'automatic';

Mets = fieldnames(metabolite_structure);
a = 1;
IDsAdded = '';

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

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

% I am not going to collect pubchemId's as kegg has deposited its own id's
% to pubchem in the past and I prefer the "real" pubchem id's
mapping ={
   'casRegistry'   '<nobr>CAS:'
   'cheBIId' 'https://www.ebi.ac.uk/chebi/'
  %  'pubchemId' 'https://pubchem.ncbi.nlm.nih.gov/'
    'chembl'    'https://www.ebi.ac.uk/chembldb'
   'knapsack'  'http://kanaya.naist.jp/knapsack_jsp'
    };

for i = startSearch : endSearch%size(Mets,1)

    if ~isempty(metabolite_structure.(Mets{i}).VMHId) && isempty(find(isnan(metabolite_structure.(Mets{i}).VMHId),1))

        if(~isempty(metabolite_structure.(Mets{i}).keggId) && isempty(find(isnan(metabolite_structure.(Mets{i}).keggId),1)))

            try

                url = strcat('https://www.genome.jp/dbget-bin/www_bget?',metabolite_structure.(Mets{i}).keggId);
                syst = urlread(url);

                for k = 1 : size(mapping,1)
                    [metabolite_structure,idNew] = getData(metabolite_structure,syst,Mets{i}, mapping(k,:),IDsAdded);
                    if ~isempty(idNew) && isempty(find(isnan(idNew),1))
                        if isempty(metabolite_structure.(Mets{i}).(mapping{k,1})) || ~isempty(find(isnan(metabolite_structure.(Mets{i}).(mapping{k,1})),1))
                            metabolite_structure.(Mets{i}).(mapping{k,1}) = (idNew);
                            metabolite_structure.(Mets{i}).(strcat(mapping{k,1},'_source')) = [annotationSource,':',annotationType,':',datestr(now)];
                            IDsAdded{a,1} = Mets{i};
                            IDsAdded{a,2} = mapping{k,1};
                            IDsAdded{a,3} = char(idNew);
                            a = a+1;
                        end
                    end
                end
            catch
                continue;
            end
        end
    end
end

function [metabolite_structure,idNew] = getData(metabolite_structure,syst,met, map,IDsAdded)
a = size(IDsAdded,1)+1;
idNew = '';
try
    startSearchvalue=strfind(syst,map{1,2});
    string = syst(startSearchvalue(1):startSearchvalue(1)+200);

    if contains(map{1,1},'cas')
        string = regexprep(string,'<nobr>CAS: </nobr></td><td>','');
        [tok,rem] = strtok(string,'<');
        idNew = tok;
    elseif contains(map{1,1},'pubchemId')
        [tok,rem] = strtok(string,'=');
        [tok2,rem2] = strtok(rem,'>');
        idNew = regexprep(tok2,'=','');
        idNew = regexprep(idNew,'\W$','');
    elseif contains(map{1,1},'cheBIId')
        [tok,rem] = strtok(string,'=');
        [tok2,rem2] = strtok(rem,'>');
        idNew = regexprep(tok2,'=','');
        idNew = regexprep(idNew,'CHEBI:','');
        idNew = regexprep(idNew,'\W$','');
    elseif contains(map{1,1},'chembl') ||  contains(map{1,1},'knapsack')
        [tok,rem] = strtok(string,'>');
        [tok2,rem2] = strtok(rem,'<');
        idNew = regexprep(tok2,'>','');

    end

end


function [im,stamp] = fmfreadframe(fid,loc,nr,nc,bytes_per_chunk,data_format)

if fseek(fid,loc,'bof') == 0,
  [im,stamp] = fmf_read_frame(fid,nr,nc,bytes_per_chunk,data_format);
else
  im = -1;
  stamp = -1;
end


%-----------------------------------------------------------------------
% Job configuration created by cfg_util (rev $Rev: 325M $)
%-----------------------------------------------------------------------
matlabbatch{1}.cfg_basicio.cfg_named_dir.name = 'Subject directory';
matlabbatch{1}.cfg_basicio.cfg_named_dir.dirs = {'<UNDEFINED>'};
matlabbatch{2}.cfg_basicio.cfg_cd.dir = '<UNDEFINED>';
matlabbatch{3}.cfg_basicio.cfg_mkdir.parent = '<UNDEFINED>';
matlabbatch{3}.cfg_basicio.cfg_mkdir.name = 'categorical';
matlabbatch{4}.spm.spatial.realign.estwrite.data = {'<UNDEFINED>'};
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.quality = 0.9;
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.sep = 4;
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.fwhm = 5;
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.rtm = 0;
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.interp = 2;
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.wrap = [0 0 0];
matlabbatch{4}.spm.spatial.realign.estwrite.eoptions.weight = {};
matlabbatch{4}.spm.spatial.realign.estwrite.roptions.which = [2 1];
matlabbatch{4}.spm.spatial.realign.estwrite.roptions.interp = 4;
matlabbatch{4}.spm.spatial.realign.estwrite.roptions.wrap = [0 0 0];
matlabbatch{4}.spm.spatial.realign.estwrite.roptions.mask = 1;
matlabbatch{4}.spm.spatial.realign.estwrite.roptions.prefix = 'r';
matlabbatch{5}.spm.temporal.st.scans = {'<UNDEFINED>'};
matlabbatch{5}.spm.temporal.st.nslices = 24;
matlabbatch{5}.spm.temporal.st.tr = 2;
matlabbatch{5}.spm.temporal.st.ta = 1.91666666666667;
matlabbatch{5}.spm.temporal.st.so = [24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1];
matlabbatch{5}.spm.temporal.st.refslice = 12;
matlabbatch{5}.spm.temporal.st.prefix = 'a';
matlabbatch{6}.spm.spatial.coreg.estimate.ref = '<UNDEFINED>';
matlabbatch{6}.spm.spatial.coreg.estimate.source = '<UNDEFINED>';
matlabbatch{6}.spm.spatial.coreg.estimate.other = {''};
matlabbatch{6}.spm.spatial.coreg.estimate.eoptions.cost_fun = 'nmi';
matlabbatch{6}.spm.spatial.coreg.estimate.eoptions.sep = [4 2];
matlabbatch{6}.spm.spatial.coreg.estimate.eoptions.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001];
matlabbatch{6}.spm.spatial.coreg.estimate.eoptions.fwhm = [7 7];
matlabbatch{7}.spm.spatial.preproc.data = '<UNDEFINED>';
matlabbatch{7}.spm.spatial.preproc.output.GM = [0 0 1];
matlabbatch{7}.spm.spatial.preproc.output.WM = [0 0 1];
matlabbatch{7}.spm.spatial.preproc.output.CSF = [0 0 0];
matlabbatch{7}.spm.spatial.preproc.output.biascor = 1;
matlabbatch{7}.spm.spatial.preproc.output.cleanup = 0;
matlabbatch{7}.spm.spatial.preproc.opts.tpm = {
                                               '/export/spm-devel/spm/trunk/tpm/grey.nii'
                                               '/export/spm-devel/spm/trunk/tpm/white.nii'
                                               '/export/spm-devel/spm/trunk/tpm/csf.nii'
                                               };
matlabbatch{7}.spm.spatial.preproc.opts.ngaus = [2
                                                 2
                                                 2
                                                 4];
matlabbatch{7}.spm.spatial.preproc.opts.regtype = 'mni';
matlabbatch{7}.spm.spatial.preproc.opts.warpreg = 1;
matlabbatch{7}.spm.spatial.preproc.opts.warpco = 25;
matlabbatch{7}.spm.spatial.preproc.opts.biasreg = 0.0001;
matlabbatch{7}.spm.spatial.preproc.opts.biasfwhm = 60;
matlabbatch{7}.spm.spatial.preproc.opts.samp = 3;
matlabbatch{7}.spm.spatial.preproc.opts.msk = {''};
matlabbatch{8}.spm.spatial.normalise.write.subj.matname = '<UNDEFINED>';
matlabbatch{8}.spm.spatial.normalise.write.subj.resample = '<UNDEFINED>';
matlabbatch{8}.spm.spatial.normalise.write.roptions.preserve = 0;
matlabbatch{8}.spm.spatial.normalise.write.roptions.bb = [-78 -112 -50
                                                          78 76 85];
matlabbatch{8}.spm.spatial.normalise.write.roptions.vox = [3 3 3];
matlabbatch{8}.spm.spatial.normalise.write.roptions.interp = 1;
matlabbatch{8}.spm.spatial.normalise.write.roptions.wrap = [0 0 0];
matlabbatch{8}.spm.spatial.normalise.write.roptions.prefix = 'w';
matlabbatch{9}.spm.spatial.smooth.data = '<UNDEFINED>';
matlabbatch{9}.spm.spatial.smooth.fwhm = [8 8 8];
matlabbatch{9}.spm.spatial.smooth.dtype = 0;
matlabbatch{9}.spm.spatial.smooth.prefix = 's';
matlabbatch{10}.spm.stats.fmri_spec.dir = '<UNDEFINED>';
matlabbatch{10}.spm.stats.fmri_spec.timing.units = 'scans';
matlabbatch{10}.spm.stats.fmri_spec.timing.RT = 2;
matlabbatch{10}.spm.stats.fmri_spec.timing.fmri_t = 24;
matlabbatch{10}.spm.stats.fmri_spec.timing.fmri_t0 = 12;
matlabbatch{10}.spm.stats.fmri_spec.sess.scans = '<UNDEFINED>';
matlabbatch{10}.spm.stats.fmri_spec.sess.cond = struct('name', {}, 'onset', {}, 'duration', {}, 'tmod', {}, 'pmod', {});
matlabbatch{10}.spm.stats.fmri_spec.sess.multi = '<UNDEFINED>';
matlabbatch{10}.spm.stats.fmri_spec.sess.regress = struct('name', {}, 'val', {});
matlabbatch{10}.spm.stats.fmri_spec.sess.multi_reg = '<UNDEFINED>';
matlabbatch{10}.spm.stats.fmri_spec.sess.hpf = 128;
matlabbatch{10}.spm.stats.fmri_spec.fact(1).name = 'Fam';
matlabbatch{10}.spm.stats.fmri_spec.fact(1).levels = 2;
matlabbatch{10}.spm.stats.fmri_spec.fact(2).name = 'Rep';
matlabbatch{10}.spm.stats.fmri_spec.fact(2).levels = 2;
matlabbatch{10}.spm.stats.fmri_spec.bases.hrf.derivs = [1 1];
matlabbatch{10}.spm.stats.fmri_spec.volt = 1;
matlabbatch{10}.spm.stats.fmri_spec.global = 'None';
matlabbatch{10}.spm.stats.fmri_spec.mask = {''};
matlabbatch{10}.spm.stats.fmri_spec.cvi = 'AR(1)';
matlabbatch{11}.spm.stats.fmri_est.spmmat = '<UNDEFINED>';
matlabbatch{11}.spm.stats.fmri_est.method.Classical = 1;
matlabbatch{12}.spm.stats.con.spmmat = '<UNDEFINED>';
matlabbatch{12}.spm.stats.con.consess{1}.fcon.name = 'Effects of interest';
%%
matlabbatch{12}.spm.stats.con.consess{1}.fcon.convec = {
                                                        [1 0 0 0 0 0 0 0 0 0 0 0
                                                        0 1 0 0 0 0 0 0 0 0 0 0
                                                        0 0 1 0 0 0 0 0 0 0 0 0
                                                        0 0 0 1 0 0 0 0 0 0 0 0
                                                        0 0 0 0 1 0 0 0 0 0 0 0
                                                        0 0 0 0 0 1 0 0 0 0 0 0
                                                        0 0 0 0 0 0 1 0 0 0 0 0
                                                        0 0 0 0 0 0 0 1 0 0 0 0
                                                        0 0 0 0 0 0 0 0 1 0 0 0
                                                        0 0 0 0 0 0 0 0 0 1 0 0
                                                        0 0 0 0 0 0 0 0 0 0 1 0
                                                        0 0 0 0 0 0 0 0 0 0 0 1]
                                                        }';
%%
matlabbatch{12}.spm.stats.con.consess{1}.fcon.sessrep = 'none';
matlabbatch{12}.spm.stats.con.delete = 0;
matlabbatch{13}.spm.stats.results.spmmat = '<UNDEFINED>';
matlabbatch{13}.spm.stats.results.conspec.titlestr = '';
matlabbatch{13}.spm.stats.results.conspec.contrasts = Inf;
matlabbatch{13}.spm.stats.results.conspec.threshdesc = 'FWE';
matlabbatch{13}.spm.stats.results.conspec.thresh = 0.05;
matlabbatch{13}.spm.stats.results.conspec.extent = 0;
matlabbatch{13}.spm.stats.results.conspec.mask = struct('contrasts', {}, 'thresh', {}, 'mtype', {});
matlabbatch{13}.spm.stats.results.print = 1;


function handle = findfig(figname)
    % function handle = findfig(FIGNAME)
    % Returns the handle of the foremost figure
    % with name FIGNAME, or 0 if not found
    %
    % Keith Rogers 9/26/94

    allfigs = get(groot,'children');
    handle = 0;
    for thisfig = (allfigs')
        if strcmp(get(thisfig,'name'),figname)
            handle = thisfig;
            break
        end
    end


a=input('Introduceti valoarea lui a:')


%  Imbed Zoom, Interp, and Info menu to view_nii window.
%
%  Usage: view_nii_menu(fig);
%

%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)
%
%--------------------------------------------------------------------
function menu_hdl = view_nii_menu(fig, varargin)

   if isnumeric(fig)
      menu_hdl = init(fig);
      return;
   end

   menu_hdl = [];

   switch fig
   case 'interp'
      if nargin > 1
         fig = varargin{1};
      else
         fig = gcbf;
      end

      nii_menu = getappdata(fig, 'nii_menu');
      interp_on_state = get(nii_menu.Minterp,'Userdata');

      if (interp_on_state == 1)
         opt.useinterp = 1;
         view_nii(fig,opt);
         set(nii_menu.Minterp,'Userdata',0,'Label','Interp off');
         reset_zoom(fig);
      else
         opt.useinterp = 0;
         view_nii(fig,opt);
         set(nii_menu.Minterp,'Userdata',1,'Label','Interp on');
         reset_zoom(fig);
      end
   case 'reset_zoom'
      if nargin > 1
         fig = varargin{1};
      else
         fig = gcbf;
      end

      reset_zoom(fig);
   case 'orient'
      orient;
   case 'editvox'
      editvox;
   case 'img_info'
      img_info;
   case 'save_disp'
      save_disp;
   end

   return					% view_nii_menu

%--------------------------------------------------------------------
function menu_hdl = init(fig)

   %  search for edit, view menu
   %
   nii_menu.Mfile = [];
   nii_menu.Medit = [];
   nii_menu.Mview = [];
   menuitems = findobj(fig, 'type', 'uimenu');

   for i=1:length(menuitems)
      filelabel = get(menuitems(i),'label');

      if strcmpi(strrep(filelabel, '&', ''), 'file')
         nii_menu.Mfile = menuitems(i);
      end

      editlabel = get(menuitems(i),'label');

      if strcmpi(strrep(editlabel, '&', ''), 'edit')
         nii_menu.Medit = menuitems(i);
      end

      viewlabel = get(menuitems(i),'label');

      if strcmpi(strrep(viewlabel, '&', ''), 'view')
         nii_menu.Mview = menuitems(i);
      end
   end

   set(fig, 'menubar', 'none');

   if isempty(nii_menu.Mfile)
      nii_menu.Mfile = uimenu('Parent',fig, ...
   	   'Label','File');

      nii_menu.Mfile_save = uimenu('Parent',nii_menu.Mfile, ...
   	   'Label','Save displayed image as ...', ...
           'Callback','view_nii_menu(''save_disp'');');
   else
      nii_menu.Mfile_save = uimenu('Parent',nii_menu.Mfile, ...
   	   'Label','Save displayed image as ...', ...
           'separator','on', ...
           'Callback','view_nii_menu(''save_disp'');');
   end

   if isempty(nii_menu.Medit)
      nii_menu.Medit = uimenu('Parent',fig, ...
   	   'Label','Edit');

      nii_menu.Medit_orient = uimenu('Parent',nii_menu.Medit, ...
   	   'Label','Convert to RAS orientation', ...
           'Callback','view_nii_menu(''orient'');');

      nii_menu.Medit_editvox = uimenu('Parent',nii_menu.Medit, ...
   	   'Label','Edit voxel value at crosshair', ...
           'Callback','view_nii_menu(''editvox'');');
   else
      nii_menu.Medit_orient = uimenu('Parent',nii_menu.Medit, ...
   	   'Label','Convert to RAS orientation', ...
           'separator','on', ...
           'Callback','view_nii_menu(''orient'');');

      nii_menu.Medit_editvox = uimenu('Parent',nii_menu.Medit, ...
   	   'Label','Edit voxel value at crosshair', ...
           'Callback','view_nii_menu(''editvox'');');
   end

   if isempty(nii_menu.Mview)
      nii_menu.Mview = uimenu('Parent',fig, ...
   	   'Label','View');

      nii_menu.Mview_info = uimenu('Parent',nii_menu.Mview, ...
   	   'Label','Image Information', ...
           'Callback','view_nii_menu(''img_info'');');
   else
      nii_menu.Mview_info = uimenu('Parent',nii_menu.Mview, ...
   	   'Label','Image Information', ...
           'separator','on', ...
           'Callback','view_nii_menu(''img_info'');');
   end

   nii_menu.Mzoom = rri_zoom_menu(fig);

   nii_menu.Minterp = uimenu('Parent',fig, ...
   	   'Label','Interp on', ...
	   'Userdata', 1, ...
           'Callback','view_nii_menu(''interp'');');

   setappdata(fig,'nii_menu',nii_menu);
   menu_hdl = nii_menu.Minterp;

   return					% init

%----------------------------------------------------------------
function reset_zoom(fig)

   old_handle_vis = get(fig, 'HandleVisibility');
   set(fig, 'HandleVisibility', 'on');

   nii_view = getappdata(fig, 'nii_view');
   nii_menu = getappdata(fig, 'nii_menu');

   set(nii_menu.Mzoom,'Userdata',1,'Label','Zoom on');
   set(fig,'pointer','arrow');
   zoom off;

   axes(nii_view.handles.axial_axes);
   setappdata(get(gca,'zlabel'), 'ZOOMAxesData', ...
			[get(gca, 'xlim') get(gca, 'ylim')])
%   zoom reset;
 %  zoom getlimits;
   zoom out;

   axes(nii_view.handles.coronal_axes);
   setappdata(get(gca,'zlabel'), 'ZOOMAxesData', ...
			[get(gca, 'xlim') get(gca, 'ylim')])
%   zoom reset;
 %  zoom getlimits;
   zoom out;

   axes(nii_view.handles.sagittal_axes);
   setappdata(get(gca,'zlabel'), 'ZOOMAxesData', ...
			[get(gca, 'xlim') get(gca, 'ylim')])
%   zoom reset;
 %  zoom getlimits;
   zoom out;

   set(fig, 'HandleVisibility', old_handle_vis);

   return;					% reset_zoom

%----------------------------------------------------------------
function img_info

   nii_view = getappdata(gcbf, 'nii_view');
   hdr = nii_view.nii.hdr;

   max_value = num2str(double(max(nii_view.nii.img(:))));
   min_value = num2str(double(min(nii_view.nii.img(:))));

   dim = sprintf('%d  %d  %d', double(hdr.dime.dim(2:4)));
   vox = sprintf('%.3f  %.3f  %.3f', double(hdr.dime.pixdim(2:4)));

   if double(hdr.dime.datatype) == 1
      type = '1-bit binary';
   elseif double(hdr.dime.datatype) == 2
      type = '8-bit unsigned integer';
   elseif double(hdr.dime.datatype) == 4
      type = '16-bit signed integer';
   elseif double(hdr.dime.datatype) == 8
      type = '32-bit signed integer';
   elseif double(hdr.dime.datatype) == 16
      type = '32-bit single float';
   elseif double(hdr.dime.datatype) == 64
      type = '64-bit double precision';
   elseif double(hdr.dime.datatype) == 128
      type = '24-bit RGB true color';
   elseif double(hdr.dime.datatype) == 256
      type = '8-bit signed integer';
   elseif double(hdr.dime.datatype) == 511
      type = '96-bit RGB true color';
   elseif double(hdr.dime.datatype) == 512
      type = '16-bit unsigned integer';
   elseif double(hdr.dime.datatype) == 768
      type = '32-bit unsigned integer';
   elseif double(hdr.dime.datatype) == 1024
      type = '64-bit signed integer';
   elseif double(hdr.dime.datatype) == 1280
      type = '64-bit unsigned integer';
   end

   msg = {};
   msg = [msg {''}];
   msg = [msg {['Dimension:  [', dim, ']']}];
   msg = [msg {''}];
   msg = [msg {['Voxel Size:  [', vox, ']']}];
   msg = [msg {''}];
   msg = [msg {['Data Type:  [', type, ']']}];
   msg = [msg {''}];
   msg = [msg {['Max Value:  [', max_value, ']']}];
   msg = [msg {''}];
   msg = [msg {['Min Value:  [', min_value, ']']}];
   msg = [msg {''}];

   if isfield(nii_view.nii, 'fileprefix')
      if isfield(nii_view.nii, 'filetype') & nii_view.nii.filetype == 2
         msg = [msg {['File Name:  [', nii_view.nii.fileprefix, '.nii]']}];
         msg = [msg {''}];
      elseif isfield(nii_view.nii, 'filetype')
         msg = [msg {['File Name:  [', nii_view.nii.fileprefix, '.img]']}];
         msg = [msg {''}];
      else
         msg = [msg {['File Prefix:  [', nii_view.nii.fileprefix, ']']}];
         msg = [msg {''}];
      end
   end

   h = msgbox(msg, 'Image Information', 'modal');
   set(h,'color',[1 1 1]);

   return;					% img_info

%----------------------------------------------------------------
function orient

   fig = gcbf;
   nii_view = getappdata(fig, 'nii_view');
   nii = nii_view.nii;

   if ~isempty(nii_view.bgimg)
      msg = 'You can not modify an overlay image';
      h = msgbox(msg, 'Error', 'modal');
      return;
   end

   old_pointer = get(fig,'Pointer');
   set(fig,'Pointer','watch');

   [nii orient] = rri_orient(nii);

   if isequal(orient, [1 2 3])		% do nothing
      set(fig,'Pointer',old_pointer);
      return;
   end

   oldopt = view_nii(fig);
   opt.command = 'updatenii';
   opt.usecolorbar = oldopt.usecolorbar;
   opt.usepanel = oldopt.usepanel;
   opt.usecrosshair = oldopt.usecrosshair;
   opt.usestretch = oldopt.usestretch;
   opt.useimagesc = oldopt.useimagesc;
   opt.useinterp = oldopt.useinterp;
   opt.setarea = oldopt.area;
   opt.setunit = oldopt.unit;
   opt.setviewpoint = oldopt.viewpoint;
   opt.setscanid = oldopt.scanid;
   opt.setcbarminmax = oldopt.cbarminmax;
   opt.setcolorindex = oldopt.colorindex;
   opt.setcolormap = oldopt.colormap;
   opt.setcolorlevel = oldopt.colorlevel;

   if isfield(oldopt,'highcolor')
      opt.sethighcolor = oldopt.highcolor;
   end

   view_nii(fig, nii, opt);
   set(fig,'Pointer',old_pointer);
   reset_zoom(fig);

   return;					% orient

%----------------------------------------------------------------
function editvox

   fig = gcbf;
   nii_view = getappdata(fig, 'nii_view');

   if ~isempty(nii_view.bgimg)
      msg = 'You can not modify an overlay image';
      h = msgbox(msg, 'Error', 'modal');
      return;
   end

   nii = nii_view.nii;
   oldopt = view_nii(fig);
   sag = nii_view.imgXYZ.vox(1);
   cor = nii_view.imgXYZ.vox(2);
   axi = nii_view.imgXYZ.vox(3);

   if nii_view.nii.hdr.dime.datatype == 128
      imgvalue = [double(nii.img(sag,cor,axi,1,nii_view.scanid)) double(nii.img(sag,cor,axi,2,nii_view.scanid)) double(nii.img(sag,cor,axi,3,nii_view.scanid))];
      init_val = sprintf('%7.4g %7.4g %7.4g',imgvalue);
   elseif nii_view.nii.hdr.dime.datatype == 511
      R = double(nii.img(sag,cor,axi,1,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
      G = double(nii.img(sag,cor,axi,2,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
      B = double(nii.img(sag,cor,axi,3,nii_view.scanid)) * (nii_view.nii.hdr.dime.glmax - ...
		nii_view.nii.hdr.dime.glmin) + nii_view.nii.hdr.dime.glmin;
      imgvalue = [R G B];
      init_val = sprintf('%7.4g %7.4g %7.4g',imgvalue);
   else
      imgvalue = double(nii.img(sag,cor,axi,nii_view.scanid));
      init_val = sprintf('%.6g',imgvalue);
   end

   old_pointer = get(fig,'Pointer');
   set(fig,'Pointer','watch');

   repeat = 1;
   while repeat
      if nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511
         init_val = inputdlg({'Replace the current voxel values with 3 new numbers:'}, ...
		'Edit voxel value at crosshair', 1, {num2str(init_val)});
      else
         init_val = inputdlg({'Replace the current voxel value with 1 new number:'}, ...
		'Edit voxel value at crosshair', 1, {num2str(init_val)});
      end

      if isempty(init_val)
         set(fig,'Pointer',old_pointer);
         return
      end

      imgvalue = str2num(init_val{1});

      if ( (nii_view.nii.hdr.dime.datatype == 128 | nii_view.nii.hdr.dime.datatype == 511) ...
		& length(imgvalue) ~= 3 ) | ...
         ( (nii_view.nii.hdr.dime.datatype ~= 128 & nii_view.nii.hdr.dime.datatype ~= 511) ...
		& length(imgvalue) ~= 1 )
	% do nothing
      else
         repeat = 0;
      end
   end

   if nii_view.nii.hdr.dime.datatype == 128
      nii.img(sag,cor,axi,1,nii_view.scanid) = imgvalue(1);
      nii.img(sag,cor,axi,2,nii_view.scanid) = imgvalue(2);
      nii.img(sag,cor,axi,3,nii_view.scanid) = imgvalue(3);
   elseif nii_view.nii.hdr.dime.datatype == 511
      nii.img(sag,cor,axi,1,nii_view.scanid) = (imgvalue(1) - nii_view.nii.hdr.dime.glmin) ...
		/ (nii_view.nii.hdr.dime.glmax - nii_view.nii.hdr.dime.glmin);
      nii.img(sag,cor,axi,2,nii_view.scanid) = (imgvalue(2) - nii_view.nii.hdr.dime.glmin) ...
		/ (nii_view.nii.hdr.dime.glmax - nii_view.nii.hdr.dime.glmin);
      nii.img(sag,cor,axi,3,nii_view.scanid) = (imgvalue(3) - nii_view.nii.hdr.dime.glmin) ...
		/ (nii_view.nii.hdr.dime.glmax - nii_view.nii.hdr.dime.glmin);
   else
      nii.img(sag,cor,axi,nii_view.scanid) = imgvalue;
   end

   opt.command = 'updatenii';
   opt.usecolorbar = oldopt.usecolorbar;
   opt.usepanel = oldopt.usepanel;
   opt.usecrosshair = oldopt.usecrosshair;
   opt.usestretch = oldopt.usestretch;
   opt.useimagesc = oldopt.useimagesc;
   opt.useinterp = oldopt.useinterp;
   opt.setarea = oldopt.area;
   opt.setunit = oldopt.unit;
   opt.setviewpoint = oldopt.viewpoint;
   opt.setscanid = oldopt.scanid;
   opt.setcbarminmax = oldopt.cbarminmax;
   opt.setcolorindex = oldopt.colorindex;
   opt.setcolormap = oldopt.colormap;
   opt.setcolorlevel = oldopt.colorlevel;

   if isfield(oldopt,'highcolor')
      opt.sethighcolor = oldopt.highcolor;
   end

   view_nii(fig, nii, opt);
   set(fig,'Pointer',old_pointer);
   reset_zoom(fig);

   return;					% editvox

%----------------------------------------------------------------
function save_disp

   [filename pathname] = uiputfile('*.*', 'Save displayed image as (*.nii or *.img)');

   if isequal(filename,0) | isequal(pathname,0)
      return;
   else
      out_imgfile = fullfile(pathname, filename);	% original image file
   end

   old_pointer = get(gcbf,'Pointer');
   set(gcbf,'Pointer','watch');

   nii_view = getappdata(gcbf, 'nii_view');
   nii = nii_view.nii;

   try
      save_nii(nii, out_imgfile);
   catch
      msg = 'File can not be saved.';
      msgbox(msg, 'File write error', 'modal');
   end

   set(gcbf,'Pointer',old_pointer);

   return;					% save_disp


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

    properties (Access = private)
        Axes
        Axes3d
        ImageDisplayParameters
        Reporting
        ViewerPanel
    end

    methods

        function obj = MimToolCallback(viewing_panel, image_display_parameters, axes, axes_3d, reporting)
            obj.ImageDisplayParameters = image_display_parameters;
            obj.ViewerPanel = viewing_panel;
            obj.Axes = axes;
            obj.Axes3d = axes_3d;
            obj.Reporting = reporting;
        end

        function EnablePan(obj, enabled)
            obj.GetAxes.EnablePan(enabled);
            obj.GetAxes3d.EnablePan(enabled);
        end

        function EnableZoom(obj, enabled)
            obj.GetAxes.EnableZoom(enabled);
            obj.GetAxes3d.EnableZoom(enabled);
        end

        function EnableRotate3d(obj, enabled)
            obj.GetAxes3d.EnableRotate3d(enabled);
        end

        function [min_coords, max_coords] = GetImageLimits(obj)
            % Gets the current limits of the visible image axes

            [min_coords, max_coords] = obj.GetAxes.GetImageLimits;
        end

        function SetImageLimits(obj, min_coords, max_coords)
            % Adjusts the image axes to make the image visible between the specified
            % coordinates

            x_lim = [min_coords(1), max_coords(1)];
            y_lim = [min_coords(2), max_coords(2)];
            obj.GetAxes.SetLimits(x_lim, y_lim);
        end

        function SetWindowWithinLimits(obj, window)
            % Sets the window subject to the current constraints

            window_limits = obj.ViewerPanel.WindowLimits;
            if ~isempty(window_limits)
                window = max(window, window_limits(1));
                window = min(window, window_limits(2));
                obj.ImageDisplayParameters.Window = window;
            end
        end

        function SetLevelWithinLimits(obj, level)
            % Sets the level subject to the current constraints

            level_limits = obj.ViewerPanel.LevelLimits;
            if ~isempty(level_limits)
                level = max(level, level_limits(1));
                level = min(level, level_limits(2));
                obj.ImageDisplayParameters.Level = level;
            end
        end

        function axes_handle = GetAxes(obj)
            axes_handle = obj.Axes;
            if isempty(axes_handle)
                obj.Reporting.Error('MimToolCallback:AxesDoNotExist', 'Axes have not been created');
            end
        end

        function axes_handle = GetAxes3d(obj)
            axes_handle = obj.Axes3d.GetRenderAxes;
            if isempty(axes_handle)
                obj.Reporting.Error('MimToolCallback:AxesDoNotExist', '3D Axes have not been created');
            end
        end
    end
end


function [ s ] = xml2struct( file )
%Convert xml file into a MATLAB structure
% [ s ] = xml2struct( file )
%
% A file containing:
% <XMLname attrib1="Some value">
%   <Element>Some text</Element>
%   <DifferentElement attrib2="2">Some more text</DifferentElement>
%   <DifferentElement attrib3="2" attrib4="1">Even more text</DifferentElement>
% </XMLname>
%
% Used to produce:
% s.XMLname.Attributes.attrib1 = "Some value";
% s.XMLname.Element.Text = "Some text";
% s.XMLname.DifferentElement{1}.Attributes.attrib2 = "2";
% s.XMLname.DifferentElement{1}.Text = "Some more text";
% s.XMLname.DifferentElement{2}.Attributes.attrib3 = "2";
% s.XMLname.DifferentElement{2}.Attributes.attrib4 = "1";
% s.XMLname.DifferentElement{2}.Text = "Even more text";
%
% Will produce (gp: to matche the output of xml2struct in XML4MAT, but note that Element(2) is empty):
% Element: Some text
% DifferentElement:
%    attrib2: 2
%    DifferentElement: Some more text
% attrib1: Some value
%
% Element:
% DifferentElement:
%    attrib3: 2
%    attrib4: 1
%    DifferentElement: Even more text
% attrib1:
%
% Note the characters : - and . are not supported in structure fieldnames and
% are replaced by _
%
% Written by W. Falkena, ASTI, TUDelft, 21-08-2010
% Attribute parsing speed increased by 40% by A. Wanner, 14-6-2011
% 2011/12/14 giopia: changes in the main function to make more similar to xml2struct of the XML4MAT toolbox, bc it's used by fieldtrip
% 2012/04/04 roboos: added the original license clause, see also http://bugzilla.fieldtriptoolbox.org/show_bug.cgi?id=645#c11
% 2012/04/04 roboos: don't print the filename that is being read

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Copyright (c) 2010, Wouter Falkena
% All rights reserved.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
%     * Redistributions of source code must retain the above copyright
%       notice, this list of conditions and the following disclaimer.
%     * Redistributions in binary form must reproduce the above copyright
%       notice, this list of conditions and the following disclaimer in
%       the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    if (nargin < 1)
        clc;
        help xml2struct
        return
    end

    %check for existance
    if (exist(file,'file') == 0)
        %Perhaps the xml extension was omitted from the file name. Add the
        %extension and try again.
        if (isempty(strfind(file,'.xml')))
            file = [file '.xml'];
        end

        if (exist(file,'file') == 0)
            ft_error(['The file ' file ' could not be found']);
        end
    end
    %fprintf('xml2struct reading %s\n', file); % gp 11/12/15
    %read the xml file
    xDoc = xmlread(file);

    %parse xDoc into a MATLAB structure
    s = parseChildNodes(xDoc);
    fn = fieldnames(s); s = s.(fn{1}); % gp 11/12/15: output is compatible with xml2struct of xml2mat
end

% ----- Subfunction parseChildNodes -----
function [children,ptext] = parseChildNodes(theNode)
    % Recurse over node children.
    children = struct;
    ptext = [];
    if theNode.hasChildNodes
        childNodes = theNode.getChildNodes;
        numChildNodes = childNodes.getLength;

        for count = 1:numChildNodes
            theChild = childNodes.item(count-1);
            [text,name,attr,childs] = getNodeData(theChild);

            if (~strcmp(name,'#text') && ~strcmp(name,'#comment'))
                %XML allows the same elements to be defined multiple times,
                %put each in a different cell
                if (isfield(children,name))
%                     if 0 % numel(children) > 1 % gp 11/12/15: (~iscell(children.(name)))
%                         %put existsing element into cell format
%                         children.(name) = {children.(name)};
%                     end
                    index = length(children)+1; % gp 11/12/15: index = length(children.(name))+1;
                else
                  index = 1; % gp 11/12/15: new field
                end
                %add new element
                children(index).(name) = childs;
                if isempty(attr)
                  if(~isempty(text))
                    children(index).(name) = text;
                  end
                else
                  fn = fieldnames(attr);
                  for f = 1:numel(fn)
                    children(index).(name)(1).(fn{f}) = attr.(fn{f}); % gp 11/12/15: children.(name){index}.('Attributes') = attr;
                  end
                  if(~isempty(text))
                    children(index).(name).(name) = text; % gp 11/12/15: children.(name){index}.('Text') = text;
                  end
                end

%                 else % gp 11/12/15: cleaner code, don't reuse the same code
%                     %add previously unknown new element to the structure
%                     children.(name) = childs;
%                     if(~isempty(text))
%                         children.(name) = text; % gp 11/12/15: children.(name).('Text') = text;
%                     end
%                     if(~isempty(attr))
%                         children.('Attributes') = attr; % gp 11/12/15 children.(name).('Attributes') = attr;
%                     end
%                 end
            elseif (strcmp(name,'#text'))
                %this is the text in an element (i.e. the parentNode)
                if (~isempty(regexprep(text,'[\s]*','')))
                    if (isempty(ptext))
                        ptext = text;
                    else
                        %what to do when element data is as follows:
                        %<element>Text <!--Comment--> More text</element>

                        %put the text in different cells:
                        % if (~iscell(ptext)) ptext = {ptext}; end
                        % ptext{length(ptext)+1} = text;

                        %just append the text
                        ptext = [ptext text];
                    end
                end
            end
        end
    end
end

% ----- Subfunction getNodeData -----
function [text,name,attr,childs] = getNodeData(theNode)
    % Create structure of node info.

    %make sure name is allowed as structure name
    name = regexprep(char(theNode.getNodeName),'[-:.]','_');

    attr = parseAttributes(theNode);
    if (isempty(fieldnames(attr)))
        attr = [];
    end

    %parse child nodes
    [childs,text] = parseChildNodes(theNode);

    if (isempty(fieldnames(childs)))
        %get the data of any childless nodes
        try
            %faster then if any(strcmp(methods(theNode), 'getData'))
            text = char(theNode.getData);
        catch
            %no data
        end
    end

end

% ----- Subfunction parseAttributes -----
function attributes = parseAttributes(theNode)
    % Create attributes structure.

    attributes = struct;
    if theNode.hasAttributes
       theAttributes = theNode.getAttributes;
       numAttributes = theAttributes.getLength;

       for count = 1:numAttributes
            %attrib = theAttributes.item(count-1);
            %attr_name = regexprep(char(attrib.getName),'[-:.]','_');
            %attributes.(attr_name) = char(attrib.getValue);

            %Suggestion of Adrian Wanner
            str = theAttributes.item(count-1).toString.toCharArray()';
            k = strfind(str,'=');
            attr_name = regexprep(str(1:(k(1)-1)),'[-:.]','_');
            attributes.(attr_name) = str((k(1)+2):(end-1));
       end
    end
end


function obj = updateStemseries(obj,dataIndex)

%-store original stem handle-%
stem_group = obj.State.Plot(dataIndex).Handle;

%-get children-%
stem_child = get(stem_group ,'Children');

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

%-update line-%
obj.State.Plot(dataIndex).Handle = stem_child(1);
updateLineseries(obj,dataIndex);
stem_temp_data = obj.data{dataIndex};

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

%-scatter mode-%
stem_temp_data.mode = 'lines+markers';

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

%-update marker-%
obj.State.Plot(dataIndex).Handle = stem_child(2);
updateLineseries(obj,dataIndex);

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

stem_temp_data.marker = obj.data{dataIndex}.marker;

%-hide every other marker-%
color_temp = cell(1,length(stem_temp_data.x));
line_color_temp = cell(1,length(stem_temp_data.x));

for n = 1:3:length(stem_temp_data.x)
    color_temp{n} = 'rgba(0,0,0,0)';
    color_temp{n+1} = stem_temp_data.marker.color;
    color_temp{n+2} = 'rgba(0,0,0,0)';
    line_color_temp{n} = 'rgba(0,0,0,0)';
    line_color_temp{n+1} = stem_temp_data.marker.line.color;
    line_color_temp{n+2} = 'rgba(0,0,0,0)';
end

% add new marker/line colors
stem_temp_data.marker.color = color_temp;
stem_temp_data.marker.line.color = line_color_temp;

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

%-revert handle-%
obj.State.Plot(dataIndex).Handle = stem_group;
obj.data{dataIndex} = stem_temp_data;

end


function edl_initctrlfile(filename, guidstr, n)
%EDL_INITCTRLFILE Creates an initial control file
%
% $ Syntax $
%   - edl_initctrlfile(filename, guidstr, n)
%
% $ Arguments $
%   - filename:     the destination control filename
%   - guidstr:      the GUID identifying the corresponding script
%   - n:            the number of items
%
% $ Description $
%   - edl_initctrlfile(filename, guidstr, n) writes an initial control
%     file with all status set to pending.
%
% $ History $
%   - Created by Dahua Lin, on Aug 14th, 2006
%

%% parse and verify input

if nargin < 3
    raise_lackinput('edl_initctrlfile', 3);
end

%% Write

doctag = 'ExpControl';
attribs.guid = guidstr;
nodetag = 'Entry';

props = struct(...
    'internal_index', mat2cell((1:n)', ones(n,1)), ...
    'status', repmat({'pending'}, [n, 1]) ...
    );

edl_writeprops(doctag, attribs, nodetag, props, filename)


function net = net_move_to_device(net, device)

isDag = isa(net, 'dagnn.DagNN');

if isDag
   net.move(device)
else
   net = vl_simplenn_move(net, device) ;
   if strcmp(device, 'gpu')
       net.useGpu = true;
   else
       net.useGpu = false;
   end
end


function dfadjustlayout(dffig,showctrl)
%ADJUSTLAYOUT Adjust layout of buttons and graph in figure window

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

% Get some measurements
fpos = get(dffig,'Position');
fwidth = fpos(3);
fheight = max(1,fpos(4));

% Adjust selection controls at top
hsel = getappdata(dffig,'selectioncontrols');
lmargin = 0;
if ~isempty(hsel)
   % If there are no selection controls, don't try to compute their height
   emax = zeros(1,4);
   allpos = get(hsel, 'Position');
   allpos = vertcat(allpos{:});
   allextent = get(hsel, 'Extent');
   allextent = vertcat(allextent{:});
   maxheight = max(allextent(2:end,4));   % max height of non-frame controls
end
for j=2:2:length(hsel)
   % Adjust label
   p = allpos(j,:);
   e = allextent(j,:);
   p(1) = lmargin + 5;
   p(2) = fheight-1.45*maxheight;
   p(3) = e(3);
   p(4) = maxheight;
   lmargin = p(1) + p(3);
   set(hsel(j),'Position',p);
   emax = max(emax,e);
   labelwidth = e(3);

   % Adjust drop-down
   p = get(hsel(j+1),'Position');
   e = get(hsel(j+1),'Extent');
   p(1) = lmargin + 5;
   p(2) = fheight-1.25*maxheight;
   p(3) = max(e(3),2.25*labelwidth);
   p(4) = maxheight;
   lmargin = p(1) + p(3) + 20;
   set(hsel(j+1),'Position',p);
   emax = max(emax,e);
end
if ~isempty(hsel)
   % Get position of the base of the frame containing these controls
   framebase = max(1, fheight-1.6*maxheight);
   p = [1, framebase, fwidth, 1.6*maxheight];
   set(hsel(1),'Position',p);
else
   % Say the base of this frame is right at the top of the figure
   framebase = fheight;
end

% Adjust all button positions below selection controls
hbuttons = getappdata(dffig,'buttoncontrols');
if isempty(hbuttons)
   % If there are no buttons, say their base is right at the frame
   buttonbase = framebase;
else
   % If there are buttons, compute the height of their base
   nbuttons = length(hbuttons);
   extents = get(hbuttons,'Extent');
   extents = vertcat(extents{:});
   bheight = 1.5 * extents(1,4);  % 1.5 * text height
   gutter = bheight/4;            % between buttons
   margin = bheight/2;            % around text within button
   bwidth = extents(:,3)' + 2*margin;
   totalwidth = sum(bwidth) + gutter*(nbuttons-1);
   startpos = max(0, (fwidth/2) - (totalwidth/2));
   bleft = startpos + [0, cumsum(bwidth + gutter)];
   buttonbase = max(1, framebase-bheight-gutter);
   for j=1:nbuttons
      pos = [bleft(j), buttonbase, bwidth(j), bheight];
      set(hbuttons(j), 'Position',pos);
   end
end

% Position the axes in the remaining area
ax = get(dffig,'CurrentAxes');
axbase = 0.11*fheight;
p1 = max(1, [.13*fwidth,  axbase, .775*fwidth, .9*buttonbase-axbase]);
set(ax,'Units','pixels','Position',p1);
set(ax,'Units','normalized');

if nargin<2
   showctrl = dfgetset('showaxlimctrl');
end
if isequal(showctrl,'on')
   dfaxlimctrl(dffig,'off');
   dfaxlimctrl(dffig,'on');
end


% gettext() - This function prints a dialog box on screen and waits for
%             the user to enter a string. There is a cancel button which
%             returns a value of [].
% Usage:
%   >> out = gettext(label1,label2,...,label7);
%
% Author: Colin Humphries, CNL / Salk Institute, La Jolla, 1997

% Copyright (C) 1997 Colin Humphries, Salk Institute
%
% 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

% 01-25-02 reformated help & license -ad

function out = gettext(label1,label2,label3,label4,label5,label6,label7);

global is_text_entered
is_text_entered = 0;

for i = 1:nargin
   eval(['leng(i) = length(label',num2str(i),');'])
end
figurelength = 15*1.0*max(leng);

if figurelength < 240
   figurelength = 290;
end

figureheight = 80+nargin*18;
% Set figure

figure('Position',[302 396 figurelength figureheight],'color',[.6 .6 .6],'NumberTitle','off')
f1 = gcf;

ax = axes('Units','Pixels','Position',[0 0 figurelength figureheight],'Visible','off','XLim',[0 figurelength],'YLim',[0 figureheight]);

for i = 1:nargin

   eval(['text(figurelength/2,',num2str(figureheight-(i-1)*18-20),',label',num2str(i),',''color'',''k'',''FontSize'',16,''HorizontalAlignment'',''center'')'])

end
% Set up uicontrols

TIMESTRING = ['global is_text_entered;is_text_entered = 1;clear is_text_entered'];

u = uicontrol('Style','Edit','Units','Pixels','Position',[15 20 figurelength-95 25],'HorizontalAlignment','left','Callback',TIMESTRING);

TIMESTRING = ['global is_text_entered;is_text_entered = 2;clear is_text_entered'];
v = uicontrol('Style','Pushbutton','Units','Pixels','Position',[figurelength-70 20 55 25],'String','Cancel','Callback',TIMESTRING);

while(is_text_entered == 0)
   drawnow
end

if is_text_entered == 1
   out = get(u,'string');
else
   out = [];
end

clear is_text_entered
delete(f1)


function ssd_file_name = generate_ssd_file_name_for_model(ply_file_name,OC_level)

if(exist('OC_level','var'))
    ssd_file_name = sprintf('%s.ssd%d.ply',ply_file_name ,OC_level);
else
    ssd_file_name = sprintf('%s.ssd.ply',ply_file_name);
end


function [env, versionString] = getEnvironment()
% Determine environment (Octave, MATLAB) and version string
% TODO: Unify private `getEnvironment` functions
    persistent cache

    if isempty(cache)
        isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
        if isOctave
            env = 'Octave';
            versionString = OCTAVE_VERSION;
        else
            env = 'MATLAB';
            vData = ver(env);
            versionString = vData.Version;
        end

        % store in cache
        cache.env = env;
        cache.versionString = versionString;

    else
        env = cache.env;
        versionString = cache.versionString;
    end
end


global iiwa;
global isConnected;
global read_state_var;
iiwa=[];
isConnected=false;
read_state_var=false;
%% Feedback values
global feedback_eef_pos;
global feedback_jpos;
feedback_eef_pos=[];
feedback_jpos=[];
%% Interface container
main_frame_width=1200;
main_frame_height=600;
main_frame_x0=10;
main_frame_y0=100;
daCaption='LBR_GUI_interface';
main_frame_h=figure('Name',daCaption,'rend','painters','pos',[main_frame_x0 main_frame_y0 main_frame_width main_frame_height]);
fcn=@closeMainScript;
set(main_frame_h,'CloseRequestFcn',fcn);  % add confirmation dialog to closing the GUI
pause(1);
%% Hand guiding home interface
interface_handguiding_home(main_frame_h)
%% Connection interface
connection_panel_width=400;
connection_panel_height=250;
connection_panel_margin=20;
interface_connection(main_frame_h,main_frame_width,main_frame_height,connection_panel_width,...
    connection_panel_height,connection_panel_margin);
%% Feedback interface
feedback_panel_width=500;
feedback_panel_height=350;
feedback_panel_margin=20;
interface_feedback_panel(main_frame_h, main_frame_width,main_frame_height,feedback_panel_width,...
    feedback_panel_height,feedback_panel_margin);
%% Buttons for adding points to command line
motionCommand_panel_width=220;
motionCommand_panel_height=230;

xPos=main_frame_width-motionCommand_panel_width-feedback_panel_width-2*feedback_panel_margin;
yPos=main_frame_height-motionCommand_panel_height-feedback_panel_margin;

interface_motionCommand_panel(main_frame_h, main_frame_width,main_frame_height,...
    xPos,yPos,motionCommand_panel_width,...
    motionCommand_panel_height);
%% Command line interface
commandLine_width=500;
commandLine_height=200;
commandLine_margin=20;
interface_instructions_commandLine(main_frame_h, main_frame_width,main_frame_height,commandLine_width,...
    commandLine_height,commandLine_margin );
%% Buttons to execute commandLine program
h=main_frame_h;
executeCommandLine_panel_width=motionCommand_panel_width;
executeCommandLine_panel_height=commandLine_height;
xPos=main_frame_width-commandLine_margin-commandLine_width-commandLine_margin-executeCommandLine_panel_width;
yPos=commandLine_margin;
interface_executeCommandLine_panel(h,xPos,yPos,executeCommandLine_panel_width,...
    executeCommandLine_panel_height)
%% Buttons to save/load a program from commandLine
h=main_frame_h;
loadSave_commandLine_Panel_width=motionCommand_panel_width/2;
loadSave_commandLine_Panel_height=commandLine_height;
xPos=main_frame_width...
    -commandLine_margin-commandLine_width...
    -commandLine_margin-executeCommandLine_panel_width...
    -loadSave_commandLine_Panel_width-commandLine_margin;
yPos=commandLine_margin;
interface_save_load_CommandLine_program_panel(h,xPos,yPos,loadSave_commandLine_Panel_width,...
    loadSave_commandLine_Panel_height)


% Defines a protein complex
%
% Author: Jonathan Karr
% Affilitation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 5/7/2009
classdef ProteinComplex < edu.stanford.covert.cell.kb.PhysicalObject & edu.stanford.covert.cell.kb.Protein
    properties
        prostheticGroups            = edu.stanford.covert.cell.kb.Metabolite.empty(0, 0);
        prostheticGroupCompartments = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);
        prostheticGroupCoefficients = [];

        chaperoneSubstrates         = edu.stanford.covert.cell.kb.ProteinMonomer.empty(0, 0);
        chaperoneCompartments       = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);
        chaperoneCoefficients       = [];

        metabolites                 = edu.stanford.covert.cell.kb.Metabolite.empty(0, 0);
        metaboliteCompartments      = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);
        metaboliteCoefficients      = [];

        rnas                        = edu.stanford.covert.cell.kb.Gene.empty(0, 0);
        rnaCompartments             = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);
        rnaCoefficients             = [];

        proteinMonomers             = edu.stanford.covert.cell.kb.ProteinMonomer.empty(0, 0);
        proteinMonomerCompartments  = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);
        proteinMonomerCoefficients  = [];

        proteinComplexs             = edu.stanford.covert.cell.kb.ProteinComplex.empty(0, 0);
        proteinComplexCompartments  = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);
        proteinComplexCoefficients  = [];

        stableModificationReactions = edu.stanford.covert.cell.kb.Reaction.empty(0, 0);

        regulatedTranscriptionUnits = edu.stanford.covert.cell.kb.TranscriptionUnit.empty(0, 0);

        compartment                 = edu.stanford.covert.cell.kb.Compartment.empty(0, 0);

        stimuliRegulators           = edu.stanford.covert.cell.kb.Stimuli.empty(0, 0);
        metaboliteRegulators        = edu.stanford.covert.cell.kb.Metabolite.empty(0, 0);
        proteinMonomerRegulators    = edu.stanford.covert.cell.kb.ProteinMonomer.empty(0, 0);
        proteinComplexRegulators    = edu.stanford.covert.cell.kb.ProteinComplex.empty(0, 0);

        regulatedProteinMonomers    = edu.stanford.covert.cell.kb.ProteinMonomer.empty(0, 0);
        regulatedProteinComplexs    = edu.stanford.covert.cell.kb.ProteinComplex.empty(0, 0);

        parameters                  = edu.stanford.covert.cell.kb.Parameter.empty(0, 0);

        complexFormationProcess      = edu.stanford.covert.cell.kb.Process.empty(0, 0); %process where complex is formed
    end

    properties %(SetAccess = protected)
        empiricalFormula
        smiles
        charge
        pKa
        halfLife
        activationRule
        disulfideBondMonomers = cell(0, 1);
        disulfideBondCysteines = zeros(0, 2);
    end

    %computed properties
    properties %(SetAccess = protected)
        rnaComposition
        proteinMonomerComposition

        molecularWeight
        density
        volume
        pI
        extinctionCoefficient
        absorbanceFactor

        negAA
        posAA
        instabilityIndex
        stable
        aliphaticIndex
        gravy

        baseCount
        cumulativeBaseCount
        decayReaction
        tRNACount

        matureBaseCount
        matureMolecularWeight
        matureHalfLife
        matureDecayReaction

        numDistinctSubunits
        numSubunits

        numNucleicAcids
        numAminoAcids
        numRNASubunits
        numProteinMonomerSubunits
    end

    methods
        function this = ProteinComplex(knowledgeBase, wid, wholeCellModelID, name,...
                dnaFootprint, dnaFootprintBindingStrandedness, dnaFootprintRegionStrandedness, molecularInteraction, chemicalRegulation, ...
                subsystem, generalClassification, proteaseClassification, ...
                transporterClassification, ...
                activationRule,...
                disulfideBonds,...
                comments, crossReferences)

            if nargin == 0; return; end;

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

                this(i, 1).dnaFootprint = dnaFootprint(i);
                this(i, 1).dnaFootprintBindingStrandedness = dnaFootprintBindingStrandedness{i};
                this(i, 1).dnaFootprintRegionStrandedness = dnaFootprintRegionStrandedness{i};
                this(i, 1).molecularInteraction = molecularInteraction{i};
                this(i, 1).chemicalRegulation = chemicalRegulation{i};
                this(i, 1).subsystem = subsystem{i};
                this(i, 1).generalClassification = generalClassification{i};
                this(i, 1).proteaseClassification = proteaseClassification{i};
                this(i, 1).transporterClassification = transporterClassification{i};
                this(i, 1).activationRule = activationRule{i};

                if disulfideBonds{i}
                    disulfideBondsArr = strsplit(';', disulfideBonds{i});

                    this(i, 1).disulfideBondMonomers = cell(length(disulfideBondsArr), 1);
                    this(i, 1).disulfideBondCysteines = zeros(length(disulfideBondsArr), 2);
                    for j = 1:length(disulfideBondsArr)
                        tmp = strsplit(': ', disulfideBondsArr{j});
                        this(i, 1).disulfideBondMonomers{j, 1} = tmp{1};
                        tmp = strsplit('-', tmp{2});
                        this(i, 1).disulfideBondCysteines(j, :) = [str2double(tmp{1}(2:end)) str2double(tmp{2}(2:end))];
                    end
                end
            end
        end

        function serializeLinks(this)
            for i = 1:numel(this)
                this(i).prostheticGroups            = this.serializeLinksHelper(this(i).prostheticGroups);
                this(i).prostheticGroupCompartments = this.serializeLinksHelper(this(i).prostheticGroupCompartments);
                this(i).prostheticGroupCoefficients = this.serializeLinksHelper(this(i).prostheticGroupCoefficients);

                this(i).chaperoneSubstrates         = this.serializeLinksHelper(this(i).chaperoneSubstrates);
                this(i).chaperoneCompartments       = this.serializeLinksHelper(this(i).chaperoneCompartments);
                this(i).chaperoneCoefficients       = this.serializeLinksHelper(this(i).chaperoneCoefficients);

                this(i).metabolites                 = this.serializeLinksHelper(this(i).metabolites);
                this(i).metaboliteCompartments      = this.serializeLinksHelper(this(i).metaboliteCompartments);
                this(i).metaboliteCoefficients      = this.serializeLinksHelper(this(i).metaboliteCoefficients);

                this(i).rnas                        = this.serializeLinksHelper(this(i).rnas);
                this(i).rnaCompartments             = this.serializeLinksHelper(this(i).rnaCompartments);
                this(i).rnaCoefficients             = this.serializeLinksHelper(this(i).rnaCoefficients);

                this(i).proteinMonomers             = this.serializeLinksHelper(this(i).proteinMonomers);
                this(i).proteinMonomerCompartments  = this.serializeLinksHelper(this(i).proteinMonomerCompartments);
                this(i).proteinMonomerCoefficients  = this.serializeLinksHelper(this(i).proteinMonomerCoefficients);

                this(i).proteinComplexs             = this.serializeLinksHelper(this(i).proteinComplexs);
                this(i).proteinComplexCompartments  = this.serializeLinksHelper(this(i).proteinComplexCompartments);
                this(i).proteinComplexCoefficients  = this.serializeLinksHelper(this(i).proteinComplexCoefficients);

                this(i).stableModificationReactions = this.serializeLinksHelper(this(i).stableModificationReactions);

                this(i).regulatedTranscriptionUnits = this.serializeLinksHelper(this(i).regulatedTranscriptionUnits);

                this(i).compartment                 = this.serializeLinksHelper(this(i).compartment);

                this(i).stimuliRegulators           = this.serializeLinksHelper(this(i).stimuliRegulators);
                this(i).metaboliteRegulators        = this.serializeLinksHelper(this(i).metaboliteRegulators);
                this(i).proteinMonomerRegulators    = this.serializeLinksHelper(this(i).proteinMonomerRegulators);
                this(i).proteinComplexRegulators    = this.serializeLinksHelper(this(i).proteinComplexRegulators);

                this(i).regulatedProteinMonomers    = this.serializeLinksHelper(this(i).regulatedProteinMonomers);
                this(i).regulatedProteinComplexs    = this.serializeLinksHelper(this(i).regulatedProteinComplexs);

                this(i).parameters                  = this.serializeLinksHelper(this(i).parameters);

                this(i).complexFormationProcess     = this.serializeLinksHelper(this(i).complexFormationProcess);

                serializeLinks@edu.stanford.covert.cell.kb.PhysicalObject(this(i));
                serializeLinks@edu.stanford.covert.cell.kb.Protein(this(i));
            end
        end

        function deserializeLinks(this, kb)
            for i = 1:numel(this)
                this(i).prostheticGroups            = this.deserializeLinksHelper(this(i).prostheticGroups, kb.metabolites);
                this(i).prostheticGroupCompartments = this.deserializeLinksHelper(this(i).prostheticGroupCompartments, kb.compartments);
                this(i).prostheticGroupCoefficients = this.deserializeLinksHelper(this(i).prostheticGroupCoefficients);

                this(i).chaperoneSubstrates         = this.deserializeLinksHelper(this(i).chaperoneSubstrates, kb.proteinMonomers);
                this(i).chaperoneCompartments       = this.deserializeLinksHelper(this(i).chaperoneCompartments, kb.compartments);
                this(i).chaperoneCoefficients       = this.deserializeLinksHelper(this(i).chaperoneCoefficients);

                this(i).metabolites                 = this.deserializeLinksHelper(this(i).metabolites, kb.metabolites);
                this(i).metaboliteCompartments      = this.deserializeLinksHelper(this(i).metaboliteCompartments, kb.compartments);
                this(i).metaboliteCoefficients      = this.deserializeLinksHelper(this(i).metaboliteCoefficients);

                this(i).rnas                        = this.deserializeLinksHelper(this(i).rnas, kb.genes);
                this(i).rnaCompartments             = this.deserializeLinksHelper(this(i).rnaCompartments, kb.compartments);
                this(i).rnaCoefficients             = this.deserializeLinksHelper(this(i).rnaCoefficients);

                this(i).proteinMonomers             = this.deserializeLinksHelper(this(i).proteinMonomers, kb.proteinMonomers);
                this(i).proteinMonomerCompartments  = this.deserializeLinksHelper(this(i).proteinMonomerCompartments, kb.compartments);
                this(i).proteinMonomerCoefficients  = this.deserializeLinksHelper(this(i).proteinMonomerCoefficients);

                this(i).proteinComplexs             = this.deserializeLinksHelper(this(i).proteinComplexs, kb.proteinComplexs);
                this(i).proteinComplexCompartments  = this.deserializeLinksHelper(this(i).proteinComplexCompartments, kb.compartments);
                this(i).proteinComplexCoefficients  = this.deserializeLinksHelper(this(i).proteinComplexCoefficients);

                this(i).stableModificationReactions = this.deserializeLinksHelper(this(i).stableModificationReactions, kb.reactions);

                this(i).regulatedTranscriptionUnits = this.deserializeLinksHelper(this(i).regulatedTranscriptionUnits, kb.transcriptionUnits);

                this(i).compartment                 = this.deserializeLinksHelper(this(i).compartment, kb.compartments);

                this(i).stimuliRegulators           = this.deserializeLinksHelper(this(i).stimuliRegulators, kb.stimulis);
                this(i).metaboliteRegulators        = this.deserializeLinksHelper(this(i).metaboliteRegulators, kb.metabolites);
                this(i).proteinMonomerRegulators    = this.deserializeLinksHelper(this(i).proteinMonomerRegulators, kb.proteinMonomers);
                this(i).proteinComplexRegulators    = this.deserializeLinksHelper(this(i).proteinComplexRegulators, kb.proteinComplexs);

                this(i).regulatedProteinMonomers    = this.deserializeLinksHelper(this(i).regulatedProteinMonomers, kb.proteinMonomers);
                this(i).regulatedProteinComplexs    = this.deserializeLinksHelper(this(i).regulatedProteinComplexs, kb.proteinComplexs);

                this(i).parameters                  = this.deserializeLinksHelper(this(i).parameters, kb.parameters);

                this(i).complexFormationProcess     = this.deserializeLinksHelper(this(i).complexFormationProcess, kb.processes);

                deserializeLinks@edu.stanford.covert.cell.kb.PhysicalObject(this(i), kb);
                deserializeLinks@edu.stanford.covert.cell.kb.Protein(this(i), kb);
            end
        end

        function deleteLinks(this)
            for i = 1:numel(this)
                this(i).prostheticGroups            = [];
                this(i).prostheticGroupCompartments = [];
                this(i).prostheticGroupCoefficients = [];

                this(i).chaperoneSubstrates         = [];
                this(i).chaperoneCompartments       = [];
                this(i).chaperoneCoefficients       = [];

                this(i).metabolites                 = [];
                this(i).metaboliteCompartments      = [];
                this(i).metaboliteCoefficients      = [];

                this(i).rnas                        = [];
                this(i).rnaCompartments             = [];
                this(i).rnaCoefficients             = [];

                this(i).proteinMonomers             = [];
                this(i).proteinMonomerCompartments  = [];
                this(i).proteinMonomerCoefficients  = [];

                this(i).proteinComplexs             = [];
                this(i).proteinComplexCompartments  = [];
                this(i).proteinComplexCoefficients  = [];

                this(i).stableModificationReactions = [];

                this(i).regulatedTranscriptionUnits = [];

                this(i).compartment                 = [];

                this(i).stimuliRegulators           = [];
                this(i).metaboliteRegulators        = [];
                this(i).proteinMonomerRegulators    = [];
                this(i).proteinComplexRegulators    = [];

                this(i).regulatedProteinMonomers    = [];
                this(i).regulatedProteinComplexs    = [];

                this(i).parameters                  = [];

                deleteLinks@edu.stanford.covert.cell.kb.PhysicalObject(this(i));
                deleteLinks@edu.stanford.covert.cell.kb.Protein(this(i));
            end
        end

        function value = get.empiricalFormula(this)
            throw(MException('ProteinComplex:error', 'property is not defined'));
        end

        function value = get.smiles(this)
            throw(MException('ProteinComplex:error', 'property is not defined'));
        end

        function value = get.charge(this)
            throw(MException('ProteinComplex:error', 'property is not defined'));
        end

        function value = get.pKa(this)
            throw(MException('ProteinComplex:error', 'property is not defined'));
        end

        function value = get.halfLife(this)
            %retrieve
            if ~isempty(this.halfLife)
                value = this.halfLife;
                return;
            end

            %calculate
            %rnaHalfLives = zeros(1,length(this.rnas));
            %for i = 1:length(this.rnas)
            %    rnaHalfLives(i) = this.rnas(i).halfLife;
            %end

            monomerHalfLives = zeros(1,length(this.proteinMonomers));
            for i = 1:length(this.proteinMonomers)
                monomerHalfLives(i) = this.proteinMonomers(i).matureSequenceHalfLife;
            end

            complexHalfLives = zeros(1,length(this.proteinComplexs));
            for i = 1:length(this.proteinComplexs)
                complexHalfLives(i) = this.proteinComplexs(i).matureHalfLife;
            end

            halfLives = [monomerHalfLives complexHalfLives];
            coefficients = [this.proteinMonomerCoefficients; this.proteinComplexCoefficients];

            if ~isempty(coefficients)
                value = halfLives * coefficients / sum(coefficients);
            else
                value = Inf;
            end

            %store
            this.halfLife = value;
        end

        function value = get.matureHalfLife(this)
            %retrieve
            if ~isempty(this.matureHalfLife)
                value = this.matureHalfLife;
                return;
            end

            %calculate
            value = this.halfLife;

            %store
            this.matureHalfLife = value;
        end

        %leave on composition tree
        function value = get.rnaComposition(this)
            %retrieve
            if ~isempty(this.rnaComposition)
                value = this.rnaComposition;
                return;
            end

            %calculate
            value = this.rnaComposition_Helper();

            %store
            this.rnaComposition = value;
        end

        %helper method because MATLAB won't let you call another objects
        %get.rnaComposition method from within get.rnaComposition
        function value = rnaComposition_Helper(this)
            value = zeros(1, this.knowledgeBase.numGenes, this.knowledgeBase.numCompartments);

            if ~isempty(this.rnas)
                value(sub2ind(size(value),...
                    ones(1, numel(this.rnas)),...
                    double([this.rnas.idx]),...
                    double([this.rnaCompartments.idx]))) = ...
                    this.rnaCoefficients;
            end

            if ~isempty(this.proteinComplexs)
                value = value + ...
                    sum(permute(reshape([this.proteinComplexs.rnaComposition],this.knowledgeBase.numGenes, [], this.knowledgeBase.numCompartments),[2 1 3]) .* ...
                    repmat(this.proteinComplexCoefficients, [1 this.knowledgeBase.numGenes this.knowledgeBase.numCompartments]),1);
            end
        end

        %leave on composition tree
        function value = get.proteinMonomerComposition(this)
            %retrieve
            if ~isempty(this.proteinMonomerComposition)
                value = this.proteinMonomerComposition;
                return;
            end

            %calculate
            value = this.proteinMonomerComposition_Helper();

            %store
            this.proteinMonomerComposition = value;
        end

        %helper method because MATLAB won't let you call another objects
        %get.proteinMonomerComposition method from within
        %get.proteinMonomerComposition
        function value = proteinMonomerComposition_Helper(this)
            value = zeros(1, this.knowledgeBase.numProteinMonomers, this.knowledgeBase.numCompartments);

            if ~isempty(this.proteinMonomers)
                value(sub2ind(size(value),...
                    ones(1, numel(this.proteinMonomers)),...
                    double([this.proteinMonomers.idx]),...
                    double([this.proteinMonomerCompartments.idx]))) = ...
                    this.proteinMonomerCoefficients;
            end

            if ~isempty(this.proteinComplexs)
                value = value + ...
                    sum(permute(reshape([this.proteinComplexs.proteinMonomerComposition],this.knowledgeBase.numProteinMonomers, [], this.knowledgeBase.numCompartments),[2 1 3]) .* ...
                    repmat(this.proteinComplexCoefficients, [1 this.knowledgeBase.numProteinMonomers this.knowledgeBase.numCompartments]),1);
            end
        end

        function value = get.molecularWeight(this)
            %retrieve
            if ~isempty(this.molecularWeight)
                value = this.molecularWeight;
                return;
            end

            %calculate
            metaboliteMolecularWeights = [this.metabolites.molecularWeight];

            rnaMolecularWeights = zeros(1, length(this.rnas));
            for i = 1:length(this.rnas)
                rnaMolecularWeights(i) = this.rnas(i).matureMolecularWeight;
            end

            monomerMolecularWeights = zeros(1, length(this.proteinMonomers));
            for i = 1:length(this.proteinMonomers)
                monomerMolecularWeights(i) = this.proteinMonomers(i).matureSequenceMolecularWeight;
            end

            complexMolecularWeights = zeros(1, length(this.proteinComplexs));
            for i = 1:length(this.proteinComplexs)
                complexMolecularWeights(i) = this.proteinComplexs(i).matureMolecularWeight;
            end

            molecularWeights = [metaboliteMolecularWeights rnaMolecularWeights monomerMolecularWeights complexMolecularWeights];
            coefficients = [this.metaboliteCoefficients; this.rnaCoefficients; this.proteinMonomerCoefficients; this.proteinComplexCoefficients];

            if ~isempty(coefficients)
                value = molecularWeights * coefficients;
            else
                value = 0;
            end

            %store
            this.molecularWeight = value;
        end

        function value = get.matureMolecularWeight(this)
            %retrieve
            if ~isempty(this.matureMolecularWeight)
                value = this.matureMolecularWeight;
                return;
            end

            %calculate
            value = this.molecularWeight;
            if ~isempty(this.prostheticGroups)
                value = value + [this.prostheticGroups.molecularWeight] * ...
                    max(1, this.prostheticGroupCoefficients');
            end

            %store
            this.matureMolecularWeight = value;
        end

        function value = get.density(this)
            %retrieve
            if ~isempty(this.density)
                value = this.density;
                return;
            end

            %calculate
            value = 1.35;

            %store
            this.density = value;
        end

        function value = get.volume(this)
            %retrieve
            if ~isempty(this.volume)
                value = this.volume;
                return;
            end

            %calculate
            value = this.molecularWeight / this.density;

            %store
            this.volume = value;
        end

        function value = get.pI(this)
            %retrieve
            if ~isempty(this.pI)
                value = this.pI;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('pI', true);

            %store
            this.pI = value;
        end

        function value = get.extinctionCoefficient(this)
            %retrieve
            if ~isempty(this.extinctionCoefficient)
                value = this.extinctionCoefficient;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('extinctionCoefficient', true);

            %store
            this.extinctionCoefficient = value;
        end

        function value = get.absorbanceFactor(this)
            %retrieve
            if ~isempty(this.absorbanceFactor)
                value = this.absorbanceFactor;
                return;
            end

            %calculate
            value = this.extinctionCoefficient/this.molecularWeight;

            %store
            this.absorbanceFactor = value;
        end

        function value = get.negAA(this)
            %retrieve
            if ~isempty(this.negAA)
                value = this.negAA;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('negAA', false);

            %store
            this.negAA = value;
        end

        function value = get.posAA(this)
            %retrieve
            if ~isempty(this.posAA)
                value = this.posAA;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('posAA', false);

            %store
            this.posAA = value;
        end

        %Instability index (II)
        function value = get.instabilityIndex(this)
            %retrieve
            if ~isempty(this.instabilityIndex)
                value = this.instabilityIndex;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('instabilityIndex', true);

            %store
            this.instabilityIndex = value;
        end

        function value = get.stable(this)
            %retrieve
            if ~isempty(this.stable)
                value = this.stable;
                return;
            end

            %calculate
            value = (this.instabilityIndex<40);

            %store
            this.stable = value;
        end

        %Aliphatic index
        function value = get.aliphaticIndex(this)
            %retrieve
            if ~isempty(this.aliphaticIndex)
                value = this.aliphaticIndex;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('aliphaticIndex', true);

            %store
            this.aliphaticIndex = value;
        end

        %GRAVY (Grand Average of Hydropathy)
        function value = get.gravy(this)
            %retrieve
            if ~isempty(this.gravy)
                value = this.gravy;
                return;
            end

            %calculate
            value = this.meanSubunitPropertyValue('gravy', true);

            %store
            this.gravy = value;
        end

        %base count (numbers of amino acids)
        function value = get.baseCount(this)
            %retrieve
            if ~isempty(this.baseCount)
                value = this.baseCount;
                return;
            end

            %calculate
            rnaBaseCounts = zeros(length(this.rnas), this.knowledgeBase.numMetabolites);
            for i = 1:length(this.rnas)
                rnaBaseCounts(i, :) = this.rnas(i).matureBaseCount;
            end

            monomerBaseCounts = zeros(length(this.proteinMonomers), this.knowledgeBase.numMetabolites);
            for i = 1:length(this.proteinMonomers)
                monomerBaseCounts(i, :) = this.proteinMonomers(i).matureSequenceBaseCount;
            end

            complexBaseCounts = zeros(length(this.proteinComplexs), this.knowledgeBase.numMetabolites);
            for i = 1:length(this.proteinComplexs)
                complexBaseCounts(i, :) = this.proteinComplexs(i).matureBaseCount;
            end

            baseCounts = [rnaBaseCounts; monomerBaseCounts; complexBaseCounts];
            coefficients = [this.rnaCoefficients; this.proteinMonomerCoefficients; this.proteinComplexCoefficients];

            if ~isempty(coefficients)
                value = coefficients' * baseCounts;
            else
                value = zeros(1, this.knowledgeBase.numMetabolites);
            end

            if ~isempty(this.metabolites)
                value([this.metabolites.idx]) = ...
                    value([this.metabolites.idx]) + ...
                    this.metaboliteCoefficients';
            end

            %store
            this.baseCount = value;
        end

        function value = get.matureBaseCount(this)
            %retrieve
            if ~isempty(this.matureBaseCount)
                value = this.matureBaseCount;
                return;
            end

            %calculate
            value = this.baseCount;
            if ~isempty(this.prostheticGroups)
                value([this.prostheticGroups.idx]) = ...
                    value([this.prostheticGroups.idx]) + ...
                    max(1, this.prostheticGroupCoefficients);
            end

            %store
            this.matureBaseCount = value;
        end

        %base count (numbers of amino acids)
        function value = get.cumulativeBaseCount(this)
            throw(MException('ProteinComplex:error','property is not defined'));
        end

        %codon count
        function value = get.tRNACount(this)
            %retrieve
            if ~isempty(this.tRNACount)
                value = this.tRNACount;
                return;
            end

            %calculate
            monomerTRNACounts = zeros(length(this.proteinMonomers),this.knowledgeBase.numMetabolites);
            for i = 1:length(this.proteinMonomers)
                switch this.proteinMonomers(i).gene.type
                    case 'mRNA', monomerTRNACounts(i,:) = this.proteinMonomers(i).matureSequenceBaseCount;
                end
            end

            complexTRNACounts = zeros(length(this.proteinComplexs),this.knowledgeBase.numMetabolites);
            for i = 1:length(this.proteinComplexs)
                complexTRNACounts(i,:) = this.proteinComplexs.matureBaseCount;
            end

            TRNACounts = [monomerTRNACounts;complexTRNACounts];
            coefficients = [this.proteinMonomerCoefficients;this.proteinComplexCoefficients];

            if ~isempty(coefficients)
                value = coefficients'*TRNACounts;
            else
                value = zeros(1,this.knowledgeBase.numMetabolites);
            end

            %store
            this.tRNACount = value;
        end

        function value = get.decayReaction(this)
            %retrieve
            if ~isempty(this.decayReaction)
                value = this.decayReaction;
                return;
            end

            %calculate
            value = this.decayReaction_Helper();

            %store
            this.decayReaction = value;
        end

        function value = decayReaction_Helper(this)
            value = zeros(1, this.knowledgeBase.numMetabolites);

            for i = 1:length(this.proteinComplexs)
                value = value + this.proteinComplexCoefficients(i) * this.proteinComplexs(i).decayReaction;
            end

            if ~isempty(this.metabolites)
                value([this.metabolites.idx]) =   ...
                    + value([this.metabolites.idx]) ...
                    + this.metaboliteCoefficients';
            end
        end

        function value = get.matureDecayReaction(this)
            %retrieve
            if ~isempty(this.matureDecayReaction)
                value = this.matureDecayReaction;
                return;
            end

            %calculate
            value = this.decayReaction;
            if ~isempty(this.prostheticGroups)
                value([this.prostheticGroups.idx]) = ...
                    + value([this.prostheticGroups.idx]) ...
                    + max(1, this.prostheticGroupCoefficients);
            end

            %store
            this.matureDecayReaction = value;
        end

        %number of distinct subunits
        function value = get.numDistinctSubunits(this)
            %retrieve
            if ~isempty(this.numDistinctSubunits)
                value = this.numDistinctSubunits;
                return;
            end

            %calculate
            value = length(this.rnas)+length(this.proteinMonomers)+length(this.proteinComplexs);

            %store
            this.numDistinctSubunits = value;
        end

        %number of subunits
        function value = get.numSubunits(this)
            %retrieve
            if ~isempty(this.numSubunits)
                value = this.numSubunits;
                return;
            end

            %calculate
            value = sum([this.proteinMonomerCoefficients;this.proteinComplexCoefficients]);
            if ~isempty(value)
                value = 0;
            end

            %store
            this.numSubunits = value;
        end

        function value = get.numNucleicAcids(this)
            %retrieve
            if ~isempty(this.numNucleicAcids)
                value = this.numNucleicAcids;
                return;
            end

            %calculate
           value = this.computeNumNucleicAcids();

           %store
            this.numNucleicAcids = value;
        end

        function value = computeNumNucleicAcids(this)
            value = 0;

            for i = 1:length(this.rnas)
                value = value + this.rnas(i).sequenceLength * this.rnaCoefficients(i);
            end

            for i = 1:length(this.proteinComplexs)
                value = value + this.proteinComplexs(i).computeNumNucleicAcids() * this.proteinComplexCoefficients(i);
            end
        end

        function value = get.numAminoAcids(this)
            %retrieve
            if ~isempty(this.numAminoAcids)
                value = this.numAminoAcids;
                return;
            end

            %calculate
            value = this.computeNumAminoAcids();

            %store
            this.numAminoAcids = value;
        end

        function value = computeNumAminoAcids(this)
            value = 0;

            for i = 1:length(this.proteinMonomers)
                value = value + this.proteinMonomers(i).matureSequenceLength * this.proteinMonomerCoefficients(i);
            end

            for i = 1:length(this.proteinComplexs)
                value = value + this.proteinComplexs(i).computeNumAminoAcids() * this.proteinComplexCoefficients(i);
            end
        end

        function value = get.numRNASubunits(this)
            %retrieve
            if ~isempty(this.numRNASubunits)
                value = this.numRNASubunits;
                return;
            end

            %calculate
            value = this.computeNumRNASubunits();

            %store
            this.numRNASubunits = value;
        end

        function value = computeNumRNASubunits(this)
            value = sum(this.rnaCoefficients);

            for i = 1:length(this.proteinComplexs)
                value = value + this.proteinComplexs(i).computeNumRNASubunits() * this.proteinComplexCoefficients(i);
            end
        end

        function value = get.numProteinMonomerSubunits(this)
            %retrieve
            if ~isempty(this.numProteinMonomerSubunits)
                value = this.numProteinMonomerSubunits;
                return;
            end

            %calculate
            value = this.computeNumProteinMonomerSubunits();

            %store
            this.numProteinMonomerSubunits = value;
        end

        function value = computeNumProteinMonomerSubunits(this)
            value = sum(this.proteinMonomerCoefficients);

            for i = 1:length(this.proteinComplexs)
                value = value + this.proteinComplexs(i).computeNumProteinMonomerSubunits() * this.proteinComplexCoefficients(i);
            end
        end

        %average/sum property value over subunits
        function value = meanSubunitPropertyValue(this, property, average)
            values = [];

            if ~isempty(this.rnas)
                values = [values this.rnas.(property)];
            end

            if ~isempty(this.proteinMonomers)
                values = [values this.proteinMonomers.(property)];
            end

            if ~isempty(this.proteinComplexs)
                values = [values this.proteinComplexs.(property)];
            end

            coefficients = [this.rnaCoefficients;this.proteinMonomerCoefficients;this.proteinComplexCoefficients];
            if ~isempty(coefficients)
                if average
                    value = values*coefficients/sum(coefficients);
                else
                    value = values*coefficients;
                end
            else
                if average
                    value = NaN;
                else
                    value = 0;
                end
            end
        end
    end
end


function view=xformFlatMenu(view)
%
% view = xformFlatMenu(view)
%
% Set up the callbacks for the xformView menu in the Flat view
%
% djh, 1/9/98
% rmk, 1/10/99 added xformParMap
% rmk, 1/15/99 added xformAllROIs

mrGlobals;

xformMenu = uimenu('Label','Xform','separator','on');

% Xform ROI callback:
%   gray=checkSelectedGray;
%   view=vol2flatCurROI(gray,view);
%   view=refreshScreen(view,0);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatCurROI(gray,',view.name,'); ',...
        view.name,'=refreshScreen(',view.name,',0);'];
uimenu(xformMenu,'Label','ROI (selected)','Separator','off',...
    'CallBack',callBackstr);

% Xform AllROIs callback:
%   gray=checkSelectedGray;
%   view=vol2flatAllROIs(gray,view);
%   view=refreshScreen(view,0);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatAllROIs(gray,',view.name,'); ',...
        view.name,'=refreshScreen(',view.name,',0);'];
uimenu(xformMenu,'Label','ROIs (all)','Separator','off',...
    'CallBack',callBackstr);

% Xform CorAnal all scans callback:
%   gray=checkSelectedGray;
%   view=vol2flatCorAnal(gray,view,0);
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatCorAnal(gray,',view.name,',0); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','CorAnal (all scans)','Separator','off',...
    'CallBack',callBackstr);

% Xform CorAnal current scan callback:
%   gray=checkSelectedGray;
%   view=vol2flatCorAnal(gray,view,getCurScan(view));
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatCorAnal(gray,',view.name,',getCurScan(',view.name,')); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','CorAnal (current scan)','Separator','off',...
    'CallBack',callBackstr);

% Xform CorAnal select scans callback:
%   gray=checkSelectedGray;
%   view=vol2flatCorAnal(gray,view);
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatCorAnal(gray,',view.name,'); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','CorAnal (select scans)','Separator','off',...
    'CallBack',callBackstr);

% Xform ParMap all scans callback:
%   gray=checkSelectedGray;
%   view=vol2flatParMap(gray,view,0);
%   view=setDisplayMode(view,'map');
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatParMap(gray,',view.name,',0); ',...
        view.name,'=setDisplayMode(',view.name,',''map''); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','Parameter Map (all scans)','Separator','off',...
    'CallBack',callBackstr);

% Xform ParMap current scan callback:
%   gray=checkSelectedGray;
%   view=vol2flatParMap(gray,view,getCurScan(view));
%   view=setDisplayMode(view,'map');
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatParMap(gray,',view.name,',getCurScan(',view.name,')); ',...
        view.name,'=setDisplayMode(',view.name,',''map''); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','Parameter Map (current scan)','Separator','off',...
    'CallBack',callBackstr);

% Xform ParMap select scans callback:
%   gray=checkSelectedGray;
%   view=vol2flatParMap(gray,view);
%   view=setDisplayMode(view,'map');
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatParMap(gray,',view.name,'); ',...
        view.name,'=setDisplayMode(',view.name,',''map''); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','Parameter Map (select scans)','Separator','off',...
    'CallBack',callBackstr);

% Xform ParMap current scan, nearest-neighbor callback:
%   gray=checkSelectedGray;
%   view=vol2flatParMap2(gray,view,getCurScan(view));
%   view=setDisplayMode(view,'map');
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatParMap2(gray,',view.name,',getCurScan(',view.name,')); ',...
        view.name,'=setDisplayMode(',view.name,',''map''); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','Parameter Map (nearest-neighbor)','Separator','off',...
    'CallBack',callBackstr);

% Xform ParMap current scan callback:
%   gray=checkSelectedGray;
%   view=vol2flatParMapLevels(gray,view,getCurScan(view));
%   view=setDisplayMode(view,'map');
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=vol2flatParMapLevels(gray,',view.name,',getCurScan(',view.name,')); ',...
        view.name,'=setDisplayMode(',view.name,',''map''); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','Parameter Map (separate gray levels)','Separator','off',...
    'CallBack',callBackstr);

% Xform retModel:
%   gray=checkSelectedGray;
%   view=rmVol2flat(gray,view);
%   view=refreshScreen(view,1);
callBackstr=['gray=checkSelectedGray; ',...
        view.name,'=rmVol2flat(gray,',view.name,'); ',...
        view.name,'=refreshScreen(',view.name,',1);'];
uimenu(xformMenu,'Label','Retinotopic Model','Separator','off',...
    'CallBack',callBackstr);

return;


classdef ConvergenceVariables < handle

    properties (GetAccess = public, SetAccess = private)
        values
        nVar
    end

    methods (Access = public)

        function obj = ConvergenceVariables(n)
            obj.nVar = n;
        end

        function reset(obj)
            obj.values = [];
            obj.nVar = 0;
        end

        function append(obj,value)
            obj.values(obj.nVar+1) = value;
            obj.nVar = obj.nVar + 1;
        end

        function set(obj,value)
            obj.values(end) = value;
        end

    end

end


function NAMES = fieldnamesr(S,varargin)
%FIELDNAMESR Get structure field names in recursive manner.
%
%   NAMES = FIELDNAMESR(S) returns a cell array of strings containing the
%   structure field names associated with s, the structure field names
%   of any structures which are fields of s, any structures which are
%   fields of fields of s, and so on.
%
%   NAMES = FIELDNAMESR(S,DEPTH) is an optional field which allows the depth
%   of the search to be defined. Default is -1, which does not limit the
%   search by depth. A depth of 1 will return only the field names of s
%   (behaving like FIELDNAMES). A depth of 2 will return those field
%   names, as well as the field names of any structure which is a field of
%   s.
%
%   NAMES = FIELDNAMESR(...,'full') returns the names of fields which are
%   structures, as well as the contents of those structures, as separate
%   cells. This is unlike the default where a structure-tree is returned.
%
%   NAMES = FIELDNAMESR(...,'prefix') returns the names of the fields
%   prefixed by the name of the input structure.
%
%   NAMES = FIELDNAMESR(...,'struct') returns only the names of fields
%   which are structures.
%
%   See also FIELDNAMES, ISFIELD, GETFIELD, SETFIELD, ORDERFIELDS, RMFIELD.

%   Developed in MATLAB 7.13.0.594 (2011b).
%   By AATJ (adam.tudorjones@pharm.ox.ac.uk). 2011-10-11. Released under
%   the BSD license.

%Set optional arguments to default settings, if they are not set by the
%caller.
if size(varargin,1) == 0
    optargs = {-1} ;
    optargs(1:length(varargin)) = varargin ;
    depth = optargs{:} ;

    full = [0] ; [prefix] = [0] ; [struct] = [0] ;
else
    if any(strcmp(varargin,'full') == 1)
        full = 1 ;
    else
        full = 0 ;
    end

    if any(strcmp(varargin,'prefix') == 1)
        prefix = 1 ;
    else
        prefix = 0 ;
    end

    if any(strcmp(varargin,'struct') == 1)
        struct = 1 ;
    else
        struct = 0 ;
    end

    if any(cellfun(@isnumeric,varargin) == 1)
        depth = varargin{find(cellfun(@isnumeric,varargin))} ;
    else
        depth = -1 ;
    end
end

%Return fieldnames of input structure, prefix these with "S.".
NAMES = cellfun(@(x) strcat('S.',x),fieldnames(S),'UniformOutput',false) ;

%Set state counters to initial values (k terminates recursive loop, g makes
%recursive loop behave in a different way.
k = 1 ; g = 0 ;

fndstruct = {} ;

%k is ~0 while all fields have not been searched to exhaustion or to
%specified depth.
while k ~= 0
    fndtemp = {} ;

    k = length(NAMES) ;

    %g set to 1 prevents fieldnames from being added to output NAMES.
    %Useful when determining whether fields at the lowest specified depth
    %are structures, without adding their child fieldnames (i.e. at
    %specified depth + 1) to NAMES output.
    if depth == 1
        g = 1 ;
    end

    for i = 1:length(NAMES)
        %If the current fieldname is a structure, find its child
        %fieldnames, add to NAMES if not at specified depth (g = 0). Add to
        %fndstruct (list of structures).
        if isstruct(eval(NAMES{i})) == 1
            if g ~= 1
                fndtemp2 = fieldnames(eval(NAMES{i})) ;
                fndtemp2 = cellfun(@(x) strcat(sprintf('%s.'            ...
                    ,NAMES{i}),x),fndtemp2,'UniformOutput',false) ;
                fndtemp = cat(1,fndtemp,fndtemp2) ;
            elseif g == 1
                fndtemp = cat(1,fndtemp,NAMES{i}) ;
                k = k - 1 ;
            end
            fndstruct = cat(1,fndstruct,NAMES{i}) ;
        else
            fndtemp = cat(1,fndtemp,NAMES{i}) ;
            k = k - 1 ;
        end
    end

    NAMES = fndtemp ;

    %If we have reached depth, stop recording children fieldnames to NAMES
    %output, but determine whether fields at final depth are structures or
    %not (g). After this, terminate loop by setting k to 0.
    if depth ~= -1                                                      ...
            && any(cellfun(@(x) size(find(x == '.'),2),NAMES) == depth)
        g = 1 ;
    elseif depth ~= -1                                                  ...
            && any(cellfun(@(x) size(find(x == '.'),2),NAMES) > depth)
        k = 0 ;
    end
end

%Return names of fields which are structures, as well as fields which are
%not structures, if 'full' optional argument is set.
if full == 1
    for i = 1:length(fndstruct)

        %If depth is specified, add structure names to appropriate depth to
        %output NAMES.
        if depth == -1 || size(find(fndstruct{i} == '.'),2) <= depth-1
            structi = find(cellfun(@(x) isempty(x) == 0                 ...
                ,strfind(NAMES,fndstruct{i})),1) ;

            %If the current structure name is related to the first field of
            %NAMES, add structure name to NAMES in a particular way, else
            %add it in another way.
            if structi > 1
                NAMES = cat(1,NAMES(1:(structi-1)),fndstruct{i}         ...
                    ,NAMES(structi:end)) ;
            elseif isempty(structi)
                error ('AATJ:fieldnamesr,NotFindStructure'              ...
                    ,'Could not find structure name in NAMES') ;
            else
                NAMES = cat(1,fndstruct{i},NAMES) ;
            end
        end
    end
end

%Return only fields which are structures, if optional argument is defined.
%If 'full' is not set, do not include both parent and child structures.
if struct == 1
    if full == 0
        fndstruct2 = {} ;
        for i = 1:length(fndstruct)
            if isempty(cell2mat(strfind(fndstruct,strcat(fndstruct{i},'.')))) == 1
                fndstruct2(end+1,1) = fndstruct(i) ;
            end
        end
        fndstruct = fndstruct2 ;
    end
    NAMES = fndstruct ;
end

%Prefix input structure name on all fields of output cell array NAME if
%user set this option.
if prefix == 1
    structname = inputname(1) ;
    NAMES = cellfun(@(x) strcat(sprintf('%s.',structname),x(3:end))     ...
        ,NAMES,'UniformOutput',false) ;
else
    NAMES = cellfun(@(x) sprintf('%s',x(3:end)),NAMES,'UniformOutput'   ...
        ,false) ;
end


%GEOM_LOFT_FACES Loft faces to solid.
%
%   [ SOUT, NEW_TAG ] = GEOM_LOFT_FACES( SIN, TAGS, FACES ) Loft
%   selected FACES from geometry objects with TAGS to a solid geometry
%   object.

% Copyright 2013-2022 Precise Simulation, Ltd.


function [valid, conditional] = valid_identifier(identifier)
% valid_identifier Verifies tracker identifier
%
% Tests if a given input string is a valid tracker identifier. A valid identifier contains only
% upper and lower case letters, digits and underscore.
%
% A conditionally valid identifier also contains dash. This is used for legacy reasons but is
% discouraged for new trackers.
%
% Input:
% - identifier: A string to test.
%
% Ouput:
% - valid: True if the string is a valid identifier.
% - conditional: True if the string is a conditionally valid identifier.

if ~ischar(identifier)
    valid = false;
	conditional = false;
    return;
end;

alpha = (identifier >= 'a' & identifier <= 'z') | (identifier >= 'A' & identifier <= 'Z');
numeric = (identifier >= '0' & identifier <= '9');
symbol = identifier == '_';

valid = all(alpha | numeric | symbol);
conditional = all(alpha | numeric | symbol | identifier == '-');


%% (Internal) Display an enumeration of options to a string
%
%     This function format a string for fprintf like functions in order to
%     present a message srtMessage followed by an enumeration of string
%     elements included in the cell str cOptionEnum
%
%   str_aux = disp_option_enumeration(srtMessage, cOptionEnum)
%
% Arguments:
%
%      + srtMessage: A title message previous to the enumeration
%
%      + cOptionEnum: cellstring with the items to enumerate
%
% Output:
%
%      + str_aux: resulting string
%
% Example:
%
%
% See also disp_string_framed, disp_string_title
%
% Author: Mariano Llamedo Soria llamedom@electron.frba.utn.edu.ar
% Version: 0.1 beta
% Last update: 14/5/2014
% Birthdate  : 21/4/2015
% Copyright 2008-2015
%
function str_aux = disp_option_enumeration(srtMessage, cOptionEnum)

%  Escape problematic strings, such as file paths
cOptionEnum = cellfun(@(a)(strrep(a, '\', '\\')), cOptionEnum, 'UniformOutput', false );

str_aux = [ repmat(' + ', length(cOptionEnum), 1) char(cOptionEnum) repmat('\n', length(cOptionEnum), 1 ) ];
str_aux = [ srtMessage '\n' rowvec(str_aux') ];