function tokens = opt_getToken(string, delimiter)
% GET_TOKENS	To extract all tokens from a string even if a token is null.
%
% Description:	GET_TOKENS extract all tokens from a string even if one or
%		more tokens are null.  It is a replacement to iteratively calling the
%		builtin function 'strtok.m' because it did not output null tokens as
%		would be normally expected.  Note that if there are two adjacent
%		delimiters then an empty token would be output representing the token
%		that could have been present between the delimiters.
%
% Usage:	tokens = get_tokens(string, delimiter)
%
% Input:
%  string: a string from which to extract tokens.
%  delimiter:	a string containing one or more delimiters. The default
%    delimiters are whitespace characters (i.e. the ASCII codes for TAB,
%    LF, VT, FF, CR and space). Note that each delimiter is assumed to be
%    a single character; so if the delimiter string has three characters,
%    each of the three characters is considered a delimiter.
%
% Output:
%		tokens: An cell array of strings; the tokens retrieved from the input
%			character array.
%
% Example:
%
%		>> s = 'what a great , day';
%
%  Note that the variable 's' is a string that uses two delimiters, a space
%  and a comma.
%
%		>> get_tokens(s, ' ,')
%
%		ans =
%
%       'what'
%       'a'
%       'great'
%       ''
%       ''
%       'day'
%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Copyright 2007  Jeff Jackson (Ocean Sciences, DFO Canada)
%   Creation Date: Oct. 20, 2006
%   Last Updated:  Jan. 22, 2008
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Check the input arguments before continuing.

% Check to see if no input arguments were supplied.  If this is the case,
% stop execution and output an error message to the user.
if nargin == 0
  error('MATLAB:get_tokens:NrInputArguments', 'No input arguments were supplied. At least one is expected.');
% Check to see if the only input argument is a cell array.  If it isn't
% then stop execution and output an error message to the user. Also set the
% DIM value since it was not supplied.
elseif nargin == 1
	% Check to see if the input is a string.  Output a message if the input
	% value is a not a character array, then exit the function.
	if ~ischar(string)
		error('MATLAB:get_tokens:InvalidInputArgument', 'The input string must be a valid character array.');
	end
	% Set the default delimiter value to whitespace characters.
	delimiter = [9:13 32];
elseif nargin == 2
	% Check to see if the two input arguments are character strings.  If
	% either check fails then stop execution and output an error message to
	% the user.
	if ~ischar(string)
		error('MATLAB:get_tokens:InvalidInputArgument', 'The first input variable must be a valid character array.');
	end
	if ~ischar(delimiter)
		error('MATLAB:get_tokens:InvalidInputArgument', 'The second input variable must be a valid character array.');
	end
elseif nargin > 2
	% Check to see if too many arguments were input.  If there were then exit
	% the function issuing a error message to the user.
	error('MATLAB:get_tokens:TooManyInputArguments', 'Too many input arguments were supplied.  The maximum permitted is two.');
end

%% If the input arguments are valid continue processing.

% Get the sizes of the input parameters.
string_size = size(string);
delim_size = size(delimiter);

% Check to see if the character array is vertical instead of horizontal. If
% it is then change it. Do the opposite for the delimiter array.
if string_size(1) > 1
	s = string';
else
	s = string;
end
if delim_size(1) > 1
	d = delimiter;
else
	d = delimiter';
end

% Get the array sizes.
if isempty(d)
   error('MATLAB:get_tokens:InputArguments', 'Delimiter is invalid.');
end

% Surround the delimiter string with square brackets so the regexprep
% function works correctly.
delimiter2 = ['[' delimiter ']'];

% Change all delimiters to the character value of the number 1.
s2 = regexprep(s,delimiter2,char(1));

% Extract all tokens from this updated string.
tokens = strread(s2,'%s','delimiter',char(1));

% Check to see if the last character in the input string is a delimiter. If
% it was then add a cell with an empty string to the end of the tokens cell
% array.
if strcmp(s2(end), char(1)) == 1
	tokens(end+1,1) = {''};
end


function progressbar(varargin)
% Description:
%   progressbar() provides an indication of the progress of some task using
% graphics and text. Calling progressbar repeatedly will update the figure and
% automatically estimate the amount of time remaining.
%   This implementation of progressbar is intended to be extremely simple to use
% while providing a high quality user experience.
%
% Features:
%   - Can add progressbar to existing m-files with a single line of code.
%   - Supports multiple bars in one figure to show progress of nested loops.
%   - Optional labels on bars.
%   - Figure closes automatically when task is complete.
%   - Only one figure can exist so old figures don't clutter the desktop.
%   - Remaining time estimate is accurate even if the figure gets closed.
%   - Minimal execution time. Won't slow down code.
%   - Randomized color. When a programmer gets bored...
%
% Example Function Calls For Single Bar Usage:
%   progressbar               % Initialize/reset
%   progressbar(0)            % Initialize/reset
%   progressbar('Label')      % Initialize/reset and label the bar
%   progressbar(0.5)          % Update
%   progressbar(1)            % Close
%
% Example Function Calls For Multi Bar Usage:
%   progressbar(0, 0)         % Initialize/reset two bars
%   progressbar('A', '')      % Initialize/reset two bars with one label
%   progressbar('', 'B')      % Initialize/reset two bars with one label
%   progressbar('A', 'B')     % Initialize/reset two bars with two labels
%   progressbar(0.3)          % Update 1st bar
%   progressbar(0.3, [])      % Update 1st bar
%   progressbar([], 0.3)      % Update 2nd bar
%   progressbar(0.7, 0.9)     % Update both bars
%   progressbar(1)            % Close
%   progressbar(1, [])        % Close
%   progressbar(1, 0.4)       % Close
%
% Notes:
%   For best results, call progressbar with all zero (or all string) inputs
% before any processing. This sets the proper starting time reference to
% calculate time remaining.
%   Bar color is choosen randomly when the figure is created or reset. Clicking
% the bar will cause a random color change.
%
% Demos:
%     % Single bar
%     m = 500;
%     progressbar % Init single bar
%     for i = 1:m
%       pause(0.01) % Do something important
%       progressbar(i/m) % Update progress bar
%     end
%
%     % Simple multi bar (update one bar at a time)
%     m = 4;
%     n = 3;
%     p = 100;
%     progressbar(0,0,0) % Init 3 bars
%     for i = 1:m
%         progressbar([],0) % Reset 2nd bar
%         for j = 1:n
%             progressbar([],[],0) % Reset 3rd bar
%             for k = 1:p
%                 pause(0.01) % Do something important
%                 progressbar([],[],k/p) % Update 3rd bar
%             end
%             progressbar([],j/n) % Update 2nd bar
%         end
%         progressbar(i/m) % Update 1st bar
%     end
%
%     % Fancy multi bar (use labels and update all bars at once)
%     m = 4;
%     n = 3;
%     p = 100;
%     progressbar('Monte Carlo Trials','Simulation','Component') % Init 3 bars
%     for i = 1:m
%         for j = 1:n
%             for k = 1:p
%                 pause(0.01) % Do something important
%                 % Update all bars
%                 frac3 = k/p;
%                 frac2 = ((j-1) + frac3) / n;
%                 frac1 = ((i-1) + frac2) / m;
%                 progressbar(frac1, frac2, frac3)
%             end
%         end
%     end
%
% Author:
%   Steve Hoelzer
%
% Revisions:
% 2002-Feb-27   Created function
% 2002-Mar-19   Updated title text order
% 2002-Apr-11   Use floor instead of round for percentdone
% 2002-Jun-06   Updated for speed using patch (Thanks to waitbar.m)
% 2002-Jun-19   Choose random patch color when a new figure is created
% 2002-Jun-24   Click on bar or axes to choose new random color
% 2002-Jun-27   Calc time left, reset progress bar when fractiondone == 0
% 2002-Jun-28   Remove extraText var, add position var
% 2002-Jul-18   fractiondone input is optional
% 2002-Jul-19   Allow position to specify screen coordinates
% 2002-Jul-22   Clear vars used in color change callback routine
% 2002-Jul-29   Position input is always specified in pixels
% 2002-Sep-09   Change order of title bar text
% 2003-Jun-13   Change 'min' to 'm' because of built in function 'min'
% 2003-Sep-08   Use callback for changing color instead of string
% 2003-Sep-10   Use persistent vars for speed, modify titlebarstr
% 2003-Sep-25   Correct titlebarstr for 0% case
% 2003-Nov-25   Clear all persistent vars when percentdone = 100
% 2004-Jan-22   Cleaner reset process, don't create figure if percentdone = 100
% 2004-Jan-27   Handle incorrect position input
% 2004-Feb-16   Minimum time interval between updates
% 2004-Apr-01   Cleaner process of enforcing minimum time interval
% 2004-Oct-08   Seperate function for timeleftstr, expand to include days
% 2004-Oct-20   Efficient if-else structure for sec2timestr
% 2006-Sep-11   Width is a multiple of height (don't stretch on widescreens)
% 2010-Sep-21   Major overhaul to support multiple bars and add labels
%

persistent progfig progdata lastupdate

% Get inputs
if nargin > 0
    input = varargin;
    ninput = nargin;
else
    % If no inputs, init with a single bar
    input = {0};
    ninput = 1;
end

% If task completed, close figure and clear vars, then exit
if input{1} == 1
    if ishandle(progfig)
        delete(progfig) % Close progress bar
    end
    clear progfig progdata lastupdate % Clear persistent vars
    drawnow
    return
end

% Init reset flag
resetflag = false;

% Set reset flag if first input is a string
if ischar(input{1})
    resetflag = true;
end

% Set reset flag if all inputs are zero
if input{1} == 0
    % If the quick check above passes, need to check all inputs
    if all([input{:}] == 0) && (length([input{:}]) == ninput)
        resetflag = true;
    end
end

% Set reset flag if more inputs than bars
if ninput > length(progdata)
    resetflag = true;
end

% If reset needed, close figure and forget old data
if resetflag
    if ishandle(progfig)
        delete(progfig) % Close progress bar
    end
    progfig = [];
    progdata = []; % Forget obsolete data
end

% Create new progress bar if needed
if ishandle(progfig)
else % This strange if-else works when progfig is empty (~ishandle() does not)

    % Define figure size and axes padding for the single bar case
    height = 0.03;
    width = height * 8;
    hpad = 0.02;
    vpad = 0.25;

    % Figure out how many bars to draw
    nbars = max(ninput, length(progdata));

    % Adjust figure size and axes padding for number of bars
    heightfactor = (1 - vpad) * nbars + vpad;
    height = height * heightfactor;
    vpad = vpad / heightfactor;

    % Initialize progress bar figure
    left = (1 - width) / 2;
    bottom = (1 - height) / 2;
    progfig = figure(...
        'Units', 'normalized',...
        'Position', [left bottom width height],...
        'NumberTitle', 'off',...
        'Resize', 'off',...
        'MenuBar', 'none' );

    % Initialize axes, patch, and text for each bar
    left = hpad;
    width = 1 - 2*hpad;
    vpadtotal = vpad * (nbars + 1);
    height = (1 - vpadtotal) / nbars;
    for ndx = 1:nbars
        % Create axes, patch, and text
        bottom = vpad + (vpad + height) * (nbars - ndx);
        progdata(ndx).progaxes = axes( ...
            'Position', [left bottom width height], ...
            'XLim', [0 1], ...
            'YLim', [0 1], ...
            'Box', 'on', ...
            'ytick', [], ...
            'xtick', [] );
        progdata(ndx).progpatch = patch( ...
            'XData', [0 0 0 0], ...
            'YData', [0 0 1 1] );
        progdata(ndx).progtext = text(0.99, 0.5, '', ...
            'HorizontalAlignment', 'Right', ...
            'FontUnits', 'Normalized', ...
            'FontSize', 0.7 );
        progdata(ndx).proglabel = text(0.01, 0.5, '', ...
            'HorizontalAlignment', 'Left', ...
            'FontUnits', 'Normalized', ...
            'FontSize', 0.7 );
        if ischar(input{ndx})
            set(progdata(ndx).proglabel, 'String', input{ndx})
            input{ndx} = 0;
        end

        % Set callbacks to change color on mouse click
        set(progdata(ndx).progaxes, 'ButtonDownFcn', {@changecolor, progdata(ndx).progpatch})
        set(progdata(ndx).progpatch, 'ButtonDownFcn', {@changecolor, progdata(ndx).progpatch})
        set(progdata(ndx).progtext, 'ButtonDownFcn', {@changecolor, progdata(ndx).progpatch})
        set(progdata(ndx).proglabel, 'ButtonDownFcn', {@changecolor, progdata(ndx).progpatch})

        % Pick a random color for this patch
        changecolor([], [], progdata(ndx).progpatch)

        % Set starting time reference
        if ~isfield(progdata(ndx), 'starttime') || isempty(progdata(ndx).starttime)
            progdata(ndx).starttime = clock;
        end
    end

    % Set time of last update to ensure a redraw
    lastupdate = clock - 1;

end

% Process inputs and update state of progdata
for ndx = 1:ninput
    if ~isempty(input{ndx})
        progdata(ndx).fractiondone = input{ndx};
        progdata(ndx).clock = clock;
    end
end

% Enforce a minimum time interval between graphics updates
myclock = clock;
if abs(myclock(6) - lastupdate(6)) < 0.01 % Could use etime() but this is faster
    return
end

% Update progress patch
for ndx = 1:length(progdata)
    set(progdata(ndx).progpatch, 'XData', ...
        [0, progdata(ndx).fractiondone, progdata(ndx).fractiondone, 0])
end

% Update progress text if there is more than one bar
if length(progdata) > 1
    for ndx = 1:length(progdata)
        set(progdata(ndx).progtext, 'String', ...
            sprintf('%1d%%', floor(100*progdata(ndx).fractiondone)))
    end
end

% Update progress figure title bar
if progdata(1).fractiondone > 0
    runtime = etime(progdata(1).clock, progdata(1).starttime);
    timeleft = runtime / progdata(1).fractiondone - runtime;
    timeleftstr = sec2timestr(timeleft);
    titlebarstr = sprintf('%2d%%    %s remaining', ...
        floor(100*progdata(1).fractiondone), timeleftstr);
else
    titlebarstr = ' 0%';
end
set(progfig, 'Name', titlebarstr)

% Force redraw to show changes
drawnow

% Record time of this update
lastupdate = clock;

% ------------------------------------------------------------------------------
function changecolor(h, e, progpatch) %#ok<INUSL>
% Change the color of the progress bar patch

% Prevent color from being too dark or too light
colormin = 1.5;
colormax = 2.8;

thiscolor = rand(1, 3);
while (sum(thiscolor) < colormin) || (sum(thiscolor) > colormax)
    thiscolor = rand(1, 3);
end

set(progpatch, 'FaceColor', thiscolor)

% ------------------------------------------------------------------------------
function timestr = sec2timestr(sec)
% Convert a time measurement from seconds into a human readable string.

% Convert seconds to other units
w = floor(sec/604800); % Weeks
sec = sec - w*604800;
d = floor(sec/86400); % Days
sec = sec - d*86400;
h = floor(sec/3600); % Hours
sec = sec - h*3600;
m = floor(sec/60); % Minutes
sec = sec - m*60;
s = floor(sec); % Seconds

% Create time string
if w > 0
    if w > 9
        timestr = sprintf('%d week', w);
    else
        timestr = sprintf('%d week, %d day', w, d);
    end
elseif d > 0
    if d > 9
        timestr = sprintf('%d day', d);
    else
        timestr = sprintf('%d day, %d hr', d, h);
    end
elseif h > 0
    if h > 9
        timestr = sprintf('%d hr', h);
    else
        timestr = sprintf('%d hr, %d min', h, m);
    end
elseif m > 0
    if m > 9
        timestr = sprintf('%d min', m);
    else
        timestr = sprintf('%d min, %d sec', m, s);
    end
else
    timestr = sprintf('%d sec', s);
end


function varargout = process_headpoints_remove( varargin )
% PROCESS_HEADPOINTS_REMOVE: Remove head points from the channel file below a certain level.
% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2015-2018

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Remove head points';
    sProcess.Category    = 'Custom';
    sProcess.SubGroup    = {'Import', 'Channel file'};
    sProcess.Index       = 63;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/ChannelFile#Automatic_registration';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data', 'raw'};
    sProcess.OutputTypes = {'data', 'raw'};
    sProcess.nInputs     = 1;
    sProcess.nMinFiles   = 1;
    sProcess.isSeparator = 1;
    % Title
    sProcess.options.title.Comment = ['Remove the head points below a certain Z-thresold.
' ...
                                      ' - Z=0 : Nasion, left ear, right ear
 - Z>0 : Towards the top of the head
 - Z<0 : Towards the neck.

'];
    sProcess.options.title.Type    = 'label';
    % Options: tolerance
    sProcess.options.zlimit.Comment = 'Limit Z-coordinate: ';
    sProcess.options.zlimit.Type    = 'value';
    sProcess.options.zlimit.Value   = {0, 'mm', 0};
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    Comment = sProcess.Comment;
end

%% ===== RUN =====
function OutputFiles = Run(sProcess, sInputs) %#ok<DEFNU>
    % Get options
    zValue = sProcess.options.zlimit.Value{1} / 1000;
    % Get all the channel files
    uniqueChan = unique({sInputs.ChannelFile});
    % Loop on all the channel files
    for i = 1:length(uniqueChan)
        % Get first input file for this subject
        strMsg = RemoveHeadpoints(uniqueChan{i}, zValue);
        % Report message
        if ~isempty(strMsg)
            bst_report('Info', sProcess, sInputs, strMsg);
        end
    end
    % Return all the files in input
    OutputFiles = {sInputs.FileName};
end

%% ===== REMOVE HEAD POINTS =====
function strMsg = RemoveHeadpoints(ChannelFile, zLimit)
    % Parse inputs
    if (nargin < 2) || isempty(zLimit)
        zLimit = [];
    end
    % Load channel file
    ChannelMat = in_bst_channel(ChannelFile);
    % Display warning: no head points
    if ~isfield(ChannelMat, 'HeadPoints') || isempty(ChannelMat.HeadPoints) || isempty(ChannelMat.HeadPoints.Label)
        strMsg = 'No head points in the file.';
        return;
    end
    % Initial head points number
    nPoints = length(ChannelMat.HeadPoints.Label);
    % Remove selected head points
    if isempty(zLimit)
        ChannelMat.HeadPoints = [];
        iDelete = 1:nPoints;
    else
        % Get EXTRA points
        iExtra = find(strcmpi(ChannelMat.HeadPoints.Type, 'EXTRA'));
        % Find the points below the z-threshold
        iDelete = find(ChannelMat.HeadPoints.Loc(3,iExtra) <= zLimit);
        % Remove the points
        if (length(iDelete) == nPoints)
            ChannelMat.HeadPoints = [];
        elseif ~isempty(iDelete)
            ChannelMat.HeadPoints.Loc(:,iExtra(iDelete)) = [];
            ChannelMat.HeadPoints.Label(iExtra(iDelete)) = [];
            ChannelMat.HeadPoints.Type(iExtra(iDelete))  = [];
        end
    end
    % Message: head points removed
    strMsg = sprintf('%d head points removed, %d points left.', length(iDelete), nPoints - length(iDelete));
    % History: Reamove all head points
    ChannelMat = bst_history('add', ChannelMat, 'headpoints', strMsg);
    % Save file back
    bst_save(file_fullpath(ChannelFile), ChannelMat, 'v7');
end


function fakeaxislabels(real,disp,whichax,hax,formatstr)

if ~exist('whichax','var'),
  whichax = 'x';
end
if ~exist('hax','var') || isempty(hax),
  hax = gca;
end
if ~exist('formatstr','var'),
  formatstr = '%f';
end
if strcmpi(whichax,'y')
  tick = 'ytick';
  ticklabel = 'yticklabel';
else
  tick = 'xtick';
  ticklabel = 'xticklabel';
end

labels = cell(1,length(disp));
for i = 1:length(disp),
  labels{i} = sprintf(formatstr,disp(i));
end

set(hax,tick,real,ticklabel,labels);


function a = gt( x, y )

evalin( 'caller', 'cvx_verify' );
b = cvx_pushcnstr( x, y, '>' );
if nargout, a = b; 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.


function printPostSolver(fid, expInfo)
%PRINTPOSTSOLVER   Print commands after solution has been found
%
% Calling sequence:
%   PRINTPOSTSOLVER(FID, EXPINFO)
% where
%   FID:        ID of a file-writing stream.
%   EXPINFO:    Struct containing information for printing the problem.

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

% Extract info from the EXPINFO struct:
sol = expInfo.sol;
indVarName = expInfo.indVarName;
deInput = expInfo.deInput;
s = expInfo.s;

% Plotting. Deal with scalar and system problems separately.
if ( numel(deInput) == 1 )
    % Scalar problems.
    fprintf(fid, '\n%%%% Plot the solution.\n');
    fprintf(fid, 'waterfall(%s, %s)\n', sol, ...
        indVarName{2});
    fprintf(fid, 'xlabel(''%s''), ylabel(''%s'')', ...
        indVarName{1},indVarName{2});

else
    % Coupled systems.
    fprintf(fid, '\n%%%% Plot the solution components.');
    for k = 1:numel(deInput)
        fprintf(fid, '\nfigure\n');
        fprintf(fid, 'waterfall(%s, %s)\n', s{k}, indVarName{2});
        fprintf(fid, 'xlabel(''%s''), ylabel(''%s''), title(''%s'')', ...
            indVarName{1},indVarName{2},s{k});
    end

end

end


function [arrival,assoc,origin,W] = db_get_arrival_info(arid,dbname,varargin)
% [ARRIVAL, ASSOC, ORIGIN, W] = DB_GET_ARRIVAL_INFO(ARID_LIST, DATABASE_NAME) Returns pertinent
% fields from the arrival, assoc and origin tables based on input arrival id numbers (arid);
% ARRIVAL_LIST must be a vector of arrival id numbers (arid). The returned structures ARRIVAL contains
% fields pulled from each of the corresponding tables.
%
% Unlike db_get_origin_info, there is currently no method for entering arrivals by time.
% arid's must be used.

% Author: Michael West, Geophysical Institute, Univ. of Alaska Fairbanks
% $Date$
% $Revision$

if isnumeric(arid)
	arrival.arid = reshape( arid , numel(arid), 1 );
else
    error('First input must be either arrival ids (arid)');
end

% Check for waveform
if numel(varargin) == 1
	W = varargin{1};
	if ~isa(W,'waveform')
		error('Third argument must be a WAVEFORM object');
	end
elseif numel(varargin) > 1
	error('Too many arguments');
end

% GET ORIGIN TIME
db = dbopen(dbname,'r');
db = dblookup_table(db,'arrival');
nlist = [];
for n = 1:length(arrival.arid);
	db1 = dbsubset(db,['arid==' num2str(arrival.arid(n))]);
	db2 = dblookup_table(db,'assoc');
	db1 = dbjoin(db1,db2);
	db2 = dblookup_table(db,'origin');
	db1 = dbjoin(db1,db2);
	[ origin.lat(n),origin.lon(n),origin.depth(n),origin.time_epoch(n),origin.ml(n),origin.orid(n)] = dbgetv(db1,'origin.lat','origin.lon','origin.depth','origin.time','origin.ml','origin.orid');
	[ arrival.sta{n},arrival.chan{n}] = dbgetv(db1,'arrival.sta','arrival.chan');
	[ arrival.time(n),arrival.iphase(n),arrival.deltim(n)] = dbgetv(db1,'arrival.time','arrival.iphase','arrival.deltim');
    [ assoc.delta(n),assoc.seaz(n),assoc.esaz(n),assoc.timeres(n) ] = dbgetv(db1,'assoc.delta','assoc.seaz','assoc.esaz','assoc.timeres');
end
dbclose(db);
origin.lat = reshape( origin.lat , numel(origin.lat), 1 );
origin.lon = reshape( origin.lon , numel(origin.lon), 1 );
origin.depth = reshape( origin.depth , numel(origin.depth), 1 );
origin.time_epoch = reshape( origin.time_epoch , numel(origin.time_epoch), 1 );
origin.time_matlab = datenum(strtime(origin.time_epoch));
origin.ml = reshape( origin.ml , numel(origin.ml), 1 );
origin.orid = reshape( origin.orid , numel(origin.orid), 1 );
%
arrival.time_epoch = reshape( arrival.time , numel(arrival.time), 1 );
arrival.time_matlab =  datenum(strtime(arrival.time_epoch));
arrival.iphase = reshape( arrival.iphase , numel(arrival.iphase), 1 );
arrival.deltim = reshape( arrival.deltim , numel(arrival.deltim), 1 );
arrival.sta = reshape( arrival.sta , numel(arrival.sta), 1 );
arrival.chan = reshape( arrival.chan , numel(arrival.chan), 1 );

%
assoc.delta = reshape( assoc.delta , numel(assoc.delta), 1 );
assoc.seaz = reshape( assoc.seaz , numel(assoc.seaz), 1 );
assoc.esaz = reshape( assoc.esaz , numel(assoc.esaz), 1 );
assoc.timeres = reshape( assoc.timeres , numel(assoc.timeres), 1 );
assoc.traveltime = arrival.time_matlab - origin.time_matlab;

if exist('W')
	for n = 1:numel(W)
		disp([ 'Retreiving origin, arrival and assoc info for orid: ' num2str(origin.orid(n)) ' ... '])
		W(n) = addfield(W(n),'ORIGIN_LAT',origin.lat(n));
		W(n) = addfield(W(n),'ORIGIN_LON',origin.lon(n));
		W(n) = addfield(W(n),'ORIGIN_DEPTH',origin.depth(n));
		W(n) = addfield(W(n),'ORIGIN_TIME_EPOCH',origin.time_epoch(n));
		W(n) = addfield(W(n),'ORIGIN_ML',origin.ml(n));
		W(n) = addfield(W(n),'ORIGIN_TIME_MATLAB',origin.time_matlab(n));
		W(n) = addfield(W(n),'ORIGIN_ORID',origin.orid(n));
		%
		W(n) = addfield(W(n),'ARRIVAL_TIME_EPOCH',arrival.time_epoch(n));
		W(n) = addfield(W(n),'ARRIVAL_TIME_MATLAB',arrival.time_matlab(n));
		W(n) = addfield(W(n),'ARRIVAL_IPHASE',arrival.iphase(n));
		W(n) = addfield(W(n),'ARRIVAL_DELTIME',arrival.deltime(n));
		%
		W(n) = addfield(W(n),'ASSOC_DELTA',assoc.delta(n));
		W(n) = addfield(W(n),'ASSOC_SEAZ',assoc.seaz(n));
		W(n) = addfield(W(n),'ASSOC_ESAZ',assoc.esaz(n));
		W(n) = addfield(W(n),'ASSOC_TIMERES',assoc.timeres(n));
	end
end


%% AI Clinician Building MIMIC-III dataset

% (c) Matthieu Komorowski, Imperial College London 2015-2019
% as seen in publication: https://www.nature.com/articles/s41591-018-0213-5

% version 16 Feb 19
% uses the sepsis-3 cohort previously defined
% builds the MIMIC-III dataset

% This code 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

%% ########################################################################
%           INITIAL REFORMAT WITH CHARTEVENTS, LABS AND MECHVENT
% ########################################################################

% gives an array with all unique charttime (1 per row) and all items in columns.
% ################## IMPORTANT !!!!!!!!!!!!!!!!!!
% Here i use -24 -> +48 because that's for the MDP

reformat=NaN(2000000,68);  %final table
qstime=zeros(100000,4);
winb4=25;   %lower limit for inclusion of data (48h before time flag)
winaft=49;  % upper limit (24h after)
irow=1;  %recording row for summary table
h = waitbar(0,'Initializing waitbar...');

tic
for icustayidrow=1:size(sepsis,1)

qst=sepsis.sepsis_time(icustayidrow);%,3); %flag for presumed infection
icustayid=sepsis.icustayid(icustayidrow)-200000;
waitbar(icustayidrow/size(sepsis,1),h,icustayidrow/size(sepsis,1)*100) %moved here to save some time

% CHARTEVENTS
    if icustayid<10000
    temp=ce010(ce010(:,1)==icustayid+200000,:);
    elseif icustayid>=10000 & icustayid<20000
    temp=ce1020(ce1020(:,1)==icustayid+200000,:);
    elseif icustayid>=20000 & icustayid<30000
    temp=ce2030(ce2030(:,1)==icustayid+200000,:);
    elseif icustayid>=30000 && icustayid<40000
    temp=ce3040(ce3040(:,1)==icustayid+200000,:);
    elseif icustayid>=40000 & icustayid<50000
    temp=ce4050(ce4050(:,1)==icustayid+200000,:);
    elseif icustayid>=50000 & icustayid<60000
    temp=ce5060(ce5060(:,1)==icustayid+200000,:);
    elseif icustayid>=60000 & icustayid<70000
    temp=ce6070(ce6070(:,1)==icustayid+200000,:);
    elseif icustayid>=70000 & icustayid<80000
    temp=ce7080(ce7080(:,1)==icustayid+200000,:);
    elseif icustayid>=80000 & icustayid<90000
    temp=ce8090(ce8090(:,1)==icustayid+200000,:);
    elseif icustayid>=90000
    temp=ce90100(ce90100(:,1)==icustayid+200000,:);
    end

ii=temp(:,2)>= qst-(winb4+4)*3600 & temp(:,2)<=qst+(winaft+4)*3600; %time period of interest -4h and +4h
temp=temp(ii,:);   %only time period of interest

%LABEVENTS
ii=labU(:,1)==icustayid+200000;
temp2=labU(ii,:);
ii=temp2(:,2)>= qst-(winb4+4)*3600 & temp2(:,2)<=qst+(winaft+4)*3600; %time period of interest -4h and +4h
temp2=temp2(ii,:);   %only time period of interest

%Mech Vent + ?extubated
ii=MV(:,1)==icustayid+200000;
temp3=MV(ii,:);
ii=temp3(:,2)>= qst-(winb4+4)*3600 & temp3(:,2)<=qst+(winaft+4)*3600; %time period of interest -4h and +4h
temp3=temp3(ii,:);   %only time period of interest

t=unique([temp(:,2);temp2(:,2); temp3(:,2)]);   %list of unique timestamps from all 3 sources / sorted in ascending order

if t
for i=1:numel(t)

    %CHARTEVENTS
    ii=temp(:,2)==t(i);
    col=temp(ii,3);
    value=temp(ii,4);
    reformat(irow,1)=i; %timestep
    reformat(irow,2)=icustayid;
    reformat(irow,3)=t(i); %charttime
    reformat(irow,3+col)=value; %store available values

    %LAB VALUES
    ii=temp2(:,2)==t(i);
    col=temp2(ii,3);
    value=temp2(ii,4);
    reformat(irow,31+col)=value; %store available values

    %MV
    ii=temp3(:,2)==t(i);
    if nansum(ii)>0
    value=temp3(ii,3:4);
      reformat(irow,67:68)=value; %store available values
    else
      reformat(irow,67:68)=NaN;
    end

    irow=irow+1;

end

qstime(icustayid,1)=qst; %time of sepsis
%HERE I SAVE FIRST and LAST TIMESTAMPS, in QSTIME, for each ICUSTAYID
qstime(icustayid,2)=t(1);  %first timestamp
qstime(icustayid,3)=t(end);  %last timestamp
qstime(icustayid,4)=table2array(demog(demog.icustay_id==icustayid+200000,5)); % discharge time

end

% end
end
toc

close(h);
reformat(irow:end,:)=[];  %delete extra unused rows

%% ########################################################################
%                                   OUTLIERS
% ########################################################################

%weight
reformat=deloutabove(reformat,5,300);  %delete outlier above a threshold (300 kg), for variable # 5

%HR
reformat=deloutabove(reformat,8,250);

%BP
reformat=deloutabove(reformat,9,300);
reformat=deloutbelow(reformat,10,0);
reformat=deloutabove(reformat,10,200);
reformat=deloutbelow(reformat,11,0);
reformat=deloutabove(reformat,11,200);

%RR
reformat=deloutabove(reformat,12,80);

%SpO2
reformat=deloutabove(reformat,13,150);
ii=reformat(:,13)>100;reformat(ii,13)=100;
reformat=deloutbelow(reformat,13,50);

%temp
ii=reformat(:,14)>90 & isnan(reformat(:,15));reformat(ii,15)=reformat(ii,14);
reformat=deloutabove(reformat,14,90);
reformat=deloutbelow(reformat,14,25);

%interface / is in col 22

% FiO2
reformat=deloutabove(reformat,23,100);
ii=reformat(:,23)<1;reformat(ii,23)=reformat(ii,23)*100;
reformat=deloutbelow(reformat,23,20);
reformat=deloutabove(reformat,24,1.5);

% O2 FLOW
reformat=deloutabove(reformat,25,70);

%PEEP
reformat=deloutbelow(reformat,26,0);
reformat=deloutabove(reformat,26,40);

%TV
reformat=deloutabove(reformat,27,1800);

%MV
reformat=deloutabove(reformat,28,50);

%K+
reformat=deloutbelow(reformat,32,1);
reformat=deloutabove(reformat,32,15);

%Na
reformat=deloutbelow(reformat,33,95);
reformat=deloutabove(reformat,33,178);

%Cl
reformat=deloutbelow(reformat,34,70);
reformat=deloutabove(reformat,34,150);

%Glc
reformat=deloutbelow(reformat,35,1);
reformat=deloutabove(reformat,35,1000);

%Creat
reformat=deloutabove(reformat,37,150);

%Mg
reformat=deloutabove(reformat,38,10);

%Ca
reformat=deloutabove(reformat,39,20);

%ionized Ca
reformat=deloutabove(reformat,40,5);

%CO2
reformat=deloutabove(reformat,41,120);

%SGPT/SGOT
reformat=deloutabove(reformat,42,10000);
reformat=deloutabove(reformat,43,10000);

%Hb/Ht
reformat=deloutabove(reformat,50,20);
reformat=deloutabove(reformat,51,65);

%WBC
reformat=deloutabove(reformat,53,500);

%plt
reformat=deloutabove(reformat,54,2000);

%INR
reformat=deloutabove(reformat,58,20);

%pH
reformat=deloutbelow(reformat,59,6.7);
reformat=deloutabove(reformat,59,8);

%po2
reformat=deloutabove(reformat,60,700);

%pco2
reformat=deloutabove(reformat,61,200);

%BE
reformat=deloutbelow(reformat,62,-50);

%lactate
reformat=deloutabove(reformat,63,30);

% ####################################################################
% some more data manip / imputation from existing values

% estimate GCS from RASS - data from Wesley JAMA 2003
ii=isnan(reformat(:,6))&reformat(:,7)>=0;
reformat(ii,6)=15;
ii=isnan(reformat(:,6))&reformat(:,7)==-1;
reformat(ii,6)=14;
ii=isnan(reformat(:,6))&reformat(:,7)==-2;
reformat(ii,6)=12;
ii=isnan(reformat(:,6))&reformat(:,7)==-3;
reformat(ii,6)=11;
ii=isnan(reformat(:,6))&reformat(:,7)==-4;
reformat(ii,6)=6;
ii=isnan(reformat(:,6))&reformat(:,7)==-5;
reformat(ii,6)=3;

% FiO2
ii=~isnan(reformat(:,23)) & isnan(reformat(:,24));
reformat(ii,24)=reformat(ii,23)./100;
ii=~isnan(reformat(:,24)) & isnan(reformat(:,23));
reformat(ii,23)=reformat(ii,24).*100;

%ESTIMATE FiO2 /// with use of interface / device (cannula, mask, ventilator....)

reformatsah=SAH(reformat,sample_and_hold);  % do SAH first to handle this task

%NO FiO2, YES O2 flow, no interface OR cannula
ii=find(isnan(reformatsah(:,23))&~isnan(reformatsah(:,25))&(reformatsah(:,22)==0|reformatsah(:,22)==2));
reformat(ii(reformatsah(ii,25)<=15),23)=70;
reformat(ii(reformatsah(ii,25)<=12),23)=62;
reformat(ii(reformatsah(ii,25)<=10),23)=55;
reformat(ii(reformatsah(ii,25)<=8),23)=50;
reformat(ii(reformatsah(ii,25)<=6),23)=44;
reformat(ii(reformatsah(ii,25)<=5),23)=40;
reformat(ii(reformatsah(ii,25)<=4),23)=36;
reformat(ii(reformatsah(ii,25)<=3),23)=32;
reformat(ii(reformatsah(ii,25)<=2),23)=28;
reformat(ii(reformatsah(ii,25)<=1),23)=24;

%NO FiO2, NO O2 flow, no interface OR cannula
ii=find(isnan(reformatsah(:,23))&isnan(reformatsah(:,25))&(reformatsah(:,22)==0|reformatsah(:,22)==2));  %no fio2 given and o2flow given, no interface OR cannula
reformat(ii,23)=21;

%NO FiO2, YES O2 flow, face mask OR.... OR ventilator (assume it's face mask)
ii=find(isnan(reformatsah(:,23))&~isnan(reformatsah(:,25))&(reformatsah(:,22)==NaN|reformatsah(:,22)==1|reformatsah(:,22)==3|reformatsah(:,22)==4|reformatsah(:,22)==5|reformatsah(:,22)==6|reformatsah(:,22)==9|reformatsah(:,22)==10));
reformat(ii(reformatsah(ii,25)<=15),23)=75;
reformat(ii(reformatsah(ii,25)<=12),23)=69;
reformat(ii(reformatsah(ii,25)<=10),23)=66;
reformat(ii(reformatsah(ii,25)<=8),23)=58;
reformat(ii(reformatsah(ii,25)<=6),23)=40;
reformat(ii(reformatsah(ii,25)<=4),23)=36;

%NO FiO2, NO O2 flow, face mask OR ....OR ventilator
ii=find(isnan(reformatsah(:,23))&isnan(reformatsah(:,25))&(reformatsah(:,22)==NaN|reformatsah(:,22)==1|reformatsah(:,22)==3|reformatsah(:,22)==4|reformatsah(:,22)==5|reformatsah(:,22)==6|reformatsah(:,22)==9|reformatsah(:,22)==10));  %no fio2 given and o2flow given, no interface OR cannula
reformat(ii,23)=NaN;

%NO FiO2, YES O2 flow, Non rebreather mask
ii=find(isnan(reformatsah(:,23))&~isnan(reformatsah(:,25))&reformatsah(:,22)==7);
reformat(ii(reformatsah(ii,25)>=10),23)=90;
reformat(ii(reformatsah(ii,25)>=15),23)=100;
reformat(ii(reformatsah(ii,25)<10),23)=80;
reformat(ii(reformatsah(ii,25)<=8),23)=70;
reformat(ii(reformatsah(ii,25)<=6),23)=60;

%NO FiO2, NO O2 flow, NRM
ii=find(isnan(reformatsah(:,23))&isnan(reformatsah(:,25))&reformatsah(:,22)==7);  %no fio2 given and o2flow given, no interface OR cannula
reformat(ii,23)=NaN;

% update again FiO2 columns
ii=~isnan(reformat(:,23)) & isnan(reformat(:,24));
reformat(ii,24)=reformat(ii,23)./100;
ii=~isnan(reformat(:,24)) & isnan(reformat(:,23));
reformat(ii,23)=reformat(ii,24).*100;

%BP
ii=~isnan(reformat(:,9))&~isnan(reformat(:,10)) & isnan(reformat(:,11));
reformat(ii,11)=(3*reformat(ii,10)-reformat(ii,9))./2;
ii=~isnan(reformat(:,09))&~isnan(reformat(:,11)) & isnan(reformat(:,10));
reformat(ii,10)=(reformat(ii,9)+2*reformat(ii,11))./3;
ii=~isnan(reformat(:,10))&~isnan(reformat(:,11)) & isnan(reformat(:,9));
reformat(ii,9)=3*reformat(ii,10)-2*reformat(ii,11);

%TEMP
%some values recorded in the wrong column
ii=reformat(:,15)>25&reformat(:,15)<45; %tempF close to 37deg??!
reformat(ii,14)=reformat(ii,15);
reformat(ii,15)=NaN;
ii=reformat(:,14)>70;  %tempC > 70?!!! probably degF
reformat(ii,15)=reformat(ii,14);
reformat(ii,14)=NaN;
ii=~isnan(reformat(:,14)) & isnan(reformat(:,15));
reformat(ii,15)=reformat(ii,14)*1.8+32;
ii=~isnan(reformat(:,15)) & isnan(reformat(:,14));
reformat(ii,14)=(reformat(ii,15)-32)./1.8;

% Hb/Ht
ii=~isnan(reformat(:,50)) & isnan(reformat(:,51));
reformat(ii,51)=(reformat(ii,50)*2.862)+1.216;
ii=~isnan(reformat(:,51)) & isnan(reformat(:,50));
reformat(ii,50)=(reformat(ii,51)-1.216)./2.862;

%BILI
ii=~isnan(reformat(:,44)) & isnan(reformat(:,45));
reformat(ii,45)=(reformat(ii,44)*0.6934)-0.1752;
ii=~isnan(reformat(:,45)) & isnan(reformat(:,44));
reformat(ii,44)=(reformat(ii,45)+0.1752)./0.6934;

%% ########################################################################
%                      SAMPLE AND HOLD on RAW DATA
% ########################################################################

reformat=SAH(reformat(:,1:68),sample_and_hold);

%% ########################################################################
%                             DATA COMBINATION
% ########################################################################

tic
     save('D:\BACKUP MIT PC\Data_100219.mat', '-v7.3');
toc

% WARNING: the time window of interest has been defined above (here -48 -> +24)!

timestep=4;  %resolution of timesteps, in hours
irow=1;
icustayidlist=unique(reformat(:,2));
reformat2=nan(size(reformat,1),84);  %output array
h = waitbar(0,'Initializing waitbar...');
npt=numel(icustayidlist);  %number of patients
% Adding 2 empty cols for future shock index=HR/SBP and P/F
reformat(:,69:70)=NaN(size(reformat,1),2);

tic
for i=1:npt

    icustayid=icustayidlist(i);  %1 to 100000, NOT 200 to 300K!

        %CHARTEVENTS AND LAB VALUES
        temp=reformat(reformat(:,2)==icustayid,:);   %subtable of interest
        beg=temp(1,3);   %timestamp of first record

        % IV FLUID STUFF
        iv=find(inputMV(:,1)==icustayid+200000);   %rows of interest in inputMV
        input=inputMV(iv,:);    %subset of interest
        iv=find(inputCV(:,1)==icustayid+200000);   %rows of interest in inputCV
        input2=inputCV(iv,:);    %subset of interest
        startt=input(:,2); %start of all infusions and boluses
        endt=input(:,3); %end of all infusions and boluses
        rate=input(:,8);  %rate of infusion (is NaN for boluses)

        pread=inputpreadm(inputpreadm(:,1)==icustayid+200000,2) ;%preadmission volume
            if ~isempty(pread)             %store the value, if available
                totvol=nansum(pread);
                waitbar(i/npt,h,i/npt*100) %moved here to save some time
            else
                totvol=0;   %if not documented: it's zero
            end

        % compute volume of fluid given before start of record!!!
        t0=0;
        t1=beg;
        %input from MV (4 ways to compute)
        infu=  nansum(rate.*(endt-startt).*(endt<=t1&startt>=t0)/3600   +    rate.*(endt-t0).*(startt<=t0&endt<=t1&endt>=t0)/3600 +     rate.*(t1-startt).*(startt>=t0&endt>=t1&startt<=t1)/3600 +      rate.*(t1-t0).*(endt>=t1&startt<=t0)   /3600);
        %all boluses received during this timestep, from inputMV (need to check rate is NaN) and inputCV (simpler):
        bolus=nansum(input(isnan(input(:,6))& input(:,2)>=t0&input(:,2)<=t1,7)) + nansum(input2(input2(:,2)>=t0&input2(:,2)<=t1,5));
        totvol=nansum([totvol,infu,bolus]);

        %VASOPRESSORS
        iv=find(vasoMV(:,1)==icustayid+200000);   %rows of interest in vasoMV
        vaso1=vasoMV(iv,:);    %subset of interest
        iv=find(vasoCV(:,1)==icustayid+200000);   %rows of interest in vasoCV
        vaso2=vasoCV(iv,:);    %subset of interest
        startv=vaso1(:,3); %start of VP infusion
        endv=vaso1(:,4); %end of VP infusions
        ratev=vaso1(:,5);  %rate of VP infusion

        %DEMOGRAPHICS / gender, age, elixhauser, re-admit, died in hosp?, died within
        %48h of out_time (likely in ICU or soon after), died within 90d after admission?
        demogi=find(demog.icustay_id==icustayid+200000);
        dem=[  demog.gender(demogi) ; demog.age(demogi) ;demog.elixhauser(demogi) ; demog.adm_order(demogi)>1 ;  demog.morta_hosp(demogi); abs(demog.dod(demogi)-demog.outtime(demogi))<(24*3600*2); demog.morta_90(demogi) ; (qstime(icustayid,4)-qstime(icustayid,3))/3600];

        % URINE OUTPUT
        iu=find(UO(:,1)==icustayid+200000);   %rows of interest in inputMV
        output=UO(iu,:);    %subset of interest
        pread=UOpreadm(UOpreadm(:,1)==icustayid,4) ;%preadmission UO
            if ~isempty(pread)     %store the value, if available
                UOtot=nansum(pread);
            else
                UOtot=0;
            end
        % adding the volume of urine produced before start of recording!
        UOnow=nansum(output(output(:,2)>=t0&output(:,2)<=t1,4));  %t0 and t1 defined above
        UOtot=nansum([UOtot UOnow]);

    for j=0:timestep:79 % -28 until +52 = 80 hours in total
        t0=3600*j+ beg;   %left limit of time window
        t1=3600*(j+timestep)+beg;   %right limit of time window
        ii=temp(:,3)>=t0 & temp(:,3)<=t1;  %index of items in this time period
        if sum(ii)>0

        %ICUSTAY_ID, OUTCOMES, DEMOGRAPHICS
        reformat2(irow,1)=(j/timestep)+1;   %'bloc' = timestep (1,2,3...)
        reformat2(irow,2)=icustayid;        %icustay_ID
        reformat2(irow,3)=3600*j+ beg;      %t0 = lower limit of time window
        reformat2(irow,4:11)=dem;           %demographics and outcomes

        %CHARTEVENTS and LAB VALUES (+ includes empty cols for shock index and P/F)
        value=temp(ii,:);%records all values in this timestep

        if sum(ii)==1   %if only 1 row of values at this timestep
          reformat2(irow,12:78)=value(:,4:end);
        else
          reformat2(irow,12:78)=nanmean(value(:,4:end)); %mean of all available values

        end

        %VASOPRESSORS
            % for CV: dose at timestamps.
            % for MV: 4 possibles cases, each one needing a different way to compute the dose of VP actually administered:
            %----t0---start----end-----t1----
            %----start---t0----end----t1----
            %-----t0---start---t1---end
            %----start---t0----t1---end----

        %MV
        v=(endv>=t0&endv<=t1)|(startv>=t0&endv<=t1)|(startv>=t0&startv<=t1)|(startv<=t0&endv>=t1);
        %CV
        v2=vaso2(vaso2(:,3)>=t0&vaso2(:,3)<=t1,4);
        v1=nanmedian([ratev(v); v2]);
        v2=nanmax([ratev(v); v2]);
        if ~isempty(v1)&~isnan(v1)&~isempty(v2)&~isnan(v2)
        reformat2(irow,79)=v1;    %median of dose of VP
        reformat2(irow,80)=v2;    %max dose of VP
        end

        %INPUT FLUID
        %input from MV (4 ways to compute)
        infu=  nansum(rate.*(endt-startt).*(endt<=t1&startt>=t0)/3600   +    rate.*(endt-t0).*(startt<=t0&endt<=t1&endt>=t0)/3600 +     rate.*(t1-startt).*(startt>=t0&endt>=t1&startt<=t1)/3600 +      rate.*(t1-t0).*(endt>=t1&startt<=t0)   /3600);
        %all boluses received during this timestep, from inputMV (need to check rate is NaN) and inputCV (simpler):
        bolus=nansum(input(isnan(input(:,6))& input(:,2)>=t0&input(:,2)<=t1,7)) + nansum(input2(input2(:,2)>=t0&input2(:,2)<=t1,5));

        %sum fluid given
        totvol=nansum([totvol,infu,bolus]);
        reformat2(irow,81)=totvol;    %total fluid given
        reformat2(irow,82)=nansum([infu,bolus]);   %fluid given at this step

        %UO
        UOnow=nansum(output(output(:,2)>=t0&output(:,2)<=t1,4));
        UOtot=nansum([UOtot UOnow]);
        reformat2(irow,83)=UOtot;    %total UO
        reformat2(irow,84)=nansum(UOnow);   %UO at this step

        %CUMULATED BALANCE
        reformat2(irow,85)=totvol-UOtot;    %cumulated balance

        irow=irow+1;
        end
    end
end
toc

reformat2(irow:end,:)=[];
close(h);

tic
     save('D:\BACKUP MIT PC\Data_110219.mat', '-v7.3');
toc

%% ########################################################################
%             CONVERT TO TABLE AND KEEP ONLY WANTED VARIABLE
% ########################################################################

dataheaders=[sample_and_hold(1,:) {'Shock_Index' 'PaO2_FiO2'}];
dataheaders=regexprep(dataheaders,'['']','');
dataheaders = ['bloc','icustayid','charttime','gender','age','elixhauser','re_admission', 'died_in_hosp', 'died_within_48h_of_out_time','mortality_90d','delay_end_of_record_and_discharge_or_death',...
    dataheaders,  'median_dose_vaso','max_dose_vaso','input_total','input_4hourly','output_total','output_4hourly','cumulated_balance'];

reformat2t=array2table(reformat2);
reformat2t.Properties.VariableNames=dataheaders;

% headers I want to keep
dataheaders5 = {'bloc','icustayid','charttime','gender','age','elixhauser','re_admission', 'died_in_hosp', 'died_within_48h_of_out_time','mortality_90d','delay_end_of_record_and_discharge_or_death','SOFA','SIRS',...
    'Weight_kg','GCS','HR','SysBP','MeanBP','DiaBP','RR','SpO2','Temp_C','FiO2_1','Potassium','Sodium','Chloride','Glucose',...
    'BUN','Creatinine','Magnesium','Calcium','Ionised_Ca','CO2_mEqL','SGOT','SGPT','Total_bili','Albumin','Hb','WBC_count','Platelets_count','PTT','PT','INR',...
    'Arterial_pH','paO2','paCO2','Arterial_BE','HCO3','Arterial_lactate','mechvent','Shock_Index','PaO2_FiO2',...
    'median_dose_vaso','max_dose_vaso','input_total','input_4hourly','output_total','output_4hourly','cumulated_balance'};

ii=find(ismember(reformat2t.Properties.VariableNames,dataheaders5));
reformat3t=reformat2t(:,ii);

%% SOME DATA MANIP BEFORE IMPUTATION

% CORRECT GENDER
reformat3t.gender=reformat3t.gender-1;

%CORRECT AGE > 200 yo
ii=reformat3t.age>150*365.25;
reformat3t.age(ii)=91.4*365.25;

% FIX MECHVENT
reformat3t.mechvent(isnan(reformat3t.mechvent))=0;
reformat3t.mechvent(reformat3t.mechvent>0)=1;

% FIX Elixhauser missing values
reformat3t.elixhauser(isnan(reformat3t.elixhauser))=nanmedian(reformat3t.elixhauser);  %use the median value / only a few missing data points

%vasopressors / no NAN
a=find(ismember(reformat3t.Properties.VariableNames,{'median_dose_vaso'}));
ii=isnan(table2array(reformat3t(:,a)));
reformat3t(ii,a)=array2table(zeros(sum(ii),1));
a=find(ismember(reformat3t.Properties.VariableNames,{'max_dose_vaso'}));
ii=isnan(table2array(reformat3t(:,a)));
reformat3t(ii,a)=array2table(zeros(sum(ii),1));

% check prop of missingness here
miss=array2table(sum(isnan(table2array(reformat3t)))./size(reformat3t,1));
miss.Properties.VariableNames=reformat3t.Properties.VariableNames;
figure; bar(sum(isnan(table2array(reformat3t)))./size(reformat3t,1))

% I fill the values temporarily with zeros, otherwise kNN imp doesnt work
reformat3t.Shock_Index=zeros(size(reformat3t,1),1);
reformat3t.PaO2_FiO2=zeros(size(reformat3t,1),1);

%% ########################################################################
%        HANDLING OF MISSING VALUES & CREATE REFORMAT4T
% ########################################################################

% Do linear interpol where missingness is low (kNN imputation doesnt work if all rows have missing values)
reformat3=table2array(reformat3t);
miss=sum(isnan((reformat3)))./size(reformat3,1);
ii=miss>0&miss<0.05;  %less than 5% missingness
mechventcol=find(ismember(reformat3t.Properties.VariableNames,{'mechvent'}));

for i=11:mechventcol-1 % correct col by col, otherwise it does it wrongly
  if ii(i)==1
    reformat3(:,i)=fixgaps(reformat3(:,i));
  end
end

reformat3t(:,11:mechventcol-1)=array2table(reformat3(:,11:mechventcol-1));

% KNN IMPUTATION -  Done on chunks of 10K records.

mechventcol=find(ismember(reformat3t.Properties.VariableNames,{'mechvent'}));
ref=reformat3(:,11:mechventcol-1);  %columns of interest

tic
for i=1:10000:size(reformat3,1)-9999   %dataset divided in 5K rows chunks (otherwise too large)
    i
    ref(i:i+9999,:)=knnimpute(ref(i:i+9999,:)',1, 'distance','seuclidean')';
end

ref(end-9999:end,:)=knnimpute(ref(end-9999:end,:)',1, 'distance','seuclidean')';  %the last bit is imputed from the last 10K rows

toc

% I paste the data interpolated, but not the demographics and the treatments
reformat3t(:,11:mechventcol-1)=array2table(ref);

reformat4t=reformat3t;
reformat4=table2array(reformat4t);

%% ########################################################################
%        COMPUTE SOME DERIVED VARIABLES: P/F, Shock Index, SOFA, SIRS...
% ########################################################################

% re-compute P/F with no missing values...
p=find(ismember(reformat4t.Properties.VariableNames,{'paO2'}));
f=find(ismember(reformat4t.Properties.VariableNames,{'FiO2_1'}));
a=find(ismember(reformat4t.Properties.VariableNames,{'PaO2_FiO2'}));
reformat4t(:,a)=array2table(reformat4(:,p)./reformat4(:,f));

%recompute SHOCK INDEX without NAN and INF
p=find(ismember(reformat4t.Properties.VariableNames,{'HR'}));
f=find(ismember(reformat4t.Properties.VariableNames,{'SysBP'}));
a=find(ismember(reformat4t.Properties.VariableNames,{'Shock_Index'}));
reformat4(:,a)=reformat4(:,p)./reformat4(:,f);
reformat4(isinf(reformat4(:,a)),a)=NaN;
d=nanmean(reformat4(:,a));
reformat4(isnan(reformat4(:,a)),a)=d;  %replace NaN with average value ~ 0.8
reformat4t(:,a)=array2table(reformat4(:,a));
ii=reformat4t.Shock_Index>=quantile(reformat4t.Shock_Index,0.999); %replace outliers with 99.9th percentile
reformat4t.Shock_Index(ii)=quantile(reformat4t.Shock_Index,0.999);

% SOFA - at each timepoint
% need (in this order):  P/F  MV  PLT  TOT_BILI  MAP  NORAD(max)  GCS  CR  UO
a=zeros(8,1);                              % indices of vars used in SOFA
a(1)=find(ismember(reformat4t.Properties.VariableNames,{'PaO2_FiO2'}));
a(2)=find(ismember(reformat4t.Properties.VariableNames,{'Platelets_count'}));
a(3)=find(ismember(reformat4t.Properties.VariableNames,{'Total_bili'}));
a(4)=find(ismember(reformat4t.Properties.VariableNames,{'MeanBP'}));
a(5)=find(ismember(reformat4t.Properties.VariableNames,{'max_dose_vaso'}));
a(6)=find(ismember(reformat4t.Properties.VariableNames,{'GCS'}));
a(7)=find(ismember(reformat4t.Properties.VariableNames,{'Creatinine'}));
a(8)=find(ismember(reformat4t.Properties.VariableNames,{'output_4hourly'}));
s=table2array(reformat4t(:,a));

p=[0 1 2 3 4];

s1=[s(:,1)>400 s(:,1)>=300 &s(:,1)<400 s(:,1)>=200 &s(:,1)<300 s(:,1)>=100 &s(:,1)<200 s(:,1)<100 ];   %count of points for all 6 criteria of sofa
s2=[s(:,2)>150 s(:,2)>=100 &s(:,2)<150 s(:,2)>=50 &s(:,2)<100 s(:,2)>=20 &s(:,2)<50 s(:,2)<20 ];
s3=[s(:,3)<1.2 s(:,3)>=1.2 &s(:,3)<2 s(:,3)>=2 &s(:,3)<6 s(:,3)>=6 &s(:,3)<12 s(:,3)>12 ];
s4=[s(:,4)>=70 s(:,4)<70&s(:,4)>=65 s(:,4)<65 s(:,5)>0 &s(:,5)<=0.1 s(:,5)>0.1 ];
s5=[s(:,6)>14 s(:,6)>12 &s(:,6)<=14 s(:,6)>9 &s(:,6)<=12 s(:,6)>5 &s(:,6)<=9 s(:,6)<=5 ];
s6=[s(:,7)<1.2 s(:,7)>=1.2 &s(:,7)<2 s(:,7)>=2 &s(:,7)<3.5 (s(:,7)>=3.5 &s(:,7)<5)|(s(:,8)<84) (s(:,7)>5)|(s(:,8)<34) ];

nrcol=size(reformat4,2);   %nr of variables in data
reformat4(1,nrcol+1:nrcol+7)=0;
for i=1:size(reformat4,1)
    t=max(p(s1(i,:)))+max(p(s2(i,:)))+max(p(s3(i,:)))+max(p(s4(i,:)))+max(p(s5(i,:)))+max(p(s6(i,:)));  %SUM OF ALL 6 CRITERIA

    if t
    reformat4(i,nrcol+1:nrcol+7)=    [max(p(s1(i,:))) max(p(s2(i,:))) max(p(s3(i,:))) max(p(s4(i,:))) max(p(s5(i,:))) max(p(s6(i,:))) t];
    end
end

% SIRS - at each timepoint |  need: temp HR RR PaCO2 WBC
a=zeros(5,1); % indices of vars used in SOFA
a(1)=find(ismember(reformat4t.Properties.VariableNames,{'Temp_C'}));
a(2)=find(ismember(reformat4t.Properties.VariableNames,{'HR'}));
a(3)=find(ismember(reformat4t.Properties.VariableNames,{'RR'}));
a(4)=find(ismember(reformat4t.Properties.VariableNames,{'paCO2'}));
a(5)=find(ismember(reformat4t.Properties.VariableNames,{'WBC_count'}));
s=table2array(reformat4t(:,a));

s1=[s(:,1)>=38| s(:,1)<=36];   %count of points for all criteria of SIRS
s2=[s(:,2)>90 ];
s3=[s(:,3)>=20|s(:,4)<=32];
s4=[s(:,5)>=12| s(:,5)<4];
reformat4(:,nrcol+8)=s1+s2+s3+s4;

% adds 2 cols for SOFA and SIRS, if necessary
if sum(ismember(reformat4t.Properties.VariableNames,{'SIRS'}))== 0
reformat4t(:,end+1:end+2)=array2table(0);
reformat4t.Properties.VariableNames(end-1:end)= {'SOFA','SIRS'};
end

% more IO corrections
 ii=reformat4t.input_total<0;
 reformat4t.input_total(ii)=0;
 ii=reformat4t.input_4hourly<0;
 reformat4t.input_4hourly(ii)=0;

% records values
reformat4t(:,end-1)=array2table(reformat4(:,end-1));
reformat4t(:,end)=array2table(reformat4(:,end));

%% ########################################################################
%                     CREATE FINAL MIMIC_TABLE
% ########################################################################

MIMICtable = reformat4t;


function [h,ax] = smooth(v,varargin)
% low level function for plotting functions on the sphere
%
% Syntax
%   smooth(v,values)
%
% Input
%
% Output
%
% Options
%
% See also
%

h = [];

% initialize spherical plot
opt = delete_option(varargin,{'lineStyle','lineColor','lineWidth','color'},1);
sP = newSphericalPlot(v,opt{:},'doNotDraw');

for j = 1:numel(sP)

  % ---------------- extract colors --------------------------

  % color given by the first argument?
  if ~isempty(varargin) && ~isempty(varargin{1}) ...
      && (islogical(varargin{1}) || isnumeric(varargin{1}))

    cdata = double(varargin{1});
    S2G = v;

  else % no color given -> do kernel density estimation

    sR = sP(j).sphericalRegion;
    if isfield(v.opt,'region'), sR = [sR,v.opt.region]; end %#ok<AGROW>
    S2G = plotS2Grid(sR);

    cdata = calcDensity(v(:),S2G,'halfwidth',5*degree,varargin{:});
    cdata = reshape(cdata,size(S2G));

  end

  sP(j).updateMinMax(cdata);

  % interpolate if no regular grid was given
  if ~isOption(S2G,'plot') || ~S2G.opt.plot

    if size(S2G,1) == 1 || size(S2G,2) == 1

      S2G = plotS2Grid(sP(j).sphericalRegion,varargin{:});
      cdata = interp(v,cdata,S2G,'cutOutside',varargin{:});

    elseif ~isa(sP(j).proj,'plainProjection')

      % close the gap between 0 and 2*pi
      varargin = set_option(varargin,'correctContour');

    end
  end

  % scale the data
  [cdata,colorRange] = scaleData(cdata,varargin{:});
  %if ~any(isnan(colorRange)), caxis(sP(j).ax,colorRange);end

  % ------------- compute contour lines ------------------------

  % number of contour lines
  contours = get_option(varargin,'contours',50);
  contours = get_option(varargin,{'contourf','contour'},contours,'double');

  % specify contourlines explicitely
  if length(contours) == 1
    if check_option(varargin,'log')
      contours = logspace(log10(colorRange(1)),log10(colorRange(2)),contours);
    else
      contours = linspace(colorRange(1),colorRange(2),contours);
    end
  end

  % ----------------- draw contours ------------------------------

  washold = ishold(sP(j).ax);
  hold(sP(j).ax,'on')

  % project data
  [x,y] = project(sP(j).proj,S2G,'noAntipodal');

  % extract non nan data
  data = reshape(cdata,size(x));

  % plot contours
  h = [h,betterContourf(sP(j).hgt,x,y,data,contours,varargin{:})]; %#ok<AGROW>

  if ~washold, hold(sP(j).ax,'off'); end

  % --------------- finalize the plot ---------------------------

  % adjust caxis according to colorRange
  if ~any(isnan(colorRange)), caxis(sP(j).ax,colorRange); end
  if check_option(varargin,'log'), set(sP(j).ax,'colorScale','log'); end

  % colormap
  if ~strcmpi(get_option(varargin,'fill'),'off')
    mtexColorMap(sP(j).ax,getMTEXpref('defaultColorMap'));
  end

  % bring grid in front
  sP(j).doGridInFront;

  sP(j).plotAnnotate(varargin{:})

end

% set styles
varargin = delete_option(varargin,'parent',1);
optiondraw(h,varargin{:});

if isappdata(sP(1).parent,'mtexFig')
  mtexFig = getappdata(sP(1).parent,'mtexFig');
  mtexFig.drawNow('figSize',getMTEXpref('figSize'),varargin{:});
end

if nargout == 0
  clear h;
else
  ax = [sP.ax];
end

end

% ------------------------------------------------------------
function h = betterContourf(ax,X,Y,data,contours,varargin)

if numel(unique(data)) == 1, data(1) = data(1) + 2*eps; end

% workauround for a MATLAB Bug
%if mean(X(:,1)) > mean(X(:,end))
%  X = fliplr(X);
%  Y = fliplr(Y);
%  data = flipdim(data,2);
%end

% contour correction
if check_option(varargin,'correctContour')
  X = [X;X(1,:)];
  Y = [Y;Y(1,:)];
  data = [data;data(1,:)];
end

if check_option(varargin,'pcolor')

  opt = {};
  if numel(data) >= 500
    opt = {'LineStyle','none','FaceColor','interp'};
  end

  % pcolor is actually surface
  h = surface(X,Y,zeros(size(X)),data,opt{:},'parent',ax);

else

  % extract style
  opt = extract_argoption([{'LineStyle','none','Fill','on'},varargin],{'LineStyle','Fill','LineColor'});

  if ~check_option(varargin,'contour')
    [CM,h] = contourf(X,Y,data,contours,opt{:},'parent',ax); %#ok<ASGLU>
  else
    [CM,h] = contour(X,Y,data,contours,opt{:},'parent',ax); %#ok<ASGLU>
  end

end

% do not display in the legend
set(get(get(h,'Annotation'),'LegendInformation'),'IconDisplayStyle','off');

end


function roidb_new = do_proposal_test(conf, model_stage, imdb, roidb)
    aboxes                      = proposal_test(conf, imdb, ...
                                        'net_def_file',     model_stage.test_net_def_file, ...
                                        'net_file',         model_stage.output_model_file, ...
                                        'cache_name',       model_stage.cache_name);

    aboxes                      = boxes_filter(aboxes, model_stage.nms.per_nms_topN, model_stage.nms.nms_overlap_thres, model_stage.nms.after_nms_topN, conf.use_gpu);

    roidb_regions               = make_roidb_regions(aboxes, imdb.image_ids);

    roidb_new                   = roidb_from_proposal(imdb, roidb, roidb_regions, ...
                                        'keep_raw_proposal', false);
end

function aboxes = boxes_filter(aboxes, per_nms_topN, nms_overlap_thres, after_nms_topN, use_gpu)
    % to speed up nms
    if per_nms_topN > 0
        aboxes = cellfun(@(x) x(1:min(length(x), per_nms_topN), :), aboxes, 'UniformOutput', false);
    end
    % do nms
    if nms_overlap_thres > 0 && nms_overlap_thres < 1
        if use_gpu
            for i = 1:length(aboxes)
                aboxes{i} = aboxes{i}(nms(aboxes{i}, nms_overlap_thres, use_gpu), :);
            end
        else
            parfor i = 1:length(aboxes)
                aboxes{i} = aboxes{i}(nms(aboxes{i}, nms_overlap_thres), :);
            end
        end
    end
    aver_boxes_num = mean(cellfun(@(x) size(x, 1), aboxes, 'UniformOutput', true));
    fprintf('aver_boxes_num = %d, select top %d\n', round(aver_boxes_num), after_nms_topN);
    if after_nms_topN > 0
        aboxes = cellfun(@(x) x(1:min(length(x), after_nms_topN), :), aboxes, 'UniformOutput', false);
    end
end

function regions = make_roidb_regions(aboxes, images)
    regions.boxes = aboxes;
    regions.images = images;
end


function robot_disp = LoadRobotDisplay(robot, varargin)

    ip = inputParser;
    ip.addParameter('UseExported',true,@(x) isequal(x,true) || isequal(x,false));
    ip.addParameter('ExportPath','',@(x)ischar(x));
    ip.addParameter('SkipExporting',false,@(x) isequal(x,true) || isequal(x,false));

    ip.parse(varargin{:});

    opts = ip.Results;
    if isempty(opts.ExportPath)
        root_path = utils.get_root_path();
        export_path = fullfile(root_path,'gen','animator');
        opts.ExportPath = export_path;
    else
        export_path = opts.ExportPath;
    end
    if ~exist(export_path,'dir')
        mkdir(export_path);
    end
    addpath(export_path);

    f = figure(1000);clf;
    robot_disp = frost.Animator.Display(f, robot, opts);frame  = robot.Joints(6);

    pelvis = robot.Links(getLinkIndices(robot,'mtorso'));
    offset = pelvis.Offset;
    torso_bar = frost.Animator.Cylinder(robot_disp.axs, robot, frame, offset, 'TorsoBar', opts);
    robot_disp.addItem(torso_bar);

    torso = frost.Animator.LinkSphere(robot_disp.axs, robot, pelvis, 'TorsoCoM', opts);
    torso.radius = 0.1;
    robot_disp.addItem(torso);
    % add feet
    left_foot = sys.frames.LeftSole(robot);
    param = sys.GetExtraParams;
    name = 'LeftFoot';
    top_offset = [0,0,-param.hf];
    wf = param.wf;
    lt = param.lt;
    lh = param.lh;
    bottom_offset = [lt,-wf/2,0;
        lt,wf/2,0;
        -lh,wf/2,0;
        -lh,-wf/2,0
        ];
    left_foot = frost.Animator.Pyramid(robot_disp.axs, robot, left_foot, top_offset, bottom_offset, name, opts);
    robot_disp.addItem(left_foot);

    right_foot = sys.frames.RightSole(robot);
    param = sys.GetExtraParams;
    name = 'RightFoot';
    top_offset = [0,0,-param.hf];
    wf = param.wf;
    lt = param.lt;
    lh = param.lh;
    bottom_offset = [lt,-wf/2,0;
        lt,wf/2,0;
        -lh,wf/2,0;
        -lh,-wf/2,0
        ];
    right_foot = frost.Animator.Pyramid(robot_disp.axs, robot, right_foot, top_offset, bottom_offset, name, opts);
    robot_disp.addItem(right_foot);

end


function b = isappr(x,y,varargin)
% check double == double

b = isnull(abs(x-y),varargin{:});


function [img, hdr_info] = hdrimread(filename)
%
%       [img, hdr_info] = hdrimread(filename)
%
%       This function reads from a file with name filename an HDR image, if
%       the format can not be opened, it tries to open it as it was an LDR
%       image using imread from MATLAB Image Processing Toolbox.
%
%       NOTE: JPEG2000 file passed as input are meant to be compressed
%       using HDR JPEG-2000.
%
%        Input:
%           -filename: the name of the file to open
%
%        Output:
%           -img: the opened image
%           -hdr_info: RGBE format extra datum such as: exposure, gamma, etc.
%
%     Copyright (C) 2011-15  Francesco Banterle
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
%

if(~exist('filename', 'var'))
    error('A filename with extension needs to be passed as input!');
end

extension = lower(fileExtension(filename));

%Radiance format can have different extensions: .hdr, .rgbe and .pic
if((strcmpi(extension,'pic')==1) || (strcmpi(extension,'rgbe')==1))
    extension = 'hdr';
end

img = [];
hdr_info = [];
bLDR = 1;

switch extension

    %PIC-HDR format by Greg Ward
    case 'hdr'
        try
	    %HDR Toolbox's HDR Reader
            [img, hdr_info] = read_rgbe(filename);
            bLDR = 0;
        catch err
            try
                %MATLAB HDR Reader
                img = double(hdrread(filename));
                bLDR = 0;
            catch err
                warning('This .hdr/.pic file cannot be read.');
            end
        end

    %OpenEXR support using TinyEXR
    case 'exr'
        try
            img = read_exr(filename);
            bLDR = 0;
        catch err
            hdr_info = struct('loaded', 0);
            warning('This .exr file cannot be read.');
        end

    %Portable float map
    case 'pfm'
        try
            img = read_pfm(filename);
            bLDR = 0;
        catch
            hdr_info = struct('loaded', 0);
            warning('This .pfm file cannot be read.');
        end

    %HDR JPEG-2000
    case 'jp2'
        try
            img = HDRJPEG2000Dec(filename);
            bLDR = 0;
        catch err
            hdr_info = struct('loaded', 0);
            warning('This .jpg2 file cannot be read as an HDR JPEG 2000 file.');
        end
end

if(isempty(img))
    if(bLDR == 1)
        img = ldrimread(filename);
        if(isempty(img))
            hdr_info = struct('loaded', 0);
            warning(['This image, ', filename,', cannot be loaded as an LDR image.']);
        else
            hdr_info = struct('loaded', 1);
            warning(['This image, ', filename,', has been loaded as an LDR image.']);
        end
    else
        hdr_info = struct('loaded', 0);
        error(['This image, ',filename,', cannot be loaded with LDR or HDR readers.']);
    end
else
    hdr_info.loaded = 1;
end

%Remove specials
img = RemoveSpecials(img);

end


function y = size( x, varargin )
y = size( cvxaff( x ), varargin{:} );

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


function dcmFolder2MATobject(varargin)

% function dcmFolder2MATobject(PathName,MaxVarSize,reOrderOpt,dicomDictFactory,fileExtension)
% ------------------------------------------------------------------------
% This function converts the DICOM files in the folder PathName to a MAT
% object which is stored as a file called IMDAT in a new subfolder called
% IMDAT.
%
%
% Kevin Mattheus Moerman
% gibbon.toolbox@gmail.com
%
% Change log
% 2018/06/11 Suppressed/removed triggertime related warning (this appears
% to be a custom field which is nearly always missing).
%------------------------------------------------------------------------

%% PARSE INPUT

switch nargin
    case 1
        PathName=varargin{1};
        MaxVarSize=[];
        reOrderOpt=0;
        dicomDictFactory=0;
        fileExtension='.dcm';
        optionStruct=[];
    case 2
        PathName=varargin{1};
        MaxVarSize=varargin{2};
        reOrderOpt=0;
        dicomDictFactory=0;
        fileExtension='.dcm';
        optionStruct=[];
    case 3
        PathName=varargin{1};
        MaxVarSize=varargin{2};
        reOrderOpt=varargin{3};
        dicomDictFactory=0;
        fileExtension='.dcm';
        optionStruct=[];
    case 4
        PathName=varargin{1};
        MaxVarSize=varargin{2};
        reOrderOpt=varargin{3};
        dicomDictFactory=varargin{4};
        fileExtension='.dcm';
    case 5
        PathName=varargin{1};
        MaxVarSize=varargin{2};
        reOrderOpt=varargin{3};
        dicomDictFactory=varargin{4};
        fileExtension=varargin{5};
        optionStruct=[];
    case 6
        PathName=varargin{1};
        MaxVarSize=varargin{2};
        reOrderOpt=varargin{3};
        dicomDictFactory=varargin{4};
        fileExtension=varargin{5};
        optionStruct=varargin{6};
end

defaultOptionStruct.ignoreDynamic=0;
defaultOptionStruct.nDownSample=[1 1 1];
defaultOptionStruct.skipInfo=0;
%Fix option structure, complete and remove empty values
[optionStruct]=structComplete(optionStruct,defaultOptionStruct,1);
nDownSample=optionStruct.nDownSample;
skipInfo=optionStruct.skipInfo;

%%
%Get/set maximum variable size (sets save steps in case the variable size
%is exceeded)
if isempty(MaxVarSize)
    MaxVarSize=1e12; %Default
end

if isempty(reOrderOpt)
    reOrderOpt=0; %Default
end

if isempty(dicomDictFactory)
    dicomDictFactory=0; %Default
end

if isempty(fileExtension)
%     fileExtension='.dcm'; %Default
end

%% Getting DICOM file names and image dimension parameters
if ~isempty(fileExtension)
    files = dir(fullfile(PathName,['*',fileExtension]));
else %No file extension
    files = dir(fullfile(PathName));

    %Remove files and hidden folders containing dot in path
    logicKeep=false(1,numel(files));
    for q=1:1:numel(files)
        if isempty(strfind(files(q).name,'.')) && isempty(strfind(files(q).name,'IMDAT'))
            logicKeep(q)=1;
        end
    end
    files=files(logicKeep);
end
files={files(1:end).name};
NumberOfFiles=numel(files);

%% Attempt to sort files
% This sorting assumes the files names make sense in terms of slice
% numbers.

try %Try to get numbers from image file names
    nameNumbers=cellfun(@str2double,regexp(files,'\d+\d*','match'));
    [~,indSort]=sort(nameNumbers); %Get sort order
    files=files(indSort); %Sort file list based on numeric data in names
catch %Normal sort instead
    files=sort(files(:)); %Attempt sort (might cause dcm1,dcm10,...)
end

%%

firstWarning_TriggerTime=0;
firstWarning_Rotation=0;
if NumberOfFiles>0
    %% SPECIFY Tags to collect

    collectTags = { 'Basename', ...
        'PatientID', ...
        'StudyInstanceUID', ...
        'SeriesInstanceUID', ...
        'StudyID', ...
        'InstanceNumber', ...
        'SeriesNumber', ...
        'SeriesDescription', ...
        'StudyDescription', ...
        'ImageType', ...
        'Rows', ...
        'Columns', ...
        'PixelSpacing',...
        'ImagePositionPatient', ...
        'ImageOrientationPatient',...
        'SliceLocation', ...
        'SliceThickness', ...
        'SpacingBetweenSlices', ...
        'SliceGap', ...
        'NumberOfTemporalPositions', ...
        'TemporalPositionIdentifier', ...
        'HeartRate', ...
        'TriggerTime', ...
        'RepetitionTime', ...
        'EchoTime', ...
        'FlipAngle', ...
        'RescaleSlope', ...
        'ScaleSlope',...
        'RescaleIntercept',...
        'RescaleType',...
        'Height',...
        'Width',...
        'MRImagePhaseNumber'...
        'SliceNumberMR'...
        'NumberOfPCDirections',...
        'NumberOfPhasesMR',...
        'NumberOfSlicesMR',...
        'MRSeriesNrOfSlices',...
        'MRSeriesNrOfPhases'...
        'MRSeriesNrOfDynamicScans',...
        'MRImagePhaseNumber',...
        'ImagePlaneNumber'...
        'MRScaleSlope'...
        'MRScaleIntercept'...
        'AcquisitionMatrix'...
        'PixelBandwidth'...
        'ImagingFrequency'...
        'MagneticFieldStrength'...
        'InPlanePhaseEncodingDirection'...
        'PhaseEncodingDirection'...
        };
    % 'EchoNumbers' is private and just a echotime identifier or sequence number
    % 'SliceNumberMR' is also private (2001,100a) and can be usefull for identifing slices that are on same position
    % N.B. Filename is added by matlab including the path, Basename is one we add ourself

    %% Creating output file name and folder
    fName='IMDAT';
    foldername_out=fullfile(PathName,fName,filesep);
    if ~exist(foldername_out,'dir') %create output folder if it does not exist already
        mkdir(foldername_out); %Create new dir
    end
    savename_out1=fullfile(foldername_out,'IMDAT.mat');
    if exist(savename_out1,'file') %Check if file exist already
        delete(savename_out1); %Remove file
    end
    matObj = matfile(savename_out1,'Writable',true);

    %% SETTING DICOM DICTIONARY
    fName=fullfile(PathName,files{1});

    %First import using factory settings
    dicomdict('factory');
    dcmInfo_full=dicominfo(fName);
    m=dicomread(fName); %Test upload first
    sizSlice=size(m);
    dictSetting=3;

    if dicomDictFactory==0
        try
            if ~isempty(strfind(lower(dcmInfo_full.Manufacturer),'philips'))
                disp(['Detected ',dcmInfo_full.Manufacturer,' files']);
                dicomdict('set','gibbon_dict.txt');
                disp('DICOM dictionary set to: gibbon_dict.txt');
                dictSetting=1;
            elseif ~isempty(strfind(lower(dcmInfo_full.Manufacturer),'pms'))
                disp(['Detected ',dcmInfo_full.Manufacturer,' files']);
                dicomdict('set','gibbon_dict.txt');
                disp('DICOM dictionary set to: gibbon_dict.txt');
                dictSetting=1;
            elseif ~isempty(strfind(lower(dcmInfo_full.Manufacturer),'siemens'))
                disp(['Detected ',dcmInfo_full.Manufacturer,' files']);
                dicomdict('set','dicom-dict-siemens.txt');
                disp('DICOM dictionary set to: dicom-dict-siemens.txt');
                dictSetting=2;
            elseif ~isempty(strfind(lower(dcmInfo_full.Manufacturer),'GE MEDICAL SYSTEMS'))
                disp(['Detected ',dcmInfo_full.Manufacturer,' files']);
                warning('No settings for this vendor using DICOM dictionary factory settings');
                dictSetting=3;
            else
                dicomdict('factory');
                warning('Unknown vendor, using DICOM dictionary factory settings');
                dictSetting=3;
            end
            %Test info import with new dictionary (if this fails we resume with
            % factory
            dcmInfo_full=dicominfo(fName);
        catch %e.g. if the manufacturer field is missing
            dicomdict('factory');
            warning('Unknown vendor, using DICOM dictionary factory settings');
            dictSetting=3;
            dcmInfo_full=dicominfo(fName);
        end
    elseif dicomDictFactory==1
        dicomdict('factory');
        dcmInfo_full=dicominfo(fName);
        dictSetting=3;
    end

    %% LOADING DICOM INFO

    if skipInfo==1
        numInfoLoad=1; %Only first will be loaded
    else
        numInfoLoad=numel(files); %All will be loaded
    end

    hw = waitbar(0,'Loading DICOM info...');
    for c=1:1:numInfoLoad
        fName=fullfile(PathName,files{c});
        %dicomdict('get');
        dcmInfo_full=dicominfo(fName);
        dcmInfo_full.Basename=fName; %Add custom field
        iFields = find(isfield(dcmInfo_full,collectTags)); %indices of existing fields
        for iField=1:numel(iFields)
            fieldName = collectTags{iFields(iField)};
            dcmInfo(c).(fieldName) = dcmInfo_full.(fieldName); %allocated after first iteration
        end
        if c==1
            dcmInfo=repmat(dcmInfo,1,numel(files)); %Allocate after size of first is known
        end
        waitbar(c/numInfoLoad,hw,['Loading DICIM info...',num2str(round(100.*c/numel(files))),'%']);
    end
    waitbar(c/numInfoLoad,hw,['Saving DICOM info to MAT-file...',num2str(round(100.*c/numel(files))),'%']);
    % matObj.dcmInfo=dcmInfo;
    close(hw);

    %% Reorder files based on InstanceNumber (file naming may deviate from slice order)
    if reOrderOpt
        [~,indSort]=sort([dcmInfo(:).InstanceNumber]);
        files=files(indSort);
        dcmInfo=dcmInfo(indSort);
    end

    %%

    %Geometry information based on first info file
    [G]=dicom3Dpar(dcmInfo(1));
    G.v=G.v(:).*nDownSample(:);

    matObj.G=G; %Saving geometry information

    %TODO this part is not memory protected yet, all DICOM info is loaded into
    %one variable

    % hw = waitbar(0,'Loading DICOM info...');
    % step_size=100;
    % q=1;
    % ind_save=[];
    % for c=1:1:numel(files)
    %     ind_save=[ind_save c];
    %     dcmInfo(q)=dicominfo(fullfile(foldername,files{c}));
    %     waitbar(c/numel(files),hw,['Loading DICIM info...',num2str(round(100.*c/numel(files))),'%']);
    %     if numel(ind_save)>=step_size
    %         waitbar(c/numel(files),hw,['Saving to MAT-file...',num2str(round(100.*c/numel(files))),'%']);
    %         matObj.dcmInfo(1,ind_save)=dcmInfo;
    %         ind_save=[];
    %         dcmInfo=[];
    %         q=1;
    %     end
    %     q=q+1;
    % end
    % matObj.dcmInfo(1,ind_save)=dcmInfo;
    % close(hw);

    %% LOADING IMAGE DATA

    if isfield(dcmInfo,'EchoTime')
        EchoTimesAll=[dcmInfo(:).EchoTime];
    else
        EchoTimesAll=nan;
    end
    EchoTimesUni=unique(EchoTimesAll);

    matObj.EchoTimesUni=EchoTimesUni;
    NumEchoTimes=numel(EchoTimesUni);

    %Get image types
    if isfield(dcmInfo,'ImageType')
        ImageTypesAll={dcmInfo.ImageType};
        checkType=1;
    else
        ImageTypesAll=repmat({'Unknown'},1,numel(files));
        checkType=0;
        warning('ImageType information missing, using Unknown as type, assuming single type');
    end

    ImageTypesUni=unique(ImageTypesAll);
    matObj.ImageTypesUni=ImageTypesUni;
    NumImageTypes=numel(ImageTypesUni);

    if isfield(dcmInfo,'TriggerTime') %Multiple dynamics
        TriggerTimesAll=[dcmInfo(:).TriggerTime];
        TriggerTimesUni=unique(TriggerTimesAll);
        NumberOfTemporalPositions=numel(TriggerTimesUni); %NumberOfPhasesMR
    else
        TriggerTimesAll=zeros(1,NumberOfFiles);
        TriggerTimesUni=unique(TriggerTimesAll);
        if isfield(dcmInfo,'NumberOfTemporalPositions') %Multiple dynamics
            NumberOfTemporalPositions=double(dcmInfo(1).NumberOfTemporalPositions);
        else
            NumberOfTemporalPositions=1;
        end
    end

    if optionStruct.ignoreDynamic==1
        NumberOfTemporalPositions=1;
    end

    NumberOfSlices=NumberOfFiles/NumImageTypes/NumEchoTimes/NumberOfTemporalPositions; %NumberOfSlicesMR
%     NumberOfFilesPerType=NumberOfSlices*NumberOfTemporalPositions;

    switch dictSetting
        case 1 %PHILIPS
            %             NumberOfRows=double(dcmInfo(1).Width);
            %             NumberOfColumns=double(dcmInfo(1).Height);
            NumberOfRows=double(dcmInfo(1).Rows);
            NumberOfColumns=double(dcmInfo(1).Columns);
        case 2 % SIEMENS
            NumberOfRows=double(dcmInfo(1).Rows);
            NumberOfColumns=double(dcmInfo(1).Columns);
        case 3 %FACTORY
            NumberOfRows=double(dcmInfo(1).Rows);
            NumberOfColumns=double(dcmInfo(1).Columns);
            %             NumberOfRows=double(dcmInfo(1).Width);
            %             NumberOfColumns=double(dcmInfo(1).Height);
    end

    %Determine image size
    ImageSize=[NumberOfRows NumberOfColumns NumberOfSlices NumberOfTemporalPositions];

    rowSelectSet=1:nDownSample(1):NumberOfRows;
    NumberOfRowsKeep=numel(rowSelectSet);
    columnSelectSet=1:nDownSample(2):NumberOfColumns;
    NumberOfColumnsKeep=numel(columnSelectSet);
    sliceSelectSet=1:nDownSample(3):NumberOfSlices;
    NumberOfSlicesKeep=numel(sliceSelectSet);

    ImageSizeKeep=[NumberOfRowsKeep NumberOfColumnsKeep NumberOfSlicesKeep NumberOfTemporalPositions];

%     %Check if slice size matching DICOM parameters
%     if sizSlice(1)~=ImageSize(1)
%         ImageSize(1)=sizSlice(1);
%         warning('Image size 2 does not match size specified in DICOM info. Using image size from image instead')
%     end
%     if sizSlice(2)~=ImageSize(2)
%         ImageSize(2)=sizSlice(2);
%         warning('Image size 2 does not match size specified in DICOM info. Using image size from image instead')
%     end

    matObj.ImageSize=ImageSizeKeep;

    NumClass=['uint',num2str(dcmInfo_full.BitsAllocated)];

    c=0;
    hw = waitbar(0,'Loading DICOM info...');

    for iEcho=1:NumEchoTimes
        %Finding files for current EchoTime
        EchoTimeNow=EchoTimesUni(iEcho); %The current echo time

        L_Echo=EchoTimesAll==EchoTimeNow;

        %String to add to type spec
        if NumEchoTimes==1
            echoNameAppend=[];
        else
            echoNameAppend=['_EchoTime_',num2str(iEcho)];
        end

        for iType=1:NumImageTypes

            %Finding files for current type
            if checkType==1
                ImageTypeNow=ImageTypesUni(iType); %The current image type
                L_Type=strcmpi(ImageTypesAll,ImageTypeNow);
            else
                L_Type=true(size(ImageTypesAll));
            end

            %Fix L_Echo in case EchoTIme is not defined
            if isnan(EchoTimesAll)
                L_Echo=true(size(L_Type));
            end

            L_now=L_Echo&L_Type;

            TypeFiles=files(L_now);
%             iStart=((iType-1)*NumberOfFilesPerType)+1; %     iEnd=iStart-1+NumberOfFilesPerType;

            TypeName=['type_',num2str(iType),echoNameAppend];
            TypeNameDcmInfo=[TypeName,'_info'];

            VarSize=(prod(ImageSizeKeep))*dcmInfo_full.BitsAllocated/8;
            if VarSize>MaxVarSize %Save to MAT-file for each temporal step
                if ImageSizeKeep(4)>1
                    matObj.(TypeName)=zeros([ImageSizeKeep(1:3) 2],NumClass);
                else
                    matObj.(TypeName)=zeros(ImageSizeKeep,NumClass);
                end
                for iTemp=1:1:NumberOfTemporalPositions
                    %Finding files for current temporal position
                    TriggerTimesType=TriggerTimesAll(L_now);%[dcmInfo(L_now).TriggerTime];
                    TriggerTime=TriggerTimesUni(iTemp);
                    L_Temp=(TriggerTimesType==TriggerTime);
                    %Creating volume by assembling slices
                    TempTypeFiles=TypeFiles(L_Temp);
                    M=zeros(ImageSizeKeep(1:3),NumClass);
                    sliceIndexResample=1;
                    for iSlice=1:nDownSample(3):numel(TempTypeFiles)

                        waitbar(c/numel(files),hw,['Loading DICIM image data...',num2str(round(100.*c/numel(files))),'%']);
                        load_name=fullfile(PathName,TempTypeFiles{iSlice});
                        m=dicomread(load_name);
                        m=m(1:nDownSample(1):end,1:nDownSample(2):end,:); %Resample
                        if size(m,3)>1
                            m=mean(double(m),3);
                            warning('Multi-dimensional (e.g. RGB) slices where converted to 2D grayscale');
                        end
                        M(:,:,sliceIndexResample)=m;

                        sliceIndexResample=sliceIndexResample+1;
                        if iSlice==1
                            c=c+1;
                        else
                            c=c+nDownSample(3);
                        end
                    end
                    waitbar(c/numel(files),hw,['Saving DICOM image data to MAT-file...',num2str(round(100.*c/numel(files))),'%']);
                    eval(['matObj.',TypeName,'(:,:,:,iTemp)=M;']);
                end
            else %create 4D array and save whole array to MAT-file
                N=zeros(ImageSizeKeep,NumClass);
                for iTemp=1:1:NumberOfTemporalPositions
                    %Finding files for current temporal position
                    TriggerTimesType=TriggerTimesAll(L_now);%[dcmInfo(L_now).TriggerTime];
                    TriggerTime=TriggerTimesUni(iTemp);
                    L_Temp=(TriggerTimesType==TriggerTime);

                    %Creating volume by assembling slices
                    TempTypeFiles=TypeFiles(L_Temp);
                    M=zeros(ImageSizeKeep(1:3),NumClass);
                    sliceIndexResample=1;
                    for iSlice=1:nDownSample(3):numel(TempTypeFiles)
                        waitbar(c/numel(files),hw,['Loading DICIM image data...',num2str(round(100.*c/numel(files))),'%']);
                        load_name=fullfile(PathName,TempTypeFiles{iSlice});
                        m=dicomread(load_name); %Current slice
                        m=m(1:nDownSample(1):end,1:nDownSample(2):end,:); %Resample
                        if size(m,3)>1
                            m=mean(double(m),3);
                            warning('Multi-dimensional (e.g. RGB) slices where converted to 2D grayscale');
                        end
                        if size(M,1)~=size(m,1)
                            M(:,:,sliceIndexResample)=m'; %Try transpose
                            if firstWarning_Rotation==0
                                warning('Image data was rotated to match expected image size!');
                                firstWarning_Rotation=1;
                            end
                        else
                            M(:,:,sliceIndexResample)=m;
                        end
                        sliceIndexResample=sliceIndexResample+1;
                        if iSlice==1
                            c=c+1;
                        else
                            c=c+nDownSample(3);
                        end
                    end
                    N(:,:,:,iTemp)=M;
                end
                waitbar(c/numel(files),hw,['Saving DICOM image data to MAT-file...',num2str(round(100.*c/numel(files))),'%']);
                eval(['matObj.',TypeName,'=N;']);
                eval(['matObj.',TypeNameDcmInfo,'=dcmInfo(L_now);']);

            end
        end
    end
    close(hw);
else
    warning(['Folder ',PathName,' skipped since it does not contain .dcm files']);
end

dicomdict('factory');

end

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


% -*- INTERNAL UNDOCUMENTED FUNCTION -*-
function sp = sp_vector_3d_piola_transform (sp1, sp2, sp3, msh)

warning ('geopdes:obsolete', 'The class SP_VECTOR_3D_PIOLA_TRANSFORM is obsolete. Using SP_VECTOR with the transformation as the last argument. Read the help for the usage')

sp = sp_vector ({sp1, sp2, sp3}, msh, 'div-preserving');


function k = get_next_char_index(str, i, c)

    k = i;
    while str(k) ~= c
        k = k + 1;
    end

end


function all_ok_ = t_run_tests(test_names, verbose)
%T_RUN_TESTS  Run a series of tests.
%   ALL_OK = T_RUN_TESTS(TEST_NAMES, VERBOSE)
%
%   Runs a set of tests whose names are given in the cell array TEST_NAMES.
%   If the optional parameter VERBOSE is true, it prints the details of the
%   individual tests. Optionally returns an ALL_OK flag, equal to 1 if all
%   tests pass (and the number matches the expected number), 0 otherwise.
%
%   Example:
%       tests{end+1} = 't_loadcase';
%       tests{end+1} = 't_jacobian';
%       tests{end+1} = 't_hessian';
%       t_run_tests( tests, verbose );
%
%   See also T_BEGIN, T_END.

%   MP-Test
%   Copyright (c) 2004-2020, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MP-Test.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/mptest for more info.

if nargin < 2
    verbose = 0;
end

global t_num_of_tests;
global t_counter;
global t_ok_cnt;
global t_not_ok_cnt;
global t_skip_cnt;

%% figure out padding for printing
if ~verbose
    len = zeros(length(test_names), 1);
    for k = 1:length(test_names)
        len(k) = length(test_names{k});
    end
    maxlen = max(len);
end

%% initialize statistics
num_of_tests = 0;
counter = 0;
ok_cnt = 0;
not_ok_cnt = 0;
skip_cnt = 0;

t0 = tic;
for k = 1:length(test_names)
    if verbose
        fprintf('\n----------  %s  ----------\n', test_names{k});
    else
        pad = maxlen + 4 - length(test_names{k});
        fprintf('%s', test_names{k});
        for m = 1:pad, fprintf('.'); end
    end
    feval( test_names{k}, ~verbose );

    num_of_tests    = num_of_tests  + t_num_of_tests;
    counter         = counter       + t_counter;
    ok_cnt          = ok_cnt        + t_ok_cnt;
    not_ok_cnt      = not_ok_cnt    + t_not_ok_cnt;
    skip_cnt        = skip_cnt      + t_skip_cnt;
end

if verbose
    fprintf('\n\n----------  Summary  ----------\n');
end
if counter == num_of_tests && counter == ok_cnt + skip_cnt && not_ok_cnt == 0
    all_ok = 1;
    if skip_cnt
        fprintf('All tests successful (%d passed, %d skipped of %d)', ...
            ok_cnt, skip_cnt, num_of_tests);
    else
        fprintf('All tests successful (%d of %d)', ok_cnt, num_of_tests);
    end
else
    all_ok = 0;
    fprintf('Ran %d of %d tests: %d passed, %d failed', ...
        counter, num_of_tests, ok_cnt, not_ok_cnt);
    if skip_cnt
        fprintf(', %d skipped', skip_cnt);
    end
end
fprintf('\nElapsed time %.2f seconds.\n', toc(t0));

if nargout
    all_ok_ = all_ok;   %% copy to optional output arg
end


% Copyright 2011 Zdenek Kalal
%
% This file is part of TLD.
%
% TLD 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.
%
% TLD 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 TLD.  If not, see <http://www.gnu.org/licenses/>.

function run_TLD

dir_names = {'06_car'};

for i = 1:numel(dir_names)
    close all;
    run_TLD_one(dir_names{i});
end

function run_TLD_one(seq_name)

addpath(genpath('.'));
init_workspace;

src_dir = sprintf('/home/yuxiang/Projects/Multiview_Tracking/dataset/TLD/%s/img/', seq_name);
dst_dir = sprintf('/home/yuxiang/Projects/Multiview_Tracking/result/OpenTLD/%s/', seq_name);

opt.source          = struct('camera',0,'input',src_dir,'bb0', []); % camera/directory swith, directory_name, initial_bounding_box (if empty, it will be selected by the user)
opt.output          = dst_dir; mkdir(opt.output); % output directory that will contain bounding boxes + confidence

min_win             = 24; % minimal size of the object's bounding box in the scanning grid, it may significantly influence speed of TLD, set it to minimal size of the object
patchsize           = [15 15]; % size of normalized patch in the object detector, larger sizes increase discriminability, must be square
fliplr              = 0; % if set to one, the model automatically learns mirrored versions of the object
maxbbox             = 1; % fraction of evaluated bounding boxes in every frame, maxbox = 0 means detector is truned off, if you don't care about speed set it to 1
update_detector     = 1; % online learning on/off, of 0 detector is trained only in the first frame and then remains fixed
opt.plot            = struct('pex',1,'nex',1,'dt',1,'confidence',1,'target',1,'replace',0,'drawoutput',3,'draw',0,'pts',1,'help', 0,'patch_rescale',1,'save',0);

% Do-not-change -----------------------------------------------------------

opt.model           = struct('min_win',min_win,'patchsize',patchsize,'fliplr',fliplr,'ncc_thesame',0.95,'valid',0.5,'num_trees',10,'num_features',13,'thr_fern',0.5,'thr_nn',0.65,'thr_nn_valid',0.7);
opt.p_par_init      = struct('num_closest',10,'num_warps',20,'noise',5,'angle',20,'shift',0.02,'scale',0.02); % synthesis of positive examples during initialization
opt.p_par_update    = struct('num_closest',10,'num_warps',10,'noise',5,'angle',10,'shift',0.02,'scale',0.02); % synthesis of positive examples during update
opt.n_par           = struct('overlap',0.2,'num_patches',100); % negative examples initialization/update
opt.tracker         = struct('occlusion',10);
opt.control         = struct('maxbbox',maxbbox,'update_detector',update_detector,'drop_img',1,'repeat',1);

% Run TLD -----------------------------------------------------------------
%profile on;
[bb,conf] = tldExample(opt);
%profile off;
%profile viewer;

% Save results ------------------------------------------------------------
dlmwrite([opt.output '/tld.txt'],[bb; conf]');
disp(['Results saved to ' dst_dir]);