-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathpspm_get_spike.m
134 lines (122 loc) · 4.86 KB
/
pspm_get_spike.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
function [sts, import, sourceinfo] = pspm_get_spike(datafile, import)
% ● Description
% pspm_get_spike is the main function for import of spike files
% ● Format
% [sts, import, sourceinfo] = pspm_get_spike(datafile, import);
% ● Arguments
% import: [struct]
% .denoise: for marker channels in CED spike format (recorded as 'level'),
% filters out markers duration longer than the value given here (in
% ms).
% ● History
% Introduced in PsPM 3.0
% Written in 2008-2015 by Dominik R Bach (Wellcome Trust Centre for Neuroimaging)
%% Initialise
global settings
if isempty(settings)
pspm_init;
end
sts = -1;
sourceinfo = [];
addpath(pspm_path('Import','SON'));
% get external file, using SON library
% -------------------------------------------------------------------------
warning off;
fid = fopen(datafile);
chanlist = SONChanList(fid);
% preallocate memory for speed
chandata = cell(numel(chanlist), 1);
errorflag = [];
% read channels
for channel = 1:numel(chanlist)
try
[chandata{channel}, chanhead{channel}]=SONGetChannel(fid, chanlist(channel).number, 'milliseconds');
catch
errorflag(channel)=1;
chandata{channel}=[];
chanhead{channel}.title='';
end;
end;
fclose(fid);
% delete empty channels
if ~isempty(errorflag)
ind=find(errorflag);
for channel=ind(end:-1:1)
chandata(channel)=[];
chanhead(channel)=[];
end;
end;
warning on;
% extract individual channels
% -------------------------------------------------------------------------
% loop through import jobs
for k = 1:numel(import)
% define channel number ---
if import{k}.channel > 0
channel = import{k}.channel;
else
channel = pspm_find_channel(arrayfun(@(i) chanhead{i}.title, 1:numel(chanhead), 'UniformOutput', 0), ...
import{k}.type); % bring channel names into a cell array
if channel < 1, return; end;
end;
if channel > numel(chandata), warning('ID:channel_not_contained_in_file', 'Channel %02.0f not contained in file %s.\n', channel, datafile); return; end;
sourceinfo.channel{k, 1} = sprintf('Channel %02.0f: %s', channel, chanhead{channel}.title);
% convert to waveform or get sample rate for wave channel types
if strcmpi(settings.channeltypes(import{k}.typeno).data, 'wave')
if chanhead{channel}.kind == 1 % waveform
import{k}.data = chandata{channel};
import{k}.sr = 1./chanhead{channel}.sampleinterval;
elseif chanhead{channel}.kind == 3 % timestamps
% get minimum frequency for reporting resolution
import{k}.minfreq = min(1./diff(chandata{channel}))*1000;
% convert pulse to waveform
import{k}.data = pspm_pulse_convert(chandata{channel}, settings.import.rsr, settings.import.sr);
import{k}.sr = settings.import.sr;
import{k}.minfreq = min(import{k}.data);
elseif chanhead{channel}.kind == 4 % up and down timestamps
pulse = chandata{channel};
% start with low to high
if chanhead{channel}.initLow==0
pulse(1)=[];
end;
pulse = pulse(1:2:end);
import{k}.data = pspm_pulse_convert(pulse, settings.import.rsr, settings.import.sr);
import{k}.sr = settings.import.sr;
import{k}.minfreq = min(workdata);
else
warning('Unknown channel format in CED spike file for import job %02.0f', k); return;
end;
% extract, and possibly denoise event channels
elseif strcmpi(settings.channeltypes(import{k}.typeno).data, 'events')
if chanhead{channel}.kind == 1 % waveform
import{k}.marker = 'continuous';
import{k}.data = chandata{channel};
import{k}.sr = 1./chanhead{channel}.sampleinterval;
elseif chanhead{channel}.kind == 4 && strcmpi(import{k}.type, 'marker') % for TTL marker channels with up AND down timestamps
kbchan = pspm_find_channel(arrayfun(@(i) chanhead{i}.title, 1:numel(chanhead), 'UniformOutput', 0), ...
{'keyboard'}); % keyboard channel doesn't exist by default but is needed for denoising
if kbchan > 0, kbdata = chandata{kbchan}; else kbdata = []; end;
if isfield(import{k}, 'denoise') && ~isempty(import{k}.denoise) && import{k}.denoise > 0
import{k}.data = pspm_denoise_spike(chandata{channel}, chanhead{channel}, kbdata, import{k}.denoise);
else
pulse = chandata{channel};
% start with low to high
if chanhead{channel}.initLow==0
pulse(1)=[];
end;
import{k}.data = pulse(1:2:end);
end;
import{k}.sr = 0.001; % milliseconds import for marker channels, see above
import{k}.marker = 'timestamp';
else % for TTL channels with up OR down timestamps
import{k}.data = chandata{channel};
import{k}.sr = 0.001; % milliseconds import for marker channels, see above
import{k}.marker = 'timestamp';
end;
end;
end;
% clear path and return
% -------------------------------------------------------------------------
rmpath(pspm_path('Import','SON'));
sts = 1;
return