-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathSTSieve.m
192 lines (152 loc) · 4.9 KB
/
STSieve.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
function [stFiltTrain, stRejectTrain] = STSieve(stTrain, fMinISI, fMaxISI)
% STSieve - FUNCTION Filter a spike train by Inter-spike interval
%
% Usage: [stFiltTrain, stRejectTrain] = STSieve(stTrain, fMinISI, fMaxISI)
%
% STSieve will only pass spikes that fall between 'fMinISI' and 'fMaxISI'
% (inclusive). If either argument is supplied as an empty matrix, that
% argument will default to zero and infinity respectively. 'stTrain'
% should be either an instantiated or mapped spike train.
%
% 'stFiltTrain' will be a new spike train containing all spikes matching
% the ISI criteria. 'stRejectTrain' will be a new spike train containing
% the non-matching spikes.
%
% Note: When an ISI falls outside the sieve criteria, BOTH spikes that
% caused the failing ISI will be removed.
% Author: Dylan Muir <dylan@ini.phys.ethz.ch>
% Created: 7th November, 2004
% Copyright (c) 2004, 2005 Dylan Richard Muir
% -- Check arguments
if (nargin > 3)
disp('--- STSieve: Extra arguments ignored');
end
if (nargin < 3)
fMaxISI = [];
end
if (nargin < 2)
disp('*** STSieve: Incorrect usage');
help STSieve;
return;
end
if (~STIsValidSpikeTrain(stTrain))
disp('*** STSieve: Invalid spike train supplied');
return;
end
% -- Determine what spike train levels to use
if (STHasMapping(stTrain))
bUseMapping = true;
else
bUseMapping = false;
end
if (STHasInstance(stTrain))
bUseInstance = true;
else
bUseInstance = false;
end
% - Check that we at least have one of the two...
if (~(bUseMapping || bUseInstance))
disp('*** STSieve: The supplied train must contain either a mapping or an instance');
return;
end
% -- Process nodes
if (bUseInstance)
% - Make new instance nodes
stFiltTrain.instance = stTrain.instance;
stRejectTrain.instance = stTrain.instance;
end
if (bUseMapping)
% - Make new mapping nodes
stFiltTrain.mapping = stTrain.mapping;
stRejectTrain.mapping = stTrain.mapping;
if (stTrain.mapping.bChunkedMode)
spikeListMapping = stTrain.mapping.spikeList;
else
spikeListMapping = {stTrain.mapping.spikeList};
end
end
% - Get a standard set of spike list chunks
if (bUseInstance)
% - Use the instance set, preferably
if (stTrain.instance.bChunkedMode)
spikeList = stTrain.instance.spikeList;
else
spikeList = {stTrain.instance.spikeList};
end
else
spikeList = spikeListMapping;
% - Convert the spike list to seconds
for (nChunkIndex = 1:numel(spikeList))
spikeList{nChunkIndex} = spikeList{nChunkIndex} .* stTrain.mapping.fTemporalResolution;
end
end
% -- What should we filter?
if (isempty(fMinISI))
bFilterMin = false;
else
bFilterMin = true;
end
if (isempty(fMaxISI))
bFilterMax = false;
else
bFilterMax = true;
end
% -- Perform the filtering
nLastSpike = NaN;
for (nChunkIndex = 1:numel(spikeList))
% - Get spike times and ISIs, including the last spike from the previous
% chunk
vTimes = [nLastSpike; spikeList{nChunkIndex}(:, 1)];
nLastSpike = vTimes(end);
vISIs = diff(vTimes);
% - Apply and merge criteria
if (bFilterMin)
vbThrow = (vISIs < fMinISI);
else
vbThrow = false(size(vISIs));
end
if (bFilterMax)
vbThrow = vbThrow & (vISIs > fMaxISI);
end
% - Include both spikes corresponding to an ISI
vbThrow(2:end) = (vbThrow(2:end) + vbThrow(1:end-1)) > 0;
% - Are we filtering out the last spike from the previous chunk?
if (vbThrow(1))
% - Throw away the last spike
if (bUseInstance)
stRejectTrain.instance.spikeList{nChunkIndex-1} = stRejectTrain.instance.spikeList{nChunkIndex-1}(1:end-1);
end
if (bUseMapping)
stRejectTrain.mapping.spikeList{nChunkIndex-1} = stRejectTrain.mapping.spikeList{nChunkIndex-1}(1:end-1, :);
end
end
% - Filter the spike lists
if (bUseInstance)
KeepInstanceSpikeList{nChunkIndex} = spikeList{nChunkIndex}(~vbThrow(2:end));
ThrowInstanceSpikeList{nChunkIndex} = spikeList{nChunkIndex}(vbThrow(2:end));
end
if (bUseMapping)
KeepMappingSpikeList{nChunkIndex} = spikeListMapping{nChunkIndex}(~vbThrow(2:end), :);
ThrowMappingSpikeList{nChunkIndex} = spikeListMapping{nChunkIndex}(vbThrow(2:end), :);
end
end
% -- Restore spike lists to chunked / flat mode
if (bUseInstance)
if (stTrain.instance.bChunkedMode)
stFiltTrain.instance.spikeList = KeepInstanceSpikeList;
stRejectTrain.instance.spikeList = ThrowInstanceSpikeList;
else
stFiltTrain.instance.spikeList = KeepInstanceSpikeList{1};
stRejectTrain.instance.spikeList = ThrowInstanceSpikeList{1};
end
end
if (bUseMapping)
if (stTrain.mapping.bChunkedMode)
stFiltTrain.mapping.spikeList = KeepMappingSpikeList;
stRejectTrain.mapping.spikeList = ThrowMappingSpikeList;
else
stFiltTrain.mapping.spikeList = KeepMappingSpikeList{1};
stRejectTrain.mapping.spikeList = ThrowMappingSpikeList{1};
end
end
% --- END of STSieve.m ---