0001 function stats = MapStats(map,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
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 if nargin < 1 | mod(length(varargin),2) ~= 0,
0068 error('Incorrect number of parameters (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).');
0069 end
0070
0071 if ~isfield(map,'z'),
0072 map.z = map.rate;
0073 map = rmfield(map,'rate');
0074 end
0075
0076
0077 threshold = 0.2;
0078 minPeak = 1;
0079 type = 'll';
0080 verbose = 0;
0081
0082 nDims = sum(size(map.z)>=2);
0083 if nDims == 2,
0084 minSize = 100;
0085 else
0086 minSize = 10;
0087 end
0088
0089
0090 for i = 1:2:length(varargin),
0091 if ~ischar(varargin{i}),
0092 error(['Parameter ' num2str(i+2) ' is not a property (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).']);
0093 end
0094 switch(lower(varargin{i})),
0095
0096 case 'threshold',
0097 threshold = varargin{i+1};
0098 if ~isdscalar(threshold,'>=0','<=1'),
0099 error('Incorrect value for property ''threshold'' (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).');
0100 end
0101
0102 case 'minsize',
0103 minSize = varargin{i+1};
0104 if ~isdscalar(minSize,'>=0'),
0105 error('Incorrect value for property ''minSize'' (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).');
0106 end
0107
0108 case 'minpeak',
0109 minPeak = varargin{i+1};
0110 if ~isdscalar(minPeak,'>=0'),
0111 error('Incorrect value for property ''minPeak'' (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).');
0112 end
0113
0114 case 'type',
0115 type = lower(varargin{i+1});
0116 if (nDims == 1 && ~isastring(type,'c','l')) || (nDims == 2 && ~isastring(type,'cc','cl','lc','ll')),
0117 error('Incorrect value for property ''type'' (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).');
0118 end
0119
0120 case {'verbose','debug'},
0121 verbose = lower(varargin{i+1});
0122 if ~isastring(verbose,'on','off'),
0123 error('Incorrect value for property ''verbose'' (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).');
0124 end
0125 verbose = strcmp(verbose,'on');
0126
0127 otherwise,
0128 error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help <a href="matlab:help MapStats">MapStats</a>'' for details).']);
0129
0130 end
0131 end
0132
0133
0134 circX = size(map.z,2) > 1 && strcmp(type(1),'c');
0135 circY = size(map.z,1) > 1 && ((size(map.z,2) > 1 && strcmp(type(2),'c')) || strcmp(type(1),'c'));
0136
0137
0138 stats.x = NaN;
0139 stats.y = NaN;
0140 stats.field = logical(zeros(0,0,0));
0141 stats.size = 0;
0142 stats.peak = 0;
0143 stats.mean = 0;
0144 stats.fieldX = [NaN NaN];
0145 stats.fieldY = [NaN NaN];
0146 stats.specificity = 0;
0147 stats.m = nan;
0148 stats.r = nan;
0149 stats.mode = nan;
0150 stats.k = nan;
0151
0152 if isempty(map.z), return; end
0153
0154
0155
0156 T = sum(map.time(:));
0157 p_i = map.time/(T+eps);
0158 lambda_i = map.z;
0159 lambda = lambda_i(:)'*p_i(:);
0160 if T == 0 || lambda == 0,
0161 stats.specificity = 0;
0162 else
0163 stats.specificity = sum(sum(p_i.*lambda_i/lambda.*log2(lambda_i/lambda)));
0164 end
0165
0166
0167
0168
0169 if max(max(map.z)) == 0,
0170 stats.field = logical(zeros(size(map.z)));
0171 return;
0172 end
0173
0174 nBinsX = max([1 length(map.x)]);
0175 nBinsY = max([1 length(map.y)]);
0176
0177
0178 z = map.z;
0179
0180 i = 1;
0181 while true,
0182
0183 [peak,idx] = max(z(:));
0184 if peak < minPeak, break; end
0185
0186 [y,x] = ind2sub(size(z),idx);
0187
0188 field1 = FindField(z,x,y,peak*threshold,circX,circY);
0189 size1 = sum(field1(:));
0190
0191
0192
0193
0194 m = peak*threshold;
0195 field2 = FindField(z-m,x,y,(peak-m)*threshold,circX,circY);
0196 size2 = sum(field2(:));
0197 if size2< 1/2*size1,
0198 field = field2;
0199 tc = ' ';sc = '*';
0200 else
0201 field = field1;
0202 tc = '*';sc = ' ';
0203 end
0204
0205 if verbose,
0206 disp([int2zstr(i,2) ') peak ' num2str(peak) ' @ (' int2str(x) ',' int2str(y) ')']);
0207 disp([' ' tc ' field size ' int2str(size1)]);
0208 disp([' ' sc ' subfield size ' int2str(size2)]);
0209 disp(' ');
0210 figure;
0211 if nDims == 1,
0212 plot(z);hold on;
0213 PlotIntervals(ToIntervals(field1),'rectangles');
0214 PlotIntervals(ToIntervals(field2),'bars');
0215 ylabel(tc);
0216 else
0217 subplot(3,1,1);imagesc(z);xlabel('Data');
0218 subplot(3,1,2);imagesc(field1);clim([0 1]);xlabel('Field');
0219 subplot(3,1,3);imagesc(field2);clim([0 1]);ylabel(tc);xlabel('Subfield');
0220 end
0221 end
0222 fieldSize = sum(field(:));
0223
0224 if fieldSize > minSize,
0225 stats.field(:,:,i) = field;
0226 stats.size(i) = fieldSize;
0227 stats.peak(i) = peak;
0228 stats.mean(i) = mean(z(field));
0229 idx = find(field & z == peak);
0230 [stats.y(i),stats.x(i)] = ind2sub(size(z),idx(1));
0231 [x,y] = FieldBoundaries(field,circX,circY);
0232 [stats.fieldX(i,:),stats.fieldY(i,:)] = FieldBoundaries(field,circX,circY);
0233 i = i + 1;
0234 end
0235
0236 z(field) = NaN;
0237 if all(isnan(z)), break; end
0238 end
0239
0240
0241
0242 if ~(nDims == 1 && circX), return; end
0243
0244 complex = map.z .* exp(j*map.x*2*pi) / sum(map.z);
0245 stats.m = angle(nanmean(complex));
0246 stats.r = abs(nansum(complex));
0247
0248 [maxZ, iMax] = max(map.z);
0249 TMax = map.x(iMax);
0250 stats.mode = TMax*2*pi;
0251
0252
0253 if stats.r < 0.53,
0254 stats.k = 2*stats.r+stats.r^3+5*stats.r^5/6;
0255 elseif stats.r < 0.85,
0256 stats.k = -0.4+1.39*stats.r+0.43/(1-stats.r);
0257 else
0258 stats.k = 1/(stats.r^3-4*stats.r^2+3*stats.r);
0259 end
0260
0261
0262
0263
0264
0265 function [x,y] = FieldBoundaries(field,circX,circY)
0266
0267
0268 x = find(any(field,1));
0269 if isempty(x),
0270 x = [NaN NaN];
0271 else
0272 x = [x(1) x(end)];
0273 end
0274 y = find(any(field,2));
0275 if isempty(y),
0276 y = [NaN NaN];
0277 else
0278 y = [y(1) y(end)];
0279 end
0280
0281
0282
0283
0284 if circX && x(1) == 1 && x(2) == size(field,2),
0285 xx = find(~all(field,1));
0286 if ~isempty(xx),
0287 x = [xx(end) xx(1)];
0288 end
0289 end
0290 if circY && y(1) == 1 && y(2) == size(field,1),
0291 yy = find(~all(field,2));
0292 if ~isempty(yy),
0293 y = [yy(end) yy(1)];
0294 end
0295 end
0296