-
Notifications
You must be signed in to change notification settings - Fork 8
/
rdmat.m
179 lines (155 loc) · 4.65 KB
/
rdmat.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
function varargout=rdmat(varargin)
%
% [tm,signal,Fs,siginfo]=rdmat(recordName)
%
% Import a signal in physical units from a *.mat file generated by WFDB2MAT.
% Required Parameters:
%
% recorName
% String specifying the name of the *.mat file.
%
% Outputs are:
%
% tm
% A Nx1 array of doubles specifying the time in seconds.
% signal
% A NxM matrix of doubles contain the signals in physical units.
% Fs
% A 1x1 integer specifying the sampling frequency in Hz for the entire record.
%siginfo
% A LxN cell array specifying the signal siginfo. Currently it is a
% structure with the following fields:
%
% siginfo.Units
% siginfo.Baseline
% siginfo.Gain
% siginfo.Description
%
% NOTE:
% You can use the WFDB2MAT command in order to convert the record data into a *.mat file,
% which can then be loaded into MATLAB/Octave's workspace using the LOAD command.
% This sequence of procedures is quicker (by several orders of magnitude) than calling RDSAMP.
% The LOAD command will load the signal data in raw units, use RDMAT to load the signal in physical units.
%
% KNOWN LIMITATIONS:
% This function currently does support several of the features described
% in the WFDB record format (such as multiresolution signals) :
% http://www.physionet.org/physiotools/wag/header-5.htm
% If you are not sure that the record (or database format) you are reading is
% supported, you can do an integrity check by comparing the output with RDSAMP:
%
% [tm,signal,Fs,siginfo]=rdmat('200m');
% [tm2,signal2]=rdsamp('200m');
% if(sum(abs(signal-signal2)) !=0);
% error('Record not compatible with RDMAT');
% end
%
%
% Written by Ikaro Silva, 2014
% Last Modified: November 26, 2014
% Version 1.2
%
% Since 0.9.7
%
% %Example:
% wfdb2mat('mitdb/200')
%tic;[tm,signal,Fs,siginfo]=rdmat('200m');toc
%tic;[signal2]=rdsamp('200m');toc
% sum(abs(signal-signal2))
%
%
% See also RDSAMP, WFDB2MAT
%endOfHelp
%Set default pararameter values
inputs={'recordName'};
defGain=200; %Default value for missing gains
for n=1:nargin
if(~isempty(varargin{n}))
eval([inputs{n} '=varargin{n};'])
end
end
outputs={'tm','val','Fs','siginfo'};
fid = fopen([recordName, '.hea'], 'rt');
if(fid==-1)
error(['Could not open file: ' recordName '.hea !'])
end
%Following the documentation described in :
%http://www.physionet.org/physiotools/wag/header-5.htm
%to parse the header file
%Skip any comment lines
str=fgetl(fid);
while(strcmp(str(1),'#'))
str=fgetl(fid);
end
%Process Record Line Info
info=textscan(str,'%s %d %f %d %s %s');
M=info{2}; %Number of signals present
Fs=info{3};
%Process Signal Specification lines. Assumes no comments between lines.
siginfo(M)=struct();
for m = 1:M
str=fgetl(fid);
info=textscan(str,'%s %s %s %d %d %f %d %d %s');
fmt=info{2}{:};
gain=info{3}{:};
%Get Signal Units if present
ind=strfind(gain,'/');
if(~isempty(ind))
siginfo(m).Units=gain(ind+1:end);
gain=gain(1:ind-1);
end
%Get Signal Baseline if present
ind=strfind(gain,'(');
if(~isempty(ind))
ind2=strfind(gain,')');
siginfo(m).Baseline=str2num(gain(ind+1:ind2-1));
gain=gain(1:ind-1);
else
%If Baseline is missing, set it equal to ADC Zero
adc_zero=info{5};
if(~isempty(adc_zero))
siginfo(m).Baseline=double(adc_zero);
else
error('Could not obtain signal baseline');
end
end
%Get Signal Gain
gain=str2num(gain);
if(gain==0)
%Set gain to default value in this case
gain=defGain;
end
siginfo(m).Gain=double(gain);
%Get Signal Descriptor
siginfo(m).Description=info{9}{:};
% Store format for later
siginfo(m).fmt=fmt(1:strfind(fmt,'+')-1);
end
fclose(fid);
load([recordName '.mat']);
for m = 1:M
% Interpreting digital values of byte offset format 80
if strcmp(siginfo(m).fmt, '80')
val(m,:)=val(m,:)-128;
wfdbNaN=-128;
elseif strcmp(siginfo(m).fmt, '16')
wfdbNaN=-32768;
else
wfdbNaN=-2147483648;
end
% Fill in NaNs before subtracting and dividing.
val(m, val(m,:)==wfdbNaN)=nan;
%Convert from digital units to physical units.
% Mapping should be similar to that of rdsamp.c:
% http://www.physionet.org/physiotools/wfdb/app/rdsamp.c
val(m, :) = (val(m, :) - siginfo(m).Baseline ) / siginfo(m).Gain;
end
%Reshape to the Toolbox's standard format
val=val';
%Generate time vector
N=size(val,1);
tm =linspace(0,(N-1)/Fs,N);
for n=1:nargout
eval(['varargout{n}=' outputs{n} ';'])
end
end