4
4
from wfdb import Annotation
5
5
6
6
7
- def resample_ann (tt , sample ):
8
- # tt: numpy.array as returned by signal.resample
9
- # sample: numpy.array containing indices of annotations (Annotation.sample)
10
-
11
- # Compute the new annotation indices
12
-
13
- tmp = numpy .zeros (len (tt ), dtype = 'int16' )
7
+ def resample_ann (resampled_t , ann_sample ):
8
+ """
9
+ Compute the new annotation indices
10
+
11
+ Parameters
12
+ ----------
13
+ resampled_t : numpy array
14
+ Array of signal locations as returned by scipy.signal.resample
15
+ ann_sample : numpy array
16
+ Array of annotation locations
17
+
18
+ Returns
19
+ -------
20
+ resampled_ann_sample : numpy array
21
+ Array of resampled annotation locations
22
+
23
+ """
24
+ tmp = numpy .zeros (len (resampled_t ), dtype = 'int16' )
14
25
j = 0
15
- tprec = tt [j ]
16
- for i , v in enumerate (sample ):
26
+ tprec = resampled_t [j ]
27
+ for i , v in enumerate (ann_sample ):
17
28
while True :
18
29
d = False
19
30
if v < tprec :
20
31
j -= 1
21
- tprec = tt [j ]
32
+ tprec = resampled_t [j ]
22
33
23
- if j + 1 == len (tt ):
34
+ if j + 1 == len (resampled_t ):
24
35
tmp [j ] += 1
25
36
break
26
37
27
- tnow = tt [j + 1 ]
38
+ tnow = resampled_t [j + 1 ]
28
39
if tprec <= v and v <= tnow :
29
40
if v - tprec < tnow - v :
30
41
tmp [j ] += 1
@@ -41,77 +52,144 @@ def resample_ann(tt, sample):
41
52
for i in idx :
42
53
for j in range (tmp [i ]):
43
54
res .append (i )
44
- assert len (res ) == len (sample )
55
+ assert len (res ) == len (ann_sample )
56
+
45
57
return numpy .asarray (res , dtype = 'int64' )
46
58
47
59
48
60
def resample_sig (x , fs , fs_target ):
49
- # x: a numpy.array containing the signal
50
- # fs: the current frequency
51
- # fs_target: the target frequency
52
-
53
- # Resample a signal
61
+ """
62
+ Resample a signal to a different frequency.
63
+
64
+ Parameters
65
+ ----------
66
+ x : numpy array
67
+ Array containing the signal
68
+ fs : int, or float
69
+ The original sampling frequency
70
+ fs_target : int, or float
71
+ The target frequency
72
+
73
+ Returns
74
+ -------
75
+ resampled_x : numpy array
76
+ Array of the resampled signal values
77
+ resampled_t : numpy array
78
+ Array of the resampled signal locations
79
+
80
+ """
54
81
55
82
t = numpy .arange (x .shape [0 ]).astype ('float64' )
56
83
57
84
if fs == fs_target :
58
85
return x , t
59
86
60
87
new_length = int (x .shape [0 ]* fs_target / fs )
61
- xx , tt = signal .resample (x , num = new_length , t = t )
62
- assert xx .shape == tt .shape and xx .shape [0 ] == new_length
63
- assert numpy .all (numpy .diff (tt ) > 0 )
64
- return xx , tt
88
+ resampled_x , resampled_t = signal .resample (x , num = new_length , t = t )
89
+ assert resampled_x .shape == resampled_t .shape and resampled_x .shape [0 ] == new_length
90
+ assert numpy .all (numpy .diff (resampled_t ) > 0 )
91
+
92
+ return resampled_x , resampled_t
65
93
66
94
67
95
def resample_singlechan (x , ann , fs , fs_target ):
68
- # x: a numpy.array containing the signal
69
- # ann: an Annotation object
70
- # fs: the current frequency
71
- # fs_target: the target frequency
72
-
73
- # Resample a single-channel signal with its annotations
74
-
75
- xx , tt = resample_sig (x , fs , fs_target )
76
-
77
- new_sample = resample_ann (tt , ann .sample )
96
+ """
97
+ Resample a single-channel signal with its annotations
98
+
99
+ Parameters
100
+ ----------
101
+ x: numpy array
102
+ The signal array
103
+ ann : wfdb Annotation
104
+ The wfdb annotation object
105
+ fs : int, or float
106
+ The original frequency
107
+ fs_target : int, or float
108
+ The target frequency
109
+
110
+ Returns
111
+ -------
112
+ resampled_x : numpy array
113
+ Array of the resampled signal values
114
+ resampled_ann : wfdb Annotation
115
+ Annotation containing resampled annotation locations
116
+
117
+ """
118
+
119
+ resampled_x , resampled_t = resample_sig (x , fs , fs_target )
120
+
121
+ new_sample = resample_ann (resampled_t , ann .sample )
78
122
assert ann .sample .shape == new_sample .shape
79
123
80
- new_ann = Annotation (ann .record_name , ann .extension , new_sample , ann .symbol , ann .num , ann .subtype , ann .chan , ann .aux_note , ann .fs )
81
- return xx , new_ann
82
-
124
+ resampled_ann = Annotation (ann .record_name , ann .extension , new_sample ,
125
+ ann .symbol , ann .num , ann .subtype , ann .chan , ann .aux_note , ann .fs )
83
126
84
- def resample_multichan (xs , ann , fs , fs_target , resamp_ann_chan = 0 ):
85
- # xs: a numpy.ndarray containing the signals as returned by wfdb.srdsamp
86
- # ann: an Annotation object
87
- # fs: the current frequency
88
- # fs_target: the target frequency
89
- # resample_ann_channel: the signal channel that is used to compute new annotation indices
127
+ return resampled_x , resampled_ann
90
128
91
- # Resample multiple channels with their annotations
92
129
130
+ def resample_multichan (xs , ann , fs , fs_target , resamp_ann_chan = 0 ):
131
+ """
132
+ Resample multiple channels with their annotations
133
+
134
+ Parameters
135
+ ----------
136
+ xs: numpy array
137
+ The signal array
138
+ ann : wfdb Annotation
139
+ The wfdb annotation object
140
+ fs : int, or float
141
+ The original frequency
142
+ fs_target : int, or float
143
+ The target frequency
144
+ resample_ann_channel : int, optional
145
+ The signal channel used to compute new annotation indices
146
+
147
+ Returns
148
+ -------
149
+ resampled_xs : numpy array
150
+ Array of the resampled signal values
151
+ resampled_ann : wfdb Annotation
152
+ Annotation containing resampled annotation locations
153
+
154
+ """
93
155
assert resamp_ann_chan < xs .shape [1 ]
94
156
95
157
lx = []
96
158
lt = None
97
159
for chan in range (xs .shape [1 ]):
98
- xx , tt = resample_sig (xs [:, chan ], fs , fs_target )
99
- lx .append (xx )
160
+ resampled_x , resampled_t = resample_sig (xs [:, chan ], fs , fs_target )
161
+ lx .append (resampled_x )
100
162
if chan == resamp_ann_chan :
101
- lt = tt
163
+ lt = resampled_t
102
164
103
165
new_sample = resample_ann (lt , ann .sample )
104
166
assert ann .sample .shape == new_sample .shape
105
167
106
- new_ann = Annotation (ann .record_name , ann .extension , new_sample , ann .symbol , ann . num , ann . subtype , ann . chan , ann . aux_note , ann . fs )
107
- return numpy . column_stack ( lx ), new_ann
168
+ resampled_ann = Annotation (ann .record_name , ann .extension , new_sample , ann .symbol ,
169
+ ann . num , ann . subtype , ann . chan , ann . aux_note , ann . fs )
108
170
171
+ return numpy .column_stack (lx ), resampled_ann
109
172
110
- def normalize (x , lb = 0 , ub = 1 ):
111
- # lb: Lower bound
112
- # ub: Upper bound
113
173
114
- # Resizes a signal between the lower and upper bound
174
+ def normalize (x , lb = 0 , ub = 1 ):
175
+ """
176
+ Normalize a signal between the lower and upper bound
177
+
178
+ Parameters
179
+ ----------
180
+ x : numpy array
181
+ Original signal to be normalized
182
+ lb : int, or float
183
+ Lower bound
184
+ ub : int, or float
185
+ Upper bound
186
+
187
+ Returns
188
+ -------
189
+ x_normalized : numpy array
190
+ Normalized signal
191
+
192
+ """
115
193
116
194
mid = ub - (ub - lb ) / 2
117
195
min_v = numpy .min (x )
0 commit comments