-
Notifications
You must be signed in to change notification settings - Fork 1
/
findAllBurstsAPS.m
342 lines (286 loc) · 9.4 KB
/
findAllBurstsAPS.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
% This script extract all bursts from a set of recordings.
% It works exactly like the script analyseBursts.
% The arguments are a cellstring of input filename (files)
% and the name of the output file (mat-file format).
%
% The output contains (among other variables):
% bursttime: start time of each burst
% burstend: end-time of bursts
% burstdur: their durations
% burstsize: burst size (number of spikes)
% 22/07/10 mhh
% adapted to APS spike trains
% takes only one input file at a time
%
% example:
% findAllBurstsAPS('Phase_01.mat','Phase_01_bursts.mat',0.75,0.05,1);
% 17/10/22 M Savage
% Adpated into scripts which use retinaWavesDefault and can be more easily
% run
% function [rate, bursttime, burstend, burstdur, burstsize, testelecs, isbad, meanrate, wlen, wskip] = findAllBurstsAPS(file)
function [waveEx] = findAllBurstsAPS(file, openGUIFlag , varargin)
%find all the bursts in the given spike files.
%This function was rewritten to return the data so
%that a single function call can produce output graphs from input spike
%data, without having to produce burst files inbetween. This was done for
%use on CARMEN. It is generally more efficient to save burst files and use
%them when working locally.
%
%Parameters
%
%rthres - Threshold for ISI rank. If set to 0, it will use the default (0.2)
%
%scthres - Threshold for spike count. if set to 0, will use the default (0.05)
%
%spiketrate_window - indow size for spike rate calculation (sec). if 0, it
%will use the default (1)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% some parameters that can be amnually adjusted
% (they are different for the turtle data)
%
% Threshold for the ISI Rank:
% If the ISI rank drops below this value, then we may have a burst.
% rthres = 0.75;
%
% Threshold for the spike count
% scthres = 0.05;
%
% window size for spike rate calculation (sec)
% spiketrate_window = 1;
%
%Scaling is how many sections we split the window up into. We go through the spikes by this increment.
% scaling = 2;
%
% the APS array sampling frequency (Hz)
%freq = 7702;
%freq = 7572;
%freq = 7022;
% freq = 7062.1;
%freq = 17855
%
% minimum number of spikes required to accept a channel
% minNSpikes = 10;
%% deal with openGUI variable viewer
if nargin< 2 || isempty(openGUIFlag)
openGUIFlag = 1;
end
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load & combine spike data
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% deals with if you are starting from the .bxr or the spk file
if strfind(file,'waveEx')
load(file);
ops = waveEx.ops;
ops.OpenGUI = openGUIFlag;
try
spikeCh = waveEx.spikeData.spikes;
catch
spikeCh = waveEx.spikeData;
end
suffix = '';
elseif strfind(file,'Spk')
spikeCh = load(file);
ops = retinaWavesDefaults;
suffix = '_waveEx';
end
% if strfind(file,'Spk')
% spikeCh = load(file);
% ops = retinaWavesDefaults;
% suffix = '_waveEx';
% else
% load(file);
% ops = waveEx.ops;
% spikeCh = waveEx.spikeData.spikes;
% suffix = '';
% end
% deal with varargin overrides
if ~isempty(varargin)
varargin = reshape(varargin,2, [])';
for xx = 1:size(varargin, 1)
if isstring(varargin{xx,2})
eval(['ops.' varargin{xx,1} '=' varargin{xx,2} ';']);
elseif isnumeric(varargin{xx,2}) && length(varargin{xx,2}) == 1
eval(['ops.' varargin{xx,1} '=' num2str(varargin{xx,2}) ';']);
elseif isnumeric(varargin{xx,2}) && length(varargin{xx,2}) > 1
eval(['ops.' varargin{xx,1} '= [' num2str(varargin{xx,2}(:)') '];']);
end
end
end
c=1;
elecs = [];
for x=1:64
for y=1:64
chname = sprintf('Ch%02d_%02d', x, y);
% chname2=['Ch',num2str(x),'_',num2str(y)];
if isfield(spikeCh,chname)
[i,j] = find(eval(['spikeCh.' chname]));
if length(i)>ops.minNSpikes & length(i)
epos(c,1)=x; % electrode position
epos(c,2)=y; % electrode position
spikes.times{c} = i/ops.freq;
nspikes(c) = length(spikes.times{c}); % number of spikes
maxt(c) = max(spikes.times{c}); % max spike time
elecs = [elecs c];
c=c+1;
end
end
end
end
nochannels = c-1;
rectime = max(maxt(elecs));
ee = elecs;
testelecs = ee;
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% calculate Spike Rate and ISI Ranks
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
max_elec_no = max(ee);
rate = cell(1, max_elec_no);
meanrate = zeros(1,max_elec_no);
wlen = zeros(1,max_elec_no);
wskip = zeros(1,max_elec_no);
for enum = ee,
meanrate(enum) = length(spikes.times{enum})/max(spikes.times{enum});
wlen(enum) = ops.spiketrate_window;
wskip(enum) = wlen(enum)/ops.scaling;
working_wlen = wlen(enum);
working_wskip = wskip(enum);
% calculate ranks
d = diff(spikes.times{enum});
isitime = cumsum(d);
[dd i]=sort(d);
rankt = i; %/max(i);
[dd i]=sort(isitime(rankt));
isirank = i/max(i);
%new spike rate calculation
%% start it off
%work out how many sliding windows we can fit in. This is the right
%answer! You need the extra tiny bit added to make sure that exact integers
%or multiples of .25 don't end up in the lower boundary - the original
%code used strictly less than
times_in_windows = ceil((spikes.times{enum} + 0.00001)/ working_wskip);
% These are the indices we will need
addbit = ops.scaling-1;
number_of_windows = max(times_in_windows)-ops.scaling;
scount = zeros(1, max(times_in_windows)-ops.scaling);
for i = times_in_windows',
scount(max(1, i-addbit):min(i,number_of_windows)) = scount(max(1, i-addbit):min(i, number_of_windows))+1;
end
% Now we can calculate the counts by adding up all the values that are
% in the valid range.
rate{enum} = scount/working_wlen;
% find bursts
rc = 1;
r = isirank;
t = spikes.times{enum}(2:length(spikes.times{enum}));
[n v] = hist(scount,200);
tmp = find((fliplr(cumsum(fliplr(n/sum(n)))))<ops.scthres);
%%jpg. I have some files where this returns an error cos tmp is empty.
%%Why? I don't know!! I am not sure what this bit does. But I will
%%ignore it and just check for emptyness, though I must check with
%%Matthias what this does
if ~isempty(tmp)
nthres = max(2,ceil(v(tmp(1))));
nthresoff = ceil(v(tmp(1))*0.5);
%nthres = max(1,round(v(tmp(1))));
% nthresoff = max(1,round(v(tmp(1))*0.5));
burston = 0;
bc = 1;
dt = working_wlen;
while rc < length(r)-nthres,
if burston == 0 & r(rc) < ops.rthres,
if t(rc+nthres) < t(rc)+dt,
burston = 1;
bursttime{enum}(bc) = t(rc);
brc = rc;
end
elseif burston == 1
if t(rc+nthresoff) > t(rc)+dt,
% if t(rc)-bursttime{enum}(bc) > 1,
burstend{enum}(bc) = t(rc);
burstdur{enum}(bc) = t(rc)-bursttime{enum}(bc);
burstsize{enum}(bc) = rc - brc;
bc = bc + 1;
% else
% bursttime{enum}(bc) = [];
% end
burston = 0;
end
end
rc = rc + 1;
end
if burston == 1,
tmp = t(rc)-bursttime{enum}(bc);
burstend{enum}(bc) = bursttime{enum}(bc)+tmp;
burstdur{enum}(bc) = t(rc)-bursttime{enum}(bc);
burstsize{enum}(bc) = rc - brc;
bc = bc + 1;
end
end
end
%% Check for row saturation ie lines of activity across the entire chip,
% this is seen in a few recordings where the chip/system has bad contact
% M Savage 20230905
meaArr = nan(64,64);
for ch = 1:max_elec_no
meaArr(epos(ch,1),epos(ch,2))=meanrate(ch);
end
% get median for all channels used in the chip
meaArrMedian = median(meaArr, 'omitnan');
medianSD = std(meaArrMedian);
% create activity threshold as 3 STDs above the mean of the median
activtyLim = (3*medianSD) + mean(meaArrMedian);
rows2Clean = find(meaArrMedian>activtyLim);
if ~isempty(rows2Clean)
disp(['Removing electrode row(s): ' num2str(rows2Clean) ' due to high noise, please check output!!!']);
% find the indexes of the channels to delete
channels2Keep = ~ismember(epos(:,2),rows2Clean);
channels2Kill = ismember(epos(:,2),rows2Clean);
% clean per channel
rate(channels2Kill) = [];
testelecs(channels2Kill) = [];
epos(channels2Kill,:) = [];
meanrate(channels2Kill) = [];
nspikes(channels2Kill) = [];
wlen(channels2Kill) = [];
wskip(channels2Kill) = [];
spikes.times(channels2Kill) = [];
% clean stuff that only goes until last valid index,ie can be shorter than
% channeels2Kill
bursttime(channels2Kill(1:length(bursttime))) = [];
burstend(channels2Kill(1:length(burstend))) = [];
burstdur(channels2Kill(1:length(burstdur))) = [];
burstsize(channels2Kill(1:length(burstsize))) = [];
end
% scount(channels2Kill) = [];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% save the data
%[path name ext v]=fileparts(files);
[pathstr, name, ext] = fileparts(file);
% create experiment object
waveEx.dataFilepath = file;
waveEx.ops = ops;
% if the spike data does not exist already, create it
if ~isfield(waveEx, 'spikeData')
waveEx.spikeData = spikeCh;
end
% burstOutput
bursts.rate = rate;
bursts.bursttime = bursttime;
bursts.burstend = burstend;
bursts.burstdur = burstdur;
bursts.burstsize = burstsize;
bursts.testelecs = testelecs;
bursts.epos = epos;
bursts.meanrate = meanrate;
bursts.wlen = wlen;
bursts.wskip = wskip;
bursts.scount = scount;
bursts.nspikes = nspikes;
bursts.spikes = spikes;
waveEx.bursts = bursts;
outfile = fullfile(pathstr,[name,suffix,ext]);
% save(outfile,'rate','bursttime', 'burstend', 'burstdur', 'burstsize', 'testelecs', 'epos', 'meanrate', 'wlen', 'wskip', 'scount', 'nspikes','spikes');
save(outfile, 'waveEx');
end