-
Notifications
You must be signed in to change notification settings - Fork 14
/
utils_sig.py
56 lines (44 loc) · 1.4 KB
/
utils_sig.py
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
import numpy as np
from scipy.fft import fft
from scipy import signal
from scipy.signal import butter, filtfilt
def butter_bandpass(sig, lowcut, highcut, fs, order=2):
# butterworth bandpass filter
sig = np.reshape(sig, -1)
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band')
y = filtfilt(b, a, sig)
return y
def hr_fft(sig, fs, harmonics_removal=True):
# get heart rate by FFT
# return both heart rate and PSD
sig = sig.reshape(-1)
sig = sig * signal.windows.hann(sig.shape[0])
sig_f = np.abs(fft(sig))
low_idx = np.round(0.6 / fs * sig.shape[0]).astype('int')
high_idx = np.round(4 / fs * sig.shape[0]).astype('int')
sig_f_original = sig_f.copy()
sig_f[:low_idx] = 0
sig_f[high_idx:] = 0
peak_idx, _ = signal.find_peaks(sig_f)
sort_idx = np.argsort(sig_f[peak_idx])
sort_idx = sort_idx[::-1]
peak_idx1 = peak_idx[sort_idx[0]]
peak_idx2 = peak_idx[sort_idx[1]]
f_hr1 = peak_idx1 / sig_f.shape[0] * fs
hr1 = f_hr1 * 60
f_hr2 = peak_idx2 / sig_f.shape[0] * fs
hr2 = f_hr2 * 60
if harmonics_removal:
if np.abs(hr1-2*hr2)<10:
hr = hr2
else:
hr = hr1
else:
hr = hr1
x_hr = np.arange(len(sig_f))/len(sig_f)*fs*60
return hr, sig_f_original, x_hr
def normalize(x):
return (x-x.mean())/x.std()