Smooth data series according to a window, weighting based on uncertainties.

    Arguments:

    window
      The smoothing window.
    uncerts
      An array of uncertainties used to weight the smoothing.
    data
      One or more data series, of the same size as *uncerts*.
    k = None
      If specified, only every *k*-th point of the results will be kept. If k
      is None (the default), it is set to ``window.size``, i.e. correlated
      points will be discarded.

    Returns: ``(s_uncerts, s_data[0], s_data[1], ...)``, the smoothed
    uncertainties and data series.

    Example::

        u, x, y = numutil.usmooth (np.hamming (7), u, x, y)

def usmooth (window, uncerts, *data, **kwargs):
    """Smooth data series according to a window, weighting based on uncertainties.

    Arguments:

    window
      The smoothing window.
    uncerts
      An array of uncertainties used to weight the smoothing.
    data
      One or more data series, of the same size as *uncerts*.
    k = None
      If specified, only every *k*-th point of the results will be kept. If k
      is None (the default), it is set to ``window.size``, i.e. correlated
      points will be discarded.

    Returns: ``(s_uncerts, s_data[0], s_data[1], ...)``, the smoothed
    uncertainties and data series.

    Example::

        u, x, y = numutil.usmooth (np.hamming (7), u, x, y)

    """
    window = np.asarray (window)
    uncerts = np.asarray (uncerts)

    # Hacky keyword argument handling because you can't write "def foo (*args,
    # k=0)".

    k = kwargs.pop ('k', None)

    if len (kwargs):
        raise TypeError ("smooth() got an unexpected keyword argument '%s'"
                         % kwargs.keys ()[0])

    # Done with kwargs futzing.

    if k is None:
        k = window.size

    conv = lambda q, r: np.convolve (q, r, mode='valid')

    if uncerts is None:
        w = np.ones_like (x)
    else:
        w = uncerts ** -2

    cw = conv (w, window)
    cu = np.sqrt (conv (w, window**2)) / cw
    result = [cu] + [conv (w * np.asarray (x), window) / cw for x in data]

    if k != 1:
        result = [x[::k] for x in result]
    return result