function [cid, alpha, mu] = circ_clust(alpha, numclust, disp) % % [cid, alpha, mu] = circClust(alpha, numclust, disp) % Performs a simple agglomerative clustering of angular data. % % Input: % alpha sample of angles % numclust number of clusters desired, default: 2 % disp show plot at each step, default: false % % Output: % cid cluster id for each entry of alpha % alpha sorted angles, matched with cid % mu mean direction of angles in each cluster % % Run without any input arguments for demo mode. % % Circular Statistics Toolbox for Matlab % By Marc J. Velasco and Philipp Berens, 2009 % velasco@ccs.fau.edu % Distributed under Open Source BSD License if nargin < 2, numclust = 5; end; if nargin < 3, disp = 0; end if nargin < 1 % demo mode n = 20; alpha = 2*pi*rand(n,1)-pi; numclust = 4; disp = 1; end; n = length(alpha); if n < numclust, error('Not enough data for clusters.'), end % prepare data cid = (1:n)'; % main clustering loop num_unique = length(unique(cid)); num_clusters_wanted = numclust; while(num_unique > num_clusters_wanted) % find centroid means... % calculate the means for each putative cluster mu = NaN(n,1); for j=1:n if sum(cid==j)>0 mu(j) = circ_mean(alpha(cid==j)'); end end % find distance between centroids... mudist = abs(circ_dist2(mu)); % find closest pair of clusters/datapoints mindist = min(mudist(tril(ones(size(mudist)),-1)==1)); [row, col] = find(mudist==mindist); % update cluster id's cid(cid==max(row)) = min(col); % update stop criteria num_unique = length(unique(cid)); end % renumber cluster ids (so cids [1 3 7 10] => [1 2 3 4] cid2 = cid; uniquecids = unique(cid); for j=1:length(uniquecids) cid(cid2==uniquecids(j)) = j; end % compute final cluster means mu = NaN(num_unique,1); r = NaN(num_unique,1); for j=1:num_unique if sum(cid==j)>0 mu(j) = circ_mean(alpha(cid==j)'); r(j) = circ_r(alpha(cid==j)'); end end if disp % plot output z2 = exp(i*alpha); plotColor(real(z2), imag(z2), cid, 2) zmu = r.*exp(i*mu); plotColor(real(zmu), imag(zmu), 1:num_unique, 2, '*', 10, 1) axis square set(gca, 'XLim', [-1, 1]); set(gca, 'YLim', [-1, 1]); end function plotColor(x, y, c, varargin) % FUNCTION plotColor(x, y, c, [figurenum], [pstring], [markersize], [overlay_tf]); % plots a scatter plot for x, y, using color values in c (c should be % categorical info), with c same size as x and y; % fourth argument can be figure#, otherwise, uses figure(1); % % colors should be positive integes % copyright (c) 2009 Marc J. Velasco if nargin < 4 figurenum = 1; else figurenum = varargin{1}; end if nargin < 5 pstring = '.'; else pstring = varargin{2}; end if nargin < 6 ms = 10; else ms = varargin{3}; end if nargin < 7 overlay = 0; else overlay = varargin{4}; end csmall = unique(c); figure(figurenum); if ~overlay, close(figurenum); end figure(figurenum); colors={'y', 'b', 'r', 'g', 'c', 'k', 'm'}; hold on; for j=1:length(csmall); ci = (c == csmall(j)); plot(x(ci), y(ci), strcat(pstring, colors{mod(j, length(colors))+1}), 'MarkerSize', ms); end if ~overlay, hold off; end figure(figurenum)