% PAC_CONT - compute phase-amplitude coupling (power of first input
%         correlation with phase of second). There is no graphical output
%         to this function.
%
% Usage:
%   >> pac_cont(x,y,srate);
%   >> [pac timesout pvals] = pac_cont(x,y,srate,'key1', 'val1', 'key2', val2' ...);
%
% Inputs:
%    x       = [float array] 1-D data vector of size (1xtimes)
%    y       = [float array] 1-D data vector of size (1xtimes)
%    srate   = data sampling rate (Hz)
%
% Optional time information inputs:
%   'winsize'   = If cycles==0: data subwindow length (fastest, 2^n<frames);
%                 If cycles >0: *longest* window length to use. This
%                 determines the lowest output frequency. Note that this
%                 parameter is overwritten if the minimum frequency has been set
%                 manually and requires a longer time window {~frames/8}
%   'ntimesout' = Number of output times (int<frames-winframes). Enter a
%                 negative value [-S] to subsample original time by S.
%   'timesout'  = Enter an array to obtain spectral decomposition at
%                 specific time values (note: algorithm find closest time
%                 point in data and this might result in an unevenly spaced
%                 time array). Overwrite 'ntimesout'. {def: automatic}
%   'tlimits'   = [min max] time limits in ms.
%
% Optional PAC inputs:
%   'method'    = ['modulation'|'plv'|'corr'|'glm'] (see reference).
%   'freqphase' = [min max] frequency limits. Default [minfreq 50],
%                 minfreq being determined by the number of data points,
%                 cycles and sampling frequency. Use 0 for minimum frequency
%                 to compute default minfreq. You may also enter an
%                 array of frequencies for the spectral decomposition
%                 (for FFT, closest computed frequency will be returned; use
%                 'padratio' to change FFT freq. resolution).
%   'freqamp'   = [float array] array of frequencies for the second
%                 argument. 'freqs' is used for the first argument.
%                 By default it is the same as 'freqs'.
%   'filterfunc' = ['eegfilt'|'iirfilt'|'eegfftfilt'] filtering function.
%                 Default is iirfilt. Warning, filtering may dramatically
%                 affect the result. With the 'corr' method, make sure you
%                 have a large window size because each window is filtered
%                 independently.
%   'filterphase' = @f_handle. Function handle to filter the data for the
%                 phase information. For example, @(x)iirfilt(x, 1000, 2,
%                 20). Note that 'freqphase' is ignore in this case.
%   'filteramp' = @f_handle. Function handle to filter the data for the
%                 amplitude information. Note that 'freqamp' is ignore in
%                 this case.
%
% Inputs for statistics:
%   'alpha'     = [float] p-value threshold. Default is none (no statistics).
%   'mcorrect'  = ['none'|'fdr'] method to correct for multiple comparison.
%                 Default is 'none'.
%   'baseline'  = [min max] baseline period for the Null distribution. Default
%                 is the whole data range. Note that this option is ignored
%                 for instanstaneous statistics.
%   'instantstat' = ['on'|'off'] performs statistics for each time window
%                 independently. Default is 'off'.
%   'naccu'     = [integer] number of accumulations for surrogate
%                 statistics.
%   'statlim'   = ['parametric'|'surrogate'] use a parametric methods to
%                 asseess the limit of the surrogate distribution or use
%                 the tail of the distribution ('surrogate' method)
%
% Other inputs:
%   'title'     = [string] figure title. Default is none.
%   'vert'      = [float array] array of time value for which to plot
%                 vertical lines. Default is none.
%
% Outputs:
%  pac      = Phase-amplitude coupling values.
%  timesout = vector of time indices
%  pvals    = Associated p-values
%
% Author: Arnaud Delorme and Makoto Miyakoshi, SCCN/INC, UCSD 2012-
%
% References:
% Methods used here are introduced and compared in:
% Penny, Duzel, Miller, Ojemann. (20089). Testing for Nested Oscilations.
% J Neuro Methods. 174:50-61
%
% Modulation Index is defined in:
% Canolty, Edwards, Dalal, Soltani, Nagarajan, Kirsch, et al. (2006). Modulation index is defined in High Gamma Power Is Phase-Locked to Theta
% Oscillations in Human Neocortex. Science. 313:1626-8.
%
% PLV (Phase locking value) is defined in:
% Lachaux, Rodriguez, Martiniere, Varela. (1999). Measuring phase synchrony
% in brain signal. Hum Brain Mapp. 8:194-208.
%
% corr (correlation) method is defined in:
% Brunce, Eckhorn. (2004). Task-related coupling from high- to
% low-frequency signals among visual cortical areas in human subdural
% recordings. Int J Psychophysiol. 51:97-116.
%
% glm (general linear model) is defined in
% Penny, Duzel, Miller, Ojemann. (20089). Testing for Nested Oscilations.
% J Neuro Methods. 174:50-61

% Copyright (C) 2012 Arnaud Delorme, UCSD
%
% 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.

function [m_raw pvals indexout] = pac_cont(X, Y, srate, varargin);

if nargin < 1
    help pac_cont;
    return;
end

% deal with 3-D inputs
% --------------------
if ndims(X) == 3 || ndims(Y) == 3, error('Cannot process 3-D input'); end
if size(X,1) > 1, X = X'; end
if size(Y,1) > 1, Y = Y'; end
if size(X,1) ~= 1 || size(Y,1) ~= 1, error('Cannot only process vector input'); end
frame = size(X,2);
pvals = [];

g = finputcheck(varargin, ...
    { ...
    'alpha'         'real'     [0 0.2]                [];
    'baseline'      'float'    []                       [];
    'freqphase'     'real'     [0 Inf]                  [0 srate/2];
    'freqamp'       'real'     [0 Inf]                  [];
    'mcorrect'      'string'   { 'none' 'fdr' }         'none';
    'method'        'string'   { 'plv' 'modulation' 'glm' 'corr' } 'modulation';
    'naccu'         'integer'  [1 Inf]                   250;
    'instantstat'   'string'   {'on','off'}              'off';
    'newfig'        'string'   {'on','off'}              'on';
    'nofig'         'string'   {'on','off'}              'off';
    'statlim'       'string'   {'surrogate','parametric'}  'parametric';
    'timesout'      'real'     []                        []; ...
    'filterfunc'    'string'   { 'eegfilt' 'iirfilt' 'eegfiltfft' }   'eegfiltfft'; ...
    'filterphase'   ''         {}                        [];
    'filteramp'     ''         {}                        [];
    'ntimesout'     'integer'  []                        200; ...
    'tlimits'       'real'     []                        [0 frame/srate];
    'title'         'string'   []                        '';
    'vert'          'real'     []                    [];
    'winsize'       'integer'  [0 Inf]                   max(pow2(nextpow2(frame)-3),4) }, 'pac');

if ischar(g), error(g); end

if ~isempty(g.filterphase)
     x_freqphase = feval(g.filterphase, X(:)');
else x_freqphase = feval(g.filterfunc, X(:)', srate, g.freqphase(1), g.freqphase(end));
end
if ~isempty(g.filteramp)
     x_freqamp   = feval(g.filteramp, Y(:)');
else x_freqamp   = feval(g.filterfunc, Y(:)', srate, g.freqamp(  1), g.freqamp( end));
end
z_phasedata = hilbert(x_freqphase);
z_ampdata   = hilbert(x_freqamp);
phase       = angle(z_phasedata);
amplitude   = abs(  z_ampdata);
z           = amplitude.*exp(i*phase); % this is the pac measure

% get time windows
% ----------------
g.verbose = 'on';
g.causal  = 'off';
[ timesout1 indexout ] = gettimes(frame, g.tlimits, g.timesout, g.winsize, g.ntimesout, g.causal, g.verbose);

% scan time windows
% -----------------
if ~isempty(g.alpha)
    m_raw = zeros(1,length(indexout));
    pvals = zeros(1,length(indexout));
end
fprintf('Computing PAC:\n');
for iWin = 1:length(indexout)
    x_phaseEpoch = x_freqphase(indexout(iWin)+[-g.winsize/2+1:g.winsize/2]);
    x_ampEpoch   = x_freqamp(  indexout(iWin)+[-g.winsize/2+1:g.winsize/2]);
    z_phaseEpoch = z_phasedata(indexout(iWin)+[-g.winsize/2+1:g.winsize/2]);
    z_ampEpoch   = z_ampdata(  indexout(iWin)+[-g.winsize/2+1:g.winsize/2]);
    z_epoch      = z(          indexout(iWin)+[-g.winsize/2+1:g.winsize/2]);

    numpoints=length(x_phaseEpoch);
    if rem(iWin,10) == 0,  verboseprintf(g.verbose, ' %d',iWin); end
    if rem(iWin,120) == 0, verboseprintf(g.verbose, '\n'); end

    % Choose method
    % -------------
    if strcmpi(g.method, 'modulation')

        % Modulation index
        m_raw(iWin) = abs(sum(z_epoch))/numpoints;

    elseif strcmpi(g.method, 'plv')

        if iWin == 145
            %dsfsd;
        end

        %amplitude_filt = sgolayfilt(amplitude, 3, 101);
        if ~isempty(g.filterphase)
             amplitude_filt = feval(g.filterphase, z_ampEpoch);
        else amplitude_filt = feval(g.filterfunc , z_ampEpoch, srate, g.freqphase(1), g.freqphase(end));
        end
        z_amplitude_filt = hilbert(amplitude_filt);

        phase_amp_modulation = angle(z_amplitude_filt);
        m_raw(iWin) = abs(sum(exp(i*(x_phaseEpoch - phase_amp_modulation)))/numpoints);

    elseif strcmpi(g.method, 'corr')

        if iWin == inf %145
            figure; plot(abs(z_ampdata))
            hold on; plot(x_phasedata/10000000000, 'r')
            x = X(indexout(iWin)+[-g.winsize/2+1:g.winsize/2]);
            hold on; plot(x, 'g');
            dsfsd;
        end
        [r_ESC pval_corr] = corrcoef(x_phaseEpoch, abs(z_ampEpoch));
        m_raw(iWin)   = r_ESC(1,2);
        pvals(iWin)   = pval_corr(1,2);

    elseif strcmpi(g.method, 'glm')

        [b dev stats] = glmfit(x_phaseEpoch', abs(z_ampEpoch)', 'normal');
        GLM_beta      = stats.beta(2,1);
        pvals(iWin)   = stats.p(2,1);
        m_raw(iWin)   = b(1);

    end

    %% compute statistics (instantaneous)
    % -----------------------------------
    if ~isempty(g.alpha) && strcmpi(g.instantstat, 'on') && ~strcmpi(g.method, 'corr') && ~strcmpi(g.method, 'glm')

        % compute surrogate values
        numsurrogate=g.naccu;
        minskip=srate;
        maxskip=numpoints-srate; % max variation half a second
        if maxskip < 1
            error('Window size shorter than 1 second; too short for computing surrogate data');
        end
        skip=ceil(numpoints.*rand(numsurrogate*4,1));
        skip(skip>maxskip)=[];
        skip(skip<minskip)=[];
        skip=skip(1:numsurrogate,1);
        surrogate_m=zeros(numsurrogate,1);
        for s=1:numsurrogate
            surrogate_amplitude=[amplitude(skip(s):end) amplitude(1:skip(s)-1)]; % consider circular shifts
            surrogate_m(s)=abs(mean(surrogate_amplitude.*exp(i*phase)));
            %disp(numsurrogate-s)
        end

        if strcmpi(g.statlim, 'surrogate')
            pvals(iWin) = stat_surrogate_pvals(surrogate_m, m_raw(iWin), 'upper');
            %fprintf('Raw PAC is %3.2f (p-value=%1.3f)\n', m_raw(iWin), pvals(iWin));

        else
            % Canolty method below

            %% fit gaussian to surrogate data, uses normfit.m from MATLAB Statistics toolbox
            [surrogate_mean,surrogate_std]=normfit(surrogate_m);

            %% normalize length using surrogate data (z-score)
            m_norm_length=(abs(m_raw(iWin))-surrogate_mean)/surrogate_std;
            pvals(iWin)  = normcdf(0, m_norm_length, 1);
            m_norm_phase=angle(m_raw(iWin));
            m_norm=m_norm_length*exp(i*m_norm_phase);

            % compare parametric and non-parametric methods (return similar
            % results)
            if iWin == length(indexout)
                figure;
                plot(-log10(pvals));
                hold on; plot(-log10(pvals2), 'r');
            end
        end
    end

end
fprintf('\n');

% Computes alpha
% --------------
if ~isempty(g.alpha) && strcmpi(g.instantstat, 'off')
    if isempty(g.baseline)
        g.baseline = [ timesout1(1) timesout1(end) ];
    end
    baselineInd = find(timesout1 >= g.baseline(1) & timesout1 <= g.baseline(end));

    m_raw_base = abs(m_raw(baselineInd));

    if strcmpi(g.statlim, 'surrogate')
        for index = 1:length(m_raw)
            pvals(index) = stat_surrogate_pvals(m_raw_base, m_raw(index), 'upper');
        end
    else
        [surrogate_mean,surrogate_std]=normfit(m_raw_base);
        m_norm_length=(abs(m_raw)-surrogate_mean)/surrogate_std;
        pvals = normcdf(0, m_norm_length, 1);
    end
    if strcmpi(g.mcorrect, 'fdr')
        pvals = fdr(pvals);
    end
end

%% plot results
% -------------
if strcmpi(g.nofig, 'on')
    return
end
if strcmpi(g.newfig, 'on')
    figure;
end
if ~isempty(g.alpha)
    plotcurve(timesout1, m_raw, 'maskarray', pvals < g.alpha);
else plotcurve(timesout1, m_raw);
end
xlabel('Time (ms)');
ylabel('PAC (0 to 1)');
title(g.title);

% plot vertical lines
% -------------------
if ~isempty(g.vert)
    hold on;
    yl = ylim;
    for index = 1:length(g.vert)
        plot([g.vert(index) g.vert(index)], yl, 'g');
    end
end

% -------------
% gettime function identical to timefreq function
% DO NOT MODIFY
% -------------
function [ timevals, timeindices ] = gettimes(frames, tlimits, timevar, winsize, ntimevar, causal, verbose);
timevect = linspace(tlimits(1), tlimits(2), frames);
srate    = 1000*(frames-1)/(tlimits(2)-tlimits(1));

if isempty(timevar) % no pre-defined time points
    if ntimevar(1) > 0
        % generate linearly space vector
        % ------------------------------
        if (ntimevar > frames-winsize)
            ntimevar = frames-winsize;
            if ntimevar < 0
                error('Not enough data points, reduce the window size or lowest frequency');
            end
            verboseprintf(verbose, ['Value of ''timesout'' must be <= frame-winsize, ''timesout'' adjusted to ' int2str(ntimevar) '\n']);
        end
        npoints = ntimevar(1);
        wintime = 500*winsize/srate;
        if strcmpi(causal, 'on')
             timevals = linspace(tlimits(1)+2*wintime, tlimits(2), npoints);
        else timevals = linspace(tlimits(1)+wintime, tlimits(2)-wintime, npoints);
        end
        verboseprintf(verbose, 'Generating %d time points (%1.1f to %1.1f ms)\n', npoints, min(timevals), max(timevals));
    else
        % subsample data
        % --------------
        nsub     = -ntimevar(1);
        if strcmpi(causal, 'on')
            timeindices = [ceil(winsize+nsub):nsub:length(timevect)];
        else timeindices = [ceil(winsize/2+nsub/2):nsub:length(timevect)-ceil(winsize/2)-1];
        end
        timevals    = timevect( timeindices ); % the conversion at line 741 leaves timeindices unchanged
        verboseprintf(verbose, 'Subsampling by %d (%1.1f to %1.1f ms)\n', nsub, min(timevals), max(timevals));
    end
else
    timevals = timevar;
    % check boundaries
    % ----------------
    wintime = 500*winsize/srate;
    if strcmpi(causal, 'on')
         tmpind  = find( (timevals >= tlimits(1)+2*wintime-0.0001) & (timevals <= tlimits(2)) );
    else tmpind  = find( (timevals >= tlimits(1)+wintime-0.0001) & (timevals <= tlimits(2)-wintime+0.0001) );
    end
    % 0.0001 account for numerical innacuracies on opteron computers
    if isempty(tmpind)
        error('No time points. Reduce time window or minimum frequency.');
    end
    if  length(timevals) ~= length(tmpind)
        verboseprintf(verbose, 'Warning: %d out of %d time values were removed (now %3.2f to %3.2f ms) so the lowest\n', ...
            length(timevals)-length(tmpind), length(timevals), timevals(tmpind(1)), timevals(tmpind(end)));
        verboseprintf(verbose, '         frequency could be computed with the requested accuracy\n');
    end
    timevals = timevals(tmpind);
end

% find closet points in data
% --------------------------
timeindices = round(eeg_lat2point(timevals, 1, srate, tlimits, 1E-3));
if length(timeindices) < length(unique(timeindices))
    timeindices = unique_bc(timeindices)
    verboseprintf(verbose, 'Warning: duplicate times, reduce the number of output times\n');
end
if length(unique(timeindices(2:end)-timeindices(1:end-1))) > 1
    verboseprintf(verbose, 'Finding closest points for time variable\n');
    verboseprintf(verbose, 'Time values for time/freq decomposition is not perfectly uniformly distributed\n');
else
    verboseprintf(verbose, 'Distribution of data point for time/freq decomposition is perfectly uniform\n');
end
timevals    = timevect(timeindices);

function verboseprintf(verbose, varargin)
if strcmpi(verbose, 'on')
    fprintf(varargin{:});
end


function yout = poolDataLIST_CONTROL(yin,ahat,nVars,polyorder,usesine)
% Copyright 2015, All Rights Reserved
% Code by Steven L. Brunton
% For Paper, "Discovering Governing Equations from Data:
%        Sparse Identification of Nonlinear Dynamical Systems"
% by S. L. Brunton, J. L. Proctor, and J. N. Kutz

n = size(yin,1);

ind = 1;
% poly order 0
yout{ind,1} = ['1'];
ind = ind+1;

% poly order 1
for i=1:nVars
    yout(ind,1) = yin(i);
    ind = ind+1;
end

if(polyorder>=2)
    % poly order 2
    for i=1:nVars
        for j=i:nVars
            yout{ind,1} = [yin{i},yin{j}];
            ind = ind+1;
        end
    end
end

if(polyorder>=3)
    % poly order 3
    for i=1:nVars
        for j=i:nVars
            for k=j:nVars
                yout{ind,1} = [yin{i},yin{j},yin{k}];
                ind = ind+1;
            end
        end
    end
end

if(polyorder>=4)
    % poly order 4
    for i=1:nVars
        for j=i:nVars
            for k=j:nVars
                for l=k:nVars
                    yout{ind,1} = [yin{i},yin{j},yin{k},yin{l}];
                    ind = ind+1;
                end
            end
        end
    end
end

if(polyorder>=5)
    % poly order 5
    for i=1:nVars
        for j=i:nVars
            for k=j:nVars
                for l=k:nVars
                    for m=l:nVars
                        yout{ind,1} = [yin{i},yin{j},yin{k},yin{l},yin{m}];
                        ind = ind+1;
                    end
                end
            end
        end
    end
end

if(usesine)
    for k=1:10;
        yout{ind,1} = ['sin(',num2str(k),'*yin)'];
        ind = ind + 1;
        yout{ind,1} = ['cos(',num2str(k),'*yin)'];
        ind = ind + 1;
    end
end

output = yout;
newout(1) = {''};
newout{1,2} = 'u';
% for k=1:length(yin)
%     newout{1,1+k} = [yin{k},'dot'];
% end
% newout = {'','xdot','ydot','udot'};
for k=1:size(ahat,1)
    newout(k+1,1) = output(k);
    for j=1:size(ahat,2)
        newout{k+1,1+j} = ahat(k,j);
    end
end
newout


% Locate place fields in a firing map.
%
% Identifies the place fields in 2D firing map. First map is converted to binary image
% by applying a global threshold. During the second step connected regions are labeled
% by function bwlabel. Final step includes filtering of identified regions and verification
% that they are valid place fields.
%
%  USAGE
%   [fieldsMap, fields] = analyses.palcefield(map, <options>)
%   map           Firing rate map either structure obtained using analyses.map
%                 or a matrix that represents firing map.
%   <options>     optional list of property-value pairs (see table below)
%
%   =========================================================================
%    Properties     Values
%   -------------------------------------------------------------------------
%    'threshold'    value above threshold*peak belong to a field (default = 0.2).
%    'minBins'      Minimum number of bins in a place field, i.e. total number
%                   of bins of place field or an area of place field. Fields with
%                   fewer bins are not considered as place fields. Remember to
%                   adjust this value when you change the bin width.
%                   (default = 9).
%    'minPeak'      peaks smaller than this value are considered spurious
%                   and ignored (default = 1). Peak is normally a rate, however
%                   it's units not necessary are Hz.
%    'binWidth'     Width of the bins in cm. It is used to calculate field size.
%                   (default = 1).
%    'pos'          Position samples. Used to calculate posInd. If not provided,
%                   then posInd will be an empty matrix.
%    'minMeanRate'  Fields with mean rate smaller that this value are ignored (default = 0).
%   =========================================================================
%
%  OUTPUT
%
%   fieldsMap       Matrix of the same size as firing map. The elements of fieldsMap
%                   are integer values greater or equal to 0. The elements labeled 0
%                   are the background (not a place field). The pixels labeled 1 make up
%                   first field; the pixels labeled 2 make up a second object; and so on.
%
%   fields          Structure with information about each field. Structure fields are:
%       row         vector of rows that constitute this field;
%       col         vector of columns that constitute this field;
%       area        area of field measured by regionprops function, i.e. number of bins in the field;
%       bbox        bounding box of the field;
%       peak        field peak value;
%       size        field size in cm; Calculated with help of binWidth argument.
%       x, y        field centre of mass point;
%       meanRate    mean firing rate;
%       PixelIdxList    linear list of indices that constitute the field.
%       peakX       X-coordinate of field's peak
%       peakY       Y-coordinate of field's peak
%       map         Binary map of the field. It has the same size as firing map. The elements of 'map'
%                   equal to one if they belong to the field and are zeros otherwise.
%       posInd      Indices of position samples that correspond to this field. In case position sample
%                   matrix is of size Nx5 ([t x y x1 y1]), posInd corresponds to the left most position
%                   columns ([x y]). If pos argument is not provided, then posInd will be an empty matrix.
%
%  EXAMPLES
%
%   1. To obtain positions of the first field run:
%       [~, fields] = analyses.placefield(map, 'threshold', 0.3, 'minBins', 5, 'minPeak', 0.1, 'pos', pos);
%       fieldPos = pos(fields(1).posInd, :);
%

% Note to developers:
% In order to improve speed and capture all fields the map is processed in two passes. First
% we extract fields based solely on global peak value. This should be enough for most of the cases.
% Secondly we check if extracted fields maxima is the same as results of imregionalmax. If they are
% different, then we perform another extraction, which is slower.
%
function [fieldsMap, fields] = placefield(map, varargin)
    inp = inputParser;
    defaultMinPeak = 1.;
    defaultThreshold = 0.2;
    defaultMinBins = 9;
    defaultBinWidth = 1;
    defaultPos = [];
    defaultMinMeanRate = 0;

    % input argument check functions
    checkThreshold = @(x) helpers.isdscalar(x, '>=0', '<=1');
    checkScalarZero = @(x) helpers.isiscalar(x, '>=0');
    checkDScalar = @(x) helpers.isdscalar(x, '>0');
    checkDScalarZero = @(x) helpers.isdscalar(x, '>=0');

    % fill input parser object
    addRequired(inp, 'map');
    addParameter(inp, 'threshold', defaultThreshold, checkThreshold);
    addParameter(inp, 'minBins', defaultMinBins, checkScalarZero);
    addParameter(inp, 'minPeak', defaultMinPeak, checkDScalarZero);
    addParameter(inp, 'binWidth', defaultBinWidth, checkDScalar);
    addParameter(inp, 'minMeanRate', defaultMinMeanRate, checkScalarZero);
    addParameter(inp, 'pos', defaultPos, @(x) ismatrix(x) && size(x, 2) >= 3);

    parse(inp, map, varargin{:});

    % get parsed arguments
    minPeak = inp.Results.minPeak;
    threshold = inp.Results.threshold;
    minBins = inp.Results.minBins;
    binWidth = inp.Results.binWidth;
    pos = inp.Results.pos;
    minMeanRate = inp.Results.minMeanRate;

    originalMap = [];
    if isstruct(map)
        originalMap = map;
        map = map.z;
    end

    fieldsMap = zeros(size(map));
    fields = struct('row', {}, 'col', {}, ...
        'size', {}, 'peak', {}, 'peakX', {}, 'peakY', {}, ...
        'area', {}, 'bbox', {}, ...
        'x', {}, 'y', {}, ...
        'meanRate', {}, 'PixelIdxList', {}, ...
        'map', {}, 'posInd', {} ...
        );

    if isempty(map)
        return
    end

    globalPeak = nanmax(nanmax(map));
    if isnan(globalPeak) || globalPeak == 0
        return;
    end

    mapNans = isnan(map);
    map(mapNans) = 0;
    regionalMaxMap = imregionalmax(map, 4); % obtain all local maxima
    testRegionalMx = zeros(size(map)); % map that will contain located fields maxima

    [ir, ic] = find(regionalMaxMap > 0);            % get peak locations
    foundPeaks = map(sub2ind(size(map), ir ,ic));   % obtain peaks value

    % remove peaks that have smaller rate than minPeak
    selected = foundPeaks < minPeak;
    regionalMaxMap(ir(selected), ic(selected)) = 0;

    % Counter for the number of fields
    nFields = 0;

    binMap = ones(size(map));

    binMap(map < globalPeak*threshold) = 0;
    binMap(mapNans) = 0;

    cc = bwconncomp(binMap, 4);
    stats = regionprops(cc, 'Area', 'BoundingBox', 'Centroid');

    for i = 1:cc.NumObjects
        linInd = cc.PixelIdxList{i};
        [fieldPeak, peakLinearInd] = max(map(linInd));
        [r, c] = ind2sub(size(map), linInd);
        meanRate = nanmean(map(linInd));

        [pr, pc] = ind2sub(size(map), linInd(peakLinearInd));
        % mark this field as visited even if we reject if further down
        testRegionalMx(pr, pc) = 1;

        if fieldPeak < minPeak
            continue;
        end
        if meanRate < minMeanRate
            continue;
        end

        if length(r) >= minBins
            nFields = nFields + 1;

            fields(nFields).row = r;
            fields(nFields).col = c;
            fields(nFields).size = length(r) * binWidth^2;
            fields(nFields).peak = fieldPeak;
            fields(nFields).peakX = pc;
            fields(nFields).peakY = pr;
            fields(nFields).area = stats(i).Area;
            fields(nFields).bbox = stats(i).BoundingBox;
            fields(nFields).PixelIdxList = linInd;

            fields(nFields).x = stats(i).Centroid(1);
            fields(nFields).y = stats(i).Centroid(2);

            fields(nFields).meanRate = meanRate;
            fields(nFields).map = zeros(size(map));
            fields(nFields).map(linInd) = 1;
            fields(nFields).map(mapNans) = nan;

            % fields(nFields).Extent = stats(i).Extent;
            % fields(nFields).Orientation = stats(i).Orientation;
            % fields(nFields).Eccentricity = stats(i).Eccentricity;
            % fields(nFields).MinorAxisLength = stats(i).MinorAxisLength;
            % fields(nFields).MajorAxisLength = stats(i).MajorAxisLength;
            % fields(nFields).Perimeter = stats(i).Perimeter;

            if ~isempty(pos)
                intRect = ceil(fields(nFields).bbox); % bounding box with integers
                if isempty(originalMap)
                    % we do not have position distribution from the map, so assume that it's based
                    % on data min/max values
                    nBins = size(map);
                    limitsX = [nanmin(pos(:, bntConstants.PosX)) nanmax(pos(:, bntConstants.PosX))];
                    limitsY = [nanmin(pos(:, bntConstants.PosY)) nanmax(pos(:, bntConstants.PosY))];
                    xSpace = linspace(limitsX(1), limitsX(2), nBins(2));
                    ySpace = linspace(limitsY(1), limitsY(2), nBins(1));
                else
                    xSpace = originalMap.x;
                    ySpace = originalMap.y;
                end

                xMin = xSpace(intRect(1));
                xMax = xSpace(intRect(1) + intRect(3) - 1);

                yMin = ySpace(intRect(2));
                yMax = ySpace(intRect(2) + intRect(4) - 1);

                posIndX = pos(:, bntConstants.PosX) >= xMin & pos(:, bntConstants.PosX) <= xMax;
                posIndY = pos(:, bntConstants.PosY) >= yMin & pos(:, bntConstants.PosY) <= yMax;
                fields(nFields).posInd = find(posIndX & posIndY);
            else
                fields(nFields).posInd = [];
            end

            fieldsMap(linInd) = nFields;
        end
    end

    if ~isequaln(testRegionalMx, regionalMaxMap)
        map(fieldsMap > 0) = 0; % turn off map values for known fields, prevent field duplicates

        % we have some uncounted fields
        leftPeaksMap = regionalMaxMap - testRegionalMx;
        [ir, ic] = find(leftPeaksMap > 0);                    % get peak locations
        foundPeaks = map(sub2ind(size(leftPeaksMap), ir ,ic));   % obtain peaks value
        mapThresholds = foundPeaks * threshold;
        if sum(foundPeaks) == 0
            return;
        end

        finalMap = zeros(size(map));
        for i = 1:length(foundPeaks)
            binMap = zeros(size(map));
            binMap( (map > mapThresholds(i)) & (map <= foundPeaks(i)) ) = 1;
            binMap(mapNans) = 0;

            [binMap, linInd] = bwselect(binMap, ic(i), ir(i), 4); % leave only region that relates to current field
            if isempty(linInd)
                continue;
            end

            % check for minimum number of bins
            [r, ~] = ind2sub(size(map), linInd);
            if length(r) < minBins
                continue;
            end

            stats = regionprops(binMap, 'Centroid', 'EulerNumber'); % find statistics on field candidates
            distToPeak = sqrt((stats.Centroid(1) - ic(i))^2 + (stats.Centroid(2) - ir(i))^2);
    %         distToPeak = pdist2(stats.Centroid, [ic(i) ir(i)]);
            if distToPeak > 4 || stats.EulerNumber < 1 % we want object without holes (euler number)
                continue;
            end
            finalMap(linInd) = 1;
        end

        cc = bwconncomp(finalMap, 4); % somehow regionprops is not working if finalMap is passed directly
        stats = regionprops(cc, 'Area', 'BoundingBox', 'Centroid');

        for fieldInd = 1:length(stats)
            linInd = cc.PixelIdxList{fieldInd};
            [r, c] = ind2sub(size(map), linInd);
            meanRate = nanmean(map(linInd));
            [peakRate, peakInd] = nanmax(map(linInd));
            [pr, pc] = ind2sub(size(map), linInd(peakInd));

            if peakRate < minPeak
                continue;
            end
            if meanRate < minMeanRate
                continue;
            end

            nFields = nFields + 1;

            fields(nFields).row = r;
            fields(nFields).col = c;
            fields(nFields).size = length(r) * binWidth^2;
            fields(nFields).peak = peakRate;
            fields(nFields).peakX = pc;
            fields(nFields).peakY = pr;
            fields(nFields).area = stats(fieldInd).Area;
            fields(nFields).bbox = stats(fieldInd).BoundingBox;
            fields(nFields).PixelIdxList = linInd;

            fields(nFields).x = stats(fieldInd).Centroid(1);
            fields(nFields).y = stats(fieldInd).Centroid(2);

            fields(nFields).meanRate = meanRate;
            fields(nFields).map = zeros(size(map));
            fields(nFields).map(linInd) = 1;
            fields(nFields).map(mapNans) = nan;

            if ~isempty(pos)
                intRect = ceil(fields(nFields).bbox); % bounding box with integers
                if isempty(originalMap)
                    % we do not have position distribution from the map, so assume that it's based
                    % on data min/max values
                    nBins = size(map);
                    limitsX = [nanmin(pos(:, bntConstants.PosX)) nanmax(pos(:, bntConstants.PosX))];
                    limitsY = [nanmin(pos(:, bntConstants.PosY)) nanmax(pos(:, bntConstants.PosY))];
                    xSpace = linspace(limitsX(1), limitsX(2), nBins(2));
                    ySpace = linspace(limitsY(1), limitsY(2), nBins(1));
                else
                    xSpace = originalMap.x;
                    ySpace = originalMap.y;
                end

                xMin = xSpace(intRect(1));
                xMax = xSpace(intRect(1) + intRect(3) - 1);

                yMin = ySpace(intRect(2));
                yMax = ySpace(intRect(2) + intRect(4) - 1);

                posIndX = pos(:, bntConstants.PosX) >= xMin & pos(:, bntConstants.PosX) <= xMax;
                posIndY = pos(:, bntConstants.PosY) >= yMin & pos(:, bntConstants.PosY) <= yMax;
                fields(nFields).posInd = find(posIndX & posIndY);
            else
                fields(nFields).posInd = [];
            end

            fieldsMap(linInd) = nFields;
        end
    end
end


% DESCRIPTION:
%       subscript to create the absorption variables
%
% ABOUT:
%       author      - Bradley Treeby
%       date        - 26th November 2010
%       last update - 11th February 2014
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox

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

% define the lossy derivative operators and proportionality coefficients
if strcmp(equation_of_state, 'absorbing')

    % make sure the operators are positive and real
    medium.alpha_coeff = abs(real(medium.alpha_coeff));
    medium.alpha_power = abs(real(medium.alpha_power));

    % convert the absorption coefficient to nepers.(rad/s)^-y.m^-1
    medium.alpha_coeff = db2neper(medium.alpha_coeff, medium.alpha_power);

    % compute the absorbing fractional Laplacian operator and coefficient
    if ~(isfield(medium, 'alpha_mode') && strcmp(medium.alpha_mode, 'no_absorption'))
        absorb_nabla1 = (kgrid.k).^(medium.alpha_power-2);
        absorb_nabla1(isinf(absorb_nabla1)) = 0;
        absorb_nabla1 = ifftshift(absorb_nabla1);
        absorb_tau = -2*medium.alpha_coeff.*medium.sound_speed.^(medium.alpha_power - 1);
    else
        absorb_nabla1 = 0;
        absorb_tau = 0;
    end

    % compute the dispersive fractional Laplacian operator and coefficient
    if ~(isfield(medium, 'alpha_mode') && strcmp(medium.alpha_mode, 'no_dispersion'))
        absorb_nabla2 = (kgrid.k).^(medium.alpha_power-1);
        absorb_nabla2(isinf(absorb_nabla2)) = 0;
        absorb_nabla2 = ifftshift(absorb_nabla2);
        absorb_eta = 2*medium.alpha_coeff.*medium.sound_speed.^(medium.alpha_power)*tan(pi*medium.alpha_power/2);
    else
        absorb_nabla2 = 0;
        absorb_eta = 0;
    end

    % pre-filter the absorption parameters if alpha_filter is defined (this
    % is used for time-reversal photoacoustic image reconstruction
    % with absorption compensation)
    if isfield(medium, 'alpha_filter');

        % update command line status
        disp('  filtering absorption variables...');

        % frequency shift the absorption parameters
        absorb_nabla1 = fftshift(absorb_nabla1);
        absorb_nabla2 = fftshift(absorb_nabla2);

        % apply the filter
        absorb_nabla1 = absorb_nabla1.*medium.alpha_filter;
        absorb_nabla2 = absorb_nabla2.*medium.alpha_filter;

        % shift the parameters back
        absorb_nabla1 = ifftshift(absorb_nabla1);
        absorb_nabla2 = ifftshift(absorb_nabla2);

    end

    % modify the sign of the absorption operators if alpha_sign is defined
    % (this is used for time-reversal photoacoustic image reconstruction
    % with absorption compensation)
    if isfield(medium, 'alpha_sign')
       if numel(medium.alpha_sign) == 2
           % if two parameters are given, apply the first to the absorption
           % parameter and the second to the disperion parameters
           absorb_tau = sign(medium.alpha_sign(1))*absorb_tau;
           absorb_eta = sign(medium.alpha_sign(2))*absorb_eta;
       else
           error('medium.alpha_sign must be given as a 2 element array controlling absorption and dispersion, respectively.');
       end
    end
end


function [s, d, S_rf, S_sf, S_k, S_l] = projHmgLinIntoPinHoleOnRob(Rf, Sf, Sk, l)

% PROJHMGLININTOPINHOLEONROB Project Hmg line into pinhole on robot.
%   [s, d] = PROJHMGLININTOPINHOLEONROB(Rf, Sf, Sk, l) projects the
%   inverse-depth line l into a pin/hole camera with intrinsic parameters
%   Sk mounted on a robot. The robot frame is Rf and the sensor frame in
%   the robot is Sf.
%
%   The results are a 2D segment S and a depths vector D.
%
%   [s, d, S_rf, S_sf, S_k, S_l] = (...) returns the Jacobians wrt all
%   input parameters.

%   Copyright 2009 Teresa Vidal.

if nargout <= 2

    sw = hmgLin2seg(l);
    s   = projSegLinIntoPinHoleOnRob(Rf, Sf, Sk, sw);
    d   = 1./l([6 9]);

else

    [sw, SW_l] = hmgLin2seg(l);
    [s, d, S_rf, S_sf, S_k, S_sw] = projSegLinIntoPinHoleOnRob(Rf, Sf, Sk, sw);
    S_l  = S_sw*SW_l;

end

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB 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.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function [hIm, ww] = L1SR(lIm, zooming, patch_size, overlap, Dh, Dl, lambda, regres)
% Use sparse representation as the prior for image super-resolution
% Usage
%       [hIm] = L1SR(lIm, zooming, patch_size, overlap, Dh, Dl, lambda)
%
% Inputs
%   -lIm:           low resolution input image, single channel, e.g.
%   illuminance
%   -zooming:       zooming factor, e.g. 3
%   -patch_size:    patch size for the low resolution image
%   -overlap:       overlap among patches, e.g. 1
%   -Dh:            dictionary for the high resolution patches
%   -Dl:            dictionary for the low resolution patches
%   -regres:       'L1' use the sparse representation directly to high
%                   resolution dictionary;
%                   'L2' use the supports found by sparse representation
%                   and apply least square regression coefficients to high
%                   resolution dictionary.
% Ouputs
%   -hIm:           the recovered image, single channel
%
% Written by Jianchao Yang @ IFP UIUC
% April, 2009
% Webpage: http://www.ifp.illinois.edu/~jyang29/
% For any questions, please email me by jyang29@uiuc.edu
%
% Reference
% Jianchao Yang, John Wright, Thomas Huang and Yi Ma. Image superresolution
% as sparse representation of raw image patches. IEEE Computer Society
% Conference on Computer Vision and Pattern Recognition (CVPR), 2008.
%

[lhg, lwd] = size(lIm);
hhg = lhg*zooming;
hwd = lwd*zooming;

mIm = imresize(lIm, 2,'bicubic');
[mhg, mwd] = size(mIm);
hpatch_size = patch_size*zooming;
mpatch_size = patch_size*2;

% extract gradient feature from lIm
hf1 = [-1,0,1];
vf1 = [-1,0,1]';
hf2 = [1,0,-2,0,1];
vf2 = [1,0,-2,0,1]';

lImG11 = conv2(mIm,hf1,'same');
lImG12 = conv2(mIm,vf1,'same');
lImG21 = conv2(mIm,hf2,'same');
lImG22 = conv2(mIm,vf2,'same');

lImfea(:,:,1) = lImG11;
lImfea(:,:,2) = lImG12;
lImfea(:,:,3) = lImG21;
lImfea(:,:,4) = lImG22;

lgridx = 2:patch_size-overlap:lwd-patch_size;
lgridx = [lgridx, lwd-patch_size];
lgridy = 2:patch_size-overlap:lhg-patch_size;
lgridy = [lgridy, lhg-patch_size];

mgridx = (lgridx - 1)*2 + 1;
mgridy = (lgridy - 1)*2 + 1;

% using linear programming to find sparse solution
bhIm = imresize(lIm, zooming, 'bicubic');
hIm = zeros([hhg, hwd]);
nrml_mat = zeros([hhg, hwd]);

hgridx = (lgridx-1)*zooming + 1;
hgridy = (lgridy-1)*zooming + 1;

disp('Processing the patches sequentially...');
count = 0;

%ProjM = inv(Dl'*Dl+0.001*eye(size(Dl,2)))*Dl';

% loop to recover each patch
for xx = 1:length(mgridx),
    for yy = 1:length(mgridy),

        mcolx = mgridx(xx);
        mrowy = mgridy(yy);

        count = count + 1;
%         if ~mod(count, 10000),
%             fprintf('.\n');
%         else
%             fprintf('.');
%         end;
        if ~mod(count, 1000),
            fprintf('%g/%g\n',count,length(mgridx)*length(mgridy));
        end
        mpatch = mIm(mrowy:mrowy+mpatch_size-1, mcolx:mcolx+mpatch_size-1);
        mmean = mean(mpatch(:));

        mpatchfea = lImfea(mrowy:mrowy+mpatch_size-1, mcolx:mcolx+mpatch_size-1, :);
        mpatchfea = mpatchfea(:);

        mnorm = sqrt(sum(mpatchfea.^2));

        if mnorm > 1,
            y = mpatchfea./mnorm;
        else
            y = mpatchfea;
        end;
        %w = ProjM*y;
        w = SolveLasso(Dl, y, size(Dl, 2), 'nnlasso', [], lambda);
        %w = feature_sign(Dl, y, lambda*2);

        if isempty(w),
            w = zeros(size(Dl, 2), 1);
        end;
        switch regres,
            case 'L1'
                if mnorm > 1,
                    hpatch = Dh*w*mnorm;
                else
                    hpatch = Dh*w;
                end;
            case 'L2'
                idx = find(w);
                lsups = Dl(:, idx);
                hsups = Dh(:, idx);
                w = inv(lsups'*lsups)*lsups'*mpatchfea;
                hpatch = hsups*w;
            otherwise
                error('Unknown fitting!');
        end;

        hpatch = reshape(hpatch, [hpatch_size, hpatch_size]);
        hpatch = hpatch + mmean;

        hcolx = hgridx(xx);
        hrowy = hgridy(yy);

        hIm(hrowy:hrowy+hpatch_size-1, hcolx:hcolx+hpatch_size-1)...
            = hIm(hrowy:hrowy+hpatch_size-1, hcolx:hcolx+hpatch_size-1) + hpatch;
        nrml_mat(hrowy:hrowy+hpatch_size-1, hcolx:hcolx+hpatch_size-1)...
            = nrml_mat(hrowy:hrowy+hpatch_size-1, hcolx:hcolx+hpatch_size-1) + 1;
    end;
end;

fprintf('done!\n');

% fill the empty
hIm(1:3, :) = bhIm(1:3, :);
hIm(:, 1:3) = bhIm(:, 1:3);

hIm(end-2:end, :) = bhIm(end-2:end, :);
hIm(:, end-2:end) = bhIm(:, end-2:end);

nrml_mat(nrml_mat < 1) = 1;
hIm = hIm./nrml_mat;
% hIm = uint8(hIm);


function c = tapas_ehgf_ar1_binary_config
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Contains the configuration for the enhanced Hierarchical Gaussian Filter (eHGF)
% for binary inputs in the absence of perceptual uncertainty.
%
% The HGF is the model introduced in
%
% Mathys C, Daunizeau J, Friston, KJ, and Stephan KE. (2011). A Bayesian foundation
% for individual learning under uncertainty. Frontiers in Human Neuroscience, 5:39.
%
% The binary HGF model has since been augmented with a positive factor kappa1 which
% scales the second level with respect to the first, i.e., the relation between the
% first and second level is
%
% p(x1=1|x2) = s(kappa1*x2), where s(.) is the logistic sigmoid.
%
% By default, kappa1 is fixed to 1, leading exactly to the model introduced in
% Mathys et al. (2011).
%
% This file refers to BINARY inputs (Eqs 1-3 in Mathys et al., (2011));
% for continuous inputs, refer to tapas_ehgf_config.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The HGF configuration consists of the priors of parameters and initial values. All priors are
% Gaussian in the space where the quantity they refer to is estimated. They are specified by their
% sufficient statistics: mean and variance (NOT standard deviation).
%
% Quantities are estimated in their native space if they are unbounded (e.g., the omegas). They are
% estimated in log-space if they have a natural lower bound at zero (e.g., the sigmas).
%
% Parameters can be fixed (i.e., set to a fixed value) by setting the variance of their prior to
% zero. Aside from being useful for model comparison, the need for this arises whenever the scale
% and origin at the j-th level are arbitrary. This is the case if the observation model does not
% contain the representations mu_j and sigma_j. A choice of scale and origin is then implied by
% fixing the initial value mu_j_0 of mu_j and either kappa_j-1 or omega_j-1.
%
% Fitted trajectories can be plotted by using the command
%
% >> tapas_ehgf_binary_plotTraj(est)
%
% where est is the stucture returned by tapas_fitModel. This structure contains the estimated
% perceptual parameters in est.p_prc and the estimated trajectories of the agent's
% representations (cf. Mathys et al., 2011). Their meanings are:
%
%         est.p_prc.mu_0       row vector of initial values of mu (in ascending order of levels)
%         est.p_prc.sa_0       row vector of initial values of sigma (in ascending order of levels)
%         est.p_prc.rho        row vector of rhos (representing drift; in ascending order of levels)
%         est.p_prc.ka         row vector of kappas (in ascending order of levels)
%         est.p_prc.om         row vector of omegas (in ascending order of levels)
%
% Note that the first entry in all of the row vectors will be NaN because, at the first level,
% these parameters are either determined by the second level (mu_0 and sa_0) or undefined (rho,
% kappa, and omega).
%
%         est.traj.mu          mu (rows: trials, columns: levels)
%         est.traj.sa          sigma (rows: trials, columns: levels)
%         est.traj.muhat       prediction of mu (rows: trials, columns: levels)
%         est.traj.sahat       precisions of predictions (rows: trials, columns: levels)
%         est.traj.v           inferred variance of random walk (rows: trials, columns: levels)
%         est.traj.w           weighting factors (rows: trials, columns: levels)
%         est.traj.da          volatility prediction errors  (rows: trials, columns: levels)
%         est.traj.ud          updates with respect to prediction  (rows: trials, columns: levels)
%         est.traj.psi         precision weights on prediction errors  (rows: trials, columns: levels)
%         est.traj.epsi        precision-weighted prediction errors  (rows: trials, columns: levels)
%         est.traj.wt          full weights on prediction errors (at the first level,
%                                  this is the learning rate) (rows: trials, columns: levels)
%
% Note that in the absence of sensory uncertainty (which is the assumption here), the first
% column of mu, corresponding to the first level, will be equal to the inputs. Likewise, the
% first column of sa will be 0 always.
%
% Tips:
% - When analyzing a new dataset, take your inputs u and use
%
%   >> est = tapas_fitModel([], u, 'tapas_ehgf_binary_config', 'tapas_bayes_optimal_binary_config');
%
%   to determine the Bayes optimal perceptual parameters (given your current priors as defined in
%   this file here, so choose them wide and loose to let the inputs influence the result). You can
%   then use the optimal parameters as your new prior means for the perceptual parameters.
%
% - If you get an error saying that the prior means are in a region where model assumptions are
%   violated, lower the prior means of the omegas, starting with the highest level and proceeding
%   downwards.
%
% - Alternatives are lowering the prior means of the kappas, if they are not fixed, or adjusting
%   the values of the kappas or omegas, if any of them are fixed.
%
%
% --------------------------------------------------------------------------------------------------
% Copyright (C) 2012-2020 Christoph Mathys, TNU, UZH & ETHZ
%
% This file is part of the HGF toolbox, which is released under the terms of the GNU General Public
% Licence (GPL), version 3. You can redistribute it and/or modify it under the terms of the GPL
% (either version 3 or, at your option, any later version). For further details, see the file
% COPYING or <http://www.gnu.org/licenses/>.

% Config structure
c = struct;

% Model name
c.model = 'ehgf_ar1_binary';

% Number of levels (minimum: 3)
c.n_levels = 3;

% Input intervals
% If input intervals are irregular, the last column of the input
% matrix u has to contain the interval between inputs k-1 and k
% in the k-th row, and this flag has to be set to true
c.irregular_intervals = false;

% Sufficient statistics of Gaussian parameter priors

% Initial mus and sigmas
% Format: row vectors of length n_levels
% For all but the first two levels, this is usually best
% kept fixed to 1 (determines origin on x_i-scale). The
% first level is NaN because it is determined by the second,
% and the second implies neutrality between outcomes when it
% is centered at 0.
c.mu_0mu = [NaN, 0, 1];
c.mu_0sa = [NaN, 0, 0];

c.logsa_0mu = [NaN,   log(0.1), log(1)];
c.logsa_0sa = [NaN,          0,      0];

% Phis
% Format: row vector of length n_levels.
% Undefined (therefore NaN) at the first level.
% Fix this to zero (-Inf in logit space) to set to zero.
c.logitphimu = [NaN, -Inf, tapas_logit(0.5,1)]; %tapas_logit(0.1,1)
c.logitphisa = [NaN,    0,                  2];

% ms
% Format: row vector of length n_levels.
% This should be fixed for all levels where the omega of
% the next lowest level is not fixed because that offers
% an alternative parametrization of the same model.
c.mmu = [NaN, c.mu_0mu(2), c.mu_0mu(3)];
c.msa = [NaN,           0,           1];

% Rhos
% Format: row vector of length n_levels.
% Undefined (therefore NaN) at the first level.
% Fix this to zero to turn off drift.
c.rhomu = [NaN, 0, 0];
c.rhosa = [NaN, 0, 0];

% Kappas
% Format: row vector of length n_levels-1.
% Fixing log(kappa1) to log(1) leads to the original HGF model.
% Higher log(kappas) should be fixed (preferably to log(1)) if the
% observation model does not use mu_i+1 (kappa then determines the
% scaling of x_i+1).
c.logkamu = [log(1), log(1)];
c.logkasa = [     0,      0];

% Omegas
% Format: row vector of length n_levels.
% Undefined (therefore NaN) at the first level.
c.ommu = [NaN,  -3,   2];
c.omsa = [NaN,   4,   4];

% Gather prior settings in vectors
c.priormus = [
    c.mu_0mu,...
    c.logsa_0mu,...
    c.logitphimu,...
    c.mmu,...
    c.rhomu,...
    c.logkamu,...
    c.ommu,...
         ];

c.priorsas = [
    c.mu_0sa,...
    c.logsa_0sa,...
    c.logitphisa,...
    c.msa,...
    c.rhosa,...
    c.logkasa,...
    c.omsa,...
         ];

% Check whether we have the right number of priors
expectedLength = 5*c.n_levels+2*(c.n_levels-1)+1;
if length([c.priormus, c.priorsas]) ~= 2*expectedLength
    error('tapas:hgf:PriorDefNotMatchingLevels', 'Prior definition does not match number of levels.')
end

% Model function handle
c.prc_fun = @tapas_ehgf_ar1_binary;

% Handle to function that transforms perceptual parameters to their native space
% from the space they are estimated in
c.transp_prc_fun = @tapas_ehgf_ar1_binary_transp;

end


function niederreiter2_test04 ( )

%*****************************************************************************80
%
%% NIEDERREITER2_TEST04 tests NIEDERREITER2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 November 2008
%
%  Author:
%
%    John Burkardt
%
  dim_max = 4;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'NIEDERREITER2_TEST04\n' );
  fprintf ( 1, '  NIEDERREITER2 computes the next element of\n' );
  fprintf ( 1, '  a Niederreiter quasirandom sequence using base 2.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  In this test, we call NIEDERREITER2 repeatedly.\n' );

  for dim_num = 2 : dim_max

    seed = 0;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Using dimension DIM_NUM =   %d\n', dim_num );
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Seed  Seed   Niederreiter2\n' );
    fprintf ( 1, '  In    Out\n' );
    fprintf ( 1, '\n' );

    for i = 0 : 110
      seed_in = seed;
      [ r, seed ] = niederreiter2 ( dim_num, seed );
      seed_out = seed;
      if ( i <= 11 | 95 <= i )
        fprintf ( 1, '%3d  %3d  ', seed_in, seed_out );
        for j = 1 : dim_num
          fprintf ( 1, '%10f', r(j) );
        end
        fprintf ( 1, '\n' );
      elseif ( i == 12 )
        fprintf ( 1, '......................\n' );
      end
    end

  end

  return
end


function frac = i4vec_frac ( n, a, k )

%*****************************************************************************80
%
%% I4VEC_FRAC searches for the K-th smallest entry in an I4VEC.
%
%  Discussion:
%
%    Hoare's algorithm is used.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 November 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of elements of A.
%
%    Input, integer A(N), the array to search.
%
%    Input, integer K, the fractile to be sought.  If K = 1, the minimum
%    entry is sought.  If K = N, the maximum is sought.  Other values
%    of K search for the entry which is K-th in size.  K must be at
%    least 1, and no greater than N.
%
%    Output, integer FRAC, the value of the K-th fractile of A.
%
  if ( n <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4VEC_FRAC - Fatal error!\n' );
    fprintf ( 1, '  Illegal nonpositive value of N = %d\n', n );
    error ( 'I4VEC_FRAC - Fatal error!' );
  end

  if ( k <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4VEC_FRAC - Fatal error!\n' );
    fprintf ( 1, '  Illegal nonpositive value of K = %d\n', k );
    error ( 'I4VEC_FRAC - Fatal error!' );
  end

  if ( n < k )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4VEC_FRAC - Fatal error!\n' );
    fprintf ( 1, '  Illegal N < K, K = %d\n', k );
    error ( 'I4VEC_FRAC - Fatal error!' );
  end

  left = 1;
  iryt = n;

  while ( 1 )

    if ( iryt <= left )
      frac = a(k);
      break;
    end

    x = a(k);
    i = left;
    j = iryt;

    while ( 1 )

      if ( j < i )
        if ( j < k )
          left = i;
        end
        if ( k < i )
          iryt = j;
        end
        break;
      end
%
%  Find I so that X <= A(I)
%
      while ( a(i) < x )
        i = i + 1;
      end
%
%  Find J so that A(J) <= X
%
      while ( x < a(j) )
        j = j - 1;
      end

      if ( i <= j )

        temp = a(i);
        a(i) = a(j);
        a(j) = temp;

        i = i + 1;
        j = j - 1;

      end

    end

  end

  return
end


function r8sp_print_some ( m, n, nz_num, isym, row, col, a, ilo, jlo, ihi, ...
  jhi, title )

%*****************************************************************************80
%
%% R8SP_PRINT_SOME prints some of a R8SP matrix.
%
%  Discussion:
%
%    This version of R8SP_PRINT_SOME has been specifically modified to allow,
%    and correctly handle, the case in which a single matrix location
%    A(I,J) is referenced more than once by the sparse matrix structure.
%    In such cases, the routine prints out the sum of all the values.
%
%    The R8SP storage format stores the row, column and value of each nonzero
%    entry of a sparse matrix.
%
%    It is possible that a pair of indices (I,J) may occur more than
%    once.  Presumably, in this case, the intent is that the actual value
%    of A(I,J) is the sum of all such entries.  This is not a good thing
%    to do, but I seem to have come across this in MATLAB.
%
%    The R8SP format is used by CSPARSE ("sparse triplet"), DLAP/SLAP
%    ("nonsymmetric SLAP triad"), by MATLAB, and by SPARSEKIT ("COO" format).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 January 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns of the matrix.
%
%    Input, integer NZ_NUM, the number of nonzero elements in the matrix.
%
%    Input, integer ISYM, is 0 if the matrix is not symmetric,
%    and 1 if the matrix is symmetric.  The symmetric case only makes sense
%    if the matrix is also square, that is, M = N.  In this case, only
%    the nonzeroes on the diagonal and in the lower triangle are stored.
%
%    Input, integer ROW(NZ_NUM), COL(NZ_NUM), the row and column indices
%    of the nonzero elements.
%
%    Input, real A(NZ_NUM), the nonzero elements of the matrix.
%
%    Input, integer ILO, JLO, IHI, JHI, the first row and
%    column, and the last row and column to be printed.
%
%    Input, string TITLE, a title.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );

  incx = 5;
%
%  Print the columns of the matrix, in strips of 5.
%
  for j2lo = jlo: incx: jhi

    j2hi = j2lo + incx - 1;
    j2hi = min ( j2hi, n );
    j2hi = min ( j2hi, jhi );

    inc = j2hi + 1 - j2lo;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col: ' );

    for j = j2lo : j2hi
      fprintf ( 1, '%7d       ', j );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row\n' );
    fprintf ( 1, '  ---\n' );
%
%  Determine the range of the rows in this strip.
%
    i2lo = max ( ilo, 1 );
    i2hi = min ( ihi, m );

    for i = i2lo : i2hi
%
%  Print out (up to) 5 entries in row I, that lie in the current strip.
%
      nonzero = 0;

      aij(1:inc) = 0.0;

      for k = 1 : nz_num

        if ( i == row(k) && j2lo <= col(k) && col(k) <= j2hi )

          j2 = col(k) - j2lo + 1;

          if ( a(k) ~= 0.0 )
            nonzero = 1;
            aij(j2) = aij(j2) + a(k);
          end

        elseif ( isym == 1 && m == n && ...
          i == col(k) && j2lo <= row(k) && row(k) <= j2hi )

          j2 = row(k) - j2lo + 1;

          if ( a(k) ~= 0.0 )
            nonzero = 1;
            aij(j2) = aij(j2) + a(k);
          end

        end

      end

      if ( nonzero )
        fprintf ( 1, '%4d', i );
        for j = 1 : inc
          fprintf ( 1, '  %12g', aij(j) );
        end
        fprintf ( 1, '\n' );
      end

    end

  end

  return
end


%**************************************************************************
% SARSA Learning applied to Cart-Pole balancing problem.
% The environment of the learning system is a black box, from which it has
% several lines and a reinforcement line. Its task is to learn to give
% responses which maximize the scalar signals on its reinforcement line.
% The Q-value update is the following, if the system takes action a from
%   state s at time t, and arrives at state ss with feedback r at time t+1:
%
%   Q(t+1, s, a) = Q(t, s, a)
%                  + alpha (r + gamma *Q(t,ss, b) - Q(t, s, a))

% get_box:  Given the current state, returns a number from 1 to 162
%           designating the region of the state space encompassing the current
%           state.
%           Returns a value of -1 if a failure state is encountered.

% cart_pole2: The cart and pole dynamics; given the Force and
%             current state, estimates next state

%Code written by: Savinay Nagendra
%email id:        nagsavi17@gmail.com
%**************************************************************************
clc;
clear all;
close all;
% Initialization

NUM_BOXES = 163;
ALPHA = 0.5;             % Learning rate parameter
GAMMA = 0.999;           % Discount factor for future reinf
Q = zeros(NUM_BOXES,2);  % State-Action Values
action = [10 -10];
MAX_FAILURES = 2000;
MAX_STEPS = 150000;
epsilon = 0;
steps = 0;
failures = 0;
thetaPlot = 0;
xPlot = 0;
%Pendulum state initialization
theta = 0;
thetaDot = 0;
x = 0;
xDot = 0;
box = getBox4(theta,thetaDot,x,xDot);
if(rand>epsilon)       % exploit
    [~,actionMax] = max(Q(box,:));
    currentAction = action(actionMax);
else                   % explore
    currentAction = datasample(action,1);
end
actionIndex1 = find(action == currentAction);

while(steps<=MAX_STEPS && failures<+MAX_FAILURES)
    steps = steps + 1;
    [thetaNext,thetaDotNext,thetaacc,xNext,xDotNext] = cart_pole2(currentAction,theta,thetaDot,x,xDot);
    thetaPlot(end + 1) = thetaNext;
    xPlot(end + 1) = xNext;
    newBox = getBox4(thetaNext,thetaDotNext,xNext,xDotNext);
    theta = thetaNext;
    thetaDot = thetaDotNext;
    x = xNext;
    xDot = xDotNext;
    if(newBox == 163)
        r = -1;
        Q(newBox,:) = 0;
        figure(2);
        plot((1:length(thetaPlot)),thetaPlot,'-ob');
        figure(3);
        plot((1:length(xPlot)),xPlot,'-og');
        thetaPlot = 0;
        xPlot = 0;
        %Swing Up. Find the box.
        theta = 0;
        thetaDot = 0;
        x = 0;
        xDot = 0;

        newBox = getBox4(theta,thetaDot,x,xDot);
        failures = failures + 1;
        fprintf('Trial %d was %d steps. \n',failures,steps);
        figure(1);
        plot(failures,steps,'-or');
        hold on;
        steps = 0;
    else
        r = 0;
    end
    if(rand > epsilon)  %exploit
        [~,newActionMax] = max(Q(newBox,:));
        newAction = action(newActionMax);
    else                %explore
        newAction = datasample(action,1);
    end
    actionIndex2 = find(action == newAction);
    Q(box,actionIndex1) = Q(box,actionIndex1) + ALPHA*(r + GAMMA*Q(newBox,actionIndex2) - Q(box,actionIndex1));
    box = newBox;
    currentAction = newAction;
    actionIndex1 = actionIndex2;
end

if(failures == MAX_FAILURES)
    fprintf('Pole not balanced. Stopping after %d failures.',failures);
else
    fprintf('Pole balanced successfully for at least %d steps\n', steps);
    figure(1);
    plot(failures+1,steps,'-or');
    hold on;
    figure(2);
    plot((1:length(thetaPlot)),thetaPlot,'-ob');
    figure(3);
    plot((1:length(xPlot)),xPlot,'-og');
    figure(4);
    plot((1:301),thetaPlot(1:301),'-ob');
    hold on;
    figure(5);
    plot((1:301),xPlot(1:301),'-og');
    hold on;
end


function [cohsig,sptsig,c] = crbs7(y,rlx_int,eukenf,c_int,c_tr,xi)
% Written by John Smith
% October 21st, 2010
% University of Colorado at Boulder, CIRES
% John.A.Smith@Colorado.EDU
% MATLAB version 7.10.0.59 (R2010a) 64-bit
% Adapted from "Coherent Rayleigh-Brillouin Scattering"
% by Xingguo Pan

% Computes the coherent and spontaneous
% RBS spectrum given the parameters
% in crbs_molecular using the s7 model
% by X. Pan, 2002

% Called by: crbs_molecular.m

n_xi=numel(xi);

n=7;
a=zeros(n,n);
b=zeros(n,2);

cohsig=zeros(1,n_xi);
sptsig=zeros(1,n_xi);

cpxunit=sqrt(-1);

y7=1.5*y;
gamma_int=c_int/(c_tr+c_int);
j020=-y;
j030=1.5*j020;
j100=-gamma_int*y/rlx_int;
j001=j100*c_tr/c_int;
j100001=j100*sqrt(c_tr/c_int);
j110=j100*5/6+j020*2/3;
j011110=j100*sqrt(5/(8*c_int));
j_nu=0.4*(1.5+c_int)+(3+c_int)/(2*rlx_int)+9*eukenf/(16*rlx_int^2);
j_de=-1+(4/15)*eukenf*(1.5+c_int)+(c_int/3)*eukenf/rlx_int;
j_co=-y*(2*gamma_int/3);
j011=j_co*j_nu/j_de;

for i=1:n_xi
    z=xi(i)+y7*cpxunit;
	w0=w0_func(z);
	w1=-sqrt(pi)+z*w0;
	w2=z*w1;
	w3=-0.5*sqrt(pi)+z*w2;
	w4=z*w3;
	w5=-3*sqrt(pi)/4+z*w4;
	w6=z*w5;

    i0000=w0/(sqrt(pi));
	i0100=w1*sqrt(2/pi);
	i0001=i0100;
	i0010=(2*w2-w0)/(sqrt(6*pi));
	i1000=i0010;
	i0011=(2*w3-3*w1)/(sqrt(5*pi));
	i1100=i0011;
	i0101=2*w2/sqrt(pi);
	i0110=(-w1+2*w3)/sqrt(3*pi);
	i1001=i0110;
	i0111=(-3*w2+2*w4)*sqrt(2/(5*pi));
	i1101=i0111;
	i1111=(13*w2-12*w4+4*w6)/(5*sqrt(pi));
	i0002=(-w0+2*w2)/sqrt(3*pi);
	i0200=i0002;
	i0211=(-w1+8*w3-4*w5)/sqrt(15*pi);
	i1102=i0211;
	i0202=2*(w0-2*w2+2*w4)/(3*sqrt(pi));
	i0210=(w0+4*w2-4*w4)/(3*sqrt(2*pi));
	i1002=i0210;
	i0102=(-w1+2*w3)*sqrt(2/(3*pi));
	i0201=i0102;
	i1010=(5*w0-4*w2+4*w4)/(6*sqrt(pi));
	i1110=(7*w1-8*w3+4*w5)/sqrt(30*pi);
	i1011=i1110;

    a(:,1)=-j030*[i0000 i0001 i0011 i0002 i0010 0 0]+[cpxunit 0 0 0 0 0 0];
    a(:,2)=-j030*[i0100 i0101 i0111 i0102 i0110 0 0]+[0 cpxunit 0 0 0 0 0];
    a(:,3)=(j030-j110)*[i1100 i1101 i1111 i1102 i1110 0 0]+j011110*[0 0 0 0 0 -i0100 -i0101]+[0 0 -cpxunit 0 0 0 0];
    a(:,4)=(j020-j030)*[i0200 i0201 i0211 i0202 i0210 0 0]+[0 0 0 3/2*cpxunit 0 0 0];
    a(:,5)=(j030-j100)*[i1000 i1001 i1011 i1002 i1010 0 0]+j100001*[0 0 0 0 0 -i0000 -i0001]+[0 0 0 0 -cpxunit 0 0];
    a(:,6)=j100001*[i1000 i1001 i1011 i1002 i1010 0 0]+(j001-j030)*[0 0 0 0 0 i0000 i0001]+[0 0 0 0 0 cpxunit 0];
    a(:,7)=j011110*[i1100 i1101 i1111 i1102 i1110 0 0]+(j011-j030)*[0 0 0 0 0 i0100 i0101]+[0 0 0 0 0 0 cpxunit];

    b(:,1)=-[i0100 i0101 i0111 i0102 i0110 0 0];
    b(:,2)=-[i0000 i0001 i0011 i0002 i0010 0 0];

    c=linsolve(a,b);

    cohsig(i)=c(1,1)*conj(c(1,1));
    sptsig(i)=2*real(c(1,2));
end
end


function [dist,binned,stats] = CircularDistribution(angles,varargin)

%CircularDistribution - Compute circular distribution and statistics.
%
%  USAGE
%
%    [dist,binned,stats] = CircularDistribution(angles,<options>)
%
%    angles         angles in radians
%    <options>      optional list of property-value pairs (see table below)
%
%    =========================================================================
%     Properties    Values
%    -------------------------------------------------------------------------
%     'nBins'       number of bins (default = 100)
%     'smooth'      standard deviation of Gaussian kernel (default = 0)
%     'groups'      groups for multiple circular distributions (see below)
%    =========================================================================
%
%  OUTPUT
%
%    dist           circular distribution (one column per group)
%    binned         centers of the angular bins
%    stats.m        mean angle (one per group)
%    stats.mode     distribution mode (one per group)
%    stats.r        mean resultant length (one per group)
%    stats.k        concentration (one per group)
%    stats.p        p-value for Rayleigh test (one per group)
%
%  NOTE
%
%    For multiple circular distributions, groups can be indicated in two different
%    manners:
%
%     - a vector of group IDs (one per angle)
%     - a logical matrix (one line per angle, one column per group), where
%       the element (i,j) is 1 iff angle i belongs to group j
%
%    The vector form is convenient when each angle can only belong to one group.
%    The matrix form is useful when a single angle can belong to multiple groups.
%
%  SEE
%
%    See also PlotCircularDistribution.

% Copyright (C) 2011-2012 by Michaël Zugaro
%
% 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.

% Default values
nBins = 100;
smooth = 0;

% Check number of parameters
if nargin < 1 | mod(length(varargin),2) ~= 0,
  error('Incorrect number of parameters (type ''help CircularDistribution'' for details).');
end

% Check parameter size
if ~isdvector(angles),
	error('Incorrect angles (type ''help CircularDistribution'' for details).');
end
angles = angles(:);
groups = ones(size(angles));

% Parse parameter list
for i = 1:2:length(varargin),
  if ~ischar(varargin{i}),
    error(['Parameter ' num2str(i+2) ' is not a property (type ''help CircularDistribution'' for details).']);
  end
  switch(lower(varargin{i})),
    case 'nbins',
      nBins = varargin{i+1};
      if ~isiscalar(nBins,'>0'),
        error('Incorrect value for property ''nBins'' (type ''help CircularDistribution'' for details).');
      end
    case 'smooth',
      smooth = varargin{i+1};
      if ~isdscalar(smooth,'>=0'),
        error('Incorrect value for property ''smooth'' (type ''help CircularDistribution'' for details).');
      end
    case 'groups',
      groups = varargin{i+1};
      if ~isdvector(groups,'>0') && ~islmatrix(groups),
        error('Incorrect value for property ''groups'' (type ''help CircularDistribution'' for details).');
      end
      if isdvector(groups), groups = groups(:); end
      if length(angles) ~= size(groups,1),
        error('Phases and groups have different numbers of lines (type ''help CircularDistribution'' for details).');
      end
    otherwise,
      error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help CircularDistribution'' for details).']);
  end
end

% Angle bins
binned = linspace(0,2*pi,nBins+1)';binned(end) = [];
binSize = binned(2)-binned(1);
binned = binned + binSize/2;

% Groups: transform vector form into matrix form
if isdvector(groups),
	groupIDs = unique(groups);
	nGroups = max(groupIDs);
	g = groups;
	groups = logical(zeros(length(g),nGroups));
	for i = 1:nGroups,
		groups(g==i,i) = 1;
	end
end

% Loop through groups
nGroups = size(groups,2);
for i = 1:nGroups,
	% Distribution
	p = angles(groups(:,i));
	h = Smooth(hist(p,binned),smooth);h = h/sum(h);
	dist(:,i) = h;
	% Stats
	if ~isempty(p)
      [stats.m(i)] = circ_mean(p);
      [stats.r(i)] = circ_r(p);
	  stats.k(i) = Concentration(p);
	  n = sum(groups(:,i));
	  R = stats.r(i)*n;
	  stats.p(i) = exp(sqrt(1+4*n+4*(n^2-R^2))-(1+2*n)); % Zar, Biostatistical Analysis, p. 617
	  x = find(h==max(h));x = x(1);
	  stats.mode(i) = binned(x);
	else
	  stats.m(i)=NaN;
	  stats.r(i)=NaN;
	  stats.k(i)=NaN;
	  stats.p(i)=NaN;
	  stats.mode(i)=NaN;
	end
end


function datapt = lvd_KinematicStateTasks(stateLogEntry, subTask, inFrame)
%lvd_KinematicStateTasks Summary of this function goes here
%   Detailed explanation goes here

    cartElem = stateLogEntry.getCartesianElementSetRepresentation();
    cartElem = cartElem.convertToFrame(inFrame);

    datapt = -1;
    switch subTask
        % Cartesian Elements
        case 'rVectX'
            rVect = cartElem.rVect;
            datapt = rVect(1);
        case 'rVectY'
            rVect = cartElem.rVect;
            datapt = rVect(2);
        case 'rVectZ'
            rVect = cartElem.rVect;
            datapt = rVect(3);
        case 'vVectX'
            vVect = cartElem.vVect;
            datapt = vVect(1);
        case 'vVectY'
            vVect = cartElem.vVect;
            datapt = vVect(2);
        case 'vVectZ'
            vVect = cartElem.vVect;
            datapt = vVect(3);

        % Keplerian Elements
        case 'sma'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.sma;
        case 'ecc'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.ecc;
        case 'inc'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = rad2deg(kepElemSet.inc);
        case 'raan'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = rad2deg(kepElemSet.raan);
        case 'arg'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = rad2deg(kepElemSet.arg);
        case 'tru'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = rad2deg(kepElemSet.tru);
        case 'mean'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = rad2deg(kepElemSet.getMeanAnomaly());

        % Geographic Elements
        case 'lat'
            geoElemSet = cartElem.convertToGeographicElementSet();
            datapt = rad2deg(geoElemSet.lat);
        case 'long'
            geoElemSet = cartElem.convertToGeographicElementSet();
            datapt = rad2deg(geoElemSet.long);
        case 'alt'
            geoElemSet = cartElem.convertToGeographicElementSet();
            datapt = geoElemSet.alt;
        case 'velAz'
            geoElemSet = cartElem.convertToGeographicElementSet();
            datapt = rad2deg(geoElemSet.velAz);
        case 'velEl'
            geoElemSet = cartElem.convertToGeographicElementSet();
            datapt = rad2deg(geoElemSet.velEl);
        case 'velMag'
            geoElemSet = cartElem.convertToGeographicElementSet();
            datapt = geoElemSet.velMag;

        % Universal Elements - don't need to do Kep repeated elements
        case 'c3'
            univElemSet = cartElem.convertToUniversalElementSet();
            datapt = univElemSet.c3;
        case 'tau'
            univElemSet = cartElem.convertToUniversalElementSet();
            datapt = univElemSet.tau;

        % Misc.
        case 'period'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.getPeriod();
        case 'rPe'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.getRadiusPeriapsis();
        case 'rApo'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.getRadiusApoapsis();
        case 'altPeri'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.getAltitudePeriapsis();
        case 'altApo'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.getAltitudeApoapsis();
        case 'H1'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [datapt, ~, ~, ~] = kepElemSet.getEquinoctialElements();
        case 'K1'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, datapt, ~, ~] = kepElemSet.getEquinoctialElements();
        case 'H2'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, ~, datapt, ~] = kepElemSet.getEquinoctialElements();
        case 'K2'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, ~, ~, datapt] = kepElemSet.getEquinoctialElements();
        case 'FPA'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = rad2deg(kepElemSet.getFlightPathAngle());
        case 'hyperVelUnitVectX'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [datapt, ~, ~, ~, ~, ~] = kepElemSet.getOutboundHyperbolicVelocityElements();
        case 'hyperVelUnitVectY'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, datapt, ~, ~, ~, ~] = kepElemSet.getOutboundHyperbolicVelocityElements();
        case 'hyperVelUnitVectZ'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, ~, datapt, ~, ~, ~] = kepElemSet.getOutboundHyperbolicVelocityElements();
        case 'hyperVelUnitVectRA'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, ~, ~, datapt, ~, ~] = kepElemSet.getOutboundHyperbolicVelocityElements();
        case 'hyperVelUnitVectDec'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, ~, ~, ~, datapt, ~] = kepElemSet.getOutboundHyperbolicVelocityElements();
        case 'hyperVelMag'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            [~, ~, ~, ~, ~, datapt] = kepElemSet.getOutboundHyperbolicVelocityElements();

        case 'radius'
            datapt = cartElem.getRadiusMagnitude();
        case 'velocity'
            datapt = cartElem.getVelocityMagnitude();
        case 'horzVel'
            [datapt, ~] = cartElem.getHorzVertVelocities();
        case 'vertVel'
            [~, datapt] = cartElem.getHorzVertVelocities();

        case 'longDriftRate'
            kepElemSet = cartElem.convertToKeplerianElementSet();
            datapt = kepElemSet.getLongDriftRate() * (3600*180/pi); %convert rad/sec to deg/hr

        case 'centralBodyId'
            datapt = stateLogEntry.centralBody.id;
    end
end


% Copyright (C) 2004 Josep Mones i Teixidor <jmones@puntbarra.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 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/>.

% -*- texinfo -*-
% @deftypefn {Function File} {@var{BW} = } octave_poly2mask (@var{x},@var{y},@var{m},@var{n})
% Convert a polygon to a region mask.
%
% BW=octave_poly2mask(x,y,m,n) converts a polygon, specified by a list of
% vertices in @var{x} and @var{y} and returns in a @var{m}-by-@var{n}
% logical mask @var{BW} the filled polygon. Region inside the polygon
% is set to 1, values outside the shape are set to 0.
%
% @var{x} and @var{y} should always represent a closed polygon, first
% and last points should be coincident. If they are not octave_poly2mask will
% close it for you. If @var{x} or @var{y} are fractional they are
% nearest integer.
%
% If all the polygon or part of it falls outside the masking area
% (1:m,1:n), it is discarded or clipped.
%
% This function uses scan-line polygon filling algorithm as described
% in http://www.cs.rit.edu/~icss571/filling/ with some minor
% modifications: capability of clipping and scan order, which can
% affect the results of the algorithm (algorithm is described not to
% reach ymax, xmax border when filling to avoid enlarging shapes). In
% this function we scan the image backwards (we begin at ymax and end
% at ymin), and we don't reach ymin, xmin, which we believe should be
% compatible with MATLAB.
% @end deftypefn

% TODO: check how to create a logical BW without any conversion

function BW = octave_poly2mask (x, y, m, n)
  if (nargin ~= 4)
    print_usage ();
  end

  % check x and y
  x = round (x (:).');
  y = round (y (:).');
  if (length (x) < 3)
    error ('octave_poly2mask: polygon must have at least 3 vertices.');
  end
  if (length (x) ~= length (y))
    error ('octave_poly2mask: length of x doesn''t match length of y.');
  end

  % create output matrix
  BW = false (m, n);

  % close polygon if needed
  if ((x (1) ~= x (length (x))) || (y (1) ~= y (length (y))))
    x = horzcat (x, x (1));
    y = horzcat (y, y (1));
  end

  % build global edge table
  ex = [x(1:length (x) - 1); x(1, 2:length (x))]; % x values for each edge
  ey = [y(1:length (y) - 1); y(1, 2:length (y))]; % y values for each edge
  idx = (ey(1, :) ~= ey(2, :));                 % eliminate horizontal edges
  ex = ex (:, idx);
  ey = ey (:, idx);
  eminy = min (ey);                               % minimum y for each edge
  emaxy = max (ey);                               % maximum y for each edge
  t = (ey == [eminy; eminy]);                     % values associated to miny
  exvec = ex(:);
  exminy = exvec(t);                            % x values associated to min y
  exmaxy = exvec(~t);                           % x values associated to max y
  emaxy = emaxy.';                                % we want them vertical now...
  eminy = eminy.';
  m_inv = (exmaxy - exminy)./(emaxy - eminy);     % calculate inverse slope
  ge = [emaxy, eminy, exmaxy, m_inv];             % build global edge table
  ge = sortrows (ge, [1, 3]);                     % sort on eminy and exminy

  % we add an extra dummy edge at the end just to avoid checking
  % while indexing it
  ge = [-Inf, -Inf, -Inf, -Inf; ge];

  % initial parity is even (0)
  parity = 0;

  % init scan line set to bottom line
  sl = ge (size (ge, 1), 1);

  % init active edge table
  % we use a loop because the table is sorted and edge list could be
  % huge
  ae = [];
  gei = size (ge, 1);
  while (sl == ge (gei, 1))
    ae = [ge(gei, 2:4); ae];
    gei = gei - 1;
  end

  % calc minimum y to draw
  miny = min (y);
  if (miny < 1)
    miny = 1;
  end

  while (sl >= miny)
    % check vert clipping
    if (sl <= m)
      % draw current scan line
      % we have to round because 1/m is fractional
      ie = round (reshape (ae (:, 2), 2, size (ae, 1)/2));

      % this discards left border of image (this differs from version at
      % http://www.cs.rit.edu/~icss571/filling/ which discards right
      % border) but keeps an exception when the point is a vertex.
      ie (1, :) = ie (1, :) + (ie (1, :) ~= ie (2, :));

      % we'll clip too, just in case m,n is not big enough
      ie (1, (ie (1, :) < 1)) = 1;
      ie (2, (ie (2, :) > n)) = n;

      % we eliminate segments outside window
      ie = ie (:, (ie (1, :) <= n));
      ie = ie (:, (ie (2, :) >= 1));
      for i = 1:size(ie,2)
        BW (sl, ie (1, i):ie (2, i)) = true;
      end
    end

    % decrement scan line
    sl = sl - 1;

    % eliminate edges that eymax==sl
    % this discards ymin border of image (this differs from version at
    % http://www.cs.rit.edu/~icss571/filling/ which discards ymax).
    ae = ae ((ae (:, 1) ~= sl), :);

    % update x (x1=x0-1/m)
    ae(:, 2) = ae(:, 2) - ae(:, 3);

    % update ae with new values
    while (sl == ge (gei, 1))
      ae = vertcat (ae, ge (gei, 2:4));
      gei = gei - 1;
    end

    % order the edges in ae by x value
    if (size(ae,1) > 0)
      ae = sortrows (ae, 2);
    end
  end
end

% This should create a filled octagon
%!demo
%! s = [0:pi/4:2*pi];
%! x = cos (s) * 90 + 101;
%! y = sin (s) * 90 + 101;
%! bw = octave_poly2mask(x, y, 200, 200);
%! imshow (bw);

% This should create a 5-vertex star
%!demo
%! s = [0:2*pi/5:pi*4];
%! s = s ([1, 3, 5, 2, 4, 6]);
%! x = cos (s) * 90 + 101;
%! y = sin (s) * 90 + 101;
%! bw = octave_poly2mask (x, y, 200, 200);
%! imshow (bw);

%!# Convex polygons

%!shared xs, ys, Rs, xt, yt, Rt
%! xs=[3,3,10,10];
%! ys=[4,12,12,4];
%! Rs=zeros(16,14);
%! Rs(5:12,4:10)=1;
%! Rs=logical(Rs);
%! xt=[1,4,7];
%! yt=[1,4,1];
%! Rt=[0,0,0,0,0,0,0;
%!     0,0,1,1,1,1,0;
%!     0,0,0,1,1,0,0;
%!     0,0,0,1,0,0,0;
%!     0,0,0,0,0,0,0];
%! Rt=logical(Rt);

%!assert(octave_poly2mask(xs,ys,16,14),Rs);          # rectangle
%!assert(octave_poly2mask(xs,ys,8,7),Rs(1:8,1:7));   # clipped
%!assert(octave_poly2mask(xs-7,ys-8,8,7),Rs(9:16,8:14)); # more clipping

%!assert(octave_poly2mask(xt,yt,5,7),Rt);            # triangle
%!assert(octave_poly2mask(xt,yt,3,3),Rt(1:3,1:3));   # clipped

%!# Concave polygons

%!test
%! x=[3,3,5,5,8,8,10,10];
%! y=[4,12,12,8,8,11,11,4];
%! R=zeros(16,14);
%! R(5:12,4:5)=1;
%! R(5:8,6:8)=1;
%! R(5:11,9:10)=1;
%! R=logical(R);
%! assert(octave_poly2mask(x,y,16,14), R);

%!# Complex polygons
%!test
%! x=[1,5,1,5];
%! y=[1,1,4,4];
%! R=[0,0,0,0,0,0;
%!    0,0,1,1,0,0;
%!    0,0,1,1,0,0;
%!    0,1,1,1,1,0;
%!    0,0,0,0,0,0];
%! R=logical(R);
%! assert(octave_poly2mask(x,y,5,6), R);


% SP_INTEGRAL_PRESERVING_TRANSFORM: apply the integral-preserving transform to the functions in the parametric domain
%
%     sp = sp_integral_preserving_transform (space, msh)
%
% INPUTS:
%
%    space:   structure with the information in the parametric domain (see sp_scalar/sp_evaluate_col)
%    msh:     msh structure containing the information of the parametrization
%              in the points where basis functions have to be computed (see msh_cartesian/msh_evaluate_col)
%
%              Name     |   Default value |  Meaning
%           ------------+-----------------+----------------------------------
%            value      |      true       |  compute shape_functions
%
% OUTPUT:
%
%    sp: struct representing the discrete function space, with the following fields:
%              (see the article for a detailed description)
%
%    FIELD_NAME      (SIZE)                                 DESCRIPTION
%    ncomp           (scalar)                               number of components of the functions of the space (actually, 1)
%    ndof            (scalar)                               total number of degrees of freedom
%    ndof_dir        (ncomp x ndim matrix)                  for each component, number of degrees of freedom along each direction
%    nsh_max         (scalar)                               maximum number of shape functions per element
%    nsh             (1 x msh_col.nel vector)               actual number of shape functions per each element
%    connectivity    (nsh_max x msh_col.nel vector)         indices of basis functions that do not vanish in each element
%    shape_functions (msh_col.nqn x nsh_max x msh_col.nel)  basis functions evaluated at each quadrature node in each element
%
% Copyright (C) 2015 Rafael Vazquez
%
%    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 sp = sp_integral_preserving_transform (sp, msh, value)

  if (nargin < 3 && isfield (sp, 'shape_functions'))
    value = true;
  end

  if (value)
    jacdet = reshape (geopdes_det__ (msh.geo_map_jac), msh.nqn, 1, msh.nel);
    sp.shape_functions = bsxfun (@rdivide, sp.shape_functions, jacdet);
    sp.shape_functions = sp.shape_functions;
    if (isfield (msh, 'side_number'))
      sp.shape_functions = sp.shape_functions * (-1)^msh.side_number;
    end
  end

  if (isfield (sp, 'shape_function_gradients'))
    sp = rmfield (sp, 'shape_function_gradients');
  end
  if (isfield (sp, 'shape_function_hessians'))
    sp = rmfield (sp, 'shape_function_hessians');
  end

end


function varargout=bss_decomp_tvfilt(varargin)

% decompose an estimated source into target/interference/noise/artefacts components, assuming the admissible distortion is a time-varying filter.
%
% Usage:
%
% [s_target,e_interf[,e_noise],e_artif]=bss_decomp_tvfilt(se,index,S[,N],tvshape,tvstep,L)
%
% Input:
%   - se: row vector of length T containing the estimated source,
%   - index: points which component of S se has to be compared to,
%   - S: n x T matrix containing the original sources,
%   - N: m x T matrix containing the noise on the obseravtions (if any).
%   - tvshape : row vector of length V at most T containing the shape of the elementary
%     allowed time variations of the filter coefficients
%   - tvstep  : hop size (in number of samples) between two consecutive
%     variations of the filter coefficients
%   - L: the number of lags
%
% Output:
%   - s_target: row vector of length T containing the target source(s)
%   contribution,
%   - e_interf: row vector of length T containing the interferences
%   contribution,
%   - e_noise: row vector of length T containing the noise contribution (if
%   any),
%   - e_artif: row vector of length T containing the artifacts
%   contribution.
%
% Developers:  - Cedric Fevotte (cf269@cam.ac.uk) - Emmanuel Vincent
% (vincent@ircam.fr) - Remi Gribonval (remi.gribonval@irisa.fr)

se=varargin{1}; index=varargin{2}; S=varargin{3};

switch nargin
    case 5
        N=[]; tvshape = varargin{4}; tvstep = varargin{5}; L = varargin{6};
    case 6
        N=varargin{4}; tvshape = varargin{5}; tvstep = varargin{6}; L = varargin{7};
    otherwise
        disp('Wrong number of arguments.')
end

[ne,Te]=size(se);
[n,T]=size(S);

%%%%%%%%%% WARNINGS %%%%%%%%%%%%%
switch isempty(N)
    case 1
        if n>T | ne>Te, disp('Watch out: signals must be in rows.'), return; end
        if ne~=1, disp('Watch out: se must contain only one row.'), return; end
        if T~=Te, disp('Watch out: se and S have different lengths.'), return; end
    case 0
        [m,Tm]=size(N);
        if n>T | ne>Te | m>Tm, disp('Watch out: signals must be in rows.'), return; end
        if ne~=1, disp('Watch out: se must contain only one row.'), return; end
        if T~=Te, disp('Watch out: S and Se have different lengths.'), return; end
        if T~=Tm, disp('Watch out: N, S and Se have different lengths.'), return; end
end

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

% Create the space of target source(s)
target_space = bss_make_lags(S(index,:),L);
% Create the space of sources
sources_space= bss_make_lags(S,L);
% Create the noise space
noise_space  = bss_make_lags(N,L);

s_target=zeros(1,T);
e_interf=zeros(1,T);
e_artif=zeros(1,T);
if isempty(noise_space)==0, e_noise=zeros(1,T); end

%%% Target source(s) contribution %%%
s_target = bss_tvproj(se,target_space,tvshape,tvstep);

%%% Interferences contribution %%%
P_S_se = bss_tvproj(se,[sources_space],tvshape,tvstep);
e_interf = P_S_se - s_target;

switch isempty(noise_space)
    case 1 % No noise
        %%% Artifacts contribution %%%
        e_artif= se - P_S_se;

        %%% Output %%%
        varargout{1}=s_target;
        varargout{2}=e_interf;
        varargout{3}=e_artif;

    case 0 % Noise
        %%% Noise contribution %%%
        P_SN_se= bss_tvproj(se,[sources_space;noise_space],tvshape,tvstep);
        e_noise=P_SN_se-P_S_se;

        %%% Artifacts contribution %%%
        e_artif=se-P_SN_se;

        %%% Output %%%
        varargout{1}=s_target;
        varargout{2}=e_interf;
        varargout{3}=e_noise;
        varargout{4}=e_artif;
end