circ_clust.m 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. function [cid, alpha, mu] = circ_clust(alpha, numclust, disp)
  2. %
  3. % [cid, alpha, mu] = circClust(alpha, numclust, disp)
  4. % Performs a simple agglomerative clustering of angular data.
  5. %
  6. % Input:
  7. % alpha sample of angles
  8. % numclust number of clusters desired, default: 2
  9. % disp show plot at each step, default: false
  10. %
  11. % Output:
  12. % cid cluster id for each entry of alpha
  13. % alpha sorted angles, matched with cid
  14. % mu mean direction of angles in each cluster
  15. %
  16. % Run without any input arguments for demo mode.
  17. %
  18. % Circular Statistics Toolbox for Matlab
  19. % By Marc J. Velasco and Philipp Berens, 2009
  20. % velasco@ccs.fau.edu
  21. % Distributed under Open Source BSD License
  22. if nargin < 2, numclust = 5; end;
  23. if nargin < 3, disp = 0; end
  24. if nargin < 1
  25. % demo mode
  26. n = 20;
  27. alpha = 2*pi*rand(n,1)-pi;
  28. numclust = 4;
  29. disp = 1;
  30. end;
  31. n = length(alpha);
  32. if n < numclust, error('Not enough data for clusters.'), end
  33. % prepare data
  34. cid = (1:n)';
  35. % main clustering loop
  36. num_unique = length(unique(cid));
  37. num_clusters_wanted = numclust;
  38. while(num_unique > num_clusters_wanted)
  39. % find centroid means...
  40. % calculate the means for each putative cluster
  41. mu = NaN(n,1);
  42. for j=1:n
  43. if sum(cid==j)>0
  44. mu(j) = circ_mean(alpha(cid==j)');
  45. end
  46. end
  47. % find distance between centroids...
  48. mudist = abs(circ_dist2(mu));
  49. % find closest pair of clusters/datapoints
  50. mindist = min(mudist(tril(ones(size(mudist)),-1)==1));
  51. [row, col] = find(mudist==mindist);
  52. % update cluster id's
  53. cid(cid==max(row)) = min(col);
  54. % update stop criteria
  55. num_unique = length(unique(cid));
  56. end
  57. % renumber cluster ids (so cids [1 3 7 10] => [1 2 3 4]
  58. cid2 = cid;
  59. uniquecids = unique(cid);
  60. for j=1:length(uniquecids)
  61. cid(cid2==uniquecids(j)) = j;
  62. end
  63. % compute final cluster means
  64. mu = NaN(num_unique,1);
  65. r = NaN(num_unique,1);
  66. for j=1:num_unique
  67. if sum(cid==j)>0
  68. mu(j) = circ_mean(alpha(cid==j)');
  69. r(j) = circ_r(alpha(cid==j)');
  70. end
  71. end
  72. if disp
  73. % plot output
  74. z2 = exp(i*alpha);
  75. plotColor(real(z2), imag(z2), cid, 2)
  76. zmu = r.*exp(i*mu);
  77. plotColor(real(zmu), imag(zmu), 1:num_unique, 2, '*', 10, 1)
  78. axis square
  79. set(gca, 'XLim', [-1, 1]);
  80. set(gca, 'YLim', [-1, 1]);
  81. end
  82. function plotColor(x, y, c, varargin)
  83. % FUNCTION plotColor(x, y, c, [figurenum], [pstring], [markersize], [overlay_tf]);
  84. % plots a scatter plot for x, y, using color values in c (c should be
  85. % categorical info), with c same size as x and y;
  86. % fourth argument can be figure#, otherwise, uses figure(1);
  87. %
  88. % colors should be positive integes
  89. % copyright (c) 2009 Marc J. Velasco
  90. if nargin < 4
  91. figurenum = 1;
  92. else
  93. figurenum = varargin{1};
  94. end
  95. if nargin < 5
  96. pstring = '.';
  97. else
  98. pstring = varargin{2};
  99. end
  100. if nargin < 6
  101. ms = 10;
  102. else
  103. ms = varargin{3};
  104. end
  105. if nargin < 7
  106. overlay = 0;
  107. else
  108. overlay = varargin{4};
  109. end
  110. csmall = unique(c);
  111. figure(figurenum);
  112. if ~overlay, close(figurenum); end
  113. figure(figurenum);
  114. colors={'y', 'b', 'r', 'g', 'c', 'k', 'm'};
  115. hold on;
  116. for j=1:length(csmall);
  117. ci = (c == csmall(j));
  118. plot(x(ci), y(ci), strcat(pstring, colors{mod(j, length(colors))+1}), 'MarkerSize', ms);
  119. end
  120. if ~overlay, hold off; end
  121. figure(figurenum)