function create_table_of_algorithms_comb(up)
%CREATE_TABLE_OF_ALGORITHMS creates a table of algorithms and their performances
%	            create_table_of_algorithms(up)
%
%	Inputs:
%		data            data files should be stored in the specified format
%       up              universal parameters structure
%
%	Outputs:
%       tables          csv tables of results
%

fprintf('\n--- Creating Results Tables ');

% save setup
save_name = up.paths.filenames.results_table;
savepath = [up.paths.tables_save_folder, save_name, '.mat'];
if ~up.analysis.redo_stats
    exist_log = check_exists(savepath, save_name);
    if exist_log
        return
    end
end

% Load BA Data
load_name = 'BA_results';
loadpath = [up.paths.data_save_folder, up.paths.filenames.global_BA, '.mat'];
load(loadpath, load_name);

% Load algorithm names
load_name = up.paths.filenames.alg_names;
loadpath = [up.paths.data_save_folder, up.paths.filenames.alg_names, '.mat'];
load(loadpath, load_name);

% Load study data
load_name = 'trad_stats';
loadpath = [up.paths.data_save_folder, up.paths.filenames.study_stats, '.mat'];
load(loadpath, load_name);

% identify groups
groups = fieldnames(BA_results);

%% Create a BA table and a Stats table for each group

for group_no = 1 : length(groups)
    group = groups{group_no};

    %% Extract relevant data
    rel_data = extract_rel_data(group, BA_results, trad_stats, up);

    %% Make Table of BA Results
    BA_results_table = create_table_results(alg_names, rel_data, up, group, 'BA');

    %% Save to file
    save_name = [up.paths.filenames.BA_results_table, '_', group];
    savepath = [up.paths.tables_save_folder, save_name];
    xlswrite(savepath, BA_results_table)

    %% Make Table of Stats Results
    stats_results_table = create_table_results(alg_names, rel_data, up, group, 'stats');

    %% Save to file
    save_name = [up.paths.filenames.stats_results_table, '_', group];
    savepath = [up.paths.tables_save_folder, save_name];
    xlswrite(savepath, stats_results_table)

    %% Make combined table of results
    comb_results_table = create_table_results(alg_names, rel_data, up, group, 'comb');

    %% Save to file
    save_name = [up.paths.filenames.comb_results_table, '_', group];
    savepath = [up.paths.tables_save_folder, save_name];
    xlswrite(savepath, comb_results_table)

end

end

function rel_data = extract_rel_data(group, BA_results, stats, up)

rel_data.BA = extractfield(BA_results, group); rel_data.BA = rel_data.BA{1,1};
rel_data.stats = extractfield(stats, group); rel_data.stats = rel_data.stats{1,1};

end

function table_data = create_table_results(alg_names, rel_data, up, group, type)

% Find alg numbers:
alg_names.no = cell(length(alg_names.names),1);
for s = 1 : length(alg_names.no)
    alg_names.no{s} = ['a', num2str(s)];
end

% Extract relevant variables for table:
tab_vars.alg_no = alg_names.no;
if isfield(alg_names.meths, 'xa')
    tab_vars.m_xa = alg_names.meths.xa;
    tab_vars.m_xb = alg_names.meths.xb;
    tab_vars.m_ef = alg_names.meths.ef;
    tab_vars.m_et = alg_names.meths.et;
    tab_vars.m_fm = alg_names.meths.fm;
    tab_vars.m_ft = alg_names.meths.ft;
    % modify the fme:
    rel_els = ~isnan(tab_vars.m_fm);
    tab_vars.m_xb(rel_els) = 99;
end
tab_vars.alg_name = alg_names.names;
tab_vars.signal = alg_names.sigs;

% Extract relevant statistics for table:
if strcmp(type, 'BA')
    tab_vars.bias = rel_data.BA.bias.val;
    tab_vars.two_sd = rel_data.BA.two_sd.val;
    tab_vars.prop_wins_est = rel_data.stats.prop_wins_est;
    tab_vars.prop_wins_ref_and_good_sqi = rel_data.stats.prop_wins_good_sqi_and_ref;
elseif strcmp(type, 'stats')
    tab_vars.percerr = rel_data.stats.percerr;
    tab_vars.mae = rel_data.stats.mae;
    tab_vars.sdae = rel_data.stats.sdae;
    tab_vars.rmse = rel_data.stats.rmse;
    tab_vars.cp2 = rel_data.stats.cp2;
    tab_vars.prop_wins_est = rel_data.stats.prop_wins_est;
    tab_vars.total_wins_all = rel_data.stats.total_wins_all;
elseif strcmp(type, 'comb')
    tab_vars.two_sd = rel_data.BA.two_sd.val;
    tab_vars.bias = rel_data.BA.bias.val;
    tab_vars.cp2 = rel_data.stats.cp2;
    tab_vars.percerr = rel_data.stats.percerr;
    tab_vars.mae = rel_data.stats.mae;
    tab_vars.sdae = rel_data.stats.sdae;
    tab_vars.rmse = rel_data.stats.rmse;
    tab_vars.prop_wins_ref_and_good_sqi = rel_data.stats.prop_wins_good_sqi_and_ref;
    tab_vars.prop_wins_est = rel_data.stats.prop_wins_est;
    tab_vars.total_wins_all = rel_data.stats.total_wins_all;
end

%% Determine what goes into the table
headers = fieldnames(tab_vars);
table_data = cell(1+length(tab_vars.alg_name), length(headers));
table_data(1,:) = headers;
for col_no = 1 : length(headers)
    eval(['col_data = tab_vars.' headers{col_no} ';']);
    if ~iscell(col_data)
        table_data(2:end,col_no) = num2cell(col_data);
    else
        table_data(2:end,col_no) = col_data;
    end
end

end

function [subj_data, BA_data, stats_data, old_names] = load_data(group, up)

% Load subj data
load_name = ['data_', group];
loadpath = [up.paths.data_save_folder, up.paths.filenames.group_data, group, '.mat'];
load(loadpath, load_name)
eval(['subj_data = data_' group  ';']);

% Load B-A results
load_name = 'BA';
loadpath = [up.paths.data_save_folder, up.paths.filenames.group_BA, group, '.mat'];
load(loadpath, load_name)
BA_data = BA; clear BA

% Load Stats data
load_name = 'acc';
loadpath = [up.paths.data_save_folder, up.paths.filenames.group_stats, group, '.mat'];
load(loadpath, load_name)
stats_data = acc;
old_names = acc.rr_alg_names;

end

function create_table_stats_results_subj(alg_names, sig_names, old_names, subj_data, up, group)

%% Find prop with an abs error of < 1 bpm
eval(['subjs = unique(subj_data.' old_names{1} '.subj);']);
prop_acc = zeros(length(old_names), length(subjs));
for alg_no = 1 : length(old_names)
     eval(['rel_data = subj_data.' old_names{alg_no} ';']);

     rel_data.error = rel_data.est - rel_data.ref;
     rel_data.abs_error = abs(rel_data.error);
     rel_data.acc_log = rel_data.abs_error < 1;

     for subj_no = 1:length(subjs)
         subj = subjs(subj_no);
         rel_els = logical(rel_data.subj == subj);
         prop_acc(alg_no, subj_no) = sum(rel_data.acc_log(rel_els)) / length(rel_data.acc_log(rel_els));
     end

     % extract relevant parts of algs:
     for comp_str = {'FMe', 'Flt', 'RSa', 'PDt', 'Est', 'MFu', 'TFu'}
         if ~exist([lower(comp_str{1,1}), '_meth'], 'var')
             eval([lower(comp_str{1,1}), '_meth = nan(length(old_names),1);']);
         end
         rel_el = strfind(alg_names{alg_no}, comp_str{1,1});
         if rel_el
             temp = str2num(alg_names{alg_no}(rel_el+3));
             eval([lower(comp_str{1,1}), '_meth(alg_no) = temp;']);
         end
     end

     clear rel_data
end

%% Determine what goes into the table
headers = {'Signal', 'Algorithm Name', 'Old Name', 'FMe', 'Flt', 'RSa', 'PDt', 'Est', 'MFu', 'TFu'};
for subj_no = 1:length(subjs)
    headers{end+1} = ['Prop_acc ' num2str(subjs(subj_no))];
end

table_data = cell(1+length(alg_names), length(headers));
table_data(1,:) = headers;
table_data(2:end,1) = sig_names;
table_data(2:end,2) = alg_names;
table_data(2:end,3) = old_names;
table_data(2:end,4) = num2cell(fme_meth);
table_data(2:end,5) = num2cell(flt_meth);
table_data(2:end,6) = num2cell(rsa_meth);
table_data(2:end,7) = num2cell(pdt_meth);
table_data(2:end,8) = num2cell(est_meth);
table_data(2:end,9) = num2cell(mfu_meth);
table_data(2:end,10) = num2cell(tfu_meth);
for s = 1 : size(prop_acc,2)
    table_data(2:end,10+s) = num2cell(prop_acc(:,s));
end

%% Save to file
save_name = [up.paths.filenames.subj_results_table '_' group];
savepath = [up.paths.tables_save_folder, save_name];
xlswrite(savepath,table_data)

end

function create_table_BA_results(alg_names, sig_names, BA_data, up, group)

%% Determine what goes into the table
headers = {'Signal', 'Algorithm Name', 'Bias', 'Bias (LCI)', 'Bias (UCI)', 'LLOA', 'LLOA (LCI)', 'LLOA (UCI)', 'ULOA', 'ULOA (LCI)', 'ULOA (UCI)', 'Precision', 'Precision (LCI)', 'Precision (UCI)'};
table_data = cell(1+length(alg_names), length(headers));
table_data(1,:) = headers;
table_data(2:end,1) = sig_names;
table_data(2:end,2) = alg_names;
table_data(2:end,3) = num2cell(BA_data.bias.val);
table_data(2:end,4) = num2cell(BA_data.bias.lci);
table_data(2:end,5) = num2cell(BA_data.bias.uci);
table_data(2:end,6) = num2cell(BA_data.lloa.val);
table_data(2:end,7) = num2cell(BA_data.lloa.lci);
table_data(2:end,8) = num2cell(BA_data.lloa.uci);
table_data(2:end,9) = num2cell(BA_data.uloa.val);
table_data(2:end,10) = num2cell(BA_data.uloa.lci);
table_data(2:end,11) = num2cell(BA_data.uloa.uci);
table_data(2:end,12) = num2cell(BA_data.prec.val);
table_data(2:end,13) = num2cell(BA_data.prec.lci);
table_data(2:end,14) = num2cell(BA_data.prec.uci);

%% Save to file
save_name = [up.paths.filenames.BA_results_table '_' group];
savepath = [up.paths.tables_save_folder, save_name];
xlswrite(savepath,table_data)

end

function create_table_stats_results(alg_names, sig_names, stats_data, up, group)

%% Determine what goes into the table
headers = {'Signal', 'Algorithm Name', 'MAE', 'MAE (lq)', 'MAE (uq)', 'SDAE', 'SDAE (lq)', 'SDAE (uq)', 'PERC ERR', 'PERC ERR (lq)', 'PERC ERR (uq)', 'RMSE', 'RMSE (lq)', 'RMSE (uq)', 'MEAN ERROR', 'MEAN ERROR (lq)', 'MEAN ERROR (uq)', 'STD ERROR', 'STD ERROR (lq)', 'STD ERROR (uq)', 'PROP WINS', 'PROP WINS (lq)', 'PROP WINS (uq)'};
table_data = cell(1+length(alg_names), length(headers));
table_data(1,:) = headers;
table_data(2:end,1) = sig_names;
table_data(2:end,2) = alg_names;
table_data(2:end,3) = num2cell(stats_data.mae.med);
table_data(2:end,4) = num2cell(stats_data.mae.lq);
table_data(2:end,5) = num2cell(stats_data.mae.uq);
table_data(2:end,6) = num2cell(stats_data.sdae.med);
table_data(2:end,7) = num2cell(stats_data.sdae.lq);
table_data(2:end,8) = num2cell(stats_data.sdae.uq);
table_data(2:end,9) = num2cell(stats_data.percerr.med);
table_data(2:end,10) = num2cell(stats_data.percerr.lq);
table_data(2:end,11) = num2cell(stats_data.percerr.uq);
table_data(2:end,12) = num2cell(stats_data.rmse.med);
table_data(2:end,13) = num2cell(stats_data.rmse.lq);
table_data(2:end,14) = num2cell(stats_data.rmse.uq);
table_data(2:end,15) = num2cell(stats_data.mean_diff.med);
table_data(2:end,16) = num2cell(stats_data.mean_diff.lq);
table_data(2:end,17) = num2cell(stats_data.mean_diff.uq);
table_data(2:end,18) = num2cell(stats_data.std_diff.med);
table_data(2:end,19) = num2cell(stats_data.std_diff.lq);
table_data(2:end,20) = num2cell(stats_data.std_diff.uq);
table_data(2:end,21) = num2cell(stats_data.prop_wins.med);
table_data(2:end,22) = num2cell(stats_data.prop_wins.lq);
table_data(2:end,23) = num2cell(stats_data.prop_wins.uq);

%% Save to file
save_name = [up.paths.filenames.stats_results_table '_' group];
savepath = [up.paths.tables_save_folder, save_name];
xlswrite(savepath,table_data)

end


% -*- INTERNAL UNDOCUMENTED FUNCTION -*-
function sp = sp_vector_curl_transform (scalar_spaces, msh)

  warning ('geopdes:obsolete', 'The function SP_VECTOR_CURL_TRANSFORM is obsolete. Using SP_VECTOR with the transformation as last argument')
  sp = sp_vector (scalar_spaces, msh, 'curl-preserving');

end


classdef WBDetector < handle
    %WBDETECTOR  WaldBoost detector - Object Detection using Boosted Features
    %
    % Class for object detection using WaldBoost from [Sochman05].
    % Uses a Waldboost cascade and local binary patterns computed as integral
    % features for 2D object detection.
    %
    % ## Example
    % The basic usage is the following:
    %
    %     % train
    %     detector = cv.WBDetector();
    %     detector.train('/path/to/pos/', '/path/to/neg/');
    %     detector.write('model.xml');
    %
    %     % detect
    %     detector = cv.WBDetector();
    %     detector.read('model.xml');
    %     img = cv.imread('image.png', 'Grayscale',true);
    %     [bboxes,conf] = detector.detect(img);
    %     for i=1:numel(bboxes)
    %         img = cv.rectangle(img, bboxes{i}, 'Color',[0 255 0]);
    %     end
    %     imshow(img)
    %
    % ## References
    % [Sochman05]:
    % > J. Sochman and J. Matas. "WaldBoost - Learning for Time Constrained
    % > Sequential Detection", IEEE Conference on CVPR 2005, Vol 2, p. 150-156
    % > [PDF](https://dspace.cvut.cz/bitstream/handle/10467/9494/2005-Waldboost-learning-for-time-constrained-sequential-detection.pdf?sequence=1)
    %
    % See also: cv.WBDetector.WBDetector, cv.WBDetector.detect,
    %  detectPeopleACF, peopleDetectorACF, trainACFObjectDetector
    %

    properties (SetAccess = private)
        % Object ID
        id
    end

    methods
        function this = WBDetector()
            %WBDETECTOR  Create instance of WBDetector
            %
            %     detector = cv.WBDetector()
            %
            % See also: cv.WBDetector, cv.WBDetector.train, cv.WBDetector.read
            %
            this.id = WBDetector_(0, 'new');
        end

        function delete(this)
            %DELETE  Destructor
            %
            %     detector.delete()
            %
            % See also: cv.WBDetector
            %
            if isempty(this.id), return; end
            WBDetector_(this.id, 'delete');
        end

        function read(this, fname_or_str, varargin)
            %READ  Read detector from file
            %
            %     detector.read(filename)
            %     detector.read(str, 'FromString',true)
            %     detector.read(..., 'OptionName', optionValue, ...)
            %
            % ## Input
            % * __filename__ Name of the file to read from.
            % * __str__ String containing serialized detector you want to load.
            %
            % ## Options
            % * __FromString__ Logical flag to indicate whether the input is a
            %   a filename or a string containing the serialized detector.
            %   default false
            %
            % See also: cv.WBDetector.write
            %
            WBDetector_(this.id, 'read', fname_or_str, varargin{:});
        end

        function varargout = write(this, filename)
            %WRITE  Write detector to file
            %
            %     detector.write(filename)
            %     str = detector.write(filename)
            %
            % ## Input
            % * __filename__ Name of the file to save to.
            %
            % ## Output
            % * __str__ optional output. If requested, the object is persisted
            %   to a string in memory instead of writing to disk.
            %
            % See also: cv.WBDetector.read
            %
            [varargout{1:nargout}] = WBDetector_(this.id, 'write', filename);
        end

        function train(this, pos_samples, neg_imgs)
            %TRAIN  Train WaldBoost detector
            %
            %     detector.train(pos_samples, neg_imgs)
            %
            % ## Input
            % * **pos_samples** Path to directory with cropped positive
            %   samples.
            % * **neg_imgs** Path to directory with negative (background)
            %   images.
            %
            % See also: cv.WBDetector.detect
            %
            WBDetector_(this.id, 'train', pos_samples, neg_imgs);
        end

        function [bboxes,confidences] = detect(this, img)
            %DETECT  Detect objects on image using WaldBoost detector
            %
            %     [bboxes,confidences] = detector.detect(img)
            %
            % ## Input
            % * __img__ Input image for detection.
            %
            % ## Output
            % * __bboxes__ Bounding boxes coordinates.
            % * __confidences__ Confidence values for bounding boxes.
            %
            % See also: cv.WBDetector.WBDetector
            %
            [bboxes,confidences] = WBDetector_(this.id, 'detect', img);
        end
    end

end


function transition_net(varargin)

opts.expDir = fullfile('../data','DCFNet-net-7') ;
opts = vl_argparse(opts, varargin);

modelPath = dir(fullfile(opts.expDir, 'net-epoch-*0.mat'));
modelPath = sort({modelPath.name});

[~,out_name,~] = fileparts(opts.expDir);

for i = numel(modelPath)
    load(fullfile(opts.expDir, modelPath{i}));
    net = dagnn.DagNN.loadobj(net) ;
    net = deployDCFNet(net);
    if ~exist('../model', 'dir')
        mkdir('../model');
    end
    save(fullfile('../model', [out_name '.mat']), 'net') ;
end
end


function vw = roiSetVertInds(vw, prefs)
%  Add a field to each current ROI with the mesh vertices needed to show
%  the ROI. By storing these values in the ROI field, they do not have to
%  be computed each time the mesh is updated. This significantly speeds the
%  update process.
%
% vw = roiSetVertInds([vw], [prefs])
%
% See roiRemoveVertInds.m
%
% Example: vw = roiSetVertInds(vw);
%
% 8/2009: JW

%% Variable check
if ~exist('vw', 'var'),
    % this takes a LONG time!
    vw = getCurView;
end

if ~exist('prefs', 'var'),
    prefs = mrmPreferences;
end

msh  = viewGet(vw, 'currentmeshnumber');
if isempty(msh), warning('need a mesh to get ROI vertex indices'); return; end

%% Set the ROI vert indices
nROIs = length(viewGet(vw, 'ROIs'));
verbose = prefsVerboseCheck;

for roi = 1:nROIs

    % Because this code can be slow, display some progress...
    if verbose
        fprintf('[%s]: Adding vertex indices to ROI %d\n', mfilename, roi);
    end

    roiVertInds = viewGet(vw, 'roiVertInds', roi, prefs);

    vw = viewSet(vw, 'roivertinds', roiVertInds, roi, prefs);

end


function save_gc_hdc_trajectory(gcFileName, hdcFileName, gcData, hdcData)
%     NeuroSLAM System Copyright (C) 2018-2019
%     NeuroSLAM: A Brain inspired SLAM System for 3D Environments
%
%     Fangwen Yu (www.yufangwen.com), Jianga Shang, Youjian Hu, Michael Milford(www.michaelmilford.com)
%
%     The NeuroSLAM V1.0 (MATLAB) was developed based on the OpenRatSLAM (David et al. 2013).
%     The RatSLAM V0.3 (MATLAB) developed by David Ball, Michael Milford and Gordon Wyeth in 2008.
%
%     Reference:
%     Ball, David, Scott Heath, Janet Wiles, Gordon Wyeth, Peter Corke, and Michael Milford.
%     "OpenRatSLAM: an open source brain-based SLAM system." Autonomous Robots 34, no. 3 (2013): 149-176.
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.

    fileID = fopen(gcFileName,'w');
    len = length(gcData(:,1));
    for ind = 1 : len
        fprintf(fileID,'%d %f %f %f \r\n',ind,gcData(ind,:, :));
    end
    fclose(fileID);

    fileID = fopen(hdcFileName,'w');
    len = length(hdcData(:,1));
    for ind = 1 : len
        fprintf(fileID,'%d %f %f \r\n',ind,hdcData(ind, :));
    end
    fclose(fileID);

end


% SVARGPLVMTOOLBOXES Load in the relevant toolboxes for shared variational gplvm.

importLatest('netlab');
importLatest('prior');
importLatest('optimi');
importLatest('datasets');
importLatest('mltools');
importLatest('kern');
importLatest('ndlutil');
importLatest('mocap');
importLatest('gp');
importLatest('noise');
importLatest('vargplvm');
importLatest('matlab');


function [fragments, fragment_offset] = sequence_fragment(sequence, fragment_length)
% sequence_fragment Returns an array of subsequences
%
% This function returns a cell array of sequence objects that are fragments of the source sequence.
%
% Input:
% - sequence (structure): A valid sequence structure.
% - fragment_length (integer): The length of a single fragment.
%
% Output:
% - fragments (cell): A cell array of sequence descriptors.
% - fragment_offset(vector): A vector of offsets in the original sequence.

fragment_offset = [1:fragment_length:sequence.length, sequence.length+1];

fragments = cell(numel(fragment_offset)-1, 1);

for f = 1:numel(fragment_offset)-1
    indices = fragment_offset(f):fragment_offset(f+1)-1;
    fragments{f} = sequence;

    fragments{f}.groundtruth = sequence.groundtruth(indices, :);
    fragments{f}.indices = sequence.indices(indices);
    fragments{f}.tags.names = sequence.tags.names;
    fragments{f}.tags.data = sequence.tags.data(indices, :);
    fragments{f}.values.names = sequence.values.names;
    fragments{f}.values.data = sequence.values.data(indices, :);
    fragments{f}.images = sequence.images(indices);
    fragments{f}.length = length(indices);

end;

fragment_offset = fragment_offset(1:end-1);


function [newMap] = changeMetColor(map, metList, color)
% Change color of every metabolite from a list of Names
%
% USAGE:
%
%   [newMap] = changeMetColor(map, metList, color);
%
% INPUTS:
%   map:            file from CellDesigner parsed to MATLAB format
%   metList:        List of metabolites names
%
% OPTIONAL INPUT:
%   color:          New color of metabolites from list(default: RED)
%
% OUTPUT:
%   newMap:         Matlab structure of map with reaction modifications
%
% .. Authors:
%       - A.Danielsdottir 17/07/2017 LCSB. Belval. Luxembourg
%       - N.Sompairac - Institut Curie, Paris, 17/07/2017.

    if nargin < 3
        color = 'RED';
    end

    newMap = map;

    colors = createColorsMap();
    % Index for specName is the same as for corresponding specID
    specID = newMap.specID(ismember(newMap.specName, metList));
    index = find(ismember(newMap.molID, specID));

    % Change color
    for i = index'
        newMap.molColor{i} = colors(color);
    end

end


%  internal function

%  - Jimmy Shen (jimmy@rotman-baycrest.on.ca)

function [hdr, filetype, fileprefix, machine] = load_nii_hdr(fileprefix)

   if ~exist('fileprefix','var'),
      error('Usage: [hdr, filetype, fileprefix, machine] = load_nii_hdr(filename)');
   end

   machine = 'ieee-le';
   new_ext = 0;

   if ~isempty(findstr('.nii',fileprefix)) && ...
                        strcmp(fileprefix(end-3:end), '.nii')
      new_ext = 1;
      fileprefix(end-3:end)='';
   end

   if ~isempty(findstr('.hdr',fileprefix)) && ...
                        strcmp(fileprefix(end-3:end), '.hdr')
      fileprefix(end-3:end)='';
   end

   if ~isempty(findstr('.img',fileprefix)) && ...
                        strcmp(fileprefix(end-3:end), '.img')
      fileprefix(end-3:end)='';
   end

   if new_ext
      fn = sprintf('%s.nii',fileprefix);

      if ~exist(fn)
         msg = sprintf('Cannot find file "%s.nii".', fileprefix);
         error(msg);
      end
   else
      fn = sprintf('%s.hdr',fileprefix);

      if ~exist(fn)
         msg = sprintf('Cannot find file "%s.hdr".', fileprefix);
         error(msg);
      end
   end

   fid = fopen(fn,'r',machine);

   if fid < 0,
      msg = sprintf('Cannot open file %s.',fn);
      error(msg);
   else
      fseek(fid,0,'bof');

      if fread(fid,1,'int32') == 348
         hdr = read_header(fid);
         fclose(fid);
      else
         fclose(fid);

         %  first try reading the opposite endian to 'machine'
         %
         switch machine,
         case 'ieee-le', machine = 'ieee-be';
         case 'ieee-be', machine = 'ieee-le';
         end

         fid = fopen(fn,'r',machine);

         if fid < 0,
            msg = sprintf('Cannot open file %s.',fn);
            error(msg);
         else
            fseek(fid,0,'bof');

            if fread(fid,1,'int32') ~= 348

               %  Now throw an error
               %
               msg = sprintf('File "%s" is corrupted.',fn);
               error(msg);
            end

            hdr = read_header(fid);
            fclose(fid);
         end
      end
   end

   if strcmp(hdr.hist.magic, 'n+1')
      filetype = 2;
   elseif strcmp(hdr.hist.magic, 'ni1')
      filetype = 1;
   else
      filetype = 0;
   end

   return					% load_nii_hdr

%---------------------------------------------------------------------
function [ dsr ] = read_header(fid)

        %  Original header structures
	%  struct dsr
	%       {
	%       struct header_key hk;            /*   0 +  40       */
	%       struct image_dimension dime;     /*  40 + 108       */
	%       struct data_history hist;        /* 148 + 200       */
	%       };                               /* total= 348 bytes*/

    dsr.hk   = header_key(fid);
    dsr.dime = image_dimension(fid);
    dsr.hist = data_history(fid);

    %  For Analyze data format
    %
    if ~strcmp(dsr.hist.magic, 'n+1') && ~strcmp(dsr.hist.magic, 'ni1')
        dsr.hist.qform_code = 0;
        dsr.hist.sform_code = 0;
    end

    return					% read_header

%---------------------------------------------------------------------
function [ hk ] = header_key(fid)

    fseek(fid,0,'bof');

	%  Original header structures
	%  struct header_key                     /* header key      */
	%       {                                /* off + size      */
	%       int sizeof_hdr                   /*  0 +  4         */
	%       char data_type[10];              /*  4 + 10         */
	%       char db_name[18];                /* 14 + 18         */
	%       int extents;                     /* 32 +  4         */
	%       short int session_error;         /* 36 +  2         */
	%       char regular;                    /* 38 +  1         */
	%       char dim_info;   % char hkey_un0;        /* 39 +  1 */
	%       };                               /* total=40 bytes  */
	%
	% int sizeof_header   Should be 348.
	% char regular        Must be 'r' to indicate that all images and
	%                     volumes are the same size.

    v6 = version;
    if str2num(v6(1))<6
       directchar = '*char';
    else
       directchar = 'uchar=>char';
    end

    hk.sizeof_hdr    = fread(fid, 1,'int32')';	% should be 348!
    hk.data_type     = deblank(fread(fid,10,directchar)');
    hk.db_name       = deblank(fread(fid,18,directchar)');
    hk.extents       = fread(fid, 1,'int32')';
    hk.session_error = fread(fid, 1,'int16')';
    hk.regular       = fread(fid, 1,directchar)';
    hk.dim_info      = fread(fid, 1,'uchar')';

    return					% header_key

%---------------------------------------------------------------------
function [ dime ] = image_dimension(fid)

	%  Original header structures
	%  struct image_dimension
	%       {                                /* off + size      */
	%       short int dim[8];                /* 0 + 16          */
        %       /*
        %           dim[0]      Number of dimensions in database; usually 4.
        %           dim[1]      Image X dimension;  number of *pixels* in an image row.
        %           dim[2]      Image Y dimension;  number of *pixel rows* in slice.
        %           dim[3]      Volume Z dimension; number of *slices* in a volume.
        %           dim[4]      Time points; number of volumes in database
        %       */
	%       float intent_p1;   % char vox_units[4];   /* 16 + 4       */
	%       float intent_p2;   % char cal_units[8];   /* 20 + 4       */
	%       float intent_p3;   % char cal_units[8];   /* 24 + 4       */
	%       short int intent_code;   % short int unused1;   /* 28 + 2 */
	%       short int datatype;              /* 30 + 2          */
	%       short int bitpix;                /* 32 + 2          */
	%       short int slice_start;   % short int dim_un0;   /* 34 + 2 */
	%       float pixdim[8];                 /* 36 + 32         */
	%	/*
	%		pixdim[] specifies the voxel dimensions:
	%		pixdim[1] - voxel width, mm
	%		pixdim[2] - voxel height, mm
	%		pixdim[3] - slice thickness, mm
	%		pixdim[4] - volume timing, in msec
	%					..etc
	%	*/
	%       float vox_offset;                /* 68 + 4          */
	%       float scl_slope;   % float roi_scale;     /* 72 + 4 */
	%       float scl_inter;   % float funused1;      /* 76 + 4 */
	%       short slice_end;   % float funused2;      /* 80 + 2 */
	%       char slice_code;   % float funused2;      /* 82 + 1 */
	%       char xyzt_units;   % float funused2;      /* 83 + 1 */
	%       float cal_max;                   /* 84 + 4          */
	%       float cal_min;                   /* 88 + 4          */
	%       float slice_duration;   % int compressed; /* 92 + 4 */
	%       float toffset;   % int verified;          /* 96 + 4 */
	%       int glmax;                       /* 100 + 4         */
	%       int glmin;                       /* 104 + 4         */
	%       };                               /* total=108 bytes */

    dime.dim        = fread(fid,8,'int16')';
    dime.intent_p1  = fread(fid,1,'float32')';
    dime.intent_p2  = fread(fid,1,'float32')';
    dime.intent_p3  = fread(fid,1,'float32')';
    dime.intent_code = fread(fid,1,'int16')';
    dime.datatype   = fread(fid,1,'int16')';
    dime.bitpix     = fread(fid,1,'int16')';
    dime.slice_start = fread(fid,1,'int16')';
    dime.pixdim     = fread(fid,8,'float32')';
    dime.vox_offset = fread(fid,1,'float32')';
    dime.scl_slope  = fread(fid,1,'float32')';
    dime.scl_inter  = fread(fid,1,'float32')';
    dime.slice_end  = fread(fid,1,'int16')';
    dime.slice_code = fread(fid,1,'uchar')';
    dime.xyzt_units = fread(fid,1,'uchar')';
    dime.cal_max    = fread(fid,1,'float32')';
    dime.cal_min    = fread(fid,1,'float32')';
    dime.slice_duration = fread(fid,1,'float32')';
    dime.toffset    = fread(fid,1,'float32')';
    dime.glmax      = fread(fid,1,'int32')';
    dime.glmin      = fread(fid,1,'int32')';

    return					% image_dimension

%---------------------------------------------------------------------
function [ hist ] = data_history(fid)

	%  Original header structures
	%  struct data_history
	%       {                                /* off + size      */
	%       char descrip[80];                /* 0 + 80          */
	%       char aux_file[24];               /* 80 + 24         */
	%       short int qform_code;            /* 104 + 2         */
	%       short int sform_code;            /* 106 + 2         */
	%       float quatern_b;                 /* 108 + 4         */
	%       float quatern_c;                 /* 112 + 4         */
	%       float quatern_d;                 /* 116 + 4         */
	%       float qoffset_x;                 /* 120 + 4         */
	%       float qoffset_y;                 /* 124 + 4         */
	%       float qoffset_z;                 /* 128 + 4         */
	%       float srow_x[4];                 /* 132 + 16        */
	%       float srow_y[4];                 /* 148 + 16        */
	%       float srow_z[4];                 /* 164 + 16        */
	%       char intent_name[16];            /* 180 + 16        */
	%       char magic[4];   % int smin;     /* 196 + 4         */
	%       };                               /* total=200 bytes */

    v6 = version;
    if str2num(v6(1))<6
       directchar = '*char';
    else
       directchar = 'uchar=>char';
    end

    hist.descrip     = deblank(fread(fid,80,directchar)');
    hist.aux_file    = deblank(fread(fid,24,directchar)');
    hist.qform_code  = fread(fid,1,'int16')';
    hist.sform_code  = fread(fid,1,'int16')';
    hist.quatern_b   = fread(fid,1,'float32')';
    hist.quatern_c   = fread(fid,1,'float32')';
    hist.quatern_d   = fread(fid,1,'float32')';
    hist.qoffset_x   = fread(fid,1,'float32')';
    hist.qoffset_y   = fread(fid,1,'float32')';
    hist.qoffset_z   = fread(fid,1,'float32')';
    hist.srow_x      = fread(fid,4,'float32')';
    hist.srow_y      = fread(fid,4,'float32')';
    hist.srow_z      = fread(fid,4,'float32')';
    hist.intent_name = deblank(fread(fid,16,directchar)');
    hist.magic       = deblank(fread(fid,4,directchar)');

    fseek(fid,253,'bof');
    hist.originator  = fread(fid, 5,'int16')';

    return					% data_history


function res = hlp_varargin2struct(args, varargin)
% Convert a list of name-value pairs into a struct with values assigned to names.
% struct = hlp_varargin2struct(Varargin, Defaults)
%
% In:
%   Varargin : cell array of name-value pairs and/or structs (with values assigned to names)
%
%   Defaults : optional list of name-value pairs, encoding defaults; multiple alternative names may
%              be specified in a cell array
%
% Example:
%   function myfunc(x,y,z,varargin)
%   % parse options, and give defaults for some of them:
%   options = hlp_varargin2struct(varargin, 'somearg',10, 'anotherarg',{1 2 3});
%
% Notes:
%   * mandatory args can be expressed by specifying them as ..., 'myparam',mandatory, ... in the defaults
%     an error is raised when any of those is left unspecified
%
%   * the following two parameter lists are equivalent (note that the struct is specified where a name would be expected,
%     and that it replaces the entire name-value pair):
%     ..., 'xyz',5, 'a',[], 'test','toast', 'xxx',{1}. ...
%     ..., 'xyz',5, struct( 'a',{[]},'test',{'toast'} ), 'xxx',{1}, ...
%
%   * names with dots are allowed, i.e.: ..., 'abc',5, 'xxx.a',10, 'xxx.yyy',20, ...
%
%   * some parameters may have multiple alternative names, which shall be remapped to the
%     standard name within opts; alternative names are given together with the defaults,
%     by specifying a cell array of names instead of the name in the defaults, as in the following example:
%     ... ,{'standard_name','alt_name_x','alt_name_y'}, 20, ...
%
% Out:
%   Result : a struct with fields corresponding to the passed arguments (plus the defaults that were
%            not overridden); if the caller function does not retrieve the struct, the variables are
%            instead copied into the caller's workspace.
%
% Examples:
%   % define a function which takes some of its arguments as name-value pairs
%   function myfunction(myarg1,myarg2,varargin)
%   opts = hlp_varargin2struct(varargin, 'myarg3',10, 'myarg4',1001, 'myarg5','test');
%
%   % as before, but this time allow an alternative name for myarg3
%   function myfunction(myarg1,myarg2,varargin)
%   opts = hlp_varargin2struct(varargin, {'myarg3','legacyargXY'},10, 'myarg4',1001, 'myarg5','test');
%
%   % as before, but this time do not return arguments in a struct, but assign them directly to the
%   % function's workspace
%   function myfunction(myarg1,myarg2,varargin)
%   hlp_varargin2struct(varargin, {'myarg3','legacyargXY'},10, 'myarg4',1001, 'myarg5','test');
%
% See also:
%   hlp_struct2varargin, arg_define
%
%                               Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                               2010-04-05

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

if isstruct(args)
    args = {args}; end

% --- handle defaults ---
if ~isempty(varargin)
    % splice substructs into the name-value list
    if any(cellfun('isclass',varargin(1:2:end),'struct'))
        varargin = flatten_structs(varargin); end

    defnames = varargin(1:2:end);
    defvalues = varargin(2:2:end);

    % make a remapping table for alternative default names...
    for k=find(cellfun('isclass',defnames,'cell'))
        for l=2:length(defnames{k})
                name_for_alternative.(defnames{k}{l}) = defnames{k}{1}; end
        defnames{k} = defnames{k}{1};
    end

    % create default struct
    if [defnames{:}]~='.'
        % use only the last assignment for each name
        [s,indices] = sort(defnames(:));
        indices( strcmp(s((1:end-1)'),s((2:end)'))) = [];
        % and make the struct
        res = cell2struct(defvalues(indices),defnames(indices),2);
    else
        % some dot-assignments are contained in the defaults
        try
            res = struct();
            for k=1:length(defnames)
                if any(defnames{k}=='.')
                    eval(['res.' defnames{k} ' = defvalues{k};']);
                else
                    res.(defnames{k}) = defvalues{k};
                end
            end
        catch
            error(['invalid field name specified in defaults: ' defnames{k}]);
        end
    end
else
    res = struct();
end

% --- handle overrides ---
if ~isempty(args)
    % splice substructs into the name-value list
    if any(cellfun('isclass',args(1:2:end),'struct'))
        args = flatten_structs(args); end

    % rewrite alternative names into their standard form...
    if exist('name_for_alternative','var')
        for k=1:2:length(args)
            if isfield(name_for_alternative,args{k})
                args{k} = name_for_alternative.(args{k}); end
        end
    end

    % override defaults with arguments...
    try
        if [args{1:2:end}]~='.'
            for k=1:2:length(args)
                res.(args{k}) = args{k+1}; end
        else
            % some dot-assignments are contained in the overrides
            for k=1:2:length(args)
                if any(args{k}=='.')
                    eval(['res.' args{k} ' = args{k+1};']);
                else
                    res.(args{k}) = args{k+1};
                end
            end
        end
    catch
        if ischar(args{k})
            error(['invalid field name specified in arguments: ' args{k}]);
        else
            error(['invalid field name specified for the argument at position ' num2str(k)]);
        end
    end
end

% check for missing but mandatory args
% note: the used string needs to match mandatory.m
missing_entries = strcmp('__arg_mandatory__',struct2cell(res));
if any(missing_entries)
    fn = fieldnames(res)';
    fn = fn(missing_entries);
    error(['The parameters {' sprintf('%s, ',fn{1:end-1}) fn{end} '} were unspecified but are mandatory.']);
end

% copy to the caller's workspace if no output requested
if nargout == 0
    for fn=fieldnames(res)'
        assignin('caller',fn{1},res.(fn{1})); end
end

% substitute any structs in place of a name-value pair into the name-value list
function args = flatten_structs(args)
k = 1;
while k <= length(args)
    if isstruct(args{k})
        tmp = [fieldnames(args{k}) struct2cell(args{k})]';
        args = [args(1:k-1) tmp(:)' args(k+1:end)];
        k = k+numel(tmp);
    else
        k = k+2;
    end
end


function GUI = sessionGUI_editMenu(GUI);
% Attach an Edit Menu to the session GUI figure, including
% callbacks for all editing-related operations.
%
% GUI = sessionGUI_editMenu(GUI);
%
%
% ras, 07/06.
GUI.menus.edit = uimenu('Label', 'Edit', 'Separator', 'on');

% add option to edit mrSESSION
cb = '[mrSESSION ok] = EditSession(mrSESSION,0); if ok, saveSession(1); end; ';
uimenu(GUI.menus.edit, 'Label', 'Session', 'Separator', 'off', 'Callback', cb);

% add option to edit alignment for this session
% Edit alignment(using mrRx):
uimenu(GUI.menus.edit, 'Label', 'Edit/View Alignment...', 'Separator', 'off', ...
      'Callback', 'rxAlign; ');

% Attach submenus
submenu_dataType(GUI.menus.edit);
submenu_eventRelated(GUI.menus.edit);
submenu_retinotopy(GUI.menus.edit);
submenu_segmentation(GUI.menus.edit);

return
% /---------------------------------------------------------------------/ %

% /---------------------------------------------------------------------/ %
function h = submenu_dataType(parent);
% attach a submenu for Study-related operations.
h = uimenu(parent, 'Label', 'Data Type', 'Separator', 'off');

cb = ['dt = GUI.settings.dataType; ' ...
      '[dataTYPES(dt) ok] = EditDataType(dataTYPES(dt)); ' ...
      'if ok, saveSession(1); end; clear dt; '];
uimenu(h, 'Label', 'Edit Data Type Parameters', 'Separator', 'off', ...
          'Callback', cb);

cb = 'removeDataType(dataTYPES(GUI.settings.dataType).name);';
uimenu(h, 'Label', 'Delete Current Data Type', 'Separator', 'on', ...
          'Callback', cb);

cb = 'duplicateDataType(INPLANE{1});';
uimenu(h, 'Label', 'Duplicate Current Data Type', ...
        'Separator', 'off', 'Callback', cb);

cb = 'groupScans(INPLANE{1});';
uimenu(h, 'Label', 'Group Scans Into Data Type', ...
        'Separator', 'off', 'Callback', cb);

return
% /---------------------------------------------------------------------/ %

% /---------------------------------------------------------------------/ %
function h = submenu_eventRelated(parent);
% attach a submenu for editing event-related settings.
h = uimenu(parent, 'Label', 'Event-Related', 'Separator', 'off');

uimenu(h, 'Label', 'Group Scans Into Scan Group', 'Separator', 'off', ...
          'Callback', 'er_groupScans(INPLANE{1}, guiGet(''scans''), 2); ');

uimenu(h, 'Label', 'Assign Scan Group to Selected Scan', 'Separator', 'off', ...
          'Callback', 'er_groupScans(INPLANE{1}, guiGet(''scans''), 1); ');

uimenu(h, 'Label', 'Assign .par files to Scans', 'Separator', 'off', ...
          'Callback', 'er_assignParfilesToScans(INPLANE{1}, guiGet(''scans'')); ');

uimenu(h, 'Label', 'Show parfiles/scan group', 'Separator', 'off', ...
          'Callback', 'er_displayParfiles(INPLANE{1}); ');

cb = ['params = er_getParams(INPLANE{1}); ' ...
      'params = er_editParams(params); ' ...
	  'er_setParams(INPLANE{1}, params); '];
uimenu(h, 'Label', 'Edit Event-Related Parameters (scan group)', ...
          'Separator', 'off', 'Callback', cb);

return
% /---------------------------------------------------------------------/ %

% /---------------------------------------------------------------------/ %
function h = submenu_retinotopy(parent);
% attach a submenu for operations related to simple mapping of
% traveling-wave analysis results to retinotopic parameters.
% (This is not the full Retinotopy Model Serge created; just parameters
% that will convert corAnal phase to estimated physical units.)
% TO DO: add functionality to the analysis menu to convert corAnal files
% into polar angle and eccentricity parameter maps.
h = uimenu(parent, 'Label', 'Retinotopy', 'Separator', 'off');

uimenu(h, 'Label', 'Set Retinotopy Params (selected scans)', ...
          'Callback', 'retinoSetParams(INPLANE{1}, guiGet(''scans'')); ');

cb = 'retinoSetParams(INPLANE{1}, [], guiGet(''scans''), ''none''); ';
uimenu(h, 'Label', 'Un-set Params (selected scans)', 'Callback', cb);

return
% /---------------------------------------------------------------------/ %

% /---------------------------------------------------------------------/ %
function h = submenu_segmentation(parent);
% attach a submenu for segmentation-related operations.
h = uimenu(parent, 'Label', 'Segmentation', 'Separator', 'off');

uimenu(h, 'Label', 'Install / Reinstall Segmentation (cur session)', ...
          'Separator', 'off', 'Callback', 'installSegmentation; ');

uimenu(h, 'Label', 'Segmentation Info', ...
          'Separator', 'off', 'Callback', 'segmentInfo(VOLUME{1}); ');

uimenu(h, 'Label', 'Load Segmentation into mrViewer', ...
          'Separator', 'on', 'Callback', 'sessionGUI_loadSegmentation; ');

return


function [model, deletedSEEDRxns] = deleteSeedGapfilledReactions(model, biomassReaction)
% Part of the DEMETER pipeline. Deletes reactions gapfilled by the Model
% SEED pipeline that are no longer needed after the reconstruction was
% refined.
%
% INPUT
% model             COBRA model structure
% biomassReaction   Biomass reaction abbreviation
%
% OUTPUT
% model             COBRA model structure
% deletedSEEDRxns   deleted gapfilled reactions
%
% .. Authors:
% Almut Heinken and Stefania Magnusdottir, 2016-2019

global CBT_LP_SOLVER
if isempty(CBT_LP_SOLVER)
    initCobraToolbox
end
solver = CBT_LP_SOLVER;

tol = 1e-8;

gfRxns = model.rxns(find(strcmp(model.grRules,'')));
gfRxns = union(gfRxns, model.rxns(strncmp('Unknown', model.grRules, length('Unknown'))));
gfRxns = union(gfRxns, model.rxns(strncmp('0000000.0.peg', model.grRules, length('0000000.0.peg'))));
gfRxns = union(gfRxns, model.rxns(strncmp('AUTOCOMPLETION', model.grRules, length('AUTOCOMPLETION'))));
gfRxns = union(gfRxns, model.rxns(strncmp('INITIALGAPFILLING', model.grRules, length('INITIALGAPFILLING'))));

% not consider exchange, demand, and sink reactions
gfRxns(find(strncmp(gfRxns,'EX_',3)),:)=[];
gfRxns(find(strncmp(gfRxns,'DM_',3)),:)=[];
gfRxns(find(strncmp(gfRxns,'sink_',5)),:)=[];

% only consider reactions that were already in draft reconstructions
translateRxns = readtable('ReactionTranslationTable.txt', 'Delimiter', '\t');
translateRxns=table2cell(translateRxns);
gfRxns=intersect(gfRxns,translateRxns(:,2));

noDelete = {biomassReaction; 'O2t'; 'O2t5i'; 'CO2t'; 'MG2abc'; 'H2Ot'; 'L2A6ODs'; 'G5SADs'; 'AOBUTDs'; 'ACGAMK'; 'DM_atp_c_'; 'FE3abc'; 'SO4t2'; 'TSULabc'; 'PDHbr'; 'PDHc'; 'INDOLEt2r'; 'SUCCt2r'; 'PHEt2r'; 'TRPt2r'};
checkDelete = setdiff(gfRxns, noDelete);

transp = {  % delete exchange reaction with following transporters
            'AHCYSts', 'EX_ahcys(e)'
            'ALAHISabc', 'EX_alahis(e)'
            'ALALEUabc', 'EX_alaleu(e)'
            'CBIabc', 'EX_cbi(e)'
            'CGLYabc', 'EX_cgly(e)'
            'CHORt', 'EX_chor(e)'
            'CMPt2', 'EX_cmp(e)'
            'COAt', 'EX_coa(e)'
            'Cut1', 'EX_cu2(e)'
            'CYTDt4', 'EX_cytd(e)'
            'DATPt', 'EX_datp(e)'
            'DDCAt', 'EX_ddca(e)'
            'DGSNt2', 'EX_dgsn(e)'
            'DGTPt', 'EX_dgtp(e)'
            'DPCOAt', 'EX_dpcoa(e)'
            'DTMPt', 'EX_dtmp(e)'
            'DTTPti', 'EX_dttp(e)'
            'ETHAt2', 'EX_etha(e)'
            'G6Pt6_2', 'EX_g6p(e)'
            'GLYC3Pt', 'EX_glyc3p[e]'
            'HDCEAtr', 'EX_hdcea(e)'
            'MALTHPabc', 'EX_malthp(e)'
            'MALTHXabc', 'EX_malthx(e)'
            'MK7te', 'EX_mqn7(e)'
            'NADPt', 'EX_nadp(e)'
            'OCDCAt2', 'EX_ocdca(e)'
%             'PTRCt2', 'EX_ptrc(e)'
            'SALCt2', 'EX_salc(e)'
            'THMMPt2', 'EX_thmmp(e)'
            'TTDCAt2', 'EX_ttdca(e)'
            'UREAt', 'EX_urea(e)'
            };
cnt = 1;
deletedSEEDRxns = {};
model = changeRxnBounds(model, model.rxns(strmatch('EX_', model.rxns)), -1000, 'l');
model = changeRxnBounds(model, 'EX_o2(e)', 0, 'l');

% minFlux = zeros(size(model.rxns));
% maxFlux = zeros(size(model.rxns));
% % reaction vector is not sorted, so cannot run fastFVA on all reactions at
% % once
% for n = 1:length(model.rxns)
%     model = changeObjective(model, model.rxns{n});
%     sol = optimizeCbModel(model, 'max');
%     maxFlux(n) = sol.f;
%     sol = optimizeCbModel(model, 'min');
%     minFlux(n) = sol.f;
% end

checkDelete=intersect(model.rxns,checkDelete,'stable');

% perform flux variability analysis
currentDir=pwd;
try
    [minFlux, maxFlux, ~, ~] = fastFVA(model, 0, 'max', 'ibm_cplex', ...
        checkDelete, 'S');
catch
    warning('fastFVA could not run, so fluxVariability is instead used. Consider installing fastFVA for shorter computation times.');
    cd(currentDir)
    [minFlux, maxFlux] = fluxVariability(model, 0, 'max', checkDelete);
end

model = changeObjective(model, biomassReaction);

% first check for and remove all blocked reactions
for i = 1:size(checkDelete, 1)
    if ~isempty(find(ismember(transp(:, 1), checkDelete{i, 1})))
        if abs(minFlux(i, 1)) < tol && abs(maxFlux(i, 1)) < tol
            modelTest = changeRxnBounds(model, checkDelete{i, 1}, 0, 'b');
            FBA = optimizeCbModel(modelTest, 'max');
            if FBA.f > tol
                deletedSEEDRxns{cnt, 1} = transp{find(strcmp(transp(:,1),checkDelete{i, 1})), 1};
                deletedSEEDRxns{cnt + 1, 1} = transp{find(strcmp(transp(:,1),checkDelete{i, 1})), 2};
                cnt = cnt + 2;
            end
        end
    else
        if abs(minFlux(i, 1)) < tol && abs(maxFlux(i, 1)) < tol
            modelTest = changeRxnBounds(model, checkDelete{i, 1}, 0, 'b');
            FBA = optimizeCbModel(modelTest, 'max');
            if FBA.f > tol
                deletedSEEDRxns{cnt, 1} = checkDelete{i, 1};
                cnt = cnt + 1;
            end
        end
    end
end

% then the reactions that are not blocked but may be safely deleted
% load complex medium
constraints = readtable('ComplexMedium.txt', 'Delimiter', 'tab');
constraints=table2cell(constraints);
constraints=cellstr(string(constraints));

% apply complex medium
modelTest = useDiet(model,constraints);
for i = 1:size(checkDelete, 1)
    if ~isempty(find(ismember(transp(:, 1), checkDelete{i, 1})))  % if deleted reaction is in transporter list
        trListInd = find(ismember(transp(:, 1), checkDelete{i, 1}));
        trInd = find(ismember(modelTest.rxns, transp{trListInd, 1}));
        exInd = find(ismember(modelTest.rxns, transp{trListInd, 2}));
        savedTrLB = modelTest.lb(trInd);
        savedTrUB = modelTest.ub(trInd);
        savedExLB = modelTest.lb(exInd);
        savedExUB = modelTest.ub(exInd);
        modelTest = changeRxnBounds(modelTest, transp{trListInd, 1}, 0, 'b');
        modelTest = changeRxnBounds(modelTest, transp{trListInd, 2}, 0, 'b');
        FBA = optimizeCbModel(modelTest, 'max');
        if FBA.f > 1e-6
            deletedSEEDRxns{cnt, 1} = transp{trListInd, 1};
            deletedSEEDRxns{cnt + 1, 1} = transp{trListInd, 2};
            cnt = cnt + 2;
            modelTest = removeRxns(modelTest, {transp{trListInd, 1}, transp{trListInd, 2}});
        else
            modelTest.lb(trInd) = savedTrLB;
            modelTest.ub(trInd) = savedTrUB;
            modelTest.lb(exInd) = savedExLB;
            modelTest.ub(exInd) = savedExUB;
        end
    else
        rxnInd = find(ismember(modelTest.rxns, checkDelete{i, 1}));
        savedRxnLB = modelTest.lb(rxnInd);
        savedRxnUB = modelTest.ub(rxnInd);
        modelTest = changeRxnBounds(modelTest, checkDelete{i, 1}, 0, 'b');
        FBA = optimizeCbModel(modelTest, 'max');
        if FBA.f > tol
            deletedSEEDRxns{cnt, 1} = checkDelete{i, 1};
            cnt = cnt + 1;
            modelTest = removeRxns(modelTest, checkDelete{i, 1});
        else
            modelTest.lb(rxnInd) = savedRxnLB;
            modelTest.ub(rxnInd) = savedRxnUB;
        end
    end
end
model = removeRxns(model, deletedSEEDRxns);

% change back to unlimited medium
% list exchange reactions
exchanges = model.rxns(strncmp('EX_', model.rxns, 3));
% open all exchanges
model = changeRxnBounds(model, exchanges, -1000, 'l');
model = changeRxnBounds(model, exchanges, 1000, 'u');

end


% recompile mex code to have actual version of the NN code

clear functions

eval('mex -I.. -I../.. ../fnearneigh.cpp -O -output fnearneigh');
eval('mex -I.. -I../.. ../fnearneigh.cpp -O -output fnearneigh_partial -DPARTIAL_SEARCH');
eval('mex -I.. -I../.. ../fnearneigh.cpp -O -DBRUTE -output nn_brute');
eval('mex -I.. -I../.. ../fnearneigh.cpp -O -DBRUTE -output nn_brute_partial -DPARTIAL_SEARCH');

eval('mex -I.. -I../.. ../nn_prepare.cpp -O -output nn_prepare');

eval('mex -I.. -I../.. ../nn_search.cpp -O -output nn_search');
eval('mex -I.. -I../.. ../nn_search.cpp -O -output nn_search_partial -DPARTIAL_SEARCH');

eval('mex -I.. -I../.. ../range_search.cpp -O -output range_search');
eval('mex -I.. -I../.. ../range_search.cpp -O -output range_search_partial -DPARTIAL_SEARCH');

eval('mex -I.. -I../.. ../corrsum.cpp -O -output corrsum');
eval('mex -I.. -I../.. ../corrsum.cpp -O -output corrsum_partial -DPARTIAL_SEARCH');


function v = reshape(v,varargin)
% overloads reshape

v.x = reshape(v.x,varargin{:});
v.y = reshape(v.y,varargin{:});
v.z = reshape(v.z,varargin{:});


%--- help for mcmc.reload_draws ---
%
%  subset is a 1 x 2 cell array in which
%  - the first cell contains the columns to retain: can be empty, defaults
%  to all
%  - the second column contains the chains to retain: can be empty, defaults
%  to all
%


%% EVENT ENUMERATION CLASSES (eventType.m) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file contains the enumeration definition of the available events
% that can happen inside the simulation environment.

% Author: James A. Douthwaite 05/10/16

classdef eventType < uint8
   % Assign uint8 type to enumeration values
   enumeration
      event(0)          % Generic event
      detection(1)      % Detection
      warning(2)        % Proximity warning
      collision(3)      % Collision
      waypoint(4)       % Waypoint achieve
      null_detection(5) % Detection loss
      null_warning(6)   % Warning-clear
      null_collision(7) % Collision-clear
      null_waypoint(8)  % Waypoint drop
   end
end


% ----------------------------------------------------------------------------
% function hfssAssignPE(fid, Name, ObjectList, [infGND = false])
%
% Description :
% -------------
% This function creates the VB Script necessary to assign a PEC boundary to
% the given object(s).
%
% Parameters :
% ------------
% fid     - file identifier of the HFSS script file.
% Name    - name of the PEC boundary. This will appear under "Boundaries"
%           in HFSS
% ObjList - a cell array of objects to which the PEC boundary condition will
%           be applied.
% infGND  - (boolean) specify as true to make the PEC represent an infinite
%           ground plane (default is false).
%
%
% Note :
% ------
%
% Example :
% ---------
% fid = fopen('myantenna.vbs', 'wt');
% ...
% hfssAssignPE(fid, 'GNDplane', {'AntennaGND'}, true);
%
% ----------------------------------------------------------------------------

% ----------------------------------------------------------------------------
% This file is part of HFSS-MATLAB-API.
%
% HFSS-MATLAB-API 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.
%
% HFSS-MATLAB-API 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
% Foobar; if not, write to the Free Software Foundation, Inc., 59 Temple
% Place, Suite 330, Boston, MA  02111-1307  USA
%
% Copyright 2004, Vijay Ramasami (rvc@ku.edu)
% ----------------------------------------------------------------------------

function hfssAssignPE(fid, Name, ObjectList, infGND)

% arguments processor.
if (nargin < 3)
	error('Insufficient # of arguments !');
elseif (nargin < 4)
	infGND = [];
end

% default arguments.
if isempty(infGND)
	infGND = false;
end

% # of objects.
nObjects = length(ObjectList);

% create the necessary script.
fprintf(fid, '\n');
fprintf(fid, 'Set oModule = oDesign.GetModule("BoundarySetup")\n');
fprintf(fid, 'oModule.AssignPerfectE _\n');
fprintf(fid, 'Array("NAME:%s", _\n', Name);

% is infinite GND ?
if (infGND)
	fprintf(fid, '"InfGroundPlane:=", true, _\n');
else
	fprintf(fid, '"InfGroundPlane:=", false, _\n');
end

fprintf(fid, '"Objects:=", _\n');
fprintf(fid, 'Array(');
for iObj = 1:nObjects
	fprintf(fid, '"%s"', ObjectList{iObj});
	if (iObj ~= nObjects)
		fprintf(fid, ',');
	end
end
fprintf(fid, '))\n');


classdef DehomogenizationTestsSuite < handle

    methods

        function obj = DehomogenizationTestsSuite()
            warning('off', 'MATLAB:structOnObject')
            results = runtests("DehomogenizingTests","Tag","Singularities", 'Debug', true);
            table(results)
            warning('on', 'MATLAB:structOnObject')
        end

    end
end


% PURPOSE: loads channel location information into an erpset
%
% FORMAT:
%
% ERP = erpchanedit(ERP, filename);
%
%
% See also borrowchanloc.m
%
%
% *** This function is part of ERPLAB Toolbox ***
% Author: Javier Lopez-Calderon && Johanna Kreither
% Center for Mind and Brain
% University of California, Davis,
% Davis, CA
% 2013

function [ERP, erpcom] = pop_erpchanedit(ERP, filename, varargin)
erpcom = '';
if nargin<1
        help erpchanedit
        return
end
if nargin==1
        [filename, filepath] = uigetfile({ ...
                '*.elp','Besa Spherical (*.elp)'; ...
                '*.sfp','BESA/EGI (*.sfp)'; ...
                '*.loc','EEGLAB (*.loc)'; ...
                '*.ced','EEGLAB (ASCII) (*.ced)'; ...
                '*.xyz','EEGLAB (Matlab) (*.xyz)'; ...
                '*.elc','EETrack (*.elc)'; ...
                '*.sph','Matlab (*.sph)'; ...
                '*.asc','Neuroscan (*.asc)'; ...
                '*.dat','Neuroscan (*.dat)'; ...
                '*.elp','Polhemus (*.elp)'; ...
                '*.*',  'All Files (*.*)'}, ...
                'Select channel location file', ...
                'MultiSelect', 'off');
        if isequal(filename,0)
                disp('User selected Cancel')
                return
        else
                filename = fullfile(filepath, filename);
                disp(['For channel location file user selected  ' filename ''])
        end

        %
        % Somersault
        %
        [ERP, erpcom] = pop_erpchanedit(ERP, filename, 'Warning', 'on', 'Saveas', 'on', 'History', 'gui');
        return
end

%
% Parsing inputs
%
p = inputParser;
p.FunctionName  = mfilename;
p.CaseSensitive = false;
p.addRequired('ERP');
p.addRequired('filename', @ischar);
% option(s)
p.addParamValue('Warning', 'off', @ischar);
p.addParamValue('Saveas', 'off', @ischar); % 'on', 'off'
p.addParamValue('History', 'script', @ischar); % history from scripting

p.parse(ERP, filename, varargin{:});

if strcmpi(p.Results.Warning,'on')
        wchmsgon = 1;
else
        wchmsgon = 0;
end
if strcmpi(p.Results.History,'implicit')
        shist = 3; % implicit
elseif strcmpi(p.Results.History,'script')
        shist = 2; % script
elseif strcmpi(p.Results.History,'gui')
        shist = 1; % gui
else
        shist = 0; % off
end
if ismember_bc2({p.Results.Saveas}, {'on','yes'})
        issaveas  = 1;
else
        issaveas  = 0;
end

%
% Subroutine
%
[ERP, serror] = erpchanedit(ERP, filename);
if isempty(serror)
        disp('User selected Cancel')
        return
end
if serror~=0
        msgboxText = ['pop_erpchanedit could not find channel locations info.\n\n'...
                'Hint: Identify channel(s) without location looking at '...
                'command window comments (Channel lookup). Try again excluding this(ese) channel(s).'];
        tittle = 'pop_scalplot:  error:';
        errorfound(sprintf(msgboxText), tittle);
        return
end

ERP.saved  = 'no';
erpcom = sprintf('%s = pop_erpchanedit( %s, ''%s'');', inputname(1), inputname(1), filename);

if issaveas
        [ERP, issave, erpcom_save] = pop_savemyerp(ERP,'gui','erplab', 'History', 'implicit');
        if issave>0
                % generate text command
                if issave==2
                        erpcom = sprintf('%s\n%s', erpcom, erpcom_save);
                        msgwrng = '*** Your ERPset was saved on your hard drive.***';
                else
                        msgwrng = '*** Warning: Your ERPset was only saved on the workspace.***';
                end
                fprintf('\n%s\n\n', msgwrng)
                try cprintf([0 0 1], 'COMPLETE\n\n');catch,fprintf('COMPLETE\n\n');end ;
        else
                ERP = ERPaux;
                msgwrng = 'ERPLAB Warning: Your changes were not saved';
                try cprintf([1 0.52 0.2], '%s\n\n', msgwrng);catch,fprintf('%s\n\n', msgwrng);end ;
        end
end
% get history from script. ERP
switch shist
        case 1 % from GUI
                displayEquiComERP(erpcom);
        case 2 % from script
                ERP = erphistory(ERP, [], erpcom, 1);
        case 3
                % implicit
                %ERP = erphistory(ERP, [], erpcom, 1);
                %fprintf('%%Equivalent command:\n%s\n\n', erpcom);
        otherwise %off or none
                erpcom = '';
end

%
% Completion statement
%
msg2end
return


function dispProgress(name, value, maxvalue)
%DISPPROGRESS display calculation progress
% initialize and update progress bar
%
% (c) Thomas Kuestner
% ---------------------------------------------------------------------

persistent prop

if(nargin < 3)
    maxvalue = 0;
end

if(~exist('prop','var') || isempty(prop) || strcmp(name,'InitDispProgress'))
    if(isstruct(value))
        prop = value;
        return;
    else
%         error('dispProgress(): Unknown data structure for property');
        return; % shortcut for GA simulation
    end
end

if(prop.flagParallel)
    if(verLessThan('matlab','8.4'))
        if(matlabpool('size') > 0)
            return; % shortcut for parallel computing
        end
    else
        if(~isempty(gcp('nocreate')))
            return % shortcut for parallel computing
        end
    end
end

% if(matlabpool('size') > 0)
%     openPool = true;
%     currpath = fileparts(fileparts(mfilename('fullpath')));
%     a = load([currpath, filesep, 'prop.mat']);
% else
%     openPool = false;
% end

if(prop.flagDisp)
    % GUI

    if(~prop.openPool)
        if(prop.disp.openBar(strcmp(prop.disp.names,name)))
            % progress bar already exists
            if(ischar(value) && strcmp(value,'Close'))
                multiWaitbar(name,value);
                prop.disp.openBar(strcmp(prop.disp.names,name)) = false;
            else
                cval = round(value*100);
                if(cval == 0), cval = max(ceil(value*100),1); end;
                if(cval > 100), cval = 100; end;
                abort = multiWaitbar(name, value, 'Color', prop.disp.colors(cval,:));
                if(abort)
                    multiWaitbar('CLOSEALL');
                    error('User Termination of CS reconstruction!');
                end
            end
        else
            % progress bar needs initialization
            if(maxvalue > 1)
                multiWaitbar(name,value,'CancelFcn', @(a,b) disp( ['Cancel ',a] ));
                prop.disp.openBar(strcmp(prop.disp.names,name)) = true;
            end
        end

    else
        % parallel computation
        if(prop.disp.openBar(strcmp(prop.disp.names,name)))
            % progress bar already exists
            if(ischar(value) && strcmp(value,'Close'))
                try
                    delete(prop.disp.ppm{strcmp(prop.disp.names,name)});
                catch err
                end
                prop.disp.openBar(strcmp(prop.disp.names,name)) = false;
            else
                prop.disp.ppm{strcmp(prop.disp.names,name)}.increment(value);
            end
        else
            % progress bar needs initialization
            if(maxvalue > 1)
                helper = ParforProgressStarter2(name, maxvalue, 1);
                prop.disp.ppm{strcmp(prop.disp.names,name)} = helper;
                prop.disp.openBar(strcmp(prop.disp.names,name)) = true;
            end
        end
%         save([currpath, filesep, 'prop.mat'], '-struct', 'a');
    end

else
    % console

    if(ischar(value) && strcmp(value,'Close'))
        if(any(strcmp(name,{'CG','SENSE - Time','SENSE - Kernel','SENSE - Concatenate','Extracting K-Space','GRAPPA calibration','Partial Fourier','ESPReSSo','Trafo','Log barrier','Newton','Proximal Average', 'ADMM'})))
            if(prop.openPool)
                fprintf([repmat('\b',1,length(name)+1)]);
            else
                fprintf([repmat('\b',1,length(prop.lastOut))]);
            end
        end

    elseif(value == 0)
        % init step
        prop.maxvals(strcmp(prop.disp.names,name)) = maxvalue;
        if(strcmp(name,'FOCUSS'))
%             prop.lastOut = sprintf('%s %3d%%',name,value);
            prop.lastVal = 0;
            fprintf('%s [%s]\n%s [', name, repmat('- ',1,25),repmat(' ',1,length(name)));
        elseif(strcmp(name,'CG'))
%             prop.lastOut = sprintf('%s\t\t%s %3d%%\n',prop.lastOut,name,value);
%             if(~prop.openPool)
%                 fprintf('%s',prop.lastOut);
%             else
%                 prop.lastOut = '';
%             end
            prop.lastVal = 0;
            fprintf('%s [%s]\n%s [', name, repmat('- ',1,25),repmat(' ',1,length(name)));
        elseif(any(strcmp(name,{'Extracting K-Space','GRAPPA calibration','Partial Fourier','ESPReSSo','Trafo','Log barrier','Newton','Proximal Average', 'ADMM'})))
%             if(prop.openPool)
%                 prop.lastOut = sprintf('%s\n',name);
%             else
%                 prop.lastOut = sprintf('%s %3d%%\n',name,value);
%             end
%             fprintf('%s',prop.lastOut);
            prop.lastVal = 0;
            fprintf('%s [%s]\n%s [', name, repmat('- ',1,25),repmat(' ',1,length(name)));
        end

    else
        if(~prop.openPool)
            switch name
                case {'Slices','Channels','Repetitions','POCS','Time','Frequency','Averages'}
                    outstring = sprintf('%s %d/%d\n', name, value*prop.maxvals(strcmp(prop.disp.names,name)), prop.maxvals(strcmp(prop.disp.names,name)));
                    delString = 0;

                case {'Extracting K-Space','GRAPPA calibration','Partial Fourier','ESPReSSo','Trafo','Log barrier','Newton','Line Search','Proximal Average', 'ADMM'}
%                     outstring = sprintf('%s %3d%%\n', name, value*100);
%                     delString = length(prop.lastOut);

                    value = round(value*100);
                    if(mod(value,2) ~= 0)
                        value = value-1;
                    end
                    value = value/2;

                    if(value >= 50)
                        outstring = sprintf('*]\n');
                    else
                        if(value == prop.lastVal)
                            outstring = '';
                        else
                            outstring = '*';
                        end
                    end
                    prop.lastVal = value;
                    delString = 0;
                case {'FOCUSS', 'CG'}

%                     if(strcmp(name,'FOCUSS'))
%                         outstring = sprintf('%s %3.0f%%%s',name,value*100,prop.lastOut(12:end));
%                     else
%                         outstring = sprintf('%s\t\t%s %3.0f%%\n', prop.lastOut(1:11),name,value*100);
%                     end
%
%                     if(~isempty(prop.lastOut))
%                         delString = length(prop.lastOut);
%                     else
%                         delString = 0;
%                     end
                    value = round(value*100);
                    if(mod(value,2) ~= 0)
                        value = value-1;
                    end
                    value = value/2;

                    if(value >= 50)
                        outstring = sprintf('*]\n');
                    else
                        if(value == prop.lastVal)
                            outstring = '';
                        else
                            outstring = '*';
                        end
                    end
                    prop.lastVal = value;
                    delString = 0;

                case 'SENSE - Slice'
                    outstring = sprintf('%s %d/%d\n', name, value*prop.maxvals(strcmp(prop.disp.names,name)), prop.maxvals(strcmp(prop.disp.names,name)));
                    delString = 0;

                case 'SENSE - Time'
                    outstring = sprintf('%s %d/%d\n', name, value*prop.maxvals(strcmp(prop.disp.names,name)), prop.maxvals(strcmp(prop.disp.names,name)));

                    if(~isempty(prop.lastOut))
                        delString = length(prop.lastOut);
                    else
                        delString = 0;
                    end

                case {'SENSE - Kernel', 'SENSE - Concatenate'}
                    outstring = sprintf('%s %3.0f%%\n',name,value);
                    if(~isempty(prop.lastOut))
                        delString = length(prop.lastOut);
                    else
                        delString = 0;
                    end

                otherwise
                    error('dispProgress(): Undetermined display name');
            end

            prop.lastOut = outstring;

            fprintf([repmat('\b',1,delString),'%s'],outstring);
        end
    end
end

end


function y = cvx_readlevel( x )

global cvx___
s = size( x.basis_ );
[ r, c ] = find( x.basis_ );
y = max( sparse( r, c, cvx___.readonly( r ), s(1), s(2) ), [], 1 );
y = cvx_reshape( y, x.size_ );

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


%SingleCell
%
% Author: Derek Macklin, macklin@stanford.edu
% Author: Jonathan Karr, jkarr@stanford.edu
% Affiliation: Covert Lab, Department of Bioengineering, Stanford University
% Last Updated: 7/6/2011
classdef SingleCell
    methods (Static = true)
        function run(simBatchDir, simNum, fileName, methodsToRun)
            import edu.stanford.covert.cell.sim.analysis.SingleCell;
            import edu.stanford.covert.cell.sim.util.SimulationDiskUtil;
            import edu.stanford.covert.cell.sim.util.PlotUtil;

            %options
            if nargin < 1 || isempty(simBatchDir)
                simBatchDir = SimulationDiskUtil.getLatestSimulationGroup();
            end

            if nargin < 2 || isempty(simNum)
                simNum = 1;
            end

            %simulation
            [~, ~, sim] = SimulationDiskUtil.getSimulation([simBatchDir filesep num2str(simNum)]);

            %evaluate each method and optionally save at the result as
            %pdf files
            metaData = meta.class.fromName('edu.stanford.covert.cell.sim.analysis.SingleCell');
            for i = 1:numel(metaData.Methods)
                %only plot methods matching the signature
                %  plotFcn(sim, simBatchDir, simNum, figHandle)
                if ...
                        numel(metaData.Methods{i}.InputNames) < 4 || ~isequal(metaData.Methods{i}.InputNames(1:4), {'sim'; 'simBatchDir'; 'simNum'; 'figHandle'}) || ...
                        numel(metaData.Methods{i}.OutputNames) < 1 || ~isequal(metaData.Methods{i}.OutputNames(1), {'figData'})
                    continue;
                end

                %get method name
                methodName = metaData.Methods{i}.Name;
                MethodName = [upper(methodName(1)) methodName(2:end)];
                if nargin >= 4 && ~ismember(metaData.Methods{i}.Name, methodsToRun)
                    continue;
                end

                %run plot method
                [~, figHandle] = edu.stanford.covert.cell.sim.util.PlotUtil.newAxesHandle();
                try
                    argout = cell(size(metaData.Methods{i}.OutputNames));
                    [argout{:}] = SingleCell.(methodName)(sim, simBatchDir, simNum, figHandle);

                    % save plot
                    if nargin >= 3
                        figData = argout{1}; %#ok<NASGU>
                        save([fileName '-' MethodName '.mat'], '-struct', 'figData');

                        orient(figHandle, 'portrait');
                        saveas(figHandle, [fileName '-' MethodName '.pdf']);
                    end

                    % save table
                    if numel(argout) > 1
                        if nargin >= 3
                            PrintUtil.printToFile(argout{2}, argout{3}, [fileName '-' MethodName '.xls'], MethodName);
                        else
                            PrintUtil.printToStdIO(argout{2}, argout{3});
                        end
                    end
                catch exception
                    warning('WholeCell:warning', 'Unable to make %s plot:\n%s', methodName, exception.getReport());
                end

                if nargin >= 2
                    close(figHandle);
                    clear figHandle;
                end
                clear argout figData;
            end
        end

        function figData = growth(sim, simBatchDir, simNum, figHandle)
            import edu.stanford.covert.cell.sim.analysis.ChromosomeSpaceTimePlot;
            import edu.stanford.covert.cell.sim.analysis.SingleCell;
            import edu.stanford.covert.cell.sim.util.PlotUtil;

            %% get data
            [time, mass, rnas, proteins, ...
                dntps, ntps, aminoAcids, ...
                growth, reactionFlux, ...
                enzymeComplex, enzymeMonomer, enzymeRNA, enzymeGene, ...
                ploidy, superhelicalDensity] = ...
                SingleCell.calcGrowthData(sim, simBatchDir, simNum);

            %% layout figure, plot data
            clf(figHandle);

            options = struct();
            options.titleStr = {'Composition'; 'Growth'; 'Organization'};
            options.position = [0.12 0.52 0.87 0.4];
            options.xdata = time;
            options.ydata = {{
                permute(mass, [1 3 2 4])
                permute(rnas, [1 3 2 4])
                permute(proteins, [1 3 2 4])
                permute(dntps, [1 3 2 4])
                permute(ntps, [1 3 2 4])
                permute(aminoAcids, [1 3 2 4])
                }
                {
                permute(growth, [1 3 2 4])
                permute(reactionFlux, [1 3 2 4])
                permute(enzymeComplex, [1 3 2 4])
                permute(enzymeMonomer, [1 3 2 4])
                permute(enzymeRNA, [1 3 2 4])
                permute(enzymeGene, [1 3 2 4])
                }
                {
                permute(ploidy, [1 3 2 4])
                permute(superhelicalDensity, [1 3 2 4])
                []
                }};
            options.ylabelStr = {{
                'Mass (fg)'
                'RNAs'
                'Proteins'
                'dNTPs'
                'NTPs'
                {'Amino' 'acids'}
                }
                {
                {'Growth' '(fg h^{-1})'}
                {sprintf('%s', rxnId) 'flux' '(MHz)'}
                {sprintf('%s', rxnId) 'complex'}
                {sprintf('%s', rxnId) 'monomer'}
                {sprintf('%s', rxnId) 'mRNA'}
                sprintf('{\\it %s}', rxnId)
                }
                {
                {'Copy', 'number'}
                {'Super-' 'helicity'}
                {'Polymerase' 'position'}
                }
                };
            axesHandles = PlotUtil.multiElementPlot(figHandle, {3 * ones(6, 1); 3 * ones(6, 1); [3 3 4*3+(4-1)*1]}, time([1 end])', ...
                options);
            ChromosomeSpaceTimePlot.plotSpaceTime(axesHandles{3}(3), simBatchDir, simNum, [], false);

            clear options;

            %% Format Y-axis
            PlotUtil.labelSubplots([axesHandles{1}(1); axesHandles{2}(1); axesHandles{3}(1)]);

            %% collect data
            figData = struct;
            figData.time = time;
            figData.mass = mass;
            figData.rnas = rnas;
            figData.proteins = proteins;
            figData.dntps = dntps;
            figData.ntps = ntps;
            figData.aminoAcids = aminoAcids;
            figData.growth = growth;
            figData.reactionFlux = reactionFlux;
            figData.enzymeComplex = enzymeComplex;
            figData.enzymeMonomer = enzymeMonomer;
            figData.enzymeRNA = enzymeRNA;
            figData.enzymeGene = enzymeGene;
            figData.ploidy = ploidy;
            figData.superhelicalDensity = superhelicalDensity;
        end

        function [time, mass, rnas, proteins, ...
                dntps, ntps, aminoAcids, ...
                growth, reactionFlux, ...
                enzymeComplex, enzymeMonomer, enzymeRNA, enzymeGene, ...
                ploidy, superhelicalDensity] = ...
                calcGrowthData(sim, simBatchDir, simNum, rxnId)

            import edu.stanford.covert.cell.sim.util.MacromoleculeUtil;
            import edu.stanford.covert.cell.sim.util.SimulationEnsemble;
            import edu.stanford.covert.cell.sim.util.SimulationDiskUtil;
            import edu.stanford.covert.cell.sim.analysis.CellOverview;
            import edu.stanford.covert.util.ConstantUtil;

            comp = sim.compartment;
            g = sim.gene;

            c = sim.state('Chromosome');
            m = sim.state('Metabolite');
            rna = sim.state('Rna');
            pm = sim.state('ProteinMonomer');
            pc = sim.state('ProteinComplex');

            sc = sim.process('DNASupercoiling');
            met = sim.process('Metabolism');

            %% get data
            stateNames = {
                'mass'              'Mass'
                'ploidy'            {'Chromosome' 'Copy Number'}
                'rnas'              'RNA'
                'proteins'          'Proteins'
                'lipids'            'Lipids'
                'growth_rate'       'Growth'
                'amino_acids'       {'Amino' 'Acids'}
                'ntps'              'NTPs'
                };
            ensemble = SimulationEnsemble(simBatchDir, stateNames, [], simNum);

            time = ensemble.stateData.time / 3600;
            mass = ensemble.stateData.values(ensemble.getPropertyIndices('mass'), :, :, :) * sim.state('Mass').cellInitialDryWeight / (1-sim.state('Mass').fractionWetWeight) * 1e15;
            ploidy = ensemble.stateData.values(ensemble.getPropertyIndices('ploidy'), :, :, :);
            rnas = ensemble.stateData.values(ensemble.getPropertyIndices('rnas'), :, :, :);
            proteins = ensemble.stateData.values(ensemble.getPropertyIndices('proteins'), :, :, :);
            %lipids = ensemble.stateData.values(ensemble.getPropertyIndices('lipids'), :, :, :);
            growth = ensemble.stateData.values(ensemble.getPropertyIndices('growth_rate'), :, :, :) * 3600 * sim.state('Mass').cellInitialDryWeight / (1-sim.state('Mass').fractionWetWeight)  * 1e15;

            clear ensemble;

            if nargin < 4
                rxnId = 'AckA';
            end
            rxnIdx = met.reactionIndexs(rxnId);
            enzId = met.enzymeWholeCellModelIDs{met.reactionCatalysisMatrix(rxnIdx, :) ~= 0};
            [~, ~, ~, ~, ~, ...
                geneIdxs, ~, ~, ~, ...
                ~, ~, ~, ~, ...
                matureRnaIdxs, ~, ~, ~, ...
                monomerIdxs, ~, ~, ~, ...
                complexIdxs, ~, ~, ~] = ...
                MacromoleculeUtil.getMacromoleculeIndexsIDsNames(enzId, sim);
            stateNames = {
                'Metabolite'        'counts'              ':'  ':'
                'MetabolicReaction' 'fluxs'               rxnIdx ':'
                'Chromosome'        'polymerizedRegions'  ':'  ':'
                'Chromosome'        'linkingNumbers'       ':'  ':'
                'Rna'               'counts' rna.matureIndexs(matureRnaIdxs)         comp.cytosolIndexs
                'ProteinMonomer'    'counts' [pm.matureIndexs([monomerIdxs; sc.enzymeGlobalIndexs(sc.enzymeIndexs_topoI)]); pm.boundIndexs([monomerIdxs; sc.enzymeGlobalIndexs(sc.enzymeIndexs_topoI)])] comp.cytosolIndexs
                'ProteinComplex'    'counts' [pc.matureIndexs([complexIdxs; sc.enzymeGlobalIndexs([sc.enzymeIndexs_gyrase; sc.enzymeIndexs_topoIV])]); pc.boundIndexs([complexIdxs; sc.enzymeGlobalIndexs([sc.enzymeIndexs_gyrase; sc.enzymeIndexs_topoIV])])] comp.cytosolIndexs
                };
            states = SimulationEnsemble.load(simBatchDir, stateNames, [], [], 1, 'extract', simNum);
            tmp = full(states.Metabolite.counts);
            %smallMolecules = sum(sum(tmp(setdiff(1:end, m.lipidIndexs), [comp.cytosolIndexs; comp.membraneIndexs], :), 2), 1);
            dntps = cat(3, NaN(4, 1), tmp(m.dntpIndexs, 1, :));
            ntps = cat(3, NaN(4, 1), tmp(m.ntpIndexs, 1, :));
            %nmps = tmp(m.nmpIndexs(1:20), comp.cytosolIndexs, :);
            aminoAcids = cat(3, NaN(20, 1), tmp(m.aminoAcidIndexs(1:20), 1, :));

            enzymeGene = cat(3, NaN(size(geneIdxs)), max(1, permute(MacromoleculeUtil.extractCopyNumberTimeCourse(c, states.Chromosome.polymerizedRegions, ...
                g.startCoordinates(geneIdxs), g.strands(geneIdxs), g.lengths(geneIdxs)), [1 3 2 4])));
            enzymeRNA = cat(3, NaN(size(matureRnaIdxs)), states.Rna.counts);
            enzymeMonomer = cat(3, NaN(size(monomerIdxs)), states.ProteinMonomer.counts(1:numel(monomerIdxs), 1, :, :));
            enzymeComplex = cat(3, NaN(size(complexIdxs)), states.ProteinComplex.counts(1:numel(complexIdxs), 1, :, :));
            reactionFlux = cat(3, NaN, states.MetabolicReaction.fluxs * 3600 * 1e-6);

            lk0 = full(sum(sum(states.Chromosome.polymerizedRegions, 2), 1)) / c.relaxedBasesPerTurn;
            superhelicalDensity = cat(3, NaN, (full(sum(sum(states.Chromosome.linkingNumbers, 2), 1)) - lk0) ./ lk0);
            %gyrase = ...
            %    + states.ProteinComplex.counts(end/2-1, 1, :, :) ...
            %    + states.ProteinComplex.counts(end-1, 1, :, :);
            %topoI = ...
            %    + states.ProteinMonomer.counts(end/2, 1, :, :) ...
            %    + states.ProteinMonomer.counts(end, 1, :, :);
            %topoIV = ...
            %    + states.ProteinComplex.counts(end/2, 1, :, :) ...
            %    + states.ProteinComplex.counts(end, 1, :, :);

            clear tmp states lk0;

            %% collect data
            figData = struct;
            figData.time = time;
            figData.mass = mass;
            figData.rnas = rnas;
            figData.proteins = proteins;
            figData.dntps = dntps;
            figData.ntps = ntps;
            figData.aminoAcids = aminoAcids;
            figData.growth = growth;
            figData.reactionFlux = reactionFlux;
            figData.enzymeComplex = enzymeComplex;
            figData.enzymeMonomer = enzymeMonomer;
            figData.enzymeRNA = enzymeRNA;
            figData.enzymeGene = enzymeGene;
            figData.ploidy = ploidy;
            figData.superhelicalDensity = superhelicalDensity;
        end

        function figData = mass(sim, simBatchDir, simNum, figHandle, normalized)
            import edu.stanford.covert.cell.sim.util.PlotUtil;
            import edu.stanford.covert.cell.sim.util.SimulationEnsemble;

            comp = sim.compartment;

            %% get data
            stateNames = {
                'Time' 'values'       ':' ':'
                'Mass' 'waterWt'      ':' comp.cellularIndexs(:)'
                'Mass' 'dnaWt'        ':' '-sum'
                'Mass' 'rnaWt'        ':' '-sum'
                'Mass' 'proteinWt'    ':' '-sum'
                'Mass' 'metaboliteWt' ':' [comp.cytosolIndexs; comp.membraneIndexs]
                };
            states = SimulationEnsemble.load(simBatchDir, stateNames, [], [], 1, 'extract', simNum);

            %% layout figure, plot data
            clf(figHandle);

            options = struct();
            options.titleStr = 'Cell Mass';

            options.plotFunc = @PlotUtil.plotStackedArea;
            axesHandle = PlotUtil.multiElementPlot(figHandle, 50, states.Time.values([1 end]), options);

            ydata = [
                permute(states.Mass.waterWt, [1 3 2])
                permute(states.Mass.proteinWt, [1 3 2])
                permute(states.Mass.dnaWt, [1 3 2])
                permute(states.Mass.metaboliteWt(:, 2, :), [1 3 2])
                permute(states.Mass.metaboliteWt(:, 1, :), [1 3 2])
                permute(states.Mass.rnaWt, [1 3 2])
                ] * 1e15;
            if nargin < 5 || ~normalized
                h = PlotUtil.plotStackedArea(axesHandle, permute(states.Time.values, [1 3 2]), ydata);
                ylabel(axesHandle, 'Mass (fg)');
                ylim(axesHandle, [0 max(sum(ydata, 1))]);
            else
                h = PlotUtil.plotNormalizedStackedArea(axesHandle, permute(states.Time.values, [1 3 2]), ydata);
                ylabel(axesHandle, 'Percent Mass');
                ylim(axesHandle, [0 100]);
            end
            legend(h, {'Water', 'Protein', 'DNA', 'Membrane', 'Metabolite', 'RNA'}, 'Location', 'SouthEast');

            PlotUtil.offsetYAxes(axesHandle, 0.02);

            clear ydata;

            %% collect data
            figData = struct;
            figData.time = states.Time.values;
            figData.waterWt = states.Mass.waterWt;
            figData.proteinWt = states.Mass.proteinWt;
            figData.dnaWt = states.Mass.dnaWt;
            figData.metaboliteWt = states.Mass.metaboliteWt;
            figData.rnaWt = states.Mass.rnaWt;
        end

        function figData = massNormalized(sim, simBatchDir, simNum, figHandle)
            import edu.stanford.covert.cell.sim.analysis.SingleCell;

            figData = SingleCell.mass(sim, simBatchDir, simNum, figHandle, true);
        end

        function figData = metabolites(sim, simBatchDir, simNum, figHandle, normalized)
            import edu.stanford.covert.cell.sim.util.PlotUtil;
            import edu.stanford.covert.cell.sim.util.SimulationEnsemble;
            import edu.stanford.covert.util.ConstantUtil;

            comp = sim.compartment;
            m = sim.state('Metabolite');
            metIdxs = [
                m.ntpIndexs
                m.ndpIndexs
                m.nmpIndexs
                m.dntpIndexs
                m.aminoAcidIndexs
                m.phosphateIndexs
                m.diphosphateIndexs
                m.hydrogenIndexs
                ];

            %% get data
            stateNames = {
                'Time'       'values'  ':'      ':'
                'Geometry'   'volume'  ':'      ':'
                'Metabolite' 'counts'  metIdxs  comp.cytosolIndexs
                };
            states = SimulationEnsemble.load(simBatchDir, stateNames, [], [], 1, 'extract', simNum);
            time = permute(states.Time.values, [1 3 2]) / 3600;

            states.Metabolite.counts = ...
                states.Metabolite.counts ./ ...
                states.Geometry.volume(ones(size(metIdxs)), :, :) / ...
                ConstantUtil.nAvogadro * 1000;

            ntps = permute(states.Metabolite.counts(1:4, :, :), [1 3 2]);
            ndps = permute(states.Metabolite.counts(5:8, :, :), [1 3 2]);
            nmps = permute(states.Metabolite.counts(9:12, :, :), [1 3 2]);
            dntps = permute(states.Metabolite.counts(13:16, :, :), [1 3 2]);
            aas = permute(states.Metabolite.counts(17:37, :, :), [1 3 2]);
            others = permute(states.Metabolite.counts(38:40, :, :), [1 3 2]);

            %% layout figure
            clf(figHandle);

            axesHandles = PlotUtil.multiElementPlot(figHandle, {10 * ones(3, 1) 10 * ones(3, 1)}, time([1 end]));

            %% plot data
            if nargin >= 5 && normalized
                plotFcn = @PlotUtil.plotNormalizedStackedArea;
            else
                plotFcn = @PlotUtil.plotStackedArea;
            end

            %ntp
            axesHandle = axesHandles{1}(1);
            h = plotFcn(axesHandle, time, ntps);
            legend(h, m.wholeCellModelIDs(m.ntpIndexs), 'Location', 'SouthEast');

            %ndp
            axesHandle = axesHandles{1}(2);
            h = plotFcn(axesHandle, time, ndps);
            legend(h, m.wholeCellModelIDs(m.ndpIndexs), 'Location', 'SouthEast');

            %nmp
            axesHandle = axesHandles{1}(3);
            h = plotFcn(axesHandle, time, nmps);
            legend(h, m.wholeCellModelIDs(m.nmpIndexs), 'Location', 'SouthEast');

            %dNTP
            axesHandle = axesHandles{2}(1);
            h = plotFcn(axesHandle, time, dntps);
            legend(h, m.wholeCellModelIDs(m.dntpIndexs), 'Location', 'SouthEast');

            %AA
            axesHandle = axesHandles{2}(2);
            plotFcn(axesHandle, time, aas);

            %other
            axesHandle = axesHandles{2}(3);
            h = plotFcn(axesHandle, time, others);
            legend(h, m.wholeCellModelIDs([m.phosphateIndexs; m.diphosphateIndexs; m.hydrogenIndexs]), 'Location', 'SouthEast');

            %labels
            for i = 1:numel(axesHandles)
                for j = 1:numel(axesHandles{i})
                    if nargin >= 5 && normalized
                        ylabel(axesHandles{i}(j), {'Relative' 'Copy Number'});
                        ylim(axesHandles{i}(j), [0 100]);
                    else
                        ylabel(axesHandles{i}(j), 'Concentration (mM)');
                    end
                end
            end

            %% ylabels
            PlotUtil.alignYAxesLabels(axesHandles);
            PlotUtil.offsetYAxes(axesHandles, 0.02);

            %% collect data
            figData = struct;
            figData.time = time;
            figData.ntps = ntps;
            figData.ndps = ndps;
            figData.nmps = nmps;
            figData.dntps = dntps;
            figData.aas = aas;
            figData.others = others;
        end

        function figData = metabolitesNormalized(sim, simBatchDir, simNum, figHandle)
            import edu.stanford.covert.cell.sim.analysis.SingleCell;

            figData = SingleCell.metabolites(sim, simBatchDir, simNum, figHandle, true);
        end

        function figData = ribosomes(sim, simBatchDir, simNum, figHandle, useGenomicCoordinates)
            import edu.stanford.covert.cell.sim.util.PlotUtil;
            import edu.stanford.covert.cell.sim.util.SimulationEnsemble;

            %get constants
            g = sim.gene;
            c = sim.state('Chromosome');
            rib = sim.state('Ribosome');

            if nargin >= 5 && useGenomicCoordinates
                startCoordinates = g.startCoordinates(g.mRNAIndexs);
                lengths = g.lengths(g.mRNAIndexs);
                strands = g.strands(g.mRNAIndexs);
            else
                startCoordinates = cumsum(g.lengths(g.mRNAIndexs)+50);
                lengths = g.lengths(g.mRNAIndexs);
                strands = ones(size(g.mRNAIndexs));
            end

            %get data
            stateNames = {
                'Time'      'values'
                'Ribosome'  'states'
                'Ribosome'  'boundMRNAs'
                'Ribosome'  'mRNAPositions'
                };
            states = SimulationEnsemble.load(simBatchDir, stateNames, [], [], 1, 'extract', simNum);
            time = permute(states.Time.values, [1 3 2]) / 3600;
            ribStates = permute(states.Ribosome.states, [1 3 2]);
            boundMRNAs = permute(states.Ribosome.boundMRNAs, [1 3 2]);
            mRNAPos = permute(states.Ribosome.mRNAPositions, [1 3 2]);

            %layout figure
            clf(figHandle);
            options = struct;
            axesHandle = PlotUtil.multiElementPlot(figHandle, 30, time([1 end]), options);

            %plot data
            colorOrder = PlotUtil.getRedGreenColorOrder(randperm(size(ribStates, 1)));
            for i = 1:size(ribStates, 1)
                pos = NaN(size(time));
                tfs = ribStates(i, :) == rib.activeValue & mRNAPos(i, :) > 0;
                pos(tfs) = ...
                    + startCoordinates(boundMRNAs(i, tfs)) ...
                    + (strands(boundMRNAs(i, tfs)) == 2) .* (lengths(boundMRNAs(i, tfs)) - 1) ...
                    + (2 * (2 - strands(boundMRNAs(i, tfs))) - 1) .* (3 * mRNAPos(i, tfs)' - 1);
                h = plot(axesHandle, time, pos);
                set(h, 'Color', colorOrder(i, :));
            end

            if nargin >= 5 && useGenomicCoordinates
                ylabel(axesHandle, 'Ribosome Position');
                ylim(axesHandle, [1 c.sequenceLen]);
                set(axesHandle, ...
                    'YTick', [1 c.terCPosition c.sequenceLen], ...
                    'YTickLabel', {'OriC' 'TerC' 'Oric'});
                PlotUtil.offsetYAxes(axesHandle, 0.02);
            else
                tmp = xlim(axesHandle);
                x = tmp(1) - 0.02 * range(tmp);
                xlim(axesHandle, [x tmp(2)]);
                ylim(axesHandle, [min(startCoordinates) max(startCoordinates + lengths - 1)]);
                line(x * ones(3 * numel(startCoordinates), 1), ...
                    reshape([startCoordinates  startCoordinates + lengths - 1  NaN(size(startCoordinates))]', [], 1), ...
                    'Parent', axesHandle, 'Color', 'k')
                set(axesHandle, 'YTick', [], 'visible', 'off');
                text(tmp(1) - 0.03 * range(tmp), mean(ylim(axesHandle)), 'Ribosome Position', ...
                    'Parent', axesHandle, ...
                    'rotation', 90, ...
                    'HorizontalAlignment', 'center', ...
                    'VerticalAlignment', 'bottom');
            end

            %% collect data
            figData = struct;
            figData.time = time;
            figData.ribStates = ribStates;
            figData.boundMRNAs = boundMRNAs;
            figData.mRNAPos = mRNAPos;
        end

        function figData = ribosomesGenomicCoordinates(sim, simBatchDir, simNum, figHandle)
            import edu.stanford.covert.cell.sim.analysis.SingleCell;

            figData = SingleCell.ribosomes(sim, simBatchDir, simNum, figHandle, true);
        end
    end
end


function aedat = ReorientatePolarity(aedat, transpose, flipX, flipY)

%{
For the frame data, if present, apply transpose, flipX and flipY operations
in that order according to the boolean inputs.
%}

dbstop if error

if ~isfield(aedat, 'data')
    disp('No data found')
    return
end
if ~isfield(aedat.data, 'polarity')
    disp('No polarity data to reorientate')
    return
end
if transpose
    temp                    = aedat.data.polarity.x;
    aedat.data.polarity.x   = aedat.data.polarity.y;
    aedat.data.polarity.y   = temp;
end

if flipX
    aedat.data.polarity.x   = aedat.info.deviceAddressSpace(1) - aedat.data.polarity.x - 1;
end

if flipY
    aedat.data.polarity.y   = aedat.info.deviceAddressSpace(2) - aedat.data.polarity.y - 1;
end


function DupEdit(topH)

% DupEdit(topH)
%
% Duplicate all the editable field contents in the present scan
% forward into all subsequent session fields. Input topH is the
% handle of the top-level edit figure.
%
% DBR 4/99
% DAR 1/22/07 - edited for compatibility with PC matlab 7.1

% Unpack the user data from the edit figure
uiData = get(topH, 'UserData');

iS = uiData.iScan; % Present scan index
nScans = length(uiData.session.functionals); % Number of scans in session

if iS == nScans, return; end % Nothing to copy
nFields = length(uiData.scanData); % Number of scan edit fields
for iScan=iS+1:nScans
    for iField=1:nFields
        editFlag = uiData.scanData(iField).edit;
        if editFlag
            hContent = uiData.scanData(iField).handle;
            fName = uiData.scanData(iField).field;
            origValue = uiData.original.functionals(iScan).(fName);
            curValue = get(hContent,'string');
            if isnumeric(origValue)
                curValue = str2num(curValue);
            end

            label = uiData.scanData(iField).label;
            uiData.session.functionals(iScan).(fName) = curValue;
        end
    end
end
set(topH, 'UserData', uiData);