%kvthick 'Thickening'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros vthick.pane file
%
% Parameters:
% InputFile: i 'Input Image', required: 'input image'
% InputFile: str1 'Struct Element 1', required: 'Structuring Element'
% InputFile: str2 'Struct Element 2', required: 'Structuring Element'
% OutputFile: o 'Output Image ', required: 'resulting output image'
%
% Example: o = kvthick({i, str1, str2}, {'i','';'str1','';'str2','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% vthick - Thickening
%
%  DESCRIPTION
% .I vthick
% will do the thickening of an input image by two set structuring elements.
%
% The output image data type will be the same as that of the highest data type
% of the input image.
%
% Some useful pairs of structuring elements:
%
%                               0 0 0    1 1 1
%   Conditional Segmentation    0 1 0    0 0 0
%                               1 1 1    0 0 0
%
%                               0 0 0    1 0 0
%   Pseudo Convex Hull          0 1 1    1 0 0
%                               0 0 0    1 0 0
%
%                               1 0 0    0 0 0
%   Convex Hull                 1 0 0    0 1 0
%                               1 0 0    0 0 0
%
%                               0 0 0    1 1 1
%   Homotopic Pruning           0 1 0    1 0 1
%                               0 0 0    1 1 1
%
%
%
%  EXAMPLES
% vthick -i ball.xv -str1 b272.str -str2 b273.str -o outimage.xv
%
% Will do the thickening of image "ball.xv" by the structuring set b272.str and b273.str, with the resulting image written to "outimage.xv".
%
%  "SEE ALSO"
% vcast1(1)
%
%  RESTRICTIONS
% .I vthick
% can be defined for all data types supported by Khoros, but at the moment it has been implemented just for the bit and unsigned char types.
% The structuring elements are subsets of the 3x3 matrix and the origin is always at the center of this matrix.
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993-1997 Junior Barrera, Roberto Lotufo.  All rights reserved.
%

function varargout = kvthick(varargin)
if nargin ==0
  Inputs={};arglist={'',''};
elseif nargin ==1
  Inputs=varargin{1};arglist={'',''};
elseif nargin ==2
  Inputs=varargin{1}; arglist=varargin{2};
else error('Usage: [out1,..] = kvthick(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'str1', '__input';'str2', '__input';'o', '__output'};
maxval={0,0,0,0};
minval={0,0,0,0};
istoggle=[0,0,0,0];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','InputFile','OutputFile'};
% identify the input arrays and assign them to the arguments as stated by the user
if ~iscell(Inputs)
Inputs = {Inputs};
end
NumReqOutputs=1; nextinput=1; nextoutput=1;
  for ii=1:size(arglist,1)
  wasmatched=0;
  for jj=1:size(narglist,1)
   if strcmp(arglist{ii,1},narglist{jj,1})  % a given argument was matched to the possible arguments
     wasmatched = 1;
     was_set(jj) = 1;
     if strcmp(narglist{jj,2}, '__input')
      if (nextinput > length(Inputs))
        error(['Input ' narglist{jj,1} ' has no corresponding input!']);
      end
      narglist{jj,2} = 'OK_in';
      nextinput = nextinput + 1;
     elseif strcmp(narglist{jj,2}, '__output')
      if (nextoutput > nargout)
        error(['Output nr. ' narglist{jj,1} ' is not present in the assignment list of outputs !']);
      end
      if (isempty(arglist{ii,2}))
        narglist{jj,2} = 'OK_out';
      else
        narglist{jj,2} = arglist{ii,2};
      end

      nextoutput = nextoutput + 1;
      if (minval{jj} == 0)
         NumReqOutputs = NumReqOutputs - 1;
      end
     elseif isstr(arglist{ii,2})
      narglist{jj,2} = arglist{ii,2};
     else
        if strcmp(paramtype{jj}, 'Integer') & (round(arglist{ii,2}) ~= arglist{ii,2})
            error(['Argument ' arglist{ii,1} ' is of integer type but non-integer number ' arglist{ii,2} ' was supplied']);
        end
        if (minval{jj} ~= 0 | maxval{jj} ~= 0)
          if (minval{jj} == 1 & maxval{jj} == 1 & arglist{ii,2} < 0)
            error(['Argument ' arglist{ii,1} ' must be bigger or equal to zero!']);
          elseif (minval{jj} == -1 & maxval{jj} == -1 & arglist{ii,2} > 0)
            error(['Argument ' arglist{ii,1} ' must be smaller or equal to zero!']);
          elseif (minval{jj} == 2 & maxval{jj} == 2 & arglist{ii,2} <= 0)
            error(['Argument ' arglist{ii,1} ' must be bigger than zero!']);
          elseif (minval{jj} == -2 & maxval{jj} == -2 & arglist{ii,2} >= 0)
            error(['Argument ' arglist{ii,1} ' must be smaller than zero!']);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} < minval{jj})
            error(['Argument ' arglist{ii,1} ' must be bigger than ' num2str(minval{jj})]);
          elseif (minval{jj} ~= maxval{jj} & arglist{ii,2} > maxval{jj})
            error(['Argument ' arglist{ii,1} ' must be smaller than ' num2str(maxval{jj})]);
          end
        end
     end
     if ~strcmp(narglist{jj,2},'OK_out') &  ~strcmp(narglist{jj,2},'OK_in')
       narglist{jj,2} = arglist{ii,2};
     end
   end
   end
   if (wasmatched == 0 & ~strcmp(arglist{ii,1},''))
        error(['Argument ' arglist{ii,1} ' is not a valid argument for this function']);
   end
end
% match the remaining inputs/outputs to the unused arguments and test for missing required inputs
 for jj=1:size(narglist,1)
     if  strcmp(paramtype{jj}, 'Toggle')
        if (narglist{jj,2} ==0)
          narglist{jj,1} = '';
        end;
        narglist{jj,2} = '';
     end;
     if  ~strcmp(narglist{jj,2},'__input') && ~strcmp(narglist{jj,2},'__output') && istoggle(jj) && ~ was_set(jj)
          narglist{jj,1} = '';
          narglist{jj,2} = '';
     end;
     if strcmp(narglist{jj,2}, '__input')
      if (minval{jj} == 0)  % meaning this input is required
        if (nextinput > size(Inputs))
           error(['Required input ' narglist{jj,1} ' has no corresponding input in the list!']);
        else
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        end
      else  % this is an optional input
        if (nextinput <= length(Inputs))
          narglist{jj,2} = 'OK_in';
          nextinput = nextinput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end;
     else
     if strcmp(narglist{jj,2}, '__output')
      if (minval{jj} == 0) % this is a required output
        if (nextoutput > nargout & nargout > 1)
           error(['Required output ' narglist{jj,1} ' is not stated in the assignment list!']);
        else
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
          NumReqOutputs = NumReqOutputs-1;
        end
      else % this is an optional output
        if (nargout - nextoutput >= NumReqOutputs)
          narglist{jj,2} = 'OK_out';
          nextoutput = nextoutput + 1;
        else
          narglist{jj,1} = '';
          narglist{jj,2} = '';
        end;
      end
     end
  end
end
if nargout
   varargout = cell(1,nargout);
else
  varargout = cell(1,1);
end
global KhorosRoot
if exist('KhorosRoot') && ~isempty(KhorosRoot)
w=['"' KhorosRoot];
else
if ispc
  w='"C:\Program Files\dip\khorosBin\';
else
[s,w] = system('which cantata');
w=['"' w(1:end-8)];
end
end
[varargout{:}]=callKhoros([w 'vthick"  '],Inputs,narglist);


function a = lt( x, y )

b = newcnstr( evalin( 'caller', 'cvx_problem', '[]' ), x, y, '<' );
if nargout, a = b; end

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


function h = plotMesh(mesh, style, az, el)

if nargin < 2
    style = 'solid';
end

if strcmpi(style, 'mesh')
    h = trimesh(mesh.F', mesh.V(1,:)', mesh.V(2,:)', mesh.V(3,:)', 'FaceColor', 'none', 'EdgeColor', 'w', ...
        'AmbientStrength', 0.4, 'EdgeLighting', 'flat');
    set(gcf, 'Color', 'k', 'Renderer', 'OpenGL');
    set(gca, 'Projection', 'perspective');
    axis equal;
    axis off;
    view(az,el);
elseif strcmpi(style, 'solid')
    h = trimesh(mesh.F', mesh.V(1,:)', mesh.V(2,:)' ,mesh.V(3,:)', 'FaceColor', 'w', 'EdgeColor', 'none', ...
        'AmbientStrength', 0.3, 'DiffuseStrength', 0.6, 'SpecularStrength', 0.0, 'FaceLighting', 'flat');
    set(gcf, 'Color', 'w', 'Renderer', 'OpenGL');
    set(gca, 'Projection', 'perspective');
    axis equal;
    axis off;
    view(az,el);
    camlight('HEADLIGHT');
elseif strcmpi(style, 'solidphong')
    mesh = normals(mesh);
    h = trimesh(mesh.F', mesh.V(1,:)', mesh.V(2,:)' ,mesh.V(3,:)', 'FaceColor', 'w', 'EdgeColor', 'none', ...
        'AmbientStrength', 0.3, 'DiffuseStrength', 0.6, 'SpecularStrength', 0.0, 'FaceLighting', 'gouraud', ...
        'VertexNormals', -mesh.Nv(1:3,:)', 'BackFaceLighting', 'reverselit');
    set(gcf, 'Color', 'w', 'Renderer', 'OpenGL');
    set(gca, 'Projection', 'perspective');
    axis equal;
    axis off;
    view(az,el);
    camlight('HEADLIGHT');
elseif strcmpi(style, 'soliddoublesided')
    mesh = normals(mesh);
    lx = cos(az) * cos(el);
    ly = cos(az) * sin(el);
    lz = sin(az);
    lightdir = [lx ly lz]';
    mesh.C = zeros( size(mesh.V, 2), 3 );
    for i=1:size(mesh.V, 2)
        mesh.C(i, :) = .3 + .6 * max( sum( lightdir .* mesh.Nv(:, i) ), sum( -lightdir .* mesh.Nv(:, i) ) );
    end
    h = trimesh(mesh.F', mesh.V(1,:)', mesh.V(2,:)' ,mesh.V(3,:)', 'EdgeColor', 'none', ...
        'FaceVertexCData', mesh.C, 'FaceColor', 'interp' );
    set(gcf, 'Color', 'w', 'Renderer', 'OpenGL');
    set(gca, 'Projection', 'perspective');
    axis equal;
    axis off;
    view(az,el);
    camlight;
end


function [fids, positions] = op_CSIExtractFids(MRSIStruct, kSpaceFile)
    table = readTable(kSpaceFile);
    TR = table.TR;
    Kx = table.Kx;
    Ky = table.Ky;
    t = table.t;
    [MRSIStruct, prevPermute, prevShape] = reshapeDimensions(MRSIStruct, {'t', 'ky', 'kx'});

end


function artifact = trl2artifact(trl)

% TRL2ARTIFACT converts between two representations of events or trials.
%
% FieldTrip uses a number of representations for events that are conceptually very similar
%   event    = structure with type, value, sample, duration and offset
%   trl      = Nx3 numerical array with begsample, endsample, offset
%   trl      = table with 3 columns for begsample, endsample, offset
%   artifact = Nx2 numerical array with begsample, endsample
%   artifact = table with 2 columns for begsample, endsample
%   boolvec  = 1xNsamples boolean vector with a thresholded TTL/trigger sequence
%   boolvec  = MxNsamples boolean matrix with a thresholded TTL/trigger sequence
%
% If trl or artifact are represented as a MATLAB table, they can have additional
% columns. These additional columns have to be named and are not restricted to
% numerical values.
%
% See also ARTIFACT2BOOLVEC, ARTIFACT2EVENT, ARTIFACT2TRL, BOOLVEC2ARTIFACT, BOOLVEC2EVENT, BOOLVEC2TRL, EVENT2ARTIFACT, EVENT2BOOLVEC, EVENT2TRL, TRL2ARTIFACT, TRL2BOOLVEC, TRL2EVENT

% Copyright (C) 2009, Ingrid Nieuwenhuis
% Copyright (C) 2020, 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$

% trl and artifact are similar, except for the offset column
if isnumeric(trl)
  % do not keep any additional columns
  artifact = trl(:,1:2);
elseif istable(trl)
  % remove the offset, the additional columns can remain
  artifact = trl(:, [1 2 4:end]);
elseif iscell(trl)
  % there are multiple types of trials/artifacts, use recursion to loop over them
  artifact = cell(size(trl));
  for i=1:numel(trl)
    artifact{i} = artifact2trl(trl{i});
  end
end


function [ ] = tapas_huge_compile( )
% Compile integrator for DCM fMRI forward model. This function assumes that
% source code file 'tapas_huge_int_euler.c' is in the same folder as this
% function and places the compiled mex-file in the same folder. Running
% this function requires a C compiler to be installed. For more information
% see:
%
% https://www.mathworks.com/support/requirements/supported-compilers.html
%

% Author: Yu Yao (yao@biomed.ee.ethz.ch)
% Copyright (C) 2019 Translational Neuromodeling Unit
%                    Institute for Biomedical Engineering,
%                    University of Zurich and ETH Zurich.
%
% This file is part of TAPAS, which is released under the terms of the GNU
% General Public Licence (GPL), version 3. For further details, see
% <https://www.gnu.org/licenses/>.
%
% This software is provided "as is", without warranty of any kind, express
% or implied, including, but not limited to the warranties of
% merchantability, fitness for a particular purpose and non-infringement.
%
% This software is intended for research only. Do not use for clinical
% purpose. Please note that this toolbox is under active development.
% Considerable changes may occur in future releases. For support please
% refer to:
% https://github.com/translationalneuromodeling/tapas/issues
%

%%
% check if mex file already exists
if exist('tapas_huge_int_euler', 'file') == 3
    return
end

% get path to toolbox
tbPath = mfilename('fullpath');
tbPath = fileparts(tbPath);

% build full path to source file
scPath = fullfile(tbPath, 'tapas_huge_int_euler.c');

% check if source file present
if exist(scPath,'file')~=2
    error('TAPAS:HUGE:missingSource',...
        ['Could not locate source file. Make sure ' ...
         'tapas_huge_int_euler.c is in the huge toolbox folder.']);
end

% compile
try
    mex(scPath, '-outdir', tbPath);
catch err
    disp('tapas_huge_compile: Failed to compile mex function.');
    disp('Make sure you have selected a C language compiler for mex.');
    disp('For more information, enter mex -help on the command line.');
    rethrow(err)
end


%function lines%
%function letter_in_a_line
function [fl re space]=letter_crop(im_texto)
% Divide letters in lines

im_texto=clip(im_texto);
num_filas=size(im_texto,2);

%figure,imshow(im_texto);
%title('line sent in the function letter');
for s=1:num_filas
    s;
    sum_col = sum(im_texto(:,s));
    if sum_col==0
        k = 'true';
        nm=im_texto(:,1:s-1); % First letter matrix
        %figure,imshow(nm);
        %title('first letter in the function letter_in_a_line');
        %pause(1);
        rm=im_texto(:,s:end);% Remaining line matrix
        %figure,imshow(rm);
        %title('remaining letters in the function letter_in_a_line');
        %pause(1);
        fl = clip(nm);
        %pause(1);
        re=clip(rm);
        space = size(rm,2)-size(re,2);
        %*-*-*Uncomment lines below to see the result*-*-*-*-
               %subplot(2,1,1);imshow(fl);
               %subplot(2,1,2);imshow(re);
       break
    else
        fl=im_texto;%Only one line.
        re=[ ];
        space = 0;
    end
end

function img_out=clip(img_in)
[f c]=find(img_in);
img_out=img_in(min(f):max(f),min(c):max(c));


function [cfconds, cfshocks, cfblocks]=loadcfpan(endo,Units,panel,CFt,Fstartdate,Fenddate,Fperiods,pref)

% identify the number of endogenous variables
numendo=size(endo,1);
% identify the number of units
numunits=size(Units,1);
% initiate the cells
cfconds={};
cfshocks={};
cfblocks=[];

% recover the cfconds cell (for all types of conditional forecasts)

% load the data from Excel
[~, ~, strngs]=xlsread(pref.excelFile,'pan conditions');
% replace NaN entries by blanks
strngs(cellfun(@(x) any(isnan(x)),strngs))={[]};
% convert potential numeric entries into strings
strngs(cellfun(@isnumeric,strngs))=cellfun(@num2str,strngs(cellfun(@isnumeric,strngs)),'UniformOutput',0);
% identify the non-empty entries (pairs of rows and columns)
[nerows, neclmns]=find(~cellfun('isempty',strngs));
% count the number of such entries
neentries=size(nerows,1);
% all these entries contrain strings: fix them to correct potential user formatting errors
% loop over entries
for ii=1:neentries
    strngs{nerows(ii,1),neclmns(ii,1)}=bear.utils.fixstring(strngs{nerows(ii,1),neclmns(ii,1)});
end
% identify the rows coresponding respectively to the forecast start date and forecast end dates
temp=find(strcmp(strngs,Fstartdate));
% if empty, return an error
if isempty(temp)
    message=['conditional forecast error: forecast start date ' Fstartdate ' cannot be found. Please verify that the ''pan conditions'' sheet of the Excel data file is properly filled.'];
    error('bear:loadcfpan:FstartdateNotFound',message)
end
% otherwise, record
rows(1,1)=temp;
temp=find(strcmp(strngs,Fenddate));
% if empty, return an error
if isempty(temp)
    message=['conditional forecast error: forecast end date ' Fenddate ' cannot be found. Please verify that the ''pan conditions'' sheet of the Excel data file is properly filled.'];
    error('bear:loadcfpan:FenddateNotFound',message)
end
% otherwise, record
rows(2,1)=temp;

% now the treatment will differ according to the type of panel VAR model

% if the model is panel 2,3 or 4, different conditional forecasts will be estimated for each unit
% then cfconds becomes a cell with a number of pages equivalent to the number of units
if panel==2 || panel==3 || panel==4
    % create the cell cfconds
    cfconds=cell(Fperiods,numendo,numunits);
    % loop over units
    for ii=1:numunits
        % loop over endogenous
        for jj=1:numendo
            % find the column corresponding to the combination unit_variable
            [~,clmns]=find(strcmp(strngs,[Units{ii,1} '_' endo{jj,1}]));
            % if the string cannot be found, return an error
            if isempty(clmns)
                message=['conditional forecast error: endogenous variable ' endo{jj,1} ' cannot be found for unit ' Units{ii,1} '. Please verify that the ''pan conditions'' sheet of the Excel data file is properly filled.'];
                error('bear:loadcfpan:endoNotFound',message)
            end
            % else, loop over forecast periods
            for kk=1:Fperiods
                % fill the corresponding entry
                cfconds{kk,jj,ii}=str2double(strngs{rows(1,1)+kk-1,clmns});
            end
        end
    end

    % if the model is panel 5 or 6, a single model is estimated with all units, hence cfconds contains only one page
elseif panel==5 || panel==6
    % create the cell cfconds
    cfconds=cell(Fperiods,numendo*numunits);
    % initiate the column count
    clmncount=0;
    % loop over units
    for ii=1:numunits
        % loop over endogenous
        for jj=1:numendo
            % increment column count
            clmncount=clmncount+1;
            % find the column corresponding to the combination unit_variable
            [~,clmns]=find(strcmp(strngs,[Units{ii,1} '_' endo{jj,1}]));
            % if the string cannot be found, return an error
            if isempty(clmns)
                message=['conditional forecast error: endogenous variable ' endo{jj,1} ' cannot be found for unit ' Units{ii,1} '. Please verify that the ''pan conditions'' sheet of the Excel data file is properly filled.'];
                error('bear:loadcfpan:endoNotFound',message)
            end
            % else, loop over forecast periods
            for kk=1:Fperiods
                % fill the corresponding entry
                cfconds{kk,clmncount}=str2double(strngs{rows(1,1)+kk-1,clmns});
            end
        end
    end
end
% if no error is returned, record on Excel
if pref.results==1
    bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),strngs,'cf conditions','B2');
end

% recover the cfshocks cell (for shock-specific conditional forecasts only)

if CFt==2
    % load the data from Excel
    [~, ~, strngs]=xlsread(pref.excelFile,'pan shocks');
    % replace NaN entries by blanks
    strngs(cellfun(@(x) any(isnan(x)),strngs))={[]};
    % convert potential numeric entries into strings
    strngs(cellfun(@isnumeric,strngs))=cellfun(@num2str,strngs(cellfun(@isnumeric,strngs)),'UniformOutput',0);
    % identify the non-empty entries (pairs of rows and columns)
    [nerows, neclmns]=find(~cellfun('isempty',strngs));
    % count the number of such entries
    neentries=size(nerows,1);
    % all these entries contrain strings: fix them to correct potential user formatting errors
    % loop over entries
    for ii=1:neentries
        strngs{nerows(ii,1),neclmns(ii,1)}=bear.utils.fixstring(strngs{nerows(ii,1),neclmns(ii,1)});
    end
    % identify the rows coresponding respectively to the forecast start date and forecast end dates
    temp=find(strcmp(strngs,Fstartdate));
    % if empty, return an error
    if isempty(temp)
        message=['conditional forecast error: forecast start date ' Fstartdate ' cannot be found. Please verify that the ''pan shocks'' sheet of the Excel data file is properly filled.'];
        msgbox(message);
        error('programme termination: conditional forecast error');
    end
    % otherwise, record
    rows(1,1)=temp;
    temp=find(strcmp(strngs,Fenddate));
    % if empty, return an error
    if isempty(temp)
        message=['conditional forecast error: forecast end date ' Fenddate ' cannot be found. Please verify that the ''pan shocks'' sheet of the Excel data file is properly filled.'];
        msgbox(message);
        error('programme termination: conditional forecast error');
    end
    % otherwise, record
    rows(2,1)=temp;

    % now the treatment will differ according to the type of panel VAR model

    % if the model is panel 2,3 or 4, different conditional forecasts will be estimated for each unit
    % then cfshocks becomes a cell with a number of pages equivalent to the number of units
    if panel==2 || panel==3 || panel==4
        % create the cell cfshocks
        cfshocks=cell(Fperiods,numendo,numunits);
        % loop over units
        for ii=1:numunits
            % loop over endogenous
            for jj=1:numendo
                % find the column corresponding to the combination unit_variable
                [~,clmns]=find(strcmp(strngs,[Units{ii,1} '_' endo{jj,1}]));
                % if the string cannot be found, return an error
                if isempty(clmns)
                    message=['conditional forecast error: endogenous variable ' endo{jj,1} ' cannot be found for unit ' Units{ii,1} '. Please verify that the ''pan shocks'' sheet of the Excel data file is properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                end
                % else, loop over forecast periods
                for kk=1:Fperiods
                    % fill the corresponding entry
                    cfshocks{kk,jj,ii}=str2double(strngs{rows(1,1)+kk-1,clmns});
                end
            end
        end

        % if the model is panel 5 or 6, a single model is estimated with all units, hence cfshocks contains only one page
    elseif panel==5 || panel==6
        % create the cell cfshocks
        cfshocks=cell(Fperiods,numendo*numunits);
        % initiate the column count
        clmncount=0;
        % loop over units
        for ii=1:numunits
            % loop over endogenous
            for jj=1:numendo
                % increment column count
                clmncount=clmncount+1;
                % find the column corresponding to the combination unit_variable
                [~,clmns]=find(strcmp(strngs,[Units{ii,1} '_' endo{jj,1}]));
                % if the string cannot be found, return an error
                if isempty(clmns)
                    message=['conditional forecast error: endogenous variable ' endo{jj,1} ' cannot be found for unit ' Units{ii,1} '. Please verify that the ''pan shocks'' sheet of the Excel data file is properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                end
                % loop over forecast periods
                for kk=1:Fperiods
                    % fill the corresponding entry
                    cfshocks{kk,clmncount}=str2double(strngs{rows(1,1)+kk-1,clmns});
                end
            end
        end
    end

    % if no error is returned, record on Excel
    if pref.results==1
        bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),strngs,'cf shocks','B2');
    end
end

% recover the cfblocks matrix (for shock-specific conditional forecasts only)

if CFt==2
    % load the data from Excel
    [~, ~, strngs]=xlsread(pref.excelFile,'pan blocks');
    % replace NaN entries by blanks
    strngs(cellfun(@(x) any(isnan(x)),strngs))={[]};
    % convert potential numeric entries into strings
    strngs(cellfun(@isnumeric,strngs))=cellfun(@num2str,strngs(cellfun(@isnumeric,strngs)),'UniformOutput',0);
    % identify the non-empty entries (pairs of rows and columns)
    [nerows, neclmns]=find(~cellfun('isempty',strngs));
    % count the number of such entries
    neentries=size(nerows,1);
    % all these entries contrain strings: fix them to correct potential user formatting errors
    % loop over entries
    for ii=1:neentries
        strngs{nerows(ii,1),neclmns(ii,1)}=bear.utils.fixstring(strngs{nerows(ii,1),neclmns(ii,1)});
    end
    % identify the rows coresponding respectively to the forecast start date and forecast end dates
    % identify the rows coresponding respectively to the forecast start date and forecast end dates
    temp=find(strcmp(strngs,Fstartdate));
    % if empty, return an error
    if isempty(temp)
        message=['conditional forecast error: forecast start date ' Fstartdate ' cannot be found. Please verify that the ''pan shocks'' sheet of the Excel data file is properly filled.'];
        msgbox(message);
        error('programme termination: conditional forecast error');
    end
    % otherwise, record
    rows(1,1)=temp;
    temp=find(strcmp(strngs,Fenddate));
    % if empty, return an error
    if isempty(temp)
        message=['conditional forecast error: forecast end date ' Fenddate ' cannot be found. Please verify that the ''pan shocks'' sheet of the Excel data file is properly filled.'];
        msgbox(message);
        error('programme termination: conditional forecast error');
    end
    % otherwise, record
    rows(2,1)=temp;

    % now the treatment will differ according to the type of panel VAR model
    % if the model is panel 2,3 or 4, different conditional forecasts will be estimated for each unit
    % then cfblocks becomes a matrix with a number of pages equivalent to the number of units
    if panel==2 || panel==3 || panel==4
        % create the matrix cfshocks
        cfblocks=zeros(Fperiods,numendo,numunits);
        % loop over units
        for ii=1:numunits
            % loop over endogenous
            for jj=1:numendo
                % find the column corresponding to the combination unit_variable
                [~,clmns]=find(strcmp(strngs,[Units{ii,1} '_' endo{jj,1}]));
                % if the string cannot be found, return an error
                if isempty(clmns)
                    message=['conditional forecast error: endogenous variable ' endo{jj,1} ' cannot be found for unit ' Units{ii,1} '. Please verify that the ''pan blocks'' sheet of the Excel data file is properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                end
                % else, loop over forecast periods
                for kk=1:Fperiods
                    % recover the entry
                    temp=str2double(strngs{rows(1,1)+kk-1,clmns});
                    % if the entry is empty, ignore
                    if isempty(temp)
                        % if not empty, record in cfblocks
                    else
                        cfblocks(kk,jj,ii)=temp;
                    end
                end
            end
        end

        % if the model is panel 5 or 6, a single model is estimated with all units, hence cfblocks contains only one page
    elseif panel==5 || panel==6
        % create the cell cfblocks
        cfblocks=zeros(Fperiods,numendo*numunits);
        % initiate the column count
        clmncount=0;
        % loop over units
        for ii=1:numunits
            % loop over endogenous
            for jj=1:numendo
                % increment column count
                clmncount=clmncount+1;
                % find the column corresponding to the combination unit_variable
                [~,clmns]=find(strcmp(strngs,[Units{ii,1} '_' endo{jj,1}]));
                % if the string cannot be found, return an error
                if isempty(clmns)
                    message=['conditional forecast error: endogenous variable ' endo{jj,1} ' cannot be found for unit ' Units{ii,1} '. Please verify that the ''pan blocks'' sheet of the Excel data file is properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                end
                % else, loop over forecast periods
                for kk=1:Fperiods
                    % recover the entry
                    temp=str2double(strngs{rows(1,1)+kk-1,clmns});
                    % if the entry is empty, ignore
                    if isempty(temp)
                        % if not empty, record in cfblocks
                    else
                        cfblocks(kk,clmncount)=temp;
                    end
                end
            end
        end
    end

    % if no error is returned, record on Excel
    if pref.results==1
        bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),strngs,'cf blocks','B2');
    end
end

% final verification: check that cfconds is consistent with the other cells/matrices (i.e. cfshocks and cfblocks)
% the way this is done depends on the panel model
% if the panel model is 2, 3 or 4
if panel==2 || panel==3 || panel==4
    % if the type of conditional forecasts is shock-specific
    if CFt==2
        % loop over units
        for ii=1:numunits
            % check if there are conditions on unit ii
            temp1=cfconds(:,:,ii);
            nconds(ii,1)=numel(temp1(cellfun(@(x) any(~isempty(x)),temp1)));
            % if there are no conditions, ignore as there is nothing to check
            if nconds==0
                % if there are conditions
            else
                % identify the non-empty elements in cfconds
                [nerows1, neclmns1]=find(~cellfun('isempty',cfconds(:,:,ii)));
                % check that cfconds is consistent with cfshocks
                % identify the non-empty elements in cfshocks
                [nerows2, neclmns2]=find(~cellfun('isempty',cfshocks(:,:,ii)));
                % if the number of non-empty elements is not similar in the two cells, there is obvioulsy a problem: return an error
                if size(nerows1,1)~=size(nerows2,1)
                    message=['conditional forecast error: the conditions for unit ' Units{ii} ' seem to be inconsistent with the shocks. Please verify that the ''pan conditions'' and ''pan shocks'' sheets of the Excel data file are properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                    % else, if there a is a similar number of non-empty entries but they don't match, there is also a problem: return an error
                elseif (~isempty(find(nerows1-nerows2)) || ~isempty(find(neclmns1-neclmns2)))
                    message=['conditional forecast error: the conditions for unit ' Units{ii} ' seem to be inconsistent with the shocks. Please verify that the ''pan conditions'' and ''pan shocks'' sheets of the Excel data file are properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                end
                % similarly, check that cfconds is consistent with cfblocks
                % first turn cfblocks to cell
                temp=num2cell(cfblocks(:,:,ii));
                % switch zero entries to empty entries
                temp(cellfun(@(x) any(~(x)),temp))={[]};
                % identify the non-empty elements in cfblocks
                [nerows3, ~]=find(~cellfun('isempty',temp));
                % if the number of non-empty elements is not similar in the two cells, there is obvioulsy a problem: return an error
                if size(nerows1,1)~=size(nerows3,1)
                    message=['conditional forecast error: the conditions for unit ' Units{ii} ' seem to be inconsistent with the blocks. Please verify that the ''pan conditions'' and ''pan blocks'' sheets of the Excel data file are properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                    % else, if there a is a similar number of non-empty entries but they don't match, there is also a problem: return an error
                elseif (~isempty(find(nerows1-nerows2)) || ~isempty(find(neclmns1-neclmns2)))
                    message=['conditional forecast error: the conditions for unit ' Units{ii} ' seem to be inconsistent with the blocks. Please verify that the ''pan conditions'' and ''pan blocks'' sheets of the Excel data file are properly filled.'];
                    msgbox(message);
                    error('programme termination: conditional forecast error');
                end
            end
        end
    end

    %else if the panel model is 5 or 6
elseif panel==5 || panel==6
    % if the type of conditional forecasts is shock-specific
    if CFt==2
        % identify the non-empty elements in cfconds
        [nerows1, neclmns1]=find(~cellfun('isempty',cfconds));
        % check that cfconds is consistent with cfshocks
        % identify the non-empty elements in cfshocks
        [nerows2, neclmns2]=find(~cellfun('isempty',cfshocks));
        % if the number of non-empty elements is not similar in the two cells, there is obvioulsy a problem: return an error
        if size(nerows1,1)~=size(nerows2,1)
            message=['conditional forecast error: the conditions seem to be inconsistent with the shocks. Please verify that the ''pan conditions'' and ''pan shocks'' sheets of the Excel data file is properly filled.'];
            msgbox(message);
            error('programme termination: conditional forecast error');
            % else, if there a is a similar number of non-empty entries but they don't match, there is also a problem: return an error
        elseif (~isempty(find(nerows1-nerows2)) || ~isempty(find(neclmns1-neclmns2)))
            message=['conditional forecast error: the conditions seem to be inconsistent with the shocks. Please verify that the ''pan conditions'' and ''pan shocks'' sheets of the Excel data file is properly filled.'];
            msgbox(message);
            error('programme termination: conditional forecast error');
        end
        % similarly, check that cfconds is consistent with cfblocks
        % first turn cfblocks to cell
        temp=num2cell(cfblocks);
        % switch zero entries to empty entries
        temp(cellfun(@(x) any(~(x)),temp))={[]};
        % identify the non-empty elements in cfblocks
        [nerows3, neclmns3]=find(~cellfun('isempty',temp));
        % if the number of non-empty elements is not similar in the two cells, there is obvioulsy a problem: return an error
        if size(nerows1,1)~=size(nerows3,1)
            message=['conditional forecast error: the conditions seem to be inconsistent with the blocks. Please verify that the ''pan conditions'' and ''pan blocks'' sheets of the Excel data file is properly filled.'];
            msgbox(message);
            error('programme termination: conditional forecast error');
            % else, if there a is a similar number of non-empty entries but they don't match, there is also a problem: return an error
        elseif (~isempty(find(nerows1-nerows3)) || ~isempty(find(neclmns1-neclmns3)))
            message=['conditional forecast error: the conditions seem to be inconsistent with the blocks. Please verify that the ''pan conditions'' and ''pan blocks'' sheets of the Excel data file is properly filled.'];
            msgbox(message);
            error('programme termination: conditional forecast error');
        end
    end
end


function rgb = skin_light

% This returns a predefined color as [red green blue] values
%   red               = [255   0   0]/255;
%   green             = [  0 192   0]/255;
%   blue              = [  0   0 255]/255;
%   magenta           = [255 255   0]/255;
%   cyan              = [  0 255 255]/255;
%   yellow            = [255 255   0]/255;
%   white             = [255 255 255]/255;
%   black             = [  0   0   0]/255;
%
%   skull             = [140  85  85]/255
%   cortex            = [255 213 119]/255;
%   cortex_light      = [199 194 169]/255;
%   cortex_dark       = [100  97  85]/255;
%   skin              = [249 223 192]/255;
%   skin_light        = [249 223 192]/255;
%   skin_medium_light = [225 194 158]/255;
%   skin_medium       = [188 142 106]/255;
%   skin_medium_dark  = [155 102	65]/255;
%   skin_dark         = [ 91  71  61]/255;
%
% The different skin-based colors follow the Fitzpatrick scale with type I and II
% combined, and return RGB values that approximate those used by Apple in the emoji
% skin tones. See also https://emojipedia.org/emoji-modifier-sequence/
%
% If no specific skin tone is specified, this function returns a light skin color.
% This corresponds with that of one of the developers who approximated his own skin
% color more than 15 years ago upon the first implementation of this function.

% returns a predefined color as [red green blue] values
rgb = [249	223	192]/255;


function F = conj( F )
%CONJ Complex conjugate of a SPHEREFUNV.
%   CONJ(F) returns the complex conjugate of F. For a complex F, CONJ(F) =
%   REAL(F) - i*IMAG(F).
%
%   Since only real SPHEREFUNV objects are supported, the result of this
%   function is always just the original function F.
%
%   See also SPHEREFUNV/IMAG, SPHEREFUNV/REAL.

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

% Empty check:
if ( isempty( F ) )
    return
end

% Take conj part of each component:
F.components = cellfun( @conj, F.components, 'UniformOutput', false );

end


clear all;
close all;
clc;
result = merge_results('ssc_nn_omp');
plot_bench_results(result, 'ssc_nn_omp');


function [s] = loadLTPLLogs(Ts, Ts_slow)

% Author: Thomas Herrmann     Date: 19-01-2021
%
% Description: This function loads the logged LTPL data, which arrived at
% the control module and prepares these LTPL information for a log data
% replay in Simulink. Using this funcitonality, the controller can be
% developed further.
%
% Input:    Ts - logging file
%           Ts_slow - slow logging file
%
% Output: s - struct with data from timeseries input oject

% specify signals you want to extract, 'd' must be a fixed string
sig_names = struct(...
    'd1', 'debug_slow_tartraj_x_m', ...
    'd2', 'debug_slow_tartraj_y_m', ...
    'd3', 'debug_slow_tartraj_psi_rad', ...
    'd4', 'debug_slow_tartraj_kappa_radpm', ...
    'd5', 'debug_slow_tartraj_v_mps', ...
    'd6', 'debug_slow_tartraj_ax_mps2', ...
    'd7', 'debug_slow_tartraj_s_loc_m', ...
    'd8', 'debug_slow_tartraj_LapCnt', ...
    'd9', 'debug_slow_tartraj_ax_lim_mps2', ...
    'd10', 'debug_slow_tartraj_ay_lim_mps2', ...
    'd11', 'debug_slow_tartraj_banking_rad');

% specify integer of how much faster the fast logging file was recorded
slow_fast_factor = 10;

%% position of vehicle (fast logging file)

% get time of first entry in slow debug file
t_zero = Ts_slow.debug_slow_ax_traj_mps2.Time(1);
% find synchronisation point in fast debug file
t_zero_fast_idx = find(t_zero==Ts.debug_mvdc_path_matching_debug_ActualTrajPoint_s_glob_m.Time);

% get global s coordinate from fast logging file which matches every entry
% in the slow logging file
s_global_slow_match_m = Ts.debug_mvdc_path_matching_debug_ActualTrajPoint_s_glob_m.Data(t_zero_fast_idx:slow_fast_factor:end);

%%
% initialize empty struct
s = struct();

s.s_global_m = s_global_slow_match_m;

% remove all entries with only zeros at beginning of race
zero_counter = 1;
for k=1:length(Ts_slow.(sig_names.d1).Data)
    if sum(abs(Ts_slow.(sig_names.d1).Data(k, :))) == 0
        zero_counter = zero_counter + 1;
    end
end

s.s_global_m = s.s_global_m(zero_counter:end);
for k=1:length( fields(sig_names) )
    en = ['d', num2str(k)];
    s.(sig_names.(en)) = Ts_slow.(sig_names.(en)).Data(zero_counter:end, :);
end

%% Write to data dictionary
DDObj = ...
    Simulink.data.dictionary.open('TrajectoryPlanningEmulation.sldd');
dataSectObj = getSection(DDObj, 'Design Data');
try addEntry(dataSectObj, 'ltpl_log', s);
% if entry was there already modify it
catch e
    if isa(e, 'MSLException')
        ltplLogObj = getEntry(dataSectObj, 'ltpl_log');
        setValue(ltplLogObj, s);
    else
        print('Something went wrong.')
    end
end

% set switch to enable local log replay
switchObj = getEntry(dataSectObj, 'P_VDC_TrajEmulation_mode');
setValue(switchObj, 1);
% save & close
saveChanges(DDObj);
close(DDObj);

% set start position
Scenario_DD = Simulink.data.dictionary.open('raceline.sldd');
dataSectObj = getSection(Scenario_DD, 'Design Data');
x0_pose = getEntry(dataSectObj, 'x0_vehiclepose_stm');
setValue(x0_pose, ...
    [s.debug_slow_tartraj_x_m(1, 1), ...
     s.debug_slow_tartraj_y_m(1, 1), ...
     s.debug_slow_tartraj_psi_rad(1, 1)]);
saveChanges(Scenario_DD);
close(Scenario_DD);

end


function [masterOutput, masterTime] = TS_ComputeMasterLoop(x,x_z,masterCode,masterID,numMasterOps,howVocal,theTsID,iterNum)
% TS_ComputeMasterLoop     Used in a loop by TS_Compute to evaluate a given master function.

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

if strcmp(howVocal,'full')
    beVocal = true;
else
    beVocal = false;
end

if beVocal
    % Display code name for error checking
    fprintf(1,'[TimeSeries_ID = %u, MasterOperation_ID = %u (%u/%u)] %s...',...
                theTsID, masterID, iterNum, numMasterOps, masterCode);
end

try
	masterTimer = tic;
    if beVocal
        % Any output text is printed to screen
    	masterOutput = BF_ParEval(x,x_z,masterCode,1);
    else
        % Output text stored in second output (could log this if you really want to)
        masterOutput = BF_ParEval(x,x_z,masterCode,0);
    end
	masterTime = toc(masterTimer);
    if beVocal
        fprintf(1,' evaluated (%s).\n',BF_TheTime(masterTime));
    end
	% For not-applicable/'real NaN', masterOutput is a NaN, otherwise a
	% structure with components to be called below by pointer operations.

catch emsg
    if beVocal
        fprintf(1,' error.\n'); % ,BF_TheTime(masterTime)
    end
	fprintf(1,'---Error evaluating %s:\n%s.\n',masterCode,emsg.message);
    masterOutput = {}; % Keep empty output
    masterTime = 0; % Set zero calculation time
	% Remains an empty cell entry.
end

end


function out = LegPlot(text,opt)
% =======================================================================
% This function creates a legend outside the chart, centered, & below
% =======================================================================
% out = LegPlot(text,opt)
% -----------------------------------------------------------------------
% INPUT
%   - text: cell, containing the legend text
% -----------------------------------------------------------------------
% OPTIONAL INPUTS
%   - opt: options for the legend, output of LegOption function
% =======================================================================
% Ambrogio Cesa Bianchi, March 2015
% ambrogio.cesabianchi@gmail.com

%% Preliminaries
% =========================================================================
if ~exist('opt','var')
    opt = LegOption;
end

hsize = opt.hsize;
interpreter = opt.interpreter;
direction = opt.direction;
handle = opt.handle;

if hsize<=0 || hsize>1
    disp('Error: hsize must be between zero and one');
    return
end

if isempty(handle)==1
    handle_flag = 0;
else
    handle_flag = 1;
end

%% Legend
% =========================================================================
% Retrieve the position of the figure: [a b c d] = get(gcf,'Position')
% a and b are the (x,y) location of the upper left corner; c and d are the width and height of the window
figpos = get(gcf,'Position');

% Create the legend
if direction==1
    if handle_flag==1
        h1 = legend(handle,text,'Orientation','Horizontal','Fontsize',get(gca,'Fontsize')-1,'Interpreter',interpreter);
    else
        h1 = legend(text,'Orientation','Horizontal','Fontsize',get(gca,'Fontsize')-1,'Interpreter',interpreter);
    end
else
    if handle_flag==1
        h1 = legend(handle,text,'Orientation','Vertical','Fontsize',get(gca,'Fontsize')-1,'Interpreter',interpreter);
    else
        h1 = legend(text,'Orientation','Vertical','Fontsize',get(gca,'Fontsize')-1,'Interpreter',interpreter);
    end
end

% Retrieve the position of the legend:
% out(1) is the location along the x-axis
% out(2) is the location along the y-axis
% out(3) is the width
% out(2) is the height
out = get(h1,'Position');

% ------------- Examples ------------------------------------
% out(1)	out(2)	Vertical alignment	Horizontal alignment
% 0       0           Bottom              Left
% 0.5     0           Bottom              Center
% 0.9     0           Bottom              Right
% 0       0.5         Center              Left
% 0.5     0.5         Center              Center
% 0.9     0.5         Center              Right
% 0       0.9         Top                 Left
% 0.5     0.9         Top                 Center
% 0.9     0.9         Top                 Right
% ------------------------------------------------------------

% Make room for sublegend if font is different from default
axpos = get(gca,'outerPosition');

% % Increase the hsize of the figure to make room for the legend
% FigSize(figpos(3),figpos(4)*(1+out(4)));

% Reduce the y hsize of the plot and move up to make room for legend
axpos(1) = axpos(1);
axpos(2) = axpos(2) + 1.1*out(4);
axpos(3) = axpos(3);
axpos(4) = 1 - 1.1*out(4);
set(gca,'outerPosition',axpos);

% Determine the position for centering the legend
out(3) = hsize; % First set the width of the legend in relative terms (1=whole figure)
out(1) = (figpos(3)-figpos(3)*out(3)) /2 /figpos(3); % Then compute the center
out(2) = 0.005;

% Place the legend
set(h1,'Position',out);


%SerialLink.plot3d Graphical display and animation of solid model robot
%
% R.plot3d(Q, options) displays and animates a solid model of the robot.
% The robot is displayed at the joint angle Q (1xN), or
% if a matrix (MxN) it is animated as the robot moves along the M-point trajectory.
%
% Options::
%
% 'color',C         A cell array of color names, one per link.  These are
%                   mapped to RGB using colorname().  If not given, colors
%                   come from the axis ColorOrder property.
% 'alpha',A         Set alpha for all links, 0 is transparant, 1 is opaque
%                   (default 1)
% 'path',P          Overide path to folder containing STL model files
% 'workspace', W    Size of robot 3D workspace, W = [xmn, xmx ymn ymx zmn zmx]
% 'floorlevel',L    Z-coordinate of floor (default -1)
%-
% 'delay',D         Delay betwen frames for animation (s)
% 'fps',fps         Number of frames per second for display, inverse of 'delay' option
% '[no]loop'        Loop over the trajectory forever
% '[no]raise'       Autoraise the figure
% 'movie',M         Save frames as files in the folder M
% 'trail',L         Draw a line recording the tip path, with line style L.
%                   L can be a cell array, eg. {'r', 'LineWidth', 2}
%-
% 'scale',S         Annotation scale factor
% 'ortho'           Orthographic view (default)
% 'perspective'     Perspective view
% 'view',V          Specify view V='x', 'y', 'top' or [az el] for side elevations,
%                   plan view, or general view by azimuth and elevation
%                   angle.
%-
% '[no]wrist'       Enable display of wrist coordinate frame
% 'xyz'             Wrist axis label is XYZ
% 'noa'             Wrist axis label is NOA
% '[no]arrow'       Display wrist frame with 3D arrows
%-
% '[no]tiles'       Enable tiled floor (default true)
% 'tilesize',S      Side length of square tiles on the floor (default 0.2)
% 'tile1color',C   Color of even tiles [r g b] (default [0.5 1 0.5]  light green)
% 'tile2color',C   Color of odd tiles [r g b] (default [1 1 1] white)
%-
% '[no]jaxes'       Enable display of joint axes (default true)
% '[no]joints'      Enable display of joints
%-
% '[no]base'        Enable display of base shape
%
% Notes::
% - Solid models of the robot links are required as STL files (ascii or
%   binary) with extension .stl.
% - The solid models live in RVCTOOLS/robot/data/meshes.
% - Each STL model is called 'linkN'.stl where N is the link number 0 to N
% - The specific folder to use comes from the SerialLink.model3d property
% - The path of the folder containing the STL files can be overridden using
%   the 'path' option
% - The height of the floor is set in decreasing priority order by:
%   - 'workspace' option, the fifth element of the passed vector
%   - 'floorlevel' option
%   - the lowest z-coordinate in the link1.stl object
%
% Making an animation::
%
% The 'movie' options saves the animation as a movie file or separate frames in a folder
% - 'movie','file.mp4' saves as an MP4 movie called file.mp4
% - 'movie','folder' saves as files NNNN.png into the specified folder
%   - The specified folder will be created
%   - NNNN are consecutive numbers: 0000, 0001, 0002 etc.
%   - To convert frames to a movie use a command like:
%          ffmpeg -r 10 -i %04d.png out.avi
%
% Authors::
% - Peter Corke, based on existing code for plot().
% - Bryan Moutrie, demo code on the Google Group for connecting ARTE and
%   RTB.
%
% Acknowledgments::
% - STL files are from ARTE: A ROBOTICS TOOLBOX FOR EDUCATION by Arturo Gil
%   (https://arvc.umh.es/arte) are included, with permission.
% - The various authors of STL reading code on file exchange, see stlRead.m
%
% See also SerialLink.plot, plotbotopt3d, SerialLink.animate, SerialLink.teach, stlRead.

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

function plot3d(robot, q, varargin)

    assert( ~robot.mdh, 'RTB:plot3d:badmodel', '3D models are defined for standard, not modified, DH parameters');

    opt = plot_options(robot, varargin);

    robot.movie = Animate(opt.movie);

    %-- load the shape if need be

    nshapes = robot.n+1;

    if isempty(robot.faces)
        % no 3d model defined, let's try to load one

        if isempty(opt.path)
            % first find the path to the models
            pth = mfilename('fullpath');
            pth = fileparts(pth);
            % peel off the last folder
            s = regexp(pth, filesep, 'split');
            pth = join(s(1:end-1), filesep);

            % find the path to this specific model
            pth = fullfile(pth{1}, 'data/meshes', robot.model3d);
            assert(exist(pth, 'dir') > 0, 'RTB:plot3d:nomodel', 'no 3D model found, install the RTB contrib zip file');
        else
            pth = opt.path;
        end

        % now load the STL files
        robot.points = cell(1, robot.n+1);
        robot.faces = cell(1, robot.n+1);
        fprintf('Loading STL models from ARTE Robotics Toolbox for Education  by Arturo Gil (http://arvc.umh.es/arte)');
        for i=1:nshapes
            [P,F] = stlRead( fullfile(pth, sprintf('link%d.stl', i-1)) );
            robot.points{i} = P;
            robot.faces{i} = F;
            fprintf('.');

        end
        fprintf('\n');
    end

    % if a base is specified set the floor height to this
    if isempty(opt.workspace)
        % workspace not provided, fall through the options for setting floor level
        if ~isempty(opt.floorlevel)
            opt.ws(5) = opt.floorlevel;
        elseif opt.base
            mn = min( robot.points{1} );
            opt.ws(5) = mn(3);
        end
    end
    opt.floorlevel = opt.ws(5);

% TODO
% should test if the plot exists, pinch the logic from plot()

    %-- set up to plot
    % create an axis
    ish = ishold();
    if ~ishold
        % if hold is off, set the axis dimensions
        axis(opt.ws);
        set(gca, 'ZLimMode', 'manual');
        axis(opt.ws);
        hold on
    end

    if opt.raise
        % note this is a very time consuming operation
        figure(gcf);
    end

    if strcmp(opt.projection, 'perspective')
        set(gca, 'Projection', 'perspective');
    end

    grid on
    xlabel('X'); ylabel('Y'); zlabel('Z');

    %--- create floor if required
    if opt.tiles
        create_tiled_floor(opt);
    end

    %--- configure view and lighting
    if isstr(opt.view)
        switch opt.view
            case 'top'
                view(0, 90);
            case 'x'
                view(0, 0);
            case 'y'
                view(90, 0)
            otherwise
                error('rtb:plot3d:badarg', 'view must be: x, y, top')
        end
    elseif isnumeric(opt.view) && length(opt.view) == 2
        view(opt.view)
    else
        campos([2 2 1]);
    end

    daspect([1 1 1]);
    light('Position', [0 0 opt.reach*2]);
    light('Position', [1 0.5 1]);

    %-- figure the colors for each shape
    if isempty(opt.color)
        % if not given, use the axis color order
        C = get(gca,'ColorOrder');
    else
        C = [];
        for c=opt.color
            C = [C; colorname(c{1})];
        end
    end

    %--- create the robot
    %  one patch per shape, use hgtransform to animate them later
    group = hggroup('Tag', robot.name);
    ncolors = numrows(C);

    h = [];
    for link=0:robot.n
        if link == 0
            if ~opt.base
                continue;
            end

            patch('Faces', robot.faces{link+1}, 'Vertices', robot.points{link+1}, ...
                'FaceColor', C(mod(link,ncolors)+1,:), 'EdgeAlpha', 0, 'FaceAlpha', opt.alpha);
        else
            h.link(link) = hgtransform('Tag', sprintf('link%d', link), 'Parent', group);

            patch('Faces', robot.faces{link+1}, 'Vertices', robot.points{link+1}, ...
                'FaceColor', C(mod(link,ncolors)+1,:), 'EdgeAlpha', 0, 'FaceAlpha', opt.alpha, ...
            'Parent', h.link(link));
        end
    end

        % display the wrist coordinate frame
    if opt.wrist
        if opt.arrow
            h.wrist = trplot(eye(4,4), 'labels', upper(opt.wristlabel), ...
                'arrow', 'rgb', 'length', 0.4);
        else
            h.wrist = trplot(eye(4,4), 'labels', upper(opt.wristlabel), ...
                'rgb', 'length', 0.4);
        end
    else
        h.wrist = [];
    end

    if ~isempty(opt.trail)
        h.trail = plot(0, 0, opt.trail{:});
        robot.trail = [];
    end

    % enable mouse-based 3D rotation
    rotate3d on

    h.robot = robot;
    h.link = [0 h.link];
    set(group, 'UserData', h);

    robot.trail = []; % clear the previous trail

    robot.animate(q);

    if opt.movie
        robot.movie.close();
    end

    if ~ish
        hold off
    end
end

function opt = plot_options(robot, optin)
    opt.color = [];
    opt.path = [];  % override path
    opt.alpha = 1;

        % timing/looping
    opt.delay = 0.1;
    opt.fps = [];
    opt.loop = false;

    opt.raise = false;

    % general appearance
    opt.scale = 1;
    opt.trail = [];

    opt.workspace = [];
    opt.floorlevel = [];

    opt.name = true;
    opt.projection = {'ortho', 'perspective'};
    opt.view = [];

    % tiled floor
    opt.tiles = true;
    opt.tile1color = [0.5 1 0.5];  % light green
    opt.tile2color = [1 1 1];  % white
    opt.tilesize = 0.2;

    % the base or pedestal
    opt.base = true;

    % wrist
    opt.wrist = true;
    opt.wristlabel = {'xyz', 'noa'};
    opt.arrow = true;

    % joint rotation axes
    opt.jaxes = false;

    % misc
    opt.movie = [];

    % build a list of options from all sources
    %   1. the M-file plotbotopt if it exists
    %   2. robot.plotopt
    %   3. command line arguments
    if exist('plotbotopt3d', 'file') == 2
        options = [plotbotopt3d robot.plotopt3d optin];
    else
        options = [robot.plotopt3d optin];
    end

    % parse the options
    [opt,args] = tb_optparse(opt, options);
    if ~isempty(args)
        error(['unknown option: ' args{1}]);
    end

    if ~isempty(opt.fps)
        opt.delay = 1/opt.fps;
    end
    % figure the size of the figure

    if isempty(opt.workspace)
        %
        % simple heuristic to figure the maximum reach of the robot
        %
        L = robot.links;
        if any(L.isprismatic)
            error('Prismatic joint(s) present: requires the ''workspace'' option');
        end
        reach = 0;
        for i=1:robot.n
            reach = reach + abs(L(i).a) + abs(L(i).d);
        end

%         if opt.wrist
%             reach = reach + 1;
%         end

        % if we have a floor, quantize the reach to a tile size
        if opt.tiles
            reach = opt.tilesize * ceil(reach/opt.tilesize);
        end

        % now create a 3D volume based on this reach
        opt.ws = [-reach reach -reach reach -reach reach];

        % if a floorlevel has been given, ammend the 3D volume
        if ~isempty(opt.floorlevel)
            opt.ws(5) = opt.floorlevel;
        end
    else
        % workspace is provided
        reach = min(abs(opt.workspace));
        if opt.tiles
            % set xy limits to be integer multiple of tilesize
            opt.ws(1:4) = opt.tilesize * round(opt.workspace(1:4)/opt.tilesize);
            opt.ws(5:6) = opt.workspace(5:6);
        else
            opt.ws=opt.workspace;
        end
    end

    opt.reach = reach;

    % update the fundamental scale factor (given by the user as a multiplier) by a length derived from
    % the overall workspace dimension
    %  we need that a lot when creating the robot model
    opt.scale = opt.scale * reach/40;

    % deal with a few options that need to be stashed in the SerialLink object

    robot.delay = opt.delay;
    robot.loop = opt.loop;
end

% draw a tiled floor in the current axes
function create_tiled_floor(opt)

    xmin = opt.ws(1);
    xmax = opt.ws(2);
    ymin = opt.ws(3);
    ymax = opt.ws(4);

    % create a colored tiled floor
    xt = xmin:opt.tilesize:xmax;
    yt = ymin:opt.tilesize:ymax;
    Z = opt.floorlevel*ones( numel(yt), numel(xt));
    C = zeros(size(Z));
    [r,c] = ind2sub(size(C), 1:numel(C));
    C = bitand(r+c,1);
    C = reshape(C, size(Z));
    C = cat(3, opt.tile1color(1)*C+opt.tile2color(1)*(1-C), ...
        opt.tile1color(2)*C+opt.tile2color(2)*(1-C), ...
        opt.tile1color(3)*C+opt.tile2color(3)*(1-C));
    [X,Y] = meshgrid(xt, yt);
    surface(X, Y, Z, C, ...
        'FaceColor','texturemap',...
        'EdgeColor','none',...
        'CDataMapping','direct');
end


function tr_xform=cosmo_fmri_convert_xform(fmt, xform)
% convert xform code between numeric and string in fmri dataset
%
% tr_xform=cosmo_fmri_convert_xform(fmt, xform)
%
% Inputs:
%   fmt              one of:
%                    - 'nii' (nifti)
%                    - 'afni' (afni)
%                    - 'bv' (BrainVoyager)
%   xform            either
%                    - a string, in which it must be one of
%                       'scanner_anat','aligned_anat','talairach',
%                       'mni_152', 'unknown'
%                    - a number, in which case it must be the view type for
%                       nii (sform or qform) or afni (the first elment of
%                       SCENE_TYPE). Any number in bv corresponds with
%                       'unknown'.
%
% Output:
%   tr_xform         if the input is a string, then the output is the
%                    corresponding view type (numeric); and vice versa
%                    if the viewtype cannot be found, the string 'unknown'
%                    or the corresponding view type is returned
%
% Examples
%     % Number to string:
%
%     % - NIFTI
%     cosmo_fmri_convert_xform('nii',1)
%     %|| 'scanner_anat'
%     cosmo_fmri_convert_xform('nii',2)
%     %|| 'aligned_anat'
%     cosmo_fmri_convert_xform('nii',3)
%     %|| 'talairach'
%     cosmo_fmri_convert_xform('nii',4)
%     %|| 'mni_152'
%     % any unknown number returns 'scanner_anat'
%     cosmo_fmri_convert_xform('nii',0)
%     %|| 'scanner_anat'
%     cosmo_fmri_convert_xform('nii',NaN)
%     %|| 'scanner_anat'
%
%     % - AFNI
%     cosmo_fmri_convert_xform('afni',0)
%     %|| 'scanner_anat'
%     cosmo_fmri_convert_xform('afni',1)
%     %|| 'aligned_anat'
%     cosmo_fmri_convert_xform('afni',2)
%     %|| 'talairach'
%     % any unknown number returns 'scanner_anat'
%     cosmo_fmri_convert_xform('afni',10)
%     %|| 'scanner_anat'
%     cosmo_fmri_convert_xform('afni',NaN)
%     %|| 'scanner_anat'
%
%     % - BV
%     % any number returns 'talairach'
%     cosmo_fmri_convert_xform('bv',0)
%     %|| 'talairach'
%     cosmo_fmri_convert_xform('bv',NaN)
%     %|| 'talairach'
%
%     % String to number:
%
%     % - NIFTI
%     cosmo_fmri_convert_xform('nii','scanner_anat')
%     %|| 1
%     cosmo_fmri_convert_xform('nii','aligned_anat')
%     %|| 2
%     cosmo_fmri_convert_xform('nii','talairach')
%     %|| 3
%     cosmo_fmri_convert_xform('nii','mni_152')
%     %|| 4
%     cosmo_fmri_convert_xform('nii','unknown')
%     %|| 1
%
%     % - AFNI
%     cosmo_fmri_convert_xform('afni','scanner_anat')
%     %|| 0
%     cosmo_fmri_convert_xform('afni','aligned_anat')
%     %|| 1
%     cosmo_fmri_convert_xform('afni','talairach')
%     %|| 2
%     % treat as talairach
%     cosmo_fmri_convert_xform('afni','mni_152')
%     %|| 2
%     % unkown
%     cosmo_fmri_convert_xform('afni','unknown')
%     %|| 0
%
%     % - BV
%     % all are unknown in BV, because BV does not support this
%     cosmo_fmri_convert_xform('bv','scanner_anat')
%     %|| 0
%     cosmo_fmri_convert_xform('bv','aligned_anat')
%     %|| 0
%     cosmo_fmri_convert_xform('bv','talairach')
%     %|| 0
%     cosmo_fmri_convert_xform('bv','mni_152')
%     %|| 0
%     cosmo_fmri_convert_xform('bv','unknown')
%     %|| 0
%
%     % any other input gives an error
%     cosmo_fmri_convert_xform('unknown','talairach')
%     %|| error('unsupported format ''unknown''')
%     cosmo_fmri_convert_xform('unknown',1)
%     %|| error('unsupported format ''unknown''')
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #

    [x,y]=get_mapping(fmt);

    if isnumeric(xform)
        % convert numeric to string
        i=find(y==xform,1,'first');
        if isempty(i)
            tr_xform=get_default(x,y);
        else
            tr_xform=x{i};
        end

    elseif ischar(xform)
        % convert string to numeric
        i=find(cosmo_match(x,xform),1,'first');
        if isempty(i)
            [unused,tr_xform]=get_default(x,y);
        else
            assert(numel(i)==1);
            tr_xform=y(i);
        end
    else
        error('unsupported input');
    end

function [xd,yd]=get_default(x,y)
    i=find(isnan(y));
    assert(numel(i)==1);
    xd=x{i};

    msk=cosmo_match(x,xd);
    msk(i)=false;

    j=find(msk);
    assert(numel(j)==1);
    yd=y(j);

function [x,y]=get_mapping(fmt)
    if ~ischar(fmt)
        error('first argument must be a string');
    end

    % mapping from codes to indices
    switch fmt
        case 'nii'
            codes={'scanner_anat',1;...
                    'aligned_anat',2;...
                    'talairach',3;...
                    'mni_152',4;...
                    'scanner_anat',NaN}; % default

        case 'afni'
            codes={'scanner_anat',0;...
                   'aligned_anat',1;... % ACPC
                   'talairach',2;...
                   'mni_152',2;...
                   'scanner_anat',NaN}; % default

        case 'bv'
            codes={'talairach',0;...
                    'talairach',NaN}; %

        otherwise
            error('unsupported format ''%s''', fmt);
    end

    x=codes(:,1);
    y=cell2mat(codes(:,2));


function title = p08_title ( )

%*****************************************************************************80
%
%% P08_TITLE returns the title of problem 8.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, the title of the problem.
%
  title = 'Extrapolation test data';

  return
end


function [currentSol, allObjValues, allSolutions] = optimizeCbModelNLP(model, varargin)
% Optimizes constraint-based model using a non-linear objective
%
% USAGE:
%
%    [currentSol, allObjValues, allSolutions] = optimizeCbModelNLP(model, varargin)
%
% INPUT:
%    model:            COBRA model structure
%
% Optional inputs are parameter/value pairs
%
% OPTIONAL INPUT:
%    objFunction:      Name of the non-linear matlab function to be optimized (the
%                      corresponding m-file must be in the current matlab path)
%                      The function receives two arguments, the current flux
%                      vector, and the `NLPProblem` structure.
%    initFunction:     Name of the matlab function used to generate random initial
%                      starting points. The function will be supplied with two
%                      arguments: the model and a cell array of input arguments
%                      (specified in the initArgs parameter)
%    osenseStr:        Optimization direction ('max' or 'min'), this will
%                      override any mention in the model.
%    nOpt:             Number of independent optimization runs performed
%    objArgs:          Cell array of arguments that are supplied to the
%                      objective function as `objArguments` in the NLPProblem
%                      structure (i.e. the second element, will have a field
%                      `objArguments`.)
%    initArgs:         Cell array of arguments to the 'initFunction', will be
%                      provided as second input Argument to the `initFunction`
%    solveroptions:    A Struct with options for the solver used. This is
%                      specific to the solver in question, but the fields should
%                      relate to options accepted by the solver.
%
% OUTPUTS:
%    currentSol:       Solution structure
%    allObjValues:     Array of objective value of each iteration
%    allSolutions:     Array of flux distribution of each iteration
%
% .. Authors:
%       - Markus Herrgard 8/24/07
%       - Modified for new options in solveCobraNLP by Daniel Zielinski 3/19/10
%       - Changed the function to use parameter/value pairs, Thomas Pfau 07/22/17

global CBT_NLP_SOLVER
defaultosenseStr = 'max';
if isfield(model,'osenseStr')
       defaultosenseStr = model.osenseStr;
end
defaultObjFunction = 'NLPobjPerFlux';
defaultInitFunction = 'randomObjFBASol';

p = inputParser;
addRequired(p,'model',@isstruct)
addParamValue(p,'objFunction',defaultObjFunction,@ischar)
addParamValue(p,'initFunction',defaultInitFunction,@ischar)
addParamValue(p,'osenseStr',defaultosenseStr,@(x) strcmp(x,'min') | strcmp(x,'max'));
addParamValue(p,'nOpt',100,@(x) rem(x,1) == 0);
addParamValue(p,'objArgs',{},@iscell)
addParamValue(p,'initArgs',[],@iscell)
addParamValue(p,'solverOptions',[],@isstruct)

parse(p,model,varargin{:});

[osenseStr,objFunction,initFunction,nOpt,objArgs,initArgs,solverOptions] = ...
    deal( p.Results.osenseStr,p.Results.objFunction,p.Results.initFunction, ...
    p.Results.nOpt,p.Results.objArgs,p.Results.initArgs, p.Results.solverOptions);
%To assure, that we don't have any complications, we replace the model
%osenseStr during the processing.
model.osenseStr = osenseStr;

if strcmp(osenseStr,'max')
    osense = -1;
else
    osense = 1;
end
%Set some defaults for fmincon:

if isnumeric(solverOptions)
    if strcmp(CBT_NLP_SOLVER,'matlab')
        if verLessThan('matlab','9')
                solverOptions = struct('TolFun',1e-20);
           else
        solverOptions = struct('FunctionTolerance', 1e-20,'OptimalityTolerance',1e-20);
        end
    else
        solverOptions = struct();
    end

end
%Set default values, if they are not set.
if ~isfield(solverOptions,'iterationLimit')
    solverOptions.iterationLimit = 100000;
end

if ~isfield(solverOptions,'printLevel')
    solverOptions.printLevel = 3; %3 prints every iteration.  1 does a summary.  0 = silent.
end

%The same as above for the objective Function
if strcmp(initFunction,defaultInitFunction) && isnumeric(initArgs)
    solOpt = optimizeCbModel(model,osenseStr);
    %Minimum fraction of the objective function to select start points from
    %is 50% of the maximal objective
    initArgs = {osenseStr,0.5, 0.5 * solOpt.f};
else
    if isnumeric(initArgs)
        initArgs = {};
    end
end

[nMets,nRxns] = size(model.S);
NLPproblem = buildLPproblemFromModel(model);

NLPproblem.objFunction = objFunction;
NLPproblem.objArguments = objArgs;

% Current best solution
currentSol.f = osense*inf;
allObjValues = zeros(nOpt,1);
allSolutions = zeros(nRxns,nOpt);

NLPproblem.user.model = model; %pass the model into the problem for access by the nonlinear objective function

for i = 1:nOpt
    x0 = feval(initFunction,model,initArgs);
    NLPproblem.x0 = x0; %x0 now a cell within the NLP problem structure
    solNLP = solveCobraNLP(NLPproblem,solverOptions); %New function call
    %solNLP = solveCobraNLP(NLPproblem,[],objArgs); Old Code
    fprintf('%d\t%f\n',i,osense*solNLP.obj);
    allObjValues(i) = osense*solNLP.obj;
    allSolutions(:,i) = solNLP.full;
    if osense*solNLP.obj > currentSol.f
       currentSol.f = osense*solNLP.obj;
       currentSol.x = solNLP.full;
       currentSol.stat = solNLP.stat;
    end
end


im = iread('building2-1.png', 'grey');
idisp(im)
C = isift(im, 'nfeat', 200);

about C
C(1)
C(1).p

C(1).plot('y', 'scale', 16, 'clock')
idisp(im, 'dark')
C.plot('w', 'scale', 4, 'clock');

d = C(1).descriptor;
about d


function [a] = spm_uncat(x,a)
% converts a matrix into an array
% FORMAT [a] = spm_uncat(x,a)
% x - matrix
% a - cell array
%
% i.e. a = spm_uncat(spm_cat(a),a)
%
% see also spm_vec and spm_unvec
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_uncat.m 5219 2013-01-29 17:07:07Z spm $

% fill in varargout
%--------------------------------------------------------------------------
[p,q] = size(a);
for i = 1:p
    for j = 1:q
          m(i,j) = size(a{i,j},1);
          n(i,j) = size(a{i,j},2);
    end
end
m     = max(m',[],1);
n     = max(n ,[],1);
for i = find(m)
    y     = x(1:m(i),:);
    x     = x((m(i) + 1):end,:);
    for j = 1:q
        a{i,j} = y(:,1:n(j));
        y      = y(:,(n(j) + 1):end);
    end
end


function imResult = blendMode_CreateResult(imResult, C, offsetW, offsetH)
%% Combine the result of the blending to obtain the final image. This
%   function is used by every blend function.
%
% Input:
%       A       -       Base Image
%       B       -       Top Image
%   offsetW     -   move picture B horizontally in respect to the top-left
%                   corner of picture A. Default value = 1.
%   offsetH     -   move picture B vertically in respect to the top-left
%                   corner of picture A. Default value = 1.
%
% Output:
%       imResult    -   Result of the blending, having the same size of the
%                       Base Image A.
%

sW = offsetW;
eW = offsetW + size(C, 2) - 1;
sH = offsetH;
eH = offsetH + size(C, 1) - 1;

if offsetW < 1
    sW = 1;
    eW = size(C, 2);
end

if offsetH < 1
    sH = 1;
    eH = size(C, 1);
end

if ((sW <= eW) && (sH <= eH))
    imResult(sH : eH, sW : eW, :) = C;
end

end


function [tags] = sequence_get_tags(sequence, index)
% sequence_get_tags Returns all tags for a given frame
%
% Input:
% - sequence (structure): A valid sequence structure.
% - index (integer): A index of a frame.
%
% Output:
% - tags (cell): A cell array of strings. Names of tags for the given frame.

if (sequence.length < index || index < 1)
    tags = {};
else
    tags = sequence.tags.names(logical(sequence.tags.data(index, :)));
end;


% Wrapper Feature Selection Toolbox by Jingwei Too - 9/12/2020

function model = jfs(type,feat,label,opts)
switch type
  % 2020
  case 'mpa'  ; fun = @jMarinePredatorsAlgorithm;
  case 'gndo' ; fun = @jGeneralizedNormalDistributionOptimization;
  case 'sma'  ; fun = @jSlimeMouldAlgorithm;
  case 'eo'   ; fun = @jEquilibriumOptimizer;
  case 'mrfo' ; fun = @jMantaRayForagingOptimization;
  % 2019
  case 'aso'  ; fun = @jAtomSearchOptimization;
  case 'hho'  ; fun = @jHarrisHawksOptimization;
  case 'hgso' ; fun = @jHenryGasSolubilityOptimization;
  case 'pfa'  ; fun = @jPathFinderAlgorithm;
  case 'pro'  ; fun = @jPoorAndRichOptimization;
  % 2018
  case 'boa'  ; fun = @jButterflyOptimizationAlgorithm;
  case 'epo'  ; fun = @jEmperorPenguinOptimizer;
  case 'tga'  ; fun = @jTreeGrowthAlgorithm;
  % 2017
  case 'abo'  ; fun = @jArtificialButterflyOptimization;
  case 'ssa'  ; fun = @jSalpSwarmAlgorithm;
  case 'sbo'  ; fun = @jSatinBowerBirdOptimization;
  case 'wsa'  ; fun = @jWeightedSuperpositionAttraction;
  % 2016
  case 'ja'   ; fun = @jJayaAlgorithm;
  case 'csa'  ; fun = @jCrowSearchAlgorithm;
  case 'sca'  ; fun = @jSineCosineAlgorithm;
  case 'woa'  ; fun = @jWhaleOptimizationAlgorithm;
  % 2015
  case 'alo'  ; fun = @jAntLionOptimizer;
  case 'hlo'  ; fun = @jHumanLearningOptimization;
  case 'mbo'  ; fun = @jMonarchButterflyOptimization;
  case 'mfo'  ; fun = @jMothFlameOptimization;
  case 'mvo'  ; fun = @jMultiVerseOptimizer;
  case 'tsa'  ; fun = @jTreeSeedAlgorithm;
  % 2014
  case 'gwo'  ; fun = @jGreyWolfOptimizer;
  case 'sos'  ; fun = @jSymbioticOrganismsSearch;
  % 2012
  case 'fpa'  ; fun = @jFlowerPollinationAlgorithm;
  case 'foa'  ; fun = @jFruitFlyOptimizationAlgorithm;
  % 2009 - 2010
  case 'ba'   ; fun = @jBatAlgorithm;
  case 'fa'   ; fun = @jFireflyAlgorithm;
  case 'cs'   ; fun = @jCuckooSearchAlgorithm;
  case 'gsa'  ; fun = @jGravitationalSearchAlgorithm;
  % Traditional
  case 'abc'  ; fun = @jArtificialBeeColony;
  case 'hs'   ; fun = @jHarmonySearch;
  case 'de'   ; fun = @jDifferentialEvolution;
  case 'aco'  ; fun = @jAntColonyOptimization;
  case 'acs'  ; fun = @jAntColonySystem;
  case 'pso'  ; fun = @jParticleSwarmOptimization;
  case 'gat'  ; fun = @jGeneticAlgorithmTour;
  case 'ga'   ; fun = @jGeneticAlgorithm;
  case 'sa'   ; fun = @jSimulatedAnnealing;
end
tic;
model = fun(feat,label,opts);
% Computational time
t = toc;

model.t = t;
fprintf('\n Processing Time (s): %f % \n',t); fprintf('\n');
end


num = length(uLINK);

for n=1:num
    uLINK(n).sister = 0;
    uLINK(n).child  = 0;
end

for n=1:num
    mom = uLINK(n).mother;  % My mother
    if mom ~= 0
        if uLINK(mom).child == 0
            uLINK(mom).child = n;  % I am the first child.
        else
            eldest_sister = uLINK(mom).child;  % I have a sister.
            SetYoungestSister(eldest_sister,n);
        end
    end
end


function [ id, index ] = cvx_id( x )
id = x.id_;
index = x.index_;

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


classdef TestDenoise_TVL1
    %TestDenoise_TVL1

    properties (Constant)
        im = fullfile(mexopencv.root(),'test','lena.jpg');
    end

    methods (Static)
        function test_1
            img = cv.imread(TestDenoise_TVL1.im, ...
                'Grayscale',true, 'ReduceScale',2);
            images = repmat({img},1,5);
            out = cv.denoise_TVL1(images, 'Lambda',1.0, 'NIters',30);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_2
            % we use IMNOISE from Image Processing Toolbox
            if ~mexopencv.require('images')
                error('mexopencv:testskip', 'toolbox');
            end

            img = cv.imread(TestDenoise_TVL1.im, ...
                'Grayscale',true, 'ReduceScale',2);
            images = cell(1,5);
            for i=1:numel(images)
                images{i} = imnoise(img, 'gaussian');
            end
            out = cv.denoise_TVL1(images, 'Lambda',1.0, 'NIters',30);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_3
            img = cv.imread(TestDenoise_TVL1.im, ...
                'Grayscale',true, 'ReduceScale',2);
            images = cell(1,5);
            for i=1:numel(images)
                images{i} = make_noisy(img, 20, 0.02);
            end
            out = cv.denoise_TVL1(images);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

        function test_4
            img = cv.imread(TestDenoise_TVL1.im, ...
                'Grayscale',true, 'ReduceScale',2);
            images = cell(1,5);
            for i=1:numel(images)
                images{i} = make_spotty(img);
            end
            out = cv.denoise_TVL1(images);
            validateattributes(out, {class(img)}, {'size',size(img)});
        end

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

end

% https://github.com/opencv/opencv/blob/3.1.0/modules/photo/test/test_denoise_tvl1.cpp

function noisy = make_noisy(img, sigma, pepper_salt_ratio)
    noise = uint8(randn(size(img))*sigma + 128);
    noisy = uint8(double(img) + double(noise) - 128);
    noise = uint8((randn(size(noise))*2)*255);
    mask = randi([0 round(1/pepper_salt_ratio)], size(img), 'uint8');
    mask(:,1:fix(end/2)) = 1;
    noise(mask~=0) = 128;
    noisy = uint8(double(noisy) + double(noise) - 128);
end

function img = make_spotty(img, r, n)
    if nargin < 3, n = 1000; end
    if nargin < 2, r = 3; end
    for i=1:n
        x = randi([1 size(img,2)-r-1]);
        y = randi([1 size(img,1)-r-1]);
        img(x:x+r, y:y+r) = randi([0 1])*255;
    end
end


function vw = zoom3view(vw, resetFlag);
% Zooms the 3D view
%
% view = zoom3view(view, <resetFlag=0>);
%
% Allows the subject to click twice (corners of a rect) on one of
% the views of the brain, gets the new extent of view,  and sets the other
% axes to be consistent with the new zoom extent.
%
% Since you can only select a rectangular zoom range in one orientation
% (axial, coronal, sagittal), leaving the third dimension unconstrained,
% there are two options for how to update the zoom range. If you use the
% left mouse button when selecting the zoom range, the zoom will affect the
% third dimension, causing an isometric zoom range (equal size in each of
% three dimensions). E.g., if you zoom in on an axial slice, the
% superior <-> inferior range will be affected in addition to a <-> p and
% l <-> r directions. If you right or middle click when selecting the range,
% the zoom range will not be isometric (in the example above, the s <-> i
% range will be unchanged; also, a very narrow rectangle will make the
% other directions uneven, while left-clicking will force each direction to
% match the wider edge of the rectangle). It is only the second mouse click
% that determines whether the zoom is isometric or not.
%
% resetFlag: if 1, will reset the zoom to be the whole view size and
% update the axis bounds of the image. If 0 <default>, will get the zoom
% from the user input.
%
%
% 01/04 ras.
% 08/04 ras. Now makes the zoom range cubic by default (equal FOV
% in all directions) if the left mouse button is used, but uses
% an asymmetric zoom (each sub-view may be rectangular) if another
% button is used.
% 06/02 ras: now just updates zoom w/ AXIS command, rather than
% going through a full refresh. Also added resetFlag, so both
% zoom buttons have callbacks to this function (for Volume/Gray views).

dims = viewGet(vw,'Size');

if exist('resetFlag', 'var') & resetFlag==1
    %%%%%reset the zoom
    zoom = [1 dims(1); 1 dims(2); 1 dims(3)];
else
    %%%%%Get from UI
    [X, Y, button] = ginput(2);
    AX = [X(1) X(2) Y(1) Y(2)];

    % use the identity of the last button press
    % to determine if the axes should be isometric
    if button(end)==1
        isoAxes = 1;
    else
        isoAxes = 0;
    end

    % could use getCurSliceOri to get orientation,
    % but this would mean we'd have to allow zooming
    % only on the selected view axes (which is fairly
    % unimportant on a 3-view) -- so figure it out manually
    if isequal(vw.refreshFn, 'volume3View')
        if vw.ui.axiAxesHandle==gca,       ori = 1;
        elseif vw.ui.corAxesHandle==gca,   ori = 2;
        else                                 ori = 3;
        end
    else
        ori = getCurSliceOri(vw);
    end

    % update the zoom for those dimensions the user restricted
    zoom = vw.ui.zoom;
    switch ori
        case 1, % axial view was zoomed in on
            zoom(2,:) = [AX(3) AX(4)];
            zoom(3,:) = [AX(1) AX(2)];
        case 2, % coronal view was zoomed in on
            zoom(1,:) = [AX(3) AX(4)];
            zoom(3,:) = [AX(1) AX(2)];
        case 3, % sagittal view was zoomed in on
            zoom(1,:) = [AX(3) AX(4)];
            zoom(2,:) = [AX(1) AX(2)];
    end

    % make axes isometric, if selected
    if isoAxes==1
        % this is a bit tricky since we want the widest
        % field-of-view from the two selected directions,
        % but ignore the fov-size for the dimension
        % orthogonal to the orientation (e.g., if selected on
        % an axi slice, ignore the axial zoom range):
        fov = diff([X'; Y'],1,2);
        switch ori
            case 1, fov = [0; fov];
            case 2, fov = [fov(1); 0; fov(2)];
            case 3, fov = [fov; 0];
        end

        [maxFov, whichAxis] = max(fov);

        for ori = 1:3
            centerPt = mean(zoom(ori,:));
            zoom(ori,1) = centerPt - maxFov/2;
            zoom(ori,2) = centerPt + maxFov/2;
        end
    end
end

% bounds check
zoom(zoom<1) = 1;
upperBound = min(zoom(:,2), dims(:));
zoom(:,2) = upperBound;

% set the zoom
vw.ui.zoom = zoom;

% update the axes
if isequal(vw.refreshFn, 'volume3View')
    % 3-view
    axis(vw.ui.axiAxesHandle, [zoom(3,:) zoom(2,:)]);
    axis(vw.ui.corAxesHandle, [zoom(3,:) zoom(1,:)]);
    axis(vw.ui.sagAxesHandle, [zoom(2,:) zoom(1,:)]);
else
    % regular gray/volume view
    switch getCurSliceOri(vw)
        case 1, axis(vw.ui.mainAxisHandle, [zoom(3,:) zoom(2,:)]);
        case 2, axis(vw.ui.mainAxisHandle, [zoom(3,:) zoom(1,:)]);
        case 3, axis(vw.ui.mainAxisHandle, [zoom(2,:) zoom(1,:)]);
    end
end

return


function events = LoadEvents(filename)

%LoadEvents - Read events from file.
%
%  USAGE
%
%    events = LoadEvents(filename)
%
%    filename            event file name

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

events.time = [];
events.description = [];
if ~exist(filename),
	error(['File ''' filename ''' not found.']);
end

file = fopen(filename,'r');
if file == -1,
	error(['Cannot read ' filename ' (insufficient access rights?).']);
end

while ~feof(file),
	time = fscanf(file,'%f',1);
	if isempty(time),
		if feof(file), break; end
		error(['Failed to read events from ' filename ' (possibly an empty file).']);
	end
	events.time(end+1,1) = time;
	line = fgetl(file);
	start = regexp(line,'[^\s]','once');
	events.description{end+1,1} = sscanf(line(start:end),'%c');
end
fclose(file);

% Convert to seconds
if ~isempty(events.time), events.time(:,1) = events.time(:,1) / 1000; end


% std_erpimageplot() - Commandline function to plot cluster ERPimage or channel erpimage.
%
% Usage:
%   >> [STUDY] = std_erpimageplot(STUDY, ALLEEG, key1, val1, key2, val2);
%   >> [STUDY data times freqs pgroup pcond pinter] = ...
%                std_erpimageplot(STUDY, ALLEEG ...);
% Inputs:
%   STUDY      - EEGLAB STUDY set comprising some or all of the EEG datasets in ALLEEG.
%   ALLEEG     - global EEGLAB vector of EEG structures for the datasets in the STUDY.
%                Note: ALLEEG for a STUDY set is typically created using load_ALLEEG().
%
% Additional help:
% Inputs and output of this function are strictly identical to the std_erspplot().
% See the help message of this function for more information.
%
% See also: std_erspplot()
%
% Authors: Arnaud Delorme, UCSD/CERCO, August, 2011-

% Copyright (C) Arnaud Delorme, arno@ucsd.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 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 [STUDY, allitc, alltimes, allfreqs, pgroup, pcond, pinter, events] = std_erpimageplot(STUDY, ALLEEG, varargin)

if nargin < 2
    help std_erpimageplot;
    return;
end;

events = [];
STUDY = pop_erpimparams(STUDY, 'default');
if strcmpi(STUDY.etc.erpimparams.concatenate, 'off')

    % use std_erspplot for stats when concatenate is off
    [STUDY allitc alltimes allfreqs pgroup pcond pinter events] = std_erspplot(STUDY, ALLEEG, 'datatype', 'erpim', varargin{:});

else
    params = STUDY.etc.erpimparams;
    [ opt moreparams ] = finputcheck( varargin, { ...
        'design'      'integer' [] STUDY.currentdesign;
        'topotime'    'real'    [] params.topotime;
        'topotrial'  'real'     [] params.topotrial;
        'timerange'   'real'    [] params.timerange;
        'trialrange'  'real'    [] params.trialrange;
        'colorlimits' 'real'    [] params.colorlimits; % ERPimage
        'statistics'  'string'  [] params.statistics;
        'groupstats'  'string'  [] params.groupstats;
        'condstats'   'string'  [] params.condstats;
        'threshold'   'real'    [] params.threshold;
        'naccu'       'integer' [] params.naccu;
        'mcorrect'    'string'  [] params.mcorrect;
        'erpimageopt' 'cell'    [] params.erpimageopt;
        'concatenate'  'string' { 'on','off' }  params.concatenate;
        'channels'    'cell'    []              {};
        'clusters'    'integer' []              [];
        'comps'       {'integer','string'}  []              []; % for backward compatibility
        'plotsubjects' 'string' { 'on','off' }  'off';
        'plotmode'    'string' { 'normal','condensed','none' }  'normal';
        'subject'     'string'  []              '' }, 'std_erpimageplot', 'ignore');

    if ~isempty(opt.topotime) && ~isempty(opt.topotrial)
        error('Cannot plot topography when ERP-image is in trial concatenation mode');
    end;
    if ~isempty(opt.trialrange)
        error('Cannot select trial range when ERP-image is in trial concatenation mode');
    end;
    if strcmpi(opt.groupstats, 'on') || strcmpi(opt.condstats, 'on')
        disp('Warning: cannot perform statistics when ERP-image is in trial concatenation mode');
    end;

    % options
    if ~isempty(opt.colorlimits), options = { 'caxis' opt.colorlimits opt.erpimageopt{:} };
    else                          options = { 'cbar' 'on' opt.erpimageopt{:}  };
    end;

    if ~isempty(opt.channels)
        [STUDY allerpimage alltimes alltrials tmp events] = std_readersp(STUDY, ALLEEG, 'channels', opt.channels, 'infotype', 'erpim', 'subject', opt.subject, ...
            'concatenate', 'on', 'timerange', opt.timerange, 'design', opt.design);

        % get figure title
        % ----------------
        locs = eeg_mergelocs(ALLEEG.chanlocs);
        locs = locs(std_chaninds(STUDY, opt.channels));
        allconditions = STUDY.design(opt.design).variable(1).value;
        allgroups     = STUDY.design(opt.design).variable(2).value;
        alltitles = std_figtitle('condnames', allconditions, 'cond2names', allgroups, 'chanlabels', { locs.labels }, ...
            'subject', opt.subject, 'valsunit', 'ms', 'datatype', 'ERPIM');

        figure;
        for iCond = 1:length(allconditions)
            for iGroup = 1:length(allgroups)
                tmpevents = events{iCond, iGroup};
                if isempty(tmpevents), tmpevents = zeros(1, size(allerpimage{iCond, iGroup},2)); end;
                subplot(length(allconditions), length(allgroups), (iCond-1)*length(allgroups) + iGroup);

                % use color scale for last plot
                if ~isempty(opt.colorlimits) && iCond == length(allconditions) && iGroup == length(allgroups)
                    options = { options{:} 'cbar' 'on' };
                end;
                erpimage(allerpimage{iCond, iGroup}, tmpevents, alltimes, alltitles{iCond, iGroup}, params.smoothing, params.nlines, options{:});
            end;
        end;

    else
        for cInd = 1:length(opt.clusters)
            [STUDY allerpimage alltimes alltrials tmp events] = std_readersp(STUDY, ALLEEG, 'clusters', opt.clusters(cInd), 'infotype', 'erpim', 'subject', opt.subject, ...
                'concatenate', 'on', 'timerange', opt.timerange, 'design', opt.design);
            % get figure title
            % ----------------
            locs = eeg_mergelocs(ALLEEG.chanlocs);
            locs = locs(std_chaninds(STUDY, opt.channels));
            allconditions = STUDY.design(opt.design).variable(1).value;
            allgroups     = STUDY.design(opt.design).variable(2).value;
            alltitles = std_figtitle('condnames', allconditions, 'cond2names', allgroups, 'clustname', STUDY.cluster(opt.clusters(cInd)).name, ...
                'subject', opt.subject, 'valsunit', 'ms', 'datatype', 'ERPIM');

            figure;
            for iCond = 1:length(allconditions)
                for iGroup = 1:length(allgroups)
                    tmpevents = events{iCond, iGroup};
                    if isempty(tmpevents), tmpevents = zeros(1, size(allerpimage{iCond, iGroup},2)); end;
                    subplot(length(allconditions), length(allgroups), (iCond-1)*length(allgroups) + iGroup);

                    % use color scale for last plot
                    if ~isempty(opt.colorlimits) && iCond == length(allconditions) && iGroup == length(allgroups)
                        options = { options{:} 'cbar' 'on' };
                    end;
                    erpimage(allerpimage{iCond, iGroup}, tmpevents, alltimes, alltitles{iCond, iGroup}, params.smoothing, params.nlines, options{:});
                end;
            end;
        end;
    end;
end;


function [node,elem]=readasc(fname)
%
% [node,elem]=readasc(fname)
%
% read FreeSurfer ASC mesh format
%
% author: Qianqian Fang <q.fang at neu.edu>
% date: 2009/04/02
%
% input:
%      fname: name of the asc file
%
% output:
%      node: node positions of the mesh
%      elem: element list of the mesh
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

node=[];
elem=[];
fid=fopen(fname,'rt');
if(fid==-1)
        error(['can not read file ' fname]);
end

line=fgetl(fid); % the first line is #!ascii ....
dim=fscanf(fid,'%d',2);
node=fscanf(fid,'%f',[4,dim(1)])';
elem=fscanf(fid,'%f',inf);
fclose(fid);

if(length(elem)==4*dim(2))
    elem=reshape(elem,[4,dim(2)])';
elseif(length(elem)==8*dim(2))
    elem=reshape(elem,[8,dim(2)])';
end

if(~any(node(:,end)))
	node=node(:,1:end-1);
end
if(~any(elem(:,end)))
        elem=elem(:,1:end-1);
end

elem=elem+1;


%% t_mrd
%
% Illustrates how to initiate mrDiffusion with scripts.
%
% There are several examples of loading data or adjusting the view by using
% the window handles and refreshing the screen.
%
% Additional mrDiffusion tutorial scripts are named t_mrd<XXXXX>.
%
% See also: t_mrdFibers, t_mrdTensor, t_mrdViewFibers, t_mrdDWI, dtiSet, dtiGet, dwiGet,
% dwiSet, dwiCreate
%
% (c) Stanford VISTA Team, 2011

%% You can initiate a mrDiffusion window with no data

% We use dtiF to store the figure number and dtiH to store the window
% handles.
[dtiF, dtiH] = mrDiffusion;

% Close the figure.  This  renders the dtiH
% (handles to objects in the window) dead.
close(dtiF);
clear dtiH

% You can also get the handles this way
dtiF = mrDiffusion;
dtiH = guidata(dtiF);

% When you make a change to the data in the figure, by adjusting the dtiH
% (window handles), you reset the data by the call
guidata(dtiF,dtiH);

% Let's start again
close(dtiF);

%% Vistadata contains a sample data set with a calculated dt6

% Load the sample data set and set the window to invisible
dataDir = fullfile(mrvDataRootPath,'diffusion','sampleData');
dt6Name = fullfile(dataDir,'dti40','dt6.mat');
[dtiF, dtiH] = mrDiffusion('off',dt6Name);

% Make the window visible
figure(dtiF)

% Normally, we interact with the diffusion data using dtiGet/Set or
% dwiGet/Set.  In this case, we have opened only a diffusion tensor imaging
% structure through this window.  Hence, we interact with the data using
% dtiGet.  We can find out which image is displayed in the background using
dtiGet(dtiH,' background name')
d = dtiGet(dtiH,' background data');
showMontage(d)

% Close the window, clear the handles
close(dtiF)

%% You can open the data and leave the window visible this way
[dtiF,dtiH] = mrDiffusion('on',dt6Name);

% Reset
close(dtiF)

%% Load some fibers

% Open the window
[dtiF,dtiH] = mrDiffusion('on',dt6Name);

% Load a sample fiber group
fgName = fullfile(mrvDataRootPath,'diffusion','sampleData','fibers','leftArcuate.pdb');
fg = mtrImportFibers(fgName);

% Attach the fiber group to the handles
dtiH = dtiSet(dtiH,'current fiber group',fg);

% We interact with the window handles using the Matlab set/get functions
% applied to the handles.
set(dtiH.cbShowFibers,'Value',1)
guidata(dtiF,dtiH)

% After setting and attaching, you refresh the window this way
dtiH = dtiRefreshFigure(dtiH);

%% Make the fibers invisible
set(dtiH.cbShowFibers,'Value',0)
guidata(dtiF,dtiH)
dtiH = dtiRefreshFigure(dtiH);

% See the script t_mrdViewFibers for examples of viewing the fibers with
% the mrMesh viewer

%% Read mrDiffusion figure handle settings

overlayThresh = get(dtiH.slider_overlayThresh, 'Value');
overlayAlpha = str2double(get(dtiH.editOverlayAlpha, 'String'));
curOvNum = get(dtiH.popupOverlay,'Value');

%% Find a mrDiffusion window
dtiF = dtiGet([],'main figure');
close(dtiF)

%% End