Source code for pyunicorn.timeseries.joint_recurrence_network

# This file is part of pyunicorn.
# Copyright (C) 2008--2024 Jonathan F. Donges and pyunicorn authors
# URL: <https://www.pik-potsdam.de/members/donges/software-2/software>
# License: BSD (3-clause)
#
# Please acknowledge and cite the use of this software and its authors
# when results are used in publications or published elsewhere.
#
# You can use the following reference:
# J.F. Donges, J. Heitzig, B. Beronov, M. Wiedermann, J. Runge, Q.-Y. Feng,
# L. Tupikina, V. Stolbova, R.V. Donner, N. Marwan, H.A. Dijkstra,
# and J. Kurths, "Unified functional network and nonlinear time series analysis
# for complex systems science: The pyunicorn package"

"""
Provides classes for the analysis of dynamical systems and time series based
on recurrence plots, including measures of recurrence quantification
analysis (RQA) and recurrence network analysis.
"""

# array object and fast numerics
import numpy as np

from ..core import Network
from .joint_recurrence_plot import JointRecurrencePlot


#
#  Class definitions
#

[docs] class JointRecurrenceNetwork(JointRecurrencePlot, Network): """ Class JointRecurrenceNetwork for generating and quantitatively analyzing joint recurrence networks. For a joint recurrence network, time series x and y need to have the same length! Formally, nodes are identified with sampling points in time, while an undirected link (i,j) is introduced if x at time i is recurrent to x at time j and also y at time i is recurrent to y at time j. Self-loops are excluded in this undirected network representation. More information on the theory and applications of joint recurrence networks can be found in [Feldhoff2013]_. **Examples:** - Create an instance of JointRecurrenceNetwork with a fixed recurrence threshold and without embedding:: JointRecurrenceNetwork(x, y, threshold=(0.1,0.2)) - Create an instance of JointRecurrenceNetwork with a fixed recurrence threshold in units of STD and without embedding:: JointRecurrenceNetwork(x, y, threshold_std=(0.03,0.05)) - Create an instance of JointRecurrenceNetwork at a fixed recurrence rate and using time delay embedding:: JointRecurrenceNetwork( x, y, dim=(3,5), tau=(2,1), recurrence_rate=(0.05,0.04)).recurrence_rate() """ # # Internal methods #
[docs] def __init__(self, x, y, metric=("supremum", "supremum"), normalize=False, lag=0, silence_level=0, **kwds): """ Initialize an instance of JointRecurrenceNetwork. .. note:: For a joint recurrence network, time series x and y need to have the same length! Creates an embedding of the given time series x and y, calculates a joint recurrence plot from the embedding and then creates a Network object from the joint recurrence plot, interpreting the joint recurrence matrix as the adjacency matrix of an undirected complex network. Either recurrence thresholds ``threshold``/``threshold_std`` or recurrence rates ``recurrence_rate`` have to be given as keyword arguments. Embedding is only supported for scalar time series. If embedding dimension ``dim`` and delay ``tau`` are **both** given as keyword arguments, embedding is applied. Multidimensional time series are processed as is by default. :type x: 2D Numpy array (time, dimension) :arg x: The time series x to be analyzed, can be scalar or multi-dimensional. :type y: 2D Numpy array (time, dimension) :arg y: The time series y to be analyzed, can be scalar or multi-dimensional. :type metric: tuple of string :arg metric: The metric for measuring distances in phase space ("manhattan", "euclidean", "supremum"). Give separately for each time series. :type normalize: tuple of bool :arg normalize: Decide whether to normalize the time series to zero mean and unit standard deviation. Give separately for each time series. :arg number lag: To create a delayed version of the JRP. :arg number silence_level: Inverse level of verbosity of the object. :type threshold: tuple of number :keyword threshold: The recurrence threshold keyword for generating the recurrence plot using a fixed threshold. Give separately for each time series. :type threshold_std: tuple of number :keyword threshold_std: The recurrence threshold keyword for generating the recurrence plot using a fixed threshold in units of the time series' STD. Give separately for each time series. :type recurrence_rate: tuple of number :keyword recurrence_rate: The recurrence rate keyword for generating the recurrence plot using a fixed recurrence rate. Give separately for each time series. :type dim: tuple of number :keyword dim: The embedding dimension. Give separately for each time series. :type tau: tuple of number :keyword tau: The embedding delay. Give separately for each time series. """ # Check for consistency if np.abs(lag) < x.shape[0]: if x.shape[0] == y.shape[0]: # Initialize the underlying RecurrencePlot object JointRecurrencePlot.__init__(self, x, y, metric, normalize, lag, silence_level, **kwds) # Set diagonal of JR to zero to avoid self-loops in the joint # recurrence network A = self.JR - np.eye((self.N-np.abs(lag)), dtype="int8") # Create a Network object interpreting the recurrence matrix # as the graph adjacency matrix. Joint recurrence networks # are undirected by definition. Network.__init__(self, A, directed=False, silence_level=silence_level) else: raise ValueError("Both time series x and y need to have the \ same length!") else: raise ValueError("Delay value (lag) must not exceed length of \ time series!")
[docs] def __str__(self): """ Returns a string representation. """ return ("JointRecurrenceNetwork:\n" f"{JointRecurrencePlot.__str__(self)}\n" f"{Network.__str__(self)}")
[docs] def clear_cache(self): """ Clean up memory by deleting information that can be recalculated from basic data. Extends the clean up methods of the parent classes. """ # Call clean up of RecurrencePlot JointRecurrencePlot.clear_cache(self) # Call clean up of Network Network.clear_cache(self)
# # Methods to handle recurrence networks #
[docs] def set_fixed_threshold(self, threshold): """ Create a joint recurrence network at fixed thresholds. :type threshold: tuple of number :arg threshold: The threshold. Give for each time series separately. """ # Set fixed threshold on recurrence plot level JointRecurrencePlot.set_fixed_threshold(self, threshold) # Set diagonal of JR to zero to avoid self-loops in the joint # recurrence network A = self.JR.copy() A.flat[::self.N+1] = 0 # Create a Network object interpreting the recurrence matrix as the # graph adjacency matrix. Joint recurrence networks are undirected by # definition. Network.__init__(self, A, directed=False, silence_level=self.silence_level)
[docs] def set_fixed_threshold_std(self, threshold_std): """ Create a joint recurrence network at fixed thresholds in units of the standard deviation of the time series. :type threshold_std: tuple of number :arg threshold_std: The threshold in units of standard deviation. Give for each time series separately. """ # Set fixed threshold on recurrence plot level JointRecurrencePlot.set_fixed_threshold_std(self, threshold_std) # Set diagonal of JR to zero to avoid self-loops in the joint # recurrence network A = self.JR.copy() A.flat[::self.N+1] = 0 # Create a Network object interpreting the recurrence matrix as the # graph adjacency matrix. Joint recurrence networks are undirected by # definition. Network.__init__(self, A, directed=False, silence_level=self.silence_level)
[docs] def set_fixed_recurrence_rate(self, recurrence_rate): """ Create a joint recurrence network at fixed link densities (recurrence rates). :type recurrence_rate: tuple of number :arg recurrence_rate: The link density / recurrence rate. Give for each time series separately. """ # Set fixed recurrence rate on recurrence plot level JointRecurrencePlot.set_fixed_recurrence_rate(self, recurrence_rate) # Set diagonal of JR to zero to avoid self-loops in the joint # recurrence network A = self.JR.copy() A.flat[::self.N+1] = 0 # Create a Network object interpreting the recurrence matrix as the # graph adjacency matrix. Joint recurrence networks are undirected by # definition. Network.__init__(self, A, directed=False, silence_level=self.silence_level)