Note
Go to the end to download the full example code.
Canonical Time Warping#
This example illustrates the use of Canonical Time Warping (CTW) between time series and plots the matches obtained by the method [1].
Note that, contrary to Dynamic Time Warping (DTW) [2], CTW can almost retrieve the ground-truth alignment (green matches) even when time series have suffered a rigid transformation (rotation+translation here).
The time series at stake in this example are color-coded trajectories whose starting (resp. end) point are depicted in blue (resp. red).
# Author: Romain Tavenard
# License: BSD 3 clause
import matplotlib.pyplot as plt
import numpy as np
from tslearn.metrics import dtw_path, ctw_path
def plot_trajectory(ts, ax, color_code=None, alpha=1.):
if color_code is not None:
colors = [color_code] * len(ts)
else:
colors = plt.cm.jet(np.linspace(0, 1, len(ts)))
for i in range(len(ts) - 1):
ax.plot(ts[i:i+2, 0], ts[i:i+2, 1],
marker='o', c=colors[i], alpha=alpha)
def get_rot2d(theta):
return np.array(
[[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]]
)
def make_one_folium(sz, a=1., noise=.1, resample_fun=None):
theta = np.linspace(0, 1, sz)
if resample_fun is not None:
theta = resample_fun(theta)
theta -= .5
theta *= .9 * np.pi
theta = theta.reshape((-1, 1))
r = a / 2 * (4 * np.cos(theta) - 1. / np.cos(theta))
x = r * np.cos(theta) + np.random.rand(sz, 1) * noise
y = r * np.sin(theta) + np.random.rand(sz, 1) * noise
return np.array(np.hstack((x, y)))
trajectory = make_one_folium(sz=30).dot(get_rot2d(np.pi + np.pi / 3))
rotated_trajectory = trajectory.dot(get_rot2d(np.pi / 4)) + np.array([0., 3.])
path_dtw, _ = dtw_path(trajectory, rotated_trajectory)
path_ctw, cca, _ = ctw_path(trajectory, rotated_trajectory,
max_iter=100, n_components=2)
plt.figure(figsize=(8, 4))
ax = plt.subplot(1, 2, 1)
for (i, j) in path_dtw:
ax.plot([trajectory[i, 0], rotated_trajectory[j, 0]],
[trajectory[i, 1], rotated_trajectory[j, 1]],
color='g' if i == j else 'r', alpha=.5)
plot_trajectory(trajectory, ax)
plot_trajectory(rotated_trajectory, ax)
ax.set_xticks([])
ax.set_yticks([])
ax.set_title("DTW")
ax = plt.subplot(1, 2, 2)
for (i, j) in path_ctw:
ax.plot([trajectory[i, 0], rotated_trajectory[j, 0]],
[trajectory[i, 1], rotated_trajectory[j, 1]],
color='g' if i == j else 'r', alpha=.5)
plot_trajectory(trajectory, ax)
plot_trajectory(rotated_trajectory, ax)
ax.set_xticks([])
ax.set_yticks([])
ax.set_title("CTW")
plt.tight_layout()
plt.show()
Total running time of the script: (0 minutes 6.771 seconds)