def iterative_savgol_filter(y, winlen=5, order=3, maxiter=10, upper_clip=None, lower_clip=None):
    'Smooth the input array with Savitzky-Golay filter with lower and/or\n    upper clippings.\n\n    Args:\n        y (:class:`numpy.ndarray`): Input array.\n        winlen (int): Window length of Savitzky-Golay filter.\n        order (int): Order of Savitzky-Gaoly filter.\n        maxiter (int): Maximum number of iterations.\n        lower_clip (float): Lower sigma-clipping value.\n        upper_clip (float): Upper sigma-clipping value.\n\n    Returns:\n        tuple: A tuple containing:\n\n            * **ysmooth** (:class:`numpy.ndarray`) – Smoothed y values.\n            * **yres** (:class:`numpy.ndarray`) – Residuals of y values.\n            * **mask** (:class:`numpy.ndarray`) – Mask of y values.\n            * **std** (float) – Standard deviation.\n    '
    x = np.arange(y.size)
    mask = np.ones_like(y, dtype=np.bool)
    for ite in range(maxiter):
        f = intp.InterpolatedUnivariateSpline(x[mask], y[mask], k=3)
        ysmooth = savgol_filter(f(x), window_length=winlen, polyorder=order)
        yres = (y - ysmooth)
        std = yres[mask].std()
        new_mask = (mask * np.ones_like(mask, dtype=np.bool))
        if (lower_clip is not None):
            new_mask *= (yres > ((- lower_clip) * std))
        if (upper_clip is not None):
            new_mask *= (yres < (upper_clip * std))
        if (new_mask.sum() == mask.sum()):
            break
        mask = new_mask
    return (ysmooth, yres, mask, std)
Smooth the input array with Savitzky-Golay filter with lower and/or
upper clippings.

Args:
    y (:class:`numpy.ndarray`): Input array.
    winlen (int): Window length of Savitzky-Golay filter.
    order (int): Order of Savitzky-Gaoly filter.
    maxiter (int): Maximum number of iterations.
    lower_clip (float): Lower sigma-clipping value.
    upper_clip (float): Upper sigma-clipping value.

Returns:
    tuple: A tuple containing:

        * **ysmooth** (:class:`numpy.ndarray`) – Smoothed y values.
        * **yres** (:class:`numpy.ndarray`) – Residuals of y values.
        * **mask** (:class:`numpy.ndarray`) – Mask of y values.
        * **std** (float) – Standard deviation.
def iterative_savgol_filter(y, winlen=5, order=3, maxiter=10, upper_clip=None, lower_clip=None):
    'Smooth the input array with Savitzky-Golay filter with lower and/or\n    upper clippings.\n\n    Args:\n        y (:class:`numpy.ndarray`): Input array.\n        winlen (int): Window length of Savitzky-Golay filter.\n        order (int): Order of Savitzky-Gaoly filter.\n        maxiter (int): Maximum number of iterations.\n        lower_clip (float): Lower sigma-clipping value.\n        upper_clip (float): Upper sigma-clipping value.\n\n    Returns:\n        tuple: A tuple containing:\n\n            * **ysmooth** (:class:`numpy.ndarray`) – Smoothed y values.\n            * **yres** (:class:`numpy.ndarray`) – Residuals of y values.\n            * **mask** (:class:`numpy.ndarray`) – Mask of y values.\n            * **std** (float) – Standard deviation.\n    '
    x = np.arange(y.size)
    mask = np.ones_like(y, dtype=np.bool)
    for ite in range(maxiter):
        f = intp.InterpolatedUnivariateSpline(x[mask], y[mask], k=3)
        ysmooth = savgol_filter(f(x), window_length=winlen, polyorder=order)
        yres = (y - ysmooth)
        std = yres[mask].std()
        new_mask = (mask * np.ones_like(mask, dtype=np.bool))
        if (lower_clip is not None):
            new_mask *= (yres > ((- lower_clip) * std))
        if (upper_clip is not None):
            new_mask *= (yres < (upper_clip * std))
        if (new_mask.sum() == mask.sum()):
            break
        mask = new_mask
    return (ysmooth, yres, mask, std)