Skip to content

Delay Coordinates

A timeseries recorded in some manner from a dynamical system can be used to gain information about the dynamics of the entire phase-space of the system. This can be done by reconstructing a new phase-space from the timeseries. One method that can do this is what is known as delay coordinates embedding or delay coordinates reconstruction.

Reconstruct/Embed

Delay embedding reconstructions are done through reconstruct or embed:

#DelayEmbeddings.reconstructFunction.

reconstruct(s, γ, τ)

Reconstruct s using the delay coordinates embedding with γ temporal neighbors and delay τ and return the result as a Dataset.

See embed for the version that accepts the embedding dimension D = γ+1 directly.

Description

Single Timeseries

If τ is an integer, then the n-th entry of the embedded space is

(s(n), s(n+\tau), s(n+2\tau), \dots, s(n+γ\tau))

If instead τ is a vector of integers, so that length(τ) == γ, then the n-th entry is

(s(n), s(n+\tau[1]), s(n+\tau[2]), \dots, s(n+\tau[γ]))

The reconstructed dataset can have same invariant quantities (like e.g. lyapunov exponents) with the original system that the timeseries were recorded from, for proper γ and τ. This is known as the Takens embedding theorem [1, 2]. The case of different delay times allows reconstructing systems with many time scales, see [3].

Notice - The dimension of the returned dataset (i.e. embedding dimension) is γ+1!

Multiple Timeseries

To make a reconstruction out of a multiple timeseries (i.e. trajectory) the number of timeseries must be known by type, so s can be either:

  • s::AbstractDataset{B}
  • s::SizedAray{A, B}

If the trajectory is for example (x, y) and τ is integer, then the n-th entry of the embedded space is

(x(n), y(n), x(n+\tau), y(n+\tau), \dots, x(n+γ\tau), y(n+γ\tau))

If τ is an AbstractMatrix{Int}, so that size(τ) == (γ, B), then we have

(x(n), y(n), x(n+\tau[1, 1]), y(n+\tau[1, 2]), \dots, x(n+\tau[γ, 1]), y(n+\tau[γ, 2]))

Notice - The dimension of the returned dataset is (γ+1)*B!

References

[1] : F. Takens, Detecting Strange Attractors in Turbulence — Dynamical Systems and Turbulence, Lecture Notes in Mathematics 366, Springer (1981)

[2] : T. Sauer et al., J. Stat. Phys. 65, pp 579 (1991)

[3] : K. Judd & A. Mees, Physica D 120, pp 273 (1998)

#DelayEmbeddings.embedFunction.

embed(s, D, τ)

Perform a delay coordinates embedding on signal s with embedding dimension D and delay time τ. The result is returned as a Dataset, which is a vector of static vectors.

See reconstruct for an advanced version that supports multiple delay times and can reconstruct multiple timeseries efficiently.


Here are some examples of reconstructing a 3D continuous chaotic system:

using DynamicalSystems, PyPlot

ds = Systems.gissinger(ones(3))
data = trajectory(ds, 1000.0, dt = 0.05)

xyz = columns(data)

figure(figsize = (12,10))
k = 1
for i in 1:3
    for τ in [5, 30, 100]
        R = reconstruct(xyz[i], 1, τ)
        ax = subplot(3,3,k)
        plot(R[:, 1], R[:, 2], color = "C$(k-1)", lw = 0.8)
        title("var = $i, τ = ")
        global k+=1
    end
end

tight_layout()
suptitle("2D reconstructed space")
subplots_adjust(top=0.9)

τ and dt

Keep in mind that whether a value of τ is "reasonable" for continuous systems depends on dt. In the above example the value τ=30 is good, only for the case of using dt = 0.05. For shorter/longer dt one has to adjust properly τ so that their product τ*dt is the same.

You can also reconstruct multidimensional timeseries. For this to be possible, the number of timeseries must be known by Type:

using StaticArrays: Size
a = rand(1000, 3) # my trajectory

A = Size(1000, 3)(a) # create array with the size as Type information
R = reconstruct(A, 2, 2) #aaaall good
9-dimensional Dataset{Float64} with 996 points
 0.054502    0.826439   0.135553    0.39143    0.310166  0.370603 
 0.639211    0.414527   0.55877      0.979642   0.502998  0.465613 
 0.171316    0.0841454  0.363251     0.345203   0.336887  0.906889 
 0.717075    0.784564   0.16234      0.782596   0.312001  0.628767 
 0.39143     0.310166   0.370603     0.0336188  0.148752  0.85327  
 0.979642    0.502998   0.465613    0.883052   0.577202  0.27189  
 0.345203    0.336887   0.906889     0.515897   0.433953  0.50353  
 0.782596    0.312001   0.628767     0.488023   0.19643   0.997044 
 0.0336188   0.148752   0.85327      0.0614884  0.509386  0.528218 
 0.883052    0.577202   0.27189      0.417898   0.25669   0.0793331
                                                                 
 0.080455    0.135499   0.35817      0.721946   0.893601  0.32365  
 0.504001    0.900806   0.217099     0.244439   0.743023  0.407145 
 0.00836735  0.675967   0.176169     0.709889   0.878236  0.391053 
 0.0951728   0.748783   0.776681     0.886417   0.716448  0.429042 
 0.721946    0.893601   0.32365     0.714942   0.267734  0.919564 
 0.244439    0.743023   0.407145     0.63069    0.980046  0.912266 
 0.709889    0.878236   0.391053     0.170436   0.841912  0.302581 
 0.886417    0.716448   0.429042     0.674132   0.672273  0.195279 
 0.714942    0.267734   0.919564     0.457574   0.12547   0.829726 
ds = Systems.towel(); tr = trajectory(ds, 10000)
R = reconstruct(tr, 2, 2) # Dataset size is also known by Type!
9-dimensional Dataset{Float64} with 9997 points
 0.085     -0.121       0.075       0.837347   0.0372633   0.555269
 0.285813  -0.0675286   0.238038     0.51969    0.0616256   0.940906
 0.76827   -0.038933    0.672094     0.966676  -0.00171595  0.2225  
 0.681871   0.0508933   0.825263     0.112748   0.0674955   0.653573
 0.837347   0.0372633   0.555269     0.386547  -0.0886542   0.869349
 0.51969    0.0616256   0.940906    0.910741  -0.0316828   0.411607
 0.966676  -0.00171595  0.2225       0.306095   0.0689305   0.909129
 0.112748   0.0674955   0.653573     0.824263  -0.056185    0.326064
 0.386547  -0.0886542   0.869349     0.545332   0.0508239   0.819404
 0.910741  -0.0316828   0.411607     0.954994   0.00453815  0.569534
                                                                  
 0.914702  -0.0315439   0.294266     0.90246    0.0242141   0.539502
 0.289932   0.0641239   0.778698     0.335976   0.0735803   0.943945
 0.793854  -0.0552801   0.664223     0.86657   -0.0497658   0.214728
 0.62671    0.0557527   0.832001     0.430816   0.0535742   0.62743 
 0.90246    0.0242141   0.539502    0.936955  -0.0200112   0.894333
 0.335976   0.0735803   0.943945     0.237481   0.0983265   0.353212
 0.86657   -0.0497658   0.214728     0.681538  -0.0476555   0.883219
 0.430816   0.0535742   0.62743      0.836353   0.0363264   0.380351
 0.936955  -0.0200112   0.894333     0.515471   0.0534613   0.898152

Embedding Functors

The high level functions embed, reconstruct utilize a low-level interface for creating embedded vectors on-the-fly. The high level interface simply loops over the low level interface. The low level interface is composed of the following two structures:

#DelayEmbeddings.DelayEmbeddingType.

DelayEmbedding(γ, τ) -> `embedding`

Return a delay coordinates embedding structure to be used as a functor, given a timeseries and some index. Calling

embedding(s, n)

will create the n-th reconstructed vector of the embedded space, which has γ temporal neighbors with delay(s) τ. See reconstruct for more.

Be very careful when choosing n, because @inbounds is used internally.

#DelayEmbeddings.MTDelayEmbeddingType.

MTDelayEmbedding(γ, τ, B) -> `embedding`

Return a delay coordinates embedding structure to be used as a functor, given multiple timeseries (B in total), either as a Dataset or a SizedArray), and some index. Calling

embedding(s, n)

will create the n-th reconstructed vector of the embedded space, which has γ temporal neighbors with delay(s) τ. See reconstruct for more.

Be very careful when choosing n, because @inbounds is used internally.