function view = cmapSetStandard(view, mode, phInMiddle)
%
%   view = cmapSetStandard(view,mode,phInMiddle)
%
% Author: JL, BW
% Purpose:
%     Put in place a standard color map for the different modes.

if ieNotDefined('mode'), mode = 'ph'; end

switch mode
    case 'ph'
    case 'co'
    case 'amp'
    otherwise
end

% ??? view = refreshView(view);

return;

%---------------------------
function cmap = cmapCenter(mp,centerPhase)

[mp, numGrays,numColors] = getColorMap(FLAT{2},'ph',1);

step = numColors/(2*pi);
horPhase = 2;

% We want the part of the default map from pi to 2pi to be centered around
% the phase that represents the horizontal midline.  That means we want to
% shift the map so that 3pi/2 in the default color map shifts down to the
% horizontal position.

sz = round(( (3*pi/2) - horPhase) *step);
cmap = circshift(mp,sz)

return;


%addpath /white/u2/bob/matlab/stats/
volView = getSelectedVolume;

%baseDir = '/home/bob/research/papers/dti/callosal_areaMaps/matlabFigs';
mkdir(tempdir, 'matlabFigs');
baseDir = fullfile(tempdir, 'matlabFigs');
disp(['figures will be saved in ' baseDir]);
[junk,sessionCode] = fileparts(pwd);
fileNameBase = fullfile(baseDir, [mrSESSION.subject '_' sessionCode]);
fileName = [fileNameBase '_' volView.ROIs(viewGet(volView, 'selectedROI')).name];
labelX = 'Left phase (rad)';
labelY = 'Right phase (rad)';
% axisLim = [-2*pi, 2*pi, -2*pi, 2*pi];
% tick = [-3*pi/2, -pi, -pi/2, 0, pi/2, pi, 3*pi/2];
% tickLabel = ['   ';'-pi';'   ';' 0 ';'   ';' pi';'   '];
eccenDeg = [0, pi/2, pi, 3*pi/2, 4*pi/2]/(2*pi) * 16;
axisLim = [-pi/2, 5*pi/2, -pi/2, 5*pi/2];
tick = [0, pi/2, pi, 3*pi/2, 4*pi/2];
tickLabel = [' 0  ';'    ';' pi ';'    ';'2 pi'];
scanNames = {'wedge','ring'};
coThresh = 0.25;
paperFigs = 0;
if(paperFigs)
    fontName = 'Helvetica';
    fontSize = 12;
    markSize = 9;
    markColor = 'k';
    lineWidth = 2;
    lineColor = 'k';
else
    fontName = 'Comic Sans MS';
    fontSize = 16;
    markSize = 12;
    markColor = 'r';
    lineWidth = 3;
    lineColor = 'b';
end
generalNotes = '';
roiCoords = getCurROIcoords(volView);
% We get the last coord, which is the left-right axis (lower = left)
% The following will swap coordinate pairs so that the left-most coord
% is always first.
fiberEndptCoordX = [roiCoords(3,1:2:end); roiCoords(3,2:2:end)];
swapThese = diff(fiberEndptCoordX)<0;
tmp = fiberEndptCoordX(1,swapThese);
fiberEndptCoordX(1,swapThese) = fiberEndptCoordX(2,swapThese);
fiberEndptCoordX(2,swapThese) = tmp;
for(scanNum=1:2)
    co = getCurDataROI(volView,'co',scanNum,roiCoords);
    ph = getCurDataROI(volView,'ph',scanNum,roiCoords);
    fiberEndptPh = [ph(1:2:end); ph(2:2:end)];
    tmp = fiberEndptPh(1,swapThese);
    fiberEndptPh(1,swapThese) = fiberEndptPh(2,swapThese);
    fiberEndptPh(2,swapThese) = tmp;
    goodVals = isfinite(fiberEndptPh(1,:)) & isfinite(fiberEndptPh(2,:)) & co(1:2:end)>coThresh & co(2:2:end)>coThresh;
    fiberEndptPh = fiberEndptPh(:,goodVals);
    % Null hypothesis test
    fiberEndptPh(2,:) = fiberEndptPh(2,randperm(length(fiberEndptPh(2,:))));
    % Unwrap phases
    if(strcmpi(scanNames{scanNum}, 'wedge'))
    else
        labelX = 'Left Eccentricity (deg)';
        labelY = 'Right Eccentricity (deg)';
        tickLabel = num2str(eccenDeg');
        d = diff(fiberEndptPh);
        unwrapThese = d>pi & fiberEndptPh(2,:)>3*pi/2;
        fiberEndptPh(1,unwrapThese) = fiberEndptPh(2,unwrapThese)+2*pi;
        unwrapThese = d<-pi & fiberEndptPh(1,:)>3*pi/2;
        fiberEndptPh(2,unwrapThese) = fiberEndptPh(2,unwrapThese)+2*pi;
    end
    x = squeeze(fiberEndptPh(1,:));
    y = squeeze(fiberEndptPh(2,:));
    %[p, r, df] = statTest(x, y, 'r'); rsq = r^2;
    %fit = polyfit(x, y, 1)
    [b,bint,r,rint,s]=regress(y',[x',ones(size(y'))]);
    fitX = [min(x),max(x)];
    fitY = fitX.*b(1) + b(2);
    p = s(3); rsq = s(1); f = s(2);
    if(paperFigs)
        if(scanNum==1) fh = figure; else figure(fh); end
        set(fh,'Position',[6, 33, 400, 820]);
        subplot(2,1,scanNum);
    else
        fh = figure;
        set(fh,'Position',[7, 50, 400, 430]);
    end
    axes;
    line([axisLim(1),axisLim(2)], [axisLim(3),axisLim(4)], 'Color', 'k', 'LineWidth', 1);
    hold on;
    h = scatter(x, y, markColor);
    hold off;
    set(gca, 'fontName', fontName);
    set(gca, 'fontSize', fontSize);
    xlabel(labelX, 'fontName', fontName, 'fontSize', fontSize, 'fontWeight','normal');
    ylabel(labelY, 'fontName', fontName, 'fontSize', fontSize, 'fontWeight','normal');
    axis(axisLim);
    set(gca, 'XTick', tick);
    set(gca, 'YTick', tick);
    set(gca, 'XTickLabel', tickLabel);
    set(gca, 'YTickLabel', tickLabel);
    set(h, 'MarkerSize', markSize); set(h, 'LineWidth', lineWidth);
    lineH = line(fitX, fitY, 'Color', lineColor, 'LineWidth', lineWidth);
    if(p<0.0001)
        title(sprintf('%s: R^2=%0.4f (p<0.0001)', scanNames{scanNum}, rsq));
    else
        title(sprintf('%s: R^2=%0.4f (p=%0.4f)', scanNames{scanNum}, rsq, p));
    end
    if(~paperFigs)
        pos = get(fh, 'Position');
        set(gca, 'Units', 'pixels');
        %[left bottom width height]
        set(gca, 'Position', [70,70,pos(3)-90,pos(3)-90]);
        set(fh, 'PaperPositionMode', 'auto');
        %print(fh, '-dpng', '-r120', [fileName '_' scanNames{scanNum} '_scatter.png']);
    end

    notes = [sprintf('coThresh=%0.3f; ', coThresh) generalNotes];
    %save([fileName '_' scanNames{scanNum} '_dat.mat'], 'fiberEndptPh', 'co', 'ph', 'roiCoords', 'notes');
end

if(paperFigs)
    set(fh, 'PaperPositionMode', 'auto');
    print(fh, '-depsc', '-tiff', [fileName '_scatter.eps']);
end
refresh;


function boxes3d(varargin)
%BOXES3D Description of functions operating on 3D boxes.
%
%   A box defined by its coordinate extents:
%   BOX = [XMIN XMAX YMIN YMAX ZMIN ZMAX].
%
%   Example
%   % Draw a polyhedron together with its bounding box
%   [n e f]= createIcosahedron;
%   drawPolyhedron(n, f);
%   hold on;
%   drawBox3d(point3dBounds(n))
%
%
%   See also
%   boundingBox3d, box3dVolume, drawBox3d
%   intersectBoxes3d, mergeBoxes3d, randomPointInBox3d
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2010-07-26,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.


function [varargout]=axis_inc(varargin)

% function [h]=axis_inc(s,ha)
% ------------------------------------------------------------------------
% This function widens the axis limits for the axis with the handle |hs|
% using the scale factor |s| (e.g. if s=2 the axis width is doubled). The
% scaling parameter |s| can be a single scalar or a vector such that each
% axis direction is scaled differently.
%
% Change log:
% 2019/06/26 Added variable input/output handling
% ------------------------------------------------------------------------

%% Parse input

switch nargin
    case 1
        s=varargin{1};
        ha=gca;
    case 2
        s=varargin{1};
        ha=varargin{2};
end

if numel(s)==1
    s=s*ones(1,3);
end

%% Set new axis limits

%Get axis limits
limSet={'XLim','YLim','ZLim'};

for q=1:1:numel(limSet)
    try
        limNow=get(ha,limSet{q});
        w=limNow(2)-limNow(1);
        if w<=eps(0)
            w=1; %Force 1 if too small
        end
        limInc=w*(s(q)-1)/2; %Axis limit increment
        limNew=limNow+[-limInc limInc];
        set(ha,limSet{q},limNew);
    catch

    end
end

%% Collect output
varargout{1}=ha;

end

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function bands = SpectrogramBands(spectrogram,frequencies,varargin)

%SpectrogramBands - Determine running power in physiological bands.
%
%  USAGE
%
%    bands = SpectrogramBands(spectrogram,frequencies,<options>)
%
%    spectrogram    spectrogram obtained using MTSpectrogram
%    frequencies    frequency bins for spectrogram
%    <options>      optional list of property-value pairs (see table below)
%
%    =========================================================================
%     Properties    Values
%    -------------------------------------------------------------------------
%     'smooth'      smoothing for ratio (0 = no smoothing) (default = 2)
%     'delta'       set delta band (default = [0 4])
%     'theta'       set theta band (default = [7 10])
%     'spindles'    set spindle band (default = [10 20])
%     'lowGamma'    set low gamma band (default = [30 80])
%     'highGamma'   set high gamma band (default = [80 120])
%     'ripples'     set ripple band (default = [100 250])
%     'broadLow'    set broad low frequency band (default = [1 12])
%     'amyGamma'    set amygdala gamma band (default = [45 65])
%    =========================================================================
%
%  OUTPUT
%
%    bands.delta      delta power
%    bands.theta      theta power
%    bands.spindles   spindle power
%    bands.lowGamma   low gamma power
%    bands.highGamma  high gamma power
%    bands.ripples    ripple power
%    bands.broadLow   broad low frequency power
%    bands.amyGamma   amygdala gamma power
%
%    bands.ratios.hippocampus      theta/delta ratio
%    bands.ratios.cortex           [0.5 4.5]/[0.5 9] and [0.5 20]/[0.5 55]
%    bands.ratios.amygdala         gamma/broad low ratio
%
%    Heuristic ratios for cortex are from Gervasoni et al. (2004).
%
%  SEE
%
%    See also MTSpectrogram.

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

% Defaults
smooth = 2;
delta = [0 4];
theta = [7 10];
spindles = [10 20];
lowGamma = [30 80];
highGamma = [80 120];
ripples = [100 250];
broadLow = [1 12];
amyGamma = [45 65];

% Check number of parameters
if nargin < 2,
  error('Incorrect number of parameters (type ''help SpectrogramBands'' for details).');
end

% Check parameter sizes
if ~isdmatrix(spectrogram),
	error('Parameter ''spectrogram'' is not a matrix (type ''help SpectrogramBands'' for details).');
end
if ~isdvector(frequencies) | length(frequencies) ~= size(spectrogram,1),
	error('Parameter ''frequencies'' is not a vector or does not match spectrogram size (type ''help SpectrogramBands'' for details).');
end

% Parse options
for i = 1:2:length(varargin),
	if ~ischar(varargin{i}),
		error(['Parameter ' num2str(i) ' is not a property (type ''help SpectrogramBands'' for details).']);
	end
	switch(lower(varargin{i})),
		case 'smooth',
			smooth = varargin{i+1};
			if ~isdscalar(smooth,'>=0'),
				error('Incorrect value for property ''smooth'' (type ''help SpectrogramBands'' for details).');
			end
		case 'delta',
			delta = varargin{i+1};
			if ~isdvector(delta,'>=0','<','#2'),
				error('Incorrect value for property ''delta'' (type ''help SpectrogramBands'' for details).');
			end
		case 'theta',
			theta = varargin{i+1};
			if ~isdvector(theta,'>=0','<','#2'),
				error('Incorrect value for property ''theta'' (type ''help SpectrogramBands'' for details).');
			end
		case 'spindles',
			spindles = varargin{i+1};
			if ~isdvector(spindles,'>=0','<','#2'),
				error('Incorrect value for property ''spindles'' (type ''help SpectrogramBands'' for details).');
			end
		case 'lowgamma',
			lowGamma = varargin{i+1};
			if ~isdvector(lowGamma,'>=0','<','#2'),
				error('Incorrect value for property ''lowGamma'' (type ''help SpectrogramBands'' for details).');
			end
		case 'highgamma',
			highGamma = varargin{i+1};
			if ~isdvector(highGamma,'>=0','<','#2'),
				error('Incorrect value for property ''highGamma'' (type ''help SpectrogramBands'' for details).');
			end
		case 'ripples',
			ripples = varargin{i+1};
			if ~isdvector(ripples,'>=0','<','#2'),
				error('Incorrect value for property ''ripples'' (type ''help SpectrogramBands'' for details).');
			end
		case 'broadlow',
			broadLow = varargin{i+1};
			if ~isdvector(broadLow,'>=0','<','#2'),
				error('Incorrect value for property ''broadLow'' (type ''help SpectrogramBands'' for details).');
			end
		case 'amygamma',
			amyGamma = varargin{i+1};
			if ~isdvector(amyGamma,'>=0','<','#2'),
				error('Incorrect value for property ''amyGamma'' (type ''help SpectrogramBands'' for details).');
			end
		otherwise,
			error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help SpectrogramBands'' for details).']);
	end
end

n = size(spectrogram,1);

% Select relevant frequency bins
thetaBins = frequencies >= theta(1) & frequencies <= theta(2);
deltaBins = frequencies >= delta(1) & frequencies <= delta(2);
spindleBins = frequencies >= spindles(1) & frequencies <= spindles(2);
lowGammaBins = frequencies >= lowGamma(1) & frequencies <= lowGamma(2);
highGammaBins = frequencies >= highGamma(1) & frequencies <= highGamma(2);
rippleBins = frequencies >= ripples(1) & frequencies <= ripples(2);
broadLowBins = frequencies >= broadLow(1) & frequencies <= broadLow(2);
amyGammaBins = frequencies >= amyGamma(1) & frequencies <= amyGamma(2);

% Compute physiological bands
bands.theta = mean(spectrogram(thetaBins,:))';
bands.delta = mean(spectrogram(deltaBins,:))';
bands.spindles = mean(spectrogram(spindleBins,:))';
bands.lowGamma = mean(spectrogram(lowGammaBins,:))';
bands.highGamma = mean(spectrogram(highGammaBins,:))';
bands.ripples = mean(spectrogram(rippleBins,:))';
bands.broadLow = mean(spectrogram(broadLowBins,:))';
bands.amyGamma = mean(spectrogram(amyGammaBins,:))';

% Theta/delta ratio
bands.ratios.hippocampus = Smooth(bands.theta./(bands.delta+eps),smooth);
bands.ratio = bands.ratios.hippocampus;

% Heuristic ratios from Gervasoni et al. (2004)
range1 = [0.5 4.5];
bins1 = frequencies >= range1(1) & frequencies <= range1(2);
band1 =  mean(spectrogram(bins1,:))';
range2 = [0.5 9];
bins2 = frequencies >= range2(1) & frequencies <= range2(2);
band2 =  mean(spectrogram(bins2,:))';
bands.ratios.cortex(:,1) = Smooth(band1./(band2+eps),smooth);
bands.ratio1 = bands.ratios.cortex;

range1 = [0.5 20];
bins1 = frequencies >= range1(1) & frequencies <= range1(2);
band1 =  mean(spectrogram(bins1,:))';
range2 = [0.5 55];
bins2 = frequencies >= range2(1) & frequencies <= range2(2);
band2 =  mean(spectrogram(bins2,:))';
bands.ratios.cortex(:,2) = Smooth(band1./(band2+eps),smooth);
bands.ratio2 = bands.ratios.cortex(:,2);

% Amygdala ratio
bands.ratios.amygdala = Smooth(bands.amyGamma./(bands.broadLow+eps),smooth);
bands.ratio3 = bands.ratios.amygdala;


% DeJong_f3.m
% De Jong's f3 function, ND, also called STEP
% from: http://www.cs.rpi.edu/~hornda/pres/node4.html
%
% f(x) = sum( floor(x) )
%
% x = N element row vector containing [ x0, x1,..., xN ]
%   each row is processed independently,
%   you can feed in matrices of timeXN no prob
%
% example: cost = DeJong_f3([1,2;3,4;5,6])
% note minimum @ x= -Inf or whatever lower bound you've chosen

% Brian Birge
% Rev 1.0
% 9/12/04

function [out]=DeJong_f3(in)
 out = sum( floor(in) , 2);


%BASE64DECODE decodes a base64 string as a vector of uint8s
% BASE64DECODE(BASE64)
%    Decodes every four BASE64 characters to three bytes.
%    If BASE64 is padded with '=', these are translated to zeros, and
%    stripped from the resulting bytes.

% (c) 2014 Bastian Bechtold
% This code is licensed under the BSD 3-clause license

function bytes = base64decode(base64)
    % strip line breaks
    base64 = strrep(base64, sprintf('\n'), '');
    % add padding if missing
    if mod(length(base64), 4) ~= 0
        base64 = [base64 repmat('=', [1 mod(length(base64), 4)])];
    end
    % remember padding
    padding = sum(base64 == '=');
    % convert from string representation to base64 bytes
    table = zeros(1, 128, 'uint8');
    table(['A':'Z' 'a':'z' '0':'9' '+' '/']+0) = 0:63;
    base64 = table(base64');

    % convert every four base64 bytes to three uint8 bytes
    bytes = zeros(length(base64)/4*3, 1, 'uint8');
    bytes(1:3:end) = bitor(bitshift(base64(1:4:end), 2), ...
                           bitshift(base64(2:4:end), -4));
    bytes(2:3:end) = bitor(bitshift(bitand(base64(2:4:end), 15), 4), ... % four LSB
                           bitshift(base64(3:4:end), -2));
    bytes(3:3:end) = bitor(bitshift(bitand(base64(3:4:end), 3), 6), ... % two LSB
                           base64(4:4:end));
    % strip padding
    bytes = bytes(1:end-padding);
end


function B = sub(A, varargin)
% sub(A,i,j,k) = A(i;j;k)
% Written by Mo Chen (sth4nth@gmail.com).
assert(ndims(A)==numel(varargin));
sz = cellfun(@numel,varargin);
IDX = cell(1,ndims(A));
for i = 1:ndims(A)
    idx = varargin{i};
    shape = ones(1,ndims(A));
    shape(i) = sz(i);
    idx = reshape(idx,shape);
    shape = sz;
    shape(i) = 1;
    idx = repmat(idx,shape);
    IDX{i} = idx(:);
end
B = reshape(A(sub2ind(size(A),IDX{:})),sz);


function [stat, cfg] = ft_statistics_montecarlo(cfg, dat, design, varargin)

% FT_STATISTICS_MONTECARLO performs a nonparametric statistical test by calculating
% Monte-Carlo estimates of the significance probabilities and/or critical values from
% the permutation distribution. This function should not be called directly, instead
% you should call the function that is associated with the type of data on which you
% want to perform the test.
%
% Use as
%   stat = ft_timelockstatistics(cfg, data1, data2, data3, ...)
%   stat = ft_freqstatistics    (cfg, data1, data2, data3, ...)
%   stat = ft_sourcestatistics  (cfg, data1, data2, data3, ...)
%
% where the data is obtained from FT_TIMELOCKANALYSIS, FT_FREQANALYSIS or
% FT_SOURCEANALYSIS respectively, or from FT_TIMELOCKGRANDAVERAGE,
% FT_FREQGRANDAVERAGE or FT_SOURCEGRANDAVERAGE respectively
% and with cfg.method = 'montecarlo'
%
% The configuration options that can be specified are:
%   cfg.numrandomization = number of randomizations, can be 'all'
%   cfg.correctm         = string, apply multiple-comparison correction, 'no', 'max', cluster', 'tfce', 'bonferroni', 'holm', 'hochberg', 'fdr' (default = 'no')
%   cfg.alpha            = number, critical value for rejecting the null-hypothesis per tail (default = 0.05)
%   cfg.tail             = number, -1, 1 or 0 (default = 0)
%   cfg.correcttail      = string, correct p-values or alpha-values when doing a two-sided test, 'alpha','prob' or 'no' (default = 'no')
%   cfg.ivar             = number or list with indices, independent variable(s)
%   cfg.uvar             = number or list with indices, unit variable(s)
%   cfg.wvar             = number or list with indices, within-cell variable(s)
%   cfg.cvar             = number or list with indices, control variable(s)
%   cfg.feedback         = string, 'gui', 'text', 'textbar' or 'no' (default = 'text')
%   cfg.randomseed       = string, 'yes', 'no' or a number (default = 'yes')
%
% If you use a cluster-based statistic, you can specify the following options that
% determine how the single-sample or single-voxel statistics will be thresholded and
% combined into one statistical value per cluster.
%   cfg.clusterstatistic = how to combine the single samples that belong to a cluster, 'maxsum', 'maxsize', 'wcm' (default = 'maxsum')
%                          the option 'wcm' refers to 'weighted cluster mass', a statistic that combines cluster size and intensity;
%                          see Hayasaka & Nichols (2004) NeuroImage for details
%   cfg.clusterthreshold = method for single-sample threshold, 'parametric', 'nonparametric_individual', 'nonparametric_common' (default = 'parametric')
%   cfg.clusteralpha     = for either parametric or nonparametric thresholding per tail (default = 0.05)
%   cfg.clustercritval   = for parametric thresholding (default is determined by the statfun)
%   cfg.clustertail      = -1, 1 or 0 (default = 0)
%
% To include the channel dimension for clustering of channel level data, you should specify
%   cfg.neighbours       = neighbourhood structure, see FT_PREPARE_NEIGHBOURS
% If you specify an empty neighbourhood structure, clustering will only be done
% over frequency and/or time and not over neighbouring channels.
%
% The statistic that is computed for each sample in each random reshuffling
% of the data is specified as
%   cfg.statistic       = 'indepsamplesT'           independent samples T-statistic,
%                         'indepsamplesF'           independent samples F-statistic,
%                         'indepsamplesregrT'       independent samples regression coefficient T-statistic,
%                         'indepsamplesZcoh'        independent samples Z-statistic for coherence,
%                         'depsamplesT'             dependent samples T-statistic,
%                         'depsamplesFmultivariate' dependent samples F-statistic MANOVA,
%                         'depsamplesregrT'         dependent samples regression coefficient T-statistic,
%                         'actvsblT'                activation versus baseline T-statistic.
% or you can specify your own low-level statistical function.
%
% You can also use a custom statistic of your choice that is sensitive to the
% expected effect in the data. You can implement the statistic in a "statfun" that
% will be called for each randomization. The requirements on a custom statistical
% function is that the function is called ft_statfun_xxx, and that the function returns
% a structure with a "stat" field containing the single sample statistical values.
% Have a look at the functions in the fieldtrip/statfun directory (e.g.
% FT_STATFUN_INDEPSAMPLEST) for the correct format of the input and output.
%
% See also FT_TIMELOCKSTATISTICS, FT_FREQSTATISTICS, FT_SOURCESTATISTICS,
% FT_STATISTICS_ANALYTIC, FT_STATISTICS_STATS, FT_STATISTICS_MVPA,
% FT_STATISTICS_CROSSVALIDATE

% Undocumented local options:
%   cfg.resampling       permutation, bootstrap
%   cfg.computecritval   yes|no, for the statfun
%   cfg.computestat      yes|no, for the statfun
%   cfg.computeprob      yes|no, for the statfun
%   cfg.voxelstatistic   deprecated
%   cfg.voxelthreshold   deprecated
%   cfg.precondition     before|after|[], for the statfun

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

% do a sanity check on the input data
assert(isnumeric(dat),    'this function requires numeric data as input, you probably want to use FT_TIMELOCKSTATISTICS, FT_FREQSTATISTICS or FT_SOURCESTATISTICS instead');
assert(isnumeric(design), 'this function requires numeric data as input, you probably want to use FT_TIMELOCKSTATISTICS, FT_FREQSTATISTICS or FT_SOURCESTATISTICS instead');

% check if the input cfg is valid for this function
cfg = ft_checkconfig(cfg, 'renamed',     {'factor',           'ivar'});
cfg = ft_checkconfig(cfg, 'renamed',     {'unitfactor',       'uvar'});
cfg = ft_checkconfig(cfg, 'renamed',     {'repeatedmeasures', 'uvar'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'clusterthreshold', 'nonparametric', 'nonparametric_individual'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'correctm', 'yes', 'max'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'correctm', 'none', 'no'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'correctm', 'bonferoni', 'bonferroni'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'correctm', 'holms', 'holm'});
cfg = ft_checkconfig(cfg, 'required',    {'statistic'});
cfg = ft_checkconfig(cfg, 'forbidden',   {'ztransform', 'removemarginalmeans', 'randomfactor', 'voxelthreshold', 'voxelstatistic'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'statfun', 'depsamplesF', 'ft_statfun_depsamplesFmultivariate'});
cfg = ft_checkconfig(cfg, 'renamedval',  {'statfun', 'ft_statfun_depsamplesF', 'ft_statfun_depsamplesFmultivariate'});

% set the defaults for the main function
cfg.alpha        = ft_getopt(cfg, 'alpha',      0.05);
cfg.tail         = ft_getopt(cfg, 'tail',       0);
cfg.correctm     = ft_getopt(cfg, 'correctm',   'no');
cfg.resampling   = ft_getopt(cfg, 'resampling', 'permutation');
cfg.feedback     = ft_getopt(cfg, 'feedback',   'text');
cfg.ivar         = ft_getopt(cfg, 'ivar',       'all');
cfg.uvar         = ft_getopt(cfg, 'uvar',       []);
cfg.cvar         = ft_getopt(cfg, 'cvar',       []);
cfg.wvar         = ft_getopt(cfg, 'wvar',       []);
cfg.correcttail  = ft_getopt(cfg, 'correcttail',  'no');
cfg.precondition = ft_getopt(cfg, 'precondition', []);

% explicit check for option 'yes' in cfg.correctail.
if strcmp(cfg.correcttail, 'yes')
  ft_error('cfg.correcttail = ''yes'' is not allowed, use either ''prob'', ''alpha'' or ''no''')
end

if strcmp(cfg.correctm, 'tfce')
  % TODO this could require some better defaults
  cfg.connectivity = ft_getopt(cfg, 'connectivity', []);
  cfg.tfce_h0      = ft_getopt(cfg, 'tfce_h0', 0);
  cfg.tfce_H       = ft_getopt(cfg, 'tfce_H',  2);
  cfg.tfce_E       = ft_getopt(cfg, 'tfce_E',  0.5);
  cfg.tfce_nsteps  = ft_getopt(cfg, 'tfce_nsteps', 100);
else
  % these options only apply to tfce, to ensure appropriate configs they are forbidden when _not_ clustering
  cfg = ft_checkconfig(cfg, 'unused', {'tfce_h0', 'tfce_H', 'tfce_E', 'tfce_nsteps'});
end

if strcmp(cfg.correctm, 'cluster')
  % set the defaults for clustering
  cfg.clusterstatistic = ft_getopt(cfg, 'clusterstatistic', 'maxsum');
  cfg.clusterthreshold = ft_getopt(cfg, 'clusterthreshold', 'parametric');
  cfg.clusteralpha     = ft_getopt(cfg, 'clusteralpha',     0.05);
  cfg.clustercritval   = ft_getopt(cfg, 'clustercritval',   []);
  cfg.clustertail      = ft_getopt(cfg, 'clustertail',      cfg.tail);
  cfg.connectivity     = ft_getopt(cfg, 'connectivity',     []); % the default is dealt with below
else
  % these options only apply to clustering, to ensure appropriate configs they are forbidden when _not_ clustering
  cfg = ft_checkconfig(cfg, 'unused', {'clusterstatistic', 'clusteralpha', 'clustercritval', 'clusterthreshold', 'clustertail'});
end

if any(strcmp(cfg.correctm, {'cluster' 'tfce'}))
  % these options might require a spatial neighbourhood matrix

  % deal with the neighbourhood of the channels/triangulation/voxels
  if isempty(cfg.connectivity)
    if isfield(cfg, 'dim') && ~isfield(cfg, 'channel') && ~isfield(cfg, 'tri')
      % input data can be reshaped into a 3D volume, use bwlabeln/spm_bwlabel rather than clusterstat
      ft_info('using connectivity of voxels in 3-D volume\n');
      cfg.connectivity = nan;
    elseif isfield(cfg, 'tri')
      % input data describes a surface along which neighbours can be defined
      ft_info('using connectivity of vertices along triangulated surface\n');
      cfg.connectivity = triangle2connectivity(cfg.tri);
      if isfield(cfg, 'insideorig')
        cfg.connectivity = cfg.connectivity(cfg.insideorig, cfg.insideorig);
      end
    elseif isfield(cfg, 'avgoverchan') && istrue(cfg.avgoverchan)
      % channel dimension has been averaged across, no sense in clustering across space
      cfg.connectivity = true(1);
    elseif isfield(cfg, 'channel')
      cfg.neighbours   = ft_getopt(cfg, 'neighbours', []);
      cfg.connectivity = channelconnectivity(cfg);
    else
      % there is no connectivity in the spatial dimension
      cfg.connectivity = false(size(dat,1));
    end
  else
    % use the specified connectivity: this is not fully robust because
    % there is no guarantee that the order of the spatial elements in the
    % data is the same as the order of the spatial elements in the
    % adjacency matrix
  end
end

% for backward compatibility and other warnings relating correcttail
if isfield(cfg,'correctp') && strcmp(cfg.correctp,'yes')
  ft_warning('cfg.correctp has been renamed to cfg.correcttail and the options have been changed')
  disp('setting cfg.correcttail to ''prob''')
  cfg.correcttail = 'prob';
  cfg = rmfield(cfg,'correctp');
elseif isfield(cfg,'correctp') && strcmp(cfg.correctp,'no')
  cfg = ft_checkconfig(cfg, 'renamed', {'correctp', 'correcttail'});
end
if strcmp(cfg.correcttail,'no') && cfg.tail==0 && cfg.alpha==0.05
  ft_warning('Doing a two-sided test without correcting p-values or alpha-level, p-values and alpha-level will reflect one-sided tests per tail. See http://bit.ly/2YQ1Hm8')
end

% for backward compatibility
if size(design,2)~=size(dat,2)
  design = transpose(design);
end

if ischar(cfg.ivar) && strcmp(cfg.ivar, 'all')
  cfg.ivar = 1:size(design,1);
end

% fetch function handle to the low-level statistics function
statfun = ft_getuserfun(cfg.statistic, 'statfun');
if isempty(statfun)
  ft_error('could not locate the appropriate statistics function');
else
  ft_info('using "%s" for the single-sample statistics\n', func2str(statfun));
end

% construct the resampled design matrix or data-shuffling matrix
ft_info('constructing randomized design\n');
resample = resampledesign(cfg, design);
Nrand = size(resample,1);

% most of the statfuns result in this warning, which is not interesting
ws = ft_warning('off', 'MATLAB:warn_r14_stucture_assignment');

if strcmp(cfg.correctm, 'cluster')
  % determine the critical value for cluster thresholding
  if strcmp(cfg.clusterthreshold, 'nonparametric_individual') || strcmp(cfg.clusterthreshold, 'nonparametric_common')
    ft_info('using a nonparametric threshold for clustering\n');
    cfg.clustercritval = [];  % this will be determined later
  elseif strcmp(cfg.clusterthreshold, 'parametric') && isempty(cfg.clustercritval)
    ft_info('computing a parametric threshold for clustering\n');
    tmpcfg = cfg; % the next line does not pass on non-standard options that a statfun might use
    % tmpcfg = keepfields(cfg, {'dim' 'dimord' 'clusteralpha' 'clustertail' 'ivar' 'uvar' 'cvar' 'wvar' 'contrastcoefs'});
    tmpcfg.computecritval = 'yes';  % explicitly request the computation of the crtitical value
    tmpcfg.computestat    = 'no';   % skip the computation of the statistic
    tmpcfg.alpha          = cfg.clusteralpha; % the statfun uses cfg.alpha most likely
    try
      cfg.clustercritval    = getfield(statfun(tmpcfg, dat, design), 'critval');
    catch
      disp(lasterr);
      ft_error('could not determine the parametric critical value for clustering');
    end
  elseif strcmp(cfg.clusterthreshold, 'parametric') && ~isempty(cfg.clustercritval)
    ft_info('using the specified parametric threshold for clustering\n');
    cfg.clusteralpha = [];
  end
end

% compute the statistic for the observed data
ft_progress('init', cfg.feedback, 'computing statistic');
% get an estimate of the time required per evaluation of the statfun
time_pre = cputime;

try
  % the nargout function in MATLAB 6.5 and older does not work on function handles
  num = nargout(statfun);
catch
  num = 1;
end

if num==1
  % only the statistic is returned
  [statobs] = statfun(cfg, dat, design);
elseif num==2
  % both the statistic and the (updated) configuration are returned
  [statobs, cfg] = statfun(cfg, dat, design);
elseif num==3
  % both the statistic and the (updated) configuration and the (updated) data are returned
  tmpcfg = cfg;
  if strcmp(cfg. precondition, 'before'), tmpcfg.preconditionflag = 1; end
  [statobs, tmpcfg, dat]  = statfun(tmpcfg, dat, design);
  tmpcfg.preconditionflag = 0;
  cfg = tmpcfg;
end

if isstruct(statobs)
  % remember all details for later reference, continue to work with the statistic
  statfull = statobs;
  statobs  = statobs.stat;
end

% remember the statistic for later reference, continue to work with the statistic
statfull.stat = statobs;

time_eval = cputime - time_pre;
ft_info('estimated time per randomization is %.2f seconds\n', time_eval);

% pre-allocate some memory
if strcmp(cfg.correctm, 'cluster')
  statrand = zeros(size(statobs,1), size(resample,1), class(dat)); % this reduces the memory footprint, requires the user to use ft_struct2single on the input data
else
  prb_pos   = zeros(size(statobs));
  prb_neg   = zeros(size(statobs));
end

if strcmp(cfg.precondition, 'after')
  tmpcfg = cfg;
  tmpcfg.preconditionflag = 1;
  [tmpstat, tmpcfg, dat] = statfun(tmpcfg, dat, design);
end

if any(strcmp(cfg.correctm, {'tfce' 'max'}))
  % pre-allocate the memory to hold the distribution of most extreme positive (right) and negative (left) statistical values
  posdistribution = nan(1,Nrand);
  negdistribution = nan(1,Nrand);
end

% compute the statistic for the randomized data and count the outliers
for i = 1:Nrand
  ft_progress(i/Nrand, 'computing statistic %d from %d\n', i, Nrand);
  if strcmp(cfg.resampling, 'permutation')
    tmpdesign = design(:,resample(i,:));     % the columns in the design matrix are reshufled by means of permutation
    tmpdat    = dat;                        % the data itself is not shuffled
    if size(tmpdesign,1)==size(tmpdat,2)
      tmpdesign = transpose(tmpdesign);
    end
  elseif strcmp(cfg.resampling, 'bootstrap')
    tmpdesign = design;                     % the design matrix is not shuffled
    tmpdat    = dat(:,resample(i,:));        % the columns of the data are resampled by means of bootstrapping
  end
  if any(strcmp(cfg.correctm, {'cluster' 'tfce'}))
    % keep each randomization in memory for cluster postprocessing
    dum = statfun(cfg, tmpdat, tmpdesign);
    if isstruct(dum)
      statrand(:,i) = dum.stat;
    else
      statrand(:,i) = dum;
    end
  else
    % do not keep each randomization in memory, but process them on the fly
    statrand = statfun(cfg, tmpdat, tmpdesign);
    if isstruct(statrand)
      statrand = statrand.stat;
    end

    % the following line is for debugging
    % stat.statkeep(:,i) = statrand;
    if strcmp(cfg.correctm, 'max')
      % compare each data element with the maximum statistic
      prb_pos = prb_pos + (statobs<max(statrand(:)));
      prb_neg = prb_neg + (statobs>min(statrand(:)));
      posdistribution(i) = max(statrand(:));
      negdistribution(i) = min(statrand(:));
    else
      % compare each data element with its own statistic
      prb_pos = prb_pos + (statobs<statrand);
      prb_neg = prb_neg + (statobs>statrand);
    end
  end
end
ft_progress('close');

if strcmp(cfg.correctm, 'cluster')
  % do the cluster postprocessing
  [stat, cfg] = clusterstat(cfg, statrand, statobs);
elseif strcmp(cfg.correctm, 'tfce')
  [stat, cfg] = tfcestat(cfg, statrand, statobs);
else
  if ~isequal(cfg.numrandomization, 'all')
    % in case of random permutations (i.e., montecarlo sample, and NOT full
    % permutation), the minimum p-value should not be 0, but 1/N
    prb_pos = prb_pos + 1;
    prb_neg = prb_neg + 1;
    Nrand = Nrand + 1;
  end
  switch cfg.tail
    case 1
      clear prb_neg  % not needed any more, free some memory
      stat.prob = prb_pos./Nrand;
    case -1
      clear prb_pos  % not needed any more, free some memory
      stat.prob = prb_neg./Nrand;
    case 0
      % for each observation select the tail that corresponds with the lowest probability
      prb_neg = prb_neg./Nrand;
      prb_pos = prb_pos./Nrand;
      stat.prob = min(prb_neg, prb_pos); % this is the probability for the most unlikely tail
  end
end

% In case of a two tailed test, the type-I error rate (alpha) refers to
% both tails of the distribution, whereas the stat.prob value computed sofar
% corresponds with one tail, i.e. the probability, under the assumption of
% no effect or no difference (the null hypothesis), of obtaining a result
% equal to or more extreme than what was actually observed. The decision
% rule whether the null-hopothesis should be rejected given the observed
% probability therefore should consider alpha divided by two, to correspond
% with the probability in one of the tails (the most extreme tail). This
% is conceptually equivalent to performing a Bonferroni correction for the
% two tails.
%
% An alternative solution to distribute the alpha level over both tails is
% achieved by multiplying the probability with a factor of two, prior to
% thresholding it wich cfg.alpha.  The advantage of this solution is that
% it results in a p-value that corresponds with a parametric probability.
% Below both options are realized
if strcmp(cfg.correcttail, 'prob') && cfg.tail==0
  stat.prob = stat.prob .* 2;
  stat.prob(stat.prob>1) = 1; % clip at p=1
  % also correct the probabilities in the pos/negcluster fields
  if isfield(stat, 'posclusters')
    for i=1:length(stat.posclusters)
      stat.posclusters(i).prob = stat.posclusters(i).prob*2;
      if stat.posclusters(i).prob>1; stat.posclusters(i).prob = 1; end
    end
  end
  if isfield(stat, 'negclusters')
    for i=1:length(stat.negclusters)
      stat.negclusters(i).prob = stat.negclusters(i).prob*2;
      if stat.negclusters(i).prob>1; stat.negclusters(i).prob = 1; end
    end
  end
elseif strcmp(cfg.correcttail, 'alpha') && cfg.tail==0
  cfg.alpha = cfg.alpha / 2;
end

% compute range of confidence interval p ? 1.96(sqrt(var(p))), with var(p) = var(x/n) = p*(1-p)/N
stddev = sqrt(stat.prob.*(1-stat.prob)/Nrand);
stat.cirange = 1.96*stddev;

if isfield(stat, 'posclusters')
  for i=1:length(stat.posclusters)
    stat.posclusters(i).stddev  = sqrt(stat.posclusters(i).prob.*(1-stat.posclusters(i).prob)/Nrand);
    stat.posclusters(i).cirange =  1.96*stat.posclusters(i).stddev;
    if i==1 && stat.posclusters(i).prob<cfg.alpha && stat.posclusters(i).prob+stat.posclusters(i).cirange>=cfg.alpha
      ft_warning('FieldTrip:posCluster_exceeds_alpha', sprintf('The p-value confidence interval of positive cluster #%i includes %.3f - consider increasing the number of permutations!', i, cfg.alpha));
    end
  end
end
if isfield(stat, 'negclusters')
  for i=1:length(stat.negclusters)
    stat.negclusters(i).stddev  = sqrt(stat.negclusters(i).prob.*(1-stat.negclusters(i).prob)/Nrand);
    stat.negclusters(i).cirange =  1.96*stat.negclusters(i).stddev;
    if i==1 && stat.negclusters(i).prob<cfg.alpha && stat.negclusters(i).prob+stat.negclusters(i).cirange>=cfg.alpha
      ft_warning('FieldTrip:negCluster_exceeds_alpha', sprintf('The p-value confidence interval of negative cluster #%i includes %.3f - consider increasing the number of permutations!', i, cfg.alpha));
    end
  end
end

if ~isfield(stat, 'prob')
  ft_warning('probability was not computed');
else
  switch lower(cfg.correctm)
    case 'max'
      % the correction is implicit in the method
      ft_notice('using a maximum-statistic based method for multiple comparison correction\n');
      ft_notice('the returned probabilities and the thresholded mask are corrected for multiple comparisons\n');
      stat.mask = stat.prob<=cfg.alpha;
      stat.posdistribution = posdistribution;
      stat.negdistribution = negdistribution;
    case 'tfce'
      ft_notice('using a threshold free cluster enhancement based method for multiple comparison correction\n');
      ft_notice('the returned probabilities and the thresholded mask are corrected for multiple comparisons\n');
      stat.mask = stat.prob<=cfg.alpha;
    case 'cluster'
      % the correction is implicit in the method
      ft_notice('using a cluster-based method for multiple comparison correction\n');
      ft_notice('the returned probabilities and the thresholded mask are corrected for multiple comparisons\n');
      stat.mask = stat.prob<=cfg.alpha;
    case 'bonferroni'
      ft_notice('performing Bonferroni correction for multiple comparisons\n');
      ft_notice('the returned probabilities are uncorrected, the thresholded mask is corrected\n');
      stat.mask = stat.prob<=(cfg.alpha ./ numel(stat.prob));
    case 'holm'
      % test the most significatt significance probability against alpha/N, the second largest against alpha/(N-1), etc.
      ft_notice('performing Holm-Bonferroni correction for multiple comparisons\n');
      ft_notice('the returned probabilities are uncorrected, the thresholded mask is corrected\n');
      [pvals, indx] = sort(stat.prob(:));                                   % this sorts the significance probabilities from smallest to largest
      k = find(pvals > (cfg.alpha ./ ((length(pvals):-1:1)')), 1, 'first'); % compare each significance probability against its individual threshold
      mask = (1:length(pvals))'<k;
      stat.mask = zeros(size(stat.prob));
      stat.mask(indx) = mask;
    case 'hochberg'
      % test the most significant significance probability against alpha/N, the second largest against alpha/(N-1), etc.
      ft_notice('performing Hochberg''s correction for multiple comparisons (this is *not* the Benjamini-Hochberg FDR procedure!)\n');
      ft_notice('the returned probabilities are uncorrected, the thresholded mask is corrected\n');
      [pvals, indx] = sort(stat.prob(:));                     % this sorts the significance probabilities from smallest to largest
      k = find(pvals <= (cfg.alpha ./ ((length(pvals):-1:1)')), 1, 'last'); % compare each significance probability against its individual threshold
      mask = (1:length(pvals))'<=k;
      stat.mask = zeros(size(stat.prob));
      stat.mask(indx) = mask;
    case 'fdr'
      ft_notice('performing FDR correction for multiple comparisons\n');
      ft_notice('the returned probabilities are uncorrected, the thresholded mask is corrected\n');
      stat.mask = fdr(stat.prob, cfg.alpha);
    otherwise
      ft_notice('not performing a correction for multiple comparisons\n');
      stat.mask = stat.prob<=cfg.alpha;
  end
end

% return the observed statistic
if ~isfield(stat, 'stat')
  stat.stat = statobs;
end

if exist('statrand', 'var')
  stat.ref = mean(statrand,2);
end

% return optional other details that were returned by the statfun
stat = copyfields(statfull, stat, fieldnames(statfull));

ft_warning(ws); % revert to original state


function y = inv_pos( x )

%INV_POS   Internal cvx version.

y = pow_cvx( x, -1, 'pow_p' );

% Copyright 2010 Michael C. Grant and Stephen P. Boyd.
% See the file COPYING.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function [] = aps_support_plot(technique)
% plotting the support information used for the APS correction methods
% technique flag
% when:
% 1 powerlaw
% 2 ERA-I
% 3 Meris
%
%     Copyright (C) 2015  Bekaert David - University of Leeds
%     Email: eedpsb@leeds.ac.uk or davidbekaert.com
%
%     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 should have received a copy of the GNU General Public License along
%     with this program; if not, write to the Free Software Foundation, Inc.,
%     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%
% By Bekaert David
%

fontsize = 15;
load tca_support

%% power- law
if technique==1
    if exist('aps_p','dir')~=7
        mkdir('aps_p')
    end
    if strcmpi(getparm_aps('powerlaw_ridge_constraint'),'y')

        deminfo = powerlaw_ridges.deminfo;
        InSAR_convexhull = powerlaw_ridges.InSAR_convexhull;
        mountain_ridge = powerlaw_ridges.mountain_ridge;
        hard_ridge_flag = powerlaw_ridges.hard_ridge_flag;

        % plotting hte powerlaw ridges
        fprintf('Plotting power-law ridges \n')

        h1 = figure('name','Power-law ridges','position', [ 200   243   610   603]);
        plot( mean([deminfo.xmin deminfo.xmax]),mean([deminfo.ymax deminfo.ymin]),'g-','linewidth',2)
        hold on
        plot( mean([deminfo.xmin deminfo.xmax]),mean([deminfo.ymax deminfo.ymin]),'r-','linewidth',2)
        hold on
        plot( mean([deminfo.xmin deminfo.xmax]),mean([deminfo.ymax deminfo.ymin]),'r--','linewidth',2)

        imagesc([deminfo.xmin deminfo.xmax],[deminfo.ymax deminfo.ymin],deminfo.dem_smooth)
        cc = colorbar;
        view(0,90)
        axis equal
        axis tight
        colormap(flipud(gray))
        axis xy
        box on

        hold on
        plot(InSAR_convexhull(:,1),InSAR_convexhull(:,2),'g-','linewidth',2)

        % plotting the line on the figure
        for counter=1:length(mountain_ridge)
            if hard_ridge_flag(counter)==1
                plot(mountain_ridge{counter}(:,1),mountain_ridge{counter}(:,2),'r-','linewidth',2)
            else
                plot(mountain_ridge{counter}(:,1),mountain_ridge{counter}(:,2),'r--','linewidth',2)
            end
        end
        box on
        xlabel(cc,'[m]','fontsize',fontsize)
        ylabel(cc,'Topography','fontsize',fontsize)
        legend('Location','NorthOutside','InSAR region','Hard ridge','Subregion boundary')
        title('Ridge definition','fontsize',fontsize)
        set(gca,'fontsize',fontsize)
        print(h1,'-dpng',['aps_p/mountain_ridges.png'])
        print(h1,'-depsc',['aps_p/mountain_ridges.eps'])

    else
       % plotting the power-law windows
        fprintf('Plotting power-law windows \n')

        % see if the real dem is available otherzie use the poitn heights
        dem_flag=1;
        if exist('powerlaw_ridges','var')==1
            deminfo = powerlaw_ridges.deminfo;
        elseif exist('era','var')==1
            deminfo = era.deminfo;
        else
            hgt_file = getparm_aps('hgt_matfile');
            ll_matfile = getparm_aps('ll_matfile');

            hgt =  load(hgt_file);
            ll = load(ll_matfile);
            if strcmpi(getparm_aps('stamps_processed'),'y')
                hgt = hgt.hgt;
                ll = ll.lonlat;
                dem_flag=0;
            end
        end
        % making sure the dem and the other data have the same origin in
        % longitude
        if dem_flag== 1
            if deminfo.xmax-max(InSAR_convexhull(:,1))>100
                deminfo.xmax = deminfo.xmax-360;
                deminfo.xmin = deminfo.xmin-360;
            end
        end

        % laoding of the data
        window_box_ll= powerlaw_windows.window_box_ll;
        window_box_center_ll = powerlaw_windows.window_box_center_ll;

        % plotting the results
        h1 = figure('name','Power-law windows','position', [ 200   243   610   603]);
        % for the legend
        plot(window_box_ll{round(0.5*(length(window_box_ll)))}(:,1),window_box_ll{round(0.5*(length(window_box_ll)))}(:,2),'r-','linewidth',2)
        hold on
        plot(window_box_center_ll(1,1),window_box_center_ll(1,2),'wo','markeredgecolor','k','markerfacecolor','w','markersize',15)
        hold on
        plot(InSAR_convexhull(:,1),InSAR_convexhull(:,2),'g-','linewidth',2)
        hold on

        if dem_flag==1
             % plot the topogrpahy
            imagesc([deminfo.xmin deminfo.xmax],[deminfo.ymax deminfo.ymin],deminfo.dem)
            view(0,90)
            axis xy
        else
            scatter3(ll(:,1),ll(:,2),hgt,3,hgt,'filled');
            view(0,90)
        end
        cc=colorbar;
        colormap(flipud(gray))
        xlabel(cc,'[m]','fontsize',fontsize)
        ylabel(cc,'Topography','fontsize',fontsize)
        axis equal
        axis tight

        hold on
        plot3(window_box_ll{round(0.5*(length(window_box_ll)))}(:,1),window_box_ll{round(0.5*(length(window_box_ll)))}(:,2),99999.*ones(size(window_box_ll{1}(:,2))),'r-','linewidth',2)
        hold on
        plot3(window_box_center_ll(:,1),window_box_center_ll(:,2),10000000.*ones(size(window_box_center_ll(:,2))),'wo','markeredgecolor','k','markerfacecolor','w','markersize',15)
        hold on
        plot3(InSAR_convexhull(:,1),InSAR_convexhull(:,2),99999.*ones(size(InSAR_convexhull(:,2))),'g-','linewidth',2)

        legend('Location','NorthOutside','Window example','Window centers','InSAR region')
        title('Window definition','fontsize',fontsize)
        set(gca,'fontsize',fontsize)

        grid off
        box on

        print(h1,'-dpng',['aps_p/window_locations.png'])
        print(h1,'-depsc',['aps_p/window_locations.eps'])

    end

%% ERA interim
elseif technique==2
    if exist('aps_e','dir')~=7
        mkdir('aps_e')
    end

    % loading the ERA data
    deminfo = era.deminfo;
    era_lonlat = era.era_lonlat;

    % check if the InSAR outline exist, if so plot it too
    if exist('InSAR_convexhull','var')==1;
        insar_flag =1;
    else
        insar_flag=0;
    end
    if insar_flag== 1
        if deminfo.xmax-max(InSAR_convexhull(:,1))>100
            InSAR_convexhull(:,1) = InSAR_convexhull(:,1)+360;
        end
    end

    % plotting the figure
    hfig = figure('name','ERA points and InSAR region','position', [ 200   243   610   603]);
    % for the legend generation
    plot(mean([deminfo.xmin deminfo.xmax]),mean([deminfo.ymax deminfo.ymin]),'wo','markeredgecolor','k','markerfacecolor','w','markersize',15)
    hold on
    % check if the insar convex hull can be plotted
    if insar_flag==1
        plot(mean([deminfo.xmin deminfo.xmax]),mean([deminfo.ymax deminfo.ymin]),'g-','linewidth',2)
    end
    % plot the topogrpahy
    imagesc([deminfo.xmin deminfo.xmax],[deminfo.ymax deminfo.ymin],deminfo.dem)
    cc=colorbar;
    view(0,90)
    colormap(flipud(gray))
    axis xy
    xlabel(cc,'[m]','fontsize',fontsize)
    ylabel(cc,'Topography','fontsize',fontsize)
    hold on
    plot(era_lonlat(:,1),era_lonlat(:,2),'wo','markeredgecolor','k','markerfacecolor','w','markersize',15)
    hold on
    if insar_flag==1
        plot(InSAR_convexhull(:,1),InSAR_convexhull(:,2),'g-','linewidth',2)
        legend('location','northoutside','Used ERA-I locations','InSAR region')
    else
        legend('location','northoutside','Used ERA-I locations')
    end
    title('ERA points distribution','fontsize',fontsize)
    set(gca,'fontsize',fontsize)
    axis equal
    axis tight

    print(hfig,'-dpng',['aps_e/era_datapoints.png'])
    print(hfig,'-depsc',['aps_e/era_datapoints.eps'])

elseif technique==3 % MERIS
    load psver
    ps = load(['ps' num2str(psver) '.mat']);
    stamps_processed = getparm_aps('stamps_processed');
    small_baseline_flag  = getparm('small_baseline_flag');
    if strcmpi(small_baseline_flag,'y')
        load('tca_sb2.mat','ph_tropo_meris');
        % for baselines you need ps of PS directory
        bperp = load(['..' filesep 'ps1.mat'],'bperp');
        bperp = bperp.bperp;
        bperp = bperp(ps.ifgday_ix);
        dates=ps.ifgday;
        ix_ifgs_keep = 1:ps.n_ifg;
    else
        load('tca2.mat','ph_tropo_meris');
        dates = [ps.day   repmat(ps.master_day,length(ps.day),1)];
        bperp = [ps.bperp zeros([length(ps.day) 1])];
        ix_ifgs_keep = 1:ps.n_ifg;
    end

    % plot the SB network and show for whcih connection there is meris data
    if strcmp(stamps_processed,'y')

        % remove that that have not been unwrapped before
        ix_dropped = getparm('drop_ifg');

        % interferograms with a meris correction
        temp = ix_ifgs_keep;
        temp(ix_dropped)=[];
        ifgs_good = find(sum(ph_tropo_meris(:,temp)~=0,1)~=0)

        if strcmp(small_baseline_flag,'n')
            ix_dropped = unique([ix_dropped ps.master_ix]);
        end
        ix_ifgs_keep(ix_dropped)=[];
        bperp(ix_dropped,:)=[];
        dates(ix_dropped,:)=[];

        % keep the original network for reference
        dates_all = dates;
        bperp_all = bperp;

        % plotting the network of the interferograms used in the RMSE computation
        h_baselineplot = figure('name','Processed network');
        % plotting all ifgs that were considered
        for ifgs_counter=1:size(bperp_all,1)
            hold on
            plot([dates_all(ifgs_counter,1)  dates_all(ifgs_counter,2)],  [bperp_all(ifgs_counter,1) bperp_all(ifgs_counter,2)] ,'k-','linewidth',1)
        end

        % plotting the network for which we have an APS correction
        for ifgs_counter=1:length(ifgs_good)
            ifgs_counter
            hold on
            plot([dates(ifgs_good(ifgs_counter),1)  dates(ifgs_good(ifgs_counter),2)],  [bperp(ifgs_good(ifgs_counter),1) bperp(ifgs_good(ifgs_counter),2)] ,'k-','linewidth',2)
            text(mean(dates(ifgs_good(ifgs_counter),:)),mean(bperp(ifgs_good(ifgs_counter),:))+20,num2str(ifgs_good(ifgs_counter)),'fontsize',fontsize-2,'backgroundColor',[1 1 1],'Margin',0.01)
        end
        hold on
        % [dates_unique,ix_unique] = unique(dates(ifgs_good,:));
        % bperp_unique = bperp(ifgs_good,:);
        % bperp_unique = bperp_unique(ix_unique);
        [dates_unique,ix_unique] = unique(dates_all);
        bperp_unique = bperp_all;
        bperp_unique = bperp_unique(ix_unique);
        plot(dates_unique,bperp_unique,'ko','markerfacecolor','r','markersize',7)
        clear dates_unique ix_unique bperp_unique
        hold on
        % set(gca,'XTick',dates_num)
        datetick('x','mmm yy')
        set(gca,'fontsize',fontsize)
        box on
        ylabel('Bperp [m]','fontsize',fontsize)
    end

end


function [fhat, fola] = blocksyn(F, c , Lb, fola)
%BLOCKSYN Blockwise synthesis interface
%   Usage: blocksyn(F, c, Lb)
%
%   Input parameters:
%      F    : Synthesis frame object.
%      c    : Coefficients of a block.
%      Lb   : Length of the block.
%      fola : Explicitly defined overlap.
%   Output parameters:
%      fhat : Reconstructed block of signal.
%      fola : Stored overlap.
%
%   `fhat=blocksyn(F,c,Lb)` reconstructs the signal block *fhat* from the
%   coefficients *c* using the frame defined by *F*. If some overlap is used,
%   it is stored internally using block_interface. Note that the function is
%   capable of handling overlaps internally only for a single call
%   to the function in the blockproc. loop.%
%
%   `[fhat,fola]=blocksyn(F,c,Lb,fola)` does the same, but the block algorithm
%   uses `fola` to read and store overlap explicitly. `fola` can be empty.
%
%   **Note:** To get perfect reconstruction, the synthesis frame *F* must
%   be a dual frame of the analysis frame used in |blockana|.
%
%   See also: block, blockana, framedual
%
%   References: dogrhove12 ltfatnote026

complainif_notenoughargs(nargin,3,'BLOCKSYN');
complainif_notvalidframeobj(F,'BLOCKSYN');

    if ~isfield(F,'blockalg')
        F.blockalg = 'naive';
    end

    if ~isfield(F,'L')
         error(['%s: The frame object was not accelerated. See ',...
                'BLOCKFRAMEACCEL.'],upper(mfilename));
    end

    if nargin<4
       fola = [];
    end

    % Next block index start (from a global point of view, starting with zero)
    nextSb = block_interface('getPos');
    % Block index start (from a global point of view, starting with zero)
    Sb = nextSb-Lb;

    if strcmp(F.blockalg,'naive')
       if F.L < Lb
          error(['%s: The frame object was accelerated with incompatible ',...
                 'length. The block length is %i but the accelerated ',...
                 'length is %i.'],upper(mfilename),Lb,F.L);
       end
       % Most general. Should work for anything.
       % Produces awful block artifacts when coefficients are altered.
       fhat = F.frsyn(c);
       fhat = fhat(1:Lb,:);
    elseif strcmp(F.blockalg,'sliced')
        if F.L < 2*Lb
          error(['%s: The frame object was accelerated with incompatible ',...
                 'length. The block length is %i but the accelerated ',...
                 'length is %i.'],upper(mfilename),Lb,F.L);
        end
        % General processing
        % Equal block length assumption
        % Reconstruct
        f = F.frsyn(c);
        % If the transform length differs from the 2*Lb,
        % Pick the correct part from the result
        pad = size(f,1) - 2*Lb;
        sIdx = floor(pad/2);
        % Result should not be longer than 2*Lb
        f = f(1+sIdx:sIdx+2*Lb,:);
        % Multiply by a slicing window
        f = bsxfun(@times,F.sliwin,f);
        % Load and add overlap (first half)
        ol = loadOverlap(Lb,size(f,2),fola);
        olLen = size(ol,1);
        f(1:olLen,:) = f(1:olLen,:) + ol;
        % Store overlap (second half)
        if nargout>1
           fola=storeOverlap(f,Lb);
        else
           storeOverlap(f,Lb);
        end
        % Return first half
        fhat = f(1:Lb,:);
    elseif strcmp(F.blockalg,'segola')
       if ~isfield(F,'winLen')
          error('%s: Frame does not have FIR windows.',upper(mfilename));
       end
       Lw = F.winLen;
       switch(F.type)
         case 'fwt'
           % The SegDWT algorithm
           J = F.J;
           w = F.g;
           m = numel(w.g{1}.h);
           a = w.a(1);
           blocksize = a^J;
           r = (a^J-1)/(a-1)*(m-1);
           Lbrec = (floor(nextSb/blocksize) - floor(Sb/blocksize))*blocksize;
           rSb = (a^J-1)/(a-1)*(m-a) + mod(Sb,a^J);
           over = r - rSb;
           f = block_ifwt(c,w,J,Lbrec);
           ol = loadOverlap(r-mod(Sb, a^J),size(c,2),fola);
           olLen = size(ol,1);
           f(1:olLen-over,:) = f(1:olLen-over,:) + ol(1+over:end,:);
           f = [ol(1:over,:);f];
           if nargout>1
              fola=storeOverlap(f,r-mod(nextSb, a^J));
           else
              storeOverlap(f,r-mod(nextSb, a^J));
           end
           fhat = f(1:Lb,:);
          case {'dgt','dgtreal','dwilt','wmdct'}
           % Time step
           a = F.a;
           % Length of the left half of the window
           Lwl = floor(Lw/2);

           Sbonelmax =  ceil((Lw-1)/a)*a + a-1;
           Sbolen = ceil((Lw-1)/a)*a + mod(Sb,a);
           % Next block overlap length
           nextSbolen = ceil((Lw-1)/a)*a + mod(nextSb,a);
           Lext = Sbolen + Lb - mod(nextSb,a);
           Lextc = Sbolen + Lb - nextSbolen + Lwl;

           startc = ceil(Lwl/a)+1;
           endc = ceil((Lextc)/a);

           cc = F.coef2native(c,size(c));
           chat = zeros(size(cc,1),ceil(F.L/a),size(cc,3),class(cc));
           chat(:,startc:endc,:) = cc;
           chat = F.native2coef(chat);
           f = F.frsyn(chat);
           f = f(1:Lext,:);
           over = Sbonelmax - Sbolen;

           ol = loadOverlap(Sbonelmax-mod(Sb,a),size(c,2),fola);
           olLen = size(ol,1);
           f(1:olLen-over,:) = f(1:olLen-over,:) + ol(1+over:end,:);
           f = [ol(1:over,:);f];
           if nargout>1
              fola=storeOverlap(f,Sbonelmax-mod(nextSb,a));
           else
              storeOverlap(f,Sbonelmax-mod(nextSb,a));
           end
           fhat = f(1:Lb,:);
          case {'filterbank','filterbankreal'}
           lcma = F.lcma;
           % Time step
           a = F.a(:,1);
           % Length of the left half of the window
           Lwl = max(-F.g_info.offset);

                if Lw-1 < a
           Sbonelmax =   lcma-1;
           Sbolen =  mod(Sb,lcma);
           nextSbolen = mod(nextSb,lcma);
                else
           Sbonelmax =  ceil((Lw-1)/lcma)*lcma + lcma-1;
           Sbolen = ceil((Lw-1)/lcma)*lcma + mod(Sb,lcma);
           nextSbolen = ceil((Lw-1)/lcma)*lcma + mod(nextSb,lcma);
                end

           Lext = Sbolen + Lb - mod(nextSb,lcma);
           Lextc = Sbolen + Lb - nextSbolen + Lwl;

           startc = ceil(Lwl./a)+1;
           endc = ceil((Lextc)./a);

           cc = F.coef2native(c,size(c));

           chat = cell(numel(cc),1);
           for ii=1:numel(cc)
              chat{ii} = zeros(ceil(F.L./a(ii)),size(cc{ii},2));
              chat{ii}(startc(ii):endc(ii),:) = cc{ii};
           end

           chat = F.native2coef(chat);
           f = F.frsyn(chat);
           f = f(1:Lext,:);
           over = Sbonelmax - Sbolen;

           ol = loadOverlap(Sbonelmax-mod(Sb,lcma),size(c,2),fola);
           olLen = size(ol,1);
           f(1:olLen-over,:) = f(1:olLen-over,:) + ol(1+over:end,:);
           f = [ol(1:over,:);f];
           if nargout>1
              fola=storeOverlap(f,Sbonelmax-mod(nextSb,lcma));
           else
              storeOverlap(f,Sbonelmax-mod(nextSb,lcma));
           end
           fhat = f(1:Lb,:);
          otherwise
           error('%s: Unsupported frame.',upper(mfilename));
        end

    else
       error('%s: Frame was not created with blockaccel.',upper(mfilename));
    end

end

function overlap = loadOverlap(L,chan,overlap)
%LOADOVERLAP Loads overlap
%
%
   if isempty(overlap)
      overlap = block_interface('getSynOverlap');
   end

   if isempty(overlap)
     overlap = zeros(L,chan,block_interface('getClassId'));
   end
   Lo = size(overlap,1);
   if nargin<1
      L = Lo;
   end
   if L>Lo
      % Required more samples than stored
      if 0
         error('%s: Required more samples than stored.',upper(mfilename));
      else
         % pad with zeros
         overlapTmp = zeros(L,chan,block_interface('getClassId'));
         overlapTmp(end-Lo+1:end,:) = overlap;
         overlap = overlapTmp;
      end
   end
   overlap = overlap(end-L+1:end,:);
end

function overlap = storeOverlap(fext,L)
%STOREOVERLAP Stores overlap
%
%
    if L>size(fext,1)
        error('%s: Storing more samples than passed.',upper(mfilename));
    end
    overlap = fext(end-L+1:end,:);

    if nargout<1
       block_interface('setSynOverlap',overlap);
    end
end % STOREOVERLAP


function varargout = HoughObject(varargin)
% HOUGHOBJECT M-file for HoughObject.fig
%      HOUGHOBJECT, by itself, creates a new HOUGHOBJECT or raises the existing
%      singleton*.
%
%      H = HOUGHOBJECT returns the handle to a new HOUGHOBJECT or the handle to
%      the existing singleton*.
%
%      HOUGHOBJECT('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in HOUGHOBJECT.M with the given input arguments.
%
%      HOUGHOBJECT('Property','Value',...) creates a new HOUGHOBJECT or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before HoughObject_OpeningFunction gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to HoughObject_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help HoughObject

% Last Modified by GUIDE v2.5 07-Dec-2005 20:15:07

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @HoughObject_OpeningFcn, ...
                   'gui_OutputFcn',  @HoughObject_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before HoughObject is made visible.
function HoughObject_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to HoughObject (see VARARGIN)

% Choose default command line output for HoughObject
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes HoughObject wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = HoughObject_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

% --- Executes on button press in pbGenerate.
function pbGenerate_Callback(hObject, eventdata, handles)
% hObject    handle to pbGenerate (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
load ObjectTemplate
S1 = zeros(180,180);
Str = {'Sq','Sc','St'};

a = 1; b = 3;
x = round(a + (b-a) * rand(1));
S2 = eval(Str{x});

a = 1; b = 90;
x = round(a + (b-a) * rand(1));
S3 = imrotate(S2,x);

S = S1;
sz = size(S3);

a = 1; b = min(sz);
x = round(a + (b-a) * rand(1));

S(x:sz(1)+x-1,x:sz(2)+x-1)=S3;
S = im2bw(S);
axes(handles.axes1);

imshow(S);
title('Original Image');
handles.S = S;
guidata(hObject, handles);

% --- Executes on button press in pnHough.
function pnHough_Callback(hObject, eventdata, handles)
% hObject    handle to pnHough (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
S = handles.S;
[H, theta,rho]=hough(S);
axes(handles.axes2);
imshow(H,[],'xdata',theta,'ydata',rho);
xlabel('\theta'),ylabel('\rho')
axis on, axis normal;
title('Hough Matrix');

clear data;
for cnt = 1:max(max(H))
    data(cnt) = sum(sum(H == cnt));
end
axes(handles.axes3);
%data(data==0)=NaN;
plot(data,'--x');
xlabel('Hough Matrix Intensity'),ylabel('Counts')
handles.data = data;
guidata(hObject, handles);

% --- Executes on button press in pbDetect.
function pbDetect_Callback(hObject, eventdata, handles)
% hObject    handle to pbDetect (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
data = handles.data;
[maxval,maxind] = max(data);
medval = median(data);

[p]=polyfit(1:maxind-5,data(1:maxind-5),2);

if maxval<3*medval
    set(handles.txtResult,'string','Triangle');
elseif  p(3)>100
    set(handles.txtResult,'string','Square');
else
    set(handles.txtResult,'string','Round');
end

% --- Executes on button press in pbInfo.
function pbInfo_Callback(hObject, eventdata, handles)
% hObject    handle to pbInfo (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
web('http://basic-eng.blogspot.com', '-browser');


function RoPSs = RoPSFunc(mesh,neighborSize,binSize, rotaSize, LocalFrames)

%  Author: Yulan Guo {yulan.guo@nudt.edu.cn}
%  NUDT, China & CSSE, UWA, Australia
%
% This function takes a mesh and local reference frames (LRFs) for a set of
% keypoints as an input, and generate RoPS feature descriptors for the
% keypoints as an output. An illustration is shown in Fig4 in Ref.[1].
%
% Arguments : mesh - with vertices and faces
%                       neighborSize - the size of neighborhood to define a
%                                                  local surface for a selected keypoint
%                       binSize - number of bins for 2D plane partition
%                       rotaSize - number of rotations around each coordinate axis
%                       LocalFrames - local reference frames corresponding to all
%                                                keypoints of the input mesh

% Return :         RoPS - RoPS feature descriptors corresponding to all
%                                     keypoints
%
% Copyright : This code is written by Yulan Guo {yulan.guo@nudt.edu.cn}, NUDT.
%               The code may be used, modified and distributed for research purposes with
%              acknowledgement of the author and inclusion this copyright information.
%References:
%           [1] Yulan Guo, Ferdous Sohel, Mohammed Bennamoun, Min Lu, Jianwei Wan.
%           Rotational Projection Statistics for 3D Local Surface Description and Object Recognition.
%           Internation Journal of Computer Vision. 2013, 105 (1), 63-86
%           [2] Yulan Guo, Mohammed Bennamoun, Ferdous A Sohel, Min Lu, Jianwei Wan.
%           3D Object Recognition in Cluttered Scenes with Local Surface Features: A Survey.
%           IEEE Transactions on Pattern Analysis and Machine Intelligence,2014
%
% Disclaimer: This code is provided as is without any warranty.

%%%%%%%%%%%% parallel computing to accelerate.
p = gcp('nocreate'); % If no pool, do not create new one.
if isempty(p)   % if exists no parallel computing handle, create one.
    poolsize = parpool;
    % disp('Create a Parallel Computing Pool to accelarate process' );
else
    poolsize = p.NumWorkers;
    % disp(sprintf( 'Parpool has %d workers', poolsize) );
end

keypntIdx = mesh.keypntIdx;
% BucketSize = floor(length(mesh.vertices)/100);
% kdtreeVertices = KDTreeSearcher(mesh.vertices,'Distance','euclidean','BucketSize',BucketSize);
% BucketSize = floor(length(mesh.vertices)/100);
kdtreeVertices = KDTreeSearcher(mesh.vertices,'Distance','euclidean');

interval = pi/2/rotaSize;
parfor i = 1:length(keypntIdx)
    %obtain the neighboring point of a keypoint
    keypnt = mesh.vertices(keypntIdx(i),:);
    [neighborIdx2,neighborDis]= rangesearch(kdtreeVertices,keypnt,neighborSize);
    neighborIdx2 = cell2mat(neighborIdx2);
    neighborIdx = neighborIdx2(2:end);
    neighbNum = length(neighborIdx);
    if neighbNum<=1
        RoPSs{i,1} = ones(rotaSize*45,1)/sum(ones(rotaSize*45,1));
        continue;
    end

    %transfom the neighboring point to the local reference frame (LRF)
    rotation = LocalFrames{i};
    neighbor = [];
    for j=1:neighbNum
        neighbor(j,:) = (mesh.vertices(neighborIdx(j),:)-mesh.vertices(keypntIdx(i),:))*inv(rotation);
    end

    RoPS = [];
   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %calculate the sub-feature of the keypoint along the Z axis
    for rotaIdx = 1:rotaSize
        rotaAngle = (rotaIdx-1)*interval + interval/2;
        R = [cos(rotaAngle) sin(rotaAngle) 0; -sin(rotaAngle) cos(rotaAngle) 0; 0 0 1]';
        rotaNeighbor = neighbor*R;
        %projection on the XY plane
        projNeighborXY = [rotaNeighbor(:,1),rotaNeighbor(:,2)];
        histTemp = subRoPSFunc(projNeighborXY,binSize);
        RoPS = [RoPS,histTemp];
        %projection on the XZ plane
        projNeighborXZ = [rotaNeighbor(:,1),rotaNeighbor(:,3)];
        histTemp = subRoPSFunc(projNeighborXZ,binSize);
        RoPS = [RoPS,histTemp];
        %projection on the YZ plane
        projNeighborYZ = [rotaNeighbor(:,2),rotaNeighbor(:,3)];
        histTemp = subRoPSFunc(projNeighborYZ,binSize);
        RoPS = [RoPS,histTemp];
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %calculate the sub-feature of the keypoint along the Y axis
    for rotaIdx = 1:rotaSize
        rotaAngle = (rotaIdx-1)*interval + interval/2;
        R = [cos(rotaAngle) 0 sin(rotaAngle); 0 1 0 ;-sin(rotaAngle) 0 cos(rotaAngle)]';
        rotaNeighbor = neighbor*R;
        %projection on the XY plane
        projNeighborXY = [rotaNeighbor(:,1),rotaNeighbor(:,2)];
        histTemp = subRoPSFunc(projNeighborXY,binSize);
        RoPS = [RoPS,histTemp];
        %projection on the XZ plane
        projNeighborXZ = [rotaNeighbor(:,1),rotaNeighbor(:,3)];
        histTemp = subRoPSFunc(projNeighborXZ,binSize);
        RoPS = [RoPS,histTemp];
        %projection on the YZ plane
        projNeighborYZ = [rotaNeighbor(:,2),rotaNeighbor(:,3)];
        histTemp = subRoPSFunc(projNeighborYZ,binSize);
        RoPS = [RoPS,histTemp];
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    end
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %calculate the sub-feature of the keypoint along the X axis
    for rotaIdx = 1:rotaSize
        rotaAngle = (rotaIdx-1)*interval + interval/2;
        R = [1,0,0; 0,cos(rotaAngle),sin(rotaAngle); 0, -sin(rotaAngle), cos(rotaAngle)]';
        rotaNeighbor = neighbor*R;
        %projection on the XY plane
        projNeighborXY = [rotaNeighbor(:,1),rotaNeighbor(:,2)];
        histTemp = subRoPSFunc(projNeighborXY,binSize);
        RoPS = [RoPS,histTemp];
        %projection on the XZ plane
        projNeighborXZ = [rotaNeighbor(:,1),rotaNeighbor(:,3)];
        histTemp = subRoPSFunc(projNeighborXZ,binSize);
        RoPS = [RoPS,histTemp];
        %projection on the YZ plane
        projNeighborYZ = [rotaNeighbor(:,2),rotaNeighbor(:,3)];
        histTemp = subRoPSFunc(projNeighborYZ,binSize);
        RoPS = [RoPS,histTemp];
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    RoPSs{i,1} = (RoPS)'/sum(RoPS);
end


function [HDR] = leadidcodexyz(arg1)
% LeadIdCodeXYZ uses the Label information for computing the
%       LeadIdCode and the XYZ position of the EEG Electrodes
%       according to Annex A of FEF Vital Signs Format [1]
%
%   HDR = leadidcodexyz(HDR);
%	adds HDR.LeadIdCode and HDR.ELEC.XYZ, if needed.
%
% see also: SLOAD, SOPEN, PHYSICALUNITS, doc/leadidtable_scpecg.txt, doc/elecpos.txt
%
% Reference(s):
% [1] CEN/TC251/PT40 (2001)
% 	File Exchange Format for Vital Signs - Annex A
%
% Birbaumer, N. (2006). Brain-computer-interface research: Coming of age. Clinical Neurophysiology, 117:479??3.
%  http://www.acns.org/pdfs/ACFDD46.pdf.
% ACNS (2006). Guidelines for standard electrode position nomenclature. American Clinical
% Neurophysiology Society. http://www.acns.org/pdfs/ACFDD46.pdf.

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

%	$Id: leadidcodexyz.m 2602 2011-02-03 13:05:03Z schloegl $
%	Copyright (C) 2006,2007,2008,2009 by Alois Schloegl <a.schloegl@ieee.org>
%    	This is part of the BIOSIG-toolbox http://biosig.sf.net/

global BIOSIG_GLOBAL;
% BIOSIG_GLOBAL=[]; %%% used for debugging, only.

if ~isfield(BIOSIG_GLOBAL,'Phi');
	BIOSIG_GLOBAL.ISLOADED_XYZ = 0 ;
end;
if ~isfield(BIOSIG_GLOBAL,'ISLOADED_XYZ')
	BIOSIG_GLOBAL.ISLOADED_XYZ = 0 ;
end;
if ~BIOSIG_GLOBAL.ISLOADED_XYZ;
    f = which('getfiletype.m'); 	% identify path to biosig
    [p,f,e] = fileparts(f);
    [p,f,e] = fileparts(p);

    BIOSIG_GLOBAL.ISLOADED_XYZ = 0 ;

    N = 0;
    fid = fopen(fullfile(p,f,'leadidtable_scpecg.txt'),'r');
    s = char(fread(fid,[1,inf],'uint8'));
    fclose(fid);

    Code = repmat(NaN, 200, 1); Phi = Code; Theta = Code;
    while ~isempty(s),
        [t,s] = strtok(s,[10,13]);
        if ~length(t)
        elseif ~strncmp(t,'#',1)
            ix3 = strfind(t,'MDC_ECG_LEAD_');
            if isempty(ix3)
                ix3 = length(t)+1;
            end
            [t1,t2] = strtok(t(1:ix3-1),[9,32]);
            [t2,t3] = strtok(t2,[9,32]);
            id = str2double(t2);
            N  = N + 1;
            Labels{N,1}	  = t1;
            Code(N,1)         = id;
            Description{N,1}  = deblank(t3);
            %MDC_ECG_LEAD{N,1} = t(ix3+13:end)
            MDC_ECG_LEAD{N,1} = t(ix3:end);
        end;
    end;
    N1 = N;

        % load table
        fid = fopen(fullfile(p,f,'elecpos.txt'),'r');
        t = char(fread(fid,[1,inf],'uint8'));
        fclose(fid);

        % extract table information
        while ~isempty(t)
                [x,t] = strtok(t,[10,13]);
                if isempty(x)
                elseif strncmp(x,'#',1)
                else
                        N = N + 1;
                        [num,status,strarray] = str2double(x);
                        Code(N,1)   = num(1);
                        Labels{N,1} = upper(strarray{2});
                        Phi(N,1)    = num(3);
                        Theta(N,1)  = num(4);
                end;
        end;
        Phi   = Phi(:)  *pi/180;
        Theta = Theta(:)*pi/180;

        % loading is done only once.
        BIOSIG_GLOBAL.XYZ = [sin(Theta).*cos(Phi), sin(Theta).*sin(Phi), cos(Theta)];
        BIOSIG_GLOBAL.Phi          = Phi*180/pi;
        BIOSIG_GLOBAL.Theta        = Theta*180/pi;
        BIOSIG_GLOBAL.LeadIdCode   = Code;
        BIOSIG_GLOBAL.Label        = Labels;
        BIOSIG_GLOBAL.Description  = Description;
        BIOSIG_GLOBAL.MDC_ECG_LEAD = MDC_ECG_LEAD;

        BIOSIG_GLOBAL.ISLOADED_XYZ = 1;
end;

if nargin<1,
        HDR.LeadIdCode = BIOSIG_GLOBAL.LeadIdCode;
        HDR.Label      = BIOSIG_GLOBAL.Label;
        HDR.ELEC.XYZ   = BIOSIG_GLOBAL.XYZ;
        HDR.TYPE       = 'ELPOS';

else    % electrode code and position

        if isstruct(arg1)
                HDR = arg1;
        elseif isnumeric(arg1),
                HDR.LeadIdCode = arg1;
        else
                HDR.Label = arg1;
        end;

        tmp.flag1 = isfield(HDR,'ELEC');
        if tmp.flag1,
                tmp.flag1 = isfield(HDR.ELEC,'XYZ');
        end;
        if tmp.flag1,
                tmp.flag1 = any(HDR.ELEC.XYZ(:));
        end;
        tmp.flag2 = isfield(HDR,'LeadIdCode');
        tmp.flag3 = isfield(HDR,'Label');

        if (~tmp.flag1 || ~tmp.flag2 || ~tmp.flag3),
        	if 0,
        	elseif tmp.flag3,
                        if ischar(HDR.Label)
                                HDR.Label = cellstr(HDR.Label);
                        end;
	                NS = length(HDR.Label);
	        elseif tmp.flag2,
	        	NS = length(HDR.LeadIdCode);
        	elseif isfield(HDR,'NS')
        		NS = HDR.NS;
        		HDR.LeadIdCode = zeros(1,HDR.NS);
	        end;

                if tmp.flag3,
	                if ~tmp.flag1,
				HDR.ELEC.XYZ   = repmat(NaN,NS,3);
				HDR.ELEC.Phi   = repmat(NaN,NS,1);
				HDR.ELEC.Theta = repmat(NaN,NS,1);
	        	end;
                	if ~tmp.flag2,
                       		HDR.LeadIdCode = repmat(NaN,NS,1);
	        	end;
                	for k = 1:NS;
				Label = upper(deblank(HDR.Label{k}));
				pos = find(Label==':');
				if ~isempty(pos)
					Label = Label(pos+1:end);
                            	end;
	                        ix = strmatch(Label,BIOSIG_GLOBAL.Label,'exact');

	                        if length(ix)==2,
	                        	%%%%% THIS IS A HACK %%%%%
	                        	%% solve ambiguity for 'A1','A2'; could be EEG or ECG
	                        	if sum(HDR.LeadIdCode(1:k)>=996)>sum(HDR.LeadIdCode(1:k)<996)
	                        		%% majority are EEG electrodes,
	                        		ix = ix(find(BIOSIG_GLOBAL.LeadIdCode(ix)>996));
	                        	else
	                        		%% majority are ECG electrodes,
	                        		ix = ix(find(BIOSIG_GLOBAL.LeadIdCode(ix)<996));
	                        	end;
	                        elseif isempty(ix)
		                        ix = strmatch(deblank(HDR.Label{k}),BIOSIG_GLOBAL.MDC_ECG_LEAD,'exact');
	                        end;

        	                if (length(ix)==1),
	                	        if ~tmp.flag1,
        	                	        HDR.ELEC.XYZ(k,1:3) = BIOSIG_GLOBAL.XYZ(ix,:);
                	        	        HDR.ELEC.Phi(k)   = BIOSIG_GLOBAL.Phi(ix);
                        		        HDR.ELEC.Theta(k) = BIOSIG_GLOBAL.Theta(ix);
                        		end;
                	        	if ~tmp.flag2,
                                		HDR.LeadIdCode(k,1) = BIOSIG_GLOBAL.LeadIdCode(ix);
	                        	end;
        	                end;
                        end;
                else
			HDR.Label = cell(NS,1);
			for k = 1:NS;
				ix = find(BIOSIG_GLOBAL.LeadIdCode==HDR.LeadIdCode(k));
				if (length(ix)>=1),
					ix=ix(1);	%
	                                HDR.Label{k} = BIOSIG_GLOBAL.Label{ix};
					if ~tmp.flag1,
        		                        HDR.ELEC.XYZ(k,1:3) = BIOSIG_GLOBAL.XYZ(ix,1:3);
        		                        HDR.ELEC.Phi(k,1)   = BIOSIG_GLOBAL.Phi(ix);
        		                        HDR.ELEC.Theta(k,1) = BIOSIG_GLOBAL.Theta(ix);
					end;
				else
					HDR.Label{k} = ['#',int2str(k)];
				end;
			end;
                end;
	end;
	if tmp.flag3 && ~any(HDR.LeadIdCode),
               	for k = 1:HDR.NS;
			ix = strmatch(upper(HDR.Label{k}),BIOSIG_GLOBAL.Label,'exact');
			if length(ix)==1,
				HDR.LeadIdCode(k) = BIOSIG_GLOBAL.LeadIdCode(ix);
			end;
		end;
        end;

end;


function s = ymdf_to_s_common ( y, m, d, f )

%*****************************************************************************80
%
%% YMDF_TO_S_COMMON writes a Common YMDF date into a string.
%
%  Format:
%
%    CE YYYY/MM/DD.FF
%    BCE YYYY/MM/DD.FF
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 December 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer Y, integer M, integer D, real F, the YMDF date.
%
%    Output, string S, a representation of the date.
%

%
%  Copy the input.
%
  y2 = y;
  m2 = m;
  d2 = d;
  f2 = f;
%
%  Check the input.
%
  [ y2, m2, d2, f2, ierror ] = ymdf_check_common ( y2, m2, d2, f2 );

  if ( ierror ~= 0 )
    s = sprintf ( '?' );
    return
  end

  if ( 0 <= y2 )
    s = sprintf ( 'CE %d/%d/%d/%f', y2, m2, d2, f2 );
  else
    s = sprintf ( 'BCE %d/%d/%d/%f', -y2, m2, d2, f2 );
  end

  return
end


% Authors: A. Iscen, G. Tolias, Y. Avrithis, T. Furon, O. Chum. 2017.
% create truncated Laplacian
function L = trunclap(A, sub, alpha)

    T = transition_matrix(A(sub, sub));
    L = speye(size(T)) - alpha * T;


function time = compute_wait(plaza)
[a,b] = size(plaza);
time = 0;
for i = 1:a
for j = 1:b
time = time + (plaza(i,j) > 0);
end
end

github-repos/MATLAB/Eurus-Holmes-Mathematical_Modeling/Mathematical_Modeling-cb9dd53af84ffbd455ec62ab89886351e0ec98d9/Cellular automaton/元胞自动机/1月13日课件（元胞自动机）/程序/The Booth Tolls for Thee/compute_wait.m


function segment_length = p14_boundary_segment_length ( segment_index, h )

%*****************************************************************************80
%
%% P14_BOUNDARY_SEGMENT_LENGTH returns boundary segment lengths in problem 14.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer SEGMENT_INDEX, the index of one of the boundary segments.
%
%    Input, real H, the suggested spacing between points.
%
%    Output, integer SEGMENT_LENGTH, the number of points in the segment.
%
  n1 = 90;
  n2 = 11;

  v1 = [ ...
    316.43027, 404.47559; ...
    291.04946, 400.70917; ...
    265.16504, 409.77890; ...
    241.46794, 402.40310; ...
    216.55145, 396.52064; ...
    163.28492, 411.37102; ...
    142.81752, 391.16355; ...
    111.95404, 346.70264; ...
    100.03538, 325.72710; ...
    103.98723, 302.51587; ...
    128.72978, 285.72802; ...
    147.49111, 266.23345; ...
    196.65261, 242.24055; ...
    213.56835, 221.67192; ...
    226.49969, 198.09326; ...
    248.37126, 183.50473; ...
    262.21952, 165.39102; ...
    278.42330, 149.91715; ...
    300.71846, 145.82601; ...
    311.12698, 166.71094; ...
    326.66315, 184.58335; ...
    359.78574, 225.48049; ...
    357.08892, 252.88958; ...
    358.76685, 285.34403; ...
    361.50834, 303.71287; ...
    371.68926, 314.92452; ...
    380.49890, 324.58632; ...
    396.37634, 328.88990; ...
    412.59116, 327.25238; ...
    425.48394, 315.28623; ...
    435.84305, 302.44664; ...
    458.34025, 297.55121; ...
    479.66439, 288.99238; ...
    493.09812, 270.20636; ...
    518.87309, 264.56427; ...
    547.18014, 268.18846; ...
    600.49708, 240.62570; ...
    625.96183, 238.40347; ...
    633.90530, 260.70629; ...
    621.50451, 285.88914; ...
    576.87224, 322.14121; ...
    570.51915, 348.85423; ...
    567.16400, 378.24075; ...
    558.00668, 406.86552; ...
    565.19008, 435.75599; ...
    567.56437, 465.33407; ...
    550.87626, 490.96358; ...
    532.98174, 515.84491; ...
    500.66817, 551.89078; ...
    478.75120, 562.17222; ...
    430.03371, 583.94286; ...
    401.20454, 587.69910; ...
    368.32214, 581.10110; ...
    354.26303, 585.86085; ...
    346.75200, 601.10367; ...
    332.85137, 628.74602; ...
    308.02188, 645.84180; ...
    295.52344, 647.18525; ...
    286.51519, 651.60328; ...
    285.98846, 662.07339; ...
    298.93455, 665.66316; ...
    301.70226, 682.79570; ...
    278.65857, 689.63850; ...
    266.25737, 712.11005; ...
    287.28701, 732.77147; ...
    318.19548, 736.85151; ...
    343.83067, 753.60957; ...
    375.53164, 758.35231; ...
    405.73444, 768.98687; ...
    406.33873, 785.59001; ...
    378.35436, 789.44240; ...
    350.02151, 795.02238; ...
    338.68030, 788.87325; ...
    325.67930, 786.10177; ...
    319.05995, 798.04657; ...
    301.78158, 795.34254; ...
    280.69272, 773.86634; ...
    254.55844, 758.02898; ...
    234.07759, 737.42090; ...
    218.38337, 711.41500; ...
    220.99086, 682.17833; ...
    224.50640, 651.96297; ...
    240.25971, 631.36117; ...
    259.86174, 612.60253; ...
    291.85381, 556.70385; ...
    315.52139, 537.56387; ...
    341.63663, 520.12519; ...
    351.37130, 458.75372; ...
    349.33183, 431.31454; ...
    328.80465, 412.43055 ]';
  v2 = [ ...
    238.64853, 266.58978; ...
    235.14026, 287.95183; ...
    238.20736, 303.46785; ...
    250.13902, 303.71290; ...
    258.51675, 297.46973; ...
    274.55300, 291.27357; ...
    284.66230, 280.72063; ...
    279.73288, 267.83455; ...
    270.68478, 255.55440; ...
    255.73801, 249.16872; ...
    241.72690, 256.73448 ]';

  if ( h <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'P14_BOUNDARY_SEGMENT_LENGTH - Fatal error!' );
    fprintf ( 1, '  Nonpositive H = %f\n', h );
    error ( 'P14_BOUNDARY_SEGMENT_LENGTH - Fatal error!' );
  end

  if ( segment_index == 1 )

    length = polyloop_length_nd ( 2, n1, v1 ) ;

  elseif ( segment_index == 2 )

    length = polyloop_length_nd ( 2, n2, v2 );

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, 'P14_BOUNDARY_SEGMENT_LENGTH - Fatal error!' );
    fprintf ( 1, '  Illegal SEGMENT_INDEX = %d\n', segment_index );
    error ( 'P14_BOUNDARY_SEGMENT_LENGTH - Fatal error!' );

  end

  n = round ( length / h );

  segment_length = n;

  return
end