0001 function [distance,units] = IsolationDistance(features,varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 distance = [];
0042 nFeatures = size(features,2)-3;
0043 units = [];
0044 show = 'off';
0045
0046
0047 if nargin < 1,
0048 error('Incorrect number of parameters (type ''help <a href="matlab:help IsolationDistance">IsolationDistance</a>'' for details).');
0049 end
0050
0051
0052 if length(size(features)) ~= 2 | size(features,2) < 4,
0053 error('Incorrect parameter ''features'' (type ''help <a href="matlab:help IsolationDistance">IsolationDistance</a>'' for details).');
0054 end
0055
0056
0057 for i = 1:2:length(varargin),
0058 if ~ischar(varargin{i}),
0059 error(['Parameter ' num2str(i) ' is not a property (type ''help <a href="matlab:help IsolationDistance">IsolationDistance</a>'' for details).']);
0060 end
0061 switch(lower(varargin{i})),
0062 case 'units',
0063 units = varargin{i+1};
0064 if ~isimatrix(units,'>=0') | size(units,2) ~= 2,
0065 error('Incorrect value for property ''units'' (type ''help <a href="matlab:help IsolationDistance">IsolationDistance</a>'' for details).');
0066 end
0067 case 'show',
0068 show = varargin{i+1};
0069 if ~isastring(show,'on','off'),
0070 error('Incorrect value for property ''show'' (type ''help <a href="matlab:help IsolationDistance">IsolationDistance</a>'' for details).');
0071 end
0072 otherwise,
0073 error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help <a href="matlab:help IsolationDistance">IsolationDistance</a>'' for details).']);
0074 end
0075 end
0076
0077
0078 artefacts = features(:,3)<=1;
0079 features(artefacts,:) = [];
0080
0081
0082 if isempty(units),
0083 units = features(:,[2 3]);
0084 units = unique(units,'rows');
0085 units = units(units(:,2)~=0&units(:,2)~=1,:);
0086 end
0087
0088 if strcmp(lower(show),'on'),
0089 figure;
0090 end
0091 for i = 1:size(units,1),
0092 unit = units(i,:);
0093 distance(i,1) = ComputeOnce(features,unit,show);
0094 end
0095
0096
0097
0098 function distance = ComputeOnce(features,unit,show)
0099
0100 distance = NaN;
0101 nFeatures = size(features,2)-3;
0102 unitStr = ['(' int2str(unit(1)) ',' int2str(unit(2)) ')'];
0103
0104
0105 spikesInCluster = features(:,2)==unit(1) & features(:,3)==unit(2);
0106 nSpikesInCluster = sum(spikesInCluster);
0107 spikesInElectrodeGroup = features(:,2)==unit(1);
0108 nSpikesInElectrodeGroup = sum(spikesInElectrodeGroup);
0109
0110
0111 if nSpikesInCluster < nFeatures,
0112 warning(['Not enough spikes for unit ' unitStr '.']);
0113 return
0114 end
0115 if nSpikesInCluster > nSpikesInElectrodeGroup/2,
0116 warning(['Too many spikes for unit ' unitStr '.']);
0117 return
0118 end
0119
0120
0121 m = mahal(features(:,4:end),features(spikesInCluster,4:end));
0122 mIn = m(spikesInCluster);
0123 mOut = m(~spikesInCluster);
0124
0125 sOut = sort(mOut);
0126 distance = sOut(nSpikesInCluster);
0127
0128 if strcmp(lower(show),'on'),
0129
0130 figure;
0131 bins = 0:1:300;
0132 subplot(3,1,1);
0133 pdfIn = hist(mIn,bins);
0134 pdfOut = hist(mOut,bins);
0135 plot(bins,[pdfIn',pdfOut']);
0136 xlim([0 100]);
0137 xlabel('Mahalanobis distance (PDF)');
0138 ylabel('Count');
0139 legend(['Cluster ' unitStr],'Others','location','southeast');
0140
0141
0142 subplot(3,1,2);
0143 cdfIn = cumsum(pdfIn);
0144 cdfOut = cumsum(pdfOut);
0145 plot(bins,[cdfIn',cdfOut']);
0146 xlim([0 100]);
0147 xlabel('Mahalanobis distance (CDF)');
0148 ylabel('Count');
0149 legend(['Cluster ' unitStr],'Others','location','southeast');
0150
0151
0152 subplot(3,1,3);
0153 sIn = sort(mIn);
0154 n = length(sIn);
0155 plot(1:n,[sIn sOut(1:n)]);
0156 hold on;
0157 plot([1 n],[distance distance],'k:');
0158 xlim([1 n*1.1]);
0159 xlabel('Spike #');
0160 ylabel('Mahalanobis distance');
0161 t = text(n,distance,num2str(round(100*distance)/100));
0162 set(t,'fontsize',12);
0163 drawnow;
0164 end