function M=find_motif34(m,n)
%FIND_MOTIF34       Motif legend
%
%   Motif_matrices = find_motif34(Motif_id,Motif_class);
%   Motif_id = find_motif34(Motif_matrix);
%
%   This function returns all motif isomorphs for a given motif id and
%   class (3 or 4). The function also returns the motif id for a given
%   motif matrix
%
%   1. Input:       Motif_id,           e.g. 1 to 13, if class is 3
%                   Motif_class,        number of nodes, 3 or 4.
%
%      Output:      Motif_matrices,     all isomorphs for the given motif
%
%   2. Input:       Motif_matrix        e.g. [0 1 0; 0 0 1; 1 0 0]
%
%      Output       Motif_id            e.g. 1 to 13, if class is 3
%
%
%Mika Rubinov, UNSW, 2007-2008

persistent M3 ID3 M4 ID4

if isscalar(m)
    if n==3
        if isempty(ID3);
            load motif34lib M3 ID3;
        end
        ind=find(ID3==m).';
        M=zeros(3,3,length(ind));
        for i=1:length(ind)
            M(:,:,i)=reshape([0 M3(ind(i),1:3) 0 ...
                M3(ind(i),4:6) 0],3,3);
        end
    elseif n==4
        if isempty(ID4);
            load motif34lib M4 ID4;
        end
        ind=find(ID4==m).';
        M=zeros(4,4,length(ind));
        for i=1:length(ind)
            M(:,:,i)=reshape([0 M4(ind(i),1:4) 0 ...
                M4(ind(i),5:8) 0 M4(ind(i),9:12) 0],4,4);
        end
    end
else
    n=size(m,1);
    M=eval(['find(motif' int2str(n) 'struct_bin(m))']);
end


function line_num = sphere_llq_line_num ( lat_num, long_num )

%*****************************************************************************80
%
%% SPHERE_LLQ_LINE_NUM counts lines for a latitude/longitude quadrilateral grid.
%
%  Discussion:
%
%    The number returned is the number of pairs of points to be connected.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 October 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer LAT_NUM, LONG_NUM, the number of latitude and
%    longitude lines to draw.  The latitudes do not include the North and South
%    poles, which will be included automatically, so LAT_NUM = 5, for instance,
%    will result in points along 7 lines of latitude.
%
%    Output, integer LINE_NUM, the number of grid lines.
%
  line_num = long_num * ( lat_num + 1 ) ...
           + lat_num * long_num;

  return
end


function p = rad(p);
%RAD          Radius of (interval) polynomial (same as p.rad)
%
%   r = rad(p)
%

% written  10/04/02     S.M. Rump
% modified 04/04/04     S.M. Rump  set round to nearest for safety
% modified 04/06/05     S.M. Rump  rounding unchanged
%

  p.c = rad(p.c);
  p = normalize(p);


function boolVal=pointIsInUBeam(points,uBounds,boundType)
%%POINTISINUBEAM A region in a single direction cosine in 2D space is
%      defined either in terms of a central direction and a half beamwidth
%      (the beamwidth being the distance between the bounds of the region)
%      or in terms of a starting direction cosine and an ending direction
%      cosine, determine whether provided points are within that span.
%      Because beams and points that go past the -1 to 1 region alias back
%      into that region, one cannot simply compare the values in the points
%      to those of the bounds.
%
%INPUTS: points A vector or matrix of direction cosines values to test
%               whether or not they are in the beam. nonaliased values are
%               between -1 and 1.
%       uBounds A 2X1 vector defining the bounds of the beam. If
%               boundType=0, then uBounds(1) is the direction of the
%               center of the beam and uBounds(2) is the half
%               beamwidth of the beam. If boundType=1, then uBounds(1) is
%               the lower bound and azBounds(2) is the upper bound --where
%               the values are taken in increasing (aliased) order. If
%               bounds go outside of the beam span, then they are assumed
%               to alias back into the valid span (a beam split between two
%               directions 180 degrees apart).
%     boundType This is either 0 or 1 and affects the format of uBounds,
%               as described above. The default if omitted or an empty
%               matrix is passed is 0.
%
%OUTPUTS: boolVal This has the same size as the input and the entries are
%                 true if the corresponding entry in the input is in the
%                 beam and false if it is not in the beam.
%
%EXAMPLE:
%This plots a beam that is aliased across the -1,1 boundary. Then, points
%uniformly spaced across the -1 to 1 u span are tested for being in the
%beam. Those in the beam are plotted in red and all the other points are
%plotted in blue. One can see that the function correctly handles aliasing
%around the -1,1 discontinuity.
% range=[0;1];
% beamHalfwidth=0.1;
% closeEnds=true;
% figure(1)
% clf
% hold on
% uCenter=0.95;
% drawUBeam(uCenter,beamHalfwidth,range,[],[],closeEnds,'-k','linewidth',2)
%
% numPoints=1000;
% uPoints=linspace(-1,1,numPoints);
% boundType=0;
% uBounds=[uCenter;beamHalfwidth];
% boolVal=pointIsInUBeam(uPoints,uBounds,boundType);
%
% %Plot all the points at unit range in blue.
% points=[ones(1,numPoints);uPoints];
% useHalfRange=true;
% xyPts=ru2Cart2D(points,useHalfRange);
% scatter(xyPts(1,:),xyPts(2,:),100,'.b')
% %Plot the points that gate in red.
% points=points(:,boolVal);
% xyPts=ru2Cart2D(points,useHalfRange);
% scatter(xyPts(1,:),xyPts(2,:),200,'.r')
% axis([-1,1,-0.5,1])
%
%January 2023 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<3||isempty(boundType))
    boundType=0;
end

if(boundType==0)
    %If defined in terms of a beam center and a beamwidth....
    beamCenter=uBounds(1);
    beamHalfwidth=uBounds(2);

    if(beamHalfwidth>=1)
        boolVal=true(size(points));
        return;
    end

    u1=beamCenter-beamHalfwidth;
    u2=beamCenter+beamHalfwidth;
else
    %If the bounds are directly given.
    u1=uBounds(1);
    u2=uBounds(2);
end
%Alias everything so that u1=0. Everything is considered in terms of
%increasing u from 0.
u2=wrapRange(u2-u1,0,2);
points=wrapRange(points-u1,0,2);

%Test whether the direction cosines are in or on the edge of the beam.
boolVal=(points<=u2);

end

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


function [h,g,a,info] = wfilt_oddevena(N)
%WFILT_ODDEVENA  Kingsbury's symmetric even filters
%
%   Usage: [h,g,a] = wfilt_oddevena(N);
%
%   `[h,g,a]=wfilt_oddevena(N)` with $N \in {1}$ returns Kingsbury's
%   even filters.
%
%   Examples:
%   ---------
%   :::
%     figure(1);
%     wfiltinfo('ana:oddevena1');
%
%     figure(2);
%     wfiltinfo('syn:oddevena1');
%
%   References: king02

% AUTHOR: Zdenek Prusa

info.istight = 0;

a = [2;2];

switch(N)
 case 1
    % Example 1. from the reference. Symmetric near-orthogonal
    garr = [
             0           0
             0           0
             0          -0.0004645
             0           0.0013349
            -0.0058109   0.0022006
             0.0166977  -0.0130127
            -0.0000641   0.0015360
            -0.0834914   0.0869008
             0.0919537   0.0833552
             0.4807151  -0.4885957
             0.4807151   0.4885957
             0.0919537  -0.0833552
            -0.0834914  -0.0869008
            -0.0000641  -0.0015360
             0.0166977   0.0130127
            -0.0058109  -0.0022006
             0          -0.0013349
             0           0.0004645
             0           0
             0           0
    ];

    % This scaling is not in the reference paper, but it is here to be
    % consistent
    garr = garr*sqrt(2);
    %garr = setnorm(garr,'energy');

    offset = -10;

  otherwise
        error('%s: No such filters.',upper(mfilename));
end

    %garr = [garr(:,3:4),garr(:,1:2)];
    modrange = (-1).^((0:size(garr,1)-1) + offset+1).';
    modrange2 = (-1).^((0:size(garr,1)-1) + offset).';

    harr =       [garr(:,2).*modrange2,...
                  garr(:,1).*modrange,...
                  ];

% In the biorthogonal case, the filters do not get time reversed
garr = flipud(garr);

htmp=mat2cell(harr,size(harr,1),ones(1,size(harr,2)));
h = cellfun(@(hEl)struct('h',hEl,'offset',offset),htmp(1:2),...
                   'UniformOutput',0);

gtmp=mat2cell(garr,size(garr,1),ones(1,size(garr,2)));

g = cellfun(@(gEl)struct('h',gEl,'offset',offset),gtmp(1:2),...
                   'UniformOutput',0);


clc;
load('detector1.mat');

I1=imread('C:\Shivanshu laptop data\Desktop data\Ortho_HOG\video\frame\frame205.jpg');

I=rgb2gray(I1);
J=edge(I,'Canny',[0.15 0.3]);
s=size(J);
u=s(1,1);
v=s(1,2);
y=[2*u/5 u u 2*u/5];%h
x=[v/2 v/4 3*v/4 v/2];%w
mask=poly2mask(x,y,u,v);
f=J.*mask;
y1=[0 u u 0];%h
x1=[0 0 v/2 v/2];%w
mask1=poly2mask(x1,y1,u,v);
f1=f.*mask1;
[H,T,R]=hough(f1);
y2=[0 u u 0];%h
x2=[v/2 v/2 v v];%w
mask2=poly2mask(x2,y2,u,v);
f2=f.*mask2;
[H,T,R]=hough(f1,'RhoResolution',2,'ThetaResolution',5);
P=houghpeaks(H,5,'threshold',ceil(0.5*max(H(:))));
lines1=houghlines(f1,T,R,P,'FillGap',15,'MinLength',7);

[H2,T2,R2]=hough(f2,'RhoResolution',2,'ThetaResolution',5);
P2=houghpeaks(H2,5,'threshold',ceil(0.5*max(H2(:))));
lines2=houghlines(f2,T2,R2,P2,'FillGap',15,'MinLength',7);

figure(6)
imshow(I);
title('0.6');

max_len1=0;
max_len2=0;
%AA1=zeros(1,length(lines1));
%AA2=zeros(1,length(lines2));
for k=1:length(lines1)
len1=norm(lines1(k).point1-lines1(k).point2);
xy1=[lines1(k).point1;lines1(k).point2];
if(len1>max_len1)
    max_len1=len1;
    xy_long=xy1;
end
end

for k=1:length(lines2)
len2=norm(lines2(k).point1-lines2(k).point2);
xy2=[lines2(k).point1;lines2(k).point2];
if(len2>max_len2)
    max_len2=len2;
    xy_2=xy2;
end
end

%for k=1:length(lines1)
 %   disp(k);
  %  xy=[lines1(k).point1;lines1(k).point2];
   % len=norm(lines(k).point1-lines(k).point2);
    %disp(xy(1,2));
    %if(xy(1,2)<=(v/2))
     %       AA1(1,k)=len;
    %else
     %   AA2(1,k)=len;
    %end
%end
%[max_len1,idx]=max(AA1);
%for k=1:length(lines)
%if(AA1(1,k)==max_len1)
 %       xy_long=[lines(k).point1;lines(k).point2];
  %      end
%end
%[max_len2,idx]=max(AA2);
%for k=1:length(lines)
%if(AA2(1,k)==max_len2)
 %       xy2=[lines(k).point1;lines(k).point2];
  %      end
%end

    %[ee,ff]=max(AA);
    %xy2=[lines(ff).point1;lines(ff).point2];
     %plot(xy_long(:,1),xy_long(:,2)+[20; 150],'LineWidth',2,'Color','green');%
     %plot(xy_2(:,1),xy_2(:,2)+[-10; -20],'LineWidth',2,'Color','green');

h1=imread('C:\Shivanshu laptop data\Desktop data\Ortho_HOG\video\frame\frame739.jpg');
I1=imread('C:\Shivanshu laptop data\Desktop data\Ortho_HOG\video\frame\frame194.jpg');
I=rgb2hsv(I1);
h=rgb2hsv(h1);
%figure(1)
%imshow(I1);
II=I(:,:,3);
HH=h(:,:,3);
for i=1:360
    for j=1:450
        if((II(i,j)<=1) && (II(i,j)>0.85))
            II(i,j)=II(i,j);
        else
           II(i,j)=0;
        end
    end
end

for i=1:360
    for j=1:450
        if((HH(i,j)<=1) && (HH(i,j)>0.12))
            HH(i,j)=HH(i,j);
        else
           HH(i,j)=0;
        end
    end
end
%figure(2)
%imshow(II);

s=size(II);
u=s(1,1);
v=s(1,2);
y=[2*u/5 u u 1*u/3 2*u/5];%h
x=[v/2 v/3 v v v/2];%w
mask=poly2mask(x,y,u,v);
f=II.*mask;
%figure(2);
%imshow(mask);
hh=HH.*mask;
hh=1-hh;

for i=1:360
  for  j=1:450
if(hh(i,j)<1)
    hh(i,j)=0;
end
end
end
f=f.*hh;

[bbox, score, label] = detect(detector1,f)
%Display detection results.
%detectedImg = insertObjectAnnotation(I1,'Rectangle',bbox);
%detectedImg = insertShape(I1,'Rectangle',bbox);
%figure(3)
%imshow(detectedImg)

% Display detection results
label_str = cell(1,1);
%conf_val = [score];
conf_lab = [label];
%for ii=1:3
    label_str =[sprintf('%s',conf_lab)];
%end
position = [bbox];
outputImage = insertObjectAnnotation(I1,'rectangle',position,label_str,...
    'TextBoxOpacity',0.9,'FontSize',10);
figure(4)
imshow(outputImage)
hold on
plot(xy_long(:,1),xy_long(:,2)+[20; 150],'LineWidth',2,'Color','green');%
     plot(xy_2(:,1),xy_2(:,2)+[-10; -20],'LineWidth',2,'Color','green');


function pass = test_addBreaksAtRoots(pref)

if ( nargin == 0 )
    pref = chebfunpref();
end

%%
% Test that pointValues are exactly zero at the new roots.

% Scalar:
f = chebfun(@(x) sin(x)-.5, pref);
g = addBreaksAtRoots(f);
pass(1) = g.pointValues(2) == 0;

% Array-valued:
f = chebfun(@(x) [sin(x), sin(x)-.5], pref);
g = addBreaksAtRoots(f);
pass(2) = g.pointValues(2,1) == 0 && g.pointValues(3,2) == 0;

%% piecewise smooth chebfun: smoothfun + singfun & splitting off.

% define the domain:
dom = [-2 7];
domCheck = [dom(1)+0.1 dom(2)-0.1];

pow1 = -0.5;
pow2 = -1.2;
op = @(x) cos(40*x).*((x-dom(1)).^pow1).*((x-dom(2)).^pow2);
f = chebfun(op, dom, 'exps', [pow1 pow2], 'splitting', 'off');
g = addBreaksAtRoots(f);

% check values:

% Generate a few random points to use as test values:
x = diff(domCheck) * rand(100, 1) + domCheck(1);

vals_g = feval(g, x);
vals_check = feval(op, x);
err = vals_g - vals_check;

r_exact = (((-25:88)+1/2)*pi/40).';

pass(3) = ( norm(err, inf) < 1e4*eps*norm(vals_check, inf) ) && ...
    ( norm( [dom(1); r_exact; dom(2)] - g.domain.', inf) < ...
    1e4*eps*norm(r_exact, inf) );

%% Tests for functions defined on unbounded domain:

% Functions on [-inf inf]:

% Set the domain:
dom = [-Inf Inf];
domCheck = [-1e2 1e2];

% Generate a few random points to use as test values:
x = diff(domCheck) * rand(100, 1) + domCheck(1);

op = @(x) (1-exp(-x.^2))./x;
f = chebfun(op, dom);
g = addBreaksAtRoots(f);
rExact = 0;

vals_g = feval(g, x);
vals_check = feval(op, x);
err = vals_g - vals_check;
pass(4) = ( norm(err, inf) < 1e2*eps*vscale(f) ) && ...
    ( norm( rExact - g.domain(2:end-1).', inf) < 1e2*eps*vscale(f) );

% Blow-up function:
op = @(x) x.^2.*(1-exp(-x.^2))-2;
f = chebfun(op, dom, 'exps', [2 2]);
g = addBreaksAtRoots(f);
rExact = [-1.4962104914103104707 ; 1.4962104914103104707];

vals_g = feval(g, x);
vals_check = feval(op, x);
err = vals_g - vals_check;
pass(5) = ( norm(err, inf) < 1e7*eps*vscale(f) ) && ...
    ( norm( rExact - g.domain(2:end-1).', inf) < 1e5*eps*vscale(f) );

% Functions on [a inf]:
dom = [0 Inf];
domCheck = [0 100];

% Generate a few random points to use as test values:
x = diff(domCheck) * rand(100, 1) + domCheck(1);

op = @(x) 0.15+sin(10*x)./exp(x);
f = chebfun(op, dom);
g = addBreaksAtRoots(f);
rExact = [0.33529141416564289113;
          0.60061694515161002799;
          0.98375750309184861332;
          1.2042605667187311146;
          1.6619482204330474390;
          1.7760894757659030239];

vals_g = feval(g, x);
vals_check = feval(op, x);
err1 = norm(vals_g - vals_check, inf);
tol1 = 1e2*eps*vscale(f);
err2 = norm( rExact - g.domain(2:end-1).', inf);
tol2 = 1e2*eps*vscale(f);
pass(6) = ( err1 < tol1 ) && ( err2 < tol2 );

% TODO: Add more tests.

end


function stroud_test052 ( )

%*****************************************************************************80
%
%% TEST052 tests BALL_VOLUME_3D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 April 2009
%
%  Author:
%
%    John Burkardt
%
  n = 3;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST052\n' );
  fprintf ( 1, '  In 3 dimensions:\n' );
  fprintf ( 1, '  BALL_VOLUME_3D computes the volume of a unit ball.\n' );
  fprintf ( 1, '  BALL_VOLUME_ND will be called for comparison.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  N    R      Volume    Method\n' );
  fprintf ( 1, '\n' );

  r = 1.0;

  for i = 1 : 3

    fprintf ( 1, '  %1d  %12f  %12f  %s\n', ...
      n, r, ball_volume_3d ( r ), 'BALL_VOLUME_3D' );

    fprintf ( 1, '  %1d  %12f  %12f  %s\n', ...
      n, r, ball_volume_nd ( n, r ), 'BALL_VOLUME_ND' );

    r = r * 2.0;

  end

  return
end


function d = dunion ( d1, d2 )

%*****************************************************************************80
%
%% DUNION returns the signed distance to a union of two regions.
%
%  Copyright:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input, real D1, D2, the signed distance of one or more points
%    to two regions.
%
%    Output, real D, the signed distance of one or more points to
%    the region formed by the union of the two regions.
%
  d = min ( d1, d2 );

  return
end


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

%% Syntax
% |[F,V,Vs]=geoSphere(n,r,solidType);|

%% Description
% Use |geoSphere| to generate triangulated spheres with nearly geodesic
% triangle distributions. The density of the triangulation can be
% controlled through a particular choice of n (number of mesh refinement
% steps).

%% Examples

clear; close all; clc;

%%
% Plot Settings
fontSize=15;
faceAlpha=1;
edgeColor=0.2*ones(1,3);
edgeWidth=1.5;

%% Building a geodesic dome based on the icosahedron
% The function inputs are n and r which define the mesh refinement and
% radius respectively. The mesh refinement number n defines the number of
% subtriangulation (see function |subTri|) iterations performed on an
% icosahedron.

r=1; %sphere radius
n=2; %Refinements
[F,V,~]=geoSphere(n,r);
[Fi,Vi,~]=geoSphere(0,r);
%%
% Visualize sphere

cFigure; hold on;
subplot(1,2,1); hold on;
gpatch(Fi,Vi,'rw','r',0.8,2);
plotV(Vi,'r.','MarkerSize',50);
camlight headlight;
axisGeom(gca,fontSize);

subplot(1,2,2); hold on;
gpatch(F,V,'bw','k',1,2);
plotV(Vi,'r.','MarkerSize',50);
camlight headlight;
axisGeom(gca,fontSize);
drawnow;

%%
% Below is a visualisation for n=0:1:3. The function outputs the geodesic
% dome faces (F) and vertices (V) and also the spherical coordinates of the
% vertices (Vs) (this output is suppressed in the example below).

cFigure; % Open figure for plotting

%Defining triangulated geodesic domes with different densities
r=1; %sphere radius
n=0:1:3; %Refinements
pColors=gjet(numel(n));
for q=1:1:numel(n)
    [F,V,~]=geoSphere(n(q),r);
    subplot(2,2,q); hold on;
    title([num2str(n(q)),' refinement iterations'],'FontSize',fontSize);
    gpatch(F,V,pColors(q,:));
    % patchNormPlot(F,V);
    camlight headlight;
    axisGeom(gca,fontSize);
end
drawnow;

%% Using other solid types
% Other platonic solids can also be used as a starting tesselation. However
% these may not be as geodesic as the result for the icosahedron and
% dodecahedron.

%e.g. using a cube
solidTypes=1:5;

cFigure; % Open figure for plotting
titleCell={'tetrahedron','cube','octahedron','icosahedron','dodecahedron'};
pColors=gjet(numel(solidTypes));
for q=solidTypes
    [F,V,~]=geoSphere(0,r,q);
    subplot(2,3,q); hold on;
    title(['Based on: ',titleCell{q}],'FontSize',fontSize);
    gpatch(F,V,pColors(q,:));
    % patchNormPlot(F,V);
    camlight headlight;
    axisGeom(gca,fontSize);
end
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 [ps,ix] = dpsimplify(p,tol)

% Recursive Douglas-Peucker Polyline Simplification, Simplify
%
% [ps,ix] = dpsimplify(p,tol)
%
% dpsimplify uses the recursive Douglas-Peucker line simplification
% algorithm to reduce the number of vertices in a piecewise linear curve
% according to a specified tolerance. The algorithm is also know as
% Iterative Endpoint Fit. It works also for polylines and polygons
% in higher dimensions.
%
% In case of nans (missing vertex coordinates) dpsimplify assumes that
% nans separate polylines. As such, dpsimplify treats each line
% separately.
%
% For additional information on the algorithm follow this link
% http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
%
% Input arguments
%
%     p     polyline n*d matrix with n vertices in d
%           dimensions.
%     tol   tolerance (maximal euclidean distance allowed
%           between the new line and a vertex)
%
% Output arguments
%
%     ps    simplified line
%     ix    linear index of the vertices retained in p (ps = p(ix))
%
% Examples
%
% 1. Simplify line
%
%     tol    = 1;
%     x      = 1:0.1:8*pi;
%     y      = sin(x) + randn(size(x))*0.1;
%     p      = [x' y'];
%     ps     = dpsimplify(p,tol);
%
%     plot(p(:,1),p(:,2),'k')
%     hold on
%     plot(ps(:,1),ps(:,2),'r','LineWidth',2);
%     legend('original polyline','simplified')
%
% 2. Reduce polyline so that only knickpoints remain by
%    choosing a very low tolerance
%
%     p = [(1:10)' [1 2 3 2 4 6 7 8 5 2]'];
%     p2 = dpsimplify(p,eps);
%     plot(p(:,1),p(:,2),'k+--')
%     hold on
%     plot(p2(:,1),p2(:,2),'ro','MarkerSize',10);
%     legend('original line','knickpoints')
%
% 3. Simplify a 3d-curve
%
%     x = sin(1:0.01:20)';
%     y = cos(1:0.01:20)';
%     z = x.*y.*(1:0.01:20)';
%     ps = dpsimplify([x y z],0.1);
%     plot3(x,y,z);
%     hold on
%     plot3(ps(:,1),ps(:,2),ps(:,3),'k*-');
%
%
%
% Author: Wolfgang Schwanghart, 13. July, 2010.
% w.schwanghart[at]unibas.ch

if nargin == 0
    help dpsimplify
    return
end

error(nargchk(2, 2, nargin))

% error checking
if ~isscalar(tol) || tol<0;
    error('tol must be a positive scalar')
end

% nr of dimensions
nrvertices    = size(p,1);
dims    = size(p,2);

% anonymous function for starting point and end point comparision
% using a relative tolerance test
compare = @(a,b) abs(a-b)/max(abs(a),abs(b)) <= eps;

% what happens, when there are NaNs?
% NaNs divide polylines.
Inan      = any(isnan(p),2);
% any NaN at all?
Inanp     = any(Inan);

% if there is only one vertex
if nrvertices == 1 || isempty(p);
    ps = p;
    ix = 1;

% if there are two
elseif nrvertices == 2 && ~Inanp;
    % when the line has no vertices (except end and start point of the
    % line) check if the distance between both is less than the tolerance.
    % If so, return the center.
    if dims == 2;
        d    = hypot(p(1,1)-p(2,1),p(1,2)-p(2,2));
    else
        d    = sqrt(sum((p(1,:)-p(2,:)).^2));
    end

    if d <= tol;
        ps = sum(p,1)/2;
        ix = 1;
    else
        ps = p;
        ix = [1;2];
    end

elseif Inanp;

    % case: there are nans in the p array
    % --> find start and end indices of contiguous non-nan data
    Inan = ~Inan;
    sIX = strfind(Inan',[0 1])' + 1;
    eIX = strfind(Inan',[1 0])';

    if Inan(end)==true;
        eIX = [eIX;nrvertices];
    end

    if Inan(1);
        sIX = [1;sIX];
    end

    % calculate length of non-nan components
    lIX = eIX-sIX+1;
    % put each component into a single cell
    c   = mat2cell(p(Inan,:),lIX,dims);

    % now call dpsimplify again inside cellfun.
    if nargout == 2;
        [ps,ix]   = cellfun(@(x) dpsimplify(x,tol),c,'uniformoutput',false);
        ix        = cellfun(@(x,six) x+six-1,ix,num2cell(sIX),'uniformoutput',false);
    else
        ps   = cellfun(@(x) dpsimplify(x,tol),c,'uniformoutput',false);
    end

    % write the data from a cell array back to a matrix
    ps = cellfun(@(x) [x;nan(1,dims)],ps,'uniformoutput',false);
    ps = cell2mat(ps);
    ps(end,:) = [];

    % ix wanted? write ix to a matrix, too.
    if nargout == 2;
        ix = cell2mat(ix);
    end

else

% if there are no nans than start the recursive algorithm
ixe     = size(p,1);
ixs     = 1;

% logical vector for the vertices to be retained
I   = true(ixe,1);

% call recursive function
p   = simplifyrec(p,tol,ixs,ixe);
ps  = p(I,:);

% if desired return the index of retained vertices
if nargout == 2;
    ix  = find(I);
end

end

% _________________________________________________________
function p  = simplifyrec(p,tol,ixs,ixe)

    % check if startpoint and endpoint are the same
    % better comparison needed which included a tolerance eps

    c1 = num2cell(p(ixs,:));
    c2 = num2cell(p(ixe,:));

    % same start and endpoint with tolerance
    sameSE = all(cell2mat(cellfun(compare,c1(:),c2(:),'UniformOutput',false)));

    if sameSE;
        % calculate the shortest distance of all vertices between ixs and
        % ixe to ixs only
        if dims == 2;
            d    = hypot(p(ixs,1)-p(ixs+1:ixe-1,1),p(ixs,2)-p(ixs+1:ixe-1,2));
        else
            d    = sqrt(sum(bsxfun(@minus,p(ixs,:),p(ixs+1:ixe-1,:)).^2,2));
        end
    else
        % calculate shortest distance of all points to the line from ixs to ixe
        % subtract starting point from other locations
        pt = bsxfun(@minus,p(ixs+1:ixe,:),p(ixs,:));

        % end point
        a = pt(end,:)';

        beta = (a' * pt')./(a'*a);
        b    = pt-bsxfun(@times,beta,a)';
        if dims == 2;
            % if line in 2D use the numerical more robust hypot function
            d    = hypot(b(:,1),b(:,2));
        else
            d    = sqrt(sum(b.^2,2));
        end
    end

    % identify maximum distance and get the linear index of its location
    [dmax,ixc] = max(d);
    ixc  = ixs + ixc;

    % if the maximum distance is smaller than the tolerance remove vertices
    % between ixs and ixe
    if dmax <= tol;
        if ixs ~= ixe-1;
            I(ixs+1:ixe-1) = false;
        end
    % if not, call simplifyrec for the segments between ixs and ixc (ixc
    % and ixe)
    else
        p   = simplifyrec(p,tol,ixs,ixc);
        p   = simplifyrec(p,tol,ixc,ixe);

    end

end
end


function z = crossp(x,y)

% crossp - compute cross product
%
%   z = crossp(x,y);
%
% x and y are (m,3) dimensional
%
%   Copyright (c) 2007 Gabriel Peyre

z = x;
z(:,1) = x(:,2).*y(:,3) - x(:,3).*y(:,2);
z(:,2) = x(:,3).*y(:,1) - x(:,1).*y(:,3);
z(:,3) = x(:,1).*y(:,2) - x(:,2).*y(:,1);


function varargout = svmtrain(varargin)
% VL_SVMTRAIN   Train a Support Vector Machine
%   [W B] = VL_SVMTRAIN(X, Y, LAMBDA) trains a linear Support Vector
%   Machine (SVM) from the data vectors X and the labels Y. X is a D
%   by N matrix, with one column per example and D feature dimensions
%   (SINGLE or DOUBLE). Y is a DOUBLE vector with N elements with a
%   binary (-1 or +1) label for each training point. To a first order
%   approximation, the function computes a weight vector W and offset
%   B such that the score W'*X(:,i)+B has the same sign of LABELS(i)
%   for all i.
%
%   VL_SVMTRAIN(DATASET, LABELS, LAMBDA) takes as input a DATASET
%   structure, which allows more sophisticated input formats to be
%   supported (see VL_SVMDATASET()).
%
%   [W, B, INFO] = VL_SVMTRAIN(...) additionally returns a structure
%   INFO with the following fields:
%
%   iteration::
%     Number of iterations performed.
%
%   epoch::
%     Number of iterations over number of training data points.
%
%   elapsedTime::
%     Time elapsed since the start of training.
%
%   objective::
%     SVM objective value.
%
%   regularizer::
%     Regularizer value.
%
%   loss::
%     Loss value.
%
%   scoreVariation:: [SGD only]
%     Mean square root of the difference between the last two
%     values of the SVM scores for each point.
%
%   dualObjective:: [SDCA only]
%     Dual objective value.
%
%   dualLoss:: [SDCA only]
%     Dual loss value::
%
%   dualityGap:: [SDCA only]
%     Difference between the objective and the dual objective.
%
%   [W, B, INFO, SCORES] = VL_SVMTRAIN(X, Y, LABMDA) returns a row
%   vector of the SVM score for each training point. This can be used
%   in combination with the options SOLVER, MODEL, and BIAS to
%   evaluate an existing SVM on new data points. Furthermore INFO will
%   contain the corresponding SVM loss, regularizer, and objective
%   function value. If this information is not of interest, it is
%   possible to pass a null vector Y instead of the actual labels as
%   well as a null regularizer.
%
%   VL_SVMTRAIN() accepts the following options:
%
%   Verbose::
%     Specify one or multiple times to increase the verbosity level.
%     Given only once, produces messages at the beginning and end of
%     the learning. Verbosity of at least 2 prints information at
%     every diagnostic step.
%
%   Epsilon:: 1e-3
%     Tolerance for the stopping criterion.
%
%   MaxNumIterations:: 10/LAMBDA
%     Maximum number of iterations.
%
%   BiasMultiplier:: 1
%     Value of the constant B0 used as bias term (see below).
%
%   BiasLearningRate:: 0.5
%     Learning rate for the bias (SGD solver only).
%
%   DiagnosticFunction:: []
%     Diagnostic function callback. The callback takes the INFO
%     structure as only argument. To trace energies and plot graphs,
%     the callback can update a global variable or, preferably, be
%     defined as a nested function and update a local variable in the
%     parent function.
%
%   DiagnosticFrequency:: Number of data points
%     After how many iteration the diagnostic is run. This step check
%     for convergence, and is done rarely, typically after each epoch
%     (pass over the data). It also calls the DiangosticFunction,
%     if any is specified.
%
%   Loss:: HINGE
%     Loss function. One of HINGE, HINGE2, L1, L2, LOGISTIC.
%
%   Solver:: SDCA
%     One of SGD (stochastic gradient descent [1]), SDCA (stochastic
%     dual coordinate ascent [2,3]), or NONE (no training). The
%     last option can be used in combination with the options MODEL
%     and BIAS to evaluate an existing SVM.
%
%   Model:: null vector
%     Specifies the initial value for the weight vector W (SGD only).
%
%   Bias:: 0
%     Specifies the initial value of the bias term (SGD only).
%
%   Weights:: []
%     Specifies a weight vector to assign a different non-negative
%     weight to each data point. An application is to rebalance
%     unbalanced datasets.
%
%   FORMULATION
%
%   VL_SVMTRAIN() minimizes the objective function of the form:
%
%     LAMBDA/2 |W|^2 + 1/N SUM_i LOSS(W' X(:,i), Y(i))
%
%   where LOSS(W' Xi,Yi) is the loss (hinge by default) for i-th
%   data point. The bias is incorporated by extending each data
%   point X with a feature of constant value B0, such that the
%   objective becomes
%
%    LAMBDA/2 (|W|^2 + WB^2) 1/N SUM_i LOSS(W' X(:,i) + WB B0, Y(i))
%
%   Note that this causes the learned bias B = WB B0 to shrink
%   towards the origin.
%
%   Example::
%     Learn a linear SVM from data X and labels Y using 0.1
%     as regularization coefficient:
%
%       [w, b] = vl_svmtrain(x, y, 0.1) ;
%
%     The SVM can be evaluated on new data XTEST with:
%
%       scores = w'*xtest + b ;
%
%     Alternatively, VL_SVMTRAIN() can be used for evaluation too:
%
%       [~,~,~, scores] = vl_svmtrain(xtest, y, 0, 'model', w, 'bias', b, 'solver', 'none') ;
%
%     The latter form is particularly useful when X is a DATASET structure.
%
%   See also: SVM fundamentals,
%   VL_SVMDATASET(), VL_HELP().
[varargout{1:nargout}] = vl_svmtrain(varargin{:});


function idx = scimat_world2index(x, scimat, CHOP)
% SCIMAT_WORLD2INDEX  Convert real world coordinates to image indices for
% the SCIMAT image struct that we use in Gerardus.
%
%   Function SCIMAT_WORLD2INDEX() converts the coordinates of a voxel given
%   as real world coordinates [x, y, z, t] into index coordinates
%   [row, column, slice, frame].
%
%      [x, y, z, t] -> [r, c, s, f]
%
%   This agrees with Matlab's convention that images are expected to be
%   (r, c, s) <-> (y, x, z), but point coordinates are given in the
%   (x, y, z)-order.
%
%   This function can also be applied to images that are not 4D, and in
%   that case, index and real world coordinates will have the same number
%   of elements as dimensions the image has.
%
%   The relation between indices IDX and real world coordinates X is
%
%     X = s.*(IDX-1)*R + t
%
%   where s is the voxel size, R the rotation matrix, and t the
%   image offset.
%
%   For points that are not within the data volume, the returned
%   indices are "NaN".
%
%   Note also that the indices are not rounded, to allow for sub-pixel
%   accuracy. If integer indices are required, then just use round(idx).
%
% IDX = SCIMAT_WORLD2INDEX(X, SCIMAT)
%
%   X is a 3-column matrix where each row contains the real world
%   (x,y,z)-coordinates of a point.
%
%   IDX has the same size as X, and the voxel indices in
%   (row, column, slice)-order, that corresponds to (y, x, z)-order.
%
%   SCIMAT is a struct with the image space metadata, i.e. spacing, offset
%   and orientation (see "help scimat" for details). SCIMAT.data (the fild
%   that contains the image itself) is not used by the function, and thus
%   can be present or absent. Note that Matlab will pass SCIMAT.data by
%   reference, so passing the whole image does not require more memory or
%   slow the function down.
%
% IDX = SCIMAT_WORLD2INDEX(..., CHOP)
%
%   CHOP is a flag to convert points outside the image volume to NaNs. By
%   default, CHOP=true.
%
%
% Example:
%
% >> idx = scimat_world2index([.01, .011, .02], scimat)
%
% idx =
%
%     55   189   780
%
% See also: scimat, scimat_index2world, scimat_load, scimat_im2scimat.

% Authors: Ramon Casero <rcasero@gmail.com>,
% Benjamin Villard <b.016434@gmail.com>,
% Christopher Kelly  <christopher.kelly28@googlemail.com>
% Copyright © 2009-2015 University of Oxford
% Version: 0.5.0
%
% University of Oxford means the Chancellor, Masters and Scholars of
% the University of Oxford, having an administrative office at
% Wellington Square, Oxford OX1 2JD, UK.
%
% This file is part of Gerardus.
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details. The offer of this
% program under the terms of the License is subject to the License
% being interpreted in accordance with English Law and subject to any
% action against the University of Oxford being under the jurisdiction
% of the English Courts.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.

% check arguments
narginchk(2, 3);
nargoutchk(0, 1);

% defaults
if (nargin < 3 || isempty(CHOP))
    CHOP = true;
end
if (~isfield(scimat, 'rotmat'))
    scimat.rotmat = [];
end

% extract parameters
xmin = [scimat.axis.min];
dx = [scimat.axis.spacing];
n = [scimat.axis.size];
orig = xmin + dx/2;
R = scimat.rotmat;

% number of dimensions
D = length(scimat.axis);

%% convert real world coordinates to indices

% remove offset
idx = x - repmat(orig([2 1 3:end]), size(x, 1), 1);

% apply inverse rotation only to the spatial coordinates
if (~isempty(R))
    idx(:, 1:size(R, 1)) = idx(:, 1:size(R, 1)) * R';
end

% (x, y) => (y, x)
idx = idx(:, [2 1 3:end]);

% i = x / dx + 1
idx = idx ./ repmat(dx, size(idx, 1), 1) + 1;

% find which coordinates are outside the volume
if CHOP
    for I = 1:D
        idx(idx(:, I) < 0.5 | idx(:, I) > n(I)+0.5, I) = NaN;
    end
end


function clenshaw_curtis_rule ( n, a, b, filename )

%*****************************************************************************80
%
%% CLENSHAW_CURTIS_RULE generates a Clenshaw Curtis rule.
%
%  Discussion:
%
%    This program computes a standard Clenshaw Curtis quadrature rule
%    and writes it to a file.
%
%    The user specifies:
%    * N, the number of points in the rule;
%    * A, the left endpoint;
%    * B, the right endpoint;
%    * FILENAME, the root name of the output files.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2014
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CLENSHAW_CURTIS_RULE\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Compute a Clenshaw Curtis rule for approximating\n' );
  fprintf ( 1, '    Integral ( A <= x <= B ) f(x) dx\n' );
  fprintf ( 1, '  of order N.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The user specifies N, A, B, and FILENAME.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  N is the number of points:\n' );
  fprintf ( 1, '  A is the left endpoint;\n' );
  fprintf ( 1, '  B is the right endpoint;\n' );
  fprintf ( 1, '  FILENAME is used to generate 3 files:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '    filename_w.txt - the weight file\n' );
  fprintf ( 1, '    filename_x.txt - the abscissa file.\n' );
  fprintf ( 1, '    filename_r.txt - the region file.\n' );
%
%  Get N.
%
  if ( nargin < 1 )
    n = input ( '  Enter the rule order N:  ' );
  elseif ( ischar ( n ) )
    n = str2num ( n );
  end
%
%  Get A.
%
  if ( nargin < 2 )
    a = input ( '  Enter the left endpoint A:  ' );
  elseif ( ischar ( a ) )
    a = str2num ( a );
  end
%
%  Get B.
%
  if ( nargin < 3 )
    b = input ( '  Enter the right endpoint B:  ' );
  elseif ( ischar ( b ) )
    b = str2num ( b );
  end
%
%  Get FILENAME.
%
  if ( nargin < 4 )
    fprintf ( 1,  '\n' );
    fprintf ( 1,  '  FILENAME is the ''root name'' of the quadrature files).\n' );
    filename = input ( '  Enter FILENAME as a quoted string:  ' );
  end
%
%  Input summary.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  N = %d\n', n );
  fprintf ( 1, '  A = %f\n', a );
  fprintf ( 1, '  B = %f\n', b );
  fprintf ( 1, '  FILENAME = "%s".\n', filename );
%
%  Construct the rule and output it.
%
  r = [ a; b ];
  [ x, w ] = clenshaw_curtis_compute ( n );
%
%  Rescale the rule.
%
  [ x, w ] = rescale ( a, b, x, w );
%
%  Write the rule.
%
  rule_write ( n, filename, x, w, r );
%
%  Terminate.
%
  fprintf ( 1,  '\n' );
  fprintf ( 1,  'CLENSHAW_CURTIS_RULE:\n' );
  fprintf ( 1,  '  Normal end of execution.\n' );
  fprintf ( 1,  '\n' );
  timestamp ( );

  return
end
function [ x, w ] = clenshaw_curtis_compute ( n )

%*****************************************************************************80
%
%% CLENSHAW_CURTIS_COMPUTE computes a Clenshaw Curtis quadrature rule.
%
%  Discussion:
%
%    Our convention is that the abscissas are numbered from left to right.
%
%    The rule is defined on [-1,1].
%
%    The integral to approximate:
%
%      Integral ( -1 <= X <= 1 ) F(X) dX
%
%    The quadrature rule:
%
%      Sum ( 1 <= I <= N ) W(I) * F ( X(I) )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 February 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the rule.
%    1 <= N.
%
%    Output, real X(N), the abscissas.
%
%    Output, real W(N), the weights.
%
  if ( n < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'CLENSHAW_CURTIS_COMPUTE - Fatal error!\n' );
    fprintf ( 1, '  Illegal value of N = %d\n', n );
    error ( 'CLENSHAW_CURTIS_COMPUTE - Fatal error!' );
  end

  w = zeros ( n, 1 );
  x = zeros ( n, 1 );

  if ( n == 1 )
    x(1) = 0.0;
    w(1) = 2.0;
    return
  end

  for i = 1 : n
    x(i) = cos ( ( n - i ) * pi / ( n - 1 ) );
  end

  x(1) = -1.0;
  if ( mod ( n, 2 ) == 1 )
    x((n+1)/2) = 0.0;
  end
  x(n) = +1.0;

  w(1:n) = 1.0;

  for i = 1 : n

    theta = ( i - 1 ) * pi / ( n - 1 );

    for j = 1 : ( n - 1 ) / 2

      if ( 2 * j == ( n - 1 ) )
        b = 1.0;
      else
        b = 2.0;
      end

      w(i) = w(i) - b * cos ( 2.0 * j * theta ) / ( 4 * j * j - 1 );

    end

  end

  w(1)     =       w(1)     / ( n - 1 );
  w(2:n-1) = 2.0 * w(2:n-1) / ( n - 1 );
  w(n)     =       w(n)     / ( n - 1 );

  return
end
function r8mat_write ( output_filename, m, n, table )

%*****************************************************************************80
%
%% R8MAT_WRITE writes an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real TABLE(M,N), the points.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'R8MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
%  For smaller data files, and less precision, try:
%
%     fprintf ( output_unit, '  %14.6f', table(i,j) );
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %24.16f', table(i,j) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function [ x, w ] = rescale ( a, b, x, w )

%*****************************************************************************80
%
%% RESCALE rescales a Legendre quadrature rule from [-1,+1] to [A,B].
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 October 2009
%
%  Author:
%
%    John Burkardt.
%
%  Parameters:
%
%    Input, real A, B, the endpoints of the new interval.
%
%    Input, integer N, the order.
%
%    Input, real X(N), the abscissas for [-1,+1].
%
%    Input, real W(N), the weights for [-1,+1].
%
%    Output, real X(N), the abscissas for [A,B].
%
%    Output, real W(N), the weights for [A,B].
%
  x = 0.5 * ( ( x + 1.0 ) * b - ( x - 1.0 ) * a );

  w = 0.5 * ( b - a ) * w;

  return
end
function rule_write ( order, filename, x, w, r )

%*****************************************************************************80
%
%% RULE_WRITE writes a quadrature rule to a file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 February 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer ORDER, the order of the rule.
%
%    Input, string FILENAME, specifies the output files.
%    write files 'filename_w.txt', 'filename_x.txt', 'filename_r.txt' defining
%    weights, abscissas, and region.
%
%    Input, real X(ORDER), the abscissas.
%
%    Input, real W(ORDER), the weights.
%
%    Input, real R(2), the region.
%
  filename_x = strcat ( filename, '_x.txt' );
  filename_w = strcat ( filename, '_w.txt' );
  filename_r = strcat ( filename, '_r.txt' );

  fprintf ( 1, '\n' );
  fprintf ( 1,'  Creating quadrature files.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  "Root" file name is   "%s".\n', filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Weight file will be   "%s".\n', filename_w );
  fprintf ( 1, '  Abscissa file will be "%s".\n', filename_x );
  fprintf ( 1, '  Region file will be   "%s".\n', filename_r );

  r8mat_write ( filename_w, 1, order, w' );
  r8mat_write ( filename_x, 1, order, x' );
  r8mat_write ( filename_r, 1, 2,     r' );

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


function [volumePVC] = PVEcorrect(volume,nIter,waveletName)
% -------------------------------------------------------------------------
% function [volumePVC] = PVEcorrect(volume,nIter,waveletName)
% -------------------------------------------------------------------------
% DESCRIPTION:
% Apply partial-volume effect (PVE) correction of an input PET volume
% using the methodology developed in ref. [1].
% -------------------------------------------------------------------------
% REFERENCE:
% [1] Boussion, N. et al. (2009). Incorporation of wavelet-based denoising
%     in iterative deconvolution for partial volume correction in
%     whole-body PET imaging. Eur J Nucl Med Mol Imaging, 36(7), 1064-1075.
% -------------------------------------------------------------------------
% INPUTS:
% - volume: 3D array representing the input PET volume to correct for PVE.
% - nIter: Number of iterations in the deconvolution process of the PVE
%          correction (see ref. [1]). If set to a string 'compute', the
%          algorithm will determine the optimal number of iterations in
%          terms of residuals up to a maximum of 10.
% - waveletName: (optional). MATLAB name of the type of wavelet used in the
%                denoising part of the PVE correction (see ref. [1]).
%                Default is 'bior3.5'.
% -------------------------------------------------------------------------
% OUTPUTS:
% - volumePVC: 3D array representing the input PET volume corrected for
%              partial volume effects.
% -------------------------------------------------------------------------
% AUTHOR(S):
% - Andre Diamant <adboustead@gmail.com>
% - Martin Vallieres <mart.vallieres@gmail.com>
% -------------------------------------------------------------------------
% HISTORY:
% - Creation: January 2016
%--------------------------------------------------------------------------
% STATEMENT:
% This file is part of <https://github.com/mvallieres/radiomics/>,
% a package providing MATLAB programming tools for radiomics analysis.
% --> Copyright (C) 2015  Martin Vallieres
%
%    This package 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 package 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 package.  If not, see <http://www.gnu.org/licenses/>.
% -------------------------------------------------------------------------

% INTIALIZATION
volumePVC = zeros(size(volume));
psf = nonIsotropicGaussianPSF(1,4);

if nargin == 3
    global wavelet_name
    wavelet_name = waveletName;
end

% PVE CORRECTION
if strcmp(nIter,'compute')
    [~,residuals] = deconvlucydenoiseNew(volume,psf,10);
    [~,nIter] = min(abs(residuals));
    fprintf('*** FOUND NUMBER OF ITERATIONS TO BE %.0f ***\n',nIter)
end
[volumePVC,~] = deconvlucydenoiseNew(volume,psf,nIter);

if nargin == 3
    clear global wavelet_name
end

end


% DEMO_VALIDATION_CSP - The demo exemplifies how to use the crossvalidation
%  function to validate CSP-based classification. The important issue here
%  is that the CSP analysis has to be performed WITHIN the cross-validation
%  on each training set. The matrix of spatial filters that is obtained from
%  the training set needs to be transfered to the test set. If you would like
%  to know more about such valiation issues, see [Lemm et al, Neuroimage
%  2011].
%  In the function crossvalidation, there is the possibility to specify
%  processing chains separately for training and test set. Variables obtained
%  from training data may be transfered to the test data. Each step in the
%  processing chain is an application of a 'proc_*' function that transforms
%  the features.

file= fullfile(BTB.DataDir, 'demoMat', 'VPkg_08_08_07', ...
               'calibration_motorimageryVPkg');
[cnt, mrk]= file_loadMatlab(file);
mrk= mrk_selectClasses(mrk, [1 2]);

[filt_b,filt_a]= butter(5, [9 13]/cnt.fs*2);
cnt= proc_filt(cnt, filt_b, filt_a);
fv= proc_segmentation(cnt, mrk, [750 3750]);

proc.train= {{'CSPW', @proc_cspAuto, 3}
             @proc_variance
             @proc_logarithm
            };
proc.apply= {{@proc_linearDerivation, '$CSPW'}
             @proc_variance
             @proc_logarithm
            };

crossvalidation(fv, {@train_RLDAshrink, 'Gamma',0}, ...
                'SampleFcn', {@sample_chronKFold, 8}, ...
                'Proc', proc)


function maxzlta()
    % maxzlta calculates the maximum z value for the LTA function.
    % The parameter step (window) can be defined by the user.

    ZG=ZmapGlobal.Data; % used by get_zmap_globals
    report_this_filefun();

    winlen_days = ZG.compare_window_dur_v3 / ZG.bin_dur;

    [len, ncu] = size(cumuall);       % redefine ncu
    len = len -2;
    lta = 1:1:ncu-2;
    var1 = zeros(1,ncu);
    var2 = zeros(1,ncu);
    lta = zeros(1,ncu);
    maxlta = zeros(1,ncu);
    maxlta = maxlta -5;
    cu = [cumuall(1:ti-1,:) ; cumuall(ti+winlen_days+1:len,:)];
    mean1 = mean(cu(:,:));
    wai = waitbar(0,'Please wait...')
    set(wai,'Color',[0.8 0.8 0.8],'NumberTitle','off','Name','Percent done');
    for i = 1:ncu
        var1(i) = cov(cu(:,i));
    end     % for i

    for it = 1:step: len - winlen_days

        waitbar(it/len)

        mean2 = mean(cumuall(it:it+winlen_days,:));
        for i = 1:ncu
            var2(i) = cov(cumuall(it:it+winlen_days,i));
        end     % for i
        lta = (mean1 - mean2)./(sqrt(var1/it+var2/(len-it)));
        maxlta2 = [maxlta ;  lta ];
        maxlta = max(maxlta2);

    end    % for it

    valueMap = reshape(maxlta,length(gy),length(gx));

    close(wai)

    stri = [  'Maximum z  Map of   '  file1];
    stri2 = ['winlen_days = ' char(days(winlen)) ];
    in = 'lta';
    view_max(valueMap,gx,gy,stri,'');

end


function [y,a]=plane_project2(x,E)
    [N,M]=size(x);
    p=size(E,2);
    a=zeros(p,M);
    ct=E(:,1);
    Ep=E(:,2:p)-ct*ones(1,p-1);
    a(2:p,:)=Ep\(x-ct*ones(1,M));
    a(1,:)=ones(1,M)-sum(a(2:p,:),1);
    y=E*a;
end


function [z, mu, s] = zscore(x, varargin)

% [Z, MU, S] = ZSCORE(X, NORMALIZEFLAG, DIM, FLAG) computes the zscore, across all cells in x along
% the dimension dim, normalising by the total number of samples
%
% X should be an linear cell-array of matrices for which the size in at
% least one of the dimensions should be the same for all cells. If flag==1, the mean will
% be subtracted first (default behavior, but to save time on already demeaned data, it
% can be set to 0). MU and S are vectors containing the mean and standard deviations used
% for zscoring

if numel(varargin)==0, varargin{1} = []; end
if numel(varargin)==1, varargin{2} = []; end
if numel(varargin)==2, varargin{3} = 1;  end

if varargin{3}
  mu = nanmean(x, varargin{2});
  x  = cellvecadd(x, -mu);
end
s = nanstd(x, varargin{1:end});
z = cellvecmult(x, 1./s);

if ~varargin{3}
  mu = zeros(size(s))+nan;
end


function data = funInterp2(x_pred, y_pred, x_obs, y_obs, data_obs, fun)
%
% SINTAX:
%   data = funInterp2(x_pred, y_pred, x_obs, y_obs, data_obs, fun)
%
% INPUT:
%   x_pred , y_pred     coordinates of the prediction point (arrays [n x 1])
%   x_obs, y_obs        coordinates of the observation (array [n x 1], sparse points)
%   data_obs            data observation array [n x n_epochs]
%   fun                 virtual function f(dist) as function of the distance
%
% OUTPUT:
%   data                interpolated data in the point of interest [n x n_epochs]
%
% DEFAULT VALUES:
%   generic interpolator using as correlation function fun
%   <default: fun = @(dist) exp(-dist)>
%
% EXAMPLE:
%   fun = @(dist) 0.2 * exp(-(dist/1e4)) + exp(-(dist/6e3).^2);
%   temp = funInterp2(ep(:), np(:), e_obs(:), n_obs(:), td_obs(:,:), fun);
%

%--- * --. --- --. .--. ... * ---------------------------------------------
%               ___ ___ ___
%     __ _ ___ / __| _ | __|
%    / _` / _ \ (_ |  _|__ \
%    \__, \___/\___|_| |___/
%    |___/                    v 1.0RC1
%
%--------------------------------------------------------------------------
%  Copyright (C) 2021 Geomatics Research & Development srl (GReD)
%  Written by:       Andrea Gatti
%  Contributors:     Andrea Gatti ...
%  A list of all the historical goGPS contributors is in CREDITS.nfo
%--------------------------------------------------------------------------
%
%   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/>.
%
%--------------------------------------------------------------------------
% 01100111 01101111 01000111 01010000 01010011
%--------------------------------------------------------------------------

    narginchk(5, 6);

    if nargin < 6
        % Correlation function
        fun = @(dist) exp(-dist);
    end

    % Init out data
    data = nan(size(data_obs, 2), numel(x_pred));

    [x_mesh, y_mesh] = meshgrid(x_obs, y_obs);
    d_obs = sqrt(abs(x_mesh - x_mesh').^2 + abs(y_mesh - y_mesh').^2);
    q_fun_obs = fun(d_obs);
    %q_fun_obs = exp(-d_obs/0.4e4);
    [xv, ~, xi] = unique(x_pred);
    [yv, ~, yi] = unique(y_pred);
    x2 = (repmat(x_obs, 1, numel(xv)) - repmat(xv', numel(x_obs), 1)).^2;
    y2 = (repmat(y_obs, 1, numel(yv)) - repmat(yv', numel(y_obs), 1)).^2;
    for i = 1 : numel(x_pred)
        d_pred = sqrt(x2(:,xi(i)) + y2(:,yi(i)));
        c_mat = q_fun_obs .* repmat(fun(d_pred)', size(q_fun_obs,1),1);
        %c_mat = bsxfun(@times, q_fun_obs, fun(d_pred)');
        c_mat = triu(c_mat) + triu(c_mat, 1)';

        trans = sum(c_mat);
        w = trans / sum(trans);
        data(:, i) = (w * data_obs)';
    end
end


function [ ap, prec_k, recall_k ] = evaluate( actual, prediction, cutoff )
% Codes for evaluate average precision (AP), precision@k and recall@k
% given actual ranking and predicted ranking
%
% ARGS:
% actual       : the given actual ranking
% prediction   : the given predicted ranking
% cutoff       : cutoff k for precision@k and recall@k
%
% RETURN:
% ap           : the average precision (not MAP)
% prec_k       : the precision@k
% recall_k     : the recall@k

ap = ap_k(actual, prediction);
prks = pr_k(actual, prediction, cutoff);
prec_k = prks(1,:);
recall_k = prks(2,:);

function scores = ap_k(actual, prediction, k)
if nargin<3
    k=inf;
end

if length(prediction)>k
    prediction = prediction(1:k);
end
score = 0;
num_hits = 0;
for i=1:min(length(prediction), k)
    if sum(actual==prediction(i))>0 && ...
            sum(prediction(1:i-1)==prediction(i))==0
        num_hits = num_hits + 1;
        score = score + num_hits / i;
    end
end
scores = score / min(length(actual), k);

function scores = pr_k(actual, prediction, ks)
scores = zeros(2, length(ks));
for i=1:length(ks)
    k = ks(i);
    if length(prediction) > k
        pred = prediction(1:k);
    else
        pred = prediction;
    end
    num_hit = length(intersect(actual, pred));
    scores(1, i) = num_hit / length(pred); % precision
    scores(2, i) = num_hit / length(actual); % recall
end


function test_libltfat_gabframediag
[~,~,enuminfo]=libltfatprotofile;
LTFAT_FIRWIN = enuminfo.LTFAT_FIRWIN;

a = 14;
gl = 34;
M = 64;
g = zeros(gl,1);
d = zeros(a,1);
gPtr = libpointer('doublePtr',g);
dPtr = libpointer('doublePtr',d);

calllib('libltfat','ltfat_firwin_d',LTFAT_FIRWIN.LTFAT_HANN,gl,gPtr);

calllib('libltfat','ltfat_gabframediag_d',gPtr,gl,a,M,a,dPtr);

d =gabframediag(gPtr.Value,a,M,lcm(a,M));
d(1:a)-dPtr.Value


%% A Unit Test Class for the OPTI Object
classdef opti_tests < matlab.unittest.TestCase

    properties

    end

    % Unit Tests
    methods (Test)

        %-- Single Precision: Nonlinear --%
        function singleNonlinear(testCase)

            optiObj = opti_tests.makeHS71();
            defaultOpts = optiset(optiObj.opts, 'warnings', 'none', 'derivCheck', 'on');

            testCase.verifyError(@() opti(optiObj, 'fun', @(x) single(opti_tests.hs71_obj(x))), 'OPTI:NotDouble');
            testCase.verifyError(@() opti(optiObj, 'nlcon', @(x) single(opti_tests.hs71_con(x))), 'OPTI:NotDouble');
            testCase.verifyError(@() opti(optiObj, 'grad', @(x) single(opti_tests.hs71_grad(x)), 'opts', defaultOpts), 'OPTI:NotDouble');
            testCase.verifyError(@() opti(optiObj, 'nljac', @(x) single(opti_tests.hs71_jac(x)), 'opts', defaultOpts), 'OPTI:NotDouble');
            testCase.verifyError(@() opti(optiObj, 'hess', @(x,s,l) single(opti_tests.hs71_hess(x,s,l)), 'opts', defaultOpts), 'OPTI:NotDouble');
        end
    end

    methods (Static)
        %-- Hock & Schittkowski #71 --%
        function optiObj = makeHS71()
            cl = [25;40];
            cu = [Inf;40];
            lb = ones(4,1);
            ub = 5*ones(4,1);
            x0 = [1 5 5 1]';
            opts = optiset('warnings', 'none');
            optiObj = opti('fun',@opti_tests.hs71_obj,'grad',@opti_tests.hs71_grad,'hess',@opti_tests.hs71_hess,...
                            'nl',@opti_tests.hs71_con,cl,cu,'nljac',@opti_tests.hs71_jac,'nljacstr',@opti_tests.hs71_jacStr,...
                            'hessstr',@opti_tests.hs71_hessStr,'bounds',lb,ub, 'x0', x0, 'opts', opts);
        end

        function obj = hs71_obj(x)
            obj = x(1)*x(4)*sum(x(1:3)) + x(3);
        end

        function grad = hs71_grad(x)
            grad = [ x(1)*x(4) + x(4)*sum(x(1:3))
                    x(1)*x(4)
                    x(1)*x(4) + 1
                    x(1)*sum(x(1:3)) ]';
        end

        function con = hs71_con(x)
            con = [ prod(x); sum(x.^2) ];
        end

        function jac = hs71_jac(x)
            jac = [ prod(x)./x'; 2*x' ];
        end

        function jacStr = hs71_jacStr()
            jacStr = sparse(ones(2,4));
        end

        function hess = hs71_hess(x, sigma, lambda)
            hess = sigma*[ 2*x(4)             0      0   0;
                              x(4)               0      0   0;
                              x(4)               0      0   0;
                              2*x(1)+x(2)+x(3)  x(1)  x(1)  0 ] + ...
                   lambda(1)*[   0          0         0         0;
                              x(3)*x(4)     0         0         0;
                              x(2)*x(4) x(1)*x(4)     0         0;
                              x(2)*x(3) x(1)*x(3) x(1)*x(2)     0  ] + ...
         		   lambda(2)*diag([2 2 2 2]);
        end

        function hessStr = hs71_hessStr()
            hessStr = sparse(tril(ones(4)));
        end
    end
end


function [hfun] = limhfn2(vert,tria,hfun,dhdx)
%LIMHFN2 impose gradient limits on a discrete mesh-size fun-
%ction defined over a 2-simplex triangulation.
%   [HFUN] = LIMHFN2(VERT,TRIA,HFUN,DHDX) returns a "gradie-
%   nt-limited" function HFUN, defined over a triangulation
%   {VERT,TRIA}. HFUN is a T-by-1 vector of function values,
%   VERT is a V-by-2 array of XY coordinates and TRIA is a
%   T-by-3 array of triangles. Each row of TRIA
%   defines a triangle, such that VERT(TRIA(II,1),:), VERT(
%   TRIA(II,2),:) and VERT(TRIA(II,3),:) are the coordinates
%   of the II-TH triangle. DHDX is a scalar gradient-limit.
%   HFUN is "limited" to control variation over the elements
%   in the triangulation, such that (HFUN(V2)-HFUN(V1))/LL<=
%   DHDX, where {V1,V2} are the vertices of a given triangle
%   edge and LL is the edge-length. Limits are enforced exh-
%   austively over all edges.
%
%   See also TRIHFN2, LFSHFN2

%   This function is based on a very simplified version of:
%   Persson, P.O. "Mesh size functions for implicit geometr-
%   ies and PDE-based gradient limiting." Engineering with
%   Computers 22 (2006): 95-109.

%   Darren Engwirda : 2017 --
%   Email           : de2363@columbia.edu
%   Last updated    : 18/04/2017

%---------------------------------------------- basic checks
    if ( ~isnumeric(vert) || ...
         ~isnumeric(tria) || ...
         ~isnumeric(hfun) || ...
         ~isnumeric(dhdx) )
        error('limhfn2:incorrectInputClass' , ...
            'Incorrect input class.') ;
    end

%---------------------------------------------- basic checks
    if (ndims(vert) ~= +2 || ...
        ndims(tria) ~= +2 || ...
        ndims(hfun) ~= +2 || ...
        numel(dhdx) ~= +1 )
        error('limhfn2:incorrectDimensions' , ...
            'Incorrect input dimensions.');
    end
    if (size(vert,2)~= +2 || ...
        size(tria,2) < +3 || ...
        size(hfun,2)~= +1 || ...
        size(vert,1)~= size(hfun,1) )
        error('limhfn2:incorrectDimensions' , ...
            'Incorrect input dimensions.');
    end

    nvrt = size(vert,1) ;

%---------------------------------------------- basic checks
    if (min(min(tria(:,1:3))) < +1 || ...
            max(max(tria(:,1:3))) > nvrt )
        error('limhfn2:invalidInputArgument', ...
            'Invalid TRIA input array.') ;
    end

%-------------------- impose gradient limits over mesh edges
   [edge,tria] = tricon2(tria);

    evec = vert(edge(:,2),:) - ...
           vert(edge(:,1),:) ;
    elen = sqrt(sum(evec.^2,2)) ;

%-------------------- impose gradient limits over edge-graph
   [hfun] = limgrad( ...
         edge,elen,hfun,dhdx,sqrt(nvrt)) ;

end


function out = normalize_rows(in)
    out = scale_rows(in,1./row_sum(in));
% rowSums = sum(x,2);
% [I,J] = size(x);
% p = zeros(I,J);
% for i=1:I
%     p(i,:) = x(i,:) / rowSums(i);
% end
%
end


function [j, dist] = LMhistintersectionquery(Query, h)
%
% Assumes histograms are normalized and sum = 1

N = size(h,1);

dist = 1-sum(min(h, repmat(Query, [N 1])),2); % histogram intersection
[dist, j] = sort(dist);


%+========================================================================+
%|                                                                        |
%|            This script uses the GYPSILAB toolbox for Matlab            |
%|                                                                        |
%| COPYRIGHT : Matthieu Aussal (c) 2017-2018.                             |
%| PROPERTY  : Centre de Mathematiques Appliquees, Ecole polytechnique,   |
%| route de Saclay, 91128 Palaiseau, France. All rights reserved.         |
%| LICENCE   : This program is free software, distributed in the hope that|
%| it will be useful, but WITHOUT ANY WARRANTY. Natively, you can use,    |
%| redistribute and/or modify it under the terms of the GNU General Public|
%| License, as published by the Free Software Foundation (version 3 or    |
%| later,  http://www.gnu.org/licenses). For private use, dual licencing  |
%| is available, please contact us to activate a "pay for remove" option. |
%| CONTACT   : matthieu.aussal@polytechnique.edu                          |
%| WEBSITE   : www.cmap.polytechnique.fr/~aussal/gypsilab                 |
%|                                                                        |
%| Please acknowledge the gypsilab toolbox in programs or publications in |
%| which you use it.                                                      |
%|________________________________________________________________________|
%|   '&`   |                                                              |
%|    #    |   FILE       : nrtMshSegment.m                               |
%|    #    |   VERSION    : 0.50                                          |
%|   _#_   |   AUTHOR(S)  : Matthieu Aussal                               |
%|  ( # )  |   CREATION   : 14.03.2017                                    |
%|  / 0 \  |   LAST MODIF : 25.11.2018                                    |
%| ( === ) |   SYNOPSIS   : Edge mesh of a segment                        |
%|  `---'  |                                                              |
%+========================================================================+

% Cleaning
clear all
close all
clc

% Gypsilab path
run('../../addpathGypsilab.m')

% Create mesh
Nvtx = 21;
L    = 4;
mesh = mshSegment(Nvtx,L);

% Colours
ctr = 1/2 .* (...
        mesh.vtx(mesh.elt(:,1),:) + ...
        mesh.vtx(mesh.elt(:,2),:) ) ;
mesh.col(ctr(:,1)<0)               = 1;
mesh.col(ctr(:,1)>=0 & ctr(:,1)<1) = 2;
mesh.col(ctr(:,1)>=1)              = 3;

% Graphical representation
figure
plot(mesh)
colorbar

% Sub-meshing
mesh1 = mesh.sub(mesh.col==1);
mesh2 = mesh.sub(mesh.col==2);
mesh3 = mesh.sub(mesh.col==3);
norm(mesh1.col-1,'inf')
norm(mesh2.col-2,'inf')
norm(mesh3.col-3,'inf')

% Graphical representation
figure
plot(mesh1)
hold on
plot(mesh2)
plot(mesh3)
colorbar

% Center
Xctr = mesh.ctr;
hold on
plot3(Xctr(:,1),Xctr(:,2),Xctr(:,3),'*y')

% Normals
plotNrm(mesh,'r')

% Volume
V = mesh.ndv;
norm(sum(V)-L)/L

% Length
l = mesh.stp;

% Edges
figure
plot(mesh.edg)
colorbar

% Particles
figure
plot(mesh.prt)
colorbar

% Unicity
tmp     = mesh;
tmp.vtx = [tmp.vtx ; tmp.vtx];
tmp.elt = [tmp.elt ; tmp.elt + size(mesh.vtx,1)];
tmp.col = [tmp.col ; tmp.col];
[~,I]   = unique(tmp);
norm(I-(1:size(mesh.elt,1))','inf')

% Intersection
[~,I] = intersect(mesh1,mesh);
norm(I-(1:size(mesh1.elt,1))','inf')

% Union
[tmp,I] = union(mesh,mesh1);
norm(I-(1:size(mesh.elt,1))','inf')

% Difference
[mesh4,~] = setdiff(mesh,mesh1);
figure
plot(mesh4)
colorbar

% Reconstruction
mesh5 = union(mesh1,mesh2);
mesh5 = union(mesh5,mesh3);
setdiff(mesh,mesh5)

% Boundary
bound = mesh5.bnd;
figure
plot(bound)
colorbar

% Clean degenerated mesh
mesh6 = mesh;
ind   = (mesh6.vtx(:,1)>0);
mesh6.vtx(ind,1) = 0;
mesh6 = clean(mesh6,1e-6);
setdiff(mesh6,mesh1)

% Clean degenerated particle mesh
vtx = mesh.vtx;
vtx(vtx(:,1)>0,1) = 0;
mesh7 = msh(vtx);
mesh7 = clean(mesh7,1e-6);
setdiff(mesh7,msh(mesh1.vtx))

disp('~~> Michto gypsilab !')


function mono_total_next_grlex_test ( )

%*****************************************************************************80
%
%% MONO_TOTAL_NEXT_GRLEX_TEST tests MONO_TOTAL_NEXT_GRLEX.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 November 2013
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'MONO_TOTAL_NEXT_GRLEX_TEST\n' );
  fprintf ( 1, '  MONO_TOTAL_NEXT_GRLEX can list the monomials\n' );
  fprintf ( 1, '  in M variables, of total degree N,\n' );
  fprintf ( 1, '  one at a time, in graded lexicographic order.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  We start the process with (0,0,...,0,N).\n' );
  fprintf ( 1, '  The process ends with (N,0,...,0,0)\n' );

  n = 3;
  m = 3;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Let M = %d\n', m );
  fprintf ( 1, '      N = %d\n', n );
  fprintf ( 1, '\n' );

  x = [ 0, 0, n ];
  i = 1;

  while ( 1 )

    fprintf ( 1, '  %2d:', i );
    for j = 1 : m
      fprintf ( 1, '  %1d', x(j) );
    end
    fprintf ( 1, '\n' );

    if ( x(1) == n )
      break
    end

    x = mono_total_next_grlex ( m, n, x );
    i = i + 1;

  end

  return
end


function cost = perm_cost(p,c)

cost = 0;
for q=1:length(p)
    cost = cost + c(q,p(q));
end

end


function [ dist ] = euclidean_dist( X_gallery, X_probe, model_para )
    dist=pdist2(X_probe,X_gallery,'euclidean');
end


function ov = regionOverlap(region1, region2, area)
% compute intersection over union of two regions
% ov = regionOverlap(region1, region2, area)

area = area(:);
r1 = false(numel(area), 1);
r2 = false(numel(area), 1);
r1(region1) = true;
r2(region2) = true;
ov = sum(area(r1 & r2)) / sum(area(r1 | r2));


function [data_out]=ofdmsymbol_fft_cp(data_in,G,TxRx)

% We can make Nfft as a parameter as well
 Nfft = 256;

 if TxRx==10
      data=data_in'; %this makes the input column vector to a array

% %% making odfm symbol and taking IFFT
% function  symbol_ofdm = createsymbol (pilots,data)

%% now first generate the pilot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A=complex(-1,0);
B=complex(1,0);
pilots = [A B A B B B A A];  %%% here we direct making the pilot,detail procedure given below

% n_symbol = 1;  % At the time of generating the pilots, I need to know what symbol i am simulating
%                % because the seed to do it depends on it.
% % The values of the pilots are to be modulated are defined in the standard as such(pp 443) :
% % Before beginning, it is necessary to consider that the value to calculate depends on 2 factors :
% % the number of symbols and whether we are in the uplink or dwnlink. We will consider that we are in
% % the downlink and we are transmitting the symbol "1".
% % If we want to consider the other uplink connection, the seed would be "10101010101".
% %
% seed = [1 1 1 1 1 1 1 1 1 1 1];
% for i=1:n_symbol+2
%     wk(i) = seed (11);
%     next = xor(seed(9),seed(11));
%     seed = [next seed(1,1:10)];
% end
%
% % Once the value of wk is found(that depends on the number of symbol with wihich it is working),
% % the values of the subcarriers must be found and of the mapping of them with BPSK constellation.
%
% wk = wk(n_symbol+2)
% A = 1 - 2*wk                           % Values defined in the standard.
% B = 1 - 2*(~wk)
% value_carrier = [A B A B B B A A]
%
% % For uplink, the values should be [A B A B A A A A]
%
% pilot_mapping = 2*mapping(value_carrier,1,Tx);
%
% % The factor of "2" is due to the fact that the pilots are transmitted to a
% % double power of the information bits.

% NOW The guard bands are prepared.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

guard1 = complex (0,0) * ones (1,28);
DC = complex (0,0);
guard2 = complex (0,0) * ones (1,27);

% The pilot and guard subcarriers are placed according to the standard.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

symbol_ofdm = [guard1 data(1:12) pilots(1) data(13:36)...
    pilots(2) data(37:60) pilots(3) data(61:84) pilots(4)...
    data(85:96) DC data(97:108) pilots(5) data(109:132) pilots(6)...
    data(133:156) pilots(7) data(157:180) pilots(8) data(181:192) guard2];

% here the ofdm symbol is completed
%Now taking IFFT
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 symbol_ofdm = sqrt(Nfft).*ifft(symbol_ofdm,Nfft);

 %Now adding cyclic prefix%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% we generate the cyclic prefix so that the multipaths do not affect our data so much.
margin = length(symbol_ofdm)*G;
data_tx = [symbol_ofdm((end-margin+1):end) symbol_ofdm];
data_out=data_tx;

   % At receiving end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif TxRx==01

data_rx=data_in;
% First, we must remove the CP.
margin = length(data_rx)*G;
margin = margin/(1+G);
symbol_ofdm_rx= data_rx(margin+1:end);

% After removing the CP, we have to inverse the IFFT, logcally by FFT.

 symbol_rx = fft(symbol_ofdm_rx,Nfft) ./ sqrt(Nfft);

 % Here the pilots are indicated, since i need to know where they are.
 % now we will be able to estimate the channel.

 pilots = [symbol_rx(41) symbol_rx(66) symbol_rx(91) symbol_rx(116) symbol_rx(142) symbol_rx(167) symbol_rx(192) symbol_rx(217)];

% After getting the received symbol, the channel is to be estimated using
% the pilot carriers. This is bypassed for an AWGN channel.

% Next, the values of the data and pilot carriers are extracted
 data_total = [symbol_rx(29:40) symbol_rx(42:65) symbol_rx(67:90) symbol_rx(92:115) symbol_rx(117:128)...
           symbol_rx(130:141) symbol_rx(143:166) symbol_rx(168:191) symbol_rx(193:216) symbol_rx(218:229)];
 data_out=data_total'; %this makes it a column vector
else
      disp('error in ofdmsymbol_fft_cp.m function');
end


% MAP_PROJECTION - Set the projection
%
% 'GLOBAL-ELLIPSE'
% 'GLOBAL-RECT'
% 'TESTBED'

function map_projection(projection)

if nargin < 1
  projection = 'global-ellipse';
end

switch lower(projection)
 case 'global-ellipse'
  m_proj('mollweide', 'clongitude', 0); % straight latitudes (equal area)
  %m_proj('hammer-aitoff', 'clon', 0); % curved latitudes (equal area)
 case 'global-rect'
  m_proj('miller');
 case 'testbed'
  m_proj('Mercator', 'lon',[22.5,26.8], 'lat',[59.74,61.0])
 otherwise
  error('Unknown projection')
end


function [PV,DV] = VariableClustering(Problem,Population,nSel,nPer)
% Detect the kind of each decision variable

%------------------------------- 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".
%--------------------------------------------------------------------------

    [N,D] = size(Population.decs);
    ND    = NDSort(Population.objs,1) == 1;
    fmin  = min(Population(ND).objs,[],1);
    fmax  = max(Population(ND).objs,[],1);
    if any(fmax==fmin)
        fmax = ones(size(fmax));
        fmin = zeros(size(fmin));
    end

    %% Calculate the proper values of each decision variable
    Angle  = zeros(D,nSel);
    RMSE   = zeros(D,nSel);
    Sample = randi(N,1,nSel);
    for i = 1 : D
        drawnow('limitrate');
        % Generate several random solutions by perturbing the i-th dimension
        Decs      = repmat(Population(Sample).decs,nPer,1);
        Decs(:,i) = unifrnd(Problem.lower(i),Problem.upper(i),size(Decs,1),1);
        newPopu   = Problem.Evaluation(Decs);
        for j = 1 : nSel
            % Normalize the objective values of the current perturbed solutions
            Points = newPopu(j:nSel:end).objs;
            Points = (Points-repmat(fmin,size(Points,1),1))./repmat(fmax-fmin,size(Points,1),1);
            Points = Points - repmat(mean(Points,1),nPer,1);
            % Calculate the direction vector of the determining line
            [~,~,V] = svd(Points);
            Vector  = V(:,1)'./norm(V(:,1)');
            % Calculate the root mean square error
            error = zeros(1,nPer);
            for k = 1 : nPer
                error(k) = norm(Points(k,:)-sum(Points(k,:).*Vector)*Vector);
            end
            RMSE(i,j) = sqrt(sum(error.^2));
            % Calculate the angle between the line and the hyperplane
            normal     = ones(1,size(Vector,2));
            sine       = abs(sum(Vector.*normal,2))./norm(Vector)./norm(normal);
            Angle(i,j) = real(asin(sine)/pi*180);
        end
    end

    %% Detect the kind of each decision variable
    VariableKind = (mean(RMSE,2)<1e-2)';
    result       = kmeans(Angle,2)';
    if any(result(VariableKind)==1) && any(result(VariableKind)==2)
        if mean(mean(Angle(result==1&VariableKind,:))) > mean(mean(Angle(result==2&VariableKind,:)))
            VariableKind = VariableKind & result==1;
        else
            VariableKind = VariableKind & result==2;
        end
    end
    PV = find(~VariableKind);
    DV = find(VariableKind);
end


function [distance_matrix, gram_matrix]= update_distance_matrix(distance_matrix, gram_matrix, gram_vector, new_sample_norm, id1, id2, w1, w2)
% Updates the distance matrix

% Normalise the weights so that they sum to one
alpha1 = w1/(w1+w2);
alpha2 = 1 - alpha1;

if id2 < 0
    norm_id1 = gram_matrix(id1, id1);

    % Update the gram matrix
    if alpha1 == 0
        % The new sample replaces an existing sample.
        gram_matrix(:,id1) = gram_vector;
        gram_matrix(id1,:) = gram_matrix(:,id1);
        gram_matrix(id1, id1) = new_sample_norm;
    elseif alpha2 == 0
        % The new sample is discared
    else
        % The new sample is merge with an existing sample
        gram_matrix(:,id1) = alpha1*gram_matrix(:,id1) + alpha2*gram_vector;
        gram_matrix(id1,:) = gram_matrix(:,id1);
        gram_matrix(id1, id1) = alpha1^2*norm_id1 + alpha2^2*new_sample_norm + 2*alpha1*alpha2*gram_vector(id1);
    end

    % Update distance matrix
    distance_matrix(:,id1) = max(gram_matrix(id1, id1) + diag(gram_matrix) - 2*gram_matrix(:,id1),0);
    distance_matrix(id1,:) = distance_matrix(:,id1) ;
    distance_matrix(id1,id1) = inf;
else
    if alpha1 == 0 || alpha2 == 0
        error('Error!');
    end

    % Two existing samples are merged and the new sample fills the empty
    % slot
    norm_id1 = gram_matrix(id1, id1);
    norm_id2 = gram_matrix(id2, id2);
    ip_id1_id2 = gram_matrix(id1,id2);

    % Handle the merge of existing samples
    gram_matrix(:,id1) = alpha1*gram_matrix(:,id1) + alpha2*gram_matrix(:,id2);
    gram_matrix(id1,:) = gram_matrix(:,id1);
    gram_matrix(id1, id1) = alpha1^2*norm_id1 + alpha2^2*norm_id2 + 2*alpha1*alpha2*ip_id1_id2;

    gram_vector(id1) = alpha1*gram_vector(id1) + alpha2*gram_vector(id2);

    % Handle the new sample
    gram_matrix(:,id2) = gram_vector;
    gram_matrix(id2,:) = gram_matrix(:,id2);
    gram_matrix(id2, id2) = new_sample_norm;

    % Update the distance matrix
    distance_matrix(:,id1) = max(gram_matrix(id1, id1) + diag(gram_matrix) - 2*gram_matrix(:,id1),0);
    distance_matrix(id1,:) = distance_matrix(:,id1) ;
    distance_matrix(id1,id1) = inf;

    distance_matrix(:,id2) = max(gram_matrix(id2, id2) + diag(gram_matrix) - 2*gram_matrix(:,id2),0);
    distance_matrix(id2,:) = distance_matrix(:,id2) ;
    distance_matrix(id2,id2) = inf;
end


function figure_num = cube3d_grid_plot ( x1, x2, x3, filename, figure_num )

%*****************************************************************************80
%
%% CUBE3D_GRID_PLOT plots hypersphere gridpoints onto the surface of a 3D cube.
%
%  Discussion:
%
%    The X1, X2, X3 data has, presumably, been computed by CUBE_GRID for
%    a 3D cube.
%
%    This function plots the surface, and then the surface plus the
%    projected grid points.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X1(2*N+1,N+1), X2(2*N+1,N+1), X3(2*N+1,N+1), the coordinates
%    of points on the cube surface, projected from the hypersphere.
%
%    Input, string FILENAME, the "first name" of the two files to be created:
%    filename_surface.png and filename_points.png.
%
%    Input/output, int FIGURE_NUM, the current figure index.
%
  if ( nargin < 4 )
    filename = 'cube';
  end
%
%  Draw the surface.
%
  figure_num = figure_num + 1;
  figure ( figure_num )
  mesh ( x3, x2, x1, 'FaceColor', 'interp' );
  axis equal
  grid on
  xlabel ( '<---X--->', 'FontSize', 16 );
  ylabel ( '<---Y--->', 'FontSize', 16 );
  zlabel ( '<---Z--->', 'FontSize', 16 );
  title ( 'Cube transition surface', 'FontSize', 24 )
  hold off
  filename1 = sprintf ( '%s_surface.png', filename );
  print ( '-dpng', filename1 );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Created plotfile "%s".\n', filename1 );
%
%  Draw the surface and points.
%
%  Listing the points in the order X1, X2, X3, rational as it may seem,
%  is apparently NOT the way to go here.
%
  figure_num = figure_num + 1;
  figure ( figure_num )
  hold on
  mesh ( x3, x2, x1, 'FaceColor', 'interp' );
  plot3 ( x3, x2, x1, 'k.', 'MarkerSize', 5 );
  axis equal
  grid on
  xlabel ( '<---X--->', 'FontSize', 16 );
  ylabel ( '<---Y--->', 'FontSize', 16 );
  zlabel ( '<---Z--->', 'FontSize', 16 );
  title ( 'Grid points on transition surface', 'FontSize', 24 )
  hold off
  filename2 = sprintf ( '%s_points.png', filename );
  print ( '-dpng', filename2 );
  fprintf ( 1, '  Created plotfile "%s".\n', filename2 );

  return
end


function [F,feasible] = filter_norm_2(all_f,all_c_w,all_c_x,all_Q_xw,x,Zmodel,allw,X,Q_xx,VariableType)

feasible = 1;
% As a first step, we figure out the radius
r = Zmodel.r;
center = Zmodel.center;
F = ([]);
ci_basis = all_c_w';
lastBici = [];
lastusedrows = [];
% (bi' + (Bi*w)')*x + (ci'*w + di).
for i = 1:length(all_f)
    Bi = 2*all_Q_xw(:,length(x)*(i-1)+1:length(x)*i)';
    bi = all_c_x(length(x)*(i-1)+1:length(x)*i);
    if (nnz(ci_basis(:,i))==0) & nnz(Bi)==0
        F = F + (X(i)>=0);
        % This constraint row is constant
    else
        ci = ci_basis(:,i);
        di = all_f(i);
        used = find(full(any([full(Bi') ci],2)));
        %        ci = ci(used);
        %        Bi = Bi(:,used);
        % Shift |w-center|, wtilde = w-center i.e. w=wtilde+center
        di = di + ci'*center;
        bi = bi + Bi*center;
        if isequal(abs(lastBici),abs([Bi' ci]))
             F = F + (x'*Q_xx{i}*x+bi'*x + di - r*s >= 0);
      %       F = F + (x'*Q_xx{i}*x+bi'*x + di - r*norm(full(Bi(used_rows,used)))*s >= 0);
        else
            s = sdpvar(1,1);
            if length(used)==1
                if nnz(Bi(:,used))==0
                    s = norm(full(ci(used)));
                    F = F + (x'*Q_xx{i}*x+bi'*x + di - r*s >= 0);
                else
                    F = F + (x'*Q_xx{i}*x+bi'*x + di - r*s >= 0) + (-s<=Bi(:,used)'*x+ci(used)<=s);
                end
                used_rows = 1:size(Bi,1);
                lastBici = [Bi' ci];
            else
                used_rows = find(any(full(Bi(:,used)')));
                if length(used_rows)==1 & nnz(ci(used))==0
                    % Special case norm(double vector*scalar)
                    if isequal(used_rows,lastusedrows)
                        F = F + (x'*Q_xx{i}*x+bi'*x + di - r*norm(full(Bi(used_rows,used)))*lasts >= 0)  ;
                    else
                        F = F + (x'*Q_xx{i}*x+bi'*x + di - r*norm(full(Bi(used_rows,used)))*s >= 0) + (-s <= x(used_rows)<=s);
                        lastBici = [Bi' ci];
                        lastusedrows = used_rows;
                        lasts = s;
                    end
                else
                    if nnz(Bi)==0
                        s = norm(full(ci(used)));
                        F = F + (x'*Q_xx{i}*x+bi'*x + di - r*s >= 0) ;
                    else
                        F = F + (x'*Q_xx{i}*x+bi'*x + di - r*s >= 0) + (cone(Bi(:,used)'*x+ci(used),s));
                    end
                    lastBici = [Bi' ci];
                end
            end
        end
    end
end


function Y = lp_fuse(M1, M2, zt, ap, mp)
%Y = fuse_lap(M1, M2, zt, ap, mp) image fusion with laplacian pyramid
%
%    M1 - input image A
%    M2 - input image B
%    zt - maximum decomposition level
%    ap - coefficient selection highpass (see selc.m)
%    mp - coefficient selection base image (see selb.m)
%
%    Y  - fused image

%    (Oliver Rockinger 16.08.99)
% whos
% check inputs
[z1 s1] = size(M1);
[z2 s2] = size(M2);
M1=double(M1);
M2=double(M2);
if (z1 ~= z2) | (s1 ~= s2)
  error('Input images are not of same size');
end;

% define filter
w  = [1 4 6 4 1] / 16;

% cells for selected images
E = cell(1,zt);
% tic
% loop over decomposition depth -> analysis
for i1 = 1:zt
    tic
  % calculate and store actual image size
  [z s]  = size(M1);
  zl(i1) = z; sl(i1)  = s;

  % check if image expansion necessary
  if (floor(z/2) ~= z/2), ew(1) = 1; else, ew(1) = 0; end;
  if (floor(s/2) ~= s/2), ew(2) = 1; else, ew(2) = 0; end;

  % perform expansion if necessary
  if (any(ew))
  	M1 = adb(M1,ew);
  	M2 = adb(M2,ew);
  end;

  % perform filtering
  G1 = conv2(conv2(es2(M1,2), w, 'valid'),w', 'valid');
  G2 = conv2(conv2(es2(M2,2), w, 'valid'),w', 'valid');

  % decimate, undecimate and interpolate
  M1T = conv2(conv2(es2(undec2(dec2(G1)), 2), 2*w, 'valid'),2*w', 'valid');
  M2T = conv2(conv2(es2(undec2(dec2(G2)), 2), 2*w, 'valid'),2*w', 'valid');
%   toc76

% tic
  % select coefficients and store them
  E(i1) = {selc(M1-M1T, M2-M2T, ap)};
% toc
  % decimate
%  tic
  M1 = dec2(G1);
  M2 = dec2(G2);
%   toc
% toc
% feature ('memstats')

end;
% toc
% select base coefficients of last decompostion stage
% tic
M1 = selb(M1,M2,mp);
% toc
% whos
% feature ('memstats')
% toc
% loop over decomposition depth -> synthesis
% tic
for i1 = zt:-1:1
  % undecimate and interpolate
%   tic
  M1T = conv2(conv2(es2(undec2(M1), 2), 2*w, 'valid'), 2*w', 'valid');
  % add coefficients
  M1  = M1T + E{i1};
%   toc
  % select valid image region
  M1 	= M1(1:zl(i1),1:sl(i1));
%   feature ('memstats')
% whos
end;

% feature ('memstats')
% copy image
Y = M1;
% toc


function [data g] = pre_detrend(varargin)
%
% Detrend each channel and trial using a least-squares linear fit.
% Alternately, one can center the data by removing the mean from each
% trial. See [1] for more details.
%
% Inputs:
%
%   data:           raw EEG data
%   SamplingRate:   data sampling rate
%
% Optional:     <'Name',Value> pairs
%
%     VerbosityLevel:   Verbosity level. 0 = no output, 1 = text, 2 = graphical
%                       Possible values: 0,1,2
%                       Default value  : 1
%                       Input Data Type: real number (double)
%
%     DetrendingMethod: Detrending options
%                       Linear: removes the least-squares fit of a straight line from each trial.
%                       Constant: removes the mean from each trial (centering)
%                       Possible values: 'linear','constant'
%                       Default value  : 'linear'
%                       Input Data Type: boolean
% Outputs:
%
%   data:       processed EEG data
%   g:          argument specification structure
%
% See Also: pop_pre_prepData(), pre_prepData(), detrend()
%
% Refences:
%
% [1] Mullen T (2010) The Source Information Flow Toolbox (SIFT):
%   Theoretical Handbook and User Manual. Section 6.5.1
%   Available at: http://www.sccn.ucsd.edu/wiki/Sift
%
% Author: Tim Mullen 2010, SCCN/INC, UCSD.
% Email:  tim@sccn.ucsd.edu

% This function is part of the Source Information Flow Toolbox (SIFT)
%
% 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, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

SegLenRange = [eps 10];
StepSizeRange = [eps 10];

g = arg_define(varargin, ...
    arg_norep('data',mandatory,[],'Raw data. This should be [num_chans x num_time x num_trials]'), ...
    arg_norep({'srate','SamplingRate'},mandatory,[],'Sampling Rate'), ...
    arg({'verb','VerbosityLevel'},1,{int32(0) int32(1) int32(2)}, ...
    'Verbosity level. 0 = no output, 1 = text, 2 = graphical'), ...
    arg({'method','DetrendingMethod'},{'linear'},{'linear','constant'}, ...
    'Detrending options. Linear: removes the least-squares fit of a straight line from each trial. Constant: removes the mean from each trial (centering)','type','logical'), ...
    arg_subtoggle({'piecewise','Piecewise'},[], ...
    { ...
    arg({'seglength','SegmentLength'},0.33,SegLenRange,'Length of each detrending segment (sec).'), ...
    arg({'stepsize','StepSize'},0.0825,StepSizeRange,'Step size between segment centers (sec). It is recommended to use at least 0.5*SegmentLength (50% overlap).'), ...
    },'Use piecewise detrending. Divide the data into (overlapping) segments and detrend each segment separately. Segment endpoints are merged and stitched together using a cubic spline function to minimize discontinuities at segment intersection points. This is useful for as an alternative to high-pass filtering for removing infraslow oscillations (e.g. SC drift) from the '), ...
    arg({'plot','Plot'},false,[],'Plot results for inspection.') ...
    );

% commit data to workspace
data = g.data;
g=rmfield(g,'data');

[nbchan pnts trials] = size(data);

% set sliding-window parameters
if ~g.piecewise.arg_selection
    % global detrending
    g.piecewise.seglength = pnts/g.srate;
    g.piecewise.stepsize = g.piecewise.seglength;
end
windowing_params = [g.piecewise.seglength g.piecewise.stepsize];

% apply each detrending method (centering,linear detrending, ...)
for i=1:length(g.method)

    % initialize verbose output
    m = g.method{i};
    if g.verb && g.piecewise.arg_selection,
        pre = 'Piecewise ';
        post = sprintf(' (using %0.4f sec segment length)',g.piecewise.seglength);
    else
        pre = '';
        post = '';
    end
    if g.verb && strcmpi(m,'mean')
        fprintf('%sCentering data%s...\n',pre,post);    end
    if g.verb && strcmpi(m,'linear')
        fprintf('%sDetrending data%s...\n',pre,post);   end

    if g.verb==2
        multiWaitbar('Detrending','Reset','Color',hlp_getNextUniqueColor);
    end
end

% variable intialization
fitlines = zeros(size(data));

% apply the detrending/centering
for ch=1:nbchan

    if g.verb==2
        multiWaitbar('Detrending',ch/nbchan);
    end

    if g.plot
        % return detrended data as well as fitted curves
        [data(ch,:,:) fitlines(ch,:,:)] = locdetrend_siftmod(squeeze(data(ch,:,:)),g.srate,windowing_params,m);
    else
        % return only detrended data (faster)
        data(ch,:,:) = locdetrend_siftmod(squeeze(data(ch,:,:)),g.srate,windowing_params,m);
    end

end

if g.verb==2
    multiWaitbar('Detrending','Close');
end

% plot results, if requested
if g.plot
    eegplot(data+fitlines,'srate',g.srate,'data2',fitlines,'title','Original Data');
    h = gcf;
    ax = findobj(gcf,'tag','eegaxis');
    plts = get(ax,'children');
    legend([plts(end) plts(1)],'original','best local-linear fit');
    eegplot(data,'srate',g.srate,'title','Detrended Data','children',h);
    ax = findobj(gcf,'tag','eegaxis');
    plts = get(ax,'children');
    legend(plts(end),'detrended data');
end


%% MATLAB code for blur-downsampled (BDx4) degradataion
scale = 4;
sigma = 1.6;

% generate LR image
kernelsize = ceil(sigma * 3) * 2 + 2;
kernel = fspecial('gaussian', kernelsize, sigma);
lq = imfilter(gt, kernel, 'replicate');
lq = lq(scale/2:scale:end-scale/2, scale/2:scale:end-scale/2, :);


% Copyright 2018 Marc René Schädler
%
% This file is part of the mobile hearing aid prototype project
% The the mobile hearing aid prototype project 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.
%
% The mobile hearing aid prototype project 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 the mobile hearing aid prototype project. If not, see http://www.gnu.org/licenses/.

function [gt_data, gt_freqs, gt_levels] = prescription_minimalistic(freqs, thresholds_left, thresholds_right, offset, marginfactor, rolloff, center, focus)
  gt_freqs = [177 297 500 841 1414 2378 4000 6727 11314];
  gt_levels = -10:1:110;
  reference_freqs  = [125 250 500 1000 2000 4000 8000 16000];
  reference_levels = abs(polyval([focus 0],log2(reference_freqs./1000)))+offset;
  thresholds_left_ext = [0 0 thresholds_left 0 0];
  thresholds_right_ext = [0 0 thresholds_right 0 0];
  freqs_ext = [0 50 freqs 16000 48000];
  gt_data_left = zeros(length(gt_levels),length(gt_freqs));
  gt_data_right = zeros(length(gt_levels),length(gt_freqs));
  maxgain = 40;
  maxlevel = 110;
  for i=1:length(gt_freqs)
    reference_level = interp1(reference_freqs,reference_levels,gt_freqs(i),'extrap');
    threshold_level_left = interp1(freqs_ext,thresholds_left_ext,gt_freqs(i),'extrap');
    threshold_level_right = interp1(freqs_ext,thresholds_right_ext,gt_freqs(i),'extrap');
    low_level_gain_left = max(0,threshold_level_left-reference_level);
    low_level_gain_right = max(0,threshold_level_right-reference_level);
    margin_left = marginfactor.*(center-(reference_level+low_level_gain_left));
    margin_right = marginfactor.*(center-(reference_level+low_level_gain_right));
    gt_data_left(:,i) = interp1([gt_levels(1);reference_level+margin_left;reference_level+margin_left+low_level_gain_left.*rolloff;gt_levels(end)],[low_level_gain_left;low_level_gain_left;0;0],gt_levels);
    gt_data_right(:,i) = interp1([gt_levels(1);reference_level+margin_right;reference_level+margin_right+low_level_gain_right.*rolloff;gt_levels(end)],[low_level_gain_right;low_level_gain_right;0;0],gt_levels);
  end
  gt_data = [gt_data_left.';gt_data_right.'];
  gt_data = min(maxgain,gt_data);
  gt_data = gt_data + min(0,maxlevel - (gt_data+gt_levels));
end