function functionStruct = agilentMSO6014A(visaRsrcString)

iObj = visa('agilent',visaRsrcString);
set(iObj,'InputBufferSize',2048);
scopeObj = icdevice('AGNMSO6014A',iObj);
connect(scopeObj);
fprintf(scopeObj.Interface,'*RST');
functionStruct.setTimeBase = @setTimeBase;
functionStruct. getTimeBase = @getTimeBase;
functionStruct.setVerticalScale = @setVerticalScale;
functionStruct.getVerticalScale = @getVerticalScale;
functionStruct.getWaveform = @getWaveform;
functionStruct.autoscale = @autoscale;
functionStruct.close = @close;

    function setTimeBase(timebase)
        set(scopeObj,'timebase',timebase);
    end

    function timebase = getTimeBase
        timebase = get(scopeObj,'timebase');
    end

    function setVerticalScale(scale)
        set(scopeObj,'verticalscale',scale);
    end

    function scale = getVerticalScale
        scale = get(scopeObj,'verticalscale');
    end

    function [yData xData] = getWaveform
        [yData xData] = invoke(scopeObj,'getwaveform');
    end

    function autoscale
        invoke(scopeObj,'autoscale');
    end

    function close
        disconnect(scopeObj);
        delete(scopeObj);
        delete(iObj);
    end

end


function hline(y, varargin)

% HLINE plot a horizontal line in the current graph

abc = axis;
y = [y y];
x = abc([1 2]);
if length(varargin)==1
  varargin = {'color', varargin{1}};
end
h = line(x, y);
set(h, varargin{:});


function test_suite = test_hierprior

%   Run specific demo, save values and compare the results to the expected.
%   Works for both xUnit Test Framework package by Steve Eddins and for
%   the built-in Unit Testing Framework (as of Matlab version 2013b).
%
%   See also
%     TEST_ALL, DEMO_HIERPRIOR
%
% Copyright (c) 2011-2012 Ville Tolvanen
% Copyright (c) 2014 Tuomas Sivula

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

  % Check which package to use
  if exist('initTestSuite', 'file')
    initTestSuite_path = which('initTestSuite');
  else
    initTestSuite_path = '';
  end
  if ~isempty(initTestSuite_path) && ...
     exist([initTestSuite_path(1:end-15) 'runtests'], 'file')
    % xUnit package
    initTestSuite;
  else
    % Built-in package
    % Use all functions except the @setup
    tests = localfunctions;
    tests = tests(~cellfun(@(x)strcmp(func2str(x),'setup'),tests));
    test_suite = functiontests(tests);
  end
end

% -------------
%     Tests
% -------------

function testRunDemo(testCase)
  % Run the correspondin demo and save the values. Note this test has to
  % be run at lest once before the other test may succeed.
  rundemo(getName())
end

function testDerivatesRegression(testCase)
  verifyVarsEqual(testCase, getName(), {'derivs'}, @(x)x{1}, ...
    'RelTolElement', 0.05, 'RelTolRange', 0.01, 'AbsTol', 0.4)
  verifyVarsEqual(testCase, getName(), {'derivs'}, @(x)x{2}, ...
    'RelTolElement', 0.05, 'RelTolRange', 0.01, 'AbsTol', 0.4)
end

function testDerivatesLaplace(testCase)
  verifyVarsEqual(testCase, getName(), {'derivs'}, @(x)x{3}, ...
    'AbsTol', 1e-5)
  verifyVarsEqual(testCase, getName(), {'derivs'}, @(x)x{4}, ...
    'AbsTol', 1e-5)
end

function testDerivatesEP(testCase)
  verifyVarsEqual(testCase, getName(), {'derivs'}, @(x)x{5}, ...
    'AbsTol', 1e-5)
  verifyVarsEqual(testCase, getName(), {'derivs'}, @(x)x{6}, ...
    'AbsTol', 1e-5)
end

% ------------------------
%     Helper functions
% ------------------------

function testCase = setup
  % Helper function to suply empty array into variable testCase as an
  % argument for each test function, if using xUnit package. Not to be
  % used with built-in test framework.
  testCase = [];
end

function name = getName
  % Helperfunction that returns the name of the demo, e.g. 'binomial1'.
  name = mfilename;
  name = name(6:end);
end


function varargout = mode(varargin)
% Allows inputs to be char
ic = ischar(varargin{1});
if ic
    varargin{1} = double(varargin{1});
end
[varargout{1:nargout}] = builtin('mode', varargin{:});
if ic
    varargout{1} = char(varargout{1});
    if nargout>2
        varargout{3} = cellfun(@char, varargout{3}, 'UniformOutput', false);
    end
end
end


function [success,msg] = ConvertMotr2JAABA(varargin)

success = false;
msg = {};  %#ok<NASGU>

% Parse inputs
[inmoviefile,seqindexfile,...
  intrxfile,...
  expdir,moviefilestr,trxfilestr,perframedirstr,...
  arenatype,arenacenterx,arenacentery,...
  arenaradius,arenawidth,arenaheight,...
  pxpermm,...
  dofliplr,doflipud,dotransposeimage,...
  dosoftlink,frameinterval,...
  sex,roi2] = myparse(varargin,...
  'inmoviefile','','seqindexfile','',...
  'intrxfile','',...
  'expdir','','moviefilestr','movie.ufmf','trxfilestr','trx.mat','perframedirstr','perframe',...
  'arenatype','None','arenacenterx',0,'arenacentery',0,...
  'arenaradius',123,'arenawidth',123,'arenaheight',123,...
  'pxpermm',1,...
  'fliplr',false,'flipud',false,'dotransposeimage',false,...
  'dosoftlink',false,...
  'frameinterval',[],...
  'sex',{},'roi2',[]);  %#ok<NASGU,ASGLU>

% Check that required inputs are given
if isempty(intrxfile),
  msg = 'Input trx mat file is empty';
  return
end

% Figure out whether it's a raw Motr _tracks.mat file or a Catalytic .ctc file by looking
% for the critical fields
td = load('-mat',intrxfile);
if isfield(td,'astrctTrackers') ,
    [success,msg] = ConvertRawMotr2JAABA(varargin{:});
elseif isfield(td,'trx') ,
    [success,msg] = ConvertMotrCtc2JAABA(varargin{:});
else
    msg='Input trx file doesn''t have astrctTrackers or trx field';
    return
end

end


% readneurone()  -  Read data from a Mega NeurOne device and arrange it
%                   into a struct.
%
% Usage:    >> NEURONE = readneurone(dataPath, sessionPhaseNumber, chans)
%
% =======================================================================
% Inputs:
%   dataPath              - Path to directory containing NeurOne data
%                           from a single measurement.
%
% Optional input arguments:
%   sessionPhaseNumber    - Defines which session phase will be read.
%                           Default value for sessionPhaseNumber is 1.
%   chans                 - Defines which channels will be read. The
%                           channel numbers have to be strings containing
%                           numeric values between 1 and the total number
%                           of channels. In addition, they are arranged in
%                           vector form without brackets. For example,
%                           if the total number of channels is 64, the
%                           'chans' input argument can be '1,6,3,7' or
%                           '1:12'. The default value for chans is an empty
%                           string which indicates that all channels will
%                           be read. The channel numbers can be arranged
%                           in a completely random order.
%
% =======================================================================
% Outputs:
%       NEURONE is a struct with the same fields as a standard EEG
%       structure under EEGLAB (see eeg_checkset.m).
%
% Used fields are:
%   NEURONE.filename
%   NEURONE.setname
%   NEURONE.srate
%   NEURONE.pnts
%   NEURONE.xmin
%   NEURONE.xmax
%   NEURONE.filepath
%   NEURONE.trials
%   NEURONE.nbchan
%   NEURONE.data
%   NEURONE.ref
%   NEURONE.times
%   NEURONE.comments
%   NEURONE.etc
%   NEURONE.subject
%   NEURONE.event (a struct containing all event data)
%   NEURONE.eventdescription
%   NEURONE.chanlocs (will be defined by EEGLAB if channel locations exist
%                for used channel names)
%   NEURONE.chaninfo
%
% The following fields were added as empty to ensure proper working:
%   NEURONE.icawinv
%   NEURONE.icaweights
%   NEURONE.icasphere
%   NEURONE.icaact
%
%
% ========================================================================
% NOTE:
% This file is part of the NeurOne data import plugin for EEGLAB.
% ========================================================================
%
% Current version: 1.0.3.4 (2016-06-17)
% Author: Mega Electronics

function NEURONE = readneurone(dataPath, varargin)
%% Parse input arguments

p = inputParser;
p.addRequired('dataPath', @ischar);
p.addOptional('sessionPhaseNumber', 1 ,@isnumeric);
p.addOptional('chans','', @isstr);

p.parse(dataPath, varargin{:});
arglist = p.Results;

%%  Empty recording structure for output

NEURONE = {};

%% Read Session and Protocol xml-files

session = module_read_neurone_xml([dataPath 'Session.xml']);
protocol = module_read_neurone_xml([dataPath 'Protocol.xml']);

%% Obtain information from session and protocol

% Obtain sampling frequency (it is same for all channels)
srate = str2num(protocol.TableProtocol.SamplingFrequency);

% Get the total number of channels
nChannels = numel(protocol.TableInput);

NEURONE.comments = ['Protocol: ' session.TableSession.ProtocolName];
NEURONE.etc = strvcat( ['NeurOne Version: ' protocol.TableInfo.NeurOneVersion], ...
    ['Protocol File Revision: ' protocol.TableInfo.Revision], ...
    ['Session File Revision: ' session.TableInfo.Revision]);

NEURONE.subject = session.TablePerson.PersonID;

NEURONE.setname = session.TableSession.ProtocolName;

%% Check the session phase number

% Total number of sessions in recording
nSessionPhases = numel(session.TableSessionPhase);
disp(['Number of session phases: ' num2str(nSessionPhases)])
disp(['Current session phase number: ' num2str(arglist.sessionPhaseNumber)]);

% Check the validity of the sessionPhaseNumber taken from GUI
if arglist.sessionPhaseNumber>nSessionPhases
    disp('Current session phase number exceeds the total number of session phases.')
    disp('Defaulting to 1.')
    sessionPhaseNumber = 1;
elseif arglist.sessionPhaseNumber<=0
    disp('Invalid session phase number.')
    disp('Defaulting to 1.')
    sessionPhaseNumber = 1;
else
    sessionPhaseNumber = arglist.sessionPhaseNumber;
end

%% Get correct channel names and locations

% Set the channels for data acquisition
if isempty(arglist.chans)
    chans = 1:nChannels;
else
    chans = [str2num(arglist.chans)];
    chans = sort(chans); % ensure that the channels are in ascending order
end

% Check that no channel number exceeds the total number of channels
if any(chans>nChannels)
    error('One or more of the given channel numbers exceeds the total number of channels. See pop_readneurone help.')
elseif any(chans<1)
    error('One or more of the given channel numbers are invalid (zero or negative). See pop_readneurone help.')
end

% Get all channel names and corresponding input numbers
inputNumbersAll = zeros(1,nChannels);
inputNumbersAll(1) = str2num(protocol.TableInput(1).InputNumber);
channelnames = protocol.TableInput(1).Name;

for n = 2:nChannels
    inputNumbersAll(n) = str2num(protocol.TableInput(n).InputNumber);
    channelnames = char(channelnames,protocol.TableInput(n).Name);
end

channelnames = cellstr(channelnames);

% The value of the highest input number
maxInput = max(inputNumbersAll);

channelnames = channelnames';

% Sort channel names in ascending order based on their input number
for k = 1:nChannels
    ii = 1;
    while ~(any(inputNumbersAll(k)==ii)) && ii<=max(inputNumbersAll)
          ii = ii+1;
    end
    sortIndex(ii) = ii; % Store the indices for future data arrangements
    channelNames(ii) = channelnames(k);
end

inputNumbersTrue = 1:maxInput;
inputNumbersTrue = inputNumbersTrue(find(sortIndex));

% Remove empty channel names:
% Find empty cells...
emptyCells = cellfun(@isempty,channelNames);
% ...and remove them.
channelNames(emptyCells) = [];

% Take only the names of the selected channels
channelNames = channelNames(chans);

fprintf('Looking up channel locations...\n')
chanlocs=struct('labels', channelNames');
% NEURONE.chanlocs = pop_chanedit(chanlocs);
NEURONE.chanlocs = chanlocs;

%% Obtain additional information about the dataset

measurementMode = protocol.TableInput(1).AlternatingCurrent;
deviceFilter = protocol.TableInput(1).Filter;
for n = 2:nChannels
    measurementMode = char(measurementMode,protocol.TableInput(n).AlternatingCurrent);
    deviceFilter = char(deviceFilter,protocol.TableInput(n).Filter);
end

measurementMode = cellstr(measurementMode);
deviceFilter = cellstr(deviceFilter);

for k = 1:nChannels
    if strcmp(measurementMode(k),'true')
        measurementMode(k) = {'AC'};
    else
        measurementMode(k) = {'DC'};
    end
end

% Arrange measurementModes according to the input number
ii = 1;
for k = inputNumbersAll
    measurementMode(k) = measurementMode(ii);
    deviceFilter(k) = deviceFilter(ii);
    ii = ii+1;
end

measurementMode = measurementMode(inputNumbersTrue);
measurementMode = measurementMode(chans);
deviceFilter = deviceFilter(inputNumbersTrue);
deviceFilter = deviceFilter(chans);

measurementModeField = [char(channelNames(1)) ': ' char(measurementMode(1))];
deviceFilterField = [char(channelNames(1)) ': ' char(deviceFilter(1))];

for k = 2:length(chans)
    measurementModeField = strvcat(measurementModeField,[char(channelNames(k)) ': ' char(measurementMode(k))]);
    deviceFilterField = strvcat(deviceFilterField,[char(channelNames(k)) ': ' char(deviceFilter(k))]);
end

NEURONE.chaninfo.measurementMode = measurementModeField;
NEURONE.chaninfo.deviceFilter = deviceFilterField;

%% Preparing to read binary data
% If the size of the measurement in each session phase has exceeded the
% file size, the data may have been split into several files named as
% 1.bin, 2.bin etc. Usually there exists only one file: 1.bin. However, all
% this data needs to be read.

dataFiles = {}; % empty structure for data files

% Get all .bin files related to the chosen sessionPhaseNumber
sessionData = dir([dataPath num2str(sessionPhaseNumber) filesep '*.bin']);

ii = 1;
for k = 1:numel(sessionData); % total number of .bin files in current session phase data folder
    [path,filename,ext] = fileparts(sessionData(k).name);
    if ~isempty(regexpi(filename,'[123456789]'))
        dataFiles{ii,1} = [dataPath num2str(sessionPhaseNumber) filesep sessionData(k).name];
        ii = ii+1;
    end
end

%% Read NeurOne binary data and calibrate it

% Read data. The data of a specific channel is arranged in a row based on its input
% number.

data = readneuronedata(dataFiles, nChannels, chans);

% Preallocate memory to read maximum and minimum values for calibration
rawMinimum = zeros(1,maxInput);
rawMaximum = zeros(1,maxInput);
calibratedMinimum = zeros(1,maxInput);
calibratedMaximum = zeros(1,maxInput);

% Get all minimum and maximum values
for n = 1:nChannels
    rawMinimum(n) = str2num(protocol.TableInput(1,n).RangeMinimum);
    rawMaximum(n) = str2num(protocol.TableInput(1,n).RangeMaximum);
    calibratedMinimum(n) = str2num(protocol.TableInput(1,n).RangeAsCalibratedMinimum);
    calibratedMaximum(n) = str2num(protocol.TableInput(1,n).RangeAsCalibratedMaximum);
end

% Arrange them in the correct according to the input number
 ii = 1;
for k = inputNumbersAll
    rawMinimum(inputNumbersAll) = rawMinimum(ii);
    rawMaximum(inputNumbersAll) = rawMaximum(ii);
    calibratedMinimum(inputNumbersAll) = calibratedMinimum(ii);
    calibratedMaximum(inputNumbersAll) = calibratedMaximum(ii);
    ii = ii+1;
end

% Remove unused input numbers
rawMinimum = rawMinimum(inputNumbersTrue);
rawMaximum = rawMaximum(inputNumbersTrue);
calibratedMinimum = calibratedMinimum(inputNumbersTrue);
calibratedMaximum = calibratedMaximum(inputNumbersTrue);

% Calibrate channels
for n = 1:numel(chans)
    data(n,:) = calibratedMinimum(n) + ...
        (data(n,:)-rawMinimum(n)) / (rawMaximum(n)-rawMinimum(n)) * (calibratedMaximum(n)-calibratedMinimum(n));
end

%% Read events

fprintf('Loading events...\n');
event = readneuroneevents([dataPath num2str(sessionPhaseNumber) filesep]);
NEURONE.event = event;

% Writing event description
latency = strvcat('Latency:','The index number indicating the point in the data when the particular event has occurred');
type = strvcat('Type:','A descriptive name for the event. Will be generated depending on the type of the event as follows:',' ', ...
    'Event type', ...
    '----------', ...
    '1) Unknown', ...
    '2) Stimulation', ...
    '3) Video trigger', ...
    '4) Mute trigger', ...
    '5) 8-bit trigger', ...
    '6) Comment', ' ', ...
    'Corresponding value of the type field', ...
    '-----------------------', ...
    '1) (Source port name) - Unknown', ...
    '2) (Source port name) - Stimulation', ...
    '3) (Source port name) - Video', ...
    '4) (Source port name) - Mute', ...
    '5) (8-bit trigger code, a value between 1-255)',...
    '6) (any user-entered comment related to the event)');

NEURONE.eventdescription = {latency type};

%% Store rest of the data
fprintf('Preparing output...\n');

% Basic dataset information:
NEURONE.srate = srate;
NEURONE.pnts = numel(data)/numel(chans);
NEURONE.xmin = 0;
NEURONE.xmax =(NEURONE.pnts-1)/srate;
NEURONE.trials = 1;
NEURONE.nbchan = length(chans);
NEURONE.data = data;
NEURONE.ref = 'common';
NEURONE.filepath = ''; % Will be generated by EEGLAB when saved
NEURONE.filename = ''; % Will be generated by EEGLAB when saved

% Additional dataset information:
NEURONE.icawinv = [];
NEURONE.icaweights = [];
NEURONE.icasphere = [];
NEURONE.icaact = [];

end


function terms = strsplit_re(s, delimiter)
%STRSPLIT_RE Splits a string into multiple terms with regex delimiter
%
%   terms = strsplit_re(s, delimiter);
%       splits the string s into multiple terms with delimiter specified
%       by a regular expression.
%
%       The extracted terms are returned in form of a cell array of
%       strings.
%
%   Remarks
%   -------
%       - If there are two consecutive non-whitespace delimiters, it is
%         regarded that there is an empty-string term between them.
%
%   Examples
%   --------
%       % split a string by whitespaces
%       ts = strsplit_re('I am using MATLAB', '\s+');
%       ts <- {'I', 'am', 'using', 'MATLAB'}
%
%       % extract terms delimited by commas
%       ts1 = strsplit_re('Apple, Orange , Banana', ',');
%       ts1 <- {'Apple', ' Orange ', ' Banana'}
%
%       ts2 = strsplit_re('Apple, Orange , Banana', '\s*,\s*');
%       ts2 <- {'Apple', 'Orange', 'Banana'}
%
%       % consecutive delimiters results in empty terms
%       ts = strsplit_re(',Apple,,Orange,Banana', ',');
%       ts <- {'', 'Apple', '', 'Orange', 'Banana'}
%

%   History
%   -------
%       - Created by Dahua Lin, on Oct 9, 2008
%

%% parse and verify input arguments

assert(ischar(s) && ndims(s) == 2 && size(s,1) <= 1, ...
    'strsplit_re:invalidarg', ...
    'The first input argument should be a char string.');

d = delimiter;
assert(ischar(d) && ndims(d) == 2 && size(d,1) == 1 && ~isempty(d), ...
    'strsplit_re:invalidarg', ...
    'The delimiter should be a non-empty char string.');

%% main

[sp, ep] = regexp(s, d, 'start', 'end');

if ~isempty(sp)
    nt = numel(sp) + 1;
    terms = cell(1, nt);
    p = 1;
    for i = 1 : nt-1
        if p < sp(i)
            terms{i} = s(p:sp(i)-1);
        else
            terms{i} = '';
        end
        p = ep(i) + 1;
    end
    if p <= length(s)
        terms{nt} = s(p:end);
    else
        terms{nt} = '';
    end
else
    terms = {s};
end


function [dat, descrip, colors, h1, s1] = bars(obj, varnames, varargin)
% Bar plot for canlab_dataset object
%
% :Usage:
% ::
%
%    [dat, descrip, colors, h1, s1] = bars(obj, varnames, [optional inputs])
%
%    Takes inputs to barplot_columns
%    e.g., 'noviolin' to suppress violin plot
%    'colors' followed by colors cell for each bar
%
% ..
%     Author and copyright information:
%
%     Copyright (C) 2013 Tor Wager
%
%     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/>.
% ..
%
%
% :Inputs:
%
%   **obj:**
%        canlab_dataset object
%
%   **varnames:**
%        Cell string of variable names to plot
%
% :Optional Inputs:
%    **colors:**
%        defined colors (default are set by scn_standard_colors.m)
%
%   **nofig:**
%        do not generate figure
%
%   Takes any optional inputs to barplot_colored.m
%
%
% :Outputs:
%
%   **dat:**
%        data matrix for each variable
%
%   **descrip:**
%        the description for this variable
%
%   **colors:**
%        selected colors (default are set by scn_standard_colors.m)
%
%   **h1:**
%        figure handle
%
%   **s1:**
%        axis handle
%
% :Examples:
% ::
%
%     create_figure('NPS values - All subjects');
%
%     varnames = {'15' '13' '11' ' 9' '16' '14' '12' '10'};
%     xvals = [1 2 4 5 8 9 11 12];
%     colors = {[1 0 0] [0 1 0] [1 0 0] [0 1 0] [1 0 0] [0 1 0] [1 0 0] [0 1 0]};
%     bars(LevoNPS, varnames, 'x', xvals, 'colors', colors, 'XTickLabels', varnames, 'within', 'nofig');
%

n = length(varnames);
colors = scn_standard_colors(n);

% -------------------------------------------------------------------------
% DEFAULTS AND INPUTS
% -------------------------------------------------------------------------

% optional inputs with default values
% -----------------------------------
% - allowable_args is a cell array of argument names
% - avoid spaces, special characters, and names of existing functions
% - variables will be assigned based on these names
%   i.e., if you use an arg named 'cl', a variable called cl will be
%   created in the workspace

allowable_args = {'colors' 'nofig'};

default_values = {colors [0]};

% define actions for each input
% -----------------------------------
% - cell array with one cell for each allowable argument
% - these have special meanings in the code below
% - allowable actions for inputs in the code below are: 'assign_next_input' or 'flag_on'

actions = {'assign_next_input' 'flag_on'};

% logical vector and indices of which inputs are text
textargs = cellfun(@ischar, varargin);
whtextargs = find(textargs);

for i = 1:length(allowable_args)

    % assign default
    % -------------------------------------------------------------------------

    eval([allowable_args{i} ' =  default_values{i};']);

    wh = strcmp(allowable_args{i}, varargin(textargs));

    if any(wh)
        % Optional argument has been entered
        % -------------------------------------------------------------------------

        wh = whtextargs(wh);
        if length(wh) > 1, warning(['input ' allowable_args{i} ' is duplicated.']); end

        switch actions{i}
            case 'assign_next_input'
                eval([allowable_args{i} ' = varargin{wh(1) + 1};']);
                %varargin{wh(1) + 1} = [];

            case 'flag_on'
                eval([allowable_args{i} ' = 1;']);

            otherwise
                error(['Coding bug: Illegal action for argument ' allowable_args{i}])
        end

    end % argument is input
end

% END DEFAULTS AND INPUTS
% -------------------------------------------------------------------------

% REST OF BAR PLOT

[dat, ~, ~, descrip] = get_var(obj, varnames, varargin{:});

%descrip = cat(1, descrip{:});
%colors = cat(1, colors{:});

xvals = 1:n;

if nofig
    % Do nothing, use existing figure
else
    create_figure('bars');
end

[h1, s1] = barplot_columns(dat, 'nofig', varargin{:});
% set(h2, 'BarWidth', .9)
%colormap(colors)

mynames = strrep(varnames, '_', ' ');
set(gca, 'XTickLabel', mynames);

% STATS OUTPUT

fprintf('T-tests against zero\n');
fprintf('Description\tt(%3.0f)\tp\n', size(dat, 1) - 1);

% Print table - t-test against zero
for i = 1:n
    [h, p, ci, stats] = ttest(dat(:, i));
    if p < .001, str = '***';
    elseif p < .01, str = '**';
    elseif p < .05, str = '*';
    elseif p < .10, str = '+';
    else str = ' ';
    end

    fprintf('%s\t%3.2f\t%3.6f\t%s\n', descrip{i}, stats.tstat, p, str);
end

end


function img = showTemplates(img, A, A_mean, A_norm, tsize, nt)
if(size(img,3) == 1)
    for i=1:3
        img_color(:,:,i) = img;
    end
    img = img_color;
end

for i=1:nt
    tt = A(:,i);
    tt = tt*A_norm(i)+A_mean(:,i);
    tt = reshape(tt, [tsize, 3]);
    for j=1:3
        img(end-tsize(1)+1:end,(i-1)*tsize(2)+1:i*tsize(2),j) = tt(:,:,j);
    end
end
%save templates templates;


function printTrainBatch(data, params)
  if params.isBi
    printSent(2, data.srcInput(1, :), params.srcVocab, '  src input 1: ');
    fprintf(2, '  src mask: %s\n', num2str(data.srcMask(1, :)));
  end

  printSent(2, data.tgtInput(1, :), params.tgtVocab, '  tgt input 1: ');
  printSent(2, data.tgtOutput(1, :), params.tgtVocab, '  tgt output 1: ');

  fprintf(2, '  tgt mask: %s\n', num2str(data.tgtMask(1, :)));
end


function s = dicomLoadAllSeries(dicomDir, studyId, sortByFilenameFlag, ignoreAcquisition)
%
% s = dicomLoadAllSeries(dicomDir, [studyId=''], [sortByFilenameFlag=false])
%
% Loads all the dicom files found in the specified directory
% (recursively searches all sub-directories too). A structure
% array is returned, with one entry for each series found in the
% directory tree.
%
% If studyID (a string) is provided, then only series with a matching
% StudyID tag will be processed. Otherwise, all studies are processed.
%
% To save each series in a directory of DICOMs to separate NIFTI files, try
% niftiFromDicom.
%
% HISTORY:
% 2007.01.?? RFD: wrote it.
% 2009.12.08 RFD: completely replaced code to compute the imToScanner
% xform. I now use code that is modeled on NYU's dinifti, so we should now
% produce results consistent with that program. Which, BTW, are more
% accurate than what we did before.

if(~exist('sortByFilenameFlag','var')||isempty(sortByFilenameFlag))
    sortByFilenameFlag = false;
end
if(~exist('ignoreAcquisition','var')||isempty(ignoreAcquisition))
    ignoreAcquisition = false;
end

n = 0;
% Get a recursive dump of all sub-directories. We'll
% process every file in the dicomDir tree.
d = genpath(dicomDir);
if(isempty(d))
  error(['Dicom dir "' d '" not found or empty.']);
end
if(isunix)
    d = explode(':',genpath(dicomDir));
else
    d = explode(';',genpath(dicomDir));
end
d = d(1:end-1);
for(ii=1:length(d))
  d2 = dir(fullfile(d{ii},'*'));
  for(jj=1:length(d2))
	if(~d2(jj).isdir)
	  n = n+1;
	  dicomFiles{n} = fullfile(d{ii},d2(jj).name);
	end
  end
end

clear d;
numSeries = 0;
% We might need this if the dicoms are gzipped.
tmp = tempdir;
tmpName = tempname;

if(~exist('studyId','var'))
    studyId = [];
end
fprintf('Processing %d files in %s:\n', n, dicomDir);
for(imNum=1:length(dicomFiles))
    curFile = dicomFiles{imNum};
    if(length(curFile)>3 && strcmpi(curFile(end-2:end),'.gz'))
        if(exist(tmpName,'file')) delete(tmpName); end
        curFile = gunzip(curFile,tmp);
        movefile(curFile{1}, tmpName);
        curFile = tmpName;
    end
	try
	  info = dicominfo(curFile);
	  if((isempty(studyId) || strcmp(studyId,info.StudyID)) &&  isfield(info,'PatientPosition'))
        if(numSeries==0)
            curSeries = [];
        else
            if(ignoreAcquisition)
                curSeries = find(str2double(info.SeriesTime)==[s(:).acqTime]);
            else
                curSeries = find(info.AcquisitionNumber==[s(:).acqNum] & str2double(info.SeriesTime)==[s(:).acqTime]);
            end
        end
        if(isempty(curSeries))
		  numSeries = numSeries+1;
          curSeries = numSeries;
		  numSlice = 1;
		  s(curSeries).studyID = info.StudyID;
		  s(curSeries).studyDescription = getFieldVal(info, 'StudyDescription', '');
		  s(curSeries).studyDateTime = [info.SeriesDate ' ' info.StudyTime];
		  s(curSeries).patientName = info.PatientName.FamilyName;
		  s(curSeries).patientPosition = getFieldVal(info, 'PatientPosition', 'NONE');
		  s(curSeries).fieldStrength = getFieldVal(info, 'MagneticFieldStrength', []);
		  s(curSeries).seriesDescription = getFieldVal(info, 'SeriesDescription', []);
		  s(curSeries).acqTime = str2double(getFieldVal(info, 'SeriesTime', []));
		  s(curSeries).acqMatrix = getFieldVal(info, 'AcquisitionMatrix',[]);
		  s(curSeries).percentFOV = [getFieldVal(info, 'PercentSampling', []) getFieldVal(info, 'PercentPhaseFieldOfView', [])];
		  s(curSeries).reconDiam = getFieldVal(info, 'ReconstructionDiameter', []);
		  s(curSeries).sliceThickness = info.SliceThickness;
          if(isfield(info,'SpacingBetweenSlices'))
              s(curSeries).mmPerVox = [info.PixelSpacing(:)' info.SpacingBetweenSlices];
          else
              s(curSeries).mmPerVox = [info.PixelSpacing(:)' s(curSeries).sliceThickness];
          end
		  s(curSeries).TR = getFieldVal(info, 'RepetitionTime', []);
		  s(curSeries).TE = getFieldVal(info, 'EchoTime', []);
		  s(curSeries).inversionTime = getFieldVal(info, 'InversionTime', []);
		  s(curSeries).SAR = getFieldVal(info, 'SAR', []);
		  s(curSeries).pixBandwidth = getFieldVal(info, 'PixelBandwidth', []);
          if(~isempty(s(curSeries).pixBandwidth) && numel(s(curSeries).acqMatrix>=2))
              s(curSeries).Bandwidth = s(curSeries).pixBandwidth*s(curSeries).acqMatrix(2);
          else
              s(curSeries).Bandwidth = [];
          end
		  s(curSeries).NEX = getFieldVal(info, 'NumberOfAverages', []);
		  s(curSeries).imageFreq = getFieldVal(info, 'ImagingFrequency',[]);
		  s(curSeries).flipAngle = getFieldVal(info, 'FlipAngle', []);
		  s(curSeries).phaseEncodeDir = getFieldVal(info, 'InPlanePhaseEncodingDirection', []);
		  % We'll fill in the 3rd and 4th dims below
		  %s(curSeries).dims = [info.Rows info.Columns info.ImagesInAcquisition];
		  s(curSeries).dims = [info.Rows info.Columns 0 0];
		  s(curSeries).seriesNum = getFieldVal(info, 'SeriesNumber', []);
		  s(curSeries).acqNum = getFieldVal(info, 'AcquisitionNumber', []);
		  s(curSeries).imageOrientation = getFieldVal(info, 'ImageOrientationPatient', []);
          if(strcmp(info.Manufacturer,'GE MEDICAL SYSTEMS'))
              % *** TO DO: these should be pulse-sequence dependent
              s(curSeries).sequenceName = getFieldVal(info, 'Private_0019_109e',[]);
              s(curSeries).mtOffset = getFieldVal(info, 'Private_0043_1034',[]);
              s(curSeries).dtiBValue = str2double(char(getFieldVal(info, 'Private_0019_10b0',[])));
              s(curSeries).dtiGradsCode = str2double(char(getFieldVal(info, 'Private_0019_10b2',[])));
          elseif(strcmp(info.Manufacturer,'SIEMENS'))
              bmtx = getFieldVal(info, 'Private_0019_1027', []);
              if(isempty(bmtx))
                  s(curSeries).dtiBMatrix = [];
                  s(curSeries).dtiBValue = 0;
                  s(curSeries).dtiGradDir = [1 0 0]';
              else
                  s(curSeries).dtiBMatrix = typecast(bmtx,'double');
                  s(curSeries).dtiBValue = norm(sqrt(s(curSeries).dtiBMatrix([1 4 6])))^2;
                  s(curSeries).dtiGradDir = sign(sign(s(curSeries).dtiBMatrix([1:3])) + 0.01).*sqrt(s(curSeries).dtiBMatrix([1 4 6])/s(curSeries).dtiBValue);
              end
          end
		  %ReferencedImageSequence

		  %s(curSeries).imData = zeros(s(curSeries).dims);
		  %s(curSeries).imagePosition = zeros(3,s(curSeries).dims(3));
		  %s(curSeries).sliceNum = zeros(1,s(curSeries).dims(3));
		  % We'll set this to more meaningful values below
		  s(curSeries).imToScanXform = eye(4);

		  fprintf('Loading series %d, acquisition %d...\n', s(curSeries).seriesNum, s(curSeries).acqNum);
        end
        s(curSeries).sliceNum(numSlice) = info.InstanceNumber;
        s(curSeries).imagePosition(:,numSlice) = info.ImagePositionPatient;
        s(curSeries).sliceLoc(numSlice) = info.SliceLocation;
        s(curSeries).fileName{numSlice} = dicomFiles{imNum};
        % Matlab seems to flip permute x and y when reading the data, so we do
        % a transpose here. Seems to make everything work better down the line.
        % *** RFD: need to flip dim 2 also?
        s(curSeries).imData(:,:,numSlice) = dicomread(info)';
        numSlice = numSlice+1;
	  end
	catch
	  disp(['failed to load ' curFile]);
	end
end

% sort the series properly
[junk,ind] = sort([s(:).seriesNum]);
s = s(ind);

% Sort the slices based on sliceNum and break timeseries up into separate
% volumes (good for fMRI and DTI acquisitions).

for(ii=1:numSeries)
    if(sortByFilenameFlag)
        [s(ii).sliceNum,sortInd] = sort(s(ii).fileName);
    else
        % Sort based on sliceNum (DICOM InstanceNumber).
        [s(ii).sliceNum,sortInd] = sort(s(ii).sliceNum);
    end
    s(ii).sliceLoc = s(ii).sliceLoc(sortInd);
    s(ii).imagePosition = s(ii).imagePosition(:,sortInd);
    s(ii).imData = s(ii).imData(:,:,sortInd);
    % Now compute the actual number of slices per timepoint
    uniqueSliceLoc = unique(s(ii).sliceLoc);
    s(ii).dims(3) = length(uniqueSliceLoc);
    s(ii).dims(4) = floor(length(sortInd)./s(ii).dims(3));
    if(prod(double(s(ii).dims))==numel(s(ii).imData))
        s(ii).imData = reshape(s(ii).imData, s(ii).dims);
    else
        warning(['Series ' num2str(ii) ' appears to contain >1 volume, but I can not guess the dimensions- keeping it a single vol.']);
    end
end

for(ii=1:length(s))
    if(isempty(s(ii).imData)) s(ii) = []; end
end
numSeries = length(s);

% Compute the scanner-to-image xform and resort the slices based on the
% slice normal.
for(ii=1:numSeries)
    % 2009.12.07 RFD: Pulled orientation code from NYU's dinifti
    dim = size(s(ii).imData);

    % Orientation information
    %-------------------------------------------------------------------
    % Axial Analyze voxel co-ordinate system:
    % x increases     right to left
    % y increases posterior to anterior
    % z increases  inferior to superior

    % DICOM patient co-ordinate system:
    % x increases     right to left
    % y increases  anterior to posterior
    % z increases  inferior to superior

    % T&T co-ordinate system:
    % x increases      left to right
    % y increases posterior to anterior
    % z increases  inferior to superior

    % Code lifted from dinifti source:
    % patient orientation cosines, in [Sag, Cor, Ax] order
    rowCosines = s(ii).imageOrientation(1:3);
    colCosines = s(ii).imageOrientation(4:6);
    sliceNorm = cross(rowCosines, colCosines);

    qto_xyz = zeros(4,4);
    qto_xyz(1,1) = -rowCosines(1); % -image->RowSagCos();
	qto_xyz(1,2) = -colCosines(1); % -image->ColSagCos();
	qto_xyz(1,3) = -sliceNorm(1); % -(rowCosines(2) * colCosines(3) - rowCosines(3) * colCosines(2)); % -image->SagNorm();

	qto_xyz(2,1) = -rowCosines(2); % -image->RowCorCos();
	qto_xyz(2,2) = -colCosines(2); % -image->ColCorCos();
	qto_xyz(2,3) = -sliceNorm(2); % -(rowCosines(3) * colCosines(1) - rowCosines(1) * colCosines(3)); % -image->CorNorm();

	qto_xyz(3,1) = rowCosines(3); % image->RowTraCos();
	qto_xyz(3,2) = colCosines(3); % image->ColTraCos();
	qto_xyz(3,3) = sliceNorm(3); % rowCosines(1) * colCosines(2) - rowCosines(2) * colCosines(1); % image->TraNorm();

    % *** TO DO: The most robust wayt to define slice order and slice
    % spacing is to project slice position onto slice normal.
    % From: http://nifti.nimh.nih.gov/board/read.php?f=1&i=579&t=508
    % Slice normal vector is the cross product of ImageOrientationPatient vectors.
    % Project each slice's ImagePositionPatient projection onto the slice normal
    % to find it's position in the slice order list.
    % pfirst = dot(sliceNorm,s(ii).imagePosition(:,1)) * sliceNorm;
    % plast = dot(sliceNorm,s(ii).imagePosition(:,end)) * sliceNorm;

    % Simple hack to decide if we need to flip the slice order:
    if(dot(sliceNorm,s(ii).imagePosition(:,1)) > dot(sliceNorm,s(ii).imagePosition(:,end)))
        s(ii).sliceNum = flipdim(s(ii).sliceNum,2);
        s(ii).sliceLoc = flipdim(s(ii).sliceLoc,2);
        s(ii).imagePosition = flipdim(s(ii).imagePosition,2);
        s(ii).imData = flipdim(s(ii).imData,3);
    end

	% offset = slicePosition(center) - M*(i,j,k of center) since we are working with the first slice k = 0.

    % For matlab's 1-indexing, we have to subtract mmPerVox from the origin
    % (imagePosition) to reflect the fact that the first voxel is [1,1,1]
    % rather than [0,0,0].
    pos = s(ii).imagePosition(:,1);
    qto_xyz(:,4) = [-pos(1) -pos(2) pos(3) 1]';
    qto_xyz(1:3,1:3) = qto_xyz(1:3,1:3)*diag(s(ii).mmPerVox);

    % Apply a 1-voxel offset to the origin to account for Matlab's
    % 1-indexing.
    qto_xyz = inv(inv(qto_xyz)+[0 0 0 1;0 0 0 1;0 0 0 1; 0 0 0 0]);

    s(ii).imToScanXform  = qto_xyz;

% OLD CODE:
%     s(ii).imToScanXform = eye(4);
%     % DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior,
%     % while NIFTI is +x is Right, +y is Anterior, +z is Superior.
%     % So, x and y offsets get flipped.
%     %s(ii).imToScanXform(1:3,4) = s(ii).imagePosition(:,1).*[-1 -1 1]';
%     s(ii).imToScanXform(1:3,4) = -s(ii).imagePosition(:,1);
%
%     % From the NIFTI-1 standard (Bob Cox):
%     % The DICOM attribute (0020,0037) "Image Orientation (Patient)"
%     % gives the orientation of the x- and y-axes of the image data
%     % in terms of 2 3-vectors. The first vector is a unit vector
%     % along the x-axis, and the second is along the y-axis. If the
%     % (0020,0037) attribute is extracted into the value
%     % (xa,xb,xc,ya,yb,yc), then the first two columns of the R
%     % matrix would be
%     %            [ -xa  -ya ]
%     %            [ -xb  -yb ]
%     %            [  xc   yc ]
%     % The negations are because DICOM's x- and y-axes are reversed
%     % relative to NIFTI's. The third column of the R matrix gives
%     % the direction of displacement (relative to the subject) along
%     % the slice-wise direction. This orientation is not encoded in
%     % the DICOM standard in a simple way; DICOM is mostly concerned
%     % with 2D images.  The third column of R will be either the
%     % cross-product of the first 2 columns or its negative.  It is
%     % possible to infer the sign of the 3rd column by examining the
%     % coordinates in DICOM attribute (0020,0032) "Image Position
%     % (Patient)" for successive slices.  However, this method
%     % occasionally fails for reasons that I (RW Cox) do not understand.
%     s(ii).imToScanXform(1:3,1) = s(ii).imageOrientation(1:3).*[-1 -1 1]';
%     s(ii).imToScanXform(1:3,2) = s(ii).imageOrientation(4:6).*[-1 -1 1]';
%     s(ii).imToScanXform(1:3,3) = cross(s(ii).imToScanXform(1:3,1),s(ii).imToScanXform(1:3,2));
%     if(s(ii).sliceLoc(1)>s(ii).sliceLoc(end))
%         % Slices run S-I, so signal a flip in this dim.
%         s(ii).imToScanXform(1:3,3) = -s(ii).imToScanXform(1:3,3);
%         s(ii).imToScanXform(3,4) = -s(ii).imToScanXform(3,4);
%     end
%
%     % CHECK THIS: How to infer the orientation?
%     % Check to see if the image plane normal goes away from the
%     % center of the volume?
%     %if(s(ii).slicePos(1)<s(ii).slicePos(end))
%     %  s(ii).imToScanXform(1:3,3) = -s(ii).imToScanXform(1:3,3);
%     %end
%     s(ii).imToScanXform = s(ii).imToScanXform*diag([s(ii).mmPerVox 1]);
end

return;

function val = getFieldVal(s, fieldName, defaultValue)
    if(isfield(s,fieldName))
        val = s.(fieldName);
    else
        val = defaultValue;
    end
return;


function ps_shapefile(filename,data,step)
%
%   12/2013 MA: Initial version
%
%

if nargin < 3
  step=':';
end

% get velocity
%if ~exist('ps_plot_v-d.mat')
% ps_plot('v-d',-1)
%end
%load ps_plot_v-d  ph_disp
%data= ph_disp;

disp('Loading lonlat matrix...')
load ps2 lonlat

step
if isinteger(step)
 step=1:step:size(lonlat,1);
end

lon=lonlat(step,:,1);
lat=lonlat(step,:,2);
data=double(data(step,:));

shape=struct('Geometry', 'Point','X',num2cell(lon),'Y',num2cell(lat),'V',num2cell(V));

shapewrite(shape,filename);


function test_suite = testAssertExceptionThrown
%testAssertExceptionThrown Unit tests for assertExceptionThrown

%   Steven L. Eddins
%   Copyright 2008 The MathWorks, Inc.

initTestSuite;

function test_happyCase
assertExceptionThrown(...
    @() error('MyProd:MyFun:MyId', 'my message'), 'MyProd:MyFun:MyId');

function test_wrongException
assertExceptionThrown(@() assertExceptionThrown(...
    @() error('MyProd:MyFun:MyId', 'my message'), ...
    'MyProd:MyFun:DifferentId'), 'assertExceptionThrown:wrongException');

function test_noException
assertExceptionThrown(@() assertExceptionThrown(@() sin(pi), 'foobar'), ...
    'assertExceptionThrown:noException');


function model = make_empty_3D_model()

model.x = [];
model.y = [];
model.z = [];
model.nx = [];
model.ny = [];
model.nz = [];
model.r = [];
model.g = [];
model.b = [];


function readHTKresult(input, output);

INPUT = fopen(input,'r');
OUTPUT = fopen(output,'w');

% Read in the data for one test
for i=1:70
    fsearch2('Date:',INPUT);
    tmp = textscan(INPUT,'%s%s%d%s%d',1);
    data.date.week(i) = tmp{1};
    data.date.month(i) = tmp{2};
    data.date.day(i) = tmp{3};
    data.date.time(i) = tmp{4};
    data.date.year(i) = tmp{5};

    fsearch2('labels/',INPUT);
    tmp = textscan(INPUT,'%2c',1);
    data.label(i) = tmp;

    fsearch2('Correct=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.sent_corr(i) = tmp{1};
    fsearch2('H=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.sent_H(i) = tmp{1};
    fsearch2('S=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.sent_S(i) = tmp{1};
    fsearch2('N=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.sent_N(i) = tmp{1};

    fsearch2('Corr=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_corr(i) = tmp{1};
    fsearch2('Acc=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_acc(i) = tmp{1};
    fsearch2('H=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_H(i) = tmp{1};
    fsearch2('D=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_D(i) = tmp{1};
    fsearch2('S=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_S(i) = tmp{1};
    fsearch2('I=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_I(i) = tmp{1};
    fsearch2('N=',INPUT);
    tmp = textscan(INPUT,'%f',1);
    data.word_N(i) = tmp{1};
end

% write the data
for i=1:70
    if i==1, fprintf(OUTPUT,'\nTEST SET A\n');
    elseif i==29, fprintf(OUTPUT,'\nTEST SET B\n');
    elseif i==57, fprintf(OUTPUT,'\nTEST SET C\n'); end
    if mod(i,7) == 1, fprintf(OUTPUT,'%s\n',data.label{i}); end
%     fprintf(OUTPUT,'%s %s %d %s %d ',...
%         data.date.week{i},data.date.month{i},data.date.day(i),data.date.time{i},data.date.year(i));
    fprintf(OUTPUT,'%s %d %s - ',data.date.month{i},data.date.day(i),data.date.time{i});
    fprintf(OUTPUT,'%2.2f	%2.2f   	%d	%d   	%d   	%d  	%d  - ',data.word_corr(i),data.word_acc(i),data.word_H(i),...
        data.word_D(i),data.word_S(i),data.word_I(i),data.word_N(i));
    fprintf(OUTPUT,'%2.2f %d %d %d \n',data.sent_corr(i),data.sent_H(i),data.sent_S(i),data.sent_N(i));
end
fprintf(OUTPUT,'\n');

fclose(INPUT);
fclose(OUTPUT);


% Copyright (C) 1993-2017, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com
classdef Tx < ETS3

    methods
        function obj = Tx(varargin)
            obj@ETS3('Tx', varargin{:});

        end

        % function s = char(ets)
        %     s = ets.what;
        % end
    end
end


function [pvec, pstruct] = tapas_cdfgaussian_obs_transp(r, ptrans)
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2012-2015 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% This is a dummy function

pvec    = [];
pstruct = struct;

return;


function hfssThickenSheet(fid,ObjectList,Thickness, Units)
% ----------------------------------------------------------------------------
% function hfssThickenSheet(fid, ObjectList, Thickness, Units)
%
% Description :
% -------------
% Thickens a given set of sheets.
%
% Parameters :
% ------------
% fid     - file identifier of the HFSS script file.
% ObjectList - a cell array of objects that need get thickened.
% Thickness - a float that defines the thickness value
% Units   - units for the thickness (use 'in', 'mm', 'meter' or
%           anything else defined in HFSS).
%
% Note :
% ------
%
% Example :
% ---------
% hfssThickenSheet(fid, {'Rectangle1', 'Rectangle2'}, 0.4, 'mm');
% ----------------------------------------------------------------------------
% ----------------------------------------------------------------------------
% Written by Franz Schroeder
% franz.dude@gmail.com / franz.schroeder@tu-dresden.de
% 16 September 2013
% -------------------------------------------------------------------------
% ---
% ----------------------------------------------------------------------------

nObjects = length(ObjectList);

% Preamble.
fprintf(fid, '\n');
fprintf(fid, 'oEditor.ThickenSheet _\n');
fprintf(fid, 'Array("NAME:Selections", _\n');

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

%set parameters
fprintf(fid, '"NewPartsModelFlag:=", _\n');
fprintf(fid, '"Model"), _\n');
fprintf(fid, 'Array("NAME:SheetThickenParameters", _\n');
fprintf(fid, '"Thickness:=", "%f%s", _\n', Thickness, Units);
fprintf(fid, '"BothSides:=", false)\n');


function [white, anatpath] = BuildWhiteVolume(hemisphere, fName)

% [white, path] = BuildWhiteVolume([hemisphere, fName]);
%
% Create a binary map of the white matter of the designated hemispheres.
% Optional input hemisphere is 0 for both [default], 1 for left, or 2 for
% right. Optional input fName allows specification of classFile name;
% default guesses file name from anatomy path.
%
% Ress, 07/05

mrGlobals

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

switch hemisphere
  case 0
    hemispheres = {'Left' 'Right'};
  case 1
    hemispheres = {'Left'};
  case 2
    hemispheres = {'Right'};
  otherwise, hemispheres = {'Left' 'Right'};
end

nHemi = length(hemispheres);

if ~exist('fName', 'var') | isempty(fName)
  if exist('vANATOMYPATH', 'var')
    [anatpath, name] = fileparts(vANATOMYPATH);
    for iH=1:nHemi
      dName = fullfile(anatpath, hemispheres{iH});
      if exist(dName, 'dir')
        fList = dir(fullfile(dName, '*.?lass'));
        if ~isempty(fList), fName{iH} = fullfile(dName, fList(1).name); end
      else
        disp(['Could not find ' hemispheres{iH} ' hemisphere class file!'])
        nHemi = nHemi - 1;
      end
    end
  end
end

if ~exist('fName', 'var') | isempty(fName)
  disp('Must provide class-file name');
  dist = [];
  return
else
  if ~iscell(fName), fName = {fName}; end
end

% Get classification volume and create binary map of white matter
for iH=1:nHemi
  class = readClassFile(fName{iH}, 0, 0);
  if exist('white', 'var')
    white = white | (class.data == class.type.white);
  else
    white = (class.data == class.type.white);
  end
end


function slSpawn(searchlight, process, processes, partitions)
% slSpawn(searchlight, process, processes, partitions)
% SEARCHLIGHT - SPAWN
% ---------------------------------------------------------
% Used by SLRUN to complete bite-sized portions of a searchlight.
%
% INPUTS
% 	searchlight - Structure initialized with slInit.
% 	process - Which of N portions to complete.
% 	processes - Number of portions to be completed.
% 	partitions - How many smaller-sized portions to break up each portion
%       into.
%
% OUTPUTS
%   N/A
%
% USAGE
%   Calling this is either handled by the SGE or layed out explicitly by
%   provided commands.  Assuming you'd like to write up a command on your
%   own, let's suppose we want to run the first portion of a searchlight
%   broken into three pieces.  Each of those portions we'll divide into 30
%   bite-sized portions to iterate over.
%       searchlight = slInit(...);
%       slSpawn(searchlight, 1, 3, 30);
%
% See also SLINIT, SLRUN, SLCOMPLETE, SVMINIT.
%
% renobowen@gmail.com [2010]
%
    isGray = strcmpi(searchlight.searchView, 'gray');
    growBy = searchlight.growBy;

    processesToRun = (((process - 1) * partitions):(process * partitions - 1)) + 1;
    for i = processesToRun
        filename = sprintf('%s/%s/searchlight%04d.mat', searchlight.path, searchlight.tmpDir, i);
        processString = sprintf('[%d/%d]', i, processes);
        if (exist(filename, 'file'))
            fprintf('%s Process already completed.  Proceeding...\n', processString);
            continue;
        end

        indices = searchlight.startInds(i):searchlight.endInds(i);

        if (isGray)
            centers = searchlight.ipInds(:, indices);
        else
            centers = searchlight.allCoords(:, indices);
        end
        nCenters = size(centers, 2);

        fprintf('%s Processing coordinate block...', processString);
        meanAccs = zeros(1, nCenters);
        for j = 1:nCenters
            [roiCoords centers(:, j)] = growROI(searchlight, centers(:, j), isGray);
            if (isempty(roiCoords))
                meanAccs(j) = 0;
            else
                meanAccs(j) = runSVM(searchlight, roiCoords);
            end
        end
        fprintf('done.\n');
        fprintf('%s Saving...', processString);
        save(filename, 'meanAccs', 'centers', 'growBy', '-v7.3');
        fprintf('done.\n');
    end
end

function [roiCoords center] = growROI(searchlight, center, isGray)
    growBy = searchlight.growBy;
    if (isGray)
        % Set nodes and edges to relevant hemisphere
        ind = center(1);
        isRightHemi = center(2);
        if (isRightHemi)
            nodes   = searchlight.vw_gray.allRightNodes;
            edges   = searchlight.vw_gray.allRightEdges;
        else
            nodes   = searchlight.vw_gray.allLeftNodes;
            edges   = searchlight.vw_gray.allLeftEdges;
        end

        % Compute coordinates of grown disc
        dist        = mrManDist(nodes, edges, double(ind), [1 1 1], 0, growBy);
        discCoords  = nodes(1:3, dist > 0);
        if (isempty(discCoords)), roiCoords = []; return; end
        roiCoords  = [discCoords(2, :); discCoords(1, :); discCoords(3, :)]; % rearranging because of fudged order

        % Recompute hemispheric index to parameter map index
        if (isRightHemi)
            [c center(1)] = intersectCols(searchlight.vw_gray.nodes(1:3, :), ...
                searchlight.vw_gray.allRightNodes(1:3, ind)); % for 3 coordinates
        else
            [c center(1)] = intersectCols(searchlight.vw_gray.nodes(1:3, :), ...
                searchlight.vw_gray.allLeftNodes(1:3, ind)); % for 3 coordinates
        end

    else
        minmax = repmat(center, [1 2]);
        minmax(:, 1) = minmax(:, 1) - growBy;
        minmax(:, 2) = minmax(:, 2) + growBy;
        if (sum(minmax(:, 1) < 1) || sum(minmax(:, 2) > searchlight.dims)), roiCoords = []; return; end % out of bounds

        cubewidth = growBy * 2 + 1;
        xcoords = reshape(repmat(minmax(1, 1):minmax(1, 2), [cubewidth^2 1]), [1 cubewidth^3]);
        ycoords = repmat(reshape(repmat(minmax(2, 1):minmax(2, 2), [cubewidth 1]), [1 cubewidth^2]), [1 cubewidth]);
        zcoords = repmat(minmax(3, 1):minmax(3, 2), [1 cubewidth^2]);

        roiCoords = [xcoords; ycoords; zcoords];
    end
end

function meanAcc = runSVM(searchlight, roiCoords)
    meanAcc = [];
    if (isempty(roiCoords)), return; end

    svmTmp = searchlight.svm;
    if (strcmp(searchlight.searchView, 'inplane'))
        coords = svmTmp.coordsInplane;
    else
        coords = svmTmp.coordsGray;
    end

    [c svmInds] = intersectCols(coords, roiCoords); % for 3 coordinates
    if (isempty(svmInds)), svmInds = 1:0; end
    svmTmp.data = svmTmp.data(:, svmInds);
    svmTmp.data = svmTmp.data(:, ~isnan(svmTmp.data(1,:)));
    svmTmp.voxel = [];

    [meanAcc models] = svmRun(svmTmp, 'options', searchlight.runOptions);
end


function net= loadNet(netID, layerName)
    if nargin<2, layerName= '_relja_none_'; end

    switch netID
        case 'vd16'
            netname= 'imagenet-vgg-verydeep-16.mat';
        case 'vd19'
            netname= 'imagenet-vgg-verydeep-19.mat';
        case 'caffe'
            netname= 'imagenet-caffe-ref.mat';
        case 'places'
            netname= 'places-caffe.mat';
        otherwise
            error( 'Unknown network ID', netID );
    end

    paths= localPaths();
    net= load( fullfile(paths.pretrainedCNNs, netname));

    net= vl_simplenn_tidy(net); % matconvnet beta17 or newer is needed

    if isfield(net.meta, 'classes')
        net.meta= rmfield(net.meta, 'classes');
    end

    if ~strcmp(layerName, '_relja_none_')
        net= relja_cropToLayer(net, layerName);
        layerNameStr= ['_', layerName];
    else
        layerNameStr= '';
    end
    net= relja_swapLayersForEfficiency(net);

    net.meta.netID= netID;

    net.meta.sessionID= sprintf('%s_offtheshelf%s', netID, layerNameStr);
    net.meta.epoch= 0;

end


function [seriesData, dicomdirpath] = load_multi_dcm_dir(dicomdirpath)
% LOAD_MULTI_DCM_DIR  Read metadata from DICOMDIR file.
%
% LOAD_MULTI_DCM_DIR reads metadata from DICOMDIR file and shows list of
% the different DICOM SERIES in Pop-up menus. After selecting a dicom
% series the program creates the dcmSeries structure containing the
% related file names and path.
%
% DICOMDIR is a standard binary file provided with DICOM data, and has
% information such as paths to files, and patient, study, series IDs, etc.
%
% [SERIESDATA, DICOMDIRPATH] = LOAD_MULTI_DCM_DIR()
% SERIESDATA = LOAD_MULTI_DCM_DIR(DICOMDIRPATH)
%
%   DICOMDIRPATH is a string with the path to the directory containing the
%   DICOMDIR file. If not provided, it opens a file browser to select the
%   directory graphically.
%
%   SERIESDATA is a structure containing image information for series
%   selected by the user in the GUI.

% Original Author: Laszlo Balkay, University of Debrecen, PET Center/LB 2008
%      Available from: http://uk.mathworks.com/matlabcentral/fileexchange/7926-dicomdir-reader
%      under BSD 2-Clause License.
%
% Modified by Christopher Kelly <christopher.kelly28@googlemail.com> and
% Benjamin Villard <b.016434@gmail.com>, University of Oxford.
% Copyright © 2014-2015 University of Oxford
% Version: 0.2.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% 10 Dec 2014 - Interface changed to give preview of image.
%             - Also allows the selection of multiple series.
%             - Fewer output arguments, now the only output contains the
%               information of the series selected
%
% This file is distributed as a derivative work of a third-party function
% with project Gerardus.
%
% http://code.google.com/p/gerardus/

% check arguments
narginchk(0, 1);
nargoutchk(0, 2);

hm = [];
dcmPatient = [];
ImgPrcTlbx = ver('images');
ImgPrcTlbxVersion = str2double(ImgPrcTlbx.Version(1));
if ImgPrcTlbxVersion < 4
    disp('The required minimum version of ImgProc. Toolbox is 4!');
    return;
end

if ((nargin == 0) || strcmp(dicomdirpath,''))
    dicomdirpath = uigetdir('','Select DICOMDIR folder');
    if dicomdirpath == 0
        return;
    end
end
filename1mat = fullfile(dicomdirpath,'dicom.mat');
dirres1mat = dir(filename1mat);
filename1 = fullfile(dicomdirpath,'dicomdir');
dirres1 = dir(filename1);
filename2 = fullfile(dicomdirpath,'DICOMDIR');
dirres2 = dir(filename2);
if ~isempty(dirres1mat)
    % if the dicomdir mat structure was saved on the first time
    % open it. It is much faster than reading the DICOMDIR dicom file
    load(filename1mat);
    SeriesListNumInfo = dcmdir.SeriesListNumInfo;
    SeriesList = dcmdir.SeriesList;
    dcmPatient = dcmdir.dcmPatient;
    dcmSeries = dcmdir.dcmSeries;
    clear dcmdir;
    disp(' ');
    disp('load dicomdir.mat');
    disp(' ');
else
    if ~isempty(dirres1)
        dcmdir_path = filename1;
    elseif ~isempty(dirres2)
        dcmdir_path = filename2;
    else
        hm = msgbox('No DICOMDIR in the selected folder !','MIA Info','warn' );
        disp('No DICOMDIR in the selected folder !')
        return;
    end

    % Show up message window and set the cursor type to "watch"
    hm = msgbox('Reading the DICOMDIR structure. It takes time. Please wait!','MIA Info' );
    set(hm, 'tag', 'Msgbox_MIA Info');
    SetData=setptr('watch');set(hm,SetData{:});
    hmc = (get(hm,'children'));
    set(hmc(2),'enable','inactive');
    pause(1);

    % open DICOMDIR file & read DirectoryRecordSequence structure
    dcmhdr = dicominfo(dcmdir_path);
    delete(hm);

    % Read the DirectoryRecordSequence structure until end,
    % and read the all included DirectoryRecordType item sequentially
    DirRecords = dcmhdr.DirectoryRecordSequence;
    DirRecordsFieldNames = fieldnames(DirRecords);
    NumOfField = size(DirRecordsFieldNames,1);
    CurrentPatient = 0;
    SeriesListNum = 0;
    waitbar_h = waitbar(0,'Scanning the DICOM files....');
    for i = 1: NumOfField
        CurrentItem = DirRecords.(DirRecordsFieldNames{i});
        CurrentItemType = CurrentItem.DirectoryRecordType;
        if strcmp(CurrentItemType,'PATIENT')
            CurrentPatient = CurrentPatient + 1;
            CurrentStudy = 0;
            if ImgPrcTlbxVersion > 4
                if isfield(CurrentItem,'PatientName')
                    dcmPatient(CurrentPatient,1).PatientName = ...
                        CurrentItem.PatientName.FamilyName;
                else
                    dcmPatient(CurrentPatient,1).PatientName = 'No value available';
                end
            elseif ImgPrcTlbxVersion == 4
                if isfield(CurrentItem,'PatientsName')
                    dcmPatient(CurrentPatient,1).PatientName = ...
                        CurrentItem.PatientsName.FamilyName;
                else
                    dcmPatient(CurrentPatient,1).PatientName = 'No value available';
                end
            end
        elseif strcmp(CurrentItemType,'STUDY')
            CurrentStudy = CurrentStudy + 1;
            CurrentSeries = 0;
            if isfield(CurrentItem,'StudyDescription')
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).StudyDescription = ...
                    CurrentItem.StudyDescription;
            else
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).StudyDescription = '';
            end
        elseif strcmp(CurrentItemType,'SERIES')
            if CurrentSeries > 0 % create summary about the previous read series for popupmenu
                SeriesListNum = SeriesListNum + 1;
                Pname = dcmPatient(CurrentPatient,1).PatientName;
                Modality = dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1).Modality;
                SeriesDescription = dcmPatient(CurrentPatient,1).Study(CurrentStudy,1). ...
                    Series(CurrentSeries,1).SeriesDescription;
                StudyDescription = dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).StudyDescription;
                NumOfImages = num2str(CurrentImage);
            end
            CurrentSeries = CurrentSeries + 1;
            CurrentImage = 0;
            dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1).Modality = ...
                CurrentItem.Modality;
            if isfield(CurrentItem,'SeriesDescription')
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1). ...
                    SeriesDescription = CurrentItem.SeriesDescription;
            else
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1). ...
                    SeriesDescription = '';
            end
            %%%
        elseif strcmp(CurrentItemType,'IMAGE')
            CurrentImage = CurrentImage + 1;
            [pathstr, dcmfname, ext] = fileparts(CurrentItem.ReferencedFileID);
            if CurrentImage == 1
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1). ...
                    ImagePath = pathstr;
            end
            if ispc
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1). ...
                    ImageNames{CurrentImage,1} = CurrentItem.ReferencedFileID;
            else
                dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1). ...
                    ImageNames{CurrentImage,1} = strrep(CurrentItem.ReferencedFileID,'\','/');
            end
            %ImageNames{CurrentImage,1} = dcmfname;
            dcmPatient(CurrentPatient,1).Study(CurrentStudy,1).Series(CurrentSeries,1). ...
                ReferencedSOPInstanceUIDInFile{CurrentImage,1} = CurrentItem.ReferencedSOPInstanceUIDInFile;
            %%%
        end
        waitbar(i/NumOfField,waitbar_h);
        drawnow;
    end
    close(waitbar_h);

    try
        dcmdir.dcmPatient = dcmPatient;
        save(filename1mat,dcmdir);
    catch
        % Unable to write file 'filename1mat' permission denied.
    end

end

global dcmVal;
dcmVal = 0;

if size(dcmPatient,1) > 1
    selectPatientFigure = figure('Units','normalized','menubar','none',...
        'NumberTitle','off','name','selectPatient',...
        'position',[2/8, 3/8, 4/8, 2/8]);
    uicontrol('Parent',selectPatientFigure,'Units','normalized','Style','text',...
        'String','Select which patient you are analysing?','Position',[0.1 0.7 0.8 0.2]);
    String  = sprintf('%s|', dcmPatient.('PatientName'));
    String(end) = [];
    lbh = uicontrol('Parent',selectPatientFigure,'Units','normalized','Style','popupmenu',...
        'String',String,'Position',[0.1 0.4 0.8 0.2],'tag','patientList');
    okCloseCallback = 'global dcmVal; dcmVal = get(findobj(''tag'',''patientList''),''value''); delete(findobj(''name'',''selectPatient''));';
    uicontrol('Parent',selectPatientFigure,'Units','normalized','Style','pushbutton','String','OK','Position',[0.1 0.1 0.8 0.2],'Callback',okCloseCallback);
    uiwait(selectPatientFigure);
else
    dcmVal = 1;
end

dcmPatient = dcmPatient(dcmVal,:);

clearvars -except dcmPatient dicomdirpath

set(0,'DefaultFigureWindowStyle','normal');

screensize = get(0,'ScreenSize');
dcmdirlistfh = figure('Units','normalized','menubar','none','NumberTitle','off',...
    'name','DICOMDIR info','position',[0.1, 0.1, 0.8, 0.8]);

lbh = uicontrol('Parent',dcmdirlistfh,'Units','normalized','Style','listbox',...
    'Position',[0.05, 0.09, 0.45, 0.88 ],'tag','dcmdirlist_popupmenu');

[seriesDescriptions,order] = sort({dcmPatient.Study.Series.SeriesDescription});
dcmPatient.Study.Series = dcmPatient.Study.Series(order);

set(lbh,'string',seriesDescriptions,'max',1.1);

global dcmdirlistVal;
dcmdirlistVal = 0;

OKCallback = 'global a; a = 1; global dcmdirlistVal; dcmdirlistVal = get(findobj(''tag'',''dcmdirlist_popupmenu''),''value''); delete(findobj(''name'',''DICOMDIR info'')); return;';
CancelCallback = 'global a; a = 1; delete(findobj(''name'',''DICOMDIR info''));';
OK_h = uicontrol('Parent',dcmdirlistfh,'Units','normalized','Style','pushbutton',...
    'String','OK','Position',[0.15, 0.03, 0.2, 0.03],'Callback',OKCallback);
Cancel_h = uicontrol('Parent',dcmdirlistfh,'Units','normalized','Style','pushbutton',...
    'String','Cancel','Position',[0.65, 0.03, 0.2, 0.03],'Callback',CancelCallback);

global a
a = 0;
axes1 = axes('Parent',dcmdirlistfh,'Units','normalized','Position',[0.55, 0.55, 0.4, 0.4]); axis square;
while a == 0
    dcmdirlistVal = get(findobj('tag','dcmdirlist_popupmenu'),'value');
    pause(0.1);
    if length(dcmdirlistVal) >= 1.1
        continue
    end
    try
        imageCurrent = double(uint16(dicomread(fullfile(dicomdirpath,dcmPatient.Study.Series(dcmdirlistVal).ImageNames{1}))));
        imagesc(imageCurrent); axis square; colormap gray; axis off;
        pause(0.1);

        strDetails = sprintf('File Location : %s \n\n Series Description : %s \n\n Number of Frames : %s \n\n ',...
            num2str(fullfile(dicomdirpath,dcmPatient.Study.Series(dcmdirlistVal).ImageNames{1})),...
            num2str(dcmPatient.Study.Series(dcmdirlistVal).SeriesDescription),...
            num2str(numel(dcmPatient.Study.Series(dcmdirlistVal).ImageNames)));

        uicontrol('Parent',dcmdirlistfh,'Units','normalized','Style','text',...
            'Position',[0.55, 0.09, 0.4, 0.4],'String',strDetails,'FontWeight','bold');
    end
end

close all;

if dcmdirlistVal == 0;
    disp('No DICOM Series was selected!');
    return;
end

seriesData = dcmPatient.Study.Series(dcmdirlistVal);

end


classdef RoiPoolingFreeform < dagnn.Layer
    % This layer has to be used AFTER the ROIPoolingFreeform.
    % It applies a mask to the roi-pooled activations, taking either fg, bg
    % or both of the image.
    %
    % inputs are: rois, masks, blobMasks
    % outputs are: rois
    %
    % Copyright by Holger Caesar, 2015

    properties
        combineFgBox = false;
    end

    properties (Transient)
        mask
    end

    methods
        function outputs = forward(obj, inputs, params) %#ok<INUSD>
            assert(numel(inputs) == 3);
            [outputs{1}, obj.mask] = roiPooling_freeform_forward(inputs{1}, inputs{2}, inputs{3}, obj.combineFgBox);
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs) %#ok<INUSL>
            assert(numel(derOutputs) == 1);
            derInputs{1} = roiPooling_freeform_backward(derOutputs{1}, obj.combineFgBox);
            derInputs{2} = [];
            derInputs{3} = [];
            derParams = {} ;
        end

        function obj = RoiPoolingFreeform(varargin)
            obj.load(varargin) ;
        end
    end
end


%{
 * Copyright (C) 2020-2030, The Regents of The University of Michigan.
 * All rights reserved.
 * This software was developed in the Biped Lab (https://www.biped.solutions/)
 * under the direction of Jessy Grizzle, grizzle@umich.edu. This software may
 * be available under alternative licensing terms; contact the address above.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * The views and conclusions contained in the software and documentation are those
 * of the authors and should not be interpreted as representing official policies,
 * either expressed or implied, of the Regents of The University of Michigan.
 *
 * AUTHOR: Bruce JK Huang (bjhuang[at]umich.edu)
 * WEBSITE: https://www.brucerobot.com/
%}

function opt = optimizeCost(opt, X, target_size, box_width)

    R_init = rotx(opt.rpy_init(1)) * roty(opt.rpy_init(2)) * rotz(opt.rpy_init(3));
    opt.H_init(1:3, 1:3) = R_init;

    if opt.UseCentroid
        centroid = mean(X, 2);
        opt.H_init(1:3, 4) = -centroid(1:3);
    else
        opt.H_init(1:3, 4) = opt.T_init;
    end

    switch opt.method
        case 'Customize'
            opt.metric = "PointToAxis";
            opt.unit = "L1-inspired";
            tic;
            optimizeCustomizedCost(opt);
            opt.computation_time = toc;
        case 'Constraint Customize'
            opt.metric = "PointToAxis";
            opt.unit = "L1-inspired";
            tic;
            opt = optimizeConstraintCustomizedCost(opt, X, target_size, box_width);
            opt.computation_time = toc;
        case 'The Wall'
            opt.metric = "PointToAxis";
            opt.unit = "L1-inspired";
            tic;
            opt = optimizeBoundaries(opt, opts, X);
            opt.computation_time = toc;
        case 'Coherent Point Drift'
            opt.metric = "--";
            opt.unit = "RMSE";
            tic;
            optimizeCPD(opt);
            opt.computation_time = toc;
        case 'Iterative Closest Point (point)'
            opt.metric = "PointToPoint";
            opt.unit = "RMSE";
            tic;
            optimizeICPPoint(opt);
            opt.computation_time = toc;
        case 'Iterative Closest Point (plane)'
            opt.metric = "PointToPlane";
            opt.unit = "RMSE";
            tic;
            optimizeICPPlane(opt);
            opt.computation_time = toc;
        case 'Normal-distributions Transform'
            opt.metric = "--";
            opt.unit = "RMSE";
            tic;
            optimizeNDT(opt);
            opt.computation_time = toc;
        case 'GICP-SE3'
            tic;
            optimizeGICP_SE3(opt)
            opt.computation_time = toc;
        case 'GICP-SE3 (plane)'
            tic;
            optimizeGICPPlane_SE3(opt)
            opt.computation_time = toc;
        case 'GICP-SE3-costimized'
            tic;
            optimizeCustomizedGICP_SE3(opt);
            opt.computation_time = toc;
        case 'Two Hollow Strips'
            tic;
            optimizeHollowStrips(opt);
            opt.computation_time = toc;
        case '3D IoU'
        case 'Project'
            tic;
            OptimizeUsingRobustNormalVector(opt);
            opt.computation_time = toc;
        otherwise
            disp('no such optimization method')
            return
    end
end


function sys = assignschur(AConstraint,thecompiler,varargin)

sys = sdpvar(1);
sys.typeflag = 30;
Schurfun_defined = 0;
Var_defined = 0;

for i = 1:nargin
    if isa(varargin{i},'sdpvar')
        sys.extra.variables{i} = varargin{i};
        Var_defined = 1;
    elseif isa(varargin{i},'double')
        sys.extra.data{i} = varargin{i};
    elseif isa(varargin{i},'char')
        sys.extra.Schurfun = varargin{i};
        Schurfun_defined = 1;
    end
end
sys.extra.negated = 0;

if ~Schurfun_defined
    error('A Schur-function must be defined.')
end

sys = constraint(sys,'>=',0);


function [str,iter]=display(comp,tab,iter)

  global display_tree_array_indexing;
  if isempty(display_tree_array_indexing)
      display_tree_array_indexing=2;
  end;
  global display_tree_index_at_front;
  if isempty(display_tree_index_at_front)
      display_tree_index_at_front=1;
  end;

  if nargin==3
   if isempty(iter)
    iter{1}=[];
   else
      i=length(iter);
      iter{i+1}=iter{i};  %% <--- new member of tree
   end
   if display_tree_array_indexing==0
     if isempty(iter{length(iter)})
      index=[];
     else
      index=[num2str(length(iter)-1) ':'];
     end
     if display_tree_index_at_front
      str=[ index get_name(comp) '\n'];
     else
      str=[ get_name(comp) ' (' index(length(index))  ')\n'];
     end;
   else
     index=[];
     if ~isempty(iter{length(iter)})
      index= num2str(iter{length(iter)});

      a=findstr('  ',index);
      a=setdiff([1:length(index)],a); index=index(a);

      if display_tree_array_indexing==2
    	a=find(index==32);
        if isempty(a)
            a=0;
        end;
	    index=index(max(a)+1:length(index));
      else
        index=['[' index ']'];
      end
      index=[index ':'];
     end;
     if display_tree_index_at_front
       str=[ index  get_name(comp) '\n'];
     else
       str=[ get_name(comp)  ' ' index(1:length(index)-1)  '\n'];
     end;
   end

  else
   disp([get_name(comp)]);
  end


function [AerobicGrowth, AnaerobicGrowth] = testGrowth(model, biomassReaction)
% Tests growth, both on unlimited media and complex medium, both aerobic and
% anaerobic conditions. In anaerobic conditions, both oxygen uptake
% (exchange reaction) and cytosolic oxygen-utilizing reactions are blocked.
%
% USAGE
%           [AerobicGrowth, AnaerobicGrowth] = testGrowth(model, biomassReaction)
%
% INPUT
% model             COBRA model structure
% biomassReaction   String listing the biomass reaction
%
% OUTPUT
% AerobicGrowth     Numeric vector showing the flux through the biomass
%                   reaction (aerobic conditions):
%                   Column 1: "unlimited" media (all exchanges to -1000
%                   mmol/gDW/h)
%                   Column 2: complex medium as defined in
%                   InputFiles\ComplexMedium.txt
% AnaerobicGrowth   Numeric vector showing the flux through the biomass
%                   reaction (anaerobic conditions):
%                   Column 1: "unlimited" media (all exchanges to -1000
%                   mmol/gDW/h)
%                   Column 2: complex medium as defined in
%                   InputFiles\ComplexMedium.txt
%
% Stefania Magnusdottir, Nov 2017

tol=0.000001;

AerobicGrowth = zeros(1, 2);
AnaerobicGrowth = zeros(1, 2);

% Test if model can grow
% set "unlimited" constraints
model = changeRxnBounds(model, model.rxns(strncmp('EX_', model.rxns, 3)), -1000, 'l');
model = changeRxnBounds(model, model.rxns(strncmp('EX_', model.rxns, 3)), 1000, 'u');

% set objective
if nargin < 2
    error('Please provide biomass reaction')
end
if ~any(ismember(model.rxns, biomassReaction))
  %  error(['Biomass reaction "', biomassReaction, '" not found in model.'])
else
    model = changeObjective(model, biomassReaction);
end

% aerobic environment
modelO2 = changeRxnBounds(model, 'EX_o2(e)', -10, 'l');

% simulate
FBA = optimizeCbModel(modelO2, 'max');
if FBA.stat==1
    AerobicGrowth(1, 1) = FBA.f;
    if FBA.f > tol
        fprintf('Model grows on unlimited media (aerobic), flux through BOF: %d mmol/gDW/h\n', FBA.f)
    else
        warning('Model cannot grow on unlimited media (aerobic)')
    end
else
    warning('Model cannot grow on unlimited media (aerobic)')
end

% anaerobic environment
modelNoO2 = changeRxnBounds(model, 'EX_o2(e)', 0, 'l');

% simulate
FBA = optimizeCbModel(modelNoO2, 'max');
if FBA.stat==1
    AnaerobicGrowth(1, 1) = FBA.f;
    if FBA.f > tol
        fprintf('Model grows on unlimited media (anaerobic), flux through BOF: %d mmol/gDW/h\n', FBA.f)
    else
        warning('Model cannot grow on unlimited media (anaerobic)')
    end
else
    warning('Model cannot grow on unlimited media (anaerobic)')
end

% implement complex medium
constraints = readtable('ComplexMedium.txt', 'Delimiter', 'tab');
constraints=table2cell(constraints);
constraints=cellstr(string(constraints));

% apply complex medium
model = useDiet(model,constraints);

% aerobic environment
modelO2 = changeRxnBounds(model, 'EX_o2(e)', -10, 'l');

% simulate
FBA = optimizeCbModel(modelO2, 'max');
if FBA.stat==1
    AerobicGrowth(1, 2) = FBA.f;
    if FBA.f > tol
        fprintf('Model grows on complex medium (aerobic), flux through BOF: %d mmol/gDW/h\n', FBA.f)
    else
        warning('Model cannot grow on complex medium (aerobic)')
    end
else
    warning('Model cannot grow on complex medium (aerobic)')
end

% anaerobic environment
modelNoO2 = changeRxnBounds(model, 'EX_o2(e)', 0, 'l');

% simulate
FBA = optimizeCbModel(modelNoO2, 'max');
if FBA.stat==1
    AnaerobicGrowth(1, 2) = FBA.f;
    if FBA.f > tol
        fprintf('Model grows on complex medium (anaerobic), flux through BOF: %d mmol/gDW/h\n', FBA.f)
    else
        warning('Model cannot grow on complex medium (anaerobic)')
    end
else
    warning('Model cannot grow on complex medium (anaerobic)')
end

end


function err = save_nifti(hdr,niftifile)
% err = save_nifti(hdr,niftifile)
%
% Pixel data should be in hdr.vol
%
% Handles data structures with more than 32k cols by setting
% hdr.dim(2) = -1 and hdr.glmin = ncols. This is FreeSurfer specific,
% for handling surfaces. The exception to this is when the total
% number of spatial voxels equals 163842, then the volume is
% reshaped to 27307x1x6xnframes. This is for handling the 7th
% order icosahedron used by FS group analysis.
%
% $Id: save_nifti.m,v 1.14 2011/10/17 19:58:37 nicks Exp $

%
% save_nifti.m
%
% Original Author: Doug Greve
% CVS Revision Info:
%    $Author: nicks $
%    $Date: 2011/10/17 19:58:37 $
%    $Revision: 1.14 $
%
% Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH"
%
% Terms and conditions for use, reproduction, distribution and contribution
% are found in the 'FreeSurfer Software License Agreement' contained
% in the file 'LICENSE' found in the FreeSurfer distribution, and here:
%
% https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense
%
% Reporting: freesurfer@nmr.mgh.harvard.edu
%

err = 1;
if(nargin ~= 2)
  fprintf('err = save_nifti(hdr,niftifile)\n');
  return;
end

ext = niftifile((strlen(niftifile)-2):strlen(niftifile));
if(strcmpi(ext,'.gz'))
  gzip_needed = 1;
  niftifile = niftifile(1:strlen(niftifile)-3);
  %fprintf('First, saving to %s before compressing\n',niftifile);
else
  gzip_needed = 0;
end

% Check for ico7
sz = size(hdr.vol);
if(sz(1) == 163842)
  %fprintf('save_nifti: ico7 reshaping\n');
  dim = [27307 1 6 size(hdr.vol,4)];
  hdr.vol = reshape(hdr.vol, dim);
end

fp = fopen(niftifile,'w');
if(fp == -1)
  fprintf('ERROR: could not open %s\n',niftifile);
  return;
end

hdr.data_type = [hdr.data_type(:)' repmat(' ',[1 10])];
hdr.data_type = hdr.data_type(1:10);

hdr.db_name = [hdr.db_name(:)' repmat(' ',[1 18])];
hdr.db_name = hdr.db_name(1:18);

hdr.dim = ones(1,8);
hdr.dim(1) = 4;
hdr.dim(2) = size(hdr.vol,1);
hdr.dim(3) = size(hdr.vol,2);
hdr.dim(4) = size(hdr.vol,3);
hdr.dim(5) = size(hdr.vol,4);

% This is to accomodate structures with more than 32k cols
% FreeSurfer specific. See also mriio.c.
if(hdr.dim(2) > 2^15)
  hdr.glmin = hdr.dim(2);
  hdr.dim(2) = -1;
end

hdr.pixdim = [hdr.pixdim(:)' repmat(0,[1 8])];
hdr.pixdim = hdr.pixdim(1:8);

hdr.descrip = [hdr.descrip(:)' repmat(' ',[1 80])];
hdr.descrip = hdr.descrip(1:80);

hdr.aux_file = [hdr.aux_file(:)' repmat(' ',[1 24])];
hdr.aux_file = hdr.aux_file(1:24);

hdr.intent_name = [hdr.intent_name(:)' repmat(' ',[1 16])];
hdr.intent_name = hdr.intent_name(1:16);

hdr.magic = [hdr.magic(:)' repmat(0,[1 4])];
hdr.magic = hdr.magic(1:4);

if(isempty(hdr.regular))  hdr.regular  = ' '; end
if(isempty(hdr.dim_info)) hdr.dim_info = ' '; end
if(isempty(hdr.slice_code)) hdr.slice_code = ' '; end
if(isempty(hdr.xyzt_units)) hdr.xyzt_units = ' '; end % should be err

hdr.vox_offset = 352; % not 348
fwrite(fp,348,'int');
fwrite(fp,hdr.data_type,    'char');
fwrite(fp,hdr.db_name,      'char');
fwrite(fp,hdr.extents,      'int');
fwrite(fp,hdr.session_error,'short');
fwrite(fp,hdr.regular,      'char');
fwrite(fp,hdr.dim_info,     'char');
fwrite(fp,hdr.dim,          'short');
fwrite(fp,hdr.intent_p1,    'float');
fwrite(fp,hdr.intent_p2,    'float');
fwrite(fp,hdr.intent_p3,    'float');
fwrite(fp,hdr.intent_code,  'short');
fwrite(fp,hdr.datatype,     'short');
fwrite(fp,hdr.bitpix,       'short');
fwrite(fp,hdr.slice_start,  'short');
fwrite(fp,hdr.pixdim,       'float');
fwrite(fp,hdr.vox_offset,   'float');
fwrite(fp,hdr.scl_slope,    'float');
fwrite(fp,hdr.scl_inter,    'float');
fwrite(fp,hdr.slice_end,    'short');
fwrite(fp,hdr.slice_code,   'char');
fwrite(fp,hdr.xyzt_units,   'char');
fwrite(fp,hdr.cal_max,      'float');
fwrite(fp,hdr.cal_min,      'float');
fwrite(fp,hdr.slice_duration,'float');
fwrite(fp,hdr.toffset,       'float');
fwrite(fp,hdr.glmax,         'int');
fwrite(fp,hdr.glmin,         'int');
fwrite(fp,hdr.descrip,       'char');
fwrite(fp,hdr.aux_file,      'char');
fwrite(fp,hdr.qform_code,    'short');
fwrite(fp,hdr.sform_code,    'short');
fwrite(fp,hdr.quatern_b,     'float');
fwrite(fp,hdr.quatern_c,     'float');
fwrite(fp,hdr.quatern_d,     'float');
fwrite(fp,hdr.quatern_x,     'float');
fwrite(fp,hdr.quatern_y,     'float');
fwrite(fp,hdr.quatern_z,     'float');
fwrite(fp,hdr.srow_x,        'float');
fwrite(fp,hdr.srow_y,        'float');
fwrite(fp,hdr.srow_z,        'float');
fwrite(fp,hdr.intent_name,   'char');
fwrite(fp,hdr.magic,         'char');

% Pad to get to 352 bytes (header size is 348)
fwrite(fp,0,'char');
fwrite(fp,0,'char');
fwrite(fp,0,'char');
fwrite(fp,0,'char');

npix = prod(size(hdr.vol));
switch(hdr.datatype)
 case   2, nitemswritten = fwrite(fp,hdr.vol,'uchar'); % dont use char
 case   4, nitemswritten = fwrite(fp,hdr.vol,'short');
 case   8, nitemswritten = fwrite(fp,hdr.vol,'int');
 case  16, nitemswritten = fwrite(fp,hdr.vol,'float');
 case  64, nitemswritten = fwrite(fp,hdr.vol,'double');
 case 512, nitemswritten = fwrite(fp,hdr.vol,'ushort');
 case 768, nitemswritten = fwrite(fp,hdr.vol,'uint');
 otherwise,
  fprintf('WARNING: data type %d not supported, but writing as float',...
	  hdr.datatype);
  nitemswritten = fwrite(fp,hdr.vol,'float');
  return;
end
fclose(fp);

if(npix ~= nitemswritten)
  fprintf('ERROR: tried to write %d, but only wrote %d',npix,nitemswritten);
  return;
end

if(gzip_needed)
  cmd = sprintf('gzip -f %s', niftifile);
  %fprintf('Compressing with\n');
  %fprintf('   %s\n',cmd);
  unix(cmd);
end

err = 0;
return;


function C = getAutoCovMat(hmm,k,verbose)
% Get the autocovariance from a TDE-HMM model, for state k,
%
% Diego Vidaurre, OHBA, University of Oxford (2019)

if nargin < 3, verbose = 1; end
C = getFuncConn(hmm,k,verbose);

end


classdef IsosurfaceOptionsDialog < handle
%ISOSURFACEOPTIONSDIALOG Dialog for 3D isosurfaces of intensity images
%
%   Class IsosurfaceOptionsDialog
%
%   Example
%   IsosurfaceOptionsDialog
%
%   See also
%     IsosurfaceOptionsDialog
%

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2013-04-19,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2013 INRA - Cepia Software Platform.

%% Properties
properties
    IsosurfaceValue = 0;

    Parent;

    Handles;
end % end properties

%% Constructor
methods
    function obj = IsosurfaceOptionsDialog(parent, varargin)
    % Constructor for IsosurfaceOptionsDialog class

         % call parent constructor to initialize members
        obj = obj@handle();
        obj.Parent = parent;

        % pre-compute initial value of isosurface (from Otsu threshold)
        obj.IsosurfaceValue = imOtsuThreshold(obj.Parent.ImageData);

        % create default figure
        fig = figure(...
            'MenuBar', 'none', ...
            'NumberTitle', 'off', ...
            'HandleVisibility', 'On', ...
            'Name', 'Isosurface Options', ...
            'CloseRequestFcn', @obj.close);
        obj.Handles.Figure = fig;

        setupLayout(fig);

        function setupLayout(hf)
            % Setup layout of figure widgets

            pos = get(hf, 'Position');
            pos(3:4) = [200 180];
            set(hf, 'Position', pos);
            set(hf, 'Units', 'normalized');

            if verLessThan('matlab', 'R2014b')
                mainPanel = uiextras.VBox('Parent', hf);
            else
                mainPanel = uix.VBox('Parent', hf);
            end

            % control panel: use vertical layout
            if verLessThan('matlab', 'R2014b')
                optionsPanel = uiextras.VButtonBox('Parent', mainPanel, ...
                    'ButtonSize', [150 30], ...
                    'VerticalAlignment', 'top', ...
                    'HorizontalAlignment', 'center', ...
                    'Spacing', 5, 'Padding', 5);
            else
                optionsPanel = uix.VButtonBox('Parent', mainPanel, ...
                    'ButtonSize', [150 30], ...
                    'VerticalAlignment', 'top', ...
                    'HorizontalAlignment', 'center', ...
                    'Spacing', 5, 'Padding', 5);
            end

            obj.Handles.ThresholdText = uicontrol(...
                'Style', 'text', 'Parent', optionsPanel, ...
                'String', 'Isosurface Value:', ...
                'HorizontalAlignment', 'Left');

            obj.Handles.IsosurfaceValue = uicontrol(...
                'Style', 'edit', 'Parent', optionsPanel, ...
                'String', num2str(obj.IsosurfaceValue), ...
                'Value', 1, ...
                'HorizontalAlignment', 'Left');

            obj.Handles.ReverseZAxis = uicontrol(...
                'Style', 'checkbox', 'Parent', optionsPanel, ...
                'String', 'Reverse Z-axis', ...
                'Value', 1, ...
                'HorizontalAlignment', 'Left');

            obj.Handles.RotateOx = uicontrol(...
                'Style', 'checkbox', 'Parent', optionsPanel, ...
                'String', 'Rotate around X-axis', ...
                'Value', 1, ...
                'HorizontalAlignment', 'Left');

            obj.Handles.Smooth = uicontrol(...
                'Style', 'checkbox', 'Parent', optionsPanel, ...
                'String', 'Smooth', ...
                'Value', 1, ...
                'HorizontalAlignment', 'Left');

            obj.Handles.ShowAxisLabel = uicontrol(...
                'Style', 'checkbox', 'Parent', optionsPanel, ...
                'String', 'Show axes label', ...
                'Value', 0, ...
                'HorizontalAlignment', 'Left');

            % add control panel with "Compute" and "Close" buttons
            if verLessThan('matlab', 'R2014b')
                buttonsPanel = uiextras.HButtonBox('Parent', mainPanel, ...
                    'ButtonSize', [70 30], ...
                    'VerticalAlignment', 'top', ...
                    'Spacing', 5, 'Padding', 5, ...
                    'Units', 'normalized', ...
                    'Position', [0 0 1 1]);
            else
                buttonsPanel = uix.HButtonBox('Parent', mainPanel, ...
                    'ButtonSize', [70 30], ...
                    'VerticalAlignment', 'top', ...
                    'Spacing', 5, 'Padding', 5, ...
                    'Units', 'normalized', ...
                    'Position', [0 0 1 1]);
            end

            obj.Handles.ApplyButton = uicontrol('Style', 'PushButton', ...
                'Parent', buttonsPanel, ...
                'String', 'Compute', ...
                'Enable', 'on', ...
                'Callback', @obj.onApplyButtonClicked);
            obj.Handles.CloseButton = uicontrol('Style', 'PushButton', ...
                'Parent', buttonsPanel, ...
                'String', 'Close', ...
                'Callback', @obj.close);

            if verLessThan('matlab', 'R2014b')
                mainPanel.Sizes = [-1 40];
            else
                mainPanel.Heights = [-1 40];
            end

        end
    end

end % end constructors

%% Methods
methods
    function onApplyButtonClicked(obj, hObject, eventdata) %#ok<INUSD>

        % first, disable "compute" button to avoid multiple calls
        set(obj.Handles.ApplyButton, 'enable', 'off');
        hDlg = msgbox({'Computing isosurfaces,', 'Please wait...'}, ...
            'Isosurface computing');

        % extract options from widgets
        str = get(obj.Handles.IsosurfaceValue, 'String');
        [value, flag] = str2num(str);
        if ~flag
            error(['Could not parse isosurface value from: ' str]);
        end
        reverseZAxis = get(obj.Handles.ReverseZAxis, 'Value');
        rotateXAxis = get(obj.Handles.RotateOx, 'Value');
        smooth = get(obj.Handles.Smooth, 'Value');
        showAxesLabel = get(obj.Handles.ShowAxisLabel, 'Value');

        % get image data stored in parent Slicer
        imgData = obj.Parent.ImageData;
        imgSize = obj.Parent.ImageSize;

        % avoid the case of empty image
        if isempty(imgData)
            return;
        end

        % eventually rotate image around X-axis
        if rotateXAxis
            imgData = stackRotate90(imgData, 'x', 1);
            imgSize = imgSize([1 3 2]);
        end

        % compute display settings
        spacing = obj.Parent.VoxelSize;
        origin  = obj.Parent.VoxelOrigin;

        % compute grid positions
        lx = (0:imgSize(1)-1) * spacing(1) + origin(1);
        ly = (0:imgSize(2)-1) * spacing(2) + origin(2);
        lz = (0:imgSize(3)-1) * spacing(3) + origin(3);

        if rotateXAxis
            ly = ly(end:-1:1);
        end

        % determine the color map to use (default is empty)
        cmap = [];
        if ~isColorStack(imgData) && ~isempty(obj.Parent.ColorMap)
            cmap = obj.Parent.ColorMap;
        end
        if isempty(cmap)
            cmap = jet(256);
        end

        % create figure
        hf = figure(); hold on;
        set(hf, 'renderer', 'opengl');

        % compute isosurface
        im = imgData >= value;
        if ~any(im)
            return;
        end

        if smooth
            im = imGaussianFilter(double(im), [5 5 5], 2);
        end

        % display isosurface
        p = patch(isosurface(lx, ly, lz, im, .5));

        % set face color
        set(p, 'FaceColor', cmap(end,:), 'EdgeColor', 'none');

        % compute display extent (add a 0.5 limit around each voxel)
        extent = stackExtent(imgSize, spacing, origin);

        % setup display
        axis equal;
        axis(extent);
        view(3);
        axis('vis3d');

        light;

        if rotateXAxis || reverseZAxis
            set(gca, 'zdir', 'reverse');
        end

        if showAxesLabel
            xlabel('X axis');
            if rotateXAxis
                ylabel('Z Axis');
                zlabel('Y Axis');
            else
                ylabel('Y Axis');
                zlabel('Z Axis');
            end
        end

        % re-enable "apply" button
        set(obj.Handles.ApplyButton, 'enable', 'on');
        if ishandle(hDlg)
            close(hDlg);
        end

    end

end % end methods

%% Figure management
methods
    function close(obj, varargin)
        delete(obj.Handles.Figure);
    end

end

end % end classdef


function su_hdr = GE_readHeaderSuite(fid, byte_align)
%
% su_hdr = GE_readHeaderSuite(fid, byte_align)
%
% Loads the suite header from the file with filed id fid
% and returns it as a structure.
% if byte_align = 1 then 32-bit alignment (SGI, LX2 format)
% if byte_align = 0 then 16-bit alignment (Sun, 5.X format)
%
%
% Souheil J. Inati
% Dartmouth College
% May 2000
% souheil.inati@dartmouth.edu
%

% define the structure and read
su_hdr = struct('su_id', fread(fid,4,'char'));                   % Suite ID
su_hdr = setfield(su_hdr, 'su_uniq', fread(fid,1,'int16'));      % The Make-Unique Flag
su_hdr = setfield(su_hdr, 'su_diskid', fread(fid,1,'char'));     % Disk ID
su_hdr = setfield(su_hdr, 'prodid', fread(fid,13,'char'));       % Product ID
su_hdr = setfield(su_hdr, 'su_verscre', fread(fid,2,'char'));    % Genesis Version
su_hdr = setfield(su_hdr, 'su_verscur', fread(fid,2,'char'));    % Genesis Version
su_hdr = setfield(su_hdr, 'su_checksum', fread(fid,1,'uint32')); % Suite  Record Checksum
su_hdr = setfield(su_hdr, 'su_padding', fread(fid,85,'char'));   % Spare Space
fseek(fid,1,0); % 16-bit alignment
if byte_align, fseek(fid,2,0); end % 32-bit alignment

return


%DEFINITIONS_POLYGONS  One-line description here, please.
%
%   output = definitions_polygons(input)
%
%   Example
%   definitions_polygons
%
%   See also
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% INRAE - BIA Research Unit - BIBS Platform (Nantes)
% Created: 2022-02-14,    using Matlab 9.10.0.1739362 (R2021a) Update 5
% Copyright 2022 INRAE.

% create polygon
poly = [

% set up display
figure(1); clf; hold on;
axis equal; axis([20 230 70 230]);