function data = read_artinis_oxy55(filename, header, begsample, endsample, chanindx)
% reads Artinix oxy55-files into FieldTrip format
%
% use as
%   header = read_artinis_oxy5(filename)
% or
%   event  = read_artinis_oxy5(filename, read_event)
% where read_event is a Boolean with the value true, or
%   data   = read_artinis_oxy55(filename, header, [begsample], [endsample], [chanindx])
% where begsample, endsample and chanindx are optional.
%
% The returned variables will be in FieldTrip style.
%
% See also FT_READ_HEADER, FT_READ_DATA, READ_ARTINIS_OXU5

% You are using the FieldTrip NIRS toolbox developed and maintained by
% Artinis Medical Systems (http://www.artinis.com). For more information
% on FieldTrip, see http://www.fieldtriptoolbox.org
%
% This work is licensed under a Creative Commons Attribution-ShareAlike 4.0
% International License. To view a copy of this license, visit
% http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to
% Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
%
% Creative Commons Attribution-ShareAlike 4.0 International License:
% -----------------------------------
% You are free to:
%
%     Share - copy and redistribute the material in any medium or format
%     Adapt - remix, transform, and build upon the material
%     for any purpose, even commercially.
%
%     The licensor cannot revoke these freedoms as long as you follow the
%     license terms.
%
% Under the following terms:
%
%     Attribution - You must give appropriate credit, provide a link to
%                    the license, and indicate if changes were made. You
%                    may do so in any reasonable manner, but not in any way
%                    that suggests the licensor endorses you or your use.
%
%     ShareAlike - If you remix, transform, or build upon the material,
%                   you must distribute your contributions under the same
%                   license as the original.
%
%     No additional restrictions - You may not apply legal terms or
%                                   technological measures that legally
%                                   restrict others from doing anything the
%                                   license permits.
%
% -----------------------------------
%
% This toolbox is not to be used for medical or clinical purposes.
%
% Copyright (c) 2021 by Artinis Medical Systems.
% Contact: askforinfo@artinis.com

if nargin > 2 && islogical(header)
  % header must be defined if begsample and endsample are used
  error('wrong type of header variable.')
end

if nargin == 1 || nargin == 2 && islogical(header) && ~header
  data = read_oxy5_header(filename);
  if isfield(data, 'opto')
    % ensure that the optode definition is according to the latest standards
    data.opto = ft_datatype_sens(data.opto);
  end
elseif nargin == 2  && islogical(header) && header
  data = read_oxy3_event(filename);
else % nargin > 1 && ~islogical(header)
  if nargin < 5
    chanindx = 1:header.nChans;
    if nargin < 4
      endsample = header.nSamples;
      if nargin < 3
        begsample = 1;
      end
    end
  end
  data = read_oxy5_data(filename, 0, header.nSamples); % sample subselection does not work yet

  if endsample > size(data, 2)
    warning('Cannot deliver all requested samples, nan''ing %d sample(s)', endsample-size(data, 2));
    data(:, end:endsample) = nan;
  end

  data = data(chanindx, begsample:endsample);
end


clear
if(isunix)
    features_exe = '"../../../build/bin/FeatureExtraction"';
else
    features_exe = '"../../../x64/Release/FeatureExtraction.exe"';
end
ck_loc = 'E:\Datasets\ck+\cohn-kanade-images\';

out_loc = 'E:\datasets\face_datasets_processed/ck+';

% Go two levels deep
ck_dirs = dir(ck_loc);
ck_dirs = ck_dirs(3:end);

parfor f1=1:numel(ck_dirs)

    ck_dirs_level_2 = dir([ck_loc, ck_dirs(f1).name]);
    ck_dirs_level_2 = ck_dirs_level_2(3:end);

    for f2=1:numel(ck_dirs_level_2)

        if(~isdir([ck_loc, ck_dirs(f1).name, '/', ck_dirs_level_2(f2).name]))
           continue;
        end

        curr_vid = [ck_loc, ck_dirs(f1).name, '/', ck_dirs_level_2(f2).name];

        name = [ck_dirs(f1).name, '_',  ck_dirs_level_2(f2).name];

        command = sprintf('%s -fdir "%s" -out_dir "%s" -of %s -hogalign -pdmparams', features_exe, curr_vid, out_loc, name);

        dos(command);

    end

end


function obj = coeftq2_hand_eye_func_new(in1)
coef_J12 = in1(:,12);
coef_J22 = in1(:,22);
coef_J29 = in1(:,29);
coef_J34 = in1(:,34);
coef_J44 = in1(:,44);
coef_J51 = in1(:,51);
coef_J56 = in1(:,56);
coef_J63 = in1(:,63);
coef_J68 = in1(:,68);
coef_J73 = in1(:,73);
coef_J82 = in1(:,82);
obj = [coef_J12,coef_J22,coef_J29,coef_J34,coef_J44,coef_J51,coef_J56,coef_J63,coef_J68,coef_J73,coef_J82];


function toolboxUpdateHeader
% Update the headers of all the files.
%
% USAGE
%  toolboxUpdateHeader
%
% INPUTS
%
% OUTPUTS
%
% EXAMPLE
%
% See also
%
% Piotr's Image&Video Toolbox      Version 3.22
% Copyright 2013 Piotr Dollar.  [pdollar-at-caltech.edu]
% Please email me if you find bugs, or have suggestions or questions!
% Licensed under the Simplified BSD License [see external/bsd.txt]

header={
  '% Piotr''s Image&Video Toolbox      Version 3.22'; ...
  '% Copyright 2013 Piotr Dollar.  [pdollar-at-caltech.edu]'; ...
  '% Please email me if you find bugs, or have suggestions or questions!'; ...
  '% Licensed under the Simplified BSD License [see external/bsd.txt]'};

% must start in /toolbox base directory
cd(fileparts(mfilename('fullpath'))); cd('../');
dirs={ 'channels', 'classify', 'classify/private', 'detector', ...
  'filters', 'images', 'images/private', 'matlab', 'external' };

% update the headers
for i=1:length(dirs)
  mFiles = dir([ dirs{i}, '/*.m' ]);
  disp( ['--------------------------------->' dirs{i}] );
  for j=1:length(mFiles);
    fName = [dirs{i} '/' mFiles(j).name]; disp( fName );
    toolboxUpdateHeader1( fName, header );
  end
end

end

function toolboxUpdateHeader1( fName, header )
lines=readFile(fName); n=length(lines);

% find first part of first lines of header in file
loc = strfind(lines,header{1}(1:30));
for i=1:n, if(~isempty(loc{i})), break; end; end; loc=i;

% if not found nothing to do, ow assert nHeader lines exist
nHeader = length(header);
if(loc>n-nHeader+1), warning([fName ' no header']); return; end %#ok<WNTAG>
for i=1:nHeader; assert( strfind(lines{loc+i-1},header{i}(1:10))>0 ); end

% check if first lines changed, if so update; optionally update rest
if(~any(strfind(lines{loc},'NEW'))); return; end
lines{loc+1}(13:16)=header{2}(13:16);
for i=[1 3:nHeader]; lines{loc+i-1}=header{i}; end
assert(isempty(lines{loc-1}) || strcmp(lines{loc-1},'%'));
lines{loc-1} = '%'; writeFile( fName, lines );

end

function lines = readFile( fName )
fid = fopen( fName, 'rt' ); assert(fid~=-1);
lines=cell(10000,1); n=0;
while( 1 )
  n=n+1; lines{n}=fgetl(fid);
  if( ~ischar(lines{n}) ), break; end
end
fclose(fid); n=n-1; lines=lines(1:n);
end

function writeFile( fName, lines )
fid = fopen( fName, 'wt' );
for i=1:length(lines); fprintf( fid, '%s\n', lines{i} ); end
fclose(fid);
end


function SO3F = uminus(SO3F)
% overloads |-SO3F|

components = cellfun(@(x) -x,SO3F.components,'UniformOutput',false);
SO3F.components = components;

end


function data = loadmsgpack(fname,varargin)
%
%   data = loadmsgpack(fname,varargin)
%
%LOADMSGPACK parses a msgpack byte buffer into Matlab data structures
% LOADMSGPACK(BYTES)
%    reads BYTES as msgpack data, and creates Matlab data structures
%    from it.
%    - strings are converted to strings
%    - numbers are converted to appropriate numeric values
%    - true, false are converted to logical 1, 0
%    - nil is converted to []
%    - arrays are converted to cell arrays
%    - maps are converted to containers.Map
%
% (c) 2016 Bastian Bechtold
% modified by Qianqian Fang <q.fang at neu.edu>
%
% license:
%     BSD 3-clause license or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
%
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
%

    if(exist(fname,'file'))
       fid = fopen(fname,'rb');
       bytes = fread(fid,inf,'uint8=>char')';
       fclose(fid);
    else
       bytes=fname;
    end

    opt=varargin2struct(varargin{:});
    opt.simplifycell=jsonopt('SimplifyCell',1,opt);
    opt.simplifycellarray=jsonopt('SimplifyCellArray',0,opt);

    jsoncount=1;
    idx=0;
    while idx <= length(bytes)
        [obj, idx] = parse(uint8(bytes(:)), 1, opt);
        data{jsoncount}=obj;
        jsoncount=jsoncount+1;
    end

    jsoncount=length(data);
    if(jsoncount==1 && iscell(data))
        data=data{1};
    end
    if(iscell(data))
        data=cellfun(@(x) jdatadecode(x),data,'UniformOutput',false);
    elseif(isstruct(data))
        data=jdatadecode(data,'Base64',0, opt);
    end
end

function [obj, idx] = parse(bytes, idx, varargin)
    % masks:
    b10000000 = 128;
    b01111111 = 127;
    b11000000 = 192;
    b00111111 = 63;
    b11100000 = 224;
    b00011111 = 31;
    b11110000 = 240;
    b00001111 = 15;
    % values:
    b00000000 = 0;
    b10010000 = 144;
    b10100000 = 160;

    currentbyte = bytes(idx);

    if bitand(b10000000, currentbyte) == b00000000
        % decode positive fixint
        obj = int8(currentbyte);
        idx = idx + 1;
        return
    elseif bitand(b11100000, currentbyte) == b11100000
        % decode negative fixint
        obj = typecast(currentbyte, 'int8');
        idx = idx + 1;
        return
    elseif bitand(b11110000, currentbyte) == b10000000
        % decode fixmap
        len = double(bitand(b00001111, currentbyte));
        [obj, idx] = parsemap(len, bytes, idx+1, varargin{:});
        return
    elseif bitand(b11110000, currentbyte) == b10010000
        % decode fixarray
        len = double(bitand(b00001111, currentbyte));
        [obj, idx] = parsearray(len, bytes, idx+1, varargin{:});
        return
    elseif bitand(b11100000, currentbyte) == b10100000
        % decode fixstr
        len = double(bitand(b00011111, currentbyte));
        [obj, idx] = parsestring(len, bytes, idx + 1);
        return
    end

    switch currentbyte
        case 192 % nil
            obj = [];
            idx = idx+1;
      % case 193 % unused
        case 194 % false
            obj = false;
            idx = idx+1;
        case 195 % true
            obj = true;
            idx = idx+1;
        case 196 % bin8
            len = double(bytes(idx+1));
            [obj, idx] = parsebytes(len, bytes, idx+2);
        case 197 % bin16
            len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
            [obj, idx] = parsebytes(len, bytes, idx+3);
        case 198 % bin32
            len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
            [obj, idx] = parsebytes(len, bytes, idx+5);
        case 199 % ext8
            len = double(bytes(idx+1));
            [obj, idx] = parseext(len, bytes, idx+1);
        case 200 % ext16
            len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
            [obj, idx] = parseext(len, bytes, idx+3);
        case 201 % ext32
            len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
            [obj, idx] = parseext(len, bytes, idx+5);
        case 202 % float32
            obj = bytes2scalar(bytes(idx+1:idx+4), 'single');
            idx = idx+5;
        case 203 % float64
            obj = bytes2scalar(bytes(idx+1:idx+8), 'double');
            idx = idx+9;
        case 204 % uint8
            obj = bytes(idx+1);
            idx = idx+2;
        case 205 % uint16
            obj = bytes2scalar(bytes(idx+1:idx+2), 'uint16');
            idx = idx+3;
        case 206 % uint32
            obj = bytes2scalar(bytes(idx+1:idx+4), 'uint32');
            idx = idx+5;
        case 207 % uint64
            obj = bytes2scalar(bytes(idx+1:idx+8), 'uint64');
            idx = idx+9;
        case 208 % int8
            obj = bytes2scalar(bytes(idx+1), 'int8');
            idx = idx+2;
        case 209 % int16
            obj = bytes2scalar(bytes(idx+1:idx+2), 'int16');
            idx = idx+3;
        case 210 % int32
            obj = bytes2scalar(bytes(idx+1:idx+4), 'int32');
            idx = idx+5;
        case 211 % int64
            obj = bytes2scalar(bytes(idx+1:idx+8), 'int64');
            idx = idx+9;
        case 212 % fixext1
            [obj, idx] = parseext(1, bytes, idx+1);
        case 213 % fixext2
            [obj, idx] = parseext(2, bytes, idx+1);
        case 214 % fixext4
            [obj, idx] = parseext(4, bytes, idx+1);
        case 215 % fixext8
            [obj, idx] = parseext(8, bytes, idx+1);
        case 216 % fixext16
            [obj, idx] = parseext(16, bytes, idx+1);
        case 217 % str8
            len = double(bytes(idx+1));
            [obj, idx] = parsestring(len, bytes, idx+2);
        case 218 % str16
            len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
            [obj, idx] = parsestring(len, bytes, idx+3);
        case 219 % str32
            len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
            [obj, idx] = parsestring(len, bytes, idx+5);
        case 220 % array16
            len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
            [obj, idx] = parsearray(len, bytes, idx+3, varargin{:});
        case 221 % array32
            len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
            [obj, idx] = parsearray(len, bytes, idx+5, varargin{:});
        case 222 % map16
            len = double(bytes2scalar(bytes(idx+1:idx+2), 'uint16'));
            [obj, idx] = parsemap(len, bytes, idx+3, varargin{:});
        case 223 % map32
            len = double(bytes2scalar(bytes(idx+1:idx+4), 'uint32'));
            [obj, idx] = parsemap(len, bytes, idx+5, varargin{:});
        otherwise
            error('JSONLAB:MSGPACK:InvalidFormat', ...
                  ['Unknown type "' dec2bin(currentbyte) '"']);
    end
end

function value = bytes2scalar(bytes, type)
    % reverse byte order to convert from little-endian to big-endian
    value = typecast(bytes(end:-1:1), type);
end

function [str, idx] = parsestring(len, bytes, idx)
    if(~isoctavemesh)
         str = native2unicode(bytes(idx:idx+len-1)', 'utf-8');
    else
         str = char(bytes(idx:idx+len-1)');
    end
    idx = idx + len;
end

function [out, idx] = parsebytes(len, bytes, idx)
    out = bytes(idx:idx+len-1);
    idx = idx + len;
end

function [out, idx] = parseext(len, bytes, idx)
    obj.type = bytes(idx);
    obj.data = bytes(idx+1:idx+len);
    idx = idx + len + 1;
end

function [out, idx] = parsearray(len, bytes, idx, varargin)
    out = cell(1,len);
    for n=1:len
        [out{n}, idx] = parse(bytes, idx, varargin{:});
    end
    if(len==1)
        out=out{1};
    end
    if(varargin{1}.simplifycell)
        if(iscell(out) && ~isempty(out) && isnumeric(out{1}))
          if(all(cellfun(@(e) isequal(size(out{1}), size(e)) , out(2:end))))
              try
                  oldobj=out;
                  if(iscell(out) && length(out)>1 && ndims(out{1})>=2)
                      catdim=size(out{1});
                      catdim=ndims(out{1})-(catdim(end)==1)+1;
                      out=cat(catdim,out{:});
                      out=permute(out,ndims(out):-1:1);
                  else
                      out=cell2mat(out')';
                  end
                  if(iscell(oldobj) && isstruct(out) && numel(out)>1 && varargin{1}.simplifycellarray==0)
                      out=oldobj;
                  end
              catch
              end
          end
        end
        if(~iscell(out) && size(out,2)>1 && ndims(out)==2)
            out=out';
        end
    end
end

function [out, idx] = parsemap(len, bytes, idx, varargin)
    out = struct();
    for n=1:len
        [key, idx] = parse(bytes, idx, varargin{:});
        [out.(encodevarname(char(key))), idx] = parse(bytes, idx, varargin{:});
    end
end


function X = flushmidfactors(X)
for i = 1:length(X.midfactors)
    if isa(X.midfactors{i},'sdpvar')
        X.midfactors{i} = flush(X.midfactors{i});
    end
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');

% 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 = [];
    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 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);
  % 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 varargin = conv(varargout)
%CONV   Operation not supported for TRIGTECH objects.
%
%   Use the function CIRCCONV.
%
% See also CIRCCONV.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

error('CHEBFUN:TRIGTECH:conv:NotSupported', ...
    'CONV is not supported for trigtech objects. Use the function CIRCCONV.');

end


close all; clear all; clc;

audio = audioload();

file = 'text.txt';
fid  = fopen(file, 'r');
text = fread(fid,'*char')';
fclose(fid);

out = iss_enc(audio.data, text);
audiosave(out, audio, '.mp3', 128);


function [h, icons, plots, legend_text] = addLegendItem(item, pos)
% Add an item to the legend
% SYNTAX:
%   addLegendItem(<item>, <pos>);
%
% EXAMPLE:
%   addLegendItem("item", 2);;
%
% INPUT:
%   item = new entry
%   pos  = position in the list of inputs
%
% DEFAULT VALUES:
%   fig_handle = gcf;
%

%--------------------------------------------------------------------------
%               ___ ___ ___
%     __ _ ___ / __| _ | __|
%    / _` / _ \ (_ |  _|__ \
%    \__, \___/\___|_| |___/
%    |___/                    v 1.0RC1
%
%--------------------------------------------------------------------------
%  Copyright (C) 2021 Geomatics Research & Development srl (GReD)
%  Written by:       Andrea Gatti
%  Contributors:     Andrea Gatti, ...
%  A list of all the historical goGPS contributors is in CREDITS.nfo
%--------------------------------------------------------------------------
%
%    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/>.
%
%--------------------------------------------------------------------------
% 01100111 01101111 01000111 01010000 01010011
%--------------------------------------------------------------------------
    l = legend;
    outm = get(l,'String');
    if nargin == 1
        pos = numel(outm) + 1;
    end
    if isempty(outm)
        [h, icons, plots, legend_text] = legend(item, 'Location', 'eastoutside');
        n_entry = 1;
        icons = icons(n_entry + 2 : 2 : end);
    else
        outm{pos} = item;
        [h, icons] = legend(outm, 'Location', 'eastoutside');
        n_entry = numel(outm);
        icons = icons(n_entry + 2 : 2 : end);
    end
end


function [OutputError,ima,frame_nr_display] = PIVlab_capture_OPTOcam_calibration_image(img_amount,exposure_time,ROI_OPTOcam)
OutputError=0;
hgui=getappdata(0,'hgui');
%% Prepare camera
try
    delete(imaqfind); %clears all previous videoinputs
    hwinf = imaqhwinfo;
    %imaqreset
catch
    errordlg('Error: Image Acquisition Toolbox not available!','Error!','modal')
    disp('Error: Image Acquisition Toolbox not available!')
end

info = imaqhwinfo(hwinf.InstalledAdaptors{1});

if strcmp(info.AdaptorName,'gentl')
    disp('gentl adaptor found.')
else
    disp('ERROR: gentl adaptor not found. Please got to Matlab file exchange and search for "GenICam Interface " to install it.')
	errordlg('ERROR: gentl adaptor not found. Please got to Matlab file exchange and search for "GenICam Interface " to install it.','Error!','modal')
end

try
	OPTOcam_name = info.DeviceInfo.DeviceName;
catch
	errordlg('Error: Camera not found! Is it connected?','Error!','modal')
end
disp(['Found camera: ' OPTOcam_name])
OPTOcam_supported_formats = info.DeviceInfo.SupportedFormats;
OPTOcam_vid = videoinput(info.AdaptorName,info.DeviceInfo.DeviceID,'Mono12'); %calibration image in 12 bit always.

OPTOcam_settings = get(OPTOcam_vid);
OPTOcam_settings.Source.DeviceLinkThroughputLimitMode = 'off';
OPTOcam_settings.PreviewFullBitDepth='On';
OPTOcam_vid.PreviewFullBitDepth='On';

triggerconfig(OPTOcam_vid, 'manual');
OPTOcam_settings.TriggerMode ='manual';
OPTOcam_settings.Source.TriggerMode ='Off';
OPTOcam_settings.Source.ExposureMode ='Timed';
OPTOcam_settings.Source.ExposureTime =exposure_time;

ROI_OPTOcam=[ROI_OPTOcam(1)-1,ROI_OPTOcam(2)-1,ROI_OPTOcam(3),ROI_OPTOcam(4)]; %unfortunaletly different definitions of ROI in pco and OPTOcam.
OPTOcam_vid.ROIPosition=ROI_OPTOcam;

OPTOcam_settings.Source.ReverseX = 'True';
OPTOcam_settings.Source.ReverseY = 'True';
OPTOcam_gain = getappdata(hgui,'OPTOcam_gain');
if isempty (OPTOcam_gain)
    OPTOcam_gain=0;
end
OPTOcam_settings.Source.Gain = OPTOcam_gain;

%% prapare axis

crosshair_enabled = getappdata(hgui,'crosshair_enabled');
sharpness_enabled = getappdata(hgui,'sharpness_enabled');
PIVlab_axis = findobj(hgui,'Type','Axes');

%image_handle_OPTOcam=imagesc(zeros(OPTOcam_settings.VideoResolution(2),OPTOcam_settings.VideoResolution(1)),'Parent',PIVlab_axis,[0 2^8]);

image_handle_OPTOcam=imagesc(zeros(ROI_OPTOcam(4),ROI_OPTOcam(3)),'Parent',PIVlab_axis,[0 2^12]);

setappdata(hgui,'image_handle_OPTOcam',image_handle_OPTOcam);

frame_nr_display=text(100,100,'Initializing...','Color',[1 1 0]);
colormap default %reset colormap steps
new_map=colormap('gray');
new_map(1:3,:)=[0 0.2 0;0 0.2 0;0 0.2 0];
new_map(end-2:end,:)=[1 0.7 0.7;1 0.7 0.7;1 0.7 0.7];
colormap(new_map);axis image;
set(gca,'ytick',[])
set(gca,'xtick',[])
colorbar

%% get images
OPTOcam_vid.FramesPerTrigger = 1;
set(frame_nr_display,'String','');
preview(OPTOcam_vid,image_handle_OPTOcam)
clim([0 2^12]); %seems to be a workaround to force preview to show full data range...
displayed_img_amount=0;
while getappdata(hgui,'cancel_capture') ~=1 && displayed_img_amount < img_amount
    ima = image_handle_OPTOcam.CData;%*16; %stretch 12 bit to 16 bit
    %% sharpness indicator
    sharpness_enabled = getappdata(hgui,'sharpness_enabled');
    if sharpness_enabled == 1 % sharpness indicator
        textx=1240;
        texty=950;
        [~,~] = PIVlab_capture_sharpness_indicator (ima,textx,texty);
    else
        delete(findobj('tag','sharpness_display_text'));
    end
    crosshair_enabled = getappdata(hgui,'crosshair_enabled');
    if crosshair_enabled == 1 %cross-hair
        %% cross-hair
        locations=[0.15 0.5 0.85];
        half_thickness=1;
        brightness_incr=101;
        ima_ed=ima;
        old_max=max(ima(:));
        for loca=locations
            %vertical
            ima_ed(:,round(size(ima,2)*loca)-half_thickness:round(size(ima,2)*loca)+half_thickness)=ima_ed(:,round(size(ima,2)*loca)-half_thickness:round(size(ima,2)*loca)+half_thickness)+brightness_incr;
            %horizontal
            ima_ed(round(size(ima,1)*loca)-half_thickness:round(size(ima,1)*loca)+half_thickness,:)=ima_ed(round(size(ima,1)*loca)-half_thickness:round(size(ima,1)*loca)+half_thickness,:)+brightness_incr;
        end
        ima_ed(ima_ed>old_max)=old_max;
        set(image_handle_OPTOcam,'CData',ima_ed);
    end
    %% HISTOGRAM
    if getappdata(hgui,'hist_enabled')==1
        if isvalid(image_handle_OPTOcam)
            hist_fig=findobj('tag','hist_fig');
            if isempty(hist_fig)
                hist_fig=figure('numbertitle','off','MenuBar','none','DockControls','off','Name','Live histogram','Toolbar','none','tag','hist_fig','CloseRequestFcn', @HistWindow_CloseRequestFcn);
            end
            if ~exist ('old_hist_y_limits','var')
                old_hist_y_limits =[0 35000];
            else
                if isvalid(hist_obj)
                    old_hist_y_limits=get(hist_obj.Parent,'YLim');
                end
            end
            hist_obj=histogram(ima(1:2:end,1:2:end),'Parent',hist_fig,'binlimits',[0 2^12]);
        end
        %lowpass hist y limits for better visibility
        if ~exist ('new_hist_y_limits','var')
            new_hist_y_limits =[0 35000];
        end
        new_hist_y_limits=get(hist_obj.Parent,'YLim');
        set(hist_obj.Parent,'YLim',(new_hist_y_limits*0.5 + old_hist_y_limits*0.5))
    else
        hist_fig=findobj('tag','hist_fig');
        if ~isempty(hist_fig)
            close(hist_fig)
        end
    end
    drawnow limitrate;
    %% Autofocus
    %% Lens control
    %Sowieso machen: Nicht lineare schritte für die anzufahrenden fokuspositionen. Diese Liste vorher ausrechnen und dann nur index anspringen

    autofocus_enabled = getappdata(hgui,'autofocus_enabled');

    if autofocus_enabled == 1
        delaycounter=delaycounter+1;
    else
        delaycounter=0;
        delaycounter2=0;
        delay_time_1=tic;
    end
    %immer mehrere Bilder abfragen nachdem fokus verstellt wurde.... nicht nur eins, sondern z.B. drei Davon nur das letzte per sharpness beurteilen

    delay_time= 0.5; %1 seconds delay between measurements %350000 / exposure_time;
    if autofocus_enabled == 1
        if delaycounter>10 %wait 10 images before starting autofocus. Needed so that servo can reach target position
            focus_start = getappdata(hgui,'focus_servo_lower_limit');
            focus_end = getappdata(hgui,'focus_servo_upper_limit');
            amount_of_raw_steps=20;
            fine_step_resolution_increase = 8;
            focus_step_raw=round(abs(focus_end - focus_start)/amount_of_raw_steps);% in microseconds)
            focus_step_fine=round(1/fine_step_resolution_increase*(abs(focus_end - focus_start)/amount_of_raw_steps));% in microseconds)
            if ~exist('sharpness_focus_table','var') || isempty(sharpness_focus_table) || isempty(sharp_loop_cnt)
                sharpness_focus_table=zeros(1,2);
                sharp_loop_cnt=0;
                focus=focus_start;
                raw_finished=0;
                aperture=getappdata(hgui,'aperture');
                lighting=getappdata(hgui,'lighting');
                PIVlab_capture_lensctrl(focus,aperture,lighting)
            end
            if raw_finished==0
                if focus < focus_end % maxialer focus = endanschlag. Bis zu dem wert wird von null gefahren
                    if toc(delay_time_1)>=delay_time %only every second image is taken for analysis. This gives more time to the servo to reach position
                        delay_time_1=tic;
                        sharp_loop_cnt=sharp_loop_cnt+1;
                        [sharpness,~] = PIVlab_capture_sharpness_indicator (ima,[],[]);
                        sharpness_focus_table(sharp_loop_cnt,1)=focus;
                        sharpness_focus_table(sharp_loop_cnt,2)=sharpness;
                        focus=focus+focus_step_raw;
                        PIVlab_capture_lensctrl(focus,aperture,lighting)		%kann steuern und aktuelle position ausgeben
						autofocus_notification(1)
                    else
                        %do nothing
                    end
                else
                    %assignin('base','sharpness_focus_table',sharpness_focus_table)
                    %find best focus
                    [r,~]=find(sharpness_focus_table == max(sharpness_focus_table(:,2)));
                    focus_peak=sharpness_focus_table(r(1),1);
                    disp(['Best raw focus: ' num2str(focus_peak)])
                    raw_finished=1;
                    %focus vs. distance is not linear!
                    focus_start_fine=focus_peak-6*focus_step_raw; %start of finer focussearch
                    focus_end_fine=focus_peak+3*focus_step_raw;
                    if focus_start_fine < focus_start
                        focus_start_fine = focus_start;
                    end
                    if focus_end_fine > focus_end
                        focus_end_fine = focus_end;
                    end
                    %original focus=focus_end_fine;
                    focus=focus_start_fine;
                    PIVlab_capture_lensctrl(focus,aperture,lighting)
                    sharp_loop_cnt=0;
                    raw_data=[sharpness_focus_table(:,1),normalize(sharpness_focus_table(:,2),'range')];
                    sharpness_focus_table=zeros(1,2);
                end
            end

            if raw_finished == 1
                delaycounter2=delaycounter2+1;
            else
                delaycounter2=0;
            end

            if raw_finished == 1
                delay_time= 0.35;
                if delaycounter2>10
                    %repeat with finer steps
                    %original if focus > focus_start_fine % maxialer focus = endanschlag. Bis zu dem wert wird von null gefahren
                    if focus < focus_end_fine % maxialer focus = endanschlag. Bis zu dem wert wird von null gefahren
                        if toc(delay_time_1)>=delay_time %only every second image is taken for analysis. This gives more time to the servo to reach position
                            delay_time_1=tic;
                            sharp_loop_cnt=sharp_loop_cnt+1;
                            [sharpness,~] = PIVlab_capture_sharpness_indicator (ima,[],[]);
                            sharpness_focus_table(sharp_loop_cnt,1)=focus;
                            sharpness_focus_table(sharp_loop_cnt,2)=sharpness;
                            %original focus=focus-focus_step_fine;
                            focus=focus+focus_step_fine;
                            PIVlab_capture_lensctrl(focus,aperture,lighting)		%kann steuern und aktuelle position ausgeben
							autofocus_notification(1)
                        else
                            %do nothing
                        end
                    else %fine focus search finished
                        %assignin('base','sharpness_focus_table',sharpness_focus_table)
                        %find best focus
                        [r,~]=find(sharpness_focus_table == max(sharpness_focus_table(:,2)));
                        focus_peak=sharpness_focus_table(r(1),1);
                        disp(['Best fine focus: ' num2str(focus_peak)])
                        PIVlab_capture_lensctrl(focus_end_fine,aperture,lighting)%backlash compensation
                        pause(0.5)
                        PIVlab_capture_lensctrl(focus_start_fine,aperture,lighting) %backlash compensation
                        pause(0.5)
                        PIVlab_capture_lensctrl(focus_peak,aperture,lighting) %set to best focus

                        setappdata(hgui,'autofocus_enabled',0); %autofocus am ende ausschalten

                        lens_control_window = getappdata(0,'hlens');
                        focus_edit_field=getappdata(lens_control_window,'handle_to_focus_edit_field');
                        set(focus_edit_field,'String',num2str(focus_peak)); %update
                        %setappdata(hgui,'cancel_capture',1); %stop recording....?
                        figure;plot(raw_data(:,1),raw_data(:,2))
                        hold on;plot(sharpness_focus_table(:,1),normalize(sharpness_focus_table(:,2),'range'));hold off
                        title('Focus search')
                        xlabel('Pulsewidth us')
                        ylabel('Sharpness')
                        legend('Coarse search','Fine search')
                        grid on

                    end
                end
            end
        end
	else
		autofocus_notification(0)
        sharpness_focus_table=[];
        sharp_loop_cnt=[];
    end

	if img_amount == 1
		if sum(ima(1:10,1,1)) ~=10 %check if the display was updated, if there is real camera data. I didnt find a more elegant way...
			displayed_img_amount=displayed_img_amount+1;
		end
	end

end
stoppreview(OPTOcam_vid)

function autofocus_notification(running)
auto_focus_active_hint=findobj('tag', 'auto_focus_active');
if running == 1

	hgui=getappdata(0,'hgui');
	PIVlab_axis = findobj(hgui,'Type','Axes');
	%image_handle_OPTOcam=getappdata(hgui,'image_handle_OPTOcam');
	postix=get(PIVlab_axis,'XLim');
	postiy=get(PIVlab_axis,'YLim');
	bg_col=get(auto_focus_active_hint,'BackgroundColor'); % Toggle background color while autofocus is active

	if ~isempty(bg_col)
		if  sum(bg_col)==0.75 %hint is currently displayed
			bg_col = [0.05 0.05 0.05];
		else
			bg_col = [0.25 0.25 0.25];
		end
		set(auto_focus_active_hint,'BackgroundColor',bg_col);
	else
		bg_col= [0.25 0.25 0.25];
		axes(PIVlab_axis);
		text(postix(2)/2,postiy(2)/2,'Autofocus running, please wait...','HorizontalAlignment','center','VerticalAlignment','middle','color','y','fontsize',24, 'BackgroundColor', bg_col,'tag','auto_focus_active','margin',10,'Clipping','on');

	end
else
	delete(auto_focus_active_hint);
end

function HistWindow_CloseRequestFcn(hObject,~)
hgui=getappdata(0,'hgui');
setappdata(hgui,'hist_enabled',0);
try
    delete(hObject);
catch
    delete(gcf);
end


classdef ArrayList < handle
    %ARRAYLIST A cell array implementation of java.util.ArrayList
    %   ArrayList(initialCapacity) mimics a fixed sized Java ArrayList
    %   using a cell array to store the data elements. initialCapacity must
    %   be greater than one and less than infinity.
    %
    %   % Example:
    %   %   Append, insert, and remove elements from the ArrayList.
    %
    %   aList = containers.ArrayList(10);
    %   aList.appendElements(1);
    %   aList.appendElements({5,6,7,8,9,10});  % Multiple elements
    %                                          % must be appended as
    %                                          % a cell array.
    %   aList.insertAtIndex(2, {2,3,4});
    %   numberTwoAndThree = aList.removeAtIndex(2:3);
    %   numberNineAndTen = aList.removeLastN(2);
    %   numberSeven = aList.removeElement(7);
    %
    %   ArrayList Methods:
    %       appendElement       - Append an element or elements to the end.
    %       elementAt           - Return the element at a specific index.
    %       insertAtIndex       - Insert an element at a specific index.
    %       isempty             - Returns true if the array is empty.
    %       lastElement         - Returns the last element.
    %       length              - Returns the number of elements.
    %       removeAtIndex       - Remove element at a specific index.
    %       removeElement       - Remove element from the array.
    %       removeFirstN        - Remove the first N elements.
    %       removeLast          - Remove the last element.
    %       removeLastN         - Remove the last N elements.
    %
    %  ArrayList Properties:
    %       Array               - Cell array storing all elements.
    %       Capacity            - The maximum, fixed capacity of the array.
    %       Count               - Number of elements in the array.

    % Copyright (C) 2013, Georgia Tech Research Corporation
    % see the LICENSE file included with this software

    properties (SetAccess = private)
        Count       % Number of elements in the array
        Capacity    % The maximum capacity of the array
    end

    properties (Access = private)
        Array       % Data structure in which elements are stored
    end

    methods

        function obj = ArrayList(initialCapacity)
            %% ARRAYLIST Constructor
            %   obj = ArrayList(initialCapacity) is the default constructor
            %   that creates an array list with a maximum, fixed capacity
            %   of initialCapacity elements.

            assert(all(imag(initialCapacity) == 0) && all(mod(initialCapacity,1) == 0), ...
                   'simiam:NotRealInteger', ...
                   'Initial capacity must be a real integer.')
            assert(initialCapacity > 0 && initialCapacity < Inf, ...
                   'simiam:OutOfBounds', ...
                   'Initial capacity must be greater than zero and less than infinity.');

            obj.Capacity = initialCapacity;
            obj.Array = cell(obj.Capacity, 1);
            obj.Count = 0;
        end

        function appendElement(obj, elementOrElements)
            %% APPENDELEMENT Append an element or elements to the end.
            %   appendElement(elementOrElements) appends an element or
            %   multiple elements to the end of the array. If multiple
            %   elements are appended, then they must be input as a cell
            %   array. An error is thrown if there is not enough space to
            %   append all of the elements.
            if iscell(elementOrElements)
                nElements = length(elementOrElements);
            else
                elementOrElements = {elementOrElements};
                nElements = 1;
            end
            assert(obj.Count+nElements <= obj.Capacity, ...
                   'simiam:NotEnoughSpace', ...
                   'Not enough space to append %d elements.', nElements);
%             assert(iscell(elementOrElements), ...
%                    'simiam:IncorrectDataType', ...
%                    'Input must be a cell array.');
            obj.Array(obj.Count+(1:nElements)) = elementOrElements;
            obj.Count = obj.Count+nElements;
        end

        function insertAtIndex(obj, elementOrElements, index)
            %% INSERTATINDEX Insert an element or elements at a specific index.
            %   insertAtIndex(elemntOrElments, index) inserts an element or
            %   multiple elements at a specific index in the range
            %   [1,min(obj.Count+1,obj.Capacity]. If multiple elements are
            %   inserted, then they must be input as a cell array. An error
            %   is thrown if there is not enough space to insert all of the
            %   elements.

            if iscell(elementOrElements)
                nElements = length(elementOrElements);
            else
                elementOrElements = {elementOrElements};
                nElements = 1;
            end
            assert(obj.Count+nElements <= obj.Capacity, ...
                   'simiam:NotEnoughSpace', ...
                   'Not enough space to insert %d elements.', nElements);
%             assert(iscell(elementOrElements), ...
%                    'simiam:IncorrectDataType', ...
%                    'Input must be a cell array.');
            obj.validateIndex(index);

            obj.Array(obj.Count+(1:nElements)) = obj.Array(index:obj.Count);
            obj.Array(index+{1:nElements}) = elementOrElements;
            obj.Count = obj.Count+nElements;
        end

        function elementOrElements = removeAtIndex(obj, indexOrIndices)
            %% REMOVEATINDEX Remove element(s) at a specific index or indicies.
            %   elementOrElements = removeAtIndex(indexOrIndicies) removes
            %   and returns the elements located at a specific index or
            %   indicies. An error is thrown if there are not enough
            %   elements in the array to remove or the indices are out of
            %   bounds.

            nElements = length(indexOrIndices);
            assert(obj.Count-nElements >= 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot remove more elements than are currently in the array.');
            obj.validateIndex(indexOrIndices);
            elementOrElements = cell(nElements, 1);

            [sortedIndices, sortIndex] = sort(indexOrIndices, 'descend');
            for i = 1:nElements
                index = sortedIndices(i);
                elementOrElements{sortIndex(i)} = obj.Array{index};
                for j = (index+1):obj.Count
                    obj.Array{j-1} = obj.Array{j};
                end
                obj.Array{obj.Count} = [];
                obj.Count = obj.Count-1;
            end
        end

        function removeElement(obj, elementOrElements)
            %% REMOVEELEMENT Remove element(s) from the array.
            %   removeElement(elementOrElements) removes the elements
            %   specified in the input if they are found. An error is
            %   thrown if there are not enough elements in the array
            %   to remove.

            nElements = length(elementOrElements);
            assert(obj.Count-nElements >= 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot remove more elements than are currently in the array.');
            for i = 1:obj.Count
                if(any(obj.Array(i) == elementOrElements))
                    obj.removeAtIndex(i);
                    break;
                end
            end
        end

        function element = removeLast(obj)
            %% REMOVELAST Remove the last element.
            %   element = removeLast() removes the last element from the
            %   array. An error is thrown if the array is empty.

            assert(obj.Count > 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot remove from an empty array.');
            element = obj.removeAtIndex(obj.Count);
        end

        function elements = removeLastN(obj, nElements)
            %% REMOVELASTN Removes the last N elements.
            %   elements = removeLastN(nElements) removes the last N
            %   elements from the array. An error is thrown if there are
            %   not enough elements to remove.

            assert(obj.Count-nElements >=0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot remove more elements than are currently in the array.');
            elements = obj.removeAtIndex((obj.Count-nElements):obj.Count);
        end

        function elements = removeFirstN(obj, nElements)
            %% REMOVEFIRSTN Removes the first N elements
            %   elements = removeFirstN(nElements) removes the first N
            %   elements from the array. An error is thrown if there are
            %   not enough elements to remove.

            assert(obj.Count-nElements >= 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot remove more elements than are currently in the array.');
            elements = obj.removeAtIndex(1:nElements);
        end

        function count = length(obj)
            %% LENGTH Returns the number of elements.
            %   count = length() returns the number of elements currently
            %   stored in the array.

            count = obj.Count;
        end

        function bool = isempty(obj)
            %% ISEMPTY Returns true if the array is empty.
            %   bool = isempty() returns true if the array is empty, false
            %   otherwise.

            bool = (obj.Count == 0);
        end

        function element = lastElement(obj)
            %% LASTELEMENT Returns the last element.
            %   element = lastElement() returns the last element in the
            %   array. An error is thrown if there are no elements stored
            %   in the array.

            assert(obj.Count > 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot fetch from an empty array.');
            element = obj.Array{obj.Count};
        end

        function elementOrElements = elementAt(obj, indexOrIndices)
            %% ELEMENTAT Return the element at the specific index.
            %   elementOrElements = elementAt(indexOrIndicies)returns the
            %   element or elements at the specific index or indicies. An
            %   error is thrown if the array is empty.

            assert(obj.Count > 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot fetch from an empty array.');
            obj.validateIndex(indexOrIndices);
            if length(indexOrIndices) > 1
                elementOrElements = obj.Array(indexOrIndices);
            else
                elementOrElements = obj.Array{indexOrIndices};
            end
        end

        function replaceElementAt(obj, element, index)
            %% REPLACEELEMENTAT Replaces the element at the specific index.
            %   replaceElementAt(element, index) replaces the
            %   element or elements at the specific index or indicies. An
            %   error is thrown if the array is empty.

            assert(obj.Count > 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot fetch from an empty array.');
            obj.validateIndex(index);
            obj.Array{index} = element;
        end

        function elementOrElements = allElements(obj)
            assert(obj.Count > 0, ...
                   'simiam:NotEnoughElementsLeft', ...
                   'Cannot fetch from an empty array.');
            elementOrElements = obj.Array(1:obj.Count);
        end

        function disp(obj)
            %% DISP Display the cell array.
            %   disp() displays the contents of the cell array.

            disp(obj.Array);
        end

    end

    methods (Access = private)

        function validateIndex(obj, indexOrIndices)
            %% VALIDATEINDEX Validate the index based on the properties of the array.
            %   validateIndex(indexOrIndices) throws an error if the index
            %   or indices are not positive, real integers than are
            %   not within the bounds of the array.

            assert(all(imag(indexOrIndices) == 0) && all(mod(indexOrIndices,1) == 0), ...
                   'simiam:NotRealInteger', ...
                   'index must be a real integer.')
            assert(all(indexOrIndices > 0) && all(indexOrIndices <= min(obj.Count+1, obj.Capacity)), ...
                   'simiam:OutOfBounds', ...
                   'index must be within bounds of the array.');
        end

    end
end


classdef ControlMode < Simulink.IntEnumType

    enumeration
        None(0)
        Manual(1)
        Acro(2)
        Stabilize(3)
        ALTCTL(4)
        POSCTL(5)
        Offboard(6)
    end

    methods (Static)

        function defaultValue = getDefaultValue()
            % GETDEFAULTVALUE  Returns the default enumerated value.
            %   If this method is not defined, the first enumeration is used.
            defaultValue = ControlMode.None;
        end

        function dScope = getDataScope()
            % GETDATASCOPE  Specifies whether the data type definition should be imported from,
            %               or exported to, a header file during code generation.
            dScope = 'Auto';
        end

        function desc = getDescription()
            % GETDESCRIPTION  Returns a description of the enumeration.
            desc = 'enumeration of control mode';
        end

        function fileName = getHeaderFile()
            % GETHEADERFILE  Returns path to header file if non-empty.
            fileName = '';
        end

        function flag = addClassNameToEnumNames()
            % ADDCLASSNAMETOENUMNAMES  Indicate whether code generator applies the class name as a prefix
            %                          to the enumeration.
            flag = true;
        end

    end
end


% The COBRAToolbox: testGenerateRules.m
%
% Purpose:
%     - testGenerateRules tests generateRules
%
% Authors:
%     - Initial Version: Uri David Akavia - August 2017

global CBTDIR

% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which('testGenerateRules'));
cd(fileDir);

if 1
    modelsToTry = {'Acidaminococcus_intestini_RyC_MR95.mat', 'Acidaminococcus_sp_D21.mat', 'Recon1.0model.mat', 'ecoli_core_model.mat', 'modelReg.mat'};
else
    modelsToTry = {'Recon2.v05.mat'};% TODO fix why this is not working
end
for i=1:length(modelsToTry)
    model = getDistributedModel(modelsToTry{i});
    fprintf('Beginning model %s\n', modelsToTry{i});

    model2 = generateRules(model);
    model.rules = strrep(model.rules, '  ', ' ');
    model3 = model;
    model3.genes = []; % Empty genes field
    model3 = generateRules(model3, 0);
    model4 = model;
    model4 = rmfield(model4, 'genes');
    model4 = generateRules(model4, 0);

    fp = FormulaParser();
    % fix for Recon2
    if strcmp(modelsToTry{i}, 'Recon2.v05.mat')
        model.rules(2240) = {'(x(2)) | (x(4)) | (x(3))'}; % '(26.1) or (314.1) or (314.2)'
        model.rules(2543) = {'(x(2)) | (x(4)) | (x(1)) | (x(3))'}; % '(26.1) or (314.1) or (8639.1) or (314.2)'
        model.rules(2750) = {'(x(2)) | (x(4)) | (x(1)) | (x(3))'}; % '(26.1) or (314.1) or (8639.1) or (314.2)'
        model.rules(2940) = {'(x(4)) | (x(60)) | (x(2)) | (x(61)) | (x(3))'}; % '(314.1) or (4128.1) or (26.1) or (4129.1) or (314.2)'
        model.rules(3133) = {'(x(2)) | (x(4)) | (x(1)) | (x(3))'}; % '(26.1) or (314.1) or (314.2)'
    end
    %also, introduce spaces around the individual genes:
    model.rules = regexprep(model.rules,'([^\s])(x\([0-9]+\))','$1 $2');
    model.rules = regexprep(model.rules,'(x\([0-9]+\))([^\s])','$1 $2');

    % Create a model with sorted genes
    sortedModel = model;
    sortedRules = sortedModel.rules;
    [sortedModel.genes, newInd] = sort(model.genes);
    [~, newInd] = sort(newInd);
    for j=1:length(newInd)
        sortedRules = strrep(sortedRules, ['x(', num2str(j), ')'], ['x(New', num2str(newInd(j)), ')']);
    end
    sortedRules = strrep(sortedRules, 'New', '');
    sortedModel.rules = sortedRules;

    for rule = 1:numel(model.rules)
        if isempty(model.rules{rule})
            %assert that both formulas are empty (and thus equal).
            assert(isequal(model.rules{rule},model2.rules{rule}))
            assert(isequal(sortedModel.rules{rule},model3.rules{rule}))
            assert(isequal(sortedModel.rules{rule},model4.rules{rule}))
            continue;
        elseif strcmp(model.rules{rule},model2.rules{rule})
            %If the strings are identical than we don't need to check
            %equivalence.
            assert(isequal(model.rules{rule},model2.rules{rule}))
            assert(isequal(sortedModel.rules{rule},model3.rules{rule}))
            assert(isequal(sortedModel.rules{rule},model4.rules{rule}))
            continue
        end

        head1 = fp.parseFormula(model.rules{rule});
        head2 = fp.parseFormula(model2.rules{rule});
        headSort = fp.parseFormula(sortedModel.rules{rule});
        head3 = fp.parseFormula(model3.rules{rule});
        head4 = fp.parseFormula(model4.rules{rule});

        %Assert that the formulas are equal.
        assert(head1.isequal(head2));
        assert(headSort.isequal(head3));
        assert(headSort.isequal(head4));
    end
    fprintf('Succesfully completed model %s\n', modelsToTry{i});
end


 function c = horzcat(varargin)
%function c = horzcat(varargin)
% called for c = [a, b, ...] where any of them is a fatrix

c = block_fatrix(varargin, 'type', 'row');


function [planC] = dicomrt_dicomrt2cerr(plan,xmesh,ymesh,zmesh,ct,ct_xmesh,ct_ymesh,ct_zmesh,voi,optName,MRCell,PETCell,SPECTCell)
% dicomrt_dicomrt2CERR(dose,xmesh,ymesh,zmesh,ct,ct_xmesh,ct_ymesh,ct_zmesh,voi)
%
% Convert DICOMRT-TOOLBOX data in CERR format .
%
% Copyright (C) 2002 Emiliano Spezi (emiliano.spezi@physics.org)
%
% LM DK merging doses and beam information incase there are more than one

% Check number of argument and set-up some parameters and variables

error(nargchk(9,13,nargin))

%Create CERR data Container & templates for certain cells.
planInitC       = initializeCERR;
indexS          = planInitC{end};
headerInitS     = planInitC{indexS.header};
commentInitS    = planInitC{indexS.comment};
scanInitS       = planInitC{indexS.scan};
structureInitS  = planInitC{indexS.structures};
beamsInitS      = planInitC{indexS.beams};
doseInitS       = planInitC{indexS.dose};

tagMapS = initTagMapS;
tags = dicomrt_d2c_rtogtags;

% Initialize planC
planC = planInitC;
nCells = length(planInitC);
tags.nimages = 0;

% NOTE that conversion sequence is important and must be retained
%

% Convert header
disp('(+) Converting DICOM headers');
if isempty(plan)==0
    headerInitS=dicomrt_d2c_header(headerInitS,plan);
    disp('(+) Fetching data from RTPLAN');
elseif isempty(plan)==1 & isempty(ct)==0
    headerInitS=dicomrt_d2c_header(headerInitS,ct);
    disp('(+) Fetching data from CT scan');
elseif ~isempty(voi)
    headerInitS=dicomrt_d2c_header(headerInitS,voi);
    disp('(+) Fetching data from RTSTRUCT');
end
disp('(=) Conversion DICOM headers completed.');

% Convert comments
% commentInitS

% Convert scans
if isempty(ct)==0
    disp('(+) Converting DICOM scans');
    [tmp_scan,tags]=dicomrt_d2c_scan(scanInitS,indexS,ct,ct_xmesh,ct_ymesh,ct_zmesh,tags);
    disp('(=) Conversion DICOM scans completed.');
else
    disp('(=) CT scan not available.');
    tmp_scan = scanInitS;
end

% Validating and converting structures
% Validation
if isempty(voi)==0
    voitype=dicomrt_checkvoitype(voi);
    if isequal(voitype,'3D')
        voi=dicomrt_3dto2dVOI(voi);
    end

    if isempty(ct)==0
        disp('(+) Fitting DICOM structures to CT scans to comply with RTOG format');
        voi=dicomrt_fitvoi2ct(voi,ct_zmesh,ct);
        disp('(=) Fitting DICOM structures completed.');

        disp('(+) Validating DICOM structures');
        [voi]=dicomrt_validatevoi(voi,ct_xmesh,ct_ymesh,ct_zmesh);
        [newvoi]=dicomrt_closevoi(voi);
        disp('(=) Validation DICOM structures completed.');

        % Conversion
        disp('(+) Converting DICOM structures');
        %         names = fieldnames(structureInitS);
        %         if length(structureInitS) == 0 & ~isempty(names)
        %             structureInitS(1).(names{1}) = deal([]);
        %         end
        [tmp_str,tags]=dicomrt_d2c_voi(structureInitS,indexS,newvoi,ct_xmesh,ct_ymesh,ct_zmesh,tags,tmp_scan.scanUID);
        disp('(=) Conversion DICOM structures completed.');

    else
        % Conversion
        disp('(+) Converting DICOM structures');
        %         names = fieldnames(structureInitS);
        %         if length(structureInitS) == 0 & ~isempty(names)
        %             structureInitS(1).(names{1}) = deal([]);
        %         end
        [tmp_str,tags]=dicomrt_d2c_voi(structureInitS,indexS,voi,ct_xmesh,ct_ymesh,ct_zmesh,tags,tmp_scan.scanUID);
        disp('(=) Conversion DICOM structures completed.');
    end
else
    disp('(=) RTSTRUCT not available.');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DK
global dosetype;

if isempty(plan)==0
    if strcmpi(dosetype,'fraction')
        try
            beams=fieldnames(plan{1,1}{1}{1}.BeamSequence);
        catch
            warning('Beam Sequence not present in RTPLAN !');
        end
    else
        try
            try
                beams=fieldnames(plan{2,1}.BeamSequence);
            catch
                beams=fieldnames(plan{1}{1}.BeamSequence);
            end
        catch
            warning('Beam Sequence not present in RTPLAN !');
        end
    end
end

if exist('beams')==1
    % Convert beam geometry
    disp('(+) Converting DICOM beam geometry');
    %     names = fieldnames(beamsInitS);
    %     if length(beamsInitS) == 0 & ~isempty(names)
    %         beamsInitS(1).(names{1}) = deal([]);
    %     end
    if strcmpi(dosetype,'fraction')
        planSiz = length(plan);
        if planSiz == 1
            [tmp_beam,tags]=dicomrt_d2c_beam(beamsInitS,indexS,plan{1},tags);
        else
            for i = 1:planSiz(end)
                if i == 1
                [tmp_beam,tags]=dicomrt_d2c_beam(beamsInitS,indexS,plan{i},tags);
                else
                [tmp_beam1,tags]=dicomrt_d2c_beam(beamsInitS,indexS,plan{i},tags);
                tmp_beam = dissimilarInsert(tmp_beam,tmp_beam1); % insert new dose intp planC
                end
            end
        end
    else
        [tmp_beam,tags]=dicomrt_d2c_beam(beamsInitS,indexS,plan,tags);
        disp('(=) Conversion DICOM beam geometry completed.');
    end
else
    warning('Beam Sequence not present in RTPLAN !');
end

% Convert digital films
nfilms=0;
if isempty(plan)==0 & strcmpi(dosetype,'fraction')
    disp('(+) Converting DICOM dose fraction');
    planSiz = size(plan);
    for i = 1:planSiz(end)
        if i == 1
            [tmp_dose,tags]=dicomrt_d2c_dose(doseInitS,indexS,plan{i},xmesh{i},ymesh{i},zmesh{i},tags,tmp_scan.scanUID);
        else
            disp('(+) Converting DICOM dose fraction');
            [tmp_dose1,tags]=dicomrt_d2c_dose(doseInitS,indexS,plan{i},xmesh{i},ymesh{i},zmesh{i},tags,tmp_scan.scanUID);
            tmp_dose = dissimilarInsert(tmp_dose,tmp_dose1); % insert new dose intp planC
        end
    end
elseif isempty(plan)==0 & ~strcmpi(dosetype,'fraction') & isempty(plan{2,1})==0
    % Convert dose
    disp('(+) Converting DICOM dose');
    %     names = fieldnames(doseInitS);
    %     if length(doseInitS) == 0 & ~isempty(names)
    %         doseInitS(1).(names{1}) = deal([]);
    %     end
    [tmp_dose,tags]=dicomrt_d2c_dose(doseInitS,indexS,plan,xmesh,ymesh,zmesh,tags,tmp_scan.scanUID);
    disp('(=) Conversion DICOM dose completed.');
else
    disp('(=) RTDOSE not available');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end DK
% Convert DVH
% Convert seed geometry
% Convert MR
if ~isempty(MRCell)
    tmp_MR = dicomrt_d2c_MR(initializeMRInfo,MRCell);
end

% Convert PET
if ~isempty(PETCell)
    tmp_PET  = dicomrt_d2c_PET(initializePETInfo, PETCell);
end

if ~isempty(SPECTCell)
    tmp_SPECT = dicomrt_d2c_SPECT(initializeSPECTInfo, SPECTCell);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%Populate planC fields %%%%%%%%%%%%%%%%%%%%%%%%%%
% Store header info
planC{indexS.header} = headerInitS;

if isempty(plan)==0 & exist('beams')==1 & exist('tmp_dose')==1
    % Store beams
    planC{indexS.beams}=tmp_beam;
    % Store dose
    planC{indexS.dose}=tmp_dose;
elseif isempty(plan)==0 & exist('beams')==1 & exist('tmp_dose')==0
    % Store beams only
    planC{indexS.beams}=tmp_beam;
elseif isempty(plan)==0 & exist('beams')==0 &  exist('tmp_dose')==1
    % Store dose only
    planC{indexS.dose}=tmp_dose;
end

if isempty(ct)==0
    % Store scan
    planC{indexS.scan}=tmp_scan;
end

if isempty(voi)==0
    % Store structures
    planC{indexS.structures}=tmp_str;
end

% Store options and indexS
pathStr = getCERRPath;
optName = [pathStr 'CERROptions.m'];
optS = opts4Exe(optName);
planC{indexS.CERROptions} = optS;
planC{indexS.indexS} = indexS;

% Post processing actions

if isempty(ct)==0
    % Determine voxel thicknesses
    planC=dicomrt_d2c_setVoxelThicknesses(planC,indexS);
end

if isempty(ct)==0 & isempty(voi)==0
    % Get structure scan segments
    planC =  getRasterSegs(planC, optS);

    % Get any dose surface points
    planC =  getDSHPoints(planC,optS);
end

if isempty(ct)==0
    % Create uniformized datasets
    flagVOI = isempty(voi);
    planC=dicomrt_d2c_uniformizescan(planC,optS,flagVOI);
end

if ~isempty(MRCell)
    planC{indexS.scan}= dissimilarInsert(planC{indexS.scan},tmp_MR);
end

if ~isempty(PETCell)
    planC{indexS.scan} = dissimilarInsert(planC{indexS.scan},tmp_PET);
end

if ~isempty(SPECTCell)
    planC{indexS.scan} = dissimilarInsert(planC{indexS.scan},tmp_SPECT);
end

% Set UID's for Scan, Dose and Structures
planC = guessPlanUID(planC);


% eeg_eventtypes()  - return a list of event or urevent types in a dataset and
%                     the respective number of events of each type. Ouput event
%                     types are sorted in reverse order of their number. If no
%                     outputs, print this list on the commandline instead.
%
% Usage:
%        >> [types,numbers] = eeg_eventtypes(EEG);
% Inputs:
%        EEG        - EEGLAB dataset structure
% Outputs:
%        types      - cell array of event type strings
%        numbers    - vector giving the numbers of each event type in the data
%
% Example:
%           >> eeg_eventtypes(EEG);       % print numner of each event types
%
% Author: Scott Makeig, SCCN/INC/UCSD, April 28, 2004-

%        >> [types,numbers] = eeg_eventtypes(EEG,types);
%        >> [types,numbers] = eeg_eventtypes(EEG,'urevents',types);
% Inputs:
%        EEG        - EEGLAB dataset structure
%        'urevents' - return event information for the EEG.urevent structure
%        types      - {cell array} of event types to return or print.
% Outputs:
%        types      - cell array of event type strings
%        numbers    - vector giving the numbers of each event type in the data
%
% Note:  Numeric (ur)event types are converted to strings, so, for example,
%        types {13} and {'13'} are not distinguished.
%
% Example:
%           >> eeg_eventtypes(EEG);       % print numner of each event types
%
% Curently disabled:
%           >> eeg_eventtypes(EEG,'urevent');  % print hist. of urevent types
%           >> eeg_eventtypes(EEG,{'rt'});% print number of 'rt' events
%           >> eeg_eventtypes(EEG,'urevent',{'rt','break'});
%                                         % print numbers of 'rt' and 'break'
%                                         % type urevents

% Copyright (C) 2004 Scott Makeig, SCCN/INC/UCSD, smakeig@ucsd.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
%
%
% event types can be numbers, Stefan Debener, 05/12/2006,
% added 2nd and 3rd args, sorted outputs by number, Scott Makeig, 09/12/06

function [types,numbers] = eeg_eventtypes(EEG,arg2,arg3)

if nargin< 1
   help eeg_eventtypes
   return
end
if ~isstruct(EEG)
   error('EEG argument must be a dataset structure')
end

if ~isfield(EEG,'event')
   error('EEG.event field not found');
end
if nargin > 1
    error('Multiple input arguments are currently disabled');
end;

UREVENTS = 0; % flag returning infor for urevents instead of events
typelist = [];
if nargin>1
   if ischar(arg2)
       if strcmp(arg2,'urevent') | strcmp(arg2,'urevents')
            UREVENTS = 1; % change flag
       else
            error('second argument string not understood')
       end
       if nargin>2
            if iscell(arg3)
                  typelist = arg3;
            end
       end
   elseif iscell(arg2)
       typelist = arg2;
   end
end
if ~isempty(typelist)     % cast to cell array of strings
   for k=1:length(typelist)
       if isnumeric(typelist{k})
          typelist{k} = num2str(typelist{k});
       end
   end
end

if ~UREVENTS
   nevents = length(EEG.event);
   alltypes = cell(nevents,1);
   for k=1:nevents
       if isnumeric(EEG.event(k).type)
          alltypes{k} = num2str(EEG.event(k).type);
       else
          alltypes{k} = EEG.event(k).type;
       end
   end
else
   nevents = length(EEG.urevent);
   alltypes = cell(nevents,1);
   for k=1:nevents
       if isnumeric(EEG.urevent(k).type)
          alltypes{k} = num2str(EEG.urevent(k).type);
       else
          alltypes{k} = EEG.urevent(k).type;
       end
   end
end

[types i j] = unique_bc(alltypes);

istypes = 1:length(types);
notistypes = [];
if ~isempty(typelist)
  notistypes = ismember_bc(typelist,types);
  istypes = ismember_bc(types,typelist(find(notistypes==1))); % types in typelist?
  notistypes = typelist(find(notistypes==0));
end

types(~istypes) = []; % restrict types to typelist

ntypes = length(types);
numbers = zeros(ntypes + length(notistypes),1);
for k=1:ntypes
  numbers(k) = length(find(j==k));
end
types = [types(:); notistypes(:)]; % concatenate the types not found
ntypes = length(types);
for j = 1:length(notistypes)
   numbers(k+j) = 0;
end

% sort types in reverse order of event numbers
[numbers nsort] = sort(numbers);
numbers = numbers(end:-1:1);
types = types(nsort(end:-1:1));

%
% print output on commandline %%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
if nargout < 1
  fprintf('\n');
  if UREVENTS
    fprintf('EEG urevent types:\n\n')
  else
    fprintf('EEG event types:\n\n')
  end

  maxx = 0;
  for k=1:ntypes
    x = length(types{k});
    if x > maxx
        maxx = x; % find max type name length
    end
  end
  for k=1:ntypes
    fprintf('  %s',types{k});
    for j=length(types{k})+1:maxx+4
       fprintf(' ');
    end
    fprintf('%d\n',numbers(k));
 end
 fprintf('\n');
 clear types % no return variables
end


function roiName = mrmNameROI(pos);
%
%   roiName = mrmNameROI(pos);
%
%Author: Wandell
%Purpose:
%   Generate a standard name for an ROI produced by the mrMesh routines.
%   By separating this routine out, we can assure that there is consistency
%   between the different ROI names for searching.
%
%   pos is the 3D position in the mrMesh window.
%
% Example:
%   pos =mrmGet(msh,'cursor');
%   roiName = mrmNameROI(pos);
%

if ieNotDefined('pos'), pos = [0,0,0]; end

roiName = sprintf('mrm-%.0f-%.0f-%.0f',pos(1),pos(2),pos(3));

return;


classdef Rx < adi.AD9361.Rx
    % adi.FMComms2.Rx Receive data from the FMComms2 evaluation platform
    %   The adi.FMComms2.Rx System object is a signal source that can
    %   receive complex data from the FMComms2.
    %
    %   rx = adi.FMComms2.Rx;
    %   rx = adi.FMComms2.Rx('uri','192.168.2.1');
    %
    %   Product Page
    %
    %   See also adi.AD9361.Rx
    methods
        %% Constructor
        function obj = Rx(varargin)
            % Returns the matlabshared.libiio.base object
            coder.allowpcode('plain');
            obj = obj@adi.AD9361.Rx(varargin{:});
        end
    end

end


function p = mtexODFPath
% returns the default path to ODF-files
%
% Syntax
%   mtexODFPath %
%   getMTEXpref('ODFPath') % long form of mtexODFPath
%   setMTEXpref('ODFPath',path) % change the path to ODF files
%
% See also
% mtexDataPath mtexCifPath mtexEBSDPath mtexPoleFigurePath mtexODFPath
% mtexTensorPath

DataPath = getMTEXpref('ODFPath');

if exist(DataPath,'dir')
  p = DataPath;
else
  error('Data package not installed!');
end


% Tracker performance evaluation tool for LaSOT
% 07/19/2018 by Heng Fan

clc; clear; close all;

addpath('./utils/');
addpath('./sequence_evaluation_config/');

tmp_mat_path  = './tmp_mat/';          % path to save temporary results
path_anno     = './annos/';            % path to annotations
path_att      = './annos/att/';        % path to attribute
rp_all        = './tracking_results/'; % path to tracking results
save_fig_path = './res_fig/';          % path to result figures
save_fig_suf  = 'eps';                 % suffix of figures, 'png' or 'eps'

att_name      = {'Illumination Variation', 'Partial Occlusion', 'Deformation', ...
                 'Motion Blur', 'Camera Motion', 'Rotation', 'Background Clutter', ...
                 'Viewpoint Change', 'Scale Variation', 'Full Occlusion', 'Fast Motion', ...
                 'Out-of-View', 'Low Resolution', 'Aspect Ration Change'};
att_fig_name  = {'IV', 'POC', 'DEF', 'MB', 'CM', 'ROT', 'BC', ...
                 'VC', 'SV', 'FOC', 'FM', 'OV', 'LR', 'ARC'};

% 'all' --- evaluation with the whole benchmark
% 'test_set' --- evaluation with training subset
evaluation_dataset_type = 'all';

% use normalization or not
norm_dst = false;

trackers   = config_tracker();
sequences  = config_sequence(evaluation_dataset_type);
plot_style = config_plot_style();

num_seq = numel(sequences);
num_tracker = numel(trackers);

% load tracker info
name_tracker_all = cell(num_tracker, 1);
for i = 1:num_tracker
    name_tracker_all{i} = trackers{i}.name;
end

% load sequence info
name_seq_all = cell(num_seq, 1);
for i = 1:num_seq
    name_seq_all{i} = sequences{i};
    seq_att         = dlmread(fullfile(path_att, [sequences{i} '.txt']));
    if i == 1
        att_all = zeros(num_seq, numel(seq_att));
    end
    att_all(i, :) = seq_att;
end

% parameters for evaluation
metric_type_set = {'error', 'overlap'};
eval_type       = 'OPE';
% ranking_type    = 'AUC';
ranking_type    = 'threshold';   % change it to 'AUC' for success plots
rank_num        = 35;

threshold_set_error   = 0:50;
if norm_dst
    threshold_set_error = threshold_set_error / 100;
end
threshold_set_overlap = 0:0.05:1;

for i = 1:numel(metric_type_set)
    % error (for distance plots) or overlap (for success plots)
    metric_type = metric_type_set{i};
    switch metric_type
        case 'error'
            threshold_set = threshold_set_error;
            rank_idx      = 21;
            x_label_name  = 'Location error threshold';
            y_label_name  = 'Precision';
        case 'overlap'
            threshold_set = threshold_set_overlap;
            rank_idx      = 11;
            x_label_name  = 'Overlap threshold';
            y_label_name  = 'Success rate';
    end

%     if strcmp(metric_type, 'error') && strcmp(ranking_type, 'AUC') % for ranking_type = 'AUC'
    if strcmp(metric_type, 'overlap') && strcmp(ranking_type, 'threshold')  % for ranking_type = 'threshold'
        continue;
    end

    t_num = numel(threshold_set);

    % we only use OPE for evaluation
    plot_type = [metric_type '_' eval_type];

    switch metric_type
        case 'error'
            title_name = ['Precision plots of ' eval_type];
            if norm_dst
                title_name = ['Normalized ' title_name];
            end

            if strcmp(evaluation_dataset_type, 'all')
                title_name = [title_name ' on LaSOT'];
            else
                title_name = [title_name ' on LaSOT Testing Set'];
            end
        case 'overlap'
            title_name = ['Success plots of ' eval_type];

            if strcmp(evaluation_dataset_type, 'all')
                title_name = [title_name ' on LaSOT'];
            else
                title_name = [title_name ' on LaSOT Testing Set'];
            end
    end

    dataName = [tmp_mat_path 'aveSuccessRatePlot_' num2str(num_tracker) ...
                'alg_'  plot_type '.mat'];

    % evaluate tracker performance
    if ~exist(dataName, 'file')
        eval_tracker(sequences, trackers, eval_type, name_tracker_all, ...
                    tmp_mat_path, path_anno, rp_all, norm_dst);
    end

    % plot performance
    load(dataName);
    num_tracker = size(ave_success_rate_plot, 1);

    if rank_num > num_tracker || rank_num <0
        rank_num = num_tracker;
    end

    fig_name= [plot_type '_' ranking_type];
    idx_seq_set = 1:numel(sequences);

    % draw and save the overall performance plot
    plot_draw_save(num_tracker, plot_style, ave_success_rate_plot, ...
                   idx_seq_set, rank_num, ranking_type, rank_idx, ...
                   name_tracker_all, threshold_set, title_name, ...
                   x_label_name, y_label_name, fig_name, save_fig_path, ...
                   save_fig_suf);

    % draw and save the per-attribute performance plot
    att_trld = 0;
    att_num  = size(att_all, 2);
    for att_idx = 1:att_num    % for each attribute
        idx_seq_set = find(att_all(:, att_idx) > att_trld);
        if length(idx_seq_set) < 2
            continue;
        end
        disp([att_name{att_idx} ' ' num2str(length(idx_seq_set))]);

        fig_name   = [att_fig_name{att_idx} '_'  plot_type '_' ranking_type];
        title_name = ['Plots of ' eval_type ': ' att_name{att_idx} ' (' num2str(length(idx_seq_set)) ')'];

        switch metric_type
            case 'overlap'
                title_name = ['Success plots of ' eval_type ' - ' att_name{att_idx} ' (' num2str(length(idx_seq_set)) ')'];
            case 'error'
                title_name = ['Precision plots of ' eval_type ' - ' att_name{att_idx} ' (' num2str(length(idx_seq_set)) ')'];
                if norm_dst
                    title_name = ['Normalized ' title_name];
                end
        end

        plot_draw_save(num_tracker, plot_style, ave_success_rate_plot, ...
                   idx_seq_set, rank_num, ranking_type, rank_idx, ...
                   name_tracker_all, threshold_set, title_name, ...
                   x_label_name, y_label_name, fig_name, save_fig_path, ...
                   save_fig_suf);
    end
end


% This make.m is for MATLAB and OCTAVE under Windows, Mac, and Unix

try
	Type = ver;
	% This part is for OCTAVE
	if(strcmp(Type(1).Name, 'Octave') == 1)
		mex libsvmread.c
		mex libsvmwrite.c
		mex train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
		mex predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c
	% This part is for MATLAB
	% Add -largeArrayDims on 64-bit machines of MATLAB
	else
		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmread.c
		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims libsvmwrite.c
		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims train.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c -output liblinear_train
		mex CFLAGS="\$CFLAGS -std=c99" -largeArrayDims predict.c linear_model_matlab.c ../linear.cpp ../tron.cpp ../blas/daxpy.c ../blas/ddot.c ../blas/dnrm2.c ../blas/dscal.c -output liblinear_predict
	end
catch
	fprintf('If make.m fails, please check README about detailed instructions.\n');
end