Information Metrics

This notebooks runs information theory metrics on time series signals, including several entropy measures.

This notebook includes:

  • approximate entropy

  • sample entropy

  • permutation entropy

  • spectral entropy

Notes:

  • sample & approximate entroy are pretty similar, maybe don’t need both (?)

  • other metrics we don’t currently consider: multiscale entropy, weighted permutation entropy

  • there are important parameter inputs to these measures, that could be explored

import numpy as np
import matplotlib.pyplot as plt

from neurodsp.sim import sim_powerlaw, sim_synaptic_current, sim_combined
from neurodsp.utils import set_random_seed
# Import custom code
import sys; from pathlib import Path
sys.path.append(str(Path('..').resolve()))

from apm.run import run_sims
from apm.run import run_sims_parallel as run_sims
from apm.methods import sample_entropy, perm_entropy, app_entropy, spectral_entropy
from apm.methods.settings import SA_ENT_PARAMS, PE_ENT_PARAMS, AP_ENT_PARAMS, SP_ENT_PARAMS

from apm.plts import plot_lines
from apm.plts.settings import AP_COL, COMB_COL

from apm.sim.settings import FS, SIM_PARAMS_AP, SIM_PARAMS_COMB, EXPS, FREQS, POWERS, N_SIMS, EXP
from apm.sim.examples import SIG_AP, SIG_KN, SIG_OSC, SIG_COMB

Settings

# Custom settings
N_SIMS = 10
# Check settings for entropy measurs
print('Sample Entropy: \t', SA_ENT_PARAMS)
print('Permutation Entropy:\t', PE_ENT_PARAMS)
print('Approximate Entropy:\t', AP_ENT_PARAMS)
print('Spectral Entropy:\t', SP_ENT_PARAMS)
Sample Entropy: 	 {'order': 2}
Permutation Entropy:	 {'order': 3, 'delay': 1}
Approximate Entropy:	 {'order': 2}
Spectral Entropy:	 {'sf': 1000, 'method': 'fft'}
# Set the random seed
set_random_seed(111)
# Notebook Settings
SAVE_FIG = False

Calculating Entropy Measures on Example Signals

Entropy measures generally measure the level of ‘randomness’ or complexity in a signal.

In all cases, smaller values of measured entropy indicate more regular time series.

print('Computed approximate entropy:')
print('  powerlaw: \t {:1.4f}'.format(app_entropy(SIG_AP, **AP_ENT_PARAMS)))
print('  osc:      \t {:1.4f}'.format(app_entropy(SIG_OSC, **AP_ENT_PARAMS)))
print('  combined: \t {:1.4f}'.format(app_entropy(SIG_COMB, **AP_ENT_PARAMS)))
print('  knee:     \t {:1.4f}'.format(app_entropy(SIG_KN, **AP_ENT_PARAMS)))
Computed approximate entropy:
  powerlaw: 	 0.4097
  osc:      	 0.2010
  combined: 	 1.0141
  knee:     	 1.4911
print('Computed sample entropy:')
print('  powerlaw: \t {:1.4f}'.format(sample_entropy(SIG_AP, **SA_ENT_PARAMS)))
print('  osc:      \t {:1.4f}'.format(sample_entropy(SIG_OSC, **SA_ENT_PARAMS)))
print('  combined: \t {:1.4f}'.format(sample_entropy(SIG_COMB, **SA_ENT_PARAMS)))
print('  knee:     \t {:1.4f}'.format(sample_entropy(SIG_KN, **SA_ENT_PARAMS)))
Computed sample entropy:
  powerlaw: 	 0.3796
  osc:      	 0.1629
  combined: 	 0.9213
  knee:     	 1.3736
print('Computed permutation entropy:')
print('  powerlaw: \t {:1.4f}'.format(perm_entropy(SIG_AP, **PE_ENT_PARAMS)))
print('  osc:      \t {:1.4f}'.format(perm_entropy(SIG_OSC, **PE_ENT_PARAMS)))
print('  combined: \t {:1.4f}'.format(perm_entropy(SIG_COMB, **PE_ENT_PARAMS)))
print('  knee:     \t {:1.4f}'.format(perm_entropy(SIG_KN, **PE_ENT_PARAMS)))
Computed permutation entropy:
  powerlaw: 	 2.5213
  osc:      	 1.1414
  combined: 	 2.5198
  knee:     	 2.5091
print('Computed spectral entropy:')
print('  powerlaw: \t {:1.4f}'.format(spectral_entropy(SIG_AP, **SP_ENT_PARAMS)))
print('  osc:      \t {:1.4f}'.format(spectral_entropy(SIG_OSC, **SP_ENT_PARAMS)))
print('  combined: \t {:1.4f}'.format(spectral_entropy(SIG_COMB, **SP_ENT_PARAMS)))
print('  knee:     \t {:1.4f}'.format(spectral_entropy(SIG_KN, **SP_ENT_PARAMS)))
Computed spectral entropy:
  powerlaw: 	 4.2230
  osc:      	 0.0000
  combined: 	 7.4309
  knee:     	 10.8893

Approximate Entropy

Approximate entropy quantifies the unpredictability of a time series.

Aperiodic Variations

# Run simulations calculating approximate entropy across exponents
outs = run_sims(sim_powerlaw, SIM_PARAMS_AP, app_entropy, AP_ENT_PARAMS, 
                'update_exp', EXPS, N_SIMS, var_func=np.std)
ap_ents, ap_ents_var = outs
# Run simulations calculating approximate entropy across exponents, with an oscillation
outs = run_sims(sim_combined, SIM_PARAMS_COMB, app_entropy, AP_ENT_PARAMS, 
                'update_comb_exp', EXPS, N_SIMS, var_func=np.std)
ap_ents_comb, ap_ents_comb_var = outs
# Plot entropy measures for with & without oscillation together
plot_lines(EXPS, ap_ents, ap_ents_var, color=AP_COL, label='Aperiodic')
plot_lines(EXPS, ap_ents_comb, ap_ents_comb_var, color=COMB_COL, label='Combined')
plot_lines(xlabel='Aperiodic Exponent', ylabel='Entropy')
plot_lines(save_fig=SAVE_FIG, file_name='ap_both', file_path='info')
../_images/16-Information_17_0.png

Periodic Variations

# Run simulations calculating approximate entropy across oscillation frequency
outs = run_sims(sim_combined, SIM_PARAMS_COMB, app_entropy, AP_ENT_PARAMS,
                'update_freq', FREQS, N_SIMS, var_func=np.std)
ap_sims_freq, ap_sims_freq_var = outs
# Run simulations calculating approximate entropy across oscillation power
outs = run_sims(sim_combined, SIM_PARAMS_COMB, app_entropy, AP_ENT_PARAMS,
                'update_pow', POWERS, N_SIMS, var_func=np.std)
ap_sims_pow, ap_sims_pow_var = outs
# Plot effect of oscillation variations on approximate entropy
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
plot_lines(FREQS, ap_sims_freq, ap_sims_freq_var, ax=axes[0])
plot_lines(xlabel='Oscillation Frequency', ylabel='Entropy', ax=axes[0])
plot_lines(POWERS, ap_sims_pow, ap_sims_pow_var, ax=axes[1])
plot_lines(xlabel='Oscillation Power', ylabel='Entropy', ax=axes[1])
plt.subplots_adjust(wspace=0.25)
plot_lines(save_fig=SAVE_FIG, file_name='ap_osc_power', file_path='info')
../_images/16-Information_21_0.png

Sample Entropy

Sample entropy is a modification of approxmiate entropy for physiological time series.

The modifications of sample entropy make it data length independent.

Aperiodic Variations

# Run simulations calculating sample entropy across exponents
outs = run_sims(sim_powerlaw, SIM_PARAMS_AP, sample_entropy, SA_ENT_PARAMS,
                'update_exp', EXPS, N_SIMS, var_func=np.std)
sa_ents, sa_ents_var = outs
# Run simulations calculating sample entropy across exponents, with an oscillation
outs = run_sims(sim_combined, SIM_PARAMS_COMB, sample_entropy, SA_ENT_PARAMS,
                'update_comb_exp', EXPS, N_SIMS, var_func=np.std)
sa_ents_comb, sa_ents_comb_var = outs
# Plot entropy measures for with & without oscillation together
plot_lines(EXPS, sa_ents, sa_ents_var, color=AP_COL, label='Aperiodic')
plot_lines(EXPS, sa_ents_comb, sa_ents_comb_var, color=COMB_COL, label='Combined')
plot_lines(xlabel='Aperiodic Exponent', ylabel='Entropy')
plot_lines(save_fig=SAVE_FIG, file_name='se_both', file_path='info')
../_images/16-Information_26_0.png

Periodic Variations

# Run simulations calculating sample entropy across oscillation frequency
outs = run_sims(sim_combined, SIM_PARAMS_COMB, sample_entropy, SA_ENT_PARAMS,
                'update_freq', FREQS, N_SIMS, var_func=np.std)
sa_sims_freq, sa_sims_freq_var = outs
# Run a set of simulations, calculating sample entropy across oscillation power
outs = run_sims(sim_combined, SIM_PARAMS_COMB, sample_entropy, SA_ENT_PARAMS,
                'update_pow', POWERS, N_SIMS, var_func=np.std)
sa_sims_pow, sa_sims_pow_var = outs
# Plot effect of oscillation variation on sample entropy
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
plot_lines(FREQS, sa_sims_freq, sa_sims_freq_var, ax=axes[0])
plot_lines(xlabel='Oscillation Frequency', ylabel='Entropy', ax=axes[0])
plot_lines(POWERS, sa_sims_pow, sa_sims_pow_var, ax=axes[1])
plot_lines(xlabel='Oscillation Power', ylabel='Entropy', ax=axes[1])
plt.subplots_adjust(wspace=0.25)
plot_lines(save_fig=SAVE_FIG, file_name='se_osc_both', file_path='info')
../_images/16-Information_30_0.png

Permutation Entropy

Permutation entropy is a measure of entropy based on the probabilities of sequences within the time series.

Permutation entropy was introduced in 2002 by Bandt & Pompe.

Aperiodic Variations

# Run simulations calculating permutation entropy across exponents
outs = run_sims(sim_powerlaw, SIM_PARAMS_AP, perm_entropy, PE_ENT_PARAMS,
                'update_exp', EXPS, N_SIMS, var_func=np.std)
pe_ents, pe_ents_var = outs
# Run simulations calculating permutation entropy across exponents, with an oscillation
outs = run_sims(sim_combined, SIM_PARAMS_COMB, perm_entropy, PE_ENT_PARAMS,
                'update_comb_exp', EXPS, N_SIMS, var_func=np.std)
pe_ents_comb, pe_ents_comb_var = outs
# Plot entropy measures for with & without oscillation together
plot_lines(EXPS, pe_ents, pe_ents_var, color=AP_COL, label='Aperiodic')
plot_lines(EXPS, pe_ents_comb, pe_ents_comb_var, color=COMB_COL, label='Combined')
plot_lines(xlabel='Aperiodic Exponent', ylabel='Entropy')
plot_lines(save_fig=SAVE_FIG, file_name='pe_both', file_path='info')
../_images/16-Information_35_0.png
# Run a set of simulations, calculating permutation entropy across oscillation frequency
outs = run_sims(sim_combined, SIM_PARAMS_COMB, perm_entropy, PE_ENT_PARAMS,
                'update_freq', FREQS, N_SIMS, var_func=np.std)
pe_sims_freq, pe_sims_freq_var = outs
# Run simulations calculating permutation entropy across oscillation power
outs = run_sims(sim_combined, SIM_PARAMS_COMB, perm_entropy, PE_ENT_PARAMS,
                'update_pow', POWERS, N_SIMS, var_func=np.std)
pe_sims_pow, pe_sims_pow_var = outs
# Plot effect of oscillation variation on sample entropy
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
plot_lines(FREQS, pe_sims_freq, pe_sims_freq_var, ax=axes[0])
plot_lines(xlabel='Oscillation Frequency', ylabel='Entropy', ax=axes[0])
plot_lines(POWERS, pe_sims_pow, pe_sims_pow_var, ax=axes[1])
plot_lines(xlabel='Oscillation Power', ylabel='Entropy', ax=axes[1])
plt.subplots_adjust(wspace=0.25)
plot_lines(save_fig=SAVE_FIG, file_name='pe_osc_both', file_path='info')
../_images/16-Information_38_0.png

Spectral Entropy

The spectral entropy measures the entropy of the power spectrum.

# Run simulations calculating spectral entropy across exponents
outs = run_sims(sim_powerlaw, SIM_PARAMS_AP, spectral_entropy, SP_ENT_PARAMS, 
                'update_exp', EXPS, N_SIMS, var_func=np.std)
sp_ents, sp_ents_var = outs
# Run simulations calculating spectral entropy across exponents, with an oscillation
outs = run_sims(sim_combined, SIM_PARAMS_COMB, spectral_entropy, SP_ENT_PARAMS, 
                'update_comb_exp', EXPS, N_SIMS, var_func=np.std)
sp_ents_comb, sp_ents_comb_var = outs
# Plot spectral entropy measures for with & without oscillation together
plot_lines(EXPS, sp_ents, sp_ents_var, color=AP_COL, label='Aperiodic')
plot_lines(EXPS, sp_ents_comb, sp_ents_comb_var, color=COMB_COL, label='Combined')
plot_lines(xlabel='Aperiodic Exponent', ylabel='Entropy')
plot_lines(save_fig=SAVE_FIG, file_name='ap_both', file_path='info')
../_images/16-Information_42_0.png

Periodic Variations

# Run simulations calculating spectral entropy across oscillation frequency
outs = run_sims(sim_combined, SIM_PARAMS_COMB, spectral_entropy, SP_ENT_PARAMS,
                'update_freq', FREQS, N_SIMS, var_func=np.std)
sp_sims_freq, sp_sims_freq_var = outs
# Run simulations calculating spectral entropy across oscillation power
outs = run_sims(sim_combined, SIM_PARAMS_COMB, spectral_entropy, SP_ENT_PARAMS,
                'update_pow', POWERS, N_SIMS, var_func=np.std)
sp_sims_pow, sp_sims_pow_var = outs
# Plot effect of oscillation variation on sample entropy
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
plot_lines(FREQS, sp_sims_freq, sp_sims_freq_var, ax=axes[0])
plot_lines(xlabel='Oscillation Frequency', ylabel='Entropy', ax=axes[0])
plot_lines(POWERS, sp_sims_pow, sp_sims_pow_var, ax=axes[1])
plot_lines(xlabel='Oscillation Power', ylabel='Entropy', ax=axes[1])
plt.subplots_adjust(wspace=0.25)
plot_lines(save_fig=SAVE_FIG, file_name='ap_osc_both', file_path='info')
../_images/16-Information_46_0.png

Conclusions

Overall, we can see the following patterns in these simulations:

Entropy (general patterns across all):

  • Entropy increases for decreasing aperiodic exponents, non-linearly

  • Entropy decreases for increasing oscillatory power, approximately linearly