function [tq,q,tu,u,t,p,Q,code]=hydrograph(uhname,rdname,method,...
                                           K,D,R,Iar,A,CN,Tc,units)
% SCS Unit Hydrograph Convolution (R11)
%
% [tq,q,tu,u,t,p,Q,code]=hydrograph(uhname,rdname,method,...
%                                   K,D,R,Iar,A,CN,Tc,units)
%
% Input
%   uhname  dimensionless unit hydrograph filename
%   rdname  dimensionless rainfall distribution filename
%   method  interpolation method
%   K       peak factor
%   D       storm duration (hr)
%   R       rainfall depth (mm | in)
%   Iar     initial abstraction ratio
%   A       basin area (km^2 | ac)
%   CN      curve number
%   Tc      time of concentration (min)
%   units   units code
%             0 = imperial
%             1 = metric
%
% Output
%   tq      runoff hydrograph time (hr)
%   q       runoff hydrograph flow rate (cms | cfs)
%   tu      unit hydrograph time (hr)
%   u       unit hydrograph flow rate (cms | cfs)
%   t       rainfall-runoff time (hr)
%   p       cumulative rainfall (mm | in)
%   Q       cumulative runoff (mm | in)
%   code    return code
%             0 = fail
%             1 = pass
%
% Example:
%
%  uhname='library\gamma.duh'; rdname='library\scsii-024.drd'; K=484;
%  method='linear'; D=24; R=200; Iar=0.2; A=3; CN=75; Tc=90; units=1;
%  [tq,q,tu,u,t,p,Q,code]=hydrograph(uhname,rdname,method,...
%                                    K,D,R,Iar,A,CN,Tc,units)
%
% See also help\hydographui.html.

% Version 2.03 Copyright(c)2008
% Tom Davis (tdavis@metzgerwillard.com)
%
% Last revision: 03/16/2008

if units
  R=R/25.4;                             % rainfall depth (in)
  cm2cf=35.3146667214886;               % cubic meters to cubic feet
  %    =1e6/(12^3*2.54^3);
  sk2ac=247.105381467165;               % square kilometers to acres
  %    =1e10/(43560*12^2*2.54^2);
  A=A*sk2ac;                            % basin area (ac)
end
A =A/640;                               % basin area (mi^2)
Tc=Tc/60;                               % time of concentration (hr)
d =Tc/7.5;                              % rain burst duration (hr)
Tp=5*d;                                 % time to peak (hr)
method1=lower(method);
method2=method1;
uhname=lower(uhname);
code=1;

if ~isempty(findstr('triangle',uhname))
  uhname='triangle';
elseif ~isempty(findstr('gamma',uhname))
  uhname='gamma';
end

switch uhname                           % dimensionless unit hydrograph
  case 'triangle'
    Tb=3872/(3*K);                      % time base
    % =2(5280^2/60^2/12)/K
    uh=[0,0;1,1;Tb,0];                  % triangular distribution
    method1='linear';
  case 'gamma'
    f =K*3/1936;
    % =K/(5280^2/60^2/12)
    a0=0.045+0.5*f+5.6*f^2+0.3*f^3;     % cubic estimate
    options=optimset('display','off','tolx',eps);
    g =inline('gamma(a)*exp(a)/a^a-1/f','a','f');
    a =fzero(g,a0,options,f);
    tu=(0:0.2:round(2500/K))';
    u =(tu.*exp(1-tu)).^a;              % gamma distribution
    u(end)=0;                           % force zero ordinate
  otherwise
    uh=load(uhname);                    % tabular distribution
    [m,n]=size(uh);
    [umax,ndx]=max(uh(:,2));            %#ok umax not used
    umin=min(min(uh));
    if m<3 | n~=2 | umin<0 | uh(1,:)~=[0 0] | uh(ndx,:)~=[1 1] %#ok (R11)
      msgbox('Unit Hydrograph is improperly formed.',...
        'File Error','error','modal');
      tq=[];q=[];tu=[];u=[];t=[];p=[];Q=[];code=0;
      return
    end
end

if ~strcmp(uhname,'gamma')
  uh=[uh;uh(end,1)+0.2,0];              % force zero ordinate
  Tu=uh(:,1);
  U =uh(:,2);
  % resample unit hydrograph
  tu=(0:0.2:Tu(end))';
  u =interp1(Tu,U,tu,method1);
end

tu=Tp*tu;                               % unit hydrograph time (hr)
u =K*A*u/Tp;                            % unit hydrograph flow rate (cfs)
u(u<0)=0;

rd=load(rdname);                        % dimensionless rainfall distribution
[m,n]=size(rd);
rmax=max(max(rd));
rmin=min(min(rd));
if m<2 | n~=2 | rmin<0 | rmax>1 | rd(1,:)~=[0 0] | rd(end,:)~=[1 1] %#ok (R11)
  msgbox('Rainfall Distribution is improperly formed.',...
    'File Error','error','modal');
  tq=[];q=[];tu=[];u=[];t=[];p=[];Q=[];code=0;
  return
end

T =D*rd(:,1);
P =R*rd(:,2);
% resample rainfall distribution
t =(0:d:T(end))';                       % rainfall time (hr)
p =interp1(T,P,t,method2);              % rainfall depth (in)

Q =zeros(size(t));
s =1000/CN-10;                          % retention (in)
i =find(p>Iar*s);
Q(i)=(p(i)-Iar*s).^2./(p(i)+(1-Iar)*s); % runoff depth (in)
dQ=[diff(Q);0];                         % incremental runoff depth (in)
q =conv(dQ,u);                          % runoff flow rate (cfs)
q(q<0)=0;
tq=(0:d:t(end)+tu(end))';               % runoff time (hr)

if units
  u=u/cm2cf; q=q/cm2cf;                 % cms
  p=p*25.4; Q=Q*25.4;                   % mm
end


function [V,D,bnd,j,work] = laneig(A,nin,k,sigma,options)

%LANEIG  Compute a few eigenvalues and eigenvectors.
%   LANEIG solves the eigenvalue problem A*v=lambda*v, when A is
%   real and symmetric using the Lanczos algorithm with partial
%   reorthogonalization (PRO).
%
%   [V,D] = LANEIG(A)
%   [V,D] = LANEIG('Afun',N)
%
%   The first input argument is either a real symmetric matrix, or a
%   string containing the name of an M-file which applies a linear
%   operator to the columns of a given matrix.  In the latter case,
%   the second input argument must be N, the order of the problem.
%
%   The full calling sequence is
%
%   [V,D,ERR] = LANEIG(A,K,SIGMA,OPTIONS)
%   [V,D,ERR] = LANEIG('Afun',N,K,SIGMA,OPTIONS)
%
%   On exit ERR contains the computed error bounds.  K is the number of
%   eigenvalues desired and SIGMA is numerical shift or a two letter string
%   which specifies which part of the spectrum should be computed:
%
%   SIGMA            Specified eigenvalues
%
%   'AL'            Algebraically Largest
%   'AS'            Algebraically Smallest
%   'LM'            Largest Magnitude   (default)
%   'SM'            Smallest Magnitude  (does not work when A is an m-file)
%   'BE'            Both Ends.  Computes k/2 eigenvalues
%                   from each end of the spectrum (one more
%                   from the high end if k is odd.)
%
%   The OPTIONS structure specifies certain parameters in the algorithm.
%
%    Field name      Parameter                              Default
%
%    OPTIONS.tol     Convergence tolerance                  16*eps
%    OPTIONS.lanmax  Dimension of the Lanczos basis.
%    OPTIONS.v0      Starting vector for the Lanczos        rand(n,1)-0.5
%                    iteration.
%    OPTIONS.delta   Level of orthogonality among the       sqrt(eps/K)
%                    Lanczos vectors.
%    OPTIONS.eta     Level of orthogonality after           10*eps^(3/4)
%                    reorthogonalization.
%    OPTIONS.cgs     reorthogonalization method used        0
%                    '0' : iterated modified Gram-Schmidt
%                    '1' : iterated classical Gram-Schmidt
%    OPTIONS.elr     If equal to 1 then extended local      1
%                    reorthogonalization is enforced.
%
%   See also LANPRO, EIGS, EIG.

% References:
% R.M. Larsen, Ph.D. Thesis, Aarhus University, 1998.
%
% B. N. Parlett, ``The Symmetric Eigenvalue Problem'',
% Prentice-Hall, Englewood Cliffs, NJ, 1980.
%
% H. D. Simon, ``The Lanczos algorithm with partial reorthogonalization'',
% Math. Comp. 42 (1984), no. 165, 115--142.

% Rasmus Munk Larsen, DAIMI, 1998

%%%%%%%%%%%%%%%%%%%%% Parse and check input arguments. %%%%%%%%%%%%%%%%%%%%%%

if ~isstr(A)
  if nargin<1
    error('Not enough input arguments.');
  end
  [m n] = size(A);
  Aisfunc = 0;
  if m~=n | ~isequal(A,A') | ~isreal(A)
    error('A must be real symmetric')
  end
  if nargin < 4 | isempty(sigma)
    options = [];
  else
    options = sigma;
  end
  if nargin < 3 | isempty(k), sigma = 'LM'; else, sigma = k; end
  if nargin < 2 | isempty(nin), k = min(n,5); else, k = nin; end
else
  if nargin<2
    error('Not enough input arguments.');
  end
  Aisfunc = 1;
  n = nin;
  if nargin < 5 | isempty(options)
    options.tol = 16*eps;
    options.lanmax = n;
    options.v0 = rand(n,1)-0.5;
  end
  if nargin < 4 | isempty(sigma), sigma = 'LM'; end
  if nargin < 3 | isempty(k), k = min(n,5);  end
end

if ~isnumeric(k) | real(abs(fix(k)))~=k | ~isnumeric(n) | real(abs(fix(n)))~=n
  error('Input arguments N and K must be positive integers.')
end

% Quick return for n<2  or k<1
if n < 1 | k<1
  if nargout < 2
    V = zeros(k,1);
  else
    V = eye(n,k);
    D = zeros(k,k);
    bnd =zeros(k,1);
  end
  return
end
if n == 1
  if ~Aisfunc
    D = A;
    V = 1;
    bnd = 0;
  else
    D = feval(A,1);
    V = 1;
    dnb = 0;
  end
  if nargout<2
    V=D;
  end
  return
end

% A is the matrix of all zeros (not detectable if A is a string)
if ~Aisfunc
  if nnz(A)==0
    if nargout < 2
      V = zeros(k,1);
    else
      V = eye(n,k);
      D = zeros(k,k);
      bnd =zeros(k,1);
    end
    return
  end
end

lanmax = n;
tol = 16*eps;
r = rand(n,1)-0.5;
part = sigma;
% Parse options struct
if ~isempty(options) & isstruct(options)
  c = fieldnames(options);
  for i=1:length(c)
    if strmatch(c(i),'v0'), r = getfield(options,'v0'); r=r(:); end
    if strmatch(c(i),'tol'), tol = getfield(options,'tol'); end
    if strmatch(c(i),'lanmax'), lanmax = getfield(options,'lanmax'); end
  end
end

% Protect against absurd arguments.
tol = max(tol,eps);
lanmax = min(lanmax,n);
if size(r,1)~=n
  error('v0 must be a vector of length n')
end

lanmax = min(lanmax,n);
if k>lanmax
  error('K must satisfy  K <= LANMAX <= N.');
end
ksave = k;

if strcmp(sigma,'SM') & ~isstr(A)
  sigma = 0;
end

% Prepare for shift-and-invert if sigma is numeric.
if  isnumeric(sigma)
  part = 'LM';
  if isstr(A)
    error('Shift-and-invert works only when the matrix A is given explicitly.');
  else
    pmmd = symmmd(A);
    A = A(pmmd,pmmd);
    [S.L,S.U] = lu(A - sigma*speye(n));
    condU = condest(S.U);
    dsigma = n * full(max(max(abs(A)))) * eps;
    if sigma < 0
      sgnsig = -1;
    else
      sgnsig = 1;
    end
    sigitr = 1;
    while condU > 1/eps & ((dsigma <= 1 & sigitr <= 10) | ~isfinite(condU))
      disps1 = sprintf(['sigma = %10e is near an exact eigenvalue of A,\n' ...
			'so we cannot use the LU factorization of (A-sigma*I): ' ...
			' condest(U) = %10e.\n'],sigma,condU);
      if abs(sigma) < 1
	sigma = sigma + sgnsig * dsigma;
	disps2 = sprintf('We are trying sigma + %10e = %10e instead.\n', ...
			 sgnsig*dsigma,sigma);
      else
	sigma = sigma * (1 + dsigma);
	disps2 = sprintf('We are trying sigma * (1 + %10e) = %10e instead.\n', ...
			 dsigma,sigma);
      end
      %     if nargout < 3 & dispn ~= 0
      disp([disps1 disps2])
      %     end
      [S.L,S.U] = lu(A - sigma*speye(n));
      condU = condest(S.U);
      dsigma = 10 * dsigma;
      sigitr = sigitr + 1;
    end
  end
  A = S;
end

neig = 0; nrestart=-1;
if ~strcmp(part,'BE')
  j = min(2*k+2,lanmax);
else
  j = min(k+1,lanmax);
end

%%%%%%%%%%%%%%%%%%%%% Here begins the computation  %%%%%%%%%%%%%%%%%%%%%%

V = []; T = []; anorm = []; work = zeros(1,2); rnorm=-1;

while neig < k
  %%%%%%%%%%%%%%%%%%%%% Compute Lanczos tridiagonalization %%%%%%%%%%%%%%%%%
  j = min(lanmax,j+1-mod(j,2));
  % "Trick" to avoid unwanted zero eigenvalues when laneig is used for
  % SVD calculations. (Nothing to if lanmax is odd, though.)

  if  ~isstr(A)
    [V,T,r,anorm,ierr,w] = lanpro(A,j,r,options,V,T,anorm);
  else
    [V,T,r,anorm,ierr,w] = lanpro(A,n,j,r,options,V,T,anorm);
  end
  work= work + w;

  if ierr<0 % Invariant subspace of dimension -ierr found.
    j = -ierr;
  end

  %%%%%%%%%%%%%%%%%% Compute eigenvalues and error bounds %%%%%%%%%%%%%%%%%%
  % Analyze T
  [D,top,bot,err] = tqlb([full(diag(T))],full([0;diag(T,1)]));
  %  if err>0
  %    printf(['TQLB failed. Eigenvalue no. %i did not converge in 30', ...
  %	  ' iterations'],err);
  %  end
  %  full(T)
  %  [P,D] = eig(full(T));
  %  D = diag(D);
  %  bot = P(end,:)';
  %  [P(1,:)' P(end,:)']
  [D,I] = sort(D);
  bot = bot(I);

  % Set simple error bounds
  rnorm = norm(r);
  bnd = rnorm*abs(bot);

  % Use Largest Ritz value to estimate ||A||_2. This might save some
  % reorth. in case of restart.
  anorm = max(abs(D));

  % Estimate gap structure and refine error bounds
  bnd = refinebounds(D,bnd,n*eps*anorm);

  %%%%%%%%%%%%%%%%%%% Check convergence criterion %%%%%%%%%%%%%%%%%%%%
  % Reorder eigenvalues according to SIGMA
  switch part
   case 'AS'
    IPART = 1:j;
   case 'AL'
    IPART = j:-1:1;
   case 'LM'
    [dummy,IPART] = sort(-abs(D));
   case 'BE'
    if j<k
      IPART=1:j;
    else
      mid = floor(k/2);
      par = rem(k,1);
      IPART = [1:mid,(j-mid-par):j]';
    end
   otherwise
    error(['Illegal value for SIGMA: ',part]);
  end
  D = D(IPART);  bnd = bnd(IPART);
  if isnumeric(sigma)
    D = sigma + 1./D;
  end

  % Check if enough have converged.
  neig = 0;
  for i=1:min(j,k)
    if bnd(i) <= tol*abs(D(i))
      neig = neig + 1;
    end
  end

  %%%%%%%%%%% Check whether to stop or to extend the Krylov basis? %%%%%%%%%%
  if ierr<0 % Invariant subspace found
    if j<k
      warning(['Invariant subspace of dimension ',num2str(j-1),' found.'])
    end
    break;
  end
  if j>=lanmax % Maximal dimension of Krylov subspace reached => Bail out!
    if neig<ksave
      warning(['Maximum dimension of Krylov subspace exceeded prior',...
	       ' to convergence.']);
    end
    break;
  end

  % Increase dimension of Krylov subspace and try again.
  if neig>0
    %    j = j + ceil(min(20,max(2,((j-1)*(k-neig+1))/(2*(neig+1)))));
    j = j + min(100,max(2,0.5*(k-neig)*j/(neig+1)));
  elseif neig<k
    %    j = j + ceil(min(20,max(8,(k-neig)/2)));
    j = max(1.5*j,j+10);
  end
  j = min(j+1,lanmax);
  nrestart = nrestart + 1;
end

%%%%%%%%%%%%%%%% Lanczos converged (or failed). Prepare output %%%%%%%%%%%%%%%
k = min(ksave,j);

if nargout>1
  j = size(T,1);
  [Q,D] = eig(full(T)); D = diag(D);
  [D,I] = sort(D);
  % Compute and normalize Ritz vectors (overwrite V to save memory).
  V = V*Q(:,I(IPART(1:k)));
  for i=1:k
    nq = norm(V(:,i));
    if isfinite(nq) & nq~=0 & nq~=1
      V(:,i) = V(:,i)/nq;
    end
  end
  [D,I] = sort(D);
  D = D(IPART(1:k));
  if isnumeric(sigma)
    D = sigma + 1./D;
    V(pmmd,:) = V;
  end
end

% Pick out desired part of the spectrum
if length(D)~=k
  D = D(1:k);
  bnd = bnd(1:k);
end

if nargout<2
  V = D;
else
  D = diag(D);
end


function T = logm(q,varargin)
% the logarithmic map that translates a rotation into a spin tensor
%
% Syntax
%   T = logm(q) % spin tensor with reference to the identical rotation
%   T = logm(q,q_ref) % spin tensor with reference q_ref
%
% Input
%  q - @quaternion
%  q_ref - @quaternion
%
% Output
%  T - @spinTensor
%
% See also
% spinTensor/exp

tq = log(q,varargin{:});

M = zeros([3,3,size(q)]);

M(2,1,:) =  tq.z;
M(3,1,:) = -tq.y;
M(3,2,:) =  tq.x;

M(1,2,:) = -tq.z;
M(1,3,:) =  tq.y;
M(2,3,:) = -tq.x;

% make it a spinTensor
T = spinTensor(M);


function incidence_matrix = gr_incidence_matrix ( node_num, ...
  node_coordinates, edge_num, edge_nodes )

%*****************************************************************************80
%
%% GR_INCIDENCE_MATRIX computes the incidence matrix.
%
%  Discussion:
%
%    The incidence matrix is of order EDGE_NUM by NODE_NUM.
%
%    A(I,J) = 1 if edge I uses node J.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, real NODE_COORDINATES(2,NODE_NUM), the coordinates of the nodes.
%
%    Input, integer EDGE_NUM, the number of edges.
%
%    Input, integer EDGE_NODES(2,EDGE_NUM), the indices of the two nodes
%    that form each edge.
%
%    Output, integer INCIDENCE_MATRIX(EDGE_NUM,NODE_NUM), the incidence
%    matrix.
%
  incidence_matrix = zeros ( edge_num, node_num );

  for e = 1 : edge_num
    for i = 1 : 2
      n = edge_nodes(i,e);
      incidence_matrix(e,n) = incidence_matrix(e,n) + 1;
    end
  end

  return
end


function matrix = rmAverageTime(matrix,nrep);
% rmAverageTime - average non-unique epochs in time (1st) dimension
%
%  out = rmAverageTime(in,nrep);
%
% 2006/03 SOD: wrote it.

% sanity check (<1 no averaging needed)
if nrep <= 1,
  return;
else,
  matrixin = matrix;
end;

% get total size input
sz  = size(matrixin);

% get total size output
len      = sz(1)./nrep;
szout    = sz;
szout(1) = len;

% initiate matrixout
matrix   = matrixin(1:len,:);

% repeat (add) process
start = len;
for n=1:nrep-1,
    matrix = matrix + matrixin(start+1:start+len,:);
    start     = start + len;
end;

% mean
matrix = matrix ./ nrep;

% reshape if necesary
matrix = reshape(matrix,szout);

return


function y = square_pos( x )

%SQUARE_POS    Square of positive part.
%   SQUARE_POS(X) is the square of the postive parts of the elements of X;
%   i.e., SQUARE_POS(X)=MAX(X,0).^2. X must be real.
%
%   Disciplined convex programming information:
%       SQUARE_POS(X) is convex and nondecreasing in X. Thus when used in
%       CVX expressions, X must be convex (or affine).

narginchk(1,1);
if ~isreal( x ),
    error( 'Argument must be real.' );
end

y = square( max( x, 0 ) );

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


function triangulation_test08 ( )

%*****************************************************************************80
%
%% TEST08 tests R8TRIS2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 June 2005
%
%  Author:
%
%    John Burkardt
%
  node_num = 9;
  dim_num = 2;

  node_xy = [ ...
       0.0, 0.0; ...
       0.0, 1.0; ...
       0.2, 0.5; ...
       0.3, 0.6; ...
       0.4, 0.5; ...
       0.6, 0.4; ...
       0.6, 0.5; ...
       1.0, 0.0; ...
       1.0, 1.0 ]';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST08\n' );
  fprintf ( 1, '  R8TRIS2 computes the Delaunay triangulation of\n' );
  fprintf ( 1, '    a set of nodes in 2D.\n' );
%
%  Set up the Delaunay triangulation.
%
  [ triangle_num, triangle_node, triangle_neighbor ] = r8tris2 ( ...
    node_num, node_xy );

  triangulation_order3_print ( node_num, triangle_num, node_xy, ...
    triangle_node, triangle_neighbor );

  return
end


function [N,X,sp] = histogramDistributionPlot(varargin)
% HISTOGRAM generates a histogram using the "optimal" number of bins
%
% If called with no output argument, histogram plots into the current axes
%
% SYNOPSIS [N,X,sp] = histogram(data,factor,normalize)
%          [...] = histogram(data,'smooth')
%          [...] = histogram(axesHandle,...)
%
% INPUT    data: vector of input data
%          factor: (opt) factor by which the bin-widths are multiplied
%                   if 'smooth' (or 's'), a smooth histogram will be formed.
%                   (requires the spline toolbox). For an alternative
%                   approach to a smooth histogram, see ksdensity.m
%                   if 'discrete' (or 'd'), the data is assumed to be a discrete
%                   collection of values. Note that if every data point is,
%                   on average, repeated at least 3 times, histogram will
%                   consider it a discrete distribution automatically.
%                   if 'continuous' (or 'c'), histogram is not automatically
%                   checking for discreteness.
%          normalize : if 1 (default), integral of histogram equals number
%                       data points. If 0, height of bins equals counts.
%                       This option is exclusive to non-"smooth" histograms
%          axesHandle: (opt) if given, histogram will be plotted into these
%                       axes, even if output arguments are requested
%
% OUTPUT   N   : number of points per bin (value of spline)
%          X   : center position of bins (sorted input data)
%          sp  : definition of the smooth spline
%
% REMARKS: The smooth histogram is formed by calculating the cumulative
%           histogram, fitting it with a smoothening spline and then taking
%           the analytical derivative. If the number of data points is
%           markedly above 1000, the spline is fitting the curve too
%           locally, so that the derivative can have huge peaks. Therefore,
%           only 1000-1999 points are used for estimation.
%           Note that the integral of the spline is almost exactly the
%           total number of data points. For a standard histogram, the sum
%           of the hights of the bins (but not their integral) equals the
%           total number of data points. Therefore, the counts might seem
%           off.
%
%           WARNING: If there are multiples of the minimum value, the
%           smooth histogram might get very steep at the beginning and
%           produce an unwanted peak. In such a case, remove the
%           multiple small values first (for example, using isApproxEqual)
%
%
% c: 2/05 jonas
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% test input
if nargin < 1
    error('not enough input arguments for histogram')
end

% check for axes handle
if length(varargin{1}) == 1 && ishandle(varargin{1});
    axesHandle = varargin{1};
    varargin(1) = [];
else
    % ensure compatibility to when axesHandle was given as last input
    if nargin == 3 && ishandle(varargin{end}) && varargin{end} ~= 0
        axesHandle = varargin{end};
        varargin(end) = [];
    else
        axesHandle = 0;
    end
end

% assign data
numArgIn = length(varargin);
data = varargin{1};
data = data(:);

% check for non-finite data points
data(~isfinite(data)) = [];

% check for "factor"
if numArgIn < 2 || isempty(varargin{2})
    factor = 1;
else
    factor = varargin{2};
end
if ischar(factor)
    switch factor
        case {'smooth','s'}
        factor = -1;
        case {'discrete','d'}
            factor = -2;
        case {'continuous','c'}
            factor = -3;
    otherwise
        error('The only string inputs permitted for histogram.m are ''smooth'',''discrete'', or ''continuous''')
    end
else
    % check for normalize, but do so only if there is no "smooth". Note
    % that numArgIn is not necessarily equal to nargin
    if numArgIn < 3 || isempty(varargin{3})
        normalize = true;
    else
        normalize = varargin{3};
    end
end

% doPlot is set to 1 for now. We change it to 0 below if necessary.
doPlot = 1;

nData = length(data);
% check whether we do a standard or a smooth histogram
if factor ~= -1
    % check for discrete distribution
    [xx,nn] = countEntries(data);
    % consider the distribution discrete if there are, on average, 3
    % entries per bin
    nBins = length(xx);
    if factor == -2 || (factor ~= -3 && nBins*3 < nData)
        % discrete distribution.
        nn = nn';
        xx = xx';
    else
        % not a discrete distribution
        if nData < 20
            warning('HISTOGRAM:notEnoughDataPoints','Less than 20 data points!')
            nBins = ceil(nData/4);
        else

            % create bins with the optimal bin width
            % W = 2*(IQD)*N^(-1/3)
            interQuartileDist = diff(prctile(data,[25,75]));
            binLength = 2*interQuartileDist*length(data)^(-1/3)*factor;

            % number of bins: divide data range by binLength
            nBins = round((max(data)-min(data))/binLength);

            if ~isfinite(nBins)
                nBins = length(unique(data));
            end

        end

        % histogram
        [nn,xx] = hist(data,nBins);
        % adjust the height of the histogram
        if normalize
            Z = trapz(xx,nn);
            nn = nn * nData/Z;
        end

    end
    if nargout > 0
        N = nn;
        X = xx;
        doPlot = axesHandle;
    end
    if doPlot
        if axesHandle
            bar(axesHandle,xx,nn,1);
        else
            bar(xx,nn,1);
        end
    end

else
    % make cdf, smooth with spline, then take the derivative of the spline

    % cdf
    xData = sort(data);
    yData = 1:nData;

    % when using too many data points, the spline fits very locally, and
    % the derivatives can still be huge. Good results can be obtained with
    % 500-1000 points. Use 1000 for now
    step = max(floor(nData/1000),1);
    xData2 = xData(1:step:end);
    yData2 = yData(1:step:end);

    % spline. Use strong smoothing
    cdfSpline = csaps(xData2,yData2,1./(1+mean(diff(xData2))^3/0.0006));

    % pdf is the derivative of the cdf
    pdfSpline = fnder(cdfSpline);

    % histogram
    if nargout > 0
        xDataU = unique(xData);
        N = fnval(pdfSpline,xDataU);
        X = xDataU;
        % adjust the height of the histogram
        Z = trapz(X,N);
        N = N * nData/Z;
        sp = pdfSpline;
        % set doPlot. If there is an axesHandle, we will plot
        doPlot = axesHandle;
    end
    % check if we have to plot. If we assigned an output, there will only
    % be plotting if there is an axesHandle.
    if doPlot
        if axesHandle
            plot(axesHandle,xData,fnval(pdfSpline,xData));
        else
            plot(xData,fnval(pdfSpline,xData));
        end
    end
end


function symmetric_sparse_size_test ( )

%*****************************************************************************80
%
%% SYMMETRIC_SPARSE_SIZE_TEST tests SYMMETRIC_SPARSE_SIZE.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 September 2012
%
%  Author:
%
%    John Burkardt.
%
%  Local parameters:
%
%    Local, integer D, the spatial dimension.
%
%    Local, integer MAXK, the maximum level to check.
%
  test_num = 3;

  dim_test = [ 5, 5, 3 ];
  nodes1 = [ ...
   0.0, 0.0, 0.0, 0.0, 0.0, 1.0;
   0.0, 0.0, 0.0, 0.0, 1.0, 0.0;
   0.0, 0.0, 0.0, 1.0, 0.0, 0.0;
   0.0, 0.0, 1.0, 0.0, 0.0, 0.0;
   0.0, 1.0, 0.0, 0.0, 0.0, 0.0 ]';
  nodes2 = [ ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    1.0, 1.0, 1.0, 1.0, 1.0, ...
    1.73205; ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    1.0, 1.0, 1.0, 1.0, 1.73205, ...
    0.0, 0.0, 0.0, 0.0, 1.0, ...
    0.0; ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.0, 1.0, 1.0, 1.0, 1.73205, ...
    0.0, 0.0, 0.0, 1.0, 0.0, ...
    0.0, 0.0, 0.0, 1.0, 0.0, ...
    0.0; ...
    0.0, 0.0, 0.0, 1.0, 1.0, ...
    1.73205, 0.0, 0.0, 1.0, 0.0, ...
    0.0, 0.0, 1.0, 0.0, 0.0, ...
    0.0, 0.0, 1.0, 0.0, 0.0, ...
    0.0; ...
    0.0, 1.0, 1.73205, 0.0, 1.0, ...
    0.0, 0.0, 1.0, 0.0, 0.0, ...
    0.0, 1.0, 0.0, 0.0, 0.0, ...
    0.0, 1.0, 0.0, 0.0, 0.0, ...
    0.0 ]';
  nodes3 = [ ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.0, 0.0, 0.741964, 1.0, 1.0, ...
    1.0, 1.0, 1.0, 1.0, 1.73205, ...
    1.73205, 1.73205, 2.33441; ...
    0.0, 0.0, 0.0, 0.0, 0.0, ...
    0.741964, 1.0, 1.0, 1.0, 1.73205, ...
    1.73205, 2.33441, 0.0, 0.0, 0.0, ...
    0.0, 1.0, 1.0, 1.73205, 0.0, ...
    0.0, 1.0, 0.0; ...
    0.0, 0.741964, 1.0, 1.73205, 2.33441, ...
    0.0, 0.0, 1.0, 1.73205, 0.0, ...
    1.0, 0.0, 0.0, 0.0, 1.0, ...
    1.73205, 0.0, 1.0, 0.0, 0.0, ...
    1.0, 0.0, 0.0 ]';
  r_test = [ 6, 21, 23 ];

  fprintf ( 1, '\n' );
  fprintf ( 1, 'SYMMETRIC_SPARSE_SIZE_TEST\n' );
  fprintf ( 1, '  Given a symmetric sparse grid rule represented only by\n' );
  fprintf ( 1, '  the points with positive values, determine the total number\n' );
  fprintf ( 1, '  of points in the grid.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  For dimension DIM, we report\n' );
  fprintf ( 1, '  R, the number of points in the positive orthant, and\n' );
  fprintf ( 1, '  R2, the total number of points.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '       DIM         R        R2\n' );
  fprintf ( 1, '\n' );

  x0 = 0.0;

  for test = 1 : test_num

    r = r_test(test);
    dim = dim_test(test);

    if ( test == 1 )
      r2 = symmetric_sparse_size ( r, dim, nodes1, x0 );
    elseif ( test == 2 )
      r2 = symmetric_sparse_size ( r, dim, nodes2, x0 );
    elseif ( test == 3 )
      r2 = symmetric_sparse_size ( r, dim, nodes3, x0 );
    end

    fprintf ( 1, '  %8d  %8d  %8d\n', dim, r, r2 );

  end

  return
end


%SUBTRACT  Calculates the per-element difference between two arrays or array and a scalar
%
%     dst = cv.subtract(src1, src2)
%     dst = cv.subtract(src1, src2, 'OptionName',optionValue, ...)
%
% ## Input
% * __src1__ first input array or a scalar.
% * __src2__ second input array or a scalar.
%
% ## Output
% * __dst__ output array of the same size and number of channels as the input
%   array(s). The depth is defined by `DType` or that of `src1`/`src2`.
%
% ## Options
% * __Mask__ optional operation mask; this is an 8-bit single channel array
%   that specifies elements of the output array to be changed. Not set by
%   default.
% * __Dest__ Used to initialize the output `dst` when a mask is used. Not set
%   by default.
% * __DType__ optional depth of the output array: `uint8`, `int16`, `double`,
%   etc. (see the discussion below). Must be specified if input arrays are of
%   different types. default -1
%
% The function cv.subtract calculates:
%
% * Difference between two arrays, when both input arrays have the same size
%   and the same number of channels:
%
%       dst(I) = saturate(src1(I) - src2(I)) if mask(I) != 0
%
% * Difference between an array and a scalar, when `src2` is constructed from
%   Scalar or has the same number of elements as `size(src1,3)`:
%
%       dst(I) = saturate(src1(I) - src2) if mask(I) != 0
%
% * Difference between a scalar and an array, when `src1` is constructed from
%   Scalar or has the same number of elements as `size(src2,3)`:
%
%       dst(I) = saturate(src1 - src2(I)) if mask(I) != 0
%
% * The reverse difference between a scalar and an array in the case of
%   `SubRS`:
%
%       dst(I) = saturate(src2 - src1(I)) if mask(I) != 0
%
% where `I` is a multi-dimensional index of array elements. In case of
% multi-channel arrays, each channel is processed independently.
%
% The first function in the list above can be replaced with matrix expressions:
%
%     dst = src1 - src2;
%
% The input arrays and the output array can all have the same or different
% depths. For example, you can subtract to 8-bit unsigned arrays and store the
% difference in a 16-bit signed array. Depth of the output array is determined
% by `DType` parameter. In the second and third cases above, as well as in the
% first case, when `class(src1) == class(src2)`, `DType` can be set to the
% default -1. In this case the output array will have the same depth as the
% input array, be it `src1`, `src2` or both.
%
% Note: Saturation is not applied when the output array has the depth `int32`.
% You may even get result of an incorrect sign in the case of overflow.
%
% See also: cv.add, cv.addWeighted
%


function [Signal, Sigma] = MPdenoising(data, mask, kernel, sampling, centering)
    %
    % "MPPCA": 4d image denoising and noise map estimation by exploiting  data redundancy in the PCA domain using universal properties of the eigenspectrum of
    % random covariance matrices, i.e. Marchenko Pastur distribution
    %
    %  [Signal, Sigma] = MPdenoising(data, mask, kernel, sampling)
    %       output:
    %           - Signal: [x, y, z, M] denoised data matrix
    %           - Sigma: [x, y, z] noise map
    %       input:
    %           - data: [x, y, z, M] data matrix
    %           - mask:   (optional)  region-of-interest [boolean]
    %           - kernel: (optional)  window size, typically in order of [5 x 5 x 5]
    %           - sampling:
    %                    1. full: sliding window (default for noise map estimation, i.e. [Signal, Sigma] = MPdenoising(...) )
    %                    2. fast: block processing (default for denoising, i.e. [Signal] = MPdenoising(...))
    %
    %  Authors: Jelle Veraart (jelle.veraart@nyumc.org)
    % Copyright (c) 2016 New York Universit and University of Antwerp
    %
    %      Permission is hereby granted, free of charge, to any non-commercial entity
    %      ('Recipient') obtaining a copy of this software and associated
    %      documentation files (the 'Software'), to the Software solely for
    %      non-commercial research, including the rights to use, copy and modify the
    %      Software, subject to the following conditions:
    %
    %        1. The above copyright notice and this permission notice shall be
    %      included by Recipient in all copies or substantial portions of the
    %      Software.
    %
    %        2. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
    %      EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIESOF
    %      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
    %      NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BELIABLE FOR ANY CLAIM,
    %      DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
    %      OTHERWISE, ARISING FROM, OUT OF ORIN CONNECTION WITH THE SOFTWARE OR THE
    %      USE OR OTHER DEALINGS IN THE SOFTWARE.
    %
    %        3. In no event shall NYU be liable for direct, indirect, special,
    %      incidental or consequential damages in connection with the Software.
    %      Recipient will defend, indemnify and hold NYU harmless from any claims or
    %      liability resulting from the use of the Software by recipient.
    %
    %        4. Neither anything contained herein nor the delivery of the Software to
    %      recipient shall be deemed to grant the Recipient any right or licenses
    %      under any patents or patent application owned by NYU.
    %
    %        5. The Software may only be used for non-commercial research and may not
    %      be used for clinical care.
    %
    %        6. Any publication by Recipient of research involving the Software shall
    %      cite the references listed below.
    %
    % REFERENCES
    %      Veraart, J.; Fieremans, E. & Novikov, D.S. Diffusion MRI noise mapping
    %      using random matrix theory Magn. Res. Med., 2016, early view, doi:
    %      10.1002/mrm.26059

    if isa(data,'integer')
        data = single(data);
    end
    [sx, sy, sz, M] = size(data);

    if ~exist('mask', 'var') || isempty(mask)
        mask = true([sx, sy, sz]);
    end
    if ~isa(mask,'boolean')
        mask = mask>0;
    end

    if ~exist('kernel', 'var') || isempty(kernel)
        kernel = [5 5 5];
    end

    if isscalar(kernel)
        kernel = [kernel, kernel, kernel];
    end
    kernel = kernel + (mod(kernel, 2)-1);   % needs to be odd.
    k = (kernel-1)/2; kx = k(1); ky = k(2); kz = k(3);
    N = prod(kernel);

    if ~exist('sampling', 'var') || isempty(sampling)
        if nargout > 1
            sampling = 'full';
        else
            sampling = 'fast';
        end
    end

    % create mask
    if ~exist('mask', 'var') || isempty(mask)
        mask = true(sx, sy, sz);
    end

    if ~exist('centering', 'var') || isempty(centering)
        centering = false;
    end

    if strcmp(sampling, 'fast')
        if nargout>1
            warning('undersampled noise map will be returned')
        end
        % compute center points of patches
        stats = regionprops(mask, 'BoundingBox');
        n = ceil(stats.BoundingBox(4:6) ./ kernel);

        x = linspace(ceil(stats.BoundingBox(1))+k(1), floor(stats.BoundingBox(1))-k(1) + stats.BoundingBox(4), n(1)); x = round(x);
        y = linspace(ceil(stats.BoundingBox(2))+k(2), floor(stats.BoundingBox(2))-k(2) + stats.BoundingBox(5), n(2)); y = round(y);
        z = linspace(ceil(stats.BoundingBox(3))+k(3), floor(stats.BoundingBox(3))-k(3) + stats.BoundingBox(6), n(3)); z = round(z);

        [y, x, z] = meshgrid(x, y, z); x = x(:); y = y(:); z = z(:);
    end

    if strcmp(sampling, 'full')
        warning('image boundaries are not processed.')
        mask(1:k(1), :, :) = 0;
        mask(sx-k(1):sx, :, :) = 0;

        mask(:, 1:k(2), :) = 0;
        mask(:, sy-k(2):sy, :, :) = 0;
        mask(:,:,1:k(3)) = 0;
        mask(:,:,sz-k(3)) = 0;

        x = []; y = []; z = [];
        for i = k(3)+1:sz-k(3)
            [x_, y_] = find(mask(:,:,i) == 1);
            x = [x; x_]; y = [y; y_];  z = [z; i*ones(size(y_))];
        end
        x = x(:); y = y(:); z = z(:);
    end

    % Declare variables:
    if logical(exist('OCTAVE_VERSION', 'builtin')) % for Octave, zeros(..,'like',data) not implemented. replace with class(data).
        zerosoption = {class(data)};
    else
        zerosoption = {'like', data};
    end
    sigma = zeros(1, numel(x), zerosoption{:});
    npars = zeros(1, numel(x), zerosoption{:});
    signal = zeros(M, prod(kernel), numel(x), zerosoption{:});

    Sigma = zeros(sx, sy, sz, zerosoption{:});
    Npars = zeros(sx, sy, sz, zerosoption{:});
    Signal = zeros(sx, sy, sz, M, zerosoption{:});

    % compute scaling factor for in case N<M
    R = min(M, N);
    scaling = (max(M, N) - (0:R-centering-1)) / N;
    scaling = scaling(:);

    % start denoising
    for nn = 1:numel(x)

        % create data matrix
        X = data(x(nn)-kx:x(nn)+kx, y(nn)-ky:y(nn)+ky, z(nn)-kz:z(nn)+kz, :);
        X = reshape(X, N, M); X = X';

        if centering
            colmean = mean(X, 1);
            X = X - repmat(colmean, [M, 1]);
        end
        % compute PCA eigenvalues
        [u, vals, v] = svd(X, 'econ');
        vals = diag(vals).^2 / N;

        % First estimation of Sigma^2;  Eq 1 from ISMRM presentation
        csum = cumsum(vals(R-centering:-1:1)); cmean = csum(R-centering:-1:1)./(R-centering:-1:1)'; sigmasq_1 = cmean./scaling;

        % Second estimation of Sigma^2; Eq 2 from ISMRM presentation
        gamma = (M - (0:R-centering-1)) / N;
        rangeMP = 4*sqrt(gamma(:));
        rangeData = vals(1:R-centering) - vals(R-centering);
        sigmasq_2 = rangeData./rangeMP;

        % sigmasq_2 > sigma_sq1 if signal-components are represented in the
        % eigenvalues

        t = find(sigmasq_2 < sigmasq_1, 1);

        if isempty(t)
            sigma(nn) = NaN;
            signal(:, :, nn) = X;
            t = R+1;
        else
            sigma(nn) = sqrt(sigmasq_1(t));
            vals(t:R) = 0;
            s = u*diag(sqrt(N*vals))*v';
            if centering
               s = s + repmat(colmean, [M, 1]);
            end

            signal(:, :, nn) = s;
        end
        npars(nn) = t-1;
    end

    for nn = 1:numel(x)
        Sigma(x(nn), y(nn), z(nn)) = sigma(nn);
        Npars(x(nn), y(nn), z(nn)) = npars(nn);
        if strcmp(sampling, 'fast')
            Signal(x(nn)-k(1):x(nn)+k(1),y(nn)-k(2):y(nn)+k(2),z(nn)-k(3):z(nn)+k(3), :) = unpatch(signal(:,:,nn), k);
        elseif strcmp(sampling, 'full')
            Signal(x(nn), y(nn),z(nn), :) = signal(:,ceil(prod(kernel)/ 2),nn);
        end
    end
end

function data = unpatch(X, k)
    kernel=k+k+1;
    data = zeros([kernel, size(X, 1)]);
    tmp = zeros(kernel);
    for i = 1:size(X, 1);
        tmp(:) = X(i, :);
        data(:,:,:,i) = tmp;
    end
end


function [f] = spm_fx_poly(x,v,P)
% Normal (bilinear) form equation of motion
% FORMAT [f] = spm_fx_poly(x,v,P)
% x      - state vector
% v      - exogenous cause
% P      - free parameters
%
% f      - dx/dt
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_fx_poly.m 3878 2010-05-07 19:53:54Z karl $

% compute Jacobian from blinear terms
%--------------------------------------------------------------------------
x     = spm_vec(x);
J     = P.A;
for i = 1:length(P.B)
    J = J + P.B{i}*x(i);
end
for i = 1:length(P.C)
    J = J + P.C{i}*v(i);
end
f     = J*x;


function s = dirichlet_initial_s(m, bar_p)

K = length(m);
m = m/sum(m);
s = (K-1)/2/(-sum(m.*bar_p)+sum(m.*log(m)));


function [result, prediction] = svr_test_linear_shift(test_labels, test_samples, model)

    prediction = test_samples * model.w(1:end-1)' + model.w(end);
%     prediction = predict(test_labels, test_samples, model);

    prediction(~model.success) = 0;

    if(model.cutoff >= 0)
        % perform shifting here per person
        users = unique(model.vid_ids);

        for i=1:numel(users)

            preds_user = prediction(strcmp(model.vid_ids, users(i)));
            sorted = sort(preds_user);

            % alternative, move to histograms and pick the highest one

            shift = sorted(round(end*model.cutoff)+1);

            prediction(strcmp(model.vid_ids, users(i))) = preds_user - shift;

        end
    end

    % Cap the prediction as well
    prediction(prediction<0)=0;
    prediction(prediction>5)=5;

    % using the average of RMS errors
%     result = mean(sqrt(mean((prediction - test_labels).^2)));
    if(~isfield(model, 'eval_ids'))
        result = corr(test_labels, prediction);
        [ ~, ~, ~, ccc, ~, ~ ] = evaluate_regression_results( prediction, test_labels );
        result = ccc;
    else
        eval_ids = unique(model.eval_ids)';
        ccc = 0;
        fprintf('CCC: ');
        for i=eval_ids
            [ ~, ~, ~, ccc_curr, ~, ~ ] = evaluate_regression_results( prediction(model.eval_ids == i), test_labels(model.eval_ids == i) );
            ccc = ccc + ccc_curr;
            fprintf('%.3f ', ccc_curr);
        end
        ccc = ccc / numel(eval_ids);
        fprintf('mean : %.3f\n', ccc);
        result = ccc;
    end

    if(isnan(result))
        result = 0;
    end

end


function p_ = ViewCurveSlope(X,p)

[J,K]=size(X);

% constrain probabilities to sum to one...
Aeq = ones(1,J);
beq=1;

% ...constrain the expectation...
V= X(:,14)-X(:,13);
v=.0005;

Aeq=[Aeq
    V'];
beq=[beq
    v];

A=[];
b=[];

% ...compute posterior probabilities
p_ = EntropyProg(p,A,b,Aeq ,beq);


function [RR_e_resamp,QRS_A_resamp] = clean_and_resample_intervals(onsets,QRS_A1,Fs)

% Use same pre-processing used for ECG in the paper ''
%
%

IBI = diff(onsets)./Fs;
t_IBI = onsets(2:end)./Fs;

RR_e0 = IBI;     % no ectopic rejection
QRS_A0 = QRS_A1;

% reject ectopic beats
% remove invalid R-R intervals if RR<0.3 or RR>2.0 & 20% outside of 41 points moving mean exclude

RR_mean_41 = meanfilt1(IBI,41);
RR = [];    % RR interval in seconds
RR_time=[]; % time of RR interval in seconds
v_RR = ones(1,length(IBI))*-1;
n_RR = 0;
for j=1:length(IBI)
    if abs(IBI(j) - RR_mean_41(j)) < 0.2*RR_mean_41(j) &&  IBI(j)>= 0.3 && IBI(j) <= 2.0
        n_RR = n_RR+1;
        RR(n_RR) = IBI(j);
        RR_time(n_RR) = onsets(j)/Fs;
        v_RR(j)=1;
    end
end
valid_RR=find(v_RR==1);
% remove invalid QRS peaks if 50% outside of 41 points moving mean
QRS_A_mean_41=meanfilt1(QRS_A1,41);
n_QRS=0;
QRS=[];
QRS_time=[];
v_QRS=ones(1,length(QRS_A1))*-1;
for k=1:length(QRS_A1)
    if abs(QRS_A1(k)-QRS_A_mean_41(k))<0.5*QRS_A_mean_41(k)
        n_QRS=n_QRS+1;
        QRS(n_QRS) = QRS_A1(k);
        QRS_time(n_QRS) = tIBI(j);
        v_QRS(k)=1;
    end
end
valid_QRS=find(v_QRS==1);
valid_RRQRS=intersect(valid_RR,valid_QRS);
valid_RR=valid_RRQRS;

onsets = onsets(valid_RR);
QRS_A1=QRS_A1(valid_RR);

RR_e1 = IBI(valid_RR);

% resample to 4Hz
onsets = onsets./Fs;
t2=round(onsets(end));
Fs_resamp=4;
t1=(1/Fs_resamp):(1/Fs_resamp):t2; % 4Hz resample

% linear interpolation
QRS_A_resamp = interp1(onsets,QRS_A1,t1);%,'spline');
RR_e_resamp = interp1(onsets,RR_e1,t1);%,'spline');
QRS_A_resamp(find(isnan(QRS_A_resamp)))=nanmean(QRS_A_resamp);
RR_e_resamp(find(isnan(RR_e_resamp)))=nanmean(RR_e_resamp);


function ret = filterBlock(in)
    in = in + 1e-8;
%     idx = [2 4 5 6 8];
%     in = in(idx, :);
    mid = in(5, :);
%     ret = sum(abs(bsxfun(@minus, log(mid), log(in)))) / 8;
    temp = abs(bsxfun(@minus, log(mid), log(in)));
    ret = sum((temp)) / 8;
end


function [Hx,Hy,Ez,time] = MaxwellPNonCon2D(pinfo, Hx, Hy, Ez, FinalTime)

% function [Hx,Hy,Ez] = MaxwellPNonCon2D(pinfo, Hx, Hy, Ez, FinalTime)
% Purpose  : Integrate TM-mode Maxwell's until FinalTime starting with initial conditions Hx,Hy,Ez

Globals2D;
time = 0;

% Runge-Kutta residual storage
resHx = zeros(size(Hx)); resHy = resHx; resEz = resHx;

% compute time step size (taking into account variable polynomial order)
dt = 100;
for N=1:length(pinfo)
  dt = min(dt, 2./( N^2*max(pinfo(N).Fscale(:)/2)));
end

% outer time step loop
tstep = 1;
while (time<FinalTime)

   if(time+dt>FinalTime), dt = FinalTime-time; end

   for INTRK = 1:5
      % compute right hand side of TM-mode Maxwell's equations
      [rhsHx, rhsHy, rhsEz] = MaxwellPNonConRHS2D(pinfo, Hx,Hy,Ez);

      % initiate and increment Runge-Kutta residuals
      resHx = rk4a(INTRK)*resHx + dt*rhsHx;
      resHy = rk4a(INTRK)*resHy + dt*rhsHy;
      resEz = rk4a(INTRK)*resEz + dt*rhsEz;

      % update fields
      Hx = Hx+rk4b(INTRK)*resHx;
      Hy = Hy+rk4b(INTRK)*resHy;
      Ez = Ez+rk4b(INTRK)*resEz;
   end;

   % Increment time
   time = time+dt; tstep = tstep+1;
end
return


%% A Unit Test Class for mklJac
classdef mklJac_tests < matlab.unittest.TestCase

    properties
        absTol = 1e-8;
    end

    % Unit Tests
    methods (Test)

        %-- Valid Operation --%
        function scalarDiff(testCase)
            testCase.verifyEqual(1, mklJac(@(x) sin(x), 0), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(1, mklJac(@(x) sin(x), 0, 1), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(-1, mklJac(@(x) sin(x), pi), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(0, mklJac(@(x) cos(x), pi), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(0, mklJac(@(x) cos(x), -pi), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(-1, mklJac(@(x) cos(x), pi/2), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(1, mklJac(@(x) cos(x), -pi/2), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(2, mklJac(@(x) 2*x, 0), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(2, mklJac(@(x) 2*x, 1), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(2, mklJac(@(x) 2*x, 2), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(-2, mklJac(@(x) -2*x, 0), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(-2, mklJac(@(x) -2*x, 1), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(-2, mklJac(@(x) -2*x, 2), 'AbsTol', testCase.absTol);
        end

        function scalarDiffSweep(testCase)
            fun = @(x) 3*cos(x^2) + 0.5*sin(x/2);
            grad = @(x) cos(x/2)/4 - 6*x*sin(x^2);
            x = linspace(-pi,pi);
            for i = 1:length(x)
                testCase.verifyEqual(grad(x(i)), mklJac(fun, x(i)), 'AbsTol', testCase.absTol);
            end
        end

        function vectorDiff(testCase)
            testCase.verifyEqual(eye(3), mklJac(@(x) sin(x), zeros(3,1)), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(eye(6), mklJac(@(x) sin(x), zeros(6,1)), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(-eye(3), mklJac(@(x) sin(x), pi*ones(3,1)), 'AbsTol', testCase.absTol);
            testCase.verifyEqual(zeros(3), mklJac(@(x) sin(x), pi/2*ones(3,1)), 'AbsTol', testCase.absTol);
        end

        function vectorDiffSweep(testCase)
            fun = @(x) 3*cos(x(1)^2)*sin(x(2)) + 0.5*sin(x(2)/2);
            grad = @(x) [ -6*x(1)*sin(x(1)^2)*sin(x(2)), cos(x(2)/2)/4 + 3*cos(x(1)^2)*cos(x(2))];
            x1 = linspace(-pi,pi);
            x2 = linspace(pi,-pi);
            for i = 1:length(x1)
                testCase.verifyEqual(grad([x1(i);x2(i)]), mklJac(fun, [x1(i);x2(i)]), 'AbsTol', testCase.absTol);
            end
        end

        function vectorFunDiffSweep(testCase)
            fun = @(x) [100*(x(2)-x(1)^2); 1 - x(1)];
            grad = @(x) [-200*x(1) 100; -1 0];
            x = linspace(-1,1,10);
            for i = 1:length(x)
                for j = 1:length(x)
                    testCase.verifyEqual(grad([x(i);x(j)]), mklJac(fun, [x(i);x(j)]), 'AbsTol', testCase.absTol*10); %this is a hard one
                end
            end
        end

        function autoSizeIdentify(testCase)
            testCase.verifyEqual(1, numel(mklJac(@(x) sin(x), zeros(1,1))));
            testCase.verifyEqual(4, numel(mklJac(@(x) sin(x), zeros(2,1))));
            testCase.verifyEqual(9, numel(mklJac(@(x) sin(x), zeros(3,1))));
            testCase.verifyEqual(16, numel(mklJac(@(x) sin(x), zeros(4,1))));
        end

        %-- Input Args --%
        function inputArgs(testCase)
            testCase.verifyError(@() mklJac(@(x) sin(x)), 'OPTIMex:InputError');   % not enough args
            testCase.verifyError(@() mklJac(1, 1), 'OPTIMex:InputError');   % not fcn handle
            testCase.verifyError(@() mklJac(@(x) sin(x), int16(1)), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), 1i), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), [1 1; 1 1]), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, int16(1)), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, [1;1]), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 0), 'OPTIMex:InputError'); % wrong val
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 1e9), 'OPTIMex:InputError'); % wrong val
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 1, int16(1)), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 1, [1;1]), 'OPTIMex:InputError'); % wrong input type
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 1, 1e-18), 'OPTIMex:InputError'); % wrong val
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 1, 1.1), 'OPTIMex:InputError'); % wrong val
            testCase.verifyError(@() mklJac(@(x) sin(x), [1;1], 1), 'OPTIMex:DataError'); % wrong length
            testCase.verifyError(@() mklJac(@(x) sin(x), [1;1], 3), 'OPTIMex:DataError'); % wrong length
            testCase.verifyError(@() mklJac(@(x) sin(x), 1, 2), 'OPTIMex:DataError'); % wrong length (something odd about this ut)
        end
    end

end


classdef RMMEDA_F4 < PROBLEM
% <multi> <real> <large/none>
% Benchmark MOP for testing RM-MEDA

%------------------------------- Reference --------------------------------
% Q. Zhang, A. Zhou, and Y. Jin, RM-MEDA: A regularity model-based
% multiobjective estimation of distribution algorithm, IEEE Transactions on
% Evolutionary Computation, 2008, 12(1): 41-63.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        %% Default settings of the problem
        function Setting(obj)
            obj.M = 3;
            if isempty(obj.D); obj.D = 30; end
            obj.lower    = zeros(1,obj.D);
            obj.upper    = ones(1,obj.D);
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,X)
            g = sum((X(:,3:end)-repmat(X(:,1),1,size(X,2)-2)).^2,2);
            PopObj(:,1) = cos(pi/2*X(:,1)).*cos(pi/2*X(:,2)).*(1+g);
            PopObj(:,2) = cos(pi/2*X(:,1)).*sin(pi/2*X(:,2)).*(1+g);
            PopObj(:,3) = sin(pi/2*X(:,1)).*(1+g);
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            R = UniformPoint(N,3);
            R = R./repmat(sqrt(sum(R.^2,2)),1,3);
        end
        %% Generate the image of Pareto front
        function R = GetPF(obj)
            a = linspace(0,pi/2,10)';
            R = {sin(a)*cos(a'),sin(a)*sin(a'),cos(a)*ones(size(a'))};
        end
    end
end


function title = p14_title ( )

%*****************************************************************************80
%
%% P14_TITLE returns the title for problem 14.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 July 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, the title of the problem.
%
  title = 'sin ( exp(-x) + exp(-4x) )';

  return
end


function out = CO_Embed2_AngleTau(y,maxTau)
% CO_Embed2_AngleTau Angle autocorrelation in a 2-dimensional embedding space
%
% Investigates how the autocorrelation of angles between successive points in
% the two-dimensional time-series embedding change as tau varies from
% tau = 1, 2, ..., maxTau.
%
%---INPUTS:
% y, a column vector time series
% maxTau, the maximum time lag to consider

% ------------------------------------------------------------------------------
% Copyright (C) 2020, Ben D. Fulcher <ben.d.fulcher@gmail.com>,
% <http://www.benfulcher.com>
%
% If you use this code for your research, please cite the following two papers:
%
% (1) B.D. Fulcher and N.S. Jones, "hctsa: A Computational Framework for Automated
% Time-Series Phenotyping Using Massive Feature Extraction, Cell Systems 5: 527 (2017).
% DOI: 10.1016/j.cels.2017.10.001
%
% (2) B.D. Fulcher, M.A. Little, N.S. Jones, "Highly comparative time-series
% analysis: the empirical structure of time series and their methods",
% J. Roy. Soc. Interface 10(83) 20130048 (2013).
% DOI: 10.1098/rsif.2013.0048
%
% This function 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/>.
% ------------------------------------------------------------------------------

doPlot = false;
tauRange = (1:1:maxTau);
numTau = length(tauRange);

% Ensure y is a column vector
if size(y,2) > size(y,1);
	y = y';
end

stats_store = zeros(3,numTau);

for i = 1:numTau
	tau = tauRange(i);

	m = [y(1:end-tau), y(1+tau:end)];

	theta = diff(m(:,2))./diff(m(:,1));
	theta = atan(theta); % measured as deviation from the horizontal

	if isempty(theta)
		error('Time series (N=%u) too short for embedding',length(y));
	end

	stats_store(1,i) = CO_AutoCorr(theta,1,'Fourier');
	stats_store(2,i) = CO_AutoCorr(theta,2,'Fourier');
	stats_store(3,i) = CO_AutoCorr(theta,3,'Fourier');
end

if doPlot
    figure('color','w'); box('on');
    plot(stats_store');
end

% ------------------------------------------------------------------------------
% Compute lots of outputs statistics:
% ------------------------------------------------------------------------------
out.ac1_thetaac1 = CO_AutoCorr(stats_store(1,:),1,'Fourier');
out.ac1_thetaac2 = CO_AutoCorr(stats_store(2,:),1,'Fourier');
out.ac1_thetaac3 = CO_AutoCorr(stats_store(3,:),1,'Fourier');
out.mean_thetaac1 = mean(stats_store(1,:));
out.max_thetaac1 = max(stats_store(1,:));
out.min_thetaac1 = min(stats_store(1,:));
out.mean_thetaac2 = mean(stats_store(2,:));
out.max_thetaac2 = max(stats_store(2,:));
out.min_thetaac2 = min(stats_store(2,:));
out.mean_thetaac3 = mean(stats_store(3,:));
out.max_thetaac3 = max(stats_store(3,:));
out.min_thetaac3 = min(stats_store(3,:));
out.meanrat_thetaac12 = out.mean_thetaac1/out.mean_thetaac2;
out.diff_thetaac12 = sum(abs(stats_store(2,:)-stats_store(1,:)));

end


function lattice_print ( dim_num, m, z, title )

%*****************************************************************************80
%
%% LATTICE_PRINT prints the points in a lattice rule.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 November 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Ian Sloan, Stephen Joe,
%    Lattice Methods for Multiple Integration,
%    Oxford, 1994,
%    ISBN: 0198534728,
%    LC: QA311.S56
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer M, the number of points to use.
%
%    Input, integer Z(DIM_NUM), the generator vector.
%
%    Input, string TITLE, an optional title.
%
  if ( 0 < s_len_trim ( title ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, '%s\n', title );
  end

  fprintf ( 1, '\n' );

  for i = 0 : m - 1
    y(1:dim_num) = mod ( i * z(1:dim_num), m );
    fprintf ( 1, '%4d    ', i + 1 );
    for dim = 1 : dim_num
      fprintf ( 1, '%4d', y(dim) );
    end
    fprintf ( 1, '\n' );
  end

  return
end


function [ y, symm ] = cvx_s_symmetric( m, n, symm ) %#ok
%CVX_S_SYMMETRIC Symmetric matrices (lower triangle storage).
if m ~= n,
    error( 'Symmetric structure requires square matrices.' );
end
symm = false;
nsq = n * n;
ntr = 0.5 * ( nsq + n );
c  = 0 : n - 1;
c  = c( ones( 1, n ), : );
r  = c';
mn = min( r, c );
mx = max( r, c );
y  = mx + mn .* ( n - 0.5 * ( mn + 1 ) ) + 1;
y  = sparse( y( : ), 1 : nsq, 1, ntr, nsq );

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


function i4_log_10_test ( )

%*****************************************************************************80
%
%% I4_LOG_10_TEST tests I4_LOG_10.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 April 2009
%
%  Author:
%
%    John Burkardt
%
  n = 13;

  x = [ 0, 1, 2, 3, 9, 10, 11, 99, 101, -1, -2, -3, -9 ];

  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4_LOG_10_TEST\n' );
  fprintf ( 1, '  I4_LOG_10: whole part of log base 10,\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  X, I4_LOG_10\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n

    fprintf ( 1, '%6d  %12d\n', x(i), i4_log_10 ( x(i) ) );

  end

  return
end


function [colChar]=xlsColNum2Str(colNum)
%XLSCOLNUM2STR takes in an array of numbers and returns a cellular array
%of the same size with cell of corresponding Excel column names.
%
%For example:
%n=[1  10;
%   53 256]
%c=xlsColNum2Str(n);
%c={'A' , 'J';
%   'BA', 'IV'}
%Note: up to Excel 2003 the number of columns was limited to 256, as of
%Excel 2007 the number of columns has increased to 16,384 or 'XFD'
%This function is designed to take accept any integer so proper handling
%of the number of columns should be taken care of outside this function

    colChar=cell(size(colNum)); %blank cell array

    % find max number of characters (AA n=2)
    numOfChars=ceil(max(colNum)/26)-1;
    n=1;

    while numOfChars>=1
        numOfChars=ceil(numOfChars/26)-1;
        n=n+1;
    end

    remainder=num2cell(colNum);

    for s=n:-1:1
        if s>1
            %find limits
            % if n=2 then the columns go from AA to ZZ or 27 to 702
            L=sum(26.^(1:s-1))+1; % lower limit
            U=sum(26.^(1:s));   %upper limit
            %place current character to right of previous
            colChar(colNum>=L & colNum<=U) = ...
                cellfun(@(x,y) ([x char(ceil((y-(L-1))/26^(s-1))+64)]),...
                colChar(colNum>=L & colNum<=U),...      % x
                remainder(colNum>=L & colNum<=U),...    % y
                'UniformOutput',false);
            %calculate the remaining string
            %for example if last string was 'ABA' the 'A' was placed to the
            %right of the previous string and now 'BA' is remaining
            remainder(colNum>=L & colNum<=U)=...
                cellfun(@(x,y) (y-26^(s-1)*(double(x(end))-64)),...
                colChar(colNum>=L & colNum<=U),...
                remainder(colNum>=L & colNum<=U),'UniformOutput',false);
            colNum=cell2mat(remainder);
        else
             colChar=cellfun(@(x,y) ([x char(y+64)]),...
                 colChar,remainder,'UniformOutput',false);
        end
    end
end


function [disp_row, disp_col] = resp_newton(response, responsef, iterations, ky, kx, use_sz)

[max_resp_row, max_row] = max(response, [], 1);
[init_max_response, max_col] = max(max_resp_row, [], 2);
max_row_perm = permute(max_row, [2 3 1]);
col = max_col(:)';
row = max_row_perm(sub2ind(size(max_row_perm), col, 1:size(response,3)));

trans_row = mod(row - 1 + floor((use_sz(1)-1)/2), use_sz(1)) - floor((use_sz(1)-1)/2);
trans_col = mod(col - 1 + floor((use_sz(2)-1)/2), use_sz(2)) - floor((use_sz(2)-1)/2);
init_pos_y = permute(2*pi * trans_row / use_sz(1), [1 3 2]);
init_pos_x = permute(2*pi * trans_col / use_sz(2), [1 3 2]);
max_pos_y = init_pos_y;
max_pos_x = init_pos_x;

% pre-compute complex exponential
exp_iky = exp(bsxfun(@times, 1i * ky, max_pos_y));
exp_ikx = exp(bsxfun(@times, 1i * kx, max_pos_x));

% gradient_step_size = gradient_step_size / prod(use_sz);

ky2 = ky.*ky;
kx2 = kx.*kx;

iter = 1;
while iter <= iterations
    % Compute gradient
    ky_exp_ky = bsxfun(@times, ky, exp_iky);
    kx_exp_kx = bsxfun(@times, kx, exp_ikx);
    y_resp = mtimesx(exp_iky, responsef, 'speed');
    resp_x = mtimesx(responsef, exp_ikx, 'speed');
    grad_y = -imag(mtimesx(ky_exp_ky, resp_x, 'speed'));
    grad_x = -imag(mtimesx(y_resp, kx_exp_kx, 'speed'));
    ival = 1i * mtimesx(exp_iky, resp_x, 'speed');
    H_yy = real(-mtimesx(bsxfun(@times, ky2, exp_iky), resp_x, 'speed') + ival);
    H_xx = real(-mtimesx(y_resp, bsxfun(@times, kx2, exp_ikx), 'speed') + ival);
    H_xy = real(-mtimesx(ky_exp_ky, mtimesx(responsef, kx_exp_kx, 'speed'), 'speed'));
    det_H = H_yy .* H_xx - H_xy .* H_xy;

    % Compute new position using newtons method
    max_pos_y = max_pos_y - (H_xx .* grad_y - H_xy .* grad_x) ./ det_H;
    max_pos_x = max_pos_x - (H_yy .* grad_x - H_xy .* grad_y) ./ det_H;

    % Evaluate maximum
    exp_iky = exp(bsxfun(@times, 1i * ky, max_pos_y));
    exp_ikx = exp(bsxfun(@times, 1i * kx, max_pos_x));

    iter = iter + 1;
end
max_response = 1 / prod(use_sz) * real(mtimesx(mtimesx(exp_iky, responsef, 'speed'), exp_ikx, 'speed'));

% check for scales that have not increased in score
ind = max_response < init_max_response;
max_pos_y(ind) = init_pos_y(ind);
max_pos_x(ind) = init_pos_x(ind);
disp_row = (mod(max_pos_y(1,1,1) + pi, 2*pi) - pi) / (2*pi) * use_sz(1);
disp_col = (mod(max_pos_x(1,1,1) + pi, 2*pi) - pi) / (2*pi) * use_sz(2);
end


function SieveAnalysis5(Granulometria)
% _____________________________________________________
% See Contents.m
%  With this routine you can get the sand sieve analysis. Routine
% displays the computation of the particle-size distribution in different
% windows. Add you can get the main parameters of statistics analysis:
% percentiles, mean, standard deviation, kurtosis, etc.
% Syntax:
%              >> Granulometria[ %your data];
%              >> SieveAnalysis5(Granulometria)
% Update: 1. I've received a couples of emails, in which  some
%                people had a lot of problems with how to give the inputs;
%                for this reason, I decided to delete the GUI. Now, the
%                user only has to do, it's to create a variable with the
%                name "Granulometria" and inside this variable, you need to
%                write your data. First column, the sieve mesh (in mm) and
%                the second, the weights (in g). For example:
%                Granulometria = [4.0 0.88; 2.0 1.08; 1.0 1.49; 0.50 3.58; 0.25 11.50;
%                                                0.125 21.50; 0.0625 9.81; 0.0313 2.70];
%                2. I deleted an enormous bugs.
%
% Last modification : 03/21/09
% Author: PhD(c) Gabriel Ruiz
% This routine is provided "as is" without warranty of any kind.
% Please, you don't attribute it.
% If you'll detect any mistake or bug, may you communicate to me,
% please?
% v1.1.5
% Copyright 2006.
% _____________________________________________________
     clc;

    screen = get(0, 'screensize');
    if screen(1,3) == 1152 && screen(1,4) == 864
                 screen(1,3) = screen(1,3) - 128; screen(1,4) = screen(1,4) - 96;
        elseif screen(1,3) == 1280 && screen(1,4) == 768
                 screen(1,3) = screen(1,3) - 256;
        elseif screen(1,3) == 1280 && screen(1,4) == 800
                 screen(1,3) = screen(1,3) - 256; screen(1,4) = screen(1,4) - 32;
        elseif screen(1,3) == 1280 && screen(1,4) == 960
                 screen(1,3) = screen(1,3) - 256; screen(1,4) = screen(1,4) - 192;
        elseif screen(1,3) == 1280 && screen(1,4) == 1024
                 screen(1,3) = screen(1,3) - 256; screen(1,4) = screen(1,4) - 256;
        elseif screen(1,3) == 1400 && screen(1,4) == 1050
                 screen(1,3) = screen(1,3) - 376; screen(1,4) = screen(1,4) - 282;
        elseif screen(1,3) == 1600 && screen(1,4) == 900
                 screen(1,3) = screen(1,3) - 576; screen(1,4) = screen(1,4) - 132;
        elseif screen(1,3) == 1600 && screen(1,4) == 1200
                 screen(1,3) = screen(1,3) - 576; screen(1,4) = screen(1,4) - 432;
    end
    vpan = screen(1,4)-35; hpan = screen(1,3);
    colores = [1 1 0.85 ]; colortexto = [0.50 0.25 0.25];
    WB = Granulometria(:,2);
    milimeters = Granulometria(:,1);
    r = length(milimeters);

        for i = 1 : r
                Worksheet_sieve_data{1,1}(i) = WB(i);
        end
        Sum_Col_1 = sum( Worksheet_sieve_data{1,1} );
        for i = 1: r
                Worksheet_sieve_data{1,2}(i) = ( Worksheet_sieve_data{1,1}(i) / Sum_Col_1) * 100;
                if i == 1
                        Worksheet_sieve_data{1,3}(i) = Worksheet_sieve_data{1,2}(i);
                        Worksheet_sieve_data{1,4}(i) = 100;
                else
                        Worksheet_sieve_data{1,3}(i) = Worksheet_sieve_data{1,2}(i) + Worksheet_sieve_data{1,3}(i-1);
                        Worksheet_sieve_data{1,4}(i) = Worksheet_sieve_data{1,4}(1) - Worksheet_sieve_data{1,3}(i);
                end
        end

        diamX = Worksheet_sieve_data{1,4} ;
        diamX = diamX';
        diamY = milimeters;
        D_5 = interp1(diamX, diamY, 5, 'pchip');
        D_10 = interp1(diamX, diamY, 10, 'pchip');
        D_16 = interp1(diamX, diamY, 16, 'pchip');
        D_25 = interp1(diamX, diamY, 25, 'pchip');
        D_30 = interp1(diamX, diamY, 30, 'pchip');
        D_50 = interp1(diamX, diamY, 50, 'pchip');
        D_60 = interp1(diamX, diamY, 60, 'pchip');
        D_75 = interp1(diamX, diamY, 75, 'pchip');
        D_84 = interp1(diamX, diamY, 84, 'pchip');
        D_95 = interp1(diamX, diamY, 95, 'pchip');

        resulchar.d_5 = num2str(D_5);
        resulchar.d_10 = num2str(D_10);
        resulchar.d_16 = num2str(D_16);
        resulchar.d_25 = num2str(D_25);
        resulchar.d_30 = num2str(D_30);
        resulchar.d_50 = num2str(D_50);
        resulchar.d_60 = num2str(D_60);
        resulchar.d_75 = num2str(D_75);
        resulchar.d_84 = num2str(D_84);
        resulchar.d_95 = num2str(D_95);

        D_5phi = -log(D_5) / log(2);      %Matlab has the function log2, but I prefer to use this form.
        D_10phi = -log(D_10) / log(2);
        D_16phi = -log(D_16) / log(2);
        D_25phi = -log(D_25) / log(2);
        D_30phi = -log(D_30) / log(2);
        D_50phi = -log(D_50) / log(2);
        D_60phi = -log(D_60) / log(2);
        D_75phi = -log(D_75) / log(2);
        D_84phi = -log(D_84) / log(2);
        D_95phi = -log(D_95) / log(2);

        Mean_grain_size = ( D_16phi + D_50phi + D_84phi ) / 3;
        Mean_grain_size_mm = 2 ^ -(Mean_grain_size);
        resulchar.MeanGS = num2str(Mean_grain_size_mm);

        if Mean_grain_size_mm <= 0.075
                    resulchar.ASTM = 'Fine Soil';
            elseif Mean_grain_size_mm >= 0.076 && Mean_grain_size_mm <= 0.425
                    resulchar.ASTM = 'Fine sand';
            elseif Mean_grain_size_mm >= 0.426 && Mean_grain_size_mm <= 2
                    resulchar.ASTM = 'Medium sand';
            elseif Mean_grain_size_mm >= 2.1 && Mean_grain_size_mm <= 4.75
                    resulchar.ASTM = 'Coarse sand';
            elseif Mean_grain_size_mm >= 4.76 && Mean_grain_size_mm <= 19
                    resulchar.ASTM = 'Fine gravel';
            elseif Mean_grain_size_mm >= 19.1 && Mean_grain_size_mm <= 75
                    resulchar.ASTM = 'Coarse gravel';
        end

        if Mean_grain_size_mm >= 0.0625 && Mean_grain_size_mm <= 0.125
                    resulchar.Wentworth = 'Very fine sand';
            elseif Mean_grain_size_mm >= 0.126 && Mean_grain_size_mm <= 0.250
                    resulchar.Wentworth = 'Fine sand';
            elseif Mean_grain_size_mm >= 0.251 && Mean_grain_size_mm <= 0.50
                    resulchar.Wentworth = 'Medium sand';
            elseif Mean_grain_size_mm >= 0.51 && Mean_grain_size_mm <= 1
                    resulchar.Wentworth = 'Coarse sand';
            elseif Mean_grain_size_mm >= 1.01 && Mean_grain_size_mm <= 2
                    resulchar.Wentworth = 'Very coarse sand';
            elseif Mean_grain_size_mm >= 2.01 && Mean_grain_size_mm <= 4.76
                    resulchar.Wentworth = 'Granule';
            elseif Mean_grain_size_mm >= 4.77 && Mean_grain_size_mm <= 8
                    resulchar.Wentworth = 'Small pebble';
            elseif Mean_grain_size_mm >= 8.01 && Mean_grain_size_mm <= 16
                    resulchar.Wentworth = 'Medium pebble';
            elseif Mean_grain_size_mm >= 16.01 && Mean_grain_size_mm <= 19.03
                    resulchar.Wentworth = 'Large pebble';
        end

        gravel = zeros(r,1);
        for i = 1 : r
            if milimeters(i,1) <= 75 && milimeters(i,1) >= 4.75
                gravel(i,1) = Worksheet_sieve_data{1,2}(i);
            end
        end
        Gravel = sum(gravel(:,1));
        resulchar.Grava = num2str(Gravel);

        sand = zeros(r,1);
        for i = 1 : r
            if milimeters(i,1) <= 4.74 && milimeters(i,1) >= 0.075
                    sand(i,1) = Worksheet_sieve_data{1,2}(i);
            end
        end
        Sand = sum(sand(:,1));
        resulchar.arena = num2str(Sand);

         fine = zeros(r,1);
        for i = 1 : r
            if milimeters(i,1) <= 0.074
                    fine(i,1) = Worksheet_sieve_data{1,2}(i);
            end
        end
        Fine = sum(fine(:,1));
        resulchar.fino =num2str(Fine);
        Muestrapor = [ Gravel Sand Fine ];

        Standard_Deviation = ( ( D_84phi - D_16phi ) / 4 ) + ( ( D_95phi - D_5phi ) / 6 );   % E.3.
        Standard_Deviation_mm = 2 ^ -(Standard_Deviation);
        resulchar.SDe = num2str(Standard_Deviation_mm);
        if Standard_Deviation < 0.34
                    resulchar.SD = 'Very well sorted';
            elseif Standard_Deviation >= 0.35 && Standard_Deviation <= 0.49
                    resulchar.SD = 'Well sorted';
            elseif Standard_Deviation >= 0.50 && Standard_Deviation <= 0.71
                    resulchar.SD = 'Moderately well sorted';
            elseif Standard_Deviation >= 0.72 && Standard_Deviation <= 0.99
                    resulchar.SD = 'Moderately sorted';
            elseif Standard_Deviation >= 1.00 && Standard_Deviation <= 1.99
                    resulchar.SD = 'Poorly sorted';
            elseif Standard_Deviation >= 2.00 && Standard_Deviation <= 3.99
                    resulchar.SD = 'Very poorly sorted';
            elseif Standard_Deviation >= 4.00
                    resulchar.SD = 'Extremely poorly sorted';
        end

        Skewness =  ( ( D_84phi + D_16phi - ( 2 * D_50phi ) ) / ( 2 * ( D_84phi - D_16phi ) ) ) + ...
                              ( ( D_95phi + D_5phi - ( 2 * D_50phi ) ) / ( 2 * ( D_95phi - D_5phi ) ) );
        Skewness_mm = 2 ^ -(Skewness);
        resulchar.S_ke = num2str(Skewness_mm);
        if Skewness < -0.29
                    resulchar.Sk = 'Very coarse skewed';
            elseif Skewness >= -0.30 && Skewness <= -0.09
                    resulchar.Sk = 'Coarse skewed';
            elseif Skewness >= -0.10 && Skewness <= 0.09
                    resulchar.Sk = 'Near symmetrical';
            elseif Skewness >= 0.10 && Skewness <= 0.29
                    resulchar.Sk = 'Fine skewed';
            elseif Skewness >= 0.30
                    resulchar.Sk = 'Very fine skewed';
        end

        Kurtosis = ( D_95phi - D_5phi ) / ( 2.44 * ( D_75phi - D_25phi ) );
        Kurtosis_mm = 2 ^ -(Kurtosis);
        resulchar.K_ur = num2str(Kurtosis_mm);
         if Kurtosis < 0.64
                    resulchar.kurt = 'Very platykurtic (flat)';
            elseif Kurtosis >= 0.65 && Kurtosis <= 0.89
                    resulchar.kurt = 'Platykurtic';
            elseif Kurtosis >= 0.90 && Kurtosis <= 1.10
                    resulchar.kurt = 'Mesokurtic ';
            elseif Kurtosis >= 1.11 && Kurtosis <= 1.49
                    resulchar.kurt = 'Leptokurtic (peaked)';
            elseif Kurtosis >= 1.50 && Kurtosis <= 2.99
                    resulchar.kurt = 'Very leptokurtic';
            elseif Kurtosis >= 3.00
                    resulchar.kurt = 'Extremely leptokurtic';
        end

        Cc_Dispersal = D_30 ^ 2 / ( D_10 * D_60 ) ;
        resulchar.CC = num2str(Cc_Dispersal);
        Cu_Hazen_uniformity = D_60 / D_10;
        resulchar.Cu =num2str(Cu_Hazen_uniformity);
        if Cu_Hazen_uniformity >= 6 && ( ( Cc_Dispersal >= 1 ) && ( Cc_Dispersal <= 3 ) )
                    resulchar.SUCS = 'SW';
        else
                    resulchar.SUCS = 'SP';
        end

        figure(3);
        set(figure(3), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , ...
                'Name' , '1.Sieve Analysis - Histogram' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [  hpan-880   vpan-440   hpan-664   vpan-464 ] );
        histo_h =bar(milimeters,Worksheet_sieve_data{1,2}, 'group');
        colormap hsv;
        xlabel('Grain Size in mm' , 'Fontsize' , 7);
        ylabel('Percent Finer by Weight (%)' , 'Fontsize' , 7);
        title('Histogram' , 'Color' , 'r' , 'FontWeight' , 'Bold' , 'Fontsize' , 8);
        set(histo_h,  'FaceColor', 'r');
        set(gca,  'Xgrid' , 'on' , 'Ygrid' , 'on' , 'Xcolor' , [0 0 0.37] , 'Ycolor' , [0 0 0.37] , 'Box' , 'off' , ...
                   'FontWeight' , 'Bold' , 'FontSize' , 7 , 'FontAngle' , 'Oblique' , 'XMinorTick' , 'on' , 'YMinorTick' , 'on');

        figure(4);
        set(figure(4), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [  hpan-859   vpan-469  hpan-664  vpan-464 ] , ...
                'name' , '2.Sieve Analysis - Frecuency Curve' );
        FCruve_h = plot(milimeters, Worksheet_sieve_data{1,2}, '-', 'Color' , 'b' , 'Linewidth' , 1.5);
        xlabel('Grain Size in mm' , 'Fontsize' , 7);
        ylabel('Percent Finer by Weight (%)' , 'Fontsize' , 7);
        title('Frecuency Curve' , 'Color' , 'b' , 'FontWeight' , 'Bold' , 'Fontsize' , 8);
        set(gca,  'Xgrid' , 'on' , 'Ygrid' , 'on' , 'Xcolor' , [0 0 0.37] , 'Ycolor' , [0 0 0.37] , 'Box' , 'off' , ...
                   'FontWeight' , 'Bold' , 'FontSize' , 7 , 'FontAngle' , 'Oblique' , 'XMinorTick' , 'on' , 'YMinorTick' , 'on');

        figure(5);
        set(figure(5), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [hpan-838  vpan-499  hpan-664  vpan-464] , ...
                'name' , '3. Sieve Analysis - Cumulative Arithmetic Curve' );
        ACurve_h = plot(milimeters, Worksheet_sieve_data{1,3}, '-', 'Color' , [0 0.5 0] , 'Linewidth' , 1.5);
        xlabel('Grain Size in mm' , 'Fontsize' , 7);
        ylabel('Percent Finer by Weight (%)' , 'Fontsize' , 7);
        title('Frecuency Cumulative  Curve' , 'Color' , [0 0.5 0] , 'FontWeight' , 'Bold' , 'Fontsize' , 8);
        set(gca,  'Xgrid' , 'on' , 'Ygrid' , 'on' , 'Xcolor' , [0 0 0.37] , 'Ycolor' , [0 0 0.37] , 'Box' , 'off' , ...
                   'FontWeight' , 'Bold' , 'FontSize' , 7 , 'FontAngle' , 'Oblique' , 'XMinorTick' , 'on' , 'YMinorTick' , 'on');

        figure(6);
        set(figure(6), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [ hpan-816   vpan-529   hpan-664  vpan-464] , ...
                'name' , '4. Sieve Analysis - Cumulative Probability Arithmetic Curve' );
        CCurve_h = plot(milimeters, Worksheet_sieve_data{1,4}, '-','Color' , [1 0.5 0] , 'Linewidth' , 1.5);
        xlabel('Grain Size in mm', 'Fontsize' , 7);
        ylabel('Probability Finer by Weight (%)' , 'Fontsize' , 7);
        title('Cumulative Probability Curve ' , 'Color' , [1 0.5 0] , 'FontWeight' , 'Bold' , 'Fontsize' , 8);
        set(gca,  'Xgrid' , 'on' , 'Ygrid' , 'on' , 'Xcolor' , [0 0 0.37] , 'Ycolor' , [0 0 0.37] , 'Box' , 'off' , ...
                   'FontWeight' , 'Bold' , 'FontSize' , 7 , 'FontAngle' , 'Oblique' , 'XMinorTick' , 'on' , 'YMinorTick' , 'on');

        figure(7);
        set(figure(7), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [   hpan-778   vpan-587    hpan-348    vpan-464  ] , ...
                 'name' , '6. Sieve Analysis - Cumulative Probability Semi-Log Curve'  );
        CCurvesl_h = semilogx(milimeters, Worksheet_sieve_data{1,4}, '-o','Color' , [0 0 0.5] , ...
                                      'Linewidth' , 2.5, 'MarkerFaceColor' , [ 0 0 0.5 ] , 'MarkerSize' , 2, ...
                                      'MarkerEdgeColor' , [ 0 0.5 0.5] );
        axis tight;
        xlabel('Grain Size in mm', 'Fontsize' , 7);
        ylabel('Probability Finer by Weight (%)' , 'Fontsize' , 7);
        title('Cumulative Probability Curve ' , 'Color' , [0 0 0.5] , 'FontWeight' , 'Bold' , 'Fontsize' , 8);
        set(gca,  'Xgrid' , 'on' , 'Ygrid' , 'on' , 'Xcolor' , [0 0 0.37] , 'Ycolor' , [0 0 0.37] , 'Box' , 'off' , 'XDir' , 'normal' , ...
                   'FontWeight' , 'Bold' , 'FontSize' , 7 , 'FontAngle' , 'Oblique' , 'XMinorTick' , 'on' , 'YMinorTick' , 'on', ...
                   'Xlim' , [0.01 10]  , 'XTickLabel', { '0.01' ; '0.1' ; '1' ;  '10' } );
        dimark = [0.074 4.76];
        hold on;
        escalY = get(gca,'YLim');
        escalY = [ 0 escalY(1,2) ];
        lenmark = length(dimark);
        xmark = reshape([dimark;dimark;ones(1,lenmark)*nan;],lenmark*3,1);
        ymark = repmat([escalY nan],1,lenmark);
        plot(xmark,ymark, 'r', 'LineWidth', 2 );
        punto07 = patch(D_50 , 50 , [1 0 0] );
        punto08 = patch(0.01, 50 ,  [1 0 0] );
        punto09 = patch(D_50 , 0.01 , [1 0 0]);
         l4 = line('Xdata' , [D_50 D_50] , 'Ydata' , [0 50] , 'Color' ,  [0.75 0.75 0.75] , ...
                        'Linestyle' , '-' , 'Linewidth' , 2 ) ;
         l5 = line('Xdata' , [0.01 D_50] , 'Ydata' , [50 50] , 'Color' ,  [0.75 0.75 0.75] , ...
                        'Linestyle' , '-' , 'Linewidth' , 2 );
        set(punto07, 'marker' , 'o' , 'MarkerEdgeColor', 'r' , 'MarkerFaceColor', 'r' , ...
                 'MarkerSize' , 2);
        set(punto08, 'marker' , 'o' , 'MarkerEdgeColor', 'r' , 'MarkerFaceColor', 'r' , ...
                 'MarkerSize' , 2);
        set(punto09, 'marker' , 'o' , 'MarkerEdgeColor', 'r' , 'MarkerFaceColor', 'r', ...
                 'MarkerSize' , 2);
        td50 = text(D_50+.005 , 3, num2str(D_50)); set(td50, 'FontSize' , 8 , ...
                            'FontAngle' , 'Normal' , 'FontWeight' , 'Bold' );
        tfinos = text(0.011 , 95, 'Fine'); set(tfinos, 'FontSize' , 8 , 'FontWeight' , 'Bold');
        tsand = text(0.085 , 95, 'Sand'); set(tsand, 'FontSize' , 8 , 'FontWeight' , 'Bold' );
        tgrav = text(5 , 95, 'Gravel'); set(tgrav, 'FontSize' , 8 , 'FontWeight' , 'Bold' );

        figure(8);
        set(figure(8), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [   hpan-796   vpan-558    hpan-664  vpan-464  ] , ...
                'name' , '5. Sieve Analysis - Cumulative Probability Logarithmic Curve' );
        CCurvel_h = loglog(milimeters, Worksheet_sieve_data{1,4}, '-','Color' , [0.5 0 0.5] , 'Linewidth' , 1.5);
        xlabel('Grain Size in mm' ,'Fontsize' , 7);
        ylabel('Probability Finer by Weight (%)', 'Fontsize' , 7);
        title('Cumulative Probability Curve ' , 'Color' , [0.5 0 0.5] , 'FontWeight' , 'Bold' , 'Fontsize' , 8);
        set(gca,  'Xgrid' , 'on' , 'Ygrid' , 'on' , 'Xcolor' , [0 0 0.37] , 'Ycolor' , [0 0 0.37] , 'Box' , 'off' , ...
                   'FontWeight' , 'Bold' , 'FontSize' , 7 , 'FontAngle' , 'Oblique' , 'XMinorTick' , 'on' , 'YMinorTick' , 'on'); clc;

        figure(9);
        set(figure(9), 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [  hpan-757   vpan-616    hpan-664  vpan-464  ] , ...
                'name' , '7. Sieve Analysis - % Percent of Sand'  );
        if Muestrapor(1,1) == 0 && Muestrapor(1,2) ~= 0 && Muestrapor(1,3) ~= 0
                    hotcake(1,1) =Muestrapor(1,2);
                    hotcake(1,2) =Muestrapor(1,3);
                    explode = [ 0 1 ];
                    piecg = pie(hotcake, explode);
                    hdlleg = legend('Sand', 'Fine', -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
                    set(piecg(1,4), 'FontUnits', 'pixels', 'FontSize' , 10);
         elseif Muestrapor(1,1) ~= 0 && Muestrapor(1,2) ~= 0 && Muestrapor(1,3) == 0
                    hotcake(1,1) =Muestrapor(1,1);
                    hotcake(1,2) =Muestrapor(1,2);
                    explode = [ 0 1 ];
                    piecg = pie(hotcake, explode);
                    hdlleg = legend('Gravel' , 'Sand',  -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
                    set(piecg(1,4), 'FontUnits', 'pixels', 'FontSize' , 10);
        elseif Muestrapor(1,1) ~= 0 && Muestrapor(1,2) ~= 0 && Muestrapor(1,3) ~= 0
                    explode = [ 0 1 0 ];
                    piecg = pie(Muestrapor, explode);
                    hdlleg = legend('Gravel' , 'Sand', 'Fine', -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
                    set(piecg(1,4), 'FontUnits', 'pixels', 'FontSize' , 10);
                    set(piecg(1,6), 'FontUnits', 'pixels', 'FontSize' , 10);
        elseif Muestrapor(1,1) ~= 0 && Muestrapor(1,2) == 0 && Muestrapor(1,3) ~= 0
                    hotcake(1,1) = Muestrapor(1,1);
                    hotcake(1,2) = Muestrapor(1,3);
                    explode = [ 0 1 ];
                    piecg = pie(hotcake, explode);
                    hdlleg = legend('Gravel' , 'Fine',  -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
                    set(piecg(1,4), 'FontUnits', 'pixels', 'FontSize' , 10);
        elseif Muestrapor(1,1) ~= 0 && Muestrapor(1,2) == 0 && Muestrapor(1,3) == 0
                    hotcake = Muestrapor(1,1) ;
                    piecg = pie(hotcake);
                    hdlleg = legend('Gravel' , -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
        elseif Muestrapor(1,1) == 0 && Muestrapor(1,2) ~= 0  && Muestrapor(1,3) == 0
                    hotcake = Muestrapor(1,2) ;
                    piecg = pie(hotcake);
                    hdlleg = legend('Sand' , -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
         elseif Muestrapor(1,1) == 0 && Muestrapor(1,2) == 0 && Muestrapor(1,3) ~= 0
                    hotcake = Muestrapor(1,3) ;
                    piecg = pie(hotcake);
                    hdlleg = legend('Fine' , -1);
                    set(piecg(1,2), 'FontUnits', 'pixels', 'FontSize' , 10);
        end
        set(hdlleg, 'Color' , [ 0.93 0.91 0.85 ], 'Box', 'on'); clc;

        result = figure(11);
        set(result, 'Units' , 'Pixels' , 'NumberTitle' , 'Off' , 'Resize' , 'on' , 'Color' , [0.93 0.91 0.85] , ...
                'Position' , [   10+hpan/3+hpan-686  35   hpan-690 (vpan/3)*2-50] , ...
                'name' , '8. Sieve Analysis - Results' );
         P4 = 12;
        uicontrol(result, 'Style' , 'Text' , 'String', 'The main results of sieve analysis were:' , 'Unit' , 'Pixels' , 'Position' , [0 418 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left' );
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_5 (mm) = ' , resulchar.d_5  ] , 'Unit' , 'Pixels' , 'Position' , [0 405 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_10 (mm) = ' , resulchar.d_10  ] , 'Unit' , 'Pixels' , 'Position' , [0 392 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_16 (mm) = ' , resulchar.d_16  ] , 'Unit' , 'Pixels' , 'Position' , [0 379 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_30 (mm) = ' , resulchar.d_30  ] , 'Unit' , 'Pixels' , 'Position' , [0 366 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_50 (mm) = ' , resulchar.d_50  ] , 'Unit' , 'Pixels' , 'Position' , [0 353 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_60 (mm) = ' , resulchar.d_60  ] , 'Unit' , 'Pixels' , 'Position' , [0 340 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_75 (mm) = ' , resulchar.d_75  ] , 'Unit' , 'Pixels' , 'Position' , [0 327 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_84 (mm) = ' , resulchar.d_84  ] , 'Unit' , 'Pixels' , 'Position' , [0 314 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85], 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['D_95 (mm) = ' , resulchar.d_95  ] , 'Unit' , 'Pixels' , 'Position' , [0 301 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Mean Grain Size  (mm) = ' , resulchar.MeanGS  ] , 'Unit' , 'Pixels' , 'Position' , [0 288 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Standard Deviation ' , resulchar.SDe  ] , 'Unit' , 'Pixels' , 'Position' , [0 273 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Skewness = ' , resulchar.S_ke  ] , 'Unit' , 'Pixels' , 'Position' , [0 260 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Kurtosis = ' , resulchar.K_ur  ] , 'Unit' , 'Pixels' , 'Position' , [0 247 200 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Coeficient of uniformity (Cc) = ' , resulchar.CC  ] , 'Unit' , 'Pixels' , 'Position' , [0 236 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Coeficient of curvature (Cu) = ' , resulchar.Cu  ] , 'Unit' , 'Pixels' , 'Position' , [0 223 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Standard Deviation Classification = ' , resulchar.SD  ] , 'Unit' , 'Pixels' , 'Position' , [0 210 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Skewness Classification = ' , resulchar.Sk  ] , 'Unit' , 'Pixels' , 'Position' , [0 197 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Kurtosis Classification = ' , resulchar.kurt  ] , 'Unit' , 'Pixels' , 'Position' , [0 184 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['ASTM Classification = ' , resulchar.ASTM  ] , 'Unit' , 'Pixels' , 'Position' , [0 169 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['% of Gravel = ' , resulchar.Grava  ] , 'Unit' , 'Pixels' , 'Position' , [0 158 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['% of Sand = ' , resulchar.arena  ] , 'Unit' , 'Pixels' , 'Position' , [0 145 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['% of Fine = ' , resulchar.fino  ] , 'Unit' , 'Pixels' , 'Position' , [0 132 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['Wentworth classification = ' , resulchar.Wentworth  ] , 'Unit' , 'Pixels' , 'Position' , [0 117 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');
        uicontrol(result, 'Style' , 'Text' , 'String', ['USCS classification = ' , resulchar.SUCS  ] , 'Unit' , 'Pixels' , 'Position' , [0 103 300 P4] , ...
                                   'BackGroundColor' , [0.93 0.91 0.85] , 'FontWeight' , 'Bold', 'ForegroundColor' , [0.5 0 0 ] , 'HorizontalAlignment', 'left');


% This is material illustrating the methods from the book
% Financial Modelling  - Theory, Implementation and Practice with Matlab
% source
% Wiley Finance Series
% ISBN 978-0-470-74489-5
%
% Date: 02.05.2012
%
% Authors:  Joerg Kienitz
%           Daniel Wetterau
%
% Please send comments, suggestions, bugs, code etc. to
% kienitzwetterau_FinModelling@gmx.de
%
% (C) Joerg Kienitz, Daniel Wetterau
%
% Since this piece of code is distributed via the mathworks file-exchange
% it is covered by the BSD license
%
% This code is being provided solely for information and general
% illustrative purposes. The authors will not be responsible for the
% consequences of reliance upon using the code or for numbers produced
% from using the code.

function [lower, upper] = UpperBound3(S, g, df, B, f, Nr, NSim, NSSim, ...
    getpaths, payoff)
% method from Broadie for computing upper bounds, see Chapter 8

iVec = 1:NSSim;

v = g(:,end);   % start for backward induction
c = zeros(NSim,Nr-1);   % continuation value

% backward induction and regression from t_{Nr-1} up to t_1
for i = Nr-1:-1:1
        index = find(g(:,i) > 0); % all ITM paths
        s = S(index,i+1);         % values of S at given time point
        v = v * df(i+1);          % option value at t_i

        Acell = B(s);             % evaluate basis function in cell array B
        A = cell2mat(Acell{:,:}); % convert to matrix

        c(index,i) = A*f(:,i);                  % continuation value

        exercise = g(index,i) >= c(index,i);    % early exercise
        v(index(exercise)) = g(index(exercise),i);
end

lower = mean(v * df(1));    % final option value

% Computing the martingale numerically, martingale = pi

L = zeros(NSim,1); %erster Teil von delta_i vgl. Formel (6.6)
expectation = zeros(NSim,Nr); %zweiter Teil von delta_i vgl. Formel (6.6)
expectation(:,1) = lower * ones(NSim,1);

for i=1:1:Nr-1
    for j=1:NSim
        expectation(j,i+1) = subsimulation(S(j,i+1), df, B, NSSim, Nr-i,...
            f(:,i:end), iVec(1:NSSim), getpaths, payoff) * prod(df(1:i));
    end
end

pi = zeros(NSim,Nr+1); % stores the values of the constructed martingale

% first time step and last are different
i_exercise = g(:,1) >= c(:,1) & c(:,1) > 0; % exercise in this case

L(i_exercise) = g(i_exercise, 1) * prod(df(1:1));
L(~i_exercise) = expectation(~i_exercise,2);

pi(:,2) = pi(:,1) + L - expectation(:,1);

for i=2:1:Nr-1
    % exercise in this case if not already exercised
    i_exercise = g(:,i) >= c(:,i) & c(:,i) > 0 & ~i_exercise;

    L(i_exercise) = g(i_exercise, i) * prod(df(1:i));
    L(~i_exercise) = expectation(~i_exercise,i+1);

    pi(:,i+1) = pi(:,i) + L - expectation(:,i);
end
% finally exercise if in the money and not already exercised
i_exercise = g(:,Nr) > 0 & ~i_exercise;

pi(i_exercise,Nr+1) = pi(i_exercise,Nr) + g(i_exercise,Nr)* prod(df(1:Nr));
pi(~i_exercise,Nr+1) = pi(~i_exercise,Nr);

% upper bound using the martingale pi

maximum = zeros(NSim,1);

for j=1:1:NSim
    maximum(j) = max(g(j,:) - pi(j,2:end)); %vgl. Formel (6.5)
end
upper = mean(maximum);

end

function y = subsimulation(S0, df, B, NSim, Nr, beta, iVec, gp,payoff)
    S2 = gp(S0,NSim,Nr); S2 = S2(:,2:end);   % paths
    g2 = payoff(S2);                         % payoff

    exercise = Nr * ones(NSim,1);            % exercise per path
    for i=1:1:Nr-1
        i_nexercised = exercise == Nr;
        I_nexercise = iVec(i_nexercised);

        s = S2(i_nexercised,i);
        Acell = B(s);
        A = cell2mat(Acell{:,:});
        c = A * beta(:,i);

        i_exercise = g2(i_nexercised,i) >= c & g2(i_nexercised,i) > 0;
        exercise(I_nexercise(i_exercise)) = i;
    end
    summe=0;
    for j=1:1:NSim
        summe = summe + g2(j,exercise(j)) * prod(df(1:exercise(j)));
    end
    y = summe / NSim;                         % MC value from subsimulation
end


% NTF | NTD-HALS | Non-negative Tucker Decomposition solved by Hierarchical ALS  (Zhou et al. 2012)
% process_video('NTF', 'NTD-HALS', 'dataset/demo.avi', 'output/demo_NTD-HALS.avi');

alg_path_aux = fullfile(lrs_conf.ntf_path,'lraNTD');
addpath(genpath(alg_path_aux));

R = [size(T,1) size(T,2) 2];
opts = struct('NumOfComp',R,'nlssolver','hals','maxiter',100,...
  'maxiniter',20,'tdalgFile','call_tucker_als_opts.mat');

T_hat = lraNTD_ANLS(T, opts);

L = double(tensor(T_hat));
S = double(T) - L;

rmpath(genpath(alg_path_aux));