% This file create a simple regression based network for speech
% dereverberation or enhancement
%
% Created by Xiong Xiao, Temasek Laboratories, NTU, Singapore.
% Last Modified: 08 Feb 2017
%
function layer = genNetworkDereverb_Gaussian(para, stage)
para.freqBin = (0:1/para.fft_len:0.5)*2*pi; % w = 2*pi*f, where f is the normalized frequency k/N is from 0 to 0.5.
nFreqBin = length(para.freqBin);

% Part 1: generate the BF weight predicting subnet

if para.useWav  % input is row waveform
    layer{1}.name = 'Input';
    layer{end}.inputIdx = 1;
    layer{end}.dim = [1 1]*para.nCh;

    layer{end+1}.name = 'stft';
    layer{end}.prev = -length(layer)+1;
    layer{end}.fft_len = para.fft_len;
    layer{end}.frame_len = para.frame_len;
    layer{end}.frame_shift = para.frame_shift;
    layer{end}.removeDC = para.removeDC;
    layer{end}.win_type = para.win_type;
    layer{end}.dim = [(para.fft_len/2+1)*para.nCh layer{length(layer)+layer{end}.prev}.dim(1)];
    layer{end}.skipBP = 1;  % skip backpropagation

    layer{end+1}.name = 'Affine';       % scaling the Fourier transform
    layer{end}.prev = -1;
    layer{end}.W = [];
    layer{end}.b = [];
    layer{end}.dim = [1 1] * layer{length(layer)+layer{end}.prev}.dim(1);
    layer{end}.update = 0;
    layer{end}.skipBP = 1;  % skip backpropagation

    % extract a subset of dimensions for prediction. Not used currently, so we
    % will use all the dimensions.
    layer{end+1}.name = 'ExtractDims';
    layer{end}.prev = -1;
    layer{end}.dimIndex = 1:nFreqBin*para.nCh;
    layer{end}.dim = [length(layer{end}.dimIndex) layer{length(layer)+layer{end}.prev}.dim(1)];
    layer{end}.skipBP = 1;

    % get the log power spectrum and perform CMN
    layer{end+1}.name = 'Power';
    layer{end}.prev = -1;
    layer{end}.dim = [1 1] * layer{end-1}.dim(1);
    layer{end}.skipBP = 1;

    layer{end+1}.name = 'Log';
    layer{end}.const = 1e-2;
    layer{end}.prev = -1;
    layer{end}.dim = [1 1]*layer{end-1}.dim(1);
    layer{end}.skipBP = 1;
else    % input is log spectrogram
    layer{1}.name = 'Input';
    layer{end}.inputIdx = 1;
    layer{end}.dim = [1 1]*(para.fft_len/2+1)*para.nCh;
end

if para.useCMN
    layer{end+1}.name = 'CMN';
    layer{end}.prev = -1;
    layer{end}.dim = [1 1]*layer{end-1}.dim(1);
    layer{end}.skipBP = 1;
end

layer{end+1}.name = 'Delta';
layer{end}.prev = -1;
layer{end}.delta_order = 2;
layer{end}.dim = [layer{end}.delta_order+1 1]*layer{length(layer)+layer{end}.prev}.dim(1);
layer{end}.skipBP = 1;

layer{end+1}.name = 'Affine';       % scaling the Fourier transform
layer{end}.prev = -1;
layer{end}.W = [];
layer{end}.b = [];
layer{end}.dim = [1 1] * layer{length(layer)+layer{end}.prev}.dim(1);
layer{end}.update = 0;
layer{end}.skipBP= 1;

affineLayer = length(layer);

if ~isempty(para.hiddenLayerSizeShared)
    tmpTopology.inputDim = layer{end}.dim(1);
    tmpTopology.hiddenLayerSizeLSTM = para.hiddenLayerSizeShared;
    tmpTopology.usePastState = zeros(1,length(para.hiddenLayerSizeShared)); % do not use peeping hole
    tmpTopology.hiddenLayerSizeFF = [];
    tmpTopology.outputDim = 1024;
    tmpTopology.useAffineBtwLSTM = 1;
    tmpTopology.costFn = 'mse';
    tmpTopology.LastActivation4MSE = 'linear';
    layerShared = genNetworkLSTM(tmpTopology);
    if stage==2.2   % for stage 2.2, we don't even update the shared layer, only update the var subnet
        for i=1:length(layerShared)
            layerShared{i}.update = 0;
            layerShared{i}.skipBP = 1;
        end
    end
    layer = [layer layerShared(2:end-3)];
end

shared_lstm_idx = length(layer);

% get the mean
tmpTopology.inputDim = layer{shared_lstm_idx}.dim(1);
tmpTopology.hiddenLayerSizeLSTM = para.hiddenLayerSizeMu;
tmpTopology.usePastState = zeros(1,length(para.hiddenLayerSizeMu)); % do not use peeping hole
tmpTopology.hiddenLayerSizeFF = [];
if strcmpi(para.DeltaGenerationType, 'DeltaByEqn')
    tmpTopology.outputDim = nFreqBin;
else
    tmpTopology.outputDim = nFreqBin*3;
end
tmpTopology.costFn = 'mse';
tmpTopology.LastActivation4MSE = 'linear';
layerMu = genNetworkLSTM(tmpTopology);
layerMu = layerMu(2:end-2);
if ~isempty(para.hiddenLayerSizeMu) && ~isempty(para.hiddenLayerSizeShared)  % add a projection layer between two LSTM layers
    layerMu = [layer(affineLayer) layerMu];
    layerMu{1}.update = 1;
    layerMu{1}.skipBP = 0;
    layerMu{1}.dim = [1 1]*layer{shared_lstm_idx}.dim(1);
end
layerMu{1}.prev = shared_lstm_idx - length(layer)-1;
if floor(stage)==2
    for i=1:length(layerMu)
        layerMu{i}.update = 0;
        if stage==2.2  % if there is no shared layers, we don't let the gradient from mean layers
            layerMu{i}.skipBP = 1;
        end
    end
end
layer = [layer layerMu];

if strcmpi(para.DeltaGenerationType, 'DeltaByEqn')
    layer{end+1}.name = 'Delta';
    layer{end}.prev = -1;
    layer{end}.delta_order = 2;
    layer{end}.dim = [layer{end}.delta_order+1 1]*layer{length(layer)+layer{end}.prev}.dim(1);
end

mean_idx = length(layer);

% get the var
tmpTopology.inputDim = layer{shared_lstm_idx}.dim(1);
tmpTopology.hiddenLayerSizeLSTM = para.hiddenLayerSizeVar;
tmpTopology.usePastState = zeros(1,length(para.hiddenLayerSizeVar)); % do not use peeping hole
tmpTopology.hiddenLayerSizeFF = [];
tmpTopology.outputDim = nFreqBin*3;
tmpTopology.costFn = 'mse';
tmpTopology.LastActivation4MSE = 'linear';
layerVar = genNetworkLSTM(tmpTopology);
layerVar = layerVar(2:end-2);
layerVar{1}.prev = shared_lstm_idx - length(layer)-1;
if stage==1
    for i=1:length(layerVar)
        layerVar{i}.update = 0;
        layerVar{i}.skipBP = 1;
    end
    % always output unit variance
    layerVar{end}.W = zeros(layerVar{end}.dim(1), layerVar{end}.dim(2));
    layerVar{end}.b = zeros(layerVar{end}.dim(1),1);
    layerVar{end}.b(nFreqBin+1:nFreqBin*2) = -log(para.MSECostWeightSDA(2)^2);
    layerVar{end}.b(nFreqBin*2+1:nFreqBin*3) = -log(para.MSECostWeightSDA(3)^2);
end
layer = [layer layerVar];

layer{end+1}.name = 'exp';
layer{end}.prev = -1;
layer{end}.dim = [1 1]* layer{end-1}.dim(1);

var_idx = length(layer);

if para.useWav
    log_idx = ReturnLayerIdxByName(layer, 'log');
    if para.useCMN
        CleanLayer = layer(1:log_idx(1)+1);
    else
        CleanLayer = layer(1:log_idx(1));
    end
    CleanLayer{1}.inputIdx = 2;
    CleanLayer{1}.dim(:) = 1;
    CleanLayer{2}.dim(:) = CleanLayer{2}.dim(:)/para.nCh;
    CleanLayer{3}.dim(:) = CleanLayer{3}.dim(:)/para.nCh;
    CleanLayer(4) = [];
else
    CleanLayer{1}.name = 'Input';
    CleanLayer{end}.inputIdx = 2;
    CleanLayer{end}.dim = [1 1]*(para.fft_len/2+1);
end

CleanLayer{end+1}.name = 'Delta';
CleanLayer{end}.prev = -1;
CleanLayer{end}.delta_order = 2;
CleanLayer{end}.dim = [CleanLayer{end}.delta_order+1 1]*CleanLayer{length(CleanLayer)+CleanLayer{end}.prev}.dim(1);

layer = [layer CleanLayer];

layer{end+1}.name = 'LL_Gaussian';
layer{end}.prev = [mean_idx-length(layer) var_idx-length(layer) -1];
layer{end}.dim = [1 layer{end-1}.dim(1)];

layer = FinishLayer(layer);
end


function [LL, prior, transmat, mu, Sigma, mixmat] = ...
     mhmm_em(data, prior, transmat, mu, Sigma, mixmat, varargin);
% LEARN_MHMM Compute the ML parameters of an HMM with (mixtures of) Gaussians output using EM.
% [ll_trace, prior, transmat, mu, sigma, mixmat] = learn_mhmm(data, ...
%   prior0, transmat0, mu0, sigma0, mixmat0, ...)
%
% Notation: Q(t) = hidden state, Y(t) = observation, M(t) = mixture variable
%
% INPUTS:
% data{ex}(:,t) or data(:,t,ex) if all sequences have the same length
% prior(i) = Pr(Q(1) = i),
% transmat(i,j) = Pr(Q(t+1)=j | Q(t)=i)
% mu(:,j,k) = E[Y(t) | Q(t)=j, M(t)=k ]
% Sigma(:,:,j,k) = Cov[Y(t) | Q(t)=j, M(t)=k]
% mixmat(j,k) = Pr(M(t)=k | Q(t)=j) : set to [] or ones(Q,1) if only one mixture component
%
% Optional parameters may be passed as 'param_name', param_value pairs.
% Parameter names are shown below; default values in [] - if none, argument is mandatory.
%
% 'max_iter' - max number of EM iterations [10]
% 'thresh' - convergence threshold [1e-4]
% 'verbose' - if 1, print out loglik at every iteration [1]
% 'cov_type' - 'full', 'diag' or 'spherical' ['full']
%
% To clamp some of the parameters, so learning does not change them:
% 'adj_prior' - if 0, do not change prior [1]
% 'adj_trans' - if 0, do not change transmat [1]
% 'adj_mix' - if 0, do not change mixmat [1]
% 'adj_mu' - if 0, do not change mu [1]
% 'adj_Sigma' - if 0, do not change Sigma [1]
%
% If the number of mixture components differs depending on Q, just set  the trailing
% entries of mixmat to 0, e.g., 2 components if Q=1, 3 components if Q=2,
% then set mixmat(1,3)=0. In this case, B2(1,3,:)=1.0.

if ~isstr(varargin{1}) % catch old syntax
  error('optional arguments should be passed as string/value pairs')
end

[max_iter, thresh, verbose, cov_type,  adj_prior, adj_trans, adj_mix, adj_mu, adj_Sigma] = ...
    process_options(varargin, 'max_iter', 10, 'thresh', 1e-4, 'verbose', 1, ...
		    'cov_type', 'full', 'adj_prior', 1, 'adj_trans', 1, 'adj_mix', 1, ...
		    'adj_mu', 1, 'adj_Sigma', 1);

previous_loglik = -inf;
loglik = 0;
converged = 0;
num_iter = 1;
LL = [];

if ~iscell(data)
  data = num2cell(data, [1 2]); % each elt of the 3rd dim gets its own cell
end
numex = length(data);

O = size(data{1},1);
Q = length(prior);
if isempty(mixmat)
  mixmat = ones(Q,1);
end
M = size(mixmat,2);
if M == 1
  adj_mix = 0;
end

while (num_iter <= max_iter) & ~converged
  % E step
  [loglik, exp_num_trans, exp_num_visits1, postmix, m, ip, op] = ...
      ess_mhmm(prior, transmat, mixmat, mu, Sigma, data);

  % M step
  if adj_prior
    prior = normalise(exp_num_visits1);
  end
  if adj_trans
    transmat = mk_stochastic(exp_num_trans);
  end
  if adj_mix
    mixmat = mk_stochastic(postmix);
  end
  if adj_mu | adj_Sigma
    [mu2, Sigma2] = mixgauss_Mstep(postmix, m, op, ip, 'cov_type', cov_type);
    if adj_mu
      mu = reshape(mu2, [O Q M]);
    end
    if adj_Sigma
      Sigma = reshape(Sigma2, [O O Q M]);
    end
  end

  if verbose, fprintf(1, 'iteration %d, loglik = %f\n', num_iter, loglik); end
  num_iter =  num_iter + 1;
  converged = em_converged(loglik, previous_loglik, thresh);
  previous_loglik = loglik;
  LL = [LL loglik];
end

%%%%%%%%%

function [loglik, exp_num_trans, exp_num_visits1, postmix, m, ip, op] = ...
    ess_mhmm(prior, transmat, mixmat, mu, Sigma, data)
% ESS_MHMM Compute the Expected Sufficient Statistics for a MOG Hidden Markov Model.
%
% Outputs:
% exp_num_trans(i,j)   = sum_l sum_{t=2}^T Pr(Q(t-1) = i, Q(t) = j| Obs(l))
% exp_num_visits1(i)   = sum_l Pr(Q(1)=i | Obs(l))
%
% Let w(i,k,t,l) = P(Q(t)=i, M(t)=k | Obs(l))
% where Obs(l) = Obs(:,:,l) = O_1 .. O_T for sequence l
% Then
% postmix(i,k) = sum_l sum_t w(i,k,t,l) (posterior mixing weights/ responsibilities)
% m(:,i,k)   = sum_l sum_t w(i,k,t,l) * Obs(:,t,l)
% ip(i,k) = sum_l sum_t w(i,k,t,l) * Obs(:,t,l)' * Obs(:,t,l)
% op(:,:,i,k) = sum_l sum_t w(i,k,t,l) * Obs(:,t,l) * Obs(:,t,l)'

verbose = 0;

%[O T numex] = size(data);
numex = length(data);
O = size(data{1},1);
Q = length(prior);
M = size(mixmat,2);
exp_num_trans = zeros(Q,Q);
exp_num_visits1 = zeros(Q,1);
postmix = zeros(Q,M);
m = zeros(O,Q,M);
op = zeros(O,O,Q,M);
ip = zeros(Q,M);

mix = (M>1);

loglik = 0;
if verbose, fprintf(1, 'forwards-backwards example # '); end
for ex=1:numex
  if verbose, fprintf(1, '%d ', ex); end
  %obs = data(:,:,ex);
  obs = data{ex};
  T = size(obs,2);
  if mix
    [B, B2] = mixgauss_prob(obs, mu, Sigma, mixmat);
    [alpha, beta, gamma,  current_loglik, xi, gamma2] = ...
	fwdback(prior, transmat, B, 'obslik2', B2, 'mixmat', mixmat);
  else
    B = mixgauss_prob(obs, mu, Sigma);
    [alpha, beta, gamma,  current_loglik, xi] = fwdback(prior, transmat, B);
  end
  loglik = loglik +  current_loglik;
  if verbose, fprintf(1, 'll at ex %d = %f\n', ex, loglik); end

  exp_num_trans = exp_num_trans + sum(xi,3);
  exp_num_visits1 = exp_num_visits1 + gamma(:,1);

  if mix
    postmix = postmix + sum(gamma2,3);
  else
    postmix = postmix + sum(gamma,2);
    gamma2 = reshape(gamma, [Q 1 T]); % gamma2(i,m,t) = gamma(i,t)
  end
  for i=1:Q
    for k=1:M
      w = reshape(gamma2(i,k,:), [1 T]); % w(t) = w(i,k,t,l)
      wobs = obs .* repmat(w, [O 1]); % wobs(:,t) = w(t) * obs(:,t)
      m(:,i,k) = m(:,i,k) + sum(wobs, 2); % m(:) = sum_t w(t) obs(:,t)
      op(:,:,i,k) = op(:,:,i,k) + wobs * obs'; % op(:,:) = sum_t w(t) * obs(:,t) * obs(:,t)'
      ip(i,k) = ip(i,k) + sum(sum(wobs .* obs, 2)); % ip = sum_t w(t) * obs(:,t)' * obs(:,t)
    end
  end
end
if verbose, fprintf(1, '\n'); end


function imdata = mcmcComputeImageData(im, imsegs)

[imh, imw] = size(imsegs.segimage);
imdata.yim = 1-repmat([(0:imh-1)/(imh-1)]', 1, imw);
imdata.xim = repmat([(0:imw-1)/(imw-1)], imh, 1);

[gx, gy] = gradient(im);
imdata.gradim = sqrt(sum(gx.^2 + gy.^2, 3));

minEdgeLen = sqrt(imh^2+imw^2)*0.02;
[vpdata.lines, vpdata.spinfo] = ...
    APPgetLargeConnectedEdges(rgb2gray(im), minEdgeLen, imsegs);
   [vpdata.v, vpdata.vars, vpdata.p, vpdata.hpos] = ...
       APPestimateVp(vpdata.lines, [imh imw], 0);
%  [vpdata.v vpdata.vars vpdata.p vpdata.hpos]=AppgetVP(vpdata.lines,[imh imw],0);

imdata.vpdata = vpdata;

% get pixels in each superpixel
stats = regionprops(imsegs.segimage, 'PixelIdxList');
imdata.pixlist = {stats.PixelIdxList};

%%by varsha%%%

for segno=1:imsegs.nseg
   BW=(imsegs.segimage==segno);
   imdata.tracedbndy{segno}= bwboundaries(BW);
end

%%%%%%%%%%%
% get boundary pixels for each superpixel
[tx, ty] = gradient(double(imsegs.segimage));
segedgeim = (tx~=0) | (ty ~=0);
stats = regionprops(double(imsegs.segimage).*segedgeim, 'PixelIdxList');
imdata.bndpixlist = {stats.PixelIdxList};
imdata.bndnpix = zeros(size(imdata.bndpixlist));
for s = 1:imsegs.nseg
    try
        imdata.bndnpix(s) = numel(imdata.bndpixlist{s});
    catch
        imdata.bndnpix(s) = 0;
    end
end

% get a random subset of pixels and boundary pixels to speed computation of
% some features
for s = 1:imsegs.nseg
    npix = imsegs.npixels(s);
    nbndpix = imdata.bndnpix(s);
    imdata.nsmpix(s) = min(npix, 1000);
    imdata.nsmbndpix(s) = floor(nbndpix/4);
    if npix>1000
        rind = randperm(npix);
        imdata.smpixlist{s} = imdata.pixlist{s}(rind(1:1000));
    else
        imdata.smpixlist(s) = imdata.pixlist(s);
    end
    rind = randperm(nbndpix);
    try
        imdata.smbndpixlist{s} = imdata.bndpixlist{s}(rind(1:imdata.nsmbndpix(s)));
    catch
        imdata.smbndpixlist{s} = [];
    end
end


clc;
clear all;
for num=1:19
  I_ir=im2double(imread(strcat('',num2str(num-1),'.png')));
  [I,v1,v2]=rgb2ihs(I_ir);
  imwrite(I, strcat('',num2str(num),'.bmp'));
%   imwrite(v1,strcat('',num2str(num),'.bmp'));
%   imwrite(v2,strcat('',num2str(num),'.bmp'));

end


function i4vec_index_delete_all_test ( )

%*****************************************************************************80
%
%% I4VEC_INDEX_DELETE_ALL_TEST tests I4VEC_INDEX_DELETE_ALL.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 April 2009
%
%  Author:
%
%    John Burkardt
%
  n_max = 25;
  n = 0;
  x = [];
  indx = [];

  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4VEC_INDEX_DELETE_ALL_TEST\n' );
  fprintf ( 1, '  I4VEC_INDEX_DELETE_ALL deletes all copies of a\n' );
  fprintf ( 1, '  particular value.\n' );

  xval = 8;
  [ n, x, indx ] = i4vec_index_insert ( n, x, indx, xval );

  xval = 7;
  [ n, x, indx ] = i4vec_index_insert ( n, x, indx, xval );

  b = 0;
  c = 20;
  seed = 123456789;

  for i = 1 : 20
    [ xval, seed ] = i4_uniform_ab ( b, c, seed );
    fprintf ( 1, '  %6d\n', xval );
    [ n, x, indx ] = i4vec_index_insert ( n, x, indx, xval );
  end

  xval = 7;
  [ n, x, indx ] = i4vec_index_insert ( n, x, indx, xval );

  xval = 8;
  [ n, x, indx ] = i4vec_index_insert ( n, x, indx, xval );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Indexed list of entries:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  I  INDX(I)  X(I)  X(INDX(I))\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n
    fprintf ( 1, '  %6d  %6d  %6d  %6d\n', i, indx(i), x(i), x(indx(i)) );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Call I4VEC_INDEX_DELETE_ALL to delete values of 7:\n' );

  xval = 7;
  [ n, x, indx ] = i4vec_index_delete_all ( n, x, indx, xval );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Indexed list of entries:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  I  INDX(I)  X(I)  X(INDX(I))\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n
    fprintf ( 1, '  %6d  %6d  %6d  %6d\n', i, indx(i), x(i), x(indx(i)) );
  end

  return
end


% PROPAGATION_KERNEL_GRID calculates the propagation kernel between data
% organized in grids.
%
% This function contains an implementation of the propagation kernel
% for grid graphs. Propagation kernels for general graphs are described in:
%
% Neumann, M., Patricia, N., Garnett, R., and Kersting, K. Efficient
% Graph Kernels by Randomization. (2012). Machine Learning And
% Knowledge Discovery in Databases: European Conference, (ECML/PKDD
% 2012), pp. 378-392.
%
% This implementation supports (approximately) preserving any of the
% following distances between the feature vectors:
%
% - \ell^1 or \ell^2 for arbitrary feature vectors
% - the total variation or Hellinger distance for
% distribution-valued features
%
% Depending on the chosen distance, the input features will be
% transformed appropriately.
%
% This implementation also supports arbitrary transformations to be
% used. See the transformations/ directory for example implementations
% (isotropic diffusion). Transformations must satisfy the following very
% general interface:
%
% A = transformation(A);
%
% Where the input is a cell array of N feature matrices of size (n x m x d).
% One feature matrix per grid graph. (n x m) are the grid dimensions and d
% is the feature dimension. The transformation function computes a new set
% of features given an old set.
%
% Usage:
%
% K = propagation_kernel_grid(A, transformation, num_iterations, varargin)
%
% Inputs:
%
% A: a cell array of N feature matrices of sizes (n x m x d) to hash. n and
% m can be different for each grid graph. If either the total variation or
% Hellinger distance is chosen, the feature matrices should sum to 1 in
% their 3rd dimension.
%
% transformation: a function handle to a feature transformation
% function satisfying the above-described API.
%
% num_iterations: the number of iterations to use for the kernel
% computation.
%
% Optional inputs (specified as name/value pairs):
%
% 'w': the bin width to use during the hashing
% computation (default: 1e-4)
%
% 'distance': a string indicating the distance to approximately
% preserve; the following values are supported:
% 'l1': \ell^1
% 'l2': \ell^2
% 'tv': total variation distance (equivalent to \ell^1)
% 'hellinger': Hellinger distance
%
% The input is not case sensitive. See
% calculate_hashes for more information.
% (default: 'l1').
%
% 'base_kernel': a function handle to the base kernel to use. The
% kernel will be called as:
%
% K = base_kernel(counts),
%
% where counts is a (N x k) matrix, where m is the number of graphs and k
% is the number of unique hashes during this step of the computation.
% counts(i, j) contains the number of times hash j occurs in graph i.
% The default base kernel is the linear one:
%
% @(counts) (counts * counts');
%
% Outputs:
%
% K: an (N x N) matrix containing the computed propagation kernel.
%
% See also CALCULATE_HASHES_GRID, LABEL_DIFFUSION_CONVOLUTION.
%
%
% Based on the implementation of propagation_kernel by
% (c) Roman Garnett, 2012--2014.
%
% Copyright (c) Marion Neumann, 2014.

function K = propagation_kernel_grid(A, transformation, ...
                                                num_iterations, varargin)
  verbose = false;

  % parse optional inputs
  options = inputParser;

  % which distance to use
  options.addOptional('distance', 'l1', ...
                      @(x) ismember(lower(x), {'l1', 'l2', 'tv', 'hellinger'}));
  % width for hashing
  options.addOptional('w', 1e-4, ...
                      @(x) (isscalar(x) && (x > 0)));
  % base kernel for counts vector, default is linear kernel
  options.addOptional('base_kernel', ...
                      @(counts) (counts * counts'), ...
                      @(x) (isa(x, 'function_handle')));
  options.addOptional('num_steps', 1, ...
                      @(x) (isscalar(x) && (x > 0)));   % do num_stps feature updates per kernel contribution

  options.parse(varargin{:});
  options = options.Results;

  num_graphs = size(A,1);
  K = zeros(num_graphs);    % initialize output
  iteration = 0;
  while (true)

    % hashing
    if (verbose); fprintf('...computing hashvalues\n'); end
    hash_labels = calculate_hashes_grid(A, options.distance, options.w);

    % GET set of existing hash labels
    sth = cellfun(@(im) (unique(im(:))), hash_labels,'UniformOutput',false);
    label_set = unique(cell2mat(sth));
    min_label = min(label_set);
    num_labels = numel(label_set);
    label_set = label_set-min_label+1;

    if num_labels > 200000
            fprintf('skipping kernel contribution at iteration %d (num hashlabels too large = %d)\n',...
                    iteration, num_labels);
    else

        % aggregate counts on graphs
        if (verbose); fprintf('...computing kernel contribution\n'); end

        add_contrib = true;
        counts = zeros(num_graphs,num_labels);
        for i=1:num_graphs
            hash_labels{i} = hash_labels{i}-min_label+1;
            try
                curr_counts = accumarray(hash_labels{i}(:), 1);
            catch
                add_contrib=false;
                warning('skipping kernel contribution at iteration %d (num hashlabels = %d)\n', iteration, num_labels);
                break
            end
            idx = ismember(label_set,find(curr_counts));
            counts(i,idx) = curr_counts(find(curr_counts));
        end

        % contribution specified by base kernel on count vectors
        if add_contrib
            K = K + options.base_kernel(counts);
        end
    end
    % avoid unnecessary transformation on last iteration
    if (iteration == num_iterations)
      break;
    end

    % apply transformation to features for next step
    if (verbose); fprintf('...label update\n'); end
    for step=1:options.num_steps
        A = transformation(A);
    end
    iteration = iteration + 1;
  end
end


function B = fast_unitary_tranform(A, D, type)
% B = fast_unitary_tranform(A, D, type)
%
% Applies a fast unitary transform (DCT, DHT and WHT) to D * A
% after padding with zeros.
%
% type is either 'DCT', 'DHT' or 'WHT'.
%
% 6-December 2009, Version 1.3
% Copyright (C) 2009, Haim Avron and Sivan Toledo.


%==============================================================================
% This code is part of the Matlab-based toolbox
% FAIR - Flexible Algorithms for Image Registration.
% For details see
% - https://github.com/C4IR and
% - http://www.siam.org/books/fa06/
%==============================================================================
%
% function [Dc,rc,dD,dr,d2psi] = SSDmex(Tc,Rc,omega,m,varargin)
%
% Wrapper for C file for Sum of Squared Differences based distance measure,
% see also SSD for details
% see also distances/contents
%==============================================================================

function [Dc,rc,dD,dr,d2psi] = SSDmex(Tc,Rc,omega,m,varargin)

if nargin == 0
    help(mfilename);
    setup2DhandData
    xc = getCellCenteredGrid(omega,m);
    Tc = linearInter(dataT,omega,xc);
    Rc = linearInter(dataR,omega,xc);
    D0 = feval(mfilename,Tc,Rc,omega,m);
    fprintf('%s: distance = %s\n',mfilename,num2str(D0))
    return
end

dD = []; dr = []; d2psi = [];
doDerivative = (nargout > 3);

for k=1:2:length(varargin)      % overwrite default parameter
    eval([varargin{k},'=varargin{',int2str(k+1),'};']);
end

hd = prod((omega(2:2:end)-omega(1:2:end))./m); % voxel size for integration

if ~doDerivative
    try
        [Dc,rc] = SSDmexC(Tc,Rc,hd);
    catch err
        FAIRerror(err);
    end
else
    try
        [Dc,rc,dD,dr,d2psi] = SSDmexC(Tc,Rc,hd);
    catch err
        FAIRerror(err);
    end
end

%==============================================================================


function B = xrepmat(A,varargin)
%XREPMAT Replicate and tile an array.
%
%   XREPMAT(A,M,N) and XREPMAT(A,[M N]) replicates and tiles the matrix
%   A to produce a M-by-N block matrix.
%
%   XREPMAT(A,(M,N,P,...) and XREPMAT(A,[M N P ...]) tiles the array A
%   to produce a M-by-N-by-P-by-... block array.  A can be N-D.
%
%   XREPMAT(A,M,N) when A is a scalar is commonly used to produce an
%   M-by-N matrix filled with A's value.  This can be much faster than
%   A*ONES(M,N) when M and/or N are large.
%
%   Example:
%       xrepmat(magic(2),2,3)
%       xrepmat(NaN,2,3)
%
%   See also REPMAT, MESHGRID, NDGRID.

%   Author:      Peter J. Acklam
%   Time-stamp:  2002-03-03 13:50:27 +0100
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

if nargin < 2
   error( 'Not enough input arguments.' );
elseif nargin == 2
   if length(varargin{1}) == 1          % XREPMAT(A,M)
      Rsiz = [ varargin{1} varargin{1} ];
   else                                 % XREPMAT(A,[M N P ...])
      Rsiz = varargin{1};
   end
else                                    % XREPMAT(A,[M N P ...])
   Rsiz = [ varargin{:} ];
end

if length(A) == 1
   nelems = prod(Rsiz);
   if nelems > 0
      % Since B doesn't exist, the first statement creates a B with the
      % right size and type.  Then use scalar expansion to fill the
      % array.  Finally reshape to the specified size.
      B(nelems) = A;
      B(:) = A;
      B = reshape(B,Rsiz);
   else
      B = A(ones(Rsiz));
   end
else
   Asiz = size(A);
   Adim = length(Asiz);
   Rdim = length(Rsiz);
   if ( Adim == 2 ) & ( Rdim == 2 )
      mind = (1:Asiz(1))';
      nind = (1:Asiz(2))';
      mind = mind(:,ones(1,Rsiz(1)));
      nind = nind(:,ones(1,Rsiz(2)));
      B = A(mind,nind);
   else
      Bdim = max(Adim,Rdim);
      Asiz = [ Asiz ones(1,Bdim-Adim) ];
      Rsiz = [ Rsiz ones(1,Bdim-Rdim) ];

      % This might be `clever', but this is usually slower than the
      % for-loop below.
%      v = reshape( reshape( 1:2*Bdim, Bdim, 2 )', 1, 2*Bdim );
%      A = A(:);
%      B = reshape( A(:,ones(1,prod(Rsiz))), [ Asiz Rsiz ] );
%      B = reshape( permute( B, v ), Asiz.*Rsiz );

      for i = 1:Bdim
         ind = (1:Asiz(i))';
         subs{i} = ind(:,ones(1,Rsiz(i)));
      end
      B = A(subs{:});

   end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Q = INVERSEKINEMATIC_FLEXION_N2(robot, T)
%   Solves the inverse kinematic problem for the ABB IRB 140 robot
%   where:
%   robot stores the robot parameters.
%   T is an homogeneous transform that specifies the position/orientation
%   of the end effector.
%
%   A call to Q=INVERSEKINEMATIC_FLEXION_N2 returns 8 possible solutions, thus,
%   Q is a 6x8 matrix where each column stores 6 feasible joint values.
%
%
%   Example code:
%
%   >>epson=load_robot('EPSON', 'FLEXION_N2');
%   >>q = [0 0 0 0 0 0];
%   >>T = directkinematic(epson, q);
%
%   %Call the inversekinematic for this robot
%
%   >> qinv = inversekinematic(epson, T);
%
%   check that all of them are feasible solutions!
%   and every Ti equals T
%
%   for i=1:8,
%        Ti = directkinematic(epson, qinv(:,i))
%   end
%
%	See also DIRECTKINEMATIC.
%
%   Author: Arturo Gil Aparicio
%           Universitas Miguel Hernandez, SPAIN.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright (C) 2012, by Arturo Gil Aparicio
%
% This file is part of ARTE (A Robotics Toolbox for Education).
%
% ARTE is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% ARTE 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 Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with ARTE.  If not, see <http://www.gnu.org/licenses/>.
function q = inversekinematic_flexion_n2(robot, T)

Ts=[-1 0 0 0; 0 -1 0 0; 0 0 -1 0.9; 0 0 0 1];
T=inv(Ts)*T;
%initialize q,
%eight possible solutions are generally feasible
q=zeros(6,8);

%Evaluate the parameters
d = eval(robot.DH.d);

%See geometry at the reference for this robot
L6=d(6);

%A1 = a(1);

%T= [ nx ox ax Px;
%     ny oy ay Py;
%     nz oz az Pz];
Px=T(1,4);
Py=T(2,4);
Pz=T(3,4);

%Compute the position of the wrist, being W the Z component of the end effector's system
W = T(1:3,3);

% Pm: wrist position
Pm = [Px Py Pz]' - L6*W;

%first joint, two possible solutions admited:
% if q(1) is a solution, then q(1) + pi is also a solution
q1=atan2(Pm(2), Pm(1))+pi/2;

%solve for q2
q2_1=solve_for_theta2(robot, [q1 0 0 0 0 0 0], Pm);

q2_2=solve_for_theta2(robot, [q1+pi 0 0 0 0 0 0], Pm);

%solve for q3
q3_1=solve_for_theta3(robot, [q1 0 0 0 0 0 0], Pm);

q3_2=solve_for_theta3(robot, [q1+pi 0 0 0 0 0 0], Pm);

%Arrange solutions, there are 8 possible solutions so far.
% if q1 is a solution, q1* = q1 + pi is also a solution.
% For each (q1, q1*) there are two possible solutions
% for q2 and q3 (namely, elbow up and elbow up solutions)
% So far, we have 4 possible solutions. Howefer, for each triplet (theta1, theta2, theta3),
% there exist two more possible solutions for the last three joints, generally
% called wrist up and wrist down solutions. For this reason,
%the next matrix doubles each column. For each two columns, two different
%configurations for theta4, theta5 and theta6 will be computed. These
%configurations are generally referred as wrist up and wrist down solution
q = [q1         q1         q1        q1       q1+pi   q1+pi   q1+pi   q1+pi;
     q2_1(1)    q2_1(1)    q2_1(2)   q2_1(2)  q2_2(1) q2_2(1) q2_2(2) q2_2(2);
     q3_1(1)    q3_1(1)    q3_1(2)   q3_1(2)  q3_2(1) q3_2(1) q3_2(2) q3_2(2);
     0          0          0         0         0      0       0       0;
     0          0          0         0         0      0       0       0;
     0          0          0         0         0      0       0       0];

%leave only the real part of the solutions
q=real(q);

%Note that in this robot, the joint q3 has a non-simmetrical range. In this
%case, the joint ranges from 60 deg to -219 deg, thus, the typical normalizing
%step is avoided in this angle (the next line is commented). When solving
%for the orientation, the solutions are normalized to the [-pi, pi] range
%only for the theta4, theta5 and theta6 joints.

%normalize q to [-pi, pi]
q(1,:) = normalize(q(1,:));
q(2,:) = normalize(q(2,:));

% solve for the last three joints
% for any of the possible combinations (theta1, theta2, theta3)
for i=1:2:size(q,2),
    % use solve_spherical_wrist2 for the particular orientation
    % of the systems in this EPSON robot
    % use either the geometric or algebraic method.
    % the function solve_spherical_wrist2 is used due to the relative
    % orientation of the last three DH reference systems.

    %use either one algebraic method or the geometric
    qtemp = solve_spherical_wrist_flexion_n2(robot, q(:,i), T, 1, 'geometric'); %wrist up
    %qtemp = solve_spherical_wrist_flexion_n2(robot, q(:,i), T, 1,'algebraic'); %wrist up
    %qtemp = solve_spherical_wrist(robot, q(:,i), T, 1, 'geometric'); %wrist up
    %qtemp = solve_spherical_wrist(robot, q(:,i), T, 1,'algebraic'); %wrist up
    qtemp(4:6)=normalize(qtemp(4:6));
    q(:,i)=qtemp;

    qtemp = solve_spherical_wrist_flexion_n2(robot, q(:,i), T, -1, 'geometric'); %wrist down
    %qtemp = solve_spherical_wrist_flexion_n2(robot, q(:,i), T, -1,'algebraic'); %wrist up
    %qtemp = solve_spherical_wrist(robot, q(:,i), T, -1, 'algebraic'); %wrist down
    qtemp(4:6)=normalize(qtemp(4:6));
    q(:,i+1)=qtemp;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% solve for second joint theta2, two different
% solutions are returned, corresponding
% to elbow up and down solution
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function q2 = solve_for_theta2(robot, q, Pm)

%Evaluate the parameters
d = eval(robot.DH.d);
a = eval(robot.DH.a);

%See geometry
L2=a(2);
L3=d(4);

%given q1 is known, compute first DH transformation
T01=dh(robot, q, 1);

%Express Pm in the reference system 1, for convenience
p1 = inv(T01)*[Pm; 1];

r = sqrt(p1(1)^2 + p1(2)^2);

beta = atan2(-p1(2), p1(1));
gamma = (acos((L2^2+r^2-L3^2)/(2*r*L2)));

if ~isreal(gamma)
    disp('WARNING:inversekinematic_flexion_n2: the point is not reachable for this configuration, imaginary solutions');
    %gamma = real(gamma);
end

%return two possible solutions
%elbow up and elbow down
%the order here is important and is coordinated with the function
%solve_for_theta3
q2(1) = pi/2 - beta - gamma; %elbow up
q2(2) = pi/2 - beta + gamma; %elbow down

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% solve for third joint theta3, two different
% solutions are returned, corresponding
% to elbow up and down solution
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function q3 = solve_for_theta3(robot, q, Pm)

%Evaluate the parameters
d = eval(robot.DH.d);
a = eval(robot.DH.a);

%See geometry
L2=a(2);
L3=d(4);

%given q1 is known, compute first DH transformation
T01=dh(robot, q, 1);

%Express Pm in the reference system 1, for convenience
p1 = inv(T01)*[Pm; 1];

r = sqrt(p1(1)^2 + p1(2)^2);

eta = (acos((L2^2 + L3^2 - r^2)/(2*L2*L3)));

if ~isreal(eta)
   disp('WARNING:inversekinematic_flexion_n2: the point is not reachable for this configuration, imaginary solutions');
   %eta = real(eta);
end

%return two possible solutions
%elbow up and elbow down solutions
%the order here is important
q3(1) = pi - eta;
q3(2) = eta - 3*pi/2 + pi/2;


function lambda = ill3_eigenvalues ( )

%*****************************************************************************80
%
%% ILL3_EIGENVALUES returns the eigenvalues of the ILL3 matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 July 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Joan Westlake,
%    A Handbook of Numerical Matrix Inversion and Solution of
%    Linear Equations,
%    John Wiley, 1968,
%    ISBN13: 978-0471936756,
%    LC: QA263.W47.
%
%  Parameters:
%
%    Output, real LAMBDA(3,1), the eigenvalues.
%
  lambda = [ 3.0; 2.0; 1.0 ];

  return
end


[afilename, apathname] = uigetfile('*.*', 'Input for Beads');
filename=fullfile(apathname,afilename);
%filename='E:\2009-05-12_GlassesBeads\tif\tryout\163m_glass40.tif'

s=40;
%a=ZEN_LSMLoad(filename);
a=readtimeseries(filename);

a=a{1};
%%Original version 20/05/2009
% ma=max(a{1},[],3);
% ExtractResults(ma);

%%Marie, 21/05/2009
% ma=max(a{1},[],3);
[pxy,bestslice]=ExtractCoordinates(a,s);

number=size(bestslice,2);
for b=1:number
    slice=squeeze(extract(a,[s s 1],[pxy(b,:) bestslice(b)]));

    FWHM(b)=FitPSF(slice);
end
sumFWHM=0;
for b=1:number
   sumFWHM=sumFWHM+FWHM(b);
end
fprintf('The average FWHM in pxl of the selected beads is\n');
averageFWHM=sumFWHM/number
fprintf('The average FWHM in nm of the selected beads is\n');
ConvertZENpxl_nm(averageFWHM)


filename = 'test_rectangular';
ptype = 'MICRO';
method = 'SIMPALL';
materialType = 'ISOTROPIC';
initial_case = 'circleInclusion'; %% Parámetro a ir variando
cost = {'enforceCh_CCstar_L2';'perimeter'};
%cost = {'enforceCh_CCstar_L2';'perimeter'};
weights = [1 1];
%weights = 1;
constraint = {'volumeConstraint'};
constraint_case = 'INEQUALITY';
optimizer = 'MMA';
%optimizer = 'AlternatingPrimalDual';

incrementFactor = 1;
designVariable = 'Density';
filterType = 'P1';
fracRadius = 0.5;

nsteps = 1;
Vfrac_final = 0.5;
optimality_final =1e-3;
constr_final =1e-3;

Vfrac_initial = 0.5;
optimality_initial = 1e-3;
constr_initial = 1e-3;
Perimeter_target = 5;

TOL.rho_plus = 1;
TOL.rho_minus = 0;
TOL.E_plus = 1;
TOL.E_minus = 1e-3;
TOL.nu_plus = 1/3;
TOL.nu_minus = 1/3;

 %Micro
epsilon_isotropy_initial=1e-1;
epsilon_isotropy_final = 1e-3;
selectiveC_Cstar = 'IsotropyHexagon';

% For all tests
plotting = false;
printing = false;
printing_physics = false;
monitoring = false;
maxiter = 30;


classdef(Abstract) AbstractBodyFixedSensorTarget < AbstractSensorTarget
    %AbstractBodyFixedSensorTarget Summary of this class goes here
    %   Detailed explanation goes here

    properties
        rVectECEF(3,:) double
    end

    methods
        function rVect = getTargetPositions(obj, time, vehElemSet, inFrame)
            arguments
                obj(1,1) AbstractBodyFixedSensorTarget
                time(1,1) double
                vehElemSet(1,1) CartesianElementSet
                inFrame(1,1) AbstractReferenceFrame
            end

            bodyFixedFrame = obj.bodyInfo.getBodyFixedFrame();

            numPts = size(obj.rVectECEF, 2);

            times = time*ones(1, numPts);
            rVects = obj.rVectECEF;
            vVects = zeros(3,numPts);
            cartElem = CartesianElementSet(times, rVects, vVects, bodyFixedFrame, true);

            cartElem = convertToFrame(cartElem, inFrame);
            rVect = cartElem.rVect;
        end

        function numPts = getNumberOfTargetPts(obj)
            numPts = width(obj.rVectECEF);
        end

        function strs = getTargetPtLabelStrs(obj)
            strs = string.empty(1,0);
            for(i=1:width(obj.rVectECEF))
                cartElem = CartesianElementSet(0, obj.rVectECEF(:,i), [0;0;0], obj.bodyInfo.getBodyFixedFrame(), false);
                geoElem = cartElem.convertToGeographicElementSet();

                strs(i) = string(sprintf('Target %u (Lat %0.3f deg, Long %0.3f deg, Alt %0.3f km)', i, rad2deg(geoElem.lat), rad2deg(geoElem.long), geoElem.alt)); %#ok<AGROW>
            end
        end
    end
end


function noise = heavisideNoiseExpandParam(noise, params)

% HEAVISIDENOISEEXPANDPARAM Expand heaviside noise structure from param vector.

% IVM

noise.eta = 0.5*sigmoidBound(params(1));
noise.bias = params(2:end);


function startIdx=findPatternInArray(pattern,array,maxTimes)
%%FINDPATTERNINARRAY Find all or a maximum number of occurrences of a
%                    pattern in an array of values.
%
%INPUTS: pattern A 1Xm or mX1 array holding elements of a pattern to be
%                found.
%        array   A 1Xn or nX1 array in which occurrences of the pattern are
%                to be found.
%       maxTimes An optional parameter specifying the maximum number of
%                occurrences of the pattern to find in array. If omitted or
%                an empty matrix is passed, then all occurrences of pattern
%                in array will be found.
%
%OUTPUTS: startIdx A numFoundX1 array of the atarting indices of the
%                occurrences of pattern in array, given in increasing
%                order.
%
%The algorithm used is a linear time method given in [1]. It is the
%algorithm of Section 2 with the modification to the next array of Section
%4 to find all occurrences of the pattern. Not all of the suggestions for
%improving efficiency of Section 3 are used, because they would require
%lengthening the input arrays and also would require defining certain
%values the inputs could not take.
%
%EXAMPLE:
% array='baabbabbaabaabbaabbaabbabaa';
% pattern='aabba';
% startIdx=findPatternInArray(pattern,array)
%One finds the string at startIdx=[2;12;16;20]. Note that some of the
%solutions overlap.
%
%REFERENCES:
%[1] D. E. Knuth, J. H. Morris Jr., and V. R. Pratty, "Fast pattern
%    matching in strings," SIAM Journal on Computing, vol. 6, no. 2, pp.
%    323-350, Jun. 1977.
%
%August 2015, David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

m=length(pattern);
n=length(array);

if(m>n)
    %If the pattern is longer than the array, then a match is impossible.
    startIdx=[];
    return;
end

if(nargin<3||isempty(maxTimes))
   maxTimes=n-m+1;%The maximum
else
   maxTimes=min([n-m+1,maxTimes]);
end

%Allocate space for the maximum possible number of matches.
startIdx=zeros(maxTimes,1);
numFound=0;

%First, compute the elements of the next table. We are computing them for a
%length m+1 table where the last element does not match anything else so
%that we can get a resume index to use when finding multiple matches.
next=zeros(m+1,1);
j=1;
t=0;
next(1)=0;
while(j<m)
   while((t>0)&&pattern(j)~=pattern(t))
       t=next(t);
   end
   t=t+1;
   j=j+1;
   if(pattern(j)==pattern(t))
       next(j)=next(j);
   else
        next(j)=t;
   end
end

%Add in the value for j=m;
while((t>0)&&pattern(j)~=pattern(t))
   t=next(t);
end
t=t+1;
j=j+1;
next(j)=t;%This sets next(m+1);

%Next, run the actual algorithm using the next table.
j=1;
k=1;

%Consider the special case of j=1 --skip forward to the first possible
%match.
while(array(k)~=pattern(1))
    k=k+1;
    if(k>n)%Nothing matches the first character of the pattern.
        startIdx=[];
        return;
    end
end

while(1)
    while((j<=m)&&(k<=n))
        while((j>0)&&(array(k)~=pattern(j)))
           j=next(j);
        end
        k=k+1;
        j=j+1;
    end

    if(j<=m)%All of the matches have been found.
        startIdx=startIdx(1:numFound);
        return;
    end

    %With j>m, the leftmost match has been found in positions k-m through
    %k-1.
    numFound=numFound+1;
    startIdx(numFound)=k-m;
    j=next(m+1);

    if(numFound==maxTimes)
        startIdx=startIdx(1:numFound);
        return;
    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.


% Test file for chebtech/cell2mat.m

function pass = test_cell2mat(pref)

if ( nargin < 2 )
    pref = chebtech.techPref();
end

for n = 1:2

    if (n == 1);
        testclass = chebtech1();
    else
        testclass = chebtech2();
    end

    f = testclass.make(@(x) [sin(x) cos(x) exp(x)], [], pref);
    g = testclass.make(@(x) sin(x), [], pref);
    h = testclass.make(@(x) [cos(x) exp(x)], [], pref);

    F = cell2mat([g h]);
    pass(n, 1) = all( sum(F - f) < max(vscale(f)*eps) );
end

end


function C = horzcat(varargin)
%HORZCAT   Horizontally concatenate chebmatrices.
%   Z = [A,B,C,...] horizontally combines the chebmatrices, operator
%   blocks, chebfuns, and scalars given in the call, if their row sizes
%   are compatible.
%
% See also CHEBMATRIX.CAT, CHEBMATRIX.VERTCAT.

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

% Remove empty arguments.
isemp = cellfun(@isempty,varargin);
varargin(isemp) = [];
nargin = length(varargin);

% First, process the blocks of the inputs, disregarding sizes. This
% simplifies the logic. The entries of the results are cells holding the
% relevant blocks to be concatenated.
blocks = cell(1, nargin);
for n = 1:nargin
    item = varargin{n};
    if ( isa(item, 'chebmatrix') )   % already a cell
        blocks{n} = item.blocks;
    elseif ( isa(item, 'linBlock') || isa(item,'chebfun') )
        blocks{n} = { item };        % encase in a cell
    elseif ( ~isempty(item) )
        blocks{n} = num2cell(item);  % encase in cell(s)
    end
end

% Now check the row sizes. Create an empty vessel if OK.
[m,n] = cellfun(@size,blocks);
if ( all(m==m(1)) )
    B = cell( m(1), sum(n) );
else
    error('CHEBFUN:CHEBMATRIX:horzcat:sizeMismatch', ...
        'Incompatible row sizes.')
end

% Now we need to flatten out all the inner nested cell divisions, leaving
% just a cell of blocks.
cs = [0 cumsum(n)];
for j = 1:nargin
    B(:,cs(j)+(1:n(j))) = blocks{j};
end

% This step will perform domain compatibility checking.
C = chebmatrix( B );

% Finally, check block size compatibility.
[row, col] = blockSizes(C);
if ( any( any( bsxfun(@ne, row(:,1), row) ) ) )
    error('CHEBFUN:CHEBMATRIX:horzcat:blockSizeMismatch', ...
        'Block row sizes must be the same.')
end

end


function check = weibull_discrete_check ( a, b )

%*****************************************************************************80
%
%% WEIBULL_DISCRETE_CHECK checks the parameters of the discrete Weibull CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 <= A <= 1.0,
%    0.0 < B.
%
%    Output, logical CHECK, is true if the parameters are legal.
%
  if ( a < 0.0 | 1.0 < a )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'WEIBULL_DISCRETE_CHECK - Fatal error!\n' );
    fprintf ( 1, '  A < 0 or 1 < A.\n' );
    check = 0;
    return
  end

  if ( b <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'WEIBULL_DISCRETE_CHECK - Fatal error!\n' );
    fprintf ( 1, '  B <= 0.\n' );
    check = 0;
    return
  end

  check = 1;

  return
end


clc
clear all
for jj=2:2
for j=73:75
filename=['.\data\3lab' num2str(jj) num2str(j)];
% filename=['.\data\x' num2str(j)];
if(exist(filename)==2)
M=1000;
N=1;
csi_trace = read_bf_file(filename);
csi=zeros(3,30,M-N);
for i=(N+1):M
    csi_entry = csi_trace{i};
    csientry = get_scaled_csi(csi_entry);
    perm = csi_entry.perm;
    for k=1:3
        if perm(k)==1
            csi(1,:,i-N)=csientry(1,perm(k),:);
%             time_csi(1,:,i-N)=ifft(csi(1,:,i-N),point);
%             time_csi_abs(1,:,i-N)=abs(time_csi(1,:,i-N));
        elseif perm(k)==2
            csi(2,:,i-N)=csientry(1,perm(k),:);
%             time_csi(2,:,i-N)=ifft(csi(2,:,i-N),point);
%             time_csi_abs(2,:,i-N)=abs(time_csi(2,:,i-N));
        elseif perm(k)==3
            csi(3,:,i-N)=csientry(1,perm(k),:);
%             time_csi(3,:,i-N)=ifft(csi(3,:,i-N),point);
%             time_csi_abs(3,:,i-N)=abs(time_csi(3,:,i-N));
        end
    end
end
csi=squeeze(csi);
save(filename,'csi');
end
end
end


function pass = test_plotting()
% Check that the very basic plotting commands do not crash.

% Real-valued functions.
f1 = chebfun3(@(x,y,z) x.*y.*z, [-1 2 -1 2 -1 2]);

% A complex-valued function.
f2 = chebfun3(@(x,y,z) exp(cos(1i*x.*y.*z)));

% Obviously, we can't check if the plots are correct without human
% intervention, so all these tests are meant to do is make sure none of the
% plotting functions crash.

hfig = figure('Visible', 'off');

%% Real-valued function
% Non-GUI plots
pass(1) = doesNotCrash(@() plot(f1));
pass(2) = doesNotCrash(@() slice(f1, 'noslider'));
pass(3) = doesNotCrash(@() slice(f1, 0.5, -0.3, 0.9));
pass(4) = doesNotCrash(@() isosurface(f1, 'noslider'));
pass(5) = doesNotCrash(@() isosurface(f1, [0.5, -0.6]));
pass(6) = doesNotCrash(@() scan(f1));
pass(6) = doesNotCrash(@() scan(f1, 1));
pass(7) = doesNotCrash(@() scan(f1, 1, 'hold'));
pass(8) = doesNotCrash(@() scan(f1, 3));
% GUI-based plots:
pass(9) = doesNotCrash(@() isosurface(f1));
pass(10) = doesNotCrash(@() slice(f1));
pass(11) = doesNotCrash(@() surf(f1));

%% Complex-valued function
% Non-GUI plots
pass(12) = doesNotCrash(@() plot(f2));
pass(13) = doesNotCrash(@() slice(f2, 'noslider'));
pass(14) = doesNotCrash(@() slice(f2, 0.5, -0.3, 0.9));
pass(15) = doesNotCrash(@() isosurface(f2, 'noslider'));
pass(16) = doesNotCrash(@() isosurface(f2, [0.5, -0.6]));
pass(17) = doesNotCrash(@() scan(f2));
pass(18) = doesNotCrash(@() scan(f2, 'hold'));
pass(19) = doesNotCrash(@() scan(f2, 2, 'hold'));
% GUI-based plots:
pass(20) = doesNotCrash(@() isosurface(f2));
pass(21) = doesNotCrash(@() slice(f2));
pass(22) = doesNotCrash(@() surf(f2));

%% Test plotting on a non-standard domain
r = chebfun3(@(r,t,p) r, [0 1 0 2*pi pi/4 pi/2]);
t = chebfun3(@(r,t,p) t, [0 1 0 2*pi pi/4 pi/2]);
p = chebfun3(@(r,t,p) p, [0 1 0 2*pi pi/4 pi/2]);
x = r.*cos(t).*cos(p);
y = r.*sin(t).*cos(p);
z = r.*sin(p);
density = sin(10*t).*cos(10*r)+1;
pass(23) = doesNotCrash(@() plot(x,y,z,density));

close(hfig);

end

function pass = doesNotCrash(fn)
try
    fn();
    pass = true;
catch ME
    pass = false;
end

end


function y = han(x,frac)
    % apply a hamming window to signal x of length x*(1+frac).
    % equivalent to zero-padding, windowing and then truncating.

    if nargin < 2 || isempty(frac)
        frac = 0.5;
    end

    if isinf(frac);
        y = x;
    else
        sx = size(x);
        h1 = hamming(sx(1) + 2*round(sx(1)*frac));
        h2 = hamming(sx(2) + 2*round(sx(2)*frac));
        %y = x.*(h1(round(sx(1)*frac)+(1:sx(1)))*h2(round(sx(2)*frac)+(1:sx(2)))');
        y = bsxfun(@times, bsxfun(@times,h2(round(sx(2)*frac)+(1:sx(2)))',x), h1(round(sx(1)*frac)+(1:sx(1))));
        if length(sx) == 3
            temp = hamming(sx(3) + 2*round(sx(3)*frac));
            h3(1,1,1:sx(3)) = temp(round(sx(3)*frac)+(1:sx(3)));
            y = bsxfun(@times, y, h3);
        end
    end


function layer = genNetworkLSTMEncoderDecoder2(para)
if isfield(para, 'LastActivation4MSE')==0
    para.LastActivation4MSE = 'linear';
end

layer{1}.name = 'Input';        % this is an input layer
layer{end}.inputIdx = 1;    % specifies the index of GCC in Visible_tr
layer{end}.dim = [1 1]*double(para.inputDim);             % [input dim; output dim];

if isfield(para, 'useFbank') && para.useFbank
    MelWindow = mel_window_FE(40, 256, 16000)';
    MelWindow(:,end+1) = 0;
    layer{end+1}.name = 'Affine';
    layer{end}.prev = -1;
    layer{end}.W = MelWindow;
    layer{end}.b = zeros(40,1);
    layer{end}.dim = [40 layer{end-1}.dim(1)];
    layer{end}.update = 0;

    layer{end+1}.name = 'log';
    layer{end}.prev = -1;
    layer{end}.const = 1e-7;
    layer{end}.dim = [1 1]*layer{end-1}.dim(1);
end

layer{end+1}.name = 'delta';
layer{end}.prev = -1;
layer{end}.dim = [3 1]*layer{end-1}.dim(1);

layer{end+1}.name = 'Affine';
layer{end}.prev = -1;
layer{end}.W = [];
layer{end}.b = [];
layer{end}.dim = [1 1]*layer{end-1}.dim(1);
layer{end}.update = 0;

layerLSTM = genNetworkLSTM(para);
for i=1:length(layerLSTM)
    layerLSTM{i} = rmfield(layerLSTM{i}, 'next');
end

layerLSTM = layerLSTM(2:end);

layerLSTM{1}.prev = -1;
layerLSTM{1}.dim(2) = layer{end}.dim(1);

layer = [layer layerLSTM];

layer{end-2}.name = 'multi_softmax';
layer{end-2}.TaskVocabSizes = para.outputDim/para.ngram_len;
if isfield(para, 'labelDelay')
    shiftLayer.name = 'frame_shift';
    shiftLayer.prev = -1;
    shiftLayer.delay = para.labelDelay;

end

layer{end}.name = 'multi_cross_entropy';
layer{end}.TaskVocabSizes = para.outputDim/para.ngram_len;
layer = FinishLayer(layer);
end


function [sts] = ft_spiketriggeredspectrum_fft(cfg, data, spike)

% FT_SPIKETRIGGEREDSPECTRUM_FFT computes the Fourier spectrum (amplitude and phase)
% of the LFP around the % spikes.  A phase of zero corresponds to the spike being on
% the peak of the LFP oscillation. A phase of 180 degree corresponds to the spike being
% in the through of the oscillation. A phase of 45 degrees corresponds to the spike
% being just after the peak in the LFP.
%
% If the triggered spike leads a spike in another channel, then the angle of the Fourier
% spectrum of that other channel will be negative. Earlier phases are in clockwise
% direction.
%
% Use as
%   [sts] = ft_spiketriggeredspectrum_convol(cfg,data,spike)
% or
%   [sts] = ft_spiketriggeredspectrum_convol(cfg,data)
% where the spike data can either be contained in the DATA input or in the SPIKE input.
%
% The input DATA should be organised as the raw datatype, obtained from FT_PREPROCESSING
% or FT_APPENDSPIKE.
%
% The (optional) input SPIKE should be organised as the spike or the raw datatype,
% obtained from FT_SPIKE_MAKETRIALS or FT_PREPROCESSING (in that case, conversion is done
% within the function)
%
% Important is that data.time and spike.trialtime should be referenced relative to the
% same trial trigger times.
%
% The configuration should be according to
%   cfg.timwin       = [begin end], time around each spike (default = [-0.1 0.1])
%   cfg.foilim       = [begin end], frequency band of interest (default = [0 150])
%   cfg.taper        = 'dpss', 'hanning' or many others, see WINDOW (default = 'hanning')
%   cfg.tapsmofrq    = number, the amount of spectral smoothing through
%                      multi-tapering. Note that 4 Hz smoothing means plus-minus 4 Hz,
%                      i.e. a 8 Hz smoothing box. Note: multitapering rotates phases (no
%                      problem for consistency)
%   cfg.spikechannel = string, name of spike channels to trigger on cfg.channel = Nx1
%                      cell-array with selection of channels (default = 'all'),
%                      see FT_CHANNELSELECTION for details
%   cfg.feedback     = 'no', 'text', 'textbar', 'gui' (default = 'no')
%
% The output STS data structure can be input to FT_SPIKETRIGGEREDSPECTRUM_STAT
%
% This function uses a NaN-aware spectral estimation technique, which will default to the
% standard Matlab FFT routine if no NaNs are present. The fft_along_rows subfunction below
% demonstrates the expected function behavior.
%
% See FT_SPIKETRIGGEREDINTERPOLATION to remove segments of LFP around spikes.
% See FT_SPIKETRIGGEREDSPECTRUM_CONVOL for an alternative implementation based
% on convolution

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

% these are used by the ft_preamble/ft_postamble function and scripts
ft_revision = '$Id$';
ft_nargin   = nargin;
ft_nargout  = nargout;

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble provenance data spike

% check input data structure
data = ft_checkdata(data,'datatype', 'raw', 'feedback', 'yes');
if nargin==3
  spike = ft_checkdata(spike, 'datatype', {'spike'}, 'feedback', 'yes');
end

% these were supported in the past, but are not any more (for consistency with other spike functions)
cfg = ft_checkconfig(cfg, 'forbidden', {'inputfile','outputfile'});

%get the options
cfg.timwin       = ft_getopt(cfg, 'timwin',[-0.1 0.1]);
cfg.spikechannel = ft_getopt(cfg,'spikechannel', 'all');
cfg.channel      = ft_getopt(cfg,'channel', 'all');
cfg.feedback     = ft_getopt(cfg,'feedback', 'no');
cfg.tapsmofrq    = ft_getopt(cfg,'tapsmofrq', 4);
cfg.taper        = ft_getopt(cfg,'taper', 'hanning');
cfg.foilim       = ft_getopt(cfg,'foilim', [0 150]);

% ensure that the options are valid
cfg = ft_checkopt(cfg,'timwin','doublevector');
cfg = ft_checkopt(cfg,'spikechannel',{'cell', 'char', 'double', 'empty'});
cfg = ft_checkopt(cfg,'channel', {'cell', 'char', 'double'});
cfg = ft_checkopt(cfg,'feedback', 'char', {'yes', 'no'});
cfg = ft_checkopt(cfg,'taper', 'char');
cfg = ft_checkopt(cfg,'tapsmofrq', 'doublescalar');
cfg = ft_checkopt(cfg,'foilim', 'doublevector');

if strcmp(cfg.taper, 'sine')
  error('sorry, sine taper is not yet implemented');
end

% get the spikechannels
if nargin==2

  % autodetect the spikechannels and EEG channels
  [spikechannel, eegchannel] = detectspikechan(data);

  % make the final selection of spike channels and check
  if strcmp(cfg.spikechannel, 'all'),
    cfg.spikechannel = spikechannel;
  else
    cfg.spikechannel = ft_channelselection(cfg.spikechannel, data.label);
    if ~all(ismember(cfg.spikechannel,spikechannel)),
      error('some selected spike channels appear eeg channels');
    end
  end

  % make the final selection of EEG channels and check
  if strcmp(cfg.channel,'all')
    cfg.channel = eegchannel;
  else
    cfg.channel      = ft_channelselection(cfg.channel, data.label);
    if ~all(ismember(cfg.channel,eegchannel)),
      warning('some of the selected eeg channels appear spike channels');
    end
  end

  % select the data and convert to a spike structure
  tmpcfg = [];
  tmpcfg.channel = cfg.spikechannel;
  data_spk = ft_selectdata(tmpcfg, data);
  tmpcfg.channel = cfg.channel;
  data     = ft_selectdata(tmpcfg, data); % leave only LFP
  spike    = ft_checkdata(data_spk,'datatype', 'spike');
  clear data_spk % remove the continuous data
else
  cfg.spikechannel = ft_channelselection(cfg.spikechannel, spike.label);
  cfg.channel      = ft_channelselection(cfg.channel, data.label);
end

% determine the channel indices and number of chans
chansel          = match_str(data.label, cfg.channel); % selected channels
nchansel         = length(cfg.channel);                % number of channels
spikesel         = match_str(spike.label, cfg.spikechannel);
nspikesel        = length(spikesel); % number of spike channels
if nspikesel==0, error('no spike channel selected'); end

% construct the taper
if ~isfield(data, 'fsample'), data.fsample = 1/mean(diff(data.time{1})); end
begpad = round(cfg.timwin(1)*data.fsample);
endpad = round(cfg.timwin(2)*data.fsample);
numsmp = endpad - begpad + 1;
if ~strcmp(cfg.taper,'dpss')
  taper  = window(cfg.taper, numsmp);
  taper  = taper./norm(taper);
else
  % not implemented yet: keep tapers, or selecting only a subset of them.
  taper  = dpss(numsmp, cfg.tapsmofrq);
  taper  = taper(:,1:end-1);            % we get 2*NW-1 tapers
  taper  = sum(taper,2)./size(taper,2); % using the linearity of multitapering
end
taper  = sparse(diag(taper));

% preallocate the output structures for different units / trials
ntrial      = length(data.trial);
spectrum    = cell(nspikesel,ntrial);
spiketime   = cell(nspikesel,ntrial);
spiketrial  = cell(nspikesel,ntrial);

% select the frequencies
freqaxis = linspace(0, data.fsample, numsmp);
fbeg = nearest(freqaxis, cfg.foilim(1));
fend = nearest(freqaxis, cfg.foilim(2));

% update the configuration to account for rounding off differences
cfg.foilim(1) = freqaxis(fbeg);
cfg.foilim(2) = freqaxis(fend);

% make a representation of the spike, this is used for the phase rotation
spike_repr = zeros(1,numsmp);
time       = linspace(cfg.timwin(1),cfg.timwin(2), numsmp);
spike_repr(1-begpad) = 1;
spike_fft = specest_nanfft(spike_repr, time);
spike_fft = spike_fft(fbeg:fend);
spike_fft = spike_fft./abs(spike_fft);
rephase   = sparse(diag(conj(spike_fft)));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% compute the spectra
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ft_progress('init', 'text',     'Please wait...');
for iUnit  = 1:nspikesel
  for iTrial = 1:ntrial

    % select the spikes that fell in the trial and convert to samples
    timeBins = [data.time{iTrial}  data.time{iTrial}(end)+1/data.fsample] - (0.5/data.fsample);
    hasTrial = spike.trial{spikesel(iUnit)} == iTrial; % find the spikes that are in the trial
    ts       = spike.time{spikesel(iUnit)}(hasTrial); % get the spike times for these spikes
    ts       = ts(ts>=timeBins(1) & ts<=timeBins(end)); % only select those spikes that fall in the trial window
    [ignore,spikesmp] = histc(ts,timeBins);
    if ~isempty(ts)
      ts(spikesmp==0 | spikesmp==length(timeBins)) = [];
    end

    spikesmp(spikesmp==0 | spikesmp==length(timeBins)) = [];

    % store in the output cell arrays as column vectors
    spiketime{iUnit, iTrial}  = ts(:);
    tr = iTrial*ones(size(spikesmp));
    spiketrial{iUnit, iTrial} = tr(:);

    % preallocate the spectrum
    spectrum{iUnit, iTrial} = zeros(length(spikesmp), nchansel, fend-fbeg+1);

    % compute the spiketriggered spectrum
    ft_progress(iTrial/ntrial, 'spectrally decomposing data for trial %d of %d, %d spikes for unit %d', iTrial, ntrial, length(spikesmp), iUnit);
    for j=1:length(spikesmp)

      % selected samples
      begsmp = spikesmp(j) + begpad;
      endsmp = spikesmp(j) + endpad;

      % handle spikes near the borders of the trials
      if (begsmp<1)
        segment = nan(nchansel, numsmp);
      elseif endsmp>size(data.trial{iTrial},2)
        segment = nan(nchansel, numsmp);
      else
        segment = data.trial{iTrial}(chansel,begsmp:endsmp);
      end

      % substract the DC component from every segment, to avoid any leakage of the taper
      segmentMean = repmat(nanmean(segment,2),1,numsmp); % nChan x Numsmp
      segment     = segment - segmentMean; % LFP has average of zero now (no DC)

      % taper the data segment around the spike and compute the fft
      segment_fft = specest_nanfft(segment * taper, time);

      % select the desired output frquencies and normalize
      segment_fft = segment_fft(:,fbeg:fend) ./ sqrt(numsmp/2);

      % rotate the estimated phase at each frequency to correct for the segment t=0 not being at the first sample
      segment_fft = segment_fft * rephase;

      % store the result for this spike in this trial
      spectrum{iUnit, iTrial}(j,:,:) = segment_fft;

    end % for each spike in this trial
  end % for each trial
end
ft_progress('close');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% collect the results in a structure that is a spike structure
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sts.lfplabel       = data.label(chansel);
sts.freq           = freqaxis(fbeg:fend);
sts.dimord         = 'rpt_chan_freq';
for iUnit = 1:nspikesel
  sts.fourierspctrm{iUnit}  = cat(1, spectrum{iUnit,:});
  spectrum(iUnit,:) = {[]}; % free from the memory
  sts.time{iUnit}           = cat(1,spiketime{iUnit,:});
  sts.trial{iUnit}          = cat(1,spiketrial{iUnit,:});
end
sts.dimord    = '{chan}_spike_lfpchan_freq';
sts.trialtime = spike.trialtime;
sts.label     = spike.label(spikesel);

% do the general cleanup and bookkeeping at the end of the function

ft_postamble previous   data
ft_postamble provenance sts
ft_postamble history    sts

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [spikelabel, eeglabel] = detectspikechan(data)

maxRate = 1000; % default on what we still consider a neuronal signal

% autodetect the spike channels
ntrial = length(data.trial);
nchans  = length(data.label);
spikechan = zeros(nchans,1);
for i=1:ntrial
  for j=1:nchans
    hasAllInts    = all(isnan(data.trial{i}(j,:)) | data.trial{i}(j,:) == round(data.trial{i}(j,:)));
    hasAllPosInts = all(isnan(data.trial{i}(j,:)) | data.trial{i}(j,:)>=0);
    fr            = nansum(data.trial{i}(j,:),2) ./ (data.time{i}(end)-data.time{i}(1));
    spikechan(j) = spikechan(j) + double(hasAllInts & hasAllPosInts & fr<=maxRate);
  end
end
spikechan = (spikechan==ntrial);

spikelabel = data.label(spikechan);
eeglabel   = data.label(~spikechan);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% SUBFUNCTION for demonstration purpose
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function y = fft_along_rows(x)
y = fft(x, [], 2); % use normal Matlab function to compute the fft along 2nd dimension


function [fx,J,dfdp] = f_embed0(Xt,Theta,ut,in)
% evolution function for dynamical system's delay embedding
% function [fx,J,dfdp] = f_embed(Xt,Theta,ut,in)

% First form delayed state vector and input
iX = (1:in.dim.n) + (in.options.delays(:)'.*in.dim.n);
dX = Xt(iX,:);

% Evaluate evolution function at the delayed state vector:
[opt,dim] = getOptions4EvalFun(in);
[fx0,J0,dfdp0] = VBA_evalFun('f',dX,Theta,ut,opt,dim);

% Construct full embedding flow and gradients:
Xe = Xt(1:in.dim.n_embed);
fx = [fx0;Xe];
J = zeros(in.dim.n_embed+in.dim.n);
J(iX,1:in.dim.n) = J0;
J(1:in.dim.n_embed,in.dim.n+1:in.dim.n+in.dim.n_embed) = ...
    eye(in.dim.n_embed);
dfdp = [dfdp0,zeros(in.dim.n_theta,in.dim.n_embed)];

function [opt,dim] = getOptions4EvalFun(in)
opt = in.options;
opt.f_fname = in.f_fname;
opt.f_nout = in.f_nout;
opt.checkGrads = 0;
dim.n = in.dim.n;
dim.n_theta = in.dim.n_theta;


classdef SpatialNorm < dagnn.ElementWise
  properties
    param = [2 2 10 2]
  end

  methods
    function outputs = forward(obj, inputs, params)
      outputs{1} = vl_nnspnorm(inputs{1}, obj.param) ;
    end

    function [derInputs, derParams] = backward(obj, inputs, param, derOutputs)
      derInputs{1} = vl_nnspnorm(inputs{1}, obj.param, derOutputs{1}) ;
      derParams = {} ;
    end

    function obj = SpatialNorm(varargin)
      obj.load(varargin) ;
    end
  end
end


%NEWFIG Create new figure on given position
%
%	NEWFIG(FIGURE_NUMBER,FIGURE_PER_ROW)
%
% INPUT
%   FIGURE_NUMBER   Number of the figure
%   FIGURE_PER_ROW  Figures per row (default: 4)
%
% OUTPUT
%
% DESCRIPTION
% Creates figure number FIGURE_NUMBER and places it on the screen,
% such that (when sufficient figures are created), the screen is
% covered by an array of figures, with FIGURE_PER_ROW figures per row.
%
% SEE ALSO (PRTools Guide)
% SCATTERD, PLOTC

% $Id: newfig.m,v 1.2 2006/03/08 22:06:58 duin Exp $

function newfig(fign,n);

	if nargin < 2, n=4; end
	if nargin < 1, fign=gcf+1; end

	% if the figure already exist, kill it!
	if any(get(0,'children') == fign)
		delete(fign);
	end

	% Create the figure,
	figure(fign);
	set(gcf,'menubar','none');
	% and place it in the correct position:
	ny = 1-ceil(fign/n)/n;
	nx = (fign -1 - n*floor((fign-1)/n))/n;
	d = 1/n;
	set(gcf,'units','normalized','position',[nx ny d*0.95 d*0.85]);

return


% RBio: MATLAB toolbox for reading/writing sparse matrices in the Rutherford/
%   Boeing format, and for reading/writing problems in the UF Sparse Matrix
%   Collection from/to a set of files in a directory.
%
%   RBread    - read a sparse matrix from a Rutherford/Boeing file
%   RBreade   - read a symmetric finite-element matrix from a R/B file
%   RBtype    - determine the Rutherford/Boeing type of a sparse matrix
%   RBwrite   - write a sparse matrix to a Rutherford/Boeing file
%   RBraw     - read the raw contents of a Rutherford/Boeing file
%   RBfix     - read a possibly corrupted matrix from a R/B file
%   RBinstall - install the RBio toolbox for use in MATLAB
%   RBmake    - compile the RBio toolbox for use in MATLAB
%
% Example:
%
%   load west0479
%   C = west0479 ;
%   RBwrite ('mywest', C, 'WEST0479 chemical eng. problem', 'west0479')
%   A = RBread ('mywest') ;
%   norm (A-C,1)
%
% See also UFget, mread, mwrite.

% Copyright 2007, Timothy A. Davis


function p = prior_gamma(varargin)
%PRIOR_GAMMA  Gamma prior structure
%
%  Description
%    P = PRIOR_GAMMA('PARAM1', VALUE1, 'PARAM2', VALUE2, ...)
%    creates Gamma prior structure in which the named parameters
%    have the specified values. Any unspecified parameters are set
%    to default values.
%
%    P = PRIOR_GAMMA(P, 'PARAM1', VALUE1, 'PARAM2', VALUE2, ...)
%    modify a prior structure with the named parameters altered
%    with the specified values.
%
%    Parametrisation is done by Bayesian Data Analysis,
%    second edition, Gelman et.al. 2004.
%
%    Parameters for Gamma prior [default]
%      sh       - shape [4]
%      is       - inverse scale [1]
%      sh_prior - prior for sh [prior_fixed]
%      is_prior - prior for is [prior_fixed]
%
%  See also
%    PRIOR_*

% Copyright (c) 2000-2001,2010 Aki Vehtari
% Copyright (c) 2010 Jaakko Riihim�ki

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

  ip=inputParser;
  ip.FunctionName = 'PRIOR_GAMMA';
  ip.addOptional('p', [], @isstruct);
  ip.addParamValue('sh',4, @(x) isscalar(x) && x>0);
  ip.addParamValue('sh_prior',[], @(x) isstruct(x) || isempty(x));
  ip.addParamValue('is',1, @(x) isscalar(x) && x>0);
  ip.addParamValue('is_prior',[], @(x) isstruct(x) || isempty(x));
  ip.parse(varargin{:});
  p=ip.Results.p;

  if isempty(p)
    init=true;
    p.type = 'Gamma';
  else
    if ~isfield(p,'type') && ~isequal(p.type,'Gamma')
      error('First argument does not seem to be a valid prior structure')
    end
    init=false;
  end

  % Initialize parameters
  if init || ~ismember('sh',ip.UsingDefaults)
    p.sh = ip.Results.sh;
  end
  if init || ~ismember('is',ip.UsingDefaults)
    p.is = ip.Results.is;
  end
  % Initialize prior structure
  if init
    p.p=[];
  end
  if init || ~ismember('sh_prior',ip.UsingDefaults)
    p.p.sh=ip.Results.sh_prior;
  end
  if init || ~ismember('is_prior',ip.UsingDefaults)
    p.p.is=ip.Results.is_prior;
  end

  if init
    % set functions
    p.fh.pak = @prior_gamma_pak;
    p.fh.unpak = @prior_gamma_unpak;
    p.fh.lp = @prior_gamma_lp;
    p.fh.lpg = @prior_gamma_lpg;
    p.fh.recappend = @prior_gamma_recappend;
  end

end

function [w, s] = prior_gamma_pak(p)

  w=[];
  s={};
  if ~isempty(p.p.sh)
    w = log(p.sh);
    s=[s; 'log(Gamma.sh)'];
  end
  if ~isempty(p.p.is)
    w = [w log(p.is)];
    s=[s; 'log(Gamma.is)'];
  end
end

function [p, w] = prior_gamma_unpak(p, w)

  if ~isempty(p.p.sh)
    i1=1;
    p.sh = exp(w(i1));
    w = w(i1+1:end);
  end
  if ~isempty(p.p.is)
    i1=1;
    p.is = exp(w(i1));
    w = w(i1+1:end);
  end
end

function lp = prior_gamma_lp(x, p)

  lp = sum(-p.is.*x + (p.sh-1).*log(x) +p.sh.*log(p.is)  -gammaln(p.sh));

  if ~isempty(p.p.sh)
    lp = lp + p.p.sh.fh.lp(p.sh, p.p.sh) + log(p.sh);
  end
  if ~isempty(p.p.is)
    lp = lp + p.p.is.fh.lp(p.is, p.p.is) + log(p.is);
  end
end

function lpg = prior_gamma_lpg(x, p)

  lpg = (p.sh-1)./x - p.is;

  if ~isempty(p.p.sh)
    lpgsh = (sum(-digamma1(p.sh) + log(p.is) + log(x)) + p.p.sh.fh.lpg(p.sh, p.p.sh)).*p.sh + 1;
    lpg = [lpg lpgsh];
  end
  if ~isempty(p.p.is)
    lpgis = (sum(p.sh./p.is+x) + p.p.is.fh.lpg(p.is, p.p.is)).*p.is + 1;
    lpg = [lpg lpgis];
  end

end

function rec = prior_gamma_recappend(rec, ri, p)
% The parameters are not sampled in any case.
  rec = rec;
  if ~isempty(p.p.sh)
    rec.sh(ri,:) = p.sh;
  end
  if ~isempty(p.p.is)
    rec.is(ri,:) = p.is;
  end
end


function prob = rowlin2nl(prob,sparsity,warn)
%ROWLIN2NL Convert Row Based Linear Constraints to Row Based Nonlinear Constraints

%   Copyright (C) 2012 Jonathan Currie (IPL)

if(isempty(prob.A))
    return; %nothing to do
end

if(~exist('warn','var') || isempty(warn))
    warn = 1;
end
if(~exist('sparsity','var') || isempty(sparsity))
    sparsity = 1;
end

%If we don't have any nonlinear constraints, just build from linear ones
if(isempty(prob.nlcon))
    %Build nonlinear constraints + jacobian + jac structure (assumes jac + str not provided)
    prob.nlcon = @(x) prob.A*x;
    if(sparsity)
        prob.nljac = @(x) sparse(prob.A);
        prob.nljacstr = @() sparse(double(prob.A ~= 0));
    else
        prob.nljac = @(x) prob.A;
        prob.nljacstr = @() double(prob.A ~= 0);
    end
    %Assign constraint bounds
    prob.cl = prob.rl;
    prob.cu = prob.ru;
    %Add sizes
    eq = prob.cl == prob.cu; neq = ~eq;
    ile = isfinite(prob.cu) & neq;
    ige = isfinite(prob.cl) & neq;
    prob.sizes.nnlineq = sum(ile + ige);
    prob.sizes.nnleq = sum(eq);
    %Indicate all linear
    prob.lincon = 1;

%Otherwise Augment linear to nonlinear constraints
else
    %Augment nonlinear constraint function
    prob.nlcon = @(x) [prob.nlcon(x);
                       prob.A*x];
    %Augment nonlinear Jacobian if it exists
    if(~isempty(prob.nljac))
        if(sparsity)
            A = sparse(prob.A);
            prob.nljac = @(x) [prob.nljac(x);
                               A];
        else
            prob.nljac = @(x) [prob.nljac(x);
                               prob.A];
        end
    end
    %Augment nonlinear jacobian structure if it exists
    if(~isempty(prob.nljacstr))
        if(sparsity)
            A = sparse(prob.A ~= 0);
            prob.nljacstr = @() [prob.nljacstr(); A];
        else
            prob.nljacstr = @() [prob.nljacstr(); double(prob.A ~= 0)];
        end
    end

    %Augment rhs + type
    prob.cl = [prob.cl;
               prob.rl];
    prob.cu = [prob.cu;
               prob.ru];
    %Add sizes
    eq = prob.rl == prob.ru; neq = ~eq;
    ile = isfinite(prob.ru) & neq;
    ige = isfinite(prob.rl) & neq;
    prob.sizes.nnlineq = prob.sizes.nnlineq + sum(ile + ige);
    prob.sizes.nnleq = prob.sizes.nnleq + sum(eq);
    %Indicate not all linear
    prob.lincon = 0;
end

if(warn > 1)
    optiwarn('opti:rowlin_nl','RowLin2NL - Linear Constraints have been converted to Nonlinear Constraints to suit NLP Solver interface');
end

end


function vt = volToTalairach(volCoords, v2t)
% talairachCoords = volToTalairach(volCoords, v2t)
%
% PURPOSE:
%   Converts arbitrary coordinates (volCoords) to Talairach space, given
%   the transform info in the v2t struct. The coords must be in 'n X 3'
%   row-vector form. The v2t struct must have a 4x4 affine transform matrix
%
%       v2t.transRot
%
%   And 7 scale factors:
%
%       v2t.superiorAcScale
%       v2t.inferiorAcScale
%       v2t.rightAcScale
%       v2t.leftAcScale
%       v2t.anteriorAcScale
%       v2t.betweenAcPcScale
%       v2t.posteriorPcScale
%
%   See computeTalairach.m for an example of how to compute these.
%
% HISTORY:
%   2001.09.14 RFD (bob@white.stanford.edu) Wrote it, with help from
%              Alex Wade and Jochem Rieger.

% MrLoadRet coords are axial,coronal,sagittal, but we need coronal,axial,sagittal.
% Oh well...

% We have to make the coords homogeneous (ie. 4d)
vt = ones(size(volCoords,1),size(volCoords,2)+1);
vt(:,1:3) = [volCoords(:,2),volCoords(:,1),volCoords(:,3)];

% now, apply translation and rotation
vt = vt * v2t.transRot;

% v shoule now be on the talairach axes:
%   X = sagittal slice (right is +)
%   Y = coronal slice (anterior is +)
%   Z = axial slice (superior is +)
%
% We just need to apply the appropriate scale factor
for(ii=1:size(vt,1))
    if(vt(ii,1)>0)
        vt(ii,1) = vt(ii,1) * v2t.rightAcScale;
    else
        vt(ii,1) = vt(ii,1) * v2t.leftAcScale;
    end
    if(vt(ii,3)>0)
        vt(ii,3) = vt(ii,3) * v2t.superiorAcScale;
    else
        vt(ii,3) = vt(ii,3) * v2t.inferiorAcScale;
    end
     if(vt(ii,2)>0)
        vt(ii,2) = vt(ii,2) * v2t.anteriorAcScale;
    else
        acpc = vt(ii,2) * v2t.betweenAcPcScale;
        % we have to apply separate scale factors if it goes beyond the PC
        if(acpc<-24)
            beyondPC = vt(ii,2) + 24/v2t.betweenAcPcScale;
            vt(ii,2) = -24 + beyondPC*v2t.posteriorPcScale;
        else
            vt(ii,2) = acpc;
        end
    end
end
vt = vt(:,1:3);
return;


function [ ap, det, inert ] = zhpdi ( ap, n, ipvt, job )

%*****************************************************************************80
%
%% ZHPDI: determinant, inertia and inverse of a complex hermitian matrix.
%
%  Discussion:
%
%    The routine uses the factors from ZHPFA.
%
%    The matrix is stored in packed form.
%
%    A division by zero will occur if the inverse is requested and ZHPCO has
%    set RCOND == 0.0 or ZHPFA has set INFO ~= 0.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex AP(N*(N+1)/2); the factored matrix
%    from ZHPFA.
%
%    Input, integer N, the order of the matrix.
%
%    Input, integer IPVT(N), the pivot vector from ZHPFA.
%
%    Input, integer JOB, has the decimal expansion ABC where:
%    if C ~= 0, the inverse is computed,
%    if B ~= 0, the determinant is computed,
%    if A ~= 0, the inertia is computed.
%    For example, JOB = 111 gives all three.
%
%    Output, complex AP(N*(N+1)/2); if the inverse was requested, then
%    the upper triangle of the inverse of the original matrix, stored in packed
%    form.  The columns of the upper triangle are stored sequentially in a
%    one-dimensional array.
%
%    Output, real DET(2), if requested, the determinant of the original matrix.
%    Determinant = DET(1) * 10.0**DET(2) with 1.0 <= abs ( DET(1) ) < 10.0
%    or DET(1) = 0.0.
%
%    Output, integer INERT(3), if requested, the inertia of the original matrix.
%    INERT(1) = number of positive eigenvalues.
%    INERT(2) = number of negative eigenvalues.
%    INERT(3) = number of zero eigenvalues.
%
  det = [];
  inert = [];

  noinv = mod ( job, 10 ) == 0;
  nodet = floor ( mod ( job, 100 ) / 10 ) == 0;
  noert = floor ( mod ( job, 1000 ) / 100 ) == 0;

  if ( ~nodet | ~noert )

    if ( ~noert )
      inert(1:3) = 0;
    end

    if ( ~nodet )
      det(1) = 1.0;
      det(2) = 0.0;
    end

    t = 0.0;
    ik = 0;

    for k = 1 : n

      kk = ik + k;
      d = real ( ap(kk) );
%
%  Check if 1 by 1
%
      if ( ipvt(k) <= 0 )
%
%  2 by 2 block
%  Use DET (D  S; S  C)  =  ( D / T * C - T ) * T, T = abs ( S )
%  to avoid underflow/overflow troubles.
%  Take two passes through scaling.  Use T for flag.
%
        if ( t == 0.0 )
          ikp1 = ik + k;
          kkp1 = ikp1 + k;
          t = abs ( ap(kkp1) );
          d = ( d / t ) * real ( ap(kkp1+1) ) - t;
        else
          d = t;
          t = 0.0;
        end

      end

      if ( ~noert )

        if ( 0.0 < d )
          inert(1) = inert(1) + 1;
        elseif ( d < 0.0 )
          inert(2) = inert(2) + 1;
        elseif ( d == 0.0 )
          inert(3) = inert(3) + 1;
        end

      end

      if ( ~nodet )

        det(1) = det(1) * d;

        if ( det(1) ~= 0.0 )

          while ( abs ( det(1) ) < 1.0 )
            det(1) = det(1) * 10.0;
            det(2) = det(2) - 1.0;
          end

          while ( 10.0 <= abs ( det(1) ) )
            det(1) = det(1) / 10.0;
            det(2) = det(2) + 1.0;
          end

        end

      end

      ik = ik + k;

    end

  end
%
%  Compute inverse(A).
%
  if ( ~noinv )

    k = 1;
    ik = 0;

    while ( k <= n )

      km1 = k - 1;
      kk = ik + k;
      ikp1 = ik + k;
      kkp1 = ikp1 + k;
%
%  1 by 1
%
      if ( 0 <= ipvt(k) )

        ap(kk) = 1.0 / real ( ap(kk) );

        if ( 1 <= km1 )

          work(1:km1) = ap(ik+1:ik+km1);

          ij = 0;
          for j = 1 : km1
            jk = ik + j;
            ap(jk) = conj ( ap(ij+1:ij+j) ) * tranpose ( work(1:j) );
            ap(ik+1:ik+j-1) = ap(ik+1:ik+j-1) + work(j) * ap(ij+1:ij+j-1);
            ij = ij + j;
          end

          ap(kk) = ap(kk) + real ( conj ( work(1:km1) ) * transpose ( ap(ik+1:ik+km1) ) );

        end

        kstep = 1;
%
%  2 by 2
%
      else

        t = abs ( ap(kkp1) );
        ak = real ( ap(kk) ) / t;
        akp1 = real ( ap(kkp1+1) ) / t;
        akkp1 = ap(kkp1) / t;
        d = t * ( ak * akp1 - 1.0 );
        ap(kk) = akp1 / d;
        ap(kkp1+1) = ak / d;
        ap(kkp1) = -akkp1 / d;

        if ( 1 <= km1 )

          work(1:km1) = ap(ikp1+1:ikp1+km1);

          ij = 0;
          for j = 1 : km1
            jkp1 = ikp1 + j;
            ap(jkp1) = conj ( ap(ij+1:ij+j) ) * transpose ( work(1:j) );
            ap(ikp1+1:ikp1+j-1) = ap(ikp1+1:ikp1+j-1) ...
              + work(j) * ap(ij+1:ij+j-1);
            ij = ij + j;
          end

          ap(kkp1+1) = ap(kkp1+1) ...
            + real ( conj ( work(1:km1) ) * transpose ( ap(ikp1+1) ) );

          ap(kkp1) = ap(kkp1) ...
            + conj ( ap(ik+1:ik+km1) ) * transpose ( ap(ikp1+1:ikp1+km1) );

          work(1:km1) = ap(ik+1:ik+km1);

          ij = 0;

          for j = 1 : km1
            jk = ik + j;
            ap(jk) = conj ( ap(ij+1:ij+j) ) * transpose ( work(1:j) );
            ap(ik+1:ik+j-1) = ap(ik+1:ik+j-1) + work(j) * ap(ij+1:ij+j-1);
            ij = ij + j;
          end

          ap(kk) = ap(kk) ...
            + real ( conj ( work(1:km1) ) * transpose ( ap(ik+1:ik+km1) ) );

        end

        kstep = 2;

      end
%
%  Swap
%
      ks = abs ( ipvt(k) );

      if ( ks ~= k )

        iks = ( ks * ( ks - 1 ) ) / 2;

        temp             = ap(iks+1:iks+ks);
        ap(iks+1:iks+ks) = ap(ik+1:ik+ks);
        ap(ik+1:ik+ks)   = temp;

        ksj = ik + ks;

        for jb = ks : k

          j = k + ks - jb;
          jk = ik + j;

          temp    = conj ( ap(jk) );
          ap(jk)  = conj ( ap(ksj) );
          ap(ksj) = temp;

          ksj = ksj - ( j - 1 );

        end

        if ( kstep ~= 1 )

          kskp1 = ikp1 + ks;

          temp      = ap(kskp1);
          ap(kskp1) = ap(kkp1);
          ap(kkp1)  = temp;

        end

      end

      ik = ik + k;

      if ( kstep == 2 )
        ik = ik + k + 1;
      end

      k = k + kstep;

    end

  end

  return
end


% Copyright 2017 Google Inc.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%     https://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.

% Calls a denoiser and return the cleaned image f_est.
% In this example the chosen denoising method is TNRD.
% Note: The devision and multiplication by the constant 5 is done to handle
% a different noise-level than a fixed one (which is equal to 5)

function f_est = Denoiser(x_est,effective_sigma)

f_est = ReactionDiffusion(5/effective_sigma*x_est);
f_est = f_est*effective_sigma/5;

return


function [] = printTextSummaryForHMMData( data_struct, model )

numObj = length(data_struct);
Ts = [ data_struct(:).T];

switch model.obsModel.type
    case 'Multinomial'
        data_struct(1).numVocab = length(model.obsModel.params.lambda);
        nV = data_struct(1).numVocab;
        obsDescr = sprintf( 'with %d distinct symbols\n', nV );
        if isfield( data_struct, 'nEmissions' )
            Es = [ data_struct(:).nEmissions ] ;
            obsDescr = [obsDescr sprintf('\t   between %d-%d emissions per timestep ( median = %.1f ) \n', min(Es), max(Es), median(Es)) ];
        else
            symbolInfo = sprintf('\t   all timesteps emit exactly %d symbols\n',  size( data_struct(1).obs,1 ) );
            obsDescr = [obsDescr symbolInfo];
        end
    case 'Bernoulli'
        D = size( data_struct(1).obs, 2 );
        obsDescr = sprintf( 'across %d dimensions', D );
    case 'Gaussian'
        D = size( data_struct(1).obs, 2 );
        obsDescr = sprintf( 'with %d dimensions', D );
    case 'AR-Gaussian'
        D = size( data_struct(1).obs, 2 );
        obsDescr = sprintf( 'with %d dimensions', D );
end

fprintf( 'Dataset Summary: \n\t %d time series objects \n', numObj );
fprintf('\t   between %d-%d timesteps per object ( median = %.1f ) \n', min(Ts), max(Ts), median(Ts));
fprintf('\t   %s emissions %s\n', model.obsModel.type, obsDescr );


function timer_cputime_test03 ( )

%*****************************************************************************80
%
%% TEST03 times the unvectorized EXP routine.
%
%  Discussion:
%
%    For the MATLAB implementation of this test, the unvectorized
%    test limits had to be DRASTICALLY reduced.  But then I noticed
%    that some kind of MATLAB cleverness causes all the loops
%    after the first cycle to be computed in almost no time.
%    This test will have to be rethought.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 December 2005
%
%  Author:
%
%    John Burkardt
%
  n_log_min = 12;
  n_log_max = 16;
  n_min = 2^n_log_min;
  n_max = 2^n_log_max;
  n_rep = 5;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST03\n' );
  fprintf ( 1, '  Time the unvectorized loops:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '    for i = 1 : n\n' );
  fprintf ( 1, '      y(i) =        x(i)\n' );
  fprintf ( 1, '      y(i) = PI *   x(i)\n' );
  fprintf ( 1, '      y(i) = sqrt ( x(i) )\n' );
  fprintf ( 1, '      y(i) = exp  ( x(i) )\n' );
  fprintf ( 1, '    end\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Data vectors will be of minimum size %d\n', n_min );
  fprintf ( 1, '  Data vectors will be of maximum size %d\n', n_max );
  fprintf ( 1, '  Number of repetitions of the operation: %d\n', n_rep );

  for func = 1 : 4

    for i_rep = 1 : n_rep

      for n_log = n_log_min : n_log_max

        n = 2^n_log;

        x = rand(n,1);

        time1 = cputime;

        if ( func == 1 )
          for i = 1: n
            y(i) = x(i);
          end
        elseif ( func == 2 )
          for i = 1: n
            y(i) = pi * x(i);
          end
        elseif ( func == 3 )
          for i = 1: n
            y(i) = sqrt ( x(i) );
          end
        elseif ( func == 4 )
          for i = 1: n
            y(i) = exp ( x(i) );
          end
        end

        time2 = cputime;

        delta(n_log,i_rep) = time2 - time1;

      end

    end

    fprintf ( 1, '\n' );
    fprintf ( 1, 'Test03 Results:\n' );
    fprintf ( 1, '\n' );
    fprintf ( 1, 'Vector Size  Rep #1        Rep #2        ' );
    fprintf ( 1, 'Rep #3        Rep #4        Rep #5\n' );
    fprintf ( 1, '\n' );

    for n_log = n_log_min : n_log_max
      n = 2^n_log;
      fprintf ( 1, '%d', n );
      for j = 1 : n_rep
        fprintf ( 1, '%14f', delta(n_log,j) );
      end
      fprintf ( 1, '\n' );
    end

  end

  return
end


function res = imThumbnail(img, siz, varargin)
%IMTHUMBNAIL Resize an image to bound the size in each direction
%
%   RES = imThumbnail(IMG, SIZ)
%   Resizes the image given in IMG such that the dimension is lower or
%   equal to the dimension given by SIZ.
%
%   Example
%     img = imread('cameraman.tif');
%     img2 = imThumbnail(img, [64 64]);
%     imshow(img2)
%
%     img = imread('peppers.png');
%     img2 = imThumbnail(img, [64 64]);
%     imshow(img2)
%
%   See also
%   imresize
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2013-02-14,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2013 INRA - Cepia Software Platform.

k1 = siz(1) / size(img, 1);
k2 = siz(2) / size(img, 2);
k = min(k1, k2);

res = imresize(img, k, varargin{:});


function disp_(c)
%DISP_        Display of interval gradients in "_" notation
%
%   disp_(c)
%

% written  06/04/09     S.M. Rump
% modified 08/26/12     S.M. Rump  global variables removed
% modified 10/05/12     S.M. Rump  complete redesign
%

  INTLAB_GRADIENT_NUMVAR = getappdata(0,'INTLAB_GRADIENT_NUMVAR');

  loose = strcmp(get(0,'FormatSpacing'),'loose');

  numvar = size(c.dx,2);
  if numvar~=INTLAB_GRADIENT_NUMVAR
    warning('**** number of dependent variables and partial derivatives do not coincide')
  end

  name = inputname(1);
  if isempty(name)                    % happens for display(gradientinit(random))
    name = 'ans';
  end

  INTLAB_INTVAL_DISPLAY = getappdata(0,'INTLAB_INTVAL_DISPLAY');
  setappdata(0,'INTLAB_INTVAL_DISPLAY','Display_');
  display(c,name)
  setappdata(0,'INTLAB_INTVAL_DISPLAY',INTLAB_INTVAL_DISPLAY);


% This demo loads two color images and efficiently computes the emd_hat
% between them. The ground distance is a thresholded linear combination of
% the spatial and color distance between pixels. This is similar to the
% distance I used for color images in my ICCV paper. Image sizes do not
% need to be the same. As a color distance I used CIEDE2000.
% emd_hat is described in the paper:
%  A Linear Time Histogram Metric for Improved SIFT Matching
%  Ofir Pele, Michael Werman
%  ECCV 2008
% The efficient algorithm is described in the paper:
%  Fast and Robust Earth Mover's Distances
%  Ofir Pele, Michael Werman
%  ICCV 2009
% CIEDE2000 is described in the papers:
% The development of the CIE 2000 colour-difference formula: CIEDE2000
%  M. R. Luo, G. Cui, B. Rigg
%  CRA 2001
% The CIEDE2000 color-difference formula: Implementation notes, supplementary test data, and mathematical observations
%  Gaurav Sharma, Wencheng Wu, Edul N. Dalal
%  CRA 2004

clc; close all; clear all;

addpath ../

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Distance parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% In the paper I used threshold=20, but I didn't use alpha_color and
% 1-alpha_color for the spatial. I just added them. So using threshold=10
% is equivalent to what I used in the paper.
threshold= 10;
alpha_color= 1/2;
% Center. In the ICCV paper center and identity were equivalent as the image
% sizes were the same.
coordinates_transformation= 2;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load images
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
im1= imresize( imread('1.jpg') , 1/30);
im2= imresize( imread('2.jpg') , 1/30);
% 3.jpg is more similar to 1.jpg and thus the running time will be longer.
%im2= imresize( imread('3.jpg') , 1/30);
im1_Y= size(im1,1);
im1_X= size(im1,2);
im1_N= im1_Y*im1_X;
im2_Y= size(im2,1);
im2_X= size(im2,2);
im2_N= im2_Y*im2_X;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% EMD input
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
P= [ ones(im1_N,1)  ;  zeros(im2_N,1) ];
Q= [ zeros(im1_N,1) ;  ones(im2_N,1)  ];

im1= double(im1)./255;
im2= double(im2)./255;
cform = makecform('srgb2lab');
im1_lab= applycform(im1, cform);
im2_lab= applycform(im2, cform);

% Creating the ground distance matrix.
% Loops in Matlab are very time consuming, so I use mex.
% Matlab corresponding code is commented out below.
tic
[ground_distance_matrix]= color_spatial_EMD_ground_distance(im1_lab,im2_lab,...
                                                  alpha_color,threshold, ...
                                                  coordinates_transformation);
fprintf(1,'computing the ground distance matrix, time in seconds: %f\n', ...
        toc);

% In ICCV paper extra_mass_penalty did not matter as image sizes were the same.
extra_mass_penalty= -1;
flowType= 3;

tic
[emd_hat_mex_val_with_flow F]= emd_hat_mex(P,Q,ground_distance_matrix,extra_mass_penalty,flowType);
fprintf(1,'Note that the ground distance here is not a metric.\n');
fprintf(1,'emd_hat_mex, time in seconds: %f\n',toc);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright (c) 2009-2012, Ofir Pele
% All rights reserved.

% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%    * Redistributions of source code must retain the above copyright
%    notice, this list of conditions and the following disclaimer.
%    * Redistributions in binary form must reproduce the above copyright
%    notice, this list of conditions and the following disclaimer in the
%    documentation and/or other materials provided with the distribution.
%    * Neither the name of the The Hebrew University of Jerusalem nor the
%    names of its contributors may be used to endorse or promote products
%    derived from this software without specific prior written permission.

% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
% IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
% THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
% PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


classdef ResponseLossL2 < dagnn.Loss
%ResponseLossL2  layer
%  `ResponseLossL2.forward({r, x*})` computes L2 loss.
%
%  Here the Loss between two matrices is defined as:
%
%     Loss = |r - r_idea|.*|r - r_idea|
%
%  Input
%       - r    w x h x 1 x N.
%       - x0   N x 2
%   QiangWang, 2016
% -------------------------------------------------------------------------------------------------------------------------
    properties
        win_size = [3,3];
        sigma = 1;
    end
    properties (Transient)
        y = [];
    end
    methods
        function outputs = forward(obj, inputs, params)
            r1 = inputs{1}; % middle result of Z1
            r2 = inputs{2}; % middle result of Z2
            r3 = inputs{3}; % final label of X
            r4 = inputs{4}; % initial label of X

            % original loss
            res_minus = bsxfun(@minus,r3,r4);
            loss = res_minus.*res_minus;
            perSample_loss = sum(sum(sum(loss,1),2),3);
            [~, index] = sort(perSample_loss, 'ascend');
            sample_drop = zeros(1,1,1,size(r1,4));
            % drop unreliable samples
            max_num = round(0.9*size(r1,4));
            sample_drop(index(1:max_num)) = 1;

            % the motion between X and Z1
            delta1 = bsxfun(@minus,r1,r4);
            % the motion between Z1 and Z2
            delta2 = bsxfun(@minus,r1,r2);
            delta = delta1.*delta1 + delta2.*delta2;
            delta_sum = sum(sum(sum(delta, 1),2),3);
            delta_drop = bsxfun(@times,delta_sum,sample_drop);
            delta_norm = delta_drop./sum(delta_drop(:)) * size(r3,4);

            % spatial weight
            spatial = exp(r4);
            weight = bsxfun(@times, delta_norm, spatial);
            % add weight
            loss = loss.*weight;

            outputs{1} = sum(loss(:))/size(r3,4);

            n = obj.numAveraged ;
            m = n + 1 ;
            obj.average = (n * obj.average + gather(outputs{1})) / m ;
            obj.numAveraged = m ;

        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
            r1 = inputs{1};
            r2 = inputs{2};
            r3 = inputs{3};
            r4 = inputs{4};

            % original loss
            res_minus = bsxfun(@minus,r3,r4);
            loss = res_minus.*res_minus;
            perSample_loss = sum(sum(sum(loss,1),2),3);
            [~, index] = sort(perSample_loss, 'ascend');
            sample_drop = zeros(1,1,1,size(r1,4));
            % drop unreliable samples
            max_num = round(0.9*size(r1,4));
            sample_drop(index(1:max_num)) = 1;

            % the motion between X and Z1
            delta1 = bsxfun(@minus,r1,r4);
            % the motion between Z1 and Z2
            delta2 = bsxfun(@minus,r1,r2);
            delta = delta1.*delta1 + delta2.*delta2;
            delta_sum = sum(sum(sum(delta, 1),2),3);
            delta_drop = bsxfun(@times,delta_sum,sample_drop);
            delta_norm = delta_drop./sum(delta_drop(:)) * size(r3,4);

            % spatial weight
            spatial = exp(r4);
            weight = bsxfun(@times, delta_norm, spatial);

            derInputs{1} = {};
            derInputs{2} = {};
            derInputs{3} = (derOutputs{1}*2/size(r3,4)).*bsxfun(@minus,r3,r4).*weight ;
            derInputs{4} = {};
            derParams = {} ;
        end

        function obj = reset(obj)
            obj.y = [] ;
            obj.average = 0 ;
            obj.numAveraged = 0 ;
        end

        function obj = ResponseLossL2(varargin)
            obj.load(varargin);
            obj.win_size = obj.win_size;
            obj.sigma = obj.sigma ;
            obj.y = [];
        end

    end

end


function [sys,x0,str,ts]=Nonlinear_PD(t,x,u,flag,Beta1,Beta2,Delta,a1,a2,h)

if flag==0

    sys = [0;1;1;2;0;1;1];
     x0 = [0];
    str = [ ];
     ts = [h 0];

elseif flag==2

    Bili=fal(u(1),a1,Delta);
    Weifen=fal(u(2),a2,Delta);
    sys=Beta1*Bili+Beta2*Weifen;

elseif flag==3
    sys=x;

elseif flag==4
    sys=sys+h;

else
    sys=[];
end
function f=fal(e,a,d)
    if abs(e)<d
        f=e*d^(a-1);
    else f=(abs(e))^a*sign(e);
    end


function opts = U_param(opts,mn,ln)

opts.do_thres=1; % threshold the output image [0 255] after each iteration
opts.grad_ran=[0.1 100]; % adaptively scale the gradient scale if it's out of range
switch opts.task
    case 0 % feature inversion
        switch mn
            case 'alex'
            opts.lambdaL2 = 8e-10 ;opts.lambdaTV = 1e0;opts.lambdaD = 1e2;
            opts.learningRate = 0.0004 * [...
                ones(1,100), ...
                0.1 * ones(1,200), ...
                0.01 * ones(1,100)];
              switch ln
                case 'p5'; % default
                opts.lambdaL2 = 8e-8 ;opts.lambdaTV = 1e2;opts.lambdaD = 1e1;
            opts.learningRate = 0.0004 * [...
                ones(1,500), ...
                0.1 * ones(1,200), ...
                0.01 * ones(1,100)];
                end
            end
    case 1 % neuron inversion
        switch mn
            case 'alex'
                opts.lambdaL2 = 1e-10 ;opts.lambdaTV = 1e2;opts.lambdaD = 1e-3;
                opts.learningRate = 0.04 * [...
                    0.05 * ones(1,100), ...
                    0.01 * ones(1,100)];
                switch ln
                case 'p5'; % default
                case 'f7'; opts.lambdaD = 3e-2;
                case 'f8'; opts.lambdaD = 1e-2;
                end
            case 'vgg16'
                opts.lambdaL2 = 1e-10 ;opts.lambdaTV = 8e2;opts.lambdaD = 3e-3;
                opts.learningRate = 0.001 * [...
                    0.05 * ones(1,100), ...
                    0.01 * ones(1,50)];
                opts.grad_ran=[0.1 100];
            case 'nin'
                opts.lambdaL2 = 1e-10 ;opts.lambdaTV = 8e2;opts.lambdaD = 3e-3;
                opts.learningRate = 0.004 * [...
                    0.05 * ones(1,100), ...
                    0.01 * ones(1,50)];
            case 'gnet'
                % annealing schedule
                opts.lambdaL2 = [1e0*ones(1,50) 1e1*ones(1,50) 1e2*ones(1,100)];
                opts.lambdaTV = 1e-1*[5e2*ones(1,100) 5e2*ones(1,100)];
                opts.lambdaD = 3e-3;
                opts.learningRate = 0.04 * [...
                    0.05 * ones(1,100), ...
                    0.01 * ones(1,100)];
        end
    case 2
        % image inpainting
        switch mn
        case 'alex'
            opts.lambdaL2 = 1e-8 ;opts.lambdaTV = 5e2;
            opts.lambdaD = 5e1;
            opts.grad_ran=[0 20];
            opts.learningRate = 0.004 * [...
            0.05 * ones(1,150), ...
            0.05 * ones(1,0), ...
            0.05 * ones(1,0)];
        end
end