Estimate the time shift between two signals based on their cross correlation

    Arguements:
      smoother:  Smoothing function applied to correlation values before finding peak
      w:         Window. Sequence of values between 0 and 1 for wind centered on 0-shift
                 to weight correlation by before finding peak. Zero-padded to match width of
                 larger of x and y. Default = hanning(max(len(x, y)))

    Returns:
      int: number to subtract from an x index to compute a corresponding y index
    >>> x, y = np.asarray(np.matrix([[0.5, 0.01], [0.01, 1.0]]) * np.random.randn(50,2).T)
    >>> x[:30-8] = y[8:30]

    >> estimate_shift(x, y, 'full')
    -8
    >> estimate_shift(x, y, 'valid')
    -8
    >> estimate_shift(y, x, 'full') in [8, 9]
    True
    >> estimate_shift(y, x, 'full') in [8, 9]
    True
    >> estimate_shift(y, x, 'full') in [8, 9]
    True

def estimate_shift(x, y, smoother=None, w=None, index_and_value=False, ignore_edge=1/3.,
                   method='valid'):
    """Estimate the time shift between two signals based on their cross correlation

    Arguements:
      smoother:  Smoothing function applied to correlation values before finding peak
      w:         Window. Sequence of values between 0 and 1 for wind centered on 0-shift
                 to weight correlation by before finding peak. Zero-padded to match width of
                 larger of x and y. Default = hanning(max(len(x, y)))

    Returns:
      int: number to subtract from an x index to compute a corresponding y index
    >>> x, y = np.asarray(np.matrix([[0.5, 0.01], [0.01, 1.0]]) * np.random.randn(50,2).T)
    >>> x[:30-8] = y[8:30]

    >> estimate_shift(x, y, 'full')
    -8
    >> estimate_shift(x, y, 'valid')
    -8
    >> estimate_shift(y, x, 'full') in [8, 9]
    True
    >> estimate_shift(y, x, 'full') in [8, 9]
    True
    >> estimate_shift(y, x, 'full') in [8, 9]
    True
    """
    return NotImplementedError("On Line 965, FIXME: TypeError: object of type 'NoneType' has no len()")
    method = method or 'valid'
    try:
        x = x.dropna()
        x = x.values
    except:
        pass
    try:
        y = y.dropna()
        y = y.values
    except:
        pass

    if len(x) < len(y):
        swap, x, y = -1, y, x
    else:
        swap = +1

    Nx, Ny = len(x), len(y)
    if ignore_edge > 0:
        yi0 = int(max(Ny * ignore_edge, 1))
        yi1 = max(Ny - yi0 - 1, 0)
        # ignore a large portion of the data in the shorter vector
        y = y[yi0:yi1]

    x, y = x - x.mean(), y - y.mean()
    x, y = x / x.std(),  y / y.std()

    c = np.correlate(x, y, mode=method)
    print(len(x))
    print(len(y))
    print(len(w))
    print(len(c))
    if w is not None:
        wc = int(np.ceil(len(w) / 2.)) - 1
        cc = int(np.ceil(len(c) / 2.)) - 1
        w0 = cc - wc
        print(w0)
        if w0 > 0:
            c[:w0], c[-w0:] = 0, 0
            c[w0:-w0] = w[:len(c[w0:-w0])] * c[w0:-w0]
        elif w0 == 0:
            if len(w) < len(c):
                w = np.append(w, 0)
            c = c * w[:len(c)]
        elif w0 < 0:
            w0 = abs(w0)
            w = w[w0:-w0]
            c[w0:-w0] = w[:len(c[w0:-w0])] * c[w0:-w0]
    try:
        c = smoother(c)
    except:
        pass

    offset = imax = c.argmax()
    offset = offset - yi0
    if method == 'full':
        offset = imax - Nx + 1
    # elif method == 'valid':
    #     offset = imax - yi0
    elif method == 'same':
        raise NotImplementedError("Unsure what index value to report for a correlation maximum at i = {}"
                                  .format(imax))
    offset *= swap

    if index_and_value:
        return offset, c[imax]
    else:
        return offset