


ANGLEHIST Magnitude-weighted angle histogram of polar data. WEIGHTS = ANGLEHIST(Z) histograms the angles of complex data Z into 10 equally spaced bins around 2*pi, with each element in Z contributing an amount equal to its magnitude to its corresponding bin. WEIGHTS = ANGLEHIST(Z, BINS), where BINS is a scalar, uses BINS bins. [WEIGHTS, ANGLEBINS] = ANGLEHIST(...) returns the bin centers corresponding to the weights. ANGLEHIST(...) without output arguments plots a polar bar histogram of the results.


0001 function [weights, anglebins] = anglehist(Z, bins) 0002 %ANGLEHIST Magnitude-weighted angle histogram of polar data. 0003 % WEIGHTS = ANGLEHIST(Z) histograms the angles of complex data Z into 10 0004 % equally spaced bins around 2*pi, with each element in Z contributing 0005 % an amount equal to its magnitude to its corresponding bin. 0006 % 0007 % WEIGHTS = ANGLEHIST(Z, BINS), where BINS is a scalar, uses BINS bins. 0008 % 0009 % [WEIGHTS, ANGLEBINS] = ANGLEHIST(...) returns the bin centers 0010 % corresponding to the weights. 0011 % 0012 % ANGLEHIST(...) without output arguments plots a polar bar histogram 0013 % of the results. 0014 0015 % Convert data into a column vector 0016 Z = Z(:); 0017 0018 % Argument parsing . . . 0019 if (nargin < 2) 0020 bins = 10; 0021 elseif (numel(bins) ~= 1) 0022 error('Second argument must be a scalar when it is supplied.'); 0023 end 0024 0025 % Make equally spaced bin centers 0026 bin_width = 2 * pi / bins; 0027 bin_center = 0 : bin_width : (2*pi - bin_width); 0028 0029 % To make the histogram, we first assign each number to a bin based on its angle. 0030 % We compute (1 - cos(angle(z) - ref_angle)) as a convenient way of comparing the 0031 % angle of each data value with a list of reference angles (this gives us minima 0032 % when the angle difference is a multiple of 2*pi and maxima at odd multiples of pi). 0033 dist_to_bin = (1 - cos(repmat(angle(Z), [1,bins]) - repmat(bin_center, [size(Z,1),1]))); 0034 0035 % We find the best bin by subtracting the best fit from each row and then looking for 0036 % zeros; this should label the best fit reference angle for each row with a 1 . . . 0037 bin_scores = [dist_to_bin - repmat(min(dist_to_bin, [], 2), [1, bins]) == 0]; 0038 0039 % . . . except for the annoying case where a data point falls between two bins. 0040 % The only fair way to arbitrate this is to choose one randomly; although this 0041 % is not efficient, it avoids the bias of choosing a default (e.g., always go 0042 % closer to 0 degrees). 0043 bin_ambiguity = find(sum(bin_scores, 2) > 1); % any ambiguous points? 0044 for ambi = 1:length(bin_ambiguity) 0045 ambiguous = bin_ambiguity(ambi); 0046 ambins = find(bin_scores(ambiguous,:)); % who are the contenders? 0047 ambins = ambins(randperm(length(bins))); % mix 'em up 0048 bin_scores(ambiguous, :) = 0; % zero the scores 0049 bin_scores(ambiguous, ambins(1)) = 1; % and set our winner 0050 end 0051 0052 % Turn the scores into bin numbers 0053 bin_assign = bin_scores * [1:bins]'; 0054 0055 % Now we add up the magnitudes of all data points in each bin and keep 0056 % this as the weight of the bin. 0057 histogram = full(sparse(bin_assign, 1, abs(Z), bins, 1)); 0058 0059 if (nargout > 0) 0060 weights = histogram'; 0061 if (nargout > 1) 0062 anglebins = bin_center; 0063 end 0064 else % we use patches because they look nicer than the lines in 'rose' 0065 xbars = zeros(3, 0); 0066 ybars = zeros(3, 0); 0067 for bin = 1:bins % draw a triangle for each bin 0068 [x, y] = pol2cart([0; bin_center(bin)-(bin_width/2); bin_center(bin)+(bin_width/2)], ... 0069 [0; histogram(bin); histogram(bin)]); 0070 xbars = cat(2, xbars, x); 0071 ybars = cat(2, ybars, y); 0072 end 0073 cla; 0074 polar(0, max(histogram)); % make a backdrop 0075 patch(xbars, ybars, 'b'); % and draw the patches 0076 end