%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% REAL-TIME BCILAB-LSL DEMONSTRATION SCRIPT
%
% This script demonstrates how to set up a default BCILAB-LSL pipeline for
% real-time data extraction and processing from an EEG device or file
%
% This script requires the following tools to be installed:
% BCILAB: https://www.sccn.ucsd.edu/wiki/BCILAB
% LSL:    https://code.google.com/p/labstreaminglayer/
%
% Optional (if using SourceLocalization)
% MobiLab: http://sccn.ucsd.edu/wiki/MoBILAB
%
% Author: Tim Mullen,  October 14, 2013, SCCN/INC/UCSD
% Email:  tmullen@ucsd.edu
%
% .........................................................................
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
% .........................................................................
%
% If you use this script as a basis for your published work, kindly
% consider acknowledging us in your manuscript. A possible example:
% "Thanks to Tim Mullen and Christian Kothe (SCCN, UCSD) for providing
%  scripting support"
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Force EEGLAB to use double precision
pop_editoptions( 'option_single', false);

%% Define config options (USER MUST DEFINE THIS)
% -------------------------------------------------------------------------
% If runlsl = true, then stream 'online' from device
% If runlsl = false then stream data from opts.PlaybackDataFile (below)
opts.runlsl = false;

% Run SIFT on the pipeline (following BCILAB filter pipeline)
opts.runSIFT = true;

% Set up the name of the LSL stream
opts.lsl.StreamName          = 'EEGDATA';
opts.lsl.SelectionProperty   = 'type';  % can also be 'name'
opts.lsl.SelectionValue      = 'EEG';

% Determine a fixed 'sliding' window length (seconds) for pulling data from LSL
% If winlen=0, pull the most recent (variable length) chunk of unprocessed data
opts.winlen = 1;

% suppress console output in processing loop?
% if false, this can reusult in a LOT of text printed to console
opts.silence = true;

% Establish file paths
% ..........................................................................
% User Tip:
%
% All paths are relative to opts.datapath. This is platform-independent and
% itself can be relative to bcilab root folder (i.e. data:/ is the userdata
% folder in the bcilab root dir)
% ..........................................................................
opts.datapath         = 'data:/';
% (required) calibration data set2
opts.TrainingDataFile = 'Simulation_EEGLAB_XVII.set'; %'MyCalibrationFile.set';
% (optional) file to "playback" if opts.runlsl = false
opts.PlaybackDataFile = 'Simulation_EEGLAB_XVII.set'; %'MyPlaybackFile.set';
% (optional) pipeline config file
opts.BCILAB_PipelineConfigFile = ''; 'MyFilteringPipeline.mat';
% (option) SIFT pipeline config file
opts.SIFT_PipelineConfigFile = ''; 'MySiftFilteringPipeline.mat';
% (optional) name of file containing MobiLab head model
opts.HeadModelDataFile= ''; %'NameOfHeadModelFile.mat';   % Look in <SIFT_RootFolder>\resources\headmodels\standard-Colin27-385ch.mat

%% Load head model object
% -------------------------------------------------------------------------
if ~isempty(opts.HeadModelDataFile)
    hmObj = headModel.loadFromFile(env_translatepath([opts.datapath opts.HeadModelDataFile]));
end

%% load calibration recording
% -------------------------------------------------------------------------
calibData = exp_eval_optimized(io_loadset([opts.datapath opts.TrainingDataFile], ...
                         'markerchannel',{'remove_eventchns',false}));
flt_pipeline('update');

%% Start LSL streaming
% -------------------------------------------------------------------------
if opts.runlsl == true
    run_readlsl('MatlabStream',opts.lsl.StreamName,                 ...
                'SelectionProperty',opts.lsl.SelectionProperty,     ...
                'SelectionValue',opts.lsl.SelectionValue);
else
    % ... OR read from datafile
    run_readdataset('MatlabStream',opts.lsl.StreamName,                         ...
                    'Dataset',io_loadset([opts.datapath opts.PlaybackDataFile], ...
                    'markerchannel',{'remove_eventchns',false}));
end

%% Set up the pipeline
% -------------------------------------------------------------------------
% load existing config file(s) (if it exists)
try    fltPipCfg = exp_eval(io_load([opts.datapath opts.BCILAB_PipelineConfigFile]));
catch, disp('-- no existing pipeline --'); fltPipCfg = {}; end
try    siftPipCfg = exp_eval(io_load([opts.datapath opts.SIFT_PipelineConfigFile]));
catch, disp('-- no existing pipeline --'); siftPipCfg = {}; end

% enforce usage of user-defined head model
if ~isempty(opts.HeadModelDataFile)
    fltPipCfg.psourceLocalize.hmObj = [opts.datapath opts.HeadModelDataFile]; end

% display GUI to allow user to configure the BCILAB pipeline...
fltPipCfg = arg_guipanel('Function',@flt_pipeline, ...
                         'Parameters',[{'signal',calibData} fltPipCfg], ...
                         'PanelOnly',false);

% display GUI to allow user to configure the SIFT pipeline...
if opts.runSIFT
    if isfield(calibData,'CAT')
        calibData = rmfield(calibData,'CAT');
    end
    siftPipCfg = arg_guipanel('Function',@onl_siftpipeline, ...
                             'Parameters',[{'EEG',calibData} siftPipCfg], ...
                             'PanelOnly',false);
    % force the modeling window length to agree with chunk length
    siftPipCfg.modeling.winlen = opts.winlen;
end
% ..........................................................................
% User Tip:
%
% You might want to save the pipeline config (fltPipCfg) at this point for
% later reload (from 'opts.BCILAB_PipelineConfigFile')
% save(env_translatepath([opts.datapath opts.SIFT_PipelineConfigFile]),'-struct','siftPipCfg');
% save(env_translatepath([opts.datapath opts.BCILAB_PipelineConfigFile]),'-struct','fltPipCfg');
% ..........................................................................

% ...apply the pipeline to calibration data
disp('-- Calibrating pipeline on training data (please wait) --');
cleaned_data = exp_eval(flt_pipeline('signal',calibData,fltPipCfg));

% ..........................................................................
% User Tip:
%
% Instead of using the GUI, you can also easily define pipelines in the
% script itself. Here are some examples:
%
% % remove flatline channels:
% noflats      = flt_clean_flatlines(flt_seltypes(calibData,'EEG'));
% % apply a high-pass filter:
% highpassed   = flt_fir(noflats,[0.5 1],'highpass');
% % discard noisy channels:
% goodchannels = flt_clean_channels('signal',highpassed,'min_corr',0.35,'ignored_quantile',0.3);
%
% % you always need to make sure to apply the pipeline
% cleaned_data = exp_eval(goodchannels);
% ..........................................................................

% ..........................................................................
% User Tip:
%
% After this step, cleaned_data will contain the results of having applied
% the entire pipeline to your calibration data. Thus, the steps up to this
% point essentially define an offline data processing pipeline which you
% can use for your publications. It is also helpful at this stage to
% examine the contents of cleaned_data for deficiencies, which can help you
% fine-tune your pipeline for later online use.
% ..........................................................................

% initialize the pipeline for streaming data
pipeline     = onl_newpipeline(cleaned_data,opts.lsl.StreamName);

% render a panel for viewing streams
gui_vis_filtered;

%% Main loop
% -------------------------------------------------------------------------
disp('-- Running pipeline on playback data --');
chunk_len = round(opts.winlen*cleaned_data.srate);
ConnData = [];
while true
    % grab a chunk of data from the stream and send through the filter pipeline
    [eeg_chunk,pipeline] = onl_filtered(pipeline, chunk_len, opts.silence);

    % process data chunk with SIFT
    if opts.runSIFT
        [eeg_chunk cfg] = hlp_scope({'is_online',1},@onl_siftpipeline,'EEG',eeg_chunk,siftPipCfg);
    end

    % .....................................................................
    % User Tip:
    %
    % The structure 'eeg_chunk' now contains the results of applying the
    % pipeline to the chunk of raw data acquired from the LSL stream.
    % This is an augmented EEGLAB data structure.
    %
    % - You can add code here to apply your own additional processing steps
    % - You'll also want to add code to store the results you'd like keep
    %
    % Hint:
    %  eeg_chunk.data contains processed/cleaned data
    %
    %  (if using source localization)
    %  eeg_chunk.srcpot contains current density for ROIs
    %
    %  (if using source localization and keepFullCsd is enabled)
    %  eeg_chunk.srcpot_all contains current density for all mesh vertices
    %
    %  (if using ICA)
    %  eeg_chunk.icaact contains ica activations
    %
    % (if using SIFT)
    % eeg_chunk.CAT  contains a SIFT object/datastructure
    %  CAT
    %   .Conn       Connectivity object
    %       .winCenterTimes
    %       .freqs
    %       .dims   dimensions for connectivity matrix
    %               e.g. (chans_to, chans_from, freqs, time)
    %       .<measure_name>    Connectivity matrix (conforms to dims above)
    %   .MODEL      Model structure
    %
    % .....................................................................

    % (optionally) give Matlab a little break...
    pause(0.0001);
end


function s=get_name(a)

s=[get_name(a.algorithm)];  %% print name of algorithm

if iscell(a.child)
  s=[s '(' get_name(a.child{1}) ',...)'];
else
  s=[s '(' get_name(a.child) ')'];
end

eval_name                   %% print values of hyperparameters


function flip = spm_flip_analyze_images
% Do Analyze format images need to be left-right flipped? The default
% behavior is to have the indices of the voxels stored as left-handed and
% interpret the mm coordinates within a right-handed coordinate system.
%
% Note: the behavior used to be set in spm_defaults.m, but this has now
% been changed.
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% John Ashburner
% $Id: spm_flip_analyze_images.m 1418 2008-04-15 19:15:16Z john $

flip = 1;


function varargout = ubcread(varargin)
% SIFTREAD Read Lowe's SIFT implementation data files
%   [F,D] = VL_UBCREAD(FILE) reads the frames F and the descriptors D
%   from FILE in UBC (Lowe's original implementation of SIFT) format
%   and returns F and D as defined by VL_SIFT().
%
%   VL_UBCREAD(FILE, 'FORMAT', 'OXFORD') assumes the format used by
%   Oxford VGG implementations .
%
%   See also: VL_SIFT(), VL_HELP().
[varargout{1:nargout}] = vl_ubcread(varargin{:});


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
% This files deals the parameters for the Testing environment
%
% options:
% FAIRtestPara('disp')          displays the current settings
% FAIRtestPara('set',list{:})	sets defaults and overwrites with user supplied values
% FAIRtestPara('get',name)		gets value of variable name
% FAIRtestPara('clear')			clears all variables
%
%==============================================================================

function varargout = FAIRtestPara(varargin)

caller = dbstack; % identify the name of the calling function

if nargin == 0,
  help(mfilename);
  FAIRtestPara('disp');
  return;
end;

if nargin > 0 && isstr(varargin{1}),
  task = varargin{1};
  varargin(1) = [];

  switch task,
    case 'set',
      setFAIRtestpara(varargin{:});

    case 'get',
      for j = 1:length(varargin)
        varargout{j} = getappdata(0,varargin{2*j-1});
      end;

%    case 'value',
%      varargout{1} = strcmp(getappdata(0,varargin{1}),'on');

    case 'disp',
      dispFAIRtestpara;

    case 'clear',
      FAIRpara = getappdata(0);
      Fnames   = fieldnames(FAIRpara);
      K        = reshape(find(cellfun(@isempty,strfind(Fnames,'FAIR'))==0),1,[]);
      for k = K
        rmappdata(0,Fnames{k});
      end;
    otherwise, error('1');
  end;
else
  error(1)
end;

%------------------------------------------------------------------------------

function setFAIRtestpara(varargin)

para = {
  'FAIRcaller',         ''
  'FAIRfolder',         ''
  'FAIRedit',           'on'
  'FAIRcompile',        'on'
  'FAIRignoreCompiles', 'on'
  'FAIRrun',            'on'
  'FAIRrange',          'full'
  'FAIRextension',      'all'
  'FAIRerror',          'on'
  'FAIRkeyboard',       'on'
  'FAIRfilter',         'off'
  'FAIRpause',          'off'
  'FAIRinput',          'off'
  'FAIRclearTemp',      'on'
  'FAIRcheckList',      []
};

for j=1:size(para,1)
  value = getappdata(0,para{j,1});
  if isempty(value)
    setappdata(0,para{j,1},para{j,2})
  end;
end;

for k=1:length(varargin)/2, % overwrites default parameter
    setappdata(0,varargin{2*k-1},varargin{2*k});
end;

%------------------------------------------------------------------------------

function dispFAIRtestpara;
FAIRpara = getappdata(0);
Fnames   = fieldnames(FAIRpara);
K        = reshape(find(cellfun(@isempty,strfind(Fnames,'FAIR'))==0),1,[]);

if isempty(K)
return;
end;

FAIRmessage('.');
for k = K
  name  = Fnames{k};
  value = getappdata(0,name);
  if ischar(value)
    fprintf('%-20s: %s\n',name,value)
  elseif isnumeric(value) && (length(value) == 1)
    fprintf('%-20s= %s\n',name,num2str(value))
  elseif isnumeric(value),
    fprintf('%-20s: %d files\n',name,length(value))
  elseif isstruct(value),
    fprintf('%-20s: %d files\n',['struct ',name],length(value))
  else
    keyboard
  end;
end;
FAIRmessage('.');

%==============================================================================


function [ newstr ] = m2tstrjoin( cellstr, delimiter )
%M2TSTRJOIN This function joins a cellstr with a separator
%
% This is an alternative implementation for MATLAB's `strjoin`, since that
% one is not available before R2013a.
%
% See also: strjoin

    %TODO: Unify the private `m2tstrjoin` functions
    %FIXME: differs from src/private/m2tstrjoin in functionality !!!

    nElem = numel(cellstr);
    if nElem == 0
        newstr = '';
        return % m2tstrjoin({}, ...) -> ''
    end

    newstr = cell(2,nElem);
    newstr(1,:)         = reshape(cellstr, 1, nElem);
    newstr(2,1:nElem-1) = {delimiter}; % put delimiters in-between the elements
    newstr(2, end)      = {''}; % for Octave 4 compatibility
    newstr = [newstr{:}];

end


function ebcdic = ch_to_ebcdic ( ch )

%*****************************************************************************80
%
%% CH_TO_EBCDIC converts a character to EBCDIC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 March 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character CH, the ASCII character.
%
%    Output, character EBCDIC, the corresponding EBCDIC character, or a
%    blank character if no correspondence holds.
%
  ic = ch;

  iebcdic = ic_to_iebcdic ( ic );

  if ( iebcdic ~= -1 )
    ebcdic = iebcdic;
  else
    ebcdic = ' ';
  end

  return
end


function runcilta() % autogenerated function wrapper
    %% This script runcias find first a maximum of all z-vlaues over all
    % frames and afterward produced a movie and start the movieviever
    % Last edit: Stefan Wiemer 11/94
    % turned into function by Celso G Reyes 2017

    ZG=ZmapGlobal.Data; % used by get_zmap_globals

    report_this_filefun(mfilename('fullpath'));
    think

    j = 0;
    it = 20
    iwl = iwl3/days(ZG.bin_days);
    [len, ncu] = size(cumuall);
    len = len -2;
    step = len/nustep;

    ma = [];
    mi = [];

    wai = waitbar(0,'Please wait...')
    set(wai,'Color',[0.8 0.8 0.8],'NumberTitle','off',...
        'Name','fin_max -Percent done','pos',[ZG.welcome_pos 300 80]);

    pause(0.1)
    % find maximu for scaling
    %
    for it = 1:step:len-iwl;
        fin_malt
        waitbar(it/len)
    end   % for i
    close(wai)

    ZG.maxc = max(max(ma));
    ZG.minc = min(min(mi));

    %set up movie axes
    %
    figure
    tmp = gcf

    cin_lta
    axes(has)
    fs_m = get(gcf,'pos');

    m = moviein(length(1:step:len-iwl));

    wai = waitbar(0,'Please wait...')
    set(wai,'Color',[0.8 0.8 0.8],'NumberTitle','off',...
        'Name','Movie -Percent done','pos',[ZG.welcome_pos 300 80]);
    pause(0.1)

    for it = 1:step:len-iwl;
        j = j+1;
        cin_lta
        axes(has)
        m(:,j) = getframe(has);
        figure(wai);
        waitbar(it/len)
    end   % for i

    close(tmp)
    close(wai)

    % save movie
    %
    clear newmatfile

    [newmatfile, newpath] = uiputfile('*.mat', 'Save As');

    if length(newpath)  > 1
        save([newpath newmatfile file1])
        showmovi
    else
        showmovi
    end

end


function [p] = mesh_write(p)

% mesh_write - a switch yard for several mesh writing functions
%
% Usage: [p] = mesh_write(p)
%
% p is a parameter structure (see eeg_toolbox_defaults for
% more details). In this function, it should contain mesh data
% in p.mesh.data and the following string fields:
%
%       p.mesh.path - the directory location of the file to load
%       p.mesh.file - the name of the file to load
%       p.mesh.type - the file formats (case insensitive) are:
%
%                    'emse'
%                    'brainstorm'
%                    'ascii' or 'freesurfer' for *.asc file
%                    'fs_surf' for freesurfer binary surface
%                    'fs_curv' for freesurfer binary curvature
%                    'fs_overlay' for freesurfer binary overlay (.w)
%
% If you have a file format you would like supported, please email
% the author with an example and description of the format.  The
% file formats supported here are described in more detail at
% their respective websites:
%
%       EMSE:       http://www.sourcesignal.com
%       BrainStorm: http://neuroimage.usc.edu/brainstorm/
%       FreeSurfer: http://surfer.nmr.mgh.harvard.edu/
%
% See also, mesh_open, mesh_write_emse,
%           mesh_write_brainstorm, mesh_write_freesurfer
%           mesh_write_fs_surf, mesh_write_fs_curv,
%           mesh_write_fs_overlay
%

% $Revision: 1.1 $ $Date: 2009-04-28 22:13:58 $

% Licence:  GNU GPL, no express or implied warranties
% History:  02/2002 Darren.Weber_at_radiology.ucsf.edu
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if ~exist('p','var'),
    msg = sprintf('\nMESH_WRITE...no input p struct.\n');
    error(msg);
elseif isempty(p),
    msg = sprintf('\nMESH_WRITE...input p struct is empty.\n');
    error(msg);
elseif isempty(p.mesh.data),
    msg = sprintf('\nMESH_WRITE...input p struct has no mesh data.\n');
    error(msg);
end

type = lower(p.mesh.type);

switch type,

case 'emse',

    mesh_write_emse(p);

case 'brainstorm',

    mesh_write_brainstorm(p);

case {'ascii','freesurfer'}, % for *.asc file

    mesh_write_freesurfer(p);

case 'fs_surf', % for freesurfer binary surface

    mesh_write_fs_surf(p);

case 'fs_curv', % for freesurfer binary curvature

    mesh_write_fs_curv(p);

case 'fs_overlay', % for freesurfer binary overlay (.w)

    mesh_write_fs_overlay(p);

otherwise,
    fprintf('...mesh format: %s\n', p.mesh.type);
    fprintf('...sorry, cannot write this data format at present.\n');
    return;
end

return


function mappedMedia = mapMediumData2AGORA(strainGrowth,inputMedia)
% This function extracts experimentally determined growth of species on
% multiple media and converts the in silico minimal medium the strain can
% grow on into an input fit for DEMETER. The input data was retrieved from
% Tramontano et al., Nat Microbiol 2019 (PMID: 29556107).
%
% USAGE
%       mappedMedia = mapMediumData2AGORA(strainGrowth,inputMedia)
%
% INPUTS
% strainGrowth          Growth of strains on the different media reported
%                       by Tramontano et al.
% inputMedia            Growth media tested by Tramontano et al. converted
%                       into a computationally readable format
%
% OUTPUT
% mappedMedia           Data from Tramontano et al. converted into a format
%                       that can be added to GrowthRequirementsTable
%
% .. Author:
%       - Almut Heinken, 03/2020

% delete organisms that did not grow on any medium
rmStrain=[];
cnt=1;
for i=2:size(strainGrowth,1)
    if sum(str2double(strainGrowth(i,2:end)))==0
        rmStrain(cnt,1)=i;
        cnt=cnt+1;
    end
end
strainGrowth(rmStrain,:)=[];

mappedMedia(1,:) = inputMedia(1,:);
for i = 2:size(strainGrowth,1)
    mappedMedia{i,1} = strainGrowth{i,1};
    % find the media it can grow on
    canGrow=strainGrowth(1,find(strcmp(strainGrowth(i,:),'1')));
    inputMediaStrain=inputMedia;
    [C,IA]=setdiff(inputMediaStrain(:,1),canGrow);
    inputMediaStrain(IA(2:end),:)=[];
    for j=2:size(inputMediaStrain,2)
        if any(strcmp(inputMediaStrain(2:end,j),'-1'))
            mappedMedia{i,j} = '-1';
        else
            mappedMedia{i,j} = '0';
        end
    end
end

end


%% sphere_index
% Below is a demonstration of the features of the |sphere_index| function

%%
clear; close all; clc;

%% Syntax
% |[I J K]=sphere_index(r,Ic,Jc,Kc);|

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


function [ readerobj ] = open_generic_reader(filename, datasize,...
    datatype, complextype, data_offset, endian, symmetry, bands_ip,...
    blocksize)
%OPEN_GENERIC_READER Generic reader object for reading pixel interleaved
% data from a flat file
%
% Written by: Wade Schwartzkopf, NGA/IDT
%
% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////

if (nargin<7||isempty(symmetry)), symmetry=[0 0 0]; end; % Assume store azimuth-major order, viewed from above
if (nargin<8||isempty(bands_ip)), bands_ip=1; end; % Assume single band
if (nargin<9||isempty(blocksize)), blocksize=datasize; end; % Assume no blocking

[chipper_function, close_function]=generic_chipper( filename, datasize,...
    datatype, complextype, data_offset, endian, symmetry, bands_ip, blocksize);
if symmetry(3), datasize=datasize(end:-1:1); end;
readerobj = chipfun2readerobj(chipper_function, datasize);
readerobj.close=close_function;

end

% //////////////////////////////////////////
% /// CLASSIFICATION: UNCLASSIFIED       ///
% //////////////////////////////////////////


% D training using ImageNet model and RPN proposals
% --------------------------------------------------------
% D&T implementation
% Modified from MATLAB  R-FCN (https://github.com/daijifeng001/R-FCN/)
% and Faster R-CNN (https://github.com/shaoqingren/faster_rcnn)
% Copyright (c) 2017, Christoph Feichtenhofer
% Licensed under The MIT License [see LICENSE for details]
% --------------------------------------------------------
clc;
clear mex;
clear is_valid_handle;
run(fullfile(fileparts(fileparts(mfilename('fullpath'))), 'startup'));

%% -------------------- CONFIG --------------------
opts.caffe_version          = 'caffe-rfcn';
opts.gpu_id                 = auto_select_gpu;

active_caffe_mex(opts.gpu_id, opts.caffe_version);

res50 = 0 ;
with_ohem = true;
concat = false;
modality = 'rgb';
with_resNext = 1;
root_path = get_root_path;

if res50
  model                       = Model.ResNet50_for_RFCN_ILSVRCvid_dilation();
  opts.cache_name             = 'rfcn_ILSVRC_ResNet50_OHEM_rpn_dilation';
  conf                        = rfcn_config_ohem('image_means', model.mean_image);
else
  model                       = Model.ResNet101_for_RFCN_ILSVRCvid_dilation();
  opts.cache_name             = 'rfcn_ILSVRC_ResNet101_OHEM_rpn_dilation';
  conf                        = rfcn_config_ohem('image_means', model.mean_image);
  if with_resNext
    model                       = Model.ResNetX101_for_RFCN_ILSVRCvid_dilation();
    opts.cache_name             = 'rfcn_ILSVRC_ResNeXt101_OHEM_rpn_dilation';
    conf                        = rfcn_config_ohem('image_means', model.mean_image);
  end
end

% check base model existance
check_dl_model(model.net_file);

conf.root_path = root_path ;
fprintf('Loading dataset...')
dataset = [];
dataset = Dataset.ilsvrc15(dataset, 'VIDval16lite3frames', false, root_path);
dataset = Dataset.ilsvrc15(dataset, 'VID+DETtrain16sample', false, root_path);
% do validation after val_interval iters, or not
opts.do_val                 = true;

%% -------------------- TRAINING --------------------
caffe.reset_all();
conf.input_modality = 'rgb';
conf.ims_per_batch = 2 ;
conf.max_size = [1000 ];

conf.sample_vid = false;
conf.use_flipped = true;
opts.cache_name_  = [opts.cache_name '_' conf.input_modality '300RPN_batch4_1e3LR_160kiter' ];

conf.num_proposals = 300;

% model.net_file = fullfile(root_path, 'output', 'rfcn_cachedir', opts.cache_name_, imdbs_name , ...
%   'iter_140000');

opts.rfcn_model        = rfcn_train(conf, dataset.imdb_train, dataset.roidb_train, ...
                                'offline_roidb',           true, ...
                                'output_dir',     root_path, ...
                                'do_val',           opts.do_val, ...
                                'imdb_val',         dataset.imdb_test, ...
                                'roidb_val',        dataset.roidb_test, ...
                                'solver_def_file',  model.solver_def_file, ...
                                'net_file',         model.net_file, ...
                                'cache_name',       opts.cache_name_, ...
                                'caffe_version',    opts.caffe_version, ...
                                'resume_iter', 0, ...
                                'val_iters', 500, ...
                                'val_interval', 5000, ...
                                'visualize_interval', 0);

%% -------------------- TESTING --------------------
%%
caffe.reset_all();
imdbs_name = cell2mat(cellfun(@(x) x.name, dataset.imdb_train, 'UniformOutput', false));
opts.rfcn_model = fullfile(root_path, 'output', 'rfcn_cachedir', opts.cache_name_, imdbs_name , ...
  'iter_140000');
proposal_path = fullfile(root_path, 'Data/VID/val/RPN_proposals/');

conf.root_path = root_path ;
imdb_val_lite = Dataset.ilsvrc15([], 'VIDval16', false, root_path);
% imdb_val_lite = Dataset.ilsvrc15([], 'VIDval16liteStride10', false, root_path);
% imdb_val_lite = Dataset.ilsvrc15([], 'VIDval16lite3frames', false, root_path);
test_classes = [];

conf.num_proposals = 300;
rfcn_test(conf, imdb_val_lite.imdb_test, imdb_val_lite.roidb_test, ...
      'net_def_file',     model.test_net_def_file, ...
      'net_file',         opts.rfcn_model, ...
      'cache_name',       opts.cache_name_,...
      'ignore_cache',     false, ...
      'proposal_path', proposal_path, ...
      'visualize_every', 0, ...
      'test_classes', test_classes, ...
      'suffix', '');

%% proposal test
recall_per_cls = compute_recall_ilsvrc15(proposal_path, 300, imdb_val_lite.imdb_test);
mean_recall = mean([recall_per_cls.recall]);
fprintf('mean rec:: %.2f\n\n', 100*mean_recall);


function err = mne_write_w_file1(filename, w)
% mne_write_w_file1(filename, w)
%
%  writes a binary 'w' file
%
%  filename - name of file to write to
%  w        - a structure with the following fields:
%
% vertices - vector of vertex indices (1-based)
% data     - vector of data values
%

%
%   Author : Matti Hamalainen, MGH Martinos Center
%   License : BSD 3-clause
%
% Revision 1.5  2006/04/23 15:29:41  msh
% Added MGH to the copyright
%
% Revision 1.4  2006/04/10 23:26:54  msh
% Added fiff reading routines
%
% Revision 1.3  2005/12/05 20:23:21  msh
% Added fiff_save_evoked. Improved error handling.
%
% Revision 1.2  2005/11/21 03:19:12  msh
% Improved error handling
%
% Revision 1.1  2005/11/21 02:15:51  msh
% Added more routines
%

me='MNE:mne_write_w_file1';
if(nargin ~= 2)
    error(me,'usage: mne_write_w_file1(filename, w)');
    return;
end

try
    w.vertices = w.vertices - 1;
    mne_write_w_file(filename,w);
catch
    w.vertices = w.vertices - 1;
    error(me,'%s',mne_omit_first_line(lasterr));
end

return;


function obj = export(obj, varargin)
% export Export gramm plot to vector or bitmap image
%
% Example syntax: gramm_object.export('file_name','my_figure','export_path','./test/','file_type','pdf')
% export() must be called after a draw() call and will save the plot to
% file using the specified 'name',value options:
% - 'file_name' Desired name for the file. Extension will be added
%   according to 'file_type'
% - 'export_path' Path of the destination folder (absolute or relative).
    %By default the file is saved in the current folder
% - 'file_type': supports 'svg','pdf' and 'eps' for vector output, and
%   'png' and 'jpg' for high-resolution bitmap output. The default is 'svg' on 2014b+ Matlab
%   versions, and 'pdf' on older versions.
% - 'width' and 'height' allow to set the desired size of the exported
%   figure. By default (recommended), the exported figure will look the same as the on-screen
%   plot. Setting this manually is tricky.
% - 'units' allows to set the units used for the 'width' and 'height'
%   input. Supports 'centimeters' and 'inches'. Default is 'centimeters'.

% Retrieve figure handle (all are the same so only the first is ok)
h_fig = obj(1).parent;

% calculating defaults
fig_pos = getpixelposition(h_fig);
%Resolution in pixels per cm (note: not the actual resolution, Matlab doesn't
%know about real screen size).
resolution = get(0, 'ScreenPixelsPerInch')/2.54;
width_fig = fig_pos(3)/resolution;
height_fig = fig_pos(4)/resolution;

%SVG is unsupported on older Matlab versions
if obj(1).handle_graphics
    default_file_type='svg';
else
    default_file_type='pdf';
end

% parse arguments and set defaults
p=inputParser;
my_addParameter(p,'file_name','gramm_export');
my_addParameter(p,'export_path','');
my_addParameter(p,'file_type', default_file_type);
my_addParameter(p,'width', width_fig);
my_addParameter(p,'height', height_fig);
my_addParameter(p,'units', 'centimeters');
parse(p,varargin{:});

% Turn off warning due to a custom defined figure resize function called on save
warning('off', 'MATLAB:print:CustomResizeFcnInPrint');

%Verify that the path is correct
if ~isempty(p.Results.export_path) && ~exist(p.Results.export_path,'dir')
    error('The specified folder does not exist')
end

% Building variables from (default) input data
file_path = fullfile(p.Results.export_path, p.Results.file_name);
width = p.Results.width;
height = p.Results.height;

% Verify that parent object is a figure object
if obj(1).handle_graphics
    if ~isa(h_fig, 'matlab.ui.Figure')
        error('Parent gramm object is not a matlab.ui.Figure.');
    end
end

% In case units are inches, we rescale to cm
if strcmp(p.Results.units, 'inches')
	if ~any(strcmp(p.UsingDefaults, 'width'))
		width = p.Results.width * 2.54;
	end

	if ~any(strcmp(p.UsingDefaults, 'height'))
		height = p.Results.height * 2.54;
	end
end

% Cropping paper to fit the figure
set(h_fig, 'Units', 'centimeters');
set(h_fig, 'PaperUnits', 'centimeters');
set(h_fig, 'PaperSize', [width, height]);
set(h_fig, 'PaperPosition', [0, 0, width, height]);

% Save figure in preferred file type
switch p.Results.file_type
	case 'pdf'
		print(h_fig, file_path, '-dpdf', '-painters');

	case 'eps'
		print(h_fig, file_path, '-depsc', '-painters', '-r300');

	case 'svg'
		print(h_fig, file_path, '-dsvg', '-painters');

	case 'png'
		print(h_fig, file_path, '-dpng', '-opengl', '-r300');

	case 'jpg'
		warning('JPEG is not recommanded for saving figures. Use PDF or SVG whenever possible');
		print(h_fig, file_path, '-djpeg', '-opengl', '-r300');

	otherwise
		error('Argument file_type not recognized. Available options are: pdf, eps, svg, png, jpg.')
end

% Turn warning back on
warning('on', 'MATLAB:print:CustomResizeFcnInPrint');

end


function AddSpikeTimes(spikes)

%AddSpikeTimes - Add spike timestamps.
%
%  USAGE
%
%    AddSpikeTimes(spikes)
%
%  SEE
%
%    See also ThresholdSpikes.

% Copyright (C) 2012 by Michaël Zugaro
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 3 of the License, or
% (at your option) any later version.

global DATA;
if isempty(DATA),
	error('No session defined (did you forget to call SetCurrentSession? Type ''help Data'' for details).');
end

% Parse parameters
if ~issamples(spikes,'#2'),
	error('Incorrect spikes (type ''help AddSpikeTimes'' for details).');
end

DATA.spikes = [DATA.spikes;spikes];