function SQL_CloseDatabase(dbc)
% SQL_CloseDatabase     Closes the connection to database, dbc.

% ------------------------------------------------------------------------------
% Copyright (C) 2020, Ben D. Fulcher <ben.d.fulcher@gmail.com>,
% <http://www.benfulcher.com>
%
% If you use this code for your research, please cite the following two papers:
%
% (1) B.D. Fulcher and N.S. Jones, "hctsa: A Computational Framework for Automated
% Time-Series Phenotyping Using Massive Feature Extraction, Cell Systems 5: 527 (2017).
% DOI: 10.1016/j.cels.2017.10.001
%
% (2) B.D. Fulcher, M.A. Little, N.S. Jones, "Highly comparative time-series
% analysis: the empirical structure of time series and their methods",
% J. Roy. Soc. Interface 10(83) 20130048 (2013).
% DOI: 10.1098/rsif.2013.0048
%
% This work is licensed under the Creative Commons
% Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of
% this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send
% a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
% California, 94041, USA.
% ------------------------------------------------------------------------------

switch class(dbc)
case 'com.mysql.jdbc.JDBC4Connection'
    % Database connection opened using java commands:
    dbc.close();
case 'database'
    % Database connection opened using database toolbox:
    close(dbc);
otherwise
    error('Unknown database connection class %s',class(dbc));
end

end


classdef TestSimpleBlobDetector
    %TestSimpleBlobDetector

    properties (Constant)
        im = fullfile(mexopencv.root(),'test','tsukuba_l.png');
        kfields = {'pt', 'size', 'angle', 'response', 'octave', 'class_id'};
    end

    methods (Static)
        function test_detect_img
            obj = cv.SimpleBlobDetector('MinThreshold',50, 'MaxThreshold',220);
            typename = obj.typeid();

            img = imread(TestSimpleBlobDetector.im);
            kpts = obj.detect(img);
            validateattributes(kpts, {'struct'}, {'vector'});
            assert(all(ismember(TestSimpleBlobDetector.kfields, fieldnames(kpts))));
        end

        function test_detect_imgset
            img = imread(TestSimpleBlobDetector.im);
            imgs = {img, img};
            obj = cv.SimpleBlobDetector();

            kpts = obj.detect(imgs);
            validateattributes(kpts, {'cell'}, {'vector', 'numel',numel(imgs)});
            cellfun(@(kpt) validateattributes(kpt, {'struct'}, {'vector'}), kpts);
            cellfun(@(kpt) assert(all(ismember(TestSimpleBlobDetector.kfields, fieldnames(kpt)))), kpts);
        end

        function test_detect_mask
            img = imread(TestSimpleBlobDetector.im);
            mask = zeros(size(img), 'uint8');
            mask(:,1:end/2) = 255;  % only search left half of the image
            obj = cv.SimpleBlobDetector();
            kpts = obj.detect(img, 'Mask',mask);
            validateattributes(kpts, {'struct'}, {'vector'});
            assert(all(ismember(TestSimpleBlobDetector.kfields, fieldnames(kpts))));
            xy = cat(1, kpts.pt);
            assert(all(xy(:,1) <= ceil(size(img,2)/2)));
        end

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

end


%=========================================================
%
%This is a prog in the MutualInfo 0.9 package written by
% Hanchuan Peng.
%
%Disclaimer: The author of program is Hanchuan Peng
%      at <penghanchuan@yahoo.com> and <phc@cbmv.jhu.edu>.
%
%The CopyRight is reserved by the author.
%
%Last modification: April/19/2002
%
%========================================================
%
%
%batch compiling of the mex files from cpp src
%by Hanchuan Peng
%April/16/2002

list = dir('*.cpp');

for i=1:length(list),

  fprintf('building mex(dll) of %s\n',list(i).name);
  mex(list(i).name);

end;


function view = editMenu(view)
%
% view = editMenu(view)
%
% Set up the callbacks of the EDIT menu.
%
% djh, 2/28/2001
editMenu = uimenu('Label','Edit','Separator','on');

% edit mrSESSION:
% [mSESSION,ok] = EditSession(mrSESSION);
% if ok, saveSession(1), end;
cb=['[mrSESSION,ok] = EditSession(mrSESSION,0); ',...
    'if ok, saveSession(1); end;'];
uimenu(editMenu,'Label','Edit/view mrSESSION','Separator','off',...
   'CallBack',cb);

% Edit alignment(using mrRx):
uimenu(editMenu,'Label','Edit/View Alignment...','Separator','off',...
    'Callback','rxAlign;', 'Accelerator', '7');

datatypeMenu = uimenu(editMenu,'Label','Data Type','Separator','off');

% Edit data type:
% c = curDataType(view)
% [dataTYPES(c),ok] = EditDataType(dataTYPES(c))
% if ok, saveSession(1), end;
cb=['c = ',view.name,'.curDataType; ',...
	'[dataTYPES(c), ok] = EditDataType(dataTYPES(c)); ',...
    'if ok, saveSession(1), end;'];
uimenu(datatypeMenu,'Label','Edit data type','Separator','off',...
   'CallBack',cb);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Assign Visual Field Map Parameters submenu:
retinoMapMenu = uimenu(datatypeMenu, 'Label', 'Set Retinotopy Parameters...', ...
                        'Separator', 'off');

% submenus for assigning visual field map params
% retinoSetParams(view);
cb = sprintf('retinoSetParams(%s); ', view.name);
uimenu(retinoMapMenu, 'Label', 'Current Scan', 'Callback', cb);

% scans = er_selectScans(view); retinoSetParams(view, [], scans);
cb = [sprintf('scans = er_selectScans(%s); ', view.name) ...
      sprintf('retinoSetParams(%s, [], scans); ', view.name)];
uimenu(retinoMapMenu, 'Label', 'Select Scans', 'Callback', cb);

% retinoSetParams(view, [], 1:numScans(view));
cb = sprintf('retinoSetParams(%s, [], 1:numScans(%s)); ', ...
               view.name, view.name);
uimenu(retinoMapMenu, 'Label', 'All Scans', 'Callback', cb);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Edit Event-Related Parameters callback:
%   params = er_getParams(view);
%   params = er_editParams(params);
%   er_setParams(view, params);
cb = sprintf('params = er_getParams(%s); ', view.name);
cb = [cb 'params = er_editParams(params); '];
cb = [cb sprintf('er_setParams(%s, params); ', view.name)];
uimenu(datatypeMenu, 'Label', 'Edit Event-Related Parameters (cur scan)', ...
    'Separator', 'off', 'CallBack', cb);

% Duplicate data type:
%   duplicateDataType(view);
cb = ['duplicateDataType(',view.name,');'];
uimenu(datatypeMenu, 'Label', 'Duplicate current data type', ...
        'Separator', 'on', 'CallBack', cb);

% Group scans into data type:
%   groupScans(view));
cb = ['groupScans(',view.name,');'];
uimenu(datatypeMenu, 'Label', 'Group scans into data type', ...
    'Separator', 'off', 'CallBack',cb);

% Remove data type:
%   removeDataType(getDataTypeName(view));
cb = ['removeDataType(getDataTypeName(',view.name,'));'];
uimenu(datatypeMenu, 'Label', 'Remove data type', 'Separator', 'on',...
   'CallBack', cb);

% Remove last scan from data type:
%   removeScan(view, numScans(view), '', 1);
cb = sprintf('removeScan(%s, numScans(%s), '''', 1); ', view.name, view.name);
uimenu(datatypeMenu, 'Label', 'Remove last scan in data type', 'Separator', 'off',...
   'CallBack', cb);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Edit Preferences callback:
% editPreferences;
uimenu(editMenu, 'Label', 'Edit Preferences', 'Accelerator', ';', ...
    'Separator', 'off', 'CallBack','editPreferences;');

return


function data = read_1_pinnacle_file(filename,display)
%
%
% 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/>.

%
data = [];
if ~exist('display','var')
	display = 1;
end

if display == 1
	h = waitbar(0,sprintf('Reading file "%s" ...',filename));
end

fid = fopen(filename);
if fid < 0
	fprintf('File "%s" cannot be opened.\n',filename);
    if display == 1
        close(h);
    end
	return;
end

%try
	while 1
		[fieldname,val] = read_1_field_pinnacle(fid);
		if isempty(fieldname) && isempty(val)
			break;
		else
			data = add_1_field_to_struct(data,fieldname,val);
		end
	end
	fclose(fid);
% catch
% 	fclose(fid);
% 	disp(lasterr);
% end

if display == 1
	close(h);
end


classdef SessClass < TreeNodeClass

    properties % (Access = private)
        runs;
    end

    methods

        % ----------------------------------------------------------------------------------
        function obj = SessClass(varargin)
            obj@TreeNodeClass(varargin);

            obj.type  = 'sess';
            obj.runs = RunClass().empty;
            if nargin==0
                obj.name  = '';
                return;
            end

            if nargin<4
                if isa(varargin{1}, 'SessClass')
                    if nargin==1
                        obj.Copy(varargin{1});
                    elseif nargin==2
                        obj.Copy(varargin{1}, varargin{2});
                    end
                    return;
                elseif isa(varargin{1}, 'FileClass')
                    [~, ~, obj.name] = varargin{1}.ExtractNames();
                else
                    obj.name = varargin{1};
                end
            elseif nargin==4
                if ~isa(varargin{1}, 'FileClass')
                    [~, obj.name] = varargin{1}.ExtractNames();
                else
                    obj.name = varargin{1};
                end
                obj.iGroup = varargin{2};
                obj.iSubj = varargin{3};
                obj.iSess = varargin{4};
            end
        end

        % ----------------------------------------------------------------------------------
        function nbytes = MemoryRequired(obj)
            nbytes = 0;
            for ii = 1:length(obj.runs)
                nbytes = nbytes + obj.runs(ii).MemoryRequired();
            end
            nbytes = nbytes + obj.procStream.MemoryRequired();
        end

        % ----------------------------------------------------------------------------------
        % Copy processing params (procInut and procResult) from
        % S to obj if obj and S are equivalent nodes
        % ----------------------------------------------------------------------------------
        function Copy(obj, obj2, conditional)
            % Copy SessClass object obj2 to SessClass object obj. Conditional option applies
            % only to all the runs under this group. If == 'conditional' ONLY derived data,
            % that is, only from procStream but NOT from acquired data is copied for all the runs.
            %
            % Conversly unconditional copy copies all properties in the runs under this session
            if nargin==3 && strcmp(conditional, 'conditional')
                if obj.Mismatch(obj2)
                    return
                end
                for i = 1:length(obj.runs)
                    j = obj.existRun(i,obj2);
                    if (j>0)
                        obj.runs(i).Copy(obj2.runs(j), 'conditional');
                    elseif i<=length(obj2.runs)
                        obj.runs(i).Copy(obj2.runs(i), 'conditional');
                    else
                        obj.Mismatch();
                    end
                end
                obj.Copy@TreeNodeClass(obj2, 'conditional');
            else
                if nargin<3
                    conditional = '';
                end
                for i=1:length(obj2.runs)
                    obj.runs(i) = RunClass(obj2.runs(i), conditional);
                end
                obj.Copy@TreeNodeClass(obj2);
            end
        end

        % --------------------------------------------------------------
        function CopyStims(obj, obj2)
            obj.CondNames = obj2.CondNames;
            for ii = 1:length(obj.runs)
                obj.runs(ii).CopyStims(obj2.runs(ii));
            end
        end

        % ----------------------------------------------------------------------------------
        % Check whether run R exists in this session and return
        % its index if it does exist. Else return 0.
        % ----------------------------------------------------------------------------------
        function j = existRun(obj, k, S)
            j=0;
            for i=1:length(S.runs)
                [~,rname1] = fileparts(obj.runs(k).name);
                [~,rname2] = fileparts(S.runs(i).name);
                if strcmp(rname1, rname2)
                    j=i;
                    break;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        % Subjects obj1 and obj2 are considered equivalent if their names
        % are equivalent and their sets of runs are equivalent.
        % ----------------------------------------------------------------------------------
        function B = equivalent(obj1, obj2)
            B=1;
            if ~strcmp(obj1.name, obj2.name)
                B=0;
                return;
            end
            for i=1:length(obj1.runs)
                j = existRun(obj1, i, obj2);
                if j==0
                    B=0;
                    return;
                end
            end
            for i=1:length(obj2.runs)
                j = existRun(obj2, i, obj1);
                if j==0
                    B=0;
                    return;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function b = CheckForNameConflict(obj, run)
            b = false;
            [~, runname] = fileparts(run.GetName());
            if strcmp(runname, obj.name)
                b = true;
            end
        end

        % ----------------------------------------------------------------------------------
        function Add(obj, run)
            [~,f,e] = fileparts(run.GetName());
            if strcmp(f, obj.name)
                msg{1} = sprintf('WARNING: The run being added (%s) has the same name as the session (%s) containing it. ', [f,e], obj.name);
                msg{2} = sprintf('The run names should not have the same name as the session, otherwise ');
                msg{3} = sprintf('it may cause incorrect results in processing. Do you want to change this run''s name?');
                obj.logger.Write('%s\n', [msg{:}]);

                % Deconflict name of session with name of run if there is no
                % session folder for this session
                if ~ispathvalid(['./',obj.name], 'dir')
                    obj.name = [obj.name, '_s'];
                    obj.logger.Write('Renaming session to %s\n', obj.name);
                end
            end

            % Add run to this session
            jj = 0;
            for ii = 1:length(obj.runs)
                if strcmp(obj.runs(ii).GetName, run.GetName())
                    jj = ii;
                    break;
                end
            end
            if jj==0
                jj = length(obj.runs)+1;
                run.SetIndexID(obj.iGroup, obj.iSubj, obj.iSess, jj);
                run.SetPath(obj.path);                      % Inherit root path from session
                obj.runs(jj) = run;
                obj.logger.Write('         Added run  "%s"  to session  "%s" .\n', obj.runs(jj).GetFileName, obj.GetFileName);
            end
            obj.children = obj.runs;
        end

        % ----------------------------------------------------------------------------------
        function list = DepthFirstTraversalList(obj)
            list{1} = obj;
            for ii = 1:length(obj.runs)
                list{ii+1,1} = obj.runs(ii);
            end
        end

        % ----------------------------------------------------------------------------------
        % Deletes derived data in procResult
        % ----------------------------------------------------------------------------------
        function Reset(obj, option)
            if ~exist('option','var')
                option = 'down';
            end
            if strcmp(option, 'down')
                for jj = 1:length(obj.runs)
                    obj.runs(jj).Reset();
                end
            end
            Reset@TreeNodeClass(obj);
        end

        % ----------------------------------------------------------------------------------
        function err = LoadSubBranch(obj)
            err = -1;
            if isempty(obj)
                return;
            end
            err1 = obj.procStream.Load([obj.path, obj.GetOutputFilename()]);
            err2 = obj.runs(1).Load();
            if err1==0 && err2==0
                err = 0;
            end
        end

        % ----------------------------------------------------------------------------------
        function FreeMemorySubBranch(obj)
            if isempty(obj)
                return;
            end
            obj.runs(1).FreeMemory()
        end

        % ----------------------------------------------------------------------------------
        function CreateOutputDir(obj)
            if ispathvalid([obj.pathOutputAlt, obj.outputDirname, obj.name])
                return;
            end
            if ~ispathvalid([obj.pathOutputAlt, obj.name])
                return;
            end
            mkdir([obj.pathOutputAlt, obj.outputDirname, obj.name]);
        end

        % ----------------------------------------------------------------------------------
        function LoadInputVars(obj, tHRF_common)
			obj.inputVars.nTrialsRuns = [];
            for iRun = 1:length(obj.runs)
                % Set common tHRF: make sure size of tHRF, dcAvg and dcAvg is same for
                % all runs. Use smallest tHRF as the common one.
                obj.runs(iRun).procStream.output.SettHRFCommon(tHRF_common, obj.runs(iRun).name, obj.runs(iRun).type);

                obj.inputVars.dodAvgRuns{obj.runs(iRun).iRun}    = obj.runs(iRun).procStream.output.GetVar('dodAvg');
                obj.inputVars.dodAvgStdRuns{obj.runs(iRun).iRun} = obj.runs(iRun).procStream.output.GetVar('dodAvgStd');
                obj.inputVars.dodSum2Runs{obj.runs(iRun).iRun}   = obj.runs(iRun).procStream.output.GetVar('dodSum2');
                obj.inputVars.dcAvgRuns{obj.runs(iRun).iRun}     = obj.runs(iRun).procStream.output.GetVar('dcAvg');
                obj.inputVars.dcAvgStdRuns{obj.runs(iRun).iRun}  = obj.runs(iRun).procStream.output.GetVar('dcAvgStd');
                obj.inputVars.dcSum2Runs{obj.runs(iRun).iRun}    = obj.runs(iRun).procStream.output.GetVar('dcSum2');
                obj.inputVars.tHRFRuns{obj.runs(iRun).iRun}      = obj.runs(iRun).procStream.output.GetTHRF();
                obj.inputVars.mlActRuns{obj.runs(iRun).iRun}     = obj.runs(iRun).procStream.output.GetVar('mlActAuto');
                obj.inputVars.nTrialsRuns{obj.runs(iRun).iRun}   = obj.runs(iRun).procStream.output.GetVar('nTrials');
                if ~isempty(obj.runs(iRun).procStream.output.GetVar('misc'))
                    if isfield(obj.runs(iRun).procStream.output.misc, 'stim') == 1
                        obj.inputVars.stimRuns{obj.runs(iRun).iRun}      = obj.runs(iRun).procStream.output.misc.stim;
                    else
                        obj.inputVars.stimRuns{obj.runs(iRun).iRun}      = obj.runs(iRun).GetVar('stim');
                    end
                else
                    obj.inputVars.stimRuns{obj.runs(iRun).iRun}      = obj.runs(iRun).GetVar('stim');
                end
                obj.inputVars.AauxRuns{obj.runs(iRun).iRun}      = obj.runs(iRun).procStream.output.GetVar('Aaux');
                obj.inputVars.tIncAutoRuns{obj.runs(iRun).iRun}  = obj.runs(iRun).procStream.output.GetVar('tIncAuto');
                obj.inputVars.rcMapRuns{obj.runs(iRun).iRun}     = obj.runs(iRun).procStream.output.GetVar('rcMap');

                % a) Find all variables needed by proc stream
                args = obj.procStream.GetInputArgs();

                % b) Find these variables in this run
                for ii = 1:length(args)
                    if ~eval( sprintf('isproperty(obj.inputVars, ''%s'')', args{ii}) )
                        eval( sprintf('obj.inputVars.%s = obj.GetVar(args{ii});', args{ii}) );
                    end
                end

                % Free run memory
                obj.runs(iRun).FreeMemory()
            end

        end

        % ----------------------------------------------------------------------------------
        function Calc(obj, options)
            if ~exist('options','var') || isempty(options)
                options = 'overwrite';
            end

            if strcmpi(options, 'overwrite')
                % Recalculating result means deleting old results, if
                % option == 'overwrite'
                obj.procStream.output.Flush();
            end

            if obj.DEBUG
                obj.logger.Write('Calculating processing stream for group %d, session %d\n', obj.iGroup, obj.iSubj);
            end

            % Calculate all runs in this session and generate common tHRF
            tHRF_common = {};
            for iRun = 1:length(obj.runs)
                obj.runs(iRun).Calc();

                % Find smallest tHRF among the sessions and make this the common one.
                tHRF_common = obj.runs(iRun).procStream.output.GeneratetHRFCommon(tHRF_common);
            end

            % Update call application GUI using it's generic Update function
            if ~isempty(obj.updateParentGui)
                obj.updateParentGui('DataTreeClass', [obj.iGroup, obj.iSubj, obj.iSess, obj.iRun]);
            end

            % Load all the variables that might be needed by procStream.Calc() to calculate proc stream for this session
            obj.LoadInputVars(tHRF_common);

            Calc@TreeNodeClass(obj);

            if obj.DEBUG
                fprintf('Completed processing stream for group %d, session %d\n', obj.iGroup, obj.iSubj);
                fprintf('\n');
            end

        end

        % ----------------------------------------------------------------------------------
        function Print(obj, indent)
            if ~exist('indent', 'var')
                indent = 4;
            else
                indent = indent+4;
            end
            Print@TreeNodeClass(obj, indent);
            for ii = 1:length(obj.runs)
                obj.runs(ii).Print(indent);
            end
        end

        % ---------------------------------------------------------------
        function PrintProcStream(obj)
            fcalls = obj.procStream.GetFuncCallChain();
            obj.logger.Write('Session processing stream:\n');
            for ii = 1:length(fcalls)
                obj.logger.Write('%s\n', fcalls{ii});
            end
            obj.logger.Write('\n');
            obj.runs(1).PrintProcStream();
        end

        % ----------------------------------------------------------------------------------
        function b = IsEmpty(obj)
            b = true;
            if isempty(obj)
                return;
            end
            for ii = 1:length(obj.runs)
                if ~obj.runs(ii).IsEmpty()
                    b = false;
                    break;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function b = IsEmptyOutput(obj)
            b = true;
            if isempty(obj)
                return;
            end
            for ii = 1:length(obj.runs)
                if ~obj.runs(ii).IsEmptyOutput()
                    b = false;
                    break;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function SaveAcquiredData(obj)
            for ii = 1:length(obj.runs)
                obj.runs(ii).SaveAcquiredData();
            end
        end

        % ----------------------------------------------------------------------------------
        function b = AcquiredDataModified(obj)
            b = false;
            for ii = 1:length(obj.runs)
                if obj.runs(ii).AcquiredDataModified()
                    b = true;
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function varval = GetVar(obj, varname)
            % First call the common code for all levels
            varval = obj.GetVar@TreeNodeClass(varname);

            % Now call the session specific part
            if isempty(varval)
                varval = obj.runs(1).GetVar(varname);
            end
        end

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Public Set/Get methods
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods

        % ----------------------------------------------------------------------------------
        function probe = GetProbe(obj, option)
            probe = obj.runs(1).GetProbe();
%             for run = obj.runs
%                if ~(probe == run.GetProbe())
%                   warning(['Probe ', run.name, 'differs from ', obj.runs(1).name])
%                end
%             end
        end

        % ----------------------------------------------------------------------------------
        function SD = GetSDG(obj,option)
            if exist('option','var')
                SD = obj.runs(1).GetSDG(option);
            else
                SD = obj.runs(1).GetSDG();
            end
        end

        % ----------------------------------------------------------------------------------
        function srcpos = GetSrcPos(obj,option)
            if exist('option','var')
                srcpos = obj.runs(1).GetSrcPos(option);
            else
                srcpos = obj.runs(1).GetSrcPos();
            end
        end

        % ----------------------------------------------------------------------------------
        function detpos = GetDetPos(obj,option)
            if exist('option','var')
                detpos = obj.runs(1).GetDetPos(option);
            else
                detpos = obj.runs(1).GetDetPos();
            end
        end

        % ----------------------------------------------------------------------------------
        function bbox = GetSdgBbox(obj)
            bbox = obj.runs(1).GetSdgBbox();
        end

        % ----------------------------------------------------------------------------------
        function wls = GetWls(obj)
            wls = obj.runs(1).GetWls();
        end

        % ----------------------------------------------------------------------------------
        function [iDataBlks, iCh] = GetDataBlocksIdxs(obj, iCh)
            if nargin<2
                iCh = [];
            end
            [iDataBlks, iCh] = obj.runs(1).GetDataBlocksIdxs(iCh);
        end

        % ----------------------------------------------------------------------------------
        function n = GetDataBlocksNum(obj)
            n = obj.runs(1).GetDataBlocksNum();
        end

        % ----------------------------------------------------------------------------------
        function SetConditions(obj, CondNames)
            if nargin==1
                CondNames = {};
                for ii = 1:length(obj.runs)
                    obj.runs(ii).SetConditions();
                    CondNames = [CondNames, obj.runs(ii).GetConditions()];
                end
            elseif nargin==2
                for ii = 1:length(obj.runs)
                    obj.runs(ii).SetConditions(CondNames);
                end
            end
            obj.CondNames = unique(CondNames);
        end

        % ----------------------------------------------------------------------------------
        function CondNames = GetConditionsActive(obj)
            CondNames = obj.CondNames;
            for ii = 1:length(obj.runs)
                CondNamesRun = obj.runs(ii).GetConditionsActive();
                for jj = 1:length(CondNames)
                    k = find(strcmp(['-- ', CondNames{jj}], CondNamesRun)); %#ok<EFIND>
                    if ~isempty(k)
                        CondNames{jj} = ['-- ', CondNames{jj}];
                    end
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function aux = GetAuxiliary(obj)
            aux = [];
        end

        % ----------------------------------------------------------------------------------
        function [fn_error, missing_args, prereqs] = CheckProcStreamOrder(obj)
            missing_args = {};
            fn_error = 0;
            prereqs = '';
            for i = 1:length(obj.runs)
                [fn_error, missing_args, prereqs] = obj.runs(i).CheckProcStreamOrder;
                if ~isempty(missing_args)
                    return
                end
            end
        end

        % ----------------------------------------------------------------------------------
        function r = ListOutputFilenames(obj, options)
            if ~exist('options','var')
                options = '';
            end
            r = obj.GetOutputFilename(options);
            fprintf('  %s %s\n', obj.path, r);
            for ii = 1:length(obj.runs)
                obj.runs(ii).ListOutputFilenames(options);
            end
        end

        % --------------------------------------------------------------------------
        function ApplyParamEditsToAllRuns(obj, iFcall, iParam, val)
            for jj = 1:length(obj.runs)
                obj.runs(jj).procStream.EditParam(iFcall, iParam, val);
            end
        end

    end

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Private methods
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    methods (Access = public)

        % ----------------------------------------------------------------------------------
        function BackwardCompatability(obj)
            obj.BackwardCompatability@TreeNodeClass();
            for ii = 1:length(obj.runs)
                obj.runs(ii).BackwardCompatability();
            end
        end

    end  % Private methods

end


function asSetAllTitlesToImageString
global asObjs
for i = 1 : length(asObjs)
%     asObjs(i).roi.setPosition(pos);
    asObjs(i).toggleTitleAsImageText;
end


function [compartments, uniqueCompartments, abbr, uniqueAbbr] = getCompartment(mets)
% Gets the compartment for each metabolite, and the unique compartments,
% from metabolite abbreviation(s), each of which must have compartment
% symbol concatentated on the right hand side (i.e. `metAbbr[*]`).
%
% USAGE:
%
%    [compartments, uniqueCompartments] = getCompartment(mets)
%
% INPUT:
%    mets:                  char array with a single metabolite abbreviation
%                           or
%                           `m x 1` cell array of metabolite abbreviations
%
% OUTPUTS:
%    compartments:          char array with a single compartment identifier
%                           or
%                           `m x 1` cell array of compartment identifiers
%
%    uniqueCompartments:    char array with a single compartment identifier
%                           or
%                           cell array of unique compartment identifiers
%    abbr:                  char array with a single metabolite
%                           abbreviation, without compartment
%                           or
%                           `m x 1` cell array of metabolite abbreviations,
%                           without compartments
%
% .. Author:
%       - Ronan M.T. Fleming
%       - Hulda SH, Nov. 2012   Switched from for loop to regular expression

bool=0;
if ischar(mets)
    tmp{1}=mets;
    mets=tmp;
    bool=1;
end

pat = '(?<abbr>[^\[]+)\[(?<compartment>[^\]]+)\]';
metStruct = regexp(mets,pat,'names'); % m x 1 cell array with fields abbr and compartment in each cell
metStruct = [metStruct{:}]'; % Convert from cell array to double
compartments = {metStruct.compartment}; % Concatenate compartment fields
compartments = reshape(compartments,length(compartments),1);
abbr = {metStruct.abbr}; % Concatenate compartment fields
abbr = reshape(abbr,length(abbr),1);
uniqueCompartments = unique(compartments);
uniqueAbbr = unique(abbr);

if bool==1
    compartments = compartments{1};
    uniqueCompartments = uniqueCompartments{1};
    abbr = abbr{1};
    uniqueAbbr = uniqueAbbr{1};
end


function val = get(A, prop_name)
%
%  Get transformMatrix properties from specified object and return
%  the value.
%
%     val = get(A, prop_name);
%
%  Valid choices for prop_name are:
%    'transform', 'transpose'
%

%  J. Nagy  6/2/02

switch prop_name
case 'transform'
  val = A.transform;
case 'transpose'
  val = A.transpose;
otherwise
  error([prop_name, 'Is not valid transformMatrix property'])
end


function [ExportFile, sFileOut] = export_data(DataFile, ChannelMat, ExportFile, FileFormat)
% EXPORT_DATA: Exports a recordings file to one of the supported file formats.
%
% USAGE:  [ExportFile, sFileOut] = export_data( DataFile,        [], ExportFile=[ask], FileFormat=[detect] )
%         [ExportFile, sFileOut] = export_data( DataMat, ChannelMat, ExportFile=[ask], FileFormat=[detect] ) : Save a data structure
%                                  export_data( DataFiles{}, ... )                      : Batch process over multiple files
%
% INPUT:
%     - DataFile   : Brainstorm data file name to be exported
%     - DataMat    : Brainstorm data structure to be exported
%     - ExportFile : Full path to target file (extension will determine the format)
%                    If not specified: asked to the user

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

% ===== PARSE INPUTS =====
if (nargin < 4) || isempty(FileFormat)
    FileFormat = [];
end
if (nargin < 3) || isempty(ExportFile)
    ExportFile = [];
end
if (nargin < 2) || isempty(ChannelMat)
    ChannelMat = [];
end
% Initialize returned variables
sFileOut = [];

% ===== RECURSIVE CALLS =====
% CALL: export_data( DataFiles, ... )
if iscell(DataFile)
    % Single file
    if (length(DataFile) == 1)
        DataFile = DataFile{1};
    % Multiple files
    else
        AllOutputs = cell(1,length(DataFile));
        % Call function once to get the output path
        [AllOutputs{1}, sFileOut1] = export_data(DataFile{1}, ChannelMat, ExportFile);
        if isempty(AllOutputs{1})
            ExportFile = [];
            return;
        end
        % Get output path
        [outPath, outBase, outExt] = bst_fileparts(AllOutputs{1});
        % Loop on the other files
        for i = 2:length(DataFile)
            % Build output file name
            [dataPath, dataBase, dataExt] = bst_fileparts(DataFile{i});
            newFile = bst_fullfile(outPath, [dataBase, outExt]);
            newFile = strrep(newFile, '_data', '');
            newFile = strrep(newFile, 'data_', '');
            newFile = strrep(newFile, '0raw_', '');
            AllOutputs{i} = newFile;
            % Export file
            export_data(DataFile{i}, ChannelMat, AllOutputs{i}, sFileOut1.format);
        end
        ExportFile = AllOutputs;
        return;
    end
end

% ===== LOAD DATA =====
% CALL: export_data( DataFile, [], ExportFile )
if ischar(DataFile)
    isRawIn = ~isempty(strfind(DataFile, '_0raw'));
    % Load initial file
    DataMat = in_bst_data(DataFile);
    % Get raw file structure
    if isRawIn
        sFileIn = DataMat.F;
        if (length(sFileIn.epochs) > 1)
            error('Cannot export epoched files.');
        end
    else
        sFileIn = in_fopen(DataFile, 'BST-DATA');
    end
    % Load channel file
    ChannelFile = bst_get('ChannelFileForStudy', DataFile);
    ChannelMat = in_bst_channel(ChannelFile);
% CALL: export_data( DataMat, ChannelMat, ExportFile )
elseif isstruct(DataFile)
    DataMat = DataFile;
    DataFile = [];
    isRawIn = 0;
    % Create a fake sFile structure
    sFileIn = in_fopen(DataMat, 'BST-DATA');
else
    error('Invalid call.');
end

% ===== SELECT OUTPUT FILE =====
if isempty(ExportFile)
    % === Build a default filename ===
    % Get default directories and formats
    LastUsedDirs = bst_get('LastUsedDirs');
    DefaultFormats = bst_get('DefaultFormats');
    % Get default extension
    switch (DefaultFormats.DataOut)
        case {'', 'BST-BIN'},   DefaultExt = '.bst';
        case 'FT-TIMELOCK',     DefaultExt = '.mat';
        case 'SPM-DAT',         DefaultExt = '.mat';
        case 'EEG-BRAINAMP',    DefaultExt = '.eeg';
        case 'EEG-CARTOOL-EPH', DefaultExt = '.eph';
        case 'EEG-EGI-RAW',     DefaultExt = '.raw';
        case 'EEG-EDF',         DefaultExt = '.edf';
        case 'NIRS-SNIRF',      DefaultExt = '.snirf';
        case 'ASCII-CSV',       DefaultExt = '.csv';
        case 'ASCII-CSV-HDR',   DefaultExt = '.csv';
        case 'ASCII-CSV-HDR-TR',DefaultExt = '.csv';
        case 'ASCII-TSV',       DefaultExt = '.tsv';
        case 'ASCII-TSV-HDR',   DefaultExt = '.tsv';
        case 'ASCII-TSV-HDR-TR',DefaultExt = '.tsv';
        case 'ASCII-SPC',       DefaultExt = '.txt';
        case 'ASCII-SPC-HDR',   DefaultExt = '.txt';
        case 'EXCEL',           DefaultExt = '.xlsx';
        case 'EXCEL-TR',        DefaultExt = '.xlsx';
        case 'BST',             DefaultExt = '_timeseries.mat';
        otherwise,              DefaultExt = '_timeseries.mat';
    end
    % Build default output filename
    if ~isempty(DataFile)
        [BstPath, BstBase, BstExt] = bst_fileparts(DataFile);
    else
        BstBase = file_standardize(DataMat.Comment);
    end
    DefaultExportFile = bst_fullfile(LastUsedDirs.ExportData, [BstBase, DefaultExt]);
    DefaultExportFile = strrep(DefaultExportFile, '_data', '');
    DefaultExportFile = strrep(DefaultExportFile, 'data_', '');
    DefaultExportFile = strrep(DefaultExportFile, '0raw_', '');

    % === Ask user filename ===
    % RAW file or imported
    if isRawIn
        FileFilters = bst_get('FileFilters', 'rawout');
    else
        FileFilters = bst_get('FileFilters', 'dataout');
    end
    % Put file
    [ExportFile, FileFormat, FileFilter] = java_getfile( 'save', ...
        'Export MEG/EEG recordings...', ... % Window title
        DefaultExportFile, ...              % Default directory
        'single', 'files', ...              % Selection mode
        FileFilters, ...
        DefaultFormats.DataOut);
    % If no file was selected: exit
    if isempty(ExportFile)
        return;
    end
    % Save new default export path
    LastUsedDirs.ExportData = bst_fileparts(ExportFile);
    bst_set('LastUsedDirs', LastUsedDirs);
    % Save default export format
    DefaultFormats.DataOut = FileFormat;
    bst_set('DefaultFormats',  DefaultFormats);

% Guess file format based on its extension
elseif isempty(FileFormat)
    [BstPath, BstBase, BstExt] = bst_fileparts(ExportFile);
    switch lower(BstExt)
        case '.bst',   FileFormat = 'BST-BIN';
        case '.eeg',   FileFormat = 'EEG-BRAINAMP';
        case '.eph',   FileFormat = 'EEG-CARTOOL-EPH';
        case '.raw',   FileFormat = 'EEG-EGI-RAW';
        case '.edf',   FileFormat = 'EEG-EDF';
        case '.snirf', FileFormat = 'NIRS-SNIRF';
        case '.txt',   FileFormat = 'ASCII-SPC';
        case '.csv',   FileFormat = 'ASCII-CSV-HDR';
        case '.tsv',   FileFormat = 'ASCII-TSV-HDR';
        case '.xlsx',  FileFormat = 'EXCEL';
        case '.mat',   FileFormat = 'BST';
        otherwise,     error('Unsupported file extension.');
    end
end
% Show progress bar
isProgress = bst_progress('isVisible');
if ~isProgress
    bst_progress('start', 'Export EEG/MEG recordings', 'Exporting file...');
end
% Option for input raw file
if isRawIn
    ImportOptions = db_template('ImportOptions');
    ImportOptions.ImportMode      = 'Time';
    ImportOptions.DisplayMessages = 0;
    ImportOptions.UseCtfComp      = 0;
    ImportOptions.UseSsp          = 0;
    ImportOptions.RemoveBaseline  = 'no';
end

% ===== REMOVE ANNOTATION CHANNELS =====
% Detect annotation channels (exclude BST-BIN output, because we want to keep everything)
if ~strcmpi(FileFormat, 'BST-BIN')
    iAnnot = channel_find(ChannelMat.Channel, {'EDF', 'BDF', 'KDF'});
else
    iAnnot = [];
end
% List of input and output channels
iChannelsIn = setdiff(1:length(ChannelMat.Channel), iAnnot);
iChannelsOut = 1:length(iChannelsIn);
% Selected channel mats
ChannelMatIn = ChannelMat;
ChannelMatOut = ChannelMat;
% Remove unwanted channels from channel file
if ~isempty(iAnnot)
    ChannelMatOut.Channel = ChannelMatOut.Channel(iChannelsIn);
    for iProj = 1:length(ChannelMatOut.Projector)
        if isequal(ChannelMatOut.Projector(iProj).SingVal, 'REF')
            ChannelMatOut.Projector(iProj).Components = ChannelMatOut.Projector(iProj).Components(iChannelsIn, iChannelsIn);
        else
            ChannelMatOut.Projector(iProj).Components = ChannelMatOut.Projector(iProj).Components(iChannelsIn, :);
        end
    end
end
% Remove unwanted channels from input data file
if ~isRawIn
    if isfield(DataMat, 'F') && ~isempty(DataMat.F)
        DataMat.F = DataMat.F(iChannelsIn,:);
    end
    if isfield(DataMat, 'ChannelFlag') && ~isempty(DataMat.ChannelFlag)
        DataMat.ChannelFlag = DataMat.ChannelFlag(iChannelsIn);
    end
end

% ===== CREATE OUTPUT RAW FILE =====
% Output data as raw file (continuous writers routines)
isRawOut = ismember(FileFormat, {'BST-BIN', 'EEG-EGI-RAW', 'SPM-DAT', 'EEG-EDF', 'EEG-BRAINAMP'});
% Open output file
if isRawOut
    [sFileOut, errMsg] = out_fopen(ExportFile, FileFormat, sFileIn, ChannelMatOut, iChannelsIn);
    % Error management
    if isempty(sFileOut) && ~isempty(errMsg)
        error(errMsg);
    elseif ~isempty(errMsg)
        disp(['BST> Warning: ' errMsg]);
    end
end

% ===== RAW IN / RAW OUT =====
if isRawIn && isRawOut
    % Check that in!=out
    if file_compare(sFileIn.filename, sFileOut.filename)
        error('Input and output files are the same.');
    end
    % Get default epoch size
    EpochSize = bst_process('GetDefaultEpochSize', sFileOut);
    % Process by sample blocks
    nSamples = round((sFileOut.prop.times(2) - sFileOut.prop.times(1)) * sFileOut.prop.sfreq) + 1;
    nBlocks = ceil(nSamples / EpochSize);
    % Show progress bar
    if ~isProgress
        bst_progress('start', 'Export EEG/MEG recordings', 'Exporting file...', 0, nBlocks);
    end
    % Copy files by block
    for iBlock = 1:nBlocks
        % Get sample indices
        SamplesBounds = sFileOut.prop.times(1) * sFileOut.prop.sfreq + [(iBlock-1) * EpochSize, min(iBlock*EpochSize-1, nSamples-1)];
        % Read from input file
        F = in_fread(sFileIn, ChannelMatIn, 1, SamplesBounds, iChannelsIn, ImportOptions);
        % Save to output file
        sFileOut = out_fwrite(sFileOut, ChannelMatOut, 1, SamplesBounds, iChannelsOut, F);
        % Increase progress bar
        if ~isProgress
            bst_progress('inc', 1);
        end
    end

% ===== SAVE FULL FILES =====
else
    % Load full file
    if isRawIn
        F = in_fread(sFileIn, ChannelMatIn, 1, [], iChannelsIn, ImportOptions);
    else
        if isfield(DataMat, 'F') && ~isempty(DataMat.F)
            F = DataMat.F;
        elseif isfield(DataMat, 'ImageGridAmp') && ~isempty(DataMat.ImageGridAmp)
            F = DataMat.ImageGridAmp;
        else
            error('No relevant data to save found in structure.');
        end
    end

    % Save full file
    if isRawOut
        out_fwrite(sFileOut, ChannelMatOut, 1, [], iChannelsOut, F);
    else
        % Switch between file formats
        switch FileFormat
            case 'BST'
                DataMat.F = F;
                bst_save(ExportFile, DataMat, 'v6');
            case 'FT-TIMELOCK'
                DataMat.F = F;
                ftData = out_fieldtrip_data(DataMat, ChannelMatOut, [], 1);
                bst_save(ExportFile, ftData, 'v6');
            case 'EEG-CARTOOL-EPH'
                % Get sampling rate
                samplingFreq = round(1/(DataMat.Time(2) - DataMat.Time(1)));
                % Write header : nb_electrodes, nb_time, sampling_freq
                dlmwrite(ExportFile, [size(F,1), size(F,2), samplingFreq], 'newline', 'unix', 'precision', '%d', 'delimiter', ' ');
                % Write data
                dlmwrite(ExportFile, F' * 1000, 'newline', 'unix', 'precision', '%0.7f', 'delimiter', '\t', '-append');
            case 'NIRS-SNIRF'
                if isRawIn
                    DataMat.Events = DataMat.F.events;
                end
                DataMat.F = F;
                out_data_snirf(ExportFile, DataMat, ChannelMatOut);
            case {'ASCII-SPC', 'ASCII-CSV', 'ASCII-TSV', 'ASCII-SPC-HDR', 'ASCII-CSV-HDR', 'ASCII-TSV-HDR', 'ASCII-CSV-HDR-TR', 'ASCII-TSV-HDR-TR', 'EXCEL', 'EXCEL-TR'}
                out_matrix_ascii(ExportFile, F, FileFormat, {ChannelMatOut.Channel.Name}, DataMat.Time, []);
            otherwise
                error('Unsupported format.');
        end
    end
end

% Hide progress bar
if ~isProgress
    bst_progress('stop');
end

end


function fiff_end_file(fid)
%
% fiff_end_file(fid)
%
% Writes the closing tags to a fif file and closes the file
%
%     fid           An open fif file descriptor
%

%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
%   Revision 1.3  2006/04/23 15:29:40  msh
%   Added MGH to the copyright
%
%   Revision 1.2  2006/04/10 23:26:54  msh
%   Added fiff reading routines
%
%   Revision 1.1  2005/12/05 16:01:04  msh
%   Added an initial set of fiff writing routines.
%

global FIFF;
if isempty(FIFF)
    FIFF = fiff_define_constants();
end

me = 'MNE:fiff_end_file';

if nargin ~= 1
    error(me, 'An open file id required as an argument');
end

datasize = 0;
count = fwrite(fid, int32(FIFF.FIFF_NOP), 'int32');
if count ~= 1
    error(me, 'write failed');
end
count = fwrite(fid, int32(FIFF.FIFFT_VOID), 'int32');
if count ~= 1
    error(me, 'write failed');
end
count = fwrite(fid, int32(datasize), 'int32');
if count ~= 1
    error(me, 'write failed');
end
count = fwrite(fid, int32(FIFF.FIFFV_NEXT_NONE), 'int32');
if count ~= 1
    error(me, 'write failed');
end
fclose(fid);

return


function imdb = cnn_imagenet_setup_data(varargin)
% CNN_IMAGENET_SETUP_DATA  Initialize ImageNet ILSVRC CLS-LOC challenge data
%    This function creates an IMDB structure pointing to a local copy
%    of the ILSVRC CLS-LOC data.
%
%    The ILSVRC data ships in several TAR archives that can be
%    obtained from the ILSVRC challenge website. You will need:
%
%    ILSVRC2012_img_train.tar
%    ILSVRC2012_img_val.tar
%    ILSVRC2012_img_test.tar
%    ILSVRC2012_devkit.tar
%
%    Note that images in the CLS-LOC challenge are the same for the 2012, 2013,
%    and 2014 edition of ILSVRC, but that the development kit
%    is different. However, all devkit versions should work.
%
%    In order to use the ILSVRC data with these scripts, please
%    unpack it as follows. Create a root folder <DATA>, by default
%
%    data/imagenet12
%
%    (note that this can be a simlink). Use the 'dataDir' option to
%    specify a different path.
%
%    Within this folder, create the following hierarchy:
%
%    <DATA>/images/train/ : content of ILSVRC2012_img_train.tar
%    <DATA>/images/val/ : content of ILSVRC2012_img_val.tar
%    <DATA>/images/test/ : content of ILSVRC2012_img_test.tar
%    <DATA>/ILSVRC2012_devkit : content of ILSVRC2012_devkit.tar
%
%    In order to speedup training and testing, it may be a good idea
%    to preprocess the images to have a fixed size (e.g. 256 pixels
%    high) and/or to store the images in RAM disk (provided that
%    sufficient RAM is available). Reading images off disk with a
%    sufficient speed is crucial for fast training.

opts.dataDir = fullfile('data','imagenet12') ;
opts.lite = false ;
opts = vl_argparse(opts, varargin) ;

% -------------------------------------------------------------------------
%                                                  Load categories metadata
% -------------------------------------------------------------------------

d = dir(fullfile(opts.dataDir, '*devkit*')) ;
if numel(d) == 0
  error('Make sure that ILSVRC data is correctly installed in %s', ...
    opts.dataDir) ;
end
devkitPath = fullfile(opts.dataDir, d(1).name) ;

% find metadata
mt = dir(fullfile(devkitPath, 'data', 'meta_clsloc.mat')) ;
if numel(mt) == 0
  mt = dir(fullfile(devkitPath, 'data', 'meta.mat')) ;
end
metaPath = fullfile(devkitPath, 'data', mt(1).name) ;

% find validation images labels
tmp = dir(fullfile(devkitPath, 'data', '*_validation_ground_truth*')) ;
valLabelsPath = fullfile(devkitPath, 'data', tmp(1).name) ;

% find validation images blacklist
tmp = dir(fullfile(devkitPath, 'data', '*_validation_blacklist*')) ;
if numel(tmp) > 0
  valBlacklistPath = fullfile(devkitPath, 'data', tmp(1).name) ;
else
  valBlacklistPath = [] ;
  warning('Could not find validation images blacklist file');
end

fprintf('using devkit %s\n', devkitPath) ;
fprintf('using metadata %s\n', metaPath) ;
fprintf('using validation labels %s\n', valLabelsPath) ;
fprintf('using validation blacklist %s\n', valBlacklistPath) ;

meta = load(metaPath) ;
cats = {meta.synsets(1:1000).WNID} ;
descrs = {meta.synsets(1:1000).words} ;

imdb.classes.name = cats ;
imdb.classes.description = descrs ;
imdb.imageDir = fullfile(opts.dataDir, 'images') ;

% -------------------------------------------------------------------------
%                                                           Training images
% -------------------------------------------------------------------------

fprintf('searching training images ...\n') ;
names = {} ;
labels = {} ;
for d = dir(fullfile(opts.dataDir, 'images', 'train', 'n*'))'
  [~,lab] = ismember(d.name, cats) ;
  ims = dir(fullfile(opts.dataDir, 'images', 'train', d.name, '*.JPEG')) ;
  names{end+1} = strcat([d.name, filesep], {ims.name}) ;
  labels{end+1} = ones(1, numel(ims)) * lab ;
  fprintf('.') ;
  if mod(numel(names), 50) == 0, fprintf('\n') ; end
  %fprintf('found %s with %d images\n', d.name, numel(ims)) ;
end
names = horzcat(names{:}) ;
labels = horzcat(labels{:}) ;

if numel(names) ~= 1281167
  warning('Found %d training images instead of 1,281,167. Dropping training set.', numel(names)) ;
  names = {} ;
  labels =[] ;
end

names = strcat(['train' filesep], names) ;

imdb.images.id = 1:numel(names) ;
imdb.images.name = names ;
imdb.images.set = ones(1, numel(names)) ;
imdb.images.label = labels ;

% -------------------------------------------------------------------------
%                                                         Validation images
% -------------------------------------------------------------------------

ims = dir(fullfile(opts.dataDir, 'images', 'val', '*.JPEG')) ;
names = sort({ims.name}) ;
labels = textread(valLabelsPath, '%d') ;

if numel(ims) ~= 50e3
  warning('Found %d instead of 50,000 validation images. Dropping validation set.', numel(ims))
  names = {} ;
  labels =[] ;
else
  if ~isempty(valBlacklistPath)
    black = textread(valBlacklistPath, '%d') ;
    fprintf('blacklisting %d validation images\n', numel(black)) ;
    keep = setdiff(1:numel(names), black) ;
    names = names(keep) ;
    labels = labels(keep) ;
  end
end

names = strcat(['val' filesep], names) ;

imdb.images.id = horzcat(imdb.images.id, (1:numel(names)) + 1e7 - 1) ;
imdb.images.name = horzcat(imdb.images.name, names) ;
imdb.images.set = horzcat(imdb.images.set, 2*ones(1,numel(names))) ;
imdb.images.label = horzcat(imdb.images.label, labels') ;

% -------------------------------------------------------------------------
%                                                               Test images
% -------------------------------------------------------------------------

ims = dir(fullfile(opts.dataDir, 'images', 'test', '*.JPEG')) ;
names = sort({ims.name}) ;
labels = zeros(1, numel(names)) ;

if numel(labels) ~= 100e3
  warning('Found %d instead of 100,000 test images', numel(labels))
end

names = strcat(['test' filesep], names) ;

imdb.images.id = horzcat(imdb.images.id, (1:numel(names)) + 2e7 - 1) ;
imdb.images.name = horzcat(imdb.images.name, names) ;
imdb.images.set = horzcat(imdb.images.set, 3*ones(1,numel(names))) ;
imdb.images.label = horzcat(imdb.images.label, labels) ;

% -------------------------------------------------------------------------
%                                                            Postprocessing
% -------------------------------------------------------------------------

% sort categories by WNID (to be compatible with other implementations)
[imdb.classes.name,perm] = sort(imdb.classes.name) ;
imdb.classes.description = imdb.classes.description(perm) ;
relabel(perm) = 1:numel(imdb.classes.name) ;
ok = imdb.images.label >  0 ;
imdb.images.label(ok) = relabel(imdb.images.label(ok)) ;

if opts.lite
  % pick a small number of images for the first 10 classes
  % this cannot be done for test as we do not have test labels
  clear keep ;
  for i=1:10
    sel = find(imdb.images.label == i) ;
    train = sel(imdb.images.set(sel) == 1) ;
    val = sel(imdb.images.set(sel) == 2) ;
    train = train(1:256) ;
    val = val(1:40) ;
    keep{i} = [train val] ;
  end
  test = find(imdb.images.set == 3) ;
  keep = sort(cat(2, keep{:}, test(1:1000))) ;
  imdb.images.id = imdb.images.id(keep) ;
  imdb.images.name = imdb.images.name(keep) ;
  imdb.images.set = imdb.images.set(keep) ;
  imdb.images.label = imdb.images.label(keep) ;
end


%  INTERNAL FUNCTION
%
%  Note:
%       At present the restrictions are enforced only in the violating periods,
%       which implies that the contemporaneous shocks are altered. But one can
%       think of a scheme whereby only future shocks are changed, keeping the
%       original/actual shocks unchanged.
%
%


function plot_savePC(hFig, obj, idxPC)

% Copy object
hFig.UserData.PC{idxPC} = obj.copy;

% Keep only active points to save memory
if sum(hFig.UserData.PC{idxPC}.act) < hFig.UserData.PC{idxPC}.noPoints

    % Deactivate logging
    originalLogLevel = msg('O', 'GetLogLevel');
    msg('O', 'SetLogLevel', 'off');

    % Reconstruct
    hFig.UserData.PC{idxPC}.reconstruct;

    % Reactivate logging
    msg('O', 'SetLogLevel', originalLogLevel);

end

% Fields saved in user property of point cloud (hFig.UserData.PC{idxPC}.U):
% PC.U.hPlot                   handles of plotted points
% PC.U.hMenu                   handle of menu
% PC.U.Visible                 logical value that defines if PC is visible or not
% PC.U.p                       plot parameters
% PC.U.percentOfVisiblePoints  percent of points visible within area defined by the parameter 'Limits'
% PC.U.plotNormals             plot normals? (true or false)
% PC.U.hPlotNormals            handle of normals

% Initialize plot handle
hFig.UserData.PC{idxPC}.U.hPlot = [];

% Initialize menu handle
hFig.UserData.PC{idxPC}.U.hMenu = [];

% Visible
hFig.UserData.PC{idxPC}.U.Visible = true;

% Default parameters
hFig.UserData.PC{idxPC}.U.p.Color        = 'A.z';
hFig.UserData.PC{idxPC}.U.p.MarkerSize   = 1;
hFig.UserData.PC{idxPC}.U.p.MaxPoints    = 1e6;
hFig.UserData.PC{idxPC}.U.p.ColormapName = 'parula';
hFig.UserData.PC{idxPC}.U.p.CAxisLim     = [];
hFig.UserData.PC{idxPC}.U.p.Limits       = [-Inf Inf; -Inf Inf; -Inf Inf];

% Plot normals
hFig.UserData.PC{idxPC}.U.plotNormals = false;

% Initialize plot handle for normals
hFig.UserData.PC{idxPC}.U.hPlotNormals = [];

end


function [panelContainer, bstPanel] = gui_show( bstPanel, contType, contName, contIcon, isModal, isAlwaysOnTop, isMaximized, winPos )
% GUI_SHOW: Display a BstPanel.
%
% USAGE: gui_show(bstPanel, contType, contName, contIcon=[], isModal=0, isAlwaysOnTop=0, isMaximized=0)

% INPUT:
%     - bstPanel : BstPanel object or panel function name (string)
%     - contType : {'JavaWindow', 'BrainstormTab', 'BrainstormPanel'} (Default : 'JavaWindow')
%     - contName : Container name (meaning of this argument depends on the contType value)
%                  => JavaWindow       : name of the Java frame (title of the java window)
%                  => BrainstormFigure : name of the panelContainer in which the panel should be added
%     - contIcon : Icon object (optional)
%     - isModal  : If 1, makes window modal
%                  => If the contType is 'BrainstormTab', the panel will not be added as a tab
%                     in a Brainstorm panel container, but will fill the whole panel container.
%     - isAlwaysOnTop : If 1, makes window always on top (only for type 'JavaWindow')
%     - isMaximized   : If 1, maximizes window to fit all the available figure space (only for type 'JavaWindow')
%     - winPos        : [x,y] Window position, relative with the main Braintorm frame (only for type 'JavaWindow')
%
% SEE ALSO gui_hide gui_show_dialog

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

import org.brainstorm.icon.*;
global GlobalData;

% Initialize returned variables
panelContainer = [];
% Headless mode: exit
if (GlobalData.Program.GuiLevel == -1)
    return
end

%% ===== PARSE INPUTS =====
if (nargin < 2) || isempty(contType)
    contType = 'JavaWindow';
end
if (nargin < 3) || isempty(contName) || ~ischar(contName)
    contName = 'New panel';
end
if (nargin < 4) || isempty(contIcon) || ~isa(contIcon, 'javax.swing.Icon')
    contIcon = [];
end
if (nargin < 5) || isempty(isModal)
    isModal = 0;
end
if (nargin < 6) || isempty(isAlwaysOnTop)
    isAlwaysOnTop = 0;
end
if (nargin < 7) || isempty(isMaximized)
    isMaximized = 0;
end
if (nargin < 8) || isempty(winPos)
    winPos = [];
end

%% ===== GET PANEL =====
if ischar(bstPanel)
    bstPanel = feval(bstPanel, 'CreatePanel');
    if isempty(bstPanel)
        return;
    end
elseif ~isa(bstPanel, 'BstPanel')
    error('First argument must be a ''BstPanel'' object.');
end
panelName    = get(bstPanel, 'name');
jPanelHandle = get(bstPanel, 'jHandle');
% Check that the panel is not already registered
if gui_brainstorm('isTabVisible', panelName)
    % Focus previous panel
    bstPanel = bst_get('Panel', panelName);
    jPanelHandle = get(bstPanel, 'jHandle');
    if ~isempty(jPanelHandle.getRootPane()) && ~isempty(jPanelHandle.getRootPane.getParent())
        jPanelHandle.getTopLevelAncestor().show();
    end
    % Return container
    panelContainer = get(bstPanel, 'container');
    return
end

%% ===== SWITCH BETWEEN CONTAINER TYPES =====
switch (contType)
    % =======================================================================
    % ==== JAVA WINDOW ======================================================
    % =======================================================================
    case 'JavaWindow'
        % Get parent frame
        jParent = bst_get('BstFrame');
        % If modal window : JDIALOG
        if (isModal)
            % Make it dependent on the the main Brainstorm JFrame, if it exists
            jWindow = java_create('javax.swing.JDialog', 'Ljava.awt.Frame;Ljava.lang.String;Z', jParent, contName, 1);
        % If not modal : JFRAME
        else
            jWindow = java_create('javax.swing.JFrame', 'Ljava.lang.String;', contName);
            jWindow.setIconImage(IconLoader.ICON_APP.getImage());
        end
        % Configure window
        jWindow.setDefaultCloseOperation(javax.swing.JFrame.DO_NOTHING_ON_CLOSE);
        java_setcb(jWindow, 'WindowClosingCallback', @ClosePanelCallback);
        % Add the BST Panel
        jWindow.getContentPane.add(jPanelHandle);
        % Always on top
        if isAlwaysOnTop
            jWindow.setAlwaysOnTop(1);
        end
        % Maximized over the figure area (ONLY WHEN TILED LAYOUT)
        if isMaximized && strcmpi(bst_get('Layout', 'WindowManager'), 'TileWindows')
            % Get current layout
            [jBstArea, FigArea, nbScreens, jFigArea, jInsets] = gui_layout('GetScreenBrainstormAreas');
            % Place this figure on the screen to take all the possible figure space
            jWindow.setSize(FigArea(3), FigArea(4));
            jWindow.setLocation(FigArea(1)-1, jBstArea.getY() - jInsets.bottom);
        % Normal display
        else
            % Set window size and location
            jWindow.pack();
            jWindow.setLocationRelativeTo(jParent);
            % Set figure position
            if (length(winPos) >= 2)
                if ~isempty(jParent)
                    winPos(1) = winPos(1) + jParent.getLocation().getX();
                    winPos(2) = winPos(2) + jParent.getLocation().getY();
                end
                jWindow.setLocation(winPos(1),winPos(2));
            end
        end
        % Show window: KEEP IT WITH AWTINVOKE
        awtinvoke(jWindow, 'setVisible(Z)', 1);
        % Returned variable
        panelContainer.type   = 'JavaWindow';
        panelContainer.handle = {jWindow};

    % =======================================================================
    % ==== BRAINSTORM TAB ===================================================
    % =======================================================================
    case 'BrainstormTab'
        % Add a Swing components tree to the main brainstorm window.
        % The component can be added in one of the registered panel containers.
        % The panel can be added either as a new tab in the target area, or
        % as the whole target (in this case, the other target tabbed panels are hidden)

        % Get the 'contName' tabbed panel
        jTabContainer = bst_get('PanelContainer', contName);
        % If container does not exist, return with a warning
        if (isempty(jTabContainer))
            warning('Brainstorm:InvalidContainer', 'Destination "%s" is not a valid Swing tab panel', contName);
            return;
        end
        % If this panel is supposed to tabbed => just add it as a new tab
        if (~isModal)
            % Attach the panel to the panel container
            if strcmpi(contName, 'tools')
                iTab = jTabContainer.getTabCount() - 1;
            else
                iTab = jTabContainer.getTabCount();
            end
            jTabContainer.insertTab(panelName, contIcon, jPanelHandle, '', iTab);
            % Make sure that the tabbed container is visible
            jTabContainer.setVisible(1);
        % Else : 1) add it to the parent of the jTabContainer
        else
            % Add panel in the container's parent
            jTabContainer.getParent().add(jPanelHandle);
            % Hide the tab container
            jTabContainer.setVisible(0);
        end

        % Returned variable
        panelContainer.type   = 'BrainstormTab';
        panelContainer.handle = {contName};

    % =======================================================================
    % ==== BRAINSTORM PANEL ===================================================
    % =======================================================================
    case 'BrainstormPanel'
        % Get the 'contName' tabbed panel
        jContainer = bst_get('PanelContainer', contName);
        % If container does not exist, return with a warning
        if (isempty(jContainer))
            warning('Brainstorm:InvalidContainer', 'Destination "%s" is not a valid Swing panel', contName);
            return;
        end
        % Add panel in the container
        jContainer.add(jPanelHandle);
        % Returned variable
        panelContainer.type   = 'BrainstormPanel';
        panelContainer.handle = {contName};

    otherwise
        error('Invalid container type.');
end

%% ===== REFERENCE NEW PANEL =====
% Update bstPanel structure
bstPanel = set(bstPanel, 'container', {panelContainer.type, panelContainer.handle{:}});
% If GUI context is defined
if isempty(GlobalData.Program.GUI.panels)
    GlobalData.Program.GUI.panels = bstPanel;
else
    % Add the new panel to the panel list
    GlobalData.Program.GUI.panels(end+1) = bstPanel;
end

%% =================================================================================
%  === CALLBACKS  ==================================================================
%  =================================================================================
    function ClosePanelCallback(varargin)
        try
            gui_hide(bstPanel);
        catch
            if strcmpi(contType, 'JavaWindow')
                warning('Brainstorm:PanelNotRegistered', 'Panel ''%s'' was not registered in Brainstorm GUI context, hide forced.', panelName);
                jWindow.dispose();
            end
        end
    end

end


function varargout = VBA_spm_print(varargin)
% Print figure
% FORMAT spm_print(fname,F,opts)
% fname  - output filename [Default: 'spm_<date>']
% F      - figure handle or tag [Default: 'Graphics']
% opts   - structure containing printing options
%          [Default: defaults.ui.print from spm_defaults.m]
%
% FORMAT spm_print(job)
% Run a batch print job (see spm_cfg_print)
%__________________________________________________________________________
% Copyright (C) 1994-2014 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_print.m 5969 2014-05-01 14:37:22Z guillaume $

%-Shortcut for list of graphics file formats available
%--------------------------------------------------------------------------
if nargin > 0 && isequal(lower(varargin{1}),'format')
    [varargout{1:nargout}] = print_format(varargin{2:end});
    return;
end

%-Conversion layer for spm.util.print batch
%--------------------------------------------------------------------------
if nargin == 1 && isstruct(varargin{1})
    job = varargin{1};
    VBA_spm_print(job.fname, job.fig.(char(fieldnames(job.fig))), job.opts);
    return;
end

%-Input parameters
%--------------------------------------------------------------------------
if nargin<1, fname = ''; else    fname = varargin{1}; end

if nargin<2, F = NaN;    else    F     = varargin{2}; end
if isnumeric(F) && ~isfinite(F), F     = [];          end
if isempty(F),                   F     = 'Graphics';  end

opts = spm_get_defaults('ui.print');
if ischar(opts)
    opts = VBA_spm_print('format',opts);
    if isempty(opts), disp('Print warning: unknown printing format.'); end
end
if nargin == 3
    o = varargin{3};
    if ischar(o), o = VBA_spm_print('format',o); end
    if isempty(o), disp('Print warning: unknown printing format.'); end
    try, opts.ext    = o.ext;    end
    try, opts.append = o.append; end
    try, opts.opt    = o.opt;    end
end
opts.opt = [opts.opt {'-noui','-painters'}];
if opts.append, opts.opt = [opts.opt {'-append'}]; end

%-Get output filename
%--------------------------------------------------------------------------
if isempty(fname)
    bname = ['spm_' datestr(now,'yyyymmmdd')];
    pname = pwd;
else
    bname = spm_file(fname,'basename');
    pname = spm_file(fname,'fpath');
end
fname = fullfile(pname,[bname opts.ext]);
if ~opts.append
    fname = spm_file(fname,'unique');
end

%-Get figure handle
%--------------------------------------------------------------------------
F = spm_figure('FindWin',F);
%if isempty(F), F = get(0,'CurrentFigure'); end
if isempty(F)
    disp('Print error: Figure not found.');
    return;
end

%-Print
%==========================================================================
try
    if ismember('-dfig',opts.opt)
        saveas(F, fname, 'fig');
    else
        if isdeployed
            deployprint(F, fname, opts.opt{:});
        else
            print(F, fname, opts.opt{:});
        end
    end
catch
    disp('Print error: nothing has been printed.');
    l = lasterror;
    disp(l.message);
    return;
end

%-Report
%--------------------------------------------------------------------------
str = '';
if ~isempty(get(F,'Tag')), str = sprintf('''%s'' ',get(F,'Tag')); end
fprintf('Printing %sfigure to:\n',str);
if ispc && ~ismember('-dfig',opts.opt), cmd = 'winopen(''%s'')';
else                                    cmd = 'open(''%s'')'; end
fprintf('  %s\n',spm_file(fname,'link',cmd));

%==========================================================================
% function pf = print_format(f)
%==========================================================================
function [pf, i] = print_format(f)

pf(1).name   = 'PostScript (PS)';
pf(1).opt    = {'-dpsc2'};
pf(1).append = true;
pf(1).ext    = '.ps';
pf(1).label  = {'ps'};

pf(2).name   = 'Encapsulated PostScript (EPS)';
pf(2).opt    = {'-depsc2'};
pf(2).append = false;
pf(2).ext    = '.eps';
pf(2).label  = {'eps'};

pf(3).name   = 'Portable Document Format (PDF)';
pf(3).opt    = {'-dpdf'};
pf(3).append = false;
pf(3).ext    = '.pdf';
pf(3).label  = {'pdf'};

pf(4).name   = 'JPEG image';
pf(4).opt    = {'-djpeg'};
pf(4).append = false;
pf(4).ext    = '.jpg';
pf(4).label  = {'jpg','jpeg'};

pf(5).name   = 'PNG image';
pf(5).opt    = {'-dpng'};
pf(5).append = false;
pf(5).ext    = '.png';
pf(5).label  = {'png'};

pf(6).name   = 'TIFF image';
pf(6).opt    = {'-dtiff'};
pf(6).append = false;
pf(6).ext    = '.tif';
pf(6).label  = {'tif','tiff'};

pf(7).name   = 'MATLAB figure';
pf(7).opt    = {'-dfig'}; % use saveas instead of print
pf(7).append = false;
pf(7).ext    = '.fig';
pf(7).label  = {'fig'};

if nargin
    for i=1:numel(pf)
        if ismember(lower(f),lower(pf(i).label))
            pf = pf(i); return;
        end
    end
    pf = []; i = [];
end


function [opts, args] = vl_argparse(opts, args, varargin)
%VL_ARGPARSE Parse list of parameter-value pairs.
%   OPTS = VL_ARGPARSE(OPTS, ARGS) updates the structure OPTS based on
%   the specified parameter-value pairs ARGS={PAR1, VAL1, ... PARN,
%   VALN}. If a parameter PAR cannot be matched to any of the fields
%   in OPTS, the function generates an error.
%
%   Parameters that have a struct value in OPTS are processed
%   recursively, updating the individual subfields.  This behaviour
%   can be suppressed by using VL_ARGPARSE(OPTS, ARGS, 'nonrecursive'),
%   in which case the struct value is copied directly (hence deleting any
%   existing subfield existing in OPTS). A direct copy occurrs also if the
%   struct value in OPTS is a structure with no fields. The nonrecursive
%   mode is especially useful when a processing time is a concern.
%
%   One or more of the (PAR, VAL) pairs in the argument list can be
%   replaced by a structure; in this case, the fields of the structure
%   are used as paramater names and the field values as parameter
%   values. This behaviour, while orthogonal to structure-valued parameters,
%   is also disabled in the 'nonrecursive' mode.
%
%   A shorthand notation for substructs is available: the pair
%   ('field.subfield', value) creates a substruct, i.e. ('field',
%   struct('subfield', value)). It also works recursively (sub-sub-fields).
%
%   [OPTS, ARGS] = VL_ARGPARSE(OPTS, ARGS) copies any parameter in
%   ARGS that does not match OPTS back to ARGS instead of producing an
%   error. Options specified as structures are passed back as a list
%   of (PAR, VAL) pairs.
%
%   A further option is VL_ARGPARSE(OPTS, ARGS, 'merge'), which merges any
%   parameter in ARGS that do not match OPTS into OPTS. This essentially
%   turns off errors for unknown options, merging them anyway, and is
%   useful if OPTS does not necessarily define all possible default values.
%   The second output argument will always be empty. Another view is that
%   VL_ARGPARSE(OPTS1, OPTS2, 'merge') merges two structs into one.
%
%   Example::
%     The function can be used to parse a list of arguments
%     passed to a MATLAB functions:
%
%        function myFunction(x,y,z,varargin)
%        opts.parameterName = defaultValue ;
%        opts = vl_argparse(opts, varargin)
%
%     If only a subset of the options should be parsed, for example
%     because the other options are interpreted by a subroutine, then
%     use the form
%
%        [opts, varargin] = vl_argparse(opts, varargin)
%
%     that copies back to VARARGIN any unknown parameter.
%
%   See also: VL_HELP().

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

if ~isstruct(opts) && ~isobject(opts), error('OPTS must be a structure') ; end
if ~iscell(args), args = {args} ; end

recursive = true ;
merge = false ;

if numel(varargin) > 2
  error('There can be at most two options.') ;
end

for i = 1:numel(varargin)
  switch lower(varargin{i})
    case 'nonrecursive'
      recursive = false ;
    case 'merge'
      merge = true ;
    otherwise
      error('Unknown option specified.') ;
  end
end

optNames = fieldnames(opts)' ;

% convert ARGS into a structure
ai = 1 ;
keep = false(size(args)) ;
while ai <= numel(args)

  % Check whether the argument is a (param,value) pair or a structure.
  if recursive && isstruct(args{ai})
    params = fieldnames(args{ai})' ;
    values = struct2cell(args{ai})' ;
    if nargout <= 1
      opts = vl_argparse(opts, vertcat(params,values), varargin{:}) ;
    else
      [opts, rest] = vl_argparse(opts, reshape(vertcat(params,values), 1, []), varargin{:}) ;
      args{ai} = cell2struct(rest(2:2:end), rest(1:2:end), 2) ;
      keep(ai) = true ;
    end
    ai = ai + 1 ;
    continue ;
  end

  if ~isstr(args{ai})
    error('Expected either a param-value pair or a structure.') ;
  end

  param = args{ai} ;
  value = args{ai+1} ;

  if any(param == '.')
    % Handy notation for substructs: convert {'train.learningRate', value}
    % to {'train', struct('learningRate', value)}. Nested structs also work
    parts = strsplit(param, '.') ;
    subs = struct('type', repmat({'.'}, 1, numel(parts) - 1), 'subs', parts(2:end)) ;
    param = parts{1} ;
    value = subsasgn(struct(), subs, value) ;
  end

  p = find(strcmpi(param, optNames)) ;
  if numel(p) ~= 1
    if merge  % Merge unknown fields, instead of erroring or leaving it
      field = param ;
    elseif nargout <= 1
      error('Unknown parameter ''%s''', param) ;
    else
      keep([ai,ai+1]) = true ;
      ai = ai + 2 ;
      continue ;
    end
  else
    field = optNames{p} ;
  end

  if ~recursive
    opts.(field) = value ;
  else
    if isfield(opts, field) && isstruct(opts.(field)) && numel(fieldnames(opts.(field))) > 0
      % The parameter has a  non-empty struct value in OPTS:
      % process recursively.
      if ~isstruct(value)
        error('Cannot assign a non-struct value to the struct parameter ''%s''.', ...
          field) ;
      end
      if nargout > 1
        [opts.(field), args{ai+1}] = vl_argparse(opts.(field), value, varargin{:}) ;
      else
        opts.(field) = vl_argparse(opts.(field), value, varargin{:}) ;
      end
    else
      % The parameter does not have a struct value in OPTS: copy as is.
      opts.(field) = value ;
    end
  end

  ai = ai + 2 ;
end

args = args(keep) ;


function for_euler
global sxyz sXYZ sa sN sav saa

set(sxyz,'Value',true);
set(sXYZ,'Value',true);
set(sa,'Value',true);
set(sN,'Value',true);
set(sav,'Value',false);
set(saa,'Value',false);

XYZ_visibility;
enter_eul_angs;


function tSeries = meanTSeriesForPlotting(vw, selectedROIs, getRawData)
% Return the mean t-series for one or more ROIs. Start by checking for data
% in Inplane. If this fails, try the gray view.
%
%   tSeries = meanTSeriesForPlotting(vw, selectedROIs)
%
%   Example:
%
%       tSeries = meanTSeriesForPlotting(vw);
%
%   See: plotMultipleSingleCycleErr.m
%
%   JW, 8/2009: Split off from various plotting functions that each
%   duplicated this code
%   JW, 9/2010: Added flag 'getRawData' in case you want to plot without
%               converting to % signal change, replaced GLOBAL INPLANE with
%               ip
mrGlobals;

viewType = viewGet(vw, 'viewType');

if ~exist('selectedROIs', 'var') || isempty(selectedROIs),
    selectedROIs = roiGetList(vw);
end

if ~exist('getRawData', 'var') || isempty(getRawData),
    getRawData  = false;
end

nROIs = length(selectedROIs);
scan  = viewGet(vw,'currentScan');

switch viewType
    case {'Volume' 'Gray'}   %%%For ROIs in Gray view - xform to inplane

        selectedVOLUME = viewSelected('volume');

        %initiate hiddenINPLANE
        ip = initHiddenInplane;
        ip = viewSet(ip,'name','hidden');

        % Set the Inplane scan number and datatype to match the Volume view.
        curDataType = viewGet(vw,'datatypenumber');

        ip = viewSet(ip,'datatypenumber',curDataType);
        ip = viewSet(ip,'currentscan',scan);

        %Transfer current VOLUME ROI to INPLANE
        for ii = 1:nROIs
            vw = viewSet(vw,'selectedROI', selectedROIs(ii));
            ip = vol2ipCurROI(vw,ip);
            selectedInplaneROIs(ii) = viewGet(ip, 'curroi');
        end

    case {'Flat'} %%%For ROIs in Flat view - xform to inplane

        %initiate and / or select VOLUME and INPLANE windows
        if isempty(VOLUME),
            VOLUME{1} = initHiddenGray;
            VOLUME{1} = viewSet(VOLUME{1},'name','hidden');
        else
            selectedVOLUME = viewSelected('volume');
        end

        ip = initHiddenInplane;
        ip = viewSet(ip,'name','hidden');

        % Set the Inplane scan number and datatype to match the Flat view.
        %         curScan =     viewGet(FLAT{selectedFLAT},'currentscan');
        curDataType = viewGet(vw,'datatypenumber');
        ip = viewSet(ip,'datatypenumber',curDataType);
        ip = viewSet(ip,'currentscan',scan);

        %Transfer current FLAT ROI to INPLANE
        for ii = 1: nROIs
            vw = viewSet(vw,'selectedROI', selectedROIs(ii));
            ip = flat2ipCurROI(vw,ip,VOLUME{selectedVOLUME});
            selectedInplaneROIs(ii) = viewGet(ip, 'curroi');
        end

    case {'Inplane'}   %%%For ROIs in INPLANE view - select inplane
        selectedInplaneROIs = selectedROIs;
        ip = vw;
end

% Compute meanTSeries for each ROI
ROIcoords = cell(1,nROIs);
try
    for r=1:nROIs
        ROIcoords{r}=ip.ROIs(selectedInplaneROIs(r)).coords;
    end
    tSeries = meanTSeries(ip,scan,ROIcoords, getRawData);
catch ME
    warning(ME.identifier, ME.message)
    for r=1:nROIs
        ROIcoords{r}=VOLUME{selectedVOLUME}.ROIs(selectedROIs(r)).coords;
    end
    tSeries = meanTSeries(VOLUME{selectedVOLUME},scan,ROIcoords, getRawData);
end

if ~iscell(tSeries)
    tmp{1}=tSeries;
    tSeries=tmp;
end

return


function p = parent(tree,uid)
% XMLTREE/PARENT Parent Method
% FORMAT uid = parent(tree,uid)
%
% tree   - XMLTree object
% uid    - UID of the lonely child
% p      - UID of the parent ([] if root is the child)
%__________________________________________________________________________
%
% Return the uid of the parent of a node.
%__________________________________________________________________________
% Copyright (C) 2002-2011  http://www.artefact.tk/

% Guillaume Flandin
% $Id: parent.m 4460 2011-09-05 14:52:16Z guillaume $

p = tree.tree{uid}.parent;


function out = cfg_run_save_vars(job)

% Save input variables to .mat file - either as a struct array, or as
% individual variables.
%
% This code is part of a batch job configuration system for MATLAB. See
%      help matlabbatch
% for a general overview.
%_______________________________________________________________________
% Copyright (C) 2007 Freiburg Brain Imaging

% Volkmar Glauche
% $Id: cfg_run_save_vars.m 6929 2016-11-14 13:07:31Z guillaume $

rev = '$Rev: 6929 $'; %#ok

[p, n, e] = fileparts(job.name);
out.file{1} = fullfile(job.outdir{1}, [n '.mat']);
for k = 1:numel(job.vars)
    svar.(job.vars(k).vname) = job.vars(k).vcont; %#ok<STRNU>
end;
if job.saveasstruct
    save(out.file{1}, 'svar','-v6');
else
    save(out.file{1}, '-struct','svar','-v6');
end;


function [ fn ] = getBatchWrapper_rgbflow(opts, numThreads, trainopts)

fn = @(imdb,batch, moreopts) getBatch(imdb,batch,opts,numThreads, trainopts, moreopts) ;
end

% -------------------------------------------------------------------------
function [im,labels] = getBatch(imdb, batch, opts, numThreads, trainopts, moreopts)
% -------------------------------------------------------------------------
nFrames=imdb.images.nFrames(batch);
images = cell(1,numel(nFrames));

labels = imdb.images.label(batch) ;

for k = 1:numel(nFrames)
    images{k}  = strcat([imdb.images.name{batch(k)}(1:end-4) filesep], images{k} ) ;
end

opts.nFrames = nFrames;

if ~isempty(moreopts) || nargin < 6
  for f = fieldnames(moreopts)'
    f = char(f) ;
    trainopts.(f) = moreopts.(f);
  end
end

opts.nFramesPerVid = trainopts.nFramesPerVid;
opts.numAugments = trainopts.numAugments;
opts.frameSample = trainopts.frameSample;
opts.augmentation =  trainopts.augmentation;
if isfield(trainopts, 'temporalStride')
  opts.temporalStride =  trainopts.temporalStride(randi(numel(trainopts.temporalStride))) ; % shuffle;
end
if isfield(trainopts, 'nFrameStack')
  opts.nFrameStack = trainopts.nFrameStack;
else
  opts.nFrameStack = trainopts.nFramesPerVid;
end
if isfield(trainopts, 'keepFramesDim')
  keepFramesDim = trainopts.keepFramesDim;
else
  keepFramesDim = false;
end
if isfield(trainopts, 'cheapResize')
  opts.cheapResize =  trainopts.cheapResize;
end
if isfield(trainopts, 'fetchGPU')
  opts.fetchGPU =  trainopts.fetchGPU;
end

if isfield(trainopts, 'prefetch')
    opts.prefetch = trainopts.prefetch;
end
if isfield(trainopts, 'frameList')
    opts.frameList = trainopts.frameList;
end
if isfield(trainopts, 'subMedian')
    opts.subMedian = trainopts.subMedian;
end

im = cnn_get_im_flow_batch(images, opts, ...
                            'numThreads', numThreads, ...
                            'augmentation', opts.augmentation , ...
                            'flowDir', imdb.flowDir, ...
                            'imageDir', imdb.imageDir) ;

if iscell(im), return; end

if nargout == 1 % to work with dag code
  if ndims(im) > 4 && ~keepFramesDim
    sz = size(im);
    nFrames = sz(5:end);
    im = permute(im, [1 2 3 5 4]);
    im = reshape(im, sz(1), sz(2), sz(3), []);

  end
  im = {'input', im(:,:,end-2:end,:,:), 'label', labels, 'input_flow', im(:,:,1:end-3,:,:)} ;

end

end


%ANIMATE Create an animation
%
% Helper class for creating animations.  Saves snapshots of a figture as a
% folder of individual PNG format frames numbered 0000.png, 0001.png and so
% on.
%
% Example::
%
%          anim = Animate('movie');
%
%          for i=1:100
%              plot(...);
%              anim.add();
%          end
%
% To convert the image files to a movie you could use a tool like ffmpeg
%           % ffmpeg -r 10 -i movie/*.png out.mp4

% Copyright (C) 1993-2014, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

classdef Animate < handle
    properties
        frame
        dir
        resolution
    end

    methods
        function a = Animate(name, res)
            %ANIMATE.ANIMATE Create an animation class
            %
            % A = ANIMATE(NAME, OPTIONS) initializes an animation, and creates a folder
            % called NAME to hold the individual frames.
            %
            % Options::
            % 'resolution',R    Set the resolution of the saved image to R pixels per
            % inch.

            a.frame = 0;
            a.dir = name;
            mkdir(name);
            if nargin > 1
                a.resolution = res;
            else
                a.resolution = [];
            end
            delete( fullfile(name, '*.png') );

        end

        function add(a, fh)
            %ANIMATE.ADD Adds current plot to the animation
            %
            % A.ADD() adds the current figure in PNG format to the animation
            % folder with a unique sequential filename.
            %
            % A.ADD(FIG) as above but captures the figure FIG.
            %
            % See also print.

            if nargin < 2
                fh = gcf;
            end

            if isempty(a.resolution)
                print(fh, '-dpng', fullfile(a.dir, sprintf('%04d.png', a.frame)));
            else
                print(fh, '-dpng', sprintf('-r%d', a.resolution), fullfile(a.dir, sprintf('%04d.png', a.frame)));
            end
            a.frame = a.frame + 1;
        end

        function close(a)
        end
    end
end


%CONVECTIONDIFFUSION Convection and diffusion physics mode definition.

% Copyright 2013-2022 Precise Simulation, Ltd.


function e = end(v,i,n)
% overloaded end function

if n==1
  e = numel(v.x);
else
  e = size(v,i);
end


function [vw, status, forceSave] = saveROI(vw, ROI, local, forceSave)
%
% [view, status, forceSave] = saveROI([view=cur view], [ROI='selected'], [local], [forceSave=0])
%
% Saves ROI to a file.
%
% INPUTS:
%   vw: mrVista view. Finds current view if omitted.
%
%   ROI: ROI structure, or index into the ROI structure in the view.
%   If this the string 'selected' the view's selected ROI to be saved.
%   [This is the default behavior if the ROI argument is omitted.]
%
% local: flag to save ROI in a local directory to the view (e.g.,
% 'Volume/ROIs'), or a shared directory (e.g., relative to the
% anatomy directory -- use "setpref('VISTA', 'defaultROIPath')" to
% set this directory.)  [For inplanes, defaults to 1, save locally.
% for other views, defaults to 0, saves in shared directory.]
%
% forceSave: if set to 0, if the ROI file exists, will ask the user if they
% want to save over the existing file. If 1, will save over existing files
% without asking. Useful for scripting. [Defaults to 0].
%
% OUTPUTS:
%   vw    : Modified view (e.g, Inplane ...).
%   status: 0 if the ROI saving was aborted. This is used when calling this
%           repeatedly (see 'saveAllROIs'), if the file exists and the
%           user selects 'Cancel'.
%   forceSave: modified forceSave flag, if the file exists, and the user
%           wants to bypass the dialog for future files. (again, see
%           'saveAllROIs'.)
%
% Example:  saveROI(INPLANE{1});
%
% See also:
%    The roi management is a mess.  This should be roiSave, but there is
%    another roiSave.  All the roi management routines have different names
%    and different behavior.  Sigh.
%
% Vistasoft Team
%
% djh, 1/24/98
% gmb, 4/25/98 added dialog box
% ARW 10/06/05 : Added default ROI path option
% (see also roiDir)
% ras 07/06: added forceSave flag.
% ras 10/06: ROI selection defaults to 'selected'; can enter ROI indices.
% ras 11/06: offers option to save over all, returning modified forceSave
% flag. (Very helpful when saving a lot of ROIs that you want to update.)

if notDefined('vw'),        vw = getCurView;        end
if notDefined('forceSave'), forceSave = 0;          end
if notDefined('ROI'),       ROI = 'selected';       end
if notDefined('local'),     local = isequal(vw.viewType, 'Inplane'); end

status = 0;
verbose = prefsVerboseCheck;

% disambiguate the ROI specification
if isnumeric(ROI), ROI = tc_roiStruct(vw, ROI); end

if ischar(ROI) && isequal(lower(ROI), 'selected')
    ROI = vw.ROIs( vw.selectedROI );
end

if isfield(ROI, 'roiVertInds')
    ROI = rmfield(ROI,'roiVertInds');
end

if isempty(ROI.coords) && forceSave==0
    q = sprintf('Save empty ROI %s?', ROI.name);
    confirm = questdlg(q, mfilename, 'Yes', 'No', 'No');
    if ~isequal(confirm, 'Yes'), disp('ROI not saved.'); return; end
end

% The method of saving the ROI starts here
% First we make sure we add a .mat extension. Matlab does this most of
% the times but not always, for example if your name contains a '.'.
% It still saves the file but without '.mat' and consequently cannot load it.
[~,~,ext]=fileparts(ROI.name);
if ~strcmp(ext,'.mat'), ROIname = [ROI.name '.mat'];
else                    ROIname = ROI.name;     end;

pathStr = fullfile(roiDir(vw,local), ROIname);

if check4File(pathStr) && forceSave==0
    q = sprintf('ROI %s already exists.  Overwrite?', ROI.name);
    saveFlag = questdlg(q, 'Save ROI', 'Yes', 'No', 'Yes To All', 'No');
else
    saveFlag = 'Yes';
end

switch saveFlag
    case 'Yes'
        if verbose,
            fprintf('Saving ROI "%s" in %s. \n', ROI.name, fileparts(pathStr));
        end
        save(pathStr,'ROI');
        status = 1;

    case 'No'
        if verbose,  fprintf('ROI %s not saved.', ROI.name);    end
        status = 1;     % not saved, but keep going if saving many ROIs

    case 'Yes To All'
        if verbose,     disp('Force-Saving all ROIs...');       end
        fprintf('Saving ROI "%s" in %s. \n', ROI.name, fileparts(pathStr));
        forceSave = 1;
        status = 1;

    case 'Cancel'
        if verbose,  disp('ROI Saving Aborted.');               end
end

return;


function opt= defopt_erps(varargin)
%DEFOPT_ERPS - Properties for plot_channel* functions, optimized for
%plotting ERPs

props= {'LineWidth',                    0.7
        'AxisType',                     'cross'
        'AxisTitleVerticalAlignment',   'top'
        'AxisTitleFontWeight',          'demi'
        'ScaleHPos',                    'left'
        'ColorOrder',             [1 .47 .02; .3 .3 .3; 0 .6 .8; .9 0 .9],
        };

opt= opt_proplistToStruct(varargin{:});
opt= opt_setDefaults(opt, props);


function y = cvx_subsasgn( y, varargin )
temp.type = '()';
temp.subs = varargin(1:end-1);
y = subsasgn( y, temp, varargin{end} );

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


classdef PTKImageFileFormat
    % PTKImageFileFormat. An enumeration used to specify how a medical image is
    % stored
    %
    %
    %     Licence
    %     -------
    %     Part of the TD MIM Toolkit. https://github.com/tomdoel
    %     Author: Tom Doel, Copyright Tom Doel 2014.  www.tomdoel.com
    %     Distributed under the MIT licence. Please see website for details.
    %

    enumeration
        Dicom       (MimImageFileFormat.Dicom),      % DICOM format
        Metaheader  (MimImageFileFormat.Metaheader), % Metaheader (mha/mhd) plus raw data
        Matlab      (MimImageFileFormat.Matlab),     % Matlab matrix
        Analyze     (MimImageFileFormat.Analyze)     % Analyze format
    end

    properties (SetAccess = immutable)
        MimImageFileFormat
    end

    methods

        function obj = PTKImageFileFormat(mim_format)
            obj.MimImageFileFormat = mim_format;
        end
    end
end


function hyperSaveFigure(h, filename, fmt)
% HYPERSAVEFIGURE Writes a figure to disk as an image.
%
% Usage
%   hyperSaveFigure(gcf, 'filename.png');
% Inputs
%   h - Handle to figure
%   filename - Filename for output file.  Extension determines image type.
%   fmt - Format of output image.  'wysiwyg' or wysiwyp' for 'what you see
%         is what you get' and what 'you see is what you print' respectively.
% Outputs
%   none

if (nargin == 2)
    fmt = 'wysiwyg';
end

fmt = lower(fmt);

if strcmp(fmt, 'wysiwyp')
    saveas(h, filename);
elseif strcmp(fmt, 'wysiwyg')
    set(h, 'Color',[1 1 1]);
    frame = getframe(h);
    [X,map] = frame2im(frame);
    imwrite(X ,filename);
else
    error('Bad format string specified.');
end
%print(h, '-dpng', filename);


function err = gzSeek(gzFp, skipBytes, origin)
%
% err = gzSeek(gzFp, skipBytes, origin)
%
% HISTORY:
% 2007.02.12 RFD: wrote it.

if isempty(gzFp) || ~isfield(gzFp,'inStream') || isempty(gzFp.inStream)
    disp('Can''t read file! Is it open?');
    err = -1;
    return;
end

if(~exist('origin','var')||isempty(origin))
    origin = 0;
end

if((isnumeric(origin)&&origin==-1) || strcmpi(origin,'bof'))
    if(gzFp.inStream.markSupported)
        gzFp.inStream.reset;
    elseif(skipBytes>=gzFp.curPos)
        % If we just want to go forward, then we can do that
        skipBytes = skipBytes - gzFp.curPos;
    else
        % Reset isn't supported
        disp('reset not supported- can''t skip from beginning.');
        err = -1;
        return;
    end
elseif((isnumeric(origin)&&origin==1) || strcmpi(origin,'eof'))
    disp('''eof'' option not supported.');
    err = -1;
    return;
end

if(skipBytes>0)
    gzFp.inStream.skip(int32(skipBytes));
    gzFp.curPos = gzFp.curPos+skipBytes;
elseif(skipBytes<0)
    disp('negative skip not supported.');
    err = -1;
    return;
end

return;


% Mat file utility functions
%
% Author: Jonathan Karr
% Affilitation: Covert Lab, Department of Bioengineering, Stanford University
% Last updated: 11/23/2010
classdef MatFileUtil
    methods (Static)
        function diff(file1, file2)
            struct1 = load(file1);
            struct2 = load(file2);

            edu.stanford.covert.util.StructUtil.diff(struct1, struct2);
        end
    end
end


classdef Filter_Boundary < Filter
    methods (Static)
        function obj = create(settings)
            switch settings.filter
                case 'P1'
                    obj = Filter_P1_LevelSet();
                case 'PDE'
                    obj = Filter_PDE_LevelSet();
            end
        end
    end
end