pythonrpy2dtw

rpy2 Dynamic Time Warping (dtw) in python - windowing does not work


A now closed discussion shows how to use the R dtw package in python. This is a little clumsy, but the R dtw package is great and better than currently available python dtw implementations. Unfortunately, the windowing functions like the Sakoe-Chiba band do not work when trying to specify a "window.size". There appears to be an issue with the mapping to the argument. Note that "." in arguments is supposed to be replaced with "_" when using rpy2. But following this convention, the argument is not being used for some reason.

import numpy as np

import rpy2.robjects.numpy2ri
from rpy2.robjects.packages import importr
rpy2.robjects.numpy2ri.activate()

# Set up our R namespaces
R = rpy2.robjects.r
DTW = importr('dtw')

# Generate our data
idx = np.linspace(0, 2*np.pi, 100)
template = np.cos(idx)
query = np.sin(idx) + np.array(R.runif(100))/10

# Calculate the alignment vector and corresponding distance
alignment = R.dtw(query, template, keep=True,window_type='sakoechiba',
                     window_size=5)

>>> RRuntimeError: Error in window.function(row(wm), col(wm), query.size= n, reference.size = m,  : 
 argument "window.size" is missing, with no default

You can see that the error states "window.size" is missing, despite "window_size" clearly being specified in the rpy2 fashion.


Solution

  • Answering my own question in case anyone ever has the same issue. The problem is the argument mapping and the R three dots ellipsis ‘...’. This can be fixed by specifying the mapping manually.

    from rpy2.robjects.functions import SignatureTranslatedFunction
    
    R.dtw = SignatureTranslatedFunction(R.dtw,
                            init_prm_translate={'window_size': 'window.size'})
    

    So with this specification the window_size argument is used correctly.

    import numpy as np
    
    import rpy2.robjects.numpy2ri
    from rpy2.robjects.packages import importr
    from rpy2.robjects.functions import SignatureTranslatedFunction
    rpy2.robjects.numpy2ri.activate()
    
    # Set up our R namespaces
    R = rpy2.robjects.r
    DTW = importr('dtw')
    R.dtw = SignatureTranslatedFunction(R.dtw,
                          init_prm_translate={'window_size': 'window.size'})
    
    # Generate our data
    idx = np.linspace(0, 2*np.pi, 100)
    template = np.cos(idx)
    query = np.sin(idx) + np.array(R.runif(100))/10
    
    # Calculate the alignment vector and corresponding distance
    alignment = R.dtw(query, template, keep=True,window_type='sakoechiba',
                         window_size=10)
    dist = alignment.rx('distance')[0][0]
    
    print(dist)
    >>> 117.348292359