function [D,DJacob,DHess,pDpt]=DCoordTurn2D(x,q0,qTurn,qLin)
%DCOORDTURN2D The continuous-time diffusion matrix function for a 2D
%             coordinated turn model with a Cartesian state. The turn rate
%             can be specified in terms of a turn rate in radians per
%             second, or in terms of a transversal acceleration.
%             Additionally, a linear acceleration can be given. This
%             diffusion matrix goes with the drift functions
%             aCoordTurn2DOmega and aCoordTurn2DTrans.
%
%INPUTS: x The target state for 2D motion. If there is no linear
%          acceleration (acceleration along the direction of motion), then
%          x can either be x=[x;y;xdot;ydot;omega], where omega is the turn
%          rate estimate in radians per second counterclockwise from the
%          x-axis or x=[x;y;xdot;ydot;at] where at is the transversal
%          acceleration, which is orthogonal to the velocity and is defined
%          such that positive values of at map to positive values of omega.
%          If there is a linear acceleration, then the target state is
%          either x=[x;y;xdot;ydot;omega;al] where omega is the turn rate
%          and al is the linear acceleration or the target state is
%          x=[x;y;xdot;ydot;at;al] if the turn is expressed in terms of a
%          transversal acceleration. The dimensionality of the state is
%          used to determine whether a linear acceleration component is
%          present. The linear acceleration component changes the speed.
%          That means that it acts in the direction of the velocity vector.
%          The number of columns in x determine how many copies of D are
%          returned.
%       q0 The power spectral density of the process noise of the velocity
%          components. It is assumed to be the same in both dimensions. It
%          covers perturbations from an ideal coordinated turn trajectory
%          and has units of m^2/s^3. If no process noise is desired for the
%          velocity (i.e. all perturbations should be covered by noise on
%          the turn component and on the linear acceleration), then a value
%          of zero should be passed.
%    qTurn If the turn is specified in terms of a turn rate in radians per
%          second, then this is the power spectral density of the turn rate
%          noise having units of radians squared per seconds cubed. If the
%          turn is expressed in terms of a transverse acceleration, then
%          this is the power spectral density of the transverse
%          acceleration noise, having units of m^2/s^5.
%     qLin This parameter is only needed if a linear acceleration is
%          present. It is the power spectral density of the linear
%          acceleration noise having units of m^2/s^5.
%
%OUTPUTS: D The diffusion matrix of a 2D continuous-time turning model
%           where the velocity is given as a Cartesian vector. If x has
%           N columns, then N copies of D are returned with D(:,:,i) being
%           the ith one.
%   DJacob, DHess The xDimXmXxDim, xDimXmXxDimXxDim matrices of first and
%           second partial derivatives of the elements of D with respect to
%           x. These are all zero, since D is a constant. it is the same
%           for all D and is not repeated N times.
%      pDpt The xDimX2 partial derivative of D with respect to time. This
%           is all zeros, because D is a constant.
%
%The basic 2D coordinated turn model in Cartesian coordinates is described
%in Section VA of [1]. When the turn rate is something that must be
%estimated, it is assumed that the continuous-time turn rate model is
%omegaDot=-(1/tau)*Omega+noise
%Note that the ordering of the state elements assumed by this function
%differs from the ordering of the state elements assumed in the paper.
%
%The 2D coordinates turn model in Cartesian coordinates is also described
%in  Chapter 4.2.3 of [2].
%
%The concept of using the transversal acceleration instead of the turn rate
%is not discussed in either of those references. It is, however, mentioned
%in [3], though no differential equations are given and a more detailed
%reference cited therein is a hard-to-get dissertation in French. The use
%of transversal acceleration is discussed in more detail in [4], though
%expressions are given when considering the 2D velocity are broken into
%components of heading and speed rather than in Cartesian space. The
%generalization to Cartesian space is not difficult and is done here.
%
%A starting point for setting q0 is to use processNoiseSuggest with
%'PolyKal-ROT' and order=1. The noise must cover small velocity deviations
%from the ideal turn model. A starting point for setting qTurn when a turn
%rate is given is to use processNoiseSuggest with 'PolyKal-ROT' and
%order=1. A starting point for setting qTurn when using a linear
%acceleration and for qLin is to use processNoiseSuggest with 'PolyKal-ROT'
%and order=2. The order chosen in the suggestion function just depends on
%the number of derivatives of time present.
%
%The corresponding drift functions are given by the functions
%aCoordTurn2DOmega and aCoordTurn2DTrans. The corresponding discrete-time
%functions are FCoordTurn2D and QCoordTurn. However, note that the
%discrete-time functions with unknown noise is a direct-discrete model and
%not a discretization of the continuous-time model.
%
%REFERENCES:
%[1] X. R. Li and V. P. Jilkov, "Survey of maneuvering target tracking.
%    Part I: Dynamic models," IEEE Transactions on Aerospace and Electronic
%    Systems, vol. 39, no. 4, pp. 1333-1364, Oct. 2003.
%[2] S. Blackman and R. Popoli, Design and Analysis of Modern Tracking
%    Systems. Norwood, MA: Artech House, 1999.
%[3] P. Vacher, I. Barret, and M. Gauvrit, "Design of a tracking algorithm
%    for an advanced ATC system," in Multitarget-Multisensor Tracking:
%    Applications and Advances, Y. Bar-Shalom, Ed. Norwood, MA: Artech
%    House, 1992, vol. II, ch. 1.
%[4] H. A. P. Blom, R. A. Hogendoorn, and B. A. van Doorn, "Design
%    of a multisensor tracking system for advanced air traffic control," in
%    Multitarget-Multisensor Tracking: Applications and Advances, Y. Bar-
%    Shalom, Ed. Norwood, MA: Artech House, 1992, vol. II, ch. 2.
%
%July 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

N=size(x,2);

rootQ0=sqrt(q0);
rootQTurn=sqrt(qTurn);

numDim=length(x);
switch(numDim)
    case 5%There is no linear acceleration
        %Equation 61 in Li's paper combined with Equation 67.
        D=[0,       0,      0;%Row for x-component noise.
           0,       0,      0;%Row for y-component noise.
           rootQ0,  0,      0;%Row for velocity-x noise.
           0,       rootQ0, 0;%Row for velocity-y noise.
           0,       0,      rootQTurn];%Row for turn noise.
       m=3;
    case 6%There is a linear acceleration component.
        rootQLin=sqrt(qLin);
        %Similar to Equation 61 in Li's paper combined with Equation 67,
        %but with an added row for noise in the linear acceleration
        %component.
        D=[0,       0,      0,  0;%Row for x-component noise.
           0,       0,      0,  0;%Row for y-component noise.
           rootQ0,  0,      0,  0;%Row for velocity-x noise.
           0,       rootQ0, 0,  0;%Row for velocity-y noise.
           0,       0, rootQTurn,0;%Row for turn rate noise.
           0,       0,      0,  rootQLin];%Row for linear accel. noise.
       m=4;
    otherwise
        error('The length of x is neither 5 nor 6.');
end

if(nargout>1)
    DJacob=zeros(numDim,m,numDim);
    if(nargout>2)
        DHess=zeros(numDim,m,numDim,numDim);
        if(nargout>3)
            pDpt=zeros(numDim,m);
        end
    end
end

if(N>1)
   D=repmat(D,[1,1,N]);
end

end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function z=getUVDirection(zC,zRx,M,includeW)
%%GETUVDIRECTION Convert a position into local direction cosines [u;v] or
%         [u;v;w]. Direction cosines u and v are just the x and y
%         coordinates of a unit vector from the receiver to the target in
%         the coordinate system at the receiver. This basically assumes
%         that the boresight direction of the receiver is the z axis.
%         Assuming the target is in front of the receiver, the third unit
%         vector coordinate is not needed. However, with the includeW
%         option, it can be provided, resulting in r-u-v-w coordinates.
%
%INPUT: zC A 3XN matrix of points in global [x;y;z] Cartesian coordinates.
%      zRx The 3XN [x;y;z] location vectors of the receivers in Cartesian
%          coordinates.  If this parameter is omitted or an empty matrix is
%          passed, then the receivers are assumed to be at the origin. If
%          only a single vector is passed, then the receiver location is
%          assumed the same for all of the target states being converted.
%        M A 3X3XN hypermatrix of the rotation matrices to go from the
%          alignment of the global coordinate system to that at the
%          receiver. The z-axis of the local coordinate system of the
%          receiver is the pointing direction of the receiver. If omitted
%          or an empty matrix is passed, then it is assumed that the local
%          coordinate system is aligned with the global and M=eye(3) --the
%          identity matrix is used. If only a single 3X3 matrix is passed,
%          then is=t is assumed to be the same for all of the N
%          conversions. Typically, if includeW is false, it doesn't make
%          sense to return the u-v values that are not local, so one will
%          usually omit M in that instance.
%  includeW An optional boolean value indicating whether a third direction
%          cosine component should be included. The u and v direction
%          cosines are two parts of a 3D unit vector. Generally, one might
%          assume that the target is in front of the sensor, so the third
%          component would be positive and is not needed. However, the
%          third component can be included if ambiguity exists. The default
%          if this parameter is omitted or an empty matrix is passed is
%          false.
%
%OUTPUT: z The 2XN (or 3XN if includeW is true) matrix of direction cosines
%          of the converted points in the form [u;v] or [u;v;w].
%
%Details of the conversion are given in [1].
%
%REFERENCES:
%[1] David F. Crouse , "Basic tracking using nonlinear 3D monostatic and
%    bistatic measurements," IEEE Aerospace and Electronic Systems
%    Magazine, vol. 29, no. 8, Part II, pp. 4-53, Aug. 2014.
%
%February 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

N=size(zC,2);

if(nargin<4||isempty(includeW))
    includeW=false;
end

if(nargin<3||isempty(M))
    M=repmat(eye(3),[1,1,N]);
elseif(size(M,3)==1)
    M=repmat(M,[1,1,N]);
end

if(nargin<2||isempty(zRx))
    zRx=zeros(3,N);
elseif(size(zRx,2)==1)
    zRx=repmat(zRx,[1,N]);
end

%Allocate space for the return values.
if(includeW==true)
    z=zeros(3,N);
else
    z=zeros(2,N);
end
for curPoint=1:N
    %The target location in the receiver's coordinate system.
    zCL=M(:,:,curPoint)*(zC(:,curPoint)-zRx(1:3,curPoint));

    %Perform the conversion.
    r1=norm(zCL);%Receiver to target.

    u=zCL(1)/r1;
    v=zCL(2)/r1;

    z(1:2,curPoint)=[u;v];
    if(includeW)
        z(3,curPoint)=zCL(3)/r1;
    end
end
end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function rf=v_lpcla2rf(la)
%V_LPCLA2RF Convert log areas to reflection coefficients RF=(LA)

%      Copyright (C) Mike Brookes 1997
%      Version: $Id: v_lpcla2rf.m 10865 2018-09-21 17:22:45Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[nf,p2]=size(la);
rf=-tanh((la(:,1:p2-1)-la(:,2:p2))/2);


function enter_ax_an_angs

global phi theta psi rad deg x y z gamma delta alpha

naner=false;

gamman=str2num(get(gamma,'String'));
if length(gamman)==0
    naner=true;
end

deltan=str2num(get(delta,'String'));
if length(deltan)==0
    naner=true;
end

alphan=str2num(get(alpha,'String'));
if length(alphan)==0
    naner=true;
end

if naner
    nan_error;
else

    if get(deg,'Value')
        gamman=pi*gamman/180;
        deltan=pi*deltan/180;
        alphan=pi*alphan/180;
    end

    an=ax_an_bounding(gamman,deltan,alphan);

    if an(1)
        gamman=an(2);
        deltan=an(3);
        alphan=an(4);
        if get(deg,'Value')
            set(gamma,'String',num2str(180*gamman/pi));
            set(delta,'String',num2str(180*deltan/pi));
            set(alpha,'String',num2str(180*alphan/pi));
        else
            set(gamma,'String',num2str(gamman));
            set(delta,'String',num2str(deltan));
            set(alpha,'String',num2str(alphan));
        end
    end

    an=axan2euler(gamman,deltan,alphan); % convert to Euler angles
    an1=an{1};
    phin=an1{1};
    thetan=an1{2};
    psin=an1{3};

    if get(deg,'Value')
        set(phi,'String',num2str(180*phin/pi));
        set(theta,'String',num2str(180*thetan/pi));
        set(psi,'String',num2str(180*psin/pi));
    else
        set(phi,'String',num2str(phin));
        set(theta,'String',num2str(thetan));
        set(psi,'String',num2str(psin));
    end

    vn=an{2};
    set(x,'string',num2str(vn(1)));
    set(y,'string',num2str(vn(2)));
    set(z,'string',num2str(vn(3)));

    %enter_eul_angs_1;
    enter_eul_angs(true,gamman,deltan,alphan); % with not set v

end


function [Q,H,M4,D,A,G,int] = hessian_squared(V,F,varargin)
  % HESSIAN_SQUARED Construct a matrix to compute the integrated squared
  % Hessian of a function over a triangle mesh using the mixed finite element
  % method.
  %
  % [Q] = hessian_squared(V,F)
  %
  % Inputs:
  %   V  #V by dim list of vertex positions
  %   F  #F by 3 list of triangle mesh indices
  %   extraint #any boundary vertices that are explicitly to be treated as
  %   the interior
  % Outputs:
  %   Q  #V by #V sparse matrix so that X'*Q*X measures the integrated squared
  %     Hessian energy of a scalar function X
  %

  extraints = [];
  if(length(varargin)>0)
      extraints = varargin{1};
  end

  % just special case curves
  if size(F,2) == 2
    E = F;
    n = size(V,1);
    int = find(accumarray(E(:),1,[n 1])==2);
    b = find(accumarray(E(:),1,[n 1])==1);
    M = massmatrix(V,E);
    H = cotmatrix(V,E);
    % Should make this #V by #V with zeros to match other size(F,2) cases
    H(b,:) = 0;
    Q = H'*(M\H);
    M4 = M;
    return;
  end

  % Number of faces
  m = size(F,1);
  % Number of vertices
  n = size(V,1);
  % Number of dimension
  dim = size(V,2);
  m = size(F,1);
  n = size(V,1);
  G = grad(V,F);
  assert(size(G,1) == dim*m,'Gradient should equal dim*m');
  M = massmatrix(V,F);
  M4 = repdiag(M,dim^2);
  % Block transpose of G
  GG = sparse(m,0);
  for d = 1:dim
    GG = [GG G((d-1)*m+(1:m),:)];
  end
  D = repdiag(GG,dim);

  %% This is not necessary. The gradient operator G is guaranteed by
  %%construction to generate vectors in the face-plane. Therefore, even if the
  %%matrix divergence lies off this plane, the dot product with the gradient will
  %%precisely ignore the off-plane component.
  % project_div = true;
  % if project_div
  %   warning('projectin''');
  %   N = normalizerow(normals(V,F));
  %   DN = sparse(repmat(1:m,3,1)',reshape(1:m*3,m,3),N,m,m*3);
  %   D = (speye(m*3)-DN'*DN)*D;
  % end

  switch size(F,2)
  case 3
    A = repdiag(diag(sparse(doublearea(V,F)*0.5)),dim);
  case 4
    A = repdiag(diag(sparse(volume(V,F))),dim);
  end
  H = D'*A*G;

  b = unique(boundary_faces(F));
  int = setdiff(1:n,b);
  int = [int(:); extraints];
  int4 = (0:(dim^2-1))*n + int;
  notint4 = setdiff(1:(n*dim^2), int4);
  %M4 = M4(int4,int4);
  %H = H(int4,:);
  H(notint4,:) = 0;
  Q = H'*(M4\H);
end


%PREX_EIGENFACES   PRTools example on the use of images and eigenfaces

help prex_eigenfaces

echo on
              % Load all faces (may take a while)

  faces = prdataset(orl);
	faces = setprior(faces,0);     % give them equal priors
  a = gendat(faces,ones(1,40));  % select one image per class

              % Compute the eigenfaces
  w = pcam(a);

              % Display them
  newfig(1,3); show(w); drawnow;

              % Project all faces onto the eigenface space

  b = [];
  for j = 1:40
    a = seldat(faces,j);
    b = [b;a*w];
    % Don't echo loops
    echo off
  end
  echo on

              % Show a scatterplot of the first two eigenfaces
  newfig(2,3)
  scatterd(b)
  title('Scatterplot of the first two eigenfaces')

              % Compute leave-one-out error curve
  featsizes = [1 2 3 5 7 10 15 20 30 39];
  e = zeros(1,length(featsizes));
  for j = 1:length(featsizes)
    k = featsizes(j);
     e(j) = testk(b(:,1:k),1);
     echo off
  end
  echo on
              % Plot error curve
  newfig(3,3)
  plot(featsizes,e)
  xlabel('Number of eigenfaces')
  ylabel('Error')
echo off


%% Experience generation
sim_100 = [];
testData = readtable('data\testData.csv');
simOpts = rlSimulationOptions('MaxSteps',4000);
for i = 1:100
    experience = sim(envT,agent,simOpts);
    prices = testData(end,:);
    nbStock = experience.Observation.StockTradingStates.Data(:,1:3,end);
    cash = experience.Observation.StockTradingStates.Data(:,7,end);
    cur_val = sum(nbStock.*prices{1,:}) + cash;
    sim_100(end+1) = cur_val;
end
sim_norm = sim_100 - 20000;

%% Analisis of the simulations
figure;
h1 = histogram(sim_norm,'Normalization','pdf');
pd = fitdist(sim_norm','Weibull');

x_pdf = linspace(min(sim_norm),max(sim_norm),100);
y = pdf(pd,x_pdf); %pdf calculation
line(x_pdf,y,'color','r')

val_5per = pd.icdf(0.05);
val_95per = pd.icdf(0.95);

prob_upto_mean = pd.cdf(pd.mean);

xlabel(['tph - prob of up to mean: ',num2str(round(100*prob_upto_mean)),'%'])
ylabel('count pdf')
title(['distribution fit of trading profit'])
xtickformat('usd');
% hold on
line([val_5per,val_5per],[0,max(h1.Values)],'color','m')
line([pd.mean,pd.mean],[0,max(h1.Values)])
line([val_95per,val_95per],[0,max(h1.Values)],'color','m')

legend('Distribution',pd.DistributionName,['Lower 5%: ',num2str(val_5per )],...
    ['Dist Mean: ',num2str(pd.mean) ] ,...
    ['Upper 5%: ',num2str(val_95per)]);


function [C,S]=getEarth2014TerrainCoeffs(M,coeffType)
%%GETEARTH2014TERRAINCOEFFS Get fully normalized spherical harmonic
%                   coefficients for the radial distance offset of the
%                   terrain out from the surface of the GRS80 reference
%                   ellipsoid in meters under various parts of the degree
%                   2160 Earth2014 model.
%
%INPUTS: M The integer maximum order of the spherical harmonic
%          coefficients obtained. This is a value between 0 and 2160. If
%          this parameter is omitted, the default value is 2160.
% coeffType An optional parameter selecting the type of coefficients to
%          load. There are five variants of this model. Possible values
%          are
%          0 (The default if omitted or an empty matrix is passed) The
%            Earth's surface including water in lakes and major ice
%            sheets. oceans are placed on the GRS80 ellipsoid surface.
%          1 The Earth's bedrock.
%          2 The Earth's toporgraphy, bedrock plus major ice sheets.
%          3 The rock-equivalent topography of the Earth (ice and water
%            masses are condensed to layers of rock)
%          4 Major ice sheets. Everything else is set to the surface of the
%            GRS80 ellipsoid.
%
%OUTPUTS: C An array holding the coefficient terms that are multiplied by
%           cosines in the spherical harmonic expansion. If given to a
%           CountingClusterSet class, C(n+1,m+1) is the coefficient of
%           degree n and order m. When a maximum degree of M is used, all C
%           have values for all n from 0 to M and for all m from 0 to n for
%           each n. The coefficients are unitless.
%         S An array holding the coefficient terms that are multiplied by
%           sines in the spherical harmonic expansion. The format of S is
%           the same as that of C.
%
%The model is described in [1]. This function is only for values up to
%degree and order 2160 as the spherical harmonic synthesis routine in the
%Tracker Component Library cannot currently handle the full degree 10,800
%model, because it does not use extended precision arithmetic.
%
%The Earth 2014 data can be downloaded from
%http://ddfe.curtin.edu.au/models/Earth2014/
%To use the data for all of the models, place the files
%Earth2014.SUR2014.degree2160.bshc, Earth2014.BED2014.degree2160.bshc
%Earth2014.TBI2014.degree2160.bshc, Earth2014.RET2014.degree2160.bshc
%and Earth2014.ICE2014.degree2160.bshc in the data folder that is in the
%same folder as this function.
%
%EXAMPLE:
%The fact that this only stores radial distance offsets can be a little
%confusing when one wants to find the location of a point on the Earth's
%surface in the WGS-84 coordinate system/ International Terrestrial
%Reference System (ITRS). Here, we give an example:
% %WGS-84 latitude and longitude in radians.
% latLon=[19.4721;-155.5922]*(pi/180);
% [C,S]=getEarth2014TerrainCoeffs();
% %To use the terrain coefficients, the latitude must be changed from
% %geodetic to geocentric. We will assume that the latitude is given in
% %WGS-84 coordinates, as is standard with GPS.
% latSpher=ellipsLat2SpherLat(latLon(1));
% azElSphere=[latLon(2);latSpher];
% terHeight=spherHarmonicEval(C,S,azElSphere);
% %Add the ellipsoidal radius of the GRS80 reference ellipsoid at the
% %point. Note that this actually changes the ellipsoidal latitude
% %slightly.
% a=Constants.GRS80SemiMajorAxis;
% f=Constants.GRS80Flattening;
% terRad=terHeight+ellipsoidalRadius(latSpher,0,a,f);
% %Convert from spherical to Cartesian coordinates to find the point.
% CartLoc=spher2Cart([terRad;azElSphere])
%
%REFERENCES:
%[1] C. Hirt and M. Rexer, "Earth2014: 1arc-min shape, topography,
%    bedrock and ice-sheet models - available as gridded data and degree-
%    10,800 spherical harmonics," International Journal of Applied Earth
%    Observation and Geoinformation, vol. 39, pp. 103-112, Jul. 2015.
%
%June 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<2||isempty(coeffType))
     coeffType=0;
end

%The Earth2014 terrain coefficient data file, should be located in a data
%folder that is in the same folder as this file. This finds the path to
%this file.
ScriptPath=mfilename('fullpath');
ScriptFolder = fileparts(ScriptPath);

switch(coeffType)
    case 0
        fileID=fopen([ScriptFolder,'/data/Earth2014.SUR2014.degree2160.bshc'],'rb');
    case 1
        fileID=fopen([ScriptFolder,'/data/Earth2014.BED2014.degree2160.bshc'],'rb');
    case 2
        fileID=fopen([ScriptFolder,'/data/Earth2014.TBI2014.degree2160.bshc'],'rb');
    case 3
        fileID=fopen([ScriptFolder,'/data/Earth2014.RET2014.degree2160.bshc'],'rb');
    case 4
        fileID=fopen([ScriptFolder,'/data/Earth2014.ICE2014.degree2160.bshc'],'rb');
    otherwise
        error('Unknown coefficient type specified.')
end

data = fread(fileID,Inf,'double');
fclose(fileID);

%Note that data(1) should be zero. data(1) is the degree of the lowest
%degree coefficient. data(2) is the degree of the maximum degree
%coefficient.
maxDeg = data(2);
maxNumCoeffs=(maxDeg+1)*(maxDeg+2)/2;

if(nargin<1||isempty(M))
    M=maxDeg;
end

totalNumCoeffs=(M+1)*(M+2)/2;

%Extract the data. The additive 2 skips the first two entries, which
%indicate the lowest and highest coefficient degrees.
C=data((2+1):(2+totalNumCoeffs));
S=data((2+maxNumCoeffs+1):(2+maxNumCoeffs+totalNumCoeffs));
end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function [simulatedata,ht,pseudorc]=matrix_garch_simulate(t,k,parameters,p,o,q,m)
% Simulation of symmetric and asymmetric MATRIX multivariate GARCH models
%
% USAGE:
%   [SIMULATEDATA, HT, PSEUDORC] = matrix_garch_simulate(T, K, PARAMETERS, P, O, Q, M)
%
% INPUTS:
%   T            - Length of the time series to be simulated
%   K            - Cross-sectional dimension
%   PARAMETERS   - A 3-D matrix of K by K matrices where
%                    CC' = PARAMETERS(:,:,1), AA'(j)=PARAMETERS(:,:,1+j),
%                    GG'(j) = PARAMETERS(:,:,1+P+j), BB'(j)=PARAMETERS(:,:,1+P+Q+j)
%                    -OR- a K(K+1)/2*(1+P+O+Q) by 1 vector of parameters of
%                    the form returned my calling matrix_garch
%   P            - Positive, scalar integer representing the number of lags of the innovation process
%   O            - Non-negative scalar integer representing the number of asymmetric lags to include
%   Q            - Non-negative scalar integer representing the number of lags of conditional covariance
%   M            - [OPTIONAL] Number of ``intradaily'' returns to simulate to pseudo-Realized
%                    Covariance. If omitted, set to 72.
%
% OUTPUTS:
%   SIMULATEDATA - A time series with constant conditional correlation covariance
%   HT           - A [k k t] matrix of simulated conditional covariances
%   PSEUDORC     - A [k k t] matrix of pseudo-Realized Covariances
%
% COMMENTS:
%    The conditional variance, H(t), of a MATRIX GARCH is modeled as follows:
%
%      H(t) = CC' + AA'(1).*r_{t-1}'*r_{t-1} + ... + AA'(P).*r_{t-P}'*r_{t-P}
%                 + GG(1)'.*n_{t-1}'*n_{t-1} + ... + GG(O)'.*n_{t-P}'*n_{t-P}
%                  + BB(1)'.*H(t-1) +...+ BB(Q)'.*H(t-q)
%
%    where n_{t} = r_{t} .* (r_{t}<0).  If using realized measures, the
%    RM_{t-1} replaces r_{t-1}'*r_{t-1}, and the asymmetric version
%    replaces n_{t-1}'*n_{t-1}
%
%   Pseudo Realized Covariances are simulated by generating m-intra daily returns from a N(0,1/m)
%   and computing the Realized Covariance of these. These were used in Patton and Sheppard (2009)
%   when evaluating variance and covariance specifications in a Monte Carlo.  If M=1, then PSEUDORC
%   is just the outer product of the SIMULATEDATA.
%
%   NOTE: This program generates 2000 more than required to minimize any start-up bias
%
% See also TARCH_SIMULATE, CCC_GARCH_SIMULATE, MATRIX_GARCH

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 3/10/2011

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
switch nargin
    case 6
        m=[];
    case 7
        % nothing
    otherwise
        error('MFEToolbox:Input','6 or 7 inputs required.');
end

% t
if ~isscalar(t) || t<0 || floor(t)~=t
    error('T must be a positive integer.');
end
% k
if ~isscalar(k) || k<2 || floor(k)~=k
    error('K must be a positive integer greater than or equal to 2.');
end
% p
if ~isscalar(p) || p<1 || floor(p)~=p
    error('P must be a positive integer if scalar.');
end

% o

if ~isscalar(o) || o<0 || floor(o)~=o
    error('O must be a non-neagative integer if scalar.');
end
% q

if ~isscalar(q) || q<0 || floor(q)~=q
    error('Q must be a non-neagative integer if scalar.');
end
% m
if isempty(m)
    m = 72;
end
if ~isscalar(m) || floor(m)~=m || m<1
    error('M must be a positive integer.')
end
% parameters
k2 = k*(k+1)/2;
if ismatrix(parameters)
    parameterCount = k*(k+1)/2 *(1+ p + o + q);
    if size(parameters,2)>size(parameters,1)
        parameters = parameters';
    end
    if length(parameters)~=parameterCount
        error('PARAMETERS must be K(K+1)/28(1+P+O+Q) when using a vector.')
    end
    parameterMatrices= zeros(k,k,1+p+o+q);
    index = 0;
    for i=1:(1+p+o+1)
        temp = vec2chol(parameters(index+1:index+k2));
        parameterMatrices(:,:,i) = (temp*temp'+temp*temp')/2;
        index=index+k2;
    end
    parameters = parameterMatrices;
elseif ndims(parameters)==3
    if any(size(parameters)~=[k k 1+p+o+q])
        error('PARAMETERS must be K by K by (1+P+O+Q) when using a 3-D matrix.')
    end
    parameterMatrices = parameters;
else
    error('The size of PARAMETERS is not compatible with this function.')
end

% Check stationarity
sumParameters = zeros(k);
for i=2:size(parameterMatrices,3)
    if i<=(p+1) || i>(1+p+o)
        w=1;
    else
        w=0.5;
    end
    sumParameters = sumParameters + w*parameterMatrices(:,:,i);
end
sumParameters = (sumParameters+sumParameters')/2;
if max(diag(sumParameters))>1
    warning('MFE::Nonstationary','The parameters do not correspond to a stationary solution.  Check for overflow.')
    uncond = parameters(:,:,1)/.005;
else
    uncond = parameters(:,:,1)./(ones(k)-sumParameters);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Set the burnin amount, 2000 is probably reasonable
burnin=2000;
%Up t by the burnin amount
t=t+burnin;

%Draw some normal random numbers
intraRandomNums=randn(m*t,k)*sqrt(1/m);
randomNums = cumsum(intraRandomNums);
randomNums = diff([zeros(1,k);randomNums(m:m:m*t,:)]);

%Perform the recursion
backCast = uncond;
backCastAsym = uncond;
T = t;
Ht = zeros(k,k,T);
simulatedData = zeros(T,k);
for t=1:T;
    Ht(:,:,t)=parameterMatrices(:,:,1);
    for j=1:p
        if (t-j)<1
            Ht(:,:,t)=Ht(:,:,t)+parameterMatrices(:,:,j+1).*backCast;
        else
            r = simulatedData(t-j,:);
            Ht(:,:,t)=Ht(:,:,t)+parameterMatrices(:,:,j+1).*(r'*r);
        end
    end
    for j=1:o
        if (t-j)<1
            Ht(:,:,t)=Ht(:,:,t)+parameterMatrices(:,:,p+j+1).*backCastAsym;
        else
            n = simulatedData(t-j,:).*(simulatedData(t-j,:)<0);
            Ht(:,:,t)=Ht(:,:,t)+parameterMatrices(:,:,p+j+1).*(n'*n);
        end
    end
    for j=1:q
        if (t-j)<1
            Ht(:,:,t)=Ht(:,:,t)+parameterMatrices(:,:,p+o+j+1).*backCast;
        else
            Ht(:,:,t)=Ht(:,:,t)+parameterMatrices(:,:,p+o+j+1).*Ht(:,:,t-j);
        end
    end
    simulatedData(t,:) = randomNums(t,:)*Ht(:,:,t)^(0.5);
end

%Initialize the covariance
pseudorc=zeros(k,k,t);
for t=1:T
    r = intraRandomNums((t-1)*m+1:t*m,:)*Ht(:,:,t)^(0.5);
    pseudorc(:,:,t) = r'*r;
end

%Truncate the data and the covariance
simulatedata=simulatedData(burnin+1:t,:);
pseudorc = pseudorc(:,:,burnin+1:t);
ht=Ht(:,:,burnin+1:t);


function wathen_test05 ( )

%*****************************************************************************80
%
%% WATHEN_TEST05 measures the storage needed for the Wathen system.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 August 2014
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'WATHEN_TEST05\n' );
  fprintf ( 1, '  For various problem sizes and storage schemes, \n' );
  fprintf ( 1, '  measure the storage used for the Wathen system.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '                                   Predicted  Observed\n' );
  fprintf ( 1, '                              GE        Band      Band' );
  fprintf ( 1, '      Band    Sparse\n' );
  fprintf ( 1, '    NX  Elements   Nodes   storage     width     width' );
  fprintf ( 1, '   storage   storage\n' );
  fprintf ( 1, '\n' );

  nx = 1;
  ny = 1;

  for test = 1 : 6
%
%  Compute the number of unknowns.
%
    n = wathen_order ( nx, ny );
%
%  Predict the bandwidth.
%
    [ bl, bd, bu ] = wathen_bandwidth ( nx, ny );
    bw1 = bl + bd + bu;
%
%  Compute the matrix.
%
    seed = 123456789;
    [ a, seed ] = wathen_ge ( nx, ny, n, seed );
    [ na1, na2 ] = size ( a );
    storage_ge = na1 * na2;
    [ bw2, lb, db, ub ] = bandwidth ( na1, na2, a );
    storage_gb = ( 2 * lb + 1 + ub ) * n;
    nnz = length ( find ( a ~= 0.0 ) );
%
%  Report.
%
    fprintf ( 1, '  %4d      %4d  %6d  %8d  %8d  %8d  %8d  %8d\n', ...
      nx, nx * ny, n, storage_ge, bw1, bw2, storage_gb, nnz );
%
%  Ready for next iteration.
%
    nx = nx * 2;
    ny = ny * 2;

  end

  return
end


%% POWER_WRITE writes a power table to a file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 October 2007
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'POWER_WRITE\n' );
  fprintf ( 1, '  Write a table of integer powers to a file.\n' );

  file_name = 'power_write.txt';

  file_unit = fopen ( file_name, 'w' );

  fprintf ( file_unit, '\n' );
  fprintf ( file_unit, '           N   N-squared     N-cubed\n' );
  fprintf ( file_unit, '\n' );
  for i = 0 : 10
    fprintf ( file_unit, '  %10d  %10d  %10d\n', i, i^2, i^3 );
  end

  fclose ( file_unit );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  POWER_WRITE wrote the file %s\n', file_name );

  exit


function [Nm] = eV2Nm(eV)
% Convert energy or work from electron volts to newton-meters.
% Chad A. Greene 2012
Nm = eV*1.6021773e-19;


function F = max_integer_model(X,t);

[M,m] = derivebounds(X);

if all(M==m)
    F = [t == max(M)];
    return
end

n = length(X);
d = binvar(n,1);
F = (sum(d)==1);
F = F + (-(max(M)-min(m))*(1-d) <= t-X <= (max(M)-min(m))*(1-d));
kk = [];
ii = [];
for i = 1:n
    k = [1:1:i-1 i+1:1:n]';
    ii = [ii;repmat(i,n-1,1)];
    kk = [kk;k];
    Mm = M(k)-m(i);
end
xii = extsubsref(X,ii);
dii = extsubsref(d,ii);
xkk = extsubsref(X,kk);
F = F + (xkk <= xii+(M(kk)-m(ii)).*(1-dii));


function [net, sName, sName_l2norm] = addOneLoop_forMeanShiftGrouping(net, sName, loopIdx, GaussianBandwidth, randSampleRatio)

if ~exist('GaussianBandwidth', 'var')
    GaussianBandwidth = 0.1;
end

if ~exist('randSampleRatio', 'var')
    randSampleRatio = 0.2;
end

%%
pre_l2_norm_layer = sName;

lName = sprintf('loop%d_meanshift_S_is_XX', loopIdx);
net.addLayer(lName, ...
    meanshift_S_is_XX(), ... softmaxlog logistic
    {sName}, lName);
sName = lName;

lName = sprintf('loop%d_meanshift_G_is_Gaussian', loopIdx);
net.addLayer(lName, ...
    meanshift_G_is_Gaussian('delta', GaussianBandwidth), ...
    {sName}, lName);
G_layer = lName;
sName = lName;

lName = sprintf('loop%d_meanshift_d_is_sumG', loopIdx);
net.addLayer(lName, ...
    meanshift_d_is_sumG(), ...
    {sName}, lName);
sName = lName;

lName = sprintf('loop%d_meanshift_q_is_inv_d', loopIdx);
net.addLayer(lName, ...
    meanshift_q_is_inv_d(), ...
    {sName}, lName);
sName = lName;

lName = sprintf('loop%d_meanshift_P_is_G_diag_q', loopIdx);
net.addLayer(lName, ...
    meanshift_P_is_G_diag_q(), ...
    {G_layer, sName}, lName);
sName = lName;

lName = sprintf('loop%d_meanshift_Y_is_XP', loopIdx);
net.addLayer(lName, ...
    meanshift_Y_is_XP(), ...
    {pre_l2_norm_layer, sName}, lName);
sName = lName;

lName = sprintf('loop%d_meanshift_Y_l2norm', loopIdx);
net.addLayer(lName, L2normalization(), sName, lName) ;
sName = lName;
sName_l2norm = lName;

lName = sprintf('loop%d_meanshift_cosSim', loopIdx);
gt_name =  sprintf('gt_ins');
net.addLayer(lName, cosineSimilarity_randSample('randSampleRatio', randSampleRatio), {sName, gt_name}, lName) ;
sName = lName;

% % add regression loss
% obj_name = sprintf('loop%d_instSeg_reg', loopIdx);
% net.addLayer(obj_name, ...
%     InstanceSegRegLoss_randSample('loss', 'cosinesimilarityabsregloss', 'lastLayerName', sName), ... softmaxlog logistic
%     {sName, gt_name}, obj_name);
%
%
% % add max-margin loss
% obj_name = sprintf('loop%d_instSeg_MM', loopIdx);
% input_name = sName;
% net.addLayer(obj_name, ...
%     InstanceSegMMLoss_randSample('loss', 'cosinesimilaritymmloss', 'marginAlpha_', 0.1, 'adaptiveMM', false, 'lastLayerName', sName), ...
%     {input_name, gt_name}, obj_name)


function [ temp ] = gbSegment( img, sigma, k, minSz )
%GBSEGMENT Summary of this function goes here
%   Detailed explanation goes here
[height, width, ~] = size(img);
img_smooth = smooth(img, sigma);
edges = zeros(width*height*4,3);
[gridX, gridY] = meshgrid(1:width,1:height);
num = 0;

x = gridX(:);
y = gridY(:);
vector = [1 0; 0 1; 1 1; 1 -1];
inda = sub2ind([height width], y, x);

for vid = 1:size(vector,1)
    xv = x+vector(vid,1);
    yv = y+vector(vid,2);
    valid = xv>=1 & xv<=width & yv>=1 & yv<=height;
    indav = inda(valid);
    indbv = sub2ind([height width], yv(valid), xv(valid));
    diff = (img_smooth(indav)-img_smooth(indbv)).^2 ...
         + (img_smooth(indav+width*height)-img_smooth(indbv+width*height)).^2 ...
         + (img_smooth(indav+2*width*height)-img_smooth(indbv+2*width*height)).^2;
    edges(num+1:num+sum(valid),:) = [x(valid)-1 + (y(valid)-1)*width ...
                                     xv(valid)-1 + (yv(valid)-1)*width ...
                                     sqrt(diff)];
    num = num + sum(valid);
end

edges = edges';
segment = segmentGraphMex(width, height, num, edges, k, minSz);
L = unique(segment);

temp = zeros(size(segment));
for i = 1:length(L)
    temp(segment==L(i)) = i;
end

end


function [cvx_w, ATest, dSigPredict, dSigTest, rows, R2] = t_mrdArcuateXvalidate(dSig,A,rows,ndir)
%
% function [cvx_w, ATest, dSigTest, rows, R2] = t_mrdArcuateXvalidate(dSig,A,rows,ndir)
%
% Cross-validate fiber predictions.
%
% dSig = the vector of diffusion measurements
% A    = the fiber prediction matrix
% rows = which rows to use
%
% Example:
%    t_mrdArcuateXvalidate(dSig,A,rows,ndir)
%
% See also:  t_mrdTensors, t_mrdViewFibers, dwiLoad, dtiGet/Set,
%            t_mrdFiberPredictions, t_mrdArcuatePRedictions
%
% (c) Stanford VISTA Team

% The user must either pass in the rows to fit and hold out or the number
% of directions so that we can randomly hold out rows
if exist('rows','var') && ~isempty(rows);
    rows = logical(rows);
elseif ~exist('rows','var') || isempty(rows);
    % This is a randomly chosen direction to hold out for each voxel
    outVols = ceil(rand(length(dSig)./ndir,1).*ndir);
    % Now we will make a vector that has a 1 for each row of dsig to fit
    % and a 0 for each row to hold out for cross validation
    rows = [];
    for ii = 1:length(outVols)
        tmp = ones(ndir,1);
        tmp(outVols(ii))=0;
        nextrow = length(rows)+1;
        rows(nextrow:nextrow+ndir-1) = tmp;
    end
   rows = logical(rows);
end

% This is the data we will hold out for cross validation
tmp        = full(A);   % we're not sure if we have to make it a full before indexing
dSigTest   = dSig(~rows);
ATest      = tmp(~rows,:);

% now run the CVX code to solve the L1-minimization problem:
ATrain    = tmp(rows,:); clear tmp
n         = size(ATrain,2);
dSigTrain = dSig(rows);
fFraction = 0.2; % fraction of the weights over which weights are nromalized

l = 0;                 % Lower and upper bounds on the weights
u = 1;
cvx_solver sedumi;     % sdpt3
cvx_precision('low')  % We can handle low precision during testing.

cvx_begin              % start te cvx environment
   variable cvx_w(n)   % set the variable we are looking to fit in the cvx environment
   minimize(norm(ATrain * cvx_w - dSigTrain,1)) % minimize using L1 norm
   subject to
     norm(cvx_w(1:n),1) <= fFraction*n;
     cvx_w >= l;
     cvx_w <= u;
cvx_end

% compute the predicted signal
dSigPredict = ATest*cvx_w;

% Amount of deviation in the data explained by the model
% relative to the total variance in the data.
R2 = 100 * (1-sum((dSigPredict - dSigTest).^2) / sum((dSigTest-mean(dSigTest)).^2));
%R2 = corr(dSigPredict,dSigTest)^2;


function datain(imagefig,varargins)
global M
global Nsamples
set(gcf,'WindowButtonMotionFcn',[]);
set(gcf,'windowbuttondownfcn',{@track});

%%% This function performes the FFT and spectrum analysis of the
%%% Input data. It is not related dirctely to the filtering process,
%%% But performs post-processing.

ini=Nsamples;
temp=get(gcf,'userdata');
temp=temp(ini:size(temp,1),:);
len=length(temp(:,3));                  % Determines the length of x
fs=1/(temp(end,3)-temp(ini,3))*len                % mean sample rate

Pad = 2 * fs * len;                  % Setting the length of ZeroPadded x
Pad = floor(Pad);
w=0:(Pad-1);
half_w=floor(length(w)/2);
win=(kaiser(len,5))';   % Creates a Kaiser window
for k=1:2
    temp(:,k)=temp(:,k).*win';    % Passes x through the Kaiser window
end
FFX=(abs(fft(temp(:,1) ,Pad)));
FFY=(abs(fft(temp(:,2) ,Pad)));

figure
subplot(2,1,1), plot(fs / Pad * w(1:half_w), 20*log10(FFX(1:half_w)));
grid on, ylabel(['[dB]']), title('X axis motion spectrum');

subplot(2,1,2), plot(fs / Pad * w(1:half_w), 20*log10(FFY(1:half_w)));
grid on, ylabel(['[dB]']), xlabel(['[Hz]']), title('Y axis motion spectrum');


function I=montec(f,a,b,n)

%I=montec('f',a,b,k);
%Calculates integral using montecarlo method
for k=1:n
    s=2.^k;
    t=rand(1,s);
    x=a+t.*(b-a);

    for i=1:s
        y(i)=feval(f,x(i));
    end

    I(k)=((b-a)./s)*sum(y);
end
plot(I);


function linpack_s_test30 ( )

%*****************************************************************************80
%
%% TEST30 tests STRDI.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 June 2009
%
%  Author:
%
%    John Burkardt
%
  n = 5;
  lda = n;
  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST30\n' );
  fprintf ( 1, '  For a triangular matrix,\n' );
  fprintf ( 1, '  STRDI computes the determinant or inverse.\n' );
  fprintf ( 1, '  The matrix size is N = %d\n', n );
%
%  Lower triangular matrix A.
%
  [ a, seed ] = r4mat_uniform_01 ( n, n, seed );

  for i = 1 : n
    for j = i+1 : n
      a(i,j) = 0.0;
    end
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Lower triangular matrix A:\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    for j = 1 : n
      fprintf ( 1, '  %14f', a(i,j) );
    end
    fprintf ( 1, '\n' );
  end

  job = 110;

  [ a, det, info ] = strdi ( a, lda, n, job );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The determinant = %f * 10 ^ %f\n ', det(1), det(2) );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The inverse matrix:\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    for j = 1 : n
      fprintf ( 1, '  %14f', a(i,j) );
    end
    fprintf ( 1, '\n' );
  end

%
%  Upper triangular matrix A.
%
  [ a, seed ] = r4mat_uniform_01 ( n, n, seed );

  for i = 1 : n
    for j = 1 : i - 1
      a(i,j) = 0.0;
    end
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Upper triangular matrix A:\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    for j = 1 : n
      fprintf ( 1, '  %14f', a(i,j) );
    end
    fprintf ( 1, '\n' );
  end

  job = 111;

  [ a, det, info ] = strdi ( a, lda, n, job );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The determinant = %f * 10 ^ %f\n ', det(1), det(2) );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The inverse matrix:\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n
    for j = 1 : n
      fprintf ( 1, '  %14f', a(i,j) );
    end
    fprintf ( 1, '\n' );
  end

  return
end


function r = subsref(p,s)
%SUBSREF      Implements subscripted references for polynomials
%
%  r = p(i)
%
%For univariate polynomials p, p(i) is the coefficient of x^i, 0<=i<=degree(p).
%  For i>degree(p), p(i):=0. Similarly, p(i:j) is the vector of coefficients
%  [ p(i) p(i+1) ... p(j) ], or, p(:) is the (row) vector of all coefficients
%  of p, the same as vector(p) for univariate polynomials.
%
%For multivariate polynomials p in k variables x_1..x_k, p(i) is the
%  coefficient of x_1^i, i.e. a polynomial in k-1 variables.
%  Similarly, p(i,[],j) or p(i,:,j) is the coefficient polynomial of
%  x1^i*x3^j. Indices i,j,... must be single indices, no range.
%Note that access to coefficients refers to the current order p.v of
%  variables of p. To change this order, see permvars.
%For example, for a polynomial in three variables p.v={'x','y','z'},
%  p(1,0,3) is the coefficient of x*z^3 (a constant), where p(1,[],3)
%  if the coefficient of x*z^3, a univariate polynomial in y.
%
%Polynomial evaluation is denoted by p{x} or p{x1,...,xn}, computing the value
%  of p at x. This is the same as polyval(p,x) of polyval(p,x1,...,xn).
%For univariate polynomials, x may be a vector or matrix yielding the vector
%  or matrix of polynomial values evaluated at the corresponding coefficients.
%For multivariate polynomials, x is a vector of values of the variables.
%  For x being a matrix, the result is the (column) vector of p{x(i,:)}.
%
%Moreover, p.mid, p.rad, p.inf, p.sup give access to the midpoint, radius,
%  infimum and supremum of p, respectively.
%
%Finally, p.e, p.c and p.v give access to the arrays of exponents, coefficients
%  and variables of p, such that polynom(p.e,p.c,p.v) is again p. Single variables
%  are accessed by p.v{i}.
%
%In the univariate case,  p == polynom(p.c,p.v)  [ degree is length(p.c)+1 ].
%In the multivariate case,  p == polynom(p.e,p.c,p.v)  [ p.e is (sparse) exponent set ].
%

% written  11/20/97     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  while 1
    if ~isa(p,'polynom')
      r = subsref(p,s(1));
    elseif strcmp(s(1).type,'()')     % index reference p(i)
      if size(p.e,2)==1               % univariate polynomial
        if length(s(1).subs)>1
          error('invalid call: more than one index')
        end
        if isequal(s(1).subs{1},':')
          r = p.c;
        else
          n1 = length(p.c);
          index = n1-s(1).subs{1};    % index vector, p(0) constant term, etc.
          if ~isreal(index) | ~isequal(index,round(index))
            error('index must be integer')
          end
          if any(index>n1)            % index negative
            error('index out of range')
          end
          if any(index<1)             % index greater than degree
            indexgt0 = ( index>0 );
            r = typeadj( zeros(1,length(index)) , typeof(p.c) );
            if any(indexgt0)
              r(indexgt0) = p.c(index(indexgt0));
            end
          else
            r = p.c(index);
          end
        end
      else                            % multivariate polynomial
        k = size(p.e,2);              % number of variables
        if length(s(1).subs)>k
          error('too many indices')
        end
        index = logical(zeros(1,k));
        exponents = [];
        for i=1:length(s(1).subs)
          if isempty(s(1).subs{i}) | isequal(s(1).subs{i},':')
            index(i) = 0;
          else
            index(i) = 1;
            exponents = [ exponents s(1).subs{i} ];
          end
        end
        if isempty(exponents)
          r = p;
          return
        end
        I = all( ( p.e(:,index) == repmat(exponents,size(p.e,1),1) ) , 2 );
        if ~any(I)                    % coefficients do not occur
          r = typeadj( 0 , typeof(p.c) );
          return
        end
        r.e = p.e(I,~index);
        if isempty(r.e)               % coefficient is single constant
          r = p.c(I);
          return
        end
        r.c = p.c(I);
        r.v = p.v(~index);
        if size(r.e,2)==1             % coefficient polynomial univariate
          if iscell(r.v)              % be sure r.v is char for univ. pol.
            r.v = r.v{1};
          end
          n = max(r.e);               % r.e is vector
          c = r.c;
          r.c = typeadj( zeros(1,n+1) , typeof(c) );
          r.c(n+1-r.e) = c;
          r.e = n;
          if r.e==0
            r = r.c;
            return
          end
        else
          r = normalize(r);
        end
        r = class(r,'polynom');
      end
    elseif strcmp(s(1).type,'{}')     % polynomial evaluation p{x}
      r = polyval(p,s(1).subs{:});
    elseif strcmp(s(1).type,'.')      % polynomial access to inf, sup, ...
      if     strcmp(s(1).subs,'mid'), r = mid(p);
      elseif strcmp(s(1).subs,'rad'), r = rad(p);
      elseif strcmp(s(1).subs,'inf'), r = inf(p);
      elseif strcmp(s(1).subs,'sup'), r = sup(p);
      elseif strcmp(s(1).subs,'e')
        if iscell(p.v)                  % multivariate
          r = flipud(sortrows(p.e));
        else
          r = p.e;                      % univariate
        end
      elseif strcmp(s(1).subs,'c')
        if iscell(p.v)                  % multivariate
          [ dummy index ] = sortrows(p.e); r = flipud(p.c(index));
        else
          r = p.c;
        end
      elseif strcmp(s(1).subs,'v'), r = p.v;
      else
        error('invalid reference for polynomial')
      end
    else
      error('invalid index reference for polynomial')
    end
    if length(s)==1
      return
    end
    s = s(2:end);
    p = r;
  end


function transfo = createBasisTransform(source, target)
%CREATEBASISTRANSFORM Compute matrix for transforming a basis into another basis
%
%   TRANSFO = createBasisTransform(SOURCE, TARGET)
%   Both SOURCE and TARGET represent basis, in the following form:
%   [x0 y0  ex1 ey1  ex2 ey2]
%   [y0 y0] is the origin of the basis, [ex1 ey1] is the first direction
%   vector, and [ex2 ey2] is the second direction vector.
%
%   The result TRANSFO is a 3-by-3 matrix such that a point expressed with
%   coordinates of the first basis will be represented by new coordinates
%   P2 = transformPoint(P1, TRANSFO) in the target basis.
%
%   TRANSFO = createBasisTransform(TARGET)
%   Assumes the source is the standard (Oij) basis, with origin at (0,0),
%   first direction vector equal to (1,0) and second direction  vector
%   equal to (0,1).
%
%
%   Example
%     % define source and target bases
%     src = [ 0 0   1  0    0  1];
%     tgt = [20 0  .5 .5  -.5 .5];
%     trans = createBasisTransform(src, tgt);
%     % create a polygon in source basis
%     poly = [10 10;30 10; 30 20; 20 20;20 40; 10 40];
%     figure;
%     subplot(121); drawPolygon(poly, 'b'); axis equal; axis([-10 50 -10 50]);
%     hold on; drawLine([0 0 1 0], 'k'); drawLine([0 0 0 1], 'k');
%     drawLine([20 0 1 1], 'r'); drawLine([20 0 -1 1], 'r');
%     t = -1:5; plot(t*5+20, t*5, 'r.'); plot(-t*5+20, t*5, 'r.');
%     % transform the polygon in target basis
%     poly2 = transformPoint(poly, trans);
%     subplot(122); drawPolygon(poly2, 'b'); axis equal; axis([-10 50 -10 50]);
%     hold on; drawLine([0 0 1 0], 'r'); drawLine([0 0 0 1], 'r');
%     t = -1:5; plot(t*10, zeros(size(t)), 'r.'); plot(zeros(size(t)), t*10, 'r.');
%
%   See also
%   transforms2d
%

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2010-12-03,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

% init basis transform to identity
t1 = eye(3);
t2 = eye(3);

if nargin == 2
    % from source to reference basis
    t1(1:2, 1) = source(3:4);
    t1(1:2, 2) = source(5:6);
    t1(1:2, 3) = source(1:2);
else
    % if only one input, use first input as target basis, and leave the
    % first matrix to identity
    target = source;
end

% from reference to target basis
t2(1:2, 1) = target(3:4);
t2(1:2, 2) = target(5:6);
t2(1:2, 3) = target(1:2);

% compute transform matrix
transfo = zeros(3, 3);
maxSz = 1;
for i = 1:maxSz
    % coordinate of three reference points in source basis
    po = t1(1:2, 3, i)';
    px = po + t1(1:2, 1, i)';
    py = po + t1(1:2, 2, i)';

    % express coordinates of reference points in the new basis
    t2i = inv(t2(:,:,i));
    pot = transformPoint(po, t2i);
    pxt = transformPoint(px, t2i);
    pyt = transformPoint(py, t2i);

    % compute direction vectors in new basis
    vx = pxt - pot;
    vy = pyt - pot;

    % concatenate result in a 3-by-3 affine transform matrix
    transfo(:,:,i) = [vx' vy' pot' ; 0 0 1];
end


function x = IWT2_PO(wc,L,qmf)
% IWT2_PO -- Inverse 2-d MRA wavelet transform (periodized, orthogonal)
%  Usage
%    x = IWT2_PO(wc,L,qmf)
%  Inputs
%    wc    2-d wavelet transform [n by n array, n dyadic]
%    L     coarse level
%    qmf   quadrature mirror filter
%  Outputs
%    x     2-d signal reconstructed from wc
%
%  Description
%    If wc is the result of a forward 2d wavelet transform, with
%    wc = FWT2_PO(x,L,qmf), then x = IWT2_PO(wc,L,qmf) reconstructs x
%    exactly if qmf is a nice qmf, e.g. one made by MakeONFilter.
%
%  See Also
%    FWT2_PO, MakeONFilter
%
	[n,J] = quadlength(wc);
	x = wc;
	nc = 2^(L+1);
	for jscal=L:J-1, % from coarse to fine
		top = (nc/2+1):nc; bot = 1:(nc/2); all = 1:nc;
		for iy=1:nc,
			x(all,iy) =  UpDyadLo(x(bot,iy)',qmf)'  ...
					   + UpDyadHi(x(top,iy)',qmf)';
		end
		for ix=1:nc,
			x(ix,all) = UpDyadLo(x(ix,bot),qmf)  ...
					  + UpDyadHi(x(ix,top),qmf);
		end
		nc = 2*nc;
	end

%
% Copyright (c) 1993. David L. Donoho
%

%
%  Part of Wavelab Version 850
%  Built Tue Jan  3 13:20:40 EST 2006
%  This is Copyrighted Material
%  For Copying permissions see COPYING.m
%  Comments? e-mail wavelab@stat.stanford.edu


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ldldown.m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% function [L,d]=ldldown(L,d,j)
% downdates LDL^T factorization when j-th row and column are replaced
% by j-th unit vector
%
% d contains diag(D) and is assumed positive
%
function [L,d]=ldldown(L,d,j);

n=size(d,1);

test=0;
if test,
  disp('enter ldldown')
  A=L*diag(d)*L';A(:,j)=zeros(n,1);A(j,:)=zeros(1,n);A(j,j)=1;
end;

if j<n,
  I=1:j-1;K=j+1:n;
  [LKK,d(K)]=ldlrk1(L(K,K),d(K),d(j),L(K,j));
  % work around expensive sparse L(K,K)=LKK
  L=[L(I,:);
     sparse(1,n);
     L(K,I),sparse(n-j,1),LKK];
  L(j,j)=1;
else
  L(n,1:n-1)=sparse(1,n-1);
end;
d(j)=1;

if test,
  A1=L*diag(d)*L',A
  quot=norm(A1-A,1)/norm(A,1),
  disp('leave ldldown')
end;


function A = calc_area(I)
% The derivative uses central difference and only applies to the interior
% points
der_x = calc_der_x(I(2:end-1,:,:));
der_y = calc_der_y(I(:,2:end-1,:));
G11 = sum(der_x.^2, 3) + 1;
G12 = sum(der_x.*der_y, 3);
G22 = sum(der_y.^2, 3) + 1;
A = sum(sum(sqrt(G11.*G22 - G12.^2)));
% A = sum(sum(G11.*G22 - G12.^2));

function der_x = calc_der_x(I)
der_x = (1/2) * (I(:,3:end,:) - I(:,1:end-2,:));

function der_y = calc_der_y(I)
der_y = (1/2) * (I(3:end,:,:) - I(1:end-2,:,:));


function  [h, compUpJP] =  lfmComputeH4JP(gamma1_p, gamma1_m, sigma2, t1, ...
    preFactor, preExp, mode)

% LFMCOMPUTEH4JP Helper function for computing part of the LFMJP kernel.
% FORMAT
% DESC computes a portion of the LFMAP kernel.
% ARG gamma1 : Gamma value for first system.
% ARG gamma2 : Gamma value for second system.
% ARG sigma2 : length scale of latent process.
% ARG t1 : first time input (number of time points x 1).
% ARG t2 : second time input (number of time points x 1).
% ARG mode: indicates in which way the vectors t1 and t2 must be transposed
% RETURN h : result of this subcomponent of the kernel for the given values.
%
% COPYRIGHT : Mauricio Alvarez, 2010
%
% SEEALSO : lfmComputeH4.m, lfmComputeH4AP.m

% KERN

if mode==0
    if nargout > 1
        compUpJP{1} = lfmjpComputeUpsilonVector(gamma1_p,sigma2, t1);
        compUpJP{2} = lfmjpComputeUpsilonVector(gamma1_m,sigma2, t1);
        h =  compUpJP{1}*( preExp(:,1)/preFactor(1) - preExp(:,2)/preFactor(2)).' ...
            + compUpJP{2}*( preExp(:,2)/preFactor(3) - preExp(:,1)/preFactor(4)).';
    else
        h =  lfmjpComputeUpsilonVector(gamma1_p,sigma2, t1)*( preExp(:,1)/preFactor(1) - preExp(:,2)/preFactor(2)).' ...
            + lfmjpComputeUpsilonVector(gamma1_m,sigma2, t1)*( preExp(:,2)/preFactor(3) - preExp(:,1)/preFactor(4)).';
    end
else
    if nargout > 1
        compUp{1} = lfmComputeUpsilonVector(gamma1_p,sigma2, t1);
        compUp{2} = lfmComputeUpsilonVector(gamma1_m,sigma2, t1);
        h =  compUp{1}*(preExp(:,2)/preFactor(2) - preExp(:,1)/preFactor(1)).' ...
            + compUp{2}*(preExp(:,1)/preFactor(4) - preExp(:,2)/preFactor(3)).';
        compUpJP = compUp;
    else
        h =  lfmComputeUpsilonVector(gamma1_p,sigma2, t1)*(preExp(:,2)/preFactor(2) - preExp(:,1)/preFactor(1) ).' ...
            + lfmComputeUpsilonVector(gamma1_m,sigma2, t1)*(preExp(:,1)/preFactor(4) - preExp(:,2)/preFactor(3)).';
    end
end


function simNoise = generateNoise(nPoints, sizeVec)
% simNoise = generateNoise(nPoints, sizeVec)
%
% generates Poisson noise with given number of points (nPoints) and given
% image size (sizeVec = [xlim1, xlim2, ylim1, ylim2]).

simNoise(:,1) = sizeVec(1) + rand(nPoints,1)*(sizeVec(2) - sizeVec(1));
simNoise(:,2) = sizeVec(3) + rand(nPoints,1)*(sizeVec(4) - sizeVec(3));


% Calculate adaptive smoothed rate map
%
% Calculates an adaptive smoothed rate map as described in "Skaggs et al 1996 -
% Theta Phase Precession in Hippocampal Neuronal Population and the Compression of Temporal Sequences"
%
%  USAGE
%   [map, posPdf] = analyses.ratemapAdaptiveSmoothing(pos, spkPos, <options>)
%   pos         Position samples (either Nx3 or Nx2 matrix). X and Y coordinates are used.
%   spkPos      Spike position samples (either Nx2 or Nx2 matrix). X and Y coordinates are used.
%   <options>   optional list of property-value pairs (see table below)
%
%   =========================================================================
%    Properties     Values
%   -------------------------------------------------------------------------
%    'binWidth'     width (and height) of bins in firing rate map. Value units
%                   are [cm]. binWidth has priority over parameter nBins. See
%                   description of nBins.
%
%    'nBins'        number of horizontal and vertical bins (default = [50 50]).
%                   If single value is provided, it is used for both horizontal
%                   and vertical number of bins (i.e. nBins = 50 => [50 50]).
%                   Either binWidth or nBins should be provided. If non is provided,
%                   then the default value of binWidth is used. If both are provided,
%                   then the value of binWidth is used.
%
%    'minTime'      minimum time spent in each bin (in s, default = 0).
%    'alphaValue'   scaling parameter. Default value is 10000. See original paper
%                   for the details.
%    'shape'        shape of the arena. Possible values are: 1 for square box,
%                   2 for cylinder. Only square box is currently supported!
%    =========================================================================
%
%  OUTPUT
%
%   map.x       x bins
%   map.y       y bins
%   map.z       adaptively smoothed firing rate map
%   posPdf      position probability density function

function [map, posPdf] = mapAdaptiveSmoothing(pos, spkPos, varargin)
    % Check number of parameters
    if nargin < 2 || mod(length(varargin), 2) ~= 0,
        error('BNT:numArgs', 'Incorrect number of parameters (type ''help analyses.mapAdaptiveSmoothing'' for details).');
    end

    % Check parameter sizes
    if size(pos, 2) < 2
        error('Parameter ''pos'' should have at least 2 columns (type ''help analyses.mapAdaptiveSmoothing'' for details).');
    end
    if size(spkPos, 2) < 2
        error('Parameter ''spkPos'' should have 1 or 2 columns (type ''help analyses.mapAdaptiveSmoothing'' for details).');
    end

    if isempty(pos)
        return;
    end

    % Default values
    alphaValue = 10000;
    binWidth = 5;
    minTime = 0;
    limits = [];
    shape = 1;
    sampleTime = helpers.sampleTimeFromData(pos);
    nBins = [50 50];

    haveBinWidth = false;
    haveNBins = false;

    % Parse parameter list
    i = 1;
    while i < length(varargin)
        if ~ischar(varargin{i}),
            error(['Parameter ' num2str(i+2) ' is not a property (type ''help analyses.mapAdaptiveSmoothing'' for details).']);
        end

        switch(lower(varargin{i})),
            case 'binwidth',
                binWidth = varargin{i+1};
                if ~helpers.isdscalar(binWidth, '>0')
                    error('Incorrect value for property ''nBins'' (type ''help analyses.mapAdaptiveSmoothing'' for details).');
                end
                haveBinWidth = true;
                i = i + 2;

            case 'nbins'
                nBins = varargin{i+1};
                if ~helpers.isivector(nBins, '>0') || length(nBins) > 2,
                    error('Incorrect value for property ''nBins'' (type ''help analyses.mapAdaptiveSmoothing'' for details).');
                end
                haveNBins = true;
                i = i + 2;

            case 'mintime',
                minTime = varargin{i+1};
                if ~helpers.isdscalar(minTime, '>=0'),
                    error('Incorrect value for property ''minTime'' (type ''help analyses.mapAdaptiveSmoothing'' for details).');
                end
                i = i + 2;

            case 'alphavalue'
                alphaValue = varargin{i+1};
                if ~helpers.isiscalar(alphaValue, '>0'),
                    error('Incorrect value for property ''alphaValue'' (type ''help analyses.mapAdaptiveSmoothing'' for details).');
                end
                i = i + 2;

            case 'limits'
                limits = varargin{i+1};
                if ~isvector(limits)
                    error('Incorrect value for property ''limits'' (type ''help analyses.mapAdaptiveSmoothing'' for details).');
                end
                i = i + 2;

            otherwise,
                error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help analyses.mapAdaptiveSmoothing'' for details).']);
        end
    end

    % Some info about x, y and z
    if size(pos, 2) > 2
        posx = pos(:, 2);
        posy = pos(:, 3);
    else
        posx = pos(:, 1);
        posy = pos(:, 2);
    end

    if size(spkPos, 2) > 2
        spkx = spkPos(:, 2);
        spky = spkPos(:, 3);
    else
        spkx = spkPos(:, 1);
        spky = spkPos(:, 2);
    end

    if length(nBins) == 1
        nBins(2) = nBins(1);
    end

    % Calculate the border coordinates
    % xStart        Minimum x-coordinate for the path
    %
    % yStart        Minimum y-coordinate for the path
    %
    % xLength       Length of the arena in the x-direction [cm](for cylinder
    %               this equals the diameter)
    % yLength       Length of the arena in the y-direction [cm] (for cylinder
    %               this equals the diameter)
    maxX = nanmax(posx);
    maxY = nanmax(posy);
    xStart = nanmin(posx);
    yStart = nanmin(posy);
    xLength = maxX - xStart;
    yLength = maxY - yStart;

    if haveNBins && ~haveBinWidth
        binWidth = ceil(xLength / nBins(1));
        numColBins = nBins(1);
        numRowBins = nBins(2);
    else
        % Number of bins in each direction of the map
        numColBins = ceil(xLength / binWidth);
        numRowBins = ceil(yLength / binWidth);
    end

    halfBin = binWidth / 2;

    rowAxis = halfBin:binWidth:(numRowBins*binWidth)-halfBin;
    rowAxis = yStart + rowAxis';
    colAxis = halfBin:binWidth:(numColBins*binWidth)-halfBin;
    colAxis = xStart + colAxis';

    maxBins = max([numColBins, numRowBins]);

    map.x = colAxis;
    map.y = rowAxis;
    map.z = zeros(numRowBins, numColBins);
    posPdf = zeros(numRowBins, numColBins);

    if shape(1) == 1
        % Overall clue:
        %     - grow circle from r=1:maxBins (mult. of binWidth), tracking inside
        %     - stop at smallest rad. such that r >= alpha/samples*sqrt(spikes)
        radsqs = ((1:maxBins) * binWidth) .^ 2; % square radius in cm

        for i = 1:numColBins
            binPosX = colAxis(i);

            dist_sample_xdir = (posx - binPosX) .^ 2;
            dist_spike_xdir = (spkx - binPosX) .^ 2;

            for j = 1:numRowBins
                binPosY = rowAxis(j);

                % Calculate sample and spike distances from bin center
                dist_sample = dist_sample_xdir + (posy-binPosY).^2;
                dist_spike = dist_spike_xdir + (spky-binPosY).^2;

                found = 0;
                % Grow circle in increments of binWidth
                for r = 1:maxBins
                   n = nnz(dist_sample <= radsqs(r));
                   s = nnz(dist_spike <= radsqs(r));

                   if r >= alphaValue/(n*sqrt(s))
                       found = 1;
                       break;
                   end
                end

                % Set the rate for this bin
                map.z(j, i) = found * s/(n*sampleTime);
                posPdf(j, i) = found * n*sampleTime;
            end
        end
    else
        for ii = 1:numColBins
            binPosY = (yStart + binWidth/2);
            for jj = 1:numRowBins
                currentPosition = sqrt(binPosX^2 + binPosY^2);
                if currentPosition > shape(2)/2
                    map.z(numRowBins-jj+1, ii) = NaN;
                    posPdf(numRowBins-jj+1, ii) = NaN;
                else
                    n = 0;
                    s = 0;
                    for r = 1:maxBins
                        % Set the current radius of the circle
                        radius = r * binWidth;
                        % Number of samples inside the circle
                        n = insideCircle(binPosX, binPosY, radius, posx, posy);
                        % Number of spikes inside the circle
                        s = insideCircle(binPosX, binPosY, radius, spkx, spky);

                        if r >= alphaValue/(n*sqrt(s))
                            break;
                        end

                    end
                    % Set the rate for this bin
                    map.z(jj,ii) = s/(n*sampleTime);
                    posPdf(jj,ii) = n*sampleTime;

                end
                binPosY = binPosY + binWidth;
            end

            binPosX = binPosX + binWidth;
        end
    end

    map.z(posPdf < minTime) = NaN;
    posPdf = posPdf / nansum(nansum(posPdf));
end


function voxel3(T,varargin)
%VOXEL3 Visualize a third-order tensor with voxels.
%   voxel3(T) visualizes the third-order tensor T by plotting its elements
%   as voxels whose color and opacity are proportional to their value. The
%   figure contains two sliders for setting the parameters thresh and
%   degree (press 'h' to hide/show them). Let alpha = (T(i,j,k)-min(T(:))/
%   (max(T(:))-min(T(:))), then the opaqueness of each voxel, where 0 is
%   transparent and 1 is opaque, is computed as
%
%      alpha                            if alpha >= thresh
%      thresh^(1-degree)*alpha^degree   if alpha <  thresh
%
%   voxel3(T,varargin) passes the parameters varargin{:} to the plot.

%   Authors: Laurent Sorber (Laurent.Sorber@cs.kuleuven.be)
%            Marc Van Barel (Marc.VanBarel@cs.kuleuven.be)
%            Lieven De Lathauwer (Lieven.DeLathauwer@kuleuven-kulak.be)

% Check the dimensions.
if ndims(T) ~= 3
    error('voxel3:T','ndims(T) should be 3.');
end

% Check options.
idx = find(strcmpi('thresh',varargin),1,'last');
if idx < length(varargin)
    thresh = varargin{idx+1};
    varargin = [varargin(1:idx-1) varargin(idx+2:end)];
end
idx = find(strcmpi('degree',varargin),1,'last');
if idx < length(varargin)
    degree = varargin{idx+1};
    varargin = [varargin(1:idx-1) varargin(idx+2:end)];
end

% If the data is complex, convert it to the modulus.
% Remove any NaNs and Infs.
if any(~isreal(T(:))), T = abs(T); end
T(isnan(T) | (isinf(T) & T < 0)) = min(T(~isinf(T(:))));
T(isinf(T) & T > 0) = max(T(~isinf(T(:))));

% Compute the vertices.
st = size(T);
sv = st+1;
verts = zeros(prod(sv),3,'single');
verts(:,3) = repmat((.5:1:st(1)+.5).',size(verts,1)/sv(1),1);
verts(:,2) = repmat(kron((.5:1:st(2)+.5).',ones(sv(1),1)),sv(3),1);
verts(:,1) = kron((.5:1:st(3)+.5).',ones(size(verts,1)/sv(3),1));

% Compute the minimal number of colors and faces.
idx = {(1:prod(st+[1 0 0]))',(1:prod(st+[0 1 0]))',(1:prod(st+[0 0 1]))'};
off = [0 cumsum(cellfun(@numel,idx))];
color = zeros(sum(cellfun(@numel,idx)),1,'single');
faces = zeros(sum(cellfun(@numel,idx)),4,'single');
Tint = cat(1,T(1,:,:),max(T(1:end-1,:,:),T(2:end,:,:)),T(end,:,:));
[i,j,k] = ind2sub(size(Tint),idx{1});
color(off(1)+idx{1}) = single(Tint(:));
faces(off(1)+idx{1},:) = [sub2ind(sv,i,j  ,k)   sub2ind(sv,i,j+1,k) ...
                          sub2ind(sv,i,j+1,k+1) sub2ind(sv,i,j  ,k+1)];
Tint = cat(2,T(:,1,:),max(T(:,1:end-1,:),T(:,2:end,:)),T(:,end,:));
[i,j,k] = ind2sub(size(Tint),idx{2});
color(off(2)+idx{2}) = single(Tint(:));
faces(off(2)+idx{2},:) = [sub2ind(sv,i  ,j,k)   sub2ind(sv,i+1,j,k) ...
                          sub2ind(sv,i+1,j,k+1) sub2ind(sv,i  ,j,k+1)];
Tint = cat(3,T(:,:,1),max(T(:,:,1:end-1),T(:,:,2:end)),T(:,:,end));
[i,j,k] = ind2sub(size(Tint),idx{3});
color(off(3)+idx{3}) = single(Tint(:));
faces(off(3)+idx{3},:) = [sub2ind(sv,i  ,j  ,k) sub2ind(sv,i+1,j  ,k) ...
                          sub2ind(sv,i+1,j+1,k) sub2ind(sv,i  ,j+1,k)];

% Compute the opacity for each voxel.
mn = min(T(:));
mx = max(T(:));
alpha = (color-mn)/(mx-mn);
cutoff = 1e-4;

% Set up the figure.
cax = newplot;
if exist('degree','var') || exist('thresh','var')
    if exist('degree','var'), k = degree; else k = 1.0; end
    if exist('thresh','var'), t = thresh; else t = 0.5; end
else
    k = 1.0; t = 0.5;
    set(gcf,'Toolbar','figure');
    zoom off; pan off; rotate3d off; datacursormode off;
    lbl1 = uicontrol('Style','text','Position',[5 25 65 15], ...
                     'HorizontalAlignment','left');
    sld1 = uicontrol('Style','slider','Position',[75 25 120 15], ...
                     'Min',0,'Max',1,'Value',0.5, ...
                     'SliderStep',[0.1 0.25], ...
                     'Callback',{@redraw,'t'}, ...
                     'KeyPressFcn',@(obj,evt)toggle(evt.Key));
    lbl2 = uicontrol('Style','text','Position',[5 5 65 15], ...
                     'HorizontalAlignment','left');
    sld2 = uicontrol('Style','slider','Position',[75 5 120 15], ...
                     'Min',1,'Max',5,'Value',1, ...
                     'SliderStep',[0.25 0.5], ...
                     'Callback',{@redraw,'k'}, ...
                     'KeyPressFcn',@(obj,evt)toggle(evt.Key));
    isVisible = true;
    set(gcf,'KeyPressFcn',@(obj,evt)toggle(evt.Key));
end
redraw();

function toggle(key)
    % Toggle show or hide of uicontrols.
    if strcmpi(key,'h')
        onoff = 'on'; if isVisible, onoff = 'off'; end
        cellfun(@(c)set(c,'Visible',onoff),{lbl1,sld1,lbl2,sld2});
        isVisible = ~isVisible;
    end
end

function redraw(hobj,~,param)

    % Update the parameter.
    if nargin > 1
        switch param
            case 't', t = get(hobj,'Value');
            case 'k', k = get(hobj,'Value');
        end
    end
    if exist('lbl1','var')
        set(lbl1,'String',sprintf('thresh = %g',t));
        set(lbl2,'String',sprintf('degree = %g',k));
    end

    % Speed up rendering a bit.
    plot3(cax,nan,nan,nan,varargin{:});
    set(gcf,'DoubleBuffer','off');
    set(cax,'XLimMode','manual','YLimMode','manual', ...
            'ZLimMode','manual','CLimMode','manual','ALimMode','manual');

    % Set axis properties.
    xlabel('k');
    ylabel('j');
    zlabel('i');
    xlim([.5 st(3)+.5]);
    ylim([.5 st(2)+.5]);
    zlim([.5 st(1)+.5]);
    set(cax,'YDir','reverse');
    set(cax,'ZDir','reverse');
    caxis([mn mx]);

    % Display grid.
    step = max(1,round(st/6));
    set(cax,'XTickMode','manual','YTickMode','manual','ZTickMode','manual');
    tk = [1:step(3):st(3)-1 st(3)];
    if tk(end)-tk(end-1) < .3*step(3), tk = [tk(1:end-2) tk(end)]; end
    set(cax,'XTick',tk);
    tk = [1:step(2):st(2)-1 st(2)];
    if tk(end)-tk(end-1) < .3*step(2), tk = [tk(1:end-2) tk(end)]; end
    set(cax,'YTick',tk);
    tk = [1:step(1):st(1)-1 st(1)];
    if tk(end)-tk(end-1) < .3*step(1), tk = [tk(1:end-2) tk(end)]; end
    set(cax,'ZTick',tk);
    grid on;

    % Draw the voxels.
    opaq = alpha;
    opaq(alpha<t) = t^(1-k)*alpha(alpha<t).^k;
    opaq(opaq > 0.9) = 1; % Fix Matlab render bug.
    patch('Vertices',verts, ...
          'Faces',faces(opaq > cutoff,:), ...
          'EdgeColor','none','FaceAlpha','flat','FaceColor','flat', ...
          'FaceVertexAlphaData',opaq(opaq > cutoff), ...
          'FaceVertexCData',color(opaq > cutoff));

end

end


function [V,W] = art1s(p,rho,flag,V,W)
%ART1S    ART1 simulation function.
%
%         [V,W] = ART1S(P,rho,flag)
%           P   - F1xQ matrix of input vectors.
%           rho - the vigilance parameter, 0<= rho <=1.
%           flag  - (Optional) Printing flag. Any value of flag
%                   enables printing of events.
%         Returns:
%           V - the new top-down (T-D) weight matrix F1xF2.
%           W - the new bottom-up (B-U) weight matrix F2xF1.
%               F2 is the number of nodes in layer F2 (max # of categories)
%	  Example:  	P = letno;
%			art1s(P,0.7);
%
%		See also LETNO

%	  Author: Val Ninov, e-mail: valninov@total.net
%		  Grad. Student, Dept. of Electrical Engineering
%	          Concordia University, Montreal, Canada
%		  (c) April, 1997
%	  References:
%	   [1]	Carpenter, G. A. and S. Grossberg, "ART2: self-organization
%		of stable category recognition codes for analog input patterns."
%		Applied Optics, vol. 26, no. 23, Dec. 1987, pp. 4919-4930.
%	   [2]	J. Freeman and D. Skapura, Neural Networks: Algorithms,
%		Applications, and Programming Techniques. Addison Wesley

if nargin<2 | nargin>5  error('Wrong number of input arguments.');  end

% NETWORK PARAMETERS
 [R,Q] = size(p);
 F1 = R;
 F2 = Q;
 L = 2;
 categ = zeros(F2,F2); % category table
 count = ones(1,F2);   % counter for patterns in one category

% INITIALIZE WEIGHTS
if nargin < 4
 W = ones(F2,F1)*(L/(L-1+F1));
 V = ones(F1,F2);
 %fprintf('INITIAL TOP-DOWN MATRIX :');  V
 %fprintf('INITIAL BOTTOM-UP MATRIX :'); W
end

% INITIALIZE RETURN VARIABLES
a1 = zeros(F1,Q);   % output of F1
i = zeros(1,Q);     % winner index
win = 1;	    % First time node 1 in F2 is the winner
nActive = 1;        % The number of active neurons in F2

% PRESENT EACH INPUT VECTOR
for q=1:Q
    Reset = 0;
    B2 = zeros(F2,1);
    resonance = 0;
  while ~resonance    % REPEAT UNTIL: LAYERS F1 & F2 RESONATE
          % Initially a1 = p;
          % Calculate the winning node in F2 (among the active nodes)
	  A2 = compet(W(1:nActive,:)*p(:,q)+B2(1:nActive,1));
          i(q) = find(A2 == 1);
          win = i(q);
      % RECALCULATE a1 WITH FEEDBACK FROM A2
      a1(:,q) = (p(:,q) & V(:,win));

      % RESET if the new a1 is too different from p
	S= sum(a1(:,q));
	X= sum(p(:,q));
      Reset = (S/X) < rho;

       % IF RESET: TAKE WINNING NEURON IN F2 OUT OF COMPETITION
       if Reset
          B2(win) = -100;
             if nargin == 3
              fprintf('              RESET: Pattern %0.f resets F2 neuron %0.f.\n',q,win);
             end

           % IF ALL NEURONS IN A2 OUT OF COMPETITION ADD NEURON TO LAYER 2
           if all(B2(1:nActive,1) == -100)
	     nActive = nActive + 1;
                if nargin == 3
                 fprintf('            A new category %d created\n',nActive);
                end
               win = nActive;
           end

      % ELSE RESET NEURON DOES NOT FIRE: LAYERS 1 & 2 RESONATE
      else
           if nargin == 3
             fprintf('Pattern %d classified in %d category.\n',q,win);
           end
      resonance = 1;
      end

    end  % end of WHILE loop

    	% Update B-U LTM and T-D LTM
    	V(:,win) = a1(:,q)&V(:,win);
    	W(win,:) = (a1(:,q)*L/(L-1+sum(a1(:,q))))';
	%V(:,win) = V(:,win).*p(:,q);
	%W(win,:) = (V(:,win).*p(:,q))'/(0.5 + sum(V(:,win).*p(:,q)));
	 categ(win, count(win)) = q;
         count(win) = count(win)+1;
end	% end of FOR loop

% Display final classification
fprintf('\n  Category      Pattern\n  -----------------------------------------------\n');
 for i = 1:nActive
  fprintf('     %d           ',i);
   for j= 1:F2
	if categ(i,j)
         fprintf('%s, ',(categ(i,j)+64));
        end
   end
   fprintf('\n  ------------------------------------------------\n');
 end


function [ max_adif, max_adif_i, max_adif_j, max_rdif, max_rdif_i, max_rdif_j ] = ...
  p00_jac_check ( problem, option, nvar, x )

%*****************************************************************************80
%
%% P00_JAC_CHECK compares the jacobian with a finite difference estimate.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer PROBLEM, the problem index.
%
%    Input, integer OPTION, the option index.
%
%    Input, integer NVAR, the number of variables.
%
%    Input, real X(NVAR), the argument of the jacobian.
%
%    Output, real MAX_ADIF, the maximum absolute difference.
%
%    Output, integer MAX_ADIF_I, MAX_ADIF_J, the indices where
%    the maximmum absolute difference was found.
%
%    Output, real MAX_RDIF, the maximum relative difference.
%
%    Output, integer MAX_RDIF_I, MAX_RDIF_J, the indices where
%    the maximmum relative difference was found.
%
  rel = 0.0001;
%
%  Compute the jacobian.
%
  jac = p00_jac ( problem, option, nvar, x );
  jac_norm = max ( max ( abs ( jac ) ) );
%
%  Estimate the jacobian via finite differences.
%
  jac_dif = p00_jac_dif ( problem, option, nvar, x );
%
%  Compare the jacobians.
%
  max_rdif = 0.0;
  max_rdif_i = 0;
  max_rdif_j = 0;

  max_adif = 0.0;
  max_adif_i = 0;
  max_adif_j = 0;

  for i = 1 : nvar - 1
    for j = 1 : nvar

      dif = abs ( jac(i,j) - jac_dif(i,j) );

      if ( max_adif < dif )
        max_adif = dif;
        max_adif_i = i;
        max_adif_j = j;
      end

      if ( rel < abs ( jac(i,j) ) )
        if ( max_rdif * abs ( jac(i,j) ) < dif )
          max_rdif = dif / abs ( jac(i,j) );
          max_rdif_i = i;
          max_rdif_j = j;
        end
      end

    end
  end

  return
end


function [intl] = embedbp(I,txt,b)
% EMBEDBP Embeds the data in the bth bit plane of the image
%
% [INTL] = EMBEDBP(I,TXT,B) embeds the string TXT in the Bth bit-plane of
% the image I and returns the watermarked image INTL. If B is not speified,
% it is taken as 1.
%
% See also RECOVERBP

if nargin == 2
    b=1;
end
N = 8*numel(txt);
S = numel(I);
if N > S
    warning('Text truncated to be within size of image')
    txt = txt(1:floor(S/8));
    N = 8*numel(txt);
end
p = 2^b;
h = 2^(b-1);
I1 = reshape(I,1,S);
addl = S-N;
dim = size(I);
I2 = round(abs(I1(1:N)));
si = sign(I1(1:N));
for k = 1:N
    if si(k) == 0
        si(k) = 1;
    end
    I2(k) = round(I2(k));
    if mod((I2(k)),p) >= h
        I2(k) = I2(k) - h;
    end
end
bt = dec2bin(txt,8);
bint = reshape(bt,1,N);
d = h*48;
bi = (h*bint) - d;
I3 = double(I2) + bi;
binadd = [bi zeros(1,addl)];
I4 = double(si).*double(I3);
I5 = [I4 I1(N+1:S)];
intl = reshape(I5,dim);
return


function FDM=aggregateFDM(FDM,z,k,n)

for i=1:n
        tmp1=[];     tmp2=[];     tmp3=[];     tmp4=[];
    for j=1:k
        tmp1=[tmp1 FDM{j}{z,i}(1)];
        tmp2=[tmp2 FDM{j}{z,i}(2)];
        tmp3=[tmp3 FDM{j}{z,i}(3)];
        tmp4=[tmp4 FDM{j}{z,i}(4)];
    end
   Wj1a(i)=min(tmp1);
   Wj2a(i)=1/k*sum(tmp2);
   Wj3a(i)=1/k*sum(tmp3);
   Wj4a(i)=max(tmp4);

end
FDMtmp=[Wj1a; Wj2a; Wj3a; Wj4a];
for i=1:n
    FDM2{:,i}=FDMtmp(:,i)';
end
FDM=FDM2;


function [x, y] = ijcvConfidenceImage2contours(confim, maxy)

[imh, imw] = size(confim);

confim = imfilter(confim, fspecial('gaussian', 25, 7), 'same');

if ~exist('maxy')
    maxy = imh-15;
end

x = [15:imw-15];

cval = [0.25 0.5 0.75];

for c = 1:numel(cval)

    for i = 1:numel(x)
        try
            y{c}(i) = max(find(confim(1:maxy, x(i))>cval(c)));
        catch
            y{c}(i) = 1;
        end
    end

end


clear all; close all; clc;
%% Semi-Supervised 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_classes = 10;
settings.batch_size = 32; settings.image_size = [28,28,1];
settings.lr = 0.0002; settings.beta1 = 0.5;
settings.loss_weights = [.5,.5];
settings.beta2 = 0.999; settings.maxepochs = 50;

%% Initialization
%% Generator
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,32]));
paramsDis.CNb1 = dlarray(zeros(32,1,'single'));
paramsDis.CNW2 = dlarray(initializeGaussian([3,3,32,64]));
paramsDis.CNb2 = dlarray(zeros(64,1,'single'));
paramsDis.BNo1 = dlarray(zeros(64,1,'single'));
paramsDis.BNs1 = dlarray(ones(64,1,'single'));
paramsDis.CNW3 = dlarray(initializeGaussian([3,3,64,128]));
paramsDis.CNb3 = dlarray(zeros(128,1,'single'));
paramsDis.BNo2 = dlarray(zeros(128,1,'single'));
paramsDis.BNs2 = dlarray(ones(128,1,'single'));
paramsDis.CNW4 = dlarray(initializeGaussian([3,3,128,256]));
paramsDis.CNb4 = dlarray(zeros(256,1,'single'));
paramsDis.FCW1 = dlarray(initializeGaussian([settings.num_classes+2,256*4*4]));
paramsDis.FCb1 = dlarray(zeros(settings.num_classes+2,1,'single'));
stDis.BN1 = []; stDis.BN2 = []; stDis.BN3 = [];

% 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);

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

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

        if i==1 || rem(i,20)==0
            progressplot(paramsGen,stGen,settings);
        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
%% 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
ohe(1:10,:) = 5/8*ohe(1:10,:);
ohe(end,:) = 1/16*ohe(end,:);

end
%% 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,params,st)
% fully connected
dly = fullyconnect(dlx,params.FCW1,params.FCb1);
dly = relu(dly);
% transposed convolution
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
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*256,[]),'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)
[fake_images,stGen] = Generator(z,paramsGen,stGen);
d_output_real = Discriminator(x,paramsDis,stDis);
[d_output_fake,stDis] = Discriminator(fake_images,paramsDis,stDis);
labels_real = onehotencoding(y,11);
labels_fake = onehotencoding(10*ones(length(y),1),11);

% Loss due to true or not
dlossreal=-mean(log(d_output_real(1,:)+eps)+...
    labels_real.*log(d_output_real(2:end,:)+eps),'all');
dlossfake=-mean(log(1-d_output_fake(1,:)+eps)+...
    labels_fake.*log(d_output_fake(2:end,:)+eps),'all');
d_loss = .5*(dlossreal+dlossfake);
% g_loss=-mean(log(d_output_fake(1,:)+eps)+...
%     labels_real.*log(d_output_fake(2:end,:)+eps),'all');
g_loss=-mean(log(d_output_fake(1,:)+eps),'all');

% 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 = 5; c = 5;
noise = gpdl(randn([settings.latentDim,r*c]),'CB');
gen_imgs = Generator(noise,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