1
1
import numpy as np
2
2
import scipy .signal as scisig
3
-
3
+ import pdb
4
+ import matplotlib .pyplot as plt
4
5
5
6
class PanTompkins (object ):
6
7
"""
@@ -14,7 +15,7 @@ def __init__(self, sig=None, fs=None, streamsig=None):
14
15
self .sig = sig
15
16
self .fs = fs
16
17
17
- self .livesig = livesig
18
+ self .streamsig = streamsig
18
19
19
20
if sig is not None :
20
21
self .siglen = len (sig )
@@ -32,18 +33,57 @@ def detect_qrs_static(self):
32
33
"""
33
34
34
35
# Resample the signal to 200Hz if necessary
35
- self .resample ()
36
+ self .resample ()
36
37
37
38
# Bandpass filter the signal
38
- self .sig_F = self . bandpass ()
39
+ self .bandpass (plotsteps = False )
39
40
40
41
# Calculate the moving wave integration signal
41
- self .sig_I = self . mwi ()
42
+ self .mwi (plotsteps = False )
42
43
43
44
# Align the filtered and integrated signal with the original
44
45
self .alignsignals ()
45
-
46
46
47
+
48
+
49
+ # Let's do some investigating!
50
+ # Compare sig, sig_F, and sig_I
51
+
52
+ # 1. Compare sig_F and sig_I peaks
53
+
54
+ fpeaks = findpeaks_radius (self .sig_F , 20 )
55
+
56
+ ipeaks = findpeaks_radius (self .sig_I , 20 )
57
+
58
+ fpeaks = fpeaks [np .where (self .sig_F [fpeaks ]> 4 )[0 ]]
59
+ ipeaks = ipeaks [np .where (self .sig_I [ipeaks ]> 4 )[0 ]]
60
+
61
+
62
+
63
+ #allpeaks = np.union1d(fpeaks, ipeaks)
64
+
65
+
66
+ print ('fpeaks:' , fpeaks )
67
+ print ('ipeaks:' , ipeaks )
68
+
69
+ plt .figure (1 )
70
+ plt .plot (self .sig_F , 'b' )
71
+ plt .plot (fpeaks , self .sig_F [fpeaks ], 'b*' )
72
+
73
+ plt .plot (self .sig_I ,'r' )
74
+ plt .plot (ipeaks , self .sig_I [ipeaks ], 'r*' )
75
+
76
+ #plt.plot(allpeaks, self.sig_F[allpeaks], 'g*')
77
+
78
+
79
+
80
+ plt .show ()
81
+
82
+
83
+
84
+
85
+
86
+
47
87
# Initialize learning parameters via the two learning phases
48
88
self .learnparams ()
49
89
@@ -133,16 +173,14 @@ def detect_qrs_static(self):
133
173
134
174
135
175
# Convert the peak indices back to the original fs if necessary
136
- self .returnresample ()
176
+ self .reverseresampleqrs ()
137
177
138
178
return
139
179
140
180
141
-
142
-
143
181
def resample (self ):
144
182
if self .fs != 200 :
145
- self .sig = scisig .resample (self .sig , int (self .siglen * 200 / fs ))
183
+ self .sig = scisig .resample (self .sig , int (self .siglen * 200 / self . fs ))
146
184
return
147
185
148
186
# Bandpass filter the signal from 5-15Hz
@@ -162,10 +200,10 @@ def bandpass(self, plotsteps):
162
200
plt .plot (self .sig_F )
163
201
plt .legend (['After LP' , 'After LP+HP' ])
164
202
plt .show ()
165
- return
203
+ return
166
204
167
205
# Compute the moving wave integration waveform from the filtered signal
168
- def mwi (sig , plotsteps ):
206
+ def mwi (self , plotsteps ):
169
207
# Compute 5 point derivative
170
208
a_deriv = [1 ]
171
209
b_deriv = [1 / 4 , 1 / 8 , 0 , - 1 / 8 , - 1 / 4 ]
@@ -245,8 +283,8 @@ def learnparams(self):
245
283
while (windownum + 1 )* learntime * 200 < self .siglen :
246
284
wavelearn_F = self .sig_F [windownum * learntime * 200 :(windownum + 1 )* learntime * 200 ]
247
285
wavelearn_I = self .sig_I [windownum * learntime * 200 :(windownum + 1 )* learntime * 200 ]
248
-
249
- # Find peaks in the signals
286
+
287
+ # Find peaks in the signal sections
250
288
peakinds_F = findpeaks_radius (wavelearn_F , radius )
251
289
peakinds_I = findpeaks_radius (wavelearn_I , radius )
252
290
peaks_F = wavelearn_F [peakinds_F ]
@@ -258,22 +296,24 @@ def learnparams(self):
258
296
# Align peaks to minimum value and set to unit variance
259
297
peaks_F = (peaks_F - min (peaks_F )) / np .std (peaks_F )
260
298
peaks_I = (peaks_I - min (peaks_I )) / np .std (peaks_I )
261
- sigpeakinds_F = np .where (peaks_F ) >= 1.4
262
- sigpeakinds_I = np .where (peaks_I ) >= 1.4
299
+ sigpeakinds_F = np .where (peaks_F >= 1.4 )
300
+ sigpeakinds_I = np .where (peaks_I >= 1.4 )
263
301
264
302
# Final signal peak when both signals agree
265
- sigpeakinds = np .intersect1d (sigpeaks_F , sigpeaks_I )
303
+ sigpeakinds = np .intersect1d (sigpeakinds_F , sigpeakinds_I )
266
304
# Noise peaks are the remainders
267
305
noisepeakinds_F = np .setdiff1d (peakinds_F , sigpeakinds )
268
306
noisepeakinds_I = np .setdiff1d (peakinds_I , sigpeakinds )
269
307
270
308
# Found at least 2 peaks. Also peak 1 and 2 must be >200ms apart
271
309
if len (sigpeakinds )> 1 and sigpeakinds [1 ]- sigpeakinds [0 ]> 40 :
310
+ print ('should be out' )
272
311
break
273
312
274
313
# Didn't find 2 satisfactory peaks. Check the next window.
275
314
windownum = windownum + 1
276
-
315
+
316
+
277
317
# Found at least 2 satisfactory peaks. Use them to set parameters.
278
318
279
319
# Set running peak estimates to first values
@@ -428,14 +468,14 @@ def istwave(self, i):
428
468
else :
429
469
return False
430
470
431
- def returnresample (self ):
471
+ def reverseresampleqrs (self ):
432
472
# Refactor the qrs indices to match the fs of the original signal
433
473
434
474
self .qrs_inds = np .array (self .qrs_inds )
435
475
436
476
if self .fs != 200 :
437
477
self .qrs_inds = self .qrs_inds * fs / 200
438
-
478
+
439
479
self .qrs_inds = self .qrs_inds .astype ('int64' )
440
480
441
481
@@ -447,7 +487,7 @@ def pantompkins(sig, fs):
447
487
448
488
detector = PanTompkins (sig = sig , fs = fs )
449
489
450
- detect_qrs_static ()
490
+ detector . detect_qrs_static ()
451
491
452
492
return detector .qrs_inds
453
493
@@ -470,7 +510,7 @@ def findpeaks_radius(sig, radius):
470
510
peaklocs = []
471
511
472
512
# Pad samples at start and end
473
- sig = np .concatenate ((np .ones (radius )* sig [0 ],sig , np .ones (radius )* sig [- 1 ]))
513
+ sig = np .concatenate ((np .ones (radius )* sig [0 ], sig , np .ones (radius )* sig [- 1 ]))
474
514
475
515
i = radius
476
516
while i < siglen + radius :
0 commit comments