# gaitsetpy.features.utils

View Source

      1import numpy as np
      2from scipy.stats import skew, kurtosis, entropy
      3from scipy.signal import welch, find_peaks
      4from scipy.fft import fft
      5from statsmodels.tsa.ar_model import AutoReg
      6
      7
      8def calculate_stride_times(signal, fs):
      9    """
     10    Calculate stride times from a signal using peak detection.
     11    Args:
     12        signal (np.array): Input signal.
     13        fs (int): Sampling frequency.
     14    Returns:
     15        avg_stride_time (float): Average stride time.
     16    """
     17    peaks, _ = find_peaks(signal)
     18    stride_times = np.diff(peaks) / fs
     19    avg_stride_time = np.mean(stride_times) if len(stride_times) > 0 else 0
     20    return avg_stride_time
     21
     22def calculate_zero_crossing_rate(signal):
     23    """
     24    Calculate the zero-crossing rate of a signal.
     25    Args:
     26        signal (np.array): Input signal.
     27    Returns:
     28        zcr (float): Zero-crossing rate.
     29    """
     30    n = len(signal)
     31    zcr = 1 / (n - 1) * sum(0.5 * abs(np.sign(signal[i + 1]) - np.sign(signal[i])) for i in range(n - 1))
     32    return zcr
     33
     34def calculate_power(signal, fs, band):
     35    """
     36    Calculate the power of a signal in a specific frequency band.
     37    Args:
     38        signal (np.array): Input signal.
     39        fs (int): Sampling frequency.
     40        band (tuple): Frequency band (low, high).
     41    Returns:
     42        band_power (float): Power in the specified frequency band.
     43    """
     44    # f, Pxx = welch(signal, fs=fs, nperseg=min(len(signal), 1024))
     45    f, Pxx = welch(signal, fs=fs, nperseg = min(len(signal), 192))  # Ensure nperseg ≤ length)
     46    band_power = np.trapz(Pxx[(f >= band[0]) & (f <= band[1])], f[(f >= band[0]) & (f <= band[1])])
     47    return band_power
     48
     49def calculate_freezing_index(signal, fs):
     50    """
     51    Calculate the freezing index of a signal.
     52    Args:
     53        signal (np.array): Input signal.
     54        fs (int): Sampling frequency.
     55    Returns:
     56        freezing_index (float): Freezing index.
     57    """
     58    power_3_8 = calculate_power(signal, fs, (3, 8))
     59    power_0_5_3 = calculate_power(signal, fs, (0.5, 3))
     60    freezing_index = power_3_8 / power_0_5_3 if power_0_5_3 != 0 else 0
     61    return freezing_index
     62
     63def calculate_standard_deviation(signal):
     64    """
     65    Calculate the standard deviation of a signal.
     66    Args:
     67        signal (np.array): Input signal.
     68    Returns:
     69        std_dev (float): Standard deviation.
     70    """
     71    return np.std(signal)
     72
     73def calculate_entropy(signal):
     74    """
     75    Calculate the entropy of a signal.
     76    Args:
     77        signal (np.array): Input signal.
     78    Returns:
     79        entropy_value (float): Entropy.
     80    """
     81    value, counts = np.unique(signal, return_counts=True)
     82    probabilities = counts / len(signal)
     83    return entropy(probabilities, base=2)
     84
     85def calculate_energy(signal):
     86    """
     87    Calculate the energy of a signal.
     88    Args:
     89        signal (np.array): Input signal.
     90    Returns:
     91        energy (float): Energy.
     92    """
     93    return np.sum(signal ** 2)
     94
     95def calculate_variance(signal):
     96    """
     97    Calculate the variance of a signal.
     98    Args:
     99        signal (np.array): Input signal.
    100    Returns:
    101        variance (float): Variance.
    102    """
    103    return np.var(signal)
    104
    105def calculate_kurtosis(signal):
    106    """
    107    Calculate the kurtosis of a signal.
    108    Args:
    109        signal (np.array): Input signal.
    110    Returns:
    111        kurtosis_value (float): Kurtosis.
    112    """
    113    try:
    114        return kurtosis(signal, fisher=False)
    115    except Exception as e:
    116        print(f"An error occurred in feature 'kurtosis': {e}")
    117        return 0
    118
    119def calculate_step_time(signal, fs):
    120    """
    121    Calculate step times from a signal using peak detection.
    122    Args:
    123        signal (np.array): Input signal.
    124        fs (int): Sampling frequency.
    125    Returns:
    126        step_times (np.array): Array of step times.
    127    """
    128    peaks, _ = find_peaks(signal)
    129    step_times = np.diff(peaks) / fs
    130    return step_times
    131
    132def calculate_mean(signal):
    133    """Calculate the mean of the signal."""
    134    return np.mean(signal)
    135
    136def calculate_max(signal):
    137    """Calculate the maximum value of the signal."""
    138    return np.max(signal)
    139
    140def calculate_min(signal):
    141    """Calculate the minimum value of the signal."""
    142    return np.min(signal)
    143
    144def calculate_median(signal):
    145    """Calculate the median of the signal."""
    146    return np.median(signal)
    147
    148def calculate_skewness(signal):
    149    """Calculate the skewness of the signal."""
    150    try:
    151        return skew(signal)
    152    except Exception as e:
    153        print(f"An error occurred in skewness: {e}")
    154        return 0
    155
    156def calculate_root_mean_square(signal):
    157    """Calculate the root mean square of the signal."""
    158    return np.sqrt(np.mean(np.square(signal)))
    159
    160def calculate_range(signal):
    161    """Calculate the range of the signal."""
    162    return np.max(signal) - np.min(signal)
    163
    164def calculate_correlation(signal1, signal2):
    165    """Calculate the correlation between two signals."""
    166    return np.corrcoef(signal1, signal2)[0, 1]
    167
    168def calculate_dominant_frequency(signal, fs):
    169    """Calculate the dominant frequency of the signal."""
    170    try:
    171        fft_values = np.abs(fft(signal))
    172        freqs = np.fft.fftfreq(len(signal), 1 / fs)
    173        dominant_freq = freqs[np.argmax(fft_values)]
    174        return dominant_freq
    175    except Exception as e:
    176        print(f"An error occurred: {e}")
    177        return 0
    178
    179def calculate_peak_height(signal):
    180    """Calculate the peak height of the signal."""
    181    peaks, _ = find_peaks(signal)
    182    return np.max(signal[peaks]) if len(peaks) > 0 else 0
    183
    184def calculate_interquartile_range(signal):
    185    """Calculate the interquartile range of the signal."""
    186    try:
    187        q75, q25 = np.percentile(signal, [75, 25])
    188        return q75 - q25
    189    except Exception as e:
    190        print(f"An error occurred in feature 'interquartile_range': {e}")
    191        return 0
    192
    193def calculate_mode(signal):
    194    """Calculate the mode of the signal."""
    195    values, counts = np.unique(signal, return_counts=True)
    196    return values[np.argmax(counts)]
    197
    198def calculate_cadence(signal, fs):
    199    """Calculate the cadence (steps per minute) of the signal."""
    200    peaks, _ = find_peaks(signal)
    201    step_count = len(peaks)
    202    duration = len(signal) / fs
    203    return (step_count / duration) * 60
    204
    205def calculate_mean_absolute_value(signal):
    206    """Calculate the mean absolute value of the signal."""
    207    return np.mean(np.abs(signal))
    208
    209def calculate_median_absolute_deviation(signal):
    210    """Calculate the median absolute deviation of the signal."""
    211    return np.median(np.abs(signal - np.median(signal)))
    212
    213def calculate_peak_frequency(signal, fs):
    214    """Calculate the peak frequency of the signal."""
    215    try:
    216        f, Pxx = welch(signal, fs=fs, nperseg=min(len(signal), 192))  # Ensure nperseg ≤ length
    217        return f[np.argmax(Pxx)]
    218    except Exception as e:
    219        print(f"An error occurred in feature 'peak_frequency': {e}")
    220        return 0
    221
    222def calculate_peak_width(signal, fs):
    223    """Calculate the peak width of the signal."""
    224    peaks, _ = find_peaks(signal)
    225    if len(peaks) == 0:
    226        return 0
    227    peak_heights = signal[peaks]
    228    half_max = np.max(peak_heights) / 2
    229    widths = np.diff(np.where(signal > half_max)[0])
    230    return np.mean(widths) / fs if len(widths) > 0 else 0
    231
    232def calculate_power_spectral_entropy(signal, fs):
    233    """Calculate the power spectral entropy of the signal."""
    234    try:
    235        f, Pxx = welch(signal, fs=fs, nperseg=min(len(signal), 192))  # Ensure nperseg ≤ length
    236        Pxx_norm = Pxx / np.sum(Pxx)
    237        return -np.sum(Pxx_norm * np.log2(Pxx_norm + np.finfo(float).eps))
    238    except Exception as e:
    239        print(f"An error occurred in feature 'power spectral entropy': {e}")
    240        return 0
    241
    242def calculate_principal_harmonic_frequency(signal, fs):
    243    """Calculate the principal harmonic frequency of the signal."""
    244    try:
    245        fft_values = np.abs(fft(signal))
    246        freqs = np.fft.fftfreq(len(signal), 1 / fs)
    247        return freqs[np.argmax(fft_values)]
    248    except Exception as e:
    249        print(f"An error occurred in feature 'principal_harmonic_frequency': {e}")
    250        return 0
    251
    252def calculate_auto_regression_coefficients(signal, order=3):
    253    """Calculate the auto-regression coefficients of the signal."""
    254    try:
    255        model = AutoReg(signal, lags=order)
    256        results = model.fit()
    257        return results.params
    258    except Exception as e:
    259        print(f"An error occurred in feature 'auto_regression_coefficients': {e}")
    260        return 0

def calculate_stride_times(signal, fs): View Source

     9def calculate_stride_times(signal, fs):
    10    """
    11    Calculate stride times from a signal using peak detection.
    12    Args:
    13        signal (np.array): Input signal.
    14        fs (int): Sampling frequency.
    15    Returns:
    16        avg_stride_time (float): Average stride time.
    17    """
    18    peaks, _ = find_peaks(signal)
    19    stride_times = np.diff(peaks) / fs
    20    avg_stride_time = np.mean(stride_times) if len(stride_times) > 0 else 0
    21    return avg_stride_time

Calculate stride times from a signal using peak detection. Args: signal (np.array): Input signal. fs (int): Sampling frequency. Returns: avg_stride_time (float): Average stride time.

def calculate_zero_crossing_rate(signal): View Source

    23def calculate_zero_crossing_rate(signal):
    24    """
    25    Calculate the zero-crossing rate of a signal.
    26    Args:
    27        signal (np.array): Input signal.
    28    Returns:
    29        zcr (float): Zero-crossing rate.
    30    """
    31    n = len(signal)
    32    zcr = 1 / (n - 1) * sum(0.5 * abs(np.sign(signal[i + 1]) - np.sign(signal[i])) for i in range(n - 1))
    33    return zcr

Calculate the zero-crossing rate of a signal. Args: signal (np.array): Input signal. Returns: zcr (float): Zero-crossing rate.

def calculate_power(signal, fs, band): View Source

    35def calculate_power(signal, fs, band):
    36    """
    37    Calculate the power of a signal in a specific frequency band.
    38    Args:
    39        signal (np.array): Input signal.
    40        fs (int): Sampling frequency.
    41        band (tuple): Frequency band (low, high).
    42    Returns:
    43        band_power (float): Power in the specified frequency band.
    44    """
    45    # f, Pxx = welch(signal, fs=fs, nperseg=min(len(signal), 1024))
    46    f, Pxx = welch(signal, fs=fs, nperseg = min(len(signal), 192))  # Ensure nperseg ≤ length)
    47    band_power = np.trapz(Pxx[(f >= band[0]) & (f <= band[1])], f[(f >= band[0]) & (f <= band[1])])
    48    return band_power

Calculate the power of a signal in a specific frequency band. Args: signal (np.array): Input signal. fs (int): Sampling frequency. band (tuple): Frequency band (low, high). Returns: band_power (float): Power in the specified frequency band.

def calculate_freezing_index(signal, fs): View Source

    50def calculate_freezing_index(signal, fs):
    51    """
    52    Calculate the freezing index of a signal.
    53    Args:
    54        signal (np.array): Input signal.
    55        fs (int): Sampling frequency.
    56    Returns:
    57        freezing_index (float): Freezing index.
    58    """
    59    power_3_8 = calculate_power(signal, fs, (3, 8))
    60    power_0_5_3 = calculate_power(signal, fs, (0.5, 3))
    61    freezing_index = power_3_8 / power_0_5_3 if power_0_5_3 != 0 else 0
    62    return freezing_index

Calculate the freezing index of a signal. Args: signal (np.array): Input signal. fs (int): Sampling frequency. Returns: freezing_index (float): Freezing index.

def calculate_standard_deviation(signal): View Source

    64def calculate_standard_deviation(signal):
    65    """
    66    Calculate the standard deviation of a signal.
    67    Args:
    68        signal (np.array): Input signal.
    69    Returns:
    70        std_dev (float): Standard deviation.
    71    """
    72    return np.std(signal)

Calculate the standard deviation of a signal. Args: signal (np.array): Input signal. Returns: std_dev (float): Standard deviation.

def calculate_entropy(signal): View Source

    74def calculate_entropy(signal):
    75    """
    76    Calculate the entropy of a signal.
    77    Args:
    78        signal (np.array): Input signal.
    79    Returns:
    80        entropy_value (float): Entropy.
    81    """
    82    value, counts = np.unique(signal, return_counts=True)
    83    probabilities = counts / len(signal)
    84    return entropy(probabilities, base=2)

Calculate the entropy of a signal. Args: signal (np.array): Input signal. Returns: entropy_value (float): Entropy.

def calculate_energy(signal): View Source

    86def calculate_energy(signal):
    87    """
    88    Calculate the energy of a signal.
    89    Args:
    90        signal (np.array): Input signal.
    91    Returns:
    92        energy (float): Energy.
    93    """
    94    return np.sum(signal ** 2)

Calculate the energy of a signal. Args: signal (np.array): Input signal. Returns: energy (float): Energy.

def calculate_variance(signal): View Source

     96def calculate_variance(signal):
     97    """
     98    Calculate the variance of a signal.
     99    Args:
    100        signal (np.array): Input signal.
    101    Returns:
    102        variance (float): Variance.
    103    """
    104    return np.var(signal)

Calculate the variance of a signal. Args: signal (np.array): Input signal. Returns: variance (float): Variance.

def calculate_kurtosis(signal): View Source

    106def calculate_kurtosis(signal):
    107    """
    108    Calculate the kurtosis of a signal.
    109    Args:
    110        signal (np.array): Input signal.
    111    Returns:
    112        kurtosis_value (float): Kurtosis.
    113    """
    114    try:
    115        return kurtosis(signal, fisher=False)
    116    except Exception as e:
    117        print(f"An error occurred in feature 'kurtosis': {e}")
    118        return 0

Calculate the kurtosis of a signal. Args: signal (np.array): Input signal. Returns: kurtosis_value (float): Kurtosis.

def calculate_step_time(signal, fs): View Source

    120def calculate_step_time(signal, fs):
    121    """
    122    Calculate step times from a signal using peak detection.
    123    Args:
    124        signal (np.array): Input signal.
    125        fs (int): Sampling frequency.
    126    Returns:
    127        step_times (np.array): Array of step times.
    128    """
    129    peaks, _ = find_peaks(signal)
    130    step_times = np.diff(peaks) / fs
    131    return step_times

Calculate step times from a signal using peak detection. Args: signal (np.array): Input signal. fs (int): Sampling frequency. Returns: step_times (np.array): Array of step times.

def calculate_mean(signal): View Source

    133def calculate_mean(signal):
    134    """Calculate the mean of the signal."""
    135    return np.mean(signal)

Calculate the mean of the signal.

def calculate_max(signal): View Source

    137def calculate_max(signal):
    138    """Calculate the maximum value of the signal."""
    139    return np.max(signal)

Calculate the maximum value of the signal.

def calculate_min(signal): View Source

    141def calculate_min(signal):
    142    """Calculate the minimum value of the signal."""
    143    return np.min(signal)

Calculate the minimum value of the signal.

def calculate_median(signal): View Source

    145def calculate_median(signal):
    146    """Calculate the median of the signal."""
    147    return np.median(signal)

Calculate the median of the signal.

def calculate_skewness(signal): View Source

    149def calculate_skewness(signal):
    150    """Calculate the skewness of the signal."""
    151    try:
    152        return skew(signal)
    153    except Exception as e:
    154        print(f"An error occurred in skewness: {e}")
    155        return 0

Calculate the skewness of the signal.

def calculate_root_mean_square(signal): View Source

    157def calculate_root_mean_square(signal):
    158    """Calculate the root mean square of the signal."""
    159    return np.sqrt(np.mean(np.square(signal)))

Calculate the root mean square of the signal.

def calculate_range(signal): View Source

    161def calculate_range(signal):
    162    """Calculate the range of the signal."""
    163    return np.max(signal) - np.min(signal)

Calculate the range of the signal.

def calculate_correlation(signal1, signal2): View Source

    165def calculate_correlation(signal1, signal2):
    166    """Calculate the correlation between two signals."""
    167    return np.corrcoef(signal1, signal2)[0, 1]

Calculate the correlation between two signals.

def calculate_dominant_frequency(signal, fs): View Source

    169def calculate_dominant_frequency(signal, fs):
    170    """Calculate the dominant frequency of the signal."""
    171    try:
    172        fft_values = np.abs(fft(signal))
    173        freqs = np.fft.fftfreq(len(signal), 1 / fs)
    174        dominant_freq = freqs[np.argmax(fft_values)]
    175        return dominant_freq
    176    except Exception as e:
    177        print(f"An error occurred: {e}")
    178        return 0

Calculate the dominant frequency of the signal.

def calculate_peak_height(signal): View Source

    180def calculate_peak_height(signal):
    181    """Calculate the peak height of the signal."""
    182    peaks, _ = find_peaks(signal)
    183    return np.max(signal[peaks]) if len(peaks) > 0 else 0

Calculate the peak height of the signal.

def calculate_interquartile_range(signal): View Source

    185def calculate_interquartile_range(signal):
    186    """Calculate the interquartile range of the signal."""
    187    try:
    188        q75, q25 = np.percentile(signal, [75, 25])
    189        return q75 - q25
    190    except Exception as e:
    191        print(f"An error occurred in feature 'interquartile_range': {e}")
    192        return 0

Calculate the interquartile range of the signal.

def calculate_mode(signal): View Source

    194def calculate_mode(signal):
    195    """Calculate the mode of the signal."""
    196    values, counts = np.unique(signal, return_counts=True)
    197    return values[np.argmax(counts)]

Calculate the mode of the signal.

def calculate_cadence(signal, fs): View Source

    199def calculate_cadence(signal, fs):
    200    """Calculate the cadence (steps per minute) of the signal."""
    201    peaks, _ = find_peaks(signal)
    202    step_count = len(peaks)
    203    duration = len(signal) / fs
    204    return (step_count / duration) * 60

Calculate the cadence (steps per minute) of the signal.

def calculate_mean_absolute_value(signal): View Source

    206def calculate_mean_absolute_value(signal):
    207    """Calculate the mean absolute value of the signal."""
    208    return np.mean(np.abs(signal))

Calculate the mean absolute value of the signal.

def calculate_median_absolute_deviation(signal): View Source

    210def calculate_median_absolute_deviation(signal):
    211    """Calculate the median absolute deviation of the signal."""
    212    return np.median(np.abs(signal - np.median(signal)))

Calculate the median absolute deviation of the signal.

def calculate_peak_frequency(signal, fs): View Source

    214def calculate_peak_frequency(signal, fs):
    215    """Calculate the peak frequency of the signal."""
    216    try:
    217        f, Pxx = welch(signal, fs=fs, nperseg=min(len(signal), 192))  # Ensure nperseg ≤ length
    218        return f[np.argmax(Pxx)]
    219    except Exception as e:
    220        print(f"An error occurred in feature 'peak_frequency': {e}")
    221        return 0

Calculate the peak frequency of the signal.

def calculate_peak_width(signal, fs): View Source

    223def calculate_peak_width(signal, fs):
    224    """Calculate the peak width of the signal."""
    225    peaks, _ = find_peaks(signal)
    226    if len(peaks) == 0:
    227        return 0
    228    peak_heights = signal[peaks]
    229    half_max = np.max(peak_heights) / 2
    230    widths = np.diff(np.where(signal > half_max)[0])
    231    return np.mean(widths) / fs if len(widths) > 0 else 0

Calculate the peak width of the signal.

def calculate_power_spectral_entropy(signal, fs): View Source

    233def calculate_power_spectral_entropy(signal, fs):
    234    """Calculate the power spectral entropy of the signal."""
    235    try:
    236        f, Pxx = welch(signal, fs=fs, nperseg=min(len(signal), 192))  # Ensure nperseg ≤ length
    237        Pxx_norm = Pxx / np.sum(Pxx)
    238        return -np.sum(Pxx_norm * np.log2(Pxx_norm + np.finfo(float).eps))
    239    except Exception as e:
    240        print(f"An error occurred in feature 'power spectral entropy': {e}")
    241        return 0

Calculate the power spectral entropy of the signal.

def calculate_principal_harmonic_frequency(signal, fs): View Source

    243def calculate_principal_harmonic_frequency(signal, fs):
    244    """Calculate the principal harmonic frequency of the signal."""
    245    try:
    246        fft_values = np.abs(fft(signal))
    247        freqs = np.fft.fftfreq(len(signal), 1 / fs)
    248        return freqs[np.argmax(fft_values)]
    249    except Exception as e:
    250        print(f"An error occurred in feature 'principal_harmonic_frequency': {e}")
    251        return 0

Calculate the principal harmonic frequency of the signal.

def calculate_auto_regression_coefficients(signal, order=3): View Source

    253def calculate_auto_regression_coefficients(signal, order=3):
    254    """Calculate the auto-regression coefficients of the signal."""
    255    try:
    256        model = AutoReg(signal, lags=order)
    257        results = model.fit()
    258        return results.params
    259    except Exception as e:
    260        print(f"An error occurred in feature 'auto_regression_coefficients': {e}")
    261        return 0

Calculate the auto-regression coefficients of the signal.