Source code for dyconnmap.ts.fnn

# -*- coding: utf-8 -*-
""" False Nearest Neighbors


|

-----


.. [Kennel1992] Kennel, M. B., Brown, R., & Abarbanel, H. D. (1992). Determining embedding dimension for phase-space reconstruction using a geometrical construction. Physical review A, 45(6), 3403.
.. [Abarbane2012] Abarbanel, H. (2012). Analysis of observed chaotic data. Springer Science & Business Media.
"""
# Author: Avraam Marimpis <avraam.marimpis@gmail.com>

import numpy as np


[docs]def fnn(ts, tau, max_dim=20, neighbors_reduction=0.10, rtol=15.0, atol=2.0): """ False Nearest Neighbors Notes ----- The execution stops either when the maxium number of embedding dimensions is reached, or the the number of neighbors is reduced to specific percentage. Parameters ---------- ts : array-like, 1d tau : int Time-delay parameter. max_dim : int Maximum embedding dimension. neighbors_reduction : float Maximum percentage of neighbors reduction. Default '0.10' (10%). rtol : float First threshold, criterion to identify a false neighbor. (Neighborhood size) atol : float Second threshold, criterion to identify a false neighbor. Returns ------- min_dimension : int Minimum embedding dimension. """ ts = ts.flatten() neighbors_perc = neighbors_reduction * 100.0 fnn_ini = 0.0 min_dimension = None Ra = np.std(ts) for dim in range(1, max_dim): min_dimension = dim ed_ts, num_points = __embed_delay(ts, dim, tau) if ed_ts is not None and num_points > 0: distances = np.zeros((num_points, num_points)) for i in range(num_points): distances[i, :] = __euclidean_distance(ed_ts, np.ones((num_points, dim)) * ed_ts[i, :]) indices = np.argsort(distances) sort_distances = np.sort(distances) all_D = np.abs(ts[np.arange(num_points) + dim * tau] - ts[indices[:, 1] + dim * tau]) all_R = np.sqrt(np.power(all_D, 2) + np.power(sort_distances[:, 1], 2)) a = all_D / sort_distances[:, 1] b = all_R / Ra fnn_a_or_b = np.where((a > rtol) | (b > atol)) fnn_value = len(fnn_a_or_b[0]) if dim == 1: fnn_ini = fnn_value elif fnn_value < fnn_ini / neighbors_perc: break else: break return min_dimension
def __euclidean_distance(x, y): return np.sqrt(np.sum(np.power(x - y, 2), 1)) def __embed_delay(ts, dim, tau): """ Embed delay, treated for FNN method. For internal use only. """ ts = ts.flatten() new_ts = np.zeros((dim, len(ts))) new_ts[0, :] = ts l = len(ts) m = l - (dim) * tau if dim == 1: m = l - tau if m < 0: return None, m for i in range(1, dim): offset = i - 1 tmp = np.roll(new_ts[offset], l - tau) new_ts[i] = tmp new_ts = new_ts.T y = new_ts[0:m, 0:dim] return y, m