Source code for neurokit2.complexity.utils_recurrence_matrix

import matplotlib.pyplot as plt
import matplotlib.ticker
import numpy as np
import scipy.spatial

from .optim_complexity_tolerance import complexity_tolerance
from .utils_complexity_embedding import complexity_embedding


[docs] def recurrence_matrix(signal, delay=1, dimension=3, tolerance="default", show=False): """**Recurrence Matrix** Fast Python implementation of recurrence matrix (tested against pyRQA). Returns a tuple with the recurrence matrix (made of 0s and 1s) and the distance matrix (the non-binarized version of the former). It is used in :func:`Recurrence Quantification Analysis (RQA) <complexity_rqa>`. Parameters ---------- signal : Union[list, np.ndarray, pd.Series] The signal (i.e., a time series) in the form of a vector of values. delay : int Time delay (often denoted *Tau* :math:`\\tau`, sometimes referred to as *lag*) in samples. See :func:`complexity_delay` to estimate the optimal value for this parameter. dimension : int Embedding Dimension (*m*, sometimes referred to as *d* or *order*). See :func:`complexity_dimension` to estimate the optimal value for this parameter. tolerance : float Tolerance (often denoted as *r*), distance to consider two data points as similar. If ``"sd"`` (default), will be set to :math:`0.2 * SD_{signal}`. See :func:`complexity_tolerance` to estimate the optimal value for this parameter. A rule of thumb is to set *r* so that the percentage of points classified as recurrences is about 2-5%. show : bool Visualise recurrence matrix. See Also -------- complexity_embedding, complexity_delay, complexity_dimension, complexity_tolerance, complexity_rqa Returns ------- np.ndarray The recurrence matrix. np.ndarray The distance matrix. Examples ---------- .. ipython:: python import neurokit2 as nk signal = nk.signal_simulate(duration=2, sampling_rate=100, frequency=[5, 6], noise=0.01) # Default r @savefig p_recurrence_matrix1.png scale=100% rc, _ = nk.recurrence_matrix(signal, show=True) @suppress plt.close() .. ipython:: python # Larger radius @savefig p_recurrence_matrix2.png scale=100% rc, d = nk.recurrence_matrix(signal, tolerance=0.5, show=True) @suppress plt.close() .. ipython:: python # Optimization of tolerance via recurrence matrix @savefig p_recurrence_matrix3.png scale=100% tol, _ = nk.complexity_tolerance(signal, dimension=1, delay=3, method="recurrence", show=True) @suppress plt.close() .. ipython:: python @savefig p_recurrence_matrix4.png scale=100% rc, d = nk.recurrence_matrix(signal, tolerance=tol, show=True) @suppress plt.close() References ---------- * Rawald, T., Sips, M., Marwan, N., & Dransch, D. (2014). Fast computation of recurrences in long time series. In Translational Recurrences (pp. 17-29). Springer, Cham. * Dabiré, H., Mestivier, D., Jarnet, J., Safar, M. E., & Chau, N. P. (1998). Quantification of sympathetic and parasympathetic tones by nonlinear indexes in normotensive rats. American Journal of Physiology-Heart and Circulatory Physiology, 275(4), H1290-H1297. """ tolerance, _ = complexity_tolerance( signal, method=tolerance, delay=delay, dimension=dimension, show=False ) # Time-delay embedding emb = complexity_embedding(signal, delay=delay, dimension=dimension) # Compute distance matrix d = scipy.spatial.distance.cdist(emb, emb, metric="euclidean") # Initialize the recurrence matrix filled with 0s recmat = np.zeros((len(d), len(d))) # If lower than tolerance, then 1 recmat[d <= tolerance] = 1 # Plotting if show is True: try: fig, axes = plt.subplots(ncols=2) axes[0].imshow(recmat, cmap="Greys") axes[0].set_title("Recurrence Matrix") im = axes[1].imshow(d) axes[1].set_title("Distance") cbar = fig.colorbar(im, ax=axes[1], fraction=0.046, pad=0.04) cbar.ax.plot([0, 1], [tolerance] * 2, color="r") # Flip the matrix to match traditional RQA representation axes[0].invert_yaxis() axes[1].invert_yaxis() axes[0].xaxis.set_major_locator(matplotlib.ticker.MaxNLocator(integer=True)) axes[1].xaxis.set_major_locator(matplotlib.ticker.MaxNLocator(integer=True)) except MemoryError as e: raise MemoryError( "NeuroKit error: complexity_rqa(): the recurrence plot is too large to display. ", "You can recover the matrix from the parameters and try to display parts of it.", ) from e return recmat, d