function x=pcmu2lin(p,s)
%PCMU2LIN Convert Mu-law PCM to linear X=(P,S)
%	lin = pcmu2lin(pcmu) where pcmu contains a vector
%	of mu-law values in the range 0 to 255.
%	No checking is performed to see that numbers are in this range.
%
%	Output values are divided by the scale factor s:
%
%		   s		Output Range
%
%		   1		+-8031	(integer values)
%		4004.2	+-2.005649 (default)
%		8031		+-1
%		8159		+-0.9843118 (+-1 nominal full scale)
%
%	The default scaling factor 4004.189931 is equal to
%	sqrt((2207^2 + 5215^2)/2) this follows ITU standard G.711.
%	The sine wave with PCM-Mu values [158 139 139 158 30 11 11 30]
%	has a mean square value of unity corresponding to 0 dBm0.

%      Copyright (C) Mike Brookes 1998
%      Version: $Id: pcmu2lin.m 713 2011-10-16 14:45:43Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   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 2 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 can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargin<2
  t=9.98953613E-4;
else
  t=4/s;
end

m=15-rem(p,16);
q=floor(p/128);
e=(127-p-m+128*q)/16;
x=(q-0.5).*(pow2(m+16.5,e)-16.5)*t;


function [cleanZ] = PatchDCTGG(Z,patchSize,noiseSD,imsize,W,invW,excludeList)
% a simple thresholding denoiser - approx. corresponds to a sprase prior
% over the marginals
if ~exist('excludeList','var')
    excludeList = [];
end

meanZ = mean(Z);
Z = bsxfun(@minus,Z,meanZ);
if (~isempty(excludeList))
    WZ = W*Z(:,excludeList);
else
    WZ = W*Z;
end

t = noiseSD*3;
WZ(abs(WZ)<t)=0;
cleanZ = Z;
if ~isempty(excludeList)
    cleanZ(:,excludeList) = invW*WZ;
else
    cleanZ = invW*WZ;
end
cleanZ = bsxfun(@plus,cleanZ,meanZ);


close all
clear all
path(path,'..\..\..\FUZZCLUST')
%the data
load motorcycle.txt
data.X = motorcycle(:,[1 2]);

[N,n]=size(data.X);

%data normalization
data = clust_normalize(data,'range');
plot(data.X(:,1),data.X(:,2),'.')
hold on
%parameters
param.c=4;
param.vis=1;
param.val=1;
%clustering
result=kmeans(data,param);
%validation
result = validity(result,data,param);
result.validity


function A = makehatch(hatch)
%MAKEHATCH Predefined hatch patterns
%  MAKEHATCH(HATCH) returns a matrix with the hatch pattern for HATCH
%   according to the following table:
%      HATCH        pattern
%     -------      ---------
%        /          right-slanted lines
%        \          left-slanted lines
%        |          vertical lines
%        -          horizontal lines
%        +          crossing vertical and horizontal lines
%        x          criss-crossing lines
%        .          single dots
%
%  See also: APPLYHATCH

%  Copyright 2009 The MathWorks, Inc.

n = 6;
A=zeros(n);
switch (hatch)
 case '/'
  A = fliplr(eye(n));
 case '\'
  A = eye(n);
 case '|'
  A(:,1) = 1;
 case '-'
  A(1,:) = 1;
 case '+'
  A(:,1) = 1;
  A(1,:) = 1;
 case 'x'
  A = eye(n) | fliplr(diag(ones(n-1,1),-1));
 case '.'
  A(1:2,1:2)=1;
 otherwise
  error(['Undefined hatch pattern "' hatch '".']);
end


%    The following is an implementation of the guided filter (GF) based
%    context enhancement (GFCE) through fusion of infrared and visible
%    images.
%    Ref: Zhiqiang Zhou et al. "Fusion of infrared and visible images for night-vision context
%    enhancement", Applied Optics, 55(23), 2016
%
%    Some of the test images were obtained at
%      http://www.imagefusion.org
%      http://www.ece.lehigh.edu/SPCRL/IF/image_fusion.htm
%
%    Zhiqiang Zhou, Beijing Institute of Technology
%    Apr. 2016
for iname =1:50

% close all;
nLevel = 4;
name = num2str(iname);
%  path_Vis = '.\image\b01_1.tif';      path_IR = '.\image\b01_2.tif';
path_Vis = ['..\..\road\ir\',name,'.jpg']; path_IR = ['..\..\road\vi\',name,'.jpg'];
% path_Vis = '.\image\Trees4906_Vis.jpg'; path_IR = '.\image\Trees4906_IR.jpg';
% path_Vis = '.\image\Octec_Vis.jpg';     path_IR = '.\image\Octec_IR.jpg';
% path_Vis = '.\image\Road_Vis.jpg';      path_IR = '.\image\Road_IR.jpg';
% path_Vis = '.\image\Kayak_Vis.jpg';     path_IR = '.\image\Kayak_IR.jpg';
% path_Vis = '.\image\Steamboat_Vis.jpg'; path_IR = '.\image\Steamboat_IR.jpg';
% path_Vis = '.\image\Trees4917_Vis.jpg'; path_IR = '.\image\Trees4917_IR.jpg';
% path_Vis = '.\image\Dune_Vis.jpg';      path_IR = '.\image\Dune_IR.jpg';

[img1, img2, para.name] = PickName(path_Vis, path_IR);
paraShow1.fig = 'Visible image';
paraShow2.fig = 'Infrared image';

%% ---------- Visibility enhancement for visible image--------------
img1E = Ehn_GF(img1);
img1 = img1E;
%% ---------- Infrared image normalization--------------
mi = min(img2(:));
ma = max(img2(:));
img2 = (img2-mi)/(ma-mi)*255;
%% ---------- Automatic parameter selection --------------
Rs = Relative_PS(img2, img1);
if Rs<0.8
    lambda = 100
else
    if Rs>1.6
        lambda = 2000
    else
        lambda = 2500*Rs - 1900
    end
end

%% ---------- Hybrid multiscale decomposition based on guided filter--------------
sigma = 2;  k = 2;
r0 = 2;     eps0 = 0.1;
l = 2;

M1 = cell(1, nLevel+1);
M1L = cell(1, nLevel+1);
M1{1} = img1/255;
M1L{1} = M1{1};
M1D = cell(1, nLevel+1);
M1E = cell(1, nLevel+1);
sigma0 = sigma;
r = r0;
eps = eps0;
for ii = 2:nLevel+1,

%     % ***using fast guided filter, which has the potential to achieve real-time performance when codes are fully optimized
%     % ***NOTE: large subsampling ratio may cause problem for fusion of some source images.
%     s = max(1, r/2); % subsampling ratio
%     M1{ii} = fastguidedfilter_md(M1{ii-1}, M1{ii-1}, r, 100^2, s);
%     M1L{ii} = fastguidedfilter_md(M1L{ii-1}, M1L{ii-1}, r, eps^2, s);

    M1{ii} = guidedfilter(M1{ii-1}, M1{ii-1}, r, 100^2);
    M1L{ii} = guidedfilter(M1L{ii-1}, M1L{ii-1}, r, eps^2);

    M1D{ii} = M1{ii-1} - M1L{ii};
    M1E{ii} = M1L{ii} - M1{ii};

    sigma0 = k*sigma0;
    r = k*r;
    eps = eps/l;
end

M2 = cell(1, nLevel+1);
M2L = cell(1, nLevel+1);
M2{1} = img2/255;
M2L{1} = M2{1};
M2D = cell(1, nLevel+1);
M2E = cell(1, nLevel+1);
sigma0 = sigma;
r = r0;
eps = eps0;
for ii = 2:nLevel+1,
%     s = max(1, r/2);
%     M2{ii} = fastguidedfilter_md(M2{ii-1}, M2{ii-1}, r, 100^2, s);
%     M2L{ii} = fastguidedfilter_md(M2L{ii-1}, M2L{ii-1}, r, eps^2, s);
    M2{ii} = guidedfilter(M2{ii-1}, M2{ii-1}, r, 100^2);
    M2L{ii} = guidedfilter(M2L{ii-1}, M2L{ii-1}, r, eps^2);

    M2D{ii} = M2{ii-1} - M2L{ii};
    M2E{ii} = M2L{ii} - M2{ii};

    sigma0 = k*sigma0;
    r = k*r;
    eps = eps/l;
end

%% ---------- Fusion --------------

for j = nLevel+1:-1:3
D2 = abs(M2E{j});
D1 = abs(M1E{j});
R = max(D2-D1, 0);
Rmax = max(R(:));
P = R/Rmax;

Cj = atan(lambda*P)/atan(lambda);

sigma_b = 2*sigma0;
if j == nLevel+1
    w = floor(3*sigma_b);
    h = fspecial('gaussian', [2*w+1, 2*w+1], sigma_b);
    lambda0 = lambda;
    Cb = atan(lambda0*P)/atan(lambda0);
    Cb = imfilter(Cb, h, 'symmetric');
    MB = Cb.*M2{nLevel+1} + (1-Cb).*M1{nLevel+1};
end

sigma_c = 1;
w = floor(3*sigma_c);
h = fspecial('gaussian', [2*w+1, 2*w+1], sigma_c);
Cj = imfilter(Cj, h, 'symmetric');

md = Cj.*M2E{j}+ (1-Cj).*M1E{j};
MB = MB + md;
md = Cj.*M2D{j}+ (1-Cj).*M1D{j};
MB = MB + md;
end

sigma_t = 1;
w = floor(3*sigma_t);
h = fspecial('gaussian', [2*w+1, 2*w+1], sigma_t);
C11 = double(abs(M1E{2}) < abs(M2E{2}));
C11 = imfilter(C11, h, 'symmetric');
md = C11.*M2E{2}+ (1-C11).*M1E{2};
MB = MB + md;
C10 = double(abs(M1D{2}) < abs(M2D{2}));
md = C10.*M2D{2}+ (1-C10).*M1D{2};
MB = MB + md;
FI = min(round(MB*275), 255);
FI = max(FI, 0);

paraShow.fig = 'Result';
ShowImageGrad(FI, paraShow,iname);

end


p560

% at zero pose
t = fkine(p560, qz)
t
q = ikine560(p560, t)
q
fkine(p560, q)
ikine560(p560, t, 'r')
ikine560(p560, t, 'rn')

ikine(p560, t)

% at nominal pose
qn
t = fkine(p560, qn)
t
%q = ikine560(p560, t)
q
fkine(p560, q)
ikine(p560, t, [0, 0.7, 3, 0, 0.7, 0])

% along trajectory
[q,qd,qdd] = jtraj(qz, qr, 20)
fkine(p560, q)

t1 = fkine(p560, qz)
t2 = fkine(p560, qr)
traj = ctraj(t1, t2, 5)
ikine(p560, traj)


function value = r4_gamma ( x )

%*****************************************************************************80
%
%% R4_GAMMA evaluates the gamma function of an R4 argument.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 September 2011
%
%  Author:
%
%    Original FORTRAN77 version by Wayne Fullerton.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Wayne Fullerton,
%    Portable Special Function Routines,
%    in Portability of Numerical Software,
%    edited by Wayne Cowell,
%    Lecture Notes in Computer Science, Volume 57,
%    Springer 1977,
%    ISBN: 978-3-540-08446-4,
%    LC: QA297.W65.
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real VALUE, the gamma function of X.
%
  persistent dxrel
  persistent gcs
  persistent ngcs
  persistent sq2pil
  persistent xmax
  persistent xmin
  persistent xsml

  sq2pil = 0.91893853320467274;

  if ( isempty ( ngcs ) )

    gcs = [ ...
      0.008571195590989331, ...
      0.004415381324841007, ...
      0.05685043681599363, ...
     -0.004219835396418561, ...
      0.001326808181212460, ...
     -0.0001893024529798880, ...
      0.0000360692532744124, ...
     -0.0000060567619044608, ...
      0.0000010558295463022, ...
     -0.0000001811967365542, ...
      0.0000000311772496471, ...
     -0.0000000053542196390, ...
      0.0000000009193275519, ...
     -0.0000000001577941280, ...
      0.0000000000270798062, ...
     -0.0000000000046468186, ...
      0.0000000000007973350, ...
     -0.0000000000001368078, ...
      0.0000000000000234731, ...
     -0.0000000000000040274, ...
      0.0000000000000006910, ...
     -0.0000000000000001185, ...
      0.0000000000000000203 ]';

    ngcs = r4_inits ( gcs, 23, 0.1 * r4_mach ( 3 ) );
    [ xmin, xmax ] = r4_gaml ( );
    xsml = exp ( max ( log ( r4_mach ( 1 ) ), ...
      - log ( r4_mach ( 2 ) ) ) + 0.01 );
    dxrel = sqrt ( r4_mach ( 4 ) );

  end

  y = abs ( x );

  if ( y <= 10.0 )

    n = r4_aint ( x );
    if ( x < 0.0 )
      n = n - 1;
    end
    y = x - n;
    n = n - 1;
    value = 0.9375 + r4_csevl ( 2.0 * y - 1.0, gcs, ngcs );

    if ( n == 0 )

      return

    elseif ( n < 0 )

      n = - n;

      if ( x == 0.0 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
        fprintf ( 1, '  X is 0.\n' );
        error ( 'R4_GAMMA - Fatal error!' )
      end

      if ( x < 0.0 && x + n - 2 == 0.0 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
        fprintf ( 1, '  X is a negative integer.\n' );
        error ( 'R4_GAMMA - Fatal error!' )
      end

      if ( x < - 0.5 && ...
        abs ( ( x - r4_aint ( x - 0.5 ) ) / x ) < dxrel )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Warning!\n' );
        fprintf ( 1, '  X too near a negative integer,\n' );
        fprintf ( 1, '  answer is half precision.\n' );
      end

      if ( y < xsml )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
        fprintf ( 1, '  X is so close to zero that Gamma overflows.\n' );
        error ( 'R4_GAMMA - Fatal error!' )
      end

      for i = 1 : n
        value = value / ( x + i - 1 );
      end

    elseif ( n == 0 )

    else

      for i = 1 : n
        value = ( y + i ) * value;
      end

    end

  else

    if ( xmax < x )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
      fprintf ( 1, '  X so big that Gamma overflows.\n' );
      error ( 'R4_GAMMA - Fatal error!' )
    end
%
%  Underflow.
%
    if ( x < xmin )
      value = 0.0;
      return
    end

    value = exp ( ( y - 0.5 ) * log ( y ) - y + sq2pil + r4_lgmc ( y ) );

    if ( 0.0 < x )
      return
    end

    if ( abs ( ( x - r4_aint ( x - 0.5 ) ) / x ) < dxrel )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'R4_GAMMA - Warning!\n' );
      fprintf ( 1, '  X too near a negative integer,\n' );
      fprintf ( 1, '  answer is half precision.\n' );
    end

    sinpiy = sin ( pi * y );

    if ( sinpiy == 0.0 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
      fprintf ( 1, '  X is a negative integer.\n' );
      error ( 'R4_GAMMA - Fatal error!' )
    end

    value = - pi / ( y * sinpiy * value );

  end

  return
end


%% Example Scene
%
% This script demonstrates using a combination of functions to create
% terrain, add a sky, set some lighting options, and provide the ability to
% rotate around the figure. It uses several of MATLAB's 3D graphics
% commands, including patches, lighting, camera positioning, and
% projection. If any of these are unfamiliar, the documentation covers them
% well. MATLAB can produce much more than simple plots.
%
% This script is likely to take between 3 and 30 seconds to complete on
% most computers.
%
% Tucker McClure
% Copyright 2012, The MathWorks, Inc.

%%
% Create or clear a figure for the rendering.
figure(1);
clf();

%% Land and Sea

% Create the terrain height map.
[~, ~, ~, hm, xm, ym] = generate_terrain(7, 513, 0, 0.1);

% Generate appropriate colors.
cm = generate_terrain_colors(hm);

% Flatten the oceans.
hmp = max(hm, 0);

% Draw the land and calculate its normal vectors.
h_land = patch(surf2patch(xm, ym, hmp, cm));
[nx, ny, nz] = surfnorm(hmp);
land_normals = [nx(:), ny(:), nz(:)];

% Set it's material properties for interpolated colors and appropriate
% lighting.
set(h_land, 'VertexNormals',    land_normals, ...
            'DiffuseStrength',  0.8, ...      % Reacts to light direction
            'SpecularStrength', 0, ...        % Not shiny
            'AmbientStrength',  0.3, ...      % Reacts to ambient light
            'BackFaceLighting', 'unlit');     % Don't illuminate reverse

% Add a black backdrop beneath the land. Sometimes a vertex seems to miss
% its position slightly, and sky colors creep through, and that's weird.
patch('Faces',           [1 2 3 4], ...
      'Vertices',        [-1 -1 -0.01; ...
                           1 -1 -0.01; ...
                           1  1 -0.01; ...
                          -1  1 -0.01], ...
      'FaceVertexCData', 0.25*ones(4, 3));

%% Sky

% Draw a random time of day between sunrise and sunset. Get the
% corresponding light color. The sky is always the color of the sun at noon
% (and is then affected by the sun color at the current time).
current_time = 0.24 + 0.52 * rand();
sun_color    = sun_tones(current_time);
sky_color    = sun_tones(0.5);

% Create the sky patch by scaling a sphere. Note that the nothing in the
% scene can be rendered outside of [-100, 100] on any axis due to a
% documented rendering bug. Therefore, the sphere will be scaleld up to
% 99, which is plenty far away since the terrain is limited to [-1, 1].
[xs, ys, zs] = sphere(16);
sky_scale = 99;
sky_patch = surf2patch(sky_scale*xs, sky_scale*ys, sky_scale*zs, ...
                       repmat(reshape(sky_color, [1 1 3]), [17 17 1]));
h_sky = patch(sky_patch);

% Set appropriate lighting options for the sky.
set(h_sky, 'DiffuseStrength',  0.3, ...
           'SpecularStrength', 0, ...
           'AmbientStrength',  1, ...
           'BackFaceLighting', 'unlit');

% Vertex normals are the opposite of what I expect. Reverse them.
set(h_sky,  'VertexNormals', -get(h_sky, 'VertexNormals'));

%% Sun

% Create a light for the sun.
h_light = lightangle(90, 360*(current_time - 0.25));

% Set the light's color.
set(h_light, 'Color', sun_color);

% Set the ambient color used in the scene.
set(gca(), 'AmbientLightColor', sun_color);

% Use decent lighting.
lighting gouraud;

%% Axes and Global Settings

% Set axes options.
camera_target   = [0 0 mean(hmp(:)) + 0.5*std(hmp(:))];
camera_position = camera_target + [1.15 0 0.5];
set(gca, 'DataAspectRatio', [1 1 1], ...
         'Visible',         'off', ...
         'Projection',      'Perspective', ...
         'Position',        [0 0 1 1], ...
         'CameraTarget',    camera_target, ...
         'CameraViewAngle', 45, ...
         'CameraUpVector',  [0 0 1], ...
         'CameraPosition',  camera_position, ...
         'XLim',            [-100 100], ...
         'YLim',            [-100 100], ...
         'ZLim',            [-100 100]);
camorbit(360*rand(), 0);

% Patches should have no edges and interpolated face colors.
shading interp;

% Force the drawing.
drawnow();

% Add FigureRotator to allow the user to rotate around the middle of the
% scene and zoom in and out using a mouse. This is available in the extras
% zip file or from File Exchange. Use |unzip terrain_generation_extras.zip|
% in this directory to extract FigureRotator along with an example file.
if exist('FigureRotator', 'class');
    f = FigureRotator(gca());
end


function [G, pixels, patches] = gsp_patch_graph(img, param)
%GSP_PATCH_GRAPH Create a graph by NN patches of an image
%   Usage :  G = compute_patch_graph( img );
%            [G, f] = gsp_patch_graph( img, param );
%            [G, f, patches] = gsp_patch_graph( img, param );
%
%   Input parameters:
%       img         : Input image (unknown pixels marked as NaN)
%       param       : Structure of optional parameters
%
%   Output parameters:
%       G           : Resulting graph
%       f           : Image signal
%       patches     : Patches
%
%   'compute_patch_graph( path , param )' creates a graph between pixels in
%   an image by connecting them using the euclidean distance between
%   patches around the pixels
%
%   Additional parameters
%   ---------------------
%
%   * *param.patch_size*      : int     the patch size in pixels (odd)
%   * *param.scale*           : float   to rescale the input image
%   * *param.rho*             : float   spatial constraint
%   * *use_incomplete_patch*  : boolean use incomplete patch for the graph construction
%   * *param.nnparam*         : struct  parameters for graph construction
%

% Author: Johan Paratte, Michael Defferrard, Nathanael Perraudin
% Date: November 2014
%

    if nargin < 2
    % Define parameters
        param = {};
    end

    if ~isfield(param, 'patch_size'), param.patch_size = 5; end
    if ~isfield(param, 'rho'), param.rho = 0.001; end
    if ~isfield(param, 'use_incomplete_patch'), param.use_incomplete_patch = 0; end
    if ~isfield(param, 'nnparam')
       param.nnparam = {};
       param.nnparam.center = 0;
       param.nnparam.resize = 0;
       param.nnparam.k = 10;
       param.nnparam.use_l1 = 0;
       param.nnparam.use_flann = 1;
    end

    if (mod(param.patch_size, 2) == 0)
        disp('Patch size must be odd, converting to closest odd number');
        param.patch_size = param.patch_size + 1;
    end

%     if length(size(img)) > 2
%        img = rgb2gray(img);
%     end

    %Extract patches
    [oheight, owidth,Nc] = size(img);

    psize = param.patch_size;

    %Parameters
    if isfield(param, 'scale')
        img = imresize(img, param.scale);
    end

    margin = floor(psize / 2);

    dim = psize*psize;
    %height = (oheight - 2*margin);
    %width = (owidth - 2*margin);

    %Expand the image to compensate the margin
    h = oheight;
    w = owidth;
    new_img = zeros(h + 2*margin, w + 2*margin,Nc);
    %Copy image
    new_img(1+margin:end-margin, 1+margin:end-margin,:) = img;
    %Four lines
    new_img(1:margin, 1+margin:end-margin,:) = img(margin:-1:1, :,:);
    new_img(1+margin:end-margin, 1:margin,:) = img(:, margin:-1:1,:);
    new_img(end-margin:end, 1+margin:end-margin,:) = img(end:-1:end-margin, :,:);
    new_img(1+margin:end-margin, end-margin:end,:) = img(:,end:-1:end-margin,:);
    %Four corners
    new_img(1:margin, 1:margin,:) = img(margin:-1:1, margin:-1:1,:);
    new_img(1:margin, end-margin:end,:) = img(margin:-1:1, end:-1:end-margin,:);
    new_img(end-margin:end, 1:margin,:) = img(end:-1:end-margin, margin:-1:1,:);
    new_img(end-margin:end, end:-1:end-margin,:) = img(end:-1:end-margin, end:-1:end-margin,:);

    % Signals on the graph.
    patches = zeros(h*w, dim*Nc+2);
    pixels  = double(reshape(img, h*w, Nc)); % zeros(h*w, 1);
    coords  = zeros(h*w, 2);  % gsp_plot_signal takes [x,y]
    coords(:,2) = repmat((h:-1:1).', w, 1);
    coords(:,1) = reshape(repmat((1:+1:w), h, 1), [], 1);

    % Pre-allocation.
    nUnknown = sum(sum(img(:,:,1)<0)) * 2;
    unknowns = zeros(nUnknown, 1);
    iUnknown = 0;

    count = 1;

    % For speed improvement, one of the for loop can probably be removed
    % here
    for w = 1:owidth
       for h = 1:oheight
            patches(count, 1:Nc*dim) = reshape(new_img(h:h+psize-1, w:w+psize-1,:), 1, Nc*dim);
            patches(count, Nc*dim+1:end) = [param.rho*w; param.rho*h];
            count = count + 1;
        end
    end

    fprintf('Compute graph with %d vertices\n', size(patches,1));

    if param.use_incomplete_patch

        G = gsp_rmse_mv_graph(patches, param.nnparam);
    else
        % Ignore patches which contain unknown pixel values.
        % We do not want them to be connected with known patches.
        clearedPatches = patches;

        for count = 1:size(clearedPatches,1)
            if sum(isnan(clearedPatches(count,:)))
                clearedPatches(count,:) = -1e3;
                % List of unknown patches.
                iUnknown = iUnknown + 1;
                unknowns(iUnknown) = count;
            end
        end

        G = gsp_nn_graph(clearedPatches, param.nnparam);

        % Disconnect unknown patches.
        unknowns = unknowns(1:iUnknown);
        G.W(unknowns,:) = 0;
        G.W(:,unknowns) = 0;

        % Update G.A, G.d and G.Ne.
        G = gsp_graph_default_parameters(G);
    end

    % These are coordinates in the high dimensional patch space. We prefer
    % to visualize the graph in the 2D image space.
%     patches = G.coords;
    G.coords = coords;
    G.plotting.limits = [1,w,1,h];

end


function M=ImpliedExpRets(S,w)

M_=S*w;

s=sqrt(mean(diag(S)));
M=M_/mean(M_)*.5*s;


function [f] = elec_ellipse_fit_optim(r, X, Y, Z, xo, yo, zo)

% elec_ellipse_fit_optim - Optimization for elec_ellipse_fit.m
%
% Called from elec_ellipse_fit.m
%

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

% Licence:  GNU GPL, no implied or express warranties
% History:  02/2002, Darren.Weber_at_radiology.ucsf.edu
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% r is a 3x1 vector of radius values for each x,y,z axis component of
% ellipse
%
% equation of ellipsoid with center (xo,yo,zo) and radius for each axis (x,y,z) = (a,b,c):
% (( x - xo )^2 / a^2) + (( y - yo )^2 / b^2) + (( z - zo )^2 / c^2) = 1
%
% This function below creates a scalar value to
% return to the fminsearch function in elec_ellipse_fit.

E = ( (X-xo).^2 )/r(1).^2 + ((Y-yo).^2)/r(2).^2 + ((Z-zo).^2)/r(3).^2  - 1;

f = sum( E .* E );  % sum of squares returned

return


function fx1 = p09_fx1 ( x )

%*****************************************************************************80
%
%% P09_FX1 evaluates the derivative of the function for problem 9.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 May 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the abscissa.
%
%    Output, real FX1, the first derivative of the function at X.
%
  x2 = x - 6.25;

  if ( x2 < - 0.25 )
    fx1 = 0.75;
  elseif ( x2 < 0.25 )
    fx1 = 2.0;
  else
    fx1 = 0.75;
  end

  return
end


function [regions, thresholds, maxSig] = imMultiOtsuThreshold(img, nClasses, varargin)
% Multilevel Thresholding using Otsu Method.
%
%   CLASSES = imMultiOtsuThreshold(IMG, NC)
%   Computes a segmentation of the input grayscale image IMG into NC
%   classes. The number of classes must be comprised between 2 and 5.
%
%   [CLASSES, THRESHOLDS] = imMultiOtsuThreshold(IMG, NC)
%   Also returns the list of threshold. The number of threshold values is
%   the number of classes minus one.
%
%   Example
%     % segment cameraman image into three classes
%     img = imread('cameraman.tif');
%     [classes, threshs] = imMultiOtsuThreshold(img, 3);
%     rgb = label2rgb(classes, 'jet', [1 0 0], 'shuffle');
%     figure; imshow(rgb);
%     % also displays histogram with threshold levels
%     figure; imHistogram(img);
%     hold on;
%     for i = 1:2
%        plot(threshs([i i]), [0 1800], 'color', 'r', 'linewidth', 2);
%     end
%
%   References
%   * Ping-Sung Liao, Tse-Sheng Chen, Pau-Choo Chung (2001). "A Fast
%   Algorithm for Multilevel Thresholding". Journal of Information Science
%   and Engineering, Vol. 17 No. 5, pp. 713-727.
%   https://jise.iis.sinica.edu.tw/JISESearch/pages/View/PaperView.jsf?keyId=86_1302#
%   * https://imagej.net/Multi_Otsu_Threshold
%
%   See also
%     imOtsuThreshold, imHistogram, imMaxEntropyThreshold
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% INRAE - BIA Research Unit - BIBS Platform (Nantes)
% Created: 2021-01-29,    using Matlab 9.8.0.1323502 (R2020a)
% Copyright 2021 INRAE.

%% Input arguments

if ~isa(img, 'uint8')
    error('Requires a grayscale uint8 image as first input');
end

if nClasses < 2 || nClasses > 5
    error('The number of classes must be comprised between 2 and 5.');
end

%% Initialisations

% compute histogram, and convert into probability density
[h, levels] = imHistogram(img, varargin{:});
h = h / sum(h);

% number of gray levels
nLevels = length(levels);

Puv = zeros(nLevels, nLevels);
Suv = zeros(nLevels, nLevels);
Huv = zeros(nLevels, nLevels);

% initialize diagonal terms
for i = 1:nLevels
    Puv(i, i) = h(i);
    Suv(i, i) = h(i) * i;
end

% initialize first rows
for i = 2:nLevels
    Puv(1, i) = Puv(1, i-1) + h(i);
    Suv(1, i) = Suv(1, i-1) + i*h(i);
end
% initialize the rest of the matrices
for u = 2:nLevels
    for v = u+1:nLevels
        Puv(u, v) = Puv(1, v) - Puv(1, u-1);
        Suv(u, v) = Suv(1, v) - Suv(1, u-1);
    end
end

% now calculate Huv
for u = 1:nLevels
    for v = u+1:nLevels
        if Puv(u,v) > 0
            Huv(u,v) = Suv(u,v) * Suv(u,v) / Puv(u,v);
        end
    end
end

%% Main processing

% create array for threshold values (first one is zeros, last one is inf)
thresholds = zeros(nClasses+1, 1);
thresholds(end) = inf;

% iterate over all possible combinations
maxSig = 0.0;
switch nClasses
    case 2
        % two classes -> only need to find second threshold value
        for i = 1:nLevels-1
            Sq = Huv(1,i) + Huv(i+1, end);
            if Sq >= maxSig
                thresholds(2) = i;
                maxSig = Sq;
            end
        end

    case 3
        % three classes
        for i = 1:nLevels-2
            for j = i+1:nLevels-1
                Sq = Huv(1,i) + Huv(i+1, j) + Huv(j+1, end);
                if Sq >= maxSig
                    thresholds(2) = i;
                    thresholds(3) = j;
                    maxSig = Sq;
                end
            end
        end

    case 4
        % four classes
        for i = 1:nLevels-3
            for j = i+1:nLevels-2
                for k = j+1:nLevels-1
                    Sq = Huv(1,i) + Huv(i+1, j) + Huv(j+1, k) + Huv(k+1, end);
                    if Sq >= maxSig
                        thresholds(2) = i;
                        thresholds(3) = j;
                        thresholds(4) = k;
                        maxSig = Sq;
                    end
                end
            end
        end

    case 5
        % five classes
        for i = 1:nLevels-3
            for j = i+1:nLevels-2
                for k = j+1:nLevels-1
                    for m = k+1:nLevels-1
                        Sq = Huv(1,i) + Huv(i+1, j) + Huv(j+1, k) + Huv(k+1, m) + Huv(m+1, end);
                        if Sq >= maxSig
                            thresholds(2) = i;
                            thresholds(3) = j;
                            thresholds(4) = k;
                            thresholds(5) = m;
                            maxSig = Sq;
                        end
                    end
                end
            end
        end

    otherwise
        error('Can not manage %d number of classes', nClasses);
end

%% Create region image

regions = zeros(size(img), 'uint8');
for i = 1:nClasses
    inds = img >= thresholds(i) & img < thresholds(i+1);
    regions(inds) = i;
end


function linplus_test0196 ( )

%*****************************************************************************80
%
%%  TEST0196 tests R8VEC_TO_R8GE, R8GE_TO_R8VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 March 2009
%
%  Author:
%
%    John Burkardt
%
  m = 4;
  n = 6;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST0196\n' );
  fprintf ( 1, '  For a general matrix,\n' );
  fprintf ( 1, '  R8VEC_TO_R8GE converts a real vector to a R8GE matrix.\n' );
  fprintf ( 1, '  R8GE_TO_R8VEC converts a R8GE matrix to a real vector.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Matrix rows M =    %d\n', m );
  fprintf ( 1, '  Matrix columns N = %d\n', n );

  a = r8ge_indicator ( m, n );

  r8ge_print ( m, n, a, '  The R8GE indicator matrix:' );

  x = r8ge_to_r8vec ( m, n, a );

  k = 0;
  for j = 1 : n
    for i = 1 : m
      k = k + 1;
      fprintf ( 1, '%4d  %4d  %4d  %14f\n', i, j, k, x(k) );
    end
  end

  a = r8vec_to_r8ge ( m, n, x );

  r8ge_print ( m, n, a, '  The recovered R8GE indicator matrix:' );

  return
end


% clear; close all; clc;

function ani_slider
fs = 200;
t = 0:1/fs:5-1/fs;
f = 1;
x = sin(2*pi*1*t);

figure;
set(gcf,'position',[500 500 640 480]);
figsize = get(gcf,'position');
h = plot(t,x);

SliderH = uicontrol('style','slider','position',[70 6 512 20],'min',1,'max',5,'value',1,'callback',@cbfcn);

    function cbfcn(src, event)
       f = SliderH.Value ;
       x = sin(2*pi*f*t);
       h = plot(t,x);
    end
end


function gsp()
% GSP General Piecewise Spline Interpolation
%
% GSP is a graphical user interface which takes x and y points as inputs, along with
% the order m, then outputs mth order splines between each of the x points. In most
% cases additional constraints are to be entered as well.
%
% Example:
%
% Input:
%
% x points : [1 2 3 4]
% y points : [2 7 -1 5]
% Order    : 2
% *One Additional Constraint is Required*
% f''(1) = 0
%
% Output:
% Polynomials:
%   0             5            -3
% -13            57           -55
%  27          -183           305
%
% In the Range:
% 1  2
% 2  3
% 3  4
%
% This means the following:
%
% for 1 < x < 2   y = 0*x^2 + 5*x - 3
% for 2 < x < 3   y = -13*x^2 + 57*x - 55
% for 3 < x < 4   y = 27*x^2 - 183*x + 305
%
% You can obtain the mentioned forms using poly2sym (requires Symbolic Math Toolbox).
%
% If you want to delete constraints, put its values as '*'. For more help and examples,
% see the pictures accompanied in the zip file. An optional feature can be
% accesessed if the function MQUAKE is present. mquake.m can be found here:
% <http://www.mathworks.com/matlabcentral/fileexchange/22816>
%
% To launch the GUI, type gsp in the command window with this file in the current directory.
% Alternatively, you can choose Debug -> Run from this editor window, or press F5.
%
%
% Husam Aldahiyat, 2009
% numandina@gmail.com
%
global aA

%% figure and uicontrols
figure('units','normalized','position',[.2 .2 .65 .65],'menubar','none','numbertitle','off','color','w','name','General Splines')
axes('position',[.35 .1 .5 .5])
ed1=uicontrol('style','edit','units','normalized','position',[.025 .875 .1 .05],'backgroundcolor','w');
uicontrol('style','text','units','normalized','position',[.025 .94 .1 .025],'backgroundcolor','w','string','x Points');
ed2=uicontrol('style','edit','units','normalized','position',[.025 .75 .1 .05],'backgroundcolor','w');
uicontrol('style','text','units','normalized','position',[.025 .81 .1 .025],'backgroundcolor','w','string','Y Points');
px=uicontrol('style','listbox','units','normalized','position',[.2 .75 .1 .2],'max',2,'backgroundcolor','w',...
	'string',{'Example 1';'Example 2';'Example 3';'Example 4';'Example 5';'Example 6'},'callback',@pn);
ed3=uicontrol('style','edit','units','normalized','position',[.045 .63 .05 .05],'backgroundcolor','w','callback',@cond);
uicontrol('style','text','units','normalized','position',[.025 .69 .1 .025],'backgroundcolor','w','string','Spline Order');
err=uicontrol('style','text','foregroundcolor','r','units','normalized','position',[.025 .55 .22 .05],'backgroundcolor','w',...
	'horizontalalignment','left');
uicontrol('style','pushbutton','units','normalized','position',[.15 .63 .05 .05],'backgroundcolor','w','callback',@go,'string','Solve');
pv=uicontrol('style','pushbutton','units','normalized','position',[.22 .63 .075 .05],'backgroundcolor','w','callback',@dv,...
	'string','Continuity','visible','off');
thih=uicontrol('style','edit','units','normalized','position',[.025 .025 .125 .525],'backgroundcolor','w','max',2,'string','',...
	'horizontalalignment','right','fontsize',13,'fontname','calibri');
edc=uicontrol('style','edit','units','normalized','position',[.15 .025 .075 .525],'backgroundcolor','w','max',2,...
	'horizontalalignment','left','fontsize',13,'fontname','calibri','string','');
Ap=uicontrol('style','listbox','units','normalized','position',[.35 .675 .5 .25],'backgroundcolor','w','max',2,'fontname','courier',...
	'callback',@chv);
Ac=uicontrol('style','listbox','units','normalized','position',[.85 .675 .125 .25],'backgroundcolor','w','max',2,'fontname','courier');
uicontrol('style','text','units','normalized','position',[.35 .935 .5 .025],'backgroundcolor','w','max',2,'string','Spline Polynomials');
uicontrol('style','text','units','normalized','position',[.85 .935 .12 .025],'backgroundcolor','w','max',2,'string','For x in the range');

	function cond(varargin)
		m=str2double(get(ed3,'string'));
		if m>1
			x=str2num(get(ed1,'string')); %#ok
			if isempty(x)
				set(err,'string','Please give values for x')
				return
			end
			set(err,'string',sprintf('%d Additional Condition(s) Needed',m-1))
			trip=cell(m*2,1);
			for k1=1:m
				koi=repmat('''',1,k1);
				trip{k1}=['f ',koi,'(',num2str(x(1)),') = '];
				trip{k1+m}=['f ',koi,'(',num2str(x(end)),') = '];
			end
			set(thih,'string',trip);
		else
			set(err,'string','No Additional Constraints Required');
			set(edc,'string','')
			set(thih,'string','')
		end
		if m>1
			set(edc,'string',repmat('*',m*2,1))
		end
	end

	function pn(varargin)
		switch get(px,'value')
			case 1
				 set(ed1,'string','0 10')
				 set(ed2,'string','0 0')
				 set(ed3,'string','2')
				 cond
				 set(err,'string','')
				 set(edc,'string',['5';'*';'*';'*'])
			case 2
				 set(ed1,'string','0 1 2')
				 set(ed2,'string','0 1 0')
				 set(ed3,'string','3')
				 cond
				 set(err,'string','')
				 set(edc,'string',['0';'*';'*';'0';'*';'*'])
			case 3
				 set(ed1,'string','0 1 2')
				 set(ed2,'string','0 1 0')
				 set(ed3,'string','5')
				 cond
				 set(err,'string','')
				 set(edc,'string',['0';'0';'*';'*';'*';'0';'0';'*';'*';'*'])
			case 4
				 set(ed1,'string','1 2 3 4 7')
				 set(ed2,'string','2 -4 0 3 0')
				 set(ed3,'string','3')
				 cond
				 set(err,'string','')
				 set(edc,'string',['*';'0';'*';'*';'0';'*'])
			case 5
				 set(ed1,'string','1 2 4 6 8 10')
				 set(ed2,'string','2 4 -2 3 1 0')
				 set(ed3,'string','5')
				 cond
				 set(err,'string','')
				 set(edc,'string',strvcat('5','0','*','*','*','-4','3','*','*','*')) %#ok
			case 6
				 set(ed1,'string','1 2 4 6 8 10')
				 set(ed2,'string','2 4 -2 3 1 0')
				 set(ed3,'string','5')
				 cond
				 set(err,'string','')
				 set(edc,'string',strvcat('-5','0','*','*','*','4','3','*','*','*')) %#ok
		end
	end

%% Solution

	function go(varargin)
		set(pv,'visible','off')
		x=str2num(get(ed1,'string')); %#ok
		y=str2num(get(ed2,'string')); %#ok
		if length(y)~=length(x)
			set(err,'string','Points are not of equal lengths')
			return
		end
		if any(find(abs(sort(x)-x)>1e-10))
			set(err,'string','x Points need to be ascending')
			return
		end
		if length(unique(x))<length(x)
			set(err,'string','Repeated x points found')
			return
		end
		m=str2double(get(ed3,'string'));
		n=length(x)-1; % number of splines
		g=fliplr(0:m);
		DAT=zeros((m+1)*n);
		B=zeros(n*(1+m),1);
		B(1:n+1)=y;
		S=zeros(n,m+1);
		for k=1:n
			DAT(k,k+m*k-m:k+m*k)=x(k).^g;
		end
		DAT(k+1,k+m*k-m:k+m*k)=x(k+1).^g;
		k=k+2;
		poln=ones(1,m+1);
		for k2=1:m
			pol=[poln,zeros(1,(k2-1))];
			for p=1:n-1
				DAT(k+p+k2*n-k2-n,p*m+p-m:p*m+p+m+1)=...
					repmat(pol,1,2).*repmat(x(p+1),1,(m+1)*2).^repmat(g-(k2-1),1,2).*[ones(1,m+1),-ones(1,m+1)];
			end
			poln=polyder(poln);
		end
		aa=(get(edc,'string'));
		if m>1
			con=find(~ismember(1:m*2,findstr(aa(:,1)','*'))==1);
			if length(con)>m-1
				set(err,'string','Too many constraints entered')
				return
			end
			if isempty(con)
				set(err,'string','Too few constraints entered')
				return
			end
			for lp=1:m-1
				poln=ones(1,m+1);
				wo=con(1);
				if wo>m
					con(1)=con(1)-m;
				end
				for h1=1:con(1)
					poln=polyder(poln);
				end
				if wo>m
					DAT(end-(m-1-lp),end-m:end)=repmat(x(end),1,m+1).^(g-con(1)).*[poln,zeros(1,m+1-length(poln))];
					B(end-(m-1-lp))=str2double(aa(wo,:));
				end
				if wo<=m
					DAT(end-(m-1-lp),1:m+1)=[poln,zeros(1,m+1-length(poln))].*repmat(x(1),1,m+1).^(g-con(1));
					B(end-(m-1-lp))=str2double(aa(con(1),:));
				end
				con(1)=[];
			end
		end
		DAT(isnan(DAT))=0;
		s=DAT\B;
		C=zeros(n,2);
		for k=1:n
			S(k,:)=s(k*(m+1)-m:k*(m+1));
			C(k,:)=x(k:k+1);
		end
		set(err,'string','')

%% Displaying Results

		set(Ap,'string',num2str(S))
		set(Ac,'string',num2str(C))
		cla reset
		hold on
		st=[1 0 0;0 1 0];
		for k=1:n
			t=linspace(C(k,1),C(k,2),100);
			f=polyval(S(k,:),t);
			aA(k)=plot(t,f);
			set(findobj('color','b'),'color',st(mod(k,2)+1,:),'linewidth',2)
		end
		plot(x,y,'.')
		set(findobj('marker','.'),'markersize',10,'color','k')
		xlabel('x')
		ylabel('y')
		xlim([x(1)-1 x(end)+1])
		h=axis;
		if h(3)>min(y)-1
			h(3)=min(y)-1;
		end
		if h(4)<max(y)+1
			h(4)=max(y)+1;
		end
		axis(h)
		set(pv,'visible','on')
	end

	function dv(varargin)
		S=str2num(get(Ap,'string')); %#ok
		C=str2num(get(Ac,'string')); %#ok
		st=[1 0 0;0 1 0];
		m=str2double(get(ed3,'string'));
		n=length(str2num(get(ed1,'string')))-1; %#ok
		figure('color','w','menubar','none','numbertitle','off','name','Continuity')
		for k2=1:m
			for g=1:n
				S(g,:)=[zeros(m+1-length([polyder(S(g,1:end-k2+1)),zeros(1,k2)])),polyder(S(g,1:end-k2+1)),zeros(1,k2)];
			end
			subplot(ceil(m/2),ceil(m/ceil(m/2)),k2)
			hold on
			for k=1:n
				t=linspace(C(k,1),C(k,2),100);
				f=polyval(S(k,1:end-k2),t);
				plot(t,f);
				set(findobj('color','b'),'color',st(mod(k,2)+1,:),'linewidth',2)
			end
			title(sprintf('Derivate Order %d',k2))
		end
	end

	function chv(varargin)
		h=axis;
		try
			mquake(aA(get(Ap,'value')),(h(2)+h(4))/4,.5,1)
		catch
		end
	end

end


% CHARACTER RECOGNITION SYSTEM

function CR()
clear workspace
clear
% Input Data Preparation
x=65;
for i=1:4
al=char(x);
fl=strcat(al,'.bmp');
inp(i,:)=roworder(fl);
x=x+1;
end
inp=inp';
inp=double(inp);
%Output Data Preparation
for i=0:3
    x=dec2bin(i,2);
    for j=1:2
        y(j)=str2num(x(j));
    end
    out(i+1,:)=y;
end
out=out';
% Network Creation
     network=newff([zeros(size(inp,1),1) ones(size(inp,1),1)],[7 2],{'logsig','logsig'});
  %   network=init(network);

network.iw{1}=dlmread('layer1.txt');
network.b{1}=dlmread('layer1b.txt');
network.lw{2}=dlmread('layer2.txt');
network.b{2}=dlmread('layer2b.txt');

% Network Training
network.performFcn = 'sse';
network.trainParam.epochs = 500;
network=train(network,inp,out);
% Network Testing
  display('Network Testing - With Boldness (Arial)');
  D=sim(network,inp);
  D=round(D);
  D
 % Testing with new data
x=65;
for i=1:4
al=char(x);
fl=strcat(al,'1.bmp');
in(i,:)=roworder(fl);
x=x+1;
end
in=in';
in=double(in);
display('Testing with New Data - Without Boldness (Arial)');
E=sim(network,in);
E=round(E);
E
%Testing with new data
 x=65;
for i=1:4
al=char(x);
fl=strcat(al,'2.bmp');
in1(i,:)=roworder(fl);
x=x+1;
end
in1=in1';
in1=double(in1);
display('Testing with New Data - With Boldness (Tahoma)');
F=sim(network,in1);
F=round(F);
F
end

function inprs=roworder(fl)
inpdt=imread(fl);
inprs=reshape(inpdt',1,size(inpdt,1)*size(inpdt,2));
end


% POP_NEWTIMEF - Returns estimates and plots of event-related (log) spectral
%           perturbation (ERSP) and inter-trial coherence (ITC) phenomena
%           timelocked to a set of single-channel input epochs
%
% Usage:
%   >> pop_newtimef(EEG, typeplot);          % pop_up window
%   >> pop_newtimef(EEG, typeplot, lastcom); % pop_up window
%   >> pop_newtimef(EEG, typeplot, channel); % do not pop-up window
%   >> pop_newtimef(EEG, typeproc, num, tlimits,cycles,
%                        'key1',value1,'key2',value2, ... );
%
% Graphical interface:
%   "Channel/component number" - [edit box] this is the index of the data
%              channel or the index of the component for which to plot the
%              time-frequency decomposition.
%   "Sub-epoch time limits" - [edit box] sub epochs may be extracted (note that
%              this function aims at plotting data epochs not continuous data).
%              You may select the new epoch limits in this edit box.
%   "Use n time points" - [multiple choice list] this is the number of time
%              points to use for the time-frequency decomposition. The more
%              time points, the longer the time-frequency decomposition
%              takes to compute.
%   "Frequency limits" - [edit box] these are the lower and upper
%              frequency limit of the time-frequency decomposition. Instead
%              of limits, you may also enter a sequence of frequencies. For
%              example to compute the time-frequency decomposition at all
%              frequency between 5 and 50 hertz with 1 Hz increment, enter "1:50"
%   "Use limits, padding n" - [multiple choice list] "using limits" means
%              to use the upper and lower limits in "Frequency limits" with
%              a specific padding ratio (padratio argument of newtimef).
%              The last option "use actual frequencies" forces newtimef to
%              ignore the padratio argument and use the vector of frequencies
%              given as input in the "Frequency limits" edit box.
%   "Log spaced" - [checkbox] you may check this box to compute log-spaced
%              frequencies. Note that this is only relevant if you specify
%              frequency limits (in case you specify actual frequencies,
%              this parameter is ignored).
%   "Use divisive baseline" - [multiple choice list] there are two types of
%              baseline correction, additive (the baseline is subtracted)
%              or divisive (the data is divided by the baseline values).
%              The choice is yours. There is also the option to perform
%              baseline correction in single trials. See the 'trialbase' "full"
%              option in the newtimef.m documentation for more information.
%   "No baseline" - [checkbox] check this box to compute the raw time-frequency
%              decomposition with no baseline removal.
%   "Wavelet cycles" - [edit box] specify the number of cycle at the lowest
%              and highest frequency. Instead of specifying the number of cycle
%              at the highest frequency, you may also specify a wavelet
%              "factor" (see newtimef help message). In addition, it is
%              possible to specify actual wavelet cycles for each frequency
%              by entering a sequence of numbers.
%   "Use FFT" - [checkbox] check this checkbox to use FFT instead of
%              wavelet decomposition.
%   "ERSP color limits" - [edit box] set the upper and lower limit for the
%              ERSP image.
%   "see log power" - [checkbox] the log power values (in dB) are plotted.
%              Uncheck this box to plot the absolute power values.
%   "ITC color limits" - [edit box] set the upper and lower limit for the
%              ITC image.
%   "plot ITC phase" - [checkbox] check this box plot plot (overlaid on
%              the ITC amplitude) the polarity of the ITC complex value.
%   "Bootstrap significance level" - [edit box] use this edit box to enter
%              the p-value threshold for masking both the ERSP and the ITC
%              image for significance (masked values appear as light green)
%   "FDR correct" - [checkbox] this correct the p-value for multiple comparisons
%              (across all time and frequencies) using the False Discovery
%              Rate method. See the fdr.m function for more details.
%   "Optional newtimef arguments" - [edit box] addition argument for the
%              newtimef function may be entered here in the 'key', value
%              format.
%   "Plot Event Related Spectral Power" - [checkbox] plot the ERSP image
%              showing event related spectral stimulus induced changes
%   "Plot Inter Trial Coherence" - [checkbox] plot the ITC image.
%   "Plot Curve at each frequency" - [checkbox] instead of plotting images,
%              it is also possible to display curves at each frequency.
%              This functionality is beta and might not work in all cases.
%
% Inputs:
%   INEEG    - input EEG dataset
%   typeproc - type of processing: 1 process the raw channel data
%                                  0 process the ICA component data
%   num      - component or channel number
%   tlimits  - [mintime maxtime] (ms) sub-epoch time limits to plot
%   cycles   -  > 0 --> Number of cycles in each analysis wavelet
%               = 0 --> Use FFTs (with constant window length
%                       at all frequencies)
%
% Optional inputs:
%    See the NEWTIMEF function.
%
% Outputs: Same as NEWTIMEF; no outputs are returned when a
%          window pops-up to ask for additional arguments
%
% Saving the ERSP and ITC output values:
%    Simply look up the history using the eegh function (type eegh).
%    Then copy and paste the POP_NEWTIMEF command and add output args.
%    See the NEWTIMEF function for a list of outputs. For instance,
% >> [ersp itc powbase times frequencies] = pop_newtimef( EEG, ....);
%
% Author: Arnaud Delorme, CNL / Salk Institute, 2001
%
% See also: NEWTIMEF, EEGLAB

% Copyright (C) 2002 University of California San Diego
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.

% 01-25-02 reformated help & license -ad
% 03-08-02 add eeglab option & optimize variable sizes -ad
% 03-10-02 change newtimef call -ad
% 03-18-02 added title -ad & sm
% 04-04-02 added outputs -ad & sm

function varargout = pop_newtimef(EEG, typeproc, num, tlimits, cycles, varargin );

varargout{1} = '';
% display help if not enough arguments
% ------------------------------------
if nargin < 2
	help pop_newtimef;
	return;
end;
lastcom = [];
if nargin < 3
	popup = 1;
else
	popup = ischar(num) | isempty(num);
	if ischar(num)
		lastcom = num;
	end
end

% pop up window
% -------------
if popup
	[txt, vars] = gethelpvar('newtimef.m');
    commandchan = 'tmpEEG = get(gcbf, ''userdata''); tmpchanlocs = tmpEEG(1).chanlocs; [tmp tmpval] = pop_chansel({tmpchanlocs.labels}, ''withindex'', ''on'', ''selectionmode'', ''single''); set(findobj(gcbf, ''tag'', ''chan''), ''string'',tmpval); clear tmpEEG tmp tmpchanlocs tmpval';

    g = [1 0.3 0.6 0.4];
    g2 = [1 0.3 0.25 0.75];
	geometry = { g2 g g g g g g g [0.975 1.27] [1] [1.2 1 1.2]};
    uilist = { ...
               { 'Style', 'text', 'string', fastif(typeproc, 'Channel number', 'Component number'), 'fontweight', 'bold'  } ...
			   { 'Style', 'edit', 'string', getkeyval(lastcom,3,[],'1') 'tag' 'chan'} ...
               { 'style' 'pushbutton' 'string'  '...', 'enable' fastif(~isempty(EEG(1).chanlocs) && typeproc, 'on', 'off') 'callback' commandchan } ...
               {} ...
               ...
			   { 'Style', 'text', 'string', 'Sub epoch time limits [min max] (msec)', 'fontweight', 'bold' } ...
			   { 'Style', 'edit', 'string', getkeyval(lastcom,4,[],[ int2str(EEG.xmin*1000) ' ' int2str(EEG.xmax*1000) ]) 'tag' 'tlimits' } ...
               { 'Style', 'popupmenu', 'string', 'Use 50 time points|Use 100 time points|Use 150 time points|Use 200 time points|Use 300 time points|Use 400 time points' 'tag' 'ntimesout' 'value' 4} { } ...
			   ...
			   { 'Style', 'text', 'string', 'Frequency limits [min max] (Hz) or sequence', 'fontweight', 'bold' } ...
			   { 'Style', 'edit', 'string', '' 'tag' 'freqs'  } ...
               { 'Style', 'popupmenu', 'string', 'Use limits, padding 1|Use limits, padding 2|Use limits, padding 4|Use actual freqs.' 'tag' 'nfreqs' }  ...
               { 'Style', 'checkbox', 'string' 'Log spaced' 'value' 0 'tag' 'freqscale' } ...
			   ...
			   { 'Style', 'text', 'string', 'Baseline limits [min max] (msec) (0->pre-stim.)', 'fontweight', 'bold' } ...
			   { 'Style', 'edit', 'string', '0' 'tag' 'baseline' } ...
			   { 'Style', 'popupmenu',  'string', 'Use divisive baseline (DIV)|Use standard deviation (STD)|Use single trial DIV baseline|Use single trial STD baseline' 'tag' 'basenorm' } ...
               { 'Style', 'checkbox', 'string' 'No baseline' 'tag' 'nobase' } ...
               ...
               { 'Style', 'text', 'string', 'Wavelet cycles [min max/fact] or sequence', 'fontweight', 'bold' } ...
               { 'Style', 'edit', 'string', getkeyval(lastcom,5,[],'3 0.8') 'tag' 'cycle' } ...
               { 'Style', 'checkbox', 'string' 'Use FFT' 'value' 0 'tag' 'fft' } ...
               { } ...
			   ...
			   { 'Style', 'text', 'string', 'ERSP color limits [max] (min=-max)', 'fontweight', 'bold' } ...
               { 'Style', 'edit', 'string', '' 'tag' 'erspmax'} ...
               { 'Style', 'checkbox', 'string' 'see log power (set)' 'tag' 'scale' 'value' 1} {} ...
			   ...
			   { 'Style', 'text', 'string', 'ITC color limits [max]', 'fontweight', 'bold' } ...
               { 'Style', 'edit', 'string', '' 'tag' 'itcmax'} ...
               { 'Style', 'checkbox', 'string' 'plot ITC phase (set)' 'tag' 'plotphase' } {} ...
			   ...
			   { 'Style', 'text', 'string', 'Bootstrap significance level (Ex: 0.01 -> 1%)', 'fontweight', 'bold' } ...
               { 'Style', 'edit', 'string', getkeyval(lastcom,'alpha') 'tag' 'alpha'} ...
               { 'Style', 'checkbox', 'string' 'FDR correct (set)' 'tag' 'fdr' } {} ...
			   ...
			   { 'Style', 'text', 'string', 'Optional newtimef() arguments (see Help)', 'fontweight', 'bold', ...
				 'tooltipstring', 'See newtimef() help via the Help button on the right...' } ...
			   { 'Style', 'edit', 'string', '' 'tag' 'options' } ...
			   {} ...
			   { 'Style', 'checkbox', 'value', ~getkeyval(lastcom,'plotersp','present',0), 'string', ...
				 'Plot Event Related Spectral Power', 'tooltipstring', ...
				 'Plot log spectral perturbation image in the upper panel' 'tag' 'plotersp' } ...
			   { 'Style', 'checkbox', 'value', ~getkeyval(lastcom,'plotitc','present',0), 'string', ...
				 'Plot Inter Trial Coherence', 'tooltipstring', ...
				 'Plot the inter-trial coherence image in the lower panel' 'tag' 'plotitc' } ...
			   { 'Style', 'checkbox', 'value', 0, 'string', ...
				 'Plot curve at each frequency' 'tag' 'plotcurve' } ...
			 };
      % { 'Style', 'edit', 'string', '''padratio'', 4, ''plotphase'', ''off''' } ...
			   %{ 'Style', 'text', 'string',  '[set] -> Plot ITC phase sign', 'fontweight', 'bold', ...
			%	 'tooltipstring', ['Plot the sign (+/-) of inter-trial coherence phase' 10 ...
			%		'as red (+) or blue (-)'] } ...
			%   { 'Style', 'checkbox', 'value', ~getkeyval(lastcom,'plotphase','present',1) } { } ...

	[ tmp1, tmp2, strhalt, result ] = inputgui( 'geometry', geometry, 'uilist', uilist, 'helpcom', 'pophelp(''pop_newtimef'');', ...
					   'title', fastif(typeproc, 'Plot channel time frequency -- pop_newtimef()', ...
							  'Plot component time frequency -- pop_newtimef()'), 'userdata', EEG);
	if length( tmp1 ) == 0 return; end

	if result.fft,      result.cycle = '0'; end
	if result.nobase,   result.baseline = 'NaN'; end

    num   = eeg_decodechan(EEG.chanlocs, result.chan );
	tlimits	 = eval( [ '[' result.tlimits ']' ] );
	cycles	 = eval( [ '[' result.cycle   ']' ] );
    freqs    = eval( [ '[' result.freqs   ']' ] );
    %result.ncycles == 2 is ignored

    % add topoplot
    % ------------
    options = [];
    if isfield(EEG.chanlocs, 'theta') && ~isempty(EEG.chanlocs(num).theta)
        if ~isfield(EEG, 'chaninfo'), EEG.chaninfo = []; end
        if typeproc == 1
            if isempty(EEG.chanlocs), caption = [ 'Channel ' int2str(num) ]; else caption = EEG.chanlocs(num).labels; end
            options = [options ', ''topovec'', ' int2str(num) ...
                        ', ''elocs'', EEG.chanlocs, ''chaninfo'', EEG.chaninfo, ''caption'', ''' caption '''' ];
        else
            options = [options ', ''topovec'', EEG.icawinv(:,' int2str(num) ...
                       '), ''elocs'', EEG.chanlocs, ''chaninfo'', EEG.chaninfo, ''caption'', [''IC ' num2str(num) ''']' ];
      end
    end

	if ~isempty( result.baseline ),  options = [ options ', ''baseline'',[' result.baseline ']' ]; end
    if ~isempty( result.alpha ),     options = [ options ', ''alpha'',' result.alpha ];   end
	if ~isempty( result.options ),   options = [ options ',' result.options ];            end
	if ~isempty( result.freqs ),     options = [ options ', ''freqs'', [' result.freqs ']'   ]; end
	if ~isempty( result.erspmax ),   options = [ options ', ''erspmax'', [' result.erspmax ']' ]; end
	if ~isempty( result.itcmax ),    options = [ options ', ''itcmax'','  result.itcmax ];      end
	if ~result.plotersp,             options = [ options ', ''plotersp'', ''off''' ];     end
	if ~result.plotitc,              options = [ options ', ''plotitc'' , ''off''' ];     end
	if result.plotcurve,             options = [ options ', ''plottype'', ''curve''' ];   end
	if result.fdr,                   options = [ options ', ''mcorrect'', ''fdr''' ];     end
	if result.freqscale,             options = [ options ', ''freqscale'', ''log''' ];    end
	if ~result.plotphase,            options = [ options ', ''plotphase'', ''off''' ];    end
	if ~result.scale,                options = [ options ', ''scale'', ''abs''' ];        end
    if result.ntimesout == 1,        options = [ options ', ''ntimesout'', 50' ];         end
    if result.ntimesout == 2,        options = [ options ', ''ntimesout'', 100' ];        end
    if result.ntimesout == 3,        options = [ options ', ''ntimesout'', 150' ];        end
    if result.ntimesout == 5,        options = [ options ', ''ntimesout'', 300' ];        end
    if result.ntimesout == 6,        options = [ options ', ''ntimesout'', 400' ];        end
    if result.nfreqs == 1,           options = [ options ', ''padratio'', 1' ];           end
    if result.nfreqs == 2,           options = [ options ', ''padratio'', 2' ];           end
    if result.nfreqs == 3,           options = [ options ', ''padratio'', 4' ];           end
    if result.nfreqs == 4,           options = [ options ', ''nfreqs'', ' int2str(length(freqs)) ]; end
    if result.basenorm == 2,         options = [ options ', ''basenorm'', ''on''' ];      end
    if result.basenorm == 4,         options = [ options ', ''basenorm'', ''on''' ];      end
    if result.basenorm >= 3,         options = [ options ', ''trialbase'', ''full''' ];      end

    % add title
    % ---------
	if isempty( findstr(  '''title''', result.options))
        if ~isempty(EEG.chanlocs) && typeproc
            chanlabel = EEG.chanlocs(num).labels;
        else
            chanlabel = int2str(num);
        end
	end

    % compute default winsize
    % -----------------------
    if EEG.xmin < 0 && isempty(findstr( '''winsize''', result.options)) && isempty( result.freqs )
        fprintf('Computing window size in pop_newtimef based on half of the length of the baseline period');
        options = [ options ', ''winsize'', ' int2str(-EEG.xmin*EEG.srate) ];
    end

	figure; try, icadefs; set(gcf, 'color', BACKCOLOR); catch, end
else
    options = [ ',' vararg2str(varargin) ];
end

% compute epoch limits
% --------------------
if isempty(tlimits)
	tlimits = [EEG.xmin, EEG.xmax]*1000;
end
pointrange1 = round(max((tlimits(1)/1000-EEG.xmin)*EEG.srate, 1));
pointrange2 = round(min((tlimits(2)/1000-EEG.xmin)*EEG.srate+1, EEG.pnts));
pointrange = [pointrange1:pointrange2];

% call function sample either on raw data or ICA data
% ---------------------------------------------------
if typeproc == 1
	tmpsig = EEG.data(num,pointrange,:);
else
	if ~isempty( EEG.icasphere )
        if ~isempty(EEG.icaact)
    		tmpsig = EEG.icaact(num,pointrange,:);
 	    else
            tmpsig = (EEG.icaweights(num,:)*EEG.icasphere)*reshape(EEG.data(:,pointrange,:), EEG.nbchan, EEG.trials*length(pointrange));
        end
	else
		error('You must run ICA first');
	end;
end;
tmpsig = reshape( tmpsig, length(num), size(tmpsig,2)*size(tmpsig,3));

% outputs
% -------
outstr = '';
if ~popup
    for io = 1:nargout, outstr = [outstr 'varargout{' int2str(io) '},' ]; end
    if ~isempty(outstr), outstr = [ '[' outstr(1:end-1) '] =' ]; end
end

% plot the datas and generate output command
% --------------------------------------------
if length( options ) < 2
    options = '';
end
if nargin < 4
    varargout{1} = sprintf('figure; pop_newtimef( EEG, %d, %d, [%s], [%s] %s);', typeproc, num, ...
			int2str(tlimits), num2str(cycles), options);
end
com = sprintf('%s newtimef( tmpsig(:, :), length(pointrange), [tlimits(1) tlimits(2)], EEG.srate, cycles %s);', outstr, options);
eval(com)

return;

% get contextual help
% -------------------
function txt = context(var, allvars, alltext);
	loc = strmatch( var, allvars);
	if ~isempty(loc)
		txt= alltext{loc(1)};
	else
		disp([ 'warning: variable ''' var ''' not found']);
		txt = '';
	end


function center = imGeodesicExtremities(img, varargin)
%IMGEODESICEXTREMITIES Compute geodesic extremities of a binary particle
%
%   RES = imGeodesicExtremities(IMG);
%   IMG is a binary image representing a connected particle. The result RES
%   is a binary image with foreground pixels corresponding to the geodesic
%   extremities of the particle. The geodesic extremities are the pixels
%   belonging to the particle whose geodesic propagation equal the geodesic
%   length of the particle.
%
%   RES = imGeodesicExtremities(IMG, WEIGHTS);
%   use different weights for the computation of distances. See
%   imChamferDistance for further details.
%
%   Example
%   imGeodesicExtremities
%
%   Note:
%   As the algorithm propagates geodesic distances from each foreground
%   pixel, the computation time may be expensive.
%
%   See also
%   imGeodesics, imChamferDistance, imGeodesicPropagation
%   imGeodesicRadius, imGeodesicCenter, imGeodesicDiameter
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2009-05-22,    using Matlab 7.7.0.471 (R2008b)
% Copyright 2009 INRA - Cepia Software Platform.

propag = imGeodesicPropagation(img, varargin{:});
maxVal = max(propag(img));
center = propag==maxVal;


function A = VBA_spm_mesh_adjacency(F)
% Compute the adjacency matrix of a triangle mesh
% FORMAT A = spm_mesh_adjacency(F)
% F        - a [fx3] faces array or a patch structure
%
% A        - adjacency matrix as a sparse [vxv] array
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_mesh_adjacency.m 4035 2010-08-05 18:54:32Z guillaume $

if ~isnumeric(F) && isfield(F,'vertices')
    N = size(F.vertices,1);
    F = double(F.faces);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1, N, N);
else
    if isstruct(F), F = F.faces; end
    F = double(F);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1);
end

A = double(A > 0);


function A = spm_mesh_adjacency(F)
% Compute the adjacency matrix of a triangle mesh
% FORMAT A = spm_mesh_adjacency(F)
% F        - a [fx3] faces array or a patch structure
%
% A        - adjacency matrix as a sparse [vxv] array
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_mesh_adjacency.m 4035 2010-08-05 18:54:32Z guillaume $

if ~isnumeric(F) && isfield(F,'vertices')
    N = size(F.vertices,1);
    F = double(F.faces);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1, N, N);
else
    if isstruct(F), F = F.faces; end
    F = double(F);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1);
end

A = double(A > 0);


function varargout = sl2dmatcov(type, data, matsiz, n, meanmat, PL, PR, w)
%SL2DMATCOV Computes the 2D matrix-covariances
%
% $ Syntax $
%   - CL = sl2dmatcov('CL', data, matsiz, n, meanmat, PL, PR, w)
%   - CR = sl2dmatcov('CR', data, matsiz, n, meanmat, PL, PR, w)
%   - [CL, CR] = sl2dmatcov('Both', data, matsiz, n, meanmat, PL, PR, w)
%
% $ Arguments $
%   - data:     the stack of matrices or the cell array of filenames of the
%               array files storing the matrices.
%   - matsiz:   the size of each matrix
%   - n:        the number of samples
%   - PL:       the left-projection matrix, default = []
%   - PR:       the right-projection matrix, default = []
%   - w:        the weights of the matrix samples, default = []
%
% $ Remarks $
%   - The function computes the 2D matrix-covariances according to
%     the following formulas:
%       Y_i = PL^T * (X - meanX)* PR
%       CL = ( sum_{i=1}^n w(i) * Y_i * Y_i^T ) / ( sum_{i=1}^n w(i) )
%       CR = ( sum_{i=1}^n w(i) * Y_i^T * Y_i ) / ( sum_{i=1}^n w(i) )
%     Following special cases are considered:
%       If w is empty, then we take w(i) = 1 for all i
%       If PL is empty, then we take PL as an identity matrix
%       If PR is empty, then we take PR as an identity matrix
%       If meanmat is 0, then we take meanmat as a zero matrix
%
% $ History $
%   - Created by Dahua Lin, on Jul 31st, 2006
%

%% parse and verify input arguments

if nargin < 5
    raise_lackinput('sl2dmatcov', 5);
end
if nargin < 6
    PL = [];
end
if nargin < 7
    PR = [];
end
if nargin < 8
    w = [];
end

matsiz = matsiz(:)';
if length(matsiz) ~= 2
    error('sltoolbox:invalidarg', ...
        'matsiz shoudl be a 2-elem vector');
end
if ~isequal(size(meanmat), matsiz)
    error('sltoolbox:invalidarg', ...
        'The size of mean matrix is not as specified');
end

d1 = matsiz(1);
d2 = matsiz(2);
if ~isempty(PL) && size(PL, 1) ~= d1
    error('sltoolbox:invalidarg', ...
        'The size of PL is inconsistent with the matrix dimension');
end
if ~isempty(PR) && size(PR, 1) ~= d2
    error('sltoolbox:invalidarg', ...
        'The size of PR is inconsistent with the matrix dimension');
end

if ~isempty(w)
    if length(w) ~= n
        error('The weights length is inconsistent with the number of samples');
    end
    tw = sum(w);
else
    tw = n;
end

%% Main body

if isnumeric(data)

    if ~isequal(size(data), [matsiz, n])
        error('sltoolbox:invalidarg', ...
            'The size of data is inconsistent with specified');
    end

    Y = compute_Y(data, meanmat, PL, PR);

    switch type
        case 'CL'
            CL = compute_SL(Y, w);
            CL = CL / tw;
            varargout = {CL};
        case 'CR'
            CR = compute_SR(Y, w);
            CR = CR / tw;
            varargout = {CR};
        case 'Both'
            [CL, CR] = compute_SLSR(Y, w);
            CL = CL / tw;
            CR = CR / tw;
            varargout = {CL, CR};
        otherwise
            error('sltoolbox:invalidarg', ...
                'invalid type: %s', type);
    end

elseif iscell(data)

    nfiles = length(data);
    cf = 0;

    switch type
        case 'CL'
            for i = 1 : nfiles
                curarr = slreadarray(data{i});
                curn = size(curarr, 3);
                Y = compute_Y(curarr, meanmat, PL, PR);
                curCL = compute_SL(Y, w);
                if i == 1
                    CL = curCL;
                else
                    CL = CL + curCL;
                end
                clear Y curCL;
                cf = cf + curn;
            end
            CL = CL / tw;
            varargout = {CL};

        case 'CR'
            for i = 1 : nfiles
                curarr = slreadarray(data{i});
                curn = size(curarr, 3);
                Y = compute_Y(curarr, meanmat, PL, PR);
                curCR = compute_SR(Y, w);
                if i == 1
                    CR = curCR;
                else
                    CR = CR + curCR;
                end
                clear Y curCR;
                cf = cf + curn;
            end
            CR = CR / tw;
            varargout = {CR};

        case 'Both'
            for i = 1 : nfiles
                curarr = slreadarray(data{i});
                curn = size(curarr, 3);
                Y = compute_Y(curarr, meanmat, PL, PR);
                [curCL, curCR] = compute_SLSR(Y, w);
                if i == 1
                    CL = curCL;
                    CR = curCR;
                else
                    CL = CL + curCL;
                    CR = CR + curCR;
                end
                clear Y curCL curCR;
                cf = cf + curn;
            end
            CL = CL / tw;
            CR = CR / tw;
            varargout = {CL, CR};

        otherwise
            error('sltoolbox:invalidarg', ...
                'invalid type: %s', type);
    end

    if cf ~= n
        error('sltoolbox:sizmismatch', ...
            'The total number of samples is not n');
    end

else
    error('sltoolbox:invalidarg', ...
        'data should be a numeric array or a cell array of filenames');
end

%% Core routine

function Y = compute_Y(X, M, PL, PR)

n = size(X, 3);
if isempty(PL)
    if isempty(PR)
        if isequal(M, 0)
            Y = X;
        else
            Y = zeros(size(X, 1), size(X, 2), n);
            for i = 1 : n
                Y(:,:,i) = X(:,:,i) - M;
            end
        end
    else
        Y = zeros(size(X, 1), size(PR, 2), n);
        if isequal(M, 0)
            for i = 1 : n
                Y(:,:,i) = X(:,:,i) * PR;
            end
        else
            for i = 1 : n
                Y(:,:,i) = (X(:,:,i) - M) * PR;
            end
        end
    end
else
    PLT = PL';
    if isempty(PR)
        Y = zeros(size(PL, 2), size(X, 2), n);
        if isequal(M, 0)
            for i = 1 : n
                Y(:,:,i) = PLT * X(:,:,i);
            end
        else
            for i = 1 : n
                Y(:,:,i) = PLT * (X(:,:,i) - M);
            end
        end
    else
        Y = zeros(size(PL, 2), size(PR, 2), n);
        if isequal(M, 0)
            for i = 1 : n
                Y(:,:,i) = PLT * X(:,:,i) * PR;
            end
        else
            for i = 1 : n
                Y(:,:,i) = PLT * (X(:,:,i) - M) * PR;
            end
        end
    end
end

function SL = compute_SL(Y, w)

SL = zeros(size(Y, 1));
n = size(Y, 3);
if isempty(w)
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + curY * curY';
    end
else
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + w(i) * curY * curY';
    end
end

function SR = compute_SR(Y, w)

SR = zeros(size(Y, 2));
n = size(Y, 3);
if isempty(w)
    for i = 1 : n
        curY = Y(:, :, i);
        SR = SR + curY' * curY;
    end
else
    for i = 1 : n
        curY = Y(:, :, i);
        SR = SR + w(i) * curY' * curY;
    end
end

function [SL, SR] = compute_SLSR(Y, w)

SL = zeros(size(Y, 1));
SR = zeros(size(Y, 2));
n = size(Y, 3);
if isempty(w)
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + curY * curY';
        SR = SR + curY' * curY;
    end
else
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + w(i) * curY * curY';
        SR = SR + w(i) * curY' * curY;
    end
end


function [solution, nIterations, bestApprox] = sparseLP(model, approximation, params)
% DC programming for solving the sparse LP
% :math:`min ||x||_0` subject to linear constraints
% See `Le Thi et al., DC approximation approaches for sparse optimization,
% European Journal of Operational Research, 2014`;
% http://dx.doi.org/10.1016/j.ejor.2014.11.031
%
% USAGE:
%
%    [solution, nIterations, bestApprox] = sparseLP(model, approximation, params);
%
% INPUTS:
%    model:       Structure containing the following fields describing the linear constraints:
%
%                        * .A - `m x n` LHS matrix
%                        * .b - `m x 1` RHS vector
%                        * .lb - `n x 1` Lower bound vector
%                        * .ub - `n x 1` Upper bound vector
%                        * .csense - `m x 1` Constraint senses, a string containting the model sense for
%                          each row in `A` ('E', equality, 'G' greater than, 'L' less than).
%
% OPTIONAL INPUTS
%    approximation:    appoximation type of zero-norm. Available approximations:
%
%                        * 'cappedL1' : Capped-L1 norm
%                        * 'exp'      : Exponential function
%                        * 'log'      : Logarithmic function
%                        * 'SCAD'     : SCAD function
%                        * 'lp-'      : `L_p` norm with `p < 0`
%                        * 'lp+'      : `L_p` norm with `0 < p < 1`
%                        * 'l1'       : L1 norm
%                        * 'all'      : try all approximations and return the best result
%
% OPTIONAL INPUTS:
%    params:           Parameters structure:
%
%                        * .nbMaxIteration - stopping criteria - number maximal of iteration (Defaut value = 1000)
%                        * .epsilon - stopping criteria - (Defaut value = 10e-6)
%                        * .theta - parameter of the approximation (Defaut value = 0.5)
%
% OUTPUT:
%    solution:         Structure containing the following fields:
%
%                        * .x - `n x 1` solution vector
%                        * .stat - status:
%
%                          * 1 =  Solution found
%                          * 2 =  Unbounded
%                          * 0 =  Infeasible
%                          * -1=  Invalid input
%
%   nIterations:       Number of iterations
%   bestApprox:        Best approximation
%
% .. Author: - Hoai Minh Le,	20/10/2015
%              Ronan Fleming,    2017

availableApprox = {'exp','log','SCAD','lp-','lp+','l1','cappedL1','all'};

if ~exist('approximation','var')
    approximation='cappedL1';
end

% Check inputs
if nargin < 3
    params.nbMaxIteration = 1000;
    params.epsilon = 1e-6;
    params.theta   = 0.5;
    params.pNeg = -1;
    params.pPos = 0.5;
else
    if ~isfield(params,'nbMaxIteration')
        params.nbMaxIteration = 1000;
    end

    if ~isfield(params,'epsilon')
        params.epsilon = 1e-6;
    end

    if ~isfield(params,'theta')
        params.theta   = 0.5;
    end

    if ~isfield(params,'pNeg')
        params.pNeg = -1;
    end

    if ~isfield(params,'pPos')
        params.pPos = 0.5;
    end

end

if ~isfield(model,'A')
    error('Error:LHS matrix is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'b')
    error('RHS vector is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'lb')
    error('Lower bound vector is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'ub')
    error('Upper bound vector is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'csense')
    error('Constraint sense vector is not defined');
    solution.stat = -1;
    return;
end

if ~ismember(approximation,availableApprox)
    error('Approximation is not valid');
    solution.stat = -1;
    return;
end

bestApprox = '';

switch approximation
    case 'all'
        approximations = setdiff(availableApprox,'all','stable');
        bestResult = size(model.A,2);
        bestSolution.x = [];
        bestSolution.stat = 0;
        bestIterations = 0;
        feasTol = getCobraSolverParams('LP','feasTol');
        for i=1:length(approximations)
            %disp(approximations(i))
            %try
            [candSolution,candIterations] = sparseLP(model,approximations{i},params);
            %catch
            %fail gracefully
            %solutionL0.stat = 0;
            %end
            if candSolution.stat == 1
                candResult = nnz(abs(candSolution.x) > feasTol);
                if bestResult >= candResult
                    bestResult = candResult;
                    bestApprox = approximations{i};
                    bestSolution = candSolution;
                    bestIterations = candIterations;
                end
            end
        end
        solution = bestSolution;
        nIterations = bestIterations;

    otherwise
        [nbMaxIteration,epsilon,theta,pNeg,pPos] = deal(params.nbMaxIteration,params.epsilon,params.theta,params.pNeg,params.pPos);
        [A,b,lb,ub,csense] = deal(model.A,model.b,model.lb,model.ub,model.csense);

        %Parameters
        nbIteration = 0;
        epsilonP = 10e-2;
        alpha = 3;
        [m,n] = size(A);

        %Create the linear sub-programme that one needs to solve at each iteration, only its
        %objective function changes, the constraints set remains.

        % Constraints
        % Ax <=b
        % t >= x
        % t >= -x
        A2 = [A         sparse(m,n);
            speye(n) -speye(n);
            -speye(n) -speye(n)];
        b2 = [b; zeros(2*n,1)];
        csense2 = [csense;repmat('L',2*n, 1)];

        % Bound;
        % lb <= x <= ub
        % 0  <= t <= max(|lb|,|ub|)
        lb2 = [lb;zeros(n,1)];
        ub2 = [ub;max(abs(lb),abs(ub))];

        %Define the linear sub-problem
        subLPproblem = struct('osense',1,'A',A2,'csense',csense2,'b',b2,'lb',lb2,'ub',ub2);

        %Initialisation
        x = zeros(n,1);
        obj_old = evalObj(x,theta,pNeg,pPos,epsilonP,alpha,approximation);

        %DCA
        tic
        while nbIteration < nbMaxIteration

            x_old = x;

            %Solve the linear problem
            subLPproblem.c = updateObj(x,theta,pNeg,pPos,epsilonP,alpha,approximation);
            solution = solveCobraLP(subLPproblem);

            if solution.stat == 1
                x = solution.full(1:n);

                %Check stopping criterion
                error_x = norm(x - x_old);
                obj_new = evalObj(x,theta,pNeg,pPos,epsilonP,alpha,approximation);
                error_obj = abs(obj_new - obj_old);
                if (error_x < epsilon) || (error_obj < epsilon)
                    break;
                else
                    obj_old = obj_new;
                end
                % Automatically update the approximation parameter theta
                if theta < 1000
                    theta = theta * 1.5;
                end
                nbIteration = nbIteration + 1;
                %             disp(strcat('DCA - Iteration: ',num2str(nbIteration)));
                %             disp(strcat('Obj:',num2str(obj_new)));
                %             disp(strcat('Stopping criteria error: ',num2str(min(error_x,error_obj))));
                %             disp('=================================');
            else
                x = [];
                break;
            end
        end

        time = toc;
        solution.x = x;
        solution.time = time;
        nIterations = nbIteration;

end


function HTriggeredRaster(H,V,L);
nPks = 5; % number of examples to plot
pkHt = .1; % min peak height compared to maximum
H(sum(H,2)==0,:)=[];
[N T] = size(V);
[K,~] = size(H);

clf
for fi = 1:K
    axStart = .1 + (fi-1)*.8/K;
    axW = .8/K*.85;
    axL(fi) = subplot('Position', [axStart .1 axW .8]);

    [pks, locs] = findpeaks(H(fi,:),'MinPeakHeight',max(H(fi,:))*pkHt);

    [~, ind] = sort(pks, 'descend');
    ind = ind(1:min(nPks,length(ind)));
    pks = pks(ind); locs = locs(ind);

    R = [];
    twin = [1:L];
    c = 1;
    for pi = 1:length(pks)
        R(c,:,:) = V(:,min(locs(pi)+twin,size(V,2)));
        c = c+1;
    end

    hold on
    for ni = 1:N
        plot([0 L+1], ni*length(pks)*[1 1], 'color', [1 .8 .8], 'linewidth', .1)
    end

    Rmat = reshape(R,N*length(pks), length(twin));
    [Xmat,Ymat] = meshgrid(1:size(Rmat,2),1:size(Rmat,1));
    indBurst = find(Rmat>0);
    s = scatter(Xmat(indBurst)+.9*(-.5+rand(size(indBurst))),Ymat(indBurst), ...
       15, 0*[1 1 1], '.', 'markerfacecolor', 'flat', 'MarkerfaceAlpha',5/nPks, 'MarkerfaceAlpha',5/nPks);

    set(gca, 'ydir', 'reverse')
    axis tight; axis off
end


function c = model_center_of_mass(model)

c = [mean(model.x),mean(model.y),mean(model.z)];


%% === compare timings for MULT

% number of repeats (to increase measurement accuracy)
R  = 10;

% what sizes of (square) matrices do we want measure? (log spacing)
nn = unique(round(exp(linspace(log(4),log(100),10))));

% number of different sizes to try
N  = length(nn);

% size of the output C, in Megabytes
Mbytes = 10;

time   = zeros(N,3,R);
ops    = zeros(N,1);

candidates = {'A*B',  'mmx_naive',  @(a,b)mmx_naive('m',a,b);
              'A''*B',  'mmx_naive',  @(a,b)mmx_naive('m',a,b,'tn');
              'A*B''',  'mmx_naive',  @(a,b)mmx_naive('m',a,b,'nt');
              'A''*B''',  'mmx_naive',  @(a,b)mmx_naive('m',a,b,'tt');
              'A*Bs',  'mmx_naive',  @(a,b)mmx_naive('m',a,b,'ns');
              'As*B',  'mmx_naive',  @(a,b)mmx_naive('m',a,b,'sn');
};

funcs = cell(0,0);
for i=1:size(candidates,1)
   found_it = ~isempty(which(candidates{i,2}));
   if found_it
      funcs(end+1,:) = candidates(i,[1 3]); %#ok<SAGROW>
   else
      fprintf('Could not find %s in your path, ignoring.\n',candidates{i,2});
   end
end
nf    = length(funcs);

for i = 1:N

   n = nn(i);

   r1 = n;
   c1 = n;
   r2 = c1;
   c2 = n;

   pages = round(1e6*Mbytes / (8*r1*c2));

   A     = rand(r1,c1,pages);
   B     = rand(r2,c2,pages);

   B(B>0.5) = 0;
   A(A>0.5) = 0;

   ops(i)   = r1*c2*(2*c1-1)*pages;
   fprintf('multiplying %d*%d matrix pairs of dimension [%dx%d]\n',R*nf,pages,n,n)

   for r = 1:R
      for f = 1:nf %nf:-1:1
         tstart = tic;
         C = funcs{length(funcs)+1-f,2}(A,B);
         time(i,length(funcs)+1-f,r)  = toc(tstart);
         pause(1/10000);
      end
   end
end

%% graphics

gflops   = 1e-9*bsxfun(@times, ops, 1./time);
gFLP     = mean(gflops,3);

clf
hold on
cols = get(gca,'ColorOrder');
cols = [cols; cols];
for i = 1:size(gflops,2)
   plot(nn,gFLP(:,i),'color',cols(i,:),'linewidth',3);
end
for i = 1:size(gflops,2)
   plot(nn,squeeze(gflops(:,i,:)),'.','color',cols(i,:))
end

grid on
set(gca,'xlim',[1 max(nn)])
ylabel('\bf Gigaflops')
xlabel('\bf dimension')

legend(funcs{:,1},'location','northwest')

title('\bf Comparison between mmx, ndfun, and mtimesx. (in Gflops, bigger is better)')

%% make PDF
% set(gcf,'color','w')
% export_fig 'comparison' -png


function [ a, info ] = cpofa ( a, lda, n )

%*****************************************************************************80
%
%% CPOFA factors a complex hermitian positive definite matrix.
%
%  Discussion:
%
%    CPOFA is usually called by CPOCO, but it can be called
%    directly with a saving in time if RCOND is not needed.
%    (time for CPOCO) = (1 + 18/N) * (time for CPOFA).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex A(LDA,N), the hermitian matrix to be factored.
%
%    Input, integer LDA, the leading dimension of A.
%
%    Input, integer N, the order of the matrix.
%
%    Output, complex A(LDA,N); an upper triangular matrix R so that
%      A = hermitian(R)*R
%    where hermitian(R) is the conjugate transpose.  The strict lower
%    triangle is unaltered.  If INFO /= 0, the factorization is not
%    complete.  Only the diagonal and upper triangle are used.
%
%    Output, integer INFO.
%    0, for normal return.
%    K, signals an error condition.  The leading minor of order K is
%    not positive definite.
%
  info = 0;

  for j = 1 : n

    s = 0.0;

    for k = 1 : j-1
      t = a(k,j) - a(1:k-1,k)' * a(1:k-1,j);
      t = t / a(k,k);
      a(k,j) = t;
      s = s + real ( t * conj ( t ) );
    end

    s = real ( a(j,j) ) - s;

    if ( s <= 0.0 | imag ( a(j,j) ) ~= 0.0 )
      info = j;
      break
    end

    a(j,j) = sqrt ( s );

  end

  return
end


function [gal] = m32gal(m3)
% Convert volume from cubic meters to US liquid gallons.
% Chad Greene 2012
gal = m3*264.17205236;


function out = sum(f)
%SUM   Definite integral of a SINGFUN on the interval [-1,1].
%   SUM(F) is the integral of F from -1 to 1.
%
% See also CUMSUM, DIFF.

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

% Note for developers:
%
% The main algorithm:
%
% When the smoothPart of F is a CHEBTECH, that is, it can be written as
% Chebyshev sum, the integral
%
% I = \int_{-1}^{1} F dx = \sum_{0}^{n-1} c_r M_r,
%
% where M_r = \int_{-1}^{1} (1+x)^a(1-x)^b T_r(x) dx is the rth Jacobi moment.
%
% The computation of M_r is treated differently for different a and b:
%
% (I) when a == b, M_r are the Gegenbauer moments, which bear a closed-form
% solution as indicated in [2] and [4].
%
% (II) when a ~= b, M_r are the general Jacobi moments, which can be obtained
% using a three-term recursive relation discussed in [3].
%
% This way, all quadratures in SINGFUN, along with those in CHEBTECH are now
% entirely of Clenshaw-Curtis style.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Useful References:
%
% [1]. K. Xu and M. Javed, Singfun Working Note, August 2013
%
% [2]. Hunter, D., and Nikolov, G., Gaussian Quadrature of Chebyshev
% Polynomials, J. Comput. Appl. Math. 94 (1998), 123-131.
%
% [3]. Piessens, R., and Branders, M., The Evaluation and Application of Some
% Modified Moments, BIT 13 (1973), 443-450.
%
% [4]. Sommariva, A., Fast construction of Fejer and Clenshaw–Curtis rules for
% general weight functions, Computers & Mathematics with Applications 65
% (2012), 682-693.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%
% Trivial cases:
if ( all(f.exponents == 0) )
    % If both the exponents are trivial, then compute the integral by calling
    % the sum in smoothfun.
    out = sum(f.smoothPart);
    return

elseif ( all(f.exponents <= -1) )
    % The integral is divergent or not a number when both the exponents are
    % non-zero.

    if ( isreal(f) )

        % The sign of the smoothPart of F at the end points:
        sl = sign(get(f.smoothPart, 'lval'));
        sr = sign(get(f.smoothPart, 'rval'));

        if  ( sl == sr )
            out = sl.*inf;
        else
            out = NaN;
        end

    else
        % The sign of the real part of the smoothPart of F at the end
        % points:
        rsl = sign(real(get(f.smoothPart, 'lval')));
        rsr = sign(real(get(f.smoothPart, 'rval')));

        % The sign of the real part of the smoothPart of F at the end
        % points:
        isl = sign(imag(get(f.smoothPart, 'lval')));
        isr = sign(imag(get(f.smoothPart, 'rval')));

        if ( (rsl == rsr) && (isl == isr) )
            out = Inf + 1i*Inf;
        else
            out = NaN;
        end
    end

    return

elseif ( any(f.exponents <= -1) )

    % The integral is divergent or not a number when one of the exponents
    % are non-zero.

    if ( isreal(f) )

        % The sign of the smoothPart of F at the end points:
        sl = sign(get(f.smoothPart, 'lval'));
        sr = sign(get(f.smoothPart, 'rval'));

        s = [sl sr];
        ind = ( f.exponents <= -1 );
        out = Inf*s(ind);

    else
        % The sign of the real part of the smoothPart of F at the end
        % points:
        rsl = sign(real(get(f.smoothPart, 'lval')));
        rsr = sign(real(get(f.smoothPart, 'rval')));

        % The sign of the real part of the smoothPart of F at the end
        % points:
        isl = sign(imag(get(f.smoothPart, 'lval')));
        isr = sign(imag(get(f.smoothPart, 'rval')));

        rs = [rsl rsr];
        is = [isl isr];
        ind = ( f.exponents <= -1 );

        % The real part:
        realPart = 0;
        if ( any(rs) )
            realPart = Inf*rs(ind);
        end

        % The imaginary part:
        imagPart = 0;
        if ( any(is) )
            imagPart = Inf*is(ind);
        end

        % The sum:
        out = realPart + imagPart;
    end

    return
end

%%
% The non-trivial case:

if ( isa(f.smoothPart, 'chebtech') )

    % If the smooth part of F is a CHEBTECH, then evaluate the integral by using
    % Clenshaw-Curtis-Jacobi moments and the Chebyshev coefficients:

    % Grab the number of points for the smooth part of f:
    n = length(f);

    % Grab the exponents:
    a = f.exponents(1);

    if ( diff(f.exponents) == 0 )
        % If the exponents at the endpoints are same, then compute the
        % appropriate modified moments for Gegenbauer weights.

        r = a + .5;
        m0 = gamma(r + .5)*sqrt(pi)/gamma(r + 1);
        k = 1:floor((n-1)/2);
        % Even modified moments for M_2k = \int_{-1}^1 (1-x)^a(1+x)^a T_2k(x) dx
        % and notice that the odd moments vanish due to parity.
        m = m0*[1, cumprod((k - r - 1)./(k + r))];
        % Form the modified moments vector:
        M(1:2:n) = m;
        M(2:2:n) = 0;

    else

        % The general case:
        b = f.exponents(2);

        % Common coefficient for the modified moments:
        c1 = a + 1;
        c2 = b + 1;
        c3 = a + b + 1;
        c4 = c1 + c2;
        c5 = a - b;
        c0 = (2^c3)*beta(c1, c2);

        % Compute the hypergeometric function related to the modified moments:
        M = zeros(1,n);
        M(1) = 1;
        if ( n > 1 )
            M(2) = c5/c4;
            % Sister Celine's three-term recurrence:
            for j = 3:n
                M(j) = (2*c5*M(j-1) + (j - 2 - c4)*M(j-2)) / (c3 + j - 1);
            end
        end
        % Compute the modified moments:
        M = c0*M;

    end

    % Chebyshev coefficients of the smooth part of F:
    coeffs = get(f, 'coeffs');

    % multiplication of weights and values
    out = M*coeffs;

else
    %%
    % If f.smoothPart is not a CHEBTECH, we evaluate the integral by using
    % Gauss-Jacobi points and weights.

    % Give a sufficiently large number:
    % [TODO]: This number needs to be determined in future when other 'tech's join.
    % [TODO]: Or perhaps compute iteratively until result doesn't change?
    n = 1000;

    [x, w] = jacpts(ceil(n/2) + 1, f.exponents(2), f.exponents(1));
    out = w*feval(f.smoothPart, x);

end

end


function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p)
% CPD_TO_LAMBDA_MSG Compute lambda message (gaussian)
% lam_msg = compute_lambda_msg(CPD, msg_type, n, ps, msg, p)
% Pearl p183 eq 4.52

switch msg_type
 case 'd',
  error('gaussian_CPD can''t create discrete msgs')
 case 'g',
  self_size = CPD.sizes(end);
  if all(msg{n}.lambda.precision == 0) % no info to send on
    lam_msg.precision = zeros(self_size);
    lam_msg.info_state = zeros(self_size, 1);
    return;
  end
  cpsizes = CPD.sizes(CPD.cps);
  dpval = 1;
  Q = CPD.cov(:,:,dpval);
  Sigmai = Q;
  wmu = zeros(self_size, 1);
  for k=1:length(ps)
    pk = ps(k);
    if pk ~= p
      bk = block(k, cpsizes);
      Bk = CPD.weights(:, bk, dpval);
      m = msg{n}.pi_from_parent{k};
      Sigmai = Sigmai + Bk * m.Sigma * Bk';
      wmu = wmu + Bk * m.mu; % m.mu = u(k)
    end
  end
  % Sigmai = Q + sum_{k \neq i} B_k Sigma_k B_k'
  i = find_equiv_posns(p, ps);
  bi = block(i, cpsizes);
  Bi = CPD.weights(:,bi, dpval);

  if 0
  P = msg{n}.lambda.precision;
  if isinf(P) % inv(P)=Sigma_lambda=0
    precision_temp = inv(Sigmai);
    lam_msg.precision = Bi' * precision_temp * Bi;
    lam_msg.info_state = precision_temp * (msg{n}.lambda.mu - wmu);
  else
    A = inv(P + inv(Sigmai));
    precision_temp = P + P*A*P;
    lam_msg.precision = Bi' * precision_temp * Bi;
    self_size = length(P);
    C = eye(self_size) + P*A;
    z = msg{n}.lambda.info_state;
    lam_msg.info_state = C*z - C*P*wmu;
  end
  end

  if isinf(msg{n}.lambda.precision)
    Sigma_lambda = zeros(self_size, self_size); % infinite precision => 0 variance
    mu_lambda = msg{n}.lambda.mu; % observed_value;
  else
    Sigma_lambda = inv(msg{n}.lambda.precision);
    mu_lambda = Sigma_lambda * msg{n}.lambda.info_state;
  end
  precision_temp = inv(Sigma_lambda + Sigmai);
  lam_msg.precision = Bi' * precision_temp * Bi;
  lam_msg.info_state = Bi' * precision_temp * (mu_lambda - wmu);
end


function [Decoded,Decoder_Chip,Temp_Decoded,intgrl] =  ...
  CDMA_decode(OutSignal,Chipbit,User_to_Decode, ...
  SamplesPerBit,SamplePerChip,TotalDataBit)

% ........................ CDMA Decoding Starts Here .....................
clipto = TotalDataBit*SamplesPerBit;

TotalChips = length(Chipbit(:,User_to_Decode));
Decoder_Chip1 =[];
for l1 = 1:TotalDataBit
    Decoder_Chip1 = vertcat(Decoder_Chip1,Chipbit(:,User_to_Decode));
end
Decoder_Chip = MakeSampled(Decoder_Chip1,length(OutSignal),SamplePerChip);
Temp_Decoded = OutSignal.*Decoder_Chip;
Temp_Decoded = Temp_Decoded(1:TotalDataBit*SamplesPerBit);

intgrl = zeros(length(Temp_Decoded),1);
Avg_Ingl = 0;
Decoded = zeros(TotalDataBit,1);
    bitno = 0;
    for l1 = 1:TotalChips*SamplePerChip:length(Temp_Decoded)
        bitno = bitno+1;
        for l2 = l1:(l1+TotalChips*SamplePerChip-1)
            if (l2==1),intgrl(1)=Temp_Decoded(1);continue;end
            intgrl(l2) = intgrl(l2-1) + Temp_Decoded(l2);
        end
        if (intgrl(l2)>0),
            Decoded(bitno)=1;
        else
            Decoded(bitno)=-1;
        end
        intgrl(l2) = 0;
    end
intgrl=vertcat(intgrl,zeros(length(OutSignal)-length(intgrl),1));
Temp_Decoded = vertcat(Temp_Decoded,zeros(length(OutSignal)-length(Temp_Decoded),1));
% ........................ CDMA Decoding Ends Here .....................


function ap_multi = compute_AP_multiCam(good_image, junk_image, index, queryCam, testCam)
good_cam = testCam(good_image);
good_cam_uni = unique(good_cam);
ap_multi = zeros(1, 6);

% on the same camera
good_cam_now = queryCam;
ngood = length(junk_image)-1;
junk_image_now = [good_image; index(1)];
good_image_now = setdiff(junk_image, index(1));
old_recall = 0;
old_precision = 1.0;
ap = 0;
intersect_size = 0;
j = 0;
good_now = 0;
for n = 1:length(index)
    flag = 0;
    if ~isempty(find(good_image_now == index(n), 1))
        flag = 1; % good image
        good_now = good_now+1;
    end
    if ~isempty(find(junk_image_now == index(n), 1))
        continue; % junk image
    end

    if flag == 1%good
        intersect_size = intersect_size + 1;
    end
    if ngood == 0
        ap_multi(good_cam_now) = 0;
        break;
    end
    recall = intersect_size/ngood;
    precision = intersect_size/(j + 1);
    ap = ap + (recall - old_recall)*((old_precision+precision)/2);
    old_recall = recall;
    old_precision = precision;
    j = j+1;

    if good_now == ngood
        ap_multi(good_cam_now) = ap;
        break;
    end
end

for k = 1:length(good_cam_uni)
    good_cam_now = good_cam_uni(k);
    ngood = length(find(good_cam == good_cam_now));
    pos_junk = find(good_cam ~= good_cam_now);
    junk_image_now = [junk_image; good_image(pos_junk)];
    pos_good = find(good_cam == good_cam_now);
    good_image_now = good_image(pos_good);
    old_recall = 0;
    old_precision = 1.0;
    ap = 0;
    intersect_size = 0;
    j = 0;
    good_now = 0;
    for n = 1:length(index)
        flag = 0;
        if ~isempty(find(good_image_now == index(n), 1))
            flag = 1; % good image
            good_now = good_now+1;
        end
        if ~isempty(find(junk_image_now == index(n), 1))
            continue; % junk image
        end

        if flag == 1%good
            intersect_size = intersect_size + 1;
        end
        recall = intersect_size/ngood;
        precision = intersect_size/(j + 1);
        ap = ap + (recall - old_recall)*((old_precision+precision)/2);
        old_recall = recall;
        old_precision = precision;
        j = j+1;

        if good_now == ngood
            ap_multi(good_cam_now) = ap;
            break;
        end
    end
end

end


 function ob = Gdelaysum1(varargin)
%function ob = Gdelaysum1([options])
%|
%| Construct Gdelaysum1 object that performs weighted sums of a delayed signal.
%| This is useful for model-based reconstruction of THz images.
%| See Gdelaysum1_test() at end for example usage.
%|
%| y[n;m] = sum_{k=0}^{Nx-1} h[n - d[k;m]] x[k], n=0,...,Ny-1, m=0,...,Nm-1
%| for 0 <= n - d[k] <= Nh - 1
%|
%| required
%|	'Ny'	[1]		output signal length
%|	'delay'	[Nx Nm]		delays
%|
%| options
%|	'h'	[Nh 1]		impulse response, default [1]
%|	'nthread' [1]		# threads, default 1
%|
%| out
%|	ob	[Ny*Nm Nx]	Fatrix object
%|
%| Copyright 2006-8-25, Jeff Fessler, University of Michigan

if nargin == 1 && streq(varargin{1}, 'test'), Gdelaysum1_test, return, end
if nargin < 4, ir_usage, end

% defaults
arg.Ny = [];
arg.delay = [];
arg.h = 1;
arg.nthread = 1;
arg.class = 'fatrix2';
arg.chat = false;

% options
arg = vararg_pair(arg, varargin);

if isempty(arg.delay), fail 'delay required', end
if isempty(arg.Ny), fail 'Ny required', end

arg.h = single(arg.h);
arg.delay = single(arg.delay);
arg.nthread = int32(arg.nthread);
arg.chat = int32(arg.chat);

[arg.Nx arg.Nm] = size(arg.delay);
arg.Nh = length(arg.h);

arg.str_forw_mex = 'delaysum1,forw';
arg.str_back_mex = 'delaysum1,back';
if arg.nthread > 1
	arg.str_forw_mex = 'delaysum1,forw,thr';
	arg.str_back_mex = 'delaysum1,back,thr';
end

switch arg.class
case 'Fatrix'
	arg.dim = [arg.Ny * arg.Nm, arg.Nx];
	ob = Fatrix(arg.dim, arg, ...
		'abs', @Gdelaysum1_abs, 'power', @Gdelaysum1_power, ...
		'forw', @Gdelaysum1_forw_Fatrix, ...
		'back', @Gdelaysum1_back_Fatrix);
case 'fatrix2'

	odim = arg.Ny*arg.Nm;
	forw = @(arg, x) delaysum1_mex(arg.str_forw_mex, arg.h, arg.delay, ...
		arg.nthread, single(x), int32(arg.Ny), arg.chat);
	back = @(arg, y) delaysum1_mex(arg.str_back_mex, arg.h, arg.delay, ...
		arg.nthread, single(y), arg.chat);
	ob = fatrix2('idim', arg.Nx, 'odim', odim, 'arg', arg, ...
		'abs', @Gdelaysum1_abs, 'power', @Gdelaysum1_power, ...
		'forw', forw, 'back', back);
otherwise
	fail 'bug'
end

% Gdelaysum1_abs(): |A|
function ob = Gdelaysum1_abs(ob)
ob.arg.h = abs(ob.arg.h);

% Gdelaysum1_power(): A .^ p
function ob = Gdelaysum1_power(ob, p)
ob.arg.h = ob.arg.h .^ p;

% Gdelaysum1_forw_Fatrix(): y = A * x
% in
%	x	[Nx L]
% out
%	y	[Ny*Nm L]
%
function y = Gdelaysum1_forw_Fatrix(arg, x)

LL = size(x, 2);
y = zeros(arg.Ny*arg.Nm, LL, 'single');
for ll=1:LL
	tmp = single(x(:,ll));
	tmp = delaysum1_mex(arg.str_forw_mex, arg.h, arg.delay, ...
		arg.nthread, tmp, int32(arg.Ny), arg.chat);
	y(:,ll) = tmp(:);
end

% Gdelaysum1_back_Fatrix(): x = A' * y
% in
%	y	[Ny*Nm L]
% out
%	x	[Nx L]
%
function x = Gdelaysum1_back_Fatrix(arg, y)

LL = size(y, 2);
x = zeros(arg.Nx, LL, 'single');
for ll=1:LL
	tmp = single(y(:,ll));
	tmp = delaysum1_mex(art.str_back_mex, arg.h, arg.delay, ...
		arg.nthread, tmp, arg.chat);
	x(:,ll) = tmp;
end

% Gdelaysum1_test
function Gdelaysum1_test

delay = [10 20 40; 50 51 52];
h = [4 3 -2 1]';
Ny = 80;
ats = {'nthread', jf('ncore')};
A = Gdelaysum1('Ny', Ny, 'h', h, 'delay', delay, ats{:});

x = [1 0]';
y1 = A * x;
y1 = reshapee(y1, Ny, []);
if im
	clf, plot(y1, '-o')
end

%mask = true(A.arg.Nx,1);
%Fatrix_test_basic(A, mask)
fatrix2_tests(A)
test_adjoint(A);

if 1 % compare Fatrix and fatrix2
	Ny = 2^11;
	Nx = 2^10;
	Nm = 2^9;
	Nh = 2^8;
	rng(0)
	delay = rand(Nx, Nm);
	x = rand(Nx, 1);
	args = {'Ny', Ny, 'h', (1:Nh)', 'delay', delay, ats{:}};
	A1 = Gdelaysum1(args{:}, 'class', 'Fatrix');
	A2 = Gdelaysum1(args{:}, 'class', 'fatrix2');
	cpu etic
	y1 = A1 * x;
	cpu etoc 'Fatrix'
	cpu etic
	y2 = A2 * x;
	cpu etoc 'fatrix2'
	jf_equal(y1, y2)
end


function y=sum_rate_direct(x,A,B,omega,K)
    tmp=zeros(K,K);
    for i0=1:K
        for k0=1:K
            tmp(i0,k0)=abs(x'*A(:,:,i0,k0)+B(i0,k0))^2;
        end
    end
    yt=zeros(K,1);
    for k0=1:K
        tmp1=sum(tmp(:,k0));
        tmp2=tmp1-tmp(k0,k0);
        yt(k0)=log(1+tmp(k0,k0)/(tmp2+1));
    end
    y=-omega*yt;
end


function ff=ref_fac(f,W,c,d,p,q,permutation)
%REF_FAC  Reference factorization.
%
%  This function cannot handle multidimensional arrays.
%  Reshape to matrix BEFORE you call this.
%

% Output
ff=zeros(p*q*W,c*d);

% If d==1, it is not possible to further reduce the size of
% wk. Actually, some of the following code produces an
% error, because Matlab interprets an fft of a 1x q*W*p as a
% a row operation !
if d>1

  % Shape to match first fft pass.
  work=zeros(d,q*W*p);

  % This loop iterates over the number of truly different wk's.
  for ko=0:c-1

    % Permute and copy into work array.
    % Format is suited for fft.
    work(:)=f(permutation+ko,:);

    % Execute the fft and place transposed in ff.
    ff(:,1+ko*d:(ko+1)*d)=fft(work.',[],2);

  end;

else

  % Work arrays.
  work=zeros(p*q*W,1);

  for ko=0:c-1

    % Permute input.
    work(:)=f(permutation+ko,:);

    % Write the block.
    ff(:,ko+1)=work;
  end

end;