% ReadSegyFast : Reads a SEG Y rev 1 formatted file, without header values (faster than ReadSegy)
%
% Call :
% [Data]=ReadSegyFast(filename);
% and equivalent to :
% [Data]=ReadSegy(filename);
%
%
% Read only the data of a SegFile - NOT Their headers.
% Much faster than ReadSegy
%
% 'minmax', 'skip'
%

% Implemented using the syntax of the SEG-Y revised format :
% SEGY-Y rev 0, SEG-Y rev 1 as described in
% http://seg.org/publications/tech-stand/
%
% Extended Textual Header is not yet tested
% If you would like it implemented, please send me an SEGY file with
% that sort of information, as well as a description of the segy file
%
%
% (C) 2001, Thomas Mejer Hansen, thomas@cultpenguin.com
%
%    This program is free software; you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation; either version 2 of the License, or
%    (at your option) any later version.
%
%    This program is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with this program; if not, write to the Free Software
%    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
%
%
%
%
function [Data,SegyHeader,SegyTraceHeadersBinary]=ReadSegyFast(filename,varargin);

  mfilename='ReadSegyFast';

  if nargin==0,
    SegymatVerbose([mfilename,' : ', filename,' does not exist !'])
    Data=[];SegyTraceHeaders=[];SegyHeader=[];HeaderInfo=[];
    return
  end

  % Initialize varargin values
  dsf=[];
  revision=[];
  endian_tight=[];
  tmin=[];tmax=[];
  headermin=[];headermax=[];header=[];
  jump=[];
  SegyHeader=[];

  segyid = fopen(filename,'r','b');   % ALL DISK FILES ARE IN BIG
                                    % ENDIAN FORMAT, ACCORDING TO SEG
                                    % Y rev 1

  fseek(segyid,0,'eof');
  BytesInFile = ftell(segyid);
  fseek(segyid,0,'bof');

ninput=nargin;
% NEXT TWO LINES TO ENUSRE THAT VARARGIN CAN BE PASSED TO FUNCTION
if ninput==2
    % CALL USING VARARGIN
    ninput=1+length(varargin{1});
    varargin=varargin{1};
else
    % DIRECT CALL
    ninput=length(varargin);
end

% TRANSFORM VARARGING INTO PARAMETERS
cargin=1;
while (cargin<ninput)

    if strcmp(varargin{cargin},'jump')
       cargin=cargin+1;
       eval(['jump=',num2str(varargin{cargin}),';']);
       SegymatVerbose(['JUMP : Read only every ',num2str(jump),'th trace'])
    end

    if strcmp(varargin{cargin},'minmax')
       cargin=cargin+1;
       eval(['header=''',varargin{cargin},''';']);
       cargin=cargin+1;
       eval(['headermin=',num2str(varargin{cargin}),';']);
       cargin=cargin+1;
       eval(['headermax=',num2str(varargin{cargin}),';']);
       SegymatVerbose(['MIN MAX : Using header ',header,' from ',num2str(headermin),' to ',num2str(headermax)])
    end

    if strcmp(varargin{cargin},'trange')
       cargin=cargin+1;
       eval(['tmin=',num2str(varargin{cargin}),';']);
       cargin=cargin+1;
       eval(['tmax=',num2str(varargin{cargin}),';']);
       SegymatVerbose(['TRANGE : tmin=',num2str(tmin),' tmax=',num2str(tmax)])
    end

    if strcmp(varargin{cargin},'revision')
       cargin=cargin+1;
       eval(['revision=',num2str(varargin{cargin}),';']);
       SegymatVerbose(['USING REVISION : rev=',num2str(revision)])
    end

    if strcmp(varargin{cargin},'dsf')
       cargin=cargin+1;
       eval(['dsf=',num2str(varargin{cargin}),';']);
       SegymatVerbose(['USING Data Sample Format : dsf=',num2str(dsf)])
    end

    if strcmp(varargin{cargin},'SegyHeader')
       cargin=cargin+1;
       SegyHeader=varargin{cargin};
       SegymatVerbose(['USING LOADED SEGYHEADER'])
    end

    cargin=cargin+1;

end

% SKIP DATA SEEMS OUTDATED, COMMENTING OUT 2003-10-24

%if exist('SkipData')==0,
%    SkipData=0; % [0] READ ONLY HEADER VALUES, [1] READ IN ALL DATA
%end%%
%
%if SkipData==1, SegymatVerbose(['Not reading data - headers only']), end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% BINARY HEADERS
if isempty(SegyHeader)==1,
  SegyHeader=GetSegyHeader(segyid);
else
  SegymatVerbose([mfilename,' - Using supplied SegyHeader'])
end

% APPLY CHANGES TO SEGY HEADER IF NEEDE
if isempty(revision)==0,
  SegyHeader.SegyFormatRevisionNumber=revision;
  SegymatVerbose([mfilename,' - Manually set SEG-Y revision to ',num2str(revision)])
end
if isempty(dsf)==0,
  SegyHeader.DataSampleFormat=dsf;
end

% JUST SOME INFORMATION TO WRITE TO SCREEN :

Revision=SegyHeader.SegyFormatRevisionNumber;
if Revision>0, Revision=1; end
FormatName=SegyHeader.Rev(Revision+1).DataSampleFormat(SegyHeader.DataSampleFormat).name;
Format=SegyHeader.Rev(Revision+1).DataSampleFormat(SegyHeader.DataSampleFormat).format;
BPS=SegyHeader.Rev(Revision+1).DataSampleFormat(SegyHeader.DataSampleFormat).bps;
txt=['SegyRevision ',sprintf('%0.4g',Revision),', ',FormatName,'(',num2str(SegyHeader.DataSampleFormat),')'];

ns=SegyHeader.ns;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% READ TEXTURAL FILE HEADER EXTENSION IF NEEDED
%if SegyHeader.NumberOfExtTextualHeaders~=0
%  SegymatVerbose(['---------------------------------------------------'])
%  SegymatVerbose(['extendeD textual file headers are not supported yet'])
%  SegymatVerbose(['They are simply skipped'])
%  SegymatVerbose(['---------------------------------------------------'])
%end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% READ DATA
%Segy=fread(segyid,4000,'float32');
fseek(segyid,0,'eof'); DataEnd=ftell(segyid);

DataStart=3600+3200*SegyHeader.NumberOfExtTextualHeaders;
fseek(segyid,DataStart,'bof');       % Go to the beginning of the file

ntraces=(DataEnd-DataStart)./(240+(SegyHeader.ns)*(BPS/8));

SegymatVerbose(['Number of Samples Per Trace=',num2str(SegyHeader.ns)])
SegymatVerbose(['Number of Traces=',num2str(ntraces)])

% Set Format :
Revision=SegyHeader.SegyFormatRevisionNumber;
if Revision>0, Revision=1; end
Format=SegyHeader.Rev(Revision+1).DataSampleFormat(SegyHeader.DataSampleFormat).format;
bitpersample=SegyHeader.Rev(Revision+1).DataSampleFormat(SegyHeader.DataSampleFormat).bps;
bytepersample=bitpersample/8;
ntraceheader=240/bytepersample;

Data=fread(segyid,[ns+ntraceheader ntraces],Format);
SegyTraceHeadersBinary=Data(1:ntraceheader,:);
Data=Data([ntraceheader+1:1:ns+ntraceheader],:);
%SegymatVerbose(['Now=',num2str(ftell(segyid)),' END=',num2str(DataEnd)])

% THE FOLLOWING DOES NOT WORK FOR OCTAVE (uint32)
SegyHeader.DataFormat=Format;
if (strcmp(Format,'uint32')==1), % IBM FLOATING POINT
        % CONVERT FROM FLOATING POINT
        verbose=2;
        SegymatVerbose([mfilename,'Converting from IBM, DataFormat :',SegyHeader.DataFormat],verbose);
        Data=ibm2num(uint32(Data));
end;

existJump=1-isempty(jump);
existHeader=1-isempty(header);
existTmin=1-isempty(tmin);
existTmax=1-isempty(tmax);

if existJump
  usetraces=[jump:jump:ntraces];
  ntraces=length(usetraces);
  Data=Data(:,usetraces);
end

if (existTmin==1)&(existTmax==1)
  SegymatVerbose('TRANGE')
  % NEXT LINE SHOULD CONSIDER THAT ns in Trace and Segy Header could vary !!!
  origtrange=[1:1:SegyHeader.ns].*SegyHeader.dt.*1e-6;
  gooddata=find(origtrange>tmin & origtrange<tmax);
  Data=Data(gooddata,:);
end


function planC = faceOff(planC, scanNum, tmpDirPath, exportDICOMFlag, outputDICOMPath)

%% parse input and set up parameters, variables
if ~exist('exportDICOMFlag', 'var') && ~exist('outputDICOMPath','var')
        exportDICOMFlag = 0;
end

if exportDICOMFlag && (~exist('outputDICOMPath','var') || isempty(outputDICOMPath))
    outputDICOMPath = pwd;
end

if ~exist('tmpDirPath', 'var') || isempty(tmpDirPath)
    tmpDirPath = fullfile(getCERRPath,'ImageRegistration','tmpFiles');
end

%% ANTs setup
% optS = getCERROptions;
% if ~exist(optS.antspath_dir,'dir')
%     error(['ANTSPATH ' optS.antspath_dir ' not found on filesystem. Please review CERROptions.']);
% end
% antspath = fullfile(optS.antspath_dir,'bin');
% setenv('ANTSPATH', antspath);
% antsScriptPath = fullfile(optS.antspath_dir, 'Scripts');
% antsCERRScriptPath = fullfile(getCERRPath,'CERR_core', 'ImageRegistration', 'antsScripts');
% if isunix
%     setenv('PATH',[antspath ':' antsScriptPath ':' antsCERRScriptPath ':' getenv('PATH')]);
% else
%     setenv('PATH',[antspath ';' antsScriptPath ';' antsCERRScriptPath ';' getenv('PATH')]);
% end

%% register scan to template

% set affine transform
inputCmdFile = fullfile(getCERRPath,'ImageRegistration','antsScripts','SyN_a.txt');
[templateImageFile, faceMaskImageFile] = loadTemplatePlanC;
[ ~, planC, ~] = register_scans(templatePlanC, 1, planC, scanNum, 'QuickSyn ANTs', 'ANTs', '', [], [], [], inputCmdFile);

%% inverse-warp the template face mask to scan space
indexS = planC{end};
deformS = planC{indexS.deform}(end);
inverseFlag = 1;
warp_structures(deformS, strCreationScanNum, movStructNumsV, planC, faceMaskImageFIle, inverseFlag);

%% export CERR to DICOM
disp('Exporting to DICOM format...');
if exportDicomFlag
    export_planC_to_DICOM(planC, outputDICOMPath, 0);
%     exportCERRtoDICOM(origCerrPath,allLabelNamesC,outputCERRPath,...
%         outputDicomPath,algorithm,savePlancFlag)
end

function [templateImageFile, faceMaskImageFile] = loadTemplatePlanC
    templateImageFile = fullfile(getCERRPath,'Extras','faceOffBeta','template0.nii.gz');
    faceMaskImageFile = fullfile(getCERRPath,'Extras','faceOffBeta','deface_template_40_M_GD_8.nii.gz');


function [dat] = read_neuralynx_cds(filename, hdr, begsample, endsample, chanindx)

% READ_NEURALYNX_CDS reads selected samples and channels from a combined Neuralynx dataset with separate subdirectories for the LFP, MUA and spike channels
%
% Use as
%    hdr = read_neuralynx_cds(parentdir)
%    dat = read_neuralynx_cds(parentdir, hdr, begsample, endsample, chanindx)
%
% This is not a formal Neuralynx file format, but at the F.C. Donders
% Centre we use it as a directory/file organization in conjunction
% with Neuralynx, SPIKESPLITTING and SPIKEDOWNSAMPLE.

% Copyright (C) 2006, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

needhdr = (nargin==1);
needdat = (nargin>=2);

dirlist = dir(filename);
haslfp   = any(filetype_check_extension({dirlist.name}, 'lfp'));
hasmua   = any(filetype_check_extension({dirlist.name}, 'mua'));
hasspike = any(filetype_check_extension({dirlist.name}, 'spike'));
%hasttl  = any(filetype_check_extension({dirlist.name}, 'ttl'));   % separate file with original Parallel_in
%hastsl  = any(filetype_check_extension({dirlist.name}, 'tsl'));   % separate file with original TimeStampLow
%hastsh  = any(filetype_check_extension({dirlist.name}, 'tsh'));   % separate file with original TimeStampHi

if needhdr
  % read the header from the LFP dataset
  if haslfp
    lfpdir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'lfp'))).name);
    lfphdr = read_header(lfpdir);
    lfpfil = lfphdr.filename;
    for i=1:lfphdr.nChans
      lfplab{i} = sprintf('lfp_%s', lfphdr.label{i});
    end
  else
    lfphdr = [];
    lfpfil = {};
    lfplab = {};
  end

  % read the header from the MUA dataset
  if hasmua
    muadir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'mua'))).name);
    muahdr = read_header(muadir);
    muafil = muahdr.filename;
    for i=1:muahdr.nChans
      mualab{i} = sprintf('mua_%s', muahdr.label{i});
    end
  else
    muahdr = [];
    muafil = {};
    mualab = {};
  end

  % read the header from the SPIKE dataset
  if hasspike
    spikedir = fullfile(filename, dirlist(find(filetype_check_extension({dirlist.name}, 'spike'))).name);
    spikehdr = read_header(spikedir);
    spikefil = spikehdr.filename;
    for i=1:spikehdr.nChans
      spikelab{i} = sprintf('spike_%s', spikehdr.label{i});
    end
  else
    spikehdr = [];
    spikefil = {};
    spikelab = {};
  end

  if haslfp
    % assume that the LFP header describes the MUA and the spikes as well
    hdr = lfphdr;
  else hasmua
    % assume that the MUA header describes the spikes as well
    hdr = muahdr;
  end

  % concatenate the lfp/mua/spike channels, they have already been renamed
  hdr.label    = cat(1, lfplab(:), mualab(:), spikelab(:));
  hdr.filename = cat(1, lfpfil(:), muafil(:), spikefil(:));
  hdr.nChans = length(hdr.label);
  % remember the original header details
  hdr.orig    = {};
  hdr.orig{1} = lfphdr;
  hdr.orig{2} = muahdr;
  hdr.orig{3} = spikehdr;

  % return the header
  dat = hdr;
else

  % use the original header details
  lfphdr   = hdr.orig{1};
  muahdr   = hdr.orig{2};
  spikehdr = hdr.orig{3};
  % the spike header does not contain these, but requires them from the LFP or MUA
  spikehdr.FirstTimeStamp     = hdr.FirstTimeStamp;
  spikehdr.TimeStampPerSample = hdr.TimeStampPerSample;

  if ~isempty(lfphdr)
    Nlfp = lfphdr.nChans;
  else
    Nlfp = 0;
  end

  if ~isempty(muahdr)
    Nmua = muahdr.nChans;
  else
    Nmua = 0;
  end

  if ~isempty(spikehdr)
    Nspike = spikehdr.nChans;
  else
    Nspike = 0;
  end

  % determine which files should be read from each respective dataset
  selchan = zeros(hdr.nChans,1);
  selchan(chanindx) = 1;
  sellfp   = find(selchan(1:Nlfp));
  selmua   = find(selchan((Nlfp+1):(Nlfp+Nmua)));
  selspike = find(selchan((Nlfp+Nmua+1):(Nlfp+Nmua+Nspike)));

  if haslfp
    % the header contains the relevant file names
    lfpdat = read_neuralynx_ds([], lfphdr, begsample, endsample, sellfp);
  else
    lfpdat = [];
  end

  if hasmua
    % the header contains the relevant file names
    muadat = read_neuralynx_ds([], muahdr, begsample, endsample, selmua);
  else
    muadat = [];
  end

  if hasspike
    % the header contains the relevant file names
    spikedat = read_neuralynx_ds([], spikehdr, begsample, endsample, selspike);
  else
    spikedat = [];
  end

  % combine all data into a single array
  dat = cat(1, lfpdat, muadat, spikedat);

end


function [ next_joint ] = neighbour_joint_list(  )

next_joint = [2 3 9 10 4 5 8 9 13 13 10 11 14];

end


addpath('..\FW_SPCP\func');
addpath('D:\solvers\PROPACK');
addpath('D:\solvers\cvx');
cvx_setup; warning off;


%DEMOS_PHRIWARE shows some demos of the pHRIWARE software package
%
% Opens a menu to choose some demonstrations, which give step-by-step
% explanations in the Command Window of using certain functionalities
% of pHRIWARE. Based on the demo format of RTB by Peter Corke.
%
% Copyright (C) Bryan Moutrie, 2013-014
% Licensed under the GNU General Public License, see file for statement
%
% This file modifies file(s) from The Robotics Toolbox for MATLAB (RTB)
% by Peter Corke (www.petercorke.com), see file for statement
%
% See also pHRIWARE

% LICENSE STATEMENT:
%
% This file is part of pHRIWARE.
%
% pHRIWARE 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.
%
% pHRIWARE 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 pHRIWARE.  If not, see <http://www.gnu.org/licenses/>.
%
% RTB LIBRARY:
%
% Copyright (C) 1993-2014, by Peter I. Corke
% http://www.petercorke.com
% Released under the GNU Lesser General Public license,
% Modified 24/7/2014 (code adapted from rtbdemo.m, uses runscript.m)

demos = {
    '*HAL basics', 'hal';
    '*Using HAL', 'hal2';
    'Load HAT collision model', 'hat';
    'Create a CollisionModel', 'collisionmodel';
    '*collisions basics', 'collisions';
    '*collisions with dynamic objects', 'collisions2';
    'Exit', '';
    };

while true
    selection = menu('*Requires Robotics Toolbox', demos{:,1});

    if strcmp(demos{selection,1}, 'Exit')
        % quit now
        delete( get(0, 'Children') );
        break;
    else
        % run the appropriate script
        script = demos{selection,2};
        runscript(['demo_', script])
    end
end


function Decis = ErrEval (FuncName, ErrCode);
%
%	Decis = ErrEval (FuncName, ErrCode);
%
%This function displays an error message based on ErrCode and
%returns 1 if it's a lethal error (Err_) , or 0 if it's
%an error or a warning (Wrn_)that does not require aborting a function
%
%
%ErrCode is a string made out of two parts
%  The first part is a 4 letter string containing
%   Err_ or Wrn_  depending on wether it's an error or
%   a warning.
%  The second part is a string that indicates the type of
%   error encountered.
%
%Defined values of ErrCode are :
%  No						%No problem
%  BadInpSize			%One of the input variables has a bad size
%  BadInOut          %Bad combination of input and output parameters
%  FewInp				%Not enough inputs
%  ManyInp				%Too many inputs
%  FewOut				%Not enough outputs
%  ManyOut				%Too many outputs
%  SubFunc				%An error has occurred in a function within the script
%  BadOpt            %Bad Option
%  BadOptCombo       %Bad Option Combination
%  InpFieldMiss      %A field is missing from one of the input structures
%  OptFieldMiss      %A fiels is missing from the Options structures
%  EmptyInp          %Input data is empty
%  FileExist         %File exists
%  FileNotExist      %File does not exist
% To pass a generic message, replace the ErrCode by any ther string
%
% Here's a typical example of the function usage
% if (ErrEval ('LoadSliceData','Err_Image Type Not Supported')), err = 1;	return;end
%
%
%		Ziad Saad Thu Mar 26 11:43:51 CST 1998

if (eq_str(ErrCode,'No')), %in case you send a No only to
	Decis = 0;
	return;
end

if (length(ErrCode) < 5),
	fprintf (2,'\nError in ErrEval, ErrCode %s is ambiguous.\nReturning a 1 decision.\n\n\a',ErrCode);
	Decis = 1;
	return;
end

tmp = ErrCode(1:3);

switch tmp
	case 'Err'
		Decis = 1;
	case 'Wrn'
		Decis = 0;
	otherwise
		warning ('Error in ErrEval, prefix %s from %s is ambiguous.\nReturning a 1 decision.\n\n\a',tmp, ErrCode);
		Decis = 1;
		return;
end

tmp = ErrCode(5:length(ErrCode));

switch tmp
	case 'No'
		Decis = 0;		%even if it was Err_No
		return;
	case 'BadInpSize'
		s = 'Bad size of at least one of the input parameters.';
	case 'BadInOut',
		s = 'Bad combination of input and output parameters.';
	case 'FewInp'
		s = 'Too few inputs.';
	case 'ManyInp'
		s = 'Too many inputs.';
	case 'FewOut'
		s = 'Too few outputs';
	case 'ManyOut'
		s = 'Too many outputs';
	case 'SubFunc'
		s = 'Error (or Warning) in a function within this function (or script).';
	case 'BadOpt'
		s = 'Bad Option';
	case 'InpFieldMiss',
		s = 'A field is missing from one of the input structures.';
	case 'OptFieldMiss',
		s = 'A field is missing from the Options structure.';
	case 'BadOptCombo',
		s = 'Bad Combinations of Options.';
	case 'EmptyInp',
		s = 'One or all of input data is empty.';
	case 'FileExist',
		s = 'File specified exists.';
	case 'FileNotExist',
		s = 'File specified does not exist.';
	otherwise
		s = tmp;
end

%For the error message
if (Decis),
	warning('\a\nError in %s : %s\n\n',FuncName,s);
else
	warning('\nWarning from %s : %s\n\n',FuncName,s);
end

return;


function [sz, maxSize] = h5size(filepath, dataset, dim)
%H5SIZE Returns the size of the specified dataset.
% Usage:
%   [size, maxSize] = h5size(filepath, dataset)
%   [size, maxSize] = h5size(filepath, dataset, dim)

if nargin < 3; dim = []; end

if nargout > 1
    info = h5info(filepath, dataset);

    sz = info.Dataspace.Size;
    maxSize = info.Dataspace.MaxSize;

    if ~isempty(dim)
        sz = sz(dim);
        maxSize = maxSize(dim);
    end
else
    sz = size(h5file(filepath, dataset));
    if ~isempty(dim)
        sz = sz(dim);
    end
end
end


function [percent progressLength] = parfor_progress(N)
%PARFOR_PROGRESS Progress monitor (progress bar) that works with parfor.
%   PARFOR_PROGRESS works by creating a file called parfor_progress.txt in
%   your working directory, and then keeping track of the parfor loop's
%   progress within that file. This workaround is necessary because parfor
%   workers cannot communicate with one another so there is no simple way
%   to know which iterations have finished and which haven't.
%
%   PARFOR_PROGRESS(N) initializes the progress monitor for a set of N
%   upcoming calculations.
%
%   PARFOR_PROGRESS updates the progress inside your parfor loop and
%   displays an updated progress bar.
%
%   PARFOR_PROGRESS(0) deletes parfor_progress.txt and finalizes progress
%   bar.
%
%   To suppress output from any of these functions, just ask for a return
%   variable from the function calls, like PERCENT = PARFOR_PROGRESS which
%   returns the percentage of completion.
%
%   Example:
%
%      N = 100;
%      parfor_progress(N);
%      parfor i=1:N
%         pause(rand); % Replace with real code
%         parfor_progress;
%      end
%      parfor_progress(0);
%
%   See also PARFOR.

% By Jeremy Scheff - jdscheff@gmail.com - http://www.jeremyscheff.com/

error(nargchk(0, 1, nargin, 'struct'));

if nargin < 1
    N = -1;
end

percent = 0;
progressLength = 0;

if usejava('desktop')==0
    return;
end
return;
w = 50; % Width of progress bar
saveDir = 'private';
filePath = [saveDir filesep 'parfor_progress.txt'];
if ~exist(saveDir,'dir');mkdir(saveDir);end

if N > 0
    f = fopen(filePath, 'w');
    if f<0
        error('Do you have write permissions for %s?', pwd);
    end
    fprintf(f, '%d\n', N); % Save N at the top of progress.txt
    fclose(f);

    if nargout == 0
        % disp(['  0%[>', repmat(' ', 1, w), ']']);
        dispstat(['  0%[>', repmat(' ', 1, w), ']']);
    end
elseif N == 0
    delete(filePath);
    percent = 100;

    if nargout == 0
        % disp([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']);
        dispstat([repmat(char(8), 1, (w+9)), char(10), '100%[', repmat('=', 1, w+1), ']']);
    end
else
    % if ~exist(filePath, 'file')
    %     error([filePath ' not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize ' filePath '.']);
    % end
    return;
    try
        f = fopen(filePath, 'A');
    catch
        error([filePath ' not found. Run PARFOR_PROGRESS(N) before PARFOR_PROGRESS to initialize ' filePath '.']);
    end
    fprintf(f, '1\n');
    fclose(f);

    f = fopen(filePath, 'r');
    progress = fscanf(f, '%d');
    progressLength = length(progress(2:end));
    fclose(f);
    try
        percent = (length(progress)-1)/progress(1)*100;
    catch
    end

    if nargout == 0
        perc = sprintf('%3.0f%%', percent); % 4 characters wide, percentage
        % reverseStr = repmat(sprintf('\b'), 1, length(perc)-1);
        % fprintf([reverseStr, perc]);drawnow;
        outputStr = [repmat(char(8), 1, (w+9)), char(10), perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']'];
        % disp(outputStr);
        dispstat(outputStr);
        % fprintf([repmat('\b', 1, (w+9)), '\n', perc, '[', repmat('=', 1, round(percent*w/100)), '>', repmat(' ', 1, w - round(percent*w/100)), ']']);
    end
end


function [success] = viewAcceptedRejectedCellExtraction(inputImages,inputSignals,valid,inputMovie,varargin)
	% Plots cell image, peak transients, and image from activity in movie for accepted and rejected cells, useful for publications.
	% Biafra Ahanonu
	% started: 2014.01.03 [19:13:01]
	% inputs
		%
	% outputs
		%

	% changelog
		% 2021.08.08 [19:30:20] - Updated to handle CIAtah v4.0 switch to all functions inside ciapkg package.
	% TODO
		%

	import ciapkg.api.* % import CIAtah functions in ciapkg package API.

	%========================
	% Int: number of cells to show for EACH accepted and rejected
	options.nCellsShow = 3;
	% Int vector: vector of cell indexes if want to analyze a specific subset
	options.showSpecificCells = [];
	% if loading movie inside function, provide framelist
	options.frameList = [];
	% name in HDF5 file where data is stored
	options.inputDatasetName = '/1';
	% pre-compute signal peaks
	options.signalPeaks = [];
	options.signalPeaksArray = [];
	% Int: 1/2 length in pixels of crop square
	options.cropSizeLength = 20;
	% Float: Value between 0 and 1 of max to crop image to get outline
	options.thresholdOutline = 0.1;
	% ROI for peak signal plotting
	options.peakROI = [-20:20];
	% number of standard deviations above the threshold to count as spike
	options.numStdsForThresh = 3.0;
	% Binary: 1 = normalize the cell images
	options.normalizeCellImages = 1;
	% get options
	options = getOptions(options,varargin);
	% display(options)
	% unpack options into current workspace
	% fn=fieldnames(options);
	% for i=1:length(fn)
	% 	eval([fn{i} '=options.' fn{i} ';']);
	% end
	%========================

	try
		success = 0;

		% make accepted/rejected vector a logical
		valid = logical(valid);

		% check whether movie is a string or not, load
		inputMovieClass = class(inputMovie);
		if strcmp(inputMovieClass,'char')
			% inputMovie = loadMovieList(inputMovie,'inputDatasetName',options.inputDatasetName,'frameList',options.frameList);
			% [pathstr,name,ext] = fileparts(inputFilePath);
			% options.newFilename = [pathstr '\concat_' name '.h5'];
		end

		% calculate grid size based
		nPlotsPerCell = 3;
		% [xPlot yPlot] = getSubplotDimensions(nPairs);
		xPlot = options.nCellsShow;
		yPlot = nPlotsPerCell*2;

		% get list of cells to show
		if isempty(options.showSpecificCells)
			% get list of cell's SNR
			[signalSnr ~] = computeSignalSnr(inputSignals,'testpeaks',options.signalPeaks,'testpeaksArray',options.signalPeaksArray,'numStdsForThresh',options.numStdsForThresh);
			signalSnr(isnan(signalSnr)) = nanmean(signalSnr(:));
			[signalSnr newIdx] = sort(signalSnr,'descend');

			% get top SNR accepted
			topSnrAccepted = newIdx(valid==1);
			topSnrAccepted = topSnrAccepted(1:options.nCellsShow);

			% get bottom SNR rejected
			bottomSnrRejected = newIdx(valid==0);
			bottomSnrRejected = bottomSnrRejected((end-options.nCellsShow+1):end);
			% bottomSnrRejected = bottomSnrRejected(randperm(length(bottomSnrRejected),options.nCellsShow));

			cellsToShow = cat(2,topSnrAccepted(:),bottomSnrRejected(:))';
			cellsToShow = cellsToShow(:);
		else
			cellsToShow = options.showSpecificCells;
		end

		% calculate signal peaks
		if isempty(options.signalPeaks)
			[signalPeaks, signalPeaksArray] = computeSignalPeaks(inputSignals(cellsToShow,:),'makePlots', 0,'makeSummaryPlots',0,'waitbarOn',1);
		else
			signalPeaks = options.signalPeaks;
			signalPeaksArray = options.signalPeaksArray;
		end

		% get the peak statistics
		[peakOutputStat] = computePeakStatistics(inputSignals(cellsToShow,:),'waitbarOn',1,'testpeaks',signalPeaks,'testpeaksArray',signalPeaksArray,'spikeROI',options.peakROI);

		figure;

		% loop and plot each cell
		tracesHere = inputSignals(cellsToShow,:);
		minValTraces = nanmin(tracesHere(:));
		maxValTraces = nanmax(tracesHere(:));
		for cellNo = 1:length(cellsToShow)
			try
				cellIdx = cellsToShow(cellNo);

				thisTrace = inputSignals(cellIdx,:);

				% get peaks for this cell
				% peakIdxs = signalPeaksArray{cellIdx};
				peakIdxs = signalPeaksArray{cellNo};

				% get cropped view of the algorithm image
				inputImageAddObjCut = getObjCutMovie(inputImages,inputImages(:,:,cellIdx),'createMontage',0,'extendedCrosshairs',0,'crossHairsOn',0,'outlines',0,'waitbarOn',0,'cropSize',options.cropSizeLength,'addPadding',1);
				inputImageAddObjCut = inputImageAddObjCut{1};
				inputImageAddObjCut = inputImageAddObjCut(:,:,cellIdx);

				% get cropped view from the movie
				if ischar(inputMovie)
					objCutMovie = getObjCutMovie(inputMovie,inputImages(:,:,cellIdx),'createMontage',0,'extendedCrosshairs',0,'outlines',0,'waitbarOn',0,'cropSize',options.cropSizeLength,'crossHairsOn',0,'addPadding',1,'frameList',peakIdxs);
				else
					objCutMovie = getObjCutMovie(inputMovie(:,:,peakIdxs),inputImages(:,:,cellIdx),'createMontage',0,'extendedCrosshairs',0,'outlines',0,'waitbarOn',0,'cropSize',options.cropSizeLength,'crossHairsOn',0,'addPadding',1);
				end

				objCutMovie = cat(3,objCutMovie{:});
				movieFrame = nanmean(objCutMovie,3);

				% create RGB with outline of cell
				[thresholdedImages boundaryIndices] = thresholdImages(inputImageAddObjCut,'binary',1,'getBoundaryIndex',1,'threshold',options.thresholdOutline);
				E = normalizeVector(double(movieFrame),'normRange','zeroToOne');
				tmpImg = zeros([size(E)]);
				tmpImg([boundaryIndices{:}]) = 1;
				movieRGB = [];
				movieRGB(:,:,1) = E+tmpImg;
				movieRGB(:,:,2) = E;
				movieRGB(:,:,3) = E;

				subplot(xPlot,yPlot,((cellNo-1)*nPlotsPerCell+1))
					if options.normalizeCellImages==1
						inputImageAddObjCut = normalizeVector(inputImageAddObjCut,'normRange','zeroToOne');
						imagesc(inputImageAddObjCut)
						caxis([0 1]);
					else
						imagesc(inputImageAddObjCut)
					end
					box off;axis off;
					axis equal tight
					if cellNo==length(cellsToShow)
						colorbar('Location','southoutside');
					end

				subplot(xPlot,yPlot,((cellNo-1)*nPlotsPerCell+2))
					imagesc(movieRGB)
					box off;axis off;
					axis equal tight
					% colorbar('Location','southoutside');

					imgRowY = size(movieRGB,1);
					imgColX = size(movieRGB,2);
					MICRON_PER_PIXEL = 2.37;
					options.scaleBarLengthMicron = 20;
					scaleBarLengthPx = options.scaleBarLengthMicron/MICRON_PER_PIXEL;
					% [imgColX-scaleBarLengthPx-round(imgColX*0.05) imgRowY-round(imgRowY*0.05) scaleBarLengthPx 5]
					rectangle('Position',[imgColX-scaleBarLengthPx-imgColX*0.05 imgRowY-imgRowY*0.05 scaleBarLengthPx 5],'FaceColor',[1 1 1],'EdgeColor','none')

				subplot(xPlot,yPlot,((cellNo-1)*nPlotsPerCell+3))

					% spikeCenterTrace = peakOutputStat.spikeCenterTrace{cellIdx};
					% avgSpikeTrace = peakOutputStat.avgSpikeTrace(cellIdx,:);
					spikeCenterTrace = peakOutputStat.spikeCenterTrace{cellNo};
					avgSpikeTrace = peakOutputStat.avgSpikeTrace(cellNo,:);
					% spikeCenterTrace
					% avgSpikeTrace
					peakROI = options.peakROI;
					peakSignalAmplitude = thisTrace(peakIdxs(:));
					[peakSignalAmplitude peakIdx] = sort(spikeCenterTrace(:,round(end/2)+1),'descend');
					spikeCenterTrace = spikeCenterTrace(peakIdx,:);
					if size(spikeCenterTrace,1)>20
						spikeCenterTrace = spikeCenterTrace(1:20,:);
					end

					plot(repmat(peakROI, [size(spikeCenterTrace,1) 1])', spikeCenterTrace','Color',[4 4 4]/8)
					hold on;
					plot(peakROI, avgSpikeTrace,'r', 'LineWidth',3);box off;
					ylim([minValTraces maxValTraces]);
					% plot(peakROI, nanmean(spikeCenterTrace),'Color',[1 0 0 1.0], 'LineWidth',2);box off;
					% add in zero line
					% xval = 0;
					% x=[xval,xval];
					% y=[minValTraces maxValTraces];
					% plot(x,y,'r'); box off;
			catch err
				success = 0;
				display(repmat('@',1,7))
				disp(getReport(err,'extended','hyperlinks','on'));
				display(repmat('@',1,7))
			end
		end

		success = 1;
	catch err
		success = 0;
		display(repmat('@',1,7))
		disp(getReport(err,'extended','hyperlinks','on'));
		display(repmat('@',1,7))
	end
end


function h = splitROIleftright(h)
h.dat.cl.iscell = [h.dat.stat.iscell];

% h.dat.cl.iscell = double(h.dat.cl.iscell);

% overwrite manual selections
% h.dat.cl.iscell(h.dat.cl.manual>1e-3) = 1;
% h.dat.cl.iscell(h.dat.cl.manual<-1e-3) = 0;
%%
IScell = zeros(h.dat.cl.Ly, h.dat.cl.Lx);
ix = h.dat.res.iclust>0;
IScell(ix) = h.dat.cl.iscell(h.dat.res.iclust(ix));
h.dat.cl.k1 = reshape(IScell, h.dat.cl.Ly, h.dat.cl.Lx);


function lit = haslight(axish)
%HASLIGHT Check if axis handle has a light attached
%
%Syntax
% lit = haslight(axish);
%
%Description
% LIT = HASLIGHT(AXISH) sets LIT to true if the axis specified by axis
% handle AXISH has a child of type 'light', and sets LIT to false otherwise.
%
%Examples
% > lit=haslight(gca)
% lit =
%      1

% Copyright 2004-2005 Paul Leopardi for the University of New South Wales.
% $Revision 1.10 $ $Date 2005-06-01 $
% Documentation files renamed
% $Revision 1.00 $ $Date 2005-02-12 $
%
% For licensing, see COPYING.
% For references, see AUTHORS.
% For revision history, see CHANGELOG.

lit = false;
ch = get(axish,'Children');

for k = 1:length(ch)
    type = get(ch(k),'Type');
    if strcmp(type,'light')
        lit = true;
        return;
    end
end
%
%end function


function varargout = optionpricegui2(varargin)
% OPTIONPRICEGUI2 M-file for optionpricegui2.fig
%      OPTIONPRICEGUI2, by itself, creates a new OPTIONPRICEGUI2 or raises the existing
%      singleton*.
%
%      H = OPTIONPRICEGUI2 returns the handle to a new OPTIONPRICEGUI2 or the handle to
%      the existing singleton*.
%
%      OPTIONPRICEGUI2('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in OPTIONPRICEGUI2.M with the given input arguments.
%
%      OPTIONPRICEGUI2('Property','Value',...) creates a new OPTIONPRICEGUI2 or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before optionpricegui2_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to optionpricegui2_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help optionpricegui2

% Last Modified by GUIDE v2.5 14-Aug-2008 14:18:46

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @optionpricegui2_OpeningFcn, ...
    'gui_OutputFcn',  @optionpricegui2_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
end
% End initialization code - DO NOT EDIT

% --- Executes just before optionpricegui2 is made visible.
function optionpricegui2_OpeningFcn(hObject, eventdata, handles, varargin)%#ok
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to optionpricegui2 (see VARARGIN)

% Choose default command line output for optionpricegui2
handles.output = hObject;

set(handles.editStart, 'String', datestr(today, 2))
set(handles.editEnd, 'String', datestr(today + 91, 2))

handles = runSimulation(handles);

% This is an awkward place to put the rotate3d command.  If you place it in
% the runSimulation function, however, it tends to toggle rotate3d on and
% off after each simulation.  Here, it gets set to "on" once and stays that
% way.
rotate3d(handles.surfAxes)

% Update handles structure
guidata(hObject, handles);
end

% UIWAIT makes optionpricegui2 wait for user response (see UIRESUME)
% uiwait(handles.mainFigure);

% --- Outputs from this function are returned to the command line.
function varargout = optionpricegui2_OutputFcn(hObject, eventdata, handles) %#ok
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;
end

function editSpot_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editSpot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editSpot as text
%        str2double(get(hObject,'String')) returns contents of editSpot as a double
end

% --- Executes during object creation, after setting all properties.
function editSpot_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editSpot (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editStrike_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editStrike (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editStrike as text
%        str2double(get(hObject,'String')) returns contents of editStrike as a double
end

% --- Executes during object creation, after setting all properties.
function editStrike_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editStrike (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editRFR_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editRFR (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editRFR as text
%        str2double(get(hObject,'String')) returns contents of editRFR as a double
end

% --- Executes during object creation, after setting all properties.
function editRFR_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editRFR (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editStart_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editStart (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editStart as text
%        str2double(get(hObject,'String')) returns contents of editStart as a double
end

% --- Executes during object creation, after setting all properties.
function editStart_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editStart (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editEnd_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editEnd (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editEnd as text
%        str2double(get(hObject,'String')) returns contents of editEnd as a double
end

% --- Executes during object creation, after setting all properties.
function editEnd_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editEnd (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editVol_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editVol (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editVol as text
%        str2double(get(hObject,'String')) returns contents of editVol as a double
end

% --- Executes during object creation, after setting all properties.
function editVol_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editVol (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editYield_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editYield (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editYield as text
%        str2double(get(hObject,'String')) returns contents of editYield as a double
end

% --- Executes during object creation, after setting all properties.
function editYield_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editYield (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

end

function editIter_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editIter (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editIter as text
%        str2double(get(hObject,'String')) returns contents of editIter as a double
end

% --- Executes during object creation, after setting all properties.
function editIter_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editIter (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end

end

function editValue_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editValue (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editValue as text
%        str2double(get(hObject,'String')) returns contents of editValue as a double
end

% --- Executes during object creation, after setting all properties.
function editValue_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editValue (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

% --- Executes on selection change in popupmenu1.
function popupmenu1_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to popupmenu1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: contents = get(hObject,'String') returns popupmenu1 contents as cell array
%        contents{get(hObject,'Value')} returns selected item from popupmenu1

% Some options only require a single strike price; others, two.  The
% butterfly option requires one strike price and a spread.
contents = get(hObject,'String');
switch contents{get(hObject,'Value')}
    case {'Call' 'Put' 'Straddle'}
        handles = oneStrike(handles);
    case {'Strangle' 'Bull Spread' 'Bear Spread'}
        handles = twoStrikes(handles);
    case {'Butterfly'}
        handles = butterfly(handles);
end
guidata(hObject, handles);
end
% --- Executes during object creation, after setting all properties.
function popupmenu1_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to popupmenu1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: popupmenu controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editStrike1_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editStrike1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editStrike1 as text
%        str2double(get(hObject,'String')) returns contents of editStrike1 as a double
end

% --- Executes during object creation, after setting all properties.
function editStrike1_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editStrike1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editStrike2_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editStrike2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editStrike2 as text
%        str2double(get(hObject,'String')) returns contents of editStrike2 as a double
end

% --- Executes during object creation, after setting all properties.
function editStrike2_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editStrike2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

function editSpread_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to editSpread (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of editSpread as text
%        str2double(get(hObject,'String')) returns contents of editSpread as a double
end

% --- Executes during object creation, after setting all properties.
function editSpread_CreateFcn(hObject, eventdata, handles)%#ok
% hObject    handle to editSpread (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white');
end
end

% --- Executes on button press in buttonRun.
function buttonRun_Callback(hObject, eventdata, handles)%#ok
% hObject    handle to buttonRun (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
handles = runSimulation(handles);
guidata(hObject, handles);
end

% --- Helper functions follow ---
% --- oneStrike, twoStrikes: toggle between displaying one and two strike
% prices in the UI panel ---
function handles = oneStrike(handles)
set(handles.text3, 'String', 'Strike Price')
set(handles.editStrike, 'Visible', 'on')
set(handles.editStrike1, 'Visible', 'off')
set(handles.editStrike2, 'Visible', 'off')
set(handles.editSpread, 'Visible', 'off')
set(handles.text11, 'Visible', 'off')
end

function handles = twoStrikes(handles)
set(handles.text3, 'String', 'Strike Prices')
set(handles.editStrike, 'Visible', 'off')
set(handles.editStrike1, 'Visible', 'on')
set(handles.editStrike2, 'Visible', 'on')
set(handles.editSpread, 'Visible', 'off')
set(handles.text11, 'Visible', 'off')
end

function handles = butterfly(handles)
set(handles.text3, 'String', 'Strike Price')
set(handles.editStrike, 'Visible', 'on')
set(handles.editStrike1, 'Visible', 'off')
set(handles.editStrike2, 'Visible', 'off')
set(handles.editSpread, 'Visible', 'on')
set(handles.text11, 'Visible', 'on')
end

%--- runSimulation: the main control program for the code ---
function handles = runSimulation(handles)
% This function has four steps:
% Step 1: Collect inputs and find option value
% Step 2: Plot the option value surface
% Step 3: Run a Monte Carlo simulation
% Step 4: Plot the Monte Carlo simulation
%
% In addition, there are two nested functions that allow you to incorporate
% a WindowButtonMotionFcn and a WindowButtonDownFcn on the Monte Carlo
% Paths axes.

% Step 1: Collect inputs and find option value
try
    spot = str2double(get(handles.editSpot, 'String'));
    rate = str2double(get(handles.editRFR, 'String'));
    vol  = str2double(get(handles.editVol, 'String'));
    yield= str2double(get(handles.editYield, 'String'));
    type = get(handles.popupmenu1,'String');
    type = type{get(handles.popupmenu1,'Value')};

    % No harm in getting Strike2 and Spread, even if they aren't used.
    strike2 = str2double(get(handles.editStrike2, 'String'));
    spread  = str2double(get(handles.editSpread, 'String'));

    startDate = get(handles.editStart, 'String');
    endDate = get(handles.editEnd, 'String');
    % I only include this extra TRY/CATCH loop in order to provide a better
    % error message if the invalid dates are applied: YEARFRAC itself will
    % do all of the appropriate error checking.
    try
        time = yearfrac(startDate, endDate);
    catch %#ok<CTCH>
        error('optionPriceGui:InvalidDates', ...
            'Dates must be in a valid format')
    end

    iter = str2double(get(handles.editIter, 'String'));
    if int32(iter) ~= iter || iter <= 0
        error('optionPriceGui:InvalidIterations',...
            'Iteration count must be a positive integer.')
    end

    switch type
        case {'Call' 'Put' 'Straddle' 'Butterfly'}
            strike = str2double(get(handles.editStrike, 'String'));
        case {'Strangle' 'Bull Spread' 'Bear Spread'}
            strike = str2double(get(handles.editStrike1, 'String'));
    end

    value = optPriceVal(type, spot, strike, rate, time, vol, yield, strike2, spread);
    set(handles.editValue, 'String', num2str(value,'%4.3f'))

catch ME
    errordlg(ME.message, 'Invalid Input', 'modal')
    set(handles.editValue, 'String', 'error')
    return
end

% Step 2: Now that we have all the data we need, let's plot the option
% value surface.

% A 51x51 surface plot should look nice and not be too taxing on the
% graphics processor, but you can adjust that here.
xPoints = 51;
yPoints = 51;

T = linspace(0, time, xPoints);

% The spot price axis span is a little tricky to determine in advance.  We
% will go with +/- 10% from the strike price in the case of a put, call, or
% straddle option, +/- 50% of the strike prices' span in the case of a
% strangle, bull spread, or bear spread option, and +/- 40% of the spread
% from a butterfly option.  Of course, we will truncate if these go below a
% price of 0.
switch type
    case {'Call' 'Put' 'Straddle'}
        lPrice = 0.9 * strike;
        uPrice = 1.1 * strike;
    case {'Strangle' 'Bull Spread' 'Bear Spread'}
        span = abs(strike2 - strike);
        if strike2 > strike
            lPrice = strike - 0.5 * span;
            uPrice = strike2+ 0.5 * span;
        else
            lPrice = strike2- 0.5 * span;
            uPrice = strike + 0.5 * span;
        end
    case 'Butterfly'
        lPrice = (1 - 1.4 * spread) * strike;
        uPrice = (1 + 1.4 * spread) * strike;
end
lPrice(lPrice < 0) = 0;
S = linspace(lPrice, uPrice, yPoints);
[S,T] = meshgrid(S,T);

% Get the option value for the surface
V = optPriceVal(type, S, strike, rate, T, vol, yield, strike2, spread);

% Plot the 3D surface of changing option value with spot price and time
surf(handles.surfAxes, S, T, V);
box(handles.surfAxes, 'on')
shading(handles.surfAxes, 'interp')
axis(handles.surfAxes, 'tight')
xlabel(handles.surfAxes, 'Underlying ($)','fontweight','bold')
ylabel(handles.surfAxes, 'Time to Expiry (Years)','fontweight','bold')
zlabel(handles.surfAxes, 'Option Value ($)','fontweight','bold')

% Step 3: Let's now run a Monte Carlo simulation
% We will run a single step of the simulation per day-- this is fairly
% coarse-grained, but it gets the message across.

% Assume geometric Brownian motion and apply Ito's lemma to simplify the
% Monte Carlo equation. (see: eqn T6.9 of Kevin Dowd's _An Introduction to
% Market Risk Measurement_, p. 224)
numDays = daysact(startDate, endDate);
TT = sqrt(time/numDays) * ones(numDays, iter);
rNum = randn(numDays, iter);

BT = TT.*rNum;
% And we pad this by an initial row of zeros to handle the initial point at
% day 0.
TT = [zeros(1, iter); TT];
BT = [zeros(1, iter); BT];

ST = spot * exp(cumsum((rate - 0.5 * vol^2) * TT + vol * BT));

% Step 4: Plot the Monte Carlo simulation
% Create line/bar object for histogram of monte-carlo price distributions
set(handles.axesHist,'yaxislocation','right','xaxislocation','top',...
    'xtick',[],'xlimmode','auto')

% Only pick at most 1000 lines from the Monte-Carlo simulation for plotting
% purposes; all data is still used for the underlying math, however.
if size(ST,2)>1000
    ind = randperm(size(ST,2))';
    STplot = ST(:,ind(1:1000));
else
    STplot = ST;
end

% Plot the monte-carlo underlying price paths
handles.pricePaths = plot(handles.axesMonte, (0:numDays), STplot,...
    'color', [.7,.7,.7]);

% Create the tracking line.  Rather, create an object to hold the tracking
% line as it is generated by the windowbuttonmotion function.
handles.trackLine = line('XData', NaN, 'YData', NaN,...
    'Parent', handles.axesMonte, 'erasemode', 'xor', 'Color', 'b', 'LineWidth', 2);
handles.trackText = text('parent', handles.axesMonte, 'erasemode','xor','edgecolor','k',...
    'background',[1,1,.87],'verticalalign','bot','fontsize',14, 'visible', 'off');
% handles.pdfLine = line('XData', NaN, 'YData', NaN,...
%     'Parent', handles.axesHist, 'erasemode', 'xor', 'Color', 'r');

% Plot the mean of the underlying monte-carlo prices paths.
STmean = mean(ST,2);
handles.meanLine = line('XData', (0:numDays), 'YData', STmean, ...
    'Parent', handles.axesMonte, 'Marker', '.' ,'MarkerSize', 10, 'Color', 'r');

% Annotate the monte-carlo plots
xlabel(handles.axesMonte, 'Time (Days)','fontweight','bold')
ylabel(handles.axesMonte, 'Underlying ($)','fontweight','bold')
axis(handles.axesMonte, 'tight')
grid(handles.axesMonte, 'on')
legend(handles.axesMonte, ...
    {'$$S_{t+dt} = S_te^{(r-\frac{{\sigma^2}}{2})dt+\sigma\epsilon\sqrt{dt}}$$'}, ...
    'fontsize',14,'interpreter','latex', 'Location', 'NorthWest');

set(handles.mainFigure,'windowbuttonmotionfcn',@wbm)

% Nested function: WBM for the window button motion function
    function wbm(src, event)
        drawnow
        ylimit = get(handles.axesMonte, 'ylim');
        xlimit = get(handles.axesMonte, 'xlim');
        pos =  get(handles.axesMonte, 'currentpoint');
        x = pos(1,1);
        y = pos(1,2);
        % check if the mouse is out of bounds of the axes
        if x < xlimit(1) || x > xlimit(2) || y < ylimit(1) || y>ylimit(2)
            return
        end

        % create a histogram of the underlying price paths at the current point
        binsC = linspace(ylimit(1), ylimit(2)+eps(ylimit(2)), 21);
        n = histc(ST(round(x)+1, :), binsC);
        n = n./max(n);
        barh(handles.axesHist, binsC, n, 'histc')
        set(handles.axesHist, 'ylim', ylimit)
        set(handles.axesHist,'YTick',[])
        set(handles.axesHist,'XTick',[])
        set(handles.trackLine,'xdata',[x,x],'ydata',ylim)

        % Create a maximum likelihood estimate of the histogram, assuming a
        % lognormal distribution.
        params = lognfit(ST(round(x)+1, :));
        pdfPts = ylimit(1) : ylimit(2);
        pdfVals = lognpdf(pdfPts, params(1), params(2));
        line('Parent', handles.axesHist, ...
            'XData', pdfVals./max(pdfVals), 'YData', pdfPts,...
            'erasemode', 'xor', 'color', 'b')

        % get the current datestr and mean value of the mouse position
        currentDate = datestr(round(x + datenum(startDate)), 2);
        currentMean = STmean(round(x)+1);

        str = sprintf(['Date: ' currentDate '\nAvg Price: $%.2f'], currentMean);
        set(handles.trackText,...
            'position',[x + diff(xlimit)*.02, y + diff(ylimit)*.02, 0],...
            'string', str, 'visible', 'on')

    end
end


function varargout = subsref(S2G,s)
%overloads subsref

switch s(1).type
  case '()'

    v = vector3d(S2G);
    [varargout{1:nargout}] = subsref(v,s);

  case '.'

    [varargout{1:nargout}] = builtin('subsref',S2G,s);

end
end


% The COBRAToolbox: testTransformModel2KEGG.m
%
% Purpose:
%     - test the transformModel2KEGG function
%
% Authors:
%     - Jacek Wachowiak
global CBTDIR
% save the current path
currentDir = pwd;

% initialize the test
fileDir = fileparts(which('testTransformModel2KEGG'));
cd(fileDir);

% test variables
model = getDistributedModel('ecoli_core_model.mat');
Dictionary = {'0', '1'; '2', '3'};
ref_KEGGID = cell(72, 1);

% function outputs
modelKEGG = transformModel2KEGG(model, Dictionary);
try
    modelKEGG_2 = transformModel2KEGG(model);
catch ME
    assert(length(ME.message) > 0);
end

% test
assert(isequal(modelKEGG.metsAbr, model.mets));
assert(isequal(modelKEGG.metKEGGID, ref_KEGGID));

% change to old directory
cd(currentDir);


% --------------------------------------------------------
% MDP Tracking
% Copyright (c) 2015 CVGL Stanford
% Licensed under The MIT License [see LICENSE for details]
% Written by Yu Xiang
% --------------------------------------------------------
%
% initialization for testing
function tracker = MDP_initialize_test(tracker, image_width, image_height, dres_det, is_show)

% normalization factor for features
tracker.image_width = image_width;
tracker.image_height = image_height;
tracker.max_width = max(dres_det.w);
tracker.max_height = max(dres_det.h);
tracker.max_score = max(dres_det.r);

tracker.streak_tracked = 0;
tracker.is_show = is_show;


% Concatenates a cell array of strings.
%
% Input arguments:
% adjoiner:
%    string separating each neighboring element
% strings:
%    a cell array of strings to join
%
% See also: strsplit2, cell2mat

% Copyright 2008-2009 Levente Hunyadi
function string = strjoin2(adjoiner, strings)

validateattributes(adjoiner, {'char'}, {'vector'});
validateattributes(strings, {'cell'}, {'vector'});
assert(iscellstr(strings), ...
    'strjoin2:ArgumentTypeMismatch', ...
    'The elements to join should be stored in a cell vector of strings (character arrays).');
if isempty(strings)
    string = '';
    return;
end

% arrange substrings into cell array of strings
concat = cell(1, 2 * numel(strings) - 1);  % must be row vector
j = 1;
concat{j} = strings{1};
for i = 2 : length(strings)
    j = j + 1;
    concat{j} = adjoiner;
    j = j + 1;
    concat{j} = strings{i};
end

% concatenate substrings preserving spaces
string = cell2mat(concat);


function lmk = newLmk(Lmk)

% NEWLMK  Get a new landmark.
%   NEWLMK(Lmk) returns the index in structure array Lmk() of the first
%   non-used landmark.
%
%   See also NEWRANGE, INITNEWLMKS.

%   Copyright 2009-2009 Joan sola @ LAAS-CNRS.

lmk = find(~[Lmk.used],1,'first');

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

%   # START GPL LICENSE

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

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

%   # END GPL LICENSE


function [varargout] = isfile(varargin)

%ISFILE Determine if the input points to a file
%   TF = ISFILE(INPUT) returns true if INPUT points to a file and false otherwise.
%
% This is a compatibility function that should only be added to the path on
% MATLAB versions prior to R2017b. Note that currently this function only allows
% for a single string in the input, as opposed to the isfile function from MATLAB,
% which allows for multiple inputs

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% see https://github.com/fieldtrip/fieldtrip/issues/899

alternatives = which(mfilename, '-all');
if ~iscell(alternatives)
  % this is needed for octave, see https://github.com/fieldtrip/fieldtrip/pull/1171
  alternatives = {alternatives};
end

keep = true(size(alternatives));
for i=1:numel(alternatives)
  keep(i) = keep(i) && ~any(alternatives{i}=='@');  % exclude methods from classes
  keep(i) = keep(i) && alternatives{i}(end)~='p';   % exclude precompiled files
end
alternatives = alternatives(keep);

if exist(mfilename, 'builtin') || any(strncmp(alternatives, matlabroot, length(matlabroot)) & cellfun(@isempty, strfind(alternatives, fullfile('private', mfilename))))
  % remove this directory from the path
  p = fileparts(mfilename('fullpath'));
  sw = warning('off','backtrace');
  warning('Removing "%s" from your path.\nSee http://www.fieldtriptoolbox.org/faq/should_i_add_fieldtrip_with_all_subdirectories_to_my_matlab_path/', p);
  warning(sw);
  rmpath(p);
  % call the original MATLAB function
  if exist(mfilename, 'builtin')
    [varargout{1:nargout}] = builtin(mfilename, varargin{:});
  else
    [varargout{1:nargout}] = feval(mfilename, varargin{:});
  end
  return
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% this is where the actual replacement code starts
% function tf = isfile(input)

% deal with the input arguments
if nargin==1
  [input] = deal(varargin{1:1});
else
  error('incorrect number of input arguments')
end

tf = ismember(exist(input),[2 3 4 5 6]);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% deal with the output arguments

varargout = {tf};


function [UV,F, res, edge_norms] = ...
  create_irregular_grid_with_min_angle( ...
    xRes, yRes, n, xWrap, yWrap, min_angle, ...
    no_interior, dart_threshold)
  % Deprecated.
  %
  % See also: create_irregular_grid

  warning('Deprecated. Call create_irregular_grid directly');
  [UV,F, res, edge_norms] = create_irregular_grid( ...
    xRes,yRes, ...
    'NumDarts',n,'xWrap',xWrap,'yWrap',yWrap, ...
    'MinAngle',min_angle,'NoInterior',no_interior, ...
    'DartThreshold',dart_threshold);
end


function mAP = rfcn_test_vid_multiframe(conf, imdb, roidb, varargin)
% Video-level testing using final D&T 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]
% --------------------------------------------------------

%% inputs
    ip = inputParser;
    ip.addRequired('conf',                              @isstruct);
    ip.addRequired('imdb',                              @isstruct);
    ip.addRequired('roidb',                             @isstruct);
    ip.addParamValue('net_def_file',    '', 			@isstr);
    ip.addParamValue('net_file',        '', 			@isstr);
    ip.addParamValue('cache_name',      '', 			@isstr);
    ip.addParamValue('suffix',          '',             @isstr);
    ip.addParamValue('ignore_cache',    false,          @islogical);
    ip.addParamValue('ab_fetch_path',    '',          @isstr);
    ip.addParamValue('visualize_every',   Inf,          @isscalar);
    ip.addParamValue('test_classes',    [] 			);
    ip.addParamValue('chain_boxes_forward',    false, 			@islogical);
    ip.addParamValue('time_stride',   1,          @isscalar);
    ip.addParamValue('thresh_tracks',   0.1,          @isscalar);

    ip.parse(conf, imdb, roidb, varargin{:});
    opts = ip.Results;
    visualize = false;

%%  set cache dir
    cache_dir = fullfile(conf.root_path, 'output', 'rfcn_cachedir', opts.cache_name, imdb.name);
    mkdir_if_missing(cache_dir);

%%  init log
    timestamp = datestr(datevec(now()), 'yyyymmdd_HHMMSS');
    mkdir_if_missing(fullfile(cache_dir, 'log'));
    log_file = fullfile(cache_dir, 'log', ['test_', timestamp, '.txt']);
    diary(log_file);

    num_images = length(imdb.image_ids);
    num_classes = imdb.num_classes;

    try
      aboxes = cell(num_classes, 1);
      if opts.ignore_cache
          throw('');
      end
      for i = 1:num_classes
        load(fullfile(cache_dir, [imdb.classes{i} '_boxes_' imdb.name opts.suffix]));
        aboxes{i} = boxes;
      end
         load(fullfile(cache_dir, ['tracks_' imdb.name opts.suffix]));
    catch
%%      testing
        % init caffe net
        caffe_log_file_base = fullfile(cache_dir, 'caffe_log');
        caffe.init_log(caffe_log_file_base);
        caffe_net = caffe.Net(opts.net_def_file, 'test');
        caffe_net.copy_from(opts.net_file);

        % set random seed
        prev_rng = seed_rand(conf.rng_seed);
        caffe.set_random_seed(conf.rng_seed);

        % set gpu/cpu
        if conf.use_gpu
            caffe.set_mode_gpu();
        else
            caffe.set_mode_cpu();
        end

        % determine the maximum number of rois in testing
        max_rois_num_in_gpu = 10000;

        disp('opts:');
        disp(opts);
        disp('conf:');
        disp(conf);

        %heuristic: keep an average of 160 detections per class per images prior to NMS
        max_per_set = 160 * num_images;
        % heuristic: keep at most 400 detection per class per image prior to NMS
        max_per_image = 400;
        % detection thresold for each class (this is adaptively set based on the max_per_set constraint)
        thresh = -inf * ones(num_classes, 1);
        % top_scores will hold one minheap of scores per class (used to enforce the max_per_set constraint)
        top_scores = cell(num_classes, 1);
        % all detections are collected into:
        %    all_boxes[cls][image] = N x 5 array of detections in
        %    (x1, y1, x2, y2, score)
        aboxes = cell(num_classes, 1);
        box_inds = cell(num_classes, 1);
        aboxes_track = cell(num_classes, 1);

        for i = 1:num_classes
            aboxes{i} = cell(length(imdb.image_ids), 1);
            box_inds{i} = cell(length(imdb.image_ids), 1);
        end
        ascores_track = aboxes{1};;
        aboxes_track = cell(length(imdb.image_ids), conf.nFramesPerVid);
        aboxes_fwd = aboxes;
        aboxes_bwd = aboxes;
        track_forward_temp = cell(length(imdb.image_ids), 1);
        if isfield(conf,'sample_vid') && conf.sample_vid
            [inds_val,frames_val] = video_generate_random_minibatch([], [], imdb, conf, false);
            frames_val = cellfun(@(x) padarray(x,conf.nFramesPerVid-mod(length(x),conf.nFramesPerVid),'symmetric','post'), frames_val, 'UniformOutput' , false); % sample first frames
        end
        if ~isfield(conf,'nFramesPerVid')
          conf.nFramesPerVid = 1;
        end
        t_stride = conf.nFramesPerVid;
        t_stride = opts.time_stride ;
        count = 0;
        t_start = tic;
        center_frame = ceil(conf.nFramesPerVid/2);
        for v = 1:numel(inds_val)
          for kk = 1:t_stride:numel(frames_val{v}) - conf.nFramesPerVid + 1
              sub_db_inds = frames_val{v}(kk:1:kk+conf.nFramesPerVid-1);
              d = roidb.rois(sub_db_inds);
              if ~isempty(opts.test_classes),
                testThis = false;
                for ii = 1:length(opts.test_classes)
                  if any(opts.test_classes(ii) == d(1).class), testThis = true; end
                end
                if ~testThis, continue; end
              end
              count = count + 1;
              fprintf('%s: test (%s) vid %d/%d frame %d/%d', procid(), imdb.name, v,numel(inds_val), kk,numel(frames_val{v}));
              th = tic;

              [image_roidb_val, ~, ~] = rfcn_prepare_image_roidb_offline(conf, imdb, roidb.rois(sub_db_inds) , conf.root_path, sub_db_inds);

              im = {}; boxes = {};
              for b = 1:numel(sub_db_inds)
                  im{end+1} = imread(image_roidb_val(b).image_path);
                  boxes{end+1} = image_roidb_val(b).boxes(~image_roidb_val(b).gt,:);
              end

              if opts.chain_boxes_forward && ~isempty(track_forward_temp{sub_db_inds(1)})
                boxes{1} = cat(1, boxes{1}, track_forward_temp{sub_db_inds(1)});
              end

              [boxes_frames, scores_frames, track_boxes] = rfcn_im_detect(conf, caffe_net, im, boxes, max_rois_num_in_gpu);
              fprintf(' time %.3fs\n', toc(th)/numel(im));

              if ~iscell(track_boxes), track_boxes = {track_boxes}; end;
              max_scores = sum(scores_frames{2}, 2);
              tracklets = (max_scores > opts.thresh_tracks) ;
              aboxes_track{sub_db_inds(2),1} = [aboxes_track{sub_db_inds(2),1}; track_boxes{1}(tracklets,1:4)];
              aboxes_track{sub_db_inds(2),2}  = [aboxes_track{sub_db_inds(2),2}; boxes_frames{2}(tracklets,1:4)];
              aboxes_track{sub_db_inds(2),3}  = [aboxes_track{sub_db_inds(2),3}; track_boxes{2}(tracklets,1:4)];
              ascores_track{sub_db_inds(2)} = [ascores_track{sub_db_inds(2)}; scores_frames{2}(tracklets,:)] ;

              track_forward_temp{sub_db_inds(2)}  =  boxes_frames{2}(tracklets,1:4);

              %% resort frame boxes
              count2 = 0;
              for i=sub_db_inds(:)'
                count2 = count2+1;
                boxes = boxes_frames{count2};  scores = scores_frames{count2}; im_f = im{count2};
                for j = 1:num_classes
                    inds = find(scores(:, j) > thresh(j));
                    if ~isempty(inds)
                        [~, ord] = sort(scores(inds, j), 'descend');
                        ord = ord(1:min(length(ord), max_per_image));
                        inds = inds(ord); inds_tmp = inds;
                        cls_boxes = boxes(inds, (1+(j-1)*4):((j)*4));
                        cls_scores = scores(inds, j);
                        aboxes{j}{i} = [aboxes{j}{i}; cat(2, single(cls_boxes), single(cls_scores))];
                        if ~isempty(box_inds{j}{i}), inds=  inds + numel(box_inds{j}{i}); end
                        box_inds{j}{i} = [box_inds{j}{i}; inds ];
                    else
                        aboxes{j}{i} = [aboxes{j}{i}; zeros(0, 5, 'single')];
                        box_inds{j}{i} = box_inds{j}{i};
                    end
                end

                if mod(count,opts.visualize_every) == 0
                 boxes_cell = cell(length(imdb.classes), 1); boxes_track = boxes_cell; boxes_track2 = boxes_cell;

                  vis_thres = 0.9;
                  for k = 1:length(boxes_cell)
                      boxes_cell{k} = [boxes(:, (1+(k-1)*4):(k*4)), scores(:, k)];
                      I = boxes_cell{k}(:, 5) >= vis_thres;
                      boxes_cell{k} = boxes_cell{k}(I, :);
                    if count2==2
                      I =  ascores_track{i,1}(:, k) >= vis_thres;
                      boxes_track{k} = [aboxes_track{i,1}(I,1:4), ascores_track{i,1}(I, k)];
                      boxes_track2{k} = [aboxes_track{i,3}(I,1:4), ascores_track{i,1}(I, k)];
                    end
                  end
                  subplot(2,3,count2);
                  showboxes(uint8(im{count2}(:,:,1:3)), boxes_cell, imdb.classes, 'default'); drawnow;
                  title(sprintf('result for frame: %s', image_roidb_val(count2).image_id)) ;

                  if (count2) == 2
                      subplot(2,3,4);

                      showboxes(uint8(im{1}(:,:,1:3)), boxes_track, imdb.classes, 'default'); drawnow;
                      title(sprintf('tracked frame 2 -> 1 : %s', image_roidb_val(count2).image_id)) ;
                      subplot(2,3,5);
                      showboxes(uint8(im{3}(:,:,1:3)), boxes_track2, imdb.classes, 'default'); drawnow;
                      title(sprintf('tracked frame 2 -> 3 : %s', image_roidb_val(count2).image_id)) ;

                  end
                end
              end
              if mod(count, 1000) == 0
                  for j = 1:num_classes
                  [aboxes{j}, box_inds{j}, thresh(j)] = ...
                      keep_top_k(aboxes{j}, box_inds{j}, i, max_per_set, thresh(j));
                  end
                  disp(thresh);
              end
          end
        end
        for j = 1:num_classes
            [aboxes{j}, box_inds{j}, thresh(j)] = ...
                keep_top_k(aboxes{j}, box_inds{j}, i, max_per_set, thresh(j));
        end
        disp(thresh);

        for i = 1:num_classes
            top_scores{i} = sort(top_scores{i}, 'descend');
            if (length(top_scores{i}) > max_per_set)
                thresh(i) = top_scores{i}(max_per_set);
            end

            % go back through and prune out detections below the found threshold
            for j = 1:length(imdb.image_ids)
                if ~isempty(aboxes{i}{j})
                    I = find(aboxes{i}{j}(:,end) < thresh(i));
                    aboxes{i}{j}(I,:) = [];
                    box_inds{i}{j}(I,:) = [];
                end

            end

            save_file = fullfile(cache_dir, [imdb.classes{i} '_boxes_' imdb.name opts.suffix]);
            boxes = aboxes{i};
            inds = box_inds{i};
            save(save_file, 'boxes', 'inds');
            clear boxes inds;
        end
        save_file = fullfile(cache_dir, ['tracks_' imdb.name opts.suffix]);
        save(save_file, 'aboxes_track', 'ascores_track');

        caffe.reset_all();
        rng(prev_rng);

   %% generate object tracks
    track_boxes = repmat({cell(size(aboxes{1}))},size(aboxes));

    [inds_val,frames_val] = video_generate_random_minibatch([], [], imdb, conf, false);
    paths = cell(numel(inds_val),numel(aboxes));

    for v = 1:numel(inds_val)
      tic_toc_print('generating tracks for video: %d/%d\n', v, length(inds_val));
      for c = 1:numel(aboxes)
        frameIdx = frames_val{v};

        frameBoxes =  aboxes{c}(frameIdx);
        nonempty_frames = (~cellfun(@isempty,frameBoxes));

        if any(nonempty_frames)
            frameBoxes = frameBoxes(nonempty_frames);
            frameIdx = frameIdx(nonempty_frames);
            paths{v,c} = make_tubes(frameBoxes, 25, true,{aboxes_track(frameIdx,:), ascores_track(frameIdx), c} );

            for j=1:numel(paths{v,c})
                for k=1:numel(frameIdx)
                    track_boxes{c}{frameIdx(k)} = [track_boxes{c}{frameIdx(k)}; [paths{v,c}(j).boxes(k,1:4) ...
                     paths{v,c}(j).scores(k) ] ] ;
                end
            end

        end
      end
    end

    end

    %%
    % ------------------------------------------------------------------------
    % Peform AP evaluation
    % ------------------------------------------------------------------------

    if isequal(imdb.eval_func, @imdb_eval_voc)
        new_parpool();
        parfor model_ind = 1:num_classes
          cls = imdb.classes{model_ind};
          res(model_ind) = imdb.eval_func(cls, aboxes{model_ind}, imdb, opts.cache_name, opts.suffix);
        end
    else
%       % sanity test:
%       boxes_gt = cell(num_classes,1);
%       classes = {roidb.rois.class};
%       boxes = {roidb.rois.boxes};
%       boxes = cellfun(@(x) cat(2,x,ones(size(x,1),1)),boxes,'UniformOutput' , false);
%       for c=1:num_classes
%         boxes_gt{c} = cell(num_images,1);
%       end
%       for j=1:num_images
%         if ~isempty(classes{j})
%           for c=unique(classes{j})'
%             boxes_gt{c}{j} = boxes{j}(classes{j}==c,:);
%           end
%         end
%       end
%       res_gt = imdb.eval_func(boxes_gt, imdb, conf, opts.suffix);
    % ilsvrc
    res = imdb.eval_func(aboxes, imdb, conf, opts.suffix);
    res = imdb.eval_func(track_boxes, imdb, conf, opts.suffix, false);
    res = imdb.eval_func(track_boxes, imdb, conf, opts.suffix, false, true);

    for v = 1:numel(inds_val)
        frameIdx = frames_val{v};
        for k=1:numel(frameIdx)
          im = imread(imdb.image_at(frameIdx(k)));
          boxes_cell = cellfun(@(x) x(frameIdx(k)), track_boxes);
          boxes_cell = cellfun(@(x) x(x(:,5) > .2,:), boxes_cell, 'UniformOutput' , false);

          figure(1);
          showboxes(uint8(im(:,:,1:3)), boxes_cell, imdb.classes, 'default'); drawnow;
          title(sprintf('tube result for frame: %s', imdb.image_ids{frameIdx(k)})) ;
          drawnow;
        end
      end
    end

    if ~isempty(res)
        fprintf('\n~~~~~~~~~~~~~~~~~~~~\n');
        fprintf('Results:\n');
        aps = [res(:).ap]' * 100;
        disp(aps);
        disp(mean(aps));
        fprintf('~~~~~~~~~~~~~~~~~~~~\n');
        mAP = mean(aps);
    else
        mAP = nan;
    end

    diary off;
end

% ------------------------------------------------------------------------
function [boxes, box_inds, thresh] = keep_top_k(boxes, box_inds, end_at, top_k, thresh)
% ------------------------------------------------------------------------
    % Keep top K
    X = cat(1, boxes{1:end_at});
    if isempty(X)
        return;
    end
    scores = sort(X(:,end), 'descend');
    thresh = scores(min(length(scores), top_k));
    for image_index = 1:end_at
        if ~isempty(boxes{image_index})
            bbox = boxes{image_index};
            keep = find(bbox(:,end) >= thresh);
            boxes{image_index} = bbox(keep,:);
            box_inds{image_index} = box_inds{image_index}(keep);
        end
    end
end


function [err, indx, SubLabel] = WhichSubBricks (InfoStat, Type, Label)
%
%   [err, indx, SubLabel] = WhichSubBricks (InfoStat, Type, Label)
%
%Purpose:
%
%
%
%Input Parameters:
%
%
%
%Output Parameters:
%   err : 0 No Problem
%       : 1  Problems
%   indx: a vector containing sub-brick indices (+1 from AFNI indexing)
%         with labels containing both of Type and Label strings
%   SubLabel: a vector of structures containing the label strings.
%         For example if indx = [1 4] then the labels you were searching
%         for are SubLabel(1).str and SubLabel(4).str which correspond to
%         AFNI sub-bricks 0 and 3 in AFNI's indexing world.
%
%
%Key Terms:
%
%More Info :
%
%
%
%
%     Author : Ziad Saad
%     Date : Fri Jul 18 16:56:58 EDT 2003
%     SSCC/NIMH/ National Institutes of Health, Bethesda Maryland

%Define the function name for easy referencing
FuncName = 'WhichSubBricks';

%Debug Flag
DBG = 1;

%initailize return variables
err = 1;

indx = zeros(1,InfoStat.DATASET_RANK(2));

%change the format of BRICK_LABS
cend = 0;
for (i=1:1:InfoStat.DATASET_RANK(2)),
   [err, SubLabel(i).str, cend] = NextString(InfoStat.BRICK_LABS,'~',cend+1);
end

cnt = 0;
for (i=1:1:InfoStat.DATASET_RANK(2)),
   if (~isempty(findstr(SubLabel(i).str, Label)) & ~isempty(findstr(SubLabel(i).str, Type))),
      cnt = cnt + 1;
      indx(cnt) = i;
   end
end

if (cnt == 0), indx = [];
else indx = indx(1:cnt);
end

err = 0;
return;


classdef MrCompare < MrCopyData
    % This class loads and compares different objects, e.g. images/rois
    %
    % EXAMPLE
    %   MrCompare(imageArray, extraDimInfo)
    %
    %   See also MrDimInfo MrImage

    % Author:   Saskia Klein & Lars Kasper
    % Created:  2019-02-25
    % Copyright (C) 2019 Institute for Biomedical Engineering
    %                    University of Zurich and ETH Zurich
    %
    % This file is part of the TAPAS UniQC Toolbox, which is released
    % under the terms of the GNU General Public Licence (GPL), version 3.
    % You can redistribute it and/or modify it under the terms of the GPL
    % (either version 3 or, at your option, any later version).
    % For further details, see the file COPYING or
    %  <http://www.gnu.org/licenses/>.
    %

    properties

        % cell(nRows,1) of strings with detailed image information, e.g.
        % previous processing steps to arrive at that image
        % (masking/thresholding...)
        % 'detailed image information'; 'given in cell strings'
        info    = {};

        % A short string identifier of the image, used e.g. as plot-title
        name    = 'MrCompare';

        % cell(nExtraDim1, ..., nExtraDimN) holding handles to all objects
        % that shall be compared in different aspects
        % The dimensions are described by the dimInfo
        data = {};

        % MrDimInfo for data, describing which items are held in data
        dimInfo

    end % properties

    methods

        function this = MrCompare(objectArray, extraDimInfo)
            % Constructor of class
            % IN
            %   objectArray cell(nExtraDim1, ..., nExtraDimN)
            %                   OR
            %               cell(nObjects,1)
            %               holding handles to all objects of the same class
            %               (MrImage, MrRoi, MrSeries, or MrDataNd,
            %               MrImageSpm4D) to be included in comparison
            %   extraDimInfo
            %               MrDimInfo, describing meta-data of objectArray,
            %               e.g., objects from different subjects, sessions,
            %               protocols

            if nargin >= 1 % needed to allow empty constructor for copyobj etc
                % select only non-singleton-dims for dimInfo
                nSamples = size(objectArray);
                iDims = nSamples > 1;
                nDims = max(sum(iDims),1);
                nSamples = nSamples(iDims);
                if isempty(nSamples), nSamples = 1; end;

                if nargin >= 2
                    this.dimInfo = extraDimInfo.copyobj();
                else

                    for iDim = 1:nDims
                        dimLabels{iDim} = sprintf('dim%d', iDim);
                        units{iDim}      = '';
                    end
                    this.dimInfo = MrDimInfo('dimLabels', dimLabels, 'units', units, ...
                        'nSamples', nSamples);
                end

                % needed for reshape...
                if nDims == 1
                    nSamples(2) = 1;
                end

                this.data = reshape(squeeze(objectArray),nSamples);

                for iObject = 1:numel(this.data);
                    this.name = sprintf('%s %s', this.name, objectArray{iObject}.name);
                end
                this.info{end+1,1} = sprintf('Constructed from %s', this.name);
            end
        end

        % NOTE: Most of the methods are saved in separate function.m-files in this folder;
        %       except: constructor, delete, set/get methods for properties.

    end % methods

end


function [version, released] = manopt_version()
% Returns the version of the Manopt package you are running, as a vector.
%
% function [version, released] = manopt_version()
%
% version(1) is the primary version number.
% released is the date this version was released, in the same format as the
% date() function in Matlab.

    version = [7, 1, 0];
    released = '30-Sep-2022';

end


function [dat] = ft_fetch_data(data, varargin)

% FT_FETCH_DATA mimics the behavior of FT_READ_DATA, but for a FieldTrip
% raw data structure instead of a file on disk.
%
% Use as
%   [dat] = ft_fetch_data(data, ...)
%
% See also FT_READ_DATA, FT_FETCH_HEADER, FT_FETCH_EVENT

% Copyright (C) 2009-2013, Jan-Mathijs Schoffelen, Robert Oostenveld
% Copyright (C) 2008, Esther Meeuwissen
%
% This file is part of FieldTrip, see http://www.fieldtriptoolbox.org
% for the documentation and details.
%
%    FieldTrip 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.
%
%    FieldTrip 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 FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$

% check whether input is data
skipcheckdata = ft_getopt(varargin, 'skipcheckdata');
if isempty(skipcheckdata) || skipcheckdata ~= 1
  data = ft_checkdata(data, 'datatype', 'raw', 'hassampleinfo', 'yes');
end

% get the options
if true
  p = inputParser;
  p.KeepUnmatched = true;
  addOptional(p, 'header', []);
  addOptional(p, 'begsample', []);
  addOptional(p, 'endsample', []);
  addOptional(p, 'chanindx', []);
  addOptional(p, 'allowoverlap', false);
  parse(p,varargin{:});
  hdr           = p.Results.header;
  begsample     = p.Results.begsample;
  endsample     = p.Results.endsample;
  chanindx      = p.Results.chanindx;
  allowoverlap  = p.Results.allowoverlap;
else
  hdr          = ft_getopt(varargin, 'header');
  begsample    = ft_getopt(varargin, 'begsample');
  endsample    = ft_getopt(varargin, 'endsample');
  chanindx     = ft_getopt(varargin, 'chanindx');
  allowoverlap = ft_getopt(varargin, 'allowoverlap', false);
end

allowoverlap = istrue(allowoverlap);

if isempty(hdr)
  hdr = ft_fetch_header(data);
end

if isempty(begsample)
  begsample = min(data.sampleinfo(:,1));
end

if isempty(endsample)
  endsample = max(data.sampleinfo(:,2));
end

if isempty(chanindx)
  chanindx = 1:hdr.nChans;
end

% get trial definition according to original data file
if isfield(data, 'sampleinfo')
  trl = data.sampleinfo;
else
  ft_error('data does not contain a consistent trial definition, fetching data is not possible');
end
trlnum = length(data.trial);

% start with the output data being all NaN
dat = nan(numel(chanindx), endsample-begsample+1);

if trlnum>1
  % original implementation, used when the input data has multiple trials

  trllen = trl(:,2) - trl(:,1) + 1;

  % check whether data.trial is consistent with trl
  if size(trl,1)~=length(data.trial)
    ft_error('trial definition is not internally consistent')
  elseif any(trllen~=(trl(:,2)-trl(:,1)+1))
    ft_error('trial definition is not internally consistent')
  end

  minchan = min(chanindx);
  maxchan = max(chanindx);
  if minchan<1 || maxchan>hdr.nChans
    ft_error('selected channels are not present in the data')
  end

  % determine for each sample in the data where it originates from
  if begsample<1
    buflen  = endsample;
  else
    buflen  = endsample - begsample + 1;
  end
  buffer    = zeros(1, buflen, 'int32');

  count     = buffer;
  trialnum  = buffer;
  samplenum = buffer;

  for trllop = 1:trlnum
    trlbeg = trl(trllop,1);
    trlend = trl(trllop,2);
    if trlbeg>endsample || trlend<begsample
      % skip this piece, it is not interesting because the requested range falls completely outside
    else
      trlbeg = trlbeg - begsample + 1;
      trlend = trlend - begsample + 1;
      offset = 0;
      overlap = 0;
      if trlbeg < 1
        offset = 1 - trlbeg;
        trlbeg = 1;
      end
      if trlend > buflen
        overlap = trlend - buflen;
        trlend = buflen;
      end
      % make vector with 0= no sample of old data, 1= one sample of old data, 2= two samples of old data, etc
      count(trlbeg:trlend) = count(trlbeg:trlend) + 1;
      % make vector with 1's if samples belong to trial 1, 2's if samples belong to trial 2 etc. overlap/ no data --> Nan
      trialnum(trlbeg:trlend) = trllop;
      % make samplenum vector with samplenrs for each sample in the old trials
      samplenum(trlbeg:trlend) = (1 + offset):(trllen(trllop) - overlap);
    end
  end

  % overlap --> NaN
  % trialnum(count>1)  = NaN;
  % samplenum(count>1) = NaN;

  % check if all samples are present and are not present twice or more
  if any(count>1)
    if ~allowoverlap
      % ft_error('some of the requested samples occur twice in the data');
      % this  can be considered OK if the overlap has exactly identical values
      sel = find(count>1); % must be row vector
      for smplop=sel
        % find in which trials the sample occurs
        seltrl = find(smplop>=trl(:,1) + 1 - begsample & ...
                      smplop<=trl(:,2) + 1 - begsample);  % which trials, requires the adjustment with begsample, if different from 1, JM 20180116
        selsmp = smplop - trl(seltrl,1) + begsample; % which sample in each of the trials, requires the adjustment with begsample, rather than 1
        for i=2:length(seltrl)
          % compare all occurences to the first one
          % consider also mutual occurring NaNs as equal values
          if ~all(isequaln(data.trial{seltrl(i)}(:,selsmp(i)), data.trial{seltrl(1)}(:,selsmp(1))))
            ft_error('some of the requested samples occur twice in the data and have conflicting values');
          end
        end
      end
    else
      ft_warning('samples present in multiple trials, using only the last occurence of each sample')
    end
  end

  %   if any(count==0)
  %     ft_warning('not all requested samples are present in the data, filling with NaNs');
  %   end

  % construct the output data array
  % dat = nan(length(chanindx), length(samplenum));
  % for smplop=1:length(samplenum)
  %   if samplenum(smplop)==0
  %    dat(:, smplop) = nan;
  %   else
  %    dat(:, smplop) = data.trial{trialnum(smplop)}(chanindx,samplenum(smplop));
  %   end
  % end

  % the following piece of code achieves the same as the commented code above,
  % but much smaller. rather than looping over samples it loops over the blocks
  % of samples defined by the original trials

  utrl = unique(trialnum);
  utrl(~isfinite(utrl)) = 0;
  utrl(utrl==0) = [];
  if length(utrl)==1
    ok   = trialnum==utrl;
    smps = samplenum(ok);
    dat(:,ok) = data.trial{utrl}(chanindx,smps);
  else
    for xlop=1:length(utrl)
      ok   = trialnum==utrl(xlop);
      smps = samplenum(ok);
      dat(:,ok) = data.trial{utrl(xlop)}(chanindx,smps);
    end
  end

else
  % only one trial is present in the input data, so it's quite simple and can be done much faster

  % get the indices
  begindx  = begsample - trl(1) + 1;
  endindx  = endsample - trl(1) + 1;
  if endindx<=0 || begindx>size(data.trial{1},2)
    % requested data samples outside the data present
    return;
  end

  tmptrl = trl([1 2]) - [trl(1) trl(1)]+1; % ignore offset in case it's present

  datbegindx = max(1,                     trl(1)-begsample+1);
  datendindx = min(endsample-begsample+1, trl(2)-begsample+1);

  %   if begsample<trl(1) || endsample>trl(2)
  %     ft_warning('not all requested samples are present in the data, filling with NaNs');
  %   end

  if begsample >= trl(1) && begsample <= trl(2)
    % the begin sample can be found in the available data
    if endsample >= trl(1) && endsample <= trl(2)
      dat(:,datbegindx:datendindx) = data.trial{1}(chanindx,begindx:endindx);
    else
      dat(:, datbegindx:datendindx) = data.trial{1}(chanindx,begindx:tmptrl(2));
    end
  elseif endsample >= trl(1) && endsample <= trl(2)
    % the end sample can be found in the available data
    dat(:, datbegindx:datendindx) = data.trial{1}(chanindx,tmptrl(1):endindx);
  else
    % neither the begin, nor the end sample are in the available data
    dat(:, datbegindx:datendindx) = data.trial{1}(chanindx,tmptrl(1):tmptrl(2));
  end

end % if trlnum is multiple or one


function cpf(fig_no,target_name,format)
% This function cpf.m (change picture format)
% takes a picture in one format
% and saves it in another format.
%
% Syntax: load_pics(fig_no,target_name,format)
% e.g.  : load_pics(1,'holiday_on_Bornholm.bmp','epsc2');
%
% fig no      : Figure number where the figure is displayed
% target_name : Filename of new file. target_name = ''
%               gives target_name=input_filename.
% format      : One of the output formats availeble in MATLAB,
%               type "help fileformats" or
%                    "help print"

if nargin ~= 3
 error('Please specify: fig no., target name and output format');
end

% Pick file
[filename, pathname,filterspec] = uigetfile('*.*');

if strcmp(target_name,'')
    target_name = filename(1:end-4);
end

% Load file as image
[A,map]=imread(filename);

% Display image
figure(fig_no)
clf
image(A);
colormap(map);
axis equal off

% Save in new format
saveas(fig_no,target_name,format);