function [channels,overall_amplitude] = eeg_amplitudearea(EEG, channels, resrate, wstart, wend)
% EEG_AMPLITUDEAREA - Resamples an ERP average using spline interpolation
%                       at a new sample rate (resrate) in Hz to get the exact limits
%                       of the window of integration. Finely samples the window
%                       and adds together very narrow rectangles capped by
%                       right-angled triangles under the window. Output is in uV.
%                       Trade-off between speed and number of resamples and number of
%                        channels selected occurs.
% Usage:
%      >> [channels, amplitude] = eeg_amplitudearea(EEG,channels, resrate, wstart, wend);
% Inputs:
%   EEG         - EEGLAB data struct containing a (3-D) epoched data matrix
%   channels    - vector of channel indices
%   resrate     - resampling rate for window of integration in Hz
%   wstart      - start of window of integration in ms post stimulus-onset
%   wend        - end of window of integration in ms post stimulus-onset
%
% Outputs:
%   channels    - a vector of channel indices.
%   amplitude   - 1-dimensional array in uV for the channels
%
% Example
%    >> [channels, amplitude] = eeg_amplitudearea(EEG,[12 18 25 29], 2000, 90.52, 120.52);
%
% Author: Tom Campbell, Helsinki Collegium for Advanced Studies, Biomag Laboratory,
%         Engineering Centre, Helsinki University Central Hospital Helsinki Brain
%         Research Centre (tom.campbell@helsinki.fi) Spartam nanctus es: Hanc exorna.
%         Combined with AMPLITUDEAREA_MSUV by Darren Weber, UCSF 28/1/05
%         Retested and debugged Tom Campbell 2/2/05
%         Reconceived, factored somewhat, tested and debugged Tom Campbell 13:24 23.3.2005

if wstart > wend
    error ('ERROR: wstart must be greater than wend')
else
    [channels, overall_amplitude] = eeg_amplitudearea_msuV (EEG,channels, resrate, wstart, wend);
    overall_amplitude = overall_amplitude/(wend - wstart);
end

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [channels, overall_area] = eeg_amplitudearea_msuV (EEG, channels, resrate, wstart, wend)

%if ndim(EEG.data) ~= 3
%  error('EEG.data must be 3-D data epochs');
%end
erp = mean(EEG.data,3);

[tmp ind1] =min( abs( EEG.times - wstart ) ); % closest time index to wstart
[tmp ind2] =min( abs( EEG.times - wend ) ); % closest time index to wend
restep = 1/resrate;

if EEG.times(ind1) > wstart
    ind1= ind1 -1;
end

if EEG.times(ind2) < wend
    ind2= ind2 +1;
end

for x= ind1:ind2
    t = (x -ind1)+1;
    tim(t) = EEG.times(x);
end

tr = 1;
timr(tr) = wstart;
while timr(tr) < wend
    tr = tr + 1;
    timr(tr) = timr(tr-1)+ restep;
end

for x = 1:size(channels,2)
    channel = channels(x);
    %resamples
    rerp(x, 1:tr) = spline(tim(:),erp(channel, ind1:ind2), timr(1:tr));
    pent = timr(tr - 1);
    overall_area(x) = 0;
    for y = 1:(tr -1)
        v1 =  rerp(x,(y));
        v2 =  rerp(x,(y+1));
        if ((v1 > 0) && (v2 < 0)) || ((v1 < 0) && (v2 > 0))
            if (y == (tr-1)) && (timr(y+1)> wend)
                area1 = zero_crossing_truncated(v1, v2, restep, wend, pent);
            else
                area1 = zero_crossing(v1, v2, restep);
            end
        else
            if( y == (tr-1)) && (timr(y+1)> wend)
                area1 = rect_tri_truncated(v1, v2, restep,wend,pent);
            else
                area1 = rect_tri(v1, v2, restep);
            end
        end
        overall_area(x) = overall_area(x) + area1;
    end
end

return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [area] = zero_crossing(v1,v2,step)
    if (v1 > v2)
        T1 = v1;
        T2 = v2;
    else
        T1 = v2;
        T2 = v1;
    end
    tantheta = (abs(T1)+ abs(T2))/step;
    if (v1 > v2)
        %decline
        z = abs(T1)/tantheta;
        tr1= abs(T1)*(z/2);
        tr2= abs(T2)*((step-z)/2);
    else
        %incline
        z = abs(T2)/tantheta;
        tr2= abs(T2)*(z/2);
        tr1= abs(T1)*((step-z)/2);
    end
    [area] = (tr1 - tr2);
return
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [area] = zero_crossing_truncated(v1,v2,step,wend,pent)
    if (v1 > v2)
        T1 = v1;
        T2 = v2;
    else
        T1 = v2;
        T2 = v1;
    end
    tantheta = (abs(T1)+ abs(T2))/step;
    s = wend - pent;
    if (v1 > v2)
        z = abs(T1)/tantheta
        if s < z
            %decline,truncated before zerocrossing
            t1 = tantheta * s;
            r1 = abs(T1)-abs(t1);
            tr1= abs(t1)*(s/2);
            tr2= 0;
            rect1 = r1*s;
            rect2 = 0;
        else
            %decline,truncated after zerocrossing
            t2= tantheta*(s-z);
            tr1= abs(T1)*(z/2);
            tr2 = abs(t2)*((s-z)/2);
            rect1 = 0;
            rect2 = 0;
        end
    else
        z = abs(T2)/tantheta;
        if s < z
            %incline,truncated before zerocrossing
            t2 = tantheta * s;
            r2 = abs(T2)-abs(t2);
            tr1= 0;
            tr2= abs(t2)*(s/2);
            rect1 = 0;
            rect2 = r2*s;
        else
            %incline,truncated after zerocrossing
            t1= tantheta*(s-z);
            tr1 = abs(t1)*((s-z)/2);
            tr2 = abs(T2) * (z/2);
            rect1 = 0;
            rect2 = 0;
        end
    end

[area] = ((rect1 + tr1) - (rect2 + tr2));
return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [area] = rect_tri(v1,v2,step)
    if (abs(v1) > abs(v2))
        T = abs(v1)-abs(v2);
        R = abs(v2);
    else
        T = abs(v2)-abs(v1);
        R = abs(v1);
    end
    rect = R*step;
    tri = T*(step/2);
    if v1 > 0
        area = 1* (rect+tri);
    else
        area = -1 * (rect+tri);
    end
return

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [area] = rect_tri_truncated(v1,v2,step,wend,pent)
    if (abs(v1) > abs(v2))
        T = abs(v1)-abs(v2);
        R = abs(v2);
    else
        T = abs(v2)-abs(v1);
        R = abs(v1);
    end

    tantheta = abs(T)/step;
    s = wend -pent;

    if (v1>0)
        if v1 >v2
        %positive decline
            t = tantheta*s;
            e = abs(T)-abs(t);
            rect = s*R;
            exrect = s*e;
            tri = (s/2)*R;
        else
        %positive incline
            t = tantheta*s;
            rect = s*R;
            exrect = 0;
            tri = (s/2)*R;
        end
    else
       if v1 >v2
        %negative decline
            t = tantheta*s;
            rect = s*R;
            exrect = 0;
            tri = (s/2)*R;
        else
        %negative incline
            t = tantheta*s;
            e = abs(T)-abs(t);
            rect = s*R;
            exrect = s*e;
            tri = (s/2)*R;
        end
    end
    tri = T*(step/2);
    if v1 > 0
        area = 1* (rect+exrect+tri);
    else
        area = -1 * (rect+exrect+tri);
    end
return


function  [value, isterminal, direction] = events_slidePos(~,Z,P)

[~, contacts] = dynamics_slidePos([],Z,P);
th = Z(1,:);
dx = Z(4,:);
H = contacts(1,:);
V = contacts(2,:);

%%%% CONSTRAINTS %%%%
% 1) -pi/2 < th
% 2) th < pi/2
% 3) dx >= 0
% 4) V >= 0
% 5) H <= 0

% As a rule, each constraint will be satisfied if it's event function value
% is positive. This makes things easier at the FSM level.
n = length(th);
value = zeros(5,n);
isterminal = true(size(value));
direction = -ones(size(value));

%%%% HACK %%%%
% avoid the singularity in the dynamics at th = pi/2
th_crit = pi/2 - 1e-10;
%%%% DONE %%%%

value(1,:) = th + th_crit ;
value(2,:) = th_crit - th;
value(3,:) = dx;
value(4,:) = V;
value(5,:) = -H;

end


%  FILE:   cluster_rects.m
%
%    This function derive canonical bounding box shapes by applying K-medoid
%    clustering on a set of bounding boxes.
%
%  INPUT:  imdb        (dataset)
%          N           (number of medoids)
%          minsz/maxsz (filter out boxes that are either too big or too small)
%          vis         (whether we visualize the clustering results)
%
%  OUTPUT: C           (N medoids)

function C  = cluster_rects(imdb, N, minsz, maxsz, vis)
if nargin < 5
  vis = 0;
end

%% cluster based on shapes of training examples
idx = find(imdb.images.set == 1);
rects = imdb.labels.rects(idx);
rects = vertcat(rects{:});

%% centralize
hs = rects(:,4) - rects(:,2) + 1;
ws = rects(:,3) - rects(:,1) + 1;
rects = [-(ws-1)/2, -(hs-1)/2, (ws-1)/2, (hs-1)/2];

%% ignore faces with size out of the range
idx = find(hs<=maxsz(1)&ws<=maxsz(2)&hs>=minsz(1)&ws>=minsz(2));
rects = rects(idx,:);
fprintf('Ignored faces smaller than %dx%d, %d bboxes left.\n',minsz(1),minsz(2),numel(idx));

%% subsample for faster clustering
rects = rects(randsample(size(rects,1), min(size(rects,1), 1e5)), :);
fprintf('Clustering on %d/%d face bounding boxes.\n', size(rects,1), numel(idx));

%% build kmedoids
[Cidx,C,sumd,D,midx] = kmedoids(rects, N, 'Options', statset('UseParallel', true), 'Distance', @rect_dist);

%% reorder clusters based on bounding box areas
[~,I] = sort(C(:,3).*C(:,4),'descend');
C = C(I,:);

if ~vis, return; end
subplot = @(m,n,k) subtightplot(m,n,k,[0.1,0.1]);
clf;
[SI,SJ] = factorize(N);
for i = 1:N
  subplot(SI,SJ,i);
  plotBoxes(C(i,1),C(i,2),C(i,3)-C(i,1)+1,C(i,4)-C(i,2)+1,rand(1,3),0.5);
  title(num2str(i));
  axis([-250,250,-250,250]);
end


function [Population,W] = updateWeight(Population,W,Z,EP,nus)
% Delete overcrowded subproblems and add new subproblems

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

% This function is written by Lucas Farias

	%% Parameter setting
    [N,M] = size(Population.objs);

    %% Delete the overcrowded subproblems
    Dis = pdist2(Population.objs,Population.objs);
    Dis(logical(eye(length(Dis)))) = inf;
    Del = false(1,length(Population));
    while sum(Del) < min(nus,length(EP))
        Remain = find(~Del);
        subDis = sort(Dis(Remain,Remain),2);
        [~,worst] = min(prod(subDis(:,1:min(M,length(Remain))),2));
        Del(Remain(worst)) = true;
    end
    Population = Population(~Del);
    W = W(~Del,:);

    %% Add new subproblems
    % Determine the new solutions be added
    Combine  = [Population,EP];
    Selected = false(1,length(Combine));
    Selected(1:length(Population)) = true;
    Dis = pdist2(Combine.objs,Combine.objs);
    Dis(logical(eye(length(Dis)))) = inf;
    while sum(Selected) < min(N,length(Selected))
        subDis = sort(Dis(~Selected,Selected),2);
        [~,best] = max(prod(subDis(:,1:min(M,size(subDis,2))),2));
        Remain = find(~Selected);
        Selected(Remain(best)) = true;
    end
    % Add new subproblems
    newObjs = EP(Selected(length(Population)+1:end)).objs;
    temp    = 1./(newObjs-repmat(Z,size(newObjs,1),1));
    temp(temp==inf) = 0.999999; % when (temp == Z) then 0
    W = [W;temp./repmat(sum(temp,2),1,size(temp,2))];
    % Add new solutions
    Population = Combine(Selected);
end


% Copyright 2014 Jason Heeris, jason.heeris@gmail.com
%
% This file is part of the gammatone toolkit, and is licensed under the 3-clause
% BSD license: https://github.com/detly/gammatone/blob/master/COPYING
function test_ERBFilterBank()

    erb_space_inputs = { ...
        100, 11025,  10, sin(2*pi*220*[0:22050/100]'/22050); ...
         20, 22050,  10, square(2*pi*150*[0:44100/200]'/44100); ...
         20, 44100,  40, square(2*pi*12000*[0:88200/400]'/88200); ...
        100, 11025, 1000, sawtooth(2*pi*10100*[0:22050/100]'/22050, 0.5); ...
        500, 80000,  200, sawtooth(2*pi*3333*[0:160000/400]'/160000, 0.5); ...
    };

    erb_filter_inputs = { ...
        44100, [22050; 2205; 220], square(2*pi*220*[0:44100/200]'/44100); ...
        16000, [8000; 7000; 6000; 5000; 4000; 3000; 2000; 1000], square(2*pi*2000*[0:16000/50]'/16000); ...
        16000, [16000; 8000; 1], square(2*pi*880*[0:16000/50]'/16000); ...
    };

    num_tests = size(erb_space_inputs)(1) ...
                + size(erb_filter_inputs)(1);

    erb_filterbank_inputs = {};

    erb_filterbank_results = {};

    % This will ONLY generate tests that use the centre frequency inputs

    % ERBSpace generated inputs
    for tnum=1:size(erb_space_inputs)(1)
        [f_low, f_high, num_f, wave] = deal(erb_space_inputs{tnum,:});
        fs = f_high*2;
        f_arr = ERBSpace(f_low, f_high, num_f);
        fcoefs = MakeERBFilters(fs, f_arr, 0);
        erb_filterbank_inputs(tnum, :) = {fcoefs, wave};
    end

    % MakeERBFilters generated inputs
    for tnum=1:size(erb_filter_inputs)
        [fs, f_arr, wave] = deal(erb_filter_inputs{tnum,:});
        fcoefs = MakeERBFilters(fs, f_arr, 0);
        offset = size(erb_space_inputs)(1);
        erb_filterbank_inputs(offset+tnum, :) = {fcoefs, wave};
    end

    for tnum=1:num_tests
        fcoefs = erb_filterbank_inputs{tnum, 1};
        wave = erb_filterbank_inputs{tnum, 2};
        erb_filterbank_results(tnum, :) = ERBFilterBank(wave, fcoefs);
    end

    results_file = fullfile('..', 'tests', 'data', 'test_filterbank_data.mat');
    save(results_file, 'erb_filterbank_inputs', 'erb_filterbank_results');
end


function [FV,C] = eeg_interp_sph_spline_scd(Zi,Ei)

% eeg_interp_sph_spline_scd - Spherical Spline Scalp Current Density
%
% Useage: [FV,C] = eeg_interp_sph_spline_scd(Zi,Ei)
%
% This function calls eeg_interp_sph_spline,
% and replaces the relevant sections from Perrin et al. (1990)
% to calculate the scalp current density (SCD).
%
% FV => interpolated spherical surface
%
% FV.faces    => triangulation of FV.vertices
% FV.vertices => cartesian coordinates (Nx3)
% FV.Cdata    => spherical spline SCD at FV.vertices
%
% C => interpolation coefficients of Ei (includes co = C(1))
%
% Notes:    This function calculates the spherical spline SCD of
%           Perrin et al (1989).  Electroenceph. & Clin.
%             Neurophysiology, 72: 184-187. Corrigenda (1990),
%             Electroenceph. & Clin. Neurophysiology, 76: 565.
%             (see comments in the .m file for details).

% $Revision: 1.1 $ $Date: 2009-04-28 22:13:51 $

% Licence:  GNU GPL, no implied or express warranties
% History:  10/2003 Darren.Weber_at_radiology.ucsf.edu, with
%                   adapted from eeg_interp_sph_spline
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[C,r] = eeg_interp_sph_spline_c(Zi,Ei);

Co = C(1);
Ci = C(2:end);

eegversion = '$Revision: 1.1 $';
fprintf('EEG_INTERP_SPH_SPLINE_SCD [v %s]\n',eegversion(11:15)); tic

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Now that C is solved, we can obtain interpolated scalp current density
% at Ej (Eq. 5)

% create spherical interpolation positions
fprintf('...generating spherical interpolation points\n');
FV = sphere_tri('ico',4,r);

% cosines between measurement electrodes and interpolation points
Cos = elec_cosines(Ei,FV.vertices);

% Calculate h(x)
Hx = eeg_interp_sph_spline_h(Cos,r);  % nElectrodes x NinterpolationPoints

% Solve Eq 5.
FV.Cdata = (Ci' * Hx)';

t=toc; fprintf('...done (%6.2f sec)\n',t);

return


% Compute h-step Weisfeiler-Lehman shortest path delta kernel for a set of graphs
% Author: Nino Shervashidze - nino.shervashidze@tuebingen.mpg.de
% Copyright 2010 Nino Shervashidze
% Input: Graphs - a 1xN array of graphs
% 		  Graphs(i).am is the adjacency matrix of the i'th graph,
% 		  Graphs(i).al is the adjacency list of the i'th graph,
%                 Graphs(i).nl.values is a column vector of node
%                 labels for the i'th graph.
%                 Graphs(i).sp (may be missing) is the shortest
%                 path length matrix of the i'th graph
%                 Graphs(i) may have other fields, but they will not be
%                 used here.
%	 h - a natural number: number of iterations of WL
%	 nl - a boolean: 1 if we want to use original node labels, 0 otherwise
%        spprec - a boolean: 1 if shortest paths are precomputed, 0
%        otherwise. Default: 0
% Output: K - a h+1-element cell array of NxN kernel matrices K for
%             each iter = 0,...,h
%         runtime - scalar (total runtime in seconds)

function [K,runtime] = WLspdelta(Graphs,h,nl,spprec)
% THIS SOURCE CODE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND, AND
% ITS AUTHOR AND THE JOURNAL OF MACHINE LEARNING RESEARCH (JMLR) AND
% JMLR'S PUBLISHERS AND DISTRIBUTORS, DISCLAIM ANY AND ALL WARRANTIES,
% INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY
% AND FITNESS FOR A PARTICULAR PURPOSE, AND ANY WARRANTIES OR NON
% INFRINGEMENT. THE USER ASSUMES ALL LIABILITY AND RESPONSIBILITY FOR
% USE OF THIS SOURCE CODE, AND NEITHER THE AUTHOR NOR JMLR, NOR JMLR'S
% PUBLISHERS AND DISTRIBUTORS, WILL BE LIABLE FOR DAMAGES OF ANY KIND
% RESULTING FROM ITS USE. Without limiting the generality of the foregoing,
% neither the author, nor JMLR, nor JMLR's publishers and distributors,
% warrant that the Source Code will be error-free, will operate without
% interruption, or will meet the needs of the user.

N=size(Graphs,2);
Lists = cell(1,N);
K = cell(1,h+1);
if nargin<4 spprec=0; end
n_nodes=0;
% compute adjacency lists and n_nodes, the total number of nodes in the dataset
for i=1:N
  Lists{i}=Graphs(i).al;
  n_nodes=n_nodes+size(Graphs(i).am,1);
end
% compute/copy shortest path matrices
maxpath = 0;
if ~spprec
  disp('computing shortest paths...');
  for i=1:N
    Ds{i}=floydwarshall(Graphs(i).am);
    aux=max(Ds{i}(~isinf(Ds{i})));
    if aux > maxpath
      maxpath=aux;
    end
  end
else
  for i=1:N
    Ds{i}=Graphs(i).sp;
    aux=max(Ds{i}(~isinf(Ds{i})));
    if aux > maxpath
      maxpath=aux;
    end
  end
end
t=cputime; % for measuring runtime

%%% INITIALISATION
% initialize the node labels for each graph with their labels or
% with degrees (for unlabeled graphs).
label_lookup=containers.Map();
label_counter=uint32(1);
% label_lookup is an associative array, which will contain the
% mapping from multiset labels (strings) to short labels (integers)
if nl==1
  for i=1:N
    % the type of labels{i} is uint32, meaning that it can only handle
    % 2^32 labels and compressed labels over all iterations. If
    % more is needed, switching (all occurences of uint32) to
    % uint64 is a possibility
    labels{i}=zeros(size(Graphs(i).nl.values,1),1,'uint32');
    for j=1:length(Graphs(i).nl.values)
      str_label=num2str(Graphs(i).nl.values(j));
      % str_label is the node label of the current node of the
      % current graph converted into a string
      if ~isKey(label_lookup, str_label)
        %str_label
        %label_counter
        label_lookup(str_label)=label_counter;
        labels{i}(j)=label_counter;
        label_counter=label_counter+1;
      else
        labels{i}(j)=label_lookup(str_label);
      end
    end
  end
else
  for i=1:N
    labels{i}=uint32(full(sum(Graphs(i).am,2)));
    for j=1:length(labels{i})
      str_label=num2str(labels{i}(j));
      % str_label is the node label of the current node of the
      % current graph converted into a string
      if ~isKey(label_lookup, str_label)
        label_lookup(str_label)=label_counter;
        labels{i}(j)=label_counter;
        label_counter=label_counter+1;
      else
        labels{i}(j)=label_lookup(str_label);
      end
    end
  end
end
L=double(label_counter)-1;
clear Graphs;
disp(['Number of original labels: ',num2str(L)]);
disp(['Number of potential shortest path features: ',num2str((maxpath+1)*L*(L+1)/2)]);
sp=sparse((maxpath+1)*L*(L+1)/2,N);
for i=1:N
  labels_aux=repmat(double(labels{i}),1,length(labels{i}));
  a=min(labels_aux, labels_aux');
  b=max(labels_aux, labels_aux');
  I=triu(~(isinf(Ds{i})));
  Ind=Ds{i}(I)*L*(L+1)/2+(a(I)-1).*(2*L+2-a(I))/2+b(I)-a(I)+1;
  minind=min(Ind);
  diff=max(Ind)-minind;
  aux=accumarray(Ind,ones(nnz(I),1),[],[],[],(minind > 5000 || diff > 3000));
  % sparse of full accumarray depending on the range of values in Ind
  % (and based on empirical observations on the speed of accumarray)
  sp(Ind,i)=aux(Ind);
end
sp=sp(sum(sp,2)~=0,:);
K{1}=full(sp'*sp);

%%% MAIN LOOP
iter=1;
new_labels=labels;
while iter<=h
  disp(['iter=',num2str(iter)]);
  % create an empty lookup table
  label_lookup=containers.Map();
  label_counter=uint32(1);
  for i=1:N
    for v=1:length(Lists{i})
      % form a multiset label of the node v of the i'th graph
      % and convert it to a string
      long_label=[labels{i}(v), sort(labels{i}(Lists{i}{v}))'];
      long_label_2bytes=typecast(long_label,'uint16');
      long_label_string=char(long_label_2bytes);
      % if the multiset label has not yet occurred, add it to the
      % lookup table and assign a number to it
      if ~isKey(label_lookup, long_label_string)
        label_lookup(long_label_string)=label_counter;
        new_labels{i}(v)=label_counter;
        label_counter=label_counter+1;
      else
        new_labels{i}(v)=label_lookup(long_label_string);
      end
    end
  end
  L=double(label_counter)-1;
  disp(['Number of compressed labels: ',num2str(L)]);
  disp(['Number of potential shortest path features: ',num2str((maxpath+1)*L*(L+1)/2)]);
  labels=new_labels;
  sp=sparse((maxpath+1)*L*(L+1)/2,N);
  for i=1:N
    labels_aux=repmat(double(labels{i}),1,length(labels{i}));
    a=min(labels_aux, labels_aux');
    b=max(labels_aux, labels_aux');
    I=triu(~(isinf(Ds{i})));
    Ind=Ds{i}(I)*L*(L+1)/2+(a(I)-1).*(2*L+2-a(I))/2+b(I)-a(I)+1;
    minind=min(Ind);
    diff=max(Ind)-minind;
    aux=accumarray(Ind,ones(nnz(I),1),[],[],[],(minind > 5000 || diff > 3000));
    % sparse of full accumarray depending on the range of values in Ind
    % (and based on empirical observations on the speed of accumarray)
    sp(Ind,i)=aux(Ind);
  end
  sp=sp(sum(sp,2)~=0,:);
  K{iter+1}=K{iter}+full(sp'*sp);
  iter=iter+1;
end
runtime=cputime-t; % computation time of K
end

function [D] = floydwarshall(A, sym, w)
% Input: A - nxn adjacency matrix,
%           sym - boolean, 1 if A and w symmetric
%	    w - nxn weight matrix
% Output: D - nxn distance matrix

n = size(A,1); % number of nodes
D=zeros(n,n);

if nargin<2 % if the graph is not weighted and we have no information about sym, then
  sym=1;
  w=A;
end

if nargin<3 % if the graph is not weighted, then
  w=A;
end

D=w.*A;
D(A+diag(repmat(Inf,n,1))==0)=Inf;
D=full(D.*(ones(n)-eye(n))); % set the diagonal to zero

if sym % then it is a bit faster
  for k=1:n
    Daux=repmat(full(D(:,k)),1,n);
    Sumdist=Daux+Daux';
    D(Sumdist<D)=Sumdist(Sumdist<D);
  end
else
  for k=1:n
    Daux1=repmat(full(D(:,k)),1,n);
    Daux2=repmat(full(D(k,:)),n,1);
    Sumdist=Daux1+Daux2;
    D(Sumdist<D)=Sumdist(Sumdist<D);
  end
end
end


function s=dec2decbin(d,n)
%DEC2BIN Internal function generate binary matrices

[f,e]=log2(max(d)); % How many digits do we need to represent the numbers?
s=rem(floor(d(:)*pow2(1-max(n,e):0)),2);


function [ a, ipvt, info ] = chifa ( a, lda, n )

%*****************************************************************************80
%
%% CHIFA factors a complex hermitian matrix.
%
%  Discussion:
%
%    CHIFA performs the factoring by elimination with symmetric pivoting.
%
%    To solve A*X = B, follow CHIFA by CHISL.
%
%    To compute inverse(A)*C, follow CHIFA by CHISL.
%
%    To compute determinant(A), follow CHIFA by CHIDI.
%
%    To compute inertia(A), follow CHIFA by CHIDI.
%
%    To compute inverse(A), follow CHIFA by CHIDI.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch and Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, (Society for Industrial and Applied Mathematics),
%    3600 University City Science Center,
%    Philadelphia, PA, 19104-2688.
%
%  Parameters:
%
%    Input, complex A(LDA,N); the hermitian matrix to be factored.
%
%    Input, integer LDA, the leading dimension of A.
%
%    Input, integer N, the order of the matrix.
%
%    Output, complex A(LDA,N); a block diagonal matrix and the multipliers which
%    were used to obtain it.  The factorization can be written
%    A = U*D*hermitian(U) where U is a product of permutation and unit upper
%    triangular matrices, hermitian(U) is the conjugate transpose of U, and
%    D is block diagonal with 1 by 1 and 2 by 2 blocks.  Only the diagonal
%    and upper triangle are used.
%
%    Output, integer IPVT(N), the pivot indices.
%
%    Output, integer INFO.
%    0, normal value.
%    K, if the K-th pivot block is singular.  This is not an error condition
%    for this subroutine, but it does indicate that CHISL or CHIDI may
%    divide by zero if called.
%

%
%  Initialize.
%
%  ALPHA is used in choosing pivot block size.
%
  alpha = ( 1.0 + sqrt ( 17.0 ) ) / 8.0;

  info = 0;
%
%  Main loop on K, which goes from N to 1.
%
  k = n;

  while ( 1 )
%
%  Leave the loop if K = 0 or K = 1.
%
    if ( k == 0 )
      break
    end

    if ( k == 1 )
      ipvt(1) = 1;
      if ( cabs1 ( a(1,1) ) == 0.0 )
        info = 1;
      end
      break
    end
%
%  This section of code determines the kind of
%  elimination to be performed.  When it is completed,
%  KSTEP will be set to the size of the pivot block, and
%  SWAP will be set to TRUE if an interchange is
%  required.
%
    km1 = k - 1;
    absakk = cabs1 ( a(k,k) );
%
%  Determine the largest off-diagonal element in column K.
%
    imax = icamax ( k-1, a(1:k-1,k), 1 );
    colmax = cabs1 ( a(imax,k) );

    if ( alpha * colmax <= absakk )

      kstep = 1;
      swap = 0;

    else
%
%  Determine the largest off-diagonal element in row IMAX.
%
      rowmax = 0.0;

      for j = imax + 1 : k
        rowmax = max ( rowmax, cabs1 ( a(imax,j) ) );
      end

      if ( imax ~= 1 )
        jmax = icamax ( imax-1, a(1:imax-1,imax), 1 );
        rowmax = max ( rowmax, cabs1 ( a(jmax,imax) ) );
      end

      if ( alpha * rowmax <= cabs1 ( a(imax,imax) )  )
        kstep = 1;
        swap = 1;
      elseif ( alpha * colmax * ( colmax / rowmax ) <= absakk )
        kstep = 1;
        swap = 0;
      else
        kstep = 2;
        swap = ( imax ~= km1 );
      end

    end
%
%  Column K is zero.  Set INFO and iterate the loop.
%
    if ( max ( absakk, colmax ) == 0.0 )
      ipvt(k) = k;
      info = k;
      k = k - kstep;
      continue
    end

    if ( kstep ~= 2 )
%
%  1 x 1 pivot block.
%
      if ( swap )

        temp           = a(1:imax,imax);
        a(1:imax,imax) = a(1:imax,k);
        a(1:imax,k)    = temp;

        for jj = imax : k
          j = k + imax - jj;
          t         = conj ( a(j,k) );
          a(j,k)    = conj ( a(imax,j) );
          a(imax,j) = t;
        end

      end
%
%  Perform the elimination.
%
      for jj = 1 : km1
        j = k - jj;
        mulk = -a(j,k) / a(k,k);
        t = conj ( mulk );
        a(1:j,j) = a(1:j,j) + t * a(1:j,k);
        a(j,j) = real ( a(j,j) );
        a(j,k) = mulk;
      end
%
%  Set the pivot array.
%
      ipvt(k) = k;

      if ( swap )
        ipvt(k) = imax;
      end

    else
%
%  2 x 2 pivot block.
%
      if ( swap )

        temp           = a(1:imax,imax);
        a(1:imax,imax) = a(1:imax,k-1);
        a(1:imax,k-1)  = temp;

        for jj = imax : km1
          j = km1 + imax - jj;
          t         = conj ( a(j,k-1) );
          a(j,k-1)  = conj ( a(imax,j) );
          a(imax,j) = t;
        end

        t         = a(k-1,k);
        a(k-1,k)  = a(imax,k);
        a(imax,k) = t;

      end
%
%  Perform the elimination.
%
      km2 = k - 2;

      if ( 0 < k - 2 )

        ak = a(k,k) / a(k-1,k);
        akm1 = a(k-1,k-1) / conj ( a(k-1,k) );
        denom = 1.0 - ak * akm1;

        for jj = 1 : k - 2

          j = km1 - jj;
          bk = a(j,k) / a(k-1,k);
          bkm1 = a(j,k-1) / conj ( a(k-1,k) );
          mulk = ( akm1 * bk - bkm1 ) / denom;
          mulkm1 = ( ak * bkm1 - bk ) / denom;
          t = conj ( mulk );
          a(1:j,j) = a(1:j,j) + t * a(1:j,k);
          t = conj ( mulkm1 );
          a(1:j,j) = a(1:j,j) + t * a(1:j,k-1);
          a(j,k) = mulk;
          a(j,k-1) = mulkm1;
          a(j,j) = real ( a(j,j) );

        end

      end
%
%  Set the pivot array.
%
      if ( swap )
        ipvt(k) = -imax;
      else
        ipvt(k) = 1 - k;
      end

      ipvt(k-1) = ipvt(k);

    end

    k = k - kstep;

  end

  return
end


function test_rb_inverse_dynamics()

path_to_urdf = 'ur10e.urdf';
ur10 = parse_urdf(path_to_urdf);

rbt = importrobot('ur10e.urdf');
rbt.DataFormat = 'column';
rbt.Gravity = [0 0 -9.81];

no_iter = 100;
for i = 1:no_iter
    q = -2*pi + 4*pi*rand(6,1);
    q_d = zeros(6,1);
    q_2d = zeros(6,1);

    Ylgr = standard_regressor_UR10E(q,q_d,q_2d);

    tau_matlab = inverseDynamics(rbt,q,q_d,q_2d);
    tau_reg = Ylgr*reshape(ur10.pi,[60,1]);
    tau_manip = M_mtrx_fcn(q, ur10.pi(:))*q_2d + ...
                C_mtrx_fcn(q, q_d, ur10.pi(:))*q_d + ...
                G_vctr_fcn(q, ur10.pi(:));

%   verifying if regressor is computed correctly
    assert(norm(tau_matlab - tau_reg) < 1e-8);
    assert(norm(tau_matlab - tau_manip) < 1e-8);
end

fprintf("Rigid Body Inverse Dynamics Test - OK!\n");


function value = r8_sign_match ( r1, r2 )

%*****************************************************************************80
%
%% R8_SIGN_MATCH is TRUE if two R8's are of the same sign.
%
%  Discussion:
%
%    This test could be coded numerically as
%
%      if ( 0 <= r1 * r2 ) then ...
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 April 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R1, R2, the values to check.
%
%    Output, logical VALUE, is TRUE if ( R1 <= 0 and R2 <= 0 )
%    or ( 0 <= R1 and 0 <= R2 ).
%
  value = ( r1 <= 0.0 && r2 <= 0.0 ) || ( 0.0 <= r1 && 0.0 <= r2 );

  return
end


classdef ABC < ALGORITHM
% <single> <real/integer> <large/none> <constrained/none>
% Artificial bee colony algorithm
% limit --- 20 --- The number of trials for releasing a food source

%------------------------------- Reference --------------------------------
% D. Karaboga, An idea based on honey bee swarm for numerical optimization,
% Erciyes University, Tech. Rep. tr06, 2005.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    methods
        function main(Algorithm,Problem)
            %% Parameter setting
            limit = Algorithm.ParameterSet(20);

            %% Generate random population
            Population = Problem.Initialization();
            Limit      = zeros(1,Problem.N);

            %% Optimization
            while Algorithm.NotTerminated(Population)
                % Employed bees
                Pdec      = Population.decs;
                Odec      = Pdec + (rand(size(Pdec))*2-1).*(Pdec-Pdec(randi(end,1,end),:));
                Offspring = Problem.Evaluation(Odec);
                replace             = FitnessSingle(Population) > FitnessSingle(Offspring);
                Population(replace) = Offspring(replace);
                Limit(~replace)     = Limit(~replace) + 1;

                % Onlooker bees
                Q         = RouletteWheelSelection(Problem.N,exp(Population.objs/mean(abs(Population.objs+1e-6))));
                Pdec      = Population.decs;
                Odec      = Pdec(Q,:) + (rand(size(Pdec))*2-1).*(Pdec(Q,:)-Pdec(randi(end,1,end),:));
                Offspring = Problem.Evaluation(Odec);
                replace             = FitnessSingle(Population) > FitnessSingle(Offspring);
                Population(replace) = Offspring(replace);
                Limit(~replace)     = Limit(~replace) + 1;

                % Scout bees
                Q = Limit > limit;
                if any(Q)
                    Population(Q) = Problem.Initialization(sum(Q));
                    Limit(Q)      = 0;
                end
            end
        end
    end
end


%% axis_inc
% Below is a demonstration of the features of the |axis_inc| function

%%
clear; close all; clc;

%% Syntax
% |h=axis_inc(s);|

%% Description
% This function widens the axis limits for the axis with the handle |hs|
% using the scale factor |s| (e.g. if s=2 the axis width is doubled). The
% scaling parameter |s| can be a single scalar or a vector such that each
% axis direction is scaled differently.
%
%% Examples
%

%%
% Plot settings
fontSize=25;
lineWidth=3;

%% Scaling limits on a 2D plot

scaleFactor=2;

cFigure;
h1=subplot(1,2,1); hold on;
title('Original axis limits');
plot([-1 1 1 -1],[-1 -1 1 1],'b-','LineWidth',lineWidth);
axis tight; axis equal; view(2); box on; grid on;
set(h1,'FontSize',fontSize);

h2=subplot(1,2,2); hold on;
title(['Axis limits expanded using scale factor of ',sprintf('%.2f',scaleFactor)]);
plot([-1 1 1 -1],[-1 -1 1 1],'b-','LineWidth',lineWidth);
axis tight; axis equal; view(2); box on; grid on;
axis_inc(scaleFactor,h2);
set(h2,'FontSize',fontSize);
drawnow;

%% Scaling limits on a 3D plot

[F,V]=graphicsModels(8);

scaleFactor=[2 4 2];

cFigure;
h1=subplot(1,2,1); hold on;
title('Original axis limits');
gpatch(F,V,'bw','none');
axisGeom(h1,fontSize);
set(h1,'FontSize',fontSize);
camlight headlight;

h2=subplot(1,2,2); hold on;
title(['Axis limits expanded using scale factor of ',sprintf('%.2f, %.2f, %.2f',scaleFactor)]);
gpatch(F,V,'bw','none');
axisGeom(h1,fontSize);
axis_inc(scaleFactor,h2);
set(h2,'FontSize',fontSize);
camlight headlight;
drawnow;

%%
%
% <<gibbVerySmall.gif>>
%
% _*GIBBON*_
% <www.gibboncode.org>
%
% _Kevin Mattheus Moerman_, <gibbon.toolbox@gmail.com>
%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function out = EN_DistributionEntropy(y,histOrKS,numBins,olremp)
% EN_DistributionEntropy    Distributional entropy.
%
% Estimates of entropy from the distribution of a data vector. The
% distribution is estimated either using a histogram with numBins bins, or as a
% kernel-smoothed distribution, using the ksdensity function from Matlab's
% Statistics Toolbox with width parameter, w (specified as the iunput numBins).
%
% An optional additional parameter can be used to remove a proportion of the
% most extreme positive and negative deviations from the mean as an initial
% pre-processing.
%
%---INPUTS:
%
% y, the input time series
%
% histOrKS: 'hist' for histogram, or 'ks' for ksdensity
%
% numBins: (*) (for 'hist'): an integer, uses a histogram with that many bins
%          (*) (for 'ks'): a positive real number, for the width parameter for
%                       ksdensity (can also be empty for default width
%                                       parameter, optimum for Gaussian)
%
% olremp [opt]: the proportion of outliers at both extremes to remove
%               (e.g., if olremp = 0.01; keeps only the middle 98% of data; 0
%               keeps all data. This parameter ought to be less than 0.5, which
%               keeps none of the data).
%               If olremp is specified, returns the difference in entropy from
%               removing the outliers.

% ------------------------------------------------------------------------------
% Copyright (C) 2020, Ben D. Fulcher <ben.d.fulcher@gmail.com>,
% <http://www.benfulcher.com>
%
% If you use this code for your research, please cite the following two papers:
%
% (1) B.D. Fulcher and N.S. Jones, "hctsa: A Computational Framework for Automated
% Time-Series Phenotyping Using Massive Feature Extraction, Cell Systems 5: 527 (2017).
% DOI: 10.1016/j.cels.2017.10.001
%
% (2) B.D. Fulcher, M.A. Little, N.S. Jones, "Highly comparative time-series
% analysis: the empirical structure of time series and their methods",
% J. Roy. Soc. Interface 10(83) 20130048 (2013).
% DOI: 10.1098/rsif.2013.0048
%
% This function 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.
%
% You should have received a copy of the GNU General Public License along with
% this program. If not, see <http://www.gnu.org/licenses/>.
% ------------------------------------------------------------------------------

doPlot = 0; % plot outputs to figure

% ------------------------------------------------------------------------------
%% Check inputs
% ------------------------------------------------------------------------------
if nargin < 2 || isempty(histOrKS)
    histOrKS = 'hist'; % use histogram by default
end
if nargin < 3 % (can be empty for default width for ksdensity)
    numBins = 10; % use 10 bins
end
if nargin < 4
    olremp = 0;
end

% ------------------------------------------------------------------------------
% (1) Remove outliers?
% ------------------------------------------------------------------------------
if olremp ~= 0
    yHat = y(y >= quantile(y,olremp) & y <= quantile(y,1-olremp));
    if isempty(yHat)
        % removed the entire time series?!
        % shouldn't be possible for good values of olremp with equality
        % in the above inequalities
        out = NaN; return
    else
        % Return the difference in entropy from removing outliers
        out = EN_DistributionEntropy(y,histOrKS,numBins) - ...
                EN_DistributionEntropy(yHat,histOrKS,numBins);
        return
    end
end

% ------------------------------------------------------------------------------
% (2) Form the histogram
% ------------------------------------------------------------------------------
switch histOrKS
case 'hist' % Use histogram to calculate pdf
    if isnumeric(numBins)
        [px,binEdges] = histcounts(y,numBins,'Normalization','probability');
    else
        [px,binEdges] = histcounts(y,'BinMethod',numBins,'Normalization','probability');
    end
    % Compute bin centers:
    xr = mean([binEdges(1:end-1); binEdges(2:end)]);
    % Compute bin widths:
    binWidths = diff(binEdges);

case 'ks' % Use ksdensity to calculate pdf
    if isempty(numBins)
        [px, xr] = ksdensity(y,'function','pdf'); % selects optimal width
    else
        [px, xr] = ksdensity(y,'width',numBins,'function','pdf'); % uses specified width
    end
    binWidths = ones(1,length(px))*(xr(2)-xr(1));

otherwise
    error('Unknown distribution method -- specify ''ks'' or ''hist''') % error; must specify 'ks' or 'hist'
end

if doPlot
    figure('color','w'); box('on');
    plot(xr,px,'k')
end

% ------------------------------------------------------------------------------
% (3) Compute the entropy sum and return it as output
% ------------------------------------------------------------------------------
% 0*log0 = 0:
out = -sum(px(px>0).*log(px(px>0)./binWidths(px>0)));

end


function ac = compressLogicalArray(a)
ac = [];
if isempty(a)
    return;
end
if all(a==1)
    ac = [1,length(a), 1];
    return
end
if all(a==0)
    ac = [1,length(a), 0];
    return
end
k = find(a==0);
kk = 1;

% Generate all zero intervals
for ii = 1:length(k)
    if ii == 1
        iS = k(ii);
        iE = k(ii);
    end
    if ii>1 && k(ii-1)+1 == k(ii)
        iE = iE+1;
    elseif ii>1 && k(ii-1)+1 < k(ii)
        ac(kk,:) = [iS, iE, 0]; %#ok<*AGROW>
        kk = kk+1;
        iS = k(ii);
        iE = k(ii);
    end
    if ii==length(k)
        ac(kk,:) = [iS, iE, 0];
    end
end

% Generate all one intervals
kk = 1;
for ii = 1:size(ac,1)
    if ii == 1
        if ac(ii,1) == 1
            ac2(kk,:) = ac(ii,:);
        else
            ac2(kk,:) = [1, ac(ii,1)-1, 1];
            kk = kk+1;
            ac2(kk,:) = ac(ii,:);
        end
    else
        ac2(kk,:) = [ac(ii-1,2)+1, ac(ii,1)-1, 1];
        kk = kk+1;
        ac2(kk,:) = ac(ii,:);
    end
    kk = kk+1;
    if ii==size(ac,1) && ac(ii,2)<length(a)
        ac2(kk,:) = [ac(ii,2)+1, length(a), 1];
        kk = kk+1;
    end
end

ac = ac2;


function [percentCorrect,correctLogical] = prtScorePercentCorrect(dataSet1,dataSet2)
% PERCENTCORRECT = prtScorePercentCorrect(GUESS, TRUTH)
%
%   PERCENTCORRECT = prtScorePercentCorrect(GUESS, TRUTH) returns the
%   percent of correct guesses in GUESS as compared to the truth in TRUTH.
%   GUESS and TRUTH should both be Nx1 vectors. The elements of both
%   TRUTH and GUESS should be binary or interger class labels.
%
%   Example:
%   TestDataSet = prtDataGenUnimodal;       % Create some test and
%   TrainingDataSet = prtDataGenUnimodal;   % training data
%   classifier = prtClassMap;               % Create a classifier
%   % Use minimum probablity of error rule
%   classifier.internalDecider = prtDecisionBinaryMinPe;
%   classifier = classifier.train(TrainingDataSet);    % Train
%   classified = run(classifier, TestDataSet);         % Test
%   percentCorr = prtScorePercentCorrect(classified,TestDataSet)
%
%   See also prtScoreConfusionMatrix, prtScoreRoc, prtScoreRmse

if nargin < 2
    dataSet2 = dataSet1;
end

[guesses,targets] = prtUtilScoreParseFirstTwoInputs(dataSet1,dataSet2);

if size(guesses,2) ~= 1
    error('prt:prtScorePercentCorrect','GUESS must be a N x 1 integer vector of class guesses');
else
    percentCorrect = mean(guesses == targets);
    if nargout > 1
        correctLogical = guesses == targets;
    end
end


function[]=makefigs_wavetrans
%MAKEFIGS_WAVETRANS  Makes a sample figure for WAVETRANS.

load bravo94
%not using 'use' as it's not compatible in scripts with some systems
num=bravo94.rcm.num;
cv=bravo94.rcm.cv;

vindex(cv,2,2);

gamma=3;beta=2;
fs=morsespace(gamma,beta,{0.05,pi},pi/1000,4);
[wp,wn]=wavetrans(cv,conj(cv),{gamma,beta,fs,'bandpass'});
h=wavespecplot(yearfrac(num),vfilt(cv,24),1./fs,sqrt(squared(wp)+squared(wn)));
colormap lansey
axes(h),ylim([-35 55]),hlines(0,'k:'),caxis([0.25 21])

%To print
if 0
    currentdir=pwd;
    cd([whichdir('jlab_license') '/figures'])
    print -dpng wavetrans
    crop wavetrans.png
    cd(currentdir)
end


function []=stvoldisp(beta_median,beta_std,beta_lbound,beta_ubound,sigma_median,sigma_t_median,sigma_t_lbound,sigma_t_ubound,gamma_median,X,Y,n,m,p,k,T,stvol,bex,ar,lambda1,lambda2,lambda3,lambda4,lambda5,gamma,alpha0,delta0,gamma0,zeta0,IRFt,const,endo,exo,startdate,enddate,stringdates1,decimaldates1,pref,PriorExcel)

% before displaying and saving the results, start estimating the evaluation measures for the model

% obtain first a point estimate betatilde of the VAR coefficients
% this is simply the median
betatilde=beta_median;
Btilde=reshape(betatilde,k,n);
% use this estimate to produce predicted values for the model, following (a.8.2)
Ytilde=X*Btilde;
% then produce the corresponding residuals, using (a.8.3)
EPStilde=Y-Ytilde;

% check first whether the model is stationary, using (a.7.2)
[stationary eigmodulus]=bear.checkstable(betatilde,n,p,k);

% Compute then the sum of squared residuals
% compute first the RSS matrix, defined in (a.8.4)
RSS=EPStilde'*EPStilde;
% retain only the diagonal elements to get the vector of RSSi values
rss=diag(RSS);

% Go on calculating R2
% generate Mbar
Mbar=eye(T)-ones(T,T)/T;
% then compute the TSS matrix, defined in (a.8.7)
TSS=Y'*Mbar*Y;
% generate the R2 matrix in (a.8.8)
R2=eye(n)-RSS./TSS;
% retain only the diagonal elements to get the vector of R2 values
r2=diag(R2);

% then calculate the adjusted R2, using (a.8.9)
R2bar=eye(n)-((T-1)/(T-k))*(eye(n)-R2);
% retain only the diagonal elements to get the vector of R2bar values
r2bar=diag(R2bar);

% now start displaying and saving the results

% preliminary task: create and open the txt file used to save the results

filelocation=fullfile(pref.results_path, [pref.results_sub '.txt']);
fid=fopen(filelocation,'wt');

% print toolbox header

fprintf('%s\n','');
fprintf(fid,'%s\n','');

% print the list of contributors
bear.printcontributors(fid);

% print then estimation results

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

toolboxinfo='BEAR toolbox estimates';
fprintf('%s\n',toolboxinfo);
fprintf(fid,'%s\n',toolboxinfo);

time=clock;
datestring=datestr(time);
dateinfo=['Date: ' datestring(1,1:11) '   Time: ' datestring(1,13:17)];
fprintf('%s\n',dateinfo);
fprintf(fid,'%s\n',dateinfo);

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

VARtypeinfo='Stochastic volatility BVAR';
fprintf('%s\n',VARtypeinfo);
fprintf(fid,'%s\n',VARtypeinfo);

if stvol==1
    modelinfo='Stochastic volatility model: standard';
elseif stvol==2
    modelinfo='Stochastic volatility model: random inertia';
elseif stvol==3
    modelinfo='Stochastic volatility model: large BVAR';
end
fprintf('%s\n',modelinfo);
fprintf(fid,'%s\n',modelinfo);

if IRFt==1
    SVARinfo='structural decomposition: none';
elseif IRFt==2
    SVARinfo='structural decomposition: choleski factorisation';
elseif IRFt==3
    SVARinfo='structural decomposition: triangular factorisation';
elseif IRFt==4
    SVARinfo='structural decomposition: sign restrictions';
end
fprintf('%s\n',SVARinfo);
fprintf(fid,'%s\n',SVARinfo);

temp='endogenous variables: ';
for ii=1:n
    temp=[temp ' ' endo{ii,1} ' '];
end
endoinfo=temp;
fprintf('%s\n',endoinfo);
fprintf(fid,'%s\n',endoinfo);

temp='exogenous variables: ';
if const==0 && m==0
    temp=[temp ' none'];
elseif const==1 && m==1
    temp=[temp ' constant '];
elseif const==0 && m>0
    for ii=1:m-1
        temp=[temp ' ' exo{ii,1} ' '];
    end
elseif const==1 && m>1
    temp=[temp ' constant '];
    for ii=1:m-1
        temp=[temp ' ' exo{ii,1} ' '];
    end
end
exoinfo=temp;
fprintf('%s\n',exoinfo);
fprintf(fid,'%s\n',exoinfo);

sampledateinfo=['estimation sample: ' startdate '-' enddate];
fprintf('%s\n',sampledateinfo);
fprintf(fid,'%s\n',sampledateinfo);

samplelengthinfo=['sample size (omitting initial conditions): ' num2str(T)];
fprintf('%s\n',samplelengthinfo);
fprintf(fid,'%s\n',samplelengthinfo);

laginfo=['number of lags included in regression: ' num2str(p)];
fprintf('%s\n',laginfo);
fprintf(fid,'%s\n',laginfo);

if PriorExcel==1
    arprint=[];
    for ii=1:n
        arprint=[arprint num2str(ar(ii,1)) '  '];
    end
    hyperparam2=['autoregressive coefficients (ar):                ' arprint];
else
    hyperparam2=['autoregressive coefficients (ar):                ' num2str(ar(1,1))];
end
fprintf('%s\n',hyperparam2);
fprintf(fid,'%s\n',hyperparam2);

hyperparam3=['overall tightness (lambda1):                    ' num2str(lambda1)];
fprintf('%s\n',hyperparam3);
fprintf(fid,'%s\n',hyperparam3);

if stvol==1||stvol==2
    hyperparam4=['cross-variable weighting (lambda2):             ' num2str(lambda2)];
    fprintf('%s\n',hyperparam4);
    fprintf(fid,'%s\n',hyperparam4);
end

hyperparam5=['lag decay (lambda3):                            ' num2str(lambda3)];
fprintf('%s\n',hyperparam5);
fprintf(fid,'%s\n',hyperparam5);

%hyperparam6=['exogenous variable tightness (lambda4):         ' num2str(lambda4)];
%fprintf('%s\n',hyperparam6);
%fprintf(fid,'%s\n',hyperparam6);

if bex==1
    hyperparam7=['block exogeneity shrinkage (lambda5):           ' num2str(lambda5)];
    fprintf('%s\n',hyperparam7);
    fprintf(fid,'%s\n',hyperparam7);
end

if stvol==1||stvol==3
    hyperparam8=['AR coefficient on residual variance (gamma):    ' num2str(gamma)];
    fprintf('%s\n',hyperparam8);
    fprintf(fid,'%s\n',hyperparam8);
end

hyperparam9=['IG shape on residual variance (alpha0):         ' num2str(alpha0)];
fprintf('%s\n',hyperparam9);
fprintf(fid,'%s\n',hyperparam9);

hyperparam10=['IG scale on residual variance (delta0):         ' num2str(alpha0)];
fprintf('%s\n',hyperparam10);
fprintf(fid,'%s\n',hyperparam10);

if stvol==2
    hyperparam11=['Prior mean on inertia (gamma0):                 ' num2str(gamma)];
    fprintf('%s\n',hyperparam11);
    fprintf(fid,'%s\n',hyperparam11);
end

if stvol==2
    hyperparam12=['Prior variance on inertia (zeta0):              ' num2str(gamma)];
    fprintf('%s\n',hyperparam12);
    fprintf(fid,'%s\n',hyperparam12);
end

% display coefficient estimates

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

coeffinfo=['VAR coefficients (beta): posterior estimates'];
fprintf('%s\n',coeffinfo);
fprintf(fid,'%s\n',coeffinfo);

for ii=1:n

    fprintf('%s\n','');
    fprintf(fid,'%s\n','');
    if ii~=1
        fprintf('%s\n','');
        fprintf(fid,'%s\n','');
    end

    endoinfo=['Endogenous: ' endo{ii,1}];
    fprintf('%s\n',endoinfo);
    fprintf(fid,'%s\n',endoinfo);

    coeffheader=fprintf('%25s %15s %15s %15s %15s\n','','Median','St.dev','Low.bound','Upp.bound');
    coeffheader=fprintf(fid,'%25s %15s %15s %15s %15s\n','','Median','St.dev','Low.bound','Upp.bound');

    % handle the endogenous
    for jj=1:n
        for kk=1:p
            values=[beta_median((ii-1)*k+n*(kk-1)+jj,1) beta_std((ii-1)*k+n*(kk-1)+jj,1) beta_lbound((ii-1)*k+n*(kk-1)+jj,1) beta_ubound((ii-1)*k+n*(kk-1)+jj,1)];
            fprintf('%25s %15.3f %15.3f %15.3f %15.3f\n',strcat(endo{jj,1},'(-',int2str(kk),')'),values);
            fprintf(fid,'%25s %15.3f %15.3f %15.3f %15.3f\n',strcat(endo{jj,1},'(-',int2str(kk),')'),values);
        end
    end

    % handle the exogenous
    % if there is no constant:
    if const==0
        % if there is no exogenous at all, obvioulsy, don't display anything
        if m==0
            % if there is no constant but some other exogenous, display them
        else
            for jj=1:m
                values=[beta_median(ii*k-m+jj,1) beta_std(ii*k-m+jj,1) beta_lbound(ii*k-m+jj,1) beta_ubound(ii*k-m+jj,1)];
                fprintf('%25s %15.3f %15.3f %15.3f %15.3f\n',exo{jj,1},values);
                fprintf(fid,'%25s %15.3f %15.3f %15.3f %15.3f\n',exo{jj,1},values);
            end
        end
        % if there is a constant
    else
        % display the results related to the constant
        values=[beta_median(ii*k-m+1,1) beta_std(ii*k-m+1,1) beta_lbound(ii*k-m+1,1) beta_ubound(ii*k-m+1,1)];
        fprintf('%25s %15.3f %15.3f %15.3f %15.3f\n','Constant',values);
        fprintf(fid,'%25s %15.3f %15.3f %15.3f %15.3f\n','Constant',values);
        % if there is no other exogenous, stop here
        if m==1
            % if there are other exogenous, display their results
        else
            for jj=1:m-1
                values=[beta_median(ii*k-m+jj+1,1) beta_std(ii*k-m+jj+1,1) beta_lbound(ii*k-m+jj+1,1) beta_ubound(ii*k-m+jj+1,1)];
                fprintf('%25s %15.3f %15.3f %15.3f %15.3f\n',exo{jj,1},values);
                fprintf(fid,'%25s %15.3f %15.3f %15.3f %15.3f\n',exo{jj,1},values);
            end
        end
    end

    fprintf('%s\n','');
    fprintf(fid,'%s\n','');

    % display evaluation measures
    rssinfo=['Sum of squared residuals: ' num2str(rss(ii,1),'%.2f')];
    fprintf('%s\n',rssinfo);
    fprintf(fid,'%s\n',rssinfo);

    r2info=['R-squared: ' num2str(r2(ii,1),'%.3f')];
    fprintf('%s\n',r2info);
    fprintf(fid,'%s\n',r2info);

    adjr2info=['adj. R-squared: ' num2str(r2bar(ii,1),'%.3f')];
    fprintf('%s\n',adjr2info);
    fprintf(fid,'%s\n',adjr2info);

end

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% display VAR stability results
eigmodulus=reshape(eigmodulus,p,n);
stabilityinfo1=['Roots of the characteristic polynomial (modulus):'];
fprintf('%s\n',stabilityinfo1);
fprintf(fid,'%s\n',stabilityinfo1);
for ii=1:p
    temp=num2str(eigmodulus(ii,1),'%.3f');
    for jj=2:n
        temp=[temp,'  ',num2str(eigmodulus(ii,jj),'%.3f')];
    end
    fprintf('%s\n',temp);
    fprintf(fid,'%s\n',temp);
end
if stationary==1;
    stabilityinfo2=['No root lies outside the unit circle.'];
    stabilityinfo3=['The estimated VAR model satisfies the stability condition'];
    fprintf('%s\n',stabilityinfo2);
    fprintf(fid,'%s\n',stabilityinfo2);
    fprintf('%s\n',stabilityinfo3);
    fprintf(fid,'%s\n',stabilityinfo3);
else
    stabilityinfo2=['Warning: at leat one root lies on or outside the unit circle.'];
    stabilityinfo3=['The estimated VAR model will not be stable'];
    fprintf('%s\n',stabilityinfo2);
    fprintf(fid,'%s\n',stabilityinfo2);
    fprintf('%s\n',stabilityinfo3);
    fprintf(fid,'%s\n',stabilityinfo3);
end

fprintf('%s\n','');
fprintf(fid,'%s\n','');
fprintf('%s\n','');
fprintf(fid,'%s\n','');

% display posterior for sigma
sigmainfo1=['sigma (residual covariance matrix): posterior estimates'];
fprintf('%s\n',sigmainfo1);
fprintf(fid,'%s\n',sigmainfo1);
% calculate the (integer) length of the largest number in sigma, for formatting purpose
width=length(sprintf('%d',floor(max(abs(bear.vec(sigma_median))))));
% add a separator, a potential minus sign, and three digits (total=5) to obtain the total space for each entry in the matrix
width=width+5;
for ii=1:n
    temp=[];
    for jj=1:n
        % convert matrix entry into string
        number=num2str(sigma_median(ii,jj),'% .3f');
        % pad potential missing blanks
        while numel(number)<width
            number=[' ' number];
        end
        number=[number '  '];
        temp=[temp number];
    end
    fprintf('%s\n',temp);
    fprintf(fid,'%s\n',temp);
end
% notice about use of long-run values
sigmainfo2=['Note: estimates rely on long-run (homoskedastic) values'];
fprintf('%s\n',sigmainfo2);
fprintf(fid,'%s\n',sigmainfo2);

% display posterior for gamma (if random intertia model)
if stvol==2
    fprintf('%s\n','');
    fprintf(fid,'%s\n','');
    fprintf('%s\n','');
    fprintf(fid,'%s\n','');
    % display posterior for gamma
    gammainfo1=['gamma (autoregressive coefficient on stochastic volatility): posterior estimates'];
    fprintf('%s\n',gammainfo1);
    %fprintf(fid,'%s\n',gammainfo1);
    gammainfo2=[];
    for ii=1:n
        gammainfo2=[gammainfo2 repmat(' ',1,5-numel(ii)) 'gamma' num2str(ii)];
    end
    fprintf('%s\n',gammainfo2);
    %fprintf(fid,'%s\n',gammainfo2);
    gammainfo3=[];
    for ii=1:n
        % convert matrix entry into string
        temp=num2str(gamma_median(1,ii),'% .3f');
        % pad potential missing blanks and complete
        temp=[repmat(' ',1,10-numel(temp)) temp];
        gammainfo3=[gammainfo3 temp];
    end
    fprintf('%s\n',gammainfo3);
    %fprintf(fid,'%s\n',gammainfo3);
end
fclose(fid);

% Finally, display the results in terms of graph
if pref.plot
    % plot actual vs. fitted
    actualfitted=figure('Tag','BEARresults');
    set(actualfitted,'Color',[0.9 0.9 0.9]);
    set(actualfitted,'name','model estimation: actual vs fitted')
    ncolumns=ceil(n^0.5);
    nrows=ceil(n/ncolumns);
    for ii=1:n
        subplot(nrows,ncolumns,ii)
        hold on
        plot(decimaldates1,Y(:,ii),'Color',[0 0 0],'LineWidth',2);
        plot(decimaldates1,Ytilde(:,ii),'Color',[1 0 0],'LineWidth',2);
        hold off
        set(gca,'XLim',[decimaldates1(1,1) decimaldates1(end,1)],'FontName','Times New Roman');
        title(endo{ii,1},'FontName','Times New Roman','FontSize',10,'FontWeight','normal');
        if ii==1
            plotlegend=legend('actual','fitted');
            set(plotlegend,'FontName','Times New Roman');
        end
    end

    % plot the residuals
    residuals=figure('Tag','BEARresults');
    set(residuals,'Color',[0.9 0.9 0.9]);
    set(residuals,'name','model estimation: residuals')
    for ii=1:n
        subplot(nrows,ncolumns,ii)
        plot(decimaldates1,EPStilde(:,ii),'Color',[0 0 0],'LineWidth',2)
        set(gca,'XLim',[decimaldates1(1,1) decimaldates1(end,1)],'FontName','Times New Roman');
        title(endo{ii,1},'FontName','Times New Roman','FontSize',10,'FontWeight','normal');
    end

    % plot first the time-varying variance and covariance estimates
    varcov=figure('Tag','BEARresults');
    set(varcov,'Color',[0.9 0.9 0.9]);
    set(varcov,'name','model estimation: residual variance and covariance')
    for ii=1:n
        for jj=1:ii
            subplot(n,n,n*(ii-1)+jj)
            hold on
            Xpatch=[decimaldates1' fliplr(decimaldates1')];
            Ypatch=[sigma_t_lbound{ii,jj}' fliplr(sigma_t_ubound{ii,jj}')];
            HDpatch=patch(Xpatch,Ypatch,[0.7 0.78 1]);
            set(HDpatch,'facealpha',0.6);
            set(HDpatch,'edgecolor','none');
            plot(decimaldates1,sigma_t_median{ii,jj},'Color',[0.4 0.4 1],'LineWidth',2);
            plot([decimaldates1(1,1),decimaldates1(end,1)],[0 0],'k--');
            hold off
            set(gca,'XLim',[decimaldates1(1,1) decimaldates1(end,1)],'FontName','Times New Roman');
            % top labels
            if jj==ii
                title(['var(' endo{ii,1} ')'],'FontWeight','normal');
            else
                title(['cov(' endo{jj,1} ',' endo{ii,1} ')'],'FontWeight','normal');
            end
        end
    end

end % pref.plot

% finally, save the results on excel

% compute the cell for actual and fitted
% create the cell that will be saved on excel
afcell={};
% build preliminary elements: space between the tables
vertspace=repmat({''},T+3,1);
% loop over variables (horizontal dimension)
for ii=1:n
    % create cell of actual/fitted for variable ii
    temp=['actual and fitted: ' endo{ii,1}];
    af_i=[temp {''} {''};{''} {''} {''};{''} {'sample'} {'fitted'};stringdates1 num2cell(Y(:,ii)) num2cell(Ytilde(:,ii))];
    afcell=[afcell af_i vertspace];
end
% trim
afcell=afcell(:,1:end-1);
% write in excel
if pref.results==1
    bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),afcell,'actual fitted','B2');
end

% then compute the cell for the residuals
% create the cell that will be saved on excel
horzspace=repmat({''},1,n);
rescell=[{'residuals'} horzspace;{''} horzspace;{''} endo';stringdates1 num2cell(EPStilde)];
% write in excel
if pref.results==1
    bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),rescell,'resids','B2');
end

% finally compute the cell for the time varying variance and covariance
% create the cell that will be saved on excel
varcovcell={};
% build preliminary elements: space between the tables
horzspace=repmat({''},2,5*n);
vertspace=repmat({''},T+3,1);
% loop over variables (vertical dimension)
for ii=1:n
    tempcell={};
    % loop over shocks (horizontal dimension)
    for jj=1:ii
        % create cell of hd record for the contribution of shock jj in variable ii fluctuation
        % if a sign restriction identification scheme has been used, use the structural shock labels
        if jj==ii
            temp=['variance of ' endo{ii,1} ' residuals'];
            % otherwise, the shocks are just orthogonalised shocks from the variables: use variable names
        else
            temp=['covariance between ' endo{jj,1} ' and ' endo{ii,1} 'residuals'];
        end
        vc_ij=[temp {''} {''} {''};{''} {''} {''} {''};{''} {'lw. bound'} {'median'} {'up. bound'};stringdates1 num2cell(sigma_t_lbound{ii,jj}) num2cell(sigma_t_median{ii,jj}) num2cell(sigma_t_ubound{ii,jj})];
        tempcell=[tempcell vc_ij vertspace];
    end
    % complete with blanks (for repeated covariance values)
    for jj=1:n-ii
        tempcell=[tempcell cell(T+3,5)];
    end
    varcovcell=[varcovcell;horzspace;tempcell];
end
% trim
varcovcell=varcovcell(3:end,1:end-1);
% write in excel
if pref.results==1
    bear.xlswritegeneral(fullfile(pref.results_path, [pref.results_sub '.xlsx']),varcovcell,'time variation','B2');
end


function [data] = ft_freqsimulation(cfg)

% FT_FREQSIMULATION simulates channel-level time-series data . The data is built up
% from different frequencies and can contain a signal in which the different
% frequencies interact (i.e. cross-frequency coherent). Different methods are
% possible to make data with specific properties.
%
% Use as
%   [data] = ft_freqsimulation(cfg)
% which will return a raw data structure that resembles the output of
% FT_PREPROCESSING.
%
% The configuration options can include
%   cfg.method     = The methods are explained in more detail below, but they can be
%                     'superimposed'    simply add the contribution of the different frequencies
%                     'broadband'       create a single broadband signal component
%                     'phalow_amphigh'  phase of low freq correlated with amplitude of high freq
%                     'amplow_amphigh'  amplitude of low freq correlated with amplithude of high freq
%                     'phalow_freqhigh' phase of low freq correlated with frequency of high signal
%                     'asymmetric'      single signal component with asymmetric positive/negative deflections
%   cfg.output     = which channels should be in the output data, can be 'mixed' or 'all' (default = 'all')
%   cfg.randomseed = 'yes' or a number or vector with the seed value (default = 'yes')
%
% The number of trials and the time axes of the trials can be specified by
%   cfg.fsample    = simulated sample frequency (default = 1200)
%   cfg.trllen     = length of simulated trials in seconds (default = 1)
%   cfg.numtrl     = number of simulated trials (default = 1)
%   cfg.baseline   = number (default = 0)
% or by
%   cfg.time       = cell-array with one time axis per trial, which are for example obtained from an existing dataset
%
% For each of the methods default parameters are configured to generate
% example data, including noise. To get full control over the generated
% data you should explicitely set all parameters involved in the method
% of your choise. The interpretation of the following signal components
% depends on the specified method:
%
% cfg.s1.freq     = frequency of signal 1
% cfg.s1.phase    = phase (in rad) relative to cosine of signal 1  (default depends on method)
%                 = number or 'random'
% cfg.s1.ampl     = amplitude of signal 1
% cfg.s2.freq     = frequency of signal 2
% cfg.s2.phase    = phase (in rad) relative to cosine of signal 1  (default depends on method)
%                 = number or 'random'
% cfg.s2.ampl     = amplitude of signal 2
% cfg.s3.freq     = frequency of signal 3
% cfg.s3.phase    = phase (in rad) relative to cosine of signal 1  (default depends on method)
%                 = number or 'random'
% cfg.s3.ampl     = amplitude of signal 3
% cfg.s4.freq     = frequency of signal 4
% cfg.s4.phase    = phase (in rad) relative to cosine of signal 1  (default depends on method)
%                 = number or 'random'
% cfg.s4.ampl     = amplitude of signal 4
%
% cfg.n1.ampl     = root-mean-square amplitude of wide-band signal prior to filtering
% cfg.n1.bpfreq   = [Flow Fhigh]
% cfg.n2.ampl     = root-mean-square amplitude of wide-band signal prior to filtering
% cfg.n2.bpfreq   = [Flow Fhigh]
%
% cfg.asymmetry   = amount of asymmetry (default = 0, which is none)
% cfg.noise.ampl  = amplitude of noise
%
%
% In the method 'superimposed' the signal contains just the sum of the different frequency contributions:
%     s1: first frequency
%     s2: second frequency
%     s3: third frequency
% and the output consists of the following channels:
%     1st channel: mixed signal = s1 + s2 + s3 + noise
%     2nd channel: s1
%     3rd channel: s2
%     4th channel: s3
%     5th channel: noise
%
% In the method 'broadband' the signal contains a the superposition of two
% broadband signal components, which are created by bandpass filtering a
% Gaussian noise signal:
%     n1: first broadband signal
%     n2: second broadband signal
% and the output consists of the following channels:
%     1st channel: mixed signal = n1 + n2 + noise
%     2nd channel: n1
%     3rd channel: n2
%     4th channel: noise
%
% In the method 'phalow_amphigh' the signal is build up of 4 components; s1, s2, s3 and noise:
%     s1: amplitude modulation (AM), frequency of this signal should be lower than s2
%     s2: second frequency, frequncy that becomes amplitude modulated
%     s3: DC shift of s1, should have frequency of 0
% and the output consists of the following channels:
%     1st channel: mixed signal = (s1 + s3)*s2 + noise,
%     2nd channel: s1
%     3rd channel: s2
%     4th channel: s3
%     5th channel: noise
%
% In the method 'amplow_amphigh' the signal is build up of 5 components; s1, s2, s3, s4 and noise.
%     s1: first frequency
%     s2: second frequency
%     s3: DC shift of s1 and s2, should have frequency of 0
%     s4: amplitude modulation (AM), frequency of this signal should be lower than s1 and s2
% and the output consists of the following channels:
%     1st channel: mixed signal = (s4 + s3)*s1 + (s4 + s3)*s2 + noise,
%     2nd channel: s1
%     3rd channel: s2
%     4th channel: s3
%     5th channel: noise
%     6th channel: s4
%     7th channel: mixed part 1: (s4 + s3)*s1
%     8th channel: mixed part 2: (s4 + s3)*s2
%
% In the method 'phalow_freqhigh' a frequency modulated signal is created.
%   signal is build up of 3 components; s1, s2 and noise.
%     s1: represents the base signal that will be modulated
%     s2: signal that will be used for the frequency modulation
% and the output consists of the following channels:
%     1st channel: mixed signal = s1.ampl * cos(ins_pha) + noise
%     2nd channel: s1
%     3rd channel: s2
%     4th channel: noise
%     5th channel: inst_pha_base   instantaneous phase of the high (=base) frequency signal s1
%     6th channel: inst_pha_mod    low frequency phase modulation, this is equal to s2
%     7th channel: inst_pha        instantaneous phase, i.e. inst_pha_base + inst_pha_mod
%
% In the method 'asymmetric' there is only one periodic signal, but that
% signal is more peaked for the positive than for the negative deflections.
% The average of the signal over time is zero.
%     s1: represents the frequency of the base signal
% and the output consists of the following channels:
%     1st channel: mixed signal = asymmetric signal + noise
%     2nd channel: sine wave with base frequency and phase, i.e. s1
%     3rd channel: asymmetric signal
%     4th channel: noise
%
% See also FT_FREQANALYSIS, FT_TIMELOCKSIMULATION, FT_DIPOLESIMULATION,
% FT_CONNECTIVITYSIMULATION

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

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

% do the general setup of the function
ft_defaults
ft_preamble init
ft_preamble debug
ft_preamble provenance
ft_preamble randomseed

% the ft_abort variable is set to true or false in ft_preamble_init
if ft_abort
  return
end

% return immediately after distributed execution
if ~isempty(ft_getopt(cfg, 'distribute'))
  return
end

% set defaults
if ~isfield(cfg, 'method'),        cfg.method = 'phalow_amphigh';         end
if ~isfield(cfg, 'output'),        cfg.output = 'all';                    end
if ~isfield(cfg, 'time'),          cfg.time = [];                         end

if isempty(cfg.time)
  cfg.fsample   = ft_getopt(cfg, 'fsample', 1200);
  cfg.trllen    = ft_getopt(cfg, 'trllen', 1);
  cfg.numtrl    = ft_getopt(cfg, 'numtrl', 1);
  cfg.baseline  = ft_getopt(cfg, 'baseline', 0);
else
  cfg.trllen  = [];                         % can be variable
  cfg.fsample = 1/mean(diff(cfg.time{1}));  % determine from time-axis
  cfg.numtrl  = length(cfg.time);
end

if strcmp(cfg.method, 'superimposed')
  if ~isfield(cfg, 's1'),           cfg.s1 = [];                          end
  if ~isfield(cfg.s1, 'freq'),      cfg.s1.freq  = 10;                    end
  if ~isfield(cfg.s1, 'phase'),     cfg.s1.phase = 0;                     end
  if ~isfield(cfg.s1, 'ampl'),      cfg.s1.ampl  = 1;                     end
  if ~isfield(cfg, 's2'),           cfg.s2 = [];                          end
  if ~isfield(cfg.s2, 'freq'),      cfg.s2.freq  = 20;                    end
  if ~isfield(cfg.s2, 'phase'),     cfg.s2.phase = 0;                     end
  if ~isfield(cfg.s2, 'ampl'),      cfg.s2.ampl  = 0;                     end
  if ~isfield(cfg, 's3'),           cfg.s3 = [];                          end
  if ~isfield(cfg.s3, 'freq'),      cfg.s3.freq  = 30;                    end
  if ~isfield(cfg.s3, 'phase'),     cfg.s3.phase = 0;                     end
  if ~isfield(cfg.s3, 'ampl'),      cfg.s3.ampl  = 0;                     end
end

if strcmp(cfg.method, 'broadband')
  if ~isfield(cfg, 'n1'),           cfg.n1 = [];                          end
  if ~isfield(cfg.n1, 'ampl'),      cfg.n1.ampl  = 1;                     end
  if ~isfield(cfg.n1, 'bpfreq'),    cfg.n1.bpfreq  = [30 50];             end
  if ~isfield(cfg, 'n2'),           cfg.n2 = [];                          end
  if ~isfield(cfg.n2, 'ampl'),      cfg.n2.ampl  = 1;                     end
  if ~isfield(cfg.n2, 'bpfreq'),    cfg.n2.bpfreq  = [80 120];            end
end

if strcmp(cfg.method, 'phalow_amphigh')
  if ~isfield(cfg, 's1'),           cfg.s1 = [];                          end
  if ~isfield(cfg.s1, 'freq'),      cfg.s1.freq = 3;                      end
  if ~isfield(cfg.s1, 'phase'),     cfg.s1.phase = -1*pi;                 end
  if ~isfield(cfg.s1, 'ampl'),      cfg.s1.ampl = 1;                      end
  if ~isfield(cfg, 's2'),           cfg.s2 = [];                          end
  if ~isfield(cfg.s2, 'freq'),      cfg.s2.freq = 20;                     end
  if ~isfield(cfg.s2, 'phase'),     cfg.s2.phase = 0;                     end
  if ~isfield(cfg.s2, 'ampl'),      cfg.s2.ampl = 1;                      end
  if ~isfield(cfg, 's3'),           cfg.s3 = [];                          end
  if ~isfield(cfg.s3, 'freq'),      cfg.s3.freq = 0;                      end
  if ~isfield(cfg.s3, 'phase'),     cfg.s3.phase = 0;                     end
  if ~isfield(cfg.s3, 'ampl'),      cfg.s3.ampl = cfg.s1.ampl;            end
end

if strcmp(cfg.method, 'amplow_amphigh')
  if ~isfield(cfg, 's1'),           cfg.s1 = [];                          end
  if ~isfield(cfg.s1, 'freq'),      cfg.s1.freq = 6;                      end
  if ~isfield(cfg.s1, 'phase'),     cfg.s1.phase = 0;                     end
  if ~isfield(cfg.s1, 'ampl'),      cfg.s1.ampl = 1;                      end
  if ~isfield(cfg, 's2'),           cfg.s2 = [];                          end
  if ~isfield(cfg.s2, 'freq'),      cfg.s2.freq = 20;                     end
  if ~isfield(cfg.s2, 'phase'),     cfg.s2.phase = 0;                     end
  if ~isfield(cfg.s2, 'ampl'),      cfg.s2.ampl = 1;                      end
  if ~isfield(cfg, 's4'),           cfg.s4 = [];                          end
  if ~isfield(cfg.s4, 'freq'),      cfg.s4.freq = 1;                      end
  if ~isfield(cfg.s4, 'phase'),     cfg.s4.phase = -1*pi;                 end
  if ~isfield(cfg.s4, 'ampl'),      cfg.s4.ampl = 1;                      end
  if ~isfield(cfg, 's3'),           cfg.s3 = [];                          end
  if ~isfield(cfg.s3, 'freq'),      cfg.s3.freq = 0;                      end
  if ~isfield(cfg.s3, 'phase'),     cfg.s3.phase = 0;                     end
  if ~isfield(cfg.s3, 'ampl'),      cfg.s3.ampl = cfg.s4.ampl;            end
end

if strcmp(cfg.method, 'phalow_freqhigh')
  if ~isfield(cfg, 's1'),           cfg.s1 = [];                          end
  if ~isfield(cfg.s1, 'freq'),      cfg.s1.freq = 20;                     end
  if ~isfield(cfg.s1, 'phase'),     cfg.s1.phase = 0;                     end
  if ~isfield(cfg.s1, 'ampl'),      cfg.s1.ampl = 1;                      end
  if ~isfield(cfg, 's2'),           cfg.s2 = [];                          end
  if ~isfield(cfg.s2, 'freq'),      cfg.s2.freq = 2;                      end
  if ~isfield(cfg.s2, 'phase'),     cfg.s2.phase = -0.5 * pi;             end %then base freq at t=0
  if ~isfield(cfg.s2, 'ampl'),      cfg.s2.ampl = pi;                     end
end

if strcmp(cfg.method, 'asymmetric')
  if ~isfield(cfg, 's1'),           cfg.s1 = [];                          end
  if ~isfield(cfg.s1, 'freq'),      cfg.s1.freq = 6;                      end
  if ~isfield(cfg.s1, 'phase'),     cfg.s1.phase = 0;                     end
  if ~isfield(cfg.s1, 'ampl'),      cfg.s1.ampl = 1;                      end
  if ~isfield(cfg, 'noise'),        cfg.noise = [];                       end
  if ~isfield(cfg.noise, 'ampl'),   cfg.noise.ampl = 0.1;                 end % default should not be too high
end

if ~isfield(cfg, 'noise'),         cfg.noise = [];                        end
if ~isfield(cfg.noise, 'ampl'),    cfg.noise.ampl = 1;                    end

if ~isempty(cfg.time)
  % use the user-supplied time vectors
  timevec = cfg.time;
else
  % give the user some feedback
  ft_debug('using %f as samping frequency', cfg.fsample);
  ft_debug('using %d trials of %f seconds long', cfg.numtrl, cfg.trllen);
  nsample = round(cfg.trllen*cfg.fsample);
  timevec = cell(1, cfg.numtrl);
  for iTr = 1:cfg.numtrl
    timevec{iTr} = (((1:nsample)-1)/cfg.fsample) - cfg.baseline;
  end
end

% give the user some feedback
ft_info('simulating data using %s method', cfg.method);

%%%%%%% SUPERIMPOSED, SIMPLY ADD THE SIGNALS %%%%%%%%%
if strcmp(cfg.method, 'superimposed')

  % make data
  for iTr = 1:length(timevec)
    if ischar(cfg.s1.phase); phase_s1 = rand * 2 * pi; else phase_s1 = cfg.s1.phase; end
    if ischar(cfg.s2.phase); phase_s2 = rand * 2 * pi; else phase_s2 = cfg.s2.phase; end
    if ischar(cfg.s3.phase); phase_s3 = rand * 2 * pi; else phase_s3 = cfg.s3.phase; end

    s1    = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1);
    s2    = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_s2);
    s3    = cfg.s3.ampl*cos(2*pi*cfg.s3.freq*timevec{iTr} + phase_s3);
    noise = cfg.noise.ampl*randn(size(timevec{iTr}));
    mix   = s1 + s2 + s3 + noise;

    data.trial{iTr}(1,:) = mix;
    if strcmp(cfg.output, 'all')
      data.trial{iTr}(2,:) = s1;
      data.trial{iTr}(3,:) = s2;
      data.trial{iTr}(4,:) = s3;
      data.trial{iTr}(5,:) = noise;
    end
    data.time{iTr} = timevec{iTr};
  end % for iTr

  data.label{1} = 'mix';
  if strcmp(cfg.output, 'all')
    data.label{2} = 's1';
    data.label{3} = 's2';
    data.label{4} = 's3';
    data.label{5} = 'noise';
  end
  data.fsample = cfg.fsample;

  %%%%%%% SUPERIMPOSED BROADBAND SIGNAL %%%%%%%%%
elseif strcmp(cfg.method, 'broadband')

  % make data
  for iTr = 1:length(timevec)
    n1    = ft_preproc_bandpassfilter(cfg.n1.ampl*randn(size(timevec{iTr})), cfg.fsample, cfg.n1.bpfreq);
    n2    = ft_preproc_bandpassfilter(cfg.n2.ampl*randn(size(timevec{iTr})), cfg.fsample, cfg.n2.bpfreq);
    noise = cfg.noise.ampl*randn(size(timevec{iTr}));
    mix   = n1 + n2 + noise;

    data.trial{iTr}(1,:) = mix;
    if strcmp(cfg.output, 'all')
      data.trial{iTr}(2,:) = n1;
      data.trial{iTr}(3,:) = n2;
      data.trial{iTr}(4,:) = noise;
    end
    data.time{iTr} = timevec{iTr};
  end % for iTr

  data.label{1} = 'mix';
  if strcmp(cfg.output, 'all')
    data.label{2} = 'n1';
    data.label{3} = 'n2';
    data.label{4} = 'noise';
  end
  data.fsample = cfg.fsample;

  %%%%%%% PHASE TO AMPLITUDE CORRELATION %%%%%%%%%
elseif strcmp(cfg.method, 'phalow_amphigh')

  % sanity checks
  if cfg.s2.freq < cfg.s1.freq
    ft_error('with method is phalow_amphigh freq s2 should be higher than freq s1')
  end
  if cfg.s2.freq > cfg.fsample/2
    ft_error('you cannot have a frequency higher than the sample frequency/2')
  end
  if cfg.s3.freq ~= 0 || cfg.s3.phase ~= 0
    ft_warning('for method phalow_amphigh s3 is DC and therefore expect freq and phase to be zero but they are not')
  end
  if cfg.s3.ampl < cfg.s1.ampl
    ft_warning('expect amplitude s3 (=DC) not to be smaller than amplitude s1 (=low frequency)')
  end

  % make data
  for iTr = 1:length(timevec)

    if ischar(cfg.s1.phase); phase_AM   = rand * 2 * pi; else phase_AM   = cfg.s1.phase;  end
    if ischar(cfg.s2.phase); phase_high = rand * 2 * pi; else phase_high = cfg.s2.phase; end
    if ischar(cfg.s3.phase); phase_DC   = rand * 2 * pi; else phase_DC   = cfg.s3.phase;   end
    high  = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_high);
    AM    = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_AM);
    DC    = cfg.s3.ampl*cos(2*pi*0*timevec{iTr} + phase_DC);
    noise = cfg.noise.ampl*randn(size(timevec{iTr}));
    mix   = ((AM + DC) .* high) + noise;

    data.trial{iTr}(1,:) = mix;
    if strcmp(cfg.output, 'all')
      data.trial{iTr}(2,:) = AM;
      data.trial{iTr}(3,:) = high;
      data.trial{iTr}(4,:) = DC;
      data.trial{iTr}(5,:) = noise;
    end
    data.time{iTr} = timevec{iTr};
  end % for iTr

  data.label{1} = 'mix';
  if strcmp(cfg.output, 'all')
    data.label{2} = 's1 (AM)';
    data.label{3} = 's2 (high)';
    data.label{4} = 's3 (DC)';
    data.label{5} = 'noise';
  end
  data.fsample = cfg.fsample;

  %%%%%%% POWER TO POWER CORRELATION %%%%%%%%%
elseif strcmp(cfg.method, 'amplow_amphigh')

  % sanity checks
  if cfg.s2.freq < cfg.s1.freq || cfg.s1.freq < cfg.s4.freq
    ft_error('with method is powlow_powhigh freq s4 < s1 < s2')
  end
  if cfg.s2.freq > cfg.fsample/2
    ft_error('you cannot have a frequency higher than the sample frequency/2')
  end
  if cfg.s3.freq ~= 0 || cfg.s3.phase ~= 0
    ft_warning('for method powlow_powhigh s3 is DC and therefore expect freq and phase to be zero but they are not')
  end
  if cfg.s3.ampl < cfg.s4.ampl
    ft_warning('expect amplitude s3 (=DC) not to be smaller than amplitude s4 (= AM frequency)')
  end

  % make data
  for iTr = 1:length(timevec)

    if ischar(cfg.s1.phase); phase_low  = rand * 2 * pi; else phase_low = cfg.s1.phase;    end
    if ischar(cfg.s2.phase); phase_high = rand * 2 * pi; else phase_high = cfg.s2.phase;   end
    if ischar(cfg.s3.phase); phase_DC   = rand * 2 * pi; else phase_DC = cfg.s3.phase;     end
    if ischar(cfg.s4.phase); phase_AM   = rand * 2 * pi; else phase_AM = cfg.s4.phase; end
    high     = cfg.s2.ampl*cos(2*pi*cfg.s2.freq*timevec{iTr} + phase_high);
    low      = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_low);
    AM       = cfg.s4.ampl*cos(2*pi*cfg.s4.freq*timevec{iTr} + phase_AM);
    DC       = cfg.s3.ampl*cos(2*pi*0*timevec{iTr} + phase_DC);
    noise    = cfg.noise.ampl*randn(size(timevec{iTr}));
    lowmix  = ((AM + DC) .* low);
    highmix = ((AM + DC) .* high);
    mix     = lowmix + highmix + noise;

    data.trial{iTr}(1,:) = mix;
    if strcmp(cfg.output, 'all')
      data.trial{iTr}(2,:) = low;
      data.trial{iTr}(3,:) = high;
      data.trial{iTr}(4,:) = DC;
      data.trial{iTr}(5,:) = noise;
      data.trial{iTr}(6,:) = AM;
      data.trial{iTr}(7,:) = lowmix;
      data.trial{iTr}(8,:) = highmix;
    end
    data.time{iTr} = timevec{iTr};
  end % for iTr

  data.label{1} = 'mix';
  if strcmp(cfg.output, 'all')
    data.label{2} = 's1 (low)';
    data.label{3} = 's2 (high)';
    data.label{4} = 's3 (DC)';
    data.label{5} = 'noise';
    data.label{6} = 's4 (AM)';
    data.label{7} = 'mixlow';
    data.label{8} = 'mixhigh';
  end
  data.fsample = cfg.fsample;

  %%%%%%% PHASE TO FREQUENCY CORRELATION %%%%%%%%%
elseif strcmp(cfg.method, 'phalow_freqhigh')

  % sanity checks
  if cfg.s1.freq > cfg.fsample/2 || cfg.s2.freq > cfg.fsample/2
    ft_error('you cannot have a frequency higher than the sample frequency/2')
  end

  % make data
  for iTr = 1:length(timevec)

    if ischar(cfg.s1.phase); phase_s1 = rand * 2 * pi; else phase_s1 = cfg.s1.phase;    end
    if ischar(cfg.s2.phase); phase_s2 = rand * 2 * pi; else phase_s2= cfg.s2.phase;    end
    s1            = cfg.s1.ampl .* cos(2*pi*cfg.s1.freq * timevec{iTr} + phase_s1); % to be modulated signal
    s2            = cfg.s2.ampl .* cos(2*pi*cfg.s2.freq * timevec{iTr} + phase_s2); % modulation of instantaneous phase
    inst_pha_base = 2*pi*cfg.s1.freq * timevec{iTr} + phase_s1; % unmodulated instantaneous phase s1 (linear)
    inst_pha_mod  = s2;                                    % modulation of instantaneous phase
    inst_pha      = inst_pha_base + inst_pha_mod;
    noise         = cfg.noise.ampl*randn(size(timevec{iTr}));
    mix           = cfg.s1.ampl .* cos(inst_pha) + noise;

    data.trial{iTr}(1,:) = mix;
    if strcmp(cfg.output, 'all')
      data.trial{iTr}(2,:) = s1;
      data.trial{iTr}(3,:) = s2;
      data.trial{iTr}(4,:) = noise;
      data.trial{iTr}(5,:) = inst_pha_base;
      data.trial{iTr}(6,:) = inst_pha_mod;
      data.trial{iTr}(7,:) = inst_pha;
    end
    data.time{iTr} = timevec{iTr};
  end % for iTr

  data.label{1} = 'mix';
  if strcmp(cfg.output, 'all')
    data.label{2} = 's1';
    data.label{3} = 's2';
    data.label{4} = 'noise';
    data.label{5} = 'inst phase base';
    data.label{6} = 'inst phase modulation (=s2)';
    data.label{7} = 'inst phase';
  end
  data.fsample = cfg.fsample;

  %%%%%%% ASYMETRIC POSITIVE AND NEGATIVE PEAKS %%%%%%%%%
elseif strcmp(cfg.method, 'asymmetric')

  % make data
  for iTr = 1:length(timevec)
    if ischar(cfg.s1.phase); phase_s1 = rand * 2 *pi; else phase_s1 = cfg.s1.phase; end

    s1    = cfg.s1.ampl*cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1);
    tmp   = cos(2*pi*cfg.s1.freq*timevec{iTr} + phase_s1);  % same signal but with unit amplitude
    tmp   = (tmp+1)/2;                                 % scaled and shifted between 0 and 1
    tmp   = tmp.^(cfg.asymmetry+1);                    % made asymmetric
    tmp   = (tmp - mean(tmp))*2*cfg.s1.ampl;           % rescale
    s2    = tmp;
    noise = cfg.noise.ampl*randn(size(timevec{iTr}));
    mix   = s2 + noise;

    data.trial{iTr}(1,:) = mix;
    if strcmp(cfg.output, 'all')
      data.trial{iTr}(2,:) = s1;
      data.trial{iTr}(3,:) = s2;
      data.trial{iTr}(4,:) = noise;
    end
    data.time{iTr} = timevec{iTr};
  end % for iTr

  data.label{1} = 'mix';
  if strcmp(cfg.output, 'all')
    data.label{2} = 's1';
    data.label{3} = 's2';
    data.label{4} = 'noise';
  end
  data.fsample = cfg.fsample;

else
  ft_error('unknown method specified')
end

% do the general cleanup and bookkeeping at the end of the function
ft_postamble debug
ft_postamble randomseed
ft_postamble provenance data
ft_postamble history    data
ft_postamble savevar    data


function [xu,yu,xl,yl,xc,yc]=GenerateNACASeries4Airfoil(afid,dotcount,xmod)

%--------------------------------------------------------------------------
%GenerateNACASeries4Airfoil
%Version 1.20
%Created by Stepen (zerocross_raptor@yahoo.com)
%Created 20 November 2010
%Last modified 30 November 2011
%--------------------------------------------------------------------------
%GenerateNACASeries4Airfoil generates the airfoil vertexes' coordinate of
%the given NACA Series 4 Airfoil. The math equation used to generates the
%airfoil coordinates is based on Theory of Wing Section Chapter 6 by Abbott
%and Doenhoff.
%--------------------------------------------------------------------------
%Syntax:
%[xu,yu,xl,yl,xc,yc]=GenerateNACASeries4Airfoil(afid,dotcount,xmod)
%Input argument:
%- afid (1 x 4 str) specifies NACA Series 4 Airfoil identifier.
%- dotcount (1 x 1 int) specifies the number of vertexes to be generated on
%  the airfoil's camber/mean line.
%- xmod (str) specifies the mode of airfoil vertex distribution. Enter
%  'Uniform' to create uniform vertex distribution or 'Cosine' to create
%  vertex distribution based on cosine function (More vertex on the leading
%  edge region).
%Output argument:
%- xu (i x 1 num) specifies the x axis location of airfoil's upper surface
%  vertexes in fraction of chord. The airfoil's upper surface vertex are
%  arranged from leading edge (the first element of xu) to the trailing
%  edge (the last element of xu).
%- yu (i x 1 num) specifies the y axis location of airfoil's upper surface
%  vertexes in fraction of chord. The airfoil's upper surface vertex are
%  arranged from leading edge (the first element of yu) to the trailing
%  edge (the last element of yu).
%- xl (i x 1 num) specifies the x axis location of airfoil's lower surface
%  vertexes in fraction of chord. The airfoil's lower surface vertex are
%  arranged from leading edge (the first element of xl) to the trailing
%  edge (the last element of xl).
%- yl (i x 1 num) specifies the y axis location of airfoil's lower surface
%  vertexes in fraction of chord. The airfoil's lower surface vertex are
%  arranged from leading edge (the first element of yl) to the trailing
%  edge (the last element of yl).
%- xc (i x 1 num) specifies the x axis location of airfoil's camber line
%  vertexes in fraction of chord. The airfoil's camber line vertex are
%  arranged from leading edge (the first element of xc) to the trailing
%  edge (the last element of xc).
%- yc (i x 1 num) specifies the y axis location of airfoil's camber line
%  vertexes in fraction of chord. The airfoil's camber line vertex are
%  arranged from leading edge (the first element of yc) to the trailing
%  edge (the last element of yc).
%--------------------------------------------------------------------------

%CodeStart-----------------------------------------------------------------
%Checking input afid
    if ~ischar(afid)
        error('Airfoil identifier must be a string!')
    end
    if numel(afid)~=4
        error('Airfoil identifier must be a 4 digit number!')
    end
    if isempty(str2double(afid))
        error('Airfoil identifier must be a 4 digit number!')
    end
%Checking input dotcount
    if numel(dotcount)~=1
        error('Number of vertex must be scalar!')
    end
    if (mod(dotcount,1~=0))||(dotcount<0)
        error('Number of vertex must be positive integer!')
    end
%Checking input xmod
    if nargin<3
        xmod='Cosine';
    end
    if (~strcmpi(xmod,'Uniform'))&&(~strcmpi(xmod,'Cosine'))
        error('Vertex distribution input must be Uniform or Cosine!')
    end
%Assigning identifier to equation coefficient
    id1=str2double(afid(1));
    id2=str2double(afid(2));
    id3=str2double(afid([3,4]));
    m=id1*(1/100);            %Maximum camber
    p=id2*(10/100);           %Maximum camber location
    t=id3*(1/100);            %Maximum thickness
    if t==0
        warning(['Zero thickness airfoil!',...
                 ' Airfoil will be just a camber line!'])
    end
%Calculating x-axis location of camber line vertexes
    panelcount=dotcount-1;
    if strcmpi(xmod,'Uniform')
        panellength=1/panelcount;
        xc=(0:panellength:1)';
    elseif strcmpi(xmod,'Cosine')
        deltadeg=90/panelcount;
        xc=1-cosd(0:deltadeg:90)';
    end
%Preallocating array for speed
    yc=zeros(dotcount,1);
    gc=zeros(dotcount,1);
    yt=zeros(dotcount,1);
    xu=zeros(dotcount,1);
    xl=zeros(dotcount,1);
    yu=zeros(dotcount,1);
    yl=zeros(dotcount,1);
%Calculating y-axis location of camber line vertexes and camber gradient
    if m~=0
        for i=1:1:dotcount
            if xc(i)<=p
                yc(i)=(m/(p^2))*((2*p*xc(i))-(xc(i)^2));
            elseif xc(i)>p
                yc(i)=(m/((1-p)^2))*(1-(2*p)+(2*p*xc(i))-(xc(i)^2));
            end
            gc(i)=(m/p^2)*(2*p+2*xc(i));
        end
    end
%Converting camber gradient to camber slope and normal
    sc=atand(gc);
%Calculating thickness distribution
    for i=1:1:dotcount
        yt(i)=5*t*((0.29690*(xc(i)^0.5))-...
                   (0.12600*xc(i))-...
                   (0.35160*(xc(i)^2))+...
                   (0.28430*(xc(i)^3))-...
                   (0.10150*(xc(i)^4)));
    end
%Generating airfoil vertexes
    for i=1:1:dotcount
        xu(i)=xc(i)-yt(i)*sind(sc(i));
        yu(i)=yc(i)+yt(i)*cosd(sc(i));
        xl(i)=xc(i)+yt(i)*sind(sc(i));
        yl(i)=yc(i)-yt(i)*cosd(sc(i));
    end
%CodeEnd-------------------------------------------------------------------

end


function [a,b,m,r,bbx,bby,f,g] = stokes_q2p1(xy,xyp,mv)
%stokes_q2p1  vectorized Q2-P1 matrix generator
%   [A,B,Q,G,Bx,By,f,g] = stokes_q2p1(xy,xyp,mv);
%   input
%          xy         Q2 nodal coordinate vector
%          xyp        Q1 nodal coordinate vector
%          mv         Q2 element mapping matrix
%   output
%          A          Q2 vector diffusion matrix
%          B          Q2-Q1 divergence matrix
%          Q          Q1 mass matrix
%          G          Q2 vector mass matrix
%          Bx         Q2 x-derivative matrix
%          By         Q2 y-derivative matrix
%          f          velocity rhs vector
%          g          pressure rhs vector
%
%   Natural boundary conditions apply. Dirichlet conditions
%   must be explicitly enforced by calling function flowbc.
%   IFISS function: DJS; 7 March 2005.
% Copyright (c) 2005 D.J. Silvester, H.C. Elman, A. Ramage
nngpt=9;
x=xy(:,1); y=xy(:,2);
xp=xyp(:,1); yp=xyp(:,2);
nvtx=length(x); nu=2*nvtx; np=3*length(xp);
nel=length(mv(:,1));  mp=[[1:3:3*nel]',[2:3:3*nel]',[3:3:3*nel]'];
lx=max(x)-min(x); ly=max(y)-min(y);
hx=max(diff(x)); hy=max(diff(y));
fprintf('setting up Q2-P1 matrices...  ')
%
% initialise global matrices
      a = sparse(nu,nu);
      r = sparse(nu,nu);
    bbx = sparse(nvtx,nvtx);
    bby = sparse(nvtx,nvtx);
     bx = sparse(np,nvtx);
     by = sparse(np,nvtx);
	  b = sparse(np,nu);
      m = sparse(np,np);
      f = zeros(nu,1);
      g = zeros(np,1);
%
%
% Gauss point integration rules
      if (nngpt==4)        % 2x2 Gauss points
      gpt=1.0e0/sqrt(3.0e0);
      s(1) = -gpt; t(1) = -gpt; wt(1)=1;
      s(2) =  gpt; t(2) = -gpt; wt(2)=1;
      s(3) =  gpt; t(3) =  gpt; wt(3)=1;
      s(4) = -gpt; t(4) =  gpt; wt(4)=1;
      elseif (nngpt==9)   % 3x3 Gauss points
      gpt=sqrt(0.6);
      s(1) = -gpt; t(1) = -gpt; wt(1)=25/81;
      s(2) =  gpt; t(2) = -gpt; wt(2)=25/81;
      s(3) =  gpt; t(3) =  gpt; wt(3)=25/81;
      s(4) = -gpt; t(4) =  gpt; wt(4)=25/81;
      s(5) =  0.0; t(5) = -gpt; wt(5)=40/81;
      s(6) =  gpt; t(6) =  0.0; wt(6)=40/81;
      s(7) =  0.0; t(7) =  gpt; wt(7)=40/81;
      s(8) = -gpt; t(8) =  0.0; wt(8)=40/81;
      s(9) =  0.0; t(9) =  0.0; wt(9)=64/81;
      else
	  error('Check Gauss point integration specification')
      end
%
% inner loop over elements
      for ivtx = 1:4
      xl_v(:,ivtx) = x(mv(:,ivtx));
      yl_v(:,ivtx) = y(mv(:,ivtx));
	  end
       ae = zeros(nel,9,9);
       re = zeros(nel,9,9);
     bbxe = zeros(nel,9,9);
     bbye = zeros(nel,9,9);
      bxe = zeros(nel,3,9);
      bye = zeros(nel,3,9);
      mpe = zeros(nel,3,3);
       ge = zeros(nel,3);
%
% loop over Gauss points
         for igpt = 1:nngpt
         sigpt=s(igpt);
         tigpt=t(igpt);
         wght=wt(igpt);
%  evaluate derivatives etc
         [jac,invjac,phi,dphidx,dphidy] = deriv(sigpt,tigpt,xl_v,yl_v);
         [psi,dpsidx,dpsidy] = qderiv(sigpt,tigpt,xl_v,yl_v);
         [chi,dchidx,dchidy] = lderiv(sigpt,tigpt,xl_v,yl_v);
            for j = 1:9
               for i = 1:9
               ae(:,i,j)  = ae(:,i,j)  + wght*dpsidx(:,i).*dpsidx(:,j).*invjac(:);
               ae(:,i,j)  = ae(:,i,j)  + wght*dpsidy(:,i).*dpsidy(:,j).*invjac(:);
               re(:,i,j)  = re(:,i,j)  + wght*psi(:,i).*psi(:,j).*jac(:);
               bbxe(:,i,j) = bbxe(:,i,j) - wght*psi(:,i) .*dpsidx(:,j);
               bbye(:,i,j) = bbye(:,i,j) - wght*psi(:,i) .*dpsidy(:,j);
               end
	       for i=1:3
               bxe(:,i,j) = bxe(:,i,j) - wght*chi(:,i) .* dpsidx(:,j);
               bye(:,i,j) = bye(:,i,j) - wght*chi(:,i) .* dpsidy(:,j);
               end
	    end
	    for j=1:3
	       for i=1:3
               mpe(:,i,j) = mpe(:,i,j) + wght*chi(:,i) .*chi(:,j) .*jac(:);
	       end
	    end
%
% end of Gauss point loop
         end
%
%%  element assembly into global matrices
% component velocity matrices ...
      for krow=1:9
	  nrow=mv(:,krow);
          for kcol=1:9
		  ncol=mv(:,kcol);
          a = a + sparse(nrow,ncol,ae(:,krow,kcol),nu,nu);
		  a = a + sparse(nrow+nvtx,ncol+nvtx,ae(:,krow,kcol),nu,nu);
          r = r + sparse(nrow,ncol,re(:,krow,kcol),nu,nu);
		  r = r + sparse(nrow+nvtx,ncol+nvtx,re(:,krow,kcol),nu,nu);
          bbx = bbx + sparse(nrow,ncol,bbxe(:,krow,kcol),nvtx,nvtx);
          bby = bby + sparse(nrow,ncol,bbye(:,krow,kcol),nvtx,nvtx);
          end
          for kcol=1:3
		  ncol=mp(:,kcol);
          bx = bx + sparse(ncol,nrow,bxe(:,kcol,krow),np,nvtx);
          by = by + sparse(ncol,nrow,bye(:,kcol,krow),np,nvtx);
		  end
       end
%
% vector velocity matrices ...
	   b = [bx,by];
%
% pressure matrices ...
	   for krow=1:3
	   nrow=mp(:,krow);
          for kcol=1:3
		  ncol=mp(:,kcol);
          m = m + sparse(nrow,ncol,mpe(:,krow,kcol),np,np);
		  end
	  end
%
fprintf('done\n')
return


% function [face,skin_region]=face(I);
%
% skin_region=skin(I);
%
% se = strel('disk',3);
% dil = imdilate(skin_region,se);        % morphologic dilation
% d2 = imfill(dil, 'holes');   % morphologic fill
% face = bwdist(~d2);            % computing minimal euclidean distance to non-white pixel
% figure;imshow(face,[]);

function [face_a,skin_region]=face(I);

skin_region=skin(I);

se = strel('disk',5);
se2 = strel('disk',3);
er = imerode(skin_region,se2);
cl = imclose(er,se);
dil = imdilate(cl,se);        % morphologic dilation
dil = imdilate(dil,se);
cl2 = imclose(dil,se);
d2 = imfill(cl2, 'holes');   % morphologic fill
facearea = bwdist(~d2);            % computing minimal euclidean distance to non-white pixel
% figure;imshow(facearea,[]);

% imshow(d2);
face(:,:,1)=double(I(:,:,1)).*d2;
face(:,:,2)=double(I(:,:,2)).*d2;
face(:,:,3)=double(I(:,:,3)).*d2;
face_a=uint8(face);
% figure;imshow(face_a);


function [xh,x,t]=simobsv(G,H)
[y,t,x]=step(G);
G=ss(G); A=G.a; B=G.b; C=G.c; D=G.d;
[y1,xh1]=step((A-H*C),(B-H*D),C,D,1,t);
[y2,xh2]=lsim((A-H*C),H,C,D,y,t);
xh=xh1+xh2;


function RHOTPH2O = h2o_rhotp(P,X)
% H2O_RHOTP  Two-phase density of H2O in kg/m^3
% H2O_RHOTP(P,X) Returns the two-phase density
% of H2O at a given pressure and quality.
%  Called function: h2o_rhof(P), h2o_rhog(P)
%  Required Inputs are: P - pressure (kPa), X - quality (fraction)
% ---------------------------------------------------------------
%  The MATLAB function was created by Tibor Balint, December 1998
% TBoreal Research Corporation, Toronto, Ont. Canada
% (tibor@netcom.ca) and also, University of Warwick, UK
% ---------------------------------------------------------------

format long g;  % set the format of the calculations

RF=h2o_rhof(P);
RG=h2o_rhog(P);

INVRHOTP=(X/RG)+((1-X)/RF);
RHOTPH2O=1/INVRHOTP;
return