% A single JIDE property field in a JIDE property grid.
% This is an internal class and is not intended to be used directly.
%
% References:
% http://www.jidesoft.com/products/JIDE_Grids_Developer_Guide.pdf
%
% See also: PropertyGrid

% Copyright 2010 Levente Hunyadi
classdef JidePropertyGridField < handle
    properties
        % A PropertyGridField instance.
        PropertyData;
    end
    properties (Dependent)
        Value;
    end
    properties (Access = private)
        % Children the property field might have.
        Children = JidePropertyGridField.empty(0,1);
        % A JIDE DefaultProperty instance.
        Control;
        % JIDE editor context (if any).
        Context;
        % JIDE editor context type (if any).
        ContextType;
    end
    methods
        function self = JidePropertyGridField(data)
            if nargin > 0
                self.Initialize(data);
            end
        end

        function self = Initialize(self, data)
        % Initializes a JIDE property based on a property grid field.
        % May register editor contexts with the global CellEditorManager.
            validateattributes(self, {'JidePropertyGridField'}, {'scalar'});

            self.PropertyData = data;
            field = com.jidesoft.grid.DefaultProperty();
            field.setName(data.Name);  % JIDE automatically uses a hierarchical naming scheme
            field.setCategory(data.Category);
            field.setDisplayName(data.DisplayName);
            field.setDescription(data.Description);
            field.setEditable(~data.ReadOnly);
            switch data.Type.Shape
                case 'scalar'
                    switch data.Type.PrimitiveType
                        case {'denserealdouble','sparserealdouble'}  % add a double-precision floating point property
                            matlabtype = 'double';  % MatLab type that is marshalled to Java
                        case {'denserealsingle','sparserealsingle'}  % add a single-precision floating point property
                            matlabtype = 'single';
                        case {'int8','uint8','int16'}
                            matlabtype = 'int16';
                        case {'uint16','int32'}  % add an integer property
                            matlabtype = 'int32';
                        case {'uint32','int64'}
                            matlabtype = 'int64';
                        case 'logical'  % add a logical property
                            matlabtype = 'logical';
                            field.setEditorContext(com.jidesoft.grid.BooleanCheckBoxCellEditor.CONTEXT);
                        case {'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle'}
                            matlabtype = [];
                            field.setType(javaclass('char',1));  % edit as string and convert with eval
                        otherwise
                            matlabtype = [];
                            field.setEditable(false);
                            %error('PropertyGrid:ArgumentTypeMismatch', 'Scalar %s is not supported.', data.Type.PrimitiveType);
                    end
                    if ~isempty(matlabtype)
                        javatype = javaclass(matlabtype);
                        field.setType(javatype);
                        if ~isempty(data.Type.Domain)
                            if iscell(data.Type.Domain)  % explicit enumeration of domain elements
                                self.AddComboBoxEditor(field, javatype, data.Type.Domain);
                            elseif isnumeric(data.Type.Domain) && isinteger(data.Type)  % domain expressed as interval
                                self.AddSpinnerEditor(field, javatype, min(data.Type.Domain), max(data.Type.Domain));
                            end
                        end
                    end
                case {'row','column'}
                    InitializeVector(self, field);
                case 'matrix'
                    InitializeMatrix(self, field);
                case 'empty'
                    field.setEditable(false);
                otherwise
                    error('PropertyGrid:ArgumentTypeMismatch', 'Data shape %s is not supported.', data.Type.Shape);
            end
            self.Control = field;
            self.Value = data.Value;

            for k = 1 : numel(data.Children)
                self.Children(k) = JidePropertyGridField(data.Children(k));
                self.Control.addChild(self.Children(k).Control);
            end
        end

        function delete(self)
        % Deallocates registered editor contexts.
            if ~isempty(self.Context)
                com.jidesoft.grid.CellEditorManager.unregisterEditor(self.ContextType, self.Context);
            end
        end

        function value = get.Value(self)
        % Gets the native MatLab value of a property.
            javavalue = self.Control.getValue();
            [value,stringconversion] = self.PropertyData.Type.ConvertFromJava(javavalue);
            if stringconversion  % display pretty-formatted value
                javavalue = self.PropertyData.Type.ConvertToJava(value);
                self.Control.setValue(javavalue);
            end
        end

        function set.Value(self, value)
        % Sets the Java value of a property based on the native value.
            javavalue = self.PropertyData.Type.ConvertToJava(value);
            self.Control.setValue(javavalue);
        end

        function tf = CanAccept(self, value)
        % Tests if the property can be assigned the native value.
        %
        % Input arguments:
        % value:
        %    a native MatLab value
            validateattributes(self, {'JidePropertyGridField'}, {'scalar'});
            tf = self.PropertyData.Type.CanAccept(value);
        end

        function self = FindByName(selfarray, name)
        % Finds the property field with the given name in an array.
            self = selfarray.FindByNameRecurse(strsplit(name, '.'));
        end

        function properties = GetProperties(selfarray)
            properties = PropertyGridField.empty(0,1);
            for k = 1 : numel(selfarray)
                properties(k) = selfarray(k).PropertyData;
            end
        end

        function list = GetTableModel(selfarray)
            n = numel(selfarray);
            ctrls = cell(1,n);
            for k = 1 : n
                ctrls{k} = selfarray(k).Control;
            end
            list = javaArrayList(ctrls);
        end
    end
    methods (Access = private)
        function self = FindByNameRecurse(selfarray, nameparts)
            names = getclassfield(getclassfield(selfarray, 'PropertyData'), 'Name');
            ix = strmatch(nameparts{1}, names, 'exact');
            if isempty(ix)
                self = JidePropertyGridField.empty(0,1);
                return;
            end
            ix = ix(1);
            namerest = nameparts(2:end);
            if isempty(namerest)
                self = selfarray(ix);
            else
                self = selfarray(ix).Children.FindByNameRecurse(namerest);
            end
        end

        function InitializeVector(self, field)
            data = self.PropertyData;
            switch data.Type.PrimitiveType
                case 'char'  % add a string property
                    switch data.Type.Shape
                        case 'row'
                            field.setType(javaclass('char',1));
                            if ~isempty(data.Type.Domain)
                                self.AddComboBoxEditor(field, javaclass('char',1), javaStringArray(data.Type.Domain));
                            end
                        otherwise
                            field.setType(javaclass('char',1));  % edit as string and convert with eval
                    end
                case 'cellstr'
                    field.setType(javaclass('char',1));
                    field.setEditorContext(com.jidesoft.grid.MultilineStringCellEditor.CONTEXT);
                case 'logical'
                    if ~isempty(data.Type.Domain)
                        field.setType(javaclass('cellstr',1));  % java.lang.String array
                        self.AddCheckBoxListEditor(field, data.Type.Domain);
                    else
                        field.setType(javaclass('char',1));  % edit as string and convert with eval
                    end
                case {...
                        'denserealdouble','sparserealdouble','denserealsingle','sparserealsingle',...
                        'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle',...
                        'int8','uint8','int16','uint16','int32','uint32','int64','uint64'}
                    field.setType(javaclass('char',1));  % edit as string and convert with eval
                otherwise
                    field.setEditable(false);
                    %error('PropertyGrid:ArgumentTypeMismatch', 'Unsupported type: %s %s.', data.Type.Shape, data.Type.PrimitiveType);
            end
        end

        function InitializeMatrix(self, field)
            data = self.PropertyData;
            switch data.Type.PrimitiveType
                case {...
                        'denserealdouble','sparserealdouble','denserealsingle','sparserealsingle',...
                        'densecomplexdouble','sparsecomplexdouble','densecomplexsingle','sparsecomplexsingle',...
                        'char','int8','uint8','int16','uint16','int32','uint32','int64','uint64','logical'}
                    field.setType(javaclass('char',1));  % edit as string and convert with eval
                otherwise
                    field.setEditable(false);
                    %error('PropertyGrid:ArgumentTypeMismatch', 'Matrix %s is not supported.', data.Type.PrimitiveType);
            end
        end

        function ApplyContext(self, field, javatype, editor, editortype)
        % Registers a context for an editor.
        %
        % Input arguments:
        % field:
        %    a com.jidesoft.grid.Property instance
        % javatype:
        %    the Java type to be associated with the context
        % editor:
        %    a cell editor instance
        % editortype:
        %    the key used for generating the name of the context
            self.Context = com.jidesoft.grid.EditorContext(['JIDE_' editortype '_' int2str(self.GetContextCounterValue())]);
            self.ContextType = javatype;
            com.jidesoft.grid.CellEditorManager.registerEditor(javatype, editor, self.Context);  % register new context
            field.setEditorContext(self.Context);  % apply context to property
        end

        function AddCheckBoxListEditor(self, field, labels)
        % Registers a new check box list context.
        %
        % Input arguments:
        % field:
        %    a com.jidesoft.grid.Property instance
        % labels:
        %    a cell array of strings to label elements in the set shown
            editor = com.jidesoft.grid.CheckBoxListComboBoxCellEditor(javaStringArray(labels), javaclass('cellstr',1));
            self.ApplyContext(field, javaclass('cellstr',1), editor, 'checkboxlist');
        end

        function AddComboBoxEditor(self, field, javatype, javadomain)
        % Registers a new list selection context.
        % A drop-down combo box allows the user to select a single value
        % from a predefined set of values.
        %
        % Input arguments:
        % field:
        %    a com.jidesoft.grid.Property instance
        % javatype:
        %    a java.lang.Class instance
        % javadomain:
        %    an array of Java objects whose type corresponds to javatype
            editor = com.jidesoft.grid.ListComboBoxCellEditor(javadomain);
            self.ApplyContext(field, javatype, editor, 'combobox');
        end

        function AddSliderEditor(self, field, javatype, lower, upper)
        % Registers a new slider context.
        % The slider has a limited range.
        %
        % field:
        %    a com.jidesoft.grid.Property instance
        % javatype:
        %    a java.lang.Class instance
        % lower:
        %    an integer representing the upper lower of the interval
        % upper:
        %    an integer representing the upper bound of the interval
            editor = com.jidesoft.grid.SliderCellEditor(int32(lower), int32(upper));
            self.ApplyContext(field, javatype, editor, 'slider');
        end

        function AddSpinnerEditor(self, field, javatype, lower, upper)
        % Registers a new spinner context.
        % The spinner has a limited range and a fixed step.
        %
        % field:
        %    a com.jidesoft.grid.Property instance
        % javatype:
        %    a java.lang.Class instance
        % lower:
        %    an integer representing the upper lower of the interval
        % upper:
        %    an integer representing the upper bound of the interval
            spinner = javax.swing.SpinnerNumberModel(int32(lower), int32(lower), int32(upper), int32(1));
            editor = com.jidesoft.grid.SpinnerCellEditor(spinner);
            self.ApplyContext(field, javatype, editor, 'spinner');
        end
    end
    methods (Static, Access = private)
        function counter = GetContextCounterValue()
        % The current counter value for the JIDE editor context.
            persistent jide_counter;
            if isempty(jide_counter)  % if not yet assigned
                jide_counter = 0;
            end
            jide_counter = jide_counter + 1;  % increment global field counter
            counter = jide_counter;           % return current value
        end
    end
end


classdef LvdSensorTargetSet < matlab.mixin.SetGet
    %LvdSensorTargetSet Summary of this class goes here
    %   Detailed explanation goes here

    properties
        targets(1,:) AbstractSensorTarget

        lvdData LvdData
    end

    methods
        function obj = LvdSensorTargetSet(lvdData)
            obj.lvdData = lvdData;
        end

        function addTarget(obj, target)
            obj.targets(end+1) = target;
        end

        function removeTarget(obj, target)
            obj.targets([obj.targets] == target) = [];
        end

        function [listBoxStr, targets] = getListboxStr(obj)
            listBoxStr = {};

            for(i=1:length(obj.targets))
                listBoxStr{end+1} = obj.targets(i).getListboxStr(); %#ok<AGROW>
            end

            targets = obj.targets;
        end

        function indPoints = getTargetsForInds(obj, inds)
            indPoints = obj.targets(inds);
        end

        function inds = getIndsForTarget(obj, indTarget)
            inds = [];
            for(i=1:length(indTarget))
                for(j=1:length(obj.targets))
                    if(indTarget(i) == obj.targets(j))
                        inds(end+1) = j; %#ok<AGROW>
                        break;
                    end
                end
            end
        end

        function indSensor = getPointAtInd(obj, ind)
            if(ind > 0 && ind <= length(obj.targets))
                indSensor = obj.targets(ind);
            else
                indSensor = AbstractSensor.empty(1,0);
            end
        end

        function tf = usesGroundObj(obj, groundObj)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGroundObj(groundObj);
            end
        end

        function tf = usesGeometricPoint(obj, point)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGeometricPoint(point);
            end
        end

        function tf = usesGeometricVector(obj, vector)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGeometricVector(vector);
            end
        end

        function tf = usesGeometricCoordSys(obj, coordSys)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGeometricCoordSys(coordSys);
            end
        end

        function tf = usesGeometricRefFrame(obj, refFrame)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGeometricRefFrame(refFrame);
            end
        end

        function tf = usesGeometricAngle(obj, angle)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGeometricAngle(angle);
            end
        end

        function tf = usesGeometricPlane(obj, plane)
            tf = false;
            for(i=1:length(obj.targets))
                tf = tf || obj.targets(i).usesGeometricPlane(plane);
            end
        end
    end
end


% Helper class for GridLayout
classdef CellProps < handle

    properties
        HAlign = 'Stretch'
        VAlign = 'Stretch'
        LMargin = 0
        RMargin = 0
        TMargin = 0
        BMargin = 0
    end
    properties (Hidden, Dependent)
        Margin
    end

    methods (Static)
        function Names = GetCellParamNames()
            Names = cellfun(@(x)(['Cell' x]),CellProps.GetParamNames(), ...
                'UniformOutput',false);
        end
        function Names = GetParamNames()
            Names = { ...
                'HAlign' ...
                'VAlign' ...
                'Margin' ...
                'LMargin' ...
                'RMargin' ...
                'TMargin' ...
                'BMargin'};
        end
    end

    methods
        function Obj = CellProps(varargin)
            if length(varargin) == 1 && isstruct(varargin{1})
                P = varargin{1};
                FieldNames = fieldnames(P);
                for i = 1:length(FieldNames)
                    FieldName = FieldNames{i};
                    if strcmp(FieldName(1:4),'Cell')
                        ObjFieldName = FieldName(5:end);
                    else
                        ObjFieldName = FieldName;
                    end
                    Field = P.(FieldName);
                    if ~isempty(Field)
                        Obj.(ObjFieldName) = Field;
                    end
                end
            else
                for i = 1:2:length(varargin)
                    Obj.(varargin{i}) = varargin{i+1};
                end
            end

        end

        function set.HAlign(Obj, Value)
            Set = {'Left','Center','Right','Stretch'};
            assert(any(strcmp(Value,Set)), ...
                'HAlign must be one of: ''Left'',''Center'',''Right'',''Stretch''.');
            Obj.HAlign = Value;
        end
        function set.VAlign(Obj, Value)
            Set = {'Top','Center','Bottom','Stretch'};
            assert(any(strcmp(Value,Set)), ...
                'VAlign must be one of: ''Top'',''Center'',''Bottom'',''Stretch''.');
            Obj.VAlign = Value;
        end

        function set.Margin(Obj, Value)
            Obj.LMargin = Value;
            Obj.RMargin = Value;
            Obj.TMargin = Value;
            Obj.BMargin = Value;
        end

        function set.LMargin(Obj, Value)
            assert(isscalar(Value) && Value >= 0, ...
                'LMargin must a non-negative scalar.');
            Obj.LMargin = Value;
        end
        function set.RMargin(Obj, Value)
            assert(isscalar(Value) && Value >= 0, ...
                'RMargin must a non-negative scalar.');
            Obj.RMargin = Value;
        end
        function set.TMargin(Obj, Value)
            assert(isscalar(Value) && Value >= 0, ...
                'TMargin must a non-negative scalar.');
            Obj.TMargin = Value;
        end
        function set.BMargin(Obj, Value)
            assert(isscalar(Value) && Value >= 0, ...
                'BMargin must a non-negative scalar.');
            Obj.BMargin = Value;
        end
    end

end

% EOF


function track_mha(srcdir, srcpattern, lookahead, load_data, destmat)
%TRACK_MHA Track eddies using Multiple Hypothesis Assignment
% srdir:      Directory in which to find saved eddy frames
% srcpattern: Filename pattern used for eddies (ex. anticyc_ for
%             anticyc_19921014.mat)
% lookahead:  Boolean value to run the scan with lookahead enabled [0 or 1]
% load data:  Path to pre-generated data. Use 0 to load no data.
% destmat:    Path to saved mat-file. (should NOT end in .mat)
    if isa(load_data, 'numeric')
        load_data = '0';
    end

    mha_path = mfilename('fullpath');
    sep = strfind(mha_path, filesep());
    mha_path = [mha_path(1:sep(end)) 'track_mha.py'];

    cmd = sprintf('python "%s" "%s" "%s" %d "%s" "%s"', mha_path, ...
        srcdir, srcpattern, lookahead, load_data, destmat);
    status = system(cmd, '-echo');
    if status
        error('Failed to run MHA');
    end
end


function ftrs = wholeMovieFtrs(moviename,trackfilename,blockSize)

tracks = load_tracks(trackfilename);
[readfcn,nframes,fid,headerinfo] = get_readframe_fcn(moviename);

if fid>0,
  fclose(fid);
end

nblocks = ceil(nframes/blockSize);

parfor ndx = 1:nblocks
  [readfcn,nframes,fid,headerinfo] = get_readframe_fcn(moviename);
  % For parfor files has to be opened for every loop.
  blockStart = (ndx-1)*blockSize + 1;
  blockEnd   = min(ndx*blockSize,nframes);
  ftrs{ndx} = genFeatures(readfcn,headerinfo,blockStart,blockEnd,tracks);
  if fid>0,
    fclose(fid);
  end
  fprintf('.');
  if mod(ndx,50)==0, fprintf('\n'); end
end


classdef Tensor2VoigtPSrepresentation < handle

    properties (Access = protected)
        indexTransformer
    end

    methods (Access = protected)

        function createIndexTransformer(obj)
            obj.indexTransformer = TensorVoigtIndexTransformerPS();
        end

    end

end


function struct = newCERRStructure(scanSet, planC, colorNum)
%"newCERRStructure"
%   Returns an empty, but valid CERR structure. This includes a null string
%   for the structure name and an appropriately formatted contour field.
%
%   scanSet is the index of the scan to register the new structure to.
%   This cannot be changed later.
%
%   Since structure contours require an item for each slice, a planC with 1+ valid
%   scanSets must be in memory.
%   in memory.
%
%JRA 6/4/04
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.
%
%Usage:
%   function struct = newCERRStructure(scanSet, planC)

global stateS

if ~exist('planC', 'var') %wy
    global planC
end

indexS = planC{end};

%Get the structure template from initializeCERR.
struct = initializeCERR('structures');

%Create and populate empty contour field.
try
    nSlices = size(getScanArray(planC{indexS.scan}(scanSet)), 3);
catch
    error('Cannot create new structure if scan is not valid.');
    return
end
segments.points = [];
[contour(1:nSlices).segments] = deal(segments);
[contour(1:nSlices).referencedSopInstanceUID] = deal({planC{indexS.scan}(1).scanInfo(:).sopInstanceUID});
[contour(1:nSlices).referencedSopClassUID] = deal({planC{indexS.scan}(1).scanInfo(:).sopClassUID});

%Create empty name field.
structureName = '';

%Visibility defaults on.
visible = 1;

%Assign color for this structure
assocScanV = getStructureAssociatedScan(1:length(planC{indexS.structures}),planC);
scanIndV = find(assocScanV==scanSet);
if ~exist('colorNum','var')
    colorNum = length(scanIndV) + 1;
end
if ~isfield(stateS,'optS')
%     color = stateS.optS.colorOrder( mod(colorNum-1, size(stateS.optS.colorOrder,1))+1,:);
% else
    stateS.optS = opts4Exe([getCERRPath,'CERROptions.json']);
%     color = stateS.optS.colorOrder( mod(colorNum-1, size(stateS.optS.colorOrder,1))+1,:);
end
colorArr = stateS.optS.colorOrder;
color = setStructureColor(planC,colorArr);
%Assign these values to structure.
struct(1).contour        = contour;
struct(1).structureName  = structureName;
struct(1).visible        = visible;
struct(1).associatedScan = scanSet;
struct(1).assocScanUID   = planC{indexS.scan}(scanSet).scanUID;
struct(1).strUID         = createUID('structure');
struct(1).structureColor = color;


function tests = test_lang
  tests = functiontests(localfunctions);
end

function test_1(testCase)
    verifyTrue(testCase, spx.lang.is_class('spx.lang'));
    verifyFalse(testCase, spx.lang.is_class('spx.lang.noop'));
    spx.lang.noop;
end


function [axis, axisLim] = extractAxisDataMultipleYAxes(obj,parentAxisData,yaxIndex)

    childAxisData = get(parentAxisData.YAxis(yaxIndex));

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

    %-axis-side-%
    if yaxIndex == 1
        axis.side = 'left';
    elseif yaxIndex == 2
        axis.side = 'right';
    end

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

    %-y-axis initializations-%
    axis.zeroline = false;
    axis.autorange = false;
    axis.exponentformat = obj.PlotlyDefaults.ExponentFormat;

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

    %-y-axis tick font size-%
    axis.tickfont.size = childAxisData.FontSize;

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

    %-y-axis tick font family-%
    axis.tickfont.family = matlab2plotlyfont(childAxisData.FontName);

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

    ticklength = min(obj.PlotlyDefaults.MaxTickLength,...
        max(childAxisData.TickLength(1)*parentAxisData.Position(3)*obj.layout.width,...
        childAxisData.TickLength(1)*parentAxisData.Position(4)*obj.layout.height));
    %-y-axis ticklen-%
    axis.ticklen = ticklength;

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

    %-y-axis coloring-%
    axiscol = sprintf('rgb(%f,%f,%f)', 255*childAxisData.Color);

    axis.linecolor = axiscol;
    axis.tickcolor = axiscol;
    axis.tickfont.color = axiscol;

    try
        axis.gridcolor = sprintf('rgba(%f,,%f,%f,%f)', 255*parentAxisData.GridColor, parentAxisData.GridAlpha);
    catch
        axis.gridcolor = axiscol;
    end

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

    %-axis show grid-%
    if strcmp(parentAxisData.YGrid, 'on')
        axis.showgrid = true;
    else
        axis.showgrid = false;
    end

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

    % grid = eval(['parentAxisData.' axisName 'Grid;']);
    % minorGrid = eval(['parentAxisData.' axisName 'MinorGrid;']);

    % if strcmp(grid, 'on') || strcmp(minorGrid, 'on')
    %     %-axis show grid-%
    %     axis.showgrid = true;
    % else
    %     axis.showgrid = false;
    % end

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

    %-line widths-%
    linewidth = max(1,childAxisData.LineWidth*obj.PlotlyDefaults.AxisLineIncreaseFactor);

    axis.linewidth = linewidth;
    axis.tickwidth = linewidth;
    axis.gridwidth = linewidth;

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

    %-axis type-%
    axis.type = childAxisData.Scale;

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

    %-axis showtick labels / ticks-%
    tickValues = childAxisData.TickValues;

    if isempty(tickValues)

        %-axis ticks-%
        axis.ticks = '';
        axis.showticklabels = false;

        %-axis autorange-%
        axis.autorange = true;

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

        % switch parentAxisData.Box
        %     case 'on'
        %         %-axis mirror-%
        %         axis.mirror = true;
        %     case 'off'
        %         axis.mirror = false;
        % end

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

    else

        %-get axis limits-%
        axisLim = childAxisData.Limits;

        %-axis tick direction-%
        switch childAxisData.TickDirection
            case 'in'
                axis.ticks = 'inside';
            case 'out'
                axis.ticks = 'outside';
        end

        %---------------------------------------------------------------------%
        % switch parentAxisData.Box
        %     case 'on'
        %         %-axis mirror-%
        %         axis.mirror = 'ticks';
        %     case 'off'
        %         axis.mirror = false;
        % end

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

        %-LOG TYPE-%
        if strcmp(axis.type, 'log')

            %-axis range-%
            axis.range = log10(axisLim);
            %-axis autotick-%
            axis.autotick = true;
            %-axis nticks-%
            axis.nticks = length(tickValues) + 1;

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

        %-LINEAR TYPE-%
        elseif strcmp(axis.type, 'linear')

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

            %-get tick label mode-%
            tickLabelMode = childAxisData.TickLabelsMode;

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

            %-AUTO MODE-%
            if strcmp(tickLabelMode, 'auto')

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

                if isnumeric(axisLim)
                    axis.range = axisLim;

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

                elseif isduration(axisLim)
                   [temp,type] = convertDuration(axisLim);

                   if (~isduration(temp))
                       axis.range = temp;
                       axis.type = 'duration';
                       axis.title = type;
                   else
                       nticks = length(tickValues) + 1;
                       delta = 0.1;
                       axis.range = [-delta nticks+delta];
                       axis.type = 'duration - specified format';
                   end

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

                elseif isdatetime(axisLim)
                    axis.range = convertDate(axisLim);
                    axis.type = 'date';
                else
                    % data is a category type other then duration and datetime
                end

                %-axis autotick-%
                axis.autotick = true;
                %-axis numticks-%
                axis.nticks = length(tickValues) + 1;
                axis.showticklabels = true;

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

            %-CUSTOM MODE-%
            else

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

                %-get tick labels-%
                tickLabels = childAxisData.TickLabels;

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

                %-hide tick labels as lichkLabels field is empty-%
                if isempty(tickLabels)

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

                    %-hide tick labels-%
                    axis.showticklabels = false;

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

                    %-axis autorange-%
                    axis.autorange = true;

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

                %-axis show tick labels as tickLabels matlab field-%
                else

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

                    axis.showticklabels = true;
                    % axis.type = 'linear';

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

                    if isnumeric(axisLim)
                        axis.range = axisLim;
                    else
                        axis.autorange = true;
                    end

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

                    axis.tickvals = tickValues;
                    axis.ticktext = tickLabels;

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

                    %+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
                    % NOTE:
                    %    The next piece of code was replaced by the previous one.
                    %    I think that the new piece of code is better, optimal and
                    %    extends to all cases. However, I will leave this piece of
                    %    code commented in case there is a problem in the future.
                    %
                    %    If there is a problem with the new piece of code, please
                    %    comment and uncomment the next piece of code.
                    %
                    %    If everything goes well with the new gripping piece, at
                    %    the end of the development we will be able to remove the
                    %    commented lines
                    %+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%

                    %-axis labels
                    % labels = str2double(tickLabels);
                    % try
                    %     %find numbers in labels
                    %     labelnums = find(~isnan(labels));
                    %     %-axis type linear-%
                    %     axis.type = 'linear';
                    %     %-range (overwrite)-%
                    %     delta = (labels(labelnums(2)) - labels(labelnums(1)))/(labelnums(2)-labelnums(1));
                    %     axis.range = [labels(labelnums(1))-delta*(labelnums(1)-1) labels(labelnums(1)) + (length(labels)-labelnums(1))*delta];
                    %     %-axis autotick-%
                    %     axis.autotick = true;
                    %     %-axis numticks-%
                    %     axis.nticks = eval(['length(parentAxisData.' axisName 'Tick) + 1;']);
                    % catch
                    %     %-axis type category-%
                    %     axis.type = 'category';
                    %     %-range (overwrite)-%
                    %     axis.autorange = true;
                    %     %-axis autotick-%
                    %     % axis.autotick = true;
                    % end
                end
            end
        end
    end

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

    %-scale direction-%
    if strcmp(childAxisData.Direction, 'reverse')
        axis.range = [axis.range(2) axis.range(1)];
    end

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

    %-y-axis label-%
    label = childAxisData.Label;
    labelData = get(label);

    %STANDARDIZE UNITS
    fontunits = get(label,'FontUnits');
    set(label,'FontUnits','points');

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

    %-title settings-%
    if ~isempty(labelData.String)
        axis.title = parseString(labelData.String,labelData.Interpreter);
    end

    axis.titlefont.color = sprintf('rgb(%f,%f,%f)', 255*labelData.Color);
    axis.titlefont.size = labelData.FontSize;
    axis.titlefont.family = matlab2plotlyfont(labelData.FontName);

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

    %REVERT UNITS
    set(label,'FontUnits',fontunits);

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

    if strcmp(childAxisData.Visible,'on')
        %-axis showline-%
        axis.showline = true;
    else
        %-axis showline-%
        axis.showline = false;
        %-axis showticklabels-%
        axis.showticklabels = false;
        %-axis ticks-%
        axis.ticks = '';
        %-axis showline-%
        axis.showline = false;
        %-axis showticklabels-%
        axis.showticklabels = false;
        %-axis ticks-%
        axis.ticks = '';
    end

    %-------------------------------------------------------------------------%
end


function res = io_load(varargin)
% Like MATLAB's builtin load(), except that the filename may be platform-independent.
% Contents = io_load(Filename,Arguments...)
%
% In:
%   Filename    :   Platform-independent file name.
%
%   Arguments...:   optional arguments to load, e.g. the list of variables, or load options
%
% Out:
%   Contents    :   structure of contents of the file, if desired (if not specified,
%                   variables are loaded into the workspace)
%
% Example:
%   % load a file
%   io_load('data:/myfile.mat');
%
%   % load only variable 'lastmodel' from the given file
%   io_load('bcilab:/resources/workspaces/myworkspace.mat', 'lastmodel')
%
% See also:
%   load, io_save, env_translatepath
%
%                               Christian Kothe, Swartz Center for Computational Neuroscience, UCSD
%                               2010-06-21

fname = varargin{1};
if length(fname)>4 && strcmpi(fname(end-3:end),'.sto')
    % load from .sto file
    if strncmp(fname,'cluster:',8)
        % load over the network
        bytes = par_fileclient(env_translatepath(fname(9:end)),'Verbosity',2);
    else
        % load from disk
        f = fopen(env_translatepath(fname),'r');
        try
            bytes = fread(f,inf,'*uint8');
            fclose(f);
        catch e
            if ~exist(fname,'file')
                error('The file named "%s" does not exist.',fname);
            else
                rethrow(e);
            end
        end
    end
    contents = hlp_deserialize(bytes);
else
    if ~isempty(varargin{1}) && varargin{1}(1) == '-' && ~any(varargin{1}=='.')
        contents = load(varargin{1},env_translatepath(varargin{2}),varargin{3:end});
    else
        contents = load(env_translatepath(varargin{1}),varargin{2:end});
    end
end

if isfield(contents,'is_serialized__')
    contents = rmfield(contents,'is_serialized__');
    for fn = fieldnames(contents)'
        contents.(fn{1}) = hlp_deserialize(contents.(fn{1})); end
end

if nargout > 0
    res = contents;
else
    for fn = fieldnames(contents)'
        assignin('caller',fn{1},contents.(fn{1})); end
end


function varargout = daqstopbutton(fig,obj,varargin);
%DAQSTOPBUTTON        Add a stop/start button to a data acquisition application
%
% DAQSTOPBUTTON(FIG,OBJ) adds a start/stop button to figure FIG.  This
% button can be used to start and stop data acquisition object OBJ.
% DAQSTOPBBUTTON will also delete OBJ when FIG is closed (i.e., it sets
% FIG's CloseRequestFcn to delete the object)
%
% DAQSTOPBUTTON(FIG,OBJ,'P1','V1','P2','V2', ...) specifies Property-Value
% pairs for configuring properties of the start/stop button.  Any valid
% property of a togglebutton can be specified.
%
% HBUTTON = DAQSTOPBUTTON(...) returns a handle to the start/stop button
%
% Note: This button does not "listen" to determine if your object changes
%   state.  For instance, if you have a finite number of samples
%   acquired after starting, the button will not reset automatically
%   when your object stops running.  Don't despair, since it is easy
%   enough to do on your own!
%
% Example:
%      fh = figure;                         % Create a figure
%      ai = analoginput('winsound');        % Create an input object
%      addchannel(ai,1);                    % Add a channel
%      set(ai,'TriggerRepeat',inf);         % Configure to run infinitely
%      set(ai,'TimerFcn','plot(peekdata(ai,500))'); % Each timer event will plot recent data
%      hButton = daqstopbutton(fh,ai);      % Add the stopbutton

%   Scott Hirsch
%   shirsch@mathworks.com
%   Copyright 2003 The MathWorks, Inc

%Error checking
msg = nargchk(2,inf,nargin);
error(msg)

if ~all(isvalid(obj))
    error('Second input argument must be valid daq object')
end;

% Create the button
hButton = uicontrol(fig,'style','togglebutton',varargin{:});

%Check current state of the object
val = strcmp(obj.Running,'On');

if val==1       %Already running
    set(hButton,'String','Stop');
    set(hButton,'Value',1)
else
    set(hButton,'String','Start');
    set(hButton,'Value',0)
end;

set(hButton,'Callback',{@localStartStopObject,obj})

% Configure the CloseRequestFcn of the figure
setappdata(fig,'DaqStopButtonObject',obj)
cr = get(fig,'CloseRequestFcn');
cr = ['obj=getappdata(gcf,''DaqStopButtonObject'');stop(obj);delete(obj);' cr];
set(fig,'CloseRequestFcn',cr);

% Return a handle to the button
if nargout
    varargout{1} = hButton;
end;

function localStartStopObject(hButton,action,obj)
% Callback for the start/stop button
val = get(hButton,'Value');
if val==1       %Pushed in
    set(hButton,'String','Stop');
    if all(isvalid(obj))
        start(obj)
    end;
else
    set(hButton,'String','Start');
    if all(isvalid(obj))
        stop(obj)
    end;
end;


function metScores = compareAllMets(Cmodel, Tmodel)
% Compares and scores similarity between all pairwise
% combinations of metabolites between two models. It is not however used
% by the main workflow.
%
% USAGE:
%
%    metScores = compareAllMets(Cmodel,Tmodel
%
% INPUTS:
%    Cmodel:      Comparison model.
%    Tmodel:      Template model.
%
% OUTPUTS:
%    metScore:    Matrix of scores of all pairwise comparisons.
%
% Please cite:
% `Sauls, J. T., & Buescher, J. M. (2014). Assimilating genome-scale
% metabolic reconstructions with modelBorgifier. Bioinformatics
% (Oxford, England), 30(7), 1036?8`. http://doi.org/10.1093/bioinformatics/btt747
%
% ..
%    Edit the above text to modify the response to help addMetInfo
%    Last Modified by GUIDE v2.5 06-Dec-2013 14:19:28
%    This file is published under Creative Commons BY-NC-SA.
%
%    Correspondance:
%    johntsauls@gmail.com
%
%    Developed at:
%    BRAIN Aktiengesellschaft
%    Microbial Production Technologies Unit
%    Quantitative Biology and Sequencing Platform
%    Darmstaeter Str. 34-36
%    64673 Zwingenberg, Germany
%    www.brain-biotech.de

nCmets = length(Cmodel.mets) ; % Declare variables and scoring structure.
nTmets = length(Tmodel.mets) ;

% Score values.
ScoreVal = struct('ID', [10,-1], ...
                  'compartment', [0,-100], ...
                  'name', [10,-1], ...
                  'formula', [10,-5], ...
                  'charge', [1,-1], ...
                  'KEGGID', [10,-5], ...
                  'SEEDID', [10,-5], ...
                  'ChEBIID', [10,-5], ...
                  'PubChemID', [10,-5], ...
                  'InChIString', [10,-5]) ;

% Score matrix.
metScores = zeros(nCmets, nTmets) ;

% Compartments of every met in T, used later for comparison.
tComp = cell(nTmets, 1) ;
for iMet = 1:nTmets
    tComp{iMet} = Tmodel.mets{iMet}(end - 2:end) ;
end

%% Compare cMet to tMets
h = waitbar(0, 'Comparing metabolites') ;
for iMet = 1:nCmets
    % metsID Match. There is always one ID.
    % Match name, removing '[.]' and add regular expression info.
    if ~isempty(regexp(Cmodel.mets{iMet}, '\[.\]', 'once'))
        name =  strcat('(\||\<)', Cmodel.mets{iMet}(1:end - 3), '(\>|\[|_|\|)') ;
    else
        name = strcat('(\||\<)', Cmodel.mets{iMet}, '(\>|\[|_|\|)') ;
    end
    % Match against IDs for all models.
    match = regexpi(Tmodel.metID, name) ;
    match = ~cellfun(@isempty, match) ;
    % Give scores.
    metScores(iMet, match) = metScores(iMet, match) + ScoreVal.ID(1) ;
    metScores(iMet, ~match) = metScores(iMet, ~match) + ScoreVal.ID(2) ;

    % Match against compartment for all models.
    match = strcmp(tComp, Cmodel.mets{iMet}(end - 2:end)) ;
    % Give scores.
    metScores(iMet, match) = metScores(iMet, match) + ScoreVal.compartment(1) ;
    metScores(iMet, ~match) = metScores(iMet, ~match) + ScoreVal.compartment(2) ;

    % metNames Match. There can be multiple names.
    fullname = Cmodel.metNames{iMet} ;
    pipePos = [0 strfind(fullname, '|') length(fullname) + 1] ;
    matchSum = zeros(length(Tmodel.mets), 1) ;
    for i = 1:length(pipePos) - 1
        name = fullname(pipePos(i) + 1:pipePos(i + 1) - 1) ;
        name = strcat('(\||\<)', name, '(\>|\|)') ;
        match = regexpi(Tmodel.metNames, name) ;
        match = ~cellfun('isempty', match) ;
        matchSum = matchSum + match ;
    end
    match = logical(matchSum) ;
    % Give scores.
    metScores(iMet, match) = metScores(iMet, match) + ScoreVal.name(1) ;
    metScores(iMet, ~match) = metScores(iMet, ~match) + ScoreVal.name(2) ;

    % metFormula Match. There will always be one Formula.
    name = strcat('(\||\<)', Cmodel.metFormulas{iMet}, '(\>|\|)') ;
    match = regexpi(Tmodel.metFormulas, name) ;
    match = ~cellfun(@isempty, match) ;
    % Give scores.
    metScores(iMet, match) = metScores(iMet, match) + ScoreVal.formula(1) ;
    metScores(iMet, ~match) = metScores(iMet, ~match) + ScoreVal.formula(2) ;

    % metCharge match. There will always be a charge.
    for i = 1:length(Tmodel.mets)
        if Cmodel.metCharge(iMet) == Tmodel.metCharge(i)
            metScores(iMet, i) = metScores(iMet, i) + ScoreVal.charge(1) ;
        else
            metScores(iMet, i) = metScores(iMet, i) + ScoreVal.charge(2) ;
        end
    end

    % metKEGGID Match. There may multiple KEGGIDs or no KEGGID.
    if ~isempty(Cmodel.metKEGGID{iMet})
        fullname = Cmodel.metKEGGID{iMet} ;
        pipePos = [ 0 strfind(fullname, '|') length(fullname) + 1 ] ;
        matchSum = zeros(length(Tmodel.mets), 1) ;
        for i = 1:length(pipePos) - 1
            name = fullname(pipePos(i) + 1:pipePos(i + 1) - 1) ;
            match = regexpi(Tmodel.metKEGGID, name) ;
            match = ~cellfun('isempty', match) ;
            matchSum = matchSum + match ;
        end
        match = logical(matchSum) ;
        % Give scores.
        metScores(iMet, match) = metScores(iMet, match) + ScoreVal.KEGGID(1) ;
        metScores(iMet, ~match) = metScores(iMet, ~match) + ScoreVal.KEGGID(2) ;
    end

    % metSEEDID Match. There may multiple SEEDIDs or no SEEDID.
    if ~isempty(Cmodel.metSEEDID{iMet})
        fullname = Cmodel.metSEEDID{iMet} ;
        pipePos = [ 0 strfind(fullname, '|') length(fullname) + 1] ;
        matchSum = zeros(length(Tmodel.mets), 1) ;
        for i = 1:length(pipePos) - 1
            name = fullname(pipePos(i) + 1:pipePos(i +1 ) - 1) ;
            match = regexpi(Tmodel.metSEEDID,name) ;
            match = ~cellfun('isempty', match) ;
            matchSum = matchSum + match ;
        end
        match = logical(matchSum) ;
        % Give scores.
        metScores(iMet, match) = metScores(iMet, match) + ScoreVal.SEEDID(1) ;
        metScores(iMet, ~match) = metScores(iMet, ~match) + ScoreVal.SEEDID(2) ;
    end
    % Update waitbar.
    waitbar(iMet / nCmets, h)
end
close(h)

%% Normalize scores.
% remove negative scores
metScores(metScores < 0) = 0 ;

if max(max(metScores)) > 0 % Avoid NaN.
    metScores = metScores - min(min(metScores)) ;
    metScores = metScores ./ max(max(metScores)) ;
else
    metScores = zeroes(size(metScores)) ;
end

% Find best matches.
[bestMatch, bestMatchIndex] = max(metScores, [], 2) ;

%% Graph data.
hold on
figure(1)
subplot(2,1,1)
hist(metScores(:), 100) % Converting to column matrix is faster.
title('Normalized score frequency')
xlabel('Score')
ylabel('Frequency')
subplot(2, 2, 3)
hist(bestMatch, 100)
title('Frequency of scores of best match per metabolite')
xlabel('Score')
ylabel('Frequency');
subplot(2, 2, 4)
imagesc(metScores)
colormap('bone')
title('Matching scores')
xlabel('Template met')
ylabel('Compared met')
hold off


function lines = readLines( fileName )
%readLines reads the file line by line
%
% lines = readLines( fileName );
%
% Input:
%   fileName - string containing the full file name
%
% Output:
%   lines - cell array of lines contained in the file

fileID = fopen(fileName, 'r');
if fileID == -1
    error(['File ', fileName, ' can not be opened!']);
end
lines = textscan(fileID, '%s\n');
fclose(fileID);

lines = lines{1};

end


function [event] = read_yokogawa_event(filename, varargin)

% READ_YOKOGAWA_EVENT reads event information from continuous,
% epoched or averaged MEG data that has been generated by the Yokogawa
% MEG system and software and allows those events to be used in
% combination with FieldTrip.
%
% Use as
%   [event] = read_yokogawa_event(filename)
%
% See also READ_YOKOGAWA_HEADER, READ_YOKOGAWA_DATA

% Copyright (C) 2005, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

event   = [];
handles = definehandles;

% get the options, the default is set below
chanindx    = ft_getopt(varargin, 'chanindx');
threshold   = ft_getopt(varargin, 'threshold');
detectflank = ft_getopt(varargin, 'detectflank');
combinebinary = ft_getopt(varargin, 'combinebinary', false);
trigshift   = ft_getopt(varargin, 'trigshift');
if isempty(combinebinary)
  combinebinary = false;
end

% ensure that the required toolbox is on the path
if ft_hastoolbox('yokogawa_meg_reader')
  % read the dataset header
  hdr = read_yokogawa_header_new(filename);
  ch_info = hdr.orig.channel_info.channel;
  type = [ch_info.type];

  % determine the trigger channels (if not specified by the user)
  if isempty(chanindx)
    chanindx = find(type==handles.TriggerChannel);
  end

  % Use the MEG Reader documentation if more detailed support is required.
  if hdr.orig.acq_type==handles.AcqTypeEvokedRaw
    % read the trigger id from all trials
    event = getYkgwHdrEvent(filename);
    % use the standard FieldTrip header for trial events
    % make an event for each trial as defined in the header
    for i=1:hdr.nTrials
      event(end+1).type     = 'trial';
      event(end  ).sample   = (i-1)*hdr.nSamples + 1;
      event(end  ).offset   = -hdr.nSamplesPre;
      event(end  ).duration =  hdr.nSamples;
      if ~isempty(value)
        event(end  ).value    =  event(i).code;
      end
    end

  % Use the MEG Reader documentation if more detailed support is required.
  elseif hdr.orig.acq_type==handles.AcqTypeEvokedAve
    % make an event for the average
    event(1).type     = 'average';
    event(1).sample   = 1;
    event(1).offset   = -hdr.nSamplesPre;
    event(1).duration =  hdr.nSamples;

  elseif hdr.orig.acq_type==handles.AcqTypeContinuousRaw
    % Events annotated by users during measurements
    bookmark_tmp = getYkgwHdrBookmark(filename);
    if ~isempty(bookmark_tmp)
      for i = 1:length(bookmark_tmp)
        event(end+1).sample = bookmark_tmp(i).sample_no + 1;
        event(end  ).type   =  'bookmarks';
        if ~isempty(bookmark_tmp(i).label)
          event(end  ).value = bookmark_tmp(i).label;
          %% 0 in default
        else
          event(end  ).value = 99;
        end
      end
    end
    clear bookmark_tmp;
  end

elseif ft_hastoolbox('yokogawa')

  % read the dataset header
  hdr = read_yokogawa_header(filename);

  % determine the trigger channels (if not specified by the user)
  if isempty(chanindx)
    chanindx = find(hdr.orig.channel_info(:,2)==handles.TriggerChannel);
  end

  if hdr.orig.acq_type==handles.AcqTypeEvokedRaw
    % read the trigger id from all trials
    fid   = fopen_or_error(filename, 'r');
    value = GetMeg160TriggerEventM(fid);
    fclose(fid);
    % use the standard FieldTrip header for trial events
    % make an event for each trial as defined in the header
    for i=1:hdr.nTrials
      event(end+1).type     = 'trial';
      event(end  ).sample   = (i-1)*hdr.nSamples + 1;
      event(end  ).offset   = -hdr.nSamplesPre;
      event(end  ).duration =  hdr.nSamples;
      if ~isempty(value)
        event(end  ).value    =  value(i);
      end
    end

  elseif hdr.orig.acq_type==handles.AcqTypeEvokedAve
    % make an event for the average
    event(1).type     = 'average';
    event(1).sample   = 1;
    event(1).offset   = -hdr.nSamplesPre;
    event(1).duration =  hdr.nSamples;

  elseif hdr.orig.acq_type==handles.AcqTypeContinuousRaw
    % the data structure does not contain events, but flank detection on the trigger channel might reveal them
    % this is done below
  end

else
  ft_error('cannot determine whether the required Yokogawa toolbox is present');
end

% read the trigger channels and detect the flanks
if ~isempty(chanindx)
  trigger = read_trigger(filename, 'header', hdr, 'denoise', false, 'chanindx', chanindx, 'detectflank', detectflank, 'threshold', threshold, 'combinebinary', combinebinary, 'trigshift', trigshift);
  % combine the triggers and the other events
  event = appendstruct(event, trigger);
end

if isempty(event)
  ft_warning('no triggers were detected, please specify the "trigindx" option');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% this defines some usefull constants
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function handles = definehandles
handles.output = [];
handles.sqd_load_flag = false;
handles.mri_load_flag = false;
handles.NullChannel         = 0;
handles.MagnetoMeter        = 1;
handles.AxialGradioMeter    = 2;
handles.PlannerGradioMeter  = 3;
handles.RefferenceChannelMark = hex2dec('0100');
handles.RefferenceMagnetoMeter       = bitor( handles.RefferenceChannelMark, handles.MagnetoMeter );
handles.RefferenceAxialGradioMeter   = bitor( handles.RefferenceChannelMark, handles.AxialGradioMeter );
handles.RefferencePlannerGradioMeter = bitor( handles.RefferenceChannelMark, handles.PlannerGradioMeter );
handles.TriggerChannel      = -1;
handles.EegChannel          = -2;
handles.EcgChannel          = -3;
handles.EtcChannel          = -4;
handles.NonMegChannelNameLength = 32;
handles.DefaultMagnetometerSize       = (4.0/1000.0);       % Square of 4.0mm in length
handles.DefaultAxialGradioMeterSize   = (15.5/1000.0);      % Circle of 15.5mm in diameter
handles.DefaultPlannerGradioMeterSize = (12.0/1000.0);      % Square of 12.0mm in length
handles.AcqTypeContinuousRaw = 1;
handles.AcqTypeEvokedAve     = 2;
handles.AcqTypeEvokedRaw     = 3;
handles.sqd = [];
handles.sqd.selected_start  = [];
handles.sqd.selected_end    = [];
handles.sqd.axialgradiometer_ch_no      = [];
handles.sqd.axialgradiometer_ch_info    = [];
handles.sqd.axialgradiometer_data       = [];
handles.sqd.plannergradiometer_ch_no    = [];
handles.sqd.plannergradiometer_ch_info  = [];
handles.sqd.plannergradiometer_data     = [];
handles.sqd.eegchannel_ch_no   = [];
handles.sqd.eegchannel_data    = [];
handles.sqd.nullchannel_ch_no   = [];
handles.sqd.nullchannel_data    = [];
handles.sqd.selected_time       = [];
handles.sqd.sample_rate         = [];
handles.sqd.sample_count        = [];
handles.sqd.pretrigger_length   = [];
handles.sqd.matching_info   = [];
handles.sqd.source_info     = [];
handles.sqd.mri_info        = [];
handles.mri                 = [];


function com = pop_expevents(EEG, filename, unit)
% pop_expevents() - export events to CSV file
%
% Usage:
%   >> pop_expevents(EEG);
%   >> pop_expevents(EEG, filename);
%   >> pop_expevents(EEG, filename, unit);
%
% Inputs:
%   EEG      - EEGLAB dataset
%   filename - text file name
%   unit     - display latency and duration in 'samples' (default) or 'seconds'
%
% Outputs:
%   com      - Command to execute this function from the command line
%
% Examples:
%   Export all events and show a dialog window:
%     >> pop_expevents(EEG);
%
%   Export all events to a file, latency and duration in samples:
%     >> pop_expevents(EEG, filename);
%
%   Export all events to a file, latency and duration in seconds:
%     >> pop_expevents(EEG, filename, 'seconds');

% Copyright by Clemens Brunner <clbrunner@ucsd.edu>
% Revision: 0.10
% Date: 09/16/2011

% Revision history:
%   0.10: Initial version

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

com = '';
if nargin < 1
    help pop_expevents;
    return
end

if nargin < 2
	[filename, filepath] = uiputfile('*.csv', 'File name -- pop_expevents()');
    drawnow;
	if filename == 0
        return;  end
	filename = [filepath filename];
end;

if nargin < 3
    unit = 'samples';  end

if ~(strcmp(unit, 'samples') || strcmp(unit, 'seconds'))
    error('Unit must be either ''samples'' or ''seconds''.');  end

eeg_eventtable(EEG, 'dispTable', false, 'exportFile', filename, 'unit', unit);

com = sprintf('pop_expevents(%s, ''%s'', ''%s'');', inputname(1), filename, unit);


function placetitlebar(fig)
%PLACETITLEBAR ensures that a figure's titlebar is on screen.
%
%   Copyright 1993-2004 The MathWorks, Inc.
%   $Revision: 1.1.4.1 $  $Date: 2004/01/24 09:36:24 $

oldRootUnits = get(0, 'Units');
oldFigUnits = get(fig, 'Units');

set(0, 'Units', 'pixels');
set(fig, 'Units', 'pixels');

screenpos = get(0, 'Screensize');
outerpos = get(fig, 'Outerposition');
if outerpos(2) + outerpos(4) > screenpos(4)
    outerpos(2) = screenpos(4) - outerpos(4);
    set(fig, 'Outerposition', outerpos);
end
%restore units
set(0, 'Units', oldRootUnits);
set(fig, 'Units', oldFigUnits);


classdef GMSHComputer < handle

    properties (Access = public)
        computation
        variables
    end

    properties (Access = private)
        testName
    end

    methods (Access = public)
        function obj = GMSHComputer(cParams)
            obj.testName = cParams.testName;
        end

        function compute(obj)
            filePath = fullfile('tests','Source','ReadingFilesTests','ReadingFiles','testReadingGmsh.msh');
            reader = GmsReader(filePath);
            reader.read();
            readData = reader.getDataBase();
            readData.isElemInThisSet = readData.isElemInThisSet{1};
            obj.variables = readData;
            obj.computation = obj;
        end
    end
end


% SB2_DIAGNOSTIC  Helper function to output diagnostics in SPARSEBAYES
%
% USAGE (1):
%
% OPTIONS = SB2_DIAGNOSTIC(OPTIONS, ACTION)
%
% OUTPUT ARGUMENTS:
%
%	OPTIONS		Returned OPTIONS settings, possibly updated
%				(e.g. with file handle after 'open' action)
%
% INPUT ARGUMENTS:
%
%	OPTIONS		Options settings (SB2_USEROPTIONS)
%
%	ACTION		One of:
%				'OPEN' or 'START'			Begin diagnostics
%				'CLOSE', 'END' or 'FINISH'	End diagnostics
%
%
% USAGE (2):
%
%	SB2_DIAGNOSTIC(OPTIONS, LEVEL, MESSAGE, VARARGIN ...)
%
% OUTPUT ARGUMENTS: None
%
% INPUT ARGUMENTS:
%
%	OPTIONS		Options settings (SB2_USEROPTIONS)
%
%	LEVEL		Importance level of message (0 to 4)
%				NB: LOWER is MORE IMPORTANT
%
%	MESSAGE		Message string
%
%	VARARGIN	Optional arguments to fill in string placeholders
%
% EXAMPLE:
%
%	OPTIONS = SB2_Diagnostic(OPTIONS, 'start');
%	SB2_Diagnostic(OPTIONS,2,'Total of %d likelihood updates\n', 25);
%	OPTIONS = SB2_Diagnostic(OPTIONS, 'end');
%
% NOTES:
%
% This function offers a convenient way to output diagnostic information,
% either to screen or to a file.
%
% It will "filter" the incoming messages and only display/write them if
% their LEVEL is less than or equal to the DIAGNOSTICLEVEL as set by
% SB2_USEROPTIONS.
%
% e.g. after
%
%	OPTIONS	= SB2_UserOptions('diagnosticLevel',2)
%
% This message won't display:
%
%	SB2_Diagnostic(OPTIONS, 3, 'Pointless message')
%
% But this will:
%
%	SB2_Diagnostic(OPTIONS, 1, 'Really important message')
%
% Messages of level 0 are therefore most "important", and those of level
% 4 least important. Level-0 messages are always displayed, since the
% DIAGNOSTICLEVEL will always be at least zero.
%

%
% Copyright 2009, Vector Anomaly Ltd
%
% This file is part of the SPARSEBAYES library for Matlab (V2.0).
%
% SPARSEBAYES is free software; you can redistribute it and/or modify it
% under the terms of the GNU General Public License as published by the Free
% Software Foundation; either version 2 of the License, or (at your option)
% any later version.
%
% SPARSEBAYES 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 SPARSEBAYES in the accompanying file "licence.txt"; if not, write to
% the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
% MA 02110-1301 USA
%
% Contact the author: m a i l [at] m i k e t i p p i n g . c o m
%
function OPTIONS = SB2_Diagnostic(OPTIONS, level, message_, varargin)

%
% Check if "level" is actually a string (this is a control call)
%
if ischar(level)
  switch upper(level)
   case {'OPEN','START'},
    if OPTIONS.diagnosticFID~=1
	  %
	  % If diagnosticFID is not 1, we must have previously set a
      % diagnostics file via SB2_USEROPTIONS
	  %
      OPTIONS.diagnosticFID	= fopen(OPTIONS.diagnosticFile_,'w');
      % Check for file open error
      if OPTIONS.diagnosticFID==-1
		error('Could not open diagnostic file ''%s''', value);
      end
    end
    %
   case {'CLOSE','END','FINISH'},
    if OPTIONS.diagnosticFID~=1
	  % diagnosticFID refers to a file opened above
      fclose(OPTIONS.diagnosticFID);
    end
  end
else
  %
  % Its a message call.
  %
  % Only output diagnostic messages if the "diagnostic level",
  % set via SB2_USEROPTIONS, is equal to or greater than the level of
  % the message to be displayed.
  %
  if level<=OPTIONS.diagnosticLevel
    fprintf(OPTIONS.diagnosticFID, repmat('    ', [1 level]));
    fprintf(OPTIONS.diagnosticFID, message_, varargin{:});
  end
end


function y = cvx_subs2str( x, mask, fieldalt )
if nargin < 2,
    mask = [ 1, 1, 1 ];
end
if nargin < 3,
    fieldalt = 0;
end
if ~isstruct( x ),
    error( 'First arugment must be a structure.' );
end
y = '';
needfield = fieldalt ~= 0;
for k = 1 : length( x ),
    try
        tp = x(k).type;
    catch %#ok
        error( 'Invalid subscript structure: field "type" is missing.' );
    end
    if ~ischar( tp ) || size( tp, 1 ) ~= 1,
        error( 'Invalid subscript entry #%d: field "type" must be a string', k );
    end
    try
        sb = x(k).subs;
    catch %#ok
        error( 'Invalid subscript structure: field "subs" is missing.' );
    end
    switch tp,
        case '.',
            if ~ischar( sb ) || size( sb, 1 ) ~= 1,
                error( 'Invalid subscript entry #%d: field name must be a string.', k );
            elseif ~isvarname( sb ),
                error( 'Invalid subscript entry #%d: invalid field name: %s', k, sb );
            end
            y = [ y, '.', sb ]; %#ok
            needfield = 0;
        case { '()', '{}' },
            if ~mask( 2 )&& tp(1) == '(',
                error( 'Invalid subscript entry #%d: array subscripts not allowed here.', k );
            elseif ~mask( 3 ) && tp(1) == '{',
                error( 'Invalid subscript entry #%d: cell subscripts not allowed here.', k );
            elseif needfield,
                error( 'Invalid subscript entry #%d: structure field expected here.', k );
            elseif ~iscell( sb ),
                error( 'Invalid subscript entry #%d: field "subs" must be a cell array.', k );
            elseif fieldalt,
                needfield = 1;
            end
            for j = 1 : length( sb ),
                if isnumeric( sb{j} ),
                    sb{j} = sprintf('%g',sb{j});
                elseif ~ischar( sb{j} ) || size( sb{j}, 1 ) ~= 1,
                    error( 'Invalid subscript entry #%d: invalid cell/array subscript', j );
                end
            end
            sb = sprintf( '%s,', sb{:} );
            y = [ y, tp(1), sb(1:end-1), tp(2) ]; %#ok
        otherwise,
            error( 'Invalid subscript entry #%d: invalid subscript tp: %s', k, tp );
    end
end

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function display( x )
long = ~isequal(get(0,'FormatSpacing'),'compact');
if long, disp( ' ' ); end
disp(x);
if long, disp( ' ' ); end

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


classdef prtUtilIntegerAssociativeArrayClassNames < prtUtilIntegerAssociativeArray
    % prtUtilIntegerAssociativeArray
    % xxx Need Help xxx

    methods
        function self = merge(self,other)
            temp = merge@prtUtilIntegerAssociativeArray(self,other);
            self = prtUtilIntegerAssociativeArrayClassNames(temp.integerKeys,temp.cellValues);
        end

        function obj = prtUtilIntegerAssociativeArrayClassNames(integerKeys,cellValues)

            if nargin == 0
                return;
            else
                obj.integerKeys = integerKeys;
                obj.cellValues = cellValues;
            end
        end

        function value = get(obj,key)
            value = cell(size(key));
            uKeys = unique(key);

            %this should be significantly faster for large vectors of keys,
            %which, btw, you should use instead of iterating over individual keys
            for uKeyInd = 1:length(uKeys)
                if isnan(uKeys(uKeyInd))
                    value(isnan(key)) = {'unlabeled'};
                else
                    keyInds = find(key == uKeys(uKeyInd));
                    refInds = find(uKeys(uKeyInd) == obj.integerKeys,1);

                    if isempty(refInds)
                        value(keyInds) = {sprintf('Class %d',uKeys(uKeyInd))};
                    else
                        value(keyInds) = {obj.cellValues{refInds}};
                    end
                end
            end

            %             for i = 1:length(key)
            %                 ind = find(key(i) == obj.integerKeys, 1);
            %                 if isempty(ind)
            %                     value{i} = sprintf('Class %d',key(i));
            %                 else
            %                     value{i} = obj.cellValues{ind};
            %                 end
            %             end
            %Don't return a cell in this case
%             if length(key) == 1
%                 value = value{1};
%             end

            % This has been changed 2013-06-12 because it is weird to do
            % this.
        end
    end
end


function value = p17_i4 ( action, name, value )

%*****************************************************************************80
%
%% P17_I4 sets or gets I4 parameters for problem 17.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string ACTION,
%    'D' to set a parameter to its default value.
%    'S' to set a parameter,
%    'G' to get a parameter,
%    'I' to increment a parameter.
%
%    Input, string NAME, the name of the variable.
%    '#' is the number of calls to the integrand routine.
%
%    Input/output, integer VALUE.
%    * If ACTION = 'I', then VALUE is an input quantity, and is the
%      new value to be added to NAME.
%    * If ACTION = 'S', then VALUE is an input quantity, and is the
%      new value to be assigned to NAME.
%    * If ACTION = 'G', then VALUE is an output quantity, and is the
%      current value of NAME.
%
  persistent calls;

  if ( action == 'D' | action == 'd' )

    if ( name == '#' | name == '*' )
      calls = 0;
    end

  elseif ( action == 'G' | action == 'g' )

    if ( name == '#' )
      value = calls;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P17_I4 - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized name = "%s".\n', name );
      error ( 'P17_I4 - Fatal error!' );
    end

  elseif ( action == 'I' | action == 'i' )

    if ( name == '#' )
      calls = calls + value;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P17_I4 - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized name = "%s".\n', name );
      error ( 'P17_I4 - Fatal error!' );
    end

  elseif ( action == 'S' | action == 's' )

    if ( name == '#' )
      calls = value;
    else
      fprintf ( 1, '\n' );
      fprintf ( 1, 'P17_I4 - Fatal error!\n' );
      fprintf ( 1, '  Unrecognized name = "%s".\n', name );
      error ( 'P17_I4 - Fatal error!' );
    end

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'P17_I4 - Fatal error!\n' );
    fprintf ( 1, '  Unrecognized action = "%s".\n', action );
    error ( 'P17_I4 - Fatal error!' );

  end

  return
end


function f_x = ParFor26(in1)
%PARFOR26
%    F_X = PARFOR26(IN1)

%    This function was generated by the Symbolic Math Toolbox version 8.1.
%    16-Jul-2019 11:58:24

f_x = 0.0;


function printCell(fid, cellArray, prefix)
  fprintf(fid, '%s', prefix);
  for ii=1:length(cellArray)
    if ii<length(cellArray)
      fprintf(fid, '%s ', cellArray{ii});
    else
      fprintf(fid, '%s\n', cellArray{ii});
    end
  end
end


function setforsave(h,linewidthvalue, fontsize)
% setforsave(h,linewidthvalue)
% Sets paramaters of the graph for saving. (linewidt, fontsize, minorticks)
if ~exist('fontsize','var')
    fontsize = 20;
end
if ~exist('linewidthvalue','var')
    linewidthvalue = 2;
end
if ~exist('h', 'var')
    h = gcf;
elseif isempty(h)
    h=gcf;
end

gh=get(h);
for ii=1:length(gh.Children)
    ga{ii} = get(gh.Children(ii));
end
figure (h)
setfontsizefigure(12)
for ii=1:length(gh.Children)
set(ga{ii}.Children, 'linewidth',linewidthvalue)

end
set(gh.Children,'XMinorTick','on', 'YMinorTick','on')
setfontsizefigure(fontsize)
grid on


function writeSupplementResultsLatex(ours, geom, ncuts)

gtdir = './figs/supp/gt/';
ourdir = './figs/supp/result/';
ncutdir = './figs/supp/ncut/';
geomdir = './figs/supp/geom/';

nf = numel(ours);

[sval, sind] = sort([ours(:).conservation], 'descend');
ours = ours(sind);
geom = geom(sind);
ncuts = ncuts(sind);

fn = {ours(:).imname};

outname = './results/suppfig.tex';

fid = fopen(outname, 'w');
for f = 1:nf

    if mod(f-1, 6)==0
        fprintf(fid, '\\begin{figure*} \n');
        fprintf(fid, '\\begin{center} \n');
        fprintf(fid, '\\begin{tabular}{cccc}\n');
    end

    fprintf(fid, '\\includegraphics[clip=true,trim=1in 3in 1in 3in, height=1.2in]');
    fprintf(fid, ['{' gtdir]);
    fprintf(fid, [strtok(fn{f}, '.') '_gt.pdf}  &  \\hspace{-.15in} \n ']);
    fprintf(fid, '\\includegraphics[clip=true,trim=1in 3in 1in 3in, height=1.2in]');
    fprintf(fid, ['{' ourdir]);
    fprintf(fid, [strtok(fn{f}, '.') '_res.pdf} & \\hspace{-.15in} \n ']);
    fprintf(fid, '\\includegraphics[clip=true,trim=1in 3in 1in 3in, height=1.2in]');
    fprintf(fid, ['{' geomdir]);
    fprintf(fid, [strtok(fn{f}, '.') '_res.pdf} & \\hspace{-.15in} \n ']);
    fprintf(fid, '\\includegraphics[clip=true,trim=1in 3in 1in 3in, height=1.2in]');
    fprintf(fid, ['{' ncutdir]);
    fprintf(fid, [strtok(fn{f}, '.') '_res.pdf} \\\\ \n']);
    fprintf(fid, ['Gt: (%.2f, %.2f) & Ours: (%.2f,%.2f) & Geom: (%.2f,%.2f) & Ncuts: (%.2f,%.2f) \\\\ \n'], ...
       0, 1, ours(f).efficiency, ours(f).conservation, ...
       geom(f).efficiency, geom(f).conservation, ncuts(f).efficiency, ncuts(f).conservation);

   if (mod(f, 6)==0 || f==nf)
        fprintf(fid, '\\end{tabular} \n');
        fprintf(fid, '\\end{center} \n');
        %fprintf(fid, '\\caption{}\n');
        fprintf(fid, '\\end{figure*}\n');
    end
end
fclose(fid);


%                               getExtraOpts.m
%
% This function creates and outputs a struct that consists of all the
% options in opts but not in otherOpts.
% It is used as a helper function in manageOptions.m and
% manageOptionsForBenchmark.m
%
% Inputs:
%         opts(struct)       :  consists of options.
%         otherOpts(struct)  :  consists of options.
% Outputs:
%         extras(struct)     :  consists of extral options appearing in
%                               opts but not in otherOpts.
%
%
% PhasePack by Rohan Chandra, Ziyuan Zhong, Justin Hontz, Val McCulloch,
% Christoph Studer, & Tom Goldstein
% Copyright (c) University of Maryland, 2017

function extras = getExtraOpts(opts, otherOpts)
    extras = struct;
    optNames = fieldnames(opts);

    for i = 1 : length(optNames)
        optName = optNames{i};
        if ~isfield(otherOpts, optName)
            extras.(optName) = opts.(optName);
        end
    end
end


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

%%
clear; close all; clc;

%% Syntax
% |dcmFolderAnon(pathName,varargin);|

%% Description
% This function aims to annonymise the dicom data in the folder pathName.
% See also: |dicomanon|

%% Examples
%

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


classdef TableExporter < handle

    properties (Access = public)
        writeVariableNames = true;
        writeRowNames = false;
        delimiter = ',';
    end

    methods (Access = public)

        function testExportTableForFileNames(obj,fileNames)

            labelingStrategy = DefaultLabelingStrategy();
            tableCreator = TableCreator();
            table = tableCreator.loadFeaturesTableFiltered(fileNames, labelingStrategy);
            featureSelector = FeatureSelector();
            bestFeatureIdxs = featureSelector.getBestNFeatures(9);
            table = table(:,[bestFeatureIdxs end]);
            obj.exportTable(table);
        end

        function exportTable(obj,table,fileName)
            writetable(table,fileName,'Delimiter',obj.delimiter,'WriteVariableNames',obj.writeVariableNames,'WriteRowNames',obj.writeRowNames);
        end
    end
end


function varargout=loadh5(filename, varargin)
%
%    [data, meta] = loadh5(filename)
%    [data, meta] = loadh5(root_id)
%    [data, meta] = loadh5(filename, rootpath)
%    [data, meta] = loadh5(filename, rootpath, options)
%    [data, meta] = loadh5(filename, options)
%    [data, meta] = loadh5(filename, 'Param1',value1, 'Param2',value2,...)
%
%    Load data in an HDF5 file to a MATLAB structure.
%
%    author: Qianqian Fang (q.fang <at> neu.edu)
%
%    input
%        filename
%            Name of the file to load data from
%        root_id: an HDF5 handle (of type 'H5ML.id' in MATLAB)
%        rootpath : (optional)
%            Root path to read part of the HDF5 file to load
%        options: (optional) a struct or Param/value pairs for user specified options
%            Order: 'creation' - creation order (default), or 'alphabet' - alphabetic
%            Regroup: [0|1]: if 1, call regrouph5() to combine indexed
%                  groups into a cell array
%            PackHex: [1|0]: convert invalid characters in the group/dataset
%                  names to 0x[hex code] by calling encodevarname.m;
%                  if set to 0, call getvarname
%            ComplexFormat: {'realKey','imagKey'}: use 'realKey' and 'imagKey'
%                  as possible keywords for the real and the imaginary part
%                  of a complex array, respectively (sparse arrays not supported);
%                  a common list of keypairs is used even without this option
%
%    output
%        data: a structure (array) or cell (array)
%        meta: optional output to store the attributes stored in the file
%
%    example:
%        a={rand(2), struct('va',1,'vb','string'), 1+2i};
%        saveh5(a,'test.h5');
%        a2=loadh5('test.h5')
%        a3=loadh5('test.h5','regroup',1)
%        isequaln(a,a3.a)
%        a4=loadh5('test.h5','/a1')
%
%    This function was adapted from h5load.m by Pauli Virtanen <pav at iki.fi>
%    This file is part of EasyH5 Toolbox: https://github.com/fangq/easyh5
%
%    License: GPLv3 or 3-clause BSD license, see https://github.com/fangq/easyh5 for details
%

path = '';
if(bitand(length(varargin),1)==0)
    opt=varargin2struct(varargin{:});
elseif(length(varargin)>=3)
    path=varargin{1};
    opt=varargin2struct(varargin{2:end});
elseif(length(varargin)==1)
    path=varargin{1};
end

if(isa(filename,'H5ML.id'))
    loc=filename;
else
    if(exist('h5read','file'))
        loc = H5F.open(filename);
    else
        error('HDF5 is not supported');
    end
end

opt.rootpath=path;

if(~(isfield(opt,'complexformat') && iscellstr(opt.complexformat) && numel(opt.complexformat)==2))
    opt.complexformat={'Real','Imag'};
end

opt.releaseid=0;
vers=ver('MATLAB');
if(~isempty(vers))
    opt.releaseid=datenum(vers(1).Date);
end

if((isfield(opt,'order') && strcmpi(opt.order,'alphabet'))  || opt.releaseid<datenum('1-Jan-2015') )
    opt.order='H5_INDEX_NAME';
else
    opt.order='H5_INDEX_CRT_ORDER';
end

try
  if(nargin>1 && ~isempty(path))
      try
          rootgid=H5G.open(loc,path);
          [varargout{1:nargout}]=load_one(rootgid, opt);
          H5G.close(rootgid);
      catch
          [gname,dname]=fileparts(path);
          rootgid=H5G.open(loc,gname);
          [status, res]=group_iterate(rootgid,dname,struct('data',struct,'meta',struct,'opt',opt));
          if(nargout>0)
              varargout{1}=res.data;
          elseif(nargout>1)
              varargout{2}=res.meta;
          end
          H5G.close(rootgid);
      end
  else
      [varargout{1:nargout}]=load_one(loc, opt);
  end
  H5F.close(loc);
catch ME
  H5F.close(loc);
  rethrow(ME);
end

if(jsonopt('Regroup',0,opt))
    if(nargout>=1)
        varargout{1}=regrouph5(varargout{1});
    elseif(nargout>=2)
        varargout{2}=regrouph5(varargout{2});
    end
end

if(isfield(opt,'jdata') && opt.jdata && nargout>=1)
    varargout{1}=jdatadecode(varargout{1},'Base64',0,opt);
end

%--------------------------------------------------------------------------
function [data, meta]=load_one(loc, opt)

data = struct();
meta = struct();
inputdata=struct('data',data,'meta',meta,'opt',opt);

% Load groups and datasets
try
    [status,count,inputdata] = H5L.iterate(loc,opt.order,'H5_ITER_INC',0,@group_iterate,inputdata);
catch ME
    if(strcmp(opt.order,'H5_INDEX_CRT_ORDER'))
        [status,count,inputdata] = H5L.iterate(loc,'H5_INDEX_NAME','H5_ITER_INC',0,@group_iterate,inputdata);
    else
        rethrow(ME);
    end
end

data=inputdata.data;
meta=inputdata.meta;

%--------------------------------------------------------------------------
function [status, res]=group_iterate(group_id,objname,inputdata)
status=0;
attr=struct();

encodename=jsonopt('PackHex',1,inputdata.opt);

try
  data=inputdata.data;
  meta=inputdata.meta;

  % objtype index
  info = H5G.get_objinfo(group_id,objname,0);
  objtype = info.type;
  objtype = objtype+1;

  if objtype == 1
    % Group
    name = regexprep(objname, '.*/', '');

	group_loc = H5G.open(group_id, name);
	try
	  [sub_data, sub_meta] = load_one(group_loc, inputdata.opt);
	  H5G.close(group_loc);
	catch ME
	  H5G.close(group_loc);
	  rethrow(ME);
	end
	if(encodename)
        name=encodevarname(name);
    else
        name=genvarname(name);
    end
    data.(name) = sub_data;
    meta.(name) = sub_meta;

  elseif objtype == 2
    % Dataset
    name = regexprep(objname, '.*/', '');

	dataset_loc = H5D.open(group_id, name);
	try
	  sub_data = H5D.read(dataset_loc, ...
	      'H5ML_DEFAULT', 'H5S_ALL','H5S_ALL','H5P_DEFAULT');
          [status, count, attr]=H5A.iterate(dataset_loc, 'H5_INDEX_NAME', 'H5_ITER_INC', 0, @getattribute, attr);
	  H5D.close(dataset_loc);
	catch exc
	  H5D.close(dataset_loc);
	  rethrow(exc);
	end

	sub_data = fix_data(sub_data, attr, inputdata.opt);
	if(encodename)
        name=encodevarname(name);
    else
        name=genvarname(name);
    end
    data.(name) = sub_data;
    meta.(name) = attr;
  end
catch ME
    rethrow(ME);
end
res=struct('data',data,'meta',meta,'opt',inputdata.opt);

%--------------------------------------------------------------------------
function data=fix_data(data, attr, opt)
% Fix some common types of data to more friendly form.

if isstruct(data)
  fields = fieldnames(data);

  if(length(intersect(fields,{'SparseIndex',opt.complexformat{1}}))==2)
    if isnumeric(data.SparseIndex) && isnumeric(data.(opt.complexformat{1}))
      if(nargin>1 && isstruct(attr))
          if(isfield(attr,'SparseArraySize'))
              spd=sparse(1,prod(attr.SparseArraySize));
              if(isfield(data,opt.complexformat{2}))
                  spd(data.SparseIndex)=complex(data.(opt.complexformat{1}),data.(opt.complexformat{2}));
              else
                  spd(data.SparseIndex)=data.(opt.complexformat{1});
              end
              data=reshape(spd,attr.SparseArraySize(:)');
              return;
          end
      end
    end
  else
      if(numel(opt.complexformat)==2 && length(intersect(fields,opt.complexformat))==2)
        if isnumeric(data.(opt.complexformat{1})) && isnumeric(data.(opt.complexformat{2}))
            data = data.(opt.complexformat{1}) + 1j*data.(opt.complexformat{2});
        end
      else
        % if complexformat is not specified or not found, try some common complex number storage formats
        if(length(intersect(fields,{'Real','Imag'}))==2)
          if isnumeric(data.Real) && isnumeric(data.Imag)
            data = data.Real + 1j*data.Imag;
          end
        elseif(length(intersect(fields,{'real','imag'}))==2)
          if isnumeric(data.real) && isnumeric(data.imag)
            data = data.real + 1j*data.imag;
          end
        elseif(length(intersect(fields,{'Re','Im'}))==2)
          if isnumeric(data.Re) && isnumeric(data.Im)
            data = data.Re + 1j*data.Im;
          end
        elseif(length(intersect(fields,{'re','im'}))==2)
          if isnumeric(data.re) && isnumeric(data.im)
            data = data.re + 1j*data.im;
          end
        elseif(length(intersect(fields,{'r','i'}))==2)
          if isnumeric(data.r) && isnumeric(data.i)
            data = data.r + 1j*data.i;
          end
        end
      end
  end
end

if(isa(data,'uint8') || isa(data,'int8'))
  if(nargin>1 && isstruct(attr))
      if(isfield(attr,'MATLABObjectClass'))
         data=getArrayFromByteStream(data); % use undocumented function
      end
  end
end

%--------------------------------------------------------------------------
function [status, dataout]= getattribute(loc_id,attr_name,info,datain)
status=0;
attr_id = H5A.open(loc_id, attr_name, 'H5P_DEFAULT');
datain.(attr_name) = H5A.read(attr_id, 'H5ML_DEFAULT');
H5A.close(attr_id);
dataout=datain;


% compile mex file
mex mex/perform_front_propagation_2d.cpp mex/perform_front_propagation_2d_mex.cpp mex/fheap/fib.cpp
mex mex/perform_front_propagation_3d.cpp mex/perform_front_propagation_3d_mex.cpp  mex/fheap/fib.cpp
mex mex/perform_circular_front_propagation_2d.cpp mex/perform_front_propagation_2d.cpp mex/fheap/fib.cpp

% Alec: these do not actually exist
% % anisotropic FM
% mex mex/anisotropic-fm//perform_front_propagation_anisotropic.cpp
% mex mex/anisotropic-fm-feth/fm2dAniso.cpp

% compiling skeleton
mex mex/skeleton.cpp
% compiling distance transform
mex mex/eucdist2.c

disp('Compiling perform_front_propagation_mesh, might time some time.');
rep = 'mex/';
files =  { ...
    'perform_front_propagation_mesh.cpp', ...
    'gw/gw_core/GW_Config.cpp',           ...
    'gw/gw_core/GW_FaceIterator.cpp',     ...
    'gw/gw_core/GW_SmartCounter.cpp',     ...
    'gw/gw_core/GW_VertexIterator.cpp',   ...
    'gw/gw_core/GW_Face.cpp',             ...
    'gw/gw_core/GW_Mesh.cpp',             ...
    'gw/gw_core/GW_Vertex.cpp',       ...
    'gw/gw_geodesic/GW_GeodesicFace.cpp', ...
    'gw/gw_geodesic/GW_GeodesicMesh.cpp',     ...
    'gw/gw_geodesic/GW_GeodesicPath.cpp',         ...
    'gw/gw_geodesic/GW_GeodesicPoint.cpp',            ...
    'gw/gw_geodesic/GW_TriangularInterpolation_Cubic.cpp', ...
    'gw/gw_geodesic/GW_GeodesicVertex.cpp',                    ...
    'gw/gw_geodesic/GW_TriangularInterpolation_Linear.cpp',      ...
    'gw/gw_geodesic/GW_TriangularInterpolation_Quadratic.cpp',  ...
};
str = 'mex ';
for i=1:length(files)
    str = [str rep files{i} ' '];
end
eval(str);


matlabbatch{1}.spm.tools.physio.save_dir = {'physio_out'};
matlabbatch{1}.spm.tools.physio.log_files.vendor = 'Siemens';
matlabbatch{1}.spm.tools.physio.log_files.cardiac = {'20191023_V02.puls'};
matlabbatch{1}.spm.tools.physio.log_files.respiration = {'20191023_V02.resp'};
matlabbatch{1}.spm.tools.physio.log_files.scan_timing = {'MR.27842.1230'};
matlabbatch{1}.spm.tools.physio.log_files.sampling_interval = 0.0025;
matlabbatch{1}.spm.tools.physio.log_files.relative_start_acquisition = [];
matlabbatch{1}.spm.tools.physio.log_files.align_scan = 'first';
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Nslices = 24;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.NslicesPerBeat = [];
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.TR = 1.5;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Ndummies = 0;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Nscans = 382;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.onset_slice = 5;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.time_slice_to_slice = 0.0625;
matlabbatch{1}.spm.tools.physio.scan_timing.sqpar.Nprep = [];
matlabbatch{1}.spm.tools.physio.scan_timing.sync.scan_timing_log = struct([]);
matlabbatch{1}.spm.tools.physio.preproc.cardiac.modality = 'PPU';
matlabbatch{1}.spm.tools.physio.preproc.cardiac.filter.no = struct([]);
matlabbatch{1}.spm.tools.physio.preproc.cardiac.initial_cpulse_select.auto_matched.min = 0.4;
matlabbatch{1}.spm.tools.physio.preproc.cardiac.initial_cpulse_select.auto_matched.file = 'initial_cpulse_kRpeakfile.mat';
matlabbatch{1}.spm.tools.physio.preproc.cardiac.initial_cpulse_select.auto_matched.max_heart_rate_bpm = 120;
matlabbatch{1}.spm.tools.physio.preproc.cardiac.posthoc_cpulse_select.off = struct([]);
matlabbatch{1}.spm.tools.physio.preproc.respiratory.filter.passband = [0.01 2];
matlabbatch{1}.spm.tools.physio.preproc.respiratory.despike = false;
matlabbatch{1}.spm.tools.physio.model.output_multiple_regressors = 'multiple_regressors.txt';
matlabbatch{1}.spm.tools.physio.model.output_physio = 'physio.mat';
matlabbatch{1}.spm.tools.physio.model.orthogonalise = 'none';
matlabbatch{1}.spm.tools.physio.model.censor_unreliable_recording_intervals = false;
matlabbatch{1}.spm.tools.physio.model.retroicor.yes.order.c = 3;
matlabbatch{1}.spm.tools.physio.model.retroicor.yes.order.r = 4;
matlabbatch{1}.spm.tools.physio.model.retroicor.yes.order.cr = 1;
matlabbatch{1}.spm.tools.physio.model.rvt.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.hrv.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.noise_rois.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.movement.no = struct([]);
matlabbatch{1}.spm.tools.physio.model.other.no = struct([]);
matlabbatch{1}.spm.tools.physio.verbose.level = 2;
matlabbatch{1}.spm.tools.physio.verbose.fig_output_file = '';
matlabbatch{1}.spm.tools.physio.verbose.use_tabs = false;


% ********************************************************************
% * mex File compiling code for Random Forest (for linux)
% * mex interface to Andy Liaw et al.'s C code (used in R package randomForest)
% * Added by Abhishek Jaiantilal ( abhishek.jaiantilal@colorado.edu )
% * License: GPLv2
% * Version: 0.02
% ********************************************************************/

function compile_windows
    system('del *.mexw32;del *.mexw64;');

    fprintf('I am going to use the precompiled fortran file\n');
    fprintf('If it doesnt work then use cygwin+g77 (or gfortran) to recompile rfsub.f\n');

    if strcmp(computer,'PCWIN64')
        mex  -DMATLAB -DWIN64 -output mexClassRF_train   src/classRF.cpp src/classTree.cpp src/cokus.cpp precompiled_rfsub/win64/rfsub.o src/mex_ClassificationRF_train.cpp   src/rfutils.cpp
        mex  -DMATLAB -DWIN64 -output mexClassRF_predict src/classRF.cpp src/classTree.cpp src/cokus.cpp precompiled_rfsub/win64/rfsub.o src/mex_ClassificationRF_predict.cpp src/rfutils.cpp
    elseif strcmp(computer,'PCWIN')
        mex  -DMATLAB -output mexClassRF_train   src/classRF.cpp src/classTree.cpp src/cokus.cpp precompiled_rfsub/win32/rfsub.o src/mex_ClassificationRF_train.cpp   src/rfutils.cpp
        mex  -DMATLAB -output mexClassRF_predict src/classRF.cpp src/classTree.cpp src/cokus.cpp precompiled_rfsub/win32/rfsub.o src/mex_ClassificationRF_predict.cpp src/rfutils.cpp
    else
        error('Wrong script to run on this Comp architecture. I cannot detect any windows system')
    end
    fprintf('Mex`s compiled correctly\n')