function varargout=rdmimic2wave(varargin)
%
% [tm,signal,Fs,recList,sigInfo]=rdmimic2wave(subjectID,clinicalTimeStamp,dataType,beginMinute,endMinute)
%
%
%
% Output Parameters:
%
% tm
%       Nx1 vector of doubles representing time in minutes if a match is
%       found, otherwise tm is empty. The time of the first index is an offset
%       from beginMinute. So that the total duration in minutes is:
%
%       tm(end) - tm(1) = endMinute - beginMinute
%
%       And the time of the clinical event (clinicalTimeStamp) in the waveform signal is given by
%       (to the closest minute):
%
%       timeStamp = tm(1) + beginMinute
%
%
% signal
%       NxM vector of doubles representing the signals from dataType that
%       match the timeStamp. If no match is found an empty matrix is
%       returned.
%
% Optional Ouput:
%
% Fs
%       A 1x1 double representing the sampling frequency (in Hz).
%
%recList
%       A Lx1 double specifying a list of valid subjectIDs  or matched record. You can use this
%       field to find which IDs are in the matched waveform list (see below). If the
%       subjectID is defined in the function signature, recList will be
%       equal to the first found matched record if it exists.
%
%
%sigInfo
%       A Mx1 structure containing meta information about the waverforms in the 'signal' output.
%
%
% Input Parameters:
%
% subjectID
%       A 1x1 Double specifying a valid MIMIC II subject ID. For a list
%       of valid subjectID with matched waveform use this to query:
%
%       [~,~,~,recList]=rdmimic2wave([],[],dataType);
%
%       Once you have a valid subjectID and pass it to RDMIMI2WAVE, recList
%       will return the string name of the first matched record if any (empty otherwise).
%
%
% clinicalTimeStamp
%      String specifying the clinical  time of the event. This string
%      should have the following format (as described in
%       http://www.physionet.org/physiobank/database/mimic2wdb/matched/) :
%
%      'YYYY-MM-DD-hh-mm'
%
%      Where:
%           YYYY = surrogate year
%           MM = month (01-12)
%           DD = day (01-31)
%           hh = real hour (00-23)
%           mm = minute (00-59)
%
% dataType (Optional)
%     String specifying what time of high resolution waveform to fetch.
%     Options are: 'numerics' and 'waveform'. Default is 'numerics'.
%
%
% beginMinute (Optional)
%     1x1 Double specifying time in minutes of
%     how much of the signal to get before clinicalTimeStamp occured.
%     Default is 60 minutes.
%
% endMinute (Optional)
%     1x1 Double specifying time in minutes of
%     how much of the signal to get after clinicalTimeStamp occured.
%     Default is 60 minutes.
%
%
%
% % Example:
%[tm,signal,Fs,recList,sigInfo]=rdmimic2wave(32805,'2986-12-15-10-00',[],0,2);
%plot(tm,signal(:,2))
%title(['Found data in record: ' recList])
%legend(sigInfo(2).Description)
%
% Written by Ikaro Silva, 2013
% Last Modified: December 1, 2014
%
% Version 1.1
%
% Since 0.9.0
%
%
%
% See also rdsamp, wfdbdesc

%endOfHelp

inputs={'subjectID','clinicalTimeStamp','dataType','beginWindow','endWindow'};
outputs={'tm','signal','Fs','recList','sigInfo'};
subjectID=[];
beginWindow=60; %beginWindow in minutes!
endWindow=60; %endWindow in minutes!
dataType='numerics';
dBName='mimic2wdb/matched/';
tm=[];
signal=[];
Fs=[];
sigInfo=[];
recList=[];
for n=1:nargin
    if(~isempty(varargin{n}))
        eval([inputs{n} '=varargin{n};']);
    end
end

persistent cachedDataType matched_id matched

if(~strcmp(cachedDataType,dataType))
    switch (dataType)
        case 'numerics'
            matched=urlread('http://www.physionet.org/physiobank/database/mimic2wdb/matched/RECORDS-numerics');
            %case 'all'
            % Dont want to mess around with mixed sample rates yet...
            %%matched=urlread('http://www.physionet.org/physiobank/database/mimic2wdb/matched/RECORDS');
        case 'waveform'
            matched=urlread('http://www.physionet.org/physiobank/database/mimic2wdb/matched/RECORDS-waveforms');
        otherwise
            error(['Unknow dataType. Options are: ''numerics'', ''all'', or ''waveform''']);
    end
    cachedDataType=dataType;

    %Get patient ID list
    matched_id=regexprep(regexp(matched,'(\<s\d\d\d\d\d)','match'),'s','');
    for n=1:length(matched_id)
        matched_id{n}=str2num(matched_id{n});
    end
    matched_id=unique(cell2mat(matched_id));

   recList=matched_id;

end

if(isempty(subjectID))
    %In this case the user is just querying for a list of matched
    %records
    recList=matched_id;
    for n=1:nargout
        eval(['varargout{n}=' outputs{n} '']);
    end
    return

end

%Convert timestam to serial data (in days)
dateFormat='yyyy-mm-dd-HH-MM';
clinicalDateNum=datenum(clinicalTimeStamp,dateFormat);

%Window to include before and after the measurement (in days)
beginTime=clinicalDateNum - (beginWindow/(60*24));
endTime=clinicalDateNum + (endWindow/(60*24));

%If id exists loop through the files to see if any file is within the
%specific time range of the clinial event
matched_pid=find(matched_id==subjectID,1);
if(~isempty(matched_pid))

    %Get all records that match the patient and search for a record
    %that includes the clinical time
    strSubjectID=sprintf('%05d',subjectID);
    eval(['recs=regexp(regexp(matched,''(\<s' strSubjectID '.*)'',''match''),''\n'',''split'');']);
    recs=recs{:};
    N=length(recs);
    for n=1:N

        recName=recs(n); %File name
        thisTimeStamp=regexp(recName,'/s\d\d\d\d\d-','end');
        if(isempty(recName{1}))
            %Empty name, keep moving...
           continue;
        end

        thisTimeStamp=recName{1,1}(1,thisTimeStamp{1}+1:end);
        if(strcmp(thisTimeStamp(end),'n'))
            thisTimeStamp(end)=[];
        end

        %Convert to datenum
        thisDateNum=datenum(thisTimeStamp,dateFormat);

        %Continue if this record started at or before beginTime
        if(thisDateNum <= beginTime)

            %Get record length and check its duration
            recList=[dBName recName{:}];
            sigInfo=wfdbdesc(recList);
            Fs=sigInfo(1).SamplingFrequency;
            waveLengthSamples=sigInfo(1).LengthSamples;

            %Get the starting/ending offsets in samples wrt the beginning of
            %the waveform
            start_offset=round(Fs*(beginTime-thisDateNum)*24*60*60) + 1;
            end_offset=round(Fs*(endTime-thisDateNum)*24*60*60) + 1;

            if(end_offset <= waveLengthSamples)
                %Found a match. Get the waveform and exit the the search
                %Get signal and exit
                [signal,Fs,tm]=rdsamp(recList,[],end_offset,start_offset);
                break;
            end
        end %of thisDateNum< beginTime
    end %of matched record sublit
end

for n=1:nargout
    eval(['varargout{n}=' outputs{n} ';']);
end


function pbmwrite(arg1,arg2,arg3,arg4)
%PBMWRITE Write a PBM (portable bitmap) file to disk.
%
%   PBMWRITE(X,MAP,'FILENAME') writes a PBM file containing the indexed
%   image X and color map MAP to the file 'FILENAME'.
%
%   PBMWRITE(X,MAP,'FILENAME','ENCODING') where 'ENCODING' is either
%   'ascii' (or 'plain') or 'binary' (or 'raw') lets the user specify
%   whether the PBM file should be ascii or binary encoded. Default is
%   'ascii'.
%
%   PBMWRITE(I,'FILENAME') writes a PBM file containing the black and
%   white image in the matrix I to the file 'FILENAME'.
%
%   PBMWRITE(I,'FILENAME','ENCODING') allows the user to specify the
%   encoding as described above.
%
%   The 'ascii' format is the most portable and is the only that allows
%   a MAXVALUE larger than 255, so it is also the most general. The
%   'binary' format files are, however, much smaller and many times
%   faster to read and write than the 'ascii' format.
%
%   If file name has no suffix, '.pbm' is used.
%
%   See also: PBMREAD, PGMREAD, PGMWRITE, PPMREAD, PPMWRITE.

%   Author:      Peter J. Acklam
%   Time-stamp:  1998-04-15 21:26:36
%   E-mail:      jacklam@math.uio.no (Internet)
%   URL:         http://www.math.uio.no/~jacklam

nargs = nargin;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Check number of input arguments.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

error( nargchk( 2, 4, nargs ) );

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Identify input arguments.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if ( nargs == 2 )               % 2 input arguments

   %
   % PBMWRITE(I,'FILENAME')
   %
   I = arg1;
   filename = arg2;
   encoding = 'ascii';
   isindexed = 0;

elseif ( nargs == 4 )           % 4 input arguments

   %
   % PBMWRITE(X,MAP,'FILENAME','ENCODING')
   %
   X = arg1;
   map = arg2;
   filename = arg3;
   encoding = arg4;
   isindexed = 1;

else                            % 3 input arguments

   if ( ischar(arg2) & ischar(arg3) )

      %
      % PBMWRITE(I,'FILENAME','ENCODING')
      %
      I = arg1;
      filename = arg2;
      encoding = arg3;
      isindexed = 0;

   else

      %
      % PBMWRITE(X,MAP,'FILENAME')
      %
      X = arg1;
      map = arg2;
      filename = arg3;
      encoding = 'ascii';
      isindexed = 1;

   end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% These are no longer needed, so delete them to save memory.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

clear arg1 arg2 arg3 arg4

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Check filename.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if ~ischar(filename) | isempty(filename)
   error( 'File name must be a non-empty string' );
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Add suffix to file name if necessary.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

k  = [ find( filename == filesep ) ];
if isempty(k)
   k = 0;
else
   k = max(k);
end
if all( filename(k+1:end) ~= '.' )
   filename = [ filename '.pbm' ];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Check and simplify the encoding specification.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if ~ischar( encoding )
   error( 'Encoding specification must be a string.' );
end

if any( encoding(1) == 'aApP' )         % Ascii (or plain) format.
   isascii = 1;
elseif any( encoding(1) == 'bBrR' )     % Binary (or raw) format.
   isascii = 0;
else
   error( 'Illegal encoding specification.' );
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Open output file for writing.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

fid = fopen( filename, 'w', 'ieee-be' );    % Big-endian byte ordering.
if ( fid == -1 )
   error( [ 'Can''t open file ''' filename ''' for writing.' ] );
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Get dimension of image.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if isindexed
   [ rows, cols ] = size( X );
else
   [ rows, cols ] = size( I );
end
pixels = rows*cols;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Write file header.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Magic number.
if isascii
   magic = 'P1';
else
   magic = 'P4';
end

% Write header. Use FLOOR( CLOCK ) to avoid a second value of 60.
fprintf( fid, [ ...
   '%s\n', ...
   '# Created by Matlab (%s) %04d-%02d-%02d %02d:%02d:%02d\n', ...
   '%d %d\n', ...
   ], magic, mfilename, floor( clock ), cols, rows );

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Write image. Color images are first converted to grayscale.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

w = [ 0.298936 ; 0.587043 ; 0.114021 ];

if isascii
   bits_on_this_line = 0;
   bits_on_each_line = 35;
   format = [ '%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d ' ...
              '%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d ' ...
              '%d %d %d %d %d\n' ];
else
   cols8 = 8*ceil( cols/8 );
end

for row = 1:rows

   % Convert to ones (black) and zeros (white).
   if isindexed
      bits = 1 - round( map(X(row,1:cols),:)*w );
   else
      bits = 1 - round( I(row,1:cols))';
   end

   if isascii           % Write ascii format.

      % If we are to fill more characters on a line already begun.
      if bits_on_this_line > 0

         % Get the format to be used when filling the rest of this line
         % and the number of bits that can be fit on this line.
         sub_format = format(bits_on_this_line*3+1:length(format));
         bits_to_eol = bits_on_each_line - bits_on_this_line;

         % Get the bits to write on this line and the remaining bits.
         bits_to_write_now = min( length(bits), bits_to_eol );
         sub_bits = bits(1:bits_to_eol);
         bits = bits(bits_to_eol+1:length(bits));

         % Write bits to file and increment number of bits on this line.
         fprintf( fid, sub_format, sub_bits );
         bits_on_this_line = bits_on_this_line + bits_to_write_now;
         bits_on_this_line = rem( bits_on_this_line, bits_on_each_line );

      end

      % If we are to begin writing on a new line.
      if bits_on_this_line == 0

         % Write bits to file and get number of bits on last line.
         fprintf( fid, format, bits );
         bits_on_this_line = rem( length(bits), bits_on_each_line );

      end

   else                 % Write binary format.

      newbits = zeros( 1, cols8 );
      newbits(1:cols) = bits;
      fwrite( fid, newbits, 'ubit1' );

   end

end

fclose( fid );          % Close file.


function Dict = edl_buildiidxdict(S, idxfn)
%EDL_BUILDIIDXDICT Builds a dictionary using internal index
%
% $ Syntax $
%   - Dict = edl_buildiidxdict(S, idxfn)
%
% $ Arguments $
%   - S:        a struct array on which the dictionary is built
%   - idxfn:    the field name of the internal index
%               (default = 'internal_index')
%   - Dict:     the built dictionary
%               a cell array, indexed by internal_index
%
% $ Remarks $
%   - The length of the cell array (dict) will be equal to the maximum
%     internal index in S.
%   - In S, different elements should have different internal indices.
%   - For the index corresponding to no element, the corresponding cells
%     are empty.
%   - The dictionary will not automatically keep track of the change of
%     S. If S is changed, the dictonary should be rebuilt in order to
%     reflect the updates.
%
% $ History $
%   - Created by Dahua Lin, on Aug 15, 2006
%

%% parse and verify input arguments

if ~isstruct(S)
    error('sltoolbox:invalidarg', ...
        'The S should be a struct');
end

if nargin < 2 || isempty(idxfn)
    idxfn = 'internal_index';
end

if ~isfield(S, idxfn)
    error('sltoolbox:invalidarg', ...
        'The S have no specified internal index field');
end

%% Build dictionary

% gather the internal indices
n = numel(S);
inds = zeros(n, 1);
for i = 1 : n
    idx = S(i).(idxfn);
    if ischar(idx)
        idx = str2double(idx);
    end
    inds(i) = idx;
end

% construct dictionary
m = max(inds);

Dict = cell(m, 1);

for i = 1 : n
    idx = inds(i);
    if ~isempty(Dict{idx})
        error('sltoolbox:rterror', ...
            'Repeated index %d is encountered', idx);
    end
    Dict{idx} = S(i);
end


%
% output = my_grep(input, pattern)
%
% Similate the function of grep in Unix
% The inputs are
%       input: texts in cell format
%       pattern: the pattern that is searched for
% The output is
%       output: lines in input that contains the pattern
%
% Author: Xiong Xiao,
%         School of Computer Engineering, Nanyang Technological University
% Date Created: 23 Oct, 2008
% Last Modified: 23 Oct, 2008
%
function output = my_grep(input, pattern)

N = length(input);

output{1} = '';
cnt = 1;
for i=1:N
    if length(regexp(input{i},pattern)) > 0
        output{cnt} = input{i};
        cnt = cnt + 1;
    end
end


function [sym1,sym2] = extractSym(obj)
% extract left and right symmetry from various objects

if isa(obj,'symmetry')
  sym1 = obj;
  sym2 = obj;
elseif isa(obj,'orientation')
  sym1 = obj.SS;
  sym2 = obj.CS;
else
  sym2 = [];
  try
    sym1 = obj.CS;
  catch
    sym1 = [];
  end
end

end


function [kSpace, evalMask] = extractKSpace3D(dData, iLC, iEvalInfoMask, dim, inLoops)
% extract kSpace from acquired 3D data
%
% (c) Thomas Kuestner
% ---------------------------------------------------------------------

% Check the input data
% These loop counters have to be constant in one slice
% iSingularLCs = iLC(:,[1, 2, 5, 7, 9, 10, 11]); % Sam, Cha, Sli, Eco, Rep, Set, Seg
% if any(min(iSingularLCs) ~= max(iSingularLCs))
%     error('CS_reconstruction()::extractKSpace3D()','Input data contains data from multiple sample sizes/channel counts/slices/echos/repetitions/sets/segments!');
% end

% extract kSpace
nCha = dim(5);
nZ = dim(3);
nSeg = double(max(iLC(:,11)) - min(iLC(:,11)) + 1);
iTotalLines = dim(1);
kSpace = cell(1,nCha);
evalMask = cell(1,nCha);

for iCha = 1:nCha
    kSpace{1,iCha} = (complex(zeros(iTotalLines, iLC(1, 1), nZ,'single'), zeros(iTotalLines, iLC(1, 1), nZ,'single')));
    evalMask{1,iCha} = zeros(iTotalLines, 1, nZ);
%     fprintf(1, 'Preprocessing Channel %2u\n', iCha);
    dChaData = dData(iCha:nCha:end, :);
    iChaLC   = iLC  (iCha:nCha:end, :);
    if(~isempty(iEvalInfoMask))
        iEvalInfoMaskLC = iEvalInfoMask(iCha:nCha:end, :);
    end
    for iPar = 1:nZ
        dParData = dChaData(iChaLC(:, 6) == iPar - 1, :);
        iParLC   = iChaLC  (iChaLC(:, 6) == iPar - 1, :);
        if(~isempty(iEvalInfoMask))
            iEvalInfoMaskParLC = iEvalInfoMaskLC(iChaLC(:,6) == iPar - 1, :);
        end
        for iSeg = 1:nSeg
            dSegData = dParData(iParLC(:,11) == iSeg - 1, :);
            iSegLC = iParLC(iParLC(:,11) == iSeg - 1, :);
            if(~isempty(iEvalInfoMask))
                iEvalInfoMaskSegLC = iEvalInfoMaskParLC(iParLC(:,11) == iSeg - 1, :);
            end
            for iLine = 1:length(iSegLC(:,3))
                kSpace{1,iCha}(iSegLC(iLine,3) + 1, :, iPar) = dSegData(iLine, :);
                if(~isempty(iEvalInfoMask) && ~isempty(iEvalInfoMaskSegLC))
                    evalMask{1,iCha}(iSegLC(iLine,3) + 1, 1, iPar) = iEvalInfoMaskSegLC(iLine,1);
                end
                if(~isempty(iEvalInfoMask) && ~isempty(iEvalInfoMaskParLC) && bitget(iEvalInfoMaskParLC(iLine,1),25)) % switched readout direction
%                 if(iSeg == 2) % switched readout
                    kSpace{1,iCha}(iSegLC(iLine,3) + 1, :, iPar) = kSpace{1,iCha}(iSegLC(iLine,3) + 1, end:-1:1, iPar);
%                     kSpace{1,iCha}(iSegLC(iLine, 3) + 1, :, iPar) = kSpace{1,iCha}(iSegLC(iLine, 3) + 1, end:-1:1, iPar);
                end
            end
            dispProgress('Extracting K-Space', ((inLoops(1)-1)*inLoops(2)*nCha*nZ*nSeg + (inLoops(2)-1)*nCha*nZ*nSeg + (iCha-1)*nZ*nSeg + iPar*nSeg + iSeg)/inLoops(3));
        end
    end
    dispProgress('Extracting K-Space', ((inLoops(1)-1)*inLoops(2)*nCha*nZ*nSeg + (inLoops(2)-1)*nCha*nZ*nSeg + iCha*nZ*nSeg)/inLoops(3));
end

end


% -------------------------------------------------------------------------------------------------------------------------
function sz = size_ndims(x, n)
% -------------------------------------------------------------------------------------------------------------------------
sz = cell(1, n);
[sz{1:n}] = size(x);
sz = cell2mat(sz);
end


% plot_parameters: script to set globally plot parameters
%
% INPUT
%   None.
%
% OUTPUT
%   None.
%
%   Copyright (C) 2014, Rodrigo Gonzalez, all rights reserved.
%
%   This file is part of NaveGo, an open-source MATLAB toolbox for
%   simulation of integrated navigation systems.
%
%   NaveGo is free software: you can redistribute it and/or modify
%   it under the terms of the GNU Lesser General Public License (LGPL)
%   version 3 as published by the Free Software Foundation.
%
%   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 Lesser General Public License for more details.
%
%   You should have received a copy of the GNU Lesser General Public
%   License along with this program. If not, see
%   <http://www.gnu.org/licenses/>.
%
% Version: 001
% Date:    2021/12/14
% Author:  Rodrigo Gonzalez <rodralez@frm.utn.edu.ar>
% URL:     https://github.com/rodralez/navego

%% COLORS

blue    = [0, 0.4470, 0.7410];
orange  = [0.8500, 0.3250, 0.0980];
green   = [0.4660, 0.6740, 0.1880];
yellow  = [0.9290, 0.6940, 0.1250];
light_blue = [0.3010, 0.7450, 0.9330];

%% TEXT SIZES

font_title  = 25;
font_label  = 15;
font_tick   = 10;
font_legend = 10;

%% LINE WIDTH

lw = 1.75;

%% MARKER SIZE

ms = 10;


function [stringTokens, numberOfTokens] = stringTokenizer( stringTarget, delimiter )
%STRINGTOKENIZER
% stringTarget = ';;ab;cd de=0==';
% delimiter = '; =';

% regexpression
pattern = ['\w*[^' delimiter ']\w*'] ;
[startIndices, endIndices] = regexp(stringTarget, pattern);

stringTokens = [];
index = 1;

for i = 1:length(startIndices)
    stringTokens = [stringTokens {stringTarget(startIndices(i):endIndices(i))}];
end

numberOfTokens = length(stringTokens);

end


%% GENERIC object CLASS (objectDefinition.m) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This class is designed to define a generic object and import its
% variables into the simulation space for the purpose of multi-vehicle
% control simulation.

% Author: James A. Douthwaite 20/05/2016

classdef objectDefinition < handle
    %% OBJECT BASE CLASS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % This class contains the basic properties of a generic agent, neither
    % aerial or ground based.
    properties
        % SIMULATION IDENTIFIERS
        objectID = 0;
        name;
        radius = 1;                 % Characteristic radius
        % KINEMATIC PROPERTIES
        localState  = zeros(6,1);   % 6DOF state vector
        % GEOMETRIC PROPERTIES
        GEOMETRY = struct(...
            'vertices',[],...
            'faces',[],...
            'normals',[],...
            'centroid',zeros(3,1));
    end
    % Private (OpenMAS-facing) properties
    properties (Access = private)
        % GLOBAL PROPERTIES (Virtual (SIMULATION) data container)
        GLOBAL;
    end
    %% ///////////////////////// MAIN METHODS /////////////////////////////
    methods (Access = public)
        % Constructor
        function [this] = objectDefinition(varargin)
            % This function is designed to automatically apply a generic
            % naming convention to all objects generated prior to a
            % simulation.
            % INPUTS:
            % varargin - A cell array of property/value pairs
            % OUTPUTS:
            % this     - The generated object

            % Check all system paths are available
            this.GetPathDependencies();

            % Assign the objectID (if required)
            if this.objectID == 0                                           % Generate objectID if not allocated by a super class
                this.objectID = this.CreateobjectID();                       % Assign the number as an ID tag
                spawnNewobject = 1;
            else
                spawnNewobject = 0;
            end

            % Assign a name string
            if numel(this.name) < 1
                this.name = this.CreateName(this.objectID);                   % No input name string specified, use greek naming scheme
            end

            % Assign default
            this.GLOBAL   = this.CreateGLOBAL();    % The GLOBAL structure
            this.GEOMETRY = this.CreateGEOMETRY();  % Get the geometry of the object

            % //////////////// Check for user overrides ///////////////////
            [this] = this.ApplyUserOverrides(varargin); % Recursive overrides
            % /////////////////////////////////////////////////////////////

            % ////////// DISPLAY THE CURRENT object PROPERTIES ////////////
            if spawnNewobject
                fprintf('objectcount: %d\tname: %s\ttype: %s\n',this.objectID,this.name,class(this));
            end
        end
        % Setup (default 6-dof state)
        function [this] = setup(this,localXYZvelocity,localXYZrotations)   % [x y z phi theta psi]
            % This function is called in order to build the initial state
            % vector for the generic agent class 'objectDefinition'.
            % INPUTS:

            % ASSUMPTIONS:
            % - The designed state is described in the ENU axes.
            % - The state is of the form:
            % - [x y z phi theta psi]

            % Standard state vector is the 6DOF: x_k = [x y z phi theta psi]
            this.localState = [zeros(3,1);localXYZrotations];
        end
        % Main  (default 6-dof state)
        function [this] = main(this,ENV,varargin)
            % This is a generic process cycle of an object that accepts no
            % input commands/feedback and simply updates its states based
            % on its current attributes
            % INPUT:
            % varargin - Generic variable input container, containing the simulation timestep
            % OUTPUT:
            % this - The updated object

            % DETERMINE THE TIMESTEP
            if isstruct(ENV)
                dt = ENV.dt;
            else
                error('object TIME packet is invalid.');
            end

            % The state differential
            x_dot = [0;0;0;0;0;0];

            % MAINTAIN LOCAL INPUT CONDITIONS
            % Default behaviour of a system is to move with constant input
            % conditions.
            [dXdt]   = this.SingleIntegratorDynamics(this.localState,x_dot);
            newState = this.localState + dt*dXdt;

            % UPDATE THE CLASS GLOBAL PROPERTIES
            this = this.GlobalUpdate(dt,newState);
        end
    end

    %% /////////////////////// CHECK FUNCTIONS ////////////////////////////
    methods
        % Get the 'idle' status
        function [flag] = IsIdle(this)
            flag = this.GetGLOBAL('idleStatus');
        end
        % Get the dimensionality of the object
        function [flag] = Is3D(this)
            flag = this.GetGLOBAL('is3D');
        end
    end
    %% ////////////////////// GET/SET FUNCTIONS ///////////////////////////
    methods
        % Set the radius
        function set.radius(this,radius)
            this.radius = radius;               % Set the radius
            this.SetGLOBAL('radius',radius);    % Set the simulation radius
            % If agent has GEOMETRY
            if ~isempty(this.GEOMETRY.vertices)
                % Normalise the geometry
                this.GEOMETRY = OMAS_graphics.normalise(this.GEOMETRY);
                % Scale the geometry to the radius
                this.GEOMETRY = OMAS_graphics.scale(this.GEOMETRY,this.radius);
            end
        end
        % Get the GLOBAL structure
        function [param] = GetGLOBAL(this,label)
            % By default return the GLOBAL structure
            if nargin < 2
                param = this.GLOBAL;
                return
            end
            assert(ischar(label),"Expecting a string parameter label");
            % Return the associated parameter
            param = this.GLOBAL.(label);
        end
        % Set the virtual structure
        function [this]  = SetGLOBAL(this,label,value)
            % By default set the GLOBAL structure
            if nargin < 3
                % Input sanity check
                assert(isstruct(label),"The object's GLOBAL field must be a structure.");
                % Set the GLOBAL structure
                this.GLOBAL = label;
                return
            end
            assert(ischar(label),"Expecting a string parameter label");
            % Assign the virtual structure
            this.GLOBAL.(label) = value;
        end
    end
    %% ////////////////// BASIC PROPERTY ASSIGNMENTS //////////////////////
    methods
        % PARSE A GENERIC INPUT SET AGAINST A DEFAULT CONFIG STRUCTURE
        function [this]     = ApplyUserOverrides(this,pairArray)
            % This function is designed to parse a generic set of user
            % inputs and allow them to be compared to a default input
            % structure. This should be called in the class constructor

            % Input sanity check #1
            if nargin < 2 || numel(pairArray) == 0
                return
            end
            % Call the all parameter overrider
            [this] = GetParameterOverrides_recursive(this,pairArray);
        end
        % Get the object GEOMETRY structure
        function [GEOMETRY] = CreateGEOMETRY(this)
            % This function prepares object STL files for representation.
            % ASSUMPTIONS:
            % - The object stl file has the same name as the object being simulated.
            % - The STL is correctly rotated to match the axes of XYZ of the agents
            %   local frame.

            % This functions allow additional operations to the GEOMETRY
            % structure to happen other than sourcing the basic structure.

            % Call the generic object.stl geometry parser
            [GEOMETRY] = this.GetObjectGeometry(this);
        end
    end
    % Only the objectDefinition class has access
    methods (Static, Access = private)
        % Get the object GLOBAL structure
        function [GLOBAL]   = CreateGLOBAL()
            % This is function that assembles the template desciption of an
            % object

            % Define the GLOBAL structure
            GLOBAL = struct();
            GLOBAL.type = OMAS_objectType.misc;
            GLOBAL.hitBoxType = OMAS_hitBoxType.none;
            GLOBAL.radius = 0.5;                        % Diameter of 1m
            GLOBAL.colour = rand(1,3,'single');         % Virtual colour (for plotting)
            GLOBAL.symbol = 'square';                   % Representative symbol
            GLOBAL.position = [0;0;0];                  % Global Cartesian position
            GLOBAL.velocity = [0;0;0];                  % Global Cartesian velocity
            GLOBAL.quaternion = [1;0;0;0];              % Global quaternion pose
            GLOBAL.idleStatus = true;                   % object idle logical
            GLOBAL.is3D = true;                         % object operates in 3D logical
            GLOBAL.priorState = [];
        end
        % Get the object name
        function [namestr]  = CreateName(objectID)
            % No input name string specified, use greek naming scheme
            defaultID = { 'alpha', 'beta','gamma', 'delta','epsilon'  ...
                        ,  'zeta',  'eta','theta',  'iota','kappa'    ...
                        ,'lambda',   'mu',   'nu',    'xi','omicron'  ...
                        ,    'pi',  'rho','sigma',   'tau','upsilon'  ...
                        ,   'phi',  'chi',  'psi', 'omega'};
            % GENERATE DEFAULT NAME STRING
            defLength = length(defaultID);
            cycle = floor(double(objectID)/defLength);
            IDvalue = mod(objectID,defLength);
            if IDvalue == 0
                IDvalue = 24;
            end
            namestr = sprintf('%s%03d',defaultID{IDvalue},cycle+1);
        end
        % Get the object ID
        function [objectID] = CreateobjectID()
            % This function allocates a basic ID convention to the class
            % heirarchy to provide object automatic numeration.

            persistent objectCount;

            % DEFINE ID BASED ON EXISTING objectS
            if isempty(objectCount)
                % INITIAL object
                objectCount = 1;
            else
                % objectS EXIST
                objectCount = objectCount + 1;
            end
            % ALLOCATE object ID
            objectID = uint16(objectCount);
        end
    end

    %% STATE UPDATE METHODS
    methods (Static)
        % STATE UPDATE - TWO WHEELED DIFFERENTIAL ROBOT
        function [dXdt] = DifferencialDriveDynamics(X,d,a_left,a_right)
            % Becker, M. (2006). Obstacle avoidance procedure for mobile robots. ABCM Symposium Series
            % [x;y;theta;v;omega]

            % BUILD THE STATE DIFFERENTAL
            dXdt = zeros(5,1);
            dXdt(1) = X(4)*cos(X(3));             % x velocity
            dXdt(2) = X(4)*sin(X(3));             % y velocity
            dXdt(3) = X(5);                       % rotational rate
            dXdt(4) = (a_right + a_left)/2;       % Linear acceleration
            dXdt(5) = (a_right - a_left)/d;       % Angular acceleration
        end
        % STATE UPDATE - UNI-CYCLE ROBOT
        function [dXdt] = UnicycleDynamics(X,speed,headingRate)
            % This function provides the dynamics of a uni-cycle model
            % moving in on a 2D plane.

            % THE STATE UPDATE
            dXdt = zeros(3,1);
            dXdt(1) = speed*cos(X(3));
            dXdt(2) = speed*sin(X(3));
            dXdt(3) = headingRate;
        end
        % STATE UPDATE - DOUBLE INTEGRATOR
        function [dXdt] = DoubleIntegratorDynamics(X,U)
            % The relationship between the input and state vector is by
            % definition of a double integrator: dX(dX/dt)/dt = U

            % X(t) here is assumed to be of the form X(t) = [q;dq]

            qDim = length(X)/2;

            % dXdt is of the form dX(t) = [dq;ddq];
            dXdt = [X(qDim+1:2*qDim,1);     % Velocity states
                    U];                     % Acceleration states
        end
        % STATE UPDATE - SINGLE INTEGRATOR
        function [dXdt] = SingleIntegratorDynamics(X,U)
            % The relationship between the input and state vector is by
            % definition of a single integrator: dX/dt = U

            % Sanity check
            assert(length(X) == length(U),"Expecting the number of inputs to correspond to the state vector.");

            % X(t) here is assumed to be of the form X(t) = [q]

            % The change in state is literally the input
            dXdt = U;
        end
        % STATE UPDATE - SIMPLE EULER VELOCITIES
        function [dXdt] = SimpleDynamics(X,velocity_k_plus,omega_k_plus)
            % This function assumes that the velocity changes are
            % implemented this timestep directly, integration then occurs
            % including the updates from this timestep:
            % State vector is assumed:
            % 2D - [x y psi dx dy dpsi]'
            % 3D - [x y z phi theta psi dx dy dz dphi dtheta dpsi]'

            % CHECK EXPECTED INPUT DIMENSIONS
            Aflag = numel(velocity_k_plus) == 3 && numel(omega_k_plus) == 3; % IS 3D
            Bflag = numel(velocity_k_plus) == 2 && numel(omega_k_plus) == 1; % IS 2D
            assert((Aflag || Bflag) == 1,'Integrator inputs are of the wrong dimensions');

            % Either rotation occurs in one dimension (2D) or in three (3D)
            rotationDOF = numel(omega_k_plus); % Is heading a yaw (2D) or [phi,theta psi] (3D)
            if rotationDOF == 1
                linearIndices = 1:2;
                angularIndices = 3;
            else
                linearIndices = 1:3;
                angularIndices = 4:6;
            end

            % THE STATE DIFFERENTIAL
            dXdt = zeros(numel([linearIndices,angularIndices]),1);
            dXdt(linearIndices) = velocity_k_plus;
            dXdt(angularIndices) = omega_k_plus;
        end
    end
    %% GLOBAL REPRESENTATION UPDATE METHODS
    methods
        % INITIAL 3D STATE - [x y z phi theta psi dx dy dz dphi dtheta dpsi]
        function [this] = setup_3DVelocities(this,localXYZVelocity,localXYZrotations)
            % This function calculates the intial state for a generic
            % object.
            % The default state vector:
            % [x y z phi theta psi; dx dy dz dphi dtheta dpsi]

            % BUILD STATE VECTOR
            this.localState = zeros(12,1);
            this.localState(4:5) = localXYZrotations(1:2);
            %this.localState(4:6) = localXYZrotations;       % Represent yaw relative to initial position
            this.localState(7:9) = localXYZVelocity;
            % Define the
            this.SetGLOBAL('priorState',this.localState);
        end
        % GLOBAL UPDATE - STATE VECTOR DEFINED AS: [x_t;x_dot]'
        function [this] = GlobalUpdate_3DVelocities(this,dt,eulerState)
            % This function preforms the state update for a state vector
            % defined as [x y z phi theta psi dx dy dz dphi dtheta dpsi].

            positionIndices = 1:3;
            angleIndices = 4:6;

            % USE THE 'RATE' STATES DIRECTLY
            localLinearRates  = eulerState(positionIndices+6);
            localAngularRates = eulerState(angleIndices+6);
            % Get current properties
            p_k = this.GetGLOBAL('position');
            v_k = this.GetGLOBAL('velocity');
            q_k = this.GetGLOBAL('quaternion');

            % MAP THE LOCAL RATES TO GLOBAL RATES AND INTEGRATE QUATERNION
            % PREVIOUS QUATERNION % [ IF THE QUATERNION DEFINES GB ]

            % PREVIOUS ROTATION-MATRIX
            R_k_plus = quat2rotm(q_k');
            % THE GLOBAL AXIS RATES
            omega = R_k_plus'*localAngularRates;
            % UPDATE THE QUATERNION POSE
            q_k_plus = OMAS_geometry.integrateQuaternion(q_k,omega,dt);
            % REDEFINE THE ROTATION MATRIX
            R_k_plus = quat2rotm(q_k_plus');
            % MAP THE LOCAL VELOCITY TO THE GLOBAL AXES
            v_k_plus = R_k_plus'*localLinearRates;
            p_k_plus = p_k + dt*v_k;

            % ///////////////// REASSIGN K+1 PARAMETERS ///////////////////
            this = this.GlobalUpdate_direct(...
                p_k_plus,...    % Global position at k plius
                v_k_plus,...    % Global velocity at k plus
                q_k_plus);      % Quaternion at k plus
        end
        % GLOBAL UPDATE - EULER 6DOF(3DOF) [x y z phi theta psi],[x y psi]
        function [this] = GlobalUpdate(this,dt,eulerState)
            % This function computes the position, velocity and
            % quaternion in the global ENU frame from a 6DOF state vector
            % with euler rotations.

            % This function is intended for state vectors of the form:
            % - [x y z phi theta psi]
            % - [x y phi]

            % NOTATION INDICIES
            if this.Is3D
                positionIndices = 1:3;
                eulerIndices = 4:6;     % The rotations about X,Y,Z
            else
                positionIndices = 1:2;
                eulerIndices = 3;       % The rotations about Z
            end

            % Get current properties
            p_k = this.GetGLOBAL('position');
            v_k = this.GetGLOBAL('velocity');
            q_k = this.GetGLOBAL('quaternion');
            x_k = this.GetGLOBAL('priorState');

            % Populate the prior state if necessary
            if isempty(x_k)
                x_k = this.localState;
            end

            % Equivalent rates
            localLinearRates  = (eulerState(positionIndices) - x_k(positionIndices))/dt;
            localAngularRates = (eulerState(eulerIndices) - x_k(eulerIndices))/dt;

            % EULER ROTATIONS -> GLOBAL ROTATIONS
            if numel(localAngularRates) ~= 3
                localAngularRates = [0;0;1]*localAngularRates;
                localLinearRates  = [localLinearRates;0];
            end

            % MAP THE LOCAL RATES TO GLOBAL RATES AND INTEGRATE QUATERNION
            % PREVIOUS ROTATION-MATRIX
            R_k_plus = quat2rotm(q_k');
            % THE GLOBAL AXIS RATES
            omega = R_k_plus'*localAngularRates;
            % UPDATE THE QUATERNION POSE
            q_k_plus = OMAS_geometry.integrateQuaternion(q_k,omega,dt);
            % REDEFINE THE ROTATION MATRIX
            R_k_plus = quat2rotm(q_k_plus');
            % MAP THE LOCAL VELOCITY TO THE GLOBAL AXES
            velocity_k_plus = R_k_plus'*localLinearRates;
            position_k_plus = p_k + dt*v_k;
            % ///////////////// REASSIGN K+1 PARAMETERS ///////////////////
            this = this.GlobalUpdate_direct(...
                position_k_plus,... 	% Global position at k plius
                velocity_k_plus,...     % Global velocity at k plus
                q_k_plus);              % Quaternion at k plus
        end
        % GLOBAL UPDATE - EULER 6DOF(3DOF) (NO ROTATIONS)
        function [this] = GlobalUpdate_fixedFrame(this,dt,eulerState)
            % This function computes the position and velocity whilst
            % maintaining a fixed quaternion rotation (constant reference
            % orientation) in the global ENU frame from a 6DOF state vector
            % with euler rotations.

            % NOTATION INDICIES
            if this.Is3D
                positionIndices = 1:3;
            else
                positionIndices = 1:2;
            end

            % Get current properties
            position_k   = this.GetGLOBAL('position');
            velocity_k   = this.GetGLOBAL('velocity');
            quaternion_k = this.GetGLOBAL('quaternion');
            state_k      = this.GetGLOBAL('priorState');

            % Equivalent velocity
            velocity_k_plus = (eulerState(positionIndices) - state_k(positionIndices))/dt;

            % ROTATION RATES ABOUT THE GLOBAL AXES
            if numel(eulerState) ~= 6
                velocity_k_plus = [velocity_k_plus;0];
            end

            % NEW ROTATION MATRIX (G>B)
            R_k_plus = OMAS_geometry.quaternionToRotationMatrix(quaternion_k);
            % MAP THE LOCAL VELOCITY TO THE GLOBAL AXES
            velocity_k_plus = R_k_plus'*velocity_k_plus;
            position_k_plus = position_k + dt*velocity_k;

            % ///////////////// REASSIGN K+1 PARAMETERS ///////////////////
            [this] = this.GlobalUpdate_direct(...
                position_k_plus,...     % Global position at k plius
                velocity_k_plus,...     % Global velocity at k plus
                quaternion_k_plus,...   % Quaternion at k plus
                eulerState);            % The new state for reference
        end
        % GLOBAL UPDATE - DIRECTLY (global default)
        function [this] = GlobalUpdate_direct(this,p,v,q)
            % Under this notation, the state vector already contains the
            % global parameters of the object.
            % INPUTS:
            % globalPosition - 3D global cartesian position given in the ENU coordinate frame.
            % globalVelocity - 3D global cartesian velocity given in the ENU coordinate frame.
            % quaternion     - The new quaternion pose of body in the global frame.
            % R              - The rotation of the body
            % this.localState - The previous localState (independant of convention)
            % eulerState     - The new state as reported by the agent

            % Input sanity check
            assert(IsColumn(p,3),'Global position must be a 3D column vector [3x1].');
            assert(IsColumn(v,3),'Global velocity must be a 3D column vector [3x1].');
            assert(IsColumn(q,4),'Global pose must be a 4D quaternion vector [4x1].');
            assert(size(this.localState,2) == 1,'The length of the objects state update must match the its local state.');

            % ///////////////// REASSIGN K+1 PARAMETERS ///////////////////
            % Convert the quaternion to the equivalent rotation matrix
            R = OMAS_geometry.quaternionToRotationMatrix(q);
            % Assign the global parameters
            this.SetGLOBAL('position',p);                 	% Reassign the global position
            this.SetGLOBAL('velocity',v);                 	% Reassign the global velocity
            this.SetGLOBAL('quaternion',q);                	% Reassign the quaternion
            this.SetGLOBAL('R',R);                          % New rotation matrix
            this.SetGLOBAL('priorState',this.localState);  	% Record the previous state
        end
    end
    methods (Static)
        % Generic .STL to geometry parser
        function [GEOMETRY] = GetObjectGeometry(entity)
            % This function prepares object STL files for representation.
            % ASSUMPTIONS:
            % - The object stl file has the same name as the object being simulated.
            % - The STL is correctly rotated to match the axes of XYZ of the agents
            %   local frame.

            % ABSOLUTE PATH TO THE object STL LOCATION
            absPath = mfilename('fullpath');
            absPath = strrep(absPath,'objectDefinition','');               % Get the current m-files directory

            % GET THE AGENT SUPERCLASSES
            aliases = superclasses(entity);
            aliases = vertcat(class(entity),aliases);
            % MOVE THROUGH THE CLASS HEIRARCHY
            for aliasNo = 1:numel(aliases)
                % BUILD THE STL ASSOCIATION
                filename = strcat(absPath,char(aliases(aliasNo)),'.stl');  % Build the associated STL path
                % GET THE object PATCH FROM STL FILE (in the object directory)
                [GEOMETRY,getFlag] = OMAS_graphics.importStlFromFile(filename);
                if getFlag
                    break                                                  % Successful import
                end
            end

            % IF PATCH RETURNED, PROCESS FOR SIMULATION
            if isstruct(GEOMETRY)
                % Get the entities representative radius
                entityRadius = entity.GetGLOBAL('radius');
                % NORMALISE THE IMPORTED GEOMETRY
                GEOMETRY = OMAS_graphics.normalise(GEOMETRY);              % Normalise
                GEOMETRY = OMAS_graphics.scale(GEOMETRY,entityRadius);     % Scale
                GEOMETRY.normals = OMAS_graphics.normals(GEOMETRY);
                % ADD CENTROID
                GEOMETRY.centroid = zeros(1,3);                            % Assume vertices are relative to a centroid
            else
                % GEOMETRIC PROPERTIES
                GEOMETRY = struct('vertices',[],...
                                  'faces',[],...
                                  'normals',[],...
                                  'centroid',zeros(1,3));                  % If the object is something other than a point.
            end
            % Return patch, empty if not successful
        end
        % Dependancy check for all objects
        function GetPathDependencies()
            % This program preforms a check of the dependencies necessary
            % for the instantiation of object classes.

            % Get the path to the install directory
            repoString = mfilename('fullpath');
            repoString = repoString(1:(strfind(repoString,'objects')-1));
            % Add the path to the repo's environment
            addpath([repoString,'environment']);
            % Check all the OMAS_dependencies
            if ~OMAS_system.GetFileDependancies()
                error('Unable to get OpenMAS dependancies.');
            end
        end
    end
end


% Generating VOCopts varible of VOC evalution toolkit for HollywoodHeads dataset
%
% This code is based on VOCinit.m from VOC2012 devkit.
% Copyright Tuan-Hung VU - tuanhungvu@gmail.com

clear VOCopts

VOCopts.dataset='HollywoodHeads';

% change this path to a writable directory for your results
curPath = pwd;

% change this path to point to your copy of the HollywoodHeads dataset
VOCopts.datadir= fullfile(curPath, 'data');

VOCopts.resdir=fullfile(curPath, 'results', VOCopts.dataset, 'VOCEval');
if ~exist(VOCopts.resdir, 'dir')
    mkdir(VOCopts.resdir);
end

% change this path to a writable local directory for the annotation cache
VOCopts.localdir=fullfile(curPath, 'results', VOCopts.dataset, 'VOCEval', 'anns');
if ~exist(VOCopts.localdir, 'dir')
    mkdir(VOCopts.localdir);
end

% initialize the training set
VOCopts.trainset='train'; % use train for development

% initialize the test set
VOCopts.testset='test'; % use validation data for development test set

% initialize main paths
VOCopts.annopath=fullfile(VOCopts.datadir, VOCopts.dataset, 'Annotations', '%s.xml');
VOCopts.imgpath=fullfile(VOCopts.datadir, VOCopts.dataset, 'JPEGImages', '%s.jpeg');
VOCopts.imgsetpath=fullfile(VOCopts.datadir, VOCopts.dataset, 'Splits', '%s.txt');

VOCopts.detrespath=fullfile(VOCopts.resdir, ['%s_det_' VOCopts.testset '_%s.txt']);

VOCopts.classes={'head'};
VOCopts.nclasses=length(VOCopts.classes);

% overlap threshold
VOCopts.minoverlap=0.5;

% annotation cache for evaluation
VOCopts.annocachepath=fullfile(VOCopts.localdir, '%s_anno.mat');


function estimateClinicalRF_Aerts(pathRF,nSplit,nBoot,seed)

startpath = pwd;

% INITIALIZATIONS
cd(pathRF), load('training')
testSplit = 1/3; % Proportion of test cases in the splits
testCost = 0.4:0.1:2.5; % Emphasis factor on positive instances during random forest training
comb = {[1,2,3],[1,2,4],[1,2,5],[1,2,3,4]};

% COMPUTATIONS
[indClinic,bestCost] = estimateClinicalRF(pathRF,'DeathSign','CT',comb,testCost,nSplit,testSplit,nBoot,seed,0);
training.clinical.bestAdd.DeathSign.CT = indClinic;
training.cost.DeathSign.CT = bestCost;

cd(pathRF), save('training','training')
cd(startpath)
end


function t = uminus(t)
%UMINUS Unary minus (-) for tensors.
%
%   See also TENSOR.
%
%MATLAB Tensor Toolbox.
%Copyright 2012, Sandia Corporation.

% This is the MATLAB Tensor Toolbox by T. Kolda, B. Bader, and others.
% http://www.sandia.gov/~tgkolda/TensorToolbox.
% Copyright (2012) Sandia Corporation. Under the terms of Contract
% DE-AC04-94AL85000, there is a non-exclusive license for use of this
% work by or on behalf of the U.S. Government. Export of this data may
% require a license from the United States Government.
% The full license terms can be found in the file LICENSE.txt

t.data = -t.data;


function m = TotalMass(j)
global uLINK

if j == 0
   m = 0;
else
   m = uLINK(j).m + TotalMass(uLINK(j).sister) ...
                  + TotalMass(uLINK(j).child);
end


classdef prtPreProc < prtAction
    % prtPreProc  Base class for prt pre processing objects
    %
    % PreProcessors are currently have no additional properties or methods
    %
    % This is an abstract class and cannot be instantiated.
    %
    % A prtPreProc object inherits all methods and properties from the
    % prtAction class
    %
    %   See Also: prtPreProc, prtPreProcPca, prtPreProcPls,
    %   prtPreProcHistEq, prtPreProcZeroMeanColumns, prtPreProcLda,
    %   prtPreProcZeroMeanRows, prtPreProcLogDisc, prtPreProcZmuv,
    %   prtPreProcMinMaxRows

    properties (SetAccess = protected)
        isSupervised = false;  % False
        isCrossValidateValid = true; % True
    end

    methods
        function obj = prtPreProc()
            % As an action subclass we must set the properties to reflect
            % our dataset requirements
            obj.classTrain = 'prtDataSetStandard';
            obj.classRun = 'prtDataSetStandard';
            obj.classRunRetained = true;
        end
	end
	methods (Hidden = true)
        function featureNameModificationFunction = getFeatureNameModificationFunction(obj)
			featureNameModificationFunction = prtUtilFeatureNameModificationFunctionHandleCreator('#strIn#_{%s}', obj.nameAbbreviation);
        end
    end
end


function setT(OCP,T)
    % assert
%     if isa(T,'numeric')
%         if T<0
%             error('T must be a positive number or parameter!');
%         end
%     else
%         if has(T,OCP.u) || has(T,OCP.x)
%             error('T cannot be an input or state!');
%         end
%     end

    OCP.T = T;
    OCP.deltaTau = OCP.T/OCP.N;
end


function inplane = vol2ipAllROIs(volume,inplane)
%
% inplane = vol2ipAllROIs(volume,inplane)
%
% Calls vol2ipROI with all ROIs.
%
% rmk, 1/15/99
% djh, 2/2001, replaced globals with local variables

% if ~volume.selectedROI
%   myErrorDlg('Must have a selected ROI in the Volume window before it can be transformed to the Inplane window.');
% end

for r=1:length(volume.ROIs)
  volROI = volume.ROIs(r);
  ipROI = vol2ipROI(volROI,volume,inplane);

    % if no coords exist in the inplanes, offer user the option of not xforming
    % this ROI
    if isempty(ipROI.coords)
        q = 'This ROI lies outside the inplane range. Xform empty ROI?';
        resp = questdlg(q, ipROI.name);
        if isequal(resp, 'No')
            continue
        elseif ~isequal(resp, 'Yes'); % cancel or close dialog
            fprintf('%s: user aborted. \n', mfilename);
            return
        end
    end

    % add but don't select (we'll select the last one at the end)
    inplane = addROI(inplane, ipROI, 0);
end

% select last one (so only 1 redraw at most):
inplane = selectROI(inplane, length(inplane.ROIs));

return


function y = fftn(varargin)
% For two inputs, if second input has a zero it gives an empty result with the
% size specified by the second input, like Matlab does, instead of giving
% an error
if nargin==2 && any(varargin{2}==0)
    y = ones(varargin{2});
else
    y = builtin('fftn', varargin{:});
end
end


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

% This is a dummy function

pvec    = [];
pstruct = struct;

return;


classdef TestDrawAxis
    %TestDrawAxis

    methods (Static)
        function test_1
            img = zeros([50 50 3], 'uint8');
            camMat = eye(3);
            distCoef = zeros(1,5);
            rvec = zeros(1,3);
            tvec = zeros(1,3);
            len = 1;
            out = cv.drawAxis(img, camMat, distCoef, rvec, tvec, len);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_error_argnum
            try
                cv.drawAxis();
                throw('UnitTest:Fail');
            catch e
                assert(strcmp(e.identifier,'mexopencv:error'));
            end
        end
    end

end


function timer_id = stic
%STIC TIC equivalent using precise system time.
% Usage:
%   stic
%   timer_id = tic
%
% See also: stoc, systime

global stic_timers;

timer_id = numel(stic_timers) + 1;
stic_timers(timer_id) = systime;

if nargout < 1
    clear timer_id
end

end


function update_visualization_func = show_video(img_files, video_path, resize_image)
%SHOW_VIDEO
%   Visualizes a tracker in an interactive figure, given a cell array of
%   image file names, their path, and whether to resize the images to
%   half size or not.
%
%   This function returns an UPDATE_VISUALIZATION function handle, that
%   can be called with a frame number and a bounding box [x, y, width,
%   height], as soon as the results for a new frame have been calculated.
%   This way, your results are shown in real-time, but they are also
%   remembered so you can navigate and inspect the video afterwards.
%   Press 'Esc' to send a stop signal (returned by UPDATE_VISUALIZATION).
%
%   Joao F. Henriques, 2014
%   http://www.isr.uc.pt/~henriques/

	%store one instance per frame
	num_frames = numel(img_files);
	boxes = cell(num_frames,1);

	%create window
	[fig_h, axes_h, unused, scroll] = videofig(num_frames, @redraw, [], [], @on_key_press);  %#ok, unused outputs
	set(fig_h, 'Number','off', 'Name', ['Tracker - ' video_path])
	axis off;

	%image and rectangle handles start empty, they are initialized later
	im_h = [];
	rect_h = [];

	update_visualization_func = @update_visualization;
	stop_tracker = false;

	function stop = update_visualization(frame, box)
		%store the tracker instance for one frame, and show it. returns
		%true if processing should stop (user pressed 'Esc').
		boxes{frame} = box;
		scroll(frame);
		stop = stop_tracker;
	end

	function redraw(frame)
		%render main image
		im = imread([video_path img_files{frame}]);
		if size(im,3) > 1,
			im = rgb2gray(im);
		end
		if resize_image,
			im = imresize(im, 0.5);
		end

		if isempty(im_h),  %create image
			im_h = imshow(im, 'Border','tight', 'InitialMag',200, 'Parent',axes_h);
		else  %just update it
			set(im_h, 'CData', im)
		end

		%render target bounding box for this frame
		if isempty(rect_h),  %create it for the first time
			rect_h = rectangle('Position',[0,0,1,1], 'EdgeColor','g', 'Parent',axes_h);
		end
		if ~isempty(boxes{frame}),
			set(rect_h, 'Visible', 'on', 'Position', boxes{frame});
		else
			set(rect_h, 'Visible', 'off');
		end
	end

	function on_key_press(key)
		if strcmp(key, 'escape'),  %stop on 'Esc'
			stop_tracker = true;
		end
	end

end


function get_basemap_parts(resolution)
    % load lake and boundaries
    % resolution is integer from 1 to 5, with 5 being full resolution
    %
    % data from:
    %  https://www.ngdc.noaa.gov/mgg/shorelines/
    %  http://www.soest.hawaii.edu/pwessel/gshhg/index.html
    %
    % this routine expectes them to be in shapefile format
    %
    % GSHHG "Early processing and assmbly of the shoreline data" processing details:
    % Wessel, P., and W. H. F. Smith, A Global Self-consistent, Hierarchical, High-resolution Shoreline Database, J. Geophys. Res., 101, 8741-8743, 1996i
    switch resolution
        case 5
            resolution='f'; % "full"
        case 4
            resolution='h'; % "high"
        case 3
            resolution='i'; % "intermediate"
        case 2
            resolution='l'; % "low"
        otherwise
            resolution='c'; % "crude"
    end

    %% define the map features
    % each MapFeature is something that can be overlain on the main map
    %
    disp('MainInteractiveMap construction');
    obj.Features = MapFeature('coast', @load_coast_and_borders, [],...
        struct('Tag','mainmap_coastline',...
        'DisplayName', 'Coastline/Borders',...
        'HitTest','off','PickableParts','none',...
        'LineWidth',1.0,...
        'Color',[0.1 0.1 0.1])...
        );

    obj.Features(2) = MapFeature('volcanoes', @load_volcanoes, [],...
        struct('Tag','mainmap_volcanoes',...
        'Marker','^',...
        'DisplayName','Volcanoes',...
        'LineWidth', 1.5,...
        'MarkerSize', 6,...
        'LineStyle','none',...
        'MarkerFaceColor','w',...
        'MarkerEdgeColor','r')...
        );

    obj.Features(3) = MapFeature('plates', @load_plates, [],...
        struct('Tag','mainmap_plates',...
        'DisplayName','plate boundaries',...
        'LineWidth', 3.0,...
        'Color',[.2 .2 .5])...
        );

    obj.Features(4) = MapFeature('faults', @load_faults, [],...
        struct('Tag','mainmap_faultlines',...
        'DisplayName','main faultine',...
        'LineWidth', 3.0,...
        'Color','b')...
        );
    %{
            obj.Features(5) = MapFeature('wells', @load_wells, [],...
                struct('Tag','mainmap_wells',...
                    'DisplayName','Wells',...
                    'Marker','d',...
                    'LineWidth',1.5,...
                    'MarkerSize',6,...
                    'LineStyle','none',...
                    'MarkerFaceColor','k',...
                    'MarkerEdgeColor','k')...
                );
            obj.Features(6) = MapFeature('minor_faults', @load_minorfaults, [],...
                struct('Tag','mainmap_faults',...
                    'DisplayName','faults',...
                    'LineWidth',0.2,...
                    'Color','k')...
                );

        %}
        figure;
        %TODO: have this on
        base='/Users/reyesc/Downloads/gshhg-shp-2';
        load_rivers(base,resolution);
        load_lakes(base,resolution);
        %load_boundaries(base,resolution);
        load_faults();
        load_continents(base, resolution);
        load_borders(base, resolution);
        load_plates();
end

function load_borders(base, resolution)
    ZG = ZmapGlobal.Data;
    % load National boundaries
    fn=fullfile(base,'WDBII_shp',resolution,['WDBII_border_' resolution '_L1']);
    S=shaperead(fn,'UseGeoCoords',true);
    ZG.borders=S;
end

function load_continents(base, resolution)
    ZG = ZmapGlobal.Data;
    % load continent boundaries (no antarctica)
    fn=fullfile(base,'GSHHS_shp',resolution,['GSHHS_' resolution '_L1']);
    S=shaperead(fn,'UseGeoCoords',true);
    ZG.coastline=S;
end

function load_faults()
    ZG = ZmapGlobal.Data;
    % load Fault traces
    % from SHARE The European Database of Seismogenic Faults:
    % http://diss.rm.ingv.it/share-edsf/SHARE_WP3.2_Downloads.html
    fn='/Users/reyesc/Downloads/DB-CFS-ESRI-shapefile/Crustal_fault_sources_TOP';
    S=shaperead(fn,'UseGeoCoords',true);
    ZG.faults=S;
end

function load_lakes(base, resolution)
    ZG = ZmapGlobal.Data;
    % load lake boundaries
    fn=fullfile(base,'GSHHS_shp',resolution,['GSHHS_' resolution '_L2']);
    S=shaperead(fn,'UseGeoCoords',true);
    ZG.lakes=S;
end

function load_rivers(base, resolution)
    ZG = ZmapGlobal.Data;
    % load river-lake boundaries
    fn=fullfile(base,'WDBII_shp',resolution,['WDBII_river_' resolution '_L01']);
    S=shaperead(fn,'UseGeoCoords',true);

    % load perm. major river boundaries
    fn=fullfile(base,'WDBII_shp',resolution,['WDBII_river_' resolution '_L02']);
    S=[S ; shaperead(fn,'UseGeoCoords',true)];

    % load addl. major rivers
    fn=fullfile(base,'WDBII_shp',resolution,['WDBII_river_' resolution '_L03']);
    S=[S ; shaperead(fn,'UseGeoCoords',true)];

    % load addl. rivers
    fn=fullfile(base,'WDBII_shp',resolution,['WDBII_river_' resolution '_L04']);
    S=[S ; shaperead(fn,'UseGeoCoords',true)];
    ZG.rivers=S;
end

function load_plates()
    ZG=ZmapGlobal.Data;
    tmp=load('resources/plates.mat','data','metadata');
    disp('Plate Boundary Metadata:');
    disp(tmp.metadata)
    ZG.plates=tmp.data;
end


function obj3 = binaryopp(f, obj1, obj2)

    if isa(obj2, 'mmo'), tmpobj = obj2; obj2 = obj1; obj1 = tmpobj; clear tmpobj; end
    if ~isequal(size(obj1), size(obj2)) && prod(size(obj2)) ~= 1
        error('Matrix dimensions must agree.');
    end
    data1 = memmapfile(obj1.dataFile, 'writable', obj1.writable, 'format', { 'single' obj1.dimensions 'x' });
    if isa(obj2, 'mmo'),
         data2 = memmapfile(obj2.dataFile, 'writable', obj2.writable, 'format', { 'single' obj2.dimensions 'x' });
    else data2 = obj2;
    end

    % make new memory mapped data file (blank)
    % --------------------------------
    newFileName = mmo.getnewfilename;
    fid = fopen(newFileName, 'w');
    s1  = size(obj1);
    ss.type = '()';
    ss.subs(1:length(s1)-1) = { ':' };
    for index = 1:s1(end)
        ss.subs{length(s1)} = index;
        if prod(size(data2)) == 1
             tmpdata = f(subsref(data1.Data.x, ss), data2);
        else tmpdata = f(subsref(data1.Data.x, ss), subsref(data2.Data.x, ss));
        end
        fwrite(fid, tmpdata, 'float');
    end
    fclose(fid);

    % create object
    % -------------
    obj3 = mmo(newFileName, s1, true, obj1.transposed);
    obj3 = updateWorkspace(obj3);


classdef Logger < handle
% A class that writes messages to log files (and/or standard out).
% To use the class, put the following two lines in your script:
%   global logger
%   logger = Logger();
% and then add and remove logfiles as required e.g.
%   logger.add_stdout(logger.All);
%   logger.add_filename('errorfile.txt',logger.Error);
%   logger.log(logger.All,'1 + 2 = %d\n',3);
%   logger.log(logger.Error,'An error occurred.\n');
%   logger.rm_filename('errorfile.txt');
%   fid = fopen('warningfile.txt','w');
%   logger.add_fid(fid);
%   logger.log(logger.Warning,'This is a warning.\n');
%   logger.clear()
%   fclose(fid);

properties (Access=private)
  fidlist = []
  fidlevels = [];
  filenamelist = {}
  filenamefids = []
  filenamelevels = []
end

properties (Access=public,Constant=true)
  None = 0
  Major_Error = 1
  Error = 2
  Warning = 4
  Minor_Warning = 8
  Info = 16
  Minor_Info = 32
  Debug_1 = 64
  Debug_2 = 128
  All = 255;
end

methods (Access=public)
  log(logger,level,message,varargin)
  add_fid(logger,fid,level)
  rm_fid(logger,fid)
  clear(logger)
  add_filename(logger,fname,level)
  rm_filename(logger,fname)
  add_stdout(logger,level)
  rm_stdout(logger)
  add_stderr(logger,level)
  rm_stderr(logger)
end

end


function title = p02_title ( )

%*****************************************************************************80
%
%% P02_TITLE returns the title of problem p02.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 August 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, the title of the problem.
%
  title = 'Product Peak';

  return
end


%% IMAGE_SCRIPT is a script to call IMAGE_FUN.
%
%  Discussion:
%
%    The BATCH command runs scripts, not functions.  So we have to write
%    this short script if we want to work with BATCH!
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 March 2010
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'IMAGE_SCRIPT\n' );
  fprintf ( 1, '  Filter an image using 3 workers\n' );

  [ x, y, z ] = image_fun ( );


function new_name = fixIndex(name,destination_folderpath)
    index = 1;
    list = updateList(destination_folderpath);

    try_name = assembleName(name,index);

    for i = 1:length(list)
        if strcmpi(try_name,list(i).name)
            index = index + 1;
            try_name = assembleName(name,index);
        end
    end
    new_name = try_name;
end

function new_name = assembleName(name,index)
    us = strfind(name,'_');
    dots = strfind(name,'.');
    name(us(end)+1:dots(end)-1)=[];
    new_name = [name(1:us(end)), num2str(index), name(us(end)+1:end)];
end


function net = concat_2net(net1,net2)
net1 = net1.saveobj();
net2 = net2.saveobj();
net.vars = [net1.vars,net2.vars];
net.layers = [net1.layers,net2.layers];
net.params = [net1.params,net2.params];
net.meta = net1.meta;
net = dagnn.DagNN.loadobj(net);
end


function reset_mem()
    global mem config;
    mem.layer_inputs = {};
    mem.activations = {};
    mem.orig_activation_size = {};
    mem.mask_inputs = {};
    mem.mask_activations = {};
    mem.mask_intermediate = {};
    mem.deltas = {};
    mem.conv2conv = {};
    mem.pool2conv = {};
    mem.gen_out_matrix = {};
    mem.convBpool = {};
    mem.convBconv = {};
    mem.pooling_matrix ={};
    mem.output = 0;
    mem.one_over_add_counts = 0;
    mem.grads = {};
    if strcmp(config.forward_pass_scheme{1}, 'conv_v_sr')
        % for SR only
        mem.grads{1} = {};
    end
end


function runAllTests(varargin)
%RUNALLTESTS  Explore all subdirectories, and run 'runtests' function
%
%   output = runAllTests(input)
%
%   Example
%   runAllTests
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-07-20,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% Add matGeom to path
addpath(genpath(strrep(mfilename('fullpath'),['tests' filesep mfilename],'matGeom')))

directories = {...
    'geom2d', ...
    'polygons2d', ...
    'graphs', ...
    'geom3d', ...
    'meshes3d', ...
    };

for i = 1:length(directories)
    name = directories{i};
    disp(['Running tests for directory: ' name]);

    cd(name);
    runtests;
    cd('..');
end


function test_bug3297

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY

filename = dccnpath('/home/common/matlab/fieldtrip/data/test/bug3297/testMEG001_1200hz_20170517_05.ds');

event = ft_read_event(filename);

% it only returned 3 'trial' events upon reading with the verion up to 22 May 2017
% after inlcuding type 20 as trigger, it returned 11 events
assert(numel(event)>3, 'incorrect number of events read from file');

% I looked it up in "CTF MEG(TM) File Formats" pdf, Release 5.2.1
%
% eMEGReference     0 Reference magnetometer channel
% eMEGReference1    1 Reference 1st-order gradiometer channel
% eMEGReference2    2 Reference 2nd-order gradiometer channel
% eMEGReference3    3 Reference 3rd-order gradiometer channel
% eMEGSensor        4 Sensor magnetometer channel located in head shell
% eMEGSensor1       5 Sensor 1st-order gradiometer channel located in head shell
% eMEGSensor2       6 Sensor 2nd-order gradiometer channel located in head shell
% eMEGSensor3       7 Sensor 3rd-order gradiometer channel located in head shell
% eEEGRef           8 EEG unipolar sensors not on the scalp
% eEEGSensor        9 EEG unipolar sensors on the scalp
% eADCRef           10 (see eADCAmpRef below)
% eADCAmpRef        10 ADC amp channels from HLU or PIU (old electronics)
% eStimRef          11 Stimulus channel for MEG41
% eTimeRef          12 Time reference coming from video channel
% ePositionRef      13 Not used
% eDACRef           14 DAC channel from ECC or HLU
% eSAMSensor        15 SAM channel derived through data analysis
% eVirtualSensor    16 Virtual channel derived by combining two or more physical channels
% eSystemTimeRef    17 System time showing elapsed time since trial started
% eADCVoltRef       18 ADC volt channels from ECC
% eStimAnalog       19 Analog trigger channels
% eStimDigital      20 Digital trigger channels
% eEEGBipolar       21 EEG bipolar sensor not on the scalp
% eEEGAflg          22 EEG ADC over range flags
% eMEGReset         23 MEG resets (counts sensor jumps for crosstalk pur- poses)
% eDipSrc           24 Dipole source
% eSAMSensorNorm    25 Normalized SAM channel derived through data analy- sis
% eAngleRef         26 Orientation of head localization field
% eExtractionRef    27 Extracted signal from each sensor of field generated by each localization coil
% eFitErr           28 Fit error from each head localization coil
% eOtherRef         29 Any other type of sensor not mentioned but still valid
% eInvalidType      30 An invalid sensor


function test_issue1991

% WALLTIME 00:10:00
% MEM 2gb
% DEPENDENCY ft_read_mri ft_hastoolbox ft_filetype

[ft_ver, ft_path] = ft_version;

file0 = fullfile(ft_path, 'template', 'anatomy', 'single_subj_T1_1mm.nii');
file1 = dccnpath('/home/common/matlab/fieldtrip/data/test/original/jnifti/samples/colin27/colin27_zlib.jnii');
file2 = dccnpath('/home/common/matlab/fieldtrip/data/test/original/jnifti/samples/colin27/colin27_zlib.bnii');

%%

mri0 = ft_read_mri(file0);
mri1 = ft_read_mri(file1);
mri2 = ft_read_mri(file2);

%%

% do not compare the anatomy in the samples to the original, as that is obviously different
% it appears that the jnifti/samples represent a segmentation rather than the original MRI
fn = {'dim', 'unit', 'transform'};

for i=1:length(fn)
  assert(isequal(mri0.(fn{i}), mri1.(fn{i})), ['difference in jnii field ' fn{i}]);
  assert(isequal(mri0.(fn{i}), mri2.(fn{i})), ['difference in bnii field ' fn{i}]);
end

%%

assert(isequal(mri1.anatomy, mri2.anatomy), 'difference in anatomy')

%%

cfg = [];
figure; ft_sourceplot(cfg, mri0);
figure; ft_sourceplot(cfg, mri1);
figure; ft_sourceplot(cfg, mri2);


function [Rob,Sen,Raw,Lmk,Obs,Tim] = createSlamStructures(Robot,Sensor,Time,Opt)

% CREATESLAMSTRUCTURES  Initialize SLAM data structures from user data.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

global Map

% Create robots and controls
Rob = createRobots(Robot);

% Create sensors
[Sen,Raw] = createSensors(Sensor);

% Install sensors in robots
[Rob,Sen] = installSensors(Rob,Sen);

% Create Landmarks and non-observables
Lmk = createLandmarks(Opt);

% Create Map - empty
Map = createMap(Rob,Sen,Opt);

% Initialize robots and sensors in Map
Rob = initRobots(Rob);
Sen = initSensors(Sen);

% Create Observations (matrix: [ line=sensor , colums=landmark ])
Obs = createObservations(Sen,Opt);

% Create time variables
Tim = createTime(Time);

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function [VMH2IDmappingAll,VMH2IDmappingPresent,VMH2IDmappingMissing]=getIDfromMetStructure(metabolite_structure,idName)

% INPUT
% metabolite_structure      Structure containg metabolite related informations
% and ID's
% idName                    Name of the ID as used in the metabolite structure
%                           to be retrieved (e.g., 'pubChemId')
%
% OUTPUT
% VMH2IDmappingAll          Mapping of all VMH metabolites present in the
%                           metabolite structure (including NaNs)
% VMH2IDmappingPresent      Mapping of all VMH metabolites present in the
%                           metabolite structure (excluding NaNs)
% VMH2IDmappingMissing      Abbreviations of metabolites that are NaN's in the
%                           metabolite structure
%
% IT, Aug 2020

Mets = fieldnames(metabolite_structure);
a = 1;
b = 1;
c = 1;
VMH2IDmappingAll = '';
VMH2IDmappingPresent = '';
VMH2IDmappingMissing = '';
for i = 1 : length(Mets)
    if length(find(isnan(metabolite_structure.(Mets{i}).(idName)))) == 0
        VMH2IDmappingPresent{b,1} =Mets{i};
        if isstr(metabolite_structure.(Mets{i}).(idName))
            id = (metabolite_structure.(Mets{i}).(idName));
        else
            id = num2str(metabolite_structure.(Mets{i}).(idName));
        end
        VMH2IDmappingPresent{b,2} = id;
        VMH2IDmappingPresent{b,3} = metabolite_structure.(Mets{i}).VMHId;
        if isfield(metabolite_structure.(Mets{i}),'metNames')
            VMH2IDmappingPresent{b,4} = metabolite_structure.(Mets{i}).metNames;
        else
            VMH2IDmappingPresent{b,4} = metabolite_structure.(Mets{i}).rxnNames;
        end
        b = b + 1;
    elseif isnan(metabolite_structure.(Mets{i}).(idName))
        VMH2IDmappingMissing{c,1} =Mets{i};
        c = c + 1;
    end

    VMH2IDmappingAll{a,1} =Mets{i};
    if isstr(metabolite_structure.(Mets{i}).(idName))
        id = (metabolite_structure.(Mets{i}).(idName));
    else
        id = num2str(metabolite_structure.(Mets{i}).(idName));
    end
    VMH2IDmappingAll{a,2} = id;
    a = a + 1;
end


function[DepMat RgbMat] = Kinect()
%---------------------------------------------------------------
% This function retrive Dep and Rgb color matries from mex code
% And return as DepMat RgbMat, respectly, after reshape them.
%---------------------------------------------------------------
[a b] = getimagedata(2);
DepMat = reshape(a,640,480)';
temp = (reshape(b(1:3:end),640,480))';
RgbMat(:,:,1) = temp(:,end:-1:1);
temp = (reshape(b(2:3:end),640,480))';
RgbMat(:,:,2) = temp(:,end:-1:1);
temp = (reshape(b(3:3:end),640,480))';
RgbMat(:,:,3) = temp(:,end:-1:1);
end


function B = horzcat(varargin)
%HORZCAT   Horizontally concatenate LINOP objects.

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

% Cast the result as a linop if there are any linop arguments.
B = linop( horzcat@chebmatrix(varargin{:}) );

end


classdef PTKSaveAirwayMesh < PTKPlugin
    % PTKSaveAirwayMesh. Plugin for saving an STL file containing the surface
    %     mesh of the airways, pruned to the segmental level
    %
    %     This is a plugin for the Pulmonary Toolkit. Plugins can be run using
    %     the gui, or through the interfaces provided by the Pulmonary Toolkit.
    %     See PTKPlugin.m for more information on how to run plugins.
    %
    %     Plugins should not be run directly from your code.
    %
    %
    %
    %     Licence
    %     -------
    %     Part of the TD Pulmonary Toolkit. https://github.com/tomdoel/pulmonarytoolkit
    %     Author: Tom Doel, 2013.  www.tomdoel.com
    %     Distributed under the GNU GPL v3 licence. Please see website for details.
    %

    properties
        ButtonText = 'Save airway<br>mesh'
        ToolTip = 'Segments the airway lumen down to the segmental bronchi, and then creates and saves an STL mesh of the lumen surface'
        Category = 'Airways'

        AllowResultsToBeCached = true
        AlwaysRunPlugin = true
        PluginType = 'ReplaceOverlay'
        HidePluginInDisplay = false
        FlattenPreviewImage = true
        PTKVersion = '1'
        ButtonWidth = 6
        ButtonHeight = 2
        GeneratePreview = false
    end

    methods (Static)
        function results = RunPlugin(dataset, reporting)
            airways_by_segment_pruned = dataset.GetResult('PTKAirwaysPrunedBySegment');
            results = airways_by_segment_pruned.PrunedSegmentsByLobeImage;
            results.ChangeRawImage(results.RawImage > 0);

            smoothing_size = 1;
            filename = 'PrunedAirwaysSurfaceMesh.stl';
            results_upsampled = results.Copy;
            results_upsampled.AddBorder(6);
            results_upsampled.DownsampleImage(0.25);

            % Specifies the coordinate system to use when saving out files
            coordinate_system = MimCoordinateSystem.DicomUntranslated;

            template_image = results;

            small_structures = true;
            dataset.SaveSurfaceMesh('PTKSaveAirwayMesh', 'Airway mesh', filename, 'Surface mesh of the segmented airways down to the level of the pulmonary segments' , results, smoothing_size, small_structures, coordinate_system, template_image);
        end

        function results = GenerateImageFromResults(results, image_templates, reporting)
        end
    end
end


% The COBRAToolbox: testConnectedComponents.m
%
% Purpose:
%     - tests the Connected Components functionality using a toy model
%
%
% Authors:
%     - Thomas Pfau

%% The model created looks as follows:
%
%
%   <-> A -> B -> C <->
%
%
%              -> F -
%             /      \
%   <-> D -> E -> G ---> H <->
%            ^
%            |
%            v
%
% And should yield 2 connected components, along with a bunch of exchangers
% which are ignored.

currentDir = pwd;
testdir = fileparts(which('testConnectedComponents.m'));
cd(testdir)

requiredToolboxes = {'image_toolbox'};

prepareTest('toolboxes',requiredToolboxes);

model = createToyModelForConnectedComponentAnalysis();
[groups,orphans,R,C] = connectedComponents(model);

%The orphan reactions, are the exchangers, which by definition are dropped
%from the connected components.Those are the last 5 reactions)
assert(isequal(orphans,numel(model.rxns)-4:numel(model.rxns)));

assert(isequal(model.rxns(1:2),model.rxns(groups(1).elements)));
assert(isequal(model.rxns(3:6),model.rxns(groups(2).elements)));

[groups,orphans] = connectedComponents(model,'largestComponent',0,1);

assert(isequal(numel(groups),1));
assert(isequal(model.rxns(3:6),model.rxns(groups.elements)));

delete('reactionsNotConnectedByAnything.txt');
delete('reactionAdjacencyOtherThanCofactors.txt')

cd(currentDir)


classdef CarlaEnvironment < matlab.System & matlab.system.mixin.Propagates
    % Untitled Add summary here
    %
    % This template includes the minimum set of functions required
    % to define a System object with discrete state.

    % Public, tunable properties
    properties

    end

    properties(DiscreteState)

    end

    % Pre-computed constants
    properties(Access = private)
        car;
    end

    methods(Access = protected)
        function setupImpl(obj)
            % Perform one-time calculations, such as computing constants
            port = int16(2000);
            client = py.carla.Client('localhost', port);
            client.set_timeout(10.0);
            world = client.get_world();

            % Spawn Vehicle
            blueprint_library = world.get_blueprint_library();
            car_list = py.list(blueprint_library.filter("model3"));
            car_bp = car_list{1};
            spawn_point = py.random.choice(world.get_map().get_spawn_points());
            obj.car = world.spawn_actor(car_bp, spawn_point);
            obj.car.set_autopilot(true);

        end

        function [x_position, x_velocity] = stepImpl(obj)
            %
            pause(0.001);
            x_position = obj.car.get_location().x;
            x_velocity = obj.car.get_velocity().x;
        end

        function [distance, velocity] = isOutputComplexImpl(~)
            distance = false;
            velocity = false;
        end

        function [distance, velocity] = getOutputSizeImpl(~)
            distance = [1 1];
            velocity = [1 1];
        end

        function [distance, velocity] = getOutputDataTypeImpl(~)
            distance = 'double';
            velocity = 'double';
        end

        function [distance, velocity] = isOutputFixedSizeImpl(~)
            distance = true;
            velocity = true;
        end

        function resetImpl(~)
            % Initialize / reset discrete-state properties
        end
    end

    methods(Access= public)
        function delete(obj)
            % Delete the car from the Carla world
            if ~isempty(obj.car)
                obj.car.destroy();
            end
        end
    end
end


%% Classify Text Data Using BERT
% This example shows how to classify text data using a pretrained BERT
% model as a feature extractor.
%
% The simplest use of a pretrained BERT model is to use it as a feature
% extractor. In particular, you can use the BERT model to convert documents
% to feature vectors which you can then use as input to train a deep
% learning classification network.
%
% This example shows how to use a pretrained BERT model to classify failure
% events given a data set of factory reports.

%% Load Pretrained BERT Model
% Load a pretrained BERT model using the |bert| function. The model
% consists of a tokenizer that encodes text as sequences of integers, and
% a structure of parameters.
mdl = bert

%%
% View the BERT model tokenizer. The tokenizer encodes text as sequences of
% integers and holds the details of padding, start, separator and mask
% tokens.
tokenizer = mdl.Tokenizer

%% Load Data
% Load the example data. The file |factoryReports.csv| contains factory
% reports, including a text description and categorical labels for each
% event.

filename = "factoryReports.csv";
data = readtable(filename,"TextType","string");
head(data)

%%
% The goal of this example is to classify events by the label in the
% |Category| column. To divide the data into classes, convert these labels
% to categorical.
data.Category = categorical(data.Category);

%%
% View the number of classes.
classes = categories(data.Category);
numClasses = numel(classes)

%%
% View the distribution of the classes in the data using a histogram.
figure
histogram(data.Category);
xlabel("Class")
ylabel("Frequency")
title("Class Distribution")

%%
% Encode the text data using the BERT model tokenizer using the |encode|
% function and add the tokens to the training data table.
data.Tokens = encode(tokenizer, data.Description);

%%
% The next step is to partition it into sets for training and validation.
% Partition the data into a training partition and a held-out partition for
% validation and testing. Specify the holdout percentage to be 20%.
cvp = cvpartition(data.Category,"Holdout",0.2);
dataTrain = data(training(cvp),:);
dataValidation = data(test(cvp),:);

%%
% View the number of training and validation observations.
numObservationsTrain = size(dataTrain,1)
numObservationsValidation = size(dataValidation,1)

%%
% Extract the text data, labels, and encoded BERT tokens from the
% partitioned tables.
textDataTrain = dataTrain.Description;
textDataValidation = dataValidation.Description;

TTrain = dataTrain.Category;
TValidation = dataValidation.Category;

tokensTrain = dataTrain.Tokens;
tokensValidation = dataValidation.Tokens;

%%
% To check that you have imported the data correctly, visualize the
% training text data using a word cloud.

figure
wordcloud(textDataTrain);
title("Training Data")

%%
% View the BERT token codes of the first few training documents.
tokensTrain{1:5}

%% Prepare Data for Training
% Convert the documents to feature vectors using the BERT model as a
% feature extractor.

% To extract the features of the training data by iterating over
% mini-batches, create a |minibatchqueue| object.

% Mini-batch queues require a single datastore that outputs both the
% predictors and responses. Create array datastores containing the training
% BERT tokens and labels and combine them using the |combine| function.
dsXTrain = arrayDatastore(tokensTrain,"OutputType","same");
dsTTrain = arrayDatastore(TTrain);
cdsTrain = combine(dsXTrain,dsTTrain);

% Create a combined datastore for the validation data using the same steps.
dsXValidation = arrayDatastore(tokensValidation,"OutputType","same");
dsTValidation = arrayDatastore(TValidation);
cdsValidation = combine(dsXValidation,dsTValidation);

%%
% Create a mini-batch queue for the training data. Specify a mini-batch
% size of 32 and preprocess the mini-batches using the
% |preprocessPredictors| function, listed at the end of the example.
miniBatchSize = 32;
paddingValue = mdl.Tokenizer.PaddingCode;
maxSequenceLength = mdl.Parameters.Hyperparameters.NumContext;

mbqTrain = minibatchqueue(cdsTrain,1,...
    "MiniBatchSize",miniBatchSize, ...
    "MiniBatchFcn",@(X) preprocessPredictors(X,paddingValue,maxSequenceLength));

%%%
% Create a mini-batch queue for the validation data using the same steps.
mbqValidation = minibatchqueue(cdsValidation,1,...
    "MiniBatchSize",miniBatchSize, ...
    "MiniBatchFcn",@(X) preprocessPredictors(X,paddingValue,maxSequenceLength));

%%
% To speed up feature extraction. Convert the BERT model weights to
% gpuArray if a GPU is available.
if canUseGPU
    mdl.Parameters.Weights = dlupdate(@gpuArray,mdl.Parameters.Weights);
end

%%
% Convert the training sequences of BERT model tokens to a
% |N|-by-|embeddingDimension| array of feature vectors, where |N| is the
% number of training observations and |embeddingDimension| is the dimension
% of the BERT embedding.

featuresTrain = [];
reset(mbqTrain);
while hasdata(mbqTrain)
    X = next(mbqTrain);
    features = bertEmbed(X,mdl.Parameters);
    featuresTrain = [featuresTrain gather(extractdata(features))];
end

%%
% Transpose the training data to have size |N|-by-|embeddingDimension|.
featuresTrain = featuresTrain.';

%%
% Convert the validation data to feature vectors using the same steps.
featuresValidation = [];

reset(mbqValidation);
while hasdata(mbqValidation)
    X = next(mbqValidation);
    features = bertEmbed(X,mdl.Parameters);
    featuresValidation = cat(2,featuresValidation,gather(extractdata(features)));
end
featuresValidation = featuresValidation.';

%% Define Deep Learning Network
% Define a deep learning network that classifies the feature vectors.

numFeatures = mdl.Parameters.Hyperparameters.HiddenSize;
layers = [
    featureInputLayer(numFeatures)
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer];

%% Specify Training Options
% Specify the training options using the |trainingOptions| function.
% * Train with a mini-batch size of 64.
% * Shuffle the data every epoch.
% * Validate the network using the validation data.
% * Display the training progress in a plot and suppress the verbose
%   output.
opts = trainingOptions('adam',...
    "MiniBatchSize",64,...
    "ValidationData",{featuresValidation,dataValidation.Category},...
    "Shuffle","every-epoch", ...
    "Plots","training-progress", ...
    "Verbose",0);

%% Train Network
% Train the network using the |trainNetwork| function.
net = trainNetwork(featuresTrain,dataTrain.Category,layers,opts);

%% Test Network
% Make predictions using the validation data and display the results in a
% confusion matrix.
YPredValidation = classify(net,featuresValidation);

figure
confusionchart(TValidation,YPredValidation)

%%
% Calculate the validation accuracy.
accuracy = mean(dataValidation.Category == YPredValidation)

%% Predict Using New Data
% Classify the event type of three new reports. Create a string array
% containing the new reports.
reportsNew = [ ...
    "Coolant is pooling underneath sorter."
    "Sorter blows fuses at start up."
    "There are some very loud rattling sounds coming from the assembler."];

%%
% Tokenize the text data using the same steps as the training documents.
tokensNew = encode(tokenizer,reportsNew);

%%
% Pad the sequences of tokens to the same length using the |padsequences|
% function and pad using the tokenizer padding code.
XNew = padsequences(tokensNew,2,"PaddingValue",tokenizer.PaddingCode);

%%
% Classify the new sequences using the trained model.
featuresNew = bertEmbed(XNew,mdl.Parameters)';
featuresNew = gather(extractdata(featuresNew));
labelsNew = classify(net,featuresNew)

%% Supporting Functions

%%% Predictors Preprocessing Functions
% The |preprocessPredictors| function truncates the mini-batches to have
% the specified maximum sequence length, pads the sequences to have the
% same length. Use this preprocessing function to preprocess the predictors
% only.
function X = preprocessPredictors(X,paddingValue,maxSeqLen)

X = truncateSequences(X,maxSeqLen);
X = padsequences(X,2,"PaddingValue",paddingValue);

end

%%% BERT Embedding Function
% The |bertEmbed| function maps input data to embedding vectors and
% optionally applies dropout using the "DropoutProbability" name-value
% pair.
function Y = bertEmbed(X,parameters,args)

arguments
    X
    parameters
    args.DropoutProbability = 0
end

dropoutProbabilitiy = args.DropoutProbability;

Y = bert.model(X,parameters, ...
    "DropoutProb",dropoutProbabilitiy, ...
    "AttentionDropoutProb",dropoutProbabilitiy);

% To return single feature vectors, return the first element.
Y = Y(:,1,:);
Y = squeeze(Y);

end


function y = cvx_isaffine( x, full ) %#ok
if nargin == 2 && full,
	y = true( size( x ) );
else
    y = true;
end

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


classdef(Abstract) AbstractGradientCalculationMethod < matlab.mixin.SetGet
    %AbstractGradientCalculationMethod Summary of this class goes here
    %   Detailed explanation goes here

    methods
        tf = useBuiltInMethod(obj);

        tf = shouldComputeSparsity(obj)

        computeGradientSparsity(obj, fun, x0, fAtX0, useParallel)

        g = computeGrad(obj, fun, x0, fAtX0, useParallel);

        J = computeJacobian(obj, cFun, x0, cAtX0, useParallel);

        openOptionsDialog(obj)
    end
end


% load all images of uiuc
% takes about 2.5 Go of ram
all_img = retrieve_uiuc;

% display all images of class 1
imagesc(display_gscatt_all(all_img{1}));