# Delay Coordinates Embedding

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.reconstruct`

— Function`reconstruct(s, γ, τ [, w])`

Reconstruct `s`

using the delay coordinates embedding with `γ`

temporal neighbors and delay `τ`

and return the result as a `Dataset`

. Optionally use weight `w`

.

Use `embed`

for the version that accepts the embedding dimension `D = γ+1`

instead. Here `τ ≥ 0`

, use `genembed`

for a generalized version.

**Description**

**Single Timeseries**

If `τ`

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

If instead `τ`

is a vector of integers, so that `length(τ) == γ`

, then the $n$-th entry is

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`

!

If `w`

(a "weight") is provided as an extra argument, then the entries of the embedded vector are further weighted with $w^\gamma$, like so

**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`

must be a `Dataset`

.

If the trajectory is for example $(x, y)$ and `τ`

is integer, then the $n$-th entry of the embedded space is

If `τ`

is an `AbstractMatrix{Int}`

, so that `size(τ) == (γ, B)`

, then we have

*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.embed`

— Function`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 `reconstruct`

ing 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)
```

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.315785 0.624665 0.64316 … 0.566011 0.263295 0.614792
0.609112 0.487551 0.285509 0.657766 0.453361 0.15749
0.415614 0.774099 0.0425551 0.420809 0.811994 0.375909
0.303753 0.435943 0.960122 0.689902 0.511303 0.0397719
0.566011 0.263295 0.614792 0.146744 0.678982 0.705166
0.657766 0.453361 0.15749 … 0.891437 0.664544 0.108511
0.420809 0.811994 0.375909 0.754021 0.641237 0.963061
0.689902 0.511303 0.0397719 0.0895821 0.240457 0.545301
0.146744 0.678982 0.705166 0.0168515 0.569302 0.467861
0.891437 0.664544 0.108511 0.467228 0.343429 0.0394357
⋮ ⋱
0.621321 0.439952 0.473898 0.662523 0.88944 0.0435264
0.551652 0.709024 0.998179 0.47478 0.0699994 0.092051
0.517067 0.416638 0.115252 0.187647 0.529061 0.591226
0.0879825 0.00992671 0.842923 0.890515 0.124723 0.615152
0.662523 0.88944 0.0435264 … 0.74956 0.770888 0.789451
0.47478 0.0699994 0.092051 0.545455 0.535903 0.646436
0.187647 0.529061 0.591226 0.505994 0.741273 0.560391
0.890515 0.124723 0.615152 0.640255 0.345553 0.963064
0.74956 0.770888 0.789451 0.618149 0.937721 0.149598
```

```
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.DelayEmbedding`

— Type`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 delay 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.** Use

`τrange`

!`DelayEmbeddings.WeightedDelayEmbedding`

— Type`WeightedDelayEmbedding(γ, τ, w) → `embedding``

Similar with `DelayEmbedding`

, but the entries of the embedded vector are further weighted with `w^γ`

. See `reconstruct`

for more.

`DelayEmbeddings.MTDelayEmbedding`

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

Return a delay coordinates embedding structure to be used as a functor, that embeds multiple timeseries (`B`

in total) given in the form of a `Dataset`

.

Calling

`embedding(s, n)`

where `s`

is a `Dataset`

will create the `n`

-th delay 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.** Use

`τrange`

!`DelayEmbeddings.τrange`

— Function`τrange(s, de::AbstractEmbedding)`

Return the range `r`

of valid indices `n`

to create delay vectors out of `s`

using `de`

.

## Generalized Embeddings

`DelayEmbeddings.genembed`

— Function`genembed(s, τs, js = ones(...)) → dataset`

Create a generalized embedding of `s`

which can be a timeseries or arbitrary `Dataset`

, and return the result as a new `dataset`

.

The generalized embedding works as follows:

`τs`

denotes what delay times will be used for each of the entries of the delay vector. It is recommended that`τs[1] = 0`

.`τs`

is allowed to have*negative entries*as well.`js`

denotes which of the timeseries contained in`s`

will be used for the entries of the delay vector.`js`

can contain duplicate indices.

`τs, js`

are tuples (or vectors) of length `D`

, which also coincides with the embedding dimension. For example, imagine input trajectory $s = [x, y, z]$ where $x, y, z$ are timeseries (the columns of the `Dataset`

). If `js = (1, 3, 2)`

and `τs = (0, 2, -7)`

the created delay vector at each step $n$ will be

`js`

can be skipped, defaulting to index 1 (first timeseries) for all delay entries.

See also `reconstruct`

. Internally uses `GeneralizedEmbedding`

.

`DelayEmbeddings.GeneralizedEmbedding`

— Type`GeneralizedEmbedding(τs [, js]) -> `embedding``

Return a delay coordinates embedding structure to be used as a functor. Given a timeseries *or* trajectory (i.e. `Dataset`

) `s`

and calling

`embedding(s, n)`

will create the delay vector of the `n`

-th point of `s`

in the embedded space using generalized embedding (see `genembed`

).

`js`

is ignored for timeseries input `s`

(since all entries of `js`

must be `1`

in this case) and in addition `js`

defaults to `(1, ..., 1)`

for all `τ`

.

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

`τrange`

!