Source code for neurokit2.complexity.fractal_higuchi

# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from .optim_complexity_k import _complexity_k_slope, complexity_k


[docs] def fractal_higuchi(signal, k_max="default", show=False, **kwargs): """**Higuchi's Fractal Dimension (HFD)** The Higuchi's Fractal Dimension (HFD) is an approximate value for the box-counting dimension for time series. It is computed by reconstructing k-max number of new data sets. For each reconstructed data set, curve length is computed and plotted against its corresponding *k*-value on a log-log scale. HFD corresponds to the slope of the least-squares linear trend. Values should fall between 1 and 2. For more information about the *k* parameter selection, see the :func:`complexity_k` optimization function. Parameters ---------- signal : Union[list, np.array, pd.Series] The signal (i.e., a time series) in the form of a vector of values. k_max : str or int Maximum number of interval times (should be greater than or equal to 2). If ``"default"``, the optimal k-max is estimated using :func:`complexity_k`, which is slow. show : bool Visualise the slope of the curve for the selected k_max value. **kwargs : optional Currently not used. Returns ---------- HFD : float Higuchi's fractal dimension of the time series. info : dict A dictionary containing additional information regarding the parameters used to compute Higuchi's fractal dimension. See Also -------- complexity_k Examples ---------- .. ipython:: python import neurokit2 as nk signal = nk.signal_simulate(duration=1, sampling_rate=100, frequency=[3, 6], noise = 0.2) @savefig p_fractal_higuchi1.png scale=100% k_max, info = nk.complexity_k(signal, k_max='default', show=True) @suppress plt.close() @savefig p_fractal_higuchi2.png scale=100% hfd, info = nk.fractal_higuchi(signal, k_max=k_max, show=True) @suppress plt.close() .. ipython:: python hfd References ---------- * Higuchi, T. (1988). Approach to an irregular time series on the basis of the fractal theory. Physica D: Nonlinear Phenomena, 31(2), 277-283. * Vega, C. F., & Noel, J. (2015, June). Parameters analyzed of Higuchi's fractal dimension for EEG brain signals. In 2015 Signal Processing Symposium (SPSympo) (pp. 1-5). IEEE. https://ieeexplore.ieee.org/document/7168285 """ # Sanity checks if isinstance(signal, (np.ndarray, pd.DataFrame)) and signal.ndim > 1: raise ValueError( "Multidimensional inputs (e.g., matrices or multichannel data) are not supported yet." ) # Get k_max if isinstance(k_max, (str, list, np.ndarray, pd.Series)): # Optimizing needed k_max, info = complexity_k(signal, k_max=k_max, show=False) idx = np.where(info["Values"] == k_max)[0][0] slope = info["Scores"][idx] intercept = info["Intercepts"][idx] average_values = info["Average_Values"][idx] k_values = np.arange(1, k_max + 1) else: # Compute Higuchi slope, intercept, info = _complexity_k_slope(k_max, signal) k_values = info["k_values"] average_values = info["average_values"] # Plot if show: _fractal_higuchi_plot(k_values, average_values, k_max, slope, intercept) return slope, { "k_max": k_max, "Values": k_values, "Scores": average_values, "Intercept": intercept, }
# ============================================================================= # Utilities # ============================================================================= def _fractal_higuchi_plot(k_values, average_values, kmax, slope, intercept, ax=None): if ax is None: fig, ax = plt.subplots() fig.suptitle("Higuchi Fractal Dimension (HFD)") else: fig = None ax.set_title( "Least-squares linear best-fit curve for $k_{max}$ = " + str(kmax) + ", slope = " + str(np.round(slope, 2)) ) ax.set_ylabel(r"$ln$(L(k))") ax.set_xlabel(r"$ln$(1/k)") colors = plt.cm.plasma(np.linspace(0, 1, len(k_values))) # Label all values unless len(k_values) > 10 then label only min and max k_max if len(k_values) < 10: for i in range(0, len(k_values)): ax.scatter( -np.log(k_values[i]), np.log(average_values[i]), color=colors[i], marker="o", zorder=2, label="k = {}".format(i + 1), ) else: for i in range(0, len(k_values)): ax.scatter( -np.log(k_values[i]), np.log(average_values[i]), color=colors[i], marker="o", zorder=2, label="_no_legend_", ) ax.plot([], label="k = {}".format(np.min(k_values)), c=colors[0]) ax.plot([], label="k = {}".format(np.max(k_values)), c=colors[-1]) fit_values = [slope * i + -intercept for i in -np.log(k_values)] ax.plot(-np.log(k_values), fit_values, color="#FF9800", zorder=1) ax.legend(loc="lower right") return fig