Skip to content

Commit

Permalink
adding entropy to feats
Browse files Browse the repository at this point in the history
  • Loading branch information
AzulGarza committed Aug 3, 2020
1 parent 97339b8 commit a92479c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 7 deletions.
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
python_requires='>=3.6',
install_requires=[
"arch>=4.11",
"entropy @ https://github.com/raphaelvallat/entropy/tarball/tag/v0.1.1",
"pandas>=1.0.5",
"scikit-learn>=0.23.1",
"statsmodels>=0.11.1",
Expand Down
10 changes: 4 additions & 6 deletions tsfeatures/tsfeatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

from arch import arch_model
from collections import ChainMap
from entropy import spectral_entropy
from functools import partial
from itertools import groupby
from math import log, e
Expand All @@ -29,11 +28,10 @@
from typing import List, Dict, Optional, Callable

from .utils import (
poly, embed, scalets,
terasvirta_test,
hurst_exponent, ur_pp,
lambda_coef_var,
FREQS
embed, FREQS, hurst_exponent,
lambda_coef_var, poly,
scalets, spectral_entropy,
terasvirta_test, ur_pp
)


Expand Down
80 changes: 80 additions & 0 deletions tsfeatures/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import numpy as np
import statsmodels.api as sm

from scipy.signal import periodogram, welch

np.seterr(divide='ignore', invalid='ignore')

################################################################################
Expand Down Expand Up @@ -245,6 +247,84 @@ def lambda_coef_var(lambda_par: float, x: np.array, period: int = 2):

return value

def spectral_entropy(x, sf, method='fft', nperseg=None, normalize=False):
"""Spectral Entropy.
TAKEN FROM https://github.com/raphaelvallat/entropy/blob/master/entropy/entropy.py
DUE TO INSTALATION ISSUES.
Parameters
----------
x : list or np.array
One-dimensional time series of shape (n_times)
sf : float
Sampling frequency, in Hz.
method : str
Spectral estimation method:
* ``'fft'`` : Fourier Transform (:py:func:`scipy.signal.periodogram`)
* ``'welch'`` : Welch periodogram (:py:func:`scipy.signal.welch`)
nperseg : int or None
Length of each FFT segment for Welch method.
If None (default), uses scipy default of 256 samples.
normalize : bool
If True, divide by log2(psd.size) to normalize the spectral entropy
between 0 and 1. Otherwise, return the spectral entropy in bit.
Returns
-------
se : float
Spectral Entropy
Notes
-----
Spectral Entropy is defined to be the Shannon entropy of the power
spectral density (PSD) of the data:
.. math:: H(x, sf) = -\\sum_{f=0}^{f_s/2} P(f) \\log_2[P(f)]
Where :math:`P` is the normalised PSD, and :math:`f_s` is the sampling
frequency.
References
----------
Inouye, T. et al. (1991). Quantification of EEG irregularity by
use of the entropy of the power spectrum. Electroencephalography
and clinical neurophysiology, 79(3), 204-210.
https://en.wikipedia.org/wiki/Spectral_density
https://en.wikipedia.org/wiki/Welch%27s_method
Examples
--------
Spectral entropy of a pure sine using FFT
>>> from entropy import spectral_entropy
>>> import numpy as np
>>> sf, f, dur = 100, 1, 4
>>> N = sf * dur # Total number of discrete samples
>>> t = np.arange(N) / sf # Time vector
>>> x = np.sin(2 * np.pi * f * t)
>>> np.round(spectral_entropy(x, sf, method='fft'), 2)
0.0
Spectral entropy of a random signal using Welch's method
>>> from entropy import spectral_entropy
>>> import numpy as np
>>> np.random.seed(42)
>>> x = np.random.rand(3000)
>>> spectral_entropy(x, sf=100, method='welch')
6.980045662371389
Normalized spectral entropy
>>> spectral_entropy(x, sf=100, method='welch', normalize=True)
0.9955526198316071
"""
x = np.array(x)
# Compute and normalize power spectrum
if method == 'fft':
_, psd = periodogram(x, sf)
elif method == 'welch':
_, psd = welch(x, sf, nperseg=nperseg)
psd_norm = np.divide(psd, psd.sum())
se = -np.multiply(psd_norm, np.log2(psd_norm)).sum()
if normalize:
se /= np.log2(psd_norm.size)
return se


################################################################################
####### TS #####################################################################
################################################################################
Expand Down

0 comments on commit a92479c

Please sign in to comment.