% STD_APCLUSTER - Affinity propagation cluster for eeglab STUDY
% Wrapper for function provided by (Frey/Dueck, Science 2007)
%
% Usage:
% >> [IDX,C,sumd] = std_apcluster(clustdata);
%
% Inputs:
% clustdata -Preclustering matrix
%
% Optional inputs:
%
% 'maxits' -maximum number of iterations (default: 1000)
% 'convits' -if the estimated exemplars stay fixed for convits
% iterations, APCLUSTER terminates early (default: 100)
% 'dampfact' -update equation damping level in [0.5, 1). Higher
% values correspond to heavy damping, which may be needed
% if oscillations occur. (default: 0.9)
% 'dist' - Same as in pdist:
% 'euclidean' - Euclidean distance (default)
% 'seuclidean' - Standardized Euclidean distance. Each coordinate
% difference between rows in X is scaled by dividing
% by the corresponding element of the standard
% deviation S=NANSTD(X). To specify another value for
% S, use D=PDIST(X,'seuclidean',S).
% 'cityblock' - City Block distance
% 'minkowski' - Minkowski distance. The default exponent is 2. To
% specify a different exponent, use
% D = PDIST(X,'minkowski',P), where the exponent P is
% a scalar positive value.
% 'chebychev' - Chebychev distance (maximum coordinate difference)
% 'mahalanobis' - Mahalanobis distance, using the sample covariance
% of X as computed by NANCOV. To compute the distance
% with a different covariance, use
% D = PDIST(X,'mahalanobis',C), where the matrix C
% is symmetric and positive definite.
% 'cosine' - One minus the cosine of the included angle
% between observations (treated as vectors)
% 'correlation' - One minus the sample linear correlation between
% observations (treated as sequences of values).
% 'spearman' - One minus the sample Spearman's rank correlation
% between observations (treated as sequences of values).
% 'hamming' - Hamming distance, percentage of coordinates
% that differ
% 'jaccard' - One minus the Jaccard coefficient, the
% percentage of nonzero coordinates that differ
%
% Outputs:
%
% See also:
% std_plotinfocluster
%
% Author: Ramon Martinez-Cancino, SCCN, 2014
%
% Copyright (C) 2014 Ramon Martinez-Cancino,INC, SCCN
%
% 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 [idx,c,sumd] = std_apcluster(clustdata,varargin)
% Input stuffs
try
options = varargin;
if ~isempty( varargin ),
for i = 1:2:numel(options)
opts.(options{i}) = options{i+1};
end
else opts= [];
end
catch
disp('std_infocluster() error: calling convention {''key'', value, ... } error'); return;
end
try opts.maxits; catch, opts.maxits = 200; end; % Maximum number of iterations
try opts.convits; catch, opts.convits = 100; end; %
try opts.dampfact; catch, opts.dampfact = 0.9; end; %
try opts.dist; catch, opts.dist = 'euclidean'; end; % Distance metric
% Getting distance matrix
S = squareform(pdist(clustdata, opts.dist));
% Spell
[idxtmp,netsim,~,expref] = apcluster(S,mean(S(:)),'maxits', opts.maxits, 'convits', opts.convits, 'dampfact',opts.dampfact);
% --- Adjusting output formats --
% Getting centroids
rmpindx = 1:length(idxtmp);
c_indx = find(rmpindx(:) == idxtmp(:));
c = clustdata(c_indx,:);
% Reindexing indxtmp
centroids_realindx = unique(idxtmp);
idx = zeros(size(idxtmp));
dist_tmp = [];
for i = 1 : length(centroids_realindx)
hit_tmp = find(idxtmp == centroids_realindx(i));
idx(hit_tmp) = i;
for j = 1:length(hit_tmp)
dist_tmp(j) = pdist([c(i,:)' clustdata(hit_tmp(j),:)']', opts.dist);
end
sumd(i) = sum(dist_tmp);
dist_tmp = [];
end