Source code for vital_sqi.sqi.dtw_sqi

import numpy as np
from dtw import dtw
from vital_sqi.common.generate_template import (
        ppg_absolute_dual_skewness_template,
        ppg_dual_double_frequency_template,
        ppg_nonlinear_dynamic_system_template,
        ecg_dynamic_template
    )
from vital_sqi.common.utils import check_valid_signal


[docs]def dtw_sqi(x, template_type=0): """ Using DTW to get the mapping point distance between a signal and its template. The DTW SQI is the ratio of the distance sum to the trace of cost matrix. The closer to 1 the better SQI. Parameters ---------- x : array_like, signal containing int or float values. template_type : int, 0: ppg_absolute_dual_skewness_template, 1: ppg_dual_double_frequency_template, 2: ppg_nonlinear_dynamic_system_template, 3: ecg_dynamic_template default = 0 Returns ------- type float, the matching score with the chosen template """ check_valid_signal(x) if template_type > 3 or type(template_type) != int: raise ValueError("Invalid template type") if template_type == 0: reference = ppg_nonlinear_dynamic_system_template(len(x)).reshape(-1) elif template_type == 1: reference = ppg_dual_double_frequency_template(len(x)) if template_type == 2: reference = ppg_absolute_dual_skewness_template(len(x)) if template_type == 3: reference = ecg_dynamic_template(len(x)) alignmentOBE = dtw(x, reference, keep_internals=True, step_pattern='asymmetric', open_end=True, open_begin=True) match_distance = [] for i in range(len(alignmentOBE.index2)): match_distance.append( alignmentOBE.costMatrix[i][alignmentOBE.index2[i]] ) trace = alignmentOBE.costMatrix.trace() if trace == 0: ratio = float(1) else: ratio = float(np.sum(match_distance)/trace) return ratio