function f = viewfig(obs,pred,flag)
%CREATEFIGURE1(RES_VERF1,YMATRIX1)
%  RES_VERF1:  vector of x data
%  YMATRIX1:  matrix of y data

%  Auto-generated by MATLAB on 10-Jun-2008 18:14:54
%load mytest
YMatrix1 = [obs pred];
x=1:length(obs);
n = length(obs);
% res_verf1=res_verf(:,1);
% YMatrix1 = res_verf(:,2:3);
% Create figure
f = figure('PaperSize',[20.98 29.68],'Position',[50 300 600 500],'visible',flag);
%f = figure('PaperSize',[20.98 29.68]);
% Create axes
axes1 = axes('Parent',f,'Position',[0.08043 0.6038 0.875013 0.3554]);
box('on');
hold('all');

% Create multiple lines using matrix input to plot
plot1 = plot(x,YMatrix1,'Parent',axes1);
set(plot1(1),'DisplayName','observed');
set(plot1(2),'DisplayName','predicted');
set(plot1(1),'color',[0.5 0.5 0.5],'LineWidth',2)
set(plot1(2),'color','b')

xlim(axes1,[0 n])
ylim(axes1,[0 max(max(YMatrix1))])
% Create xlabel
xlabel('Time (hr)');

% Create ylabel
ylabel('Median of discharge');
%legend(axes1,'Observed','Predicted')

%% Zoomed axis
x=4200:4500;

% Create axes
axes2 = axes('Parent',f,'Position',[0.08043 0.09201 0.4089 0.4118]);
% Uncomment the following line to preserve the X-limits of the axes
% xlim([4200 4500]);
box('on');
hold('all');

% Create multiple lines using matrix input to plot
plot2 = plot(x,YMatrix1(x,:),'Parent',axes2);
set(plot2(1),'color',[0.5 0.5 0.5],'LineWidth',2)
set(plot2(2),'color','b')
ylim(axes2,[0 max(max(YMatrix1(x,:)))])
x=4700:5000;
% Create axes
axes3 = axes('Parent',f,'Position',[0.5703 0.09201 0.3835 0.4133]);
% Uncomment the following line to preserve the X-limits of the axes
% xlim([4700 5000]);
box('on');
hold('all');

% Create multiple lines using matrix input to plot
plot3 = plot(x,YMatrix1(x,:),'Parent',axes3);
set(plot3(1),'color',[0.5 0.5 0.5],'LineWidth',2)
set(plot3(2),'color','b')
ylim(axes3,[0 max(max(YMatrix1(x,:)))])
% Create legend
legend(axes1,'show','Location','Best');
%print -dtiff -r900 picture1
% [pathstr, name, ext, versn] = fileparts(figName) ;
% switch  ext
%     case '.fig'
%         saveas(f,figName)
%     case '.tiff'
%       print(f,'-dtiff', '-r900', figName)
%     case '.emf'
%         print(f,'-dmeta', '-r2400', figName)
%     case '.eps'
%         print(f,'-depsc', '-r2400', figName)
%     otherwise
%         error('does not know the figure format')
% end
%delete(f)


function y = conFun(x)
y = [x(1)-1;x(2)];


function neqn = p39_neqn ( )

%*****************************************************************************80
%
%% P39_NEQN returns the number of equations for problem P39.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer NEQN, the number of equations.
%
  neqn = 1;

  return
end


% POP_SUBCOMP - remove specified components from an EEG dataset.
%                 and subtract their activities from the data. Else,
%                 remove components already marked for rejection. When used
%                 with the options 'keepcomp', the function will retain [1]
%                 or reject[0] the components provided as input.
% Usage:
%   >> OUTEEG = pop_subcomp( INEEG ); % pop-up window mode
%   >> OUTEEG = pop_subcomp( INEEG, components, plotag);
%   >> OUTEEG = pop_subcomp( INEEG, components, plotag, keepcomp);
%
% Pop-up window interface:
%   "Component(s) to remove ..." - [edit box] Array of components to
%                remove from the data. Sets the 'components' parameter
%                in the command line call (see below).
%   "Component(s) to retain ..." - [edit box] Array of components to
%                to retain in the data. Sets the 'components' parameter in
%                the command line call. Then, comp_to_remove = ...
%                    setdiff([1:size(EEG.icaweights,1)], comp_to_keep). See
%                    option 'keepcomp' for command line call.
%                Overwrites "Component(s) to remove" (above).
% Command line inputs:
%   INEEG      - Input EEG dataset.
%   components - Array of components to remove from the data. If empty,
%                 remove components previously marked for rejection (e.g.,
%                 EEG.reject.gcompreject).
%   plotag     - [0|1] Display the difference between original and processed
%                dataset. 1 = Ask for confirmation. 0 = Do not ask. {Default: 0}
%   keepcomp   - [0|1] If [1] will retain the components provided by the
%                input variable 'components', [0] will reject them. Option
%                intended to be used only with the components provided in
%                'components', and not with components marked for rejection
%                {Default: 0}
% Outputs:
%   OUTEEG     - output dataset.
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: COMPVAR

% Copyright (C) 2001 Arnaud Delorme, Salk Institute, arno@salk.edu
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% 01-25-02 reformated help & license -ad
% 02-15-02 propagate ica weight matrix -ad sm jorn

function [EEG, com] = pop_subcomp( EEG, components, plotag, keepflag)

com='';
if nargin < 1
   help pop_subcomp;
   return;
end
if nargin < 3
	plotag = 0;
end
if nargin < 4
    keepflag = 0;
end

if nargin < 2
    components = [];
	% popup window parameters
	% -----------------------
    res = 'Manual rej.';
    if any(cellfun(@(x)any(x.gcompreject), { EEG.reject }))
        if length(EEG) == 1
            compStr = sprintf('%d,', find(EEG.reject.gcompreject == 1));
            msg = sprintf('Components [%s] flagged for rejection.', compStr(1:end-1));
            res = questdlg2(strvcat(msg, 'Do you want to remove these components?', 'Note: we recommend removing components in STUDY instead'), 'Remove components from data', 'Cancel', 'Manual rej.', 'Yes', 'Cancel');
        else
            msg = 'Components flagged for rejection detected in some datasets.';
            res = questdlg2(strvcat(msg, 'Do you want to remove these components?', 'Note: we recommend removing components in STUDY instead'), 'Remove components from data', 'Cancel', 'Yes', 'Cancel');
        end
        if strcmpi(res, 'Cancel')
            return;
        end
        if strcmpi(res, 'Yes')
            components = '';
        end
    else
        if length(EEG) > 1
            warndlg2(strvcat('You have multiple datasets selected and no components', ...
                'flagged for rejection. Flag components first.'));
            return;
        end
    end

    if strcmpi(res, 'Manual rej.')
        if ~isempty(EEG.reject.gcompreject)
            components = find(EEG.reject.gcompreject == 1);
            components = components(:)';
            %promptstr    = { ['Components to subtract from data' 10 '(default: pre-labeled components to reject):'] };
        else
            components = [];
        end
        uilist    = { { 'style' 'text' 'string' 'Note: for group level analysis, remove components in STUDY' } ...
                      { 'style' 'text' 'string' 'List of component(s) to remove from data' } ...
                      { 'style' 'edit' 'string' int2str(components) } ...
                      { 'style' 'text' 'string' 'Or list of component(s) to retain' } ...
                      { 'style' 'edit' 'string' '' } ...
                      };
        geom = { 1 [2 0.7] [2 0.7] };
        result       = inputgui( 'uilist', uilist, 'geometry', geom, 'helpcom', 'pophelp(''pop_subcomp'')', ...
                                         'title', 'Remove components from data -- pop_subcomp()');
        if length(result) == 0 return; end
        components   = eval( [ '[' result{1} ']' ] );
        if ~isempty(result{2})
            componentsOld = components;
            components   = eval( [ '[' result{2} ']' ] );
            if isequal(components, componentsOld)
                components = [];
            end
            keepflag = 1; %components  = setdiff_bc([1:size(EEG.icaweights,1)], components);
        end
    end
end

% process multiple datasets
% -------------------------
if length(EEG) > 1
    if nargin < 2
        [ EEG, com ] = eeg_eval( 'pop_subcomp', EEG, 'params', { components, plotag, keepflag }, 'warning', 'on' );
    else
        [ EEG, com ] = eeg_eval( 'pop_subcomp', EEG, 'params', { components, plotag, keepflag } );
    end
    if isempty( components )
        com = [ com ' % [] or '' means removing components flagged for rejection' ];
    end
    return;
end

componentsOri = components;
if isempty(components)
    if ~isempty(EEG.reject.gcompreject)
        components = find(EEG.reject.gcompreject == 1);
    else
        fprintf('Warning: no components specified, no rejection performed\n');
        return;
    end
else
    if keepflag == 1; components  = setdiff_bc([1:size(EEG.icaweights,1)], components); end
    if (max(components) > size(EEG.icaweights,1)) || min(components) < 1
        error('Component index out of range');
    end
end

fprintf('Computing projection and removing %d components ....\n', length(components));
component_keep = setdiff_bc(1:size(EEG.icaweights,1), components);
compproj = EEG.icawinv(:, component_keep)*eeg_getdatact(EEG, 'component', component_keep, 'reshape', '2d');
compproj = reshape(compproj, size(compproj,1), EEG.pnts, EEG.trials);

%fprintf( 'The ICA projection accounts for %2.2f percent of the data\n', 100*varegg);

if nargin < 2 || plotag ~= 0

    ButtonName = 'continue';
    while ~strcmpi(ButtonName, 'Cancel') && ~strcmpi(ButtonName, 'Accept')
        ButtonName=questdlg2( [ 'Please confirm your choice. Are you sure you want to remove the selected components from the data?' ], ...
                             'Confirmation', 'Cancel', 'Plot ERPs', 'Plot single trials', 'Accept', 'Accept');
        if strcmpi(ButtonName, 'Plot ERPs')
            if EEG.trials > 1
                tracing  = [ squeeze(mean(compproj,3)) squeeze(mean(EEG.data(EEG.icachansind,:,:),3))];
                figure;
                plotdata(tracing, EEG.pnts, [EEG.xmin*1000 EEG.xmax*1000 0 0], ...
                    'Trial ERPs (blue) with and (red) without these components');
            else
                warndlg2('Cannot plot ERPs for continuous data');
            end
        elseif strcmpi(ButtonName, 'Plot single trials')
        	eegplot( EEG.data(EEG.icachansind,:,:), 'srate', EEG.srate, 'title', 'Black = channel before rejection; red = after rejection -- eegplot()', ...
            	 'limits', [EEG.xmin EEG.xmax]*1000, 'data2', compproj);
        end
    end
    switch ButtonName
        case 'Cancel'
        	disp('Operation cancelled');
        	return;
        case 'Accept'
       		disp('Components removed');
    end % switch
end
EEG.data(EEG.icachansind,:,:) = compproj;
EEG.setname = [ EEG.setname ' pruned with ICA'];
EEG.icaact  = [];
goodinds    = setdiff_bc(1:size(EEG.icaweights,1), components);
EEG.icawinv     = EEG.icawinv(:,goodinds);
EEG.icaweights  = EEG.icaweights(goodinds,:);
EEG.specicaact  = [];
EEG.specdata    = [];
EEG.reject      = [];

if isfield(EEG.etc, 'ic_classification')
    if isfield(EEG.etc.ic_classification, 'ICLabel')
        if isfield(EEG.etc.ic_classification.ICLabel, 'classifications')
            if ~isempty(EEG.etc.ic_classification.ICLabel.classifications)
                EEG.etc.ic_classification.ICLabel.classifications = EEG.etc.ic_classification.ICLabel.classifications(goodinds,:);
            end
        end
    end
end

try
    EEG.dipfit.model = EEG.dipfit.model(goodinds);
catch, end

com = sprintf('EEG = pop_subcomp( EEG, [%s], %d);', int2str(componentsOri(:)'), plotag);
if isempty( components )
    com = [ com ' % [] means removing components flagged for rejection' ];
end
return;


function test_suite = test_polylinePoint
%TESTPOLYLINEPOINT  One-line description here, please.
%   output = testPolylinePoint(input)
%
%   Example
%   testPolylinePoint
%
%   See also
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2009-06-16,    using Matlab 7.7.0.471 (R2008b)
% Copyright 2009 INRA - Cepia Software Platform.
% Licensed under the terms of the LGPL, see the file "license.txt"

test_suite = functiontests(localfunctions);

function testSquare(testCase) %#ok<*DEFNU>

p1 = [10 10];
p2 = [20 10];
p3 = [20 20];
p4 = [10 20];
square = [p1;p2;p3;p4];
testCase.assertEqual(polygonPoint(square, 0), p1, 'AbsTol', .01);
testCase.assertEqual(polygonPoint(square, 1), p2, 'AbsTol', .01);
testCase.assertEqual(polygonPoint(square, 2), p3, 'AbsTol', .01);
testCase.assertEqual(polygonPoint(square, 3), p4, 'AbsTol', .01);

testCase.assertEqual(polygonPoint(square, 4), p1);
testCase.assertEqual(polygonPoint(square, 3.5), centroid([p1;p4]), 'AbsTol', .01);


function [O,lo] = update_order_greedy(A)
    % greedy method for updating order
    K = size(A,2);
    if ~(size(A,1) == K)
        A = A'*A;
    end

    A = A>0;
    A(1:K+1:K^2) = 0;

    O{1} = 1;
    lo(1) = 1;
    for i = 2:K
       cont = true;
       for j = 1:length(O)
           if ~any(A(i,O{j}))
               O{j} = [O{j},i];
               lo(j) = lo(j) + 1;
               cont = false;
               break;
           end
       end
       if cont
           O{length(O)+1} = j;
           lo = [lo,1];
       end
    end
end


function masks = txt2img( strings, h, txtPrp )
% Convert text string to a binary image.
%
% For each input string, creates a binary matrix of dimensions [hxw] that
% when displayed as an image shows the string. See example for usage.
% First, uses text() to display the text using Matlab's display
% functionality. Next uses getframe() to capture the screen and crops the
% resulting image appropriately.
%
% USAGE
%  masks = txt2img( strings, h, [txtPrp] )
%
% INPUTS
%  strings  - {1xn} text string or cell array of text strings to convert
%  h        - font height in pixels
%  txtPrp   - [] additional properites for call to "text"
%
% OUTPUTS
%  masks    - {1xn} binary image masks of height h for each string
%
% EXAMPLE
%  masks=txt2img('hello world',100); im(masks{1})
%
% See also CHAR2IMG, GETFRAME, TEXT
%
% Piotr's Computer Vision Matlab Toolbox      Version 2.35
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]

% set up blank figure to which to write text
if(nargin<3 || isempty(txtPrp)), txtPrp={}; end
txtPrp = [txtPrp 'units','pixels', 'position',[2 2], 'FontUnits', ...
  'pixels', 'fontsize',h-2, 'VerticalAlignment','Bottom', 'string'];
ss=get(0,'ScreenSize'); w=ss(3)-250;
hf=figure; clf; imshow(ones([h-1 w]));
% write each string and use screen capture to save image
if(~iscell(strings)), strings={strings}; end
n=length(strings); masks=cell(1,n);
for s=1:n
  ht=text(txtPrp{:},strings{s}); pos=get(ht,'Extent');
  if(pos(3)>w), error('string does not fit on screen'); end
  M=getframe(gca); M=M.cdata; M=M(:,1:pos(3),1); M=uint8(M>100);
  k=find(sum(M==0)>0); if(k), M=M(:,max(1,k(1)-1):min(end,k(end)+1)); end
  masks{s}=M; delete(ht);
end; close(hf);
end


function h = showsolutionpoly(node,elem,u,varargin)
%% SHOWSOLUTIONPOLY plots the solution u on a polygonal mesh in 2-D.
%
%    showmeshpoly(node,elem, u) displays u on a polygonal mesh. elem{j} is a cell
%    array with j-th cell representing the j-th element.
%
%    showmeshpoly(node,elem,u,viewangle) changes the display angle. The
%    deault view angle on planar meshes is view(2) and view(3) for surface
%    meshes.
%
%   Example:
%
%     load polygonunstruct
%     u = @(p) sin(2*pi*p(:,1)).*cos(2*pi*p(:,2));
%     uI = u(node);
%     showsolutionpoly(node,elem,uI);
%
%   See also showmesh, showboundary3, showmeshpoly.
%
% Added by Shuhao Cao.
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

V = [node, u];
elemVertexNumber = cellfun('length',elem); % the number of vertices per element
for Nv = min(elemVertexNumber):max(elemVertexNumber)
    idx = (elemVertexNumber == Nv); % index of elements with Nv vertices
    elemNv = cell2mat(elem(idx));
    if size(elemNv,2) == 1
        elemNv = reshape(elemNv,[Nv,nnz(idx)])';
    end
    h = patch('faces',elemNv,'vertices',V);
    hold on;
    set(h,    'FaceVertexCData',u,...
              'Facecolor','interp',...
              'Edgecolor','k',...
              'Edgealpha',1/log(size(node,1)),...
              'FaceAlpha',0.65);
   %%
   if (nargin>3) && ~isempty(varargin) % set display property
       if isnumeric(varargin{1})
           view(varargin{1});
           if nargin>4
               set(h,varargin{2:end});
           end
       else
           set(h,varargin{1:end});
       end
   end
end
view(3); axis tight; grid on;
camproj('perspective');
hold off
%%


function s = hms2point(s)
% convert Herman – Mauguin (International) Symbol to point group
%
% Input
%  s - Herman – Mauguin (International) space group symbol
%
% Output
%  s - international point group symbol
%
% See also
%

% ignore first letter
assert(any(strcmp(s(1),{'A','B','C','F','I','P','R'})));
s = s(2:end);

% convert all planes to mirror planes
rep = {'a','b','c','d','n'};
for i = 1:length(rep)
  s = strrep(s,rep{i},'m');
end

% remove two consecutive numbers if the second is a divisor of the first
% eg. 63 62 42 32
if length(regexp(s,'[\dm]'))>=4
  ind = regexp(s,'\d\d');
  if ~isempty(ind)
    ind = ind(1);
    n1 = str2num(s(ind)); %#ok<ST2NM>
    n2 = str2num(s(ind+1)); %#ok<ST2NM>
    if n1 > n2, s(ind+1) = [];end
  end
end

% ignore 1
if ~isempty(regexp(s,'[m2-6]')), s = strrep(s,'1','');end

% clear all spaces
s = strrep(s,' ','');

% remove all upcase letter
ind = s==upper(s) & s~=lower(s);
s(ind) = [];

s= regexprep(s,'[:.]','');  % occurs sometimes

if isempty(s), s = '1';end


function varargout = process_canoltymap2( varargin )
% This function generates Canolty like maps (Science 2006, figure 1) for the input signal.

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

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Canolty maps (FileB=MaxPAC)';
    sProcess.Category    = 'File2';
    sProcess.SubGroup    = 'Frequency';
    sProcess.Index       = 661;
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'raw',      'data',     'results',  'matrix'};
    sProcess.OutputTypes = {'timefreq', 'timefreq', 'timefreq', 'timefreq'};
    sProcess.nInputs     = 2;
    sProcess.nMinFiles   = 1;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/Resting#Canolty_maps';
    % ==== INPUT ====
    sProcess.options.label_in.Comment = 'Input options:';
    sProcess.options.label_in.Type    = 'label';
    % === TIME WINDOW
    sProcess.options.timewindow.Comment = 'Time window: ';
    sProcess.options.timewindow.Type    = 'timewindow';
    sProcess.options.timewindow.Value   = [];
    % === SENSOR SELECTION
    sProcess.options.target_data.Comment    = 'Sensor types or names (empty=all): ';
    sProcess.options.target_data.Type       = 'text';
    sProcess.options.target_data.Value      = 'MEG, EEG';
    sProcess.options.target_data.InputTypes = {'data', 'raw'};
    % === SCOUTS SELECTION
    sProcess.options.scouts.Comment    = 'Use scouts';
    sProcess.options.scouts.Type       = 'scout_confirm';
    sProcess.options.scouts.Value      = {};
    sProcess.options.scouts.InputTypes = {'results'};
    % === SCOUT FUNCTION ===
    sProcess.options.scoutfunc.Comment    = {'Mean', 'Max', 'PCA', 'Std', 'All', 'Scout function:'};
    sProcess.options.scoutfunc.Type       = 'radio_line';
    sProcess.options.scoutfunc.Value      = 1;
    sProcess.options.scoutfunc.InputTypes = {'results'};
    % === SCOUT TIME ===
    sProcess.options.scouttime.Comment    = {'Before', 'After', 'When to apply the scout function:'};
    sProcess.options.scouttime.Type       = 'radio_line';
    sProcess.options.scouttime.Value      = 1;
    sProcess.options.scouttime.InputTypes = {'results'};
    % === ROW NAMES
    sProcess.options.target_tf.Comment    = 'Row names or indices (empty=all): ';
    sProcess.options.target_tf.Type       = 'text';
    sProcess.options.target_tf.Value      = '';
    sProcess.options.target_tf.InputTypes = {'timefreq', 'matrix'};

    % ==== ESTIMATOR ====
    sProcess.options.label_method.Comment = '
Estimator options:';
    sProcess.options.label_method.Type    = 'label';
    % === EPOCH TIME
    sProcess.options.epochtime.Comment = 'Epoch time: ';
    sProcess.options.epochtime.Type    = 'range';
    sProcess.options.epochtime.Value   = {[-0.5, 0.5], 'ms', []};
    % === MAX_BLOCK_SIZE
    sProcess.options.max_block_size.Comment = 'Number of signals to process at once: ';
    sProcess.options.max_block_size.Type    = 'value';
    sProcess.options.max_block_size.Value   = {100, ' ', 0};

    % ==== OUTPUT ====
    sProcess.options.label_out.Comment = '
Output configuration:';
    sProcess.options.label_out.Type    = 'label';
    % === SAVE AVERAGED LOW-FREQ SIGNALS
    sProcess.options.save_erp.Comment = 'Save averaged low frequency signals';
    sProcess.options.save_erp.Type    = 'checkbox';
    sProcess.options.save_erp.Value   = 1;
end

%% ===== FORMAT COMMENT =====
function Comment = FormatComment(sProcess) %#ok<DEFNU>
    Comment = sProcess.Comment;
end

%% ===== RUN =====
function OutputFile = Run(sProcess, sInputA, sInputB) %#ok<DEFNU>
    % Load the optimal low-frequency values from the MaxPAC file in InputB
    DataMat = load(file_fullpath(sInputB.FileName), 'sPAC');
    if ~isfield(DataMat, 'sPAC') || isempty(DataMat.sPAC) || ~isfield(DataMat.sPAC, 'NestingFreq') || isempty(DataMat.sPAC.NestingFreq)
        bst_report('Error', sProcess, sInputB, 'Invalid MaxPAC file in FilesB.');
        OutputFile = {};
        return;
    end
    % Set option from the file
    sProcess.options.lowfreq.Value{1} = DataMat.sPAC.NestingFreq;
    % Run the megPAC process
    OutputFile = process_canoltymap('Run', sProcess, sInputA);
end


function kern = linearKernParamInit(kern)

% LINEARKERNPARAMINIT Linear kernel parameter initialisation.

% KERN

% KERN

kern.variance = 1;
kern.nParams = 1;


colors =  ['r' 'b' 'k' 'g' 'c' 'y' 'm' ...
	   'r' 'b' 'k' 'g' 'c' 'y' 'm'];
symbols = ['o' 'x' '+' '>' '<' '^' 'v' ...
	   '*' 'p' 'h' 's' 'd' 'o' 'x'];
for i=1:length(colors)
  styles{i} = sprintf('-%s%s', colors(i), symbols(i));
end


%EarthView Image from Google maps
%
% A concrete subclass of ImageSource that acquires images from Google
% maps.
%
% Methods::
% grab    Grab a frame from Google maps
% size    Size of image
% close   Close the image source
% char    Convert the object parameters to human readable string
%
% Examples::
% Create an EarthView camera
%          ev = EarthView();
% Zoom into QUT campus in Brisbane
%          ev.grab(-27.475722,153.0285, 17);
% Show aerial view of Brisbane in satellite and map view
%          ev.grab('brisbane', 14)
%          ev.grab('brisbane', 14, 'map')
%
% Notes::
% - Google limit the number of map queries limit to 1000 unique (different)
%   image requests per viewer per day.  A 403 error is returned if the daily
%   quota is exceeded.
% - Maximum size is 640x640 for free access, business users can get more.
% - There are lots of conditions on what you can do with the images,
%   particularly with respect to publication.  See the Google web site for
%   details.
%
% Author::
%  Peter Corke, with some lines of code from from get_google_map by Val
%  Schmidt.
%
% See also ImageSource.

%TODO:
% map features/element control
% street view
% roadmap, satellite, terrain, hybrid

classdef EarthView < ImageSource

% e = EarthView() is an object that returns images of the Earth's surface
% obtained from Google Maps.
%
% e = EarthView(googlekey) as above but the google key string is passed in.
%
% e.grab(lat, lon, zoom, options)

    properties
        key
        type
        scale
    end

    methods
        function ev = EarthView(varargin)
        %EarthView.EarthView Create EarthView object
        %
        % EV = EarthView(OPTIONS)
        %
        % Options::
        % 'satellite'    Retrieve satellite image
        % 'map'          Retrieve map image
        % 'hybrid'       Retrieve satellite image with map overlay
        % 'scale'        Google map scale (default 18)
        % 'width',W      Set image width to W (default 640)
        % 'height',H     Set image height to H (default 640)
        % 'key',S        The Google maps key string
        %
        % see also options for ImageSource.
        %
        % Notes::
        % - A key is required before you can use the Google Static Maps API.
        %   The key is a long string that can be passed to the constructor or
        %   saved as an environment variable GOOGLE_KEY.  You need a Google
        %   account before you can register for a key.
        %
        % Notes::
        % - Scale is 1 for the whole world, ~20 is about as high a resolution
        %   as you can get.
        %
        % See also ImageSource, EarthView.grab.

        %TODO
        %  clone this for new StreetView API
        %  method to return lat/long or NE matrices corresp to pixels

            ev = ev@ImageSource(varargin{:});

            opt.type = {'satellite', 'map', 'hybrid'};
            opt.scale = 18;
            opt.key = [];

            [opt,args] = tb_optparse(opt, varargin);

            ev.type = opt.type;
            ev.scale = 1;

            % set default size params if not set
            if isempty(ev.width)
                ev.width = 640;
                ev.height = 640;
            end

            if isempty(opt.key)
                opt.key = getenv('GOOGLE_KEY');
            end
            ev.key = opt.key;

        end

        function [im,E,N] = grab(ev, varargin)
            % EarthView.grab Grab an aerial image
            %
            % IM = EV.grab(LAT, LONG, OPTIONS) is an image of the Earth
            % centred at the geographic coordinate (lat, long).
            %
            % IM = EarthView.grab(LAT, LONG, ZOOM, OPTIONS) as above with the
            % specified zoom.  ZOOM is an integer between 1 (zoom right out)
            % to a maximum of 18-20 depending on where in the world you
            % are looking.
            %
            % [IM,E,N] = EarthView.grab(LAT, LONG, OPTIONS) as above but also
            % returns the estimated easting E and northing N.  E and N are both
            % matrices, the same size as IM, whose corresponding elements are
            % the easting and northing are the coordinates of the pixel.
            %
            % [IM,E,N] = EarthView.grab(NAME, OPTIONS) as above but uses a
            % geocoding web site to resolve the name to a location.
            %
            % Options::
            % 'satellite'      Retrieve satellite image
            % 'map'            Retrieve map image
            % 'roadmap'        Retrieve map image (synonym for 'map')
            % 'terrain'        Retrieve terrain map
            % 'hybrid'         Retrieve satellite image with map overlay
            % 'roads'          Retrieve a binary image that shows only roads, no labels.
            %                  Roads are white, everything else is black.
            % 'noplacenames'   Don't show placenames.
            % 'noroadnames'    Don't show roadnames.
            %
            %
            % Examples::
            % Zoom into QUT campus in Brisbane
            %          ev.grab(-27.475722,153.0285, 17);
            % Show aerial view of Brisbane in satellite and map view
            %          ev.grab('brisbane', 14)
            %          ev.grab('brisbane', 14, 'map')
            %
            % Notes::
            % - If northing/easting outputs are requested the function
            %   deg2utm is required (from MATLAB Central)
            % - The easting/northing is somewhat approximate, see
            %   get_google_map on MATLAB Central.
            % - If no output argument is given the image is displayed using idisp.

            opt.type = {'satellite', 'map', 'hybrid', 'terrain', 'roadmap', 'roads'};
            opt.scale = ev.scale;
            opt.roadnames = true;
            opt.placenames = true;
            opt.landscape = false;
            opt.onlyroads = false;

            [opt,args] = tb_optparse(opt, varargin);

            switch opt.type
                case 'map'
                    opt.type = 'roadmap'
                case 'roads'
                    opt.type = 'roadmap';
                    opt.onlyroads = true;
            end

            % build the URL
            if ischar(args{1})
                % given a string name, do a geocode lookup
                place = args{1};
                zoom = args{2};

                % build the URL, and load the XML document
                url = sprintf('http://maps.googleapis.com/maps/api/geocode/xml?address=%s&sensor=false', place);
                doc = xmlread(url);

                % walk the XML document
                locations = doc.getElementsByTagName('location')

                if locations.getLength > 1
                    fprintf('%d places called %s found\n', locations.getLength, place);
                end

                location = locations.item(0);   % take the first return

                assert(~isempty(location), 'location not found');

                node_lat = location.getElementsByTagName('lat');
                el = node_lat.item(0);
                lat = str2num( el.getFirstChild.getData );

                node_lon = location.getElementsByTagName('lng');
                el = node_lon.item(0);
                lon = str2num( el.getFirstChild.getData );
            else
                lat = args{1};
                lon = args{2};
                if length(args) == 3
                    zoom = args{3};
                else
                    zoom = 18;
                end

            end
            % now read the map
            baseurl = sprintf('https://maps.googleapis.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&scale=%d&format=png&maptype=%s&key=%s&sensor=false', lat, lon, zoom, ev.width, ev.height, opt.scale, opt.type, ev.key);

            opturl = '';

            if ~opt.roadnames
                opturl = strcat(opturl, '&style=feature:road|element:labels|visibility:off');
            end
            if ~opt.placenames
                opturl = strcat(opturl, '&style=feature:administrative|element:labels.text|visibility:off&style=feature:poi|visibility:off');
            end

            if opt.onlyroads
                opturl = strcat(opturl, ['&style=feature:landscape|element:geometry.fill|color:0x000000|visibility:on'...
                    '&style=feature:landscape|element:labels|visibility:off'...
                    '&style=feature:administrative|visibility:off'...
                    '&style=feature:road|element:geometry.fill|color:0xffffff|visibility:on'...
                    '&style=feature:road|element:labels|visibility:off'...
                    '&style=feature:poi|element:all|visibility:off'...
                    '&style=feature:transit|element:all|visibility:off'...
                    '&style=feature:water|element:all|visibility:off'...
                    ]);
            end

            %opturl = urlencode(opturl)
            opturl = strrep(opturl, '|', '%7C');

            %opturl

            try
            [idx,cmap] = imread([baseurl opturl], 'png');
            catch
                error('Failed to read the URL: check your Google API key');
            end
            cmap = iint(cmap);

            % apply the color map
            view = cmap(idx(:)+1,:);

            % knock it into shape
            view = shiftdim( reshape(view', [3 size(idx)]), 1);
            view = ev.convert(view);

            if nargout == 0
                idisp(view);
            else
                im = view;
            end

            if nargout > 1
                % compute the northing/easting at each pixel.
                %
                % the following lines of code from get_google_map by Val Schmidt
                % ESTIMATE BOUNDS OF IMAGE:
                %
                % Normally one must specify a center (lat,lon) and zoom level for a map.
                % Zoom Notes:
                % ZL: 15, hxw = 640x640, image dim: 2224.91 x 2224.21 (mean 2224.56)
                % ZL: 16, hxw = 640x640, image dim: 1128.01m x 1111.25m (mean 1119.63)
                % This gives an equation of roughly (ZL-15)*3.4759 m/pix * pixels
                % So for an image at ZL 16, the LHS bound is
                % LHS = centerlonineastings - (zl-15) * 3.4759 * 640/2;
                [lonutm latutm zone] = deg2utm(lat,lon);
                Hdim = (2^15/2^zoom) * 3.4759 * ev.width;
                Vdim = (2^15/2^zoom) * 3.4759 * ev.height;

                ell = lonutm - Hdim/2;
                nll = latutm - Vdim/2;
                eur = lonutm + Hdim/2;
                nur = latutm + Vdim/2;

                Nvec = linspace(nur,nll,ev.height); % lat is highest at image row 1
                Evec = linspace(ell,eur,ev.width);
                [E,N] = meshgrid(Evec, Nvec);
            end
        end

        function close()
        end

        function s = char(m)
        %EarthView.char Convert to string
        %
        % EV.char() is a string representing the state of the EarthView object in
        % human readable form.
        %
        % See also EarthView.display.

            s = sprintf('EarthView: %d x %d', ...
                m.width, m.height);
            s2 = char@ImageSource(m);
            if ~isempty(s2)
                s = strvcat(s, strcat(' - ', s2));
            end
        end

        function paramSet(varargin)
        end

    end
end


function [ rectsLTRB ] = RectLTWH2LTRB(rectsLTWH)
%rects (l, t, r, b) to (l, t, w, h)

rectsLTRB = [rectsLTWH(:, 1), rectsLTWH(:, 2), rectsLTWH(:, 1)+rectsLTWH(:,3)-1, rectsLTWH(:,2)+rectsLTWH(:,4)-1];
end


function displayBarResults_MetricBased_HN_tempFig4(pathExperiments,fSetNames,nameOutcome,metrics,titlePart)
% - fSetNames: Cell of strings specifying the names of all feature sets
% - nameOutcome: String, specifying the name of a given specific outcome
% - titlePart: optional

startpath = pwd;

nExp = 1;

colors = {'red','blue','green'};

nMetrics = numel(metrics);
if nargin < 5
    prefix = 'testResults';
else
    prefix = ['testResults',titlePart];
end

nFset = numel(fSetNames);
data = cell(1,nMetrics);
for m = 1:nMetrics
    data{m} = zeros(nExp,nFset);
end

% Obtaining data
cd(pathExperiments), pathExperiment = pwd;
for exp = 1:nExp
    for f = 1:nFset
        results = load([prefix,'_',fSetNames{f},'_',nameOutcome]); results = struct2cell(results); results = results{1};
        for m = 1:nMetrics
            data{m}(exp,f) = results.(metrics{m});
        end
    end
end

% Producing bar plot
% scrsz = get(groot,'ScreenSize');
% h = figure('Position',[1 7*scrsz(4)/10 19*scrsz(3)/40 7*scrsz(4)/10]);
ind = strfind(nameOutcome,'Death');
if ~isempty(ind)
    nameOutcome(ind:ind+4) = [];
    nameOutcome = ['Survival',nameOutcome];
end
if nargin < 5
    titleName = nameOutcome;
else
    titleName = [nameOutcome,' -- ',titlePart];
end
if exp > 1
    y = zeros(nMetrics,nFset);
    err = zeros(nMetrics,nFset);
    stdData = data;
    for m = 1:nMetrics
        data{m} = mean(data{m});
        stdData{m} = std(data{m});
        y(m,:) = data{m}(1,:);
        err(m,:) = stdData{m}(1,:);
    end
    model_series = y; model_error = err;
    bar(model_series,1);
    set(gca,'YGrid','on')
    set(gca,'GridLineStyle','-')
    set(gca,'XTicklabel','Modelo1|Modelo2|Modelo3')
    lh = legend('Serie1','Serie2','Serie3');
    set(lh,'Location','BestOutside','Orientation','horizontal')
    hold on;
    numgroups = size(model_series, 1);
    numbars = size(model_series, 2);
    groupwidth = min(0.8, numbars/(numbars+1.5));
    for i = 1:numbars
          % Based on barweb.m by Bolu Ajiboye from MATLAB File Exchange
          x = (1:numgroups) - groupwidth/2 + (2*i-1) * groupwidth / (2*numbars);  % Aligning error bar with individual bar
          errorbar(x, model_series(:,i), model_error(:,i), 'k', 'linestyle', 'none','LineWidth',3);
    end
else
    y = zeros(nMetrics,nFset);
    for m = 1:nMetrics
        y(m,:) = data{m}(1,:);
    end
    if nMetrics > 1
        b = bar(y,1);
        for c = 1:nFset
            b(c).FaceColor = colors{c};
        end
    else
        bar([y;zeros(nFset-1,nFset)],1)
    end
end
set(gca,'XTickLabel',metrics)
set(gca,'FontSize',10)
%set(gca,'XTickLabelRotation',45)
axis([0.5 nMetrics+0.5 0 1])
legend(fSetNames)
grid on
%title(titleName,'FontSize',26,'FontWeight','bold')
% annotation(h,'line',[0.13 0.905],[0.515673981191221 0.515673981191221],...
%     'Color',[0.850980401039124 0.325490206480026 0.0980392172932625],...
%     'LineWidth',5,'LineStyle',':');

hold on
x = 0:0.01:nMetrics+1;
y = ones(1,numel(x))*0.5;
plot(x,y,'.m')
hold off

cd(startpath)
end


function [c, r, t, cpulse, acq_codes, verbose, gsr] = tapas_physio_read_physlogfiles_biopac_txt(...
    log_files, cardiac_modality, verbose, varargin)
% Reads in 4-column txt-export from BioPac Data (resp, ppu, gsr, trigger)
%
% [c, r, t, cpulse, acq_codes, verbose] = tapas_physio_read_physlogfiles_biopac_txt(...
%    log_files, cardiac_modality, verbose, varargin)
%
% IN    log_files
%       .log_cardiac        *.txt file, contains 4 columns of the form
%                           RESP - RSP100C	GSR - EDA100C-MRI	PPG - PPG100C	Marker
%                             -0.949402	-0.00610382	0.0134277	0
%                             -0.949402	-0.00610382	0.0134277	0
%                             -0.951233	-0.00915558	0.0204468	0
%                             -0.951233	-0.00915558	0.0204468	0
%                             -0.953064	-0.0122073	0.0259399	0
%                             -0.953064	-0.0122073	0.0259399	0
%                             -0.95459	-0.0076297	0.0296021	0
%                             -0.95459	-0.0076297	0.0296021	0
%       .log_respiration    same as .log_cardiac
%       .sampling_interval  sampling interval (in seconds)
%                           default: 1 ms (1000 Hz)
%       cardiac_modality    'ECG' or 'PULS'/'PPU'/'OXY' to determine
%                           which channel data to be returned
%                           UNUSED, is always pulse plethysmographic unit
%                           for BioPac
%       verbose
%       .level              debugging plots are created if level >=3
%       .fig_handles        appended by handle to output figure
%
% OUT
%   cpulse              time events of R-wave peak in cardiac time series (seconds)
%                       <UNUSED>, since not written to logfile
%   r                   respiratory time series
%   t                   vector of time points (in seconds)
%   c                   cardiac time series (PPU)
%   acq_codes           slice/volume start events marked by number <> 0
%                       for time points in t
%                       10/20 = scan start/end;
%                       1 = ECG pulse; 2 = OXY max; 4 = Resp trigger;
%                       8 = scan volume trigger (on)
%                       16 = scan volume trigger (off)
%   gsr                 galvanic skin response (not used)
%
% EXAMPLE
%   tapas_physio_read_physlogfiles_biopac_txt
%
%   See also tapas_physio_read_physlogfiles_siemens tapas_physio_plot_raw_physdata_siemens_hcp

% Author: Lars Kasper
% Created: 2018-09-27
% Copyright (C) 2018 TNU, Institute for Biomedical Engineering,
%                    University of Zurich and ETH Zurich.

% This file is part of the TAPAS PhysIO Toolbox, which is released under the terms of the GNU General Public
% License (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

%% read out values
DEBUG = verbose.level >= 2;

hasRespirationFile = ~isempty(log_files.respiration);
hasCardiacFile = ~isempty(log_files.cardiac);

hasRespirationFile = ~isempty(log_files.respiration);
hasCardiacFile = ~isempty(log_files.cardiac);

if hasCardiacFile
    fileName = log_files.cardiac;
elseif hasRespirationFile
    fileName = log_files.respiration;
end

[C, columnNames] = tapas_physio_read_columnar_textfiles(fileName, 'BIOPAC_TXT');
c = double(C{3});
r = double(C{1});
gsr = double(C{2});
iAcqOn = (double(C{4})~=0); % trigger has 11, rest is 0;

%% Create timing vector from samples

dt = log_files.sampling_interval;

if isempty(dt)
    dt = 1/1000; % 1000 Hz sampling interval
end

nSamples = max(numel(c), numel(r));
t = -log_files.relative_start_acquisition + ((0:(nSamples-1))*dt)';

%% Recompute acq_codes as for Siemens (volume on/volume off)
acq_codes = [];

if ~isempty(iAcqOn) % otherwise, nothing to read ...
    % iAcqOn is a column of 1s and 0s, 1 whenever scan acquisition is on
    % Determine 1st start and last stop directly via first/last 1
    % Determine everything else in between via difference (go 1->0 or 0->1)
    iAcqStart   = find(iAcqOn, 1, 'first');
    iAcqEnd     = find(iAcqOn, 1, 'last');
    d_iAcqOn    = diff(iAcqOn);

    % index shift + 1, since diff vector has index of differences i_(n+1) - i_n,
    % and the latter of the two operands (i_(n+1)) has sought value +1
    iAcqStart   = [iAcqStart; find(d_iAcqOn == 1) + 1];
    % no index shift, for the same reason
    iAcqEnd     = [find(d_iAcqOn == -1); iAcqEnd];

    acq_codes = zeros(nSamples,1);
    acq_codes(iAcqStart) = 8; % to match Philips etc. format
    acq_codes(iAcqEnd) = 16; % don't know...

    % report estimated onset gap between last slice of volume_n and 1st slice of
    % volume_(n+1)
    nAcqStarts = numel(iAcqStart);
    nAcqEnds = numel(iAcqEnd);
    nAcqs = min(nAcqStarts, nAcqEnds);

    if nAcqs >= 1
        % report time of acquisition, as defined in SPM
        TA = mean(t(iAcqEnd(1:nAcqs)) - t(iAcqStart(1:nAcqs)));
        verbose = tapas_physio_log(...
            sprintf('TA = %.4f s (Estimated time of acquisition during one volume TR)', ...
            TA), verbose, 0);
    end
end

%% Plot, if wanted

if DEBUG
    stringTitle = 'Read-In: Raw BioPac physlog data (TXT Export)';
    verbose.fig_handles(end+1) = ...
        tapas_physio_plot_raw_physdata_siemens_hcp(t, c, r, acq_codes, ...
        stringTitle);
end

%% Undefined output parameters

cpulse = [];


function b = nlfilter_cerr(varargin)
%NLFILTER General sliding-neighborhood operations.
%   B = NLFILTER(A,[M N],FUN) applies the function FUN to each M-by-N
%   sliding block of the grayscale image A. FUN is a function that accepts
%   an M-by-N matrix as input and returns a scalar:
%
%       C = FUN(X)
%
%   FUN must be a FUNCTION_HANDLE.
%
%   C is the output value for the center pixel in the M-by-N block X.
%   NLFILTER calls FUN for each pixel in A. NLFILTER zero pads the M-by-N
%   block at the edges, if necessary.
%
%   B = NLFILTER(A,'indexed',...) processes A as an indexed image, padding
%   with ones if A is of class single or double and zeros if A is of class
%   logical, uint8, or uint16.
%
%   Class Support
%   -------------
%   The input image A can be of any class supported by FUN. The class of B
%   depends on the class of the output from FUN. When A is grayscale, it
%   can be any numeric type or logical. When A is indexed, it can be
%   logical, uint8, uint16, single or double.
%
%   Remarks
%   -------
%   NLFILTER can take a long time to process large images. In some cases,
%   the COLFILT function can perform the same operation much faster.
%
%   Example
%   -------
%   This example produces the same result as calling MEDFILT2 with a 3-by-3
%   neighborhood:
%
%       A = imread('cameraman.tif');
%       fun = @(x) median(x(:));
%       B = nlfilter(A,[3 3],fun);
%       imshow(A), figure, imshow(B)
%
%   See also BLOCKPROC, COLFILT, FUNCTION_HANDLE.

%   Copyright 1993-2009 The MathWorks, Inc.
%   $Revision: 5.20.4.10 $  $Date: 2009/12/28 04:16:40 $

% Obsolete syntax:
%   B = NLFILTER(A,[M N],FUN,P1,P2,...) passes the additional parameters
%   P1,P2,..., to FUN.
%

[a, nhood, fun, params, padval] = parse_inputs(varargin{:});

% Expand A
[ma,na] = size(a);
aa = mkconstarray(class(a), padval, size(a)+nhood-1);
aa(floor((nhood(1)-1)/2)+(1:ma),floor((nhood(2)-1)/2)+(1:na)) = a;

% Find out what output type to make.
rows = 0:(nhood(1)-1);
cols = 0:(nhood(2)-1);
b = mkconstarray(class(feval(fun,aa(1+rows,1+cols),params{:})), 0, size(a));

% Apply fun to each neighborhood of a
f = waitbar(0,'Applying neighborhood operation...');
for i=1:ma,
    for j=1:na,
        x = aa(i+rows,j+cols);
        b(i,j) = feval(fun,x,params{:});
    end
    waitbar(i/ma)
end
close(f)

%%%
%%% Function parse_inputs
%%%
function [a, nhood, fun, params, padval] = parse_inputs(varargin)

blockSizeParamNum = 2;

switch nargin
    case {0,1,2}
        eid = sprintf('Images:%s:tooFewInputs',mfilename);
        msg = 'Too few inputs to NLFILTER';
        error(eid,'%s',msg);
    case 3
        if (strcmp(varargin{2},'indexed'))
            eid = sprintf('Images:%s:tooFewInputsIfIndexedImage',mfilename);
            msg = 'Too few inputs to NLFILTER';
            error(eid,'%s',msg);
        else
            % NLFILTER(A, [M N], 'fun')
            a = varargin{1};
            nhood = varargin{2};
            fun = varargin{3};
            params = cell(0,0);
            padval = 0;
        end

    otherwise
        if (strcmp(varargin{2},'indexed'))
            % NLFILTER(A, 'indexed', [M N], 'fun', P1, ...)
            a = varargin{1};
            nhood = varargin{3};
            fun = varargin{4};
            params = varargin(5:end);
            padval = 1;
            blockSizeParamNum = 3;

        else
            % NLFILTER(A, [M N], 'fun', P1, ...)
            a = varargin{1};
            nhood = varargin{2};
            fun = varargin{3};
            params = varargin(4:end);
            padval = 0;
        end
end

if (isa(a,'logical') || isa(a,'uint8') || isa(a,'uint16'))
    padval = 0;
end

% Validate 2D input image
iptcheckinput(a,{'logical','numeric'},{'2d'},mfilename,'A',1);

% Validate neighborhood
iptcheckinput(nhood,{'numeric'},{'integer','row','positive','nonnegative','nonzero'},mfilename,'[M N]',blockSizeParamNum);
if (numel(nhood) ~= 2)
    eid = sprintf('Images:%s:invalidBlockSize',mfilename);
    msg = 'Invalid block size, expected [M N].';
    error(eid,'%s',msg);
end

fun = fcnchk(fun,length(params));


function x = stretch_r ( r, i )

%*****************************************************************************80
%
%% STRETCH_R returns a data component given (R).
%
%  Discussion:
%
%    This routine shifts by 1 and stretches by 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the coordinate of a point that lies on the
%    boundary of the cube.
%
%    Input, integer I, the component of the data which is to be returned.
%
%    Output, real X, the I-th component of the data vector X, evaluated
%    at the point (R), which is on an endpoint of the unit line segment.
%
  if ( i == 1 )
    x = 2.0 * r + 1.0;
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'STRETCH_R - Fatal error!\n' );
    fprintf ( 1, '  Illegal component index I = %d\n', i );
    error ( 'STRETCH_R - Fatal error!' );
  end

  return
end


function test_suite=test_randperm
% tests for cosmo_randperm
%
% #   For CoSMoMVPA's copyright information and license terms,   #
% #   see the COPYING file distributed with CoSMoMVPA.           #
    try % assignment of 'localfunctions' is necessary in Matlab >= 2016
        test_functions=localfunctions();
    catch % no problem; early Matlab versions can use initTestSuite fine
    end
    initTestSuite;

function test_randperm_no_seed
    helper_test_deterministic(false);

function test_randperm_with_seed
    helper_test_deterministic(true);

function helper_test_deterministic(with_seed)
    if with_seed
        seed=ceil(rand()*1e5);
        args={'seed',seed};
    else
        args={};
    end

    f=@(varargin)cosmo_randperm(varargin{:},args{:});

    % single input
    n=randint();
    x1=f(n);
    assertEqual(size(x1),[1 n]);
    assertEqual(sort(x1),1:n);

    x1a=f(n);
    if with_seed
        assertEqual(x1,x1a);
    else
        assert(~isequal(x1,x1a));
    end

    % two inputs, select all
    x1a=f(n,n);

    if with_seed
        assertEqual(x1,x1a);
    else
        assert(~isequal(x1,x1a));
    end

    % two inputs, k<n
    k=randint();
    n=k+randint();
    assert(k<n);
    x2=f(n,k);
    assertEqual(size(x2),[1 k]);
    msk=bsxfun(@eq,(1:n)',x2);
    assertEqual(sum(msk(:)==1),k);
    assertEqual(sum(sum(msk==1,1),2),k); % each column has one 1
    assertEqual(sum(sum(msk==1,2),1),k); % each row has one 1

    if with_seed
        % deterministic
        x2a=f(n,k);
        assertEqual(x2,x2a);
    else
        found=false;
        for attempt=1:10
            x2a=f(n,k);
            if ~isequal(x2,x2a)
                found=true;
                break;
            end
        end

        if ~found
            error('Different calls do not lead to different outputs');
        end
    end

    x3=f(0);
    assertTrue(isempty(x3));

    x4=f(1);
    assertEqual(x4,1);

    x5=f(1,1);
    assertEqual(x5,1);

function test_randperm_different_seeds
    count=10;
    seed=0;
    result=cell(count,1);
    for k=1:count
        seed=seed+randint();

        result{k}=cosmo_randperm(1000,'seed',seed);
        for j=1:(k-1)
            assertFalse(isequal(result{j},result{k}));
        end
    end

function test_randperm_exceptions
    aet=@(varargin)assertExceptionThrown(@()...
                        cosmo_randperm(varargin{:}),'');
    illegal_args={-1,.5,[1 2],'foo',struct,cell(0)};
    narg=numel(illegal_args);

    % illegal first and/or second arguments
    for k=1:narg
        for second_arg=[false,true]
            for j=1:narg
                if second_arg
                    args=illegal_args([k j]);
                elseif j>1
                    continue;
                else
                    % single arg if j==1
                    args=illegal_args(k);
                end
                aet(args{:});
            end
        end
    end

    % illegal seed arguments
    for k=1:narg
        arg=illegal_args(k);
        aet(4,2,'seed',arg{:});
    end

    % missing seed
    aet(4,2,'seed');

    % double seed
    aet(4,2,'seed',1,'seed',1);

    % 3 numeric arguments
    aet(4,2,1);

    % second argument greater than first
    aet(2,4);
    aet(2,4,'seed',1);

    % unknown keyword
    aet(2,'foo',1);
    aet(2,'foo');

function x=randint(n)
    x=ceil(10+rand()*50);


function alpha = p03_alpha ( )

%*****************************************************************************80
%
%% P03_ALPHA returns ALPHA for problem 3.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 July 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real ALPHA, the value of ALPHA.
%
  alpha = 2.0;

  return
end


%kmreplicate 'Replicate a Given Matrix as Submatrices of a Larger Matrix'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros mreplicate.pane file
%
% Parameters:
% InputFile: i 'Input ', required: 'Input mmatrix data object'
% Integer: r 'Replica count along rows ', default: 1: 'replica count along rows'
% Integer: c 'Replica count along cols ', default: 1: 'replica count along columns'
% OutputFile: o 'Output', required: 'Resulting matrix output data object'
%
% Example: o = kmreplicate(i, {'i','';'r',1;'c',1;'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% mreplicate - Replicate a Given Matrix as Submatrices of a Larger Matrix
%
%  DESCRIPTION
% .I mreplicate
% replicates the input matrix as a rectangular array of submatrices to form
% a larger matrix. The input maybe of any dimension NxM as long as N>1 and M>1.
% The output matrix will be (R*N)x(C*M) where R is the number of times the
% input matrix is to be replicated along the row dimension and C is the number of
% times the input matrix is to be replicated along the column dimension.
%
% The output data type is the same as the input data type.
%
%
%
%  EXAMPLES
%
% % mreplicate -i image:moon -o blah -r 2 -c 3
%
% Produces an image of the moon replicated 3 times in the horizontal direction
% and 2 times in the vertical direction.
%
%  "SEE ALSO"
%
%  RESTRICTIONS
%
%  REFERENCES
%
%  COPYRIGHT
% Copyright (C) 1993 - 1997, Khoral Research, Inc. ("KRI")  All rights reserved.
%

function varargout = kmreplicate(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,..] = kmreplicate(Inputs,arglist).');
end
if size(arglist,2)~=2
  error('arglist must be of form {''ParameterTag1'',value1;''ParameterTag2'',value2}')
 end
narglist={'i', '__input';'r', 1;'c', 1;'o', '__output'};
maxval={0,2,2,0};
minval={0,2,2,0};
istoggle=[0,1,1,0];
was_set=istoggle * 0;
paramtype={'InputFile','Integer','Integer','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 'mreplicate"  '],Inputs,narglist);


function r8mat_print_some ( m, n, a, ilo, jlo, ihi, jhi, title )

%*****************************************************************************80
%
%% R8MAT_PRINT_SOME prints out a portion of an R8MAT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns of the matrix.
%
%    Input, real A(M,N), an M by N matrix to be printed.
%
%    Input, integer ILO, JLO, the first row and column to print.
%
%    Input, integer IHI, JHI, the last row and column to print.
%
%    Input, string TITLE, an optional title.
%
  incx = 5;

  if ( 0 < s_len_trim ( title ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, '%s\n', title );
  end

  for j2lo = max ( jlo, 1 ): incx : min ( jhi, n )

    j2hi = j2lo + incx - 1;
    j2hi = min ( j2hi, n );
    j2hi = min ( j2hi, jhi );

    inc = j2hi + 1 - j2lo;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col: ' );

    for j = j2lo : j2hi
      fprintf ( 1, '%7d       ', j );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row\n' );

    i2lo = max ( ilo, 1 );
    i2hi = min ( ihi, m );

    for i = i2lo : i2hi

      fprintf ( 1, '%7d  ', i );

      for j = j2lo : j2hi
        fprintf ( 1, '%12g  ', a(i,j) );
      end

      fprintf ( 1, '\n' );

    end

  end

  return
end


function Z = zeros(d)
%ZEROS     Zero operator.
%   This function is deprecated. Use OPERATORBLOCK.ZEROS.

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

Z = linop( operatorBlock.zeros(double(d)) );

end


function b = bodewig_rhs ( )

%*****************************************************************************80
%
%% BODEWIG_RHS returns the BODEWIG right hand side.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 November 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real B(4,1), the right hand side vector.
%
  b(1:4,1) = [ 29.0, 18.0, 15.0, 4.0 ];

  return
end


function hh = plot_uc(md, varargin)
%PLOT_UC   Plot generator commitment summary
%
%   PLOT_UC(MD)
%   PLOT_UC(MD, IDX)
%   PLOT_UC(MD, IDX, '<option1_name>', '<option1_value', ...)
%   PLOT_UC(MD, IDX, OPT)
%   PLOT_UC(MD, IDX, OPT, '<option1_name>', '<option1_value', ...)
%   PLOT_UC(MD, MD2)
%   PLOT_UC(MD, MD2, IDX, )
%   PLOT_UC(MD, MD2, IDX, '<option1_name>', '<option1_value', ...)
%   PLOT_UC(MD, MD2, IDX, OPT)
%   PLOT_UC(MD, MD2, IDX, OPT, '<option1_name>', '<option1_value', ...)
%   H = PLOT_UC(MD, ...)
%
%   IDX is a vector of gen indices, if empty, it includes all generators in
%   MD. Options can be specified as an OPT struct or as individual pairs of
%   'name' and 'value' arguments. The possible options include the following,
%   where the default is shown in parenthesis:
%       'title'         ('Unit Commitment - %s') title for the plot, where
%                       %s is an optional placeholder for the subtitle
%       'subtitle'      ({'First', 'Second', 'Both'}) cell array of labels
%                       to use for legend (if two schedules are provided)
%                       and to replace a placeholder in the title (based
%                       on which commitment schedule(s) is(are) provided in
%                       UC1 and/or UC2); can also be a simple string, in
%                       which case no legend will be displayed even if both
%                       UC1 and UC2 are supplied
%       'xlabel'        ('Period') label for horizontal axis
%       'ylabel'        (<empty>) label for vertical axis
%       'rowlabels'     ({'1', '2', '3', ...) labels for rows (top to bottom)
%       'saveit'        (false) flag to indicate whether to create PDF file
%       'saveall'       (false) flag to indicate whether to create a single
%                       PDF file or, if both MD and MD2 are supplied, three
%                       PFF files, one for MD, one for MD2 and one for both.
%       'savepath'      ('') path to directory to save files in
%       'savename'      ('uc-%s.pdf') name of PDF file
%                       %s is optional placeholder for storage unit index
%       'size_factor'   (1) to scale font/marker sizes in case you want to
%                       do sub-plots or something
%
%   Returns handle to current figure window.

%   MOST
%   Copyright (c) 2015-2016, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MOST.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://github.com/MATPOWER/most for more info.

%% define named indices into data matrices
[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
    MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
    QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;

%% gather data
nt = md.idx.nt;
ng = size(md.mpc.gen, 1);
nj_max = max(md.idx.nj);
nc_max = max(max(md.idx.nc));

%% default optional args
idx = [];
md2 = [];
k = 1;
if nargin > 1                   %% 2nd arg is ...
    if isstruct(varargin{k})    %% ... md2
        md2 = varargin{k};
    else                        %% ... idx
        idx = varargin{k};
    end
    k = k + 1;
end
if isempty(idx) && nargin > 2   %% 3rd arg is ...
    if isnumeric(varargin{k})
        idx = varargin{k};      %% ... idx
        k = k + 1;
    end
end

%% default idx
if isempty(idx)
    idx = find(any(md.UC.CommitKey == 0, 2) | any(md.UC.CommitKey == 1, 2));
end
nidx = length(idx);
if nidx > 1 && size(idx, 1) == 1
    idx = idx';     %% convert row vector to column vector
end
b = md.mpc.gen(idx, GEN_BUS);

%% default options
opt = struct( ...
    'title', 'Unit Commitment - %s', ...
    'subtitle', {{'First', 'Second', 'Both'}}, ...
    'xlabel', 'Period', ...
    'ylabel', '', ...
    'rowlabels', [], ...
    'saveit', false, ...
    'saveall', false, ...
    'savepath', '', ...
    'savename', 'uc-%s.pdf', ...
    'size_factor', 1 );

%% process options
vargs = varargin(k:end); %% remaining arguments
if mod(length(vargs), 2)    %% odd number of options, first must be OPT struct
    if ~isstruct(vargs{1})
        error('plot_uc: Single OPT argument must be a struct');
    end
    myopt = vargs{1};
    k = 2;
else                        %% even number of options
    myopt = struct;
    k = 1;
end
while k < length(vargs)
    opt_name = vargs{k};
    opt_val  = vargs{k+1};
    if ~isfield(opt, opt_name)
        error('plot_uc: ''%s'' is not a valid option name', opt_name);
    end
    myopt.(opt_name) = opt_val;
    k = k + 2;
end
fields = fieldnames(myopt);
for f = 1:length(fields)
    opt.(fields{f}) = myopt.(fields{f});
end

%% check CommitKey match
uc1 = md.UC.CommitSched(idx, :);
if ~isempty(md2)
    uck2 = md2.UC.CommitKey(idx, :);
    if any(any( uck2 ~= md.UC.CommitKey(idx, :) & (uck2 == 2 | uck2 == 0) ))
        error('plot_uc: CommitKey fields in MD and MD2 do not match');
    end
    uc2 = md2.UC.CommitSched(idx, :);
else
    uc2 = [];
end

%% generator labels
m = size(uc1, 1);
opt.rowlabels = cell(m, 1);
if isfield(md.mpc, 'genfuel')
    for i = 1:m
        opt.rowlabels{i} = sprintf('Gen %d @ Bus %d, %s', idx(i), b(i), md.mpc.genfuel{idx(i)});
    end
else
    for i = 1:m
        opt.rowlabels{i} = sprintf('Gen %d @ Bus %d', idx(i), b(i));
    end
end

%% do the plots
if opt.saveall
    opt.saveit = 1;
end
if opt.saveall || isempty(uc2)
    cla;
    h = plot_uc_data(uc1, [], opt);
end
if ~isempty(uc2)
    if opt.saveall || isempty(uc1)
        cla;
        h = plot_uc_data([], uc2, opt);
    end
    if opt.saveall || ~isempty(uc1)
        cla;
        h = plot_uc_data(uc1, uc2, opt);
    end
end

if nargout
    hh = h;
end


function outStrMat = mat2strDisplay(inNumMat,inNumFmt)
[nrow,ncol] = size(inNumMat);
dispFmt = ['%0.',num2str(inNumFmt),'f'];
outStrMat = '[';
for i=1:nrow
    for j=1:ncol
        if j~=ncol
            outStrMat = [outStrMat,sprintf(dispFmt,inNumMat(i,j)),','];
        else
            if nrow~=1
                outStrMat = [outStrMat,sprintf(dispFmt,inNumMat(i,j)),';'];
            else
                outStrMat = [outStrMat,sprintf(dispFmt,inNumMat(i,j))];
            end
        end
    end
end
outStrMat = [outStrMat,']'];
end


function initials = tc_condInitials(condNames);
%
% initials = tc_condInitials(condNames);
%
% Provides brief initials for a set of condition names.
%
% PROBLEM: when creating bar graphs or other images where conditions
% are plotted against one another, oftentimes there isn't space for the
% full condition label. (And often there's a legend with the full label
% next to the colors). So, just as a reminder, we want to have some
% abbreviated form of the condition names.
%
% SOLUTION: This code figures out 'good' initials, meaning initials that
% are the smallest possible to be unambiguous. If each condition name starts
% with a different letter, it will just be the first letters. If some are
% the same, it will use heuristics like finding capital letters or spacers
% (e.g. '_'), and making each initial unique.
%
% The returned initials are all capital, in a cell array of strings.
%
% ras, 02/06.
nConds = length(condNames);

% check that there aren't duplicate condition names: if so, the
% code below may get stuck in a loop (because there are always non-unique
% identifiers), so fix them by appending numbers
condNames = lower(condNames);
for i = 1:nConds
    test = cellfind(condNames, condNames{i});
    if length(test) > 1
        msg = sprintf(['Condition name %s is not unique! ' ...
                       'Appears in entries %s. ' ...
                       'Am numbering these duplicate entries. '], ...
                       condNames{i}, num2str(test));
        warning(msg);
        for j = test
            condNames{j} = [condNames{j} num2str(j)];
        end
    end
end

% remove any leading and trailing spaces from condNames:
for i = 1:nConds
    while isequal(condNames{i}(1), ' ')
        condNames{i} = condNames{i}(2:end);
    end
end

% initialize the initials ( :-) ) as the first letter of each cond name
for i = 1:nConds
    initials{i} = upper(condNames{i}(1));
end

% if each letter is unique, great! We're done.
if length(unique(initials))==length(initials)
    return;
end

% if we got here, there are some non-unique letters. Find them and fix
% them:

% First, go through each non-unique cond name, and see if we can find
% a 'second word', meaning a string after a space or an underscore,
% or a capital letter (or number). If we find one for a condition name,
% reshape that condition name to be 2D (words by characters in word).
for i = 1:nConds
    str = condNames{i};

    % blank spacers
    spacers = [findstr('_', str) findstr(' ', str)];

    % upper-case letters (ASCII range 65-90): find the preceding letter as
    % the spacer:
    spacers = [spacers find(ismember(str, 65:90))-1];

    % do the same operation for numbers as for upper-case letters, only
	% the ASCII range for number strings is 48-57:
    spacers = [spacers find(ismember(str, 48:57))-1];

    % sort into ascending indices in the string; remove spacers at end
    % points:
    spacers = spacers(spacers>1 & spacers<length(str));
    spacers = unique( sort(spacers) );
    if ~isempty(spacers)
        for j = spacers
            str = strvcat(str(1:j-1), str(j+1:end));
        end
        condNames{i} = str;
    end
end

notUnique = ones(size(initials)); % initialize index of remaining non-unique entries
while any(notUnique)
    % find which entries are repeated
    for i = 1:length(initials)
        if length(cellfind(initials, initials{i})) > 1
            notUnique(i) = 1;
        else
            notUnique(i) = 0;
        end
    end

    % for each non-unique entry, add one more character
    for j = find(notUnique)
        N = min( length(initials{j})+1, prod(size(condNames{j})) );
        initials{j} = upper(condNames{j}(1:N));

		% if the initials are as long as the condition name, stop.
		if N == numel(condNames{j})
			notUnique(j) = 0;
		end
    end
end

initials = upper(initials);

return


function do_plot_unconditional_forecasts(mycast,m)

vnames=m.endogenous;

nvars=numel(vnames);

figure('name','unconditional forecasts');

for ivar=1:nvars

    subplot(nvars,1,ivar);

    plot(mycast.(vnames{ivar}),'linewidth',2);

    ylabel(vnames{ivar});

end

tmp=set([mycast.ygap mycast.pi mycast.FFR],'varnames',{'ygap','pi','FFR'});

disp('********** Unconditional forecasts ***********');
display(tmp)

end


function res = imMergeCells(img, c1, c2)
%IMMERGECELLS merge labeled cell of an image
%
%   Deprecated: use 'imMergeLabels' instead.
%
%   Usage:
%   LBL2 = imMergeCells(LBL, C1, C2);
%   LBL is a label image, C1 and C2 are labels of the 2 cells to merge.
%   The indices of two regions are set to the same value, and the boundary
%   between the 2 regions is also merged to the new region, preserving
%   topology of adjacent regions.
%
%
%   -----
%
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 19/07/2004.
%

warning('imael:deprecated', ...
    'imMergeCells is deprecated, use imMergeLabels instead');

ind = imBoundaryIndices(img, c1, c2);
res = img;
res(img==c2)=c1;
res(ind)=c1;

return;


function str = vector2str(num)
% Converts a vector to string with colon operators
str = num2str(num(1));
incrementStart = true;
for a = 2:length(num)
    if num(a) - num(a-1) == 1
        incrementStart = handleConsecutive(incrementStart);
    else
        incrementStart = handleNonConsecutive(num(a-1), num(a), ...
            incrementStart);
    end
end
handleLastIndex(num(length(num)), incrementStart);

    function incrementStart = handleNonConsecutive(previous, current, ...
            incrementStart)
        % Handles a number that is not a consecutive number
        if ~incrementStart
            str = [str num2str(previous)];
        end
        str = [str ' ' num2str(current)];
        incrementStart = true;
    end % handleNonConsecutive

    function handleLastIndex(last, incrementStart)
        % Handles the last number in the vecor
        if ~incrementStart
            str = [str num2str(last)];
        end
    end % handleLastIndex

    function incrementStart = handleConsecutive(incrementStart)
        % Handles a number that is a consecutive number
        if incrementStart
            str = [str ':'];
            incrementStart = false;
        end
    end % handleConsecutive

end % vector2str


%kvskelthinP 'Skeleton by Thinning Mult. P'
% This MatLab function was automatically generated by a converter (KhorosToMatLab) from the Khoros vskelthinP.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'
% InputFile: str3 'Struct Element 3', required: 'Structuring Element'
% InputFile: str4 'Struct Element 4', required: 'Structuring Element'
% OutputFile: o 'Output Image ', required: 'resulting output image'
%
% Example: o = kvskelthinP({i, str1, str2, str3, str4}, {'i','';'str1','';'str2','';'str3','';'str4','';'o',''})
%
% Khoros helpfile follows below:
%
%  PROGRAM
% vskelthinP - Skeleton by Thinning Mult. P
%
%  DESCRIPTION
% .I vskelthinP
% will do the skeleton by thinning with mult. str. sets of an input image by a set of structuring elements. This program is based on an algorithm proposed by Roland T. Chin and Ben-Kwei Jang.
%
% The output image data type will be the same as that of the highest data type
% of the input image.
%
% Useful set of structuring elements:
%
%                         0 0 0    1 1 0    0 0 0    0 1 0
%   Homotopic Skeleton    0 1 1    1 0 0    1 1 1    0 0 0
%                         0 1 0    0 0 0    0 1 0    0 0 0
%
%
%
%  EXAMPLES
% vskelthinP -i ball.xv -str1 b272 -str2 b273 -str3 b274 -str4 b275 -o outimage.xv
%
% Will do the skeleton by thinning with mult. str. sets of image "ball.xv" by the structuring sets b272, b273, b274 and b275, with the resulting image written to "outimage.xv".
%
%  "SEE ALSO"
%
%  RESTRICTIONS
% .I vskelthinP
% 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 = kvskelthinP(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,..] = kvskelthinP(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';'str3', '__input';'str4', '__input';'o', '__output'};
maxval={0,0,0,0,0,0};
minval={0,0,0,0,0,0};
istoggle=[0,0,0,0,0,0];
was_set=istoggle * 0;
paramtype={'InputFile','InputFile','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 'vskelthinP"  '],Inputs,narglist);


function jointfig(hfig,no_row,no_col)

%   jointfig(hfig,no_row,no_col)
%	--> joint subplots without any space between them
%   hfig : figure handler, if none, keyin gcf instead
%   no_row    : No. of row subplots
%   no_col    : No. of column subplots
%
%                 DO-SIG GONG,
%				  mail: D.Gong@soton.ac.uk
%				  HFRU/ISVR, University of Southampton, UK
%				  latest modified at 99-03-01 7:27PM

% All the movement of subplots should be done in unit of points
figure(hfig), hsubplot = get(hfig,'Children');
% convert the position unit from pixel into points : should be restored)
set(hfig,'unit','point')

% BEWARE! hsubplot has different order from the original subplot sequence
% for instance,
%
%  -----------------------         -----------------------
%  |     1    |     2     |        |     4    |     3     |
%  |----------+-----------|        |----------+-----------|
%  |     3    |     4     |        |     2    |     1     |
%  -----------------------         -----------------------
%       subplot(22i)                  get(gcf,'Children')
%
% THEREFORE, transpose hsubplot into the one in original subplot sequence, like this..

hsubplot = hsubplot(length(hsubplot):-1:1);

no_subplot1 = length(hsubplot);
no_space  = no_row*no_col;
no_delta = no_space - no_subplot1;

% in case of the odd number of subplots
if no_delta,
	for i = 1:no_delta
		addsubplot = subplot(no_row,no_col,no_subplot1+i);
		hsubplot = [hsubplot; addsubplot];
	end
end

no_subplot = length(hsubplot);

% Default position of figure in a window in point coord

for i=1:no_subplot,
	set(hsubplot(i),'unit','point'),
	tmp_ylab_pos = get(get(hsubplot(i),'ylabel'),'position');
	ylab_pos(i) = tmp_ylab_pos(1);
end

new_ylab_pos = min(ylab_pos);

coner1 = get(hsubplot(1),'position');
coner2 = get(hsubplot(length(hsubplot)),'position');

% position of lowest-left coner
inix = coner1(1);
iniy = coner2(2)*1.13;

% axis line width
alinewidth = get(hsubplot(1),'linewidth');

% total lengths
total_xlength = (coner2(1) + coner2(3) - coner1(1)) + (no_col-1) * alinewidth;
total_ylength = (coner1(2) + coner1(4) - coner2(2)) + (no_row-1) * alinewidth;

% width of each subplot
delx = 1.0 * total_xlength / no_col;

% height of each subplot
dely = 0.97 * total_ylength / no_row;

%index_loop = 0;                   % total subplots index
%for index_row = 1:no_row,         % loop for row index
%    for index_col = 1:no_col          % loop for column index
%        index_loop = index_loop+1;
%
%        startx = inix + (index_col - 1) * delx;
%        starty = iniy + (no_row - index_row) * dely;
%
%%.......It's kind of bug of MATLAB
%        if alinewidth < 1.0
%           set(hsubplot(index_loop),'position',...
%              [ startx - 0.5 * alinewidth * (index_col-1), ...
%                starty - 0.5 * alinewidth * (index_row-1), delx ,dely]);
%%              [startx-1.0*alinewidth*(index_col-1), starty+1.5*alinewidth*(index_row-1), delx ,dely]);
%        else
%           set(hsubplot(index_loop),'position',[startx, starty, delx ,dely]);
%        end
%
%        subplot(hsubplot(index_loop));

index_loop = no_subplot+1;              % total subplots index (reverse order)
for index_row = no_row:-1:1,             % loop for row index
    for index_col = no_col:-1:1          % loop for column index
        index_loop = index_loop - 1;

        startx = inix + (index_col - 1) * delx;
        starty = iniy + (no_row - index_row) * dely;
        POSITION = [startx, starty, delx ,dely];

%.......It's kind of bug of MATLAB
        if alinewidth < 1.0
           POSITION =  [ startx - 0.5 * alinewidth * (index_col-1), ...
                         starty + 0.9 * alinewidth * (index_row-1), delx ,dely];
%          POSITION =  [startx-1.0*alinewidth*(index_col-1), starty+1.5*alinewidth*(index_row-1), delx ,dely]);
        end

        set(hsubplot(index_loop),'position',POSITION);

        subplot(hsubplot(index_loop));

        iscale = size(get(gca,'yscale'),2);  % 3:log, 6:linear

        % remove xlabels & xticklabels of subplots located in upper rows other than lowest row

        if index_row ~= no_row,
        	if ~(no_delta & index_row == (no_row - 1) & index_col == no_col),
            	set(get(gca,'xlabel'),'String',[])
            	set(gca,'xticklabel',[]);  %remove xticklabel
            end
        end

        % remove ylabels & yticklabels of subplots located in right columns other than leftmost column
        if index_col ~= 1,
           set(get(gca,'ylabel'),'String',[])
           set(gca,'yticklabel',[]);  %remove yticklabel
        end

        % remove first yticklabel of subplots located in lower rows other than highest row, linear yscale only
		% .... only linear scale
        if index_row ~= 1 & iscale == 6
           	a = get(gca,'ytick'); b = get(gca,'ylim');
			if a(length(a)) == b(length(b)),
           		a = a(1:length(a)-1);
           		set(gca,'ytick',a);
           	end
        end

        % remove first xticklabel of subplots located in left columns other than rightmost column
		% .... only linear scale

		if ~no_delta,
  	      	if index_col ~= no_col & iscale == 6
       	       	a = get(gca,'xtick'); b = get(gca,'xlim');
           	   	if a(length(a)) == b(length(b)),
          			a = a(1:length(a)-1);
           			set(gca,'xtick',a);
           		end
        	end
        else
	   	    if index_col == no_col & index_row == no_row - 1 & iscale == 6,
       	       	a = get(gca,'xtick');
          		a = a(2:length(a));
           		set(gca,'xtick',a);
           	end
        end

   end
end

% get back to initial unit
set(hfig,'unit','default')
for i=1:no_subplot,	set(hsubplot(i),'unit','default'),end

% delete dummy subplots
if no_delta, for i = 1:no_delta, delete(hsubplot(no_subplot1+i)); end, end


%% mission_data.param4 contains some NaN data, which is invalid for timeserials.
%% so remove it as we are not using param4 yet.

[row, col] = size(Mission_Data.param4.Data);

for i = 1 : row * col
    if isnan(Mission_Data.param4.Data(i))
       Mission_Data.param4.Data(i) = single(0);
    end
end


function title = p17_title ( option )

%*****************************************************************************80
%
%% P17_TITLE sets the title for problem 17.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer OPTION, the option index.
%
%    Output, string TITLE, the title of the problem.
%
  if ( option == 1 )
    title = 'Bremermann Propane Combustion System, fixed pressure.';
  else
    title = 'Bremermann Propane Combustion System, fixed concentration.';
  end

  return
end


function savejmesh(node,face,elem,fname,varargin)
%
% savejmesh(node,face,elem,fname,opt)
%
% export a mesh to the JMesh format defined in http://github.com/fangq/jmesh
%
% author: Qianqian Fang, <q.fang at neu.edu>
% date: 2011/10/06
%
% input:
%      node: node list, dimension (nn,3)
%      face: can be empty, surface face element list, dimension (be,3)
%      elem: can be empty, tetrahedral element list, dimension (ne,4)
%      fname: output file name; if file name has a suffix .bmsh,
%           the mesh data will be saved in the binary jmesh format; otherwise,
%           the file will be saved as a text-based jmesh (which is a plain
%           JSON file)
%      opt: additional parameters in the form of 'parameter',value pairs
%           valid parameters include:
%           'Dimension': 2 - a 2D mesh, 3 - a 3D mesh
%           'Author': a string to set the author of the mesh
%           'MeshTitle': a string to set the title of the mesh
%           'MeshTag': a value as the tag of the mesh data
%           'Comment': a string as the additional note for the mesh data
%           'MeshTag': a value as the tag of the mesh data
%           'Flexible': 0 (default)- use dimension-specific data containers
%                 (MeshVertex3, MeshTet4 ...). 1 - use flexible mesh data
%                 containers (MeshNode, MeshSurf, MeshElem)
%           'Header': 1 - include _DataInfo_ header, 0 - do not include
%
%           please type 'help savejson' and 'help savebj' to see additional
%           supported options
%
% examples:
%
%    [no,fc,el]=meshabox([0 0 0],[60,30,40],3,10);
%    savejmesh(no,fc,[],'box_surf.jmsh','dimension',3);
%    savejmesh(no,fc,el,'box_zlib.jmsh','compression','zlib');
%    savejmesh(no,fc,el,'box.bmsh','dimension',3);
%    savejmesh(no,fc,el,'box_zlib.bmsh','dimension',3,'compression','zlib');
%    savejmesh(no,[],el,'box_elem.jmsh','flexible',1) %sue MeshNode/MeshSurf/MeshElem
%    mesh=loadbj('box.bmsh')
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

if(nargin==2)
   fname=face;
   face=[];
   elem=[];
end

if(nargin==3)
   fname=elem;
   elem=[];
end

if(length(varargin)==1 && ischar(varargin{1}))
   opt=struct('FileName',varargin{1});
else
   opt=varargin2struct(varargin{:});
end

meshdim=jsonopt('Dimension',size(node,2),opt);

if(jsonopt('Header',1,opt)==1) % use metadata header
    mesh.(encodevarname('_DataInfo_'))=struct();

    metadata.JMeshVersion=0.5;
    metadata.Dimension=meshdim;
    metadata.CreationTime=datestr(now);
    metadata.Comment=['Created by Iso2Mesh ' iso2meshver '(http://iso2mesh.sf.net)'];
    metadata.AnnotationFormat='https://github.com/NeuroJSON/jmesh/blob/master/JMesh_specification.md';
    metadata.SerialFormat='http://json.org';
    metadata.Parser=struct('Python',[], ...
                           'MATLAB','https://github.com/NeuroJSON/jsonlab', ...
                           'JavaScript',[],...
                           'CPP', 'https://github.com/NeuroJSON/json',...
                           'C', []);
    metadata.Parser.Python={'https://pypi.org/project/jdata','https://pypi.org/project/bjdata'};
    metadata.Parser.JavaScript={'https://github.com/NeuroJSON/jsdata','https://github.com/NeuroJSON/js-bjdata'};
    metadata.Parser.C={'https://github.com/DaveGamble/cJSON','https://github.com/NeuroJSON/ubj'};
end

if(jsonopt('Flexible',0,opt)==1) % a user-defined mesh
    mesh.MeshNode=node;
    if(~isempty(face))
        mesh.MeshSurf=face;
    end
    if(~isempty(elem))
        mesh.MeshElem=elem;
    end
elseif(meshdim==3) % a 3D mesh
    nd=size(node);
    if(nd(2)<3)
        error('expecting 3 or more columns in node');
    end
    mesh.MeshVertex3=node(:,1:3);
    if(nd(2)>3)
        mesh.MeshVertex3=struct('Data',mesh.MeshVertex3,'Properties',struct('Value',node(:,4:end)));
    end
    if(~isempty(face))
        nd=size(face);
        if(nd(2)<3)
            error('expecting 3 or more columns in face');
        end
        mesh.MeshTri3=face(:,1:3);
        if(nd(2)>3)
            mesh.MeshTri3=struct('Data',mesh.MeshTri3,'Properties',struct('Value',face(:,4:end)));
        end
    end
    if(~isempty(elem))
        nd=size(elem);
        if(nd(2)<4)
            error('expecting 4 or more columns in elem');
        end
        mesh.MeshTet4=elem(:,1:4);
        if(nd(2)>4)
            mesh.MeshTet4=struct('Data',mesh.MeshTet4,'Properties',struct('Value',elem(:,5:end)));
        end
    end
elseif(meshdim==2) % a 2D mesh
    nd=size(node);
    if(nd(2)<2)
        error('expecting 2 or more columns in node');
    end
    mesh.MeshVertex2=node(:,1:2);
    if(nd(2)>2)
        mesh.MeshVertex2=struct('Data',mesh.MeshVertex2,'Properties',struct('Value',node(:,3:end)));
    end
    if(~isempty(face))
        nd=size(face);
        if(nd(2)<3)
            error('expecting 3 or more columns in face');
        end
        mesh.MeshTri3=face(:,1:3);
        if(nd(2)>3)
            mesh.MeshTri3=struct('Data',mesh.MeshTri3,'Properties',struct('Value',face(:,4:end)));
        end
    end
    if(~isempty(elem))
        warning('elem is redundant in a 2D mesh, skip');
    end
else
    error('the specified Dimension is not supported, please remove to save data to a general format');
end

author=jsonopt('Author','',opt);
if(~isempty(author))
    metadata.Author=author;
end

title=jsonopt('MeshTitle','',opt);
if(~isempty(title))
    metadata.MeshTitle=title;
end

tag=jsonopt('MeshTag',[],opt);
if(~isempty(tag))
    metadata.MeshTag=tag;
end

comm=jsonopt('Comment','',opt);
if(~isempty(comm))
    metadata.Comment=comm;
end

if(exist('metadata','var')) % use metadata
    mesh.(encodevarname('_DataInfo_'))=metadata;
end

if(~isempty(regexp(fname,'\.bmsh$', 'once')) || ~isempty(regexp(fname,'\.bmesh$', 'once')))
   savebj('',mesh,'FileName',fname,varargin{:});
else
   savejson('',mesh,'FileName',fname,varargin{:});
end


function [ h, hmin, hmax ] = p16_stepsize ( option )

%*****************************************************************************80
%
%% P16_STEPSIZE returns step sizes for problem 16.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer OPTION, the option index.
%
%    Output, real H, HMIN, HMAX, suggested values for the
%    initial step, the minimum step, and the maximum step.
%
  h =    0.200;
  hmin = 0.001;
  hmax = 2.000;

  return
end