-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathpspm_get_txt.m
165 lines (144 loc) · 5.72 KB
/
pspm_get_txt.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
function [sts, import, sourceinfo] = pspm_get_txt(datafile, import)
% ● Description
% pspm_get_txt is the main function for import of text files
% ● Format
% [sts, import, sourceinfo] = pspm_get_txt(datafile, import);
% ● Arguments
% ┌─datafile: a .txt-file containing numerical data (with any delimiter) and
% │ optionally the channel names in the first line.
% ├───import: import job structure
% │ - required fields:
% ├────.type: A char array corresponding to a valid PsPM data type, see
% │ `pspm_init.m` for more details.
% ├─.channel: A numeric value representing the column number of the
% │ corresponding numerical data.
% │- optional fields:
% ├─.delimiter:
% │ A char array corresponding to the delimiter used in the datafile
% │ to delimit data columns. To be used it should be specified on
% │ the first import cell, e.g.: import{1}.delimiter == ','
% │ Default: white-space (see textscan function)
% ├─.header_lines:
% │ A numeric value corresponding to the number of header lines.
% │ Which means the data start on line number: "header_lines + 1".
% │ To be used it should be specified on the first import cell,
% │ e.g.: import{1}.header_lines == 3. Default: 1.
% ├─.channel_names_line:
% │ A numeric value corresponding to the line number where the
% │ channel names are specified. To be used it should be specified
% │ on the first import cell, e.g. import{1}.channel_names_line == 2
% │ Default: 1.
% └─.exclude_columns:
% A numeric value corresponding to the number of columns to
% exclude starting from the left. To be used it should be
% specified on the first import cell, e.g.
% import{1}.exclude_columns == 2. Default: 0.
% ● History
% Introduced in PsPM 3.0
% Written in 2008-2015 by Dominik R Bach (Wellcome Trust Centre for Neuroimaging)
% 2020 Ivan Rojkov (UZH) - added dsv support
% Maintained in 2022 by Teddy Chao (UCL)
%% Initialise
global settings
if isempty(settings)
pspm_init;
end
sts = -1;
sourceinfo = [];
% check import structure options
% -------------------------------------------------------------------------
if ~isfield(import{1}, 'delimiter') || isempty(import{1}.delimiter)
delim = 0;
elseif ~ischar(import{1}.delimiter)
warning('ID:invalid_input','The ''delimiter'' option should be a char array.')
return;
else
delim = import{1}.delimiter;
end
if ~isfield(import{1}, 'header_lines')
header_lines = 1;
elseif ~isnumeric(import{1}.header_lines)
warning('ID:invalid_input','The ''header_lines'' option should be a numeric value.')
return;
else
header_lines = import{1}.header_lines;
end
if ~isfield(import{1}, 'channel_names_line')
channel_names_line = 1;
if header_lines < channel_names_line, channel_names_line=0; end
elseif ~isnumeric(import{1}.channel_names_line)
warning('ID:invalid_input','The ''channel_names_line'' option should be a numeric value.')
return;
else
channel_names_line = import{1}.channel_names_line;
end
if ~isfield(import{1}, 'exclude_columns')
exclude_columns = 0;
elseif ~isnumeric(import{1}.exclude_columns)
warning('ID:invalid_input','The ''exclude_columns'' option should be a numeric value.')
return;
else
exclude_columns = import{1}.exclude_columns;
end
% read channel names
% -------------------------------------------------------------------------
fid = fopen(datafile);
% go to the specific line to read the channel names
if channel_names_line ~= 0
for k=1:channel_names_line-1
fgetl(fid); % read and dump
end
end
if ischar(delim)
channel_names = textscan(fgetl(fid), '%s', 'Delimiter', delim);
else
channel_names = textscan(fgetl(fid), '%s');
end
channel_names = channel_names{1};
fclose(fid);
% load & check data
% -------------------------------------------------------------------------
fid = fopen(datafile);
formatSpec = repmat('%f', 1, numel(channel_names));
if exclude_columns
formatSpec = repmat('%*s', 1, exclude_columns);
formatSpec = [formatSpec,repmat('%f', 1,numel(channel_names)-exclude_columns)];
end
if ischar(delim)
data = textscan(fid, formatSpec, 'HeaderLines', header_lines, 'Delimiter', delim);
else
data = textscan(fid, formatSpec, 'HeaderLines', header_lines);
end
fclose(fid);
try
data = cell2mat(data);
if isempty(data), error('The imported data are empty.'); end
catch
warning('ID:textscan_error','An error occured while reading a textfile.\n');
return;
end
% warning('An error occured while reading a textfile.\n'); return; end;
% select desired channels
% -------------------------------------------------------------------------
for k = 1:numel(import)
% define channel number
if import{k}.channel > 0
channel = import{k}.channel;
elseif channel_names_line ~= 0
channel = pspm_find_channel(channel_names, import{k}.type);
if channel < 1, return; end;
else
warning('ID:invalid_input', ...
['Neiter ''channel'' nor ''channel_names_line'' options were specified.', ...
' Not able to import the data.'])
return;
end
if channel > size(data, 2), warning('ID:channel_not_contained_in_file', 'Channel %02.0f not contained in file %s.\n', channel, datafile); return; end;
import{k}.data = data(:, channel);
if isfield(import{k},'typeno') && strcmpi(settings.channeltypes(import{k}.typeno).data, 'events')
import{k}.marker = 'continuous';
end;
sourceinfo.channel{k} = sprintf('Data column %02.0', channel);
end;
sts = 1;
return