def f_widths(self, beats, beat_det_names, **kwargs): widths_at = kwargs["widths_at"] interp_dim = kwargs["interp_dim"] feature_names = ["meta_counter"] widths_at = list(map(int, widths_at)) feature_names.extend(["w@%d" % x for x in widths_at]) features = [] for beat_det_name in beat_det_names: for beat_counter in beats[beat_det_name].keys(): this_b_features = [beat_counter] signal = np.array(beats[beat_det_name][beat_counter]) signal -= signal.min() signal /= signal.max() x, y = interpolate_beat(signal, interp_dim) for x in widths_at: index_x = np.argwhere(y >= float(x) / 100.0).flatten() this_b_features.append(np.abs(index_x[0] - index_x[-1])) features.append(this_b_features) features = np.array(features) if features.shape[0] == 0: features = np.empty((0, len(feature_names))) assert features.shape[1] == len( feature_names), "%d, %d" % (features.shape[1], len(feature_names)) return features, feature_names
def f_fft(self, beats, beat_det_names, **kwargs): interp_dim = kwargs["interp_dim"] feature_names = ["meta_counter"] feature_names.extend(["bin_%d" % i for i in range(interp_dim)]) features = [] for beat_det_name in beat_det_names: for beat_counter in beats[beat_det_name].keys(): this_b_features = [beat_counter] signal = np.array(beats[beat_det_name][beat_counter]) signal -= signal.min() signal /= signal.max() x, y = interpolate_beat(signal, interp_dim) sp = np.fft.fft(y) fft_magnitudes = np.abs(sp) this_b_features.extend(fft_magnitudes) features.append(this_b_features) features = np.array(features) if features.shape[0] == 0: features = np.empty((0, len(feature_names))) assert features.shape[1] == len( feature_names), "%d, %d" % (features.shape[1], len(feature_names)) return features, feature_names
def dwt_filter_with_reference(self, beats_dict, ref, threshold, interp_dim): good_beats = [] mask = {} dwt_dist = {} keys = list(sorted(beats_dict.keys())) for k in keys: b = beats_dict[k] _b = np.array(b) _b = _b - _b.min() _b = _b / _b.max() x, _b = interpolate_beat(_b, interp_dim) dist = dtw(_b, ref) dwt_dist[k] = "%.2f" % dist if dist < threshold: good_beats.append(b) mask[k] = True else: mask[k] = False return good_beats, mask, dwt_dist
def plot_things(beats_original, beats_ftaed, reference, headers, distances, masks, filename): x_counter = 0 plt.figure(figsize=(30, 5)) _, i_ref = interpolate_beat(reference, 30) text_gap = 0.05 for i, h in enumerate(headers): plt.text(-200 - len(i_ref), -(i + 1) * text_gap, h) keys_org = list(sorted(map(int, beats_original.keys()))) keys_fta = list(sorted(map(int, beats_ftaed.keys()))) for i, key in enumerate(keys_org): b = beats_original[str(key)] b = np.array(b) b = b - b.min() b = b / b.max() color = "b" if np.all(masks[i, :]) else "r" plt.plot(np.arange(x_counter, x_counter + len(b)), b, c=color) for j in range(masks.shape[1]): plt.text(x_counter, -(j + 1) * text_gap, distances[i][j], c="black" if masks[i, j] else "red") x_counter += len(b) plt.ylim(-.3, 1.05) plt.savefig(filename, bbox_inches="tight") plt.close()
def spread(self, beats, beat_det_names, interp_dim): beat_set = [] for beat_det_name in beat_det_names: for beat_counter in beats[beat_det_name].keys(): signal = np.array(beats[beat_det_name][beat_counter]) # s_min = signal.min() signal -= signal.min() signal /= signal.max() x, y = interpolate_beat(signal, interp_dim) beat_set.append(list(y)) return beat_set
def f_fiducial_points(self, beats, beat_det_names, **kwargs): interp_dim = kwargs["interp_dim"] fiducial_points = kwargs["fiducial_points"] feature_names = [ "meta_counter", "peak_to_peak_t", # From [1] as delta T "systolic_peak_index", # From [1], as y "dychrotic_notch_index", # From [1] as t1, time to first peak "diastolic_peak_index", # From [1] as t3, diastolic peak index "A2_area", # From [1], but instead of notch we do to diastolic peak "A1_area", # From [1], but we do from diastolic peak down as opposed to notch down "A2_A1_ratio", "a1", # Maximum of first derivative "b1", # Minimum of first derivative "ta1", # Index of a1 "tb1", # index of b1 "a2", # Maximum value of second derivative "b2", # Minimum value of second derivative "ta2", # Index of a2 "tb2", # Index of b2 "b2_a2", # b2 / a2 "systolic_peak_c", "dychrotic_notch_c", "diastolic_peak_c" ] features = [] for beat_det_name in beat_det_names: for beat_counter in beats[beat_det_name].keys(): this_b_features = [beat_counter] signal = np.array(beats[beat_det_name][beat_counter]) signal -= signal.min() signal /= signal.max() x, y = interpolate_beat(signal, interp_dim) scale_factor = interp_dim / signal.shape[0] systolic_peak_index = int( fiducial_points[beat_counter]["systolic_peak_i"] * scale_factor) systolic_peak_conf = fiducial_points[beat_counter][ "systolic_peak_c"] systolic_peak_value = y[systolic_peak_index] dychrotic_notch_index = int( fiducial_points[beat_counter]["dychrotic_notch_i"] * scale_factor) dychrotic_notch_conf = fiducial_points[beat_counter][ "dychrotic_notch_c"] dychrotic_notch_value = y[dychrotic_notch_index] diastolic_peak_index = int( fiducial_points[beat_counter]["diastolic_peak_i"] * scale_factor) diastolic_peak_conf = fiducial_points[beat_counter][ "diastolic_peak_c"] diastolic_peak_value = y[diastolic_peak_index] peak_to_peak = np.abs(diastolic_peak_index - systolic_peak_index) a1_area = np.trapz(y[:dychrotic_notch_index]) a2_area = np.trapz(y[dychrotic_notch_index:]) area_ratio = a2_area / a1_area first_deriv = self.derivative(y, 1) second_deriv = self.derivative(y, 2) a1 = np.max(first_deriv) b1 = np.min(first_deriv) ta1 = np.argmax(first_deriv) tb1 = np.argmin(first_deriv) a2 = np.max(second_deriv) b2 = np.min(second_deriv) ta2 = np.argmax(second_deriv) tb2 = np.argmin(second_deriv) b2_a2 = b2 / a2 this_b_features.extend([ peak_to_peak, systolic_peak_index, dychrotic_notch_index, diastolic_peak_index, a1_area, a2_area, area_ratio, a1, b1, ta1, tb1, a2, b2, ta2, tb2, b2_a2 ]) this_b_features.extend([ systolic_peak_conf, dychrotic_notch_conf, diastolic_peak_conf ]) features.append(this_b_features) features = np.array(features) if features.shape[0] == 0: features = np.empty((0, len(feature_names))) assert features.shape[1] == len( feature_names), "%d, %d" % (features.shape[1], len(feature_names)) return features, feature_names