Source code for cdtw.dtw

"""
Dynamic Time Warping Python API
-------------------------------

.. autosummary::
    :toctree: toctree

    dtw_dist
    dtw_mat
    dtw_path
"""

import numpy as np

from cdtw.utils import cdtwlib


__all__ = [
    "dtw_dist",
    "dtw_mat",
    "dtw_path"
]


[docs]def dtw_mat(x, y): r""" Computes the full cost (distance) matrix ``D`` between all elements of ``x`` and ``y`` according to .. math:: \boldsymbol{D}_{ij} = d(x_i, y_j) + \min{\lbrace \boldsymbol{D}_{i-1,j-1}, \boldsymbol{D}_{i-1, j}, \boldsymbol{D}_{i, j-1} \rbrace} where :math:`d(x_i, y_j) = (x_i - u_j)^2` is the Euclidean metric. A squared root of the output matrix ``D`` is returned. Parameters ---------- x, y : np.ndarray Input time series, 1-d arrays of arbitrary length. Returns ------- cost_mat : np.ndarray A squared root of the distance matrix ``D``. """ if len(x) == 0 or len(y) == 0: raise ValueError("Got an empty array") x = np.ascontiguousarray(x, dtype=np.float32) y = np.ascontiguousarray(y, dtype=np.float32) nx, ny = len(x), len(y) cost_mat = np.empty((nx + 1) * (ny + 1), dtype=np.float32) cdtwlib.dtw_mat(cost_mat, x, y, nx, ny) cost_mat = cost_mat.reshape((nx + 1, ny + 1)) cost_mat = np.sqrt(cost_mat, out=cost_mat) # the first row & col are inf return cost_mat[1:, 1:]
[docs]def dtw_dist(x, y): """ Computes the DTW distance between ``x`` and ``y`` aligned in time, using dynamic programming. It's equivalent but more efficient to calling ``dtw_mat(x, y)[-1, -1]``. Parameters ---------- x, y : np.ndarray Input time series, 1-d arrays of arbitrary length. Returns ------- dist : float The distance between ``x`` and ``y``. """ if len(x) == 0 or len(y) == 0: raise ValueError("Got an empty array") x = np.ascontiguousarray(x, dtype=np.float32) y = np.ascontiguousarray(y, dtype=np.float32) if len(x) < len(y): # swap the order to allocate less memory x, y = y, x nx, ny = len(x), len(y) dist = cdtwlib.dtw_dist(x, y, nx, ny) return dist
[docs]def dtw_path(cost_mat): """ Finds the best path (an array of x- and y-coordinates) to align ``x`` to ``y``, given the cost matrix ``cost_mat = dtw_mat(x, y)``. Parameters ---------- cost_mat : (N, M) np.ndarray The output of the :func:`dtw_mat` function. Returns ------- path : (L, 2) np.ndarray The path that aligns ``x`` to ``y`` in time. """ nx, ny = cost_mat.shape cost_mat = np.ascontiguousarray(cost_mat.reshape(-1), dtype=np.float32) # the path length is at most 2(n + m) path = np.empty(2 * (nx + ny), dtype=np.int32) path_len = cdtwlib.dtw_path(path, cost_mat, nx, ny) path = path.reshape((-1, 2))[:path_len][::-1] return path
if __name__ == '__main__': from cdtw import dtw_mat, dtw_dist, dtw_path x = [1, 2, 3, 4, 5] y = [2, 3, 4] print(dtw_dist(x, y)) cost = dtw_mat(x, y) print(dtw_path(cost).tolist())