Source code for biosppy.features.time

# -*- coding: utf-8 -*-
"""
biosppy.features.time
---------------------

This module provides methods to extract time features.

:copyright: (c) 2015-2023 by Instituto de Telecomunicacoes
:license: BSD 3-clause, see LICENSE for more details.
"""

# Imports
# 3rd party
import numpy as np

# local
from .. import utils
from ..signals import tools as st
from .. import stats


[docs]def time(signal=None, sampling_rate=1000., include_diff=True): """Compute various time metrics describing the signal. Parameters ---------- signal : array Input signal. sampling_rate : int, float, optional Sampling Rate (Hz). include_diff : bool, optional Whether to include the features of the signal's differences (first, second and absolute). Returns ------- feats : ReturnTuple object Time features of the signal. Notes ----- Besides the features directly extracted in this function, it also calls: - biosppy.signals.tools.signal_stats - biosppy.stats.quartiles - biosppy.stats.histogram - biosppy.features.time.hjorth_features """ # check inputs if signal is None: raise TypeError("Please specify an input signal.") # ensure numpy signal = np.array(signal) # initialize output feats = utils.ReturnTuple((), ()) # basic stats signal_feats = st.signal_stats(signal) feats = feats.join(signal_feats) # quartile features quartile_feats = stats.quartiles(signal) feats = feats.join(quartile_feats) # number of maxima nb_maxima = st.find_extrema(signal, mode="max") feats = feats.append(len(nb_maxima['extrema']), 'nb_maxima') # number of minima nb_minima = st.find_extrema(signal, mode="min") feats = feats.append(len(nb_minima['extrema']), 'nb_minima') # autocorrelation sum autocorr_sum = np.sum(np.correlate(signal, signal, 'full')) feats = feats.append(autocorr_sum, 'autocorr_sum') # total energy total_energy = np.sum(np.abs(signal)**2) feats = feats.append(total_energy, 'total_energy') # histogram relative frequency hist_feats = stats.histogram(signal, normalize=True) feats = feats.join(hist_feats) # linear regression t_signal = np.arange(0, len(signal)) / sampling_rate linreg = stats.linear_regression(t_signal, signal, show=False) feats = feats.append(linreg['m'], 'linreg_slope') feats = feats.append(linreg['b'], 'linreg_intercept') # pearson correlation from linear regression linreg_pred = linreg['m'] * t_signal + linreg['b'] pearson_feats = stats.pearson_correlation(signal, linreg_pred) feats = feats.append(pearson_feats['r'], 'pearson_r') # hjorth features hjorth_feats = hjorth_features(signal) feats = feats.join(hjorth_feats) # diff stats if include_diff: diff_feats = stats.diff_stats(signal, stats_only=True) feats = feats.join(diff_feats) return feats
[docs]def hjorth_features(signal=None): """Compute Hjorth mobility, complexity, chaos and hazard. Parameters ---------- signal : array Input signal. Returns ------- hjorth_mobility : float Hjorth mobility. hjorth_complexity : float Hjorth complexity. hjorth_chaos : float Hjorth chaos. hjorth_hazard : float Hjorth hazard. Notes ----- Hjorth activity corresponds to the variance of the signal. """ # helper functions def _hjorth_mobility(s): if np.var(s) == 0: return None return np.sqrt(np.var(np.diff(s)) / np.var(s)) def _hjorth_complexity(s): mobility = _hjorth_mobility(s) if mobility is None or mobility == 0: return None return _hjorth_mobility(np.diff(s)) / mobility def _hjorth_chaos(s): complexity = _hjorth_complexity(s) if complexity is None or complexity == 0: return None return _hjorth_complexity(np.diff(s)) / complexity def _hjorth_hazard(s): chaos = _hjorth_chaos(s) if chaos is None or chaos == 0: return None return _hjorth_chaos(np.diff(s)) / chaos # check inputs if signal is None: raise TypeError("Please specify an input signal.") # ensure numpy signal = np.array(signal) # initialize output feats = utils.ReturnTuple((), ()) # hjorth mobility signal_mobility = _hjorth_mobility(signal) feats = feats.append(signal_mobility, 'hjorth_mobility') if signal_mobility is None: print("Hjorth mobility is undefined. Returning None.") # hjorth complexity signal_complexity = _hjorth_complexity(signal) feats = feats.append(signal_complexity, 'hjorth_complexity') if signal_complexity is None: print("Hjorth complexity is undefined. Returning None.") # hjorth chaos signal_chaos = _hjorth_chaos(signal) feats = feats.append(signal_chaos, 'hjorth_chaos') if signal_chaos is None: print("Hjorth chaos is undefined. Returning None.") # hjorth hazard signal_hazard = _hjorth_hazard(signal) feats = feats.append(signal_hazard, 'hjorth_hazard') if signal_hazard is None: print("Hjorth hazard is undefined. Returning None.") return feats