function lvec_print ( n, a, title )

%*****************************************************************************80
%
%% LVEC_PRINT prints a logical vector.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the dimension of the vector.
%
%    Input, logical A(N), the vector to be printed.
%
%    Input, string TITLE, a title to be printed first.
%    TITLE may be blank.
%
  if ( 0 < s_len_trim ( title ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, '%s\n', title );
  end

  fprintf ( 1, '\n' );
  for i = 1 : n
    value = ( a(i) ~= 0 );
    fprintf ( 1, '%6d  %1d\n', i, value );
  end

  return
end


function [eigVec, eigVal, mmPerVox] = dtiLoadTensor(vectorsBasename, tensorBasename, b0Basename)
% [eigVec, eigVal, mmPerVox] = dtiLoadTensor([vectorsBasename], [tensorBasename], [b0Basename])
%
% 'eigVec' is a 5d array- a 3d array of 3x3 eigenVectors.
% To get the eigenVector for a particular voxel, use: v = eigVec(x,y,z,:,:);
%
% If you also provide the 'Tensor.float' file, then the eigen values are
% also returned (eigVal).
%
% If you provide the B0 filename, then we can get some useful info from the
% header, like the voxel dimensions.
%
% Loads the 3x3 matrix from the tensorcalc-format 'Vectors.float' file.
% The Vectors.float files are 32-bit floating point arrays (raw data- no header)
% with 9 images per file:
%   X1, Y1, Z1 = (signed) components of the eigenvector corresponding to the
%                largest eigenvalue.
%   X2, Y2, Z2 = (signed) components of the eigenvector corresponding to the
%                middle eigenvalue.
%   X3, Y3, Z3 = (signed) components of the eigenvector corresponding to the
%                smallest eigenvalue.
% All vectors are unit vectors.
%
%
% HISTORY:
% 2002.08.16 RFD (bobd@stanford.edu) Wrote it.
% 2003.11.13 RFD changed to return eigen vectors and values separately.
% 2003.11.26 RFD- we now get some useful info from the B0 header, if it's available.
%
% TODO:
%
%
% EXAMPLE:
% [eigVec,eigVal] = dtiLoadTensor('Vectors.float','Tensor.float');
% meanDiffusivity = sum(eigVal,4)/3;
% stdevDiffusivity = sqrt(sum((eigVal-repmat(meanDiffusivity,[1,1,1,3])).^2,4));
% normDiffusivity = sqrt(sum(eigVal.^2,4));
% fa = sqrt(3/2).*(stdevDiffusivity./normDiffusivity);
%

if(~exist('vectorsBasename', 'var') | isempty(vectorsBasename))
    [f,p] = uigetfile({'*.001';'*.*'},'Select a slice from the Vectors file...');
    vectorsBasename = fullfile(p,f(1:end-3));
    tensorBasename = fullfile(p,'Tensor.float.');
    b0Basename = fullfile(p,'B0.');
end
if(~exist('tensorBasename', 'var') | isempty(tensorBasename))
    tensorBasename = fullfile(fileparts(vectorsBasename),'Tensor.float.');
else
    if(tensorBasename(end) ~= '.')
        tensorBasename = [tensorBasename '.'];
    end
end
if(~exist('b0Basename', 'var') | isempty(b0Basename))
    b0Basename = fullfile(fileparts(vectorsBasename),'B0.');
else
    if(b0Basename(end) ~= '.')
        b0Basename = [b0Basename '.'];
    end
end

if(vectorsBasename(end) ~= '.')
    vectorsBasename = [vectorsBasename '.'];
end

nSlices = length(dir([vectorsBasename,'*']));
if(~isempty(b0Basename))
    [su,ex,se,im] = readIfileHeader([b0Basename,'001']);
    imdim = [im.imatrix_X, im.imatrix_Y, nSlices];
    mmPerVox = [im.pixsize_X, im.pixsize_Y, im.slthick];
else
    warning('B0 file not provided- guessing parameters!');
    mmPerVox = [260/128 260/128 3];
    % Now try to guess the image size
    d = dir([vectorsBasename,'001']);
    % OK- there are 9*4=36 bytes per voxel -> d.bytes/36 voxels. log2 tells us
    % how many bits this requires. We assume that the bits are divided equally
    % between X and Y (thus the /2), and then convert from bits to decimal (2^)
    xySize = 2^(log2(d.bytes./36)./2);
    imdim = [xySize,xySize,nSlices];
    disp(['I''m guessing that the image dimension is [',num2str(imdim),'].']);
end

npix = imdim(1)*imdim(2);
eigVec = zeros([imdim,3,3]);
if(~isempty(tensorBasename))
    eigVal = zeros([imdim,3]);
else
    eigVal = [];
end
disp(['Reading ',num2str(nSlices),' slices...']);
for(ii=1:imdim(3))
    fname = sprintf('%s%03d', vectorsBasename, ii);
    fid = fopen(fname, 'rb', 'ieee-be');
    eigVec(:,:,ii,:,:) = reshape(fread(fid, inf, 'float32'),[imdim(1),imdim(2),1,3,3]);
    fclose(fid);
    % Unfortunately, tensorcalc stores only the unit vectors in the Vectors
    % file. So, we need to open up the corresponding Tensor file and get
    % the eigenvalues from there.
    if(~isempty(tensorBasename))
        fname = sprintf('%s%03d', tensorBasename, ii);
        % 2004.03.26 RFD: Data now in ieee-le format?
        fid = fopen(fname, 'rb', 'ieee-be');
        % The eigen values are in the 2:4 sections of the Tensor.float
        % file.  Here, we just read the first four sections.
        tmp = fread(fid, npix*4, 'float32');
        % Drop the first section, since it's the mean diffusivity.
        tmp = tmp(npix+1:end);
        fclose(fid);
        eigVal(:,:,ii,1) = reshape(tmp(1:npix), imdim(1), imdim(2));
        eigVal(:,:,ii,2) = reshape(tmp(npix+1:npix*2), imdim(1), imdim(2));
        eigVal(:,:,ii,3) = reshape(tmp(npix*2+1:npix*3), imdim(1), imdim(2));
    end
end
return;

% Genreal notes about tensorcalc data:
% Each slice is in a separate file. Included are two different data file types,
% Tensor.float and Vectors.float. Tensor.float contains most of the info that
% you would need to do fiber tracing, except that it does not contain the
% eigenvectors corresponding to the two smaller eigenvalues. Vectors.float
% contains all 3 eigenvectors. (For more info about these files, see
% http://sirl.stanford.edu/dwi/maj/)
%
% Tensor.float files are 32-bit floating point arrays (raw data- no header)
% containing the following maps:
%
% 1. Mean diffusivity (or Trace/3, units x106 mm2/s)
% 2. Maximum eigenvalue
% 3. Medium eigenvalue
% 4. Minimum eigenvalue
% 5. X component of the maximum eigenvector (values between -1 and 1)
% 6. Y component of the maximum eigenvector
% 7. Z component of the maximum eigenvector
% 8. Fractional Anisotropy, FA (multiplied by 1000)
% 9. Lattice index, Add (if asked for via -Add option)
% 10. Coherence index, CI (if asked for via -CI option)
% 11. b=0 image (arbitrary units)
%
% Sample matlab code to read these files:
%
% baseName = 'Tensor.float.';
% imDim = [128,128,38];
% meanDiffusion = zeros(imDim);
% maxEigVal = zeros(imDim);
% medEigVal = zeros(imDim);
% minEigVal = zeros(imDim);
% maxEigValX = zeros(imDim);
% maxEigValY = zeros(imDim);
% maxEigValZ = zeros(imDim);
% fa = zeros(imDim);
% for(ii=1:imDim(3))
%     fname = sprintf('%s%03d', baseName, ii);
%     fid = fopen(fname, 'rb', 'ieee-be');
%     tmp = reshape(fread(fid, inf, 'float32'),[imDim(1),imDim(2),11]);
%     fclose(fid);
%     meanDiffusion(:,:,ii) = tmp(:,:,1);
%     maxEigVal(:,:,ii) = tmp(:,:,2);
%     medEigVal(:,:,ii) = tmp(:,:,3);
%     minEigVal(:,:,ii) = tmp(:,:,4);
%     maxEigValX(:,:,ii) = tmp(:,:,5);
%     maxEigValY(:,:,ii) = tmp(:,:,6);
%     maxEigValZ(:,:,ii) = tmp(:,:,7);
%     fa(:,:,ii) = tmp(:,:,8);
%     b0(:,:,ii) = tmp(:,:,11);
% end


function [stepsize newx storedb lsmem lsstats] = ...
                linesearch(problem, x, d, f0, df0, options, storedb, lsmem)
% Standard line search algorithm (step size selection) for descent methods.
%
% function [stepsize newx storedb lsmem lsstats] =
%               linesearch(problem, x, d, f0, df0, options, storedb, lsmem)
%
% Base linesearch algorithm for descent methods, based on a simple
% backtracking method. The search direction provided has to be a descent
% direction, as indicated by a negative df0 = directional derivative of f
% at x along d.
%
% The algorithm is invariant under positive scaling of the cost function
% and under offsetting, that is: if the cost function f is replaced by
% 8*f+3 for example, the returned step size will be the same. Furthermore,
% the returned step size is independent of the norm of the search direction
% vector d: only the direction of d is important.
%
% Below, the step will be constructed as alpha*d, and the step size is the
% norm of that vector, thus: stepsize = alpha*norm_d. The step is executed
% by retracting the vector alpha*d from the current point x, giving newx.
%
% Inputs
%
%  problem : structure holding the description of the optimization problem
%  x : current point on the manifold problem.M
%  d : tangent vector at x (descent direction) -- its norm is irrelevant
%  f0 : cost value at x
%  df0 : directional derivative at x along d
%  options : options structure (see in code for usage)
%  storedb : store database structure for caching purposes
%  lsmem : a special memory holder to give the linesearch the opportunity
%          to "remember" what happened in the previous calls. See below.
%
% Outputs
%
%  stepsize : norm of the vector retracted to reach newx from x.
%  newx : next iterate suggested by the line search algorithm, such that
%         the retraction at x of the vector alpha*d reaches newx.
%  storedb : the (possibly updated) store database structure.
%  lsmem : the (possibly updated) lsmem memory holder.
%  lsstats : statistics about the line search procedure (stepsize, number
%            of trials etc).
%
% About lsmem : It can be anything, and will typically be a matrix or a
%               structure. When first calling the line search, it should be
%               passed as the empty matrix []. For subsequent calls
%               (pertaining to the same solver call), the previously
%               returned lsmem should be passed as input. This memory
%               holder gives the line search a chance to exploit knowledge
%               of previous decisions to make new decisions.
%
% See also: steepestdescent conjugategradients linesearch_adaptive

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, Dec. 30, 2012.
% Contributors:
% Change log:
%     Sept. 13, 2013 (NB) : User control over the parameters of the
%                           linesearch via the options
%                           ls_contraction_factor, ls_optimism,
%                           ls_suff_decr and ls_max_steps. See in code for
%                           the effect of those.
%     Sept. 13, 2013 (NB) : The automatic direction reversal feature was
%                           removed (it triggered when df0 > 0). Direction
%                           reversal is a decision that needs to be made by
%                           the solver, so it can know about it.
%     Sept. 13, 2013 (NB) : The linesearch is now invariant under rescaling
%                           of the cost function f. That is, if f is
%                           replaced by 8*f (and hence the directional
%                           derivatives of f are scaled accordingly), the
%                           stepsizes computed will not change.
%     Nov. 7, 2013 (NB) :   The linesearch is now invariant under rescaling
%                           of the search direction d. The meaning of
%                           stepsize is also more clear in the comments.
%                           Added a parameter ls_initial_stepsize to give
%                           users control over the first step size trial.

    % Backtracking default parameters. These can be overwritten in the
    % options structure which is passed to the solver.
    default_options.ls_contraction_factor = .5;
    default_options.ls_optimism = 1/.5;
    default_options.ls_suff_decr = 1e-4;
    default_options.ls_max_steps = 25;
    default_options.ls_initial_stepsize = 1;

    options = mergeOptions(default_options, options);

    contraction_factor = options.ls_contraction_factor;
    optimism = options.ls_optimism;
    suff_decr = options.ls_suff_decr;
    max_ls_steps = options.ls_max_steps;
    initial_stepsize = options.ls_initial_stepsize;

    % Compute the norm of the search direction.
    % This is useful to make the linesearch algorithm invariant under the
    % scaling of d. The rationale is that the important information is the
    % search direction, not the size of that vector. The question of how
    % far we should go is precisely what the linesearch algorithm is
    % supposed to answer: the calling algorithm should not need to care.
    norm_d = problem.M.norm(x, d);

    % At first, we have no idea of what the step size should be.
    alpha = NaN;

    % If we know about what happened at the previous step, we can leverage
    % that to compute an initial guess for the step size, as inspired from
    % Nocedal&Wright, p59.
    if isstruct(lsmem) && isfield(lsmem, 'f0')
        % Pick initial step size based on where we were last time,
        alpha = 2*(f0-lsmem.f0)/df0;
        % and go look a little further (or less far), just in case.
        alpha = optimism*alpha;
    end

    % If we have no information about the previous iteration (maybe this is
    % the first one?) or if the above formula gave a too small step size
    % (perhaps it is even negative), then fall back to a user supplied
    % suggestion for the first step size (the "a priori").
    % At any rate, the choice should be invariant under rescaling of the
    % cost function f and of the search direction d, and it should be
    % bounded away from zero for convergence guarantees. We must allow it
    % to be close to zero though, for fine convergence.
    if isnan(alpha) || alpha*norm_d <= eps
        alpha = initial_stepsize/norm_d;
    end

    % Make the chosen step and compute the cost there.
    newx = problem.M.retr(x, d, alpha);
    [newf storedb] = getCost(problem, newx, storedb);
    cost_evaluations = 1;

    % Backtrack while the Armijo criterion is not satisfied
    while newf > f0 + suff_decr*alpha*df0

        % Reduce the step size,
        alpha = contraction_factor * alpha;

        % and look closer down the line
        newx = problem.M.retr(x, d, alpha);
        [newf storedb] = getCost(problem, newx, storedb);
        cost_evaluations = cost_evaluations + 1;

        % Make sure we don't run out of budget
        if cost_evaluations >= max_ls_steps
            break;
        end

    end

    % If we got here without obtaining a decrease, we reject the step.
    if newf > f0
        alpha = 0;
        newx = x;
        newf = f0; %#ok<NASGU>
    end

    % As seen outside this function, stepsize is the size of the vector we
    % retract to make the step from x to newx. Since the step is alpha*d:
    stepsize = alpha * norm_d;

    % Save the situtation faced now so that at the next iteration, we will
    % know something about the previous decision.
    lsmem.f0 = f0;
    lsmem.df0 = df0;
    lsmem.stepsize = stepsize;

    % Save some statistics also, for possible analysis.
    lsstats.costevals = cost_evaluations;
    lsstats.stepsize = stepsize;
    lsstats.alpha = alpha;

end


%% HILBERT_FSU uses the fsuClusterMatlab command to run the HILBERT "computation".
%
%  Discussion:
%
%    The arguments to fsuClusterMatlab mean:
%
%    '~/matlab/hilbert_parfor' allows us to specify an output directory;
%
%    [] allows us to specify switches to the MOAB queue handler, such as more time.
%
%    'p" indicates this is a "parfor" job;
%
%    'w' indicates that the MATLAB session should wait for completion;
%
%    workers is the number of processors requested;
%
%    @hilbert_fun indicates the function we want to execute;
%
%    { n } contains input arguments to the function.
%
%    The function "hilbert_fun" must correspond to a MATLAB M-file "hilbert_fun.m"
%    and that file must be in MATLAB's path.
%
%    The easiest way to ensure that the file is in MATLAB's path is to
%    create a subdirectory called "matlab" immediately below your home directory,
%    and place the function file there (as well as any other files needed
%    by the job).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2012
%
%  Author:
%
%    John Burkardt
%
  m = 100;
  n = 100;
  workers = 4;

  tic

  fsuClusterMatlab ( '~/matlab/hilbert_parfor', [], 'p', 'w', workers, ...
    @hilbert_fun, { m, n } )

  toc


function weight = read_filter(file_name);
FID = fopen(file_name,'r');
tmp = textscan(FID,'%f ',2);
filter_len = tmp{1}(1);
N_ch = tmp{1}(2);
for i=1:N_ch,
    tmp = textscan(FID,'%f ', filter_len);
    weight(:,i) = tmp{1};
end
fclose(FID);


function hole_point = p04_hole_point ( hole_index, m )

%*****************************************************************************80
%
%% P04_HOLE_POINT returns a point inside a given hole in problem 4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer HOLE_INDEX, the index of the hole.
%
%    Input, integer M, the spatial dimension.
%
%    Output, real HOLE_POINT(M), a point in the hole
%
  hole_point(1:2) = [ 0.0, 0.0 ];

  return
end


function c = mpower(a,b)
% MPOWER implements c = a^b, where either a or b is an adiff object.
% For adiff objects, a^b is taken to be equivalent to a.^b

c=power(a,b);


function th=rotateticklabel(h,rot,demo)
%ROTATETICKLABEL rotates tick labels
%   TH=ROTATETICKLABEL(H,ROT) is the calling form where H is a handle to
%   the axis that contains the XTickLabels that are to be rotated. ROT is
%   an optional parameter that specifies the angle of rotation. The default
%   angle is 90. TH is a handle to the text objects created. For long
%   strings such as those produced by datetick, you may have to adjust the
%   position of the axes so the labels don't get cut off.
%
%   Of course, GCA can be substituted for H if desired.
%
%   TH=ROTATETICKLABEL([],[],'demo') shows a demo figure.
%
%   Known deficiencies: if tick labels are raised to a power, the power
%   will be lost after rotation.
%
%   See also datetick.

%   Written Oct 14, 2005 by Andy Bliss
%   Copyright 2005 by Andy Bliss

%DEMO:
if nargin==3
    x=[now-.7 now-.3 now];
    y=[20 35 15];
    figure
    plot(x,y,'.-')
    datetick('x',0,'keepticks')
    h=gca;
    set(h,'position',[0.13 0.35 0.775 0.55])
    rot=90;
end

%set the default rotation if user doesn't specify
if nargin==1
    rot=90;
end
%make sure the rotation is in the range 0:360 (brute force method)
while rot>360
    rot=rot-360;
end
while rot<0
    rot=rot+360;
end
%get current tick labels
a=get(h,'XTickLabel');
%erase current tick labels from figure
set(h,'XTickLabel',[]);
%get tick label positions
b=get(h,'XTick');
c = get(h,'YLim');
ydir = get(h,'YDir');
if strcmpi(ydir,'reverse'),
  c = c([2,1]);
end
%make new tick labels
if rot<180
    th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','right','rotation',rot,'Parent',h);
    for i = 1:numel(th),
      ex = get(th(i),'Extent');
      pos = get(th(i),'Position');
      if strcmpi(ydir,'normal'),
        off = c(1) - (ex(2)+ex(4));
        pos(2) = pos(2) + off;
        set(th(i),'Position',pos);
      else
        off = ex(2)-ex(4) - c(1);
        pos(2) = pos(2) - off;
        set(th(i),'Position',pos);
      end
    end
else
    th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','left','rotation',rot,'Parent',h);
end
set(th,'Interpreter','none');


function n = p17_n ( )

%*****************************************************************************80
%
%% P17_N returns the number of variables for problem 17.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 March 2000
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer N.  If N is positive, N represents the
%    only legal value for N for this problem.  If N is
%    negative, the absolute value of N is the least legal
%    value of N, but other values are allowable.
%
  n = 4;

  return
end


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

%*****************************************************************************80
%
%% I4MAT_PRINT_SOME prints out a portion of an I4MAT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns of the matrix.
%
%    Input, integer 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 = 10;

  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' );
    fprintf ( 1, '\n' );

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

    for i = i2lo : i2hi

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

      fprintf ( 1, '\n' );

    end

  end

  return
end


function Qdec = num2Qdec(M,Vars)
% Qdec = num2Qdec(M,Vars)
%
% Converts numeric matrix M to two dimensional cell string array Qdec.
%
% Input
% M: Numeric matrix.
% Vars: One dimensional cell string array with the name of the Qdec
% variables corresponding to the columns of M.
%
% Output
% Qdec: Two dimensional cell string array of Qdec data .
%
% $Revision: 1.2 $  $Date: 2015/01/06 17:14:53 $
% Original Author: Jorge Luis Bernal Rusiel
% CVS Revision Info:
%    $Author: mreuter $
%    $Date: 2015/01/06 17:14:53 $
%    $Revision: 1.2 $
%
if nargin < 2
    error('Too few inputs');
end;
szM = size(M);
Qdec = cell(szM(1)+1,szM(2));
Qdec(1,1:end) = Vars;
for i=2:szM(1)+1
    for j=1:szM(2)
        Qdec{i,j} = num2str(M(i-1,j));
    end;
end;


function [ convertedstr ] = convertSBMLID( str, toSBML )
%CONVERTSBMLID converts the given str to a valid SBML ID
% USAGE:
%
%       convertedstr = convertSBMLID(str,toSBML)
%
% INPUT:
%
%       str:        The String to convert
%
% OPTIONAL INPUT:
%       toSBML:     Whether to convert to SBML format (or undo a
%                   conversion) (default true, ie convert to SBML)
%
% OUTPUT:
%
%       convertedstr:   The converted String.
%
% .. Authors:
%       - Thomas Pfau May 2017

if ~exist('toSBML','var')
    toSBML = true;
end
if toSBML
    convertedstr = regexprep(str,'([^0-9_a-zA-Z])','__${num2str($1+0)}__');
else
    convertedstr = regexprep(str,'__([0-9]+)__','${char(str2num($1))}');
    %Biomodels specific conversions for Input of Biomodels
    convertedstr = strrep(convertedstr,'-DASH-','-');
    convertedstr = strrep(convertedstr,'_DASH_','-');
    convertedstr = strrep(convertedstr,'_FSLASH_','/');
    convertedstr = strrep(convertedstr,'_BSLASH_','\');
    convertedstr = strrep(convertedstr,'_LPAREN_','(');
    convertedstr = strrep(convertedstr,'_LSQBKT_','[');
    convertedstr = strrep(convertedstr,'_RSQBKT_',']');
    convertedstr = strrep(convertedstr,'_RPAREN_',')');
    convertedstr = strrep(convertedstr,'_COMMA_',',');
    convertedstr = strrep(convertedstr,'_PERIOD_','.');
    convertedstr = strrep(convertedstr,'_APOS_','''');
end

end


%% Copyright (C) 2014-2016, 2018-2019, 2022 Colin B. Macdonald
%% Copyright (C) 2014-2015 Andrés Prieto
%% Copyright (C) 2020 Rafael Laboissière
%% Copyright (C) 2020 Jing-Chen Peng
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published
%% by the Free Software Foundation; either version 3 of the License,
%% or (at your option) any later version.
%%
%% This software is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty
%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
%% the GNU General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with this software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @deftypemethod  @@sym {@var{sol} =} dsolve (@var{ode})
%% @deftypemethodx @@sym {@var{sol} =} dsolve (@var{ode}, @var{IC})
%% @deftypemethodx @@sym {@var{sol} =} dsolve (@var{ODEs}, @var{IC1}, @var{IC2}, @dots{})
%% @deftypemethodx @@sym {@var{sol} =} dsolve (@var{ODEs}, @var{ICs})
%% @deftypemethodx @@sym {[@var{sol}, @var{classify}] =} dsolve (@dots{})
%% Solve ordinary differential equations (ODEs) symbolically.
%%
%% Basic example:
%% @example
%% @group
%% syms y(x)
%% DE = diff(y, x) - 4*y == 0
%%   @result{} DE = (sym)
%%                 d
%%       -4⋅y(x) + ──(y(x)) = 0
%%                 dx
%% @end group
%%
%% @group
%% sol = dsolve (DE)
%%   @result{} sol = (sym)
%%           4⋅x
%%       C₁⋅ℯ
%% @end group
%% @end example
%%
%% You can specify initial conditions:
%% @example
%% @group
%% sol = dsolve (DE, y(0) == 1)
%%   @result{} sol = (sym)
%%        4⋅x
%%       ℯ
%% @end group
%% @end example
%%
%% In some cases, SymPy can return a classification of the
%% differential equation:
%% @example
%% @group
%% DE = diff(y) == y^2
%%   @result{} DE = (sym)
%%       d           2
%%       ──(y(x)) = y (x)
%%       dx
%%
%% [sol, classify] = dsolve (DE, y(0) == 1)
%%   @result{} sol = (sym)
%%        -1
%%       ─────
%%       x - 1
%%   @result{} classify = ... separable ...
%% @end group
%% @end example
%%
%% Many types of ODEs can be solved, including initial-value
%% problems and boundary-value problem:
%% @example
%% @group
%% DE = diff(y, 2) == -9*y
%%   @result{} DE = (sym)
%%          2
%%         d
%%        ───(y(x)) = -9⋅y(x)
%%          2
%%        dx
%%
%% dsolve (DE, y(0) == 1, diff(y)(0) == 12)
%%   @result{} (sym) 4⋅sin(3⋅x) + cos(3⋅x)
%%
%% dsolve (DE, y(0) == 1, y(sym(pi)/2) == 2)
%%   @result{} (sym) -2⋅sin(3⋅x) + cos(3⋅x)
%% @end group
%% @end example
%%
%% Some systems can be solved, including initial-value problems
%% involving linear systems of first order ODEs with constant
%% coefficients:
%% @example
%% @group
%% syms x(t) y(t)
%% ode_sys = [diff(x(t),t) == 2*y(t);  diff(y(t),t) == 2*x(t)]
%%   @result{} ode_sys = (sym 2×1 matrix)
%%       ⎡d                ⎤
%%       ⎢──(x(t)) = 2⋅y(t)⎥
%%       ⎢dt               ⎥
%%       ⎢                 ⎥
%%       ⎢d                ⎥
%%       ⎢──(y(t)) = 2⋅x(t)⎥
%%       ⎣dt               ⎦
%% @end group
%%
%% @group
%% soln = dsolve (ode_sys)
%%   @result{} soln = scalar structure containing ...
%%        x = ...
%%        y = ...
%%
%% @c doctest: +SKIP_IF(pycall_sympy__ ('return Version(spver) <= Version("1.5.1")'))
%% soln.x
%%   @result{} ans =
%%       (sym)
%%               -2⋅t       2⋅t
%%         - C₁⋅ℯ     + C₂⋅ℯ
%%
%% @c doctest: +SKIP_IF(pycall_sympy__ ('return Version(spver) <= Version("1.5.1")'))
%% soln.y
%%   @result{} ans =
%%       (sym)
%%             -2⋅t       2⋅t
%%         C₁⋅ℯ     + C₂⋅ℯ
%% @end group
%% @end example
%%
%% Note: The Symbolic Math Toolbox used to support strings like 'Dy + y = 0'; we
%% are unlikely to support this so you will need to assemble a symbolic
%% equation instead.
%%
%% @seealso{@@sym/diff, @@sym/int, @@sym/solve}
%% @end deftypemethod

function [soln,classify] = dsolve(ode,varargin)

  % Usually we cast to sym in the _cmd call, but want to be
  % careful here b/c of symfuns
  if (~ iscell (ode) && ~ all (isa (ode, 'sym')))
    error('Inputs must be sym or symfun')
  end

  % FIXME: might be nice to expose SymPy's "sp.ode.classify_sysode" and
  %        "sp.ode.classify_ode" with their own commands
  if (isscalar(ode) && nargout==2)
    cmd = { 'from sympy.solvers import classify_ode'
            'return classify_ode(_ins[0]),' };
    classify = pycall_sympy__ (cmd, ode);
  elseif(~isscalar(ode) && nargout==2)
    warning('Classification of systems of ODEs is currently not supported')
    classify='';
  end

  cmd = { 'ode=_ins[0]; ics=_ins[1:]'
          'if len(ics) == 1:'
          '    ics = ics[0]'
          'try:'
          '    ics = {ic.lhs: ic.rhs for ic in ics}'
          'except TypeError:'  % not iterable
          '    ics = {ics.lhs: ics.rhs}'
          'sol = sp.dsolve(ode, ics=ics)'
          'def convert_helper(sympy_obj):'
          '    if isinstance(sympy_obj, Eq) and sympy_obj.lhs.is_Function:'
                   % y(t) = rhs to str "y", rhs expression
          '        return str(sympy_obj.lhs.func), sympy_obj.rhs'
          '    return None, None'
          % if just single equality with simple lhs, we return the rhs
          'if isinstance(sol, Eq):'
          '    if sol.lhs.is_Function:'
          '        return sol.rhs'
          % If the solution set is iterable (system or multiple solutions),
          % we will try to convert to structure of {"x": expr, "y": expr2, ...}
          'try:'
          '    return_data = dict()'
          '    for solution_part in sol:'
          '        key, rhs = convert_helper(solution_part)'
          '        if key is None:'
          '            raise ValueError("not of right form for extraction")'
          '        if key in return_data.keys():'
          '            raise KeyError(f"repeated key {key}")'
          '        return_data[key] = rhs'
          '    return return_data'
          'except (TypeError, ValueError, KeyError):'
          '    pass'
          % if nothing else worked, give back whatever form we have
          'return sol' };
  soln = pycall_sympy__ (cmd, ode, varargin{:});
end

%!error <sym> dsolve (1, sym('x'))

%!test
%! syms y(x)
%! de = diff(y, 2) - 4*y == 0;
%! f = dsolve(de);
%! syms C1 C2
%! g1 = C1*exp(-2*x) + C2*exp(2*x);
%! g2 = C2*exp(-2*x) + C1*exp(2*x);
%! assert (isequal (f, g1) || isequal (f, g2))

%!test
%! % Not enough initial conditions
%! syms y(x) C1
%! de = diff(y, 2) + 4*y == 0;
%! g = 3*cos(2*x) + C1*sin(2*x);
%! try
%!   f = dsolve(de, y(0) == 3);
%!   waserr = false;
%! catch
%!   waserr = true;
%!   expectederr = regexp (lasterr (), 'Perhaps.*under-specified');
%!   f = 42;
%! end
%! assert ((waserr && expectederr) || isequal (f, g))

%!test
%! % Solution in implicit form
%! syms y(x) C1
%! de = (2*x*y(x) - exp(-2*y(x)))*diff(y(x), x) + y(x) == 0;
%! sol = dsolve (de);
%! eqn = x*exp(2*y(x)) - log(y(x)) == C1;
%! % could differ by signs
%! sol = lhs (sol) - rhs (sol);
%! eqn = lhs (eqn) - rhs (eqn);
%! sol2 = subs (sol, C1, -C1);
%! assert (isequal (sol, eqn) || isequal (sol2, eqn))

%%!xtest
%%! % system with solution in implicit form
%%! % TODO: not implemented upstream?
%%! syms y(x) z(x) C1
%%! de1 = (2*x*y(x) - exp(-2*y(x)))*diff(y(x), x) + y(x) == 0;
%%! de2 = diff(z, x) == 0;
%%! sol = dsolve ([de1; de2]);

%!test
%! % Compute solution and classification
%! syms y(x) C1
%! de = (2*x*y(x) - exp(-2*y(x)))*diff(y(x), x) + y(x) == 0;
%! [sol, classy] = dsolve (de);
%! assert (any (strcmp (classy, '1st_exact')))

%!test
%! % initial conditions (first order ode)
%! syms y(x)
%! de = diff(y, x) + 4*y == 0;
%! f = dsolve(de, y(0) == 3);
%! g = 3*exp(-4*x);
%! assert (isequal (f, g))

%!test
%! % initial conditions (second order ode)
%! syms y(x)
%! de = diff(y, 2) + 4*y == 0;
%! f = dsolve(de, y(0) == 3, subs(diff(y,x),x,0)==0);
%! g = 3*cos(2*x);
%! assert (isequal (f, g))

%!test
%! % Dirichlet boundary conditions (second order ode)
%! syms y(x)
%! de = diff(y, 2) + 4*y == 0;
%! f = dsolve(de, y(0) == 2, y(1) == 0);
%! g = -2*sin(2*x)/tan(sym('2'))+2*cos(2*x);
%! assert (isequal (simplify (f - g), 0))

%!test
%! % Neumann boundary conditions (second order ode)
%! syms y(x)
%! de = diff(y, 2) + 4*y == 0;
%! f = dsolve(de, subs(diff(y,x),x,0)==1, subs(diff(y,x),x,1)==0);
%! g = sin(2*x)/2+cos(2*x)/(2*tan(sym('2')));
%! assert (isequal (simplify (f - g), 0))

%!test
%! % Dirichlet-Neumann boundary conditions (second order ode)
%! syms y(x)
%! de = diff(y, 2) + 4*y == 0;
%! f = dsolve(de, y(0) == 3, subs(diff(y,x),x,1)==0);
%! g = 3*sin(2*x)*tan(sym('2'))+3*cos(2*x);
%! assert (isequal (simplify (f - g), 0))

%!test
%! % System of ODEs gives struct, Issue #1003.
%! syms x(t) y(t)
%! ode1 = diff(x(t),t) == 2*y(t);
%! ode2 = diff(y(t),t) == 2*x(t);
%! soln = dsolve([ode1, ode2]);
%! assert (isstruct (soln))
%! assert (numfields (soln) == 2)
%! assert (isequal (sort (fieldnames (soln)), {'x'; 'y'}))

%!test
%! % System of ODEs
%! syms x(t) y(t) C1 C2
%! ode1 = diff(x(t),t) == 2*y(t);
%! ode2 = diff(y(t),t) == 2*x(t);
%! soln = dsolve([ode1, ode2]);
%! soln = [soln.x, soln.y];
%! g1 = [C1*exp(-2*t) + C2*exp(2*t), -C1*exp(-2*t) + C2*exp(2*t)];
%! g2 = [C1*exp(2*t) + C2*exp(-2*t), C1*exp(2*t) - C2*exp(-2*t)];
%! g3 = [-C1*exp(-2*t) + C2*exp(2*t), C1*exp(-2*t) + C2*exp(2*t)];
%! g4 = [C1*exp(2*t) - C2*exp(-2*t), C1*exp(2*t) + C2*exp(-2*t)];
%! % old SymPy <= 1.5.1 had some extra twos
%! g5 = [2*C1*exp(-2*t) + 2*C2*exp(2*t), -2*C1*exp(-2*t) + 2*C2*exp(2*t)];
%! g6 = [2*C1*exp(2*t) + 2*C2*exp(-2*t), 2*C1*exp(2*t) - 2*C2*exp(-2*t)];
%! assert (isequal (soln, g1) || isequal (soln, g2) || ...
%!         isequal (soln, g3) || isequal (soln, g4) || ...
%!         isequal (soln, g5) || isequal (soln, g6))

%!test
%! % System of ODEs (initial-value problem)
%! syms x(t) y(t)
%! ode_1=diff(x(t),t) == 2*y(t);
%! ode_2=diff(y(t),t) == 2*x(t);
%! sol_ivp=dsolve([ode_1,ode_2],x(0)==1,y(0)==0);
%! g_ivp=[exp(-2*t)/2+exp(2*t)/2,-exp(-2*t)/2+exp(2*t)/2];
%! assert (isequal ([sol_ivp.x, sol_ivp.y], g_ivp))

%!test
%! syms y(x)
%! de = diff(y, 2) + 4*y == 0;
%! f = dsolve(de, y(0) == 0, y(sym(pi)/4) == 1);
%! g = sin(2*x);
%! assert (isequal (f, g))

%!test
%! % Nonlinear example
%! syms y(x) C1
%! e = diff(y, x) == y^2;
%! g = -1 / (C1 + x);
%! soln = dsolve(e);
%! assert (isequal (soln, g))

%!test
%! % Nonlinear example with initial condition
%! syms y(x)
%! e = diff(y, x) == y^2;
%! g = -1 / (x - 1);
%! soln = dsolve(e, y(0) == 1);
%! assert (isequal (soln, g))

%!test
%! % forcing, Issue #183, broken in older sympy
%! if (pycall_sympy__ ('return Version(spver) >= Version("1.7.1")'))
%! syms x(t) y(t)
%! ode1 = diff(x) == x + sin(t) + 2;
%! ode2 = diff(y) == y - t - 3;
%! soln = dsolve([ode1 ode2], x(0) == 1, y(0) == 2);
%! X = soln.x;
%! Y = soln.y;
%! assert (isequal (diff(X) - (X + sin(t) + 2), 0))
%! assert (isequal (diff(Y) - (Y - t - 3), 0))
%! end

%!test
%! syms f(x) a b
%! de = diff(f, x) == 4*f;
%! s = dsolve(de, f(a) == b);
%! assert (isequal (subs(s, x, a), b))

%!test
%! % array of ICs
%! syms x(t) y(t)
%! ode_1 = diff (x(t), t) == 2*y(t);
%! ode_2 = diff (y(t), t) == 2*x(t);
%! sol = dsolve([ode_1, ode_2], [x(0)==1 y(0)==0]);
%! g = [exp(-2*t)/2+exp(2*t)/2, -exp(-2*t)/2+exp(2*t)/2];
%! assert (isequal ([sol.x, sol.y], g))

%!test
%! % cell-array of ICs or ODEs, but not both
%! % Note: to support both we'd need a wrapper outside of @sym
%! syms x(t) y(t)
%! ode_1 = diff (x(t), t) == 2*y(t);
%! ode_2 = diff (y(t), t) == 2*x(t);
%! sol = dsolve([ode_1, ode_2], {x(0)==1 y(0)==0});
%! g = [exp(-2*t)/2+exp(2*t)/2, -exp(-2*t)/2+exp(2*t)/2];
%! assert (isequal ([sol.x, sol.y], g))
%! sol = dsolve({ode_1, ode_2}, [x(0)==1 y(0)==0]);
%! g = [exp(-2*t)/2+exp(2*t)/2, -exp(-2*t)/2+exp(2*t)/2];
%! assert (isequal ([sol.x, sol.y], g))

%!test
%! % array of ICs, Issue #1040.
%! if (pycall_sympy__ ('return Version(spver) >= Version("1.7.1")'))
%! syms x(t) y(t) z(t)
%! syms x_0 y_0 z_0
%! diffEqns = [diff(x, t) == -x + 1, diff(y, t) == -y, diff(z, t) == -z];
%! initCond = [x(0) == x_0, y(0) == y_0, z(0) == z_0];
%! soln = dsolve (diffEqns, initCond);
%! soln = [soln.x, soln.y, soln.z];
%! exact_soln = [(x_0 - 1)*exp(-t) + 1  y_0*exp(-t)  z_0*exp(-t)];
%! assert (isequal (soln, exact_soln))
%! end


% Read point cloud from PLY file and return coordinates
function [X, Y, Z] = readPointCloud(plyFile, s)
    if (nargin < 2) s = 1; end;

    ptCloud = pcread(plyFile);
    N = ptCloud.Count;
    if (s<=1)
        idx = randsample(N, round(N*s))';
    else
        idx = randsample(N, s)';
    end
    X = ptCloud.Location(idx,1)';
    Y = ptCloud.Location(idx,2)';
    Z = ptCloud.Location(idx,3)';

    X = double(X); Y = double(Y); Z = double(Z);
end


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

%%
clear; close all; clc;

%% Syntax
% |axisGeom(h,fontSize);|

%% Description
% This function sets axis properties commonly used for viewing geometry in
% 3D:
%
% |axis equal; axis vis3d; axis tight;|
%
% The optional inputs include the axis handle and the desired font size.

%% Examples
%

%% Setting axis parameters for 3D geometry viewing

%%
% Create something to visualize
[F,V]=graphicsModels(9);

%%
% Visualize

cFigure; hold on;
gpatch(F,V,'w','k');

axisGeom; %Set axis properties

camlight headlight;
gdrawnow;

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


function varargout = splitting(on_off)
%SPLITTING   CHEBFUN splitting option.
%   SPLITTING('ON') allows the CHEBFUN constructor to split the interval by a
%   process of automatic subdivision and edge detection. This option is
%   recommended when working with functions with singularities or jumps.
%
%   SPLITTING('OFF') disables this kind of automatic splitting, and is
%   recommended for working with functions that are complicated but still
%   smooth. Even with splitting off, breakpoints may still be introduced by the
%   MAX, MIN, ABS, CEIL, FLOOR, and ROUND commands. One may switch freely back
%   and forth between the two modes during a Chebfun computation.
%
%   SPLITSTATE = SPLITTING(...) will return the current state splitting option
%   (as a string), before any changes are applied.
%
%   SPLITTING by itself, displays a string detailing the current splitting
%   state. By default, this is OFF.
%
% See also CHEBFUNPREF.

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

if ( nargout > 0 && nargin == 0 )
    % Return current splitting state:
    splitState = chebfunpref().splitting;

elseif ( nargin == 0 )
    % Display splitting state:
    switch ( chebfunpref().splitting )
        case 1
            disp('SPLITTING is currently ON.')
        case 0
            disp('SPLITTING is currently OFF.')
    end

else
    % Throw a warning:
    warning('CHEBFUN:splitting:deprecated', ...
        ['The syntax ''splitting on'' is deprecated.\n', ...
        'Please see CHEBFUNPREF documentation for further details.']);
    % But only throw it once:
    warning('off', 'CHEBFUN:splitting:deprecated');

    if ( nargout > 0 )
        splitState = chebfunpref().splitting;
    end

    if ( strcmpi(on_off, 'on') )
        chebfunpref.setDefaults('splitting', true);

    elseif strcmpi(on_off, 'off')
        chebfunpref.setDefaults('splitting', false);

    else
        error('CHEBFUN:splitting:UnknownOption',...
            'Unknown splitting option: only ON and OFF are valid options.')
    end

end

if ( nargout > 0 )
    onOffStr = {'off', 'on'};
    varargout{1} = onOffStr{splitState+1};
end

end


function out = myresize(img, dim, type)
% resize to fixed dimension according to short side or long side
% --------------------------------------------------------------

if nargin < 3
    error('input not enough!');
end
if ~strcmp(type, 'short') && ~strcmp(type, 'long')
    error('wrong type!');
end
H = size(img, 1);
W = size(img, 2);

if strcmp(type, 'short')
    if H <= W
        out = imresize(img, [dim, NaN], 'bilinear');
    else
        out = imresize(img, [NaN, dim], 'bilinear');
    end
else
    if H <= W
        out = imresize(img, [NaN, dim], 'bilinear');
    else
        out = imresize(img, [dim, NaN], 'bilinear');
    end
end


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

%% -*- texinfo -*-
%% @defun mat_rccross_access (@var{A}, @var{r}, @var{c})
%% Private helper routine for symbolic array access.
%%
%% Access entries of @var{A} that are the cross product of vectors
%% @var{r} and @var{c}.  @var{r} and @var{c} could be strings.
%% Namely @code{':'}.
%%
%% @var{r} and @var{c} could contain duplicates.  This is one
%% reason why this code doesn't easily replace
%% @code{mat_rclist_access}.
%%
%% @var{z} return is small matrix with @code{len(@var{c})} columns
%% and @code{len(@var{r})} rows.
%%
%% @end defun

function z = mat_rccross_access(A, r, c)

  if (ischar(r) && ischar(c) && strcmp(r, ':') && strcmp(c, ':'))
    z = A;
    return
  end

  %if both expressible as py slices...
  % FIXME: Could optimize these cases

  [n, m] = size(A);

  if (isnumeric(r) && isempty(r))
    % no-op
  elseif (isnumeric(r) && isvector(r))
    assert(all(r >= 1) && all(r <= n), 'index out of range')
  elseif (strcmp(r, ':'))
    r = 1:n;
  elseif (islogical(r) && isvector(r) && (length(r) == n))
    I = r;
    r = 1:n;  r = r(I);
  else
    error('unknown 2d-indexing in rows')
  end

  if (isnumeric(c) && isempty(c))
    % no-op
  elseif (isnumeric(c) && isvector(c))
    assert(all(c >= 1) && all(c <= m), 'index out of range')
  elseif (strcmp(c,':'))
    c = 1:m;
  elseif (islogical(c) && isvector(c) && (length(c) == m))
    J = c;
    c = 1:m;  c = c(J);
  else
    error('unknown 2d-indexing in columns')
  end

  cmd = { '(A, rr, cc) = _ins'
          'if not A.is_Matrix:'
          '    A = sp.Matrix([A])'
          'M = [[0]*len(cc) for i in range(len(rr))]'
          'for i in range(0, len(rr)):'
          '    for j in range(0, len(cc)):'
          '        M[i][j] = A[rr[i], cc[j]]'
          '# M = sp.Matrix(M)'
          '# not quite b/c of preserving 3x0 and 0x3 for example'
          'M = sp.Matrix(len(rr), len(cc), [c for r in M for c in r])'
          'return M,' };

  rr = num2cell(int32(r-1));
  cc = num2cell(int32(c-1));
  z = pycall_sympy__ (cmd, A, rr, cc);

  % FIXME: here's some code could be used for slices
  if (1==0)
  cmd = { 'A = _ins[0]'  ...
          'r = slice(_ins[1],_ins[2])'  ...
          'c = slice(_ins[3],_ins[4])'  ...
          'M = A[r,c]'  ...
          'return M,' };
  z = pycall_sympy__ (cmd, A, r1-1, r2, c1-1, c2);
  end
end


function p09_default ( dim_num )

%*****************************************************************************80
%
%% P09_DEFAULT sets default values for problem 09.
%
%  Discussion:
%
%    If a problem uses vector parameters, then the spatial dimension
%    DIM_NUM is needed as input, so that the vector parameters can be
%    properly dimensioned.
%
%    Every problem keeps a count of the number of function calls.  Calling
%    this routine causes that count to be reset to 0.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the problem.
%
  i4 = 0;
  p09_i4 ( 'D', '*', i4 );

  r8vec = [];
  p09_r8vec ( 'D', '*', dim_num, r8vec );

  return
end


function varargout = process_corr1n_time( varargin )
% PROCESS_COHERE1N_TIME: Compute the time-resolved coherence between all the pairs of signals, in one file.
%
% USAGE:   OutputFiles = process_corr1n_time('Run', sProcess, sInputA)
%                        process_corr1n_time('Test')

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

eval(macro_method);
end

%% ===== GET DESCRIPTION =====
function sProcess = GetDescription() %#ok<DEFNU>
    % Description the process
    sProcess.Comment     = 'Time-resolved correlation NxN';
    sProcess.Category    = 'Custom';
    sProcess.SubGroup    = 'Connectivity';
    sProcess.Index       = 653;
    sProcess.Description = 'https://neuroimage.usc.edu/brainstorm/Tutorials/Connectivity';
    % Definition of the input accepted by this process
    sProcess.InputTypes  = {'data',     'results',  'matrix'};
    sProcess.OutputTypes = {'timefreq', 'timefreq', 'timefreq'};
    sProcess.nInputs     = 1;
    sProcess.nMinFiles   = 1;
    sProcess.isSeparator = 1;

    % === CONNECT INPUT
    sProcess = process_corr1n('DefineConnectOptions', sProcess, 1);
    % Time window
    sProcess.options.win.Comment = 'Estimation window length:';
    sProcess.options.win.Type    = 'value';
    sProcess.options.win.Value   = {.350, 'ms', []};
    % overlap
    sProcess.options.overlap.Comment = 'Sliding window overlap:';
    sProcess.options.overlap.Type    = 'value';
    sProcess.options.overlap.Value   = {50, '%', []};
    % === TITLE
    sProcess.options.label2.Comment = '
Estimator options:';
    sProcess.options.label2.Type    = 'label';
%     % === P-VALUE THRESHOLD
%     sProcess.options.pthresh.Comment = 'Metric significativity:     p<';
%     sProcess.options.pthresh.Type    = 'value';
%     sProcess.options.pthresh.Value   = {0.05,'',4};
    % === SCALAR PRODUCT
    sProcess.options.scalarprod.Comment    = 'Compute scalar product instead of correlation
(do not remove average of the signal)';
    sProcess.options.scalarprod.Type       = 'checkbox';
    sProcess.options.scalarprod.Value      = 0;
    % === OUTPUT MODE
    sProcess.options.label3.Comment = '
Output configuration:';
    sProcess.options.label3.Type    = 'label';
%     sProcess.options.outputmode.Comment = {'Save individual results (one file per input file)', 'Save average connectivity matrix (one file)'};
%     sProcess.options.outputmode.Type    = 'radio';
%     sProcess.options.outputmode.Value   = 1;
    % === OUTPUT COMMENT TAG
    sProcess.options.commenttag.Comment = 'Comment tag: ';
    sProcess.options.commenttag.Type    = 'text';
    sProcess.options.commenttag.Value   = '';
end

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

%% ===== RUN =====
function OutputFiles = Run(sProcess, sInputA) %#ok<DEFNU>
    % Initialize returned values
    OutputFiles = {};
    % Forcing the concatenation of the inputs
    sProcess.options.outputmode.Comment = {'Save individual results (one file per input file)', 'Save average connectivity matrix (one file)'};
    sProcess.options.outputmode.Type    = 'radio';
    sProcess.options.outputmode.Value   = 2;
    % Input options
    OPTIONS = process_corr1n('GetConnectOptions', sProcess, sInputA);
    if isempty(OPTIONS)
        return
    end
    CommentTag = sProcess.options.commenttag.Value;
    % Metric options
    OPTIONS.Method     = 'corr';
    OPTIONS.pThresh    = 0.05;
    OPTIONS.RemoveMean = ~sProcess.options.scalarprod.Value;
    OPTIONS.isSave     = 0;
    % Sliding time windows options
    WinLength  = sProcess.options.win.Value{1};
    WinOverlap = sProcess.options.overlap.Value{1};

    % Read time information
    TimeVector   = in_bst(sInputA(1).FileName, 'Time');
    sfreq        = round(1/(TimeVector(2) - TimeVector(1)));
    % Select input time window
    TimeVector = TimeVector((TimeVector >= OPTIONS.TimeWindow(1)) & (TimeVector <= OPTIONS.TimeWindow(2)));
    nTime      = length(TimeVector);

    % Compute sliding windows length
    Lwin  = round(WinLength * sfreq);
    Loverlap = round(Lwin * WinOverlap / 100);
    Nwin = floor((nTime - Loverlap) ./ (Lwin - Loverlap));
    % If window is bigger than the data
    if (Lwin > nTime)
        bst_report('Error', sProcess, sInputA, 'Sliding window for the coherence estimation is too long compared with the epochs in input.');
        return;
    end

    % Loop over all the time windows
    for iWin = 1:Nwin
        % Select time window
        iTimes = (1:Lwin) + (iWin-1)*(Lwin - Loverlap);
        OPTIONS.TimeWindow = TimeVector(iTimes([1,end]));
        % Compute metric
        ConnectMat = bst_connectivity({sInputA.FileName}, [], OPTIONS);
        % Processing errors
        if isempty(ConnectMat) || ~iscell(ConnectMat) || ~isstruct(ConnectMat{1}) || isempty(ConnectMat{1}.TF)
            bst_report('Error', sProcess, sInputA, 'Correction for the selected time segment could not be calculated.');
            return;
        end
        % Start a new brainstorm structure
        if (iWin == 1)
            NewMat = ConnectMat{1};
            NewMat.Time = OPTIONS.TimeWindow(1);
            NewMat.TimeBands = [];
        % Add next time point
        else
            NewMat.TF(:,iWin,:) = ConnectMat{1}.TF;
            NewMat.Time(end+1) = OPTIONS.TimeWindow(1);
        end
    end

    % Fix time vector
    if (length(NewMat.Time) == 1)
        bst_report('Warning', sProcess, sInputA, 'Only one sliding time window could be estimated.');
        NewMat.Time = [TimeVector(1), TimeVector(end)];
    end
    % Add comment tag
    if ~isempty(CommentTag)
        NewMat.Comment = [NewMat.Comment ' | ' CommentTag];
    end
    % Output filename
    sOutputStudy = bst_get('Study', OPTIONS.iOutputStudy);
    OutputFiles{1} = bst_process('GetNewFilename', bst_fileparts(sOutputStudy.FileName), 'timefreq_connectn_corr_time');
    % Save file
    bst_save(OutputFiles{1}, NewMat, 'v6');
    % Add file to database structure
    db_add_data(OPTIONS.iOutputStudy, OutputFiles{1}, NewMat);
end


function fd2d_heat_steady_test ( )

%*****************************************************************************80
%
%% FD2D_HEAT_STEADY_TEST tests the FD2D_HEAT_STEADY library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 August 2013
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FD2D_HEAT_STEADY_TEST:\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the FD2D_HEAT_STEADY library.'

  fd2d_heat_steady_test01 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FD2D_HEAT_STEADY_TEST:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


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

%%
clear; close all; clc;

%% Syntax
% |[F,V]=quadPlate(plateDim,plateEl)|

%% Description
% This function generates a quadrilateral mesh for a rectangular place

%% Examples

%%
% Plot settings
fontSize=20;

%% Example: Creating a meshed plate

%Define input parameters
plateDim = [2 2]; %Plate dimensions in X and Y direction
plateEl  = [6 7]; %Number of elements in X and Y direction

%Use |quadPlate| to create a quadrilateral mesh
[F,V]=quadPlate(plateDim,plateEl);

%%
% Plotting model
cFigure; hold on;
gpatch(F,V,'bw','k');
% patchNormPlot(F,V);
axisGeom(gca,fontSize);
drawnow;

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>

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


function [uttName_sorted, aliID_sorted, vocab] = readKaldiAlignmentText(file_name)
lines = my_cat(file_name);

vocab = [];
for i=1:length(lines)
    PrintProgress(i,length(lines),1000);
    idx = regexp(lines{i}, ' ');
    uttName{i} = lines{i}(1:idx(1)-1);
    aliID{i} = str2num(lines{i}(idx(1)+1:end))';
    vocab = [vocab; aliID{i}];
    if mod(i,100)==0
        vocab = unique(vocab);
    end
end
vocab = unique(vocab);

[uttName_sorted, order] = sort(uttName);
aliID_sorted = aliID(order);


%%*****************************************************************
%% sqlptermcode.m: explains the termination code in sqlp.m
%%*****************************************************************
%% SDPT3: version 4.0
%% Copyright (c) 1997 by
%% Kim-Chuan Toh, Michael J. Todd, Reha H. Tutuncu
%% Last Modified: 16 Sep 2004
%%*****************************************************************

   function termcode = sqlptermcode;

   fprintf('\n   3: norm(X) or norm(Z) diverging');
   fprintf('\n   2: dual   problem is suspected to be infeasible')
   fprintf('\n   1: primal problem is suspected to be infeasible')
   fprintf('\n   0: max(relative gap,infeasibility) < gaptol');
   fprintf('\n  -1: relative gap < infeasibility');
   fprintf('\n  -2: lack of progress in predictor or corrector');
   fprintf('\n  -3: X or Z not positive definite');
   fprintf('\n  -4: difficulty in computing predictor or corrector direction');
   fprintf('\n  -5: progress in relative gap or infeasibility is bad');
   fprintf('\n  -6: maximum number of iterations reached');
   fprintf('\n  -7: primal infeasibility has deteriorated too much');
   fprintf('\n  -8: progress in relative gap has deteriorated');
   fprintf('\n  -9: lack of progress in infeasibility');
   fprintf('\n')
%%*************************************************************************


function p05_story ( )

%*****************************************************************************80
%
%% P05_STORY prints the "story" for problem 5.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  This example is due to deBoor.\n' );
  fprintf ( 1, '  This data represents a temperature dependent property of titanium.\n' );

  return
end


% t_meshFromFreesurfer
%
% Illustrates how to create mrVista compatible meshes from a freesurfer
% surface.
%
%
% Dependencies:
%   Remote Data Toolbox
%   Freesurfer paths
%
% This tutorial is part of a sequence. Run
%   t_initAnatomyFromFreesurfer
% prior to running this tutorial.
%
% Summary
%
% - Do actiom A
% - Do action B
% - Visualize
% - Clean up
%
% Tested 09/14/2016 - MATLAB r2015b, Mac OS 10.11.6
%
%  See t_initAnatomyFromFreesurfer
%
% NYU Winawer lab

%% Download ernie freesurfer directory
% Note that this is also done in the prior tutorial,
% t_initAnatomyFromFreesurfer. Doing it a second time won't hurt anyone,
% and it will make this tutorial work on its own, even without running the
% prior one in the sequence.

% Check whether freesurfer paths exist
fssubjectsdir = getenv('SUBJECTS_DIR');
if isempty(fssubjectsdir)
    error('Freesurfer paths not found. Cannot proceed.')
end

% Get ernie freesufer1 directory and install it in freesurfer subjects dir
%   If we find the directory, do not bother unzipping again
forceOverwrite = false;

% Do it
dFolder = mrtInstallSampleData('anatomy/freesurfer', 'ernie', ...
    fssubjectsdir, forceOverwrite);

fprintf('Freesurfer directory for ernie installed here:\n %s\n', dFolder)

%% Create Freesurfer meshes

% mrVista Project directory
erniePath      = fullfile(vistaRootPath, 'local', 'scratch', 'erniePRF');

if ~exist(erniePath, 'dir')
    % If we did not find the temporary directory created by prior
    % tutorials, then use the full directory, downloading if necessary
    erniePath = mrtInstallSampleData('functional', 'erniePRF');
end

% Install Ernie freesurfer directory and ernie vistasession
cd(erniePath);

% Create and save meshes
hemi = 'b';
surfaces = {'white' 'pial' 'sphere' 'inflated'};
[meshes, fnames] = meshImportFreesurferSurfaces('ernie', hemi, surfaces);

%% Visualize

% View the 4 left meshes: white, pial, inflated, sphere

for ii = 1:4
    meshVisualize(meshes(ii))
    % This call should open a new application, mrMeshMac or a related name
    % (depending on your OS), if it is not already open. Then it will open a
    % new window and show the mesh. You can rotate, zoom, and translate with
    % the appropriate mouse actions. We BELIEVE that the mouse buttons are as
    % follows:
    %   Rotation:  left mouse button plus movement
    %   Zoom:      right mouse button plus up/down movement
    %   Translate: left and right together plus movement

end

%% Alernative visualiztion in Matlab

for m = 1:4

    figure,

    % Faces (also called triangles) are defined by 3 points, each of
    % which is an index into the x, y, z vertices
    faces = meshes(m).triangles' + 1; % we need to 1-index rather than 0-index for Matlab

    % The vertices are the locations in mm spacing
    x     = meshes(m).vertices(1,:)';
    y     = meshes(m).vertices(2,:)';
    z     = meshes(m).vertices(3,:)';

    % The colormap will, by default, paint sulci dark and gyri light
    c     = meshes(m).colors(1,:)';

    % Render the triangle mesh
    tH = trimesh(faces, x,y,z);

    % Make it look nice
    set(tH, 'LineStyle', 'none', 'FaceColor', 'interp', 'FaceVertexCData',c)
    axis equal off; colormap gray; set(gca, 'CLim', [0 255])

    % Lighting to make it look glossy
    light('Position',100*[0 1 1],'Style','local')
    lighting gouraud

    % Which mesh are we plotting?
    title(meshes(m).name)

    % Rotate it
    set(gca, 'View', [-16.7000  -90.0000]);

end


% timtopo()   - plot all channels of a data epoch on the same axis
%               and map its scalp map(s) at selected latencies.
% Usage:
%  >> timtopo(data, chan_locs);
%  >> timtopo(data, chan_locs, 'key', 'val', ...);
% Inputs:
%  data       = (channels,frames) single-epoch data matrix
%  chan_locs  = channel location file or EEG.chanlocs structure.
%               See >> topoplot example for file format.
%
% Optional ordered inputs:
%  'limits'    = [minms maxms minval maxval] data limits for latency (in ms) and y-values
%                 (assumes uV) {default|0 -> use [0 npts-1 data_min data_max];
%                 else [minms maxms] or [minms maxms 0 0] -> use
%                [minms maxms data_min data_max]
%  'plottimes' = [vector] latencies (in ms) at which to plot scalp maps
%                {default|NaN -> latency of maximum variance}
% 'title'      = [string] plot title {default|0 -> none}
% 'plotchans'  = vector of data channel(s) to plot. Note that this does not
%                affect scalp topographies {default|0 -> all}
% 'voffsets'   = vector of (plotting-unit) distances vertical lines should extend
%                above the data (in special cases) {default -> all = standard}
%
% Optional keyword, arg pair inputs (must come after the above):
% 'topokey','val' = optional topoplot() scalp map plotting arguments. See >> help topoplot
%
% Author: Scott Makeig, SCCN/INC/UCSD, La Jolla, 1-10-98
%
% See also: envtopo(), topoplot()

% Copyright (C) 1-10-98 Scott Makeig, SCCN/INC/UCSD, scott@sccn.ucsd.edu
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% 5-31-00 added o-time line and possibility of plotting 1 channel -sm & mw
% 11-02-99 added maplimits arg -sm
% 01-22-01 added to help message -sm
% 01-25-02 reformated help & license, added link -ad
% 03-15-02 add all topoplot options -ad

function M = timtopo(data, chan_locs, varargin)

MAX_TOPOS = 24;

if nargin < 1 %should this be 2?
   help timtopo;
   return
end

[chans,frames] = size(data);
icadefs;

%
% if nargin > 2
%     if ischar(limits)
%         varargin = { limits,plottimes,titl,plotchans,voffsets varargin{:} };
%
%     else
%         varargin = { 'limits' limits 'plottimes' plottimes 'title' titl 'plotchans' plotchans 'voffsets' voffsets varargin{:} };
%     end;
% end;

if nargin > 2 && ~ischar(varargin{1})
   options = {};
   if length(varargin) > 0, options = { options{:} 'limits' varargin{1} }; end;
   if length(varargin) > 1, options = { options{:} 'plottimes' varargin{2} }; end;
   if length(varargin) > 2, options = { options{:} 'title'      varargin{3} }; end;
   if length(varargin) > 3, options = { options{:} 'plotchans' varargin{4} }; end;
   if length(varargin) > 4, options = { options{:} 'voffsets'     varargin{5} }; end;
   if length(varargin) > 5, options = { options{:} varargin{6:end} }; end;
else
   options = varargin;
end;

fieldlist = { 'limits'        'real'     []                       0;
              'plottimes'     'real'     []                       [];
              'title'         'string'   []                       '';
              'plotchans'     'integer'  [1:size(data,1)]         0;
              'voffsets'      'real'     []                       [] ;};
[g topoargs] = finputcheck(options, fieldlist, 'timtopo', 'ignore');

if ischar(g), error(g); end;
%Set Defaults
if isempty(g.title), g.title = ''; end;
if isempty(g.voffsets) || g.voffsets == 0, g.voffsets = zeros(1,MAX_TOPOS); end;
if isempty(g.plotchans) || isequal(g.plotchans,0), g.plotchans = 1:chans; end;
plottimes_set=1;   % flag variable
if isempty(g.plottimes) || any(isnan(g.plottimes)), plottimes_set = 0;end;
limitset = 0; %flag variable
if isempty(g.limits), g.limits = 0; end;
if length(g.limits)>1, limitset = 1; end;

% if nargin < 7 | voffsets == 0
%   voffsets = zeros(1,MAX_TOPOS);
% end
%
% if nargin < 6
%    plotchans = 0;
% end
%
% if plotchans==0
%    plotchans = 1:chans;
% end
%
% if nargin < 5,
%    titl = '';     % DEFAULT NO TITLE
% end
%
% plottimes_set=1;   % flag variable
% if nargin< 4 | isempty(plottimes) | any(isnan(plottimes))
%    plottimes_set = 0;
% end
%
% limitset = 0;
% if nargin < 3,
%     limits = 0;
% elseif length(limits)>1
%     limitset = 1;
% end

if nargin < 2 %if first if-statement is changed to 2 should this be 3?
    chan_locs = 'chan.locs';  % DEFAULT CHAN_FILE
end
if isnumeric(chan_locs) && chan_locs == 0,
    chan_locs = 'chan.locs';  % DEFAULT CHAN_FILE
end

  %
  %%%%%%%%%%%%%%%%%%%%%%% Read and adjust limits %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  % defaults: limits == 0 or [0 0 0 0]
  if ( length(g.limits) == 1 & g.limits==0) | (length(g.limits)==4 & ~any(g.limits))
    xmin=0;
    xmax=frames-1;
    ymin=min(min(data));
    ymax=max(max(data));
  elseif length(g.limits) == 2  % [minms maxms] only
    ymin=min(min(data));
    ymax=max(max(data));
    xmin = g.limits(1);
    xmax = g.limits(2);
 elseif length(g.limits) == 4
    xmin = g.limits(1);
    xmax = g.limits(2);
    if any(g.limits([3 4]))
      ymin = g.limits(3);
      ymax = g.limits(4);
    else % both 0
      ymin=min(min(data));
      ymax=max(max(data));
    end
  else
    fprintf('timtopo(): limits format not correct. See >> help timtopo.\n');
    return
  end;

  if xmax == 0 & xmin == 0,
    x = (0:1:frames-1);
    xmin = 0;
    xmax = frames-1;
  else
    dx = (xmax-xmin)/(frames-1);
    x=xmin*ones(1,frames)+dx*(0:frames-1); % compute x-values
  end;
  if xmax<=xmin,
      fprintf('timtopo() - in limits, maxms must be > minms.\n')
      return
  end

  if ymax == 0 & ymin == 0,
      ymax=max(max(data));
      ymin=min(min(data));
  end
  if ymax<=ymin,
      fprintf('timtopo() - in limits, maxval must be > minmval.\n')
      return
  end

sampint = (xmax-xmin)/(frames-1); % sampling interval = 1000/srate;
x = xmin:sampint:xmax;   % make vector of x-values

%
%%%%%%%%%%%%%%% Compute plot times/frames %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
if plottimes_set == 0
  [mx plotframes] = max(sum(data.*data));
                  % default plotting frame has max variance
  if nargin< 4 | isempty(g.plottimes)
	  g.plottimes = x(plotframes);
  else
	  g.plottimes(find(isnan(g.plottimes))) = x(plotframes);
  end;
  plottimes_set = 1;
end;

if plottimes_set == 1
  ntopos = length(g.plottimes);
  if ntopos > MAX_TOPOS
    fprintf('timtopo(): too many plottimes - only first %d will be shown!\n',MAX_TOPOS);
    g.plottimes = g.plottimes(1:MAX_TOPOS);
    ntopos = MAX_TOPOS;
  end

  if max(g.plottimes) > xmax | min(g.plottimes)< xmin
    fprintf(...
'timtopo(): at least one plottimes value outside of epoch latency range - cannot plot.\n');
    return
  end

  g.plottimes = sort(g.plottimes); % put map latencies in ascending order,
                               % else map lines would cross.
  xshift = [x(2:frames) xmax+1]; % 5/22/2014 Ramon: '+1' was added to avoid errors when time== max(x) in line 231
  plotframes = ones(size(g.plottimes));
  for t = 1:ntopos
    time = g.plottimes(t);
    plotframes(t) = find(time>=x & time < xshift);
  end
end

vlen = length(g.voffsets); % extend voffsets if necessary
i=1;
while vlen< ntopos
        g.voffsets = [g.voffsets g.voffsets(i)];
        i=i+1;
        vlen=vlen+1;
end

%
%%%%%%%%%%%%%%%%  Compute title and axes font sizes %%%%%%%%%%%%%%%
%
pos = get(gca,'Position');
axis('off')
cla % clear the current axes
if pos(4)>0.70
   titlefont= 16;
   axfont = 16;
elseif pos(4)>0.40
   titlefont= 14;
   axfont = 14;
elseif pos(4)>0.30
   titlefont= 12;
   axfont = 12;
elseif pos(4)>0.22
   titlefont= 10;
   axfont = 10;
else
   titlefont= 8;
   axfont = 8;
end

%
%%%%%%%%%%%%%%%% Compute topoplot head width and separation %%%%%%%%%%%%%%%
%
head_sep = 0.2;
topowidth = pos(3)/((6*ntopos-1)/5); % width of each topoplot
if topowidth> 0.25*pos(4) % dont make too large (more than 1/4 of axes width)!
  topowidth = 0.25*pos(4);
end

halfn = floor(ntopos/2);
if rem(ntopos,2) == 1  % odd number of topos
   topoleft = pos(3)/2 - (ntopos/2+halfn*head_sep)*topowidth;
else % even number of topos
   topoleft = pos(3)/2 - ((halfn)+(halfn-1)*head_sep)*topowidth;
end
topoleft = topoleft - 0.01; % adjust left a bit for colorbar

if max(plotframes) > frames |  min(plotframes) < 1
    fprintf('Requested map frame %d is outside data range (1-%d)\n',max(plotframes),frames);
    return
end

%
%%%%%%%%%%%%%%%%%%%% Print times and frames %%%%%%%%%%%%%%%%%%%%%%%%%%
%

fprintf('Scalp maps will show latencies: ');
for t=1:ntopos
  fprintf('%4.0f ',g.plottimes(t));
end
fprintf('\n');
fprintf('                     at frames: ');
for t=1:ntopos
  fprintf('%4d ',plotframes(t));
end
fprintf('\n');

%
%%%%%%%%%%%%%%%%%%%%%%% Plot the data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
%%%%%%%%%%%% site the plot at bottom of the figure %%%%%%%%%%%%%%%%%%
%
axdata = axes('Units','Normalized','Position',[pos(1) pos(2) pos(3) 0.6*pos(4)],'FontSize',axfont);
set(axdata,'Color',BACKCOLOR);

g.limits = get(axdata,'Ylim');
set(axdata,'GridLineStyle',':')
set(axdata,'Xgrid','off')
set(axdata,'Ygrid','on')
axes(axdata)
axcolor = get(gcf,'Color');
set(axdata,'Color',BACKCOLOR);
pl=plot(x,data(g.plotchans,:)');    % plot the data
if length(g.plotchans)==1
  set(pl,'color','k');
  set(pl,'linewidth',2);
end
xl= xlabel('Latency (ms)');
set(xl,'FontSize',axfont);
yl=ylabel('Potential (\muV)');
set(yl,'FontSize',axfont,'FontAngle','normal');
axis([xmin xmax ymin ymax]);
hold on

%
%%%%%%%%%%%%%%%%%%%%%%%%% Plot zero time line %%%%%%%%%%%%%%%%%%%%%%%%%%
%

if xmin<0 & xmax>0
   plot([0 0],[ymin ymax],'k:','linewidth',1.5);
else
  fprintf('xmin %g and xmax %g do not cross time 0.\n',xmin,xmax)
end
%
%%%%%%%%%%%%%%%%%%%%%%%%% Draw vertical lines %%%%%%%%%%%%%%%%%%%%%%%%%%
%
width  = xmax-xmin;
height = ymax-ymin;
lwidth = 1.5;  % increment line thickness

for t=1:ntopos % dfraw vertical lines through the data at topoplot frames
 if length(g.plotchans)>1 | g.voffsets(t)
  l1 = plot([g.plottimes(t) g.plottimes(t)],...
       [min(data(g.plotchans,plotframes(t))) ...
       g.voffsets(t) + max(data(g.plotchans,plotframes(t)))],'w'); % white underline behind
  set(l1,'linewidth',2);
  l1 = plot([g.plottimes(t) g.plottimes(t)],...
       [min(data(g.plotchans,plotframes(t))) ...
       g.voffsets(t) + max(data(g.plotchans,plotframes(t)))],'b'); % blue line
  set(l1,'linewidth',lwidth);
 end
end
%
%%%%%%%%%%%%%%%%%%%%%%%%% Draw oblique lines %%%%%%%%%%%%%%%%%%%%%%%%%%
%
axall = axes('Position',pos,...
             'Visible','Off','FontSize',axfont);   % whole-gca invisible axes
axes(axall)
set(axall,'Color',BACKCOLOR);
axis([0 1 0 1])
  axes(axall)
  axis([0 1 0 1]);
  set(gca,'Visible','off'); % make whole-figure axes invisible

for t=1:ntopos % draw oblique lines through to the topoplots
  maxdata = max(data(:,plotframes(t))); % max data value at plotframe
  axtp = axes('Units','Normalized','Position',...
       [pos(1)+topoleft+(t-1)*(1+head_sep)*topowidth ...
              pos(2)+0.66*pos(4) ...
                  topowidth ...
                       topowidth*(1+head_sep)]); % this will be the topoplot axes
                       % topowidth]); % this will be the topoplot axes
  axis([-1 1 -1 1]);

  from = changeunits([g.plottimes(t),maxdata],axdata,axall); % data axes
  to   = changeunits([0,-0.74],axtp,axall);                % topoplot axes
  delete(axtp);
  axes(axall);                                             % whole figure axes
  l1 = plot([from(1) to(1)],[from(2) to(2)]);
  set(l1,'linewidth',lwidth);

  hold on
  set(axall,'Visible','off');
  axis([0 1 0 1]);
end
%
%%%%%%%%%%%%%%%%%%%%%%%%% Plot the topoplots %%%%%%%%%%%%%%%%%%%%%%%%%%
%
topoaxes = zeros(1,ntopos);
for t=1:ntopos
       % [pos(3)*topoleft+pos(1)+(t-1)*(1+head_sep)*topowidth ...
  axtp = axes('Units','Normalized','Position',...
       [topoleft+pos(1)+(t-1)*(1+head_sep)*topowidth ...
              pos(2)+0.66*pos(4) ...
                  topowidth topowidth*(1+head_sep)]);
  axes(axtp)                             % topoplot axes
  topoaxes(t) = axtp; % save axes handles
  cla

  if topowidth<0.12
      topoargs = { topoargs{:} 'electrodes' 'off' };
  end
  topoplot( data(:,plotframes(t)),chan_locs, topoargs{:});

  % Else make a 3-D headplot
  %
  % headplot(data(:,plotframes(t)),'chan.spline');

  timetext = [num2str(g.plottimes(t),'%4.0f')];
  % timetext = [num2str(plottimes(t),'%4.0f') ' ms']; % add ' ms'
  text(0.00,0.80,timetext,'FontSize',axfont-3,'HorizontalAlignment','Center'); % ,'fontweight','bold');
end

%
%%%%%%%%%%%%%%%%%%% Plot a topoplot colorbar %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
axcb = axes('Position',[pos(1)+pos(3)*0.995 pos(2)+0.62*pos(4) pos(3)*0.02 pos(4)*0.09]);
h=cbar(axcb);                        % colorbar axes
pos_cb = get(axcb,'Position');
set(h,'Ytick',[]);

axes(axall)
set(axall,'Color',axcolor);
%
%%%%%%%%%%%%%%%%%%%%% Plot the color bar '+' and '-' %%%%%%%%%%%%%%%%%%%%%%%%%%
%
text(0.986,0.695,'+','FontSize',axfont,'HorizontalAlignment','Center');
text(0.986,0.625,'-','FontSize',axfont,'HorizontalAlignment','Center');

%
%%%%%%%%%%%%%%%%%%%%%%%%% Plot the plot title if any %%%%%%%%%%%%%%%%%%%%%%%%%%
%
% plot title between data panel and topoplots (to avoid crowding at top of
% figure), on the left
ttl = text(0.03,0.635,g.title,'FontSize',titlefont,'HorizontalAlignment','left'); % 'FontWeight','Bold');

% textent = get(ttl,'extent');
% titlwidth = textent(3);
% ttlpos = get(ttl,'position');
% set(ttl,'position',[     ttlpos(2), ttlpos(3)]);

axes(axall)
set(axall,'layer','top'); % bring component lines to top
for t = 1:ntopos
  set(topoaxes(t),'layer','top'); % bring topoplots to very top
end

  if ~isempty(varargin)
    try,
		if ~isempty( strmatch( 'absmax', varargin))
			text(0.86,0.624,'0','FontSize',axfont,'HorizontalAlignment','Center');
		end;
	catch, end;
  end

%
% Turn on axcopy()
%

% clicking on ERP pop_up topoplot
% -------------------------------
disp('Click on ERP waveform to show scalp map at specific latency');

dat.times = x;
dat.erp   = data;
dat.chanlocs = chan_locs;
dat.options  = topoargs;
dat.srate    = (size(data,2)-1)/(x(end)-x(1))*1000;
dat.axes     = axtp;
dat.line     = l1;

cb_code = [ 'tmppos = get(gca, ''currentpoint'');' ...
            'dattmp = get(gcf, ''userdata'');' ...
            'set(dattmp.line, ''visible'', ''off'');' ...
            'axes(dattmp.axes); cla;' ...
            'latpoint = round((tmppos(1)-dattmp.times(1))/1000*dattmp.srate);' ...
            'topoplot(dattmp.erp(:,latpoint), dattmp.chanlocs, dattmp.options{:});' ...
            'title(sprintf(''%.0f ms'', tmppos(1)));' ...
            'clear latpoint dattmp;' ...
          ];
axcopy;

set(gcf, 'userdata', dat);
set(axdata, 'ButtonDownFcn', cb_code); %windowbuttondownfcn', cb_code);
set(pl, 'ButtonDownFcn', cb_code);

%axcopy(gcf, cb_code);


function hb_to_st_test ( )

%*****************************************************************************80
%
%% HB_TO_ST_TEST tests the HB_TO_ST library.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 November 2008
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'HB_TO_ST_TEST:\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Test the HB_TO_ST library.\n' );

  hb_to_st_test01 ( );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'HB_TO_ST_TEST:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function hb_to_st_test01 ( )

%*****************************************************************************80
%
%% HB_TO_ST_TEST01 tests HB_TO_ST.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 November 2008
%
%  Author:
%
%    John Burkardt
%
  input_file = 'rua_32.hb';
  output_file = 'rua_32.st';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'HB_TO_ST_TEST01\n' );
  fprintf ( 1, '  We will read a Harwell-Boeing sparse matrix file\n' );
  fprintf ( 1, '  called "%s"\n', input_file );
  fprintf ( 1, '  and have HB_TO_ST convert it to an ST file.\n' );

  hb_to_st ( input_file, output_file );

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%         Demonstration of Basic Utilities of JSONlab
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

rngstate = rand ('state');
randseed=hex2dec('623F9A9E');
clear data2json json2data

if(exist('isequaln')==0)
    isequaln=@isequal;
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a simple scalar value \n')
fprintf(1,'%%=================================================\n\n')

data2json=pi
savejson('',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  an empty array \n')
fprintf(1,'%%=================================================\n\n')

data2json=[]
savejson('',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  an ampty string \n')
fprintf(1,'%%=================================================\n\n')

data2json=''
savejson('emptystr',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a simple row vector \n')
fprintf(1,'%%=================================================\n\n')

data2json=1:3
savejson('',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a simple column vector \n')
fprintf(1,'%%=================================================\n\n')

data2json=(1:3)'
savejson('',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a string array \n')
fprintf(1,'%%=================================================\n\n')

data2json=['AC';'EG']
savejson('',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a string with escape symbols \n')
fprintf(1,'%%=================================================\n\n')

data2json=sprintf('AB\tCD\none"two')
savejson('str',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a mix-typed cell \n')
fprintf(1,'%%=================================================\n\n')

data2json={'a',true,[2;3]}
savejson('',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 3-D array in nested array form\n')
fprintf(1,'%%=================================================\n\n')

data2json=reshape(1:(2*4*6),[2,4,6]);
savejson('',data2json,'NestArray',1)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 3-D array in annotated array form\n')
fprintf(1,'%%=================================================\n\n')

data2json=reshape(1:(2*4*6),[2,4,6]);
savejson('',data2json,'NestArray',0)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 4-D array in annotated array form\n')
fprintf(1,'%%=================================================\n\n')

data2json=reshape(1:(2*4*3*2),[2,4,3,2]);
savejson('',data2json,'NestArray',0)  % nestarray for 4-D or above is not working
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 3-D array in nested array form (JSONLab 1.9)\n')
fprintf(1,'%%=================================================\n\n')

data2json=reshape(1:(2*4*6),[2,4,6]);
savejson('',data2json,'NestArray',1,'FormatVersion',1.8)
json2data=loadjson(ans,'FormatVersion',1.8)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 3-D array in annotated array form (JSONLab 1.9 or earlier)\n')
fprintf(1,'%%=================================================\n\n')

data2json=reshape(1:(2*4*6),[2,4,6]);
savejson('',data2json,'NestArray',0,'FormatVersion',1.8)
json2data=loadjson(ans,'FormatVersion',1.8)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a complex number\n')
fprintf(1,'%%=================================================\n\n')

data2json=1+2i
savejson('',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a complex matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=magic(6);
data2json=data2json(:,1:3)+data2json(:,4:6)*1i
savejson('',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  MATLAB special constants\n')
fprintf(1,'%%=================================================\n\n')

data2json=[NaN Inf -Inf]
savejson('specials',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data.specials,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a real sparse matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=sprand(10,10,0.1)
savejson('sparse',data2json,'FloatFormat','%.18g')
json2data=loadjson(ans)
if(~isequaln(json2data.sparse,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a complex sparse matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=sprand(10,10,0.1);
data2json=data2json-data2json*1i
savejson('complex_sparse',data2json,'FloatFormat','%.18g')
json2data=loadjson(ans)
if(~isequaln(json2data.complex_sparse,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  an all-zero sparse matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=sparse(2,3);
savejson('all_zero_sparse',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data.all_zero_sparse,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  an empty sparse matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=sparse([]);
savejson('empty_sparse',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data.empty_sparse,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  an empty 0-by-0 real matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=[];
savejson('empty_0by0_real',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  an empty 0-by-3 real matrix\n')
fprintf(1,'%%=================================================\n\n')

data2json=zeros(0,3);
savejson('empty_0by3_real',data2json)
json2data=loadjson(ans)
if(~isequaln(json2data.empty_0by3_real,data2json))
    warning('conversion does not preserve original data');
end

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a sparse real column vector\n')
fprintf(1,'%%=================================================\n\n')

data2json=sparse([0,3,0,1,4]');
savejson('sparse_column_vector',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a sparse complex column vector\n')
fprintf(1,'%%=================================================\n\n')

data2json=data2json-1i*data2json;
savejson('complex_sparse_column_vector',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a sparse real row vector\n')
fprintf(1,'%%=================================================\n\n')

data2json=sparse([0,3,0,1,4]);
savejson('sparse_row_vector',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a sparse complex row vector\n')
fprintf(1,'%%=================================================\n\n')

data2json=data2json-1i*data2json;
savejson('complex_sparse_row_vector',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a structure\n')
fprintf(1,'%%=================================================\n\n')

data2json=struct('name','Think Different','year',1997,'magic',magic(3),...
                 'misfits',[Inf,NaN],'embedded',struct('left',true,'right',false))
savejson('astruct',data2json,struct('ParseLogical',1))
json2data=loadjson(ans)
class(json2data.astruct.embedded.left)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a structure array\n')
fprintf(1,'%%=================================================\n\n')

data2json=struct('name','Nexus Prime','rank',9);
data2json(2)=struct('name','Sentinel Prime','rank',9);
data2json(3)=struct('name','Optimus Prime','rank',9);
savejson('Supreme Commander',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a cell array\n')
fprintf(1,'%%=================================================\n\n')

data2json=cell(3,1);
data2json{1}=struct('buzz',1.1,'rex',1.2,'bo',1.3,'hamm',2.0,'slink',2.1,'potato',2.2,...
              'woody',3.0,'sarge',3.1,'etch',4.0,'lenny',5.0,'squeeze',6.0,'wheezy',7.0);
data2json{2}=struct('Ubuntu',['Kubuntu';'Xubuntu';'Lubuntu']);
data2json{3}=[10.04,10.10,11.04,11.10]
savejson('debian',data2json,struct('FloatFormat','%.2f'))
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  invalid field-name handling\n')
fprintf(1,'%%=================================================\n\n')

json2data=loadjson('{"ValidName":1, "_InvalidName":2, ":Field:":3, "项目":"绝密"}')

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a function handle\n')
fprintf(1,'%%=================================================\n\n')

data2json=@(x) x+1
savejson('handle',data2json)
json2data=loadjson(ans)

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 2D cell array\n')
fprintf(1,'%%=================================================\n\n')

data2json={{1,{2,3}},{4,5},{6};{7},{8,9},{10}};
savejson('data2json',data2json)
json2data=loadjson(ans)  % only savejson works for cell arrays, loadjson has issues

fprintf(1,'\n%%=================================================\n')
fprintf(1,'%%  a 2D struct array\n')
fprintf(1,'%%=================================================\n\n')

data2json=repmat(struct('idx',0,'data','structs'),[2,3])
for i=1:6
    data2json(i).idx=i;
end
savejson('data2json',data2json)
json2data=loadjson(ans)

if(exist('datetime'))
    fprintf(1,'\n%%=================================================\n')
    fprintf(1,'%%  datetime object \n')
    fprintf(1,'%%=================================================\n\n')

    data2json=datetime({'8 April 2015','9 May 2015'}, 'InputFormat','d MMMM yyyy')
    savejson('',data2json)
    json2data=loadjson(ans)
end

if(exist('containers.Map'))
    fprintf(1,'\n%%=================================================\n')
    fprintf(1,'%%  a container.Maps object \n')
    fprintf(1,'%%=================================================\n\n')

    data2json=containers.Map({'Andy','William','Om'},{21,21,22})
    savejson('',data2json)
    json2data=loadjson(ans)
end

if(exist('istable'))
    fprintf(1,'\n%%=================================================\n')
    fprintf(1,'%%  a table object \n')
    fprintf(1,'%%=================================================\n\n')

    Names={'Andy','William','Om'}';
    Age=[21,21,22]';
    data2json=table(Names,Age)
    savejson('table',table(Names,Age))
    json2data=loadjson(ans)
end

if(exist('bandwidth'))
    fprintf(1,'\n%%=================================================\n')
    fprintf(1,'%%  use _ArrayShape_ \n')
    fprintf(1,'%%=================================================\n\n')

    lband=2;
    uband=3;
    data2json=spdiags(true(8,lband+uband+1),-uband:lband,5,8);
    data2json=full(double(data2json));
    data2json(data2json~=0)=find(data2json)

    savejson('',data2json,'usearrayshape',1)
    json2data=loadjson(ans,'fullarrayshape',1)

    savejson('',tril(data2json),'usearrayshape',1)
    json2data=loadjson(ans,'fullarrayshape',1)

    savejson('',triu(data2json+1i*data2json),'usearrayshape',1)
    json2data=loadjson(ans,'fullarrayshape',1)

    savejson('',tril(triu(int8(data2json))),'usearrayshape',1)
    json2data=loadjson(ans,'fullarrayshape',1)

    savejson('',data2json(:,1:5)+data2json(:,1:5)','usearrayshape',1)
    json2data=loadjson(ans,'fullarrayshape',1)
end

try
    val=zlibencode('test');
    fprintf(1,'\n%%=================================================\n')
    fprintf(1,'%%  a 2-D array in compressed array format\n')
    fprintf(1,'%%=================================================\n\n')

    data2json=eye(10);
    data2json(20,1)=1;
    savejson('',data2json,'Compression','zlib','CompressArraySize',0)  % nestarray for 4-D or above is not working
    json2data=loadjson(ans)
    if(~isequaln(json2data,data2json))
        warning('conversion does not preserve original data');
    end
catch
end

rand ('state',rngstate);


function [ y, m, d ] = inflate_common ( y, m, d )

%*****************************************************************************80
%
%% INFLATE_COMMON "inflates" dates in the Common Calendar transition month.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 March 2001
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y, integer M, integer D, the YMD date.
%
%    Output, integer Y, integer M, integer D, the YMD date.
%
  if ( y == 1582 )
    if ( m == 10 )
      if ( 5 <= d )
        d = d + 10;
      end
    end
  end

  return
end


targetWorkCount = 100;
barWidth= int32( targetWorkCount/3 );
p =  TimedProgressBar( targetWorkCount, barWidth, ...
    'Computing, wait for ', ', completed ', 'Concluded in ' );
parfor i=1:targetWorkCount      % could be just a for cycle
    pause(rand);                % Replace with real code
    p.progress;                 % Also percent = p.progress;
end
p.stop;                         % Also percent = p.stop;


function test01 ( input_file_name )

%*****************************************************************************80
%
%% TEST01 tests STLA_CHECK.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 September 2005
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST01\n' );
  fprintf ( 1, '  STLA_CHECK makes some simple checks on a file.\n' );

  fprintf ( 1, '\n' );
  if ( stla_check ( input_file_name ) )
    fprintf ( 1, ...
      '  The file "%s" seems to be a legal ASCII STL file.\n', ...
      input_file_name );
  else
    fprintf ( 1, ...
      '  The file "%s" does NOT seem to be a legal ASCII STL file.\n', ...
      input_file_name );
  end

  return
end


function range = p17_range ( )

%*****************************************************************************80
%
%% P17_RANGE returns an interval bounding the root for problem 17.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 May 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real RANGE(2), the minimum and maximum values of
%    an interval containing the root.
%
  range(1) = 2.0;
  range(2) = 3.0;

  return
end


function [ y2, m2, d2, f2 ] = ymdf_inc_roman ( y1, m1, d1, f1, days )

%*****************************************************************************80
%
%% YMDF_INC_ROMAN increments a Roman YMDF date by a DAYS days.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 April 2103
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y1, M1, D1, real F1,
%    the YMDF date.
%
%    Input, real DAYS, the number of days to advance the date.
%
%    Output, integer Y2, M2, D2, real F2,
%    the incremented YMDF date.
%

%
%  Copy the parameters.
%
  y2 = y1;
  m2 = m1;
  d2 = d1;
  f2 = f1 + days;
%
%  Check the parameters.
%
  [ y2, m2, d2, f2, ierror ] = ymdf_check_roman ( y2, m2, d2, f2 );

  return
end


function s = char(ebsd)
% ebsd -> char

s = [];
for p = 1:numel(ebsd.phaseMap)

  ss = [];
  ss = [ss, 'phase ',num2str(ebsd.phaseMap(p)) ' ']; %#ok<AGROW>

  CS = ebsd.CSList{p};
  if ischar(CS)
    ss = [ss, '(not Indexed): ' CS ', ']; %#ok<AGROW>
  else

    if ~isempty(CS.mineral)
      ss = [ss, '(' CS.mineral '): ']; %#ok<AGROW>
    else
      ss = [ss, ': ']; %#ok<AGROW>
    end

    ss = [ss 'symmetry ' CS.pointGroup ', ']; %#ok<AGROW>
  end

  ss = [ss, num2str(nnz(ebsd.phaseId == p)),' orientations '];    %#ok<AGROW>

  s = strvcat(s,ss);
end


function obj = setInitialValue(obj, x)
    % Sets a typical initial value for the NLP variables. This value will
    % be used to assign the initial value for the NLP solver.
    %
    % @note If the initial value is not given, then use the middle value of
    % the lower/upper boundaries.
    %
    % Parameters:
    % x: an array of initial value of the NLP variables @type colvec

    % determine the typical value
    if nargin > 1

        if isscalar(x)
            x = x*ones(obj.Dimension,1);
        else
            if isrow(x)
                x = transpose(x);
            end
            validateattributes(x,{'double'},...
                {'vector','numel',obj.Dimension,'real'},...
                'NlpVariable.setInitialValue','InitialValue');
        end
        obj.InitialValue = x;
    else
        % preallocate

        lb_tmp = obj.LowerBound;
        ub_tmp = obj.UpperBound;

        % replace infinity with very high numbers
        lb_tmp(lb_tmp==-inf) = -1e5;
        ub_tmp(ub_tmp==inf)  = 1e5;

        obj.InitialValue = (ub_tmp + lb_tmp)/2;
    end

end


function too_young = under_age(age, limit)
    if nargin == 1
        limit = 21;
    end
    too_young = age < limit;
end