function ierror = edge_check ( n_node, n_edge, t )

%*****************************************************************************80
%
%% EDGE_CHECK checks a graph stored by edges.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer  N_NODE, the number of nodes in the graph.
%    N_NODE must be positive.
%
%    Input, integer N_EDGE, the number of edges in the graph.
%    N_EDGE must be positive.
%
%    Input, integer T(2,N_EDGE), describes the edges of the tree
%    as pairs of nodes.
%
%    Output, integer IERROR, error flag.
%    -1, N_NODE is not positive.
%    -2, N_EDGE is not positive.
%    0, no error.
%    I, edge T(1,I), T(2,I) is illegal.
%
  ierror = 0;

  if ( n_node < 1 )
    ierror = -1;
    return
  end

  if ( n_edge < 1 )
    ierror = -2;
    return
  end
%
%  Every edge must join two legal nodes.
%
  for i = 1 : 2
    for j = 1 : n_edge
      if ( t(i,j) < 1 || n_node < t(i,j) )
        ierror = i;
        return
      end
    end
  end
%
%  Every edge must join distinct nodes.
%
  for j = 1 : n_edge
    if ( t(1,j) == t(2,j) )
      ierror = i;
      return
    end
  end
%
%  Every edge must be distinct.
%
  for j = 1 : n_edge - 1
    for j2 = j + 1 : n_edge
      if ( t(1,j) == t(1,j2) && t(2,j) == t(2,j2) )
        ierror = j2;
        return
      elseif ( t(1,j) == t(2,j2) && t(2,j) == t(1,j2) )
        ierror = j2;
        return
      end
    end
  end

  return
end


function edgenb=edgeneighbors(t,opt)
%
% edgenb=edgeneighbors(t,opt)
%
% to find neighboring triangular elements in a triangule surface
%
% author: Qianqian Fang, <q.fang at neu.edu>
%
% input:
%     t: a triangular surface element list, 3 columns of integers
%     opt: if opt='general', return the edge neighbors for a general
%          triangular surface: each edge can be shared by more than 2
%          triangles; if ignored, we assume all triangles are shared by no
%          more than 2 triangles.
%
% output:
%     edgenb: if opt is not supplied, edgenb is a size(t,1) by 3 array with
%     each element being the triangle ID of the edge neighbor of that
%     triangle. For each row, the order of the neighbors is listed as those
%     sharing edges [1 2], [2 3] and [3 1] between the triangle nodes.
%
%     when opt='general', edgenb is a cell array with a length of size(t).
%     each member of the cell array is a list of edge neighbors (the order
%     is not defined).
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

edges=[t(:,[1,2]);
       t(:,[2,3]);
       t(:,[3 1])];
edges=sort(edges,2);
[foo,ix,jx]=unique(edges,'rows');

if(nargin==2)
  if(strcmp(opt,'general'))
        ne=size(t,1);
        edgenb=cell(ne,1);
        for i=1:ne
            % this is very slow, need to be optimized
            nb=unique(mod([find(jx==jx(i) | jx==jx(i+ne) | jx==jx(i+2*ne))]',ne),'first');
            nb(nb==0)=ne;
            edgenb{i}=nb(nb~=i);
        end
        return;
  else
        error(['supplied option "' opt '" is not supported.']);
  end
end

if(isoctavemesh)
        u=unique(jx);
        qx=u(hist(jx,u)==2);
else
        vec=histc(jx,1:max(jx));
        qx=find(vec==2);
end

nn=max(t(:));
ne=size(t,1);
edgenb=zeros(size(t));

% now I need to find all repeatitive elements
% that share a face, to do this, unique('first')
% will give me the 1st element, and 'last' will
% give me the second. There will be no more than 2

% doing this is 60 times faster than doing find(jx==qx(i))
% inside a loop

[ujx,ii]=unique(jx,'first');
[ujx,ii2]=unique(jx,'last');

% iddup is the list of all pairs that share a common face

iddup=[ii(qx) ii2(qx)];
faceid=ceil(iddup/ne);
eid=mod(iddup,ne);
eid(eid==0)=ne;

% now rearrange this list into an element format

for i=1:length(qx)
	edgenb(eid(i,1),faceid(i,1))=eid(i,2);
	edgenb(eid(i,2),faceid(i,2))=eid(i,1);
end

% edgenb may contain 0s, that just means the corresponding
% face is a boundary face and has no neighbor.

% if the second option is 'surface', I am going to find
% and return surface patches only


function check = zipf_check ( a )

%*****************************************************************************80
%
%% ZIPF_CHECK checks the parameter of the Zipf PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, the parameter of the PDF.
%    1.0 < A.
%
%    Output, logical CHECK, is true if the parameters are legal.
%
  if ( a <= 1.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'ZIPF_CHECK - Fatal error!\n' );
    fprintf ( 1, '  A <= 1.\n' );
    check = 0;
    return
  end

  check = 1;

  return
end


function [ n_data, tc, sigma ] = surten_values ( n_data )

%*****************************************************************************80
%
%% SURTEN_VALUES returns some values of the surface tension.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Lester Haar, John Gallagher and George Kell,
%    NBS/NRC Steam Tables:
%    Thermodynamic and Transport Properties and Computer Programs
%    for Vapor and Liquid States of Water in SI Units,
%    Hemisphere Publishing Corporation, Washington, 1984,
%    TJ270.H3, pages 267.
%
%  Parameters:
%
%    Input/output, integer N_DATA.  The user sets N_DATA to 0 before the
%    first call.  On each call, the routine increments N_DATA by 1, and
%    returns the corresponding data; when there is no more data, the
%    output value of N_DATA will be 0 again.
%
%    Output, real TC, the temperature, in degrees Celsius.
%
%    Output, real SIGMA, the surface tension,
%    in Pascal * m = Newton / m.
%
  n_max = 14;

  sigma_vec = [ ...
     74.22E+00, ...
     72.74E+00, ...
     71.20E+00, ...
     69.60E+00, ...
     67.95E+00, ...
     58.92E+00, ...
     48.75E+00, ...
     37.68E+00, ...
     26.05E+00, ...
     14.37E+00, ...
      8.78E+00, ...
      3.67E+00, ...
      0.40E+00, ...
      0.00E+00 ];

  tc_vec = [ ...
      10.000E+00, ...
      20.000E+00, ...
      30.000E+00, ...
      40.000E+00, ...
      50.000E+00, ...
     100.000E+00, ...
     150.000E+00, ...
     200.000E+00, ...
     250.000E+00, ...
     300.000E+00, ...
     325.000E+00, ...
     350.000E+00, ...
     370.000E+00, ...
     373.976E+00 ];

  if ( n_data < 0 )
    n_data = 0;
  end

  n_data = n_data + 1;

  if ( n_max < n_data )
    n_data = 0;
    tc = 0.0;
    sigma = 0.0;
  else
    tc = tc_vec(n_data);
    sigma = sigma_vec(n_data);
  end

  return
end


function [model, B, elapse] = SH_learn(A, maxbits)
%   This is a wrapper function of Spectral Hashing learning.
%
%	Usage:
%	[model, B, elapse] = SH_learn(A, maxbits)
%
%	      A: Rows of vectors of data points. Each row is sample point
%   maxbits: Code length
%
%     model: Used for encoding a test sample point.
%	      B: The binary code of the input data A. Each row is sample point
%    elapse: The coding time (training time).
%
%
%
%   version 2.0 --Dec/2016
%   version 1.0 --Jan/2013
%
%   Written by  Yue Lin (linyue29@gmail.com)
%               Deng Cai (dengcai AT gmail DOT com)
%

tmp_T = tic;

model = SpectralHashing(A, maxbits);

B = SH_compress(A, model);

elapse = toc(tmp_T);

end


function g = ngaussNoiseGradientParam(noise, mu, varsigma, y)

% NGAUSSNOISEGRADIENTPARAM Gradient of NGAUSS noise's parameters.
% FORMAT
% DESC computes the gradient of the log Z of the noiseless Gaussian noise model with respect to the of functions with respect to the
% noiseless Gaussian
% noise's parameters.
% ARG noise : the noise structure for which the gradients are being
% computed.
% ARG mu : the input means for which the gradients are being computed.
% ARG varSigma : the input variances for which the gradients are being computed.
% ARG y : the target values for the noise model.
% RETURN g : gradients of the log Z with respect to
% the noise parameters. The ordering of the vector should match
% that provided by the function noiseExtractParam.
%
%
% SEEALSO ngaussNoiseParamInit, ngaussnoiseGradVals, noiseGradientParam
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005

% NOISE

D = size(y, 2);
u = zeros(size(y));

for i = 1:D
  mu(:, i) = mu(:, i) + noise.bias(i);
end

u = y - mu;
nu = 1./(varsigma+noise.sigma2);
u = u.*nu;
gbias = sum(u, 1);
g = [gbias];


function input2conv(in)
    global config mem;
    for m = 1:config.batch_size
        for n = 1:config.chs
            mem.layer_inputs{1}((n-1)*config.kernel_size(1, 1)*config.kernel_size(1, 2)+1:n*config.kernel_size(1, 1)*config.kernel_size(1, 2), (m-1)*(size(mem.layer_inputs{1}, 2)/config.batch_size)+1:m*size(mem.layer_inputs{1}, 2)/config.batch_size) = ...
                    config.SCALE_INPUT(config.IM2COL(in(:,:,n,m), [config.kernel_size(1, 1), config.kernel_size(1, 2)]));
        end
    end
end


function [U,G,J,BC,SU,L] = slice_isolines(V,F,SV,val,varargin)
  % SLICE_ISOLINES Slice through a triangle mesh (V,F) at isolines val of a given
  % per-vertex scalar function.
  %
  % [U,G] = slice_isolines(V,F,SV,val);
  % [U,G,J,BC,SU] = slice_isolines(V,F,SV,val, ...
  %   'ParameterName',parameter_value, ...)
  %
  % Inputs:
  %   V  #V by dim list of tet mesh vertices
  %   F  #F by 3 list of tet indices into V
  %   S  #V list of scalar values per vertex
  %   val  #val list of isolines values
  %   Optional:
  %     'Manifold' followed by whether to stitch together triangles into a
  %       manifold mesh {false}: results in more compact U but slightly slower.
  % Outputs:
  %   U  #U by 3 list of triangle mesh vertices along slice
  %   G  #G by 3 list of triangles indices into U
  %   J  #G list of indices into F revealing which tet this face came from
  %   BC  #U by #V list of barycentric coordinates (or more generally: linear
  %     interpolation coordinates) so that U = BC*V
  %   SU  #U list of interpolated scalar values at U
  %   L  #G list of indices into val of next value above this triangle
  %

  manifold = false;

  % Map of parameter names to variable names
  params_to_variables = containers.Map( ...
    {'Manifold'}, ...
    {'manifold'});
  v = 1;
  while v <= numel(varargin)
    param_name = varargin{v};
    if isKey(params_to_variables,param_name)
      assert(v+1<=numel(varargin));
      v = v+1;
      % Trick: use feval on anonymous function to use assignin to this
      % workspace
      feval(@()assignin('caller',params_to_variables(param_name),varargin{v}));
    else
      error('Unsupported parameter: %s',varargin{v});
    end
    v=v+1;
  end

  % helper assuming val is a scalar
  function [U,G,J,BC,SU,L] = single_val(V,F,SV,val)
    function [U,G,BC,L] = one_below(V,F,SF,val)
      [sSF,sJ] = sort(SF,2);
      sF = F(sub2ind(size(F),repmat(1:size(F,1),size(F,2),1)',sJ));
      lambda = (sSF(:,2:3)-val)./bsxfun(@minus,sSF(:,2:3),sSF(:,1));
      BC = sparse( ...
        repmat((1:size(sF,1)*2)',1,2), ...
        [repmat(sF(:,1),2,1) reshape(sF(:,2:3),size(sF,1)*2,1)], ...
        [lambda(:) 1-lambda(:)], ...
        size(sF,1)*2,size(V,1));
      U = [V;BC * V];
      % Split into three triangles
      G = [ ...
        sF(:,1) size(V,1)+[1:size(F,1);size(F,1)+(1:size(F,1))]'; ...
        fliplr([sF(:,2) size(V,1)+[1:size(F,1);size(F,1)+(1:size(F,1))]']); ...
        sF(:,[2 3]) size(V,1)+[size(F,1)+(1:size(F,1))]'; ...
        ];
      L = [ones(size(sF,1),1);2*ones(2*size(sF,1),1)];
      flip = repmat( ...
        (sJ(:,1)==1 & sJ(:,2)==3) | ...
        (sJ(:,1)==2 & sJ(:,2)==1) | ...
        (sJ(:,1)==3 & sJ(:,2)==2),3,1);
      G(flip,:) = fliplr(G(flip,:));
    end
    SF = reshape(SV(F),size(F));
    I12 = sum(SF<val,2) == 1;
    % U is the running set of vertices
    U = V;
    [U,G12,BC12,L12] = one_below(U,F(I12,:),SF(I12,:),val);
    I21 = sum(SF>=val,2) == 1;
    [U,G21,BC21,L21] = one_below(U,F(I21,:),2*val-SF(I21,:),val);
    BC = [speye(size(V,1));BC12;BC21(:,1:size(V,1))];
    untouched = find(~I12&~I21);
    G = [F(untouched,:);G12;G21];
    J = [untouched;repmat(find(I12),3,1);repmat(find(I21),3,1)];
    SU = BC*SV;
    L = [(sum(SF(untouched,:)>=val,2)==3)+1;L12;3-L21];
  end

  U = V;
  G = F;
  SU = SV;
  J = 1:size(F,1);
  L = ones(size(F,1),1);
  BC = 1;
  for v = 1:numel(val)
    prev_J = J;
    prev_L = L;
    [U,G,J,BCC,SU,L] = single_val(U,G,SU,val(v));
    L = prev_L(J)+(L-1);
    J = prev_J(J);
    BC = BCC*BC;
  end

  if manifold
    % should be able to do this combinatorially
    bbd = normrow(max(V)-min(V));
    flag = [(1:size(V,1))';ones(size(U,1)-size(V,1),1)];
    [U,I,IM] = remove_duplicate_vertices([U flag],1e-14*bbd);
    U = U(:,1:3);
    BC = BC(I,:);
    SU = SU(I,:);
    G = IM(G);
  end

end


function r = rdivide(a,b)
%RDIVIDE      Hessian elementwise right division  a ./ b
%

% written  04/04/04     S.M. Rump
% modified 04/06/05     S.M. Rump  rounding unchanged
% modified 09/28/08     S.M. Rump  check for rounding to nearest improved
% modified 08/26/12     S.M. Rump  global variables removed
%

  if prod(size(b))==1               % scalar denominator
    r = a / b;
    return
  end

  e = 1e-30;
  if 1+e==1-e                           % fast check for rounding to nearest
    rndold = 0;
  else
    rndold = getround;
    setround(0)
  end

  scalar_a = ( prod(size(a))==1 );
  if ( ~scalar_a ) & ( ~isequal(size(a),size(b)) )
    error('dimensions do not match in hessian elementwise division')
  end

  N = getappdata(0,'INTLAB_HESSIAN_NUMVAR');

  % check for emptyness: cures Matlab bug
  % a=sparse([],[],[],2,1), [i,j,s]=find(a), s(i).*s(:)  yields error
  % throughout this routine use e.g.  sparse(ib,jb,reshape(D(jb),size(sb)).*sb,N,m);
  % rather than  sparse(ib,jb,D(jb).*sb(:),N,m);

  if ~isa(a,'hessian')              % non-hessian (scalar or array) ./ hessian array
    if issparse(b.hx)
      m = prod(size(b.x));
      r.x = a ./ b.x;
      D = -r.x ./ b.x;
      [ib,jb,sb] = find(b.dx);
      r.dx = sparse(ib,jb,reshape(D(jb),size(sb)).*sb,N,m);
      bdx = sparse(ib,jb,reshape(1./b.x(jb),size(sb)).*sb,N,m);
      r.hx = adx2rhx(N,m,bdx,b.dx);
      [ib,jb,sb] = find(b.hx-r.hx);
      r.hx = sparse(ib,jb,reshape(D(jb),size(sb)).*sb,N^2,m);
    else
      r.x = a ./ b.x;
      D = r.x ./ b.x;
      D = repmat(-D(:).',N^2,1);
      r.dx = D(1:N,:) .* b.dx;
      bdx1 = b.dx./repmat(b.x(:).',N,1);
      index = repmat(1:N,N,1);
      r.hx = D .* ( b.hx - bdx1(index,:).*b.dx(index',:) );
    end
  elseif ~isa(b,'hessian')          % hessian ./ non-hessian array
    r.x = a.x ./ b;
    bb = 1 ./ (b(:).');
    if scalar_a                     % hessian scalar ./ non-hessian array
      r.dx = a.dx * bb;
      r.hx = a.hx * bb;
    else                            % hessian array ./ non-hessian array
      if issparse(a.hx)
        m = prod(size(a.x));
        [ia,ja,sa] = find(a.dx);
        r.dx = sparse(ia,ja,reshape(bb(ja),size(sa)).*sa,N,m);
        [ia,ja,sa] = find(a.hx);
        r.hx = sparse(ia,ja,reshape(bb(ja),size(sa)).*sa,N^2,m);
      else
        bb = repmat(bb,N^2,1);
        r.dx = a.dx .* bb(1:N,:);
        r.hx = a.hx .* bb;
      end
    end
  else                              % hessian ./ hessian array
    m = prod(size(b.x));
    r.x = a.x ./ b.x;
    if scalar_a                     % hessian scalar ./ hessian array
      if issparse(a.hx) | issparse(b.hx)
        bx = sparse(b.x(:));
        D = 1 ./ sqr(bx);
        Num = a.dx * bx.' - a.x * b.dx;
        [i,j,s] = find(Num);
        r.dx = sparse(i,j,s.*reshape(D(j),size(s)),N,m);
        Num = sparse(i,j,s./reshape(bx(j),size(s)),N,m);
        r.hx = a.hx * sparse(bx.') - adx2rhx(N,m,b.dx,Num) - a.x * b.hx;
        [i,j,s] = find(r.hx);
        r.hx = sparse(i,j,s.*reshape(D(j),size(s)),N^2,m);
      else
        Num = a.dx * b.x(:).' - a.x * b.dx;
        D = repmat( sqr((1./b.x(:)).') , N^2 , 1 );
        r.dx = Num .* D(1:N,:);
        index = repmat(1:N,N,1);
        Num = Num ./ repmat(b.x(:).',N,1);
        r.hx = ( a.hx * b.x(:).' - reshape(b.dx(index,:) .* Num(index',:),size(b.hx)) - a.x * b.hx ) .* D;
      end
    else                            % hessian array ./ hessian array
      if issparse(a.hx) | issparse(b.hx)
        [ia,ja,sa] = find(a.dx);
        [ib,jb,sb] = find(b.dx);
        ax = a.x(:);
        bx = b.x(:);
        Num = sparse(ia,ja,reshape(bx(ja),size(sa)).*sa,N,m) - sparse(ib,jb,reshape(ax(jb),size(sb)).*sb,N,m);
        D = sqr( 1 ./ bx );
        [ia,ja,sa] = find(Num);
        r.dx = sparse(ia,ja,reshape(D(ja),size(sa)).*sa,N,m);
        Num = sparse(ia,ja,sa./reshape(bx(ja),size(sa)),N,m);
        [ia,ja,sa] = find(a.hx);
        [ib,jb,sb] = find(b.hx);
        r.hx = sparse(ia,ja,reshape(bx(ja),size(sa)).*sa,N^2,m) - adx2rhx(N,m,b.dx,Num) - ...
               sparse(ib,jb,reshape(ax(jb),size(sb)).*sb,N^2,m);
        [ia,ja,sa] = find(r.hx);
        r.hx = sparse(ia,ja,sa.*reshape(D(ja),size(sa)),N^2,m);
      else
        ax = repmat(a.x(:).',N^2,1);
        bx = repmat(b.x(:).',N^2,1);
        Num = a.dx .* bx(1:N,:) - ax(1:N,:) .* b.dx;
        D = repmat( sqr((1./b.x(:)).') , N^2 , 1 );
        r.dx = Num .* D(1:N,:);
        index = repmat(1:N,N,1);
        Num = Num ./ bx(1:N,:);
        r.hx = ( a.hx .* bx - reshape(b.dx(index,:) .* Num(index',:),size(a.hx)) - ax .* b.hx ) .* D;
      end
    end
  end

  r = class(r,'hessian');

  if rndold
    setround(rndold)
  end


classdef GenericCylinder < Shape
	% GenericCylinder is a Shape for a cylinder whose cross section is any 2D
	% shape.

	properties (SetAccess = immutable)
		lsf2d  % level set function in lateral domain
	end

	methods
        function this = GenericCylinder(normal_axis, lsf2d, lprim_cell, dl_max)
			chkarg(istypesizeof(normal_axis, 'Axis'), '"normal_axis" should be instance of Axis.');

			% lsf2d is a level set function defined in 2D.  It takes an argument
			% r = [h, v], where, e.g., (h, v) is (x, y) for narmal_axis: z.
			chkarg(istypeof(lsf2d, 'function_handle'), '"lsf2d" should be function handle.');

			chkarg(istypesizeof(lprim_cell, 'realcell', [1 Axis.count], [1 0]), ...
				'"lprim_cell" should be length-%d row cell array whose each element is row vector with real elements.', Axis.count);

			[h, v, n] = cycle(normal_axis);
			bound_n = [min(lprim_cell{n}), max(lprim_cell{n})];
			sn = diff(bound_n) / 2;  % semiside in normal direction
			cn = mean(bound_n);  % center in normal direction

			% For rhv = r([h, v]), and rn = r(n), the level set
			% function is basically min(lsf2d(rhv), 1 - abs(rn-cn)./sn, [], 2),
			% but it is vectorized, i.e., modified to handle r = [x y z] with
			% column vectors x, y, z.
			function level = lsf(x, y, z)
				chkarg(istypeof(x, 'real'), '"x" should be array with real elements.');
				chkarg(istypeof(y, 'real'), '"y" should be array with real elements.');
				chkarg(istypeof(z, 'real'), '"z" should be array with real elements.');
				chkarg(isequal(size(x), size(y), size(z)), '"x", "y", "z" should have same size.');

				loc = {x, y, z};
				level = min(lsf2d(loc{h}, loc{v}), 1 - abs(loc{n}-cn)./sn);  % intersection of regions defined by two level set functions
			end

			if nargin < 4  % no dl_max
				super_args = {lprim_cell, @lsf};
			else
				super_args = {lprim_cell, @lsf, dl_max};
			end

			this = this@Shape(super_args{:});
			this.lsf2d = lsf2d;
		end
	end
end


% MatrixUser, a multi-dimensional matrix analysis software package
% https://sourceforge.net/projects/matrixuser/
%
% The MatrixUser is a matrix analysis software package developed under Matlab
% Graphical User Interface Developing Environment (GUIDE). It features
% functions that are designed and optimized for working with multi-dimensional
% matrix under Matlab. These functions typically includes functions for
% multi-dimensional matrix display, matrix (image stack) analysis and matrix
% processing.
%
% Author:
%   Fang Liu <leoliuf@gmail.com>
%   University of Wisconsin-Madison
%   Aug-30-2014

function MU_funcACos(Temp,Event,handles)
handles = guidata(handles.MU_matrix_display);

MergeM=get(handles.Matrix_name_edit,'String');
if isfloat(handles.TMatrix(1))
    set(handles.Matrix_name_edit,'String',['acos([' MergeM '])']);
else
    set(handles.Matrix_name_edit,'String',['acos(double([' MergeM ']))']);
end
MU_calc_matrix(handles);

end


function h = glm_plotTcs(model,voxNames,conds,active,control);
%
% h = glm_plotTcs(model,voxNames,conds,active,control);
%
% Make a figure showing the deconvolved responses
% for each 'voxel'/roi. If voxNames is supplied,
% will title each subplot w/ those names. If active and
% control are supplied, will perform a contrast
% and put up the stats for the peak data point.
%
% if conds is supplied, will only plot the
% specified conditions.
%
% ras 02/05
if ieNotDefined('voxNames')
    voxNames = [];
end

if ieNotDefined('active')
    active = [];
end

if ieNotDefined('control')
    control = [];
end

if ieNotDefined('conds')
    conds = 1:size(model.h_bar,2);
end

h = figure('Color','w',...
           'Units','Normalized',...
           'Position',[0 .2 .4 .6]);

Y = model.h_bar;
E = model.h_bar_sem;

peak = find(Y(:,2,1)==max(Y(:,2,1)))
if ~isempty(active) & ~isempty(control)
    sig = er_contrast(model,active,control,'weights',peak);
else
    sig = [];
end

nvoxels = size(Y,3);

nrows = ceil(sqrt(nvoxels));
ncols = ceil(nvoxels/nrows);

for i = 1:nvoxels
    subplot(nrows,ncols,i);
    errorbar(Y(:,conds,i),E(:,conds,i));
    if ~isempty(voxNames)
        title(voxNames{i});
    end
    if ~isempty(sig)
        AX = axis;
        msg = sprintf('p = %1.3f',10^(-1*sig(i)));
        text(AX(1)+0.63*(AX(2)-AX(1)), AX(3)+0.8*(AX(4)-AX(3)), msg);
    end
end

return


function checkMeshAdjacentFaces(vertices, edges, faces)
%CHECKMESHADJACENTFACES Check if adjacent faces of a mesh have similar orientation
%
%   checkMeshAdjacentFaces(VERTICES, EDGES, FACES)
%   The functions returns no output, but if two faces share a common edge
%   with the same direction (meaning that adjacent faces have normals in
%   opposite direction), a warning is displayed.
%
%   Example
%   [v e f] = createCube();
%   checkMeshAdjacentFaces(v, e, f);
%   % no output -> all faces have normal outwards of the cube
%
%   v = [0 0 0; 10 0 0; 0 10 0; 10 10 0];
%   e = [1 2;1 3;2 3;2 4;3 4];
%   f = [1 2 3; 2 3 4];
%   checkMeshAdjacentFaces(v, e, f);
%      Warning: Faces 1 and 2 run through the edge 3 (2-3) in the same direction
%
%   See also
%   meshes3d
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2010-10-06,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

pattern = 'Faces %d and %d run through the edge %d (%d-%d) in the same direction';

edgeFaces = meshEdgeFaces(vertices, edges, faces);
Ne = size(edgeFaces, 1);

for i = 1:Ne
    % indices of extreimty vertices
    v1 = edges(i, 1);
    v2 = edges(i, 2);

    % index of adjacent faces
    indF1 = edgeFaces(i, 1);
    indF2 = edgeFaces(i, 2);

    % if one of the faces has index 0, then the edge is at the boundary
    if indF1 == 0 || indF2 == 0
        continue;
    end
    % vertices of adjacent faces
    face1 = meshFace(faces, indF1);
    face2 = meshFace(faces, indF2);

    % position of vertices in face vertex array
    ind11 = find(face1 == v1);
    ind12 = find(face1 == v2);
    ind21 = find(face2 == v1);
    ind22 = find(face2 == v2);

    % check if edge is traveled forward or backard
    direct1 = (ind12 == ind11+1) | (ind12 == 1 & ind11 == length(face1));
    direct2 = (ind22 == ind21+1) | (ind22 == 1 & ind21 == length(face2));

    % adjacent faces should travel the edge in opposite direction
    if direct1 == direct2
        warning(pattern, indF1, indF2, i, v1, v2); %#ok<WNTAG>
    end
end


function vbmc_plot(vp_array,stats)

if nargin < 2; stats = []; end

Nsamples = 1e5;

if ~iscell(vp_array)
    temp{1} = vp_array;
    vp_array = temp;
end

if numel(vp_array) == 1 && vbmc_isavp(vp_array{1})
    X = vbmc_rnd(vp_array{1},Nsamples);
    for d = 1:size(X,2); names{d} = ['x_{' num2str(d) '}']; end
    cornerplot(X,names);
else
    Nbins = 40;
    Nvps = numel(vp_array);
    D = vp_array{1}.D;
    mm = zeros(Nvps,D);
    cmap = colormap;
    cmap = cmap(mod((1:27:(1+27*64))-1,64)+1,:);

    plotmat = [1 1; 1 2; 1 3; 2 2; 2 3; 2 3; 2 4; 2 4; 3 3; 3 4; 3 4; 3 4; 3 5; 3 5; 3 5; 4 4; 4 5; 4 5; 4 5];
    nrows = plotmat(D,1);
    ncols = plotmat(D,2);

    for i = 1:Nvps
        if ~isempty(stats) && stats.idx_best == i; best_flag = true; else; best_flag = false; end
        ltext{i} = ['vp #' num2str(i)];
        if best_flag; ltext{i} = [ltext{i} ' (best)']; end

        X = vbmc_rnd(vp_array{i},Nsamples);
        mm(i,:) = median(X);

        for d = 1:D
            subplot(nrows,ncols,d);
            if best_flag; lw = 3; else; lw = 1; end
            hst(i)=histogram(X(:,d),Nbins,'Normalization','probability','Displaystyle','stairs','LineWidth',lw,'EdgeColor',cmap(i,:));
            hold on;
        end
    end

    for i = 1:Nvps
        if ~isempty(stats) && stats.idx_best == i; best_flag = true; else; best_flag = false; end
        for d = 1:D
            subplot(nrows,ncols,d);
            if best_flag; lw = 3; else; lw = 1; end
            hln(i)=plot(mm(i,d)*[1 1],ylim,'-','LineWidth',lw,'Color',cmap(i,:));
            hold on;
        end
    end

    for d = 1:D
        subplot(nrows,ncols,d);

        xlabel(['x_{' num2str(d) '}']);
        set(gca,'TickDir','out');
        box off;

        if d == D
            hleg = legend(hln,ltext{:});
            set(hleg,'box','off','location','best');
        end

    end
    set(gcf,'Color','w');

end

end


function openface=volface(t)
%
% openface=volface(t)
%
% find the surface patches of a volume
%
% author: Qianqian Fang (fangq<at> nmr.mgh.harvard.edu)
% date: 2009/10/13
%
% input:
%      t: input, volumetric element list, dimension (ne,4)
%
% output:
%      openface: list of faces of the specified volume
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

openface=surfedge(t);


%--- help for polyshape/translate ---
%
%  TRANSLATE Translate a polyshape
%
%  PG = TRANSLATE(pshape, V) translates a polyshape according to a
%  two-element row vector V. The first element of V is the translation
%  distance in the x direction, and the second element is the translation
%  distance in the y direction. Positive values in V translate right and up,
%  and negative values translate left and down. When pshape is an array of
%  polyshapes, each element of pshape is translated according to V.
%
%  PG = TRANSLATE(pshape, x, y) specifies the x and y translation distances
%  as separate arguments.
%
%  See also scale, rotate, polybuffer, polyshape
%
%    Reference page in Doc Center
%       doc polyshape/translate
%
%    Other functions named translate
%
%       dsge/translate
%


function [ fxx, fxy, fyy ] = f00_f2 ( fi, n, x, y )

%*****************************************************************************80
%
%% F00_F2 returns second derivatives of any function.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 August 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer FI, the index of the function.
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real X(N,1), Y(N,1), the evalution points.
%
%    Output, real FXX(N,1), FXY(N,1), FYY(N,1), the second derivatives.
%
  if ( fi == 1 )
    [ fxx, fxy, fyy ] = f01_f2 ( n, x, y );
  elseif ( fi == 2 )
    [ fxx, fxy, fyy ] = f02_f2 ( n, x, y );
  elseif ( fi == 3 )
    [ fxx, fxy, fyy ] = f03_f2 ( n, x, y );
  elseif ( fi == 4 )
    [ fxx, fxy, fyy ] = f04_f2 ( n, x, y );
  elseif ( fi == 5 )
    [ fxx, fxy, fyy ] = f05_f2 ( n, x, y );
  elseif ( fi == 6 )
    [ fxx, fxy, fyy ] = f06_f2 ( n, x, y );
  elseif ( fi == 7 )
    [ fxx, fxy, fyy ] = f07_f2 ( n, x, y );
  elseif ( fi == 8 )
    [ fxx, fxy, fyy ] = f08_f2 ( n, x, y );
  elseif ( fi == 9 )
    [ fxx, fxy, fyy ] = f09_f2 ( n, x, y );
  elseif ( fi == 10 )
    [ fxx, fxy, fyy ] = f10_f2 ( n, x, y );
  elseif ( fi == 11 )
    [ fxx, fxy, fyy ] = f11_f2 ( n, x, y );
  elseif ( fi == 12 )
    [ fxx, fxy, fyy ] = f12_f2 ( n, x, y );
  elseif ( fi == 13 )
    [ fxx, fxy, fyy ] = f13_f2 ( n, x, y );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'F00_F2 - Fatal error!\n' );
    fprintf ( 1, '  Illegal function index FI = %d\n', fi );
    error ( 'F00_F2 - Fatal error!' );
  end

  return
end


function medit_io_test01 ( )

%*****************************************************************************80
%
%% MEDIT_IO_TEST01 creates a MESH dataset and writes it to a file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 December 2010
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'MEDIT_IO_TEST01:\n' );
  fprintf ( 1, '  Create a hexahedral mesh and write it to a file.\n' );

  [ dim, vertices, edges, triangles, quadrilaterals, tetrahedrons, ...
    hexahedrons, vertex_coordinate, vertex_label, edge_vertex, edge_label, ...
    triangle_vertex, triangle_label, quadrilateral_vertex, ...
    quadrilateral_label, tetrahedron_vertex, tetrahedron_label, ...
    hexahedron_vertex, hexahedron_label ] = hexahexa_2x2x2 ( );

  filename = 'hexahexa_2x2x2.mesh';

  mesh_write ( filename, dim, vertices, edges, triangles, quadrilaterals, ...
    tetrahedrons, hexahedrons, vertex_coordinate, vertex_label, edge_vertex, ...
    edge_label, triangle_vertex, triangle_label, quadrilateral_vertex, ...
    quadrilateral_label, tetrahedron_vertex, tetrahedron_label, ...
    hexahedron_vertex, hexahedron_label );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Created the file "%s".\n', filename );

  return
end


function [pdag, G] = learn_struct_pdag_pc_mod(cond_indep, n, k, varargin)
% LEARN_STRUCT_PDAG_PC Learn a partially oriented DAG (pattern) using the PC algorithm
% P = learn_struct_pdag_pc(cond_indep, n, k, ...)
%
% n is the number of nodes.
% k is an optional upper bound on the fan-in (default: n)
% cond_indep is a boolean function that will be called as follows:
%   feval(cond_indep, x, y, S, ...)
% where x and y are nodes, and S is a set of nodes (positive integers),
% and ... are any optional parameters passed to this function.
%
% The output P is an adjacency matrix, in which
% P(i,j) = -1 if there is an i->j edge.
% P(i,j) = P(j,i) = 1 if there is an undirected edge i <-> j
%
% The PC algorithm does structure learning assuming all variables are observed.
% See Spirtes, Glymour and Scheines, "Causation, Prediction and Search", 1993, p117.
% This algorithm may take O(n^k) time if there are n variables and k is the max fan-in,
% but this is quicker than the Verma-Pearl IC algorithm, which is always O(n^n).

sep = cell(n,n);
ord = 0;
done = 0;
G = ones(n,n);
G=setdiag(G,0);
while ~done
 done = 1;
 [X,Y] = find(G);
 for i=1:length(X)
   x = X(i); y = Y(i);
   %nbrs = mysetdiff(myunion(neighbors(G, x), neighbors(G,y)), [x y]);
   nbrs = mysetdiff(neighbors(G, y), x);  % bug fix by Raanan Yehezkel <raanany@ee.bgu.ac.il> 6/27/04
   if length(nbrs) >= ord & G(x,y) ~= 0
     done = 0;
     %SS = subsets(nbrs, ord, ord); % all subsets of size ord
     SS = subsets1(nbrs, ord);
     for si=1:length(SS)
       S = SS{si};
       if feval(cond_indep, x, y, S, varargin{:})
         %if isempty(S)
         %  fprintf('%d indep of %d ', x, y);
         %else
         %  fprintf('%d indep of %d given ', x, y); fprintf('%d ', S);
         %end
         %fprintf('\n');

         % diagnostic
         %[CI, r] = cond_indep_fisher_z(x, y, S, varargin{:});
         %fprintf(': r = %6.4f\n', r);

         G(x,y) = 0;
         G(y,x) = 0;
         sep{x,y} = myunion(sep{x,y}, S);
         sep{y,x} = myunion(sep{y,x}, S);
         break; % no need to check any more subsets
       end
     end
   end
 end
 ord = ord + 1;
end

% Create the minimal pattern,
% i.e., the only directed edges are V structures.
pdag = G;
[X, Y] = find(G);
% We want to generate all unique triples x,y,z
% This code generates x,y,z and z,y,x.
for i=1:length(X)
 x = X(i);
 y = Y(i);
 Z = find(G(y,:));
 Z = mysetdiff(Z, x);
 for z=Z(:)'
   if G(x,z)==0 & ~ismember(y, sep{x,z}) & ~ismember(y, sep{z,x})
     %fprintf('%d -> %d <- %d\n', x, y, z);
     pdag(x,y) = -1; pdag(y,x) = 0;
     pdag(z,y) = -1; pdag(y,z) = 0;
   end
 end
end

% Convert the minimal pattern to a complete one,
% i.e., every directed edge in P is compelled
% (must be directed in all Markov equivalent models),
% and every undirected edge in P is reversible.
% We use the rules of Pearl (2000) p51 (derived in Meek (1995))

old_pdag = zeros(n);
iter = 0;
while ~isequal(pdag, old_pdag)
 iter = iter + 1;
 old_pdag = pdag;
 % rule 1
 [A,B] = find(pdag==-1); % a -> b
 for i=1:length(A)
   a = A(i); b = B(i);
   C = find(pdag(b,:)==1 & G(a,:)==0); % all nodes adj to b but not a
   if ~isempty(C)
     pdag(b,C) = -1; pdag(C,b) = 0;
     %fprintf('rule 1: a=%d->b=%d and b=%d-c=%d implies %d->%d\n', a, b, b, C, b, C);
   end
 end
 % rule 2
 [A,B] = find(pdag==1); % unoriented a-b edge
 for i=1:length(A)
   a = A(i); b = B(i);
   if any( (pdag(a,:)==-1) & (pdag(:,b)==-1)' );
     pdag(a,b) = -1; pdag(b,a) = 0;
     %fprintf('rule 2: %d -> %d\n', a, b);
   end
 end
 % rule 3
 [A,B] = find(pdag==1); % a-b
 for i=1:length(A)
   a = A(i); b = B(i);
   % Bug fix by Imme Ebert-Uphoff (ebert@tree.com), Jan 2007
   % C = find( (G(a,:)==1) & (pdag(:,b)==-1)' );
   C = find( (pdag(a,:)==1) & (pdag(:,b)==-1)' );
   % C contains nodes c s.t. a-c->ba
   G2 = setdiag(G(C, C), 1);
   if any(G2(:)==0) % there are 2 different non adjacent elements of C
     pdag(a,b) = -1; pdag(b,a) = 0;
     %fprintf('rule 3: %d -> %d\n', a, b);
   end
 end
end

%  % Test Rule 3 of PC algorithm
%
%  % Define PDAG
%  pdag = zeros(4);
%  pdag(2,1)=-1;
%  pdag(3,1)=-1;
%  pdag(2,4)=-1;
%  pdag(3,4)=-1;
%  pdag(1,4)=1;
%  pdag(4,1)=1;
%
%  fprintf('\nSample input PDAG:\n');
%  pdag
%
%  fprintf('Sample DAG generated from PDAG:\n');
%  dag = abs(pdag_to_dag(pdag))
%
%  fprintf('Output from current PC algorithm:\n');
%  pdag_PC = learn_struct_pdag_pc('dsep', 4, 3, dag)
%
%  % Problem can be fixed by changing Line 120 of learn_struct_pdag_pc.m
%  %    C = find( (G(a,:)==1) & (pdag(:,b)==-1)' );
%  % to
%  %    C = find( (pdag(a,:)==1) & (pdag(:,b)==-1)' );
%
%  fprintf('Correct version:\n');
%  pdag_PC_mod = learn_struct_pdag_pc_mod('dsep', 4, 3, dag)


  function img = feldkamp(cg, ig, proj, varargin)
%|function img = feldkamp(cg, ig, proj, varargin)
%|
%| version modified by james balter and others to try accelereys "jacket"
%| UNDER DEVELOPMENT!
%|
%| FBP reconstruction of cone-beam tomography data collected with
%| a circular source trajectory.
%| See feldkamp_example.m for example.
%|
%| in:
%|	cg			ct_geom()
%|	ig			image_geom()
%|	proj	[ns,nt,na]	cone-beam projection views (line integrals)
%|
%| options:
%|	'window' [npad]		'ramp' (default), or 'hann', or array.
%|				if array, then use samples [-K/2, K/2).
%|	'offset_source'		distance from isocenter to perpendicular ray
%|				[the same units (e.g., mm) as pixel_size etc.]
%|				caution: probably should not be used
%|	'ia_skip' [int]		downsample in angle to save time for tests
%|	'use_mex' 0|1		backprojector: 0 for matlab, 1 for mex (default)
%|	'nthread'		default: jf('ncore')
%|
%| out:
%|	img	[nx,ny,nz]	reconstructed image
%|
%| References: Feldkamp, Davis, Kress, JOSA-A, 1(6):612-9, June 1984.
%| Notation here follows Fessler tomography book chapter (ask if interested).
%|
%| Copyright 2004-8-28 Nicole Caparanis, Patty Laskowsky, Taka Masuda,
%| and Jeff Fessler, University of Michigan
%| arc detector case contributed by Yingying Zhang 2005-6-13

if nargin == 1 && streq(cg, 'test')
	run_mfile_local('feldkamp_example')
return
end
if nargin < 3, ir_usage, end

if isnumeric(cg)
	img = feldkamp_old(cg, ig, proj, varargin{:});
return
end

% defaults
arg.use_mex = 1;
arg.window = 'ramp';
arg.offset_source = 0; % r_off, distance between rotation iso-center
			% and ray from source that is orthogonal to detector.
arg.ia_skip = 1;
arg.nthread = jf('ncore');
arg = vararg_pair(arg, varargin);

if cg.pitch ~= 0 || any(cg.zshifts ~= 0)
	fail('sorry, helical CT unsupported')
end

img = feldkamp_do(proj, ...
	cg.ds, cg.dt, cg.offset_s, cg.offset_t, arg.offset_source, ...
	cg.dsd, cg.dso, cg.dfs, cg.orbit, cg.orbit_start, ...
	ig.mask_or, ig.nz, ig.dx, ig.dy, ig.dz, ...
	[ig.offset_x ig.offset_y ig.offset_z], ...
	arg.window, arg.ia_skip, arg.use_mex, arg.nthread);
end % feldkamp()

 function img = feldkamp_old(proj, mask, varargin)
%function img = feldkamp_old(proj, mask, [options])
%
% FBP reconstruction of cone-beam tomography data collected with
% a circular source trajectory.
% See feldkamp_example.m for example.
%
% in:
%	proj	[ns,nt,na]	cone-beam projection views (line integrals)
%	mask	[nx,ny]		logical array of desired (2d) fov support
%
% options:
%	window	[npad]		'ramp' (default), or 'hann', or array.
%				if array, then use samples [-K/2, K/2).
%	'dx' 'dy' 'dz'		voxel dimensions
%	'nz'			# of slices
%	'center_xyz'		image center [pixels] (default: 0)
%	'ds' 'dt'		detector sample spacing (horiz, vert)
%	'offset_st'		detector offset_s,t [integer number of samples
%				or fraction thereof, for 1/4-detector offset.
%	'orbit'			default 360 degrees
%	'orbit_start'		default 0 degrees
%	'dis_src_det'
%	'dis_iso_det'
%	'dis_foc_src'		default inf (flat), or 0 for arc
%	'offset_source'		distance from isocenter to perpendicular ray
%				[the same units (e.g., mm) as pixel_size etc.]
%	'ia_skip' [int]		downsample in angle to save time for tests
%	'use_mex' 0|1		backprojector: 0 for matlab, 1 for mex (default)
%
% out:
%	img	[nx,ny,nz]		reconstructed image
%
% offset_s is an integer or fraction thereof, e.g., 0.25,
% relative to centerline between two central channels.
%
% References: Feldkamp, Davis, Kress, JOSA-A, 1(6):612-9, June 1984.
% Fessler tomography chapter.
%
% Copyright 2004-8-28 Nicole Caparanis, Patty Laskowsky, Taka Masuda,
% and Jeff Fessler, University of Michigan
% arc detector case contributed by Yingying Zhang 2005-6-13

warn 'this is obsolete use of feldkamp.m - use new style!'

% defaults
arg.use_mex = 1; % force MATLAB
arg.window = 'ramp';
arg.dx = nan;
arg.dy = [];
arg.dz = [];
arg.nz = size(proj,2);
arg.center_xyz = [0 0 0]; % center_x,y,z (pixels)
arg.flip_y = 1;

arg.dsd = []; % 'dis_src_det'
arg.dod	= []; %	'dis_iso_det'
arg.dfs = inf; % 'dis_foc_src' default flat
arg.offset_source = 0; % r_off, distance between rotation iso-center
			% and ray from source that is orthogonal to detector.

arg.ds = nan;
arg.dt = [];
arg.offset_st = [0 0]; % offset_s,t
arg.ia_skip = 1;
arg.orbit = 360;
arg.orbit_start = 0;
arg = vararg_pair(arg, varargin, 'subs', ...
	{'dis_src_det', 'dsd';
	'dis_iso_det', 'dod';
	'dis_foc_src', 'dfs'});
if isnan(arg.ds) || isnan(arg.dx), fail('ds and dx required'), end

if isempty(arg.dy), arg.dy = -arg.dx; end
if isempty(arg.dz), arg.dz = arg.dx; end
if isempty(arg.dt), arg.dt = arg.ds; end

arg.dso = arg.dsd - arg.dod; % src to "isocenter" distance

if ~isempty(arg.zshifts), error 'todo: helical feldkamp not done', end

img = feldkamp_do(proj, ...
	arg.ds, arg.dt, arg.offset_st(1), arg.offset_st(2), ...
	arg.offset_source, ...
	arg.dsd, arg.dso, arg.dfs, ...
	arg.orbit, arg.orbit_start, ...
	mask, arg.nz, arg.dx, arg.dy, arg.dz, arg.center_xyz, ...
	arg.window, arg.ia_skip, arg.use_mex, 1);

end % feldkamp_old()

%
% feldkamp_do()
%
function img = feldkamp_do(proj, ...
	ds, dt, offset_s, offset_t, offset_source, ...
	dsd, dso, dfs, orbit, orbit_start, ...
	mask, nz, dx, dy, dz, offset_xyz, ...
	window, ia_skip, use_mex, nthread)

% step 1: weight the projections as in fan-beam case
proj = feldkamp_weight1(proj, ds, dt, offset_s, offset_t, dsd, dso, dfs);

% step 2: filter the (zero padded) projections
[ns nt na] = size(proj);
if use_mex
	pad1 = 0;
else
	pad1 = 2;
end
proj = feldkamp_filter(proj, window, dsd, dfs, ds, pad1);

if pad1 % trick: zero at end saves indexing in loop
%	proj = [proj; zeros(2, nt, na)];
	proj(:,end+1,:) = 0;
end

% step 3: cone-beam backprojection of the filtered views
cpu etic
img = feldkamp_back(proj, ns, nt, na, ...
	ds, dt, offset_s, offset_t, offset_source, ...
	dsd, dso, dfs, orbit, orbit_start, ...
	mask, nz, dx, dy, dz, offset_xyz, ...
	ia_skip, use_mex, nthread);
cpu etoc 'fdk backprojection cpu time:'

end % feldkamp_do()

%
% feldkamp_weight1()
% step 1: weight the projections as in fan-beam case
%
function proj = feldkamp_weight1(proj, ds, dt, offset_s, offset_t, ...
	dsd, dso, dfs);
[ns nt na] = size(proj);
ss = ([-(ns-1)/2:(ns-1)/2]' - offset_s) * ds;
tt = ([-(nt-1)/2:(nt-1)/2]' - offset_t) * dt;

[ss tt] = ndgrid(ss, tt);
if isinf(dfs) % flat
	ww1 = dso * sqrt(1 + (tt/dsd).^2) ./ sqrt(dsd^2 + ss.^2 + tt.^2);
elseif dfs == 0 % arc
	ww1 = (dso/dsd) * cos(ss ./ (dsd * sqrt(1 + (tt/dsd).^2)));
else
	error 'other configurations not implemented'
end

for ia=1:na % same weighting for each view angle
	proj(:,:,ia) = proj(:,:,ia) .* ww1;
end
end % feldkamp_weight1()

%
% feldkamp_filter()
% step 2: filter the (zero padded) projections
%
function proj = feldkamp_filter(proj, window, dsd, dfs, ds, pad1)
[ns nt na] = size(proj);
npadh = 2^ceil(log2(2*ns-1));
printf('ns=%d npadh=%d', ns, npadh)

if isinf(dfs)
	H = fan_filter('flat', npadh, ds, [], window);	% [nb,1]
elseif dfs == 0
	H = fan_filter('arc', npadh, ds, dsd, window);
end
H = ds * H; % differential for discrete-space convolution vs integral

%% START JACKET
GPU = 1;
if GPU,
    proj = gsingle( proj );
    H = gsingle( H );
    proj_large = gzeros( npadh, size(proj,2), size(proj,3) );
else,
    proj_large = zeros( npadh, size(proj,2), size(proj,3) );
end
%% END JACKET

tic;
proj_large(1:size(proj,1),:,:) = proj;
proj = ifft( fft(proj_large) .* repmat(H, [1 nt na]) );
proj = proj(1:(ns+pad1),:,:); % trick: extra zero at end saves indexing in loop
toc

%% START JACKET
if GPU,
    proj = double( proj );
end
%% END JACKET

end % feldkamp_filter()

%
% fan_filter()
% apodized filter frequency response
%
function H = fan_filter(type, n, ds, dsd, window)

if streq(type, 'flat')
	h = fbp_ramp('flat', n, ds);
else
	h = fbp_ramp('arc', n, ds, dsd);
end
H = reale(fft(fftshift(h)));

if ischar(window)
	if streq(window, 'ramp')
		window = ones(n,1);
	elseif streq(window, 'hann')
		window = ir_hann_periodic(n);
	else
		error 'unknown window'
	end
elseif length(window) ~= n
	error 'bad window length'
end

H = H .* fftshift(window);
end % fan_filter()

%
% feldkamp_back()
% step 3: cone-beam backprojection of the filtered views
%
function img = feldkamp_back(proj, ns, nt, na, ...
	ds, dt, offset_s, offset_t, offset_source, ...
	dsd, dso, dfs, orbit, orbit_start, ...
	mask, nz, dx, dy, dz, offset_xyz, ...
	ia_skip, use_mex, nthread)
[nx ny] = size(mask);

betas = deg2rad(orbit_start + orbit * [0:na-1] / na); % [na] source angles

% mex backprojector
if use_mex
	proj = single(proj);
	nthread = int32(nthread);

	if use_mex == 1 % loop in mex
		proj = permute(proj, [2 1 3]); % ts
		tmp = jf_mex('fdk,ts,back', int32([nx ny nz]), [dx dy dz], ...
				offset_xyz, uint8(mask), ...
				dso, dsd, dfs, [ds dt], [offset_s offset_t], ...
				proj, betas, nthread);
		img = double6(tmp);
		img = permute(img, [2 3 1]); % zxy -> xyz

	elseif use_mex == 2 % loop in matlab (for testing)
		proj = permute(proj, [2 1 3]); % ts
		img = 0;
		for ia=1:na
			ticker(mfilename, ia, na)
			% note: 2006-5-30: replaced -dy with dy
			tmp = jf_mex('fdk,ts,back', ...
				int32([nx ny nz]), [dx dy dz], ...
				offset_xyz, uint8(mask), ...
				dso, dsd, dfs, [ds dt], [offset_s offset_t], ...
				proj(:,:,ia), betas(ia), nthread);
			tmp = double6(tmp);
			img = img + tmp;
		end
		img = permute(img, [2 3 1]); % zxy -> xyz

	elseif use_mex == 3 % fdk,st (for testing only - slower!)
		tmp = jf_mex('fdk,st,back', int32([nx ny nz]), [dx dy dz], ...
				offset_xyz, uint8(mask), ...
				dso, dsd, dfs, [ds dt], [offset_s offset_t], ...
				proj, betas, nthread);
		img = double6(tmp);

	else
		fail 'bug'
	end

	% final "\der angle" scale:
	img = (0.5 * deg2rad(abs(orbit)) / (na/ia_skip)) * img;
return
end

% matlab backprojector (slower)

fprintf('We are using slower version!\n');

% precompute as much as possible
wx = (nx-1)/2 + offset_xyz(1);
wy = (ny-1)/2 + offset_xyz(2);
wz = (nz-1)/2 + offset_xyz(3);
[xc yc] = ndgrid(([0:nx-1] - wx) * dx, ([0:ny-1] - wy) * dy);
zc = ([0:nz-1] - wz) * dz;

if 0 % limit back-projection to FOV?  removed 2008-10-9
	rr = sqrt(xc.^2 + yc.^2); % [nx,ny]
	smax = ((ns-1)/2-abs(offset_s)) * ds; % maximum detector s coordinate

	if isinf(dfs)
		gamma_max = atan(smax/dsd);
	elseif dfs == 0
		gamma_max = smax / dsd;
	end

	rmax = dso * sin(gamma_max);
	mask = mask & (rr < rmax);
end
clear wx wy wz rr smax rmax

xc = xc(mask); % [np] pixels within mask
yc = yc(mask);

% loop over slices
GPU = 0;
if GPU,
    img = gzeros([size(mask) nz]) + i;
    img = img - i;
else,
    img = zeros([size(mask) nz]);
end;
ticker reset
tic;
for iz=1:nz

	% loop over each projection angle
	img2 = 0;
	for ia=1:na
		ticker(mfilename, [iz ia], [nz na])
		beta = betas(ia);

		x_beta = +xc * cos(beta) + yc * sin(beta);
		y_beta = -xc * sin(beta) + yc * cos(beta);

		% detector indices
		mag = dsd ./ (dso - y_beta);

		if isinf(dfs)
			sprime = mag .* x_beta;
		elseif (dfs == 0)
			d_loop = dso - y_beta;
			r_loop = x_beta - offset_source;
			sprime = dsd * atan2(r_loop, d_loop);
		end

		tprime = mag * zc(iz);
		bh = sprime / ds + (ns+1)/2 + offset_s;
		bv = tprime / dt + (nt+1)/2 + offset_t;

		% bi-linear interpolation:
		ih = floor(bh); % left bin
		iv = floor(bv);
		igood = 1<=ih & ih<ns & 1<= iv & iv<nt;

		ih(~igood) = ns+1; % trick! point at harmless zeros
		iv(~igood) = 1;

		wr = bh - ih;	% left weight
		wl = 1 - wr;	% right weight
		wu = bv - iv;	% upper weight
		wd = 1 - wu;	% lower weight

		sdim = size(proj);
		ia1 = ia * ones(size(ih));

		p1 =	wl .* proj(sub2ind(sdim, ih,iv,ia1)) + ...
			wr .* proj(sub2ind(sdim, ih+1,iv,ia1));
		p2 =	wl .* proj(sub2ind(sdim, ih,iv+1,ia1)) + ...
			wr .* proj(sub2ind(sdim, ih+1,iv+1,ia1));

		p0 = wu .* p1 + wd .* p2; % vertical interpolation

		if isinf(dfs)
			p0 = p0 .* mag.^2; % back-projection weighting for flat
		elseif dfs == 0
			p0 = p0 .* (dsd.^2) ./ (r_loop.^2 + d_loop.^2);
		end

		img2 = img2 + p0;
	end % ia

	img(:,:,iz) = embed(img2, mask);
end % iz
toc

img = (0.5 * deg2rad(orbit) / (na/ia_skip)) * img; % final "\der angle" scale
img = double( img );

end % feldkamp_back()


classdef AffinityLoss < dagnn.Loss
    properties
        Alpha = 1;
    end

    methods
        function outputs = forward(obj, inputs, params)
            BatchSize = size(inputs{1}, 4);
            outputs{1} = mean(inputs{1}(:) .* (1-inputs{2}(:))) + obj.Alpha * mean(inputs{3}(:) .* inputs{2}(:));
            n = obj.numAveraged;
            m = n + BatchSize;
            obj.average = (n * obj.average + double(gather(outputs{1} * BatchSize))) / m ;
            obj.numAveraged = m;
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
            [W,H,C,~] = size(inputs{1});
            NumSamples = W * H * C;
            derInputs{1} = derOutputs{1} * (1-inputs{2}) / NumSamples;
            derInputs{2} = derOutputs{1} * (-inputs{1} + obj.Alpha * inputs{3})/ NumSamples;
            derInputs{3} = derOutputs{1} * obj.Alpha * inputs{2} / NumSamples;
            derParams = {};
        end

        function reset(obj)
            obj.average = 0 ;
            obj.numAveraged = 0 ;
        end
        function obj = AffinityLoss(varargin)
            obj.load(varargin) ;
        end
    end
end


function w = K_symmetrised(psi,q1,q2,CS,SS,varargin)
% evaluate kernel modulo symmetries
%
% Input
%  psi    - @SO3Kernel
%  q1, q2 - @quaternion(s)
%  CS, SS - crystal , specimen @symmetry
%
% Options
%  exact -
%  epsilon -
%
% Description
% K(q1,q2) = Sum(S) Sum(l) A_l Tr T_l(s1^-1 q1 s2)

% only the pur rotational part is of interest
% TODO
qCS = unique(quaternion(CS));
qSS = unique(quaternion(SS));

if check_option(varargin,'exact')
  epsilon = pi;
else
  epsilon = min(pi,get_option(varargin,'epsilon',psi.halfwidth*3.5));
end

% how to use sparse matrix representation
if isa(q1,'SO3Grid')
  lg1 = length(q1);
else
  lg1 = -length(q1);
end
if isa(q2,'SO3Grid')
  lg2 = length(q2);
else
  lg2 = -length(q2);
end

if epsilon>2*pi/CS.Laue.multiplicityZ % full matrixes

  q1 = quaternion(q1);
  q2 = quaternion(q2);
  w = zeros(length(q1),length(q2));

	for iks = 1:length(qCS)
		for ips = 1:length(qSS) % for all symmetries

			sg    = qSS(ips) * q1 * qCS(iks);  % rotate g1
      omega = abs(dot_outer(sg,q2));      % calculate full distance matrix
      w = w + psi.eval(omega);

		end
  end

elseif (lg1>0 || lg2>0) && ~check_option(varargin,'old')

  w = sparse(abs(lg1),abs(lg2));

  % sum over specimen symmetry
  if (lg1 >= lg2)              % first argument is SO3Grid
    for issq = 1:length(qSS)
      d = abs(dot_outer(q1,qSS(issq)*quaternion(q2),'epsilon',epsilon,...
        'nospecimensymmetry'));
        w = w + spfun(@psi.eval,d);
    end
  else                         % second argument is SO3Grid
    for issq = 1:length(qSS)
      d = abs(dot_outer(q2,qSS(issq)*quaternion(q1),'epsilon',epsilon,...
        'nospecimensymmetry'));
      w = w + spfun(@psi.eval,d.');
    end
  end

else

	q1 = quaternion(q1);
	q2 = quaternion(q2);

	w = sparse(length(q1),length(q2));

	for iks = 1:length(qCS)
		for ips = 1:length(qSS) % for all symmetries

      if abs(lg1) > abs(lg2)
        sg    = qSS(ips) * q2 * qCS(iks);  % rotate g1
        omega = abs(dot_outer(q1,sg));      % calculate full distance matrix
      else
        sg    = qSS(ips) * q1 * qCS(iks);  % rotate g1
        omega = abs(dot_outer(sg,q2));      % calculate full distance matrix
      end

%  z = find(omega>cos(epsilon));
%  if length(z) > length(omega)/length(CS)/10, w = full(w); end
%  w(z) = w(z) +  kk.K(omega(z));

%  if length(z) > numel(omega)/length(CS)/10, w = full(w); end

      [y,x] = find(omega>cos(epsilon));
      dummy = sparse(y,x,psi.eval(omega(sub2ind(size(w),y,x))),length(q1),length(q2));

      w = w + dummy;

		end
  end

end
%nnz(w)
w = w / length(qCS) / length(qSS);


function [sp, dcell] = deconvolution_standalone2(ops, ca, neu, gt)
% takes as input the calcium and (optionally) neuropil traces,
% both NT by NN (number of neurons).
% outputs a cell array dcell containing spike times (dcell.st) and amplitudes
% (dcell.c). dcell.B(3) is the neuropil contamination coefficient.
% dcell.B(2) is an estimate of the baseline.

% this version also estimates a single timescale

% specify in ops the following options, or leave empty for defaults
%       fs = sampling rate
%       recomputeKernel = whether to estimate kernel from data
%       sensorTau  = timescale of sensor, if recomputeKernel = 0
% additional options can be specified (mostly for linking with Suite2p, see below).

ops.imageRate    = getOr(ops, {'imageRate'}, 30); % total image rate (over all planes)
ops.nplanes      = getOr(ops, {'nplanes'}, 1); % how many planes at this total imaging rate
ops.sensorTau    = getOr(ops, {'sensorTau'}, 2); % approximate timescale in seconds
ops.sameKernel   = getOr(ops, {'sameKernel'}, 1); % 1 for same kernel per plane, 0 for individual kernels (does not work right now)
ops.maxNeurop    = getOr(ops, {'maxNeurop'}, Inf); % maximum allowed neuropil contamination coefficient.
ops.recomputeKernel = getOr(ops, {'recomputeKernel'}, 1); % whether to estimate kernel from data
lam = getOr(ops, 'lam', 3);

% the kernel should depend on timescale of sensor and imaging rate
ops.fs           = getOr(ops, 'fs', ops.imageRate/ops.nplanes);
mtau             = ops.fs * ops.sensorTau;

if nargin<3 || isempty(neu)
    neu = zeros(size(ca));
end

Params = [1 lam 1 2e4]; %parameters of deconvolution

% f0 = (mtau/2); % resample the initialization of the kernel to the right number of samples
kernel = exp(-[1:ceil(5*mtau)]'/mtau) ;
%
npad        = 250;
[NT, NN]    = size(ca);
coefNeu     = .8 * ones(1,NN); % initialize neuropil subtraction coef with 0.8

caCorrected = ca - bsxfun(@times, neu, coefNeu);

if ops.recomputeKernel
    tlag                     = 1;
    [kernel, mtau]           = estimateKernel(ops, caCorrected, tlag);

%     [kernel, mtau, coefNeu]  = estimateKernel(ops, ca - coefNeu * neu, tlag);

    fprintf('Timescale determined is %4.4f samples \n', mtau);
end
kernel = normc(kernel(:));
%%
kernelS     = repmat(kernel, 1, NN);
dcell       = cell(NN,1);

% running minimum subtraction here???

Fsort       = my_conv2(caCorrected, ceil(ops.fs), 1);

Fsort       = sort(Fsort, 1, 'ascend');
baselines   = Fsort(ceil(NT/20), :);

% determine and subtract the neuropil
F1 = caCorrected - bsxfun(@times, ones(NT,1), baselines);

% normalize signal
% sd   = 1/2 * std(F1 - my_conv2(F1, max(2, ops.fs/4), 1), [], 1);

sd   = 1/2 * 1/sqrt(2) * std(F1(2:end, :) - F1(1:end-1, :), [], 1);

F1   = bsxfun(@rdivide, F1 , 1e-12 + sd);

if 1
    % get new kernel
    kerns = exp(-bsxfun(@rdivide, [1:ceil(5*mtau)]',  mtau * [.05 .125 .25 .5 1 2]));
    spfilt = ones([size(kerns,2) size(F1)]);
    for j = 1:size(kerns,2)
        spfilt(j, :,:) = filter(kerns(:,j), 1, gt);
    end

    sts = zeros(size(spfilt,1));
    stF = zeros(size(spfilt,1), 1);
    for k = 1:size(spfilt,3)
        sts = sts + spfilt(:,:,k) * spfilt(:,:,k)';
        stF = stF + spfilt(:,:,k) * F1(:,k);
    end
    coefs = sts \ stF;
    kernel = normc(kerns * coefs);
    kernelS = repmat(kernel, 1, NN);

    plot(kernel)
    drawnow
end

sp = zeros(size(F1));

% run the deconvolution to get fs etc\
parfor icell = 1:size(ca,2)
    [sp(:,icell),dcell{icell}] = ...
        single_step_single_cell(F1(:,icell), Params, kernelS(:,icell), NT, npad,dcell{icell});
end

% rescale baseline contribution
for icell = 1:size(ca,2)
    dcell{icell}.c                      = dcell{icell}.c * sd(icell);
    dcell{icell}.baseline               = baselines(icell);
    dcell{icell}.neuropil_coefficient   = coefNeu(icell);
end

%%


function [mean_norm, stdd] = spp_feature_stats(imdb, roidb, layer, spp_model)
% [mean_norm, stdd] = spp_feature_stats(imdb, roidb, layer, spp_model)
%
% Adapted from spp code written by Ross Girshick
% AUTORIGHTS
% ---------------------------------------------------------
% Copyright (c) 2014, Shaoqing Ren
%
% This file is part of the SPP code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------
% Copyright (c) 2014, Ross Girshick
%
% This file is part of the R-CNN code and is available
% under the terms of the Simplified BSD License provided in
% LICENSE. Please retain this notice and LICENSE if you use
% this file (or any portion of it) in your project.
% ---------------------------------------------------------

imdbs_name = cell2mat(cellfun(@(x) x.name, imdb, 'UniformOutput', false));
conf = spp_config('sub_dir', fullfile(spp_model.cache_name, imdbs_name));
save_file = sprintf('%s/feature_stats_layer_%d.mat', ...
                    conf.cache_dir, layer);

t_start = tic();
try
  ld = load(save_file);
  mean_norm = ld.mean_norm;
  stdd = ld.stdd;
  clear ld;
catch
  % fix the random seed for repeatability
  prev_rng = seed_rand();

  image_idx_in_imdb = cell2mat(cellfun(@(x) 1:length(x.image_ids), imdb, 'UniformOutput', false));
  image_imdb_id = cell2mat(cellfun(@(x, y) ones(1, length(x.image_ids))*y, imdb, num2cell(1:length(imdb)), 'UniformOutput', false));

  num_images = min(length(image_idx_in_imdb), 200);
  boxes_per_image = 200;

  valid_idx = randperm(length(image_idx_in_imdb), num_images);

  ns = [];
  for i = 1:length(valid_idx)
    image_idx = valid_idx(i);
    tic_toc_print('feature stats: %d/%d\n', i, length(valid_idx));

    imdb_idx = image_imdb_id(image_idx);
    d = roidb{imdb_idx}.rois(image_idx_in_imdb(image_idx));
    d.feat = spp_load_cached_poolX_features(spp_model.spp_pooler, spp_model.feat_cache{imdb_idx}, ...
        imdb{imdb_idx}.name, imdb{imdb_idx}.image_ids{image_idx_in_imdb(image_idx)}, d.boxes);
    if isempty(d.feat)
        continue;
    end
    X = d.feat(:, randperm(size(d.feat,2), min(boxes_per_image, size(d.feat,2))));
    X = spp_poolX_to_fcX(X, layer, spp_model, conf.use_gpu);

    ns = cat(2, ns, sqrt(sum(X.^2, 1)));
  end

  mean_norm = mean(ns);
  stdd = std(ns);
  save(save_file, 'mean_norm', 'stdd');

  % restore previous rng
  rng(prev_rng);
end
fprintf('spp_feature_stats_spm in %f seconds.\n', toc(t_start));


function images = loadMNISTImages(filename)
%loadMNISTImages returns a 28x28x[number of MNIST images] matrix containing
%the raw MNIST images

fp = fopen(filename, 'rb');
assert(fp ~= -1, ['Could not open ', filename, '']);

magic = fread(fp, 1, 'int32', 0, 'ieee-be');
assert(magic == 2051, ['Bad magic number in ', filename, '']);

numImages = fread(fp, 1, 'int32', 0, 'ieee-be');
numRows = fread(fp, 1, 'int32', 0, 'ieee-be');
numCols = fread(fp, 1, 'int32', 0, 'ieee-be');

images = fread(fp, inf, 'unsigned char');
images = reshape(images, numCols, numRows, numImages);
images = permute(images,[2 1 3]);

fclose(fp);

% Reshape to #pixels x #examples
images = reshape(images, size(images, 1) * size(images, 2), size(images, 3));
% Convert to double and rescale to [0,1]
images = double(images) / 255;

end


 function job = calcGraph(job, varargin)
 % set up similarity graph for parent grain reconstruction
 %
 % Syntax
 %   job.calcGraph
 %
 % Input
 %  job - @parentGrainReconstructor
 %
 % Output
 %  job.graph - adjacency matrix of the graph
 %
 % Options
 %  threshold - misfit at which the probability is set to 0.5, default is 2 degree
 %  tolerance - range around the threshold where the probability increases from 0 to 1
 %  noC2C     - ignore child to child grain boundaries
 %  noP2C     - ignore parent to child grain boundaries
 %
 % Description
 % The weights of the graph are computed from a cummulative gaussion
 % distribution with mean given by the option |'threshold'| and variance
 % given by the option |'tolerance'|
 %

 threshold = get_option(varargin,'threshold',2*degree);
 tol = get_option(varargin,'tolerance',1.5*degree);

 % OR fit of grain neighbors
 [fit, grainPairs] = calcGBFit(job,varargin{:});

 % turn into probability
 prob = 1 - 0.5 * (1 + erf(2*(fit - threshold)./tol));

 % write into similarity matrix
 job.graph = sparse(grainPairs(:,1),grainPairs(:,2),prob,...
   length(job.grains),length(job.grains));

 % ensure graph is symmetric
 job.graph = max(job.graph, job.graph.');

 end


function F = binary_implies_linearequality(f,X,M,m,eps);

if nargin < 3 || isempty(M)
    [M,m,infbound] = derivebounds(f);
    if infbound
        warning('You have unbounded variables in an implication leading to a lousy big-M relaxation.');
    end
end

if all(m==0)
    lhs = m;
elseif all(m==1)
    lhs = 1-X;
else
    lhs = m.*(1-X);
end
if all(M==0)
    rhs = M;
elseif all(M==1)
    rhs = 1-X;
else
    rhs = M.*(1-X);
end
F = [f <= rhs, -f <= -lhs];


clear all; close all; clc;
%% Auxiliary Classifier Generative Adversarial Network
%% Load Data
load('mnistAll.mat')
trainX = preprocess(mnist.train_images);
trainY = mnist.train_labels;
testX = preprocess(mnist.test_images);
testY = mnist.test_labels;
%% Settings
settings.latentDim = 100; settings.num_labels = 10;
settings.batch_size = 32; settings.image_size = [28,28,1];
settings.lrD = 0.0002; settings.lrG = 0.0002; settings.beta1 = 0.5;
settings.beta2 = 0.999; settings.maxepochs = 50;

%% Initialization
%% Generator
paramsGen.EMW1 = dlarray(...
    initializeGaussian([settings.latentDim,...
    settings.num_labels]));
paramsGen.FCW1 = dlarray(initializeGaussian([128*7*7,...
    settings.latentDim]));
paramsGen.FCb1 = dlarray(zeros(128*7*7,1,'single'));
paramsGen.BNo1 = dlarray(zeros(128,1,'single'));
paramsGen.BNs1 = dlarray(ones(128,1,'single'));
paramsGen.TCW1 = dlarray(initializeGaussian([3,3,128,128]));
paramsGen.TCb1 = dlarray(zeros(128,1,'single'));
paramsGen.BNo2 = dlarray(zeros(128,1,'single'));
paramsGen.BNs2 = dlarray(ones(128,1,'single'));
paramsGen.TCW2 = dlarray(initializeGaussian([3,3,64,128]));
paramsGen.TCb2 = dlarray(zeros(64,1,'single'));
paramsGen.BNo3 = dlarray(zeros(64,1,'single'));
paramsGen.BNs3 = dlarray(ones(64,1,'single'));
paramsGen.CNW1 = dlarray(initializeGaussian([3,3,64,1]));
paramsGen.CNb1 = dlarray(zeros(1,1,'single'));
stGen.BN1 = []; stGen.BN2 = []; stGen.BN3 = [];

%% Discriminator
paramsDis.CNW1 = dlarray(initializeGaussian([3,3,1,16]));
paramsDis.CNb1 = dlarray(zeros(16,1,'single'));
paramsDis.CNW2 = dlarray(initializeGaussian([3,3,16,32]));
paramsDis.CNb2 = dlarray(zeros(32,1,'single'));
paramsDis.BNo1 = dlarray(zeros(32,1,'single'));
paramsDis.BNs1 = dlarray(ones(32,1,'single'));

paramsDis.CNW3 = dlarray(initializeGaussian([3,3,32,64]));
paramsDis.CNb3 = dlarray(zeros(64,1,'single'));
paramsDis.BNo2 = dlarray(zeros(64,1,'single'));
paramsDis.BNs2 = dlarray(ones(64,1,'single'));

paramsDis.CNW4 = dlarray(initializeGaussian([3,3,64,128]));
paramsDis.CNb4 = dlarray(zeros(128,1,'single'));

paramsDis.FCW1 = dlarray(initializeGaussian([1+settings.num_labels,128*4*4]));
paramsDis.FCb1 = dlarray(zeros(1+settings.num_labels,1,'single'));
stDis.BN1 = []; stDis.BN2 = [];

% average Gradient and average Gradient squared holders
avgG.Dis = []; avgGS.Dis = []; avgG.Gen = []; avgGS.Gen = [];
%% Train
numIterations = floor(size(trainX,4)/settings.batch_size);
out = false; epoch = 0; global_iter = 0;
while ~out
    tic;
    shuffleid = randperm(size(trainX,4));
    trainXshuffle = trainX(:,:,:,shuffleid);
    trainYshuffle = trainY(shuffleid);
    fprintf('Epoch %d\n',epoch)
    for i=1:numIterations
        global_iter = global_iter+1;
        noise = gpdl(randn([settings.latentDim,...
            settings.batch_size]),'CB');
        idx = (i-1)*settings.batch_size+1:i*settings.batch_size;
        XBatch=gpdl(single(trainXshuffle(:,:,:,idx)),'SSCB');
        YBatch=gpdl(single(trainYshuffle(idx)),'B');

        [GradGen,GradDis,stGen,stDis] = ...
                dlfeval(@modelGradients,XBatch,YBatch,noise,...
                paramsGen,paramsDis,stGen,stDis,settings);

        % Update Discriminator network parameters
        [paramsDis,avgG.Dis,avgGS.Dis] = ...
            adamupdate(paramsDis, GradDis, ...
            avgG.Dis, avgGS.Dis, global_iter, ...
            settings.lrD, settings.beta1, settings.beta2);

        % Update Generator network parameters
        [paramsGen,avgG.Gen,avgGS.Gen] = ...
            adamupdate(paramsGen, GradGen, ...
            avgG.Gen, avgGS.Gen, global_iter, ...
            settings.lrG, settings.beta1, settings.beta2);

        if i==1 || rem(i,20)==0
            progressplot(paramsGen,stGen,settings);
%             if i==1 || (epoch>=0 && i==1)
%                 h = gcf;
%                 % Capture the plot as an image
%                 frame = getframe(h);
%                 im = frame2im(frame);
%                 [imind,cm] = rgb2ind(im,256);
%                 % Write to the GIF File
%                 if epoch == 0
%                   imwrite(imind,cm,'DCGANmnist.gif','gif', 'Loopcount',inf);
%                 else
%                   imwrite(imind,cm,'DCGANmnist.gif','gif','WriteMode','append');
%                 end
%             end
        end

    end

    elapsedTime = toc;
    disp("Epoch "+epoch+". Time taken for epoch = "+elapsedTime + "s")
    epoch = epoch+1;
    if epoch == settings.maxepochs
        out = true;
    end
end
%% Helper Functions
%% preprocess
function x = preprocess(x)
x = double(x)/255;
x = (x-.5)/.5;
x = reshape(x,28,28,1,[]);
end
%% extract data
function x = gatext(x)
x = gather(extractdata(x));
end
%% gpu dl array wrapper
function dlx = gpdl(x,labels)
dlx = gpuArray(dlarray(x,labels));
end
%% Weight initialization
function parameter = initializeGaussian(parameterSize,sigma)
if nargin < 2
    sigma = 0.05;
end
parameter = randn(parameterSize, 'single') .* sigma;
end
%% Generator
function [dly,st] = Generator(dlx,labels,params,st)
dly = embedding(dlx,labels,params);

% fully connected
dly = fullyconnect(dly,params.FCW1,params.FCb1);
dly = relu(dly);
dly = gpdl(reshape(dly,7,7,128,[]),'SSCB');
if isempty(st.BN1)
    [dly,st.BN1.mu,st.BN1.sig] = batchnorm(dly,...
        params.BNo1,params.BNs1,'MeanDecay',0.8);
else
    [dly,st.BN1.mu,st.BN1.sig] = batchnorm(dly,params.BNo1,...
        params.BNs1,st.BN1.mu,st.BN1.sig,...
        'MeanDecay',.8);
end
% transposed convolution
dly = dltranspconv(dly,params.TCW1,params.TCb1,...
    'Stride',2,'Cropping','same');
dly = relu(dly);
if isempty(st.BN2)
    [dly,st.BN2.mu,st.BN2.sig] = batchnorm(dly,...
        params.BNo2,params.BNs2,'MeanDecay',0.8);
else
    [dly,st.BN2.mu,st.BN2.sig] = batchnorm(dly,params.BNo2,...
        params.BNs2,st.BN2.mu,st.BN2.sig,...
        'MeanDecay',.8);
end
dly = dltranspconv(dly,params.TCW2,params.TCb2,...
    'Stride',2,'Cropping','same');
dly = relu(dly);
if isempty(st.BN3)
    [dly,st.BN3.mu,st.BN3.sig] = batchnorm(dly,...
        params.BNo3,params.BNs3,'MeanDecay',0.8);
else
    [dly,st.BN3.mu,st.BN3.sig] = batchnorm(dly,params.BNo3,...
        params.BNs3,st.BN3.mu,st.BN3.sig,...
        'MeanDecay',.8);
end

dly = dlconv(dly,params.CNW1,params.CNb1,...
            'Padding','same');
% tanh
dly = tanh(dly);
end
%% Discriminator
function [dly,st] = Discriminator(dlx,params,st)
% convolution
%1
dly = dlconv(dlx,params.CNW1,params.CNb1,...
            'Stride',2,'Padding','same');
dly = leakyrelu(dly,0.2);
dly = dropout(dly,.25);
%2
dly = dlconv(dly,params.CNW2,params.CNb2,...
            'Stride',2,'Padding','same');
dly = leakyrelu(dly,0.2);
dly = dropout(dly,.25);
if isempty(st.BN1)
    [dly,st.BN1.mu,st.BN1.sig] = batchnorm(dly,...
        params.BNo1,params.BNs1,'MeanDecay',0.8);
else
    [dly,st.BN1.mu,st.BN1.sig] = batchnorm(dly,params.BNo1,...
        params.BNs1,st.BN1.mu,st.BN1.sig,...
        'MeanDecay',0.8);
end

%3
dly = dlconv(dly,params.CNW3,params.CNb3,...
            'Stride',2,'Padding','same');
dly = leakyrelu(dly,0.2);
dly = dropout(dly,.25);
if isempty(st.BN2)
    [dly,st.BN2.mu,st.BN2.sig] = batchnorm(dly,...
        params.BNo2,params.BNs2,'MeanDecay',0.8);
else
    [dly,st.BN2.mu,st.BN2.sig] = batchnorm(dly,params.BNo2,...
        params.BNs2,st.BN2.mu,st.BN2.sig,...
        'MeanDecay',0.8);
end

%4
dly = dlconv(dly,params.CNW4,params.CNb4,...
            'Stride',1,'Padding','same');
dly = leakyrelu(dly,0.2);
dly = dropout(dly,.25);

% Fully connected
dly = gpdl(reshape(dly,4*4*128,[]),'CB');
dly = fullyconnect(dly,params.FCW1,params.FCb1);
% sigmoid
dly(1,:) = sigmoid(dly(1,:));
% softmax
dly(2:end,:) = softmax(dly(2:end,:));
end
%% modelGradients
function [GradGen,GradDis,stGen,stDis]=modelGradients(x,y,z,paramsGen,...
    paramsDis,stGen,stDis,settings)
y0 = randi([0,9],[settings.batch_size,1]);
ohey0 = onehotencoding(y0,settings.num_labels);
ohey = onehotencoding(y,settings.num_labels);

[fake_images,stGen] = Generator(z,y0,paramsGen,stGen);
d_output_real = Discriminator(x,paramsDis,stDis);
[d_output_fake,stDis] = Discriminator(fake_images,paramsDis,stDis);

% Loss due to true or not
% d_loss = -mean(.9*log(d_output_real+eps)+log(1-d_output_fake+eps));
d_loss_real = -.5*mean(log(d_output_real(1,:)+eps))-...
    .5*mean(log(sum(d_output_real(2:end,:).*ohey,1))+eps);
d_loss_fake = -.5*mean(log(1-d_output_fake(1,:)+eps))-...
    .5*mean(log(sum(d_output_fake(2:end,:).*ohey0,1))+eps);
d_loss = (d_loss_real+d_loss_fake)/2;
g_loss = -.5*mean(log(d_output_fake(1,:)+eps))-...
    .5*mean(log(sum(d_output_fake(2:end,:).*ohey0,1))+eps);

% For each network, calculate the gradients with respect to the loss.
GradGen = dlgradient(g_loss,paramsGen,'RetainData',true);
GradDis = dlgradient(d_loss,paramsDis);
end
%% progressplot
function progressplot(paramsGen,stGen,settings)
r = 2; c = 5;
labels = gpdl(single([0:9]'),'B');
noise = gpdl(randn([settings.latentDim,r*c]),'CB');
gen_imgs = Generator(noise,labels,paramsGen,stGen);
gen_imgs = reshape(gen_imgs,28,28,[]);

fig = gcf;
if ~isempty(fig.Children)
    delete(fig.Children)
end

I = imtile(gatext(gen_imgs));
I = rescale(I);
imagesc(I)
title("Generated Images")
colormap gray

drawnow;
end
%% dropout
function dly = dropout(dlx,p)
if nargin < 2
    p = .3;
end
[n,d] = rat(p);
mask = randi([1,d],size(dlx));
mask(mask<=n)=0;
mask(mask>n)=1;
dly = dlx.*mask;
end
%% embedding
function dly = embedding(dlx,labels,params)
% params EM W (latentDim,num_labels)
%               / (img_elements,num_labels)
maskW = params.EMW1(:,labels+1);
dly = dlx.*maskW;
end
%% one hot encoding
function ohe = onehotencoding(labels,numLabels)
numBatch = length(labels);
ohe = zeros(numLabels,numBatch);

for i = 1:numBatch
    ohe(labels(i)+1,i)=1;
end

end


function test_mu(varargin)
%
% demonstration file for NMFLibrary.
%
% This file illustrates how to use this library.
%
% This file is part of NMFLibrary.
%
% Created by H.Kasai on OCt. 27, 2017
%

    if nargin < 1
        clc;
        clear;
        close all;
        rng('default')

        m = 500;
        n = 100;
        V = rand(m,n);
        rank = 20;
        options = [];
        options.verbose = 2;
        options.max_epoch = 100;
        health_check_mode = false;
    else
        V = varargin{1};
        rank = varargin{2};
        options = varargin{3};
        health_check_mode = true;
    end

    % initialize factor matrices
    [x_init, ~] = generate_init_factors(V, rank, []);
    options.x_init = x_init;

    %% MU variants
    % MU
    options.alg = 'mu';
    [w_nmf_mu, infos_nmf_mu] = fro_mu_nmf(V, rank, options);

    % MU mod
    options.alg = 'mu_mod';
    [w_nmf_mu_mod, infos_nmf_mu_mod] = fro_mu_nmf(V, rank, options);

    % Accelerated MU
    options.alg = 'mu_acc';
    [w_nmf_mu_acc, infos_nmf_mu_acc] = fro_mu_nmf(V, rank, options);

    if ~health_check_mode
        %% plot
        display_graph('iter','cost', {'MU', 'MU-Mod', 'MU-ACC'}, {w_nmf_mu, w_nmf_mu_mod, w_nmf_mu_acc},  {infos_nmf_mu, infos_nmf_mu_mod, infos_nmf_mu_acc});
        display_graph('time','cost', {'MU', 'MU-Mod', 'MU-ACC'}, {w_nmf_mu, w_nmf_mu_mod, w_nmf_mu_acc},  {infos_nmf_mu, infos_nmf_mu_mod, infos_nmf_mu_acc});
    end

end


function [ywarp,dwarp_dt,dwarp_dtheta,d2warp_dthetadt] = outwarp_negpowc1(hyp,y,invflag)
%GPLITE_NOISEFUN Noise function for lite Gaussian Process regression.
%   SN2 = GPLITE_NOISEFUN(HYP,X,NOISEFUN) computes the GP noise function
%   NOISEFUN, that is the variance of observation noise evaluated at test
%   points X. HYP is a single column vector of noise function
%   hyperparameters. NOISEFUN is a numeric array whose elements specify
%   features of the noise function, as follows:
%
%   See also GPLITE_COVFUN, GPLITE_MEANFUN.

if nargin < 2; y = []; end
if nargin < 3 || isempty(invflag); invflag = false; else; invflag = true; end

if invflag && nargout > 1
    error('outwarp_fun:InverseOnly', ...
        ['When calling for the inverse output warping function, only one function output is expected.']);
end

%--------------------------------------------------------------------------
% CUSTOM: Number of hyperparameters
Noutwarp = 2;       % # hyperparameters of the output warping function
%--------------------------------------------------------------------------

N = size(y,1);      % Number of training points

% Return number of output warping function hyperparameters and additional info
if ischar(hyp)
    ywarp = Noutwarp;
    if nargout > 1

        if isempty(y); y = [0;1]; end

        % Initialize bounds for all hyperparameters
        outwarp_info.LB = -Inf(1,Noutwarp);
        outwarp_info.UB = Inf(1,Noutwarp);
        outwarp_info.PLB = -Inf(1,Noutwarp);
        outwarp_info.PUB = Inf(1,Noutwarp);
        outwarp_info.x0 = NaN(1,Noutwarp);

        %------------------------------------------------------------------
        % CUSTOM: Initialize hyperparameter bounds and other details

        % Threshold parameter
        outwarp_info.LB(1) = min(y);
        outwarp_info.UB(1) = max(y);
        outwarp_info.PLB(1) = min(y);
        outwarp_info.PUB(1) = max(y);
        outwarp_info.x0(1) = NaN;

        % Power exponent k (log space)
        outwarp_info.LB(2) = -Inf;
        outwarp_info.UB(2) = Inf;
        outwarp_info.PLB(2) = -3;
        outwarp_info.PUB(2) = 3;
        outwarp_info.x0(2) = 0;

        %------------------------------------------------------------------

        % Assign handle of current output warping function
        outwarp_info.outwarpfun = str2func(mfilename);

        % Plausible starting point
        idx_nan = isnan(outwarp_info.x0);
        outwarp_info.x0(idx_nan) = 0.5*(outwarp_info.PLB(idx_nan) + outwarp_info.PUB(idx_nan));

        dwarp_dt = outwarp_info;

    end

    return;
end

[Nhyp,Ns] = size(hyp);      % Hyperparameters and samples

if Nhyp ~= Noutwarp
    error('outwarp_fun:WrongLikHyp', ...
        ['Expected ' num2str(Noutwarp) ' output warping function hyperparameters, ' num2str(Nhyp) ' passed instead.']);
end
if Ns > 1
    error('outwarp_fun:nosampling', ...
        'Output warping function output is available only for one-sample hyperparameter inputs.');
end

%--------------------------------------------------------------------------
% CUSTOM: Compute output warping function and gradients

% Read hyperparameters
y0 = hyp(1);
k = exp(hyp(2));

% Compute output warping or inverse warping
ywarp = y;
idx = y < y0;
if invflag      % Inverse output warping
    ywarp(idx) = y0 + 1 - (1 + k*y0 - k*y(idx)).^(1/k);
else            % Direct output warping
    delta = (1 + y0 - y(idx));
    deltak = delta.^k;
    ywarp(idx) = y0 - deltak/k + 1/k;
end

if nargout > 1
    % First-order derivative of output warping function in output space
    dwarp_dt = ones(size(y));
    deltakm1 = delta.^(k-1);

    dwarp_dt(idx) = deltakm1;

    if nargout > 2
        % Gradient of output warping function wrt hyperparameters
        dwarp_dtheta = zeros(N,Noutwarp);

        dwarp_dtheta(idx,1) = 1 - deltakm1;                         % y0
        dwarp_dtheta(idx,2) = -deltak.*log(delta) + deltak/k - 1/k; % log(k)

        if nargout > 3
            % Gradient of derivative of output warping function
            d2warp_dthetadt = zeros(N,Noutwarp);

            d2warp_dthetadt(idx,1) = (k-1)*delta.^(k-2);        % y0
            d2warp_dthetadt(idx,2) = k*deltakm1.*log(delta);    % log(k)

        end

    end
end

end


function X = sigmrnd(P)
%     X = double(1./(1+exp(-P)))+1*randn(size(P));
    X = double(1./(1+exp(-P)) > rand(size(P)));
end


function voxels = mask2voxel(mask)
% convert from 3-D mask to voxel list in canonical orientation
%
% :Usage:
% ::
%
%     function voxels = mask2voxel(mask)
%
% [i j k] = row, column, slice
%
% [x y z] in brain if brain is in analyze format
%
% (x is rows, y is columns, z is slices)
%
% ..
%    Tor Wager, 10/17/01
%
%    Refactored to be orders of magnitude faster
%    Matthew Davidson, 6/1/2006
% ..

% ..
%     Loop below is very slow. The find() function is much faster.
%
%     voxels = [];
%     index = 1;
%     for i = 1:size(mask,1)
%         for j = 1:size(mask,2)
%             for k = 1:size(mask,3)
%                 if mask(i,j,k) > 0, voxels(index,:) = [i j k];,index = index+1;,end
%             end
%         end
%     end
% ..

    [X Y Z] = ind2sub(size(mask), find(mask > 0));
    voxels = [X Y Z];
    voxels = sortrows(voxels);

end


% Run example 3 to test multi-scale meshing, bound_courant_number, and interp
clearvars; clc

addpath('..')
addpath(genpath('../utilities/'))
addpath(genpath('../datasets/'))
addpath(genpath('../m_map/'))

ERR_TOL = 0.05;
ERR2_TOL = 0.01;
QUAL_TOL = 0.25;
Re2 = 111^2;

bbox = [-71.6 42.7; -64 30; -80 24; -85 38; -71.6 42.7]; %polygon boubox
min_el    = 1e3;  		        % minimum resolution in meters.
max_el    = 50e3; 		        % maximum resolution in meters.
wl        = 30;                 % 60 elements resolve M2 wavelength.
dt        = [50,0.5,6.0];      % Automatically set timestep based on nearshore res
grade     = 0.15;               % mesh grade in decimal percent.
R         = 3; 			        % Number of elements to resolve feature.

dem       = 'SRTM15+.nc';
coastline = 'GSHHS_f_L1';
gdat1 = geodata('shp',coastline,'dem',dem,'h0',min_el,...
                'bbox',bbox);

fh1 = edgefx('geodata',gdat1,...
             'fs',R,'wl',wl,'max_el',max_el,...
             'dt',dt,'g',grade);

mshopts = meshgen('ef',fh1,'bou',gdat1,...
                  'plot_on',1,'proj','lam');
mshopts = mshopts.build;

m = mshopts.grd;

m = interp(m,gdat1);

%  Set desired courant criteria and time step parameter
dt     = 50; %[s]
max_cr = 4.0;
min_cr = 0.25;
max_it = 20;
m = bound_courant_number(m,dt,max_cr,min_cr,max_it);

Crnew = CalcCFL(m,dt);

if sum(Crnew > max_cr) > 0
    error(['Unable to bound maximum Courant number. Got ',...
        num2str(max(Crnew)),' expecting < ' num2str(max_cr)]);
else
    disp(['Bounded maximum Courant number. Got ',...
        num2str(max(Crnew)),' expecting < ' num2str(max_cr)]);
end
if sum(Crnew < min_cr) > 0
    error(['Unable to bound minimum Courant number. Got ',...
        num2str(min(Crnew)), ' expecting > ' num2str(min_cr)]);
else
    disp(['Bounded minimum Courant number. Got ',...
        num2str(min(Crnew)), ' expecting > ' num2str(min_cr)]);
end

disp('Passed: ECGC');


function test23
%TEST23 test cs_dmspy
%
% Example:
%   test23
% See also: testall

%   Copyright 2006-2007, Timothy A. Davis.
%   http://www.cise.ufl.edu/research/sparse

clear functions

randn ('state', 0) ;
rand ('state', 0) ;

clf

for trials = 1:1000

    % m = fix (100 * rand (1)) ;
    n = fix (100 * rand (1)) ;
    m = n ;
    % d = 0.1 * rand (1) ;
    d = rand (1) * 4 * max (m,n) / max (m*n,1) ;
    A = sprandn (m,n,d) ;
    % S = sprandn (m,m,d) + speye (m) ;

    if (~ispc)
        if (rand ( ) > .5)
            A = A + 1i * sprand (A) ;
        end
    end

    cs_dmspy (A) ;
    drawnow

    % pause
end


function amin_index = i4vec_amin_index ( n, a )

%*****************************************************************************80
%
%% I4VEC_AMIN_INDEX returns the index of the smallest magnitude in an I4VEC.
%
%  Discussion:
%
%    An I4VEC is a vector of integer values.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 November 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries to be checked.
%
%    Input, integer A(N), the vector to be checked.
%
%    Output, integer AMIN_INDEX, the entry of the smallest magnitude.
%
  if ( n <= 0 )

    amin_index = 0;

  else

    aamin = a(1);
    amin_index = 1;

    for i = 2 : n

      if ( abs ( a(i) ) < aamin )
        aamin = abs ( a(i) );
        amin_index = i;
      end

    end

  end

  return
end


function [S,f,R,varS,zerosp,C,Serr]=mtspectrumsegpt(data,win,params,segave,fscorr)
% Multi-taper segmented spectrum for a univariate binned point process
%
% Usage:
%
% [S,f,R,varS,zerosp,C,Serr]=mtspectrumsegpt(data,win,params,segave,fscorr)
% Input:
% Note units have to be consistent. See chronux.m for more information.
%       data (structure array of one channel of spike times;
%            also accepts 1d vector of spike times) -- required
%       win  (duration of the segments) - required.
%       params: structure with fields tapers, pad, Fs, fpass, err
%       - optional
%           tapers : precalculated tapers from dpss or in the one of the following
%                    forms:
%                   (1) A numeric vector [TW K] where TW is the
%                       time-bandwidth product and K is the number of
%                       tapers to be used (less than or equal to
%                       2TW-1).
%                   (2) A numeric vector [W T p] where W is the
%                       bandwidth, T is the duration of the data and p
%                       is an integer such that 2TW-p tapers are used. In
%                       this form there is no default i.e. to specify
%                       the bandwidth, you have to specify T and p as
%                       well. Note that the units of W and T have to be
%                       consistent: if W is in Hz, T must be in seconds
%                       and vice versa. Note that these units must also
%                       be consistent with the units of params.Fs: W can
%                       be in Hz if and only if params.Fs is in Hz.
%                       The default is to use form 1 with TW=3 and K=5
%
%	        pad		    (padding factor for the FFT) - optional (can take values -1,0,1,2...).
%                    -1 corresponds to no padding, 0 corresponds to padding
%                    to the next highest power of 2 etc.
%			      	 e.g. For N = 500, if PAD = -1, we do not pad; if PAD = 0, we pad the FFT
%			      	 to 512 points, if pad=1, we pad to 1024 points etc.
%			      	 Defaults to 0.
%           Fs   (sampling frequency) - optional. Default 1.
%           fpass    (frequency band to be used in the calculation in the form
%                                   [fmin fmax])- optional.
%                                   Default all frequencies between 0 and Fs/2
%           err  (error calculation [1 p] - Theoretical error bars; [2 p] - Jackknife error bars
%                                   [0 p] or 0 - no error bars) - optional. Default 0.
%       segave - (0 for don't average over segments, 1 for average) - optional - default  1
%       fscorr   (finite size corrections, 0 (don't use finite size corrections) or
%                1 (use finite size corrections) - optional
%                (available only for spikes). Defaults 0.
% Output:
%       S       (spectrum in form frequency x segments if segave=0; function of frequency if segave=1)
%       f       (frequencies)
%       R       (spike rate)
%       varS    (variance of the spectrum as a function of frequency)
%       zerosp  (0 for segments in which spikes were found, 1 for segments
%       C       (covariance matrix of the log spectrum - frequency x
%       frequency matrix)
%       Serr    (error bars) - only if err(1)>=1

if nargin < 2; error('Need data and segment information'); end;
if nargin < 3; params=[]; end;
if nargin < 4 || isempty(segave); segave=1; end;
[tapers,pad,Fs,fpass,err,trialave,params]=getparams(params);
clear params trialave
if nargin < 5 || isempty(fscorr); fscorr=0;end;

if nargout > 4 && err(1)==0; error('cannot compute error bars with err(1)=0; change params and run again'); end;

dtmp=change_row_to_column(data);
T=max(dtmp); % total length of data
minT=min(dtmp);
E=minT:win:T-win; % fictitious event triggers
win=[0 win]; % use window length to define left and right limits of windows around triggers
dtmp=createdatamatpt(dtmp,E,win); % create segmented data set
[mintime,maxtime]=minmaxsptimes(dtmp);
dt=1/Fs; % sampling time
t=mintime-dt:dt:maxtime+dt; % time grid for prolates
N=length(t); % number of points in grid for dpss
nfft=max(2^(nextpow2(N)+pad),N); % number of points in fft of prolates
[f,findx]=getfgrid(Fs,nfft,fpass); % get frequency grid for evaluation
tapers=dpsschk(tapers,N,Fs); % check tapers
[J,Msp,Nsp]=mtfftpt(dtmp,tapers,nfft,t,f,findx);% mt fft for point process times
R=Msp*Fs;
S=squeeze(mean(conj(J).*J,2)); % spectra of non-overlapping segments (averaged over tapers)
if segave==1; SS=squeeze(mean(S,2));R=mean(R);else;SS=S;end;% mean of the spectrum averaged across segments
if nargout > 3
    lS=log(SS); % log spectrum for nonoverlapping segments
%     varS=var(lS,1,2); % variance of log spectrum
    varS=var(lS',1)';% variance of the log spectrum R13
    if nargout > 4
       zerosp=zeros(1,size(data,2));
       zerosp(Nsp==0)=1;
       if nargout > 5
          C=cov(lS'); % covariance matrix of the log spectrum
          if nargout==7;
             if fscorr==1;
                Serr=specerr(SS,J,err,segave,Nsp);
             else
                Serr=specerr(SS,J,err,segave);
             end;
          end;
       end;
    end;
end;
S=SS;


function patches = extract_patches(image, keypoints, patch_radius)
% EXTRACT_PATCHES - Extract local patches for all keypoints in an image.
%   image:
%       Gray-scale single image containing the keypoints.
%   keypoints:
%       The keypoints with each row as x, y, scale, orientation.
%   patch_radius:
%       The desired patch radius in pixels.
%
%   patches:
%       The local patches around each keypoint with normalized intensities.
%
% Copyright 2017: Johannes L. Schoenberger <jsch at inf.ethz.ch>

if size(keypoints, 1) == 0
    patches = zeros(0, 2 * patch_radius + 1, 2 * patch_radius + 1);
    return
end

[~, patches, ~] = vl_covdet(image, ...
                            'frames', vl_frame2oell(keypoints'), ...
                            'descriptor', 'patch', ...
                            'patchresolution', patch_radius);
patches = reshape(patches, [2 * patch_radius + 1, 2 * patch_radius + 1, ...
                            size(keypoints, 1)]);
patches = permute(patches, [3, 1, 2]);

end


function tt=simular(robot,t,y,mode)

    global radio
    global precision

    drawrobot3d(robot,[0 0 0 0 0 0])
    axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
    adjust_view()
    f=length(t);
    d=1;

    pause(3)
    %Recorrido desde posicion inicial hasta inicio pintado
     tin=inicial(y,t,robot);
     in=length(tin);
     for i=1:in;
        T=tin{i};
        q = inversekinematic_kuka_kr160_r1570_nanoC(robot, T) ;
        drawrobot3d(robot, q)

        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
        hold on

         treal=directkinematic(robot,q(:,1));
         pin(:,i)=treal(1:3,4);
         tt{d}=treal;
         d=d+1;

         Representacion_en_esfera(y);
         hold on
        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
         switch mode
             case 'trayectoria'
                 plot3(pin(1,:),pin(2,:),pin(3,:));

             case 'letras'

         end
       % pause(0.005);
    end

    %Pintado esfera
    let=1;
    frase=[0; 0; 0];
    for i=1:f;
        T=y*t{i};
        q = inversekinematic_kuka_kr160_r1570_nanoC(robot, T) ;
        drawrobot3d(robot, q)

        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
        hold on
        treal=directkinematic(robot,q(:,1));
        tt{d}=treal;
        d=d+1;

            if abs((treal(1,4)-y(1,4))^2+(treal(2,4)-y(2,4))^2+(treal(3,4)-y(3,4))^2-radio^2) < precision
                frase(:,let)=treal(1:3,4);
                let=let+1;
            end
            p(:,i)=treal(1:3,4);

        %end
         Representacion_en_esfera(y);
         hold on
        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
         switch mode
             case 'trayectoria'
                  plot3(p(1,:),p(2,:),p(3,:));
                  plot3(pin(1,:),pin(2,:),pin(3,:));
             case 'letras'
                  plot3(frase(1,:),frase(2,:),frase(3,:));
         end

       % pause(0.005);
    end

    %Recorrido desde posicion final del pintado hasta posicion inicial
     tfin=final(y,t,robot);
     fin=length(tfin);
     for i=1:fin;
        T=tfin{i};
        q = inversekinematic_kuka_kr160_r1570_nanoC(robot, T) ;
        drawrobot3d(robot, q)

        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
        hold on
        treal=directkinematic(robot,q(:,1));
        tt{d}=treal;
        d=d+1;

            pfin(:,i)=treal(1:3,4);
            %axis([-1 1 -1 1]);

       % end
        Representacion_en_esfera(y);
        hold on
        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
         switch mode
             case 'trayectoria'
                  plot3(p(1,:),p(2,:),p(3,:));
                  plot3(pin(1,:),pin(2,:),pin(3,:));
                  plot3(pfin(1,:),pfin(2,:),pfin(3,:));
             case 'letras'
                 plot3(frase(1,:),frase(2,:),frase(3,:),'r');

         end

       % pause(0.005);
    end

    drawrobot3d(robot, [0 0 0 0 0 0])
    hold on

    Representacion_en_esfera(y);

        axis([-1.5 1.50 -1.5 0.75 -0.25 1.75]);
         switch mode
             case 'trayectoria'
                  plot3(p(1,:),p(2,:),p(3,:));
                  plot3(pin(1,:),pin(2,:),pin(3,:));
                  plot3(pfin(1,:),pfin(2,:),pfin(3,:));
             case 'letras'
                 %figure
                  %Representacion_en_esfera(y);
                 %hold on
                  plot3(frase(1,:),frase(2,:),frase(3,:),'r');

         end
end


function t=getInvHaarTransform(im,N)
h=haarmtx(N);
t=h'*im*h;


% ------------------------------------------------------------------------
%  Copyright (C)
%  Universitat Politecnica de Catalunya BarcelonaTech (UPC) - Spain
%  University of California Berkeley (UCB) - USA
%
%  Jordi Pont-Tuset <jordi.pont@upc.edu>
%  Pablo Arbelaez <arbelaez@berkeley.edu>
%  June 2014
% ------------------------------------------------------------------------
% This file is part of the MCG package presented in:
%    Arbelaez P, Pont-Tuset J, Barron J, Marques F, Malik J,
%    "Multiscale Combinatorial Grouping,"
%    Computer Vision and Pattern Recognition (CVPR) 2014.
% Please consider citing the paper if you use this code.
% ------------------------------------------------------------------------
function area = box_area( bbox )
    up    = bbox(1);
    left  = bbox(2);
    down  = bbox(3);
    right = bbox(4);

    area = (down-up+1)*(right-left+1);
end


function Ft=frametight(F);
%FRAMETIGHT  Construct the canonical tight frame
%   Usage: Ft=frametight(F);
%
%   `Ft=frametight(F)` returns the canonical tight frame of *F*.
%
%   The canonical tight frame can be used to get perfect reconstruction if
%   it is used for both analysis and synthesis. This is demonstrated in the
%   following example:::
%
%     % Create a frame and its canonical tight
%     F=frame('dgt','hamming',32,64);
%     Ft=frametight(F);
%
%     % Compute the frame coefficients and test for perfect
%     % reconstruction
%     f=gspi;
%     c=frana(Ft,f);
%     r=frsyn(Ft,c);
%     norm(r(1:length(f))-f)
%
%   See also: frame, framepair, framedual

complainif_notenoughargs(nargin,1,'FRAMETIGHT');
complainif_notvalidframeobj(F,'FRAMETIGHT');

% Default operation, works for a lot of frames
Ft=F;

% Handle the windowed transforms
switch(F.type)
  case {'dgt','dgtreal','dwilt','wmdct','filterbank','ufilterbank',...
        'nsdgt','unsdgt','nsdgtreal','unsdgtreal'}

    Ft=frame(F.type,{'tight',F.g},F.origargs{2:end});

  case {'filterbankreal','ufilterbankreal'}
    Ft=frame(F.type,{'realtight',F.g},F.origargs{2:end});

  case 'gen'
    [U,sv,V] = svd(F.g,'econ');
    Ft=frame('gen',U*V');

  case 'tensor'
    for ii=1:F.Nframes
        tight_frames{ii}=frametight(F.frames{ii});
    end;
    F=frame('tensor',tight_frames{:});

  case 'fusion'
    tight_w=1./F.w;
    for ii=1:F.Nframes
        tight_frames{ii}=frametight(F.frames{ii});
    end;
    Ft=frame('fusion',tight_w,tight_frames{:});

  case 'ufwt'
    % The canonical tight made from ufwt might not keep the iterated
    % filterbank structure
    [g,a] = wfbt2filterbank({F.g,F.J,'dwt'});
    g = comp_filterbankscale(g,a,F.flags.scaling);

    Ft = frametight(frame('filterbank',g,ones(numel(g),1),numel(g)));

  case 'uwfbt'
    % The canonical tight made from uwfbt might not keep the iterated
    % filterbank structure
    [g,a] = wfbt2filterbank(F.g,F.J);
    g = comp_filterbankscale(g,a,F.flags.scaling);

    Ft = frametight(frame('filterbank',g,ones(numel(g),1),numel(g)));

  case 'uwpfbt'
    % The canonical tight made from uwpfbt might not keep the iterated
    % filterbank structure
    [g, a] = wpfbt2filterbank(F.g,F.flags.interscaling);
    g = comp_filterbankscale(g,a,F.flags.scaling);

    Ft = frametight(frame('filterbank',g,ones(numel(g),1),numel(g)));

  case 'fwt'
    is_basis = abs(sum(1./F.g.a)-1)<1e-6;
    is_tight = F.info.istight;

    if is_basis && is_tight
        Ft = F;
    else
        error(['%s: Cannot create the canonical tight frame with the ',...
               'same structure. Consider casting the system to an ',...
               'uniform filterbank.'],...
               upper(mfilename));
    end

  case 'wfbt'
    is_basis = all(cellfun(@(nEl) abs(sum(1./nEl.a)-1)<1e-6,F.g.nodes));
    is_tight = F.info.istight;

    if is_basis && is_tight
        Ft = F;
    else
        error(['%s: Cannot create the canonical tight frame with the ',...
               'same structure. Consider casting the system to an ',...
               'uniform filterbank.'],...
               upper(mfilename));
    end

   case 'wpfbt'
     % WPFBT is too wierd.
     error(['%s: Canonical tight frame of wpfbt might not keep the ',...
           'same structure. '],upper(mfilename))

end;

switch(F.type)
    case {'ufwt','uwfbt','uwpfbt'}
      warning(sprintf(['%s: The canonical tight system does not preserve ',...
                     'the iterated filterbank structure.'],...
                      upper(mfilename)));
end

% Treat the fixed length frames
if isfield(F,'fixedlength') && F.fixedlength && isfield(F,'L')
   Ft = frameaccel(Ft,F.L);
   Ft.fixedlength = 1;
end


function [ y, m, d, ierror ] = ymd_check_gregorian ( y, m, d )

%*****************************************************************************80
%
%% YMD_CHECK_GREGORIAN checks a Gregorian YMD date.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 June 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input/output, integer Y, M, D, the YMD date, which may
%    be corrected if necessary and possible.
%
%    Output, integer IERROR, is 0 if the date is legal.
%

%
%  Check the month.
%
  [ y, m, ierror ] = ym_check_gregorian ( y, m );

  if ( ierror ~= 0 )
    return
  end
%
%  Check the day.
%
  [ y, m, d ] = day_borrow_gregorian ( y, m, d );

  [ y, m, d ] = day_carry_gregorian ( y, m, d );

  return
end


function [ssx, y2] = dofit(y, Qd)
%DOFIT Do constrained least squares fit and reduce data for subsequent fits

% Fit y to design matrix in null space
y2 = Qd' * y;            % rotate y into that space: predicted y value
ssx = norm(y2)^2;        % sum of squares explained by fit