function [ node_num, face_num, normal_num, order_max ] = obj_size ( ...
  input_file_name )

%*****************************************************************************80
%
%% OBJ_SIZE determines sizes of graphics objects in an Alias OBJ file.
%
%  Discussion:
%
%    The only items of interest to this routine are vertices,
%    faces, and normal vectors.
%
%  Example:
%
%    #  magnolia.obj
%
%    v -3.269770 -39.572201 0.876128
%    v -3.263720 -39.507999 2.160890
%    ...
%    v 0.000000 -9.988540 0.000000
%
%    vn 1.0 0.0 0.0
%    ...
%    vn 0.0 1.0 0.0
%
%    f 8 9 11 10
%    f 12 13 15 14
%    ...
%    f 788 806 774
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the input file name.
%
%    Output, integer NODE_NUM, the number of points.
%
%    Output, integer FACE_NUM, the number of faces.
%
%    Output, integer NORMAL_NUM, the number of normal vectors.
%
%    Output, integer ORDER_MAX, the maximum face order.
%
  ierror = 0;

  face_num = 0;
  node_num = 0;
  normal_num = 0;
  order_max = 0;
  text_num = 0;
%
%  If no file input, try to get one from the user.
%
  if ( nargin < 1 )
    input_file_name = input ( 'Enter the name of the ASCII OBJ file.' );
    if ( isempty ( input_file_name ) )
      return
    end
  end
%
%  Open the file.
%
  input_file_unit = fopen ( input_file_name, 'r' );

  if ( input_file_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'OBJ_SIZE - Fatal error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'OBJ_SIZE - Fatal error!' );
    return
  end
%
%  Read a line of text from the file.
%
  while ( 1 )

    text = fgetl ( input_file_unit );

    if ( text == -1 )
      break
    end

    text_num = text_num + 1;
%
%  Replace any control characters (in particular, TABs) by blanks.
%
    s_control_blank ( text );

    done = 1;
    word_index = 0;
%
%  Read a word from the line.
%
    [ word, done ] = word_next_read ( text, done );
%
%  If no more words in this line, read a new line.
%
    if ( done )
      continue
    end
%
%  If this word begins with '#' or '$', then it is a comment.  Read a new line.
%
    if ( word(1) == '#' || word(1) == '$' )
      continue
    end

    word_index = word_index + 1;

    if ( word_index == 1 )
      word_one = word;
    end
%
%  F V1 V2 V3 ...
%    or
%  F V1/VT1/VN1 V2/VT2/VN2 ...
%    or
%  F V1//VN1 V2//VN2 ...
%
%  Face.
%  A face is defined by the vertices.
%  Optionally, slashes may be used to include the texture vertex
%  and vertex normal indices.
%
    if ( s_eqi ( word_one, 'F' ) )

      face_num = face_num + 1;

      vertex = 0;

      while ( 1 )

        [ word, done ] = word_next_read ( text, done );

        if ( done )
          break
        end

        vertex = vertex + 1;
        order_max = max ( order_max, vertex );
%
%  Locate the slash characters in the word, if any.
%
        i1 = ch_index ( word, '/' );
        if ( 0 < i1 )
          i2 = ch_index ( word(i1+1), '/' ) + i1;
        else
          i2 = 0;
        end
%
%  Read the vertex index.
%
        itemp = s_to_i4 ( word );
%
%  If there are two slashes, then read the data following the second one.
%
        if ( 0 < i2 )
          itemp = s_to_i4 ( word(i2+1) );
        end

      end
%
%  V X Y Z W
%  Geometric vertex.
%
    elseif ( s_eqi ( word_one, 'V' ) )

      node_num = node_num + 1;
      continue
%
%  VN
%  Vertex normals.
%
    elseif ( s_eqi ( word_one, 'VN' ) )

      normal_num = normal_num + 1;
      continue

    end

  end

  fclose ( input_file_unit );

  return
end


%% Demo: White balancing a single image
%
% Copyright (c) 2018-present, Mahmoud Afifi
% York University, Canada
% mafifi@eecs.yorku.ca | m.3afifi@gmail.com
%
% This source code is licensed under the license found in the
% LICENSE file in the root directory of this source tree.
% All rights reserved.
%
% Please cite the following work if this program is used:
% Mahmoud Afifi, Brian Price, Scott Cohen, and Michael S. Brown,
% "When color constancy goes wrong: Correcting improperly white-balanced
% images", CVPR 2019.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%

%% input and options
infileName = fullfile('..','example_images','figure3.jpg');
outfileName = fullfile('result.jpg');
device = 'cpu'; % 'cpu' or 'gpu'
gamut_mapping = 2; % use 1 for scaling, 2 for clipping (our paper's results reported using clipping).
upgraded_model = 1; % use 1 to load our new model that is upgraded with new training examples.

%%
switch lower(device)
    case 'cpu'
        if upgraded_model == 1
            load(fullfile('models','WB_model+.mat'));
        elseif upgraded_model == 0
            load(fullfile('models','WB_model.mat'));
        else
            error('Wrong upgraded_model value; please use 0 or 1');
        end
    case 'gpu'
        try
            gpuDevice();
        catch
            error('Cannot find a GPU device');
        end
        if upgraded_model == 1
            load(fullfile('models','WB_model+_gpu.mat'));
        elseif upgraded_model == 0
            load(fullfile('models','WB_model_gpu.mat'));
        else
            error('Wrong upgraded_model value; please use 0 or 1');
        end
    otherwise
        error('Wrong device; please use ''gpu'' or ''cpu''')
end
model.gamut_mapping = gamut_mapping;
fprintf('Processing image: %s\n',infileName);
I_in = imread(infileName);
tic
I_corr = model.correctImage(I_in);
disp('Done!');
toc
subplot(1,2,1); imshow(I_in); title('Input');
subplot(1,2,2); imshow(I_corr); title('Our result');
disp('Saving...');
if strcmpi(device,'cpu')
    imwrite(I_corr,outfileName);
else
    imwrite(gather(I_corr),outfileName);
end
disp('Saved!');


classdef Pooling < dagnn.Filter
  properties
    method = 'max'
    poolSize = [1 2]
    opts = {'cuDNN'}
  end

  methods
    function outputs = forward(self, inputs, params)
      outputs{1} = vl_nnpool(inputs{1}, self.poolSize, ...
                             'pad', self.pad, ...
                             'stride', self.stride, ...
                             'method', self.method, ...
                             self.opts{:}) ;
    end

    function [derInputs, derParams] = backward(self, inputs, params, derOutputs)
      derInputs{1} = vl_nnpool(inputs{1}, self.poolSize, derOutputs{1}, ...
                               'pad', self.pad, ...
                               'stride', self.stride, ...
                               'method', self.method, ...
                               self.opts{:}) ;
      derParams = {} ;
    end

    function kernelSize = getKernelSize(obj)
      kernelSize = obj.poolSize ;
    end

    function outputSizes = getOutputSizes(obj, inputSizes)
      outputSizes = getOutputSizes@dagnn.Filter(obj, inputSizes) ;
      outputSizes{1}(3) = inputSizes{1}(3) ;
    end

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


% This file serves as a template of defining the topology of the
% beamforming network with cross entropy training.
% You should create a copy for each of your experiments and name them
% differently.
%
% Created by Xiong Xiao, Temasek Laboratories, NTU, Singapore.
% Last Modified: 29 Nov 2016
%
function para = ConfigDereverbNet_Regression(para)
para.topology = SetDefaultValue(para.topology, 'fs', 16000);
if isfield(para.topology, 'useChannel')
    para.topology.nCh = length(para.topology.useChannel);
else
    para.topology.nCh = 1;      % by default use 2 channels
end
para.topology = SetDefaultValue(para.topology, 'useFileName', 0);   % by default load waveforms into memory. If data is too big, we can also use wave file names

para.topology = SetDefaultValue(para.topology, 'fft_len', 512);
para.topology.freqBin = (0:1/para.topology.fft_len:0.5)*2*pi;
para.topology.nFreqBin = length(para.topology.freqBin);
% define the parameters for extracting Fourier coefficients
para.topology.frame_len = para.topology.fs * 0.025;
para.topology.frame_shift = para.topology.fs * 0.01;
para.topology.removeDC = 0;     % do not remove DC for faster speed.
para.topology.win_type = 'hamming';

% define the regression network type
para.topology = SetDefaultValue(para.topology, 'RegressionNetType', 'LSTM');
switch para.topology.RegressionNetType
    case 'DNN'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSize', [1024]);
        para.topology = SetDefaultValue(para.topology, 'contextSize', 11);  % for DNN, we use 11 frames of consecutive frames
    case 'LSTM'
        para.topology = SetDefaultValue(para.topology, 'hiddenLayerSize', [512]);
        para.topology = SetDefaultValue(para.topology, 'useDelta', 1);    % for LSTM, we use delta features without splicing
end

end


function y = blkdiag( varargin )

%Disciplined convex/geometric programming information for BLKDIAG:
%   BLKDIAG imposes no convexity restrictions on its arguments.

nv = 0;
nz = 0;
sz = [ 0, 0 ];
for k = 1 : nargin,
    x  = cvx( varargin{k} );
    sx = x.size_;
    if length( sx ) > 2,
        error( 'N-D matrices not supported.' );
    end
    b  = x.basis_;
    sz = sz + sx;
    nv = max( nv, size( b, 1 ) );
    nz = nz + nnz( b );
    varargin{k} = x;
end
bz = sparse( [], [], [], prod( sz ), nz, nv );
roff = 0;
coff = 0;
for k = 1 : nargin,
    x  = varargin{k};
    b  = x.basis_;
    sx = x.size_;
    ndxr = ( roff : roff + sx( 1 ) - 1 )';
    ndxr = ndxr( :, ones( 1, sx( 2 ) ) );
    ndxc = ( coff : coff + sx( 2 ) - 1 );
    ndxc = ndxc( ones( 1, sx( 1 ) ), : );
    bz( 1 : size( b, 1 ), ndxc( : ) * sz( 1 ) + ndxr( : ) + 1 ) = b; %#ok
    roff = roff + sx( 1 );
    coff = coff + sx( 2 );
end
y = cvx( sz, bz );

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


% Q = vbfa(D, Y, W_module, X_module, noise_module, ...)
%
% Variational Bayesian (VB) factor analysis (FA) learning algorithm with
% changeable modules for the latent variables.

function Q = vbfa(D, Y, W_module, X_module, noise_module, varargin)

[M,N] = size(Y);

options = struct('maxiter', 100, ...
                 'update_x', 1, ...
                 'update_w', 1, ...
                 'update_noise', 1, ...
                 'rotate', 1, ...
                 'rotation_checkgrad', false, ...
                 'rotation_show', false, ...
                 'rotation_maxiter', 10, ...
                 'debug', false, ...
                 'autosave', false,...
                 'autosavefile', 'vbfa_autosave');

[options, errmsg] = argparse(options, varargin{:});
error(errmsg);

% Initialize
disp('Initializing variables..')
[Q.v_W,Q.W,Q.CovW] = W_module.initialize();
[Q.v_X,Q.X,Q.CovX] = X_module.initialize();
[Q.Tau] = noise_module.initialize();
Q.W_module = W_module;
Q.X_module = X_module;
Q.noise_module = noise_module;

% Observed values
Obs = ~isnan(Y);
MN_obs = sum(Obs(:));

% Replace missing values with zeros for computational reasons
Y(~Obs) = 0;

%%
%% VB learning

loglikelihood_old = -inf;
Q.loglikelihood = nan(options.maxiter,1);

Q.Y = Y;

KL_W = -inf;
KL_X = -inf;
KL_Tau = -inf;

%f = zeros(4,options.maxiter);

disp('Starting the VB iteration..')
for ind=1:options.maxiter

  startitercpu = cputime;

  %
  % Update variables
  %

  if index_selected(ind, options.update_x)
    if index_selected(ind, options.debug)
      disp('Update X')
    end
    [Q.v_X,Q.X,Q.CovX,KL_X] = X_module.update(ind, Y, Obs, Q.v_W, Q.W, Q.CovW, Q.Tau);
  end

  if index_selected(ind, options.update_w)
    if options.debug, disp('Update W'), end
    if index_selected(ind, options.debug)
      disp('Update W')
    end
    [Q.v_W,Q.W,Q.CovW,KL_W] = W_module.update(ind, Y', Obs', Q.v_X, Q.X, Q.CovX, Q.Tau');
  end

  % Compute squared errors <(y_mn-w_m*x_n)^2>
  % (used by noise update and loglikelihood)
  E2 = zeros(size(Y));
  Yh = Q.W'*Q.X;
  E2 = Y.*Y;
  E2 = E2 - 2*Y.*Yh;
  if ndims(Q.CovW) == 2 && ndims(Q.CovX) == 2
    E2 = E2 + Yh.^2 + Q.W'.^2*Q.CovX + Q.CovW'*Q.X.^2 + Q.CovW'*Q.CovX;
  elseif ndims(Q.CovW) == 3 && ndims(Q.CovX) == 3
    xx = bsxfun(@times, reshape(Q.X,[D,1,N]), reshape(Q.X,[1,D,N])) + Q.CovX;
    xx = reshape(xx, [D*D,N]);
    ww = bsxfun(@times, reshape(Q.W,[D,1,M]), reshape(Q.W,[1,D,M])) + Q.CovW;
    ww = reshape(ww, [D*D,M]);
    E2 = E2 + ww'*xx;
  else
    % TODO: Optimize this..
    warning('Optimize this..');
    for m=1:M
      for n=1:N
        if Obs(m,n)
          if ndims(Q.CovW) == 2
            ww = Q.W(:,m)*Q.W(:,m)' + diag(Q.CovW(:,m));
          else
            ww = Q.W(:,m)*Q.W(:,m)' + Q.CovW(:,:,m);
          end
          if ndims(Q.CovX) == 2
            xx = Q.X(:,n)*Q.X(:,n)' + diag(Q.CovX(:,n));
          else
            xx = Q.X(:,n)*Q.X(:,n)' + Q.CovX(:,:,n);
          end
          %WX_WX = WX_WX + traceprod(ww, xx);
          E2(m,n) = E2(m,n) + traceprod(ww, xx);
        end
      end
    end
  end
  E2(~Obs) = 0;

  if index_selected(ind, options.update_noise)
    if index_selected(ind, options.debug)
      disp('Update Tau')
    end

    [Q.Tau,LogTau,KL_Tau] = noise_module.update(ind, E2, Obs);
%    [Tau,lowerbound] = noise_module.update(Y, Obs, v_W, W, CovW, v_X, X, CovX);
  end

  %
  % Rotate
  %

  if index_selected(ind, options.rotate)

    % TODO: You could optimize the hyperparameters at the same time?
    disp('Rotating..')
    A = eye(D);

    if index_selected(ind, options.rotation_checkgrad)
      mycheckgrad(@rotation_cost, A(:) + 0.5*randn(D^2,1), 1e-3, W_module, ...
                  X_module);
    end
    A = minimize(A(:), @rotation_cost, options.rotation_maxiter, W_module, ...
                 X_module);
    A = reshape(A, [D D]);
    if index_selected(ind, options.rotation_show)
      A
    end
    [Q.W, Q.CovW] = W_module.rotate(A);
    [Q.X, Q.CovX] = X_module.rotate(inv(A)');

  end

  %
  % Evaluate VB lower bound
  %

  % Likelihood part: <log p(Y|...)>
  logpdf_y = gaussian_logpdf(Q.Tau(Obs)'*E2(Obs), ...
                             0, ...
                             0, ...
                             -sum(LogTau(Obs)), ...
                             MN_obs);

  % Lower bound
  Q.loglikelihood(ind) = logpdf_y - KL_W - KL_X - KL_Tau;

% $$$   if ~isreal(Q.loglikelihood(ind))
% $$$     KL_W
% $$$     KL_X
% $$$     KL_Tau
% $$$     error('Loglikelihood imaginary')
% $$$   end

  if Q.loglikelihood(ind) < loglikelihood_old
    warning(sprintf('Loglikelihood lower bound decreased relatively %e!', ...
                    (loglikelihood_old - Q.loglikelihood(ind)) / loglikelihood_old));
  end

  fprintf('Iteration step %d: loglikelihood=%e (%.2f seconds)\n', ind, ...
          Q.loglikelihood(ind), cputime()-startitercpu);

% $$$   f(1,ind) = KL_W;
% $$$   f(2,ind) = KL_X;
% $$$   f(3,ind) = KL_Tau;
% $$$   f(4,ind) = loglikelihood(ind);

  loglikelihood_old = Q.loglikelihood(ind);

  if index_selected(ind, options.autosave)
    fprintf('Saving results to %s...', options.autosavefile);
    save(options.autosavefile, '-struct', 'Q');
    fprintf(' done.\n');
  end

end

% $$$ figure
% $$$ plot(f');

% $$$ if nargout >= 1
% $$$
% $$$   Q.W_module = W_module;
% $$$   Q.W = W;
% $$$   Q.CovW = CovW;
% $$$
% $$$   Q.X_module = X_module;
% $$$   Q.X = X;
% $$$   Q.CovX = CovX;
% $$$
% $$$   Q.noise_module = noise_module;
% $$$   Q.Tau = Tau;
% $$$
% $$$   Q.loglikelihood = loglikelihood;
% $$$
% $$$ end

%function rotate(W_module, X_module)
%end

function [c, dc] = rotation_cost(a, W_module, X_module)
N = sqrt(length(a));
A = reshape(a, N, N);
[U,S,V] = svd(A);
invS = diag(1./diag(S));
invAt = U*invS*V';
[c_w, dc_w] = W_module.rotation_cost(A, U, S, V);
[c_x, dc_x] = X_module.rotation_cost(invAt, U, invS, V);
dc_x = -invAt*dc_x'*invAt;
c = c_w + c_x;
dc = dc_w(:) + dc_x(:);


% THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION IS RELEASED "AS IS."  THE U.S. GOVERNMENT MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, CONCERNING THIS SOFTWARE AND ANY ACCOMPANYING DOCUMENTATION, INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT WILL THE U.S. GOVERNMENT BE LIABLE FOR ANY DAMAGES, INCLUDING ANY LOST PROFITS, LOST SAVINGS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE, OR INABILITY TO USE, THIS SOFTWARE OR ANY ACCOMPANYING DOCUMENTATION, EVEN IF INFORMED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
%
% file: interval_est_r.m
% computes confidence interval estimates for rates.
%
% 022400 tdr created
% 031600 tdr created rate version from interval_est_p.m
% 032200 tdr added cs1, cs2, and tl methods.
% 012601 tdr added input checking.
% 012901 tdr added 1-sided CIs for CS1 method
% 031501 tdr added minimum length method
%

function ci = interval_est_r(x,A,alpha,method)

% ------------------------------------------------------------
% start checking inputs

if nargin ~= 4,
    error('Requires four input arguments (x,A,alpha,method)');
end

% inputs must all be scalars
if (max(max([size(x); size(A); size(alpha)])) ~= 1)
    error('Non-scalar input');
end;

% x must be integer
if (round(x) ~= x)
    x = round(x);
    warning('Non-integer input x');
end;

% A must be > 0
if (A <= 0),
   ci = [ NaN NaN NaN];
   warning('A <= 0');
   return;
end;

% x must be >= 0
if ( x < 0),
   ci = [ NaN NaN NaN];
   warning('x < 0');
   return;
end;

% alpha must be > 0.0 and < 1.0
if ( alpha < 0 | alpha > 1),
   ci = [ NaN NaN NaN];
   warning('alpha < 0 or alpha > 1');
   return;
end;

% normalize case
if strcmpi(method,'cs1'), method = 'cs1'; end;
if strcmpi(method,'cs1_1s'), method = 'cs1_1s'; end;
if strcmpi(method,'cs2'), method = 'cs2'; end;
if strcmpi(method,'ibp'), method = 'ibp'; end;
%if strcmpi(method,'ibp_1s'), method = 'ibp_1s'; end;
if strcmpi(method,'ml'), method = 'ml'; end;
if strcmpi(method,'nibp'), method = 'nibp'; end;
%if strcmpi(method,'nibp_1s'), method = 'nibp_1s'; end;
if strcmpi(method,'na'), method = 'na'; end;
if strcmpi(method,'tl'), method = 'tl'; end;

% end checking inputs
% ------------------------------------------------------------

switch method
case 'cs1',
   ci = get_r_ci_cs1(x,A,alpha);
case 'cs1_1s',
   ci = get_r_ci_cs1_1s(x,A,alpha);
case 'cs2',
   ci = get_r_ci_cs2(x,A,alpha);
case 'ibp',
   ci = get_r_ci_ibp(x,A,alpha);
case 'ml',
   ci = get_r_ci_ml(x,A,alpha);
case 'na',
   ci = get_r_ci_na(x,A,alpha);
case 'tl',
   ci = get_r_ci_tl(x,A,alpha);
otherwise
   error('Method not recognized. Methods Available: cs1/cs2 - COMPASE Standards, ibp - Integration of Bayes Posterior; ml - minimum length; na - Normal Approximation; tl - Table Lookup');
end;


function mcrop = matcrop_withpad(m,varargin)

subs = varargin;

ndim = length(subs);
sz = size(m);
if sz(1) == 1 && ndim == 1,
  subs = [1,subs];
  ndim = 2;
elseif length(sz) ~= ndim,
  error('size(m) does not match number of input indices');
end

mcrop = m;
for dim = 1:ndim,
  if subs{dim}(1) > subs{dim}(2),
    mcrop = eval(['mcrop(',repmat(':,',[1,dim-1]),'[]',repmat(',:',[1,ndim-dim]),');']);
    continue;
  end
  npadprev = max(0,1 - subs{dim}(1));
  npadafter = max(0,subs{dim}(2)-sz(dim));
  subs{dim}(1) = max(1,subs{dim}(1));
  subs{dim}(2) = min(sz(dim),subs{dim}(2));
  mcrop = eval(['mcrop(',repmat(':,',[1,dim-1]),sprintf('%d:%d',subs{dim}(1),subs{dim}(2)),...
    repmat(',:',[1,ndim-dim]),');']);
  if npadprev > 0,
    tmppad = size(mcrop);
    tmppad(dim) = npadprev;
    mcrop = cat(dim,zeros(tmppad),mcrop);
  end
  if npadafter > 0,
    tmppad = size(mcrop);
    tmppad(dim) = npadafter;
    mcrop = cat(dim,mcrop,zeros(tmppad));
  end
end


%
% This is a calling routine to test & check out the power spectrum &
% spectrogram routines for unequal segment lengths. In addition, use it
% to compare with Chronux routines when segments are of equal length.
%
clear all;

if 0
    dir = 'G:\ravi\Chrowser\Pass~ Tioga_0e927741-9673-46e5-9050-ca1d7541bf22\';
    xfile = 'Pass~ Tioga_0e927741-9673-46e5-9050-ca1d7541bf22'
    %dir = 'G:\ravi\Chrowser\sample~ data_8ef647e3-e5ea-43a6-8c69-fb848b8db7c2\';
    %xfile = 'sample~ data_8ef647e3-e5ea-43a6-8c69-fb848b8db7c2'
else
    dir = 'Z:\xltekRawData\Wallis~ Terry_c3f44891-afa7-4fa7-a643-55c772a05241\'
    xfile = 'Wallis~ Terry_c3f44891-afa7-4fa7-a643-55c772a05241'
end

% Get header info
% Channels are labelled from C1 through C127 and ''
% total of 128 channels
hdr = eegMex( dir, xfile);

gram = 1 ; % 0=spectra, 1=coherence
chronux = 0 ; % 0=no comparison with Chronux; 1=compare with chronux

%nSamples = 4210;
nChannels = 2;
nSegments = 1;
movingwin = [25, 25];

%
% Spectral Parameters
%
params.fpass = [ 0 0.5 ];
params.pad = 2;
params.err = [2 0.05];  % err(1)=0 is no err estimates; err(1)=1 is asymptotic estimates; err(1)=2 is Jacknife
params.trialave = 1;
params.Fs = 1;

%
% Tapers issues
%
halfBandWidth = 2.5;
kCap = 2*halfBandWidth - 1;
%params.tapers = [ halfBandWidth, kCap ];
params.tapers = [ halfBandWidth, 2 ];

%
% Basic checks on inputs
%
if (gram==1) && (nChannels < 2), error( 'Coherence requires at least 2 channels...' ); end
%if (nSegments==1) && (params.err(1)==2), error( 'Jacknife requires more than 1 segment'); end

%
% Generate segments endpoints randomly
% myrandint is a 3rd party routine (from matlab site)
%
% Randomly generated segment end points
sMarkers = reshape( sort( myrandint( 2*nSegments, 1, [ ceil(hdr.nSamples/500) : ceil(hdr.nSamples/50) ], 'noreplace' ) )', 2, nSegments )';
%sMarkers = [ ceil(hdr.nSamples/80), ceil(hdr.nSamples/65) ];

%
% Randomly select a few channels
%
if ~chronux
    %chIndices = sort( myrandint( nChannels, 1, [ round(hdr.nChans/4) : round(3*hdr.nChans/4) ], 'noreplace' ) );
    chIndices = [ 3 : 3+nChannels-1 ];
else
    %chIndices = [ 10 : 10+nChannels-1 ];
    chIndices = [ 3, 7 ];
end

%
% Randomly generate the time series
%
fulldata = eegMex( dir, xfile, chIndices, [ 1 hdr.nSamples/50 1 ] );
mDiscardBits = 0;
conversionFactor = ( 8711 / (2^21 - 0.5) ) * 2^mDiscardBits;
fulldata{:} = fulldata{:} * conversionFactor;

%
% Create a data matrix with all the segments aligned one after another
%
totalSegmentLength = sum( sMarkers(:,2) - sMarkers(:,1) + 1 );
data = zeros( totalSegmentLength, length(chIndices) ); % preallocate to ensure contiguous memory
newMarkers(1,1) = 1;
newMarkers(1,2) = sMarkers(1,2) - sMarkers(1,1) + 1;
data( newMarkers(1,1):newMarkers(1,2), : ) = detrend( fulldata{1}( sMarkers(1,1):sMarkers(1,2), :) );
for sg = 2:size( sMarkers, 1 )
    newMarkers(sg,1) = newMarkers(sg-1,2) + 1;
    newMarkers(sg,2) = newMarkers(sg,1) + sMarkers(sg,2) - sMarkers(sg,1);
    data( newMarkers(sg,1):newMarkers(sg,2), : ) = detrend( fulldata{1}( sMarkers(sg,1):sMarkers(sg,2), :) );
end

% To ensure that we check results from array indices beyond 1
if nChannels > 1
    ix = sort( myrandint( 1, 2, [1:length(chIndices)], 'noreplace' ) ); % Arbitrarily pick two indices from selected channels for testing results
    i1=ix(1); i2=ix(2);
    % iC = m + (n-1)*(n-2)/2, for elements of the the coherence matrix, Cmn
    iC = ix(1) + (ix(2)-1)*(ix(2)-2)/2;
else
    ix = sort( myrandint( 1, 1, [1:length(chIndices)], 'noreplace' ) ); % Arbitrarily pick 1 indices from selected channels for testing results
    i1=ix(1);
end

%
% Power spectrum/spectrogram/coherence/coherogram
%
if gram==0
    [ S, f, Serr ] = avgSpectrum( data, movingwin, params, newMarkers );
    figure; plot( f, 10*log10( S(:,i1) ), 'k', f, 10*log10( Serr(2,:,i1) ), 'g--', f, 10*log10( Serr(1,:,i1)), 'g--' ); title('Avg. Routine:: Spectrum');
    %figure; plot( f, 10*log10( S(:,i1) )); title('Avg. Routine:: Spectrum');
elseif gram==1
    [Cmn,Phimn,Smn,Smm,f,ConfC,PhiStd,Cerr] = avgCoherence( data, movingwin, params, newMarkers );
    %  C(i,j) = Cmn(:,k) where k = j + (1/2)*(i-1)*(i-2)
    figure; plot( f, Cmn(:,iC), 'k', f, Cerr(2,:,iC), 'g--', f, Cerr(1,:,iC), 'g--' );
    title('Avg. Routine:: Coherence'); ylim([0 1])
    %figure; plot( f, 10*log10( Cmn(:,iC) ) ); title('Avg. Routine:: Coherence-Magnitude');
    %figure; plot( f, phimn(:,iC) ); title('Avg. Routine:: Coherence-Phase');
    disp( ['Confidence level for C (confC) at (1-p) level: ' num2str( ConfC(iC)) ] );
end

%
% Use to check against Chronux: only for equal length segments
%
if chronux

    win = floor( newMarkers(1,2) / movingwin(1) );
    newMarkers(1,2) = newMarkers(1,2) - mod( newMarkers(1,2), win );
    cdata = data( [1:newMarkers(1,2)], i1 );
    cdata = detrend( reshape( cdata, [ newMarkers(1,2)/win, win ] ) );
    cdata2 = data( [1:newMarkers(1,2)], i2 );
    cdata2 = detrend( reshape( cdata2, [ newMarkers(1,2)/win, win ] ) );
    params.trialave = 1;
    if gram==0
        [ cS, cf, cSerr ] = mtspectrumc( cdata, params );
        figure; plotvector( cS, cf, 'l', cSerr );
        %figure; plot( cf, 10*log10( cS )); title('Chronux:: Spectrum');
        figure; plot( cf, 10*log10(cSerr(1,:)), cf, 10*log10(cSerr(2,:)) ); title('Chronux Error-Bar Computations');
        figure; plot( cf, 10*log10( cS ) - 10*log10( S(:,i1) )); title('Error in Spectrum = |New Routines - Chronux|');
        figure; plot( cf, 10*log10(cSerr(1,:)) - 10*log10(Serr(1,:,i1)), cf, 10*log10(cSerr(2,:)) - 10*log10(Serr(2,:,i1)) );title('Error in Error-Bar Computations = |New Routines - Chronux| ');
    elseif gram==1

        [cC,cphi,cS12,cS1,cS2,cf,cconfC,cphistd,cCerr]=coherencyc( cdata, cdata2, params );

        %figure; plotvector( cC(:,1), cf, 'n', cCerr );
        figure; plot( cf, cC(:,iC), 'k', cf, cCerr(2,:,iC), 'g--', cf, cCerr(1,:,iC), 'g--' );
        title('Chronux:: Coherence'); ylim([0 1])
        %figure; plot( cf, 10*log10( cC(:,1) ) ); title('Chronux:: Coherence-Magnitude');
        figure; plot( cf, 10*log10( cC(:,1) ) - 10*log10( Cmn(:,iC) ) ); title('Error in Coherence = |New Routines - Chronux|');
        % Phase may give a problem of 2pi difference... look into it.
        figure; plot( cf, cphi(:,1) -  Phimn(:,iC) ); title('Error in Phase = |New Routines - Chronux|');
        %
        % Note the remaining quantities do not really need to checked since
        % coherence = cross-spectrum/power spectra* power spectra, ie C = S12/(S1*S2)
        % so unlikely that S12, S1, S2 are incorrect if C is correct.
        if 1
            figure; plot( cf, 10*log10( cS1(:,1) ) - 10*log10( Smm(:,ix(1)) ) ); title('Error in Power Spectrogram-1 = |New Routines - Chronux|');
            figure; plot( cf, 10*log10( cS2(:,1) ) - 10*log10( Smm(:,ix(2)) ) ); title('Error in Power Spectrogram-2 = |New Routines - Chronux|');
        end
        %
        % Error-Bars & Confidence Levels
        disp( ['Confidence levelfor C (confC) at (1-p) level: ' num2str( cconfC) ' (Chronux)' ] );
        disp( ['Error in confidence level, confC: ' num2str( ConfC(iC) - cconfC ) ] );
        %figure; plot( cf, cphistd(:,1), f, phistd(:,iC) ); title('Phase-Error-Bar Computations');
        figure; plot( cf, cphistd(:,1) -  PhiStd(:,iC) ); title('Error in PhiStd-1');
        figure; plot( cf, cphistd(:,1) -  PhiStd(:,iC) ); title('Error in PhiStd-2');
        figure; plot( cf, abs(cCerr(1,:,1) -  Cerr(1,:,iC)), cf, abs(cCerr(2,:,1) -  Cerr(2,:,iC))  ); title('Error in Abs(Coherence)-Error-Bar Computations = |New Routines - Chronux|');
    end
end


function net = resnet52_new_hope()

%----------------------img cnn----------------------
netStruct = load('./data/imagenet-resnet-50-dag.mat') ;
net = dagnn.DagNN.loadobj(netStruct) ;
net.removeLayer('fc1000');
net.removeLayer('prob');

for i = 1:numel(net.params)
    if(mod(i,2)==0)
        net.params(i).learningRate= 0; %0.02;
    else net.params(i).learningRate= 0; %0.001;
    end
    net.params(i).weightDecay=0; %1;
end

net.params(1).learningRate = 0; %1e-5;

fc1Block = dagnn.Conv('size',[1 1 2048 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc1',fc1Block,{'pool5'},{'fc1'},{'fc1f'});
net.addLayer('fc1bn',dagnn.BatchNorm(),{'fc1'},{'fc1bn'},...
    {'fc1bn_w','fc1bn_b','fc1bn_m'});
net.addLayer('fc1x',dagnn.ReLU(),{'fc1bn'},{'fc1bnx'});
fc1Block = dagnn.Conv('size',[1 1 2048 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc1_1',fc1Block,{'fc1bnx'},{'fc1_1'},{'fc1_1f'});
net.addLayer('fc1_1bn',dagnn.BatchNorm(),{'fc1_1'},{'fc1_1bn'},...
    {'fc1_1bn_w','fc1_1bn_b','fc1_1bn_m'});
net.addLayer('fc1_1x',dagnn.ReLU(),{'fc1_1bn'},{'fc1_1bnx'});
net.addLayer('dropout',dagnn.DropOut('rate',0.5),{'fc1_1bnx'},{'fc1_1bnxd'});

%----------------------char cnn----------------------
% input is 1*32*20074*16
fc2Block = dagnn.Conv('size',[1 1 29972 300],'hasBias',true,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc2',fc2Block,{'data2'},{'fc2'},{'fc2f','fc2b'});
net.addLayer('fc2bn',dagnn.BatchNorm(),{'fc2'},{'fc2bn'},...
    {'fc2bn_w','fc2bn_b','fc2bn_m'});
%net.addLayer('fc2x',dagnn.ReLU(),{'fc2bn'},{'fc2bnx'});
%net.addLayer('dropout_diction',dagnn.DropOut('rate',0.5),{'fc2bn'},{'fc2bnd'});
% 32*256
convBlock = dagnn.Conv('size',[1 1 300 128],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc2_1_1',convBlock,{'fc2bn'},{'fc2_1_1'},{'fc2_1_1f'});
net.addLayer('fc2_1_1bn',dagnn.BatchNorm(),{'fc2_1_1'},{'fc2_1_1bn'},...
    {'fc2_1_1bn_w','fc2_1_1bn_b','fc2_1_1bn_m'});
net.addLayer('fc2_1_1x',dagnn.ReLU(),{'fc2_1_1bn'},{'fc2_1_1bnx'});

convBlock = dagnn.Conv('size',[1 2 128 128],'hasBias',false,'stride',[1,1],'pad',[0,0,1,0]);
net.addLayer('fc2_1_2',convBlock,{'fc2_1_1bnx'},{'fc2_1_2'},{'fc2_1_2f'});
net.addLayer('fc2_1_2bn',dagnn.BatchNorm(),{'fc2_1_2'},{'fc2_1_2bn'},...
    {'fc2_1_2bn_w','fc2_1_2bn_b','fc2_1_2bn_m'});
net.addLayer('fc2_1_2x',dagnn.ReLU(),{'fc2_1_2bn'},{'fc2_1_2bnx'});

convBlock = dagnn.Conv('size',[1 1 128 256],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc2_1_3',convBlock,{'fc2_1_2bnx'},{'fc2_1_3'},{'fc2_1_3f'});
net.addLayer('fc2_1_3bn',dagnn.BatchNorm(),{'fc2_1_3'},{'fc2_1_3bn'},...
    {'fc2_1_3bn_w','fc2_1_3bn_b','fc2_1_3bn_m'});

convBlock = dagnn.Conv('size',[1 1 300 256],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc2_1b',convBlock,{'fc2bn'},{'fc2_1b'},{'fc2_1bf'});
net.addLayer('fc2_1bbn',dagnn.BatchNorm(),{'fc2_1b'},{'fc2_1bbn'},...
    {'fc2_1bbn_w','fc2_1bbn_b','fc2_1bbn_m'});

net.addLayer('fc2_1sum',dagnn.Sum(),{'fc2_1_3bn','fc2_1bbn'},...
    {'fc2_1sum'});
net.addLayer('fc2_1x',dagnn.ReLU(),{'fc2_1sum'},{'fc2_1sumx'});

% 32*256
for i  = 2:3
    convBlock = dagnn.Conv('size',[1 1 256 64],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
    net.addLayer( sprintf('fc2_%d_1',i),convBlock,{sprintf('fc2_%dsumx',i-1)},{sprintf('fc2_%d_1',i)}, ...
        {sprintf('fc2_%d_1f',i)});
    net.addLayer(sprintf('fc2_%d_1bn_1',i),dagnn.BatchNorm(),{sprintf('fc2_%d_1',i)},{sprintf('fc2_%d_1bn',i)},...
        {sprintf('fc2_%d_1bn_w',i),sprintf('fc2_%d_1bn_b',i),sprintf('fc2_%d_1bn_m',i)});
    net.addLayer(sprintf('fc2_%d_1x',i),dagnn.ReLU(),{sprintf('fc2_%d_1bn',i)},{sprintf('fc2_%d_1bnx',i)});

    convBlock = dagnn.Conv('size',[1 2 64 64],'hasBias',false,'stride',[1,1],'pad',[0,0,1,0]);
    net.addLayer( sprintf('fc2_%d_2',i),convBlock,{sprintf('fc2_%d_1bnx',i)},{sprintf('fc2_%d_2',i)}, ...
        {sprintf('fc2_%d_2f',i)});
    net.addLayer(sprintf('fc2_%d_2bn',i),dagnn.BatchNorm(),{sprintf('fc2_%d_2',i)},{sprintf('fc2_%d_2bn',i)},...
        {sprintf('fc2_%d_2bn_w',i),sprintf('fc2_%d_2bn_b',i),sprintf('fc2_%d_2bn_m',i)});
    net.addLayer(sprintf('fc2_%d_2x',i),dagnn.ReLU(),{sprintf('fc2_%d_2bn',i)},{sprintf('fc2_%d_2bnx',i)});

    convBlock = dagnn.Conv('size',[1 1 64 256],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
    net.addLayer( sprintf('fc2_%d_3',i),convBlock,{sprintf('fc2_%d_2bnx',i)},{sprintf('fc2_%d_3',i)}, ...
        {sprintf('fc2_%d_3f',i)});
    net.addLayer(sprintf('fc2_%d_3bn',i),dagnn.BatchNorm(),{sprintf('fc2_%d_3',i)},{sprintf('fc2_%d_3bn',i)},...
        {sprintf('fc2_%d_3bn_w',i),sprintf('fc2_%d_3bn_b',i),sprintf('fc2_%d_3bn_m',i)});

    net.addLayer(sprintf('fc2_%dsum',i),dagnn.Sum(),{sprintf('fc2_%dsumx',i-1),sprintf('fc2_%d_3bn',i)},...
        {sprintf('fc2_%dsum',i)});
    net.addLayer(sprintf('fc2_%dx',i),dagnn.ReLU(),{sprintf('fc2_%dsum',i)},{sprintf('fc2_%dsumx',i)});
end

%32*256
convBlock = dagnn.Conv('size',[1 1 256 512],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc2_4a_1',convBlock,{'fc2_3sumx'},{'fc2_4a_1'},{'fc2_4a_1f'});
net.addLayer('fc2_4a_1bn',dagnn.BatchNorm(),{'fc2_4a_1'},{'fc2_4a_1bn'},...
    {'fc2_4a_1bn_w','fc2_4a_1bn_b','fc2_4a_1bn_m'});
net.addLayer('fc2_4a_1x',dagnn.ReLU(),{'fc2_4a_1bn'},{'fc2_4a_1bnx'});

convBlock = dagnn.Conv('size',[1 2 512 512],'hasBias',false,'stride',[2,2],'pad',[0,0,1,0]);
net.addLayer('fc2_4a_2',convBlock,{'fc2_4a_1bnx'},{'fc2_4a_2'},{'fc2_4a_2f'});
net.addLayer('fc2_4a_2bn',dagnn.BatchNorm(),{'fc2_4a_2'},{'fc2_4a_2bn'},...
    {'fc2_4a_2bn_w','fc2_4a_2bn_b','fc2_4a_2bn_m'});
net.addLayer('fc2_4a_2x',dagnn.ReLU(),{'fc2_4a_2bn'},{'fc2_4a_2bnx'});

convBlock = dagnn.Conv('size',[1 1 512 512],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc2_4a_3',convBlock,{'fc2_4a_2bnx'},{'fc2_4a_3'},{'fc2_4a_3f'});
net.addLayer('fc2_4a_3bn',dagnn.BatchNorm(),{'fc2_4a_3'},{'fc2_4a_3bn'},...
    {'fc2_4a_3bn_w','fc2_4a_3bn_b','fc2_4a_3bn_m'});

convBlock = dagnn.Conv('size',[1 1 256 512],'hasBias',false,'stride',[2,2],'pad',[0,0,0,0]);
net.addLayer('fc2_4b',convBlock,{'fc2_3sumx'},{'fc2_4b'},{'fc2_4bf'});
net.addLayer('fc2_4bbn',dagnn.BatchNorm(),{'fc2_4b'},{'fc2_4bbn'},...
    {'fc2_4bbn_w','fc2_4bbn_b','fc2_4bbn_m'});

%16*512
net.addLayer('fc2_4sum',dagnn.Sum(),{'fc2_4a_3bn','fc2_4bbn'},...
    {'fc2_4sum'});
net.addLayer('fc2_4x',dagnn.ReLU(),{'fc2_4sum'},{'fc3_1sumx'});

for i  = 2:4
    convBlock = dagnn.Conv('size',[1 1 512 128],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
    net.addLayer( sprintf('fc3_%d_1',i),convBlock,{sprintf('fc3_%dsumx',i-1)},{sprintf('fc3_%d_1',i)}, ...
        {sprintf('fc3_%d_1f',i)});
    net.addLayer(sprintf('fc3_%d_1bn_1',i),dagnn.BatchNorm(),{sprintf('fc3_%d_1',i)},{sprintf('fc3_%d_1bn',i)},...
        {sprintf('fc3_%d_1bn_w',i),sprintf('fc3_%d_1bn_b',i),sprintf('fc3_%d_1bn_m',i)});
    net.addLayer(sprintf('fc3_%d_1x',i),dagnn.ReLU(),{sprintf('fc3_%d_1bn',i)},{sprintf('fc3_%d_1bnx',i)});

    convBlock = dagnn.Conv('size',[1 2 128 128],'hasBias',false,'stride',[1,1],'pad',[0,0,1,0]);
    net.addLayer( sprintf('fc3_%d_2',i),convBlock,{sprintf('fc3_%d_1bnx',i)},{sprintf('fc3_%d_2',i)}, ...
        {sprintf('fc3_%d_2f',i)});
    net.addLayer(sprintf('fc3_%d_2bn',i),dagnn.BatchNorm(),{sprintf('fc3_%d_2',i)},{sprintf('fc3_%d_2bn',i)},...
        {sprintf('fc3_%d_2bn_w',i),sprintf('fc3_%d_2bn_b',i),sprintf('fc3_%d_2bn_m',i)});
    net.addLayer(sprintf('fc3_%d_2x',i),dagnn.ReLU(),{sprintf('fc3_%d_2bn',i)},{sprintf('fc3_%d_2bnx',i)});

    convBlock = dagnn.Conv('size',[1 1 128 512],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
    net.addLayer( sprintf('fc3_%d_3',i),convBlock,{sprintf('fc3_%d_2bnx',i)},{sprintf('fc3_%d_3',i)}, ...
        {sprintf('fc3_%d_3f',i)});
    net.addLayer(sprintf('fc3_%d_3bn',i),dagnn.BatchNorm(),{sprintf('fc3_%d_3',i)},{sprintf('fc3_%d_3bn',i)},...
        {sprintf('fc3_%d_3bn_w',i),sprintf('fc3_%d_3bn_b',i),sprintf('fc3_%d_3bn_m',i)});

    net.addLayer(sprintf('fc3_%dsum',i),dagnn.Sum(),{sprintf('fc3_%dsumx',i-1),sprintf('fc3_%d_3bn',i)},...
        {sprintf('fc3_%dsum',i)});
    net.addLayer(sprintf('fc3_%dx',i),dagnn.ReLU(),{sprintf('fc3_%dsum',i)},{sprintf('fc3_%dsumx',i)});
end

convBlock = dagnn.Conv('size',[1 1 512 1024],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc3_5a_1',convBlock,{'fc3_4sumx'},{'fc3_5a_1'},{'fc3_5a_1f'});
net.addLayer('fc3_5a_1bn',dagnn.BatchNorm(),{'fc3_5a_1'},{'fc3_5a_1bn'},...
    {'fc3_5a_1bn_w','fc3_5a_1bn_b','fc3_5a_1bn_m'});
net.addLayer('fc3_5a_1x',dagnn.ReLU(),{'fc3_5a_1bn'},{'fc3_5a_1bnx'});

convBlock = dagnn.Conv('size',[1 2 1024 1024],'hasBias',false,'stride',[2,2],'pad',[0,0,1,0]);
net.addLayer('fc3_5a_2',convBlock,{'fc3_5a_1bnx'},{'fc3_5a_2'},{'fc3_5a_2f'});
net.addLayer('fc3_5a_2bn',dagnn.BatchNorm(),{'fc3_5a_2'},{'fc3_5a_2bn'},...
    {'fc3_5a_2bn_w','fc3_5a_2bn_b','fc3_5a_2bn_m'});
net.addLayer('fc3_5a_2x',dagnn.ReLU(),{'fc3_5a_2bn'},{'fc3_5a_2bnx'});

convBlock = dagnn.Conv('size',[1 1 1024 1024],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc3_5a_3',convBlock,{'fc3_5a_2bnx'},{'fc3_5a_3'},{'fc3_5a_3f'});
net.addLayer('fc3_5a_3bn',dagnn.BatchNorm(),{'fc3_5a_3'},{'fc3_5a_3bn'},...
    {'fc3_5a_3bn_w','fc3_5a_3bn_b','fc3_5a_3bn_m'});

convBlock = dagnn.Conv('size',[1 1 512 1024],'hasBias',false,'stride',[2,2],'pad',[0,0,0,0]);
net.addLayer('fc3_5b',convBlock,{'fc3_4sumx'},{'fc3_5b'},{'fc3_5bf'});
net.addLayer('fc3_5bbn',dagnn.BatchNorm(),{'fc3_5b'},{'fc3_5bbn'},...
    {'fc3_5bbn_w','fc3_5bbn_b','fc3_5bbn_m'});

%8*1024
net.addLayer('fc3_5sum',dagnn.Sum(),{'fc3_5a_3bn','fc3_5bbn'},...
    {'fc3_5sum'});
net.addLayer('fc3_5x',dagnn.ReLU(),{'fc3_5sum'},{'fc4_1sumx'});

for i  = 2:6
    convBlock = dagnn.Conv('size',[1 1 1024 256],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
    net.addLayer( sprintf('fc4_%d_1',i),convBlock,{sprintf('fc4_%dsumx',i-1)},{sprintf('fc4_%d_1',i)}, ...
        {sprintf('fc4_%d_1f',i)});
    net.addLayer(sprintf('fc4_%d_1bn_1',i),dagnn.BatchNorm(),{sprintf('fc4_%d_1',i)},{sprintf('fc4_%d_1bn',i)},...
        {sprintf('fc4_%d_1bn_w',i),sprintf('fc4_%d_1bn_b',i),sprintf('fc4_%d_1bn_m',i)});
    net.addLayer(sprintf('fc4_%d_1x',i),dagnn.ReLU(),{sprintf('fc4_%d_1bn',i)},{sprintf('fc4_%d_1bnx',i)});

    convBlock = dagnn.Conv('size',[1 2 256 256],'hasBias',false,'stride',[1,1],'pad',[0,0,1,0]);
    net.addLayer( sprintf('fc4_%d_2',i),convBlock,{sprintf('fc4_%d_1bnx',i)},{sprintf('fc4_%d_2',i)}, ...
        {sprintf('fc4_%d_2f',i)});
    net.addLayer(sprintf('fc4_%d_2bn',i),dagnn.BatchNorm(),{sprintf('fc4_%d_2',i)},{sprintf('fc4_%d_2bn',i)},...
        {sprintf('fc4_%d_2bn_w',i),sprintf('fc4_%d_2bn_b',i),sprintf('fc4_%d_2bn_m',i)});
    net.addLayer(sprintf('fc4_%d_2x',i),dagnn.ReLU(),{sprintf('fc4_%d_2bn',i)},{sprintf('fc4_%d_2bnx',i)});

    convBlock = dagnn.Conv('size',[1 1 256 1024],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
    net.addLayer( sprintf('fc4_%d_3',i),convBlock,{sprintf('fc4_%d_2bnx',i)},{sprintf('fc4_%d_3',i)}, ...
        {sprintf('fc4_%d_3f',i)});
    net.addLayer(sprintf('fc4_%d_3bn',i),dagnn.BatchNorm(),{sprintf('fc4_%d_3',i)},{sprintf('fc4_%d_3bn',i)},...
        {sprintf('fc4_%d_3bn_w',i),sprintf('fc4_%d_3bn_b',i),sprintf('fc4_%d_3bn_m',i)});

    net.addLayer(sprintf('fc4_%dsum',i),dagnn.Sum(),{sprintf('fc4_%dsumx',i-1),sprintf('fc4_%d_3bn',i)},...
        {sprintf('fc4_%dsum',i)});
    net.addLayer(sprintf('fc4_%dx',i),dagnn.ReLU(),{sprintf('fc4_%dsum',i)},{sprintf('fc4_%dsumx',i)});
end

convBlock = dagnn.Conv('size',[1 1 1024 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc4_7a_1',convBlock,{'fc4_6sumx'},{'fc4_7a_1'},{'fc4_7a_1f'});
net.addLayer('fc4_7a_1bn',dagnn.BatchNorm(),{'fc4_7a_1'},{'fc4_7a_1bn'},...
    {'fc4_7a_1bn_w','fc4_7a_1bn_b','fc4_7a_1bn_m'});
net.addLayer('fc4_7a_1x',dagnn.ReLU(),{'fc4_7a_1bn'},{'fc4_7a_1bnx'});

convBlock = dagnn.Conv('size',[1 2 2048 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,1,0]);
net.addLayer('fc4_7a_2',convBlock,{'fc4_7a_1bnx'},{'fc4_7a_2'},{'fc4_7a_2f'});
net.addLayer('fc4_7a_2bn',dagnn.BatchNorm(),{'fc4_7a_2'},{'fc4_7a_2bn'},...
    {'fc4_7a_2bn_w','fc4_7a_2bn_b','fc4_7a_2bn_m'});
net.addLayer('fc4_7a_2x',dagnn.ReLU(),{'fc4_7a_2bn'},{'fc4_7a_2bnx'});

convBlock = dagnn.Conv('size',[1 1 2048 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc4_7a_3',convBlock,{'fc4_7a_2bnx'},{'fc4_7a_3'},{'fc4_7a_3f'});
net.addLayer('fc4_7a_3bn',dagnn.BatchNorm(),{'fc4_7a_3'},{'fc4_7a_3bn'},...
    {'fc4_7a_3bn_w','fc4_7a_3bn_b','fc4_7a_3bn_m'});

convBlock = dagnn.Conv('size',[1 1 1024 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc4_7b',convBlock,{'fc4_6sumx'},{'fc4_7b'},{'fc4_7bf'});
net.addLayer('fc4_7bbn',dagnn.BatchNorm(),{'fc4_7b'},{'fc4_7bbn'},...
    {'fc4_7bbn_w','fc4_7bbn_b','fc4_7bbn_m'});

%8*2048
net.addLayer('fc4_7sum',dagnn.Sum(),{'fc4_7a_3bn','fc4_7bbn'},...
    {'fc4_7sum'});
net.addLayer('fc4_7x',dagnn.ReLU(),{'fc4_7sum'},{'fc5_1sumx'});

poolBlock = dagnn.Pooling('poolSize',[1 8]);
net.addLayer('fc5_1',poolBlock,{'fc5_1sumx'},{'fc5_1bnx'});
%net.addLayer('fc5_1bn',dagnn.BatchNorm(),{'fc5_1'},{'fc5_1bn'},...
 %   {'fc5_1bn_w','fc5_1bn_b','fc5_1bn_m'});
%net.addLayer('fc5_1x',dagnn.ReLU(),{'fc5_1bn'},{'fc5_1bnx'});

fc5_2Block = dagnn.Conv('size',[1 1 2048 2048],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc5_2',fc5_2Block,{'fc5_1bnx'},{'fc5_2'},{'fc5_2f'});
net.addLayer('fc5_2bn',dagnn.BatchNorm(),{'fc5_2'},{'fc5_2bn'},...
    {'fc5_2bn_w','fc5_2bn_b','fc5_2bn_m'});
net.addLayer('fc5_2x',dagnn.ReLU(),{'fc5_2bn'},{'fc5_2bnx'});
net.addLayer('dropout2',dagnn.DropOut('rate',0.5),{'fc5_2bnx'},{'fc5_2bnxd'});

%----------------------add share layer----------------------
%1

fc_imgBlock = dagnn.Conv('size',[1 1 2048 113287],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc_img',fc_imgBlock,{'fc1_1bnxd'},{'prediction_img'},{'fcsharef'});
net.addLayer('softmaxloss_img',dagnn.Loss('loss','softmaxlog'),{'prediction_img','label_img'},'objective_img');
net.addLayer('top1err_img', dagnn.Loss('loss', 'classerror'), ...
    {'prediction_img','label_img'}, 'top1err_img') ;
net.addLayer('top5err_img', dagnn.Loss('loss', 'topkerror', ...
    'opts', {'topK',5}), ...
    {'prediction_img','label_img'}, 'top5err_img') ;
%2
fc_txtBlock = dagnn.Conv('size',[1 1 2048 113287],'hasBias',false,'stride',[1,1],'pad',[0,0,0,0]);
net.addLayer('fc_txt',fc_txtBlock,{'fc5_2bnxd'},{'prediction_txt'},{'fcsharef'});
net.addLayer('softmaxloss_txt',dagnn.Loss('loss','softmaxlog'),{'prediction_txt','label_txt'},'objective_txt');
net.addLayer('top1err_txt', dagnn.Loss('loss', 'classerror'), ...
    {'prediction_txt','label_txt'}, 'top1err_txt') ;
net.addLayer('top5err_txt', dagnn.Loss('loss', 'topkerror', ...
    'opts', {'topK',5}), ...
    {'prediction_txt','label_txt'}, 'top5err_txt') ;
%}

%}
net.initParams();
%----------NOTICE--------------
first = net.getParamIndex('fc2f');

net.params(first).learningRate = 1e-3;  %w
net.params(first+1).learningRate = 1e-3;  %b

load('./dataset/MSCOCO-prepare/COCO_dictionary.mat');
net.params(first).value = reshape(single(subset.features'),1,1,29972,300);

end


function [conf, tx] = useBoundaryClassifier(bndinfo, X, classifier, featureset)
% [conf, tx] = useBoundaryClassifier(bndinfo, X, classifier, featureset)

tx = double(getBoundaryClassifierFeatures(bndinfo, X, (1:bndinfo.ne)));

if exist('featureset', 'var') && ~isempty(featureset)
    tx = getPartialFeatures(tx, [], featureset);
end

conf = test_boosted_dt_mc(classifier, tx);
conf = 1 ./ (1+exp(-conf));
conf = conf ./ repmat(sum(conf, 2), [1 size(conf, 2)]);


function keypointsAll = scoremaps2keypoints(expidx, image_set)

p = exp_params(expidx);

pad_orig = p.([image_set 'Pad']);
stride = p.stride;
inv_scale_factor = 1/p.scale_factor;
locref = p.locref;
scale_mul = sqrt(53);

pidxs = p.pidxs;
[~,parts] = util_get_parts24();

load(p.testGT,'annolist');

keypointsAll = [];

min_det_score = 1e-03;

save_dir = fullfile(p.exp_dir, image_set);

for imgidx = 1:length(annolist)
    fprintf('imgidx: %d/%d\n', imgidx, length(annolist));
    im_fn = annolist(imgidx).image.name;
    [~,im_name,~] = fileparts(im_fn);
    load(fullfile(p.unary_scoremap_dir, im_name), 'scoremaps');
    if locref
        load(fullfile(p.unary_scoremap_dir, [im_name '_locreg']), 'locreg_pred');
    end

    size2d = size(scoremaps(:,:,1));
    num_proposals = size(scoremaps, 1) * size(scoremaps, 2);
    num_channels = size(scoremaps, 3);
    unPosAll = zeros(num_proposals, 2);
    unProbAll = zeros(num_proposals, num_channels);
    if locref
        locationRefine = zeros(num_proposals, num_channels, 2);
    end

    for k = 1:num_proposals
        idx = k;
        [row, col] = ind2sub(size2d, idx);
        % transform heatmap to image coordinates
        im_y = (row-1)*stride;
        im_x = (col-1)*stride;
        unPosAll(k, :) = [pad_orig, pad_orig] + [im_x, im_y]*inv_scale_factor;
        unProbAll(k,:) = scoremaps(row,col,:);
        if locref
            locationRefine(k, :, :) = squeeze(locreg_pred(row, col, :, :))*scale_mul*inv_scale_factor;
        end
    end

    for i = 1:length(pidxs)
        pidx = pidxs(i);
        % part is a joint
        assert(parts(pidx+1).pos(1) == parts(pidx+1).pos(2));
        jidx = parts(pidx+1).pos(1);

        unPos = unPosAll;
        if locref
            unPos = unPos + squeeze(locationRefine(:,i,:));
        end
        unProb = unProbAll(:,i);

        I = unProb >= min_det_score;
        unProb = unProb(I,:);
        unPos = unPos(I,:);
        [unProb,I] = sort(unProb, 'descend');
        unPos = unPos(I,:);

        keypointsAll(imgidx).det{jidx+1} = [unPos unProb];
    end
end

mkdir_if_missing(save_dir);
save(fullfile(save_dir, 'keypointsAll'), 'keypointsAll');


solinit=bvpinit(linspace(-1,1,20),@dropinit);
sol=bvp4c(@drop,@dropbc,solinit);
fill(sol.x,sol.y(1,:),[0.7,0.7,0.7])
axis([-1,1,0,1])
xlabel('x','FontSize',12)
ylabel('h','Rotation',0,'FontSize',12)


%% This is for testing the SerialLink models in the robotics Toolboxg
function tests = SerialLinkModelsTest
  tests = functiontests(localfunctions);
end

function models_test(tc)
    models

    names = models();
    verifyTrue(tc, iscell(names) );

    models('6dof')

    names = models('6dof');
    verifyTrue(tc, iscell(names) );
end

function all_models_test(tc)

    all = models();

    for model = all'
        try
            eval( [model{1} ';'] );
        catch
            verifyFail(tc, sprintf('model %s failed to load', model{1}) );
        end

        % find all the SerialLink objects
        vars = whos;
        k = find( cellfun(@(s) strcmp(s,'SerialLink'), {vars.class}) );
        if isempty(k)
            verifyFail(tc, sprintf('no SerialLink models loaded by %s', model{1}) );
        end

        for kk = k
            clear(vars(kk).name)
        end

%         if exist('qz', 'var') ~= 1
%             verifyFail(tc, sprintf('model %s doesn''t set qz', model{1}));
%         end
        clear qz
    end
end

function query_test(tc)
    names = models('6dof');
    for model = names'
        % attempt to load the model
        try
            eval( [model{1} ';'] );
        catch
            verifyFail(tc, 'model %s failed', model{1});
        end

        % find the number of DOF in the model
        vars = whos;

        k = find( cellfun(@(s) strcmp(s,'SerialLink'), {vars.class}) );

        if ~isempty(k)
            if eval( [vars(k).name '.n'] ) ~= 6
                verifyFail(tc, 'query failed');
            end
        end

        clear(vars(k).name)

    end
end


function adjList = meshFaceAdjacency(vertices, edges, faces)
%MESHFACEADJACENCY Compute adjacency list of face around each face.
%
%
%   Example
%     % Create a sample 3D mesh
%     [v, e, f] = createDodecahedron;
%     adjList = meshFaceAdjacency(v, e, f);
%     figure; hold on; axis equal; view([100 40]);
%     drawMesh(v, f);
%     % draw sample face in a different color
%     drawMesh(v, f(1, :), 'faceColor', 'b');
%     % draw the neighbors of a sample face
%     drawMesh(v, f(adjList{1}, :), 'faceColor', 'g')
%
%

% ------
% Author: David Legland
% E-mail: david.legland@grignon.inra.fr
% Created: 2010-10-04, using Matlab 7.9.0.529 (R2009b)
% Copyright 2010-2022 INRA - Cepia Software Platform

edgeFaceList = meshEdgeFaces(vertices, edges, faces);

% allocate memory for adjacency list
nFaces = max(edgeFaceList(:));
adjList = cell(1, nFaces);

% iterate over edges to populate adjacency list
for iEdge = 1:size(edgeFaceList)
    f1 = edgeFaceList(iEdge, 1);
    f2 = edgeFaceList(iEdge, 2);
    adjList{f1} = [adjList{f1} f2];
    adjList{f2} = [adjList{f2} f1];
end


function [xh,pf, P, L] = RBPF(x_true, y, LRS, u, a, pf, Nsamples, resampling_strategy)

    % x_true: true position of robot
    % y: True laser scan
    % LRS: laser scan inforamtion
    % u: Movement control
    % a: Odometry parameters found via Motion_Model_Velocity_Test
    % pf: pf class with all particle filter information
    % Nsamples: number of samples for the Particle Filter
    % resampling_startegy: DO NOT CHANGE

    %% Variable Initialization

    k = pf.k;
    NPC = pf.NPC;
    q_past = pf.q(:,k-1);
    x_past= pf.particles(:,:,k-1);

    % Initialise  new variables
    x_initial_estimate=zeros(3, NPC);           % Initial estimate from previous Xt-1 and Ut
    yh=zeros(2, 361, NPC);                      % Laser scan estimate from x_initial_estimate
    x_new_sm=zeros(3, NPC);                     % New position after scan matching (ICP)
    x_sampled=zeros(3,Nsamples, NPC);           % Smaple position around every particle position
    p_xt=zeros(Nsamples, NPC);                  % Density function for odometry (Motion_Model_velocity)
    p_zt=zeros(Nsamples, NPC);                  % Density function for scans (Scan Matching)
    tau_xt=zeros(Nsamples, NPC);                % Optimal Proposal Distribution
    n=zeros(1,NPC);                             % Sample normalizer
    mu=zeros(3, NPC);                           % Mean for Gaussian distribution from all particle samples
    cov=zeros(1, NPC);                          % Covariance for Gaussian distribution from all particle samples
    q=zeros(size(q_past));                      % Particle weights
    x_final=zeros(3, NPC);                      % final estimate particle position after RBPF

    %% RBPF for every particle
    for i = 1:NPC

        %Estimate particle position from x_(t-1) after Ut
        x_initial_estimate(:,i) = Kinematics(x_past(:,i),u+sqrt(pf.R1)*randn(length(u),1));

        if  x_initial_estimate(3,i)>2*pi
            x_initial_estimate(3,i)=x_initial_estimate(3,i)-2*pi;
        elseif x_initial_estimate(3,i)<-2*pi
            x_initial_estimate(3,i)=x_initial_estimate(3,i)+2*pi;
        end

        %Scan Matcher returns estimate of laser given an initial particle position estimate
        yh(:,:,i) = Measurement_Estimate_From_Grid(x_initial_estimate(:,i),pf.P(:,:, i),LRS.Resolution,LRS.FoV, LRS.MaxDistance, pf.UsableArea);

        % Scan pre-processing prior to ICP algortithm
            y_help=y;
            yh_help=yh(:,:,i);

            % Use data inside Usable Area only
            y_help(y_help>pf.UsableArea)=nan;
            yh_help(yh_help>pf.UsableArea)=nan;

            % Chose data that whose angle is usable in both scans
            find_y_help=isnan(y_help(2,:));
            find_yh_help=isnan(yh_help(2,:));
            del_cols=or(find_y_help, find_yh_help);
            y_help(:,(del_cols(1,:)==1))=[];
            yh_help(:,(del_cols(1,:)==1))=[];

            % Transform to Polar coordinates and World frame
            y_help=Polar2Cart(y_help);
            yh_help=Polar2Cart(yh_help);
            y_help=Rotate_Data(y_help, x_true);
            yh_help=Robot2World([x_initial_estimate(1,i); x_initial_estimate(2,i); x_initial_estimate(3,i)], yh_help);

            % Add the particles position so that its also transformed
            y_help=horzcat(y_help, x_true(1:2));
            yh_help=horzcat(yh_help, x_initial_estimate(1:2,i));

        failure=false;                               % Initialse ICP failure to FALSE

        try
        [TR,TT, data] = ICP(y_help, yh_help);        % ICP algortithm returns the translational and rotational matrices and the resulting data
        catch
            failure=true;
        end
        % Check if ICP failed
        if abs(TT(1))>50  || abs(TT(2))>50
            failure=true;
        end

        if failure
            disp('ICP failed')
            x_final(:,i)=x_initial_estimate(:,i);    % If ICP failed used last known position estimate
            q(i)=q_past(i);                          % do not change particle weights
        else

            theta_new_sm=x_initial_estimate(3,i)+asin(TR(2,1));     % Modify theta angle according to the rotation given by ICP
            x_new_sm(:,i)=[data(1:2,end); theta_new_sm];            % Use rotated+translated initila_estimate as new (and better) positon

            %Plot grid-map, all positions and all scans (Black: True postion, Blue: Position and scan initial estimates, red:
            %Converged position and laser data
                figure(42)
                set(gcf,'units','normalized','outerposition',[1 0 1 1]);
                clf;
                caxis([0, 1]);
                colormap gray;
                colormap(flipud(colormap));
                hold on;
                imagesc(flipud(pf.P(:,:, i)));

                % Plot scans
                plot(y_help(1,:), y_help(2,:), '.g')
                plot(yh_help(1,:), yh_help(2,:), '.b')
                plot(data(1,:), data(2,:), '.r')

                % Plot positions
                plot(x_true(1), x_true(2), 'dk')
                plot(x_initial_estimate(1,i), x_initial_estimate(2, i), 'db')
                plot(x_new_sm(1,i), x_new_sm(2,i), 'dr')
                hold off;

                % Save each iteration map into as png
                % str=sprintf('path_images/fig%d.png', pf.k);
                % saveas(gcf, str)

            % Randomize samples around good estimate (x_new_sm) of particle position
            theta_samples=x_new_sm(3,i);
            if theta_samples > 2*pi
                theta_samples=theta_samples-2*pi;
            elseif theta_samples < -2*pi
                theta_samples=theta_samples-2*pi;
            end

            x_sampled(:,:, i) = [ normrnd([x_new_sm(1,i).*ones(1, Nsamples); x_new_sm(2,i).*ones(1, Nsamples)],0.5, [2 Nsamples]); theta_samples.*ones(1, Nsamples)];

            for h=1:Nsamples

                % Calculate odometry probability for that sample
                p_xt(h,i)= Motion_Model_Velocity(x_sampled(:,h,i), u, x_past(:,i), a);

                % Calculate scan matching probability for that sample
                ytru=y;
                yest = Measurement_Estimate_From_Grid(x_sampled(:,h,i),pf.P(:,:, i),LRS.Resolution,LRS.FoV, LRS.MaxDistance, pf.UsableArea);
                yest(yest>pf.UsableArea)=nan;
                find_yest=isnan(yest(2,:));
                yest(:,(find_yest(1,:)==1))=[];
                ytru(:,(find_yest(1,:)==1))=[];
                p_zt(h,i) = Measurement_Model(ytru,yest,[1 1]);

                % Calculate optimal proposal distribution
                tau_xt(h,i)=abs(p_xt(h,i)*p_zt(h,i));

            end

            n(i)=sum(tau_xt(:,i));                                  % Calculate sample normalizer
            mu(1, i)=(1/n(i))*(x_sampled(1,:,i)*tau_xt(:,i));       % Calculate mu for gaussian distribution from samples
            mu(2, i)=(1/n(i))*(x_sampled(2,:,i)*tau_xt(:,i));
            mu(3, i)=theta_samples;                                 % Orientation of samples is constant (the one from ICP)

            % Calculate covariance for gaussian distribution from samples
            cov_sum=0;
            for h=1:Nsamples
                cov_sum=cov_sum+(x_sampled(1:2,h,i)-mu(1:2,i))'*(x_sampled(1:2,h,i)-mu(1:2,i))*tau_xt(h,i);
            end
            cov(i)=(1/n(i))*cov_sum;

            %Calculate new weights
            q(i)=q_past(i)*n(i);

            %Sample gaussian for final position of particle
            x_final(:,i)=[normrnd([mu(1,i); mu(2,i)],cov(i), [2 1]); mu(3, i)];
        end

        %Update GridMap for taht particle
        [pf.P(:,:,i), pf.L(:,:,i)] = Occupancy_Grid_Mapping(pf.L(:,:,i), x_final(:,i), y, pf.UsableArea, pf.L0, pf.gridsize, LRS);

    end

    q=q/norm(q,1);                      % Normalize weights
    Neff = 1/sum(q.^2);                 % Calcuklate Neff for possible resampling

    %% Resampling step

    resample_percentage = 0.3;          % 0.5 is the best resample percentage proposed by Cyrill Stachniss
    Nt = resample_percentage*NPC;
    if Neff < Nt
        disp('Resampling');
        [x_final(:,:), q, idx] = Resample(x_final(:,:), q, resampling_strategy);
        P_save_resamp=pf.P(:,:,:);
        L_save_resamp=pf.L(:,:,:);
        for n=1:NPC
           pf.P(:,:,n)=P_save_resamp(:,:,idx(n));
           pf.L(:,:,n)=L_save_resamp(:,:,idx(n));
        end
    end

    pf.q(:,k) = q;                      % Save particle weights (might have changed during resampling)

    %% Calculate estimate of true position (xh) given all weighted particles
    xh = zeros(3,1);
    for i=1:NPC
            xh = xh +(q(i).*x_final(:,i));
    end
    pf.xh(:, k)= xh;

    %% Store final position of all particles
    pf.particles(:,:,k) = x_final(:,:);

    % Make sure no errors have occured. If so probably becasue of p_xt or p_zt being equal to 0
    if isnan(x_final(1,i)) || isnan(x_final(2,i))
                1; %debugger
                x_final=x_initial_estimate;
    end

    %% Visualize results: Plot Particles
%         figure(89)
%         set(gcf,'units','normalized','outerposition',[-1 0 1 1]);
%         clf;
%         hold on;
%         for g = 1:size(map,2)
%             plot([map(1,g) map(3,g)],[map(2,g) map(4,g)],'k')
%         end
%         plot(squeeze(pf.particles(1,:,pf.k-1))',squeeze(pf.particles(2,:,pf.k-1))','bo');
%         plot(squeeze(pf.particles(1,:,pf.k))',squeeze(pf.particles(2,:,pf.k))','k+');
%         plot(squeeze(pf.xh(1,pf.k))',squeeze(pf.xh(2,pf.k))','ro');
%         plot(x_true(1), x_true(2), 'go')
%         hold off;

end


function [param, names] = gpnddisimExtractParam(model)

% NDDISIMEXTRACTPARAM Extract the parameters of a NDDISIM model.
% FORMAT
% DESC extracts the model parameters from a structure containing
% the information about a Gaussian process for single input motif
% modelling.
% ARG model : the model structure containing the information about
% the model.
% RETURN params : a vector of parameters from the model.
%
% SEEALSO : gpdisimCreate, gpdisimExpandParam, modelExtractParam
%
% COPYRIGHT : Neil D. Lawrence, 2006
%
% COPYRIGHT : Antti Honkela, 2007
%
% COPYRIGHT : Jaakko Peltonen, 2011

% GPSIM

if nargout>1
  [param, names] = kernExtractParam(model.kern);

%  fprintf(1,'gpdisimExtractParam: parameters from kernels\n');
%  param
%  names

  %  model.mu
  %  length(model.mu)
  %for i=1:length(model.mu),
  for i=1:model.numGenes,
    names{end+1}=['Basal transcription ' num2str(i)];
  end
  if model.numGenes>0,
    if (model.use_disimstartmean==1),
      for i=1:model.numGenes,
	names{end+1}=['NDDISIM startmean ' num2str(i)];
      end;
    end;
  end;

  names{end+1}=['NDSIM mean ' num2str(i)];
else
  param = kernExtractParam(model.kern);
end

%length(param)
%model.numGenes
%length(model.B)
if model.numGenes>0,
  for k=1:model.numGenes,
    param = [param doTransform(model.B(k), 'xtoa',model.bTransform(k))];
  end;
end;
%length(param)

if model.numGenes>0,
  if (model.use_disimstartmean==1),
    for i=1:model.numGenes,
      param = [param doTransform(model.disimStartMean(k),'xtoa',model.disimStartMeanTransform(k))];
    end;
  end;
end;

param = [param doTransform(model.simMean,'xtoa',model.simMeanTransform)];

if isfield(model, 'fix')
%model.fix
  for i = 1:length(model.fix)
    param(model.fix(i).index) = model.fix(i).value;
  end
end
param = real(param);


%% t_tseriesLoadFromInplane
%
% Illustrates how to load a time series from a functional data set.
%
% Tested 01/05/2011 - MATLAB r2008a, Fedora 12, Current Repos
%
% Stanford VISTA
%

%% Initialize the key variables and data path
% Data directory (where the mrSession file is located)
dataDir = mrtInstallSampleData('functional','vwfaLoc');

%% Retain original directory, change to data directory
curDir = pwd;
cd(dataDir);

% There can be several data types - name the one you want to plot
dataType = 'MotionComp';

% Which scan number from that data type?
scan = 1;

% Would you like the raw time series?
isRawTSeries = true;

%% Get data structure:
vw = initHiddenInplane(); % Foregoes interface - loads data silently

%% Set data structure properties:
vw = viewSet(vw, 'CurrentDataType', dataType); % Data type

%% Get time series from ROI:
% Format returned is rows x cols x slices x time
tSeries = tSeries4D(vw, scan, [], 'usedefaults', ~isRawTSeries);

%% Show movie of a single slice across the given scan
figure;
colormap autumn;
nSlices = size(tSeries, 3);
nTimePoints = size(tSeries, 4);
rg = [-1 1] * max(abs(tSeries(:)));
for i = 1:nTimePoints
    imagesc(tSeries(:, :, ceil(nSlices/2), i), rg);
    axis image; colormap gray
    title(sprintf('Volume %d', i))
    pause(.1);
end
close;

%% Show movie of slices at a single time point
figure;
colormap autumn;
for i = 1:nSlices
    imagesc(tSeries(:, :, i, ceil(nTimePoints/2)));
    colormap gray
    axis image;
    title(sprintf('Slice %d', i))
    pause(.1);
end
close;

%% Restore original directory
cd(curDir);

%% END


function f = logical(f)
%LOGICAL   CLASSICFUN logical.
%   LOGICAL(F) returns a CLASSICFUN which evaluates to one at all points where F is
%   nonzero and zero otherwise.  F cannot have any roots in its domain.  If F
%   does have roots, then LOGICAL(F) will return garbage with no warning. F may
%   be complex.

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

f.onefun = logical(f.onefun);

end


%% housekeeping
clear all
close all
clc
%% RISE the model
m=rise('ireland2004');

%% load the data
mydat=load('ych.dat');
data=ts('1948Q1',log(mydat),{'LY','LC','LH'});
data=pages2struct(data);
data.TREND=ts(data.LY.start,(1:data.LY.NumberOfObservations).');
%%
ms=estimate(m,'data',data,'kf_tol',0);
%% Redo filtering?

mfilt=filter(ms,'data',data,'kf_tol',0);


function [Y, XYZ] = iimg_read_vols(V, mask)
% Drop-in replacement for spm_read_vols
% Primary difference is that if the images have the same voxel size but are NOT resliced
% (e.g., have differing affine matrices), this will handle reading each individually and
% putting them together.

    if nargin<2, mask = 0; end
    if nargin<1, error('insufficient arguments'); end

    if length(V)>1 && any(any(diff(cat(1, V.dim), 1, 1), 1))
        error('images don''t all have the same dimensions');
    end
    if any(any(any(diff(cat(3, V.mat), 1, 3), 3)))
        %error('images don''t all have same orientation & voxel size');
        for i = 1:length(V)
            Y(:,:,:,i) = spm_read_vols(V(i), mask);
        end

        if nargout > 1
            [R, C, P] = ndgrid(1:V(1).dim(1), 1:V(1).dim(2), 1:V(1).dim(3));
            RCP = [R(:)';C(:)';P(:)'];
            clear R C P
            RCP(4,:) = 1;
            XYZ = V(1).mat(1:3,:)*RCP;
        end
    else
        [Y, XYZ] = spm_read_vols(V, mask);
    end
end


function g = rbfhKernGradient(kern, x1, x2, covGrad)

% RBFHKERNGRADIENT Gradient of RBFH kernel's parameters.
% FORMAT
% DESC computes the gradient of functions with respect to the
% radial basis function heat kernel's parameters. As well as the kernel
% structure and the input positions, the user provides a matrix PARTIAL
% which gives the partial derivatives of the function with respect to the
% relevant elements of the kernel matrix.
% ARG kern : the kernel structure for which the gradients are being
% computed.
% ARG x1 : the input locations for which the gradients are being
% computed.
% ARG covGrad : matrix of partial derivatives of the function of
% interest with respect to the kernel matrix. The argument takes
% the form of a square matrix of dimension  numData, where numData is
% the number of rows in X.
% RETURN g : gradients of the function of interest with respect to
% the kernel parameters. The ordering of the vector should match
% that provided by the function kernExtractParam.
%
% FORMAT
% DESC computes the derivatives as above, but input locations are
% now provided in two matrices associated with rows and columns of
% the kernel matrix.
% ARG kern : the kernel structure for which the gradients are being
% computed.
% ARG x1 : the input locations associated with the rows of the
% kernel matrix.
% ARG x2 : the input locations associated with the columns of the
% kernel matrix.
% ARG covGrad : matrix of partial derivatives of the function of
% interest with respect to the kernel matrix. The matrix should
% have the same number of rows as X1 and the same number of columns
% as X2 has rows.
% RETURN g : gradients of the function of interest with respect to
% the kernel parameters.
%
% SEEALSO: rbfhKernParamInit, kernGradient
%
% COPYRIGHT : Mauricio A. Alvarez, 2010

% KERN

if nargin < 4
    covGrad = x2;
    x2 = x1;
end
if size(x1, 2) ~= 2 || size(x2, 2) ~= 2
    error('Input can only have two columns');
end

% Split the domain into time domain and spatial domain and account for
% missing values. If there are no missing values the computation of the
% kernel is a pointwise prodruct, otherwise it is a kronecker product.
t1 = x1(x1(:,1)~=Inf,1);
t2 = x2(x2(:,1)~=Inf,1);
s1 = x1(x1(:,2)~=Inf,2);
s2 = x2(x2(:,2)~=Inf,2);
if (length(t1) == length(s1)) && (length(t2) == length(s2))
    ut1 = unique(t1);
    ut2 = unique(t2);
    us1 = unique(s1);
    us2 = unique(s2);
    if (length(ut1)*length(us1) == length(t1)) && ...
            (length(ut2)*length(us2) == length(t2))
        t1 = ut1; s1 = us1; t2 = ut2; s2 = us2;
        isPointwise = false;
    else
        isPointwise = true;
    end
else
    isPointwise = false;
end

kern.rbf.inverseWidth = kern.inverseWidthTime;
Kt = rbfKernCompute(kern.rbf, t1, t2);
kern.rbf.inverseWidth = kern.inverseWidthSpace;
Ks = rbfKernCompute(kern.rbf, s1, s2);

if isPointwise
    covGradt = covGrad.*Ks;
    covGrads = covGrad.*Kt;
else
    covGradt = zeros(length(t1), length(t2));
    covGrads = zeros(length(s1), length(s2));
    endOne = 0;
    startOne = 1;
    for k=1:length(t1)
        endOne = endOne + length(s1);
        startTwo = 1;
        endTwo = 0;
        for l=1:length(t2)
            endTwo = endTwo + length(s2);
            covGradt(k,l) = sum(sum(covGrad(startOne:endOne, startTwo:endTwo).*Ks));
            startTwo = endTwo + 1;
        end
        startOne = endOne + 1;
    end
    for k=1:length(s1)
        indRows = (k:length(s1):(length(t1)*length(s1)))';
        for l=1:length(s2)
            indCols = l:length(s2):(length(t2)*length(s2));
            covGrads(k,l) = sum(sum(covGrad(indRows, indCols).*Kt));
        end
    end
end

kern.rbf.inverseWidth = kern.inverseWidthTime;
gt = rbfKernGradient(kern.rbf, t1, t2, covGradt);
kern.rbf.inverseWidth = kern.inverseWidthSpace;
gs = rbfKernGradient(kern.rbf, s1, s2, covGrads);

g = [gt(1) gs(1)];


function [res, plotind] = coor2D(this, ind, val, mindist)
% returns x and y coordinates of channels in 2D plane
% FORMAT coor2D(this)
% _______________________________________________________________________
% Copyright (C) 2008-2012 Wellcome Trust Centre for Neuroimaging

% Vladimir Litvak, Laurence Hunt
% $Id: coor2D.m 7445 2018-10-12 13:24:48Z vladimir $

megind = indchantype(this, {'MEG', 'MEGPLANAR', 'MEGCOMB'});
eegind = indchantype(this, {'EEG'});
otherind = setdiff(1:nchannels(this), [megind eegind]);

if nargin==1 || isempty(ind)
    if nargin<3 || (size(val, 2)<nchannels(this))
        if ~isempty(megind)
            ind = megind;
        elseif ~isempty(eegind)
            ind = eegind;
        else
            ind = 1:nchannels(this);
        end
    else
        ind = 1:nchannels(this);
    end
elseif ischar(ind)
    switch upper(ind)
        case 'MEG'
            ind = megind;
        case 'EEG'
            ind = eegind;
        case ':'
            ind = 1:nchannels(this);
        otherwise
            ind = otherind;
    end
end

if nargin < 3 || isempty(val)
    if ~isempty(intersect(ind, megind))

        if this.montage.Mind==0
            if ~any(cellfun('isempty', {this.channels(megind).X_plot2D this.channels(megind).Y_plot2D}))
                meg_xy = [this.channels(megind).X_plot2D; this.channels(megind).Y_plot2D];
            elseif all(cellfun('isempty', {this.channels(megind).X_plot2D this.channels(megind).Y_plot2D}))
                meg_xy = grid(length(megind));
            else
                error('Either all or none of MEG channels should have 2D coordinates defined.');
            end
        else
            if ~any(cellfun('isempty', {this.montage.M(this.montage.Mind).channels(megind).X_plot2D ...
                    this.montage.M(this.montage.Mind).channels(megind).Y_plot2D}))
                meg_xy = [this.montage.M(this.montage.Mind).channels(megind).X_plot2D; ...
                    this.montage.M(this.montage.Mind).channels(megind).Y_plot2D];
            elseif all(cellfun('isempty', {this.montage.M(this.montage.Mind).channels(megind).X_plot2D...
                    this.montage.M(this.montage.Mind).channels(megind).Y_plot2D}))
                meg_xy = grid(length(megind));
            else
                error('Either all or none of EEG channels should have 2D coordinates defined.');
            end
        end
    end

    if ~isempty(intersect(ind, eegind))
        if this.montage.Mind==0
            if ~any(cellfun('isempty', {this.channels(eegind).X_plot2D this.channels(eegind).Y_plot2D}))
                eeg_xy = [this.channels(eegind).X_plot2D; this.channels(eegind).Y_plot2D];
            elseif all(cellfun('isempty', {this.channels(eegind).X_plot2D this.channels(eegind).Y_plot2D}))
                eeg_xy = grid(length(eegind));
            else
                error('Either all or none of EEG channels should have 2D coordinates defined.');
            end
        else
            if ~any(cellfun('isempty', {this.montage.M(this.montage.Mind).channels(eegind).X_plot2D ...
                    this.montage.M(this.montage.Mind).channels(eegind).Y_plot2D}))
                eeg_xy = [this.montage.M(this.montage.Mind).channels(eegind).X_plot2D; ...
                    this.montage.M(this.montage.Mind).channels(eegind).Y_plot2D];
            elseif all(cellfun('isempty', {this.montage.M(this.montage.Mind).channels(eegind).X_plot2D...
                    this.montage.M(this.montage.Mind).channels(eegind).Y_plot2D}))
                eeg_xy = grid(length(eegind));
            else
                error('Either all or none of EEG channels should have 2D coordinates defined.');
            end
        end
    end

    if ~isempty(intersect(ind, otherind))
        other_xy = grid(length(otherind));
    end

    xy = zeros(2, length(ind));
    plotind = zeros(1, length(ind));
    for i = 1:length(ind)
        [found, loc] = ismember(ind(i), megind);
        if found
            xy(:, i) = meg_xy(:, loc);
            plotind(i) = 1;
        else
            [found, loc] = ismember(ind(i), eegind);
            if found
                xy(:, i) = eeg_xy(:, loc);
                plotind(i) = 2;
            else
                [found, loc] = ismember(ind(i), otherind);
                if found
                    xy(:, i) = other_xy(:, loc);
                    plotind(i) = 3;
                end
            end
        end
    end

    if nargin > 3 && ~isempty(mindist)
        xy = shiftxy(xy,mindist);
    end

    res = xy;
else
    if this.montage.Mind==0
        this = getset(this, 'channels', 'X_plot2D', ind, val(1, :));
        this = getset(this, 'channels', 'Y_plot2D', ind, val(2, :));
    else
        this.montage.M(this.montage.Mind) = getset(this.montage.M(this.montage.Mind), 'channels', 'X_plot2D', ind, val(1, :));
        this.montage.M(this.montage.Mind) = getset(this.montage.M(this.montage.Mind), 'channels', 'Y_plot2D', ind, val(2, :));
    end
    res = this;
end

function xy = grid(n)

ncol = ceil(sqrt(n));
x = 0:(1/(ncol+1)):1;
x = 0.9*x+0.05;
x = x(2:(end-1));
y = fliplr(x);
[X, Y] = meshgrid(x, y);
xy = [X(1:n); Y(1:n)];

function xy = shiftxy(xy,mindist)

x = xy(1,:);
y = xy(2,:);

l=1;
i=1; %filler
mindist = mindist/0.999; % limits the number of loops
while (~isempty(i) && l<50)
    xdiff = repmat(x,length(x),1) - repmat(x',1,length(x));
    ydiff = repmat(y,length(y),1) - repmat(y',1,length(y));
    xydist= sqrt(xdiff.^2 + ydiff.^2); %euclidean distance between all sensor pairs

    [i,j] = find(xydist<mindist*0.999);
    rm=(i<=j); i(rm)=[]; j(rm)=[]; %only look at i>j

    for m = 1:length(i);
        if (xydist(i(m),j(m)) == 0)
            diffvec = [mindist./sqrt(2) mindist./sqrt(2)];
        else
            xydiff = [xdiff(i(m),j(m)) ydiff(i(m),j(m))];
            diffvec = xydiff.*mindist./xydist(i(m),j(m)) - xydiff;
        end
        x(i(m)) = x(i(m)) - diffvec(1)/2;
        y(i(m)) = y(i(m)) - diffvec(2)/2;
        x(j(m)) = x(j(m)) + diffvec(1)/2;
        y(j(m)) = y(j(m)) + diffvec(2)/2;
    end
    l = l+1;
end

xy = [x; y];


function ebsdNew = interp(ebsd, varargin)
% interpolate at arbitrary points (x,y)
%
% Syntax
%
%   ebsdNew = interp(ebsd,xNew,yNew)
%
%   ebsdNew = interp(ebsd,xNew,yNew,'method','invDist')
%
% Input
%  ebsd - @EBSD
%  xNew, yNew - new x,y coordinates
%
% Output
%  ebsdNew - @EBSD with coordinates (xNew,yNew)
%
% Options
%  method - 'invDist', 'nearest'
%
% See also
%

ebsdNew = interp(ebsd.gridify,varargin{:});


function selected = SelectSpikes(spikes,varargin)

%SelectSpikes - Discriminate bursts vs single spikes.
%
%  USAGE
%
%    selected = SelectSpikes(spikes,<options>)
%
%    spikes         spike times
%    <options>      optional list of property-value pairs (see table below)
%
%    =========================================================================
%     Properties    Values
%    -------------------------------------------------------------------------
%     'mode'        either 'bursts' (default) or 'single'
%     'isi'         max inter-spike interval for bursts (default = 0.006),
%                   or min for single spikes (default = 0.020)
%    =========================================================================
%
%  OUTPUT
%
%    selected       a logical vector indicating for each spike whether it
%                   matches the criterion

% Copyright (C) 2011 by Michaël Zugaro
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 3 of the License, or
% (at your option) any later version.

% Default values
isiBursts = 0.006;
isiSpikes = 0.020;
mode = 'bursts';

% Check number of parameters
if nargin < 1 | mod(length(varargin),2) ~= 0,
  error('Incorrect number of parameters (type ''help SelectSpikes'' for details).');
end

% Check parameter size
if ~isdvector(spikes),
	error('Incorrect spikes (type ''help SelectSpikes'' for details).');
end

% Parse parameter list
for i = 1:2:length(varargin),
  if ~ischar(varargin{i}),
    error(['Parameter ' num2str(i+2) ' is not a property (type ''help SelectSpikes'' for details).']);
  end
  switch(lower(varargin{i})),
    case 'mode',
      mode = varargin{i+1};
      if ~isstring_FMAT(mode,'bursts','single'),
        error('Incorrect value for property ''mode'' (type ''help SelectSpikes'' for details).');
      end
    case 'isi',
      isi = varargin{i+1};
      if ~isdscalar(isi,'>0'),
        error('Incorrect value for property ''isi'' (type ''help SelectSpikes'' for details).');
      end
    otherwise,
      error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help SelectSpikes'' for details).']);
  end
end

t = spikes(:);
dt = diff(t);

if strcmp(mode,'bursts'),
	b = dt<isi;
	selected = logical([0;b])|logical([b;0]); % either next or previous isi < threshold
else
	s = dt>isi;
	selected = logical([0;s])&logical([s;0]); % either next or previous isi < threshold
end


function [atomicWeights] = parse_Atomic_Weights_and_Isotopic_Compositions_for_All_Elements
% Parses NIST data on atomic weights
%
% USAGE:
%
%    [atomicWeights] = parse_Atomic_Weights_and_Isotopic_Compositions_for_All_Elements
%
% OUTPUT:
%    atomicWeights:    atomic weights of the isotopes
%
% The atomic weight J. S. Coursey, D. J. Schwab, and R. A. Dragoset
% NIST, Physics Laboratory, Office of Electronic Commerce in Scientific and
% Engineering Data.
% The atomic weights are available for elements 1 through 112, 114, & 116 and
% isotopic compositions or abundances are given when appropriate. The atomic
% weights data were published by T.B. Coplen in `Atomic Weights of the Elements
% 1999`, (and include changes reported from the 2001 review in `Chem. Int., 23, 179 (2001)`)
% and the isotopic compositions data were published by K.J.R. Rosman2 and P.D.P. Taylor3
% in `Isotopic Compositions of the Elements 1997`. The relative atomic masses of the
% isotopes data were published by G. Audi4 and A. H. Wapstra5 in `The 1995 Update To
% The Atomic Mass Evaluation`.
% http://physics.nist.gov/PhysRefData/Compositions/
%
% .. Author: - Ronan Fleming, 9 March 09

fid=fopen('Atomic_Weights_and_Isotopic_Compositions_for_All_Elements.txt','r');

nElements=2816/8;
p=1;
ele=1;
fieldNames={'AtomicNumber';
'AtomicSymbol';
'MassNumber';
'RelativeAtomicMass';
'IsotopicComposition';
'StandardAtomicWeight';
'Notes'};

for x=1:2816
    line= fgetl(fid);
    if ~isempty(line)
        if p==2 || p==7
            tmp=textscan(line,'%s%s\n',2815,'Delimiter','=(','TreatAsEmpty',' ');
            if ~isempty(tmp{2})
                atomicWeights.data(ele).(fieldNames{p})=tmp{2};
            end
            if p==2
                tmp2=tmp{2};
                if ~isempty(tmp2)
                    atomicWeights.AtomicSymbol{ele}=tmp2{1};
                end
            end
        else
            tmp=textscan(line,'%s%f\n',2815,'Delimiter','=(','TreatAsEmpty',' ');
            atomicWeights.data(ele).(fieldNames{p})=tmp{2};
        end
        p=p+1;
    else
        ele=ele+1;
        p=1;
    end
end

fclose(fid);


classdef (TestTags = {'SPGR', 'Demo', 'Integration'}) SimDemo_SPGR_Test < matlab.unittest.TestCase

    properties
       qmrlabPath = cell2mat(regexp(cd, '.*qMRLab/', 'match'));
    end
    methods (TestClassSetup)
        function addqMRLabToPath(testCase)
            addpath(genpath(testCase.qmrlabPath));
        end
    end

    methods (TestClassTeardown)
        function removeqMRILabFromPath(testCase)
            clear all, close all
        end
    end

    methods (Test)
        function testFittedParamsNearInputValues(testCase)
            run([testCase.qmrlabPath, '/Models_Functions/SPGRfun/SimDemo_SPGR.m'])

            inputParams  = Sim.Param;
            outputParams = SimCurveResults;

            inputArr  = [inputParams.F  inputParams.kf  inputParams.R1f  inputParams.T2f  inputParams.T2r];
            outputArr = [outputParams.F outputParams.kf outputParams.R1f outputParams.T2f outputParams.T2r];

            %                                                 , # percent
            %                                                 . [F  kf R1f T2f T2r]
            testCase.verifyLessThan(pDiff(inputArr, outputArr), [30 30 30  30  30]);
        end
    end

end

function value = pDiff(inputVal, outputVal)
    value = abs((outputVal-inputVal)./inputVal).*100;
end


function [dt6,b0] = dtiDeformer(dt6,b0,deformField)
% function [outDt6,outb0] = dtiDeformer(inputImgFN,deformFieldFN,dfType,outputImgFN)
% DTI Deformer: Warps dt6 image according to given deformation field
%
% ARGUMENTS:
% dt6: Input dt6 image
% b0: input b0 image
% deformField: Deformation field (XxYxZx3)
%
% HISTORY:
% 2004.01.19 GSM (gmulye@stanford.edu) wrote it and cleaned up the interface
%

dimSrc = size(dt6);
H = zeros(dimSrc(1),dimSrc(2),dimSrc(3),3);
for x = 1:dimSrc(1)
    for y = 1:dimSrc(2)
        for z = 1:dimSrc(3)
            H(x,y,z,:) = [y x z];
        end
    end
end
newH = H + deformField;
%Giant matrix of coordinates

% CREATE NEW DT6 IMAGE
coordsList = reshape(newH,dimSrc(1)*dimSrc(2)*dimSrc(3),3);
newDt6List = zeros(dimSrc(1)*dimSrc(2)*dimSrc(3),6);
for i = 1:6
    newDt6List(:,i) = myCinterp3(dt6(:,:,:,i),[dimSrc(1),dimSrc(2)],dimSrc(3),coordsList)';
end
newDt6 = zeros(dimSrc(1),dimSrc(2),dimSrc(3),6);
for i = 1:6
    newDt6(:,:,:,i) = reshape(newDt6List(:,i),dimSrc(1),dimSrc(2),dimSrc(3));
end
dt6 = newDt6; clear newDt6 newDt6List;

%CREATE NEW B0 IMAGE, SAVE OUT
newB0List(:,:,:) = myCinterp3(double(b0),[dimSrc(1),dimSrc(2)],dimSrc(3),coordsList)';
newB0 = reshape(newB0List,dimSrc(1),dimSrc(2),dimSrc(3));
b0 = int16(newB0); clear newB0List newB0; clear coordsList;

% %OUTPUT FILE NAMING CONVENTION
% if (~exist('outputImgFN', 'var'))
%     [a imgFN b c] = fileparts(inputImgFN);
%     us=findstr('_',inputImgFN);
%     subjectCode = inputImgFN(1:us(1)-1);
%     outputImgFN = ['registered_',subjectCode];
% end
% deformationNotes = [deformFieldFN];
% save(outputImgFN,'b0','xformToAcPc','xformToAnat','notes','deformationNotes',...
%     'mmPerVox','anat','dt6');

return


function f = vargplvmObjective(params, model)

% VARGPLVMOBJECTIVE Wrapper function for variational GP-LVM objective.
% FORMAT
% DESC provides a wrapper function for the variational GP-LVM, it
% takes the negative of the log likelihood, feeding the parameters
% correctly to the model.
% ARG params : the parameters of the variational GP-LVM model.
% ARG model : the model structure in which the parameters are to be
% placed.
% RETURN f : the negative of the log likelihood of the model.
%
% SEEALSO : vargplvmCreate, vargplvmLogLikelihood, vargplvmExpandParam
%
% COPYRIGHT : Michalis K. Titsias, 2009-2011
% COPYRIGHT : Neil D. Lawrence, 2009-2011

% VARGPLVM

model = modelExpandParam(model, params);
f = - vargplvmLogLikelihood(model);


function [Z,order,Md] = som_linkage(sM,varargin)

%SOM_LINKAGE Make a hierarchical linkage of the SOM map units.
%
% [Z,order,Dist] = som_linkage(sM, [[argID,] value, ...])
%
%  Z = som_linkage(sM);
%  Z = som_linkage(D,'complete');
%  Z = som_linkage(sM,'single','ignore',find(~som_hits(sM,D)));
%  Z = som_linkage(sM,pdist(sM.codebook,'mahal'));
%  som_dendrogram(Z);
%
%  Input and output arguments ([]'s are optional):
%   sM       (struct) map or data struct to be clustered
%            (matrix) size dlen x dim, a data set: the matrix must not
%                     contain any NaN's!
%   [argID,  (string) See below. The values which are unambiguous can
%    value]  (varies) be given without the preceeding argID.
%
%   Z        (matrix) size dlen-1 x 3, the linkage info
%                     Z(i,1) and Z(i,2) hold the indeces of clusters
%                     combined on level i (starting from bottom). The new
%                     cluster has index dlen+i. The initial cluster
%                     index of each unit is its linear index in the
%                     original data matrix. Z(i,3) is the distance
%                     between the combined clusters. See LINKAGE
%                     function in the Statistics Toolbox.
%                     The ignored samples are listed at the
%                     end of the Z-matrix and have Z(*,3) == Inf
%   Dist     (matrix) size dlen x dlen, pairwise distance matrix
%
% Here are the valid argument IDs and corresponding values. The values
% which are unambiguous (marked with '*') can be given without the
% preceeding argID.
%   'linkage' *(string) the linkage criteria to use: 'single' (the
%                       default), 'average' or 'complete'
%   'topol'   *(struct) topology struct
%   'connect' *(string) 'neighbors' or 'any' (default), whether the
%                       connections should be allowed only between
%                       neighbors or between any vectors
%              (matrix) size dlen x dlen indicating the connections
%                       between vectors
%              (scalar) the N-neighborhood upto which the connections
%                       should be formed (implies 'neighbors')
%   'ignore'   (vector) the units/vectors which should be ignored
%   'dist'     (matrix) size dlen x dlen, pairwise distance matrix to
%                       be used instead of euclidian distances
%              (vector) as the output of PDIST function
%              (scalar) distance norm to use (euclidian = 2)
%   'mask'     (vector) size dim x 1, the search mask used to
%                       weight distance calculation. By default
%                       sM.mask or a vector of ones is used.
%
% Note that together 'connect'='neighbors' and 'ignore' may form
% areas on the map which will never be connected: connections
% across the ignored map units simply do not exist.
%
% See also KMEANS_CLUSTERS, LINKAGE, PDIST, DENDROGRAM.

% Copyright (c) 2000 by Juha Vesanto
% Contributed to SOM Toolbox on June 16th, 2000 by Juha Vesanto
% http://www.cis.hut.fi/projects/somtoolbox/

% Version 2.0beta juuso 160600

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% input arguments

% the data
if isstruct(sM),
  if isfield(sM,'data'), D = sM.data; sT = []; mask = [];
  else D = sM.codebook; sT = sM.topol; mask = sM.mask;
  end
else
  D = sM; sT = []; mask = [];
end
[dlen dim] = size(D);
if isempty(mask), mask = ones(dim,1); end
if any(isnan(D(:))), error('Data matrix must not have any NaNs.'); end

% varargin
Md = 2;
linkage = 'single';
ignore_units = [];
constrained = 0;
i=1;
while i<=length(varargin),
  argok = 1;
  if ischar(varargin{i}),
    switch varargin{i},
      % argument IDs
     case {'topol','som_topol','sTopol'}, i=i+1; sT = varargin{i};
     case 'connect', i=i+1;
       if ischar(varargin{i}), constrained = ~strcmp(varargin{i},'any');
       else constrained = varargin{i}; end
     case 'ignore',  i=i+1; ignore_units = varargin{i};
     case 'dist',    i=i+1; Md = varargin{i};
     case 'linkage', i=i+1; linkage = varargin{i};
     case 'mask',    i=i+1; mask = varargin{i};
     case 'tracking',i=i+1; tracking = varargin{i};
      % unambiguous values
     case 'neighbors', constrained = 1;
     case 'any',       constrained = 0;
     case {'single','average','complete'}, linkage = varargin{i};
     otherwise argok=0;
    end
  elseif isstruct(varargin{i}) & isfield(varargin{i},'type'),
    switch varargin{i}(1).type,
     case 'som_topol', sTopol = varargin{i};
     otherwise argok=0;
    end
  else
    argok = 0;
  end
  if ~argok,
    disp(['(som_linkage) Ignoring invalid argument #' num2str(i+1)]);
  end
  i = i+1;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% distance matrix

% given distance matrix % jh corrected this place totally 27.3. 03
if (prod(size(Md))==1), % no explicit distance matrix, set flag
  q=2; % 17.2.03 kr added some brackets
else
  if (prod(size(Md))<dlen^2), % check pdist form
    Md = squareform(Md);   % transform to ordinary square diastance matrix
  end
  % jh: 27.3. 03 "calculate pairwise dist. matrix" see approx. 20 lines below
  % sets self-distance to Inf! This must be set here also,
  % otherwise clustering fails for user defined dist. matrix!
  Md(eye(dlen)==1)=Inf;
end

% neighborhood constraint
if length(constrained)==1 & constrained>0,
  Ne1 = som_unit_neighs(sT);
  Conn = som_neighborhood(Ne1,constrained);
  Conn(~isfinite(Conn(:))) = 0;
else Conn = constrained; end
if ~isempty(Conn), for i=1:dlen, C(i,i) = 1; end, end

% pairwise distance matrix across connected units
n = size(D,1);
if prod(size(Md))>1,
  % remove distances between non-neighbors
  if constrained, for i = 1:n, Md(i,find(Conn(i,:)==0)) = Inf; end, end
else
  % calculate pairwise distance matrix
  q = Md;
  Md = zeros(n,n)+Inf;
  if ~constrained & q==2, % fast for the default case
    for i = 1:n-1,
      x = D(i,:);
      inds = [(i+1):n];
      Diff = D(inds,:) - x(ones(n-i,1),:);
      Md(inds,i) = sqrt((Diff.^2)*mask);
      Md(i,inds) = Md(inds,i)';
    end
  else
    for i = 1:n-1,
      inds = find(Conn(i,:)==1);
      inds = inds(find(inds>i));
      Diff = abs(D(inds,:) - D(i*ones(length(inds),1),:));
      switch q,
       case 1,    dist = Diff*mask;
       case 2,    dist = sqrt((Diff.^2)*mask);
       case Inf,  dist = max(Diff,[],2);
       otherwise, dist = ((Diff.^q)*mask).^(1/q);
      end
      Md(inds,i) = dist;
      Md(i,inds) = dist';
    end
  end
end

% set distances to ignored units to Inf
if ~isempty(ignore_units),
  Md(ignore_units,:) = Inf;
  Md(:,ignore_units) = Inf;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% construct dendrogram

Z = zeros(n-1,3)+NaN;  % merged clusters and distance for each step
clusters = 1:dlen;     % each vector is at first in its own cluster
Cd = Md;               % distances between clusters

h = waitbar(0,'Constructing hierarchical clustering');

for i=1:n-1,

  % tracking
  waitbar(i/(n-1),h);

  %% combine two closest clusters
  % find the clusters which are closest to each other (c1 and c2)
  [d,ind] = min(min(Cd));
  if ~isfinite(d), break; end   % no more connected clusters
  [d,c1] = min(Cd(:,ind));      % cluster1
  c2 = clusters(ind);           % cluster2
  % combine the two clusters
  c1_inds = find(clusters==c1); % vectors belonging to c1
  c2_inds = find(clusters==c2); % vectors belonging to c2
  c_inds = [c1_inds, c2_inds];  % members of the new cluster
  % new cluster index = bigger cluster
  if length(c2_inds)>length(c1_inds), c=c2; k=c1; else c=c1; k=c2; end
  clusters(c_inds) = c;         % update cluster info
  Z(i,:) = [c, k, d];           % save info into Z

  %% update cluster distances
  % remove the subclusters from the Cd table
  Cd(c_inds,c_inds) = Inf;      % distance of the cluster to its members = Inf
  k_inds = c_inds(c_inds ~= c); % vectors of the smaller cluster
  Cd(k_inds,:) = Inf;           % distance of the subclusters to
  Cd(:,k_inds) = Inf;           % other clusters = Inf
  % update the distance of this cluster to the other clusters
  cl = unique(clusters(clusters ~= c)); % indeces of all other clusters
  if ~isempty(cl), % added since v6.5 works differently than 6.1
    for l=cl,
      o_inds = find(clusters==l); % indeces belonging to cluster k
      vd = Md(c_inds,o_inds);     % distances between vectors in c and k
      vd = vd(isfinite(vd(:)));   % remove infinite distances (no connection)
      len = length(vd);
      if ~len, % if the two clusters are not connected, their distance in Inf
	sd = Inf;
      else   % otherwise, calculate the distance between them
	switch linkage,
	 case 'single',   sd = min(vd);
	 case 'average',  sd = sum(vd)/len;
	 case 'complete', sd = max(vd);
	 otherwise, error(['Unknown set distance: ' linkage]);
	end
      end
      Cd(c,l) = sd; Cd(l,c) = sd;
    end
  end
end
close(h);

last = Z(i,1);
if isnan(last),
  last = Z(i-1,1);
  rest = setdiff(unique(clusters),last);
  Z(i:n-1,1) = rest';
  Z(i:n-1,2) = last;
  Z(i:n-1,3) = Inf;
  i = i - 1;
else
  rest = [];
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% return values

% calculate the order of samples
order = last;
% go through the combination matrix from top to down
for k=i:-1:1,
  c = Z(k,1); k = Z(k,2);                     % what (k) change to what (c)
  j = find(order==c);                         % the occurance of c in order
  if j == length(order), order = [order k];   % put k behind c
  else order = [order(1:j) k order(j+1:end)];
  end
end
order = [rest, order];

% to maintain compatibility with Statistics Toolbox, the values in
% Z must be yet transformed so that they are similar to the output
% of LINKAGE function

Zs = Z;
current_cluster = 1:dlen;
for i=1:size(Z,1),
  Zs(i,1) = current_cluster(Z(i,1));
  Zs(i,2) = current_cluster(Z(i,2));
  current_cluster(Z(i,[1 2])) = dlen+i;
end

Z = Zs;

return;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%