3
3
4
4
import numpy as np
5
5
from scipy import signal
6
- from sklearn .preprocessing import normalize
7
6
8
- from wfdb .processing .basic import get_filter_gain
7
+ from wfdb .processing .basic import get_filter_gain , normalize
9
8
from wfdb .processing .peaks import find_local_peaks
10
9
from wfdb .io .record import Record
11
10
12
11
13
12
class XQRS (object ):
14
13
"""
15
- The QRS detector class for the XQRS algorithm. The `XQRS.Conf`
16
- class is the configuration class that stores initial parameters
14
+ The QRS detector class for the XQRS algorithm. The `XQRS.Conf`
15
+ class is the configuration class that stores initial parameters
17
16
for the detection. The `XQRS.detect` method runs the detection algorithm.
18
17
19
18
The process works as follows:
@@ -85,7 +84,7 @@ class Conf(object):
85
84
----------
86
85
hr_init : int, float, optional
87
86
Initial heart rate in beats per minute. Used for calculating
88
- recent R-R intervals.
87
+ recent R-R intervals.
89
88
hr_max : int, float, optional
90
89
Hard maximum heart rate between two beats, in beats per
91
90
minute. Used for refractory period.
@@ -104,13 +103,13 @@ class Conf(object):
104
103
ref_period : int, float, optional
105
104
The QRS refractory period.
106
105
t_inspect_period : int, float, optional
107
- The period below which a potential QRS complex is
108
- inspected to see if it is a T-wave.
106
+ The period below which a potential QRS complex is inspected to
107
+ see if it is a T-wave. Leave as 0 for no T-wave inspection .
109
108
110
109
"""
111
110
def __init__ (self , hr_init = 75 , hr_max = 200 , hr_min = 25 , qrs_width = 0.1 ,
112
111
qrs_thr_init = 0.13 , qrs_thr_min = 0 , ref_period = 0.2 ,
113
- t_inspect_period = 0.36 ):
112
+ t_inspect_period = 0 ):
114
113
if hr_min < 0 :
115
114
raise ValueError ("'hr_min' must be >= 0" )
116
115
@@ -134,7 +133,7 @@ def __init__(self, hr_init=75, hr_max=200, hr_min=25, qrs_width=0.1,
134
133
def _set_conf (self ):
135
134
"""
136
135
Set configuration parameters from the Conf object into the detector
137
- object. Time values are converted to samples, and amplitude values
136
+ object. Time values are converted to samples, and amplitude values
138
137
are in mV.
139
138
140
139
Parameters
@@ -288,10 +287,10 @@ def _learn_init_params(self, n_calib_beats=8):
288
287
289
288
# Question: should the signal be squared? Case for inverse QRS
290
289
# complexes
291
- sig_segment = normalize (( self .sig_f [i - self .qrs_radius :
292
- i + self .qrs_radius ]). reshape ( - 1 , 1 ), axis = 0 )
290
+ sig_segment = normalize (self .sig_f [i - self .qrs_radius :
291
+ i + self .qrs_radius ])
293
292
294
- xcorr = np .correlate (sig_segment [:, 0 ] , ricker_wavelet [:,0 ])
293
+ xcorr = np .correlate (sig_segment , ricker_wavelet [:,0 ])
295
294
296
295
# Classify as QRS if xcorr is large enough
297
296
if xcorr > 0.6 and i - last_qrs_ind > self .rr_min :
@@ -470,15 +469,15 @@ def _update_qrs(self, peak_num, backsearch=False):
470
469
The peak number of the MWI signal where the QRS is detected.
471
470
backsearch: bool, optional
472
471
Whether the QRS was found via backsearch.
473
-
472
+
474
473
Returns
475
474
-------
476
475
N/A
477
476
478
477
"""
479
478
i = self .peak_inds_i [peak_num ]
480
479
481
- # Update recent R-R interval if the beat is consecutive (do this
480
+ # Update recent R-R interval if the beat is consecutive (do this
482
481
# before updating self.last_qrs_ind)
483
482
rr_new = i - self .last_qrs_ind
484
483
if rr_new < self .rr_max :
@@ -514,7 +513,7 @@ def _is_twave(self, peak_num):
514
513
----------
515
514
peak_num : int
516
515
The peak number of the MWI signal where the QRS is detected.
517
-
516
+
518
517
Returns
519
518
-------
520
519
bool
@@ -530,8 +529,7 @@ def _is_twave(self, peak_num):
530
529
531
530
# Get half the QRS width of the signal to the left.
532
531
# Should this be squared?
533
- sig_segment = normalize ((self .sig_f [i - self .qrs_radius :i ]
534
- ).reshape (- 1 , 1 ), axis = 0 )
532
+ sig_segment = normalize (self .sig_f [i - self .qrs_radius :i ])
535
533
last_qrs_segment = self .sig_f [self .last_qrs_ind - self .qrs_radius :
536
534
self .last_qrs_ind ]
537
535
@@ -901,7 +899,7 @@ def __init__(self, fs, adc_gain, hr=75,
901
899
class Peak (object ):
902
900
"""
903
901
Holds all of the peak information for the QRS object.
904
-
902
+
905
903
Attributes
906
904
----------
907
905
peak_time : int, float
@@ -923,7 +921,7 @@ def __init__(self, peak_time, peak_amp, peak_type):
923
921
class Annotation (object ):
924
922
"""
925
923
Holds all of the annotation information for the QRS object.
926
-
924
+
927
925
Attributes
928
926
----------
929
927
ann_time : int, float
@@ -1160,8 +1158,8 @@ def qfv_put(self, t, v):
1160
1158
1161
1159
def sm (self , at_t ):
1162
1160
"""
1163
- Implements a trapezoidal low pass (smoothing) filter (with a gain
1164
- of 4*smdt) applied to input signal sig before the QRS matched
1161
+ Implements a trapezoidal low pass (smoothing) filter (with a gain
1162
+ of 4*smdt) applied to input signal sig before the QRS matched
1165
1163
filter qf(). Before attempting to 'rewind' by more than BUFLN-smdt
1166
1164
samples, reset smt and smt0.
1167
1165
@@ -1220,7 +1218,7 @@ def qf(self):
1220
1218
N/A
1221
1219
1222
1220
"""
1223
- # Do this first, to ensure that all of the other smoothed values
1221
+ # Do this first, to ensure that all of the other smoothed values
1224
1222
# needed below are in the buffer
1225
1223
dv2 = self .sm (self .t + self .c .dt4 )
1226
1224
dv2 -= self .smv_at (self .t - self .c .dt4 )
@@ -1302,17 +1300,17 @@ def add_peak(peak_time, peak_amp, peak_type):
1302
1300
1303
1301
def peaktype (p ):
1304
1302
"""
1305
- The neighborhood consists of all other peaks within rrmin.
1306
- Normally, "most prominent" is equivalent to "largest in
1307
- amplitude", but this is not always true. For example, consider
1308
- three consecutive peaks a, b, c such that a and b share a
1309
- neighborhood, b and c share a neighborhood, but a and c do not;
1310
- and suppose that amp(a) > amp(b) > amp(c). In this case, if
1303
+ The neighborhood consists of all other peaks within rrmin.
1304
+ Normally, "most prominent" is equivalent to "largest in
1305
+ amplitude", but this is not always true. For example, consider
1306
+ three consecutive peaks a, b, c such that a and b share a
1307
+ neighborhood, b and c share a neighborhood, but a and c do not;
1308
+ and suppose that amp(a) > amp(b) > amp(c). In this case, if
1311
1309
there are no other peaks, a is the most prominent peak in the (a, b)
1312
- neighborhood. Since b is thus identified as a non-prominent peak,
1313
- c becomes the most prominent peak in the (b, c) neighborhood.
1314
- This is necessary to permit detection of low-amplitude beats that
1315
- closely precede or follow beats with large secondary peaks (as,
1310
+ neighborhood. Since b is thus identified as a non-prominent peak,
1311
+ c becomes the most prominent peak in the (b, c) neighborhood.
1312
+ This is necessary to permit detection of low-amplitude beats that
1313
+ closely precede or follow beats with large secondary peaks (as,
1316
1314
for example, in R-on-T PVCs).
1317
1315
1318
1316
Parameters
@@ -1323,7 +1321,7 @@ def peaktype(p):
1323
1321
Returns
1324
1322
-------
1325
1323
int
1326
- Whether the input peak is the most prominent peak in its
1324
+ Whether the input peak is the most prominent peak in its
1327
1325
neighborhood (1) or not (2).
1328
1326
1329
1327
"""
@@ -1534,8 +1532,8 @@ def gqrs_detect(sig=None, fs=None, d_sig=None, adc_gain=None, adc_zero=None,
1534
1532
"""
1535
1533
Detect QRS locations in a single channel ecg. Functionally, a direct port
1536
1534
of the GQRS algorithm from the original WFDB package. Accepts either a
1537
- physical signal, or a digital signal with known adc_gain and adc_zero. See
1538
- the notes below for a summary of the program. This algorithm is not being
1535
+ physical signal, or a digital signal with known adc_gain and adc_zero. See
1536
+ the notes below for a summary of the program. This algorithm is not being
1539
1537
developed/supported.
1540
1538
1541
1539
Parameters
0 commit comments