Note
Click here to download the full example code
Detects j-point in a ECG signal. J-point is defined as 45 Degree at 25mm/s and 10mm/mV.
import numpy as np import matplotlib.pyplot as plt from scipy.signal import find_peaks import lmlib as lm from lmlib.utils.beta import find_max_mask from lmlib.utils.beta import load_source_csv # --- LOAD ECG TEST SIGNAL --- y = load_source_csv('./csv-data/cerebral-vasoreg-diabetes-heaad-up-tilt_day1-s0030DA-noheader.csv', time_format = "H:M:S", K=2100, k=2200, ch_select=2) # for script start K = y.shape[0] # number of loaded samples # --- CONFIG: SLOPE of J-POINT --- FS = 500 # sampling frequency SEC_PER_MM = 25e-3 # x-axis: seconds per mm MV_PER_MM = 0.1 # y-axis: mV per mm SLOPE_MV_SEC = ( MV_PER_MM / SEC_PER_MM ) # slope of j-point [mV per s] SLOPE_MV_SAMP = SLOPE_MV_SEC * 1 / FS # [mV per Sample] # -- APPLY ALSSM Model --- # Generate ALSSM Model for a line (offset+slope) alssm = lm.AlssmPoly(poly_degree=1) segment = lm.Segment(a=-10, b=10, direction=lm.FORWARD, g=1000) cost = lm.CostSegment(alssm, segment) # Apply ALSSM Filter/approximation separam = lm.SEParam(cost) separam.filter(y) x_hat = separam.minimize_x() slope = x_hat[:,1] # Extract slope from estimated line y_hat = cost.eval_alssm(x_hat) # Get peak estimate (on the slope line) # Find QRS locations using simple peak detection (peaks_ecg_ind, _) = find_peaks(y, distance=FS*0.6, height=1.0) # find positions of slope=SLOPE_MV_SAMP (45 Degree) peaks_ecg_slope_ind = find_max_mask(-np.abs(slope-SLOPE_MV_SAMP), () , locs=peaks_ecg_ind, range_start=+int(FS*0.05), range_end=+int(FS*0.15)) # Get trajectories & windows (to be displayed in the plots) trajs_edge = lm.map_trajectories(cost.trajectories(x_hat[peaks_ecg_slope_ind]), peaks_ecg_slope_ind, K, merge_ks=True) wins = lm.map_window(cost.window(), peaks_ecg_slope_ind, K, merge_ks=True) # ---------- PLOTTING -------------- k = range(K) _, axs = plt.subplots(2, 1, sharex='all', figsize=(8, 4)) axs[0].plot(k, y, lw=0.5, c='k', label='') axs[0].plot(k, trajs_edge[:, 0], lw=1, c='r', label='') axs[0].scatter(peaks_ecg_ind, y[peaks_ecg_ind], s=30, marker='+', c='k', label='QRS peak', zorder=20) axs[0].scatter(peaks_ecg_slope_ind, y_hat[peaks_ecg_slope_ind], s=30, marker=7, c='k', label='J point', zorder=20) # axs[0].scatter(peaks_abp_slope_ind, offset[peaks_abp_slope_ind], lw='2', marker='+', s=120, c='r', facecolors='none', label='$x_1=0$', zorder=20) for xc in peaks_ecg_ind: axs[0].axvline(x=xc, c='k', ls='--') axs[0].set_xlim((200,1100)) axs[0].set_ylim((-.5,1.5)) axs[0].set(xlabel='k', ylabel=r'$y_k$ [mV]') axs[0].set_title('Electrocardiogram (ECG) - J-Point Detection') axs[0].legend(loc=4) axs[1].plot(k, slope, c='tab:red', label='$a_1$ (Slope)') for xc in peaks_ecg_ind: axs[1].axvline(x=xc, c='tab:gray', ls='--') axs[1].axhline(y=SLOPE_MV_SAMP, c='k', ls='--', label='45 Degree') axs[1].scatter(peaks_ecg_slope_ind, slope[peaks_ecg_slope_ind], s=30, marker=7, c='k', label='J point', zorder=20) axs[1].set_ylim((-SLOPE_MV_SAMP*10,SLOPE_MV_SAMP*10)) axs[1].set(xlabel='k', ylabel=r'slope [mV/Sample]') axs[1].legend(loc=4) axs[1].grid(True) plt.show()
Total running time of the script: ( 0 minutes 0.486 seconds)
Gallery generated by Sphinx-Gallery