function planDB = updatePlanDB(planDB, varargin)
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.
%
%"updatePlanDB"
%   Sync the plan database with contents of <path> and its subdirs.
%
%   Given a planDB (or [] if a new planDB is being created), scan <path>
%   and all subdirectories for .mat/.mat.bz2 files. If .mat files are encountered
%   that did not exist in the planDB or have been modified since the last
%   update, load them and attempt to compile a planC extract.  If files
%   exist in planDB that do not exist in <path>, flag them as not present.
%   .mat files that do not contain planCs have an extract of [] and their
%   isPlanC field is set to 0.
%
%   If a user defined function handle @<fcnName> has been specified,
%   it is executed by passing planC as the only parameter.  Output is
%   stored in the userdata field.  The 'userfiles' field is a list of
%   filenames that, if changed, require the database to recompile. This
%   should be the file(s) containing <fcnName> and its child functions.
%
%   planDB parameters 'path', 'template' and 'function' are stored in the
%   planDB and only need to be referenced after the first update if they
%   need to be changed.
%
%   JRA 11/28/03
%
%  To make new DB:
%     planDB = updateplanDB([],'path', <path>, 'template', makeTemplate, 'addfunction', @<fcnName>, <full path to function file>)
%  Update existing:
%     planDB = updateplanDB(planDB);
%  Update for new template:
%     planDB = updateplanDB(planDB, 'template', makeTemplate);

% Steps to update the database:
%    1. Parse Input Arguments        - gives path, template, and ufs
%    2. Check validity of plan path
%    3. Scan HD path for plans.

%    4. Compare found plans to stored plans:
%         i. add new plans -- keep index of new plans
%         ii. flag missing files -- keep index of missing
%         iii. flag changed files as needing update -- keep index.
%         iv. leave unchanged files alone
%
%    4. check for a template change: if changed, flag all plans to get new template.
%
%    3. Update ufs
%     i. Remove deleted ufs
%     ii. add new userfunctions
%     iii. for functions that must be recalced this run flag all plans to get recalc.
%
%
%    5. loop over plans, loading if user or template.  calc necessary stuff. Update plan timestamp at load time.

%Start timer.
updateStartTime = datestr(now);

%Check arguments.  If no args, use the internal template and path.
[path, template, userfuncts, reusePlanC] = evaluateArgs(planDB, nargin, varargin);

%Check validity of path.
if ~isdir(path)
    disp(['planDB>> ''' path ''' does not exist. All files will be flagged not present.']);
    %No matfiles exist, create empty struct.
    matFiles = struct('name', {}, 'path', {}, 'lastMod', {});
else
	%Find all the .mat and .mat.bz2 files in path.
	disp(['planDB>> Searching for .mat & .mat.bz2 files in ' path]);
	matFiles = findMatFiles(path);
    disp(['planDB>> Found ' num2str(length(matFiles)) ' .mat and .mat.bz2 files.']);
end

%Get list of archived files, get list of files found in HD scan.
[storedFileNames, presentFileNames, planDB] = getFilenameList(planDB, matFiles);

%Find indices of new files, removed files.
[newFiles newIndex] = setdiff(presentFileNames, storedFileNames);
[removedFiles removedIndex] = setdiff(storedFileNames, presentFileNames);

%Add the new files to the planDB.
disp(['planDB>> ADDING ' num2str(length(newIndex)) ' new files.']);
for i=1:length(newIndex)
    plan.extract = [];
    plan.userdata = [];
    plan.info.name = matFiles(newIndex(i)).name;
    plan.info.path = matFiles(newIndex(i)).path;
    %Leave lastMod empty so these matFiles will be updated.
    plan.info.lastMod = '';
    plan.isPlanC = [];
    plan.isPresent = 1;
    planDB.matFiles(end+1) = plan;
end

%set isPresent flag for files that no longer exist, do not remove from db.
disp(['planDB>> FLAGGING ' num2str(length(removedIndex)) ' files as missing.']);
for i=1:length(removedIndex)
    planDB.matFiles(removedIndex(i)).isPresent = 0;
end

%Refresh lists.
[storedFileNames, presentFileNames, planDB] = getFilenameList(planDB, matFiles);

%Find indices of files already existing in the database.
storedPlanInfo = [planDB.matFiles.info];
[bool, ind] = ismember(storedFileNames, presentFileNames);

ind(ind==0) = [];

%Flag modified or new files for updating.
needsFullUpdate = ~strcmp({storedPlanInfo(bool).lastMod}, {matFiles(ind).lastMod});

%set isPresent flag for all found files.
presentFiles = find(bool);
disp(['planDB>> FLAGGING ' num2str(length(presentFiles)) ' files as present.']);
for i=1:length(presentFiles)
    planDB.matFiles(presentFiles(i)).isPresent = 1;
end

%We have a fully updated file list in planDB, and a list of flags to indicate which files
%have changed or been added at this point in needsFullUpdate.

%Find which userfunctions have changed or been added, and need calculation.
[ufChanged, planDB] = userFilesChanged(planDB, userfuncts);
changed = find(ufChanged);

%Some output statements for the kids.
if ~isempty(changed)
    string = [];
    for i = 1:length(changed)
        string = [string ' ' planDB.userfunctions(changed(i)).fHandle];
    end
    if length(changed) == 1
        plural = '';
        verb = ' is';
    else
        plural = 's';
        verb = ' are';
    end
    disp(['planDB>> User function' plural string verb ' new or changed and requires calculation.']);
end

%Create a boolean matrix where each row is a plan and each column a
%userfunction.  If userfunction 3 for matFile 5 is true, calculate that
%user function for matFile 5.  New user functions are flagged true for all
%plans, as all plans need this new function calculated.  For new or changed
%plans, flag all userfunctions as needing calculation.
refreshUD = repmat(ufChanged, length(planDB.matFiles), 1);
refreshUD(needsFullUpdate,:) = 1;

%Create a similar boolean vector to refresh template.
refreshTemplate = zeros(length(planDB.matFiles), 1);
refreshTemplate(needsFullUpdate) = 1;

%If template has changed, all plans need template refreshed.
if isfield(planDB, 'template')
	templateExpired = ~isempty(setxor(template, planDB.template));
else
    templateExpired = 1;
end
if templateExpired
    planDB.template = template;
    refreshTemplate = ones(length(planDB.matFiles),1);
end

%Now iterate over all files in planDB.matFiles.  If a matFile is a plan,
%check if it requires its extract or any userfunctions to be recalculated
%by looking at refreshTemplate and refreshUD.  If so, load the plan and
%calculate only what needs refreshing.
for i=1:length(planDB.matFiles)
    plan = planDB.matFiles(i);
    if plan.isPresent
        %If any changes, load the plan.
        fullfilename = fullfile(planDB.matFiles(i).info.path,planDB.matFiles(i).info.name);
        if any([refreshTemplate(i) refreshUD(i,:)])
            disp(['planDB>> UPDATE ' planDB.matFiles(i).info.name]);

            tic
            if reusePlanC
                global planC
            end
            planC = loadPlan(fullfilename);
            disp(['      >> Loaded in ' num2str(toc) 's']);
        end

        if refreshTemplate(i)
            tic
            plan.extract = compileExtract(planC, template);
            disp(['      >> Extracted in ' num2str(toc) 's']);
        end

        for j=1:size(refreshUD, 2)
            if refreshUD(i, j)
                tic
                plan.userdata{j} = compileUser(planC, str2func(planDB.userfunctions(j).fHandle));
                disp(['      >> User function ' planDB.userfunctions(j).fHandle ' run in ' num2str(toc) 's']);
            end
        end
        info = dir(fullfilename);
        %Set timestamp to detect future modifications.
        plan.info.lastMod = info.date;
        %If no extract, file is not a planC.
        plan.isPlanC = ~isempty(plan.extract);
        planDB.matFiles(i) = plan;
    end
end

%PlanDB is now fully updated.  Stamp.
updateEndTime = datestr(now);

planDB.lastUpdateStart = updateStartTime;
planDB.lastUpdateEnd = updateEndTime;
planDB.template = template;
planDB.path = path;

%Build the index of fieldnames into plans, for database browsing.
planDB.fieldIndex = compileFieldnameIndex(planDB.matFiles);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function extract = compileExtract(planC, template)
%Make an extract out of the planC if it is not [].
if isempty(planC)
   extract = [];
   return;
else
   extract = makeExtract(planC, template);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function userdata = compileUser(planC, fHandle);
%Run user function if it exists, store returend data.
if isempty(fHandle) | isempty(planC)
    userdata = [];
    return;
else
    userdata = feval(fHandle, planC);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function planC = loadPlan(filename)
%Load the .mat file and check if a planC exists in the workspace.
%If it does, return planC, else return [].  Also handles .bz2 by extracting
%to a tempfile in the tempDirectory and deleting when finished.
compressed = 0;

oldPathStr = pwd;
newPathStr = getCERRPath;

if strcmpi(filename(end-3:end), '.bz2')
    %Is compressed.  Decompress and load. LEAVE original file.
    cd(newPathStr);
    cd('Compression');
    compressed = 1;
    tempFile = fullfile(tempdir, 'temp.mat');
    if ispc
        dos(['bzip2-102-x86-win32.exe -vdkc "', filename, '">> ' tempFile]);
    elseif isunix
        unix(['bzip2 -dck ', filename, ' > ' tempFile]);
    end
    filename = tempFile;
    cd(oldPathStr);
end

clear planC;
try
    load(filename);
catch
    planC = []; %fileload has failed. return.
    return;
end

if compressed
    try
        delete(tempFile);
    end
end

if ~exist('planC')
    planC = [];
    return;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [path, template, userfunctions, reusePlanC] = evaluateArgs(planDB, nargs, vargs)
% Evaluated passed arguments, returning parameters needed to run update.
ufs = [];
oldfHandle = 0;

%Grab old values if they exist.
try,    path        = planDB.path;                 ,end
try,    template    = planDB.template;             ,end
try,    ufs         = planDB.userfunctions;        ,end

reusePlanC = 0;

i = 1;
while i <= nargs-1
    switch vargs{i}
        case 'path'
            %Overwrite path if a new one is specified.
            path = vargs{i+1};
            i = i + 2;
        case 'template'
            %Overwrite template if a new one is specified.
            template = vargs{i+1};
            i = i + 2;
        case 'delfunction'
            %Scrap the specified user function.
            [jnk, ind] = intersect({ufs.fHandle} , func2str(vargs{i+1}));
            ufs(ind) = [];
            i = i + 2;
        case 'addfunction'
            %Add the new user function and userfiles list.

            %First check if it already exists.
            if isfield(ufs, 'fHandle')
                [jnk, ind] = intersect({ufs.fHandle} , func2str(vargs{i+1}));
            else
                jnk = [];
            end
            if ~isempty(jnk)
                warning(['User function ' func2str(vargs{i+1}) ' already exists. Overwriting old associated userfiles.']);
            else
                ind = length(ufs) + 1;
            end
            ufs(ind).fHandle = func2str(vargs{i+1});
            ufs(ind).files = vargs{i+2};
            if ~iscell(ufs(ind).files)
                ufs(ind).files = {ufs(ind).files};
            end
            ufs(ind).date = [];
            i = i + 3;
        case 'reusePlanC'
            i = i + 1;
            reusePlanC = 1;
        otherwise
            error('Invalid Call');
    end
end
userfunctions = ufs;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [storedFileNames, presentFileNames, planDB] = getFilenameList(planDB, matFiles);
%Returns a list of matfiles on the local HD and a list of matfiles stored in the planDB
if ~isempty(planDB) & isfield(planDB, 'matFiles')
	for i=1:length(planDB.matFiles)
        storedFileNames{i} = fullfile(planDB.matFiles(i).info.path, planDB.matFiles(i).info.name);
	end
else
    planDB.matFiles = struct('extract', {}, 'userdata', {}, 'info', {}, 'isPlanC', {}, 'isPresent', {});
    storedFileNames = {};
end
for i=1:length(matFiles)
    presentFileNames{i} = fullfile(matFiles(i).path,matFiles(i).name);
end
%Filenames/directories are caps insensitive and caps inconsistent on pc.
%Uppercase them for purposes of name comparison.
if (ispc)
    presentFileNames = upper(presentFileNames);
    storedFileNames = upper(storedFileNames);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [changed, planDB] = userFilesChanged(planDB, userfuncts)
%Returns a vector of userFile sets that have been modified. Also returns planDB with
%the userfiletime field changed.

%Array of flags to indicate if any userfiles have changed.
changed = zeros(1,length(userfuncts));

if isfield(planDB, 'userfunctions')
    oldFuncts = planDB.userfunctions;

    %Get indices of userfunctions that has been removed.
    [diff,ind] = setdiff({planDB.userfunctions.fHandle}, {userfuncts.fHandle});

    %Delete old userdata.
    for i=1:length(planDB.matFiles)
        planDB.matFiles(i).userdata(ind) = [];
    end
    planDB.userfunctions(ind) = [];

    %Get indices of new userfunctions, add to planDB.
    [newDiff, newInd] = setdiff({userfuncts.fHandle}, {planDB.userfunctions.fHandle});
    planDB.userfunctions(end+1:end+length(newDiff)) = userfuncts(newInd);

    %Flag these new userfuncs as needing calculation.
    [diff,ind] = setdiff({planDB.userfunctions.fHandle}, {userfuncts.fHandle});
    changed(ind) = 1;
else
    %All userfunctions are new, update all.
    planDB.userfunctions = userfuncts;
    changed = ones(1,length(userfuncts));
end

%Check and update userfile timestamps
for j = 1:length(planDB.userfunctions)
    files = planDB.userfunctions(j).files;
	fileInfo = struct('name', {}, 'date', {}, 'bytes', {}, 'isdir', {});

	for i=1:length(files)
        fileInfo(end+1) = dir(files{i});
	end

	%Has file list changed? If so flag as needing recalculation.
	if ~isfield(planDB.userfunctions, 'files') | ~isfield(planDB.userfunctions, 'date')
        changed(j) = 1;
    elseif ~isequal(length(files), length(planDB.userfunctions(j).files))
        changed(j) = 1;
	elseif ~isempty(setxor(files, planDB.userfunctions(j).files))
        changed(j) = 1;
	elseif ~isequal({fileInfo.date}, planDB.userfunctions(j).date)
        changed(j) = 1;
	end

    %Save current timestamp info.
	if changed(j)
        files = files;
        planDB.userfunctions(j).date = {fileInfo.date};
    end

end


function etaButtonCallback(blockHandle)
% Callback function for ETAButton
% Allows user to specify what .mat file to use for elevationImport wave type

    [filename,filepath] = uigetfile('.mat');               % Return filename, filepath of user-chosen file
    % Don't set value if no file is chosen, or prompt canceled.
    if ~isequal(filename,0) && ~isequal(filepath,0)
        mask = Simulink.Mask.get(blockHandle);
        fileParam = mask.getParameter('elevationFile');
        fileParam.Value = [filepath,filename];             % Update elevationFile with new filename
    end
end


function as_l_d
%
%  Deletes the global data that has been generated by 'as_l_i'.
%
%  Calling sequence:
%
%    as_l_d
%
%
%  LYAPACK 1.0 (Thilo Penzl, May 1999)

global LP_U

clear global LP_U


function [headername, dataname, fid] = write_text(D, varargin)
% "Flatten" dataset and write text files with header and data
% For all Event-level and Subject-level data.  Files are created in the
% current working directory.
%
% :Usage:
% ::
%
%    function [headername, dataname, fid] = write_text(D, [optional inputs])
%
% ..
%     Author and copyright information:
%
%     Copyright (C) 2013 Tor Wager
%
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%     GNU General Public License for more details.
%
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <http://www.gnu.org/licenses/>.
% ..
%
%
% :Inputs:
%
%   **D:**
%        a canlab_dataset object
%
% :Optional Inputs:
%    the first varargin parameter is the delimiter. Comma-delimited by default.
%    the second varargin parameter is a logical vector of subjects to use. All subjects by default.
%
%
% :Outputs:
%
%   **headername:**
%        filename of header output file
%
%   **dataname:**
%        filename of data output file
%
%   **fid:**
%        file ID (currently does not look to be used)
%

delim = ','; % flesh this out later as needed
wh_keep = true(size(D.Subj_Level.id));

if nargin > 1, delim = varargin{1}; end
if nargin > 2, wh_keep = varargin{2}; end

% Checks
% ----------------------------------------------------------------------
for i = 1:length(D.Subj_Level.names)

    if length(D.Subj_Level.descrip) < i
        D.Subj_Level.descrip{i} = 'No description provided';
    end

end

for i = 1:length(D.Event_Level.names)

    if length(D.Event_Level.descrip) < i
        D.Event_Level.descrip{i} = 'No description provided';
    end

end

if isempty(D.Event_Level.data)
    D.Event_Level.data = cell(1,length(D.Subj_Level.id));
end

if isempty(D.Event_Level.names)
    D.Event_Level.names = {};
end

% Open Files
% ----------------------------------------------------------------------
headername = [D.Description.Experiment_Name '_info_' scn_get_datetime '.txt'];
dataname = [D.Description.Experiment_Name '_data_' scn_get_datetime '.csv'];
fid = fopen(headername, 'w');

% Write Header
% ----------------------------------------------------------------------

u = '______________________________________________________________';

fprintf(fid, 'Experiment: %s\n', D.Description.Experiment_Name);

fprintf(fid, '\n%d subjects\n', length(D.Subj_Level.id));
fprintf(fid, 'Missing values coded with: %f\n', D.Description.Missing_Values);
fprintf(fid, '%s\n', u);

fprintf(fid, 'Subject Level\n\n');
fprintf(fid, 'Description:\n');

for i = 1:length(D.Description.Subj_Level)
    fprintf(fid, '\t%s\n', D.Description.Subj_Level{i});
end

fprintf(fid, 'Names:\n');
for i = 1:length(D.Subj_Level.names)
    fprintf(fid, '\t%s\t%s\n', D.Subj_Level.names{i}, D.Subj_Level.descrip{i});
end

fprintf(fid, '%s\n', u);

fprintf(fid, 'Event Level\n\n');
fprintf(fid, 'Description:\n');

for i = 1:length(D.Description.Event_Level)
    fprintf(fid, '\t%s\n', D.Description.Event_Level{i});
end

fprintf(fid, 'Names:\n');
for i = 1:length(D.Event_Level.names)
    fprintf(fid, '\t%s\t%s\n', D.Event_Level.names{i}, D.Event_Level.descrip{i});
end

fprintf(fid, '%s\n', u);

fclose(fid);

%% Write subj-level & event-level data
% -----------------------------------------------------------------------

fid = fopen(dataname, 'w');

if isempty(D.Event_Level.names)
    names = {'id' D.Subj_Level.names{:}};
else
    names = {'id' D.Subj_Level.names{:} 'Event_number' D.Event_Level.names{:}};
end

n = length(D.Subj_Level.id);

%slevels = length(D.Subj_Level.names);

printcell = @(x) fprintf(fid, ['%s' delim], x);
cellfun(printcell, names);
fprintf(fid, '\n');

for i = 1:n  % for each subject

    if ~wh_keep(i), continue; end % skip this subj

    e = size(D.Event_Level.data{i}, 1);

    if e==0 % no events
        fprintf(fid, ['%s' delim], D.Subj_Level.id{i});  % ID, can be char
        datarow = [D.Subj_Level.data(i, :)];
        printrow(fid, datarow, delim);
    else
        for j = 1:e  % for events within subject
            fprintf(fid, ['%s' delim], D.Subj_Level.id{i});  % ID, can be char
            datarow = [D.Subj_Level.data(i, :) j D.Event_Level.data{i}(j, :)];
            printrow(fid, datarow, delim);

        end  % events
    end
end  % subjects

fclose(fid);

end % function

function printrow(fid, datarow, delim)
    % Could switch by datatype in a better way here!!  need datatype codes in dataset.
    for k = 1:length(datarow)
        if datarow(k) == round(datarow(k))
            fprintf(fid, ['%d' delim], datarow(k));
        else
            fprintf(fid, ['%3.3f' delim], datarow(k));
        end
    end % row

    fprintf(fid, '\n');
end


function write_images_to_webrtDB(patient_id)

global stateS planC
indexS = planC{end};

% absolutePathForImageFiles = fullfile('/Users/aptea/Documents/MSKCC/Projects/webRT',['patient_',num2str(patient_id)]);

absolutePathForImageFiles = fullfile('/Volumes/DeasyLab3/Repository/RIVIEW',['patient_',num2str(patient_id)]);

% Open planC in CERR viewer
if isfield(stateS,'handle')
    hCSV = stateS.handle.CERRSliceViewer;
else
    hCSV = [];
end
if isempty(hCSV) || ~exist('hCSV') || ~ishandle(hCSV)
    CERR('CERRSLICEVIEWER')
end

stateS.CTToggle = 1;
stateS.CTDisplayChanged = 1;
sliceCallBack('OPENWORKSPACEPLANC')

% Capture Scan Images and store pointers in DB

%Find the scan with scanUID matching this scan's CERR scan UID

for scanNum = 1:length(planC{indexS.scan})

    % Write scan images to file
    write_scan_images_to_disk(absolutePathForImageFiles,scanNum,'transverse')
    write_scan_images_to_disk(absolutePathForImageFiles,scanNum,'coronal')
    write_scan_images_to_disk(absolutePathForImageFiles,scanNum,'sagittal')

    % Write dose images to file
    dosesV = getScanAssociatedDose(scanNum,'all');
    for doseNum = dosesV
        write_dose_images_to_disk(absolutePathForImageFiles,doseNum,scanNum,'transverse')
        write_dose_images_to_disk(absolutePathForImageFiles,doseNum,scanNum,'coronal')
        write_dose_images_to_disk(absolutePathForImageFiles,doseNum,scanNum,'sagittal')
    end

%     % Toggle plane locators off
%
%     % Display Transverse View in larger window
%
%     % Toggle Dose off
%
%     % Toggle Structures off
%
%     % Capture Axis and save scan as png file
%
%     % Toggle Dose on
%
%     % Toggle Scan off
%
%     % Capture Axis and save dose as png file
%
%
%     % Find structures associated to this scan
%     assocScanV = getStructureAssociatedScan(1:numStructs);
%     structsInScanV = find(assocScanV == scanNum);
%
%     % Loop over structures to store contours in the database
%
%     for structNum = structsInScanV
%
%         px = axes2pix(ncols,xLim,planC{indexS.structures}(12).contour(74).segments.points(:,1));
%         py = axes2pix(nrows,-yLim,planC{indexS.structures}(12).contour(74).segments.points(:,2));
%         ptsM = [px py];
%         aa = ptsM';
%         mat2str(aa(:))
%
%     end

end


function display(sAF,varargin)
% standard output

displayClass(sAF,inputname(1),varargin{:});

disp([' bandwidth: ' num2str(sAF.sF.bandwidth)]);

if sAF.sF.antipodal, disp(' antipodal: true'); end

end


any(cellfun(@exist,{'lsl_pull_sample_buf', 'lsl_loadlib_', 'lsl_push_sample'})==3)


function trackers = config_tracker()
% config trackers to be evaluated
trackers = {struct('name', 'BACF',       'publish', 'ICCV-17') ...
            struct('name', 'CFNet',      'publish', 'CVPR-17') ...
            struct('name', 'CN',         'publish', 'CVPR-14') ...
            struct('name', 'CSK',        'publish', 'ECCV-12') ...
            struct('name', 'CSRDCF',     'publish', 'CVPR-17') ...
            struct('name', 'ASLA',       'publish', 'CVPR-12') ...
            struct('name', 'CT',         'publish', 'ECCV-12') ...
            struct('name', 'DSiam',      'publish', 'ICCV-17') ...
            struct('name', 'DSST',       'publish', 'BMVC-14') ...
            struct('name', 'ECO_HC',     'publish', 'CVPR-17') ...
            struct('name', 'ECO',        'publish', 'CVPR-17') ...
            struct('name', 'HCFT',       'publish', 'ICCV-15') ...
            struct('name', 'fDSST',      'publish', 'TPAMI-17')...
            struct('name', 'PTAV',       'publish', 'ICCV-17')...
            struct('name', 'IVT',        'publish', 'IJCV-08') ...
            struct('name', 'KCF',        'publish', 'TPAMI-15')...
            struct('name', 'L1APG',      'publish', 'CVPR-12') ...
            struct('name', 'LCT',        'publish', 'CVPR-15') ...
            struct('name', 'MEEM',       'publish', 'ECCV-14') ...
            struct('name', 'MIL',        'publish', 'CVPR-09') ...
            struct('name', 'SAMF',       'publish', 'ECCVW-14')...
            struct('name', 'SCT4',       'publish', 'CVPR-16') ...
            struct('name', 'SiamFC',     'publish', 'ECCVW-16')...
            struct('name', 'SINT',       'publish', 'CVPR-16') ...
            struct('name', 'SRDCF',      'publish', 'ICCV-15') ...
            struct('name', 'Staple_CA',  'publish', 'CVPR-17')...
            struct('name', 'Staple',     'publish', 'CVPR-16')...
            struct('name', 'STC',        'publish', 'ECCV-14') ...
            struct('name', 'STRCF',      'publish', 'CVPR-18') ...
            struct('name', 'Struck',     'publish', 'TPAMI-16')...
            struct('name', 'TLD',        'publish', 'TPAMI-12')...
            struct('name', 'MDNet',      'publish', 'CVPR-16')...
            struct('name', 'StructSiam', 'publish', 'ECCV-18')...
            struct('name', 'VITAL',      'publish', 'CVPR-18')...
            struct('name', 'TRACA',      'publish', 'CVPR-18')};
end


%{
    Copyright (C) Cambridge Electronic Design Limited 2014
    Author: James Thompson
    Web: www.ced.co.uk email: james@ced.co.uk, softhelp@ced.co.uk

    This file is part of CEDS64ML, a MATLAB interface to the SON64 library.

    CEDS64ML 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.

    CEDS64ML 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 CEDS64ML.  If not, see <http://www.gnu.org/licenses/>.
%}

function [ iOk, sTitleOut ] = CEDS64ChanTitle( fhand, iChan, sTitleIn )
%CEDS64CHANTITLE Gets and sets a channel title
%   [ iOk, sTitleOut ] = CEDS64ChanTitle( fhand, iChan {, sTitleIn} )
%   Input
%   fhand - An integer handle to an open file
%   iChan - A channel number
%   sTitleIn - (Optional) A string containing the new title
%   Output
%   iOk - 0 if the title was set correctly otherwise a negative error code
%   sTitleOut - A string containing the old title

if (nargin == 2 || nargin == 3) % always get the old title
    %step 1 find out how big the title is is
    dummystring = blanks(1);
    [iSize] = calllib('ceds64int', 'S64GetChanTitle', fhand, iChan, dummystring, -1);
    %step 2 create a string buffer of the correct size
    stringptr = blanks(iSize+1);
    [iOk, sTitleOut] = calllib('ceds64int', 'S64GetChanTitle', fhand, iChan, stringptr, 0);
else
    iOk = -22;
end

% has there been an error?
if iOk < 0
    return;
end

% if not set the new title if we're given one
if (nargin == 3)
iOk = calllib('ceds64int', 'S64SetChanTitle', fhand, iChan, sTitleIn);
end
end


% readbvconf() - read Brain Vision Data Exchange format configuration
%                file
%
% Usage:
%   >> CONF = readbvconf(pathname, filename);
%
% Inputs:
%   pathname  - path to file
%   filename  - filename
%
% Outputs:
%   CONF      - structure configuration
%
% Author: Andreas Widmann, University of Leipzig, 2007

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

% $Id: readbvconf.m 44 2009-11-12 02:00:56Z arnodelorme $

function CONF = readbvconf(pathname, filename)

if nargin < 2
    error('Not enough input arguments');
end

% Open and read file
[IN, message] = fopen(fullfile(pathname, filename));
if IN == -1
    [IN, message] = fopen(fullfile(pathname, lower(filename)));
    if IN == -1
        error(message)
    end;
end
raw={};
while ~feof(IN)
    raw = [raw; {fgetl(IN)}];
end
fclose(IN);

% Remove comments and empty lines
raw(strmatch(';', raw)) = [];
raw(cellfun('isempty', raw) == true) = [];

% Find sections
sectionArray = [strmatch('[', raw)' length(raw) + 1];
for iSection = 1:length(sectionArray) - 1

    % Convert section name
    fieldName = lower(char(strread(raw{sectionArray(iSection)}, '[%s', 'delimiter', ']')));
    fieldName(isspace(fieldName) == true) = [];

    % Fill structure with parameter value pairs
    switch fieldName
        case {'commoninfos' 'binaryinfos'}
            for line = sectionArray(iSection) + 1:sectionArray(iSection + 1) - 1
                splitArray = strfind(raw{line}, '=');
                CONF.(fieldName).(lower(raw{line}(1:splitArray(1) - 1))) = raw{line}(splitArray(1) + 1:end);
            end
        case {'channelinfos' 'coordinates'}
            for line = sectionArray(iSection) + 1:sectionArray(iSection + 1) - 1
                splitArray = strfind(raw{line}, '=');
                tmp = str2num(strtrim(raw{line}(3:splitArray(1) - 1)));
                if isempty(tmp)
                    tmp = NaN; end
                CONF.(fieldName)(tmp) = {raw{line}(splitArray(1) + 1:end)};
            end
        case {'markerinfos'} % Allow discontinuity for markers (but not channelinfos and coordinates!)
            for line = sectionArray(iSection) + 1:sectionArray(iSection + 1) - 1
                splitArray = strfind(raw{line}, '=');
                tmp = str2num(strtrim(raw{line}(3:splitArray(1) - 1)));
                if isempty(tmp)
                    tmp = NaN; end
                CONF.(fieldName)(line - sectionArray(iSection), :) = {raw{line}(splitArray(1) + 1:end) tmp};
            end
            if ~all(1:size(CONF.(fieldName), 1) == [CONF.(fieldName){:, 2}])
                warning('Marker number discontinuity.')
            end
        case 'comment'
            CONF.(fieldName) = raw(sectionArray(iSection) + 1:sectionArray(iSection + 1) - 1);
    end
end


function YamlStruct = ReadYaml(yaml_file)
% This function reads Yaml file into struct
% Example
% >> yaml_file = 'EnaspolMain.yaml';
% >> YamlStruct = ReadYaml(yaml_file)
%
%  %======================================================================
%{
		Copyright (c) 2011
		This program is a result of a joined cooperation of Energocentrum
		PLUS, s.r.o. and Czech Technical University (CTU) in Prague.
        The program is maintained by Energocentrum PLUS, s.r.o. and
        licensed under the terms of MIT license. Full text of the license
        is included in the program release.

        Author(s):
		Jiri Cigler, Dept. of Control Engineering, CTU Prague
		Jan  Siroky, Energocentrum PLUS s.r.o.

        Implementation and Revisions:

        Auth  Date        Description of change
        ----  ---------   -------------------------------------------------
        jc    01-Mar-11   First implementation
        jc    02-Mar-11   .jar package initialization moved to external fun
        jc    18-Mar-11   Warning added when imported file not found
%}
%======================================================================

import prtExternal.yaml.*;

%InitYaml();
packagePath = fullfile(prtRoot,'+prtExternal','+yaml','YAMLMatlab','external-packages','snakeyaml');
jarPath = fullfile(packagePath,'snakeyaml-1.8.jar');

v = strfind(javaclasspath,packagePath);
if isempty(v) || isempty(v{1})
    javaaddpath(jarPath)
end
import('org.yaml.snakeyaml.Yaml');

yamlreader = Yaml();
yml = fileread(yaml_file);
if isempty(yml)
    YamlStruct = repmat(struct,0,0);
    return;
end
jymlobj = yamlreader.load(yml);

Data = Hash2Struct(jymlobj);
work_folder=fileparts(yaml_file);
if isfield(Data,'import')
    yml = '';
    for i=1:numel(Data.import)
        fToImport= fullfile(work_folder,Data.import{i});
        try
            fxx=fileread(fToImport);
            yml=sprintf('%s\n%s',yml,  fxx);
        catch %#ok<CTCH>
            warning('YAMLMatlab:FileNotFoundException','YAMLMatlab: File %s not found',fToImport);
        end
    end
    jymlobj = yamlreader.load(yml);
    YamlStruct = Hash2Struct(jymlobj);
else
    YamlStruct = Data;
end


function [idx,fstr] = PVcipmatch(clist,str)
% function [Idx,Fstr] = PVcipmatch(Clist,Str)
%
% DESCRIPTION
%   Case insensitive partial match.
%
% INPUTS
%   Clist:
%   Str:
%
% OUTPUTS
%   Idx:
%   Fstr:
%
% SYNTAX
%   [Idx,Fstr] = PVcipmatch(Clist,Str)

% 6/7/2002: Written by Packard

lstr = length(str);
tf = find(strncmpi(clist,str,lstr));
if length(tf)==1
    idx = tf;
    fstr = clist{idx};
elseif isempty(tf)
    idx = [];
    fstr = [];
else
    cnt = 0;
    for i=1:length(tf)
        if length(clist{tf(i)})==lstr
            tfuse = tf(i);
            cnt = cnt + 1;
        end
    end
    if cnt==1
        idx = tfuse;
        fstr = clist{idx};
    else
        tf = find(strncmp(clist,str,lstr));
        if length(tf)==1
            idx = tf;
            fstr = clist{idx};
        elseif isempty(tf)
            idx = [];
            fstr = [];
        else
            cnt = 0;
            for i=1:length(tf)
                if length(clist{tf(i)})==lstr
                    tfuse = tf(i);
                    cnt = cnt + 1;
                end
            end
            if cnt==1
                idx = tfuse;
                fstr = clist{idx};
            else
                error(['Ambiguous property: ''' str '''.']);
            end
        end
    end
end


function dicom_tarzip(varargin)
% tars all .dcm files in subdirectories you specify, and deletes the
% original .dcm files if successful.
%
% :Inputs:
%
%   none (default): all directories under the current one
%   directory wildcard, e.g., 'run*' to search only those subdirectories.
%   absolute path names should also be ok.
%
% :Examples:
% ::
%
%    dicom_tarzip
%
%    dicom_tarzip('18*')
%
% Or, let's say you have runs within subjects, and dicom files within run dirs.
% Subject dirs all start with NSF*.  run dirs all start with 18*
% Starting from the directory above subjects, you could do this to zip ALL subjects:
% ::
%
%    subjdirs = dir('NSF*');
%    for s = 1:length(subjdirs)
%        dicom_tarzip([subjdirs(s).name filesep '18*']);
%    end
%
% Needless to say, use this with extreme caution, as it deletes your original files.
% And test it thoroughly with a backup dataset first!!
%
% ..
%    Note: Ash's checksum program would be very useful to add here.
% ..

dirwildcard = '*';

if ~isempty(varargin), dirwildcard = varargin{1}; end

prevwd = pwd;

% list directories

d = dir(dirwildcard);

isd = cat(1, d.isdir);
d = d(isd);
d(strmatch('.', char(d.name))) = [];  % exclude . dirs

if isempty(d)
    fprintf('No matching directories for %s. Quitting.\n', dirwildcard);
    cd(prevwd);
    return
else
    disp('Working on directories:')
    disp(char(d.name))
    disp('  ')
end

basedir = fullfile(pwd, fileparts(dirwildcard));
% % dir returns relative paths, so go there if we have a path name for a
% % wildcard
% if ~isdir(basedir)
%     fprintf('%s is not a directory. Quitting.\n\n', basedir);
%     return
% end
if ~isempty(basedir), cd(basedir); end  % this would be the subject directory if a path name was entered as a wildcard
fprintf('Working in dir: %s\n', basedir)

for i = 1:length(d)

    dicomtarname = [d(i).name filesep d(i).name '_dicoms.tar'];

    fprintf('Working on: %s.\n', dicomtarname);

    if exist(dicomtarname, 'file')
        fprintf('%s already exists!!! Skipping.\n\n', dicomtarname);
        continue
    end

    str = ['!tar cvf ' dicomtarname ' ' d(i).name filesep '*dcm >& tarchecktmp.txt  > tarfilelisttmp.txt'];
    disp(str)
    eval(str)
    errchk = fileread('tarchecktmp.txt');
    isok = isempty(strfind(errchk, 'Error'));

    if ~isok
        fprintf('Error in creating: %s .\n', dicomtarname);
        disp(errchk)
        disp('Removing failed tar archive.')
        str = ['!rm ' dicomtarname];
        disp(str)
        eval(str)

    else
        % remove original files
        fprintf('%s created successfully. Checking number of files...\n', dicomtarname);

        % check length/files
        % TOO LONG str = ['!tar -t ' dicomtarname ' > tarchecktmp.txt'];
        %filelist = fileread('tarfilelisttmp.txt');
        fid = fopen('tarfilelisttmp.txt');
        filelist = textscan(fid, '%s');
        fclose(fid);
        filelist = filelist{1};
        nfiles = length(filelist);

        dd = dir([d(i).name filesep '*dcm']);
        nfiles2 = length(dd);

        if nfiles == nfiles2
            fprintf('tar archive contains %3.0f files.\n', nfiles);
            fprintf('Removing originals.\n');
            str = ['!rm ' d(i).name filesep '*dcm'];
            disp(str)
            eval(str)
            disp('   ')
        else
            fprintf('tar archive contains %3.0f files, but counted %3.0f that should be there.\n', nfiles, nfiles2);
            disp('Check this. Not removing originals.');
        end

    end

    !rm tarchecktmp.txt
    !rm tarfilelisttmp.txt

    disp('   ')

end

if ~isempty(basedir), cd(prevwd); end

end % main function

%dcmf = filenames([d(i).name filesep '*dcm'], 'char');

%%
% dcmf2 = [];
% if ~isempty(dcmf)
%     for ff = 1:size(dcmf, 1)
%        dcmf2 = strcat(dcmf2, [dcmf(ff, :) ' ']);
%     end
%
% end
% str = ['!tar cvf ' d(i).name '_dicoms.tar ' dcmf2];


classdef Event < Data
    properties (Access = public)
        sample;
        label;
    end

    methods (Access = public)
        function obj = Event(sample,label)
            if nargin == 2
                obj.sample = sample;
                obj.label = label;
            end
            obj.type = DataType.kEvent;
        end
    end

    methods (Access = public, Static)

        %creates an array of events with the provided locations and an
        %empty label
        function events = EventsArrayWithEventLocations(eventLocations)
            nEvents = length(eventLocations);
            events = repmat(Event,1,nEvents);

            for i = 1 : nEvents
                eventLocation = eventLocations(i);
                events(i) = Event(eventLocation,[]);
            end
        end
    end
end


function [] = prints(a,b)
%
%
%     Print Simulink model as EPS-file to the current working directory
%
%     Syntax: PRINTS('FILENAME','<OPTION>')
%
%     Filename must be given without extension, e.g. 'MyFile'.
%
%     Options: p = Portrait, l = Landscape
%     No option returns the default 'Portrait' paperorientation.
%
%     Written by Bjřrn R. Sřrensen (1997)
%     Narvik Institute of Technology
%     N-8505 Norway
%     E-mail: brs@hin.no
%
%     Tested on versions 5.0-5.3 of Matlab (simulink 3.0)
%
%
filename=[a];
if nargin==2
   if b=='p'
      % Set 'Paper orientation' 'Portrait'
      set_param(filename, 'PaperOrientation','Portrait');
   end;
   if b=='l'
      % Set 'Paper orientation' 'Landscape'
      set_param(filename, 'PaperOrientation','Landscape');
   end;
end;
if nargin==1
   set_param(filename, 'PaperOrientation','Portrait');
end;
eval(['print -deps -s ', filename]);


function outputFormatOK = changeCbMapOutput(outputFormat)
%changeCbMapOutput sets the output format for drawCbMap. Displays
%outputFormat if no inputs provided.
%
% outputFormatOK = changeCbMapOutput(outputFormat)
%
%OPTIONAL INPUT
% outputFormat      drawCbMap render format
%                   {'svg', 'matlab', 'java'} (java not implemented)
%OUTPUT
% outputFormatOK    True if output format set properly, else false.
%
%

global CB_MAP_OUTPUT

%% List output format if no inputs
if nargin <1
    outputFormatOK = 0;
    fprintf('CB map output set to : %s\n',CB_MAP_OUTPUT);
    return;
end

%% List supported output here
supportedOutput = {'matlab','svg'};

%% Set CB_MAP_OUTPUT if outputFormat is supported
if any(strcmpi(outputFormat,supportedOutput))
    CB_MAP_OUTPUT = outputFormat;
    outputFormatOK = 1;
else
    warning([outputFormat ' is not a supported render format.']);
    outputFormatOK = 0;
end


function param = gpReversibleDynamicsExtractParam(model)

% GPREVERSIBLEDYNAMICSEXTRACTPARAM Extract parameters from the GP reversible dynamics model.

% FGPLVM

param = gpDynamicsExtractParam(model);


base64 = org.apache.commons.codec.binary.Base64;
tsv_file = 'MsCelebV1-Faces-Cropped.tsv';

root_folder = 'data';
mkdir(root_folder);

tsv_fid = fopen(tsv_file, 'r');
total_lines = 8456240;
image_id = 0;

pdollar_toolbox_path='D:/face project/pdollar-toolbox';
addpath(genpath(pdollar_toolbox_path));

MTCNN_path = 'D:\face project\MTCNN_face_detection_alignment\code\codes\MTCNNv2';
caffe_model_path=[MTCNN_path , '/model'];
addpath(genpath(MTCNN_path));

coord5points = [30.2946, 65.5318, 48.0252, 33.5493, 62.7299; ...
                51.6963, 51.5014, 71.7366, 92.3655, 92.2041];
imgSize = [112, 96];

%caffe.set_mode_cpu();
gpu_id=0;
caffe.set_mode_gpu();
caffe.set_device(gpu_id);
caffe.reset_all();

%three steps's threshold
threshold=[0.6 0.7 0.7]

minsize = 100;

%scale factor
factor=0.709;

%load caffe models
prototxt_dir =strcat(caffe_model_path,'/det1.prototxt');
model_dir = strcat(caffe_model_path,'/det1.caffemodel');
PNet=caffe.Net(prototxt_dir,model_dir,'test');
prototxt_dir = strcat(caffe_model_path,'/det2.prototxt');
model_dir = strcat(caffe_model_path,'/det2.caffemodel');
RNet=caffe.Net(prototxt_dir,model_dir,'test');
prototxt_dir = strcat(caffe_model_path,'/det3.prototxt');
model_dir = strcat(caffe_model_path,'/det3.caffemodel');
ONet=caffe.Net(prototxt_dir,model_dir,'test');
prototxt_dir =  strcat(caffe_model_path,'/det4.prototxt');
model_dir =  strcat(caffe_model_path,'/det4.caffemodel');
LNet=caffe.Net(prototxt_dir,model_dir,'test');
faces=cell(0);

while ~feof(tsv_fid)
    line = fgetl(tsv_fid);%MID,EntityNameString,ImageURL,FaceID,FaceRectangle_Base64Encoded,FaceData_Base64Encoded
    image_id = image_id + 1;
    if image_id < 5000000
        if mod(image_id, 100000)==0
            disp(image_id);
        end;
        continue;
    end;
    C = strsplit(line,'\t');
    folder = fullfile(root_folder,C{1});
    if exist(folder,'dir')==0
        mkdir(folder);
    end;
    filename = fullfile(folder,[C{2} '-FaceId-0.jpg']);
    if exist(filename, 'file')>0
        continue;
    end;
    raw  = base64decode(C{end});
%     img_fid = fopen(filename, 'wb');
%     fwrite(img_fid, raw, 'uint8');
%     fclose(img_fid);
    jImg = javax.imageio.ImageIO.read(java.io.ByteArrayInputStream(raw));
    h = jImg.getHeight;
    w = jImg.getWidth;
    p = typecast(jImg.getData.getDataStorage, 'uint8');
    img = permute(reshape(p, [3 w h]), [3 2 1]);
    img = img(:,:,[3 2 1]);
    if size(img, 3) < 3
       img(:,:,2) = img(:,:,1);
       img(:,:,3) = img(:,:,1);
    end
        disp([num2str(image_id) '/' num2str(total_lines) ' ' filename]);
    [boundingboxes points]=detect_face(img,minsize,PNet,RNet,ONet,LNet,threshold,false,factor);
    if isempty(boundingboxes)
        continue;
    end;
    default_face = 1;
    if size(boundingboxes,1) > 1
        for bb=2:size(boundingboxes,1)
            if abs((boundingboxes(bb,1) + boundingboxes(bb,3))/2 - size(img,2) / 2) + abs((boundingboxes(bb,2) + boundingboxes(bb,4))/2 - size(img,1) / 2) < ...
                    abs((boundingboxes(default_face,1) + boundingboxes(default_face,3))/2 - size(img,2) / 2) + abs((boundingboxes(default_face,2) + boundingboxes(default_face,4))/2 - size(img,1) / 2)
                default_face = bb;
            end;
        end;
    end;
    facial5points = double(reshape(points(:,default_face),[5 2])');
    Tfm =  cp2tform(facial5points', coord5points', 'similarity');
    cropImg = imtransform(img, Tfm, 'XData', [1 imgSize(2)],...
                                  'YData', [1 imgSize(1)], 'Size', imgSize);
    imwrite(cropImg, filename);
	%show detection result
% 	numbox=size(boundingboxes,1);
%     figure(1);
% 	imshow(img)
% 	hold on;
% 	for j=1:numbox
% 		plot(points(1:5,j),points(6:10,j),'g.','MarkerSize',10);
% 		r=rectangle('Position',[boundingboxes(j,1:2) boundingboxes(j,3:4)-boundingboxes(j,1:2)],'Edgecolor','g','LineWidth',3);
%     end
%     hold off;
%     figure(2);
%     imshow(cropImg);
% 	pause
end;
fclose(tsv_fid);


classdef ResultsPrinterFactory < handle

    properties (Access = private)
        printer
    end

    methods (Access = public)
        function p = create(obj,resultCase,d)
            obj.createPrinter(resultCase,d);
            p = obj.printer;
        end

    end

    methods (Access = private)

        function createPrinter(obj,resultCase,d)
            switch resultCase
                case 'Elasticity'
                    p = ElasticityResultsPrinter(d);
                case 'ElasticityMicro'
                    p = ElasticityMicroResultsPrinter(d);
                case 'NumericalHomogenizer'
                    p = NumericalHomogenizerPrinter(d);
                case 'TopOptProblem'
                    p = TopOptResultsPrinter(d);
                case 'HomogenizedTensor'
                    p = HomogenizedTensorPrinter(d);
                case 'HomogenizedTensorStressBasis'
                    p = HomogenizedTensorStressBasisPrinter(d);
                case 'ElasticityMicroAndLevelSet'
                    p = ElasticityMicroDefinedByLevelSet(d);
                case {'ShapeFunction'}
                    p = ShapesPrinter(d);
                case {'PerimeterPrinter'}
                    p = PerimeterPrinter(d);
                case {'VectorGauss'}
                    d.fieldName = d.name;
                    p = VectorGaussVariablePrinter(d);
                case {'ScalarGauss'}
                    d.fieldName = d.name;
                    p = ScalarGaussVariablePrinter(d);
                case {'ScalarNodal'}
                    d.fieldName = d.name;
                    p = ScalarNodalVariablePrinter(d);
                case {'DensityGauss'}
                    p = DensityGaussResultsPrinter(d);
                case {'LevelSet'}
                    p = LevelSetResultsPrinter(d);
                otherwise
                    p = [];
            end
            obj.printer = p;
        end

    end

end


function [userCount, licenseCount] = licenseuse(toolbox,verbose)
%LICENSEUSE Counts licenses currently checked out from a license server.
% [USERCOUNT, LICENSECOUNT] = LICENSEUSE(TOOLBOX,VERBOSE)
%  Returns the number of current users of the feature TOOLBOX for a Matlab
%   installation that uses a shared network license. LICENSEUSE can also
%   display the usernames and computer names of the users who have the
%   licenses checked out. LICENSEUSE uses the Flexlm(R) license manager
%   utility to get information about the network license status.
%
% TOOLBOX is the Flexlm license manager's name for each Matlab toolbox.
%   Leave empty to count all available toolboxes plus Matlab base licenses.
%   The license manager's name for a toolbox can be found by inspecting the
%   output from
%     >> licenseuse([],2);
%   Correct capitalization is required.
% VERBOSE (0|1|2) is the level of messages printed on the command line.
%   Use VERBOSE=2 to see a list of current users for each toolbox, or to
%   see a list of all available toolboxes if TOOLBOX=[].
%
% USERCOUNT     The total number of MATLAB licenses in use.
% LICENSECOUNT  The total number of licenses available to you. If TOOLBOX
%   is not included in your license, LICENSECOUNT=-1.
%  (Note: The number of licenses remaining that can be checked out for
%      TOOLBOX is equal to LICENSECOUNT - USERCOUNT)
%
% Examples:
%  To display a list of the current users of the Instrument Control Toolbox,
%   use:
%
%  >> licenseuse('Instr_Control_Toolbox',2);
%
%  To return a count of the number of current users of MATLAB on your
%   license, use
%
%  >> [usersMatlab, licensesMatlab] = licenseuse('MATLAB');
%
%
% Note that the only way to release a license is to exit Matlab.
%
%   See also LICENSEUSER, LICENSE, VER.
%
%
% Matt Hopcroft
%  mhopeng@gmail.com
%

% MH Nov 2012
% v2.11 find file for Windows or *nix
% v2.1  update for new location of lm utilities (R2010b+)
% MH Apr2012
% v2.0  counts user/licenses and returns results
%       changed "all" behaviour- counts MATLAB + toolboxes
%       added VERBOSE parameter, improved results reporting
%       fixed help file/comments
% MH Apr2011
% v1.1  added error message
% MH Oct2010
% v1.0
%

% Note: See the an updated MATLAB help page for FlexLM utilities at:
%  http://www.mathworks.fr/support/tech-notes/1300/1303.html

%% Welcome
if nargin < 2
    if nargin < 1 || isempty(toolbox) || strcmp(toolbox,'MATLAB')
        verbose=2;
    else
        verbose=1;
    end
end
if verbose >= 1, fprintf(1,'licenseuse v2.11: %s\n',datestr(clock)); end

if nargin < 1 || isempty(toolbox)
    if verbose >= 1, fprintf(1,'licenseuse: Checking for users of all MATLAB products on your license...\n'); end
    toolboxStr = '-a';
else
    if verbose >= 1, fprintf(1,'licenseuse: Checking for current users of MATLAB "%s"...\n',toolbox); end
    toolboxStr = ['-f ' toolbox];
end

cdir=cd;

%% Determine path to lmutil
if isunix % v2.11
    lmExe='lmutil';
else
    lmExe='lmutil.exe';
end

lmPath=[matlabroot filesep 'bin' filesep computer('arch') filesep]; % prior to R2010b
if ~exist([lmPath lmExe],'file')
    lmPath=[matlabroot filesep 'etc' filesep computer('arch') filesep]; % R2010b+
    if ~exist([lmPath lmExe],'file')
        fprintf(1,'ERROR: "%s" not found in bin/ or etc/ locations!\n\n',lmExe);
        return
    end
end
if verbose >= 3, fprintf(1,'License manager utilities found at:\n  %s\n',lmPath); end

cd(lmPath);

%% Execute license manager command
[ltstat, lt]=system(['.' filesep 'lmutil lmstat -c "' matlabroot filesep 'licenses' filesep 'network.lic" ' toolboxStr]);
cd(cdir);

if ltstat ~= 0
    fprintf(1,'ERROR: "%s"\n',strtrim(lt));
    if strfind(lt, 'No such file')
        fprintf(1,'On Linux you may need to upgrade the package "lsb"\n  (see %s)\n',...
            'https://www.mathworks.com/support/solutions/en/data/1-GLXUHV/index.html?product=ML&solution=1-GLXUHV');
    end
    error('OS returned error %d when executing lmutil',ltstat);
else
    if verbose >= 2, disp(lt); end % display the license manager status
end

%% Count number of users
tlines=textscan(lt,'%s','delimiter','\n'); tlines=tlines{1};
tIndC=strfind(tlines,'Total of');
licenseCount=0; % number of licenses available to you ("issued")
userCount=0;    % number of users that have checked out a license ("in use")
toolboxFound=0;
for i = 1:length(tIndC)
    if ~isempty(tIndC{i})
        if strcmp(toolboxStr,'-a') % if -a, count users of matlab and all users
            if ~isempty(strfind(tlines{i},'Users of MATLAB:'))
                mCount=textscan(tlines{i},'Users of MATLAB:  (Total of %d %*s issued; Total of %d %*s in use)',1);
                userCountMatlab=mCount{2};
                licenseCountMatlab=mCount{1};
            else
                uCount=textscan(tlines{i},'Users of %*s (Total of %d %*s issued; Total of %d %*s in use)',1);
                userCount=userCount+uCount{2};
                licenseCount=licenseCount+uCount{1};
            end
        else % else, look for only the requested toolbox
            if ~isempty(strfind(tlines{i},toolbox))
                toolboxFound=1;
                uCount=textscan(tlines{i},['Users of ' toolbox ': (Total of %d %*s issued; Total of %d %*s in use)'],1);
                userCount=uCount{2};
                licenseCount=uCount{1};
            end
        end
    end
end

%% Report results
if verbose >= 1
    if verbose >= 2, fprintf(1,'licenseuse: Results:\n'); end
    if strcmp(toolboxStr,'-a')
        fprintf(1,'  There are %d MATLAB licenses in use out of %d available to you,\n',userCountMatlab,licenseCountMatlab);
        fprintf(1,'   and %d additional toolbox licenses in use out of %d available to you.\n\n',userCount,licenseCount);
        userCount=userCount+userCountMatlab;
        licenseCount=licenseCount+licenseCountMatlab;
    else
        if toolboxFound==0
            fprintf(1,'  There do not appear to be any licenses for "%s" available to you.\n',toolbox);
            fprintf(1,'  Check for typos in the toolbox name, and/or try using the ''ver'' command,\n');
            fprintf(1,'   and/or verify that the license server is up (use VERBOSE=2).\n\n');
            licenseCount=-1;
        else
            fprintf(1,'  There are %d %s licenses in use out of %d available to you.\n\n',userCount,toolbox,licenseCount);
        end
    end
end


% PWD2PATH()
%
% add current working directory (pwd) to path.

P = path;
path(pwd,P);


function meta = get_metadata(filename, pattern)
% Read a BIDS's file metadata according to the inheritance principle
% FORMAT meta = get_metadata(filename, pattern)
% filename    - name of file following BIDS standard
% pattern     - regular expression matching metadata file
% meta        - metadata structure
%__________________________________________________________________________

% Copyright (C) 2016-2018, Guillaume Flandin, Wellcome Centre for Human Neuroimaging
% Copyright (C) 2018--, BIDS-MATLAB developers

if nargin == 1, pattern = '^.*_%s\\.json$'; end
pth = fileparts(filename);
p = parse_filename(filename);

meta = struct();

N = 3;
if isfield(p,'ses') && ~isempty(p.ses)
    N = N + 1; % there is a session level in the hierarchy
end

for n=1:N
    metafile = file_utils('FPList',pth, sprintf(pattern,p.type));
    if isempty(metafile), metafile = {}; else metafile = cellstr(metafile); end
    for i=1:numel(metafile)
        p2 = parse_filename(metafile{i});
        fn = setdiff(fieldnames(p2),{'filename','ext','type'});
        ismeta = true;
        for j=1:numel(fn)
            if ~isfield(p,fn{j}) || ~strcmp(p.(fn{j}),p2.(fn{j}))
                ismeta = false;
                break;
            end
        end
        if ismeta
            if strcmp(p2.ext,'.json')
                meta = update_metadata(meta,bids.util.jsondecode(metafile{i}));
            else
                meta.filename = metafile{i};
            end
        end
    end
    pth = fullfile(pth,'..');
end

%==========================================================================
%-Inheritance principle
%==========================================================================
function s1 = update_metadata(s1,s2)
fn = fieldnames(s2);
for i=1:numel(fn)
    if ~isfield(s1,fn{i})
        s1.(fn{i}) = s2.(fn{i});
    end
end


function value = p11_i4 ( action, name, value )

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

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

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

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

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

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

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

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

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

  else

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

  end

  return
end


function varargout=enframe(varargin)
%
% For calling details please see v_enframe.m
%
% This dummy routine is included for backward compatibility only
% and will be removed in a future release of voicebox. Please use
% v_enframe.m in future and/or update with v_voicebox_update.m
%
%      Copyright (C) Mike Brookes 2018
%      Version: $Id: enframe.m 10863 2018-09-21 15:39:23Z dmb $
%
if nargout
    varargout=cell(1,nargout);
    [varargout{:}]=v_enframe(varargin{:});
else
    v_enframe(varargin{:});
end


function aux_plotvolcano(params, hParentFigure)
% function aux_FMD(params, hParentFigure);
%-------------------------------------------
%
% Incoming variables:
% params        : all variables
% hParentFigure : Handle of the parent figure
%
% Thomas van Stiphout, thomas@sed.ethz.ch
% last update: 7.9.2005

report_this_filefun(mfilename('fullpath'));
hold on;plot3(-150,62,0,'r^','MarkerSize',15)
hold on;plot3([-150 -150],[62 62],[0 -200],'k','Linewidth',4)


function ctr = ctrCreate(user_defaults)
% Create ConTrac (ctr) structure
%
%   ctr = ctrCreate(user_defaults)
%
% Creates a structure of parameters needed to run ConTrac/MetroTrack.
%
% Originally by BW?
%
% Modified by DY 7/25/2008 to include calls to ctrSet to install default
% values and allows for the user to pass in a new set of default values
% (user_defaults) if they want, but more needed to make this work. Right
% now, they pass in default values to ctrSet according to what I happen to
% want to be defaults at the moment.

% Initialize the CTR struct
ctr=struct;

% Set the defaults
% If user_defaults passed in, use them. Otherwise, use defaults below.
if ~notDefined('user_defaults')
    d=user_defaults;
else
    d.version=1; % We are at version 1 on July 18, 2008
    d.image_directory='none';
    d.tensors_filename='none';
    d.fa_filename='none';
    d.pdf_filename='none';
    d.mask_filename='none';
    d.Xmask_filename='none';
    d.script_filename='none';
    d.compute_fa='false';
    d.require_way='false';
    d.sampler_type     = 'SISR';
    d.desired_samples  = 50000;
    d.burnin           = 1;
    d.max_nodes    = 240;
    d.min_nodes    = 3;
    d.step_size    = 1;
    d.skip_samples = 1;
    d.roi{1}.coords = [1 1 1; 2 2 2];
    d.roi{2}.coords = [1 1 1; 3 3 3];
    d.roi{1}.valid_cortex = 'true';
    d.roi{2}.valid_cortex = 'true';
    d.roi{1}.seed_region  = 'true';
    d.roi{2}.seed_region  = 'true';
    d.translate = 0;
    d.isr       = 0;
    d.esr       = 1;
    d.temp_swap = 0.1;
    d.inv_temp  = 1;
    d.start_path_tries = 1;
    d.save_out_spacing = 50;
    d.fa_absorb   = 0.01;
    d.abs_normal  = 0;
    d.abs_penalty = 0;
    d.smooth_std  = 14;
    d.angle_cutoff = 130;
    d.shape_params_vec = [0.175 0.15 100];
end

ctr=ctrSet(ctr,'version',d.version);
ctr=ctrSet(ctr,'tensors_filename',d.tensors_filename);
ctr=ctrSet(ctr,'image_directory',d.image_directory);
ctr=ctrSet(ctr,'fa_filename',d.fa_filename);
ctr=ctrSet(ctr,'pdf_filename',d.pdf_filename);
ctr=ctrSet(ctr,'mask_filename',d.mask_filename);
ctr=ctrSet(ctr,'Xmask_filename',d.Xmask_filename);
ctr=ctrSet(ctr,'script_filename',d.script_filename);
ctr=ctrSet(ctr,'compute_fa',d.compute_fa);
ctr=ctrSet(ctr,'require_way',d.require_way);
ctr=ctrSet(ctr,'sampler_type',d.sampler_type);
ctr=ctrSet(ctr,'desired_samples',d.desired_samples);
ctr=ctrSet(ctr,'burnin',d.burnin);
ctr=ctrSet(ctr,'max_nodes',d.max_nodes);
ctr=ctrSet(ctr,'min_nodes',d.min_nodes );
ctr=ctrSet(ctr,'step_size',d.step_size);
ctr=ctrSet(ctr,'skip_samples',d.skip_samples);
ctr=ctrSet(ctr,'roi',d.roi{1}.coords,1,'coords');
ctr=ctrSet(ctr,'roi',d.roi{2}.coords,2,'coords');
ctr=ctrSet(ctr,'roi',d.roi{1}.valid_cortex,1,'valid_cortex');
ctr=ctrSet(ctr,'roi',d.roi{2}.valid_cortex,2,'valid_cortex');
ctr=ctrSet(ctr,'roi',d.roi{1}.seed_region,1,'seed_region');
ctr=ctrSet(ctr,'roi',d.roi{2}.seed_region,2,'seed_region');
ctr=ctrSet(ctr,'translate',d.translate);
ctr=ctrSet(ctr,'isr',d.isr);
ctr=ctrSet(ctr,'esr',d.esr);
ctr=ctrSet(ctr,'temp_swap',d.temp_swap);
ctr=ctrSet(ctr,'inv_temp',d.inv_temp);
ctr=ctrSet(ctr,'start_path_tries',d.start_path_tries);
ctr=ctrSet(ctr,'save_out_spacing',d.save_out_spacing);
ctr=ctrSet(ctr,'fa_absorb',d.fa_absorb);
ctr=ctrSet(ctr,'abs_normal',d.abs_normal);
ctr=ctrSet(ctr,'abs_penalty',d.abs_penalty);
ctr=ctrSet(ctr,'smooth_std',d.smooth_std);
ctr=ctrSet(ctr,'angle_cutoff',d.angle_cutoff);
ctr=ctrSet(ctr,'shape_params_vec',d.shape_params_vec);
return


% close all; clc;

processStatus = [processStatus, newline, ...
                     datestr(now), ' >> ', '[Start text outputing].'];

targetFile = 'in.txt';
targetFile = strcat(inputFilesFolder, '\', targetFile);

processStatus = [processStatus, newline, ...
                     datestr(now), ' >> ', 'Reading text file ...'];

% Read the contents an array
fid = fopen(targetFile);
linesFromFile = fread(fid, '*char')';
fclose(fid);

% Read the contents an array in ascii dec values
fid = fopen(targetFile);
linesFromFileInAscii = fread(fid, '*uint8')';
fclose(fid);

% '\r\t' == [13   10]
newlineInAscii1 = [13 10]; % carriage return + newline (used in most text files)
% '\r\t' unaddressed yet
newlineInAscii2 = [13 9]; % newlineChar = '\r\t';

% scan for both to be sure
locationOfCarriageReturnChar = strfind(linesFromFileInAscii, newlineInAscii1(1));
% locationOfHorizontalTabChar = strfind(linesFromFileInAscii, newlineInAscii1(2));

fileContents = [];
startPos = 1;

for i=1:length(locationOfCarriageReturnChar)
    if(linesFromFileInAscii(locationOfCarriageReturnChar(i)+1) == newlineInAscii1(2))
        fileContents = [fileContents {linesFromFile(startPos:(locationOfCarriageReturnChar(i)-1))}];
        startPos = locationOfCarriageReturnChar(i)+2; % skip over 2 character
    end
end

fileContents = [fileContents {linesFromFile(startPos:end)}];

% locationOfCarriageReturnChar = strfind(linesFromFileInAscii, newlineInAscii2(1));
% locationOfHorizontalTabChar = strfind(linesFromFileInAscii, newlineInAscii2(2));

lineCount = 0;

for i = 1:length(fileContents)
   if (length(char(fileContents(i))) ~= 0)
        lineCount = lineCount + 1;
        nonEmptyLines(lineCount) = fileContents(i);
   end
end

nonEmptyLinesInAscii = [];

nonEmptyLinesInAscii = uint8(char(nonEmptyLines(1)));

for i = 2:lineCount
    lineToBeAddressed = uint8(char(nonEmptyLines(i)));
    nonEmptyLinesInAscii = [nonEmptyLinesInAscii newlineInAscii1 lineToBeAddressed]; % fit in the newlineInAscii1
end

targetFile = 'out.txt';
targetFile = strcat(outputFilesFolder, '\', targetFile);

processStatus = [processStatus, newline, ...
                     datestr(now), ' >> ', 'Writing text file ...'];

% write to file
fid = fopen(targetFile, 'w');
fwrite(fid, char(nonEmptyLinesInAscii), '*char');
fclose(fid);

processStatus = [processStatus, newline, ...
                     datestr(now), ' >> ', '[END text outputing].'];


%                                                 y = triumtriu(r,u,K)
% TRIUMTRIU  Computes y = r * u
%   Both r and u should be upper triangular.
%
% **********  INTERNAL FUNCTION OF SEDUMI **********
%
% See also sedumi

function y = triumtriu(r,u,K) %#ok
%
% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA
%

disp('The SeDuMi binaries are not installed.')
disp('In Matlab, launch "install_sedumi" in the folder you put the SeDuMi files.')
disp('For more information see the file Install.txt.')
error(' ')


function [common,system_not_matlab,matlab_not_system] = comparePaths(NAME,printLevel)
%compare the system and matlab paths for a given NAME environment variable
%
% INPUT
% NAME          environment variable, e.g., PATH or LD_LIBRARY_PATH
% printLevel
%
% OUTPUT
% common                cell array
% system_not_matlab
% matlab_not_system
%
% USAGE example
% [common,system_not_matlab,matlab_not_system] = comparePaths('LD_LIBRARY_PATH',1);

if ~exist('printLevel','var')
    printLevel=0;
end

if strcmp(NAME,'PYTHON')
    matlab_split = get_py_path();
    [success,system_response]=system('python -c "import sys; print(sys.path)"');
    system_split = split(system_response,',');
    system_split{1}=strtrim(system_split{1});
    system_split{1}=strrep(system_split{1},'[','');
    system_split{end}=strtrim(system_split{end});
    system_split{end}=strrep(system_split{end},']','');
    system_split{end}=strrep(system_split{end},'''','');
    for i=1:length(system_split)
        system_split{i}=strrep(system_split{i},' ','');
        system_split{i}=strrep(system_split{i},'''','');
    end
else
    [success,system_response]=system(['echo $' NAME]);
    system_split = split(system_response,':');
    for i=1:length(system_split)
        system_split{i} = strtrim(system_split{i});
    end

    matlab_response = getenv(NAME);
    matlab_split = split(matlab_response,':');
    for i=1:length(matlab_split)
        matlab_split{i} = strtrim(matlab_split{i});
    end
end

if printLevel>1
    disp(system_split)
    disp(matlab_split)
end

common = intersect(system_split,matlab_split);
if printLevel>1
    fprintf('%s\n',[NAME ' common to system and matlab'])
    for i=1:length(common)
        fprintf('%s\n',common{i})
    end
end

system_not_matlab = setdiff(system_split,matlab_split);
if printLevel>0
    if isempty(system_not_matlab)
        fprintf('%s\n',['No ' NAME ' in system but not matlab'])
    else
        fprintf('\n%s\n',[NAME ' in system but not matlab'])
        for i=1:length(system_not_matlab)
            fprintf('%s\n',system_not_matlab{i})
        end
    end
end

matlab_not_system = setdiff(matlab_split,system_split);
if printLevel>0
    if isempty(matlab_not_system)
        fprintf('%s\n',['No ' NAME ' in matlab but not system'])
    else
        fprintf('\n%s\n',[NAME ' in matlab but not system'])
        for i=1:length(matlab_not_system)
            fprintf('%s\n',matlab_not_system{i})
        end
    end
end


function v = repmat(v,varargin)
% overloads repmat

v.x = repmat(v.x,varargin{:});
v.y = repmat(v.y,varargin{:});
v.z = repmat(v.z,varargin{:});


function output = base64decode(varargin)
%
% output = base64decode(input)
%
% Decoding a Base64-encoded byte-stream to recover the original data
% This function depends on JVM in MATLAB or, can optionally use the ZMat
% toolbox (http://github.com/fangq/zmat)
%
% Copyright (c) 2012, Kota Yamaguchi
% URL: https://www.mathworks.com/matlabcentral/fileexchange/39526-byte-encoding-utilities
%
% Modified by: Qianqian Fang (q.fang <at> neu.edu)
%
% input:
%      input: a base64-encoded string
%
% output:
%      output: the decoded binary byte-stream as a uint8 vector
%
% examples:
%      bytes=base64encode('Test JSONLab');
%      orig=char(base64decode(bytes))
%
% license:
%     BSD or GPL version 3, see LICENSE_{BSD,GPLv3}.txt files for details
%
% -- this function is part of JSONLab toolbox (http://iso2mesh.sf.net/cgi-bin/index.cgi?jsonlab)
%

if(nargin==0)
    error('you must provide at least 1 input');
end
if(exist('zmat','file')==2 || exist('zmat','file')==3)
    output=zmat(varargin{1},0,'base64');
    return;
elseif(isoctavemesh)
    error('You must install the ZMat toolbox (http://github.com/fangq/zmat) to use this function in Octave');
end

error(javachk('jvm'));

if(ischar(varargin{1}))
    varargin{1}=uint8(varargin{1});
end

input=typecast(varargin{1}(:)','uint8');

output = typecast(org.apache.commons.codec.binary.Base64.decodeBase64(input), 'uint8')';


function [tests,pass,perf]=test_wfdbtest(varargin)

inputs={'verbose'};
verbose=0;
for n=1:nargin
    if(~isempty(varargin{n}))
        eval([inputs{n} '=varargin{n};'])
    end
end
%Sounds redundant, I know, but wfdbtest is used for remote installation
%debugging, it has a  nice suite of test not in the function examples.
%Should be one the first tests run (or for a light check of the toolbox).
test_string={'good=wfdbtest;close all;if(!good) error(''wfdbtest failed'');end'};
[tests,pass,perf]=test_wrapper(test_string,[],verbose);


%COMSetSubCodes COMSetSubCodes enumeration for the brick
%
% Notes::
% - COMSetSubCodes can be found in the EV3 documentation and source code
% (bytecodes.h)

classdef COMSetSubCodes < uint8
    enumeration
         SetOnOff (1)
         SetVisible (2)
         SetSearch (3)
         SetPin (5)
         SetPasskey (6)
         SetConnection (7)
         SetBrickName (8)
         SetMoveUp (9)
         SetMoveDown (10)
         SetEncrypt (11)
         SetSSID (12)
         SetMode2 (13)
    end
end


function vl_testnn(varargin)
%VL_TESTNN Run MatConvNet test suite
% VL_TESTNN('option', value, ...) takes the following options:
%  `cpu`:: true
%    Run the CPU tests.
%
%  `gpu`:: false
%    Run the GPU tests.
%
%  `single`:: true
%    Perform tests in single precision.
%
%  `double`:: false
%    Perform tests in double precision.
%
%  `command`:: `'nn'`
%    Run only tests which name starts with the specified substring.
%    E.g. `vl_testnn('command', 'nnloss') would run only the nnloss tests.
%
%  `break`:: false
%    Stop tests in case of error.
%
%  `tapFile`:: ''
%    Output the test results to a file. If a specified file does
%    exist it is overwritten.
%
%  This function uses the Matlab unit testing framework which was
%  introduced in Matlab R2013a (v8.1).

% Copyright (C) 2015-16 Andrea Vedaldi, Karel Lenc.
% All rights reserved.
%
% This file is part of the VLFeat library and is made available under
% the terms of the BSD license (see the COPYING file).

opts.cpu = true ;
opts.gpu = false ;
opts.single = true ;
opts.double = false ;
opts.command = 'nn' ;
opts.break = false ;
opts.tapFile = '';
opts = vl_argparse(opts, varargin) ;

import matlab.unittest.constraints.* ;
import matlab.unittest.selectors.* ;
import matlab.unittest.plugins.TAPPlugin;
import matlab.unittest.plugins.ToFile;

% Choose which tests to run
sel = HasName(StartsWithSubstring(opts.command)) ;
if ~opts.gpu
  sel = sel & ~HasName(ContainsSubstring('device=gpu')) ;
end
if ~opts.cpu
  sel = sel & ~HasName(ContainsSubstring('device=cpu')) ;
end
if ~opts.double
  sel = sel & ~HasName(ContainsSubstring('dataType=double')) ;
end
if ~opts.single
  sel = sel & ~HasName(ContainsSubstring('dataType=single')) ;
end

% Run tests
root = fileparts(mfilename('fullpath')) ;
suite = matlab.unittest.TestSuite.fromFolder(fullfile(root, 'suite'), sel) ;
runner = matlab.unittest.TestRunner.withTextOutput('Verbosity',3);
if opts.break
  runner.addPlugin(matlab.unittest.plugins.StopOnFailuresPlugin) ;
end
if ~isempty(opts.tapFile)
  if exist(opts.tapFile, 'file')
    delete(opts.tapFile);
  end
  runner.addPlugin(TAPPlugin.producingOriginalFormat(ToFile(opts.tapFile)));
end
result = runner.run(suite);
display(result)


% pop_readneurone() - A function for reading NeurOne data.
%
% Usage: >> [EEGOUT,command] = pop_readneurone() % Launches GUI for user input
%       OR
%        >> [EEGOUT,command] = pop_readneurone(dataPath, sessionPhaseNumber, chans)
%
% Please note that if this function is called without using the menu item
% in EEGLAB, it will not be automatically stored in its memory.
% ========================================================================
% Inputs:
%        dataPath           - A string containing the full path for .ses
%                             -file to be read. This input argument is
%                             required.
%        sessionPhaseNumber - A number indicating the session
%                             phase to be observed. This input argument is
%                             optional. If the session phase number is left
%                             empty, default value 1 will be used.
%        chans              - Another optional input argument to indicate
%                             the channels to be imported. Acceptable
%                             values are strings where the channels are
%                             in a vector form without brackets e.g.
%                             '1,3,5' or '1:4' (when the GUI is executed,
%                             the quotation marks should not be used).
%                             Note that only acceptable values
%                             are those between 1 and the total number of
%                             channels. It should also be noted that the
%                             number of the channel may not be the same as
%                             its input number since when an input
%                             number is missing, the channel numbering will
%                             continue with next available input number.
%                             Here is an example of the channel numbering
%                             (note the missing input numbers 3 and 4):
%
%              Input number               Channel number
%             ------------               --------------
%                   1          ----->           1
%                   2          ----->           2
%                   5          ----->           3
%                   6          ----->           4
%
%
% Outputs:
%        EEGOUT             - A struct with the same fields as a standard
%                             EEG data structure under EEGLAB
%                             (see eeg_checkset.m).
%        command            - A string containing all the input parameters
%                             and the command used to execute this
%                             function.
% ========================================================================
% GUI help:
%
% When this function is used without any input arguments, it will open
% several windows to ask for required information as described above. The
% first pop-up window asks the user to specify the .ses -file to be loaded.
% If 'Cancel' -button is pressed at this point, the importing process will
% terminate. The next window is a GUI asking for information about the
% channels to be loaded and the number of the desired session phase to be
% observed. When 'Ok' -button is pressed, the data is sent to readneurone.m
% for further processing. Again, if 'Cancel' -button is pressed, the whole
% importing process will be terminated.
%
% IMPORTANT NOTE: For a computer with high memory capacity it is much more
%                 faster to import data by leaving the channel field empty
%                 and removing unnecessary channels afterwards. However,
%                 in case of limited memory it is recommended to first
%                 specify the channels to be imported.
%
% ========================================================================
% NOTE:
% This file is part of the NeurOne data import plugin for EEGLAB.
% ========================================================================
%
% Current version: 1.0.3.4 (2016-06-17)
% Author: Mega Electronics
%
% see also: eegplugin_neurone.m or readneurone.m

function [EEG,command] = pop_readneurone(dataPath,sessionPhaseNumber,chans)
%% Initialize empty structure for the data

EEG = {};              % Create empty space for data
command = '';

%% Check the number of input arguments
nargchk(0,1,nargin);

%% Use the GUI

if nargin==0

    if isfield(evalin('base','EEG'),'history')
        history = evalin('base','EEG.history');
        if  ~(isempty(strfind(history,'dataPath')))
            dataPathIndex = strfind(history,'dataPath=''');
            idx = strfind(history,'''');
            idx = idx(idx>dataPathIndex);
            dataPath = history(idx(1)+1:idx(2)-1);
            dataPath = fileparts(dataPath);
            [dataPath folder] = fileparts(dataPath);
        else
            dataPath = cd;
        end
    else
        dataPath = cd;
    end

    [fname dataPath] = uigetfile({'*.ses', ...
        'NeurOne session file (*.ses)'}, ...
        'Load NeurOne session file',dataPath);

    % If cancel is pressed, the import process will terminate
    if fname==0
        return
    end

    % If ok, manipulate the filename
    fullpath = [dataPath fname];
    a = dir(dataPath);
    for k = 3:numel(a)
        if a(k).isdir==1
            if ~(isempty(regexpi(fullpath,a(k).name)))
                dataPath = [dataPath a(k).name filesep];
            end
        end
    end

    fprintf('\n----------IMPORTING DATA----------\n')
    fprintf('File to Import: %s\n',fullpath)

    guifig=guireadneurone;

    try
       SETTINGS=guidata(guifig);
    catch
       return;
    end

    switch SETTINGS.loadStatus
    % When cancel button is pressed, the GUI terminates
    case 0
        disp('NeurOne import cancelled')
        delete(guifig);
        return
    % When ok button is pressed, proceed to read the data
    case 1
        delete(guifig);

        SETTINGS.dataPath=dataPath;

        if  isempty(SETTINGS.chans)
            fprintf('Channels to be read: all\n');
        else
            fprintf('Channels to be read: %s\n',SETTINGS.chans);
        end

        EEG = readneurone(SETTINGS.dataPath, ...
            SETTINGS.sessionPhaseNumber,SETTINGS.chans);
        EEG = eeg_checkset(EEG); % EEGLAB function to check consistency
        EEG = eeg_checkset(EEG,'eventconsistency'); % check event structure
        EEG = eeg_checkset(EEG,'makeur');
    end

% ====================================================================
% Read data using direct command

else
    if nargin>=1
         fullpath=dataPath;
         fprintf('\n----------IMPORTING DATA----------\n')
         fprintf('File to Import: %s\n',fullpath)

      % Manipulate the given path
      [dataPath fname] = fileparts(fullpath);
      a = dir(dataPath);
      for k = 3:numel(a)
          if a(k).isdir==1
             if ~(isempty(regexpi(fullpath,a(k).name)))
                dataPath = [dataPath filesep a(k).name filesep];
             end
          end
      end
         SETTINGS=struct();
         SETTINGS.dataPath=dataPath;

         if ~(exist('sessionPhaseNumber'))
            SETTINGS.sessionPhaseNumber = 1;
         else
            SETTINGS.sessionPhaseNumber=sessionPhaseNumber;
         end

         if ~(exist('chans'))
            SETTINGS.chans = '';
         else
            SETTINGS.chans=chans;
         end

    end

    EEG = readneurone(SETTINGS.dataPath,SETTINGS.sessionPhaseNumber, ...
        SETTINGS.chans);
    EEG = eeg_checkset(EEG);                    % check EEG data structure
    EEG = eeg_checkset(EEG,'eventconsistency'); % check event structure
    EEG = eeg_checkset(EEG,'makeur');

end

comline = sprintf('dataPath=''%s'';',SETTINGS.dataPath);
comline = sprintf('%s sessionPhaseNumber=''%d'';',...
    comline,SETTINGS.sessionPhaseNumber);
comline = sprintf('%s chans=''%s'';',...
    comline,SETTINGS.chans);
command = sprintf('%s [EEG,COM]=pop_readneurone(dataPath,sessionPhaseNumber,chans);',comline);

return


%
%   FILE NAME:    addManuallyCuratedMetAssoc.m
%
%   PURPOSE: Incorporate manual curation results of met association
%            with Recon/BiGG/MetaNetX ids to ihumanMets2MNX_v2.mat
%

% Load met association to MNX/BiGG
load('ihumanMets2MNX_v2.mat');

% Get the list of empty elements of Recon3D/BiGG
emptyList=find(cellfun(@isempty, ihuman.metRecon3DID));
MNXID=reformatElements(ihuman.metMNXID,'cell2str');
for i=1:length(emptyList)
		m=emptyList(i);
		fprintf('%s\t%s\t%s\n',ihuman.mets{m},ihuman.metNames{m},MNXID{m});
end

% Locate the ones with multiple Recon3D associations
HMRmetsNoComp=regexprep(ihuman.mets,'\w$','');
multi_index=find(cellfun(@numel, ihuman.metRecon3DID)>1);
% Obtain the non-unique assoc
metString=reformatElements(ihuman.metRecon3DID,'cell2str');
[multiMetAssoc.Recon3DID, I, ~]=unique(metString(multi_index));
multiMetAssoc.HMRID=HMRmetsNoComp(multi_index(I));
multiMetAssoc.MNXID=reformatElements(ihuman.metMNXID(multi_index(I)),'cell2str');
for i=1:length(multiMetAssoc.HMRID)
		fprintf('%s\t%s\t%s\n',multiMetAssoc.HMRID{i},multiMetAssoc.MNXID{i},multiMetAssoc.Recon3DID{i});
end

% These ones with missing and multiple Recon3D/BiGG ids were organized into
% an excel file metaboliteCuration_20180605.xlsx for manual cuartion

% The following updates are based on the manual curation results
% 1. For the elements without Recon3D/BiGG assoc
ihuman.metRecon3DID{find(strcmp('m00077p',ihuman.mets))}={'CE2416'};
ihuman.metRecon3DID{find(strcmp('m00678m',ihuman.mets))}={'dec24dicoa'};
ihuman.metRecon3DID{find(strcmp('m00678p',ihuman.mets))}={'dec24dicoa'};
ihuman.metRecon3DID{find(strcmp('m03035m',ihuman.mets))}={'dece3coa'};
ihuman.metRecon3DID{find(strcmp('m03035p',ihuman.mets))}={'dece3coa'};
ihuman.metRecon3DID{find(strcmp('m00980m',ihuman.mets))}={'dece4coa'};
ihuman.metRecon3DID{find(strcmp('m00980p',ihuman.mets))}={'dece4coa'};
ihuman.metRecon3DID{find(strcmp('m01422c',ihuman.mets))}={'cbtnCCP'};
ihuman.metRecon3DID{find(strcmp('m01942g',ihuman.mets))}={'gd1a_hs'};

ihuman.metMNXID{find(strcmp('m01942g',ihuman.mets))}={'MNXM11644','MNXM8637'};
ihuman.metMNXID{find(strcmp('m02149c',ihuman.mets))}={'MNXM56888'};
ihuman.metMNXID{find(strcmp('m02147m',ihuman.mets))}={'MNXM527231'};
ihuman.metMNXID{find(strcmp('m02147x',ihuman.mets))}={'MNXM527231'};
ihuman.metMNXID{find(strcmp('m02147s',ihuman.mets))}={'MNXM527231'};
ihuman.metMNXID{find(strcmp('m02147c',ihuman.mets))}={'MNXM527231'};

% 2. For the elements with multiple Recon3D/BiGG association
ihuman.metRecon3DID{find(strcmp('m00490c',ihuman.mets))}={'mag_hs'};
ihuman.metRecon3DID{find(strcmp('m02733c',ihuman.mets))}={'pa_hs'};
ihuman.metRecon3DID{find(strcmp('m02733r',ihuman.mets))}={'pa_hs'};
ihuman.metRecon3DID{find(strcmp('m00240c',ihuman.mets))}={'dag_hs'};
ihuman.metRecon3DID{find(strcmp('m00240g',ihuman.mets))}={'dag_hs'};
ihuman.metRecon3DID{find(strcmp('m00240n',ihuman.mets))}={'dag_hs'};
ihuman.metRecon3DID{find(strcmp('m01818c',ihuman.mets))}={'11_cis_retfa'};
ihuman.metRecon3DID{find(strcmp('m01818s',ihuman.mets))}={'11_cis_retfa'};
ihuman.metRecon3DID{find(strcmp('m01818x',ihuman.mets))}={'11_cis_retfa'};
ihuman.metRecon3DID{find(strcmp('m02959s',ihuman.mets))}={'tag_hs'};

save('ihumanMets2MNX_v2.mat','ihuman');  % 2018-06-12
% Some MNX IDs also need refinement (to be continued)

% 3. Generate the array structure (metAssocHMR2Recon3D) of metabolite
% association for further curation and model integration, by trimming
% off duplicate mets in multiple compartments
HMRmets=regexprep(ihuman.mets,'\w$','');   % HMR met ids without comp id
[metAssocHMR2Recon3.metHMRID, I, ~]=unique(HMRmets,'stable');
metAssocHMR2Recon3.metBiGGID=ihuman.metBiGGID(I);
metAssocHMR2Recon3.metMNXID=ihuman.metMNXID(I);
metAssocHMR2Recon3.metRecon3DID=ihuman.metRecon3DID(I);
metAssocHMR2Recon3.metNames=ihuman.metNames(I);
save('metAssocHMR2Recon3.mat','metAssocHMR2Recon3');  % 2018-06-17

% 4. Detect mets associated from one Recon3D id to multiple HMR ids
% get the array of non-empty Recon3D met assocations
Recon3DID=reformatElements(metAssocHMR2Recon3.metRecon3DID,'cell2str');
Recon3DID_nonEmpty=Recon3DID(getNonEmptyList(Recon3DID));

% get the array of unique Recon3D met id and the occurrences
check=countFrequency(Recon3DID_nonEmpty);
list=find([check.frequency{:}] > 1);   % Recon3D mets with multiple occurrences
for i=1:numel(list)
		m=list(i);
		ind=find(strcmp(check.uniqueList{m},Recon3DID));
		fprintf('%s\t%s\n',check.uniqueList{m},strjoin(metAssocHMR2Recon3.metHMRID(ind),';'));
end
% These Recon3D mets associated to multiple HMR ids were subjected to
% manual cuartion 2018-06-18

% 5. The following updates of HMR-Recon3D assoc are based on the curation results
% in excel file metaboliteCuration_20180618_HW.xlsx
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m00591',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m00352',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m00379',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m00555',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m01123',metAssocHMR2Recon3.metHMRID))}={'CE7097'};
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m01911',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m01942',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m02410',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m02487',metAssocHMR2Recon3.metHMRID))}='';
metAssocHMR2Recon3.metRecon3DID{find(strcmp('m02578',metAssocHMR2Recon3.metHMRID))}='';

% 6. Associate Recon3D mets 'M00196' and 'protein' to HMR2 met 'm00196'
ind=find(strcmp(metAssocHMR2Recon3.metHMRID,'m00196'));
metAssocHMR2Recon3.metRecon3DID{ind}{2}='protein';
save('metAssocHMR2Recon3.mat','metAssocHMR2Recon3');  % 2018-08-03

% 7. Synchronize curtated metabolite association previously in % 5 and % 6
% from 'metAssocHMR2Recon3.mat' to 'ihumanMets2MNX_v2.mat'
load('ihumanMets2MNX_v2.mat');
ihuman.metRecon3DID{find(strcmp('m00591c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m00591s',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m00352r',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m00379c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m00555c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m00555g',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m00555r',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m01123c',ihuman.mets))}{1}='CE7097';
ihuman.metRecon3DID{find(strcmp('m01911c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m01942g',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02410c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02410m',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02410r',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02487c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02487m',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578c',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578m',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578n',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578p',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578r',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578s',ihuman.mets))}='';
ihuman.metRecon3DID{find(strcmp('m02578x',ihuman.mets))}='';
% Associate Recon3D mets 'M00196' and 'protein' to HMR2 met 'm00196'
ihuman.metRecon3DID{find(strcmp('m00196c',ihuman.mets))}{2}='protein';
save('ihumanMets2MNX_v2.mat','ihuman');  % 2018-09-03


function varargout = test(varargin)
% VL_TEST  Run test suite
%  RESULTS = VL_TEST() runs all VLFeat test suites. The tests
%  verify that VLFeat is working correctly.
%
%  RESULTS is a structure listing the result of each test.
%  It has fileds:
%
%  TESTNAME:   name of the test
%  SUCCEDED:   a boolean flag indicating whether the test succeded
%  EXCEPTION:  the exception generated if the test failed
%
%  VL_TEST(SUITE) runs only the specified SUITE.
%
%  VL_TEST(SUITE, TEST) runs the specified SUITE/TEST without catching
%  the potential exception. Useful to DBSTOP to debug.
[varargout{1:nargout}] = vl_test(varargin{:});


function dicomrt_createmclinks = dicomrt_createmclinks(study,beam_module,int)
% dicomrt_createmclinks(study,beam_module,int)
%
% Create links from original MC phase space file directory to a user specified directory
% this is to avoid PHSPFILENAME being longer than 80 character supported by BEAM/DOSXYZ
%
% rtplanform contains plan data coded (warmed) by dicomrt_mcwarm.
% beam_module is the MC model to use
% int is a parameter which determines an interactive session (int~=0). During interactive session
%     it is possible to specify the name of directories where files will be linked. (OPTIONAL)
%
% Example:
%
% dicomrt_createmclinks(A,'BEAM_Clinac21CD')
%
% will create:
%
% A.createlinks     when executed links phsp files from original BEAM 'BEAM_Clinac21CD' dir
%                   to user defined dir this may be useful when path to original BEAM dir
%                   is too long to fit in the BEAM/DOSXYZ supported 80 characters
%
%
% See also dicomrt_mcwarm, dicomrt_BEAMexport, dicomrt_DOSXYZexport, dicomrt_createmcscripts
%
% Copyright (C) 2002 Emiliano Spezi (emiliano.spezi@physics.org)

% Check number of argument
error(nargchk(2,3,nargin))

% Check input
[study,type]=dicomrt_checkinput(study);
if isequal(type,'RTPLAN')==1
    rtplanformc=dicomrt_mcwarm(study);
else
    error('dicomrt_createmcscripts: invalid input data format');
end

if exist('int')==0
    int=0;
end

% Default directories
LOCAL_EGS=['/user/phexternal/phx1pl/cardiff/egs4'];
PHSPFILEDIR=['/user/phexternal/phx1pl/cardiff'];

% Almost ready to write link file: ask some question if session is interactive
if int~=0
    disp(' ');
    disp('Current default for local egs4 directory is: ');
    disp(LOCAL_EGS);
    egs4option = input('Do you want to change this default path Y/N [N]:','s');
    if egs4option == 'Y' | egs4option == 'y';
        LOCAL_EGS = input('Input the filename complete of full path : ','s');
    end

    % PHSPFILEDIR is the directory where phsp files are suppose to be linked
    % this is to avoid PHSPFILENAME being longer than 80 character supported by BEAM/DOSXYZ
    disp(' ');
    disp('Current directory where phsp files will be linked is: ');
    disp(PHSPFILEDIR);
    linkoption = input('Do you want to change this default path Y/N [N]:','s');
    if linkoption == 'Y' | linkoption == 'y';
        PHSPFILEDIR = input('Input the full path : ','s');
    end
end

ORIGDIR=[LOCAL_EGS,'/',beam_module,'/'];
PHSPFILEDIR = [PHSPFILEDIR,'/'];

% Prepare title and strings for internal file identification
MAINtitle=['#MCTP - BEAM link phsp files utility. Case study name: ',inputname(1)];
comma=[','];
space=[' '];

% Write link file
linkfilename=[inputname(1),'.createlinks'];
linkfilenameid=fopen(linkfilename,'w');

if linkfilenameid<0
    error('dicomrt_createmclinks: Error writing script file. Exit now!');
    return
end

time=fix(clock);
fprintf(linkfilenameid,'#!/bin/sh');
fprintf(linkfilenameid,'\n');
fprintf(linkfilenameid,'#****************************************************************************************');
fprintf(linkfilenameid,'\n');
fprintf(linkfilenameid,'#Session started: ');
fprintf(linkfilenameid,date);fprintf(linkfilenameid,'%c',comma);
fprintf(linkfilenameid,'%2i',time(4));
fprintf(linkfilenameid,'%c',':');
fprintf(linkfilenameid,'%2i',time(5));
fprintf(linkfilenameid,'\n');
fprintf(linkfilenameid,MAINtitle);
fprintf(linkfilenameid,'\n');
fprintf(linkfilenameid,'#****************************************************************************************');
fprintf(linkfilenameid,'\n');
fprintf(linkfilenameid,'echo ----------');
fprintf(linkfilenameid,'\n');
for i=1:size(rtplanformc,1) % loop over # beams
    for j=1:size(rtplanformc{i,3},1)
        filename=[inputname(1),'_b',int2str(i),'s',int2str(j),'.egs4phsp1'];
        fprintf(linkfilenameid,'ln -s ');
        fprintf(linkfilenameid,ORIGDIR);
        fprintf(linkfilenameid,filename);
        fprintf(linkfilenameid,space);
        fprintf(linkfilenameid,PHSPFILEDIR);
        fprintf(linkfilenameid,filename);
        fprintf(linkfilenameid,'\n');
    end
end
fclose(linkfilenameid);


function result=cosmo_parcellfun(nproc,func,arg_cell,varargin)
% applies a function to elements in a cell in parallel
%
% result=cosmo_parcellfun(nproc,func,arg_cell,...)
%
% Inputs:
%   nproc                   Maximum number of processes to run in parallel
%   func                    Function handle that takes a single input
%                           argument and gives a single output
%   arg_cell                Cell with arguments to be given to func
%   'UniformOutput',o_u     If false, then the output is converted to a
%                           numeric or logical array. Default: true
%
% Output:
%   result                  Cell with the same size as arg_cell, with
%                               result{i}=func(arg_cell{i})
%                           If o_u is true, then result is converted to a
%                           numeric or logical array, assuming that each
%                           output is a scalar. If any output is not a
%                           scalar while o_u is true, an exception is
%                           thrown.
%

    default=struct();
    default.UniformOutput=true;

    opt=cosmo_structjoin(default,varargin{:});

    check_input(nproc,func,arg_cell,opt);

    % see how many processes to use
    narg_cell=numel(arg_cell);

    if narg_cell==1
        nproc_to_use=1;
    else
        nproc_available=cosmo_parallel_get_nproc_available(opt);
        nproc_to_use=min([nproc,narg_cell,nproc_available]);
    end

    if nproc_to_use<=1
        helper_func=@run_single_thread;
    else
        is_matlab=cosmo_wtf('is_matlab');
        if is_matlab
            helper_func=@run_parallel_matlab;
        else
            helper_func=@run_parallel_octave;
        end
    end

    result=helper_func(nproc_to_use,func,arg_cell,opt);

function args=get_extra_builtin_cellfun_args(opt)
    if opt.UniformOutput
        args={};
    else
        args={'UniformOutput',false};
    end

function result=run_single_thread(nproc,func,arg_cell,opt)
% single thread, Matlab of Octave --- redirect to cellfun
    result_cell=cellfun(func,arg_cell,'UniformOutput',false);
    result=convert_to_uniform_output_if_necessary(result_cell,opt);

function result=run_parallel_matlab(nproc,func,arg_cell,opt)
% multi-thread, Matlab
    narg_cell=numel(arg_cell);
    result_cell=cell(size(arg_cell));

    parfor (i=1:narg_cell, nproc)
        result_cell{i}=func(arg_cell{i});
    end

    result=convert_to_uniform_output_if_necessary(result_cell,opt);

function result=convert_to_uniform_output_if_necessary(result_cell,opt)
    if opt.UniformOutput
        is_uniform_func=@(x)isequal(size(x),[1 1]);
        is_uniform_mask=cellfun(is_uniform_func, result_cell);
        if ~all(is_uniform_mask)
            error(['Not all outputs are scalar. Use\n'...
                    '    ''UniformOutput'',false\n'...
                    'to return cell output']);
        end

        % concatenate and put in original shape
        result=reshape(cat(1,result_cell{:}),size(result_cell));
    else
        result=result_cell;
    end

function result=run_parallel_octave(nproc,func,arg_cell,opt)
% multi-thread, Octave
    extra_octave_args={'VerboseLevel',0};

    cellfun_args=get_extra_builtin_cellfun_args(opt);
    result=parcellfun(nproc,func,arg_cell,...
                                cellfun_args{:},...
                                extra_octave_args{:});

function check_input(nproc,func,arg_cell,opt)
    if ~(isnumeric(nproc) && ...
            isscalar(nproc) && ...
            round(nproc)==nproc && ...
            nproc>0)
        error(['nproc must be a positive integer. Use nproc=inf to use '...
                'as many processes as there are cores available']);
    end

    if ~isa(func,'function_handle')
        error('second argument must be a function handle');
    end

    if ~iscell(arg_cell)
        error('third argument must be a cell');
    end

    if ~(islogical(opt.UniformOutput) && ...
                isscalar(opt.UniformOutput))
        error('option ''UniformOutput'' must be scalar boolean');
    end


function simulink2svg
% Show the hidden handles to get access to the simulink figures
set(0,'ShowHiddenHandles','on');
% Iterate over all children of the root
child = get(0,'children');
for i = 1:length(child)
    % Pick all scope figures
    if strcmp(get(child(i),'Tag'),'SIMULINK_SIMSCOPE_FIGURE')
        % In order to get the correct background turn inverted background
        % off. If you like a white background you should invert all labels
        % and lines.
        set(child(i),'InvertHardcopy','off');
        % Use plot2svg
        plot2svg(['Scope_' num2str(i) '.svg'], child(i))
        set(0,'ShowHiddenHandles','off')
    end
end