TEAP (Toolbox for Emotion Analysis using Physiological Signals) doc
spikes2bursts.m
Go to the documentation of this file.
1 function [H, s] = spikes2bursts(fn, varargin)
2 % spikes2bursts convert spike trains into bursts.
3 % Spikes with an interspike interval smaller
4 % than 75 ms are considered a burst. The results are stored as an
5 % event table.
6 %
7 % HDR = spikes2bursts(filename)
8 % ... = spikes2bursts(HDR)
9 % ... = spikes2bursts(... [, dT_Burst ])
10 % ... = spikes2bursts(... [, dT_Burst [, dT_Exclude] ])
11 % ... = spikes2bursts(... , 'dT_Burst', dT_Burst)
12 % ... = spikes2bursts(... , 'dT_Exclude', dT_Exclude)
13 % ... = spikes2bursts(filename, ... , '-o',outputFilename)
14 % ... = spikes2bursts(... , '-e',eventFilename)
15 % ... = spikes2bursts(... , '-b',burstFilename)
16 %
17 % Input:
18 % filename name of file containing spikes in the event table
19 % HDR header structure obtained by SOPEN, SLOAD, or meXSLOAD
20 % dT_Burst [default: 50e-3 s] am inter-spike-interval (ISI) exceeding this value,
21 % marks the beginning of a new burst
22 % dT_Exclude an interspike interval smaller than this value, indicates a
23 % double detection, and the second detection is deleted.
24 % in case of several consecutive ISI's smaller than this value,
25 % all except the first spikes are deleted.
26 % outputFilename
27 % filename to store the original data together with the newly compuated
28 % burst information. (Remark: this option is only supported if
29 % filename (not HDR) is given as first argument
30 % eventFilename
31 % filename to store event inforamation in GDF format. this is similar to
32 % the outputFile, except that the signal data is not included and is, therefore,
33 % much smaller than the outputFile
34 % burstFilename
35 % filename for the "burst table", containing basic properties of each burst,
36 % (it is an ASCII file in <tab>-delimited format)
37 %
38 % Output:
39 % HDR header structure as defined in biosig
40 % HDR.EVENT includes the detected spikes and bursts.
41 % HDR.BurstTable contains for each burst (each in a row) the following 5 numbers:
42 % channel number, sweep number, OnsetTime within sweep [s],
43 % number of spikes within burst, average inter-spike interval (ISI) [ms],
44 % and minimum ISI [ms]
45 % data signal data, one channel per column
46 % between segments, NaN values for 0.1s are introduced
47 %
48 % References:
49 %
50 
51 % $Id: detect_spikes_bursts.m 2739 2011-07-13 15:42:05Z schloegl $
52 % Copyright (C) 2011 by Alois Schloegl <alois.schloegl@gmail.com>
53 % This is part of the BIOSIG-toolbox http://biosig.sf.net/
54 %
55 % BioSig is free software: you can redistribute it and/or modify
56 % it under the terms of the GNU General Public License as published by
57 % the Free Software Foundation, either version 3 of the License, or
58 % (at your option) any later version.
59 %
60 % BioSig is distributed in the hope that it will be useful,
61 % but WITHOUT ANY WARRANTY; without even the implied warranty of
62 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63 % GNU General Public License for more details.
64 %
65 % You should have received a copy of the GNU General Public License
66 % along with BioSig. If not, see <http://www.gnu.org/licenses/>.
67 
68 if nargin < 1,
69  help spikes2bursts;
70 end;
71 
72 %%%%% default settings %%%%%
73 dT_Burst = 50e-3; %%% smaller ISI is a burst [s]
74 dT_Exclude = []; %%% for identifying double detections, spikes with smaller ISI are excluded
75 outFile = [];
76 evtFile = [];
77 burstFile = [];
78 
79 
80 %%%%% analyze input arguments %%%%%
81 k = 1;
82 K = 0;
83 while k <= length(varargin)
84  if ischar(varargin{k})
85  if (strcmp(varargin{k},'-e'))
86  k = k + 1;
87  evtFile = varargin{k};
88  elseif (strcmp(varargin{k},'-b'))
89  k = k + 1;
90  burstFile = varargin{k};
91  elseif (strcmp(varargin{k},'-o'))
92  k = k + 1;
93  outFile = varargin{k};
94  elseif (strcmpi(varargin{k},'dT_Burst'))
95  k = k + 1;
96  dT_Burst = varargin{k};
97  elseif (strcmpi(varargin{k},'dT_Exclude'))
98  k = k + 1;
99  dT_Exclude = varargin{k};
100  else
101  warning(sprintf('unknown input argument <%s>- ignored',varargin{k}));
102  end;
103  elseif isnumeric(varargin{k})
104  K = K + 1
105  switch (K)
106  case {1}
107  dT_Burst = varargin{k};
108  case {2}
109  dT_Exclude = varargin{k};
110  otherwise
111  warning(sprintf('unknown input argument <%f> - ignored',varargin{k}));
112  end;
113  end;
114  k = k+1;
115 end;
116 
117 
118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
119 % load data
120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 
122  if ischar(fn) && exist(fn,'file')
123  [s, HDR] = sload(fn);
124  elseif isstruct(fn)
125  HDR = fn;
126  else
127  help(mfilename);
128  end
129 
130  EVENT = HDR.EVENT;
131  ix = (EVENT.TYP ~= hex2dec('0202'));
132  %if ~all(ix) warning('previously defined bursts are ignored'); end;
133  EVENT.POS = EVENT.POS(ix);
134  EVENT.TYP = EVENT.TYP(ix);
135  if ~isfield(EVENT,'DUR');
136  EVENT.DUR = zeros(size(EVENT.POS));
137  else
138  EVENT.DUR = HDR.EVENT.DUR(ix);
139  end;
140  if ~isfield(EVENT,'CHN');
141  EVENT.CHN = zeros(size(EVENT.TYP));
142  else
143  EVENT.CHN = HDR.EVENT.CHN(ix);
144  end;
145 
146  Fs = HDR.SampleRate;
147  chan = unique(EVENT.CHN);
148 
149 
150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151 % Set Parameters for Burst Detection
152 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153  HDR.BurstTable = [];
154 
155  for ch = chan(:)'; % look for each channel
156  OnsetSpike = EVENT.POS((EVENT.CHN==ch) & (EVENT.TYP==hex2dec('0201'))); %% spike onset time [samples]
157  if isempty(OnsetSpike)
158  continue;
159  end;
160 
161  if ~isempty(dT_Exclude)
162  % --- remove double detections < 1 ms
163  OnsetSpike = OnsetSpike([1; 1+find(diff(OnsetSpike) > Fs * dT_Exclude)]);
164  end;
165 
166  %%%%%%% Burst Detection %%%%%%%%%%%%%%%%%%%
167  OnsetBurst = OnsetSpike ( [1; 1 + find( diff(OnsetSpike) > Fs * dT_Burst ) ] );
168 
169  DUR = repmat(NaN, size(OnsetBurst));
170  BurstTable = repmat(NaN, length(OnsetBurst), 6);
171  OnsetBurst(end+1) = inf;
172 
173  m2 = 0;
174  t0 = [1; EVENT.POS(EVENT.TYP==hex2dec('7ffe'))];
175  for m = 1:length(OnsetBurst)-1, % loop for each burst candidate
176  tmp = OnsetSpike( OnsetBurst(m) <= OnsetSpike & OnsetSpike < OnsetBurst(m+1) );
177  d = diff(tmp);
178  ix = sum(t0 < OnsetBurst(m)); %% number of sweep
179  T0 = t0(ix); % time since beginning of sweep
180  if length(tmp) > 1,
181  m2 = m2 + 1;
182  DUR(m) = length(tmp)*mean(d);
183  BurstTable(m,:) = [ch, ix, (OnsetBurst(m) - T0)/HDR.SampleRate, length(tmp), 1000*mean(d)/HDR.SampleRate, 1000*min(d)/HDR.SampleRate];
184  elseif length(tmp)==1
185  % single spikes are not counted as bursts, DUR(m)==NaN marks them as invalid
186  BurstTable(m,:) = [ch, ix, (OnsetBurst(m) - T0)/HDR.SampleRate, length(tmp), NaN,NaN];
187  end;
188  end;
189 
190  % remove single spike bursts
191  HDR.BurstTable = [HDR.BurstTable; BurstTable];
192 
193  EVENT.TYP = [EVENT.TYP; repmat(hex2dec('0202'), size(DUR))];
194  EVENT.POS = [EVENT.POS; OnsetBurst(1:end-1)];
195  EVENT.DUR = [EVENT.DUR; DUR];
196  EVENT.CHN = [EVENT.CHN; repmat(ch, size(DUR,1), 1) ];
197  end;
198 
199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 % Output
201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202  HDR.EVENT = EVENT;
203  H = HDR; %% return value
204  if ~isempty(burstFile),
205  fid = fopen(burstFile, 'w');
206  if (fid<0)
207  fprintf(2,'Warning can not open file <%s> - burst table not written\n',burstFile);
208  else
209  fprintf(fid,'#Burst\t#chan\t#sweep\tOnset [s] \t#spikes\tavgISI [ms] \tminISI [ms] \n');
210  for m = 1:size(HDR.BurstTable,1);
211  fprintf(fid,'%3d\t%d\t%d\t%9.5f\t%d\t%6.2f\t%6.2f\n', m, HDR.BurstTable(m,:) );
212  end;
213  if (fid>3) fclose(fid); end;
214  end;
215  end;
216 
217  if ~isempty(outFile) && exist('s','var')
218  %%% write data to output
219  HDR.TYPE = 'GDF';
220  HDR.VERSION = 3;
221  HDR.FILE = [];
222  HDR.FileName = outFile;
223  HDR.FILE.Path = '';
224  HDR.Dur = 1/HDR.SampleRate;
225  HDR = sopen(HDR, 'w');
226  if (HDR.FILE.FID < 0)
227  fprintf(2,'Warning can not open file <%s> - GDF file can not be written\n',HDR.FileName);
228  else
229  HDR = swrite(HDR,s);
230  HDR = sclose(HDR);
231  end;
232  end;
233  WarnState = warning;
234  warning('off');
235  if ~isempty(evtFile)
236  %%% write data to output
237  HDR.TYPE = 'EVENT';
238  HDR.VERSION = 3;
239  %[p,f,e]=fileparts(fn);
240  HDR.FILE = [];
241  HDR.FileName = evtFile;
242  HDR.FILE.Path = '';
243  HDR.NRec = 0;
244  HDR.SPR = 0;
245  HDR.Dur = 1/HDR.SampleRate;
246  HDR = rmfield(HDR,'AS');
247  HDR = sopen(HDR, 'w');
248  if (HDR.FILE.FID<0)
249  fprintf(2,'Warning can not open file <%s> - EVT file can not be written\n',HDR.FileName);
250  else
251  HDR = sclose(HDR);
252  end;
253  end;
254  warning(WarnState);
255 
256 
sclose
function sclose(in HDR)
swrite
function swrite(in HDR, in data)
sopen
function sopen(in arg1, in PERMISSION, in CHAN, in MODE, in arg5, in arg6)
spikes2bursts
function spikes2bursts(in fn, in varargin)