function varargout = cgal_fixed_alpha_shape3(varargin)
% CGAL_FIXED_ALPHA_SHAPE3  Individual alpha-shapes of a 3D set of points
%
% TRI = cgal_fixed_alpha_shape3(X, ALPHA)
%
%   X is a 3-column matrix. X(i, :) contains the xyz-coordinates of a 3D
%   point.
%
%   ALPHA is a vector of scalar alpha values, alpha=R^2, where R is the
%   probe radius.
%
%   TRI is a cell array of the same length as ALPHA. Cell TRI{i} contains
%   the alpha shape triangulation for ALPHA{i}. Each row contains the 3
%   nodes that form one triangular facet in the mesh. The i-th mesh can be
%   visualised running:
%
%     >> trisurf(tri{i}, x)
%
%
% This function uses CGAL's implementation of fixed alpha shapes [1]. Fixed
% alpha shapes are more efficient when only the shape for one or a few
% alpha values is required. When many alpha values are required, it may be
% faster to use cgal_alpha_shape3().
%
% However, note that Matlab function alphavol() implemented by Jonas
% Lundgren and provided as a third-party function in Gerardus seems to be
% faster than either of the CGAL MEX functions, at least for a single alpha
% value.
%
% [1] http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Alpha_shapes_3/Chapter_main.html
%
% See also: alphavol, cgal_alpha_shape3, scimat_lconvhull_smoothing

% Author: Ramon Casero <rcasero@gmail.com>
% Copyright © 2013 University of Oxford
% Version: 0.1.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see
% <http://www.gnu.org/licenses/>.

error('MEX file not found')


classdef orientationRegion
  %sphericalRegion implements a region in orientation space
  % The region is bounded by planes normal to quaternions N i.e., all
  % quaternions q inside a region satisfy the condition dot(q, N) <= 0 or
  % dot(-q, N) <= 0 for all N

  properties
    N = quaternion  % the normal vectors of the bounding faces
    V = orientation % list of vertices
    F = {}          % list of faces
    antipodal = false % whether to identify q and inv(q)
  end

  properties (Dependent = true)
    CS1
    CS2
    E % list of edges
    faceCenter
  end

  methods

    function oR = orientationRegion(varargin)
      %

      if nargin > 0
        if isa(varargin{1},'quaternion') && ~isa(varargin{1},'symmetry') && ~check_option(varargin,'complete')
          oR.N = varargin{1};
          varargin{1} = [];
        end
      end

      % compute vertices
      oR.V = orientation.id(0,varargin{:});
      oR.antipodal = check_option(varargin,'antipodal');
      oR = oR.cleanUp;

    end

    function CS = get.CS1(oR)
      CS = oR.V.CS;
    end

    function CS = get.CS2(oR)
      CS = oR.V.SS;
    end

    function E = get.E(oR)

      % extract the vertices
      left = oR.F;
      right = cellfun(@(x) circshift(x,1), oR.F,'UniformOutput',false);
      E = [vertcat(left{:}),vertcat(right{:})];

    end

    function c = get.faceCenter(oR)

      if oR.antipodal
        c = orientation.nan(oR.CS1,oR.CS2,'antipodal');
      else
        c = orientation.nan(oR.CS1,oR.CS2);
      end
      for j = 1:length(oR.F)

        c(j) = mean(oR.V(unique(oR.F{j})),'noSymmetry');

      end

    end

  end

end


function r = subsasgn(r,s,b)
%SUBSASGN     Implements subscripted assignments for Taylor
%
%  example  r(2,:) = b
%

% written  05/21/09     S.M. Rump
% modified 02/28/10     S.M. Rump  multiple index
% modified 08/26/12     S.M. Rump  global variables removed
% modified 09/26/12     S.M. Rump  index handling (thanks to Matthew Weinstein)
%

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

  K1 = getappdata(0,'INTLAB_TAYLOR_ORDER') + 1;

  if length(s)>1
    error('multiple indexing for Taylor assignment not allowed')
  end

  if strcmp(s.type,'()')     % assignment r(i) = b

    rEmpty = isempty(r);    % assignment r(i) = b for empty r
    if isempty(b)
      % does not work in Matlab 5.3 for sparse r
      index = reshape(1:prod(r.size),r.size);
      index(s.subs{:}) = [];
      r.size = size(index);
      r.t = r.t(:,index);
      if rndold
        setround(rndold)
      end
      return
    end

    if ~isa(b,'taylor')
      b = taylor(b);
    end

    if ~rEmpty
      resultIsintval = isa(r.t,'intval');
      if ~resultIsintval & isa(b.t,'intval')
        r = intval(r);
        resultIsintval = 1;
      end
      sizeincreased = 0;
      rsizeold = r.size;
      if length(s.subs)==1               % single index
        if ~isequal(s.subs{1},':')       % not call r(:)=...
          if r.size(1)==1                % row vector
            M = s.subs{1};
            sizeincreased = ( M>r.size(2) );
            if sizeincreased
              r.size(2) = M;
            end
          else
            sizeincreased = ( s.subs{1} > prod(r.size) );
            if sizeincreased
              error('In an assignment A(I) = B a Taylor matrix cannot be resized')
            end
          end
          if sizeincreased
            srx = r.size;
            if length(srx)==2
              if all(prod(srx)~=srx)
                error('matrix cannot be resized by assignment a(I) = b')
              end
            else
              error('attempt to grow size of array along ambiguous dimension')
            end
          end
        end
      else                            % multiple index
        for i=1:length(s.subs)
          if ~isequal(s.subs{i},':')
            M = max(s.subs{i});
            if ( M > r.size(i) )
              sizeincreased = 1;
              r.size(i) = M;
            end
          end
        end
      end
      if sizeincreased                % size increased, adapt .t
        rt = r.t;
        value = ones(rsizeold);
        value( s.subs{:} ) = 0;
        r.t = zeros(K1,prod(size(value)));
        if resultIsintval
          r.t = intval(r.t);
        end
        r.t( : , value==1 ) = rt;
      end
    else                     % assignment r(i) = b for empty r
      resultIsintval = isa(b.t,'intval');
      for i=1:length(s.subs)
        r.size(i) = max(s.subs{i});
      end
      if length(r.size)==1
        r.size = [1 r.size];
      end
      N = prod(r.size);
      if N>10
        r.t = sparse([],[],[],K1,N);
      else
        r.t = zeros(K1,N);
      end
      index = reshape(1:prod(r.size),r.size);
      r.t(:,index(s.subs{:})) = 0;
      if resultIsintval
        r.t = intval(r.t);
      end
    end
    value = reshape(1:prod(r.size),r.size);
    index = value( s.subs{:} );
    if ( prod(b.size)==1 ) & ( length(index)~=1 )
      r.t(:,index) = repmat(b.t,1,length(index));
    else
      r.t(:,index) = b.t;
    end
    if rEmpty
      r = class(r,'taylor');
    end
  else
    error('invalid index reference for taylor')
  end

  if rndold
    setround(rndold)
  end


function fwseg_dist= comp_fwseg(cleanFile, enhancedFile);

% ----------------------------------------------------------------------
%      Frequency weighted SNRseg Objective Speech Quality Measure
%
%   This function implements the frequency-weighted SNRseg measure [1]
%   using a different weighting function, the clean spectrum.
%
%   Usage:  fwSNRseg=comp_fwseg(cleanFile.wav, enhancedFile.wav)
%
%         cleanFile.wav - clean input file in .wav format
%         enhancedFile  - enhanced output file in .wav format
%         fwSNRseg      - computed frequency weighted SNRseg in dB
%
%         Note that large numbers of fwSNRseg are better.
%
%  Example call:  fwSNRseg =comp_fwseg('sp04.wav','enhanced.wav')
%
%
%  References:
%   [1]  Tribolet, J., Noll, P., McDermott, B., and Crochiere, R. E. (1978).
%        A study of complexity and quality of speech waveform coders. Proc.
%        IEEE Int. Conf. Acoust. , Speech, Signal Processing, 586-590.
%
%   Author: Philipos C. Loizou
%  (critical-band filtering routines were written by Bryan Pellom & John Hansen)
%
% Copyright (c) 2006 by Philipos C. Loizou
% $Revision: 0.0 $  $Date: 10/09/2006 $
% ----------------------------------------------------------------------

if nargin~=2
    fprintf('USAGE: fwSNRseg=comp_fwseg(cleanFile.wav, enhancedFile.wav)\n');
    fprintf('For more help, type: help comp_fwseg\n\n');
    return;
end

[data1, Srate1, Nbits1]= wavread(cleanFile);
[data2, Srate2, Nbits2]= wavread(enhancedFile);
if ( Srate1~= Srate2) | ( Nbits1~= Nbits2)
    error( 'The two files do not match!\n');
end

len= min( length( data1), length( data2));
data1= data1( 1: len)+eps;
data2= data2( 1: len)+eps;

wss_dist_vec= fwseg( data1, data2,Srate1);

fwseg_dist=mean(wss_dist_vec);

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

function distortion = fwseg(clean_speech, processed_speech,sample_rate)

% ----------------------------------------------------------------------
% Check the length of the clean and processed speech.  Must be the same.
% ----------------------------------------------------------------------

clean_length      = length(clean_speech);
processed_length  = length(processed_speech);

if (clean_length ~= processed_length)
  disp('Error: Files  must have same length.');
  return
end

% ----------------------------------------------------------------------
% Global Variables
% ----------------------------------------------------------------------

winlength   = round(30*sample_rate/1000); 	   % window length in samples
skiprate    = floor(winlength/4);		   % window skip in samples
max_freq    = sample_rate/2;	   % maximum bandwidth
num_crit    = 25;		   % number of critical bands
USE_25=1;
n_fft       = 2^nextpow2(2*winlength);
n_fftby2    = n_fft/2;		   % FFT size/2
gamma=0.2;  % power exponent

% ----------------------------------------------------------------------
% Critical Band Filter Definitions (Center Frequency and Bandwidths in Hz)
% ----------------------------------------------------------------------

cent_freq(1)  = 50.0000;   bandwidth(1)  = 70.0000;
cent_freq(2)  = 120.000;   bandwidth(2)  = 70.0000;
cent_freq(3)  = 190.000;   bandwidth(3)  = 70.0000;
cent_freq(4)  = 260.000;   bandwidth(4)  = 70.0000;
cent_freq(5)  = 330.000;   bandwidth(5)  = 70.0000;
cent_freq(6)  = 400.000;   bandwidth(6)  = 70.0000;
cent_freq(7)  = 470.000;   bandwidth(7)  = 70.0000;
cent_freq(8)  = 540.000;   bandwidth(8)  = 77.3724;
cent_freq(9)  = 617.372;   bandwidth(9)  = 86.0056;
cent_freq(10) = 703.378;   bandwidth(10) = 95.3398;
cent_freq(11) = 798.717;   bandwidth(11) = 105.411;
cent_freq(12) = 904.128;   bandwidth(12) = 116.256;
cent_freq(13) = 1020.38;   bandwidth(13) = 127.914;
cent_freq(14) = 1148.30;   bandwidth(14) = 140.423;
cent_freq(15) = 1288.72;   bandwidth(15) = 153.823;
cent_freq(16) = 1442.54;   bandwidth(16) = 168.154;
cent_freq(17) = 1610.70;   bandwidth(17) = 183.457;
cent_freq(18) = 1794.16;   bandwidth(18) = 199.776;
cent_freq(19) = 1993.93;   bandwidth(19) = 217.153;
cent_freq(20) = 2211.08;   bandwidth(20) = 235.631;
cent_freq(21) = 2446.71;   bandwidth(21) = 255.255;
cent_freq(22) = 2701.97;   bandwidth(22) = 276.072;
cent_freq(23) = 2978.04;   bandwidth(23) = 298.126;
cent_freq(24) = 3276.17;   bandwidth(24) = 321.465;
cent_freq(25) = 3597.63;   bandwidth(25) = 346.136;

W=[  % articulation index weights
0.003
0.003
0.003
0.007
0.010
0.016
0.016
0.017
0.017
0.022
0.027
0.028
0.030
0.032
0.034
0.035
0.037
0.036
0.036
0.033
0.030
0.029
0.027
0.026
0.026];

W=W';

if USE_25==0  % use 13 bands
    % ----- lump adjacent filters together ----------------
    k=2;
    cent_freq2(1)=cent_freq(1);
    bandwidth2(1)=bandwidth(1)+bandwidth(2);
    W2(1)=W(1);
    for i=2:13
        cent_freq2(i)=cent_freq2(i-1)+bandwidth2(i-1);
        bandwidth2(i)=bandwidth(k)+bandwidth(k+1);
        W2(i)=0.5*(W(k)+W(k+1));
        k=k+2;
    end

    sumW=sum(W2);
    bw_min      = bandwidth2 (1);	   % minimum critical bandwidth
else
    sumW=sum(W);
    bw_min=bandwidth(1);
end

% ----------------------------------------------------------------------
% Set up the critical band filters.  Note here that Gaussianly shaped
% filters are used.  Also, the sum of the filter weights are equivalent
% for each critical band filter.  Filter less than -30 dB and set to
% zero.
% ----------------------------------------------------------------------

min_factor = exp (-30.0 / (2.0 * 2.303));       % -30 dB point of filter
if USE_25==0

    num_crit=length(cent_freq2);

    for i = 1:num_crit
        f0 = (cent_freq2 (i) / max_freq) * (n_fftby2);
        all_f0(i) = floor(f0);
        bw = (bandwidth2 (i) / max_freq) * (n_fftby2);
        norm_factor = log(bw_min) - log(bandwidth2(i));
        j = 0:1:n_fftby2-1;
        crit_filter(i,:) = exp (-11 *(((j - floor(f0)) ./bw).^2) + norm_factor);
        crit_filter(i,:) = crit_filter(i,:).*(crit_filter(i,:) > min_factor);
    end

else
    for i = 1:num_crit
        f0 = (cent_freq (i) / max_freq) * (n_fftby2);
        all_f0(i) = floor(f0);
        bw = (bandwidth (i) / max_freq) * (n_fftby2);
        norm_factor = log(bw_min) - log(bandwidth(i));
        j = 0:1:n_fftby2-1;
        crit_filter(i,:) = exp (-11 *(((j - floor(f0)) ./bw).^2) + norm_factor);
        crit_filter(i,:) = crit_filter(i,:).*(crit_filter(i,:) > min_factor);
    end
end

num_frames = clean_length/skiprate-(winlength/skiprate); % number of frames
start      = 1;					% starting sample
window     = 0.5*(1 - cos(2*pi*(1:winlength)'/(winlength+1)));

for frame_count = 1:num_frames

   % ----------------------------------------------------------
   % (1) Get the Frames for the test and reference speech.
   %     Multiply by Hanning Window.
   % ----------------------------------------------------------

   clean_frame = clean_speech(start:start+winlength-1);
   processed_frame = processed_speech(start:start+winlength-1);
   clean_frame = clean_frame.*window;
   processed_frame = processed_frame.*window;

   % ----------------------------------------------------------
   % (2) Compute the magnitude Spectrum of Clean and Processed
   % ----------------------------------------------------------

       clean_spec     = abs(fft(clean_frame,n_fft));
       processed_spec = abs(fft(processed_frame,n_fft));

    % normalize spectra to have area of one
    %
    clean_spec=clean_spec/sum(clean_spec(1:n_fftby2));
    processed_spec=processed_spec/sum(processed_spec(1:n_fftby2));

   % ----------------------------------------------------------
   % (3) Compute Filterbank Output Energies
   % ----------------------------------------------------------

   clean_energy=zeros(1,num_crit);
   processed_energy=zeros(1,num_crit);
   error_energy=zeros(1,num_crit);
   W_freq=zeros(1,num_crit);

   for i = 1:num_crit
      clean_energy(i) = sum(clean_spec(1:n_fftby2) ...
                         	.*crit_filter(i,:)');
      processed_energy(i) = sum(processed_spec(1:n_fftby2) ...
          .*crit_filter(i,:)');

        error_energy(i)=max((clean_energy(i)-processed_energy(i))^2,eps);
        W_freq(i)=(clean_energy(i))^gamma;

   end
   SNRlog=10*log10((clean_energy.^2)./error_energy);

   fwSNR=sum(W_freq.*SNRlog)/sum(W_freq);

   distortion(frame_count)=min(max(fwSNR,-10),35);

   start = start + skiprate;

end


% SCRIPT TO TEST THE KINEMATICS OF THE 5R robot
%
% 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/>.

close all

%load the robot
%the robot is represented (interiorly) by two planar 2dof arms
robot=load_robot('example','Delta');

adjust_view(robot)

%Represent a final point in space that will be achieved by the end effector
%P=[Px, Py, Pz]=[0.6 0.4 -0.2]

T=eye(4);
T(1,4)=-0.2;%change, for example, to 0.3
T(2,4)=0.3; %change, for example to 0.6
T(3,4)=-0.5;

%find 8 solutions for the INVERSE KINEMATIC in position
q=inversekinematic(robot, T);

drawrobot3d(robot, q(:,8)), pause(2);
drawrobot3d(robot, q(:,7)), pause(2);
drawrobot3d(robot, q(:,6)), pause(2);
drawrobot3d(robot, q(:,5)), pause(2);
drawrobot3d(robot, q(:,4)), pause(2);
drawrobot3d(robot, q(:,3)), pause(2);
drawrobot3d(robot, q(:,2)), pause(2);
drawrobot3d(robot, q(:,1)), pause(2);

% now solve the DIRECTKINEMATIC problem for each of the above computed q
% In this case, only the "down" solution is returned
T=directkinematic(robot,q(:,1))
T=directkinematic(robot,q(:,2))
T=directkinematic(robot,q(:,3))
T=directkinematic(robot,q(:,4))
T=directkinematic(robot,q(:,5))
T=directkinematic(robot,q(:,6))
T=directkinematic(robot,q(:,7))
T=directkinematic(robot,q(:,8))


function [ a, b ] = p08_ab ( m )

%*****************************************************************************80
%
%% P08_AB evaluates the limits of the optimization region for problem 08.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 December 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Marcin Molga, Czeslaw Smutnicki,
%    Test functions for optimization needs.
%
%  Parameters:
%
%    Input, integer M, the spatial dimension.
%
%    Output, real A(M), B(M), the lower and upper bounds.
%
  a(1:m) = - 1.0;
  b(1:m) = + 1.0;

  return
end


function [predicted_label] = rec_test(model)
% Given the full 3D shape, recognition test for a generative model.
% After the model is (generatively) trained, this function test the
% recognition ability(discriminative) of the model using a seperate test
% data.
% The classification method is free-energy.

debug = 0;
if ~isfield(model.layers{2},'uw')
    model = merge_model(model);
end
global kConv_forward2 kConv_forward_c;

num_layer = length(model.layers);

test_list = read_data_list(model.data_path, model.classnames, ...
    model.volume_size + 2 * model.pad_size, 'test', debug);

label = [];
new_list = repmat(struct('filename', '', 'label', 0), 1, 1);
now = 1;
for i = 1 : model.classes
    cnt = length(test_list{i});
    label(now:now+cnt-1,1) = i;
    new_list(now:now+cnt-1,1) = test_list{i};
    now = now + cnt;
end
n = length(label);

batch_size = 32;
batch_num = ceil(n / batch_size);
predicted_label = zeros(n, model.classes); % prediction results.
for b = 1 : batch_num
    batch_end = min(n, b * batch_size);
	batch_index = (b-1)*batch_size + 1 : batch_end;
    batch_data = read_batch(model, new_list(batch_index), false);
    this_size = size(batch_data, 1);

    % propagate/inference bottum up using recognition weight.
    for l = 2 : num_layer - 1
        if l == 2
            stride = model.layers{l}.stride;
            hidden_presigmoid = myConvolve2(kConv_forward2, batch_data, model.layers{l}.uw, stride, 'forward');
            hidden_presigmoid = bsxfun(@plus, hidden_presigmoid, permute(model.layers{l}.c, [2,3,4,5,1]));
        elseif strcmp(model.layers{l}.type, 'convolution')
            stride = model.layers{l}.stride;
            hidden_presigmoid = myConvolve(kConv_forward_c, batch_data, model.layers{l}.uw, stride, 'forward');
            hidden_presigmoid = bsxfun(@plus, hidden_presigmoid, permute(model.layers{l}.c, [2,3,4,5,1]));
        else
            batch_data = reshape(batch_data, size(batch_data,1), []);
            hidden_presigmoid = bsxfun(@plus, ...
                batch_data * model.layers{l}.uw, model.layers{l}.c);
        end
        batch_data = 1 ./ ( 1 + exp(-hidden_presigmoid) );
    end

    batch_data = reshape(batch_data, this_size, []);
    % calculate the free energy for each label hypothesis
    for c = 1 : model.classes
        try_label = zeros(this_size, model.classes);
        try_label(:, c) = 1;
        predicted_label((b-1) * batch_size+1: batch_end, c) = free_energy(model, [try_label, batch_data], num_layer);
    end

end

predicted_label = bsxfun(@rdivide, predicted_label, sum(predicted_label, 2));
[~, predicted_label] = max(predicted_label, [], 2);

acc = sum(predicted_label == label) / n;
fprintf('acc is : %f\n', acc * 100);


clear all;
cd('./MLP');
disp('Testing training a multilayer perceptron.')
Main_MNIST_MLP_RMSPROP();
cd ..

clear all;

cd('./ReinforcementLearning');
disp('Testing training a Q-network.')
Main_Cart_Pole_Q_Network
cd ..

clear all;

cd('./ReinforcementLearning');
disp('Testing training a policy network.')
Main_Cart_Pole_Policy_Network
cd ..

clear all;
cd('./RNN');
disp('Testing training a Quasi-RNN.')
Main_Char_RNN();
cd ..

clear all;
cd('./CNN');
disp('Testing using a pretrained ImageNet convolutional neural network model.')
Main_CNN_ImageNet_minimal();
cd ..

clear all;
cd('./CNN');
disp('Testing training a new convolutional neural network using SGD.')
disp('An Nvidia GPU is required by default.')
disp('If you do not have it please set use_gpu=0')
disp('Neural Network Toolbox is required by default.')
disp('If you do not have it please set opts.use_nntoolbox=0')
Main_CIFAR_CNN_SGD();
cd ..

clear all;
disp('Second-order SGD test 1.')
cd('./SGD2');
disp('Testing training a new convolutional neural network using SGD2.')
disp('An Nvidia GPU is required by default.')
disp('If you do not have it please set use_gpu=0')
disp('Neural Network Toolbox is required by default.')
disp('If you do not have it please set opts.use_nntoolbox=0')
Main_CIFAR_CNN_SGD2();
cd ..

clear all;
cd('./SGD2');
disp('Second-order SGD test 2.')
disp('SGD2 initialization tests.')
MNIST_Deep_MLP_Init_Comparison();
cd ..


function [satpos,satclk,vare,varc,stat]=pephpos(time,sat,nav)

global glc
stat=1; norder=10; %polynomial fitting order
tdiff=zeros(norder+1,1); p=zeros(3,norder+1);
satpos=zeros(3,1); s=zeros(3,1); satclk=0;
varc=0;vare=0;

if nav.np<norder||timediff(time,nav.peph(1).time)<-900||...
        timediff(time,nav.peph(end).time)>900
    stat=0; return;
end

%binary search
i=0;
j=nav.np-1;
while i<j
    k=fix((i+j)/2);
    if timediff(nav.peph(k+1).time,time)<0
        i=k+1;
    else
        j=k;
    end
end

if i<=0,index=0;  else,index=i-1;  end
index=index+1;

idx=index-norder/2; %start of fitting interval
if idx<1,idx=1;  elseif idx+norder>nav.np,idx=nav.np-norder;  end

nt=1;
for j=0:norder
    tdiff(nt)=timediff(nav.peph(idx+j).time,time); %time difference
    nt=nt+1;
    if dot(nav.peph(idx+j).pos(sat,1:3),nav.peph(idx+j).pos(sat,1:3))<=0
        stat=0; return;
    end
end

for j=0:norder
    pos=nav.peph(idx+j).pos(sat,:);

    %correciton for earh rotation
    sinl=sin(glc.OMGE*tdiff(j+1));
    cosl=cos(glc.OMGE*tdiff(j+1));

    p(1,j+1)=cosl*pos(1)-sinl*pos(2);
    p(2,j+1)=sinl*pos(1)+cosl*pos(2);
    p(3,j+1)=pos(3);

end

%polynomial interpolation using Neville's algorithm
for i=1:3
    satpos(i,1)=polyinter(tdiff,p(i,:));
end

%calculate satellite position variance
for i=1:3
    s(i)=nav.peph(index).std(sat,i);
end
std=sqrt(dot(s,s)); %error caused by ephemeris
if tdiff(1)>0
    std=std+(5E-7*tdiff(1)^2)/2; %error caused by fitting
elseif tdiff(end)<0
    std=std+(5E-7*tdiff(end)^2)/2;
end
vare=std^2;

%linear interpolation for clock
t0=timediff(time,nav.peph(index).time);
t1=timediff(time,nav.peph(index+1).time);
c0=nav.peph(index).pos(sat,4);
c1=nav.peph(index+1).pos(sat,4);

if t0<=0
    satclk=c0;
    if satclk~=0
        varc=(nav.peph(index).std(sat,4)*glc.CLIGHT-1E-3*t0)^2;
    end
elseif t1>=0
    satclk=c1;
    if satclk~=0
        varc=(nav.peph(index+1).std(sat,4)*glc.CLIGHT+1E-3*t1)^2;
    end
elseif c0~=0 && c1~=0
    satclk=(c1*t0-c0*t1)/(t0-t1);
    if abs(t0)-abs(t1)>0
        varc=(nav.peph(index+1).std(sat,4)*glc.CLIGHT+1E-3*abs(t1))^2;
    else
        varc=(nav.peph(index).std(sat,4)*glc.CLIGHT+1E-3*abs(t0))^2;
    end
else
    satclk=0;
    varc=0;
end

return


clc;
close all;
clear all;

[num,txt,raw] = xlsread('data\final105.xls');

descriptions = raw(2:size(raw,1),2);
style_ratings = num(1:size(num,1),1);
comfort_ratings = num(1:size(num,1),4);
overal_ratings = num(1:size(num,1),5);

productids = cell2mat(raw(2:size(raw,1),7));
uniqueprodids =unique(productids);
outputdata = [];
outputdesc = {};

for productid = 1:size(uniqueprodids,1)

    rawdataindex = (find(productids==uniqueprodids(productid)));
    temp_style_rating = mean(style_ratings(rawdataindex));
    temp_comfort_ratings = mean(comfort_ratings(rawdataindex));
    temp_overal_ratings = mean(overal_ratings(rawdataindex));
    temp_individual_desc = descriptions(rawdataindex);
    temp_descriptions = strcat(temp_individual_desc{:},' ');
    outputdata = [outputdata; temp_style_rating, temp_comfort_ratings, temp_overal_ratings];
    outputdesc{end+1} = temp_descriptions;
end

hist(outputdata,500)
tic
%featurize_parallel(inputcellarray, nminFeatures, removeStopWords, doStem, grams, cores)
[featureVector,selectedheaderskeys] = featurize_parallel(outputdesc', 20, 0, 1, 1, 4);
toc
csvwrite('data\productsdesc.csv', featureVector);
csvwrite('data\productsvocab.csv', selectedheaderskeys);
csvwrite('data\productsratings.csv', outputdata);
%


function [im,lv,rv,myo] = ventricles_phantom(m,v)
% VENTRICLES_PHANTOM Create phantom image of simplified heart ventricles
%
% [IM,LV,RV,MYO] = ventricles(M,V)
%
%   IM is a 3D image that consists of a heart phantom depicting the left
%   ventricle, right ventricle and myocardium
%
%   LV is a 3D image that consists of the LV cavity phantom
%
%   RV is a 3D image that consists of the RV cavity phantom
%
%   MYO is a 3D image that consists of a myocardium phantom
%
%   M is the mean Gaussian white noise added to the final heart phantom
%   generated (the default value is zero)
%
%   V is the the variance of the Gaussian white noise added to the final
%   heart phantom generated (the default value is zero)

% Author: Christopher Kelly <christopher.kelly28@gmail.com>
% Copyright © 2013 University of Oxford
% Version: 0.1.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% 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.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% check arguments

narginchk(0,2);
nargoutchk(0,4);

% default values

if (nargin == 1)
    error('You must either specify all 2 input parameters or none at all')
elseif (nargin < 2)
    m      = 0;
    v      = 0;
end

% TODO: we hard-code these values. In the future, we may want to have these
% as input arguments, but currently changing these values produces odd
% looking results
lvendo = 300;
lvepi  = 400;
rvendo = 300;
rvepi  = 400;

%% create image space

xRange = -(128/2) + 0.5 : (128/2) - 0.5;
yRange = xRange;
zRange = xRange;

[ x, y, z ] = ndgrid( xRange, yRange, zRange );

im = zeros(size(x));

lv = im;
rv = im;
myo = im;
heart = im;

%% define ellipsoids shapes

radius1 = ( (x).^2 + (y).^2 + (z/2).^2 );
radius2 = ( (x).^2 + (y/1.7).^2 + (z/2).^2 );

%% define voxels in left ventricle wall

% define LV ellpsoid edge thickness
ellipsoid1Outer = find(radius1 < lvepi );
ellipsoid1Inner = find(radius1 < lvendo );

% define LV ellipsoid
ellipsoid1 = ismember(ellipsoid1Outer,ellipsoid1Inner);
ellipsoid1 = ellipsoid1Outer(ellipsoid1 == 0);

[ellipsoid1X, ellipsoid1Y,ellipsoid1Z] = ind2sub(size(im),ellipsoid1);

ellipsoid1X(ellipsoid1Z > 70) = [];
ellipsoid1Y(ellipsoid1Z > 70) = [];
ellipsoid1Z(ellipsoid1Z > 70) = [];

% find voxel numbers that will make up LV wall
LV_wall = sub2ind(size(im),ellipsoid1X,ellipsoid1Y,ellipsoid1Z);

%% define voxels in right ventricle wall

% define RV ellpsoid edge thickness
ellipsoid2Outer = find(radius2 < rvepi );
ellipsoid2Inner = find(radius2 < rvendo );

% define RV ellipsoid
ellipsoid2 = ismember(ellipsoid2Outer, ellipsoid2Inner);
ellipsoid2 = ellipsoid2Outer(ellipsoid2 == 0);                                	% find voxel numbers that will make up RV wall

[ellipsoid2X, ellipsoid2Y,ellipsoid2Z] = ind2sub(size(im),ellipsoid2);

ellipsoid2X(ellipsoid2Z > 70) = [];
ellipsoid2Y(ellipsoid2Z > 70) = [];
ellipsoid2Z(ellipsoid2Z > 70) = [];

ellipsoid2X(ellipsoid2Y > (size(im,2)/2)) = [];
ellipsoid2Z(ellipsoid2Y > (size(im,2)/2)) = [];
ellipsoid2Y(ellipsoid2Y > (size(im,2)/2)) = [];

RV_wall = sub2ind(size(im),ellipsoid2X,ellipsoid2Y,ellipsoid2Z);

%% define left ventricle

lv(radius1 < lvendo) = 1;

LVellipsoid = find(lv == 1);
[LVellipsoidX, LVellipsoidY, LVellipsoidZ] = ind2sub(size(im),LVellipsoid);

LVellipsoidX(LVellipsoidZ < 70) = [];
LVellipsoidY(LVellipsoidZ < 70) = [];
LVellipsoidZ(LVellipsoidZ < 70) = [];

LVellipsoid = sub2ind(size(im),LVellipsoidX, LVellipsoidY, LVellipsoidZ);
lv(LVellipsoid) = 0;

%% define right ventricle

rv(radius2 < rvendo) = 1;

RVellipsoid = find(rv == 1);
[RVellipsoidX, RVellipsoidY, RVellipsoidZ] = ind2sub(size(im),RVellipsoid);

RVellipsoidX( (RVellipsoidZ < 70) ) = [];
RVellipsoidY( (RVellipsoidZ < 70) ) = [];
RVellipsoidZ( (RVellipsoidZ < 70) ) = [];

RVellipsoid = sub2ind(size(im),RVellipsoidX, RVellipsoidY, RVellipsoidZ);
rv(RVellipsoid) = 0;

RVellipsoid = find(rv == 1);
[RVellipsoidX, RVellipsoidY, RVellipsoidZ] = ind2sub(size(im),RVellipsoid);

RVellipsoidX(RVellipsoidY < (size(im,2)/2)) = [];
RVellipsoidZ(RVellipsoidY < (size(im,2)/2)) = [];
RVellipsoidY(RVellipsoidY < (size(im,2)/2)) = [];

RVellipsoid = sub2ind(size(im),RVellipsoidX, RVellipsoidY, RVellipsoidZ);
rv(RVellipsoid) = 0;

rv([LV_wall;find(lv == 1)]) = 0;

%% define myocardium

myo([LV_wall;RV_wall]) = 1;

%% define heart

heart( lv == 1 ) = 1;
heart( rv == 1 ) = 2;
heart( myo == 1 ) = 3;

%% add noise

heart = (heart - min(heart(:)))/(max(max(max(heart)))-min(min(min(heart))));

for i = 1:size(im,3)
    heart(:,:,i) = imnoise(heart(:,:,i),'Gaussian',m,v);
    lv(:,:,i) = imnoise(lv(:,:,i),'Gaussian',m,v);
    rv(:,:,i) = imnoise(rv(:,:,i),'Gaussian',m,v);
    myo(:,:,i) = imnoise(myo(:,:,i),'Gaussian',m,v);
end

im = heart;


function out = linearlcc(in, quantization)
%  @inproceedings{zhang2017learning,
%    title={Learning Deep CNN Denoiser Prior for Image Restoration},
%    author={Zhang, Kai and Zuo, Wangmeng and Gu, Shuhang and Zhang, Lei},
%    booktitle={IEEE Conference on Computer Vision and Pattern Recognition},
%    pages={3929--3938},
%    year={2017},
%  }
%quantization = 0;
% in : uint8; RGB or Bayer pattern [0~255];
% out: double/uint8: RGB [0~255];

[m,n,ch]=size(in);
% if ch==3
%     B=zeros(m,n);
%     B(1:2:m,1:2:n)=in(1:2:m,1:2:n,2);
%     B(2:2:m,2:2:n)=in(2:2:m,2:2:n,2);
%     B(1:2:m,2:2:n)=in(1:2:m,2:2:n,1);
%     B(2:2:m,1:2:n)=in(2:2:m,1:2:n,3);
%     in=B;
%     clear B;
% end

in = double(in);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% function out = lcc1(in)
% returns the color interpolated image using Laplacian
% second-order color correction I
%
% Assumptions : in has following color patterns
%
%  ------------------> grbg
%  |  G R G R ...
%  |  B G B G ...
%  |  G R G R ...
%  |  B G B G ...
%  |  . . . . .

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

inR = in; inG = in; inB = in;
out = in;
outR = inR; outG = inG; outB = inB;

% G channel
for i=4:2:m-2,
    for j=3:2:n-3,
        delta_H = abs(inB(i,j-2)+inB(i,j+2)-2*inB(i,j))+abs(inG(i,j-1)-inG(i,j+1));
        delta_V = abs(inB(i-2,j)+inB(i+2,j)-2*inB(i,j))+abs(inG(i-1,j)-inG(i+1,j));
        if delta_H < delta_V,
            outG(i,j) = 1/2*(inG(i,j-1)+inG(i,j+1))+1/4*(2*inB(i,j)-inB(i,j-2)-inB(i,j+2));
        elseif delta_H > delta_V,
            outG(i,j) = 1/2*(inG(i-1,j)+inG(i+1,j))+1/4*(2*inB(i,j)-inB(i-2,j)-inB(i+2,j));
        else
            outG(i,j) = 1/4*(inG(i,j-1)+inG(i,j+1)+inG(i-1,j)+inG(i+1,j))+1/8*(4*inB(i,j)-inB(i,j-2)-inB(i,j+2)-inB(i-2,j)-inB(i+2,j));
        end
    end
end

for i=3:2:m-3,
    for j=4:2:n-2,
        delta_H = abs(inR(i,j-2)+inR(i,j+2)-2*inR(i,j))+abs(inG(i,j-1)-inG(i,j+1));
        delta_V = abs(inR(i-2,j)+inR(i+2,j)-2*inR(i,j))+abs(inG(i-1,j)-inG(i+1,j));
        if delta_H < delta_V,
            outG(i,j) = 1/2*(inG(i,j-1)+inG(i,j+1))+1/4*(2*inR(i,j)-inR(i,j-2)-inR(i,j+2));
        elseif delta_H > delta_V,
            outG(i,j) = 1/2*(inG(i-1,j)+inG(i+1,j))+1/4*(2*inR(i,j)-inR(i-2,j)-inR(i+2,j));
        else
            outG(i,j) = 1/4*(inG(i,j-1)+inG(i,j+1)+inG(i-1,j)+inG(i+1,j))+1/8*(4*inR(i,j)-inR(i,j-2)-inR(i,j+2)-inR(i-2,j)-inR(i+2,j));
        end
    end
end

% R channel
for i=1:2:m-1,
    outR(i,3:2:n-1) = 1/2*(inR(i,2:2:n-2)+inR(i,4:2:n))+1/4*(2*outG(i,3:2:n-1)-outG(i,2:2:n-2)-outG(i,4:2:n));
end

for i=2:2:m-2,
    outR(i,2:2:n) = 1/2*(inR(i-1,2:2:n)+inR(i+1,2:2:n))+1/4*(2*outG(i,2:2:n)-outG(i-1,2:2:n)-outG(i+1,2:2:n));
end

for i=2:2:m-2,
    for j=3:2:n-1,
        delta_P = abs(inR(i-1,j+1)-inR(i+1,j-1))+abs(2*outG(i,j)-outG(i-1,j+1)-outG(i+1,j-1));
        delta_N = abs(inR(i-1,j-1)-inR(i+1,j+1))+abs(2*outG(i,j)-outG(i-1,j-1)-outG(i+1,j+1));
        if delta_N < delta_P,
            outR(i,j) = 1/2*(inR(i-1,j-1)+inR(i+1,j+1))+1/2*(2*outG(i,j)-outG(i-1,j-1)-outG(i+1,j+1));
        elseif delta_N > delta_P,
            outR(i,j) = 1/2*(inR(i-1,j+1)+inR(i+1,j-1))+1/2*(2*outG(i,j)-outG(i-1,j+1)-outG(i+1,j-1));
        else
            outR(i,j) = 1/4*(inR(i-1,j-1)+inR(i-1,j+1)+inR(i+1,j-1)+inR(i+1,j+1))+1/4*(4*outG(i,j)-outG(i-1,j-1)-outG(i-1,j+1)-outG(i+1,j-1)-outG(i+1,j+1));
        end
    end
end

% B channel
for i=2:2:m,
    outB(i,2:2:n-2) = 1/2*(inB(i,1:2:n-3)+inB(i,3:2:n-1))+1/4*(2*outG(i,2:2:n-2)-outG(i,1:2:n-3)-outG(i,3:2:n-1));
end

for i=3:2:m-1,
    outB(i,1:2:n-1) =  1/2*(inB(i-1,1:2:n-1)+inB(i+1,1:2:n-1))+1/4*(2*outG(i,1:2:n-1)-outG(i-1,1:2:n-1)-outG(i+1,1:2:n-1));
end

for i=3:2:m-1,
    for j=2:2:n-2,
        delta_P = abs(inB(i-1,j+1)-inB(i+1,j-1))+abs(2*outG(i,j)-outG(i-1,j+1)-outG(i+1,j-1));
        delta_N = abs(inB(i-1,j-1)-inB(i+1,j+1))+abs(2*outG(i,j)-outG(i-1,j-1)-outG(i+1,j+1));
        if delta_N < delta_P,
            outB(i,j) = 1/2*(inB(i-1,j-1)+inB(i+1,j+1))+1/2*(2*outG(i,j)-outG(i-1,j-1)-outG(i+1,j+1));
        elseif delta_N > delta_P,
            outB(i,j) = 1/2*(inB(i-1,j+1)+inB(i+1,j-1))+1/2*(2*outG(i,j)-outG(i-1,j+1)-outG(i+1,j-1));
        else
            outB(i,j) = 1/4*(inB(i-1,j-1)+inB(i-1,j+1)+inB(i+1,j-1)+inB(i+1,j+1))+1/4*(4*outG(i,j)-outG(i-1,j-1)-outG(i-1,j+1)-outG(i+1,j-1)-outG(i+1,j+1));
        end
    end
end

out(:,:,1) = outR;
out(:,:,2) = outG;
out(:,:,3) = outB;

if quantization
    out = uint8(out);
end


grayFileName='test.gray';

[gNodes, gEdges, gvSize] = readGrayGraph_progress(grayFileName,0);

% Do all the gray node stages in a loop so that we can have arbitrary
% numbers of layers.
numGrayLayers=max(gNodes(6,:));

% Get the indices for all the gnodes (all layers)
for t=1:numGrayLayers
    grayNodeIndices{t}=find(gNodes(6,:)==t);
end

% Extract the layer 1 nodes. These are special because they are used to map
% down to the unfolded boundary mesh.

l1gNodes=gNodes(:,grayNodeIndices{1});
l1mesh.vertices=l1gNodes(1:3,:);
l1mesh.indices=grayNodeIndices{1};

% How many gNodes are there?
nGnodes=length(gNodes);
% How many gEdges are there?
nGedges=length(gEdges);

% We want to make a grey node connection matrix - which grey nodes are connected to which other gnodes?
%statusStringAdd(statusHandle,'Finding grey connection matrix (slow)');

grayConMat=makeGrayConMat(gNodes,gEdges,0);

% We can assign layer 1 grey nodes to the white matter mesh using assignToNearest.dll (see assignToNearest.c)
% Can't do this for higher levels of grey matter 'cos they might get mis-assigned. (Also, potential problem near
% very crinkly edges. - Could we accidentally assign a l1 grey matter node to the wrong WM point?)
% (I think the answer is 'yes, rarely'. If a single layer or gray is sandwiched between two sides of a sulcus (say) : It's grown from
% one side but mrFlatMesh has no way of telling which one.
% Going deeper into mrGray's source code to determine the parentage of l1 gray nodes might be possible...)

% So for higher grey matter points, we have to restrict the possible sub node search space by assigning them >only< to
% points they are connected to. Note that a single layer2 grey node may be connected to several l1 nodes

% The gray may be defined over the entire mesh but we only want to deal with gray points over the
% unfolded part. The strategy should be....
% 1) do assignToNearest for each mesh point to find the nearest connected l1 node
% 2) Use the set of l1 nodes found in 1) to build up a list of other connected gray nodes
% 3) Repeat stage 2 for l3,l4

%statusStringAdd(statusHandle,'Mapping L1 to mesh.');

% Find 3D coords of all the l1 gnodes
l1GNodeCoords=l1gNodes(1:3,:)';

% Find conmat of l1 gNodes
l1conMat=grayConMat(grayNodeIndices{1},grayNodeIndices{1});

% Find the 3d neighbour distances
mesh.connectionMatrix=l1conMat;
mesh.uniqueVertices=l1GNodeCoords;
scaleFactor=[1 1 1];

D=find3DNeighbourDists(mesh,scaleFactor); % We're now in a voxel framework: everything has been scaled in the mrReadMrM function.
perimDist=30;
startNode=1000; % I don't know where this is
mesh.dist=dijkstra(D,startNode);

mesh.perimDist=perimDist;

[perimeterEdges,eulerCondition]=findLegalPerimeters(mesh,perimDist);
gplot3(mesh.connectionMatrix,mesh.uniqueVertices) ;


% =========================================================================
% (c) 2018 Ronald Nissel, ronald.nissel@gmail.com
% =========================================================================
% Allows to reproduce Figure 2, 3, 4 and 5 of "Doubly-Selective Channel
% Estimation in FBMC-OQAM and OFDM Systems", R. Nissel, et al, IEEE VTC
% Fall, 2018. In particular, this script simulates an FBMC and OFDM
% transmission over a doubly-selective channel, including doubly-selective
% MMSE channel estimation and interference cancellation. Note that, to
% truly reproduce the figures, the lines 41-46 must be uncommented.

clear; close all;
addpath('./Theory');

%% Parameters
% Simulation
M_SNR_dB                  = [10:5:40];              % Signal-to-Noise Ratio in dB
NrRepetitions             = 25;                     % Number of Monte Carlo repetition (different channel realizations)
ZeroThresholdSparse       = 8;                      % Set some matrix values, smaller than "10^(-ZeroThresholdSparse)", to zero.
PlotIterationStepsSNRdB   = 35;                     % Plot the BER over iteration step for an SNR of 35dB.

% FBMC and OFDM parameters
L                         = 12*2;                   % Number of Subcarriers, one resource block consists of 12 subcarriers (and 0.5ms in time)
F                         = 15e3;                   % Subcarrier Spacing in Hz
SamplingRate              = F*12*2;                 % Sampling rate in (Samples/s)
NrSubframes               = 1;                      % Number of subframes. One subframe requires 1ms for F=15kHz.
QAM_ModulationOrder       = 256;                    % QAM signal constellation order, 4, 16, 64, 256, 1024,...

% Channel estimation parameters
PilotToDataPowerOffset    = 2;                      % Pilot to data power offset for OFDM. In FBMC data spreading, the power offset is twice this number.
PilotToDataPowerOffsetAux = 4.685;                  % Pilot to data power offset for FBMC, auxiliary method.
NrIterations              = 4;                      % Number of iterations for interference cancellation scheme.

% Channel
Velocity_kmh              = 500;                    % Velocity in km/h. Note that [mph]*1.6=[kmh] and [m/s]*3.6=[kmh]
PowerDelayProfile         = 'VehicularA';           % Channel model, either string or vector: 'Flat', 'AWGN', 'PedestrianA', 'PedestrianB', 'VehicularA', 'VehicularB', 'ExtendedPedestrianA', 'ExtendedPedestrianB', or 'TDL-A_xxns','TDL-B_xxns','TDL-C_xxns' (with xx the RMS delay spread in ns, e.g. 'TDL-A_30ns'), or [1 0 0.2] (Self-defined power delay profile which depends on the sampling rate)

% ###########################################################################
% % In the paper:
% M_SNR_dB                = [10:2:40];
% PlotIterationStepsSNRdB = 32;
% NrRepetitions           = 1000;
% SamplingRate            = F*14*14;
% NrSubframes             = 2;
% ###########################################################################

%% FBMC Object
FBMC = Modulation.FBMC(...
    L,...                               % Number subcarriers
    30*NrSubframes,...                  % Number FBMC symbols
    F,...                               % Subcarrier spacing (Hz)
    SamplingRate,...                    % Sampling rate (Samples/s)
    0,...                               % Intermediate frequency first subcarrier (Hz)
    false,...                           % Transmit real valued signal
    'Hermite-OQAM',...                  % Prototype filter (Hermite, PHYDYAS, RRC) and OQAM or QAM,
    8, ...                              % Overlapping factor (also determines oversampling in the frequency domain)
    0, ...                              % Initial phase shift
    true ...                            % Polyphase implementation
    );

%% OFDM Object (Add zeroes to the OFDM signal so that it fits the FBMC signal)
ZeroGuardTimeLength = ((FBMC.Nr.SamplesTotal-(round((1/15e3/14)*SamplingRate)+round(SamplingRate/15e3))*14*NrSubframes)/2)/SamplingRate;
OFDM = Modulation.OFDM(...
    L,...                           % Number Subcarriers
    14*NrSubframes,...              % Number OFDM Symbols
    F,...                           % Subcarrier spacing (Hz)
    SamplingRate,...                % Sampling rate (Samples/s)
    0,...                           % Intermediate frequency first subcarrier (Hz)
    false,...                       % Transmitreal valued signal
    1/15e3/14, ...                  % Cyclic prefix length (s)
    ZeroGuardTimeLength ...         % Zero guard length (s)
    );

%% Check Number of Samples
if  OFDM.Nr.SamplesTotal~=FBMC.Nr.SamplesTotal
   error('Total number of samples must be the same for OFDM and FBMC.');
end
N = OFDM.Nr.SamplesTotal;

%% PAM and QAM Object
PAM = Modulation.SignalConstellation(sqrt(QAM_ModulationOrder),'PAM');
QAM = Modulation.SignalConstellation(QAM_ModulationOrder,'QAM');

%% Pilot Matrices, 0="Data", 1=Pilot
PilotMatrix_OFDM = zeros(OFDM.Nr.Subcarriers,14);
PilotMatrix_OFDM(2:2*6:end,2:2*3.5:end)=1;
PilotMatrix_OFDM(5:2*6:end,6:2*3.5:end)=1;
PilotMatrix_OFDM(8:2*6:end,2:2*3.5:end)=1;
PilotMatrix_OFDM(11:2*6:end,6:2*3.5:end)=1;
PilotMatrix_OFDM = repmat(PilotMatrix_OFDM,[1 NrSubframes]);

PilotMatrix_FBMC =  zeros(FBMC.Nr.Subcarriers,30);
PilotMatrix_FBMC(2:12:end,3:16:end) = 1;
PilotMatrix_FBMC(5:12:end,11:16:end) = 1;
PilotMatrix_FBMC(8:12:end,3+1:16:end) = 1;
PilotMatrix_FBMC(11:12:end,11+1:16:end) = 1;
PilotMatrix_FBMC = repmat(PilotMatrix_FBMC,[1 NrSubframes]);

AuxilaryPilotMatrix_FBMC = PilotMatrix_FBMC;
[a,b] = find(PilotMatrix_FBMC);
for i_pilot = 1:length(a)
    AuxilaryPilotMatrix_FBMC(a(i_pilot)+1,b(i_pilot))=-1;
    AuxilaryPilotMatrix_FBMC(a(i_pilot)-1,b(i_pilot))=-1;
    AuxilaryPilotMatrix_FBMC(a(i_pilot),b(i_pilot)+1)=-1;
    AuxilaryPilotMatrix_FBMC(a(i_pilot),b(i_pilot)-1)=-1;
end

%% Cancel Imaginary Interference At Pilot Position Object (Precoding Matrix)
AuxiliaryMethod = ChannelEstimation.ImaginaryInterferenceCancellationAtPilotPosition(...
    'Auxiliary', ...                                    % Cancellation method
    AuxilaryPilotMatrix_FBMC, ...                       % PilotAndAuxiliaryMatrix
    FBMC.GetFBMCMatrix, ...                             % Imaginary interference matrix
    28, ...                                             % Cancel 28 closest interferers
    PilotToDataPowerOffsetAux ...                       % Pilot to data power offset
    );
CodingMethod = ChannelEstimation.ImaginaryInterferenceCancellationAtPilotPosition(...
    'Coding', ...                                       % Cancellation method
    PilotMatrix_FBMC, ...                               % PilotMatrix
    FBMC.GetFBMCMatrix, ...                             % Imaginary interference matrix
    20, ...                                             % Cancel 28 closest interferers
    2*PilotToDataPowerOffset ...                        % Pilot to data power offset
    );

NrPilotSymbols = sum(PilotMatrix_OFDM(:)==1);
NrDataSymbols_OFDM = sum(PilotMatrix_OFDM(:)==0);

PilotMapping_OFDM = zeros(numel(PilotMatrix_OFDM));
PilotMapping_OFDM(PilotMatrix_OFDM(:)==1,1:NrPilotSymbols) = sqrt(PilotToDataPowerOffset)*eye(NrPilotSymbols);
PilotMapping_OFDM(PilotMatrix_OFDM(:)==0,NrPilotSymbols+1:end) = eye(NrDataSymbols_OFDM);
PilotMapping_OFDM = PilotMapping_OFDM/sqrt(mean(diag(PilotMapping_OFDM*PilotMapping_OFDM')));
DataPowerReduction_OFDM = numel(PilotMatrix_OFDM)/(NrPilotSymbols*PilotToDataPowerOffset+NrDataSymbols_OFDM);

Kappa_Aux  = AuxiliaryMethod.PilotToDataPowerOffset*AuxiliaryMethod.DataPowerReduction;
Kappa_Cod  = CodingMethod.PilotToDataPowerOffset*CodingMethod.DataPowerReduction;
Kappa_OFDM = PilotToDataPowerOffset*DataPowerReduction_OFDM;

%% Evaluate only the BER near the center. i.e., ignore edges
ConsideredTimeFrequencyPositions_FBMC = zeros(size(PilotMatrix_FBMC));
ConsideredTimeFrequencyPositions_FBMC(5:end-4,11:end-10)= 1;

ConsideredTimeFrequencyPositions_OFDM = zeros(size(PilotMatrix_OFDM));
ConsideredTimeFrequencyPositions_OFDM(5:end-4,6:end-5)= 1;

for i_lk = 1: AuxiliaryMethod.NrDataSymbols
    xD_Temp = zeros(AuxiliaryMethod.NrDataSymbols,1);
    xD_Temp(i_lk) = 1;
    x_FBMC_Aux = AuxiliaryMethod.PrecodingMatrix*[zeros(NrPilotSymbols,1);xD_Temp];
    ConsideredDataPositions_FBMC_Aux(i_lk) = sum(abs(x_FBMC_Aux(1==ConsideredTimeFrequencyPositions_FBMC.*not(AuxilaryPilotMatrix_FBMC))))>AuxiliaryMethod.DataPowerReduction*0.9;
end
for i_lk = 1: CodingMethod.NrDataSymbols
    xD_Temp = zeros(CodingMethod.NrDataSymbols,1);
    xD_Temp(i_lk) = 1;
    x_FBMC_Cod = CodingMethod.PrecodingMatrix*[zeros(NrPilotSymbols,1);xD_Temp];
    ConsideredDataPositions_FBMC_Cod(i_lk) =not(any(x_FBMC_Cod(not(ConsideredTimeFrequencyPositions_FBMC))));
end
for i_lk = 1: NrDataSymbols_OFDM
    xD_Temp = zeros(NrDataSymbols_OFDM,1);
    xD_Temp(i_lk) = 1;
    x_OFDM = PilotMapping_OFDM*[zeros(NrPilotSymbols,1);xD_Temp];
    ConsideredDataPositions_OFDM(i_lk) = sum(abs(x_OFDM(1==ConsideredTimeFrequencyPositions_OFDM.*not(PilotMatrix_OFDM))))>DataPowerReduction_OFDM*0.9;
end

ConsideredBits_FBMC_Aux = reshape(repmat(ConsideredDataPositions_FBMC_Aux,log2(QAM_ModulationOrder)/2,1),[],1);
ConsideredBits_FBMC_Cod = reshape(repmat(ConsideredDataPositions_FBMC_Cod,log2(QAM_ModulationOrder)/2,1),[],1);
ConsideredBits_OFDM     = reshape(repmat(ConsideredDataPositions_OFDM,log2(QAM_ModulationOrder),1),[],1);

%% Channel Model Object
ChannelModel = Channel.FastFading(...
    SamplingRate,...                                   % Sampling rate (Samples/s)
    PowerDelayProfile,...                              % Power delay profile, either string or vector: 'Flat', 'AWGN', 'PedestrianA', 'PedestrianB', 'VehicularA', 'VehicularB', 'ExtendedPedestrianA', 'ExtendedPedestrianB', or 'TDL-A_xxns','TDL-B_xxns','TDL-C_xxns' (with xx the RMS delay spread in ns, e.g. 'TDL-A_30ns'), or [1 0 0.2] (Self-defined power delay profile which depends on the sampling rate)
    N,...                                              % Number of total samples
    Velocity_kmh/3.6*2.5e9/2.998e8,...                 % Maximum Doppler shift: Velocity_kmh/3.6*CarrierFrequency/2.998e8
    'Jakes',...                                        % Which Doppler model: 'Jakes', 'Uniform', 'Discrete-Jakes', 'Discrete-Uniform'. For "Discrete-", we assume a discrete Doppler spectrum to improve the simulation time. This only works accuratly if the number of samples and the velocity is sufficiently large
    200,...                                            % Number of paths for the WSSUS process. Only relevant for a 'Jakes' and 'Uniform' Doppler spectrum
    1,...                                              % Number of transmit antennas
    1,...                                              % Number of receive antennas
    1 ...                                              % Gives a warning if the predefined delay taps of the channel do not fit the sampling rate. This is usually not much of a problem if they are approximatly the same.
    );
R_vecH = ChannelModel.GetCorrelationMatrix;

%% Precalculate Transmit and Receive Matrices
G_FBMC = FBMC.GetTXMatrix;
Q_FBMC = (FBMC.GetRXMatrix)';

G_OFDM = OFDM.GetTXMatrix;
Q_OFDM = (OFDM.GetRXMatrix)';

GP_FBMC = G_FBMC(:,PilotMatrix_FBMC(:)==1);
GP_OFDM = G_OFDM(:,PilotMatrix_OFDM(:)==1);

QP_FBMC = Q_FBMC(:,PilotMatrix_FBMC(:)==1);
QP_OFDM = Q_OFDM(:,PilotMatrix_OFDM(:)==1);

G_Aux = G_FBMC*AuxiliaryMethod.PrecodingMatrix;
G_Cod = G_FBMC*CodingMethod.PrecodingMatrix;
G_OFDM_PilotMapping = G_OFDM*PilotMapping_OFDM;

%% Calculate Correlation Matrices
disp('Calculate Correlation Matrix of Pilot Estimates (no Noise, no Interference)...');
R_hP_FBMC  = nan(NrPilotSymbols,NrPilotSymbols);
R_hP_OFDM = nan(NrPilotSymbols,NrPilotSymbols);
for j_pilot = 1:NrPilotSymbols
    R_hP_FBMC(:,j_pilot) = sum((QP_FBMC'*reshape(R_vecH*kron(GP_FBMC(:,j_pilot).',QP_FBMC(:,j_pilot)')',N,N)).*(GP_FBMC.'),2);
    R_hP_OFDM(:,j_pilot) = sum((QP_OFDM'*reshape(R_vecH*kron(GP_OFDM(:,j_pilot).',QP_OFDM(:,j_pilot)')',N,N)).*(GP_OFDM.'),2);
end

disp('Calculate Correlation Matrix of Pilot Estimates (no Interference)...');
R_hP_est_noNoise_FBMC_Aux = R_hP_FBMC;
R_hP_est_noNoise_FBMC_Cod = R_hP_FBMC;
R_hP_est_noNoise_OFDM = R_hP_OFDM;
for i_pilots = 1: NrPilotSymbols
    % FBMC Auxiliary Method, Similar as Equation (13) but computationally more efficient
    Temp = kron(sparse(eye(N)),QP_FBMC(:,i_pilots)')/sqrt(Kappa_Aux);
    R_hP_est_noNoise_FBMC_Aux(i_pilots,i_pilots)=abs(sum(sum((G_Aux.'*(Temp*R_vecH*Temp')).*G_Aux',2)));

    % FBMC Coding
    Temp = kron(sparse(eye(N)),QP_FBMC(:,i_pilots)')/sqrt(Kappa_Cod);
    R_hP_est_noNoise_FBMC_Cod(i_pilots,i_pilots)=abs(sum(sum((G_Cod.'*(Temp*R_vecH*Temp')).*G_Cod',2)));

    % OFDM
    Temp = kron(sparse(eye(N)),QP_OFDM(:,i_pilots)')/sqrt(Kappa_OFDM);
    R_hP_est_noNoise_OFDM(i_pilots,i_pilots)=abs(sum(sum((G_OFDM_PilotMapping.'*(Temp*R_vecH*Temp')).*G_OFDM_PilotMapping',2)));
end

disp('Calculate Correlation Matrix of Pilot Estimates...');
R_hP_est_FBMC_Aux = repmat(R_hP_est_noNoise_FBMC_Aux,[1 1 length(M_SNR_dB)]);
R_hP_est_FBMC_Cod = repmat(R_hP_est_noNoise_FBMC_Cod,[1 1 length(M_SNR_dB)]);
R_hP_est_OFDM = repmat(R_hP_est_noNoise_OFDM,[1 1 length(M_SNR_dB)]);
for i_SNR = 1:length(M_SNR_dB)
    SNR_dB = M_SNR_dB(i_SNR);
    Pn_time = SamplingRate/(F*L)*10^(-SNR_dB/10);
    for i_pilots = 1: NrPilotSymbols
        R_hP_est_FBMC_Aux(i_pilots,i_pilots,i_SNR)=R_hP_est_noNoise_FBMC_Aux(i_pilots,i_pilots)+Pn_time*QP_FBMC(:,i_pilots)'*QP_FBMC(:,i_pilots)/(Kappa_Aux);
        R_hP_est_FBMC_Cod(i_pilots,i_pilots,i_SNR)=R_hP_est_noNoise_FBMC_Cod(i_pilots,i_pilots)+Pn_time*QP_FBMC(:,i_pilots)'*QP_FBMC(:,i_pilots)/(Kappa_Cod);
        R_hP_est_OFDM(i_pilots,i_pilots,i_SNR)=R_hP_est_noNoise_OFDM(i_pilots,i_pilots)+Pn_time*QP_OFDM(:,i_pilots)'*QP_OFDM(:,i_pilots)/Kappa_OFDM;
    end
end

R_hP_est_noInterference_FBMC_Aux = R_hP_est_FBMC_Aux-repmat((R_hP_est_noNoise_FBMC_Aux-R_hP_FBMC),[1 1 length(M_SNR_dB)]);
R_hP_est_noInterference_FBMC_Cod = R_hP_est_FBMC_Cod-repmat((R_hP_est_noNoise_FBMC_Cod-R_hP_FBMC),[1 1 length(M_SNR_dB)]);
R_hP_est_noInterference_OFDM = R_hP_est_OFDM-repmat((R_hP_est_noNoise_OFDM-R_hP_OFDM),[1 1 length(M_SNR_dB)]);

disp('Calculate Correlation Matrix between Transmission-Matrix D and Pilot Estimates...');
R_Dij_hP_FBMC = sparse(size(G_FBMC,2)^2,NrPilotSymbols);
R_Dij_hP_OFDM = sparse(size(G_OFDM,2)^2,NrPilotSymbols);
for i_pilot = 1: NrPilotSymbols
    R_Dij_hP_FBMC_Temp = reshape(Q_FBMC'*reshape(R_vecH*kron(GP_FBMC(:,i_pilot).',QP_FBMC(:,i_pilot)')',N,N)*G_FBMC,[],1);
    R_Dij_hP_OFDM_Temp = reshape(Q_OFDM'*reshape(R_vecH*kron(GP_OFDM(:,i_pilot).',QP_OFDM(:,i_pilot)')',N,N)*G_OFDM,[],1);

    R_Dij_hP_FBMC_Temp(abs(R_Dij_hP_FBMC_Temp)<10^(-ZeroThresholdSparse))=0;
    R_Dij_hP_OFDM_Temp(abs(R_Dij_hP_OFDM_Temp)<10^(-ZeroThresholdSparse))=0;

    R_Dij_hP_FBMC(:,i_pilot) = R_Dij_hP_FBMC_Temp;
    R_Dij_hP_OFDM(:,i_pilot) = R_Dij_hP_OFDM_Temp;
end
clear R_vecH;

%% Calculate SIR at Pilot Positions
SIR_P_FBMC_Aux_dB = 10*log10(trace(abs(R_hP_FBMC))./trace(abs(R_hP_est_noNoise_FBMC_Aux-R_hP_FBMC)));
SIR_P_FBMC_Cod_dB = 10*log10(trace(abs(R_hP_FBMC))./trace(abs(R_hP_est_noNoise_FBMC_Cod-R_hP_FBMC)));
SIR_P_OFDM_dB     = 10*log10(trace(abs(R_hP_OFDM))./trace(abs(R_hP_est_noNoise_OFDM-R_hP_OFDM)));

%% Calculate MMSE Estimation Matrix Using Correlation
disp('Calculate MMSE Solution ...');
W_MMSE_FBMC_Aux = sparse(size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,length(M_SNR_dB));
W_MMSE_FBMC_Cod = sparse(size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,length(M_SNR_dB));
W_MMSE_OFDM     = sparse(size(G_OFDM,2)*size(G_OFDM,2)*NrPilotSymbols,length(M_SNR_dB));
for i_SNR = 1:length(M_SNR_dB)
    W_MMSE_FBMC_Aux_Temp = reshape(R_Dij_hP_FBMC*pinv(R_hP_est_FBMC_Aux(:,:,i_SNR)),size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,1);
    W_MMSE_FBMC_Cod_Temp = reshape(R_Dij_hP_FBMC*pinv(R_hP_est_FBMC_Cod(:,:,i_SNR)),size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,1);
    W_MMSE_OFDM_Temp     = reshape(R_Dij_hP_OFDM*pinv(R_hP_est_OFDM(:,:,i_SNR)),size(G_OFDM,2)*size(G_OFDM,2)*NrPilotSymbols,1);

    W_MMSE_FBMC_Aux_Temp(abs(W_MMSE_FBMC_Aux_Temp)<10^(-ZeroThresholdSparse))=0;
    W_MMSE_FBMC_Cod_Temp(abs(W_MMSE_FBMC_Cod_Temp)<10^(-ZeroThresholdSparse))=0;
    W_MMSE_OFDM_Temp(abs(W_MMSE_OFDM_Temp)<10^(-ZeroThresholdSparse))=0;

    W_MMSE_FBMC_Aux(:,i_SNR) = W_MMSE_FBMC_Aux_Temp;
    W_MMSE_FBMC_Cod(:,i_SNR) = W_MMSE_FBMC_Cod_Temp;
    W_MMSE_OFDM(:,i_SNR)     = W_MMSE_OFDM_Temp;
end

%% Calculate MMSE Estimation if no Interference is present at the pilot positions
disp('Calculate MMSE Solution (no Interference)...');
W_MMSE_noInterference_FBMC_Aux = sparse(size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,length(M_SNR_dB));
W_MMSE_noInterference_FBMC_Cod = sparse(size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,length(M_SNR_dB));
W_MMSE_noInterference_OFDM     = sparse(size(G_OFDM,2)*size(G_OFDM,2)*NrPilotSymbols,length(M_SNR_dB));
for i_SNR = 1:length(M_SNR_dB)
    W_MMSE_noInterference_FBMC_Aux_Temp = reshape(R_Dij_hP_FBMC*pinv(R_hP_est_noInterference_FBMC_Aux(:,:,i_SNR)),size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,1);
    W_MMSE_noInterference_FBMC_Cod_Temp = reshape(R_Dij_hP_FBMC*pinv(R_hP_est_noInterference_FBMC_Cod(:,:,i_SNR)),size(G_FBMC,2)*size(G_FBMC,2)*NrPilotSymbols,1);
    W_MMSE_noInterference_OFDM_Temp = reshape(R_Dij_hP_OFDM*pinv(R_hP_est_noInterference_OFDM(:,:,i_SNR)),size(G_OFDM,2)*size(G_OFDM,2)*NrPilotSymbols,1);

    W_MMSE_noInterference_FBMC_Aux_Temp(abs(W_MMSE_noInterference_FBMC_Aux_Temp)<10^(-ZeroThresholdSparse))=0;
    W_MMSE_noInterference_FBMC_Cod_Temp(abs(W_MMSE_noInterference_FBMC_Cod_Temp)<10^(-ZeroThresholdSparse))=0;
    W_MMSE_noInterference_OFDM_Temp(abs(W_MMSE_noInterference_OFDM_Temp)<10^(-ZeroThresholdSparse))=0;

    W_MMSE_noInterference_FBMC_Aux(:,i_SNR) = W_MMSE_noInterference_FBMC_Aux_Temp;
    W_MMSE_noInterference_FBMC_Cod(:,i_SNR) = W_MMSE_noInterference_FBMC_Cod_Temp;
    W_MMSE_noInterference_OFDM(:,i_SNR)     = W_MMSE_noInterference_OFDM_Temp;
end

%% Theoretical BEP for a Doubly Flat Rayleigh Channel
M_SNR_dB_morePoints = min(M_SNR_dB):1:max(M_SNR_dB);
BitErrorProbability = BitErrorProbabilityDoublyFlatRayleigh(M_SNR_dB_morePoints,QAM.SymbolMapping,QAM.BitMapping);

%% Preallocate for Parfor
BER_FBMC_Aux_PerfectCSI_InterferenceCancellation        = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Aux_PerfectCSI_InterferenceCancellation_NoEdge = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Cod_PerfectCSI_InterferenceCancellation        = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Cod_PerfectCSI_InterferenceCancellation_NoEdge = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_OFDM_PerfectCSI_InterferenceCancellation            = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_OFDM_PerfectCSI_InterferenceCancellation_NoEdge     = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Aux_OneTapEqualizer_PerfectCSI                 = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Aux_OneTapEqualizer_PerfectCSI_NoEdge          = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Cod_OneTapEqualizer_PerfectCSI                 = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Cod_OneTapEqualizer_PerfectCSI_NoEdge          = nan(length(M_SNR_dB),NrRepetitions);
BER_OFDM_OneTapEqualizer_PerfectCSI                     = nan(length(M_SNR_dB),NrRepetitions);
BER_OFDM_OneTapEqualizer_PerfectCSI_NoEdge              = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Aux_InterferenceCancellation                   = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Cod_InterferenceCancellation                   = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_OFDM_InterferenceCancellation                       = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Aux_InterferenceCancellation_NoEdge            = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Cod_InterferenceCancellation_NoEdge            = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_OFDM_InterferenceCancellation_NoEdge                = nan(length(M_SNR_dB),NrRepetitions,NrIterations);
BER_FBMC_Aux_OneTapEqualizer                            = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Aux_OneTapEqualizer_NoEdge                     = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Cod_OneTapEqualizer                            = nan(length(M_SNR_dB),NrRepetitions);
BER_FBMC_Cod_OneTapEqualizer_NoEdge                     = nan(length(M_SNR_dB),NrRepetitions);
BER_OFDM_OneTapEqualizer                                = nan(length(M_SNR_dB),NrRepetitions);
BER_OFDM_OneTapEqualizer_NoEdge                         = nan(length(M_SNR_dB),NrRepetitions);

%% Start Simulation
tic
disp('Monte Carlo Simulation ...');
for i_rep = 1:NrRepetitions
    %% Update Channel
    ChannelModel.NewRealization;

    %% Binary Data
    BinaryDataStream_FBMC_Aux = randi([0 1],AuxiliaryMethod.NrDataSymbols*log2(PAM.ModulationOrder),1);
    BinaryDataStream_FBMC_Cod = randi([0 1],CodingMethod.NrDataSymbols*log2(PAM.ModulationOrder),1);
    BinaryDataStream_OFDM     = randi([0 1],NrDataSymbols_OFDM*log2(QAM.ModulationOrder),1);

    %% Data Symbols
    xD_FBMC_Aux = PAM.Bit2Symbol(BinaryDataStream_FBMC_Aux);
    xD_FBMC_Cod = PAM.Bit2Symbol(BinaryDataStream_FBMC_Cod);
    xD_OFDM     = QAM.Bit2Symbol(BinaryDataStream_OFDM);

    %% Pilot Symbols
    xP_FBMC = PAM.SymbolMapping(randi(PAM.ModulationOrder,AuxiliaryMethod.NrPilotSymbols,1));
    xP_FBMC = xP_FBMC./abs(xP_FBMC);
    xP_OFDM = QAM.SymbolMapping(randi(QAM.ModulationOrder,NrPilotSymbols,1));
    xP_OFDM = xP_OFDM./abs(xP_OFDM);

    %% Transmitted Data Symbols (Map bin to symbol)
    x_FBMC_Aux = AuxiliaryMethod.PrecodingMatrix*[xP_FBMC;xD_FBMC_Aux];
    x_FBMC_Cod = CodingMethod.PrecodingMatrix*[xP_FBMC;xD_FBMC_Cod];
    x_OFDM     = PilotMapping_OFDM*[xP_OFDM;xD_OFDM];

    %% Transmitted Signal (time domain)
    s_FBMC_Aux = G_FBMC*x_FBMC_Aux(:); % Same as "FBMC.Modulation(x_FBMC_Aux)" which is computationally more efficient. But G_FBMC is consistent with the paper.
    s_FBMC_Cod = G_FBMC*x_FBMC_Cod(:);
    s_OFDM     = G_OFDM*x_OFDM(:);

    %% Channel
    ConvolutionMatrix = ChannelModel.GetConvolutionMatrix{1};

    r_FBMC_Aux_noNoise = ConvolutionMatrix*s_FBMC_Aux;
    r_FBMC_Cod_noNoise = ConvolutionMatrix*s_FBMC_Cod;
    r_OFDM_noNoise     = ConvolutionMatrix*s_OFDM;

    %% Transmission Matrix
    D_FBMC = Q_FBMC'*ConvolutionMatrix*G_FBMC;
    D_OFDM = Q_OFDM'*ConvolutionMatrix*G_OFDM;

    %% One-Tap Channel (for perfect channel knowledge)
    h_FBMC = diag(D_FBMC);
    h_OFDM = diag(D_OFDM);

    for i_SNR = 1:length(M_SNR_dB)
        %% Add Noise
        SNR_dB  = M_SNR_dB(i_SNR);
        Pn_time = SamplingRate/(F*L)*10^(-SNR_dB/10);
        noise   = sqrt(Pn_time/2)*(randn(size(s_OFDM))+1j*randn(size(s_OFDM)));

        r_FBMC_Aux = r_FBMC_Aux_noNoise+noise;
        r_FBMC_Cod = r_FBMC_Cod_noNoise+noise;
        r_OFDM     = r_OFDM_noNoise+noise;

        %% Demodulate FBMC signal
        y_FBMC_Aux         = Q_FBMC'*r_FBMC_Aux; % Same as "FBMC.Demodulation(r_FBMC_Aux)"
        y_FBMC_Cod         = Q_FBMC'*r_FBMC_Cod; % Same as "FBMC.Demodulation(r_FBMC_Cod)"
        y_FBMC_Cod_PostCod = CodingMethod.PrecodingMatrix'*y_FBMC_Cod;
        y_OFDM             = Q_OFDM'*r_OFDM; % Same as "OFDM.Demodulation(r_OFDM)"

        %% Channel Estimation at Pilot Position
        hP_est_FBMC_Aux = y_FBMC_Aux(PilotMatrix_FBMC==1)./xP_FBMC/sqrt(Kappa_Aux);
        hP_est_FBMC_Cod = y_FBMC_Cod(PilotMatrix_FBMC==1)./xP_FBMC/sqrt(Kappa_Cod);
        hP_est_OFDM     = y_OFDM(PilotMatrix_OFDM==1)./xP_OFDM/sqrt(Kappa_OFDM);

        %% Estimate Transmit Matix
        D_FBMC_est_Aux = sum(bsxfun(@times,...
            reshape(full(W_MMSE_FBMC_Aux(:,i_SNR)),size(G_FBMC,2),size(G_FBMC,2),NrPilotSymbols),...
            reshape(hP_est_FBMC_Aux,1,1,[])),3);
        D_FBMC_est_Cod = sum(bsxfun(@times,...
            reshape(full(W_MMSE_FBMC_Cod(:,i_SNR)),size(G_FBMC,2),size(G_FBMC,2),NrPilotSymbols),...
            reshape(hP_est_FBMC_Cod,1,1,[])),3);
        D_OFDM_est = sum(bsxfun(@times,...
            reshape(full(W_MMSE_OFDM(:,i_SNR)),size(G_OFDM,2),size(G_OFDM,2),NrPilotSymbols),...
            reshape(hP_est_OFDM,1,1,[])),3);

        %% One-Tap Equalizer
        h_est_FBMC_Aux = diag(D_FBMC_est_Aux);
        x_est_OneTapEqualizer_FBMC_Aux = y_FBMC_Aux./h_est_FBMC_Aux;
        xD_est_OneTapEqualizer_FBMC_Aux = real(x_est_OneTapEqualizer_FBMC_Aux(AuxilaryPilotMatrix_FBMC(:)==0)./sqrt(AuxiliaryMethod.DataPowerReduction));
        DetectedBitStream_OneTapEqualizer_FBMC_Aux = PAM.Symbol2Bit(xD_est_OneTapEqualizer_FBMC_Aux);
        BER_FBMC_Aux_OneTapEqualizer(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Aux~=DetectedBitStream_OneTapEqualizer_FBMC_Aux);
        BER_FBMC_Aux_OneTapEqualizer_NoEdge(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Aux(ConsideredBits_FBMC_Aux)~=DetectedBitStream_OneTapEqualizer_FBMC_Aux(ConsideredBits_FBMC_Aux));

        h_est_FBMC_Cod = diag(D_FBMC_est_Cod);
        x_est_OneTapEqualizer_FBMC_Cod = CodingMethod.PrecodingMatrix'*(y_FBMC_Cod./h_est_FBMC_Cod);
        xD_est_OneTapEqualizer_FBMC_Cod = real(x_est_OneTapEqualizer_FBMC_Cod(NrPilotSymbols+1:end))/CodingMethod.DataPowerReduction;
        DetectedBitStream_OneTapEqualizer_FBMC_Cod = PAM.Symbol2Bit(xD_est_OneTapEqualizer_FBMC_Cod);
        BER_FBMC_Cod_OneTapEqualizer(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Cod~=DetectedBitStream_OneTapEqualizer_FBMC_Cod);
        BER_FBMC_Cod_OneTapEqualizer_NoEdge(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Cod(ConsideredBits_FBMC_Cod)~=DetectedBitStream_OneTapEqualizer_FBMC_Cod(ConsideredBits_FBMC_Cod));

        h_est_OFDM = diag(D_OFDM_est);
        x_est_OneTapEqualizer_OFDM = y_OFDM./h_est_OFDM;
        xD_est_OneTapEqualizer_OFDM = x_est_OneTapEqualizer_OFDM(PilotMatrix_OFDM(:)==0)./sqrt(DataPowerReduction_OFDM);
        DetectedBitStream_OneTapEqualizer_OFDM = QAM.Symbol2Bit(xD_est_OneTapEqualizer_OFDM);
        BER_OFDM_OneTapEqualizer(i_SNR,i_rep) = mean(BinaryDataStream_OFDM~=DetectedBitStream_OneTapEqualizer_OFDM);
        BER_OFDM_OneTapEqualizer_NoEdge(i_SNR,i_rep) = mean(BinaryDataStream_OFDM(ConsideredBits_OFDM)~=DetectedBitStream_OneTapEqualizer_OFDM(ConsideredBits_OFDM));

        %% One-Tap Equalizer, Perfect Channel Knowledge
        x_est_OneTapEqualizer_FBMC_Aux_PerfectCSI = y_FBMC_Aux./h_FBMC;
        xD_est_OneTapEqualizer_FBMC_Aux_PerfectCSI = real(x_est_OneTapEqualizer_FBMC_Aux_PerfectCSI(AuxilaryPilotMatrix_FBMC(:)==0)./sqrt(AuxiliaryMethod.DataPowerReduction));
        DetectedBitStream_OneTapEqualizer_FBMC_Aux_PerfectCSI = PAM.Symbol2Bit(xD_est_OneTapEqualizer_FBMC_Aux_PerfectCSI);
        BER_FBMC_Aux_OneTapEqualizer_PerfectCSI(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Aux~=DetectedBitStream_OneTapEqualizer_FBMC_Aux_PerfectCSI);
        BER_FBMC_Aux_OneTapEqualizer_PerfectCSI_NoEdge(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Aux(ConsideredBits_FBMC_Aux)~=DetectedBitStream_OneTapEqualizer_FBMC_Aux_PerfectCSI(ConsideredBits_FBMC_Aux));

        x_est_OneTapEqualizer_FBMC_Cod_PerfectCSI = CodingMethod.PrecodingMatrix'*(y_FBMC_Cod./h_FBMC);
        xD_est_OneTapEqualizer_FBMC_Cod_PerfectCSI = real(x_est_OneTapEqualizer_FBMC_Cod_PerfectCSI(NrPilotSymbols+1:end))/CodingMethod.DataPowerReduction;
        DetectedBitStream_OneTapEqualizer_FBMC_Cod_PerfectCSI = PAM.Symbol2Bit(xD_est_OneTapEqualizer_FBMC_Cod_PerfectCSI);
        BER_FBMC_Cod_OneTapEqualizer_PerfectCSI(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Cod~=DetectedBitStream_OneTapEqualizer_FBMC_Cod_PerfectCSI);
        BER_FBMC_Cod_OneTapEqualizer_PerfectCSI_NoEdge(i_SNR,i_rep) = mean(BinaryDataStream_FBMC_Cod(ConsideredBits_FBMC_Cod)~=DetectedBitStream_OneTapEqualizer_FBMC_Cod_PerfectCSI(ConsideredBits_FBMC_Cod));

        x_est_OneTapEqualizer_OFDM_PerfectCSI = y_OFDM./h_OFDM;
        xD_est_OneTapEqualizer_OFDM_PerfectCSI = x_est_OneTapEqualizer_OFDM_PerfectCSI(PilotMatrix_OFDM(:)==0)./sqrt(DataPowerReduction_OFDM);
        DetectedBitStream_OneTapEqualizer_OFDM_PerfectCSI = QAM.Symbol2Bit(xD_est_OneTapEqualizer_OFDM_PerfectCSI);
        BER_OFDM_OneTapEqualizer_PerfectCSI(i_SNR,i_rep) = mean(BinaryDataStream_OFDM~=DetectedBitStream_OneTapEqualizer_OFDM_PerfectCSI);
        BER_OFDM_OneTapEqualizer_PerfectCSI_NoEdge(i_SNR,i_rep) = mean(BinaryDataStream_OFDM(ConsideredBits_OFDM)~=DetectedBitStream_OneTapEqualizer_OFDM_PerfectCSI(ConsideredBits_OFDM));

        %% Improved Channel Estimation and Data Detection
        xD_est_FBMC_Aux_Temp = xD_est_OneTapEqualizer_FBMC_Aux; % initialize with one tap estimates
        xD_est_FBMC_Cod_Temp = xD_est_OneTapEqualizer_FBMC_Cod; % initialize with one tap estimates
        xD_est_OFDM_Temp     = xD_est_OneTapEqualizer_OFDM; % initialize with one tap estimates
        xD_est_FBMC_Aux_PerfectCSI_Temp = xD_est_OneTapEqualizer_FBMC_Aux_PerfectCSI; % initialize with one tap estimates
        xD_est_FBMC_Cod_PerfectCSI_Temp = xD_est_OneTapEqualizer_FBMC_Cod_PerfectCSI; % initialize with one tap estimates
        xD_est_OFDM_PerfectCSI_Temp     = xD_est_OneTapEqualizer_OFDM_PerfectCSI; % initialize with one tap estimates
        D_FBMC_est_Aux_Temp  = D_FBMC_est_Aux;
        D_FBMC_est_Cod_Temp  = D_FBMC_est_Cod;
        D_OFDM_est_Temp      = D_OFDM_est;
        h_est_FBMC_Aux_Temp  = h_est_FBMC_Aux;
        h_est_FBMC_Cod_Temp  = h_est_FBMC_Cod;
        h_est_OFDM_Temp      = h_est_OFDM;
        for i_iteration = 1:NrIterations
            y_FBMC_Aux_InterferenceCancellation = (y_FBMC_Aux(:) - (D_FBMC_est_Aux_Temp-diag(h_est_FBMC_Aux_Temp))*AuxiliaryMethod.PrecodingMatrix*[xP_FBMC;PAM.SymbolQuantization(xD_est_FBMC_Aux_Temp)]);
            y_FBMC_Cod_InterferenceCancellation = (y_FBMC_Cod - (D_FBMC_est_Cod_Temp-diag(h_est_FBMC_Cod_Temp))*CodingMethod.PrecodingMatrix*[xP_FBMC;PAM.SymbolQuantization(xD_est_FBMC_Cod_Temp)]);
            y_OFDM_InterferenceCancellation     = (y_OFDM - (D_OFDM_est_Temp-diag(h_est_OFDM_Temp))*PilotMapping_OFDM*[xP_OFDM;QAM.SymbolQuantization(xD_est_OFDM_Temp)]);

            % New Channel Estimates at Pilot Positions
            hP_est_FBMC_Aux_Temp = y_FBMC_Aux_InterferenceCancellation(PilotMatrix_FBMC==1)./xP_FBMC/sqrt(Kappa_Aux);
            hP_est_FBMC_Cod_Temp = y_FBMC_Cod_InterferenceCancellation(PilotMatrix_FBMC==1)./xP_FBMC/sqrt(Kappa_Cod);
            hP_est_OFDM_Temp     = y_OFDM_InterferenceCancellation(PilotMatrix_OFDM==1)./xP_OFDM/sqrt(Kappa_OFDM);

            % Improved Channel Estimation
            if i_iteration<=NrIterations/2
                D_FBMC_est_Aux_Temp = sum(bsxfun(@times,...
                    reshape(full(W_MMSE_FBMC_Aux(:,i_SNR)),size(G_FBMC,2),size(G_FBMC,2),NrPilotSymbols),...
                    reshape(hP_est_FBMC_Aux_Temp,1,1,[])),3);
                D_FBMC_est_Cod_Temp = sum(bsxfun(@times,...
                    reshape(full(W_MMSE_FBMC_Cod(:,i_SNR)),size(G_FBMC,2),size(G_FBMC,2),NrPilotSymbols),...
                    reshape(hP_est_FBMC_Cod_Temp,1,1,[])),3);
                D_OFDM_est_Temp = sum(bsxfun(@times,...
                    reshape(full(W_MMSE_OFDM(:,i_SNR)),size(G_OFDM,2),size(G_OFDM,2),NrPilotSymbols),...
                    reshape(hP_est_OFDM_Temp,1,1,[])),3);
            else
                D_FBMC_est_Aux_Temp = sum(bsxfun(@times,...
                    reshape(full(W_MMSE_noInterference_FBMC_Aux(:,i_SNR)),size(G_FBMC,2),size(G_FBMC,2),NrPilotSymbols),...
                    reshape(hP_est_FBMC_Aux_Temp,1,1,[])),3);
                D_FBMC_est_Cod_Temp = sum(bsxfun(@times,...
                    reshape(full(W_MMSE_noInterference_FBMC_Cod(:,i_SNR)),size(G_FBMC,2),size(G_FBMC,2),NrPilotSymbols),...
                    reshape(hP_est_FBMC_Cod_Temp,1,1,[])),3);
                D_OFDM_est_Temp = sum(bsxfun(@times,...
                    reshape(full(W_MMSE_noInterference_OFDM(:,i_SNR)),size(G_OFDM,2),size(G_OFDM,2),NrPilotSymbols),...
                    reshape(hP_est_OFDM_Temp,1,1,[])),3);
            end

            % One-Tap Channel
            h_est_FBMC_Aux_Temp = diag(D_FBMC_est_Aux_Temp);
            h_est_FBMC_Cod_Temp = diag(D_FBMC_est_Cod_Temp);
            h_est_OFDM_Temp     = diag(D_OFDM_est_Temp);

            x_est_FBMC_Aux_Temp = y_FBMC_Aux_InterferenceCancellation(:)./h_est_FBMC_Aux_Temp;
            x_est_FBMC_Cod_Temp = CodingMethod.PrecodingMatrix'*(y_FBMC_Cod_InterferenceCancellation./h_est_FBMC_Cod_Temp);
            x_est_OFDM_Temp     =  y_OFDM_InterferenceCancellation./h_est_OFDM_Temp;

            xD_est_FBMC_Aux_Temp = real(x_est_FBMC_Aux_Temp(AuxilaryPilotMatrix_FBMC(:)==0)./sqrt(AuxiliaryMethod.DataPowerReduction));
            xD_est_FBMC_Cod_Temp = real(x_est_FBMC_Cod_Temp(NrPilotSymbols+1:end))/CodingMethod.DataPowerReduction;
            xD_est_OFDM_Temp     = x_est_OFDM_Temp(PilotMatrix_OFDM(:)==0)./sqrt(DataPowerReduction_OFDM);

            DetectedBitStream_FBMC_Aux_Temp = PAM.Symbol2Bit(xD_est_FBMC_Aux_Temp);
            DetectedBitStream_FBMC_Cod_Temp = PAM.Symbol2Bit(xD_est_FBMC_Cod_Temp);
            DetectedBitStream_OFDM_Temp     = QAM.Symbol2Bit(xD_est_OFDM_Temp);

            BER_FBMC_Aux_InterferenceCancellation(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Aux~=DetectedBitStream_FBMC_Aux_Temp);
            BER_FBMC_Cod_InterferenceCancellation(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Cod~=DetectedBitStream_FBMC_Cod_Temp);
            BER_OFDM_InterferenceCancellation(i_SNR,i_rep,i_iteration)     = mean(BinaryDataStream_OFDM~=DetectedBitStream_OFDM_Temp);

            BER_FBMC_Aux_InterferenceCancellation_NoEdge(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Aux(ConsideredBits_FBMC_Aux)~=DetectedBitStream_FBMC_Aux_Temp(ConsideredBits_FBMC_Aux));
            BER_FBMC_Cod_InterferenceCancellation_NoEdge(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Cod(ConsideredBits_FBMC_Cod)~=DetectedBitStream_FBMC_Cod_Temp(ConsideredBits_FBMC_Cod));
            BER_OFDM_InterferenceCancellation_NoEdge(i_SNR,i_rep,i_iteration)     = mean(BinaryDataStream_OFDM(ConsideredBits_OFDM)~=DetectedBitStream_OFDM_Temp(ConsideredBits_OFDM));

            % Perfect Channel Knoweledge
            y_FBMC_Aux_InterferenceCancellation_PerfectCSI = (y_FBMC_Aux(:) - (D_FBMC-diag(h_FBMC))*AuxiliaryMethod.PrecodingMatrix*[xP_FBMC;PAM.SymbolQuantization(xD_est_FBMC_Aux_PerfectCSI_Temp)]);
            y_FBMC_Cod_InterferenceCancellation_PerfectCSI = (y_FBMC_Cod - (D_FBMC-diag(h_FBMC))*CodingMethod.PrecodingMatrix*[xP_FBMC;PAM.SymbolQuantization(xD_est_FBMC_Cod_PerfectCSI_Temp)]);
            y_OFDM_InterferenceCancellation_PerfectCSI     = (y_OFDM - (D_OFDM-diag(h_OFDM))*PilotMapping_OFDM*[xP_OFDM;QAM.SymbolQuantization(xD_est_OFDM_PerfectCSI_Temp)]);

            x_est_FBMC_Aux_PerfectCSI_Temp = y_FBMC_Aux_InterferenceCancellation_PerfectCSI./h_FBMC;
            xD_est_FBMC_Aux_PerfectCSI_Temp = real(x_est_FBMC_Aux_PerfectCSI_Temp(AuxilaryPilotMatrix_FBMC(:)==0)./sqrt(AuxiliaryMethod.DataPowerReduction));
            DetectedBitStream_FBMC_Aux_PerfectCSI_Temp = PAM.Symbol2Bit(xD_est_FBMC_Aux_PerfectCSI_Temp);
            BER_FBMC_Aux_PerfectCSI_InterferenceCancellation(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Aux~=DetectedBitStream_FBMC_Aux_PerfectCSI_Temp);
            BER_FBMC_Aux_PerfectCSI_InterferenceCancellation_NoEdge(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Aux(ConsideredBits_FBMC_Aux)~=DetectedBitStream_FBMC_Aux_PerfectCSI_Temp(ConsideredBits_FBMC_Aux));

            x_est_FBMC_Cod_PerfectCSI_Temp = CodingMethod.PrecodingMatrix'*(y_FBMC_Cod_InterferenceCancellation_PerfectCSI./h_FBMC);
            xD_est_FBMC_Cod_PerfectCSI_Temp = real(x_est_FBMC_Cod_PerfectCSI_Temp(NrPilotSymbols+1:end))/CodingMethod.DataPowerReduction;
            DetectedBitStream_FBMC_Cod_PerfectCSI_Temp = PAM.Symbol2Bit(xD_est_FBMC_Cod_PerfectCSI_Temp);
            BER_FBMC_Cod_PerfectCSI_InterferenceCancellation(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Cod~=DetectedBitStream_FBMC_Cod_PerfectCSI_Temp);
            BER_FBMC_Cod_PerfectCSI_InterferenceCancellation_NoEdge(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_FBMC_Cod(ConsideredBits_FBMC_Cod)~=DetectedBitStream_FBMC_Cod_PerfectCSI_Temp(ConsideredBits_FBMC_Cod));

            x_est_OFDM_PerfectCSI_Temp = y_OFDM_InterferenceCancellation_PerfectCSI./h_OFDM;
            xD_est_OFDM_PerfectCSI_Temp = x_est_OFDM_PerfectCSI_Temp(PilotMatrix_OFDM(:)==0)./sqrt(DataPowerReduction_OFDM);
            DetectedBitStream_OFDM_PerfectCSI_Temp = QAM.Symbol2Bit(xD_est_OFDM_PerfectCSI_Temp);
            BER_OFDM_PerfectCSI_InterferenceCancellation(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_OFDM~=DetectedBitStream_OFDM_PerfectCSI_Temp);
            BER_OFDM_PerfectCSI_InterferenceCancellation_NoEdge(i_SNR,i_rep,i_iteration) = mean(BinaryDataStream_OFDM(ConsideredBits_OFDM)~=DetectedBitStream_OFDM_PerfectCSI_Temp(ConsideredBits_OFDM));

        end

    end
    TimeNeededSoFar = toc;
    disp([int2str(i_rep/NrRepetitions*100) '% Completed! Time Left: ' int2str(TimeNeededSoFar/i_rep*(NrRepetitions-i_rep)/60) 'min, corresponding to approx. '  int2str(TimeNeededSoFar/i_rep*(NrRepetitions-i_rep)/3600) 'hour']);

    %% Plot results
    % OFDM
    figure(2);
    Markersize = 4;
    hold off;
    semilogy(M_SNR_dB_morePoints, BitErrorProbability,'Color',[1 1 1]*0.75);
    hold on;
    semilogy(M_SNR_dB, nanmean(BER_OFDM_PerfectCSI_InterferenceCancellation(:,:,end),2),'-x black','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_OFDM_InterferenceCancellation(:,:,end),2),'-s magenta','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_OFDM_InterferenceCancellation_NoEdge(:,:,end),2),'-o blue','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_OFDM_OneTapEqualizer_PerfectCSI,2),'-x','Color',[1 1 0]*0.7,'Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_OFDM_OneTapEqualizer,2),'-s red','Markersize',Markersize);
    ylim([10^-2 0.5]);
    title(['OFDM, Realization ' int2str(i_rep) '/'  int2str(NrRepetitions)])
    legend({'Doubly-Flat Theory','Cancellation (Perfect CSI)','Cancellation','Cancellation (no Edges)','One-Tap (Perfect CSI)','One-Tap'});
    ylabel('Bit Error Ratio');
    xlabel('Signal-to-Noise Ratio [dB]');

    % FBMC, Auxiliary Method
    figure(3);
    hold off;
    semilogy(M_SNR_dB_morePoints, BitErrorProbability,'Color',[1 1 1]*0.75);
    hold on;
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Aux_PerfectCSI_InterferenceCancellation(:,:,end),2),'-x black','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Aux_InterferenceCancellation(:,:,end),2),'-s magenta','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Aux_InterferenceCancellation_NoEdge(:,:,end),2),'-o blue','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Aux_OneTapEqualizer_PerfectCSI,2),'-x','Color',[1 1 0]*0.7,'Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Aux_OneTapEqualizer,2),'-s red','Markersize',Markersize);
    ylim([10^-2 0.5]);
    semilogy([PlotIterationStepsSNRdB PlotIterationStepsSNRdB],[10^-2 10^-1],'Color',[1 1 1]*0.5,'Linewidth',1);
    title(['FBMC Auxiliary Symbols, Realization ' int2str(i_rep) '/'  int2str(NrRepetitions)])
    legend({'Doubly-Flat Theory','Cancellation (Perfect CSI)','Cancellation','Cancellation (no Edges)','One-Tap (Perfect CSI)','One-Tap'});
    ylabel('Bit Error Ratio');
    xlabel('Signal-to-Noise Ratio [dB]');

    % FBMC, Data Spreading Method
    figure(4);
    hold off;
    semilogy(M_SNR_dB_morePoints, BitErrorProbability,'Color',[1 1 1]*0.75);
    hold on;
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Cod_PerfectCSI_InterferenceCancellation(:,:,end),2),'-x black','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Cod_InterferenceCancellation(:,:,end),2),'-s magenta','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Cod_InterferenceCancellation_NoEdge(:,:,end),2),'-o blue','Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Cod_OneTapEqualizer_PerfectCSI,2),'-x','Color',[1 1 0]*0.7,'Markersize',Markersize);
    semilogy(M_SNR_dB, nanmean(BER_FBMC_Cod_OneTapEqualizer,2),'-s red','Markersize',Markersize);
    ylim([10^-2 0.5]);
    title(['FBMC Data Spreading, Realization ' int2str(i_rep) '/'  int2str(NrRepetitions)])
    legend({'Doubly-Flat Theory','Cancellation (Perfect CSI)','Cancellation','Cancellation (no Edges)','One-Tap (Perfect CSI)','One-Tap'});
    ylabel('Bit Error Ratio');
    xlabel('Signal-to-Noise Ratio [dB]');

    % FBMC, Auxiliary Method, BER over Interation
    figure(5);
    hold off;
    semilogy(0:NrIterations, repmat(BitErrorProbability(find(PlotIterationStepsSNRdB==M_SNR_dB_morePoints)),NrIterations+1,1),'Color',[1 1 1]*0.75);
    hold on;
    Index = find(PlotIterationStepsSNRdB==M_SNR_dB);
    semilogy(0:NrIterations, [nanmean(BER_FBMC_Aux_OneTapEqualizer_PerfectCSI(Index,:),2);squeeze(nanmean(BER_FBMC_Aux_PerfectCSI_InterferenceCancellation(Index,:,:),2))],'-x black','Markersize',Markersize);
    semilogy(0:NrIterations, [nanmean(BER_FBMC_Aux_OneTapEqualizer(Index,:),2);squeeze(nanmean(BER_FBMC_Aux_InterferenceCancellation(Index,:,:),2))],'-s magenta','Markersize',Markersize);
    semilogy(0:NrIterations, [nanmean(BER_FBMC_Aux_OneTapEqualizer_NoEdge(Index,:),2);squeeze(nanmean(BER_FBMC_Aux_InterferenceCancellation_NoEdge(Index,:,:),2))],'-o blue','Markersize',Markersize);
    semilogy(0:NrIterations, repmat(nanmean(BER_FBMC_Aux_OneTapEqualizer_PerfectCSI(Index,:),2),NrIterations+1,1),'-x','Color',[1 1 0]*0.7,'Markersize',Markersize);
    semilogy(0:NrIterations, repmat(nanmean(BER_FBMC_Aux_OneTapEqualizer(Index,:),2),NrIterations+1,1),'-s red','Markersize',Markersize);
    title(['FBMC Auxiliary Symbols, Realization ' int2str(i_rep) '/'  int2str(NrRepetitions)])
    legend({'Doubly-Flat Theory','Cancellation (Perfect CSI)','Cancellation','Cancellation (no Edges)','One-Tap (Perfect CSI)','One-Tap'});
    set(gca, 'XTick',0:NrIterations);
    ylabel('Bit Error Ratio');
    xlabel('Iteration Step i');

    pause(0.01);

end

%% Plot Additional Information
fprintf('=============================\n');
fprintf('========= Data Rate =========\n');
fprintf('OFDM       |%7.2f Mbit/s  | \n', length(BinaryDataStream_OFDM)     / (OFDM.PHY.TimeSpacing*OFDM.Nr.MCSymbols)/1e6   );
fprintf('FBMC, Aux. |%7.2f Mbit/s  | \n', length(BinaryDataStream_FBMC_Aux) / (OFDM.PHY.TimeSpacing*OFDM.Nr.MCSymbols)/1e6   );
fprintf('FBMC, Cod. |%7.2f Mbit/s  | \n', length(BinaryDataStream_FBMC_Cod) / (OFDM.PHY.TimeSpacing*OFDM.Nr.MCSymbols)/1e6   );
fprintf('=============================\n');

% The power is normalized so that the average transmit power is one
fprintf('================================================\n');
fprintf('============== Relative SNR Shift ==============\n');
fprintf('================================================\n');
fprintf('           |    SNR    |  Data SNR  | Pilot SNR |\n');
fprintf('OFDM       |   %2.1fdB   |   %2.1fdB   |   %2.1fdB   |\n', 0, 10*log10(DataPowerReduction_OFDM), 10*log10(Kappa_OFDM))
fprintf('FBMC, Aux. |   %2.1fdB   |   %2.1fdB   |   %2.1fdB   |\n', 0, 10*log10(AuxiliaryMethod.DataPowerReduction), 10*log10(Kappa_Aux/2))
fprintf('FBMC, Cod. |   %2.1fdB   |   %2.1fdB   |   %2.1fdB   |\n', 0, 10*log10(CodingMethod.DataPowerReduction), 10*log10(Kappa_Cod/2))
fprintf('================================================\n');


function mv = mv_sortByVoxR(mv,plotFlag);
%
% mv = mv_sortByVoxR([mv],[plotFlag]);
%
% For MultiVoxel UI, sorts voxels by the "voxel reliability"
% metric, which is computed in mv_reliability, and stored
% in the 'voxR' field of the anal struct that code produces.
%
% Images the voxels sorted by this metric (rows at the top
% will have a higher voxel reliability), and produces
% a performance curve by stepping through progressively
% larger subsets of the data, running the WTA classifier
% on those subsets, to estimate if this metric finds voxels
% that reliability discriminate objects.
%
% if plotFlag is set to 0, the code doesn't visualize the
% results, just returns the results in a 'voxRSorting'
% substruct.
%
% ras, 05/05
if ieNotDefined('mv')
    mv = get(gcf,'UserData');
end

if ieNotDefined('plotFlag')
    plotFlag = 1;
end

% params
sel = find(tc_selectedConds(mv)) - 1;
% sel = setdiff(sel-1, 13); % GUM FOR E-R ANALYSES
nConds = length(sel);
nRuns = length(unique(mv.trials.run));
names = mv.trials.condNames(sel); % ignore null

%%%%% recompute voxR for current event-related parameters
A1 = mv_amps(mv, 1:2:nRuns);
A2 = mv_amps(mv, 2:2:nRuns);
nVoxels = size(A1,1);
for v = 1:nVoxels
    [R p] = corrcoef(A1(v,sel), A2(v,sel));
    voxR(v) = R(1,2);
end

% grab unsorted voxel data from all runs
amps = mv_amps(mv);

% get new row index for voxel data
[ignore rank] = sort(voxR);
rank = fliplr(rank); % high rank at the top

% re-sort vox data by this ranking
sortedAmps = amps(rank,:);
A1 = A1(rank,:);
A2 = A2(rank,:);

% plot results if selected
if plotFlag==1
    oldaxes = findobj('Type','axes','Parent',gcf);
    delete(oldaxes)

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % display a regression, color-coding each point
    % by its approximate rank
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    subplot(221);
    regressPlot(mv.wta.mu1,mv.wta.mu2,'x');
    hold on

    binSz = ceil(nVoxels/256); % # voxels per color bin
    ranked1 = repmat(NaN,[binSz 256]);
    ranked2 = repmat(NaN,[binSz 256]);
    ranked1(1:nVoxels) = mv.wta.mu1(rank);
    ranked2(1:nVoxels) = mv.wta.mu2(rank);
    plot(fliplr(ranked1),fliplr(ranked2),'x');
    xlabel('Mean Response, subset 1',...
        'FontName',mv.params.font,'FontSize',10);
    ylabel('Mean Response, subset 2',...
        'FontName',mv.params.font,'FontSize',10);
    setLineColors(jet(256));

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % show sorted voxels
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    subplot(223);
    imagesc(sortedAmps'); % sorted
    set(gca,'YTick',1:nConds,'YTickLabel',names);
    title('Sorted')
    xlabel Voxels

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Test subplots of the sorted data and plot results
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    subplot(122);
    mv.voxRSorting = mv_wtaCurve(mv, A1, A2, 1);
    set(gca, 'ButtonDownFcn', 'mv_selectSubset([],[],''voxR'');');
    axis square
else
    mv.voxRSorting = mv_wtaCurve(mv, A1, A2, 0);
end

% add the sorted amps
mv.voxRSorting.sortedAmps = sortedAmps;
mv.voxRSorting.ampType = mv.params.ampType;
mv.voxRSorting.A1 = A1;
mv.voxRSorting.A2 = A2;
mv.voxRSorting.rank = rank;
mv.voxRSorting.metric = mv.wta.voxR;

% if a UI exists, set as user data
if isfield(mv.ui,'fig') & ishandle(mv.ui.fig)
    set(mv.ui.fig,'UserData',mv);
end

return


% -------------------------------------------------------------------------
% This file is copied from matconvnet-fcn repository (has minor modification)
% (https://github.com/vlfeat/matconvnet-fcn)
% -------------------------------------------------------------------------
classdef SegmentationAccuracy < dagnn.Loss

    properties (Transient)
        pixelAccuracy = 0
        meanAccuracy = 0
        meanIntersectionUnion = 0
        confusion = 0
    end
    properties
        numClasses = 0;
    end

    methods
        function outputs = forward(obj, inputs, params)
            [~,predictions] = max(inputs{1}, [], 3) ;
            predictions = gather(predictions) ;
            labels = gather(inputs{2}) ;

            % compute statistics only on accumulated pixels
            ok = labels > 0 ;
            numPixels = sum(ok(:)) ;
            obj.confusion = obj.confusion + accumarray([labels(ok),predictions(ok)],1,[obj.numClasses obj.numClasses]) ;

            % compute various statistics of the confusion matrix
            pos = sum(obj.confusion,2) ;
            res = sum(obj.confusion,1)' ;
            tp = diag(obj.confusion) ;

            obj.pixelAccuracy = sum(tp) / max(1,sum(obj.confusion(:))) ;
            obj.meanAccuracy = mean(tp ./ max(1, pos)) ;
            obj.meanIntersectionUnion = mean(tp ./ max(1, pos + res - tp)) ;

            obj.average = [obj.pixelAccuracy ; obj.meanAccuracy ; obj.meanIntersectionUnion] ;
            obj.numAveraged = obj.numAveraged + numPixels ;
            outputs{1} = obj.average ;
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
            derInputs{1} = [] ;
            derInputs{2} = [] ;
            derParams = {} ;
        end

        function reset(obj)
            obj.confusion = 0 ;
            obj.pixelAccuracy = 0 ;
            obj.meanAccuracy = 0 ;
            obj.meanIntersectionUnion = 0 ;
            obj.average = [0;0;0] ;
            obj.numAveraged = 0 ;
        end

        function str = toString(obj)
            str = sprintf('acc:%.2f, mAcc:%.2f, mIU:%.2f', ...
                obj.pixelAccuracy, obj.meanAccuracy, obj.meanIntersectionUnion) ;
        end

        function obj = SegmentationAccuracy(varargin)
            obj.load(varargin) ;
            obj.numClasses = obj.numClasses;
        end
    end
end


categnames={'aeroplane';'bicycle';'bird';'boat';'bottle';'bus';'car';'cat';'chair';'cow';'diningtable';'dog';'horse';'motorbike';'person';'pottedplant';'sheep';'sofa';'train';'tvmonitor'};
transport=[1 2 4 6 7 14 19];
artic=[3 8 10 12 13 15 17];
indoor=[5 9 11 16 18 20];

groups={transport, artic, indoor};
for i=1:numel(groups)
for k=1:numel(groups{i})
	similar{groups{i}(k)}=setdiff(groups{i}, groups{i}(k));
end
end
for i=1:20
other{i}=setdiff([1:20], similar{i});
end


function triangle_fekete_rule_test01 ( )

%*****************************************************************************80
%
%% TRIANGLE_FEKETE_RULE_TEST01 tests FEKETE_RULE_NUM, FEKETE_DEGREE, FEKETE_ORDER_NUM.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 March 2014
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TRIANGLE_FEKETE_RULE_TEST01\n' );
  fprintf ( 1, '  FEKETE_RULE_NUM returns the number of rules;\n' );
  fprintf ( 1, '  FEKETE_DEGREE returns the degree of a rule;\n' );
  fprintf ( 1, '  FEKETE_ORDER_NUM returns the order of a rule.\n' );

  rule_num = fekete_rule_num ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of available rules = %d\n', rule_num );
  fprintf ( 1, '\n' );
  fprintf ( 1, '      Rule    Degree     Order\n' );
  fprintf ( 1, '\n' );

  for rule = 1 : rule_num
    order_num = fekete_order_num ( rule );
    degree = fekete_degree ( rule );
    fprintf ( 1, '  %8d  %8d  %8d\n', rule, degree, order_num );
  end

  return
end


clear all
close all
clc

i = 1;
switch i
    case 1
        load Dat_1.mat

    case 2
        load Dat_1.mat
end

N = 10000;
f = 1/N;
iterations = 12;
bits = 3;
levels = 2^bits;
m_max = 3.9;
delta = (2*m_max)/levels;
m = linspace(-m_max, m_max, levels+1);

for i = 1:iterations
    m
    for k = 1:levels

        sum=0;
        count=0;
        for j = 1:N
            if m(k) <= X(j) && X(j) < m(k+1)
                count = count + 1;
                sum = sum + X(j);
            end
        end

        if count == 0 && k <= levels/2
            v(k) = m(k);
        else
        if count == 0 && k > levels/2
            v(k) = m(k+1);
        else v(k) = sum/count;
        end
        end

    end

    for k = 2:levels-1
        m(k) = (v(k) + v(k+1))/2;
    end
   v
end


recall_i = 0:0.1:1.0;
fh = figure(1);clf;colormap(lines);
pr_wzr = [1.0000    0.5767    0.4589    0.3738    0.3135    0.2703    0.2331    0.2031    0.1722    0.1383    0.0250
1.0000    0.6796    0.5637    0.4768    0.4179    0.3639    0.3143    0.2654    0.2194    0.1662    0.0250
1.0000    0.7184    0.6358    0.5793    0.5322    0.4842    0.4371    0.3928    0.3345    0.2533    0.0250];
plot(recall_i,pr_wzr(1,:),recall_i,pr_wzr(2,:),recall_i,pr_wzr(3,:)); hold on;

eval_mvcnn = load('data/features/l11/evalRet.mat');
eval_mvcnn_metric = load('data/features/l12/evalRet.mat');
eval_fv = load('data/features/l5/evalRet.mat');

info = eval_fv.info;
pr_fv = zeros(size(info.recall_i,1),length(recall_i));
for i=1:size(info.recall_i,1),
    [recall_all,I] = unique(info.recall_i(i,:));
    precision_all = info.precision_i(i,I);
    pr_fv(i,:) = interp1(recall_all,precision_all,recall_i);
end

info = eval_mvcnn.info;
pr_mvcnn = zeros(size(info.recall_i,1),length(recall_i));
for i=1:size(info.recall_i,1),
    [recall_all,I] = unique(info.recall_i(i,:));
    precision_all = info.precision_i(i,I);
    pr_mvcnn(i,:) = interp1(recall_all,precision_all,recall_i);
end

info = eval_mvcnn_metric.info;
pr_mvcnn_metric = zeros(size(info.recall_i,1),length(recall_i));
for i=1:size(info.recall_i,1),
    [recall_all,I] = unique(info.recall_i(i,:));
    precision_all = info.precision_i(i,I);
    pr_mvcnn_metric(i,:) = interp1(recall_all,precision_all,recall_i);
end
plot(recall_i,mean(pr_fv),recall_i,mean(pr_mvcnn),recall_i,mean(pr_mvcnn_metric));
grid on; axis square;
legend('Spherical Harmonic','Light Field','3D ShapeNets','Fisher vector', 'Ours (MVCNN)','Ours (MVCNN+metric)');
ylabel('Precision');
xlabel('Recall');

print(fh,'pr.eps','-depsc');