def _build_2D_tapering_function(win_size, win_type="flat-hanning"):
    """
    Produces two-dimensional tapering function for rectangular fields.

    Parameters
    ----------
    win_size: tuple of int
        Size of the tapering window as two-element tuple of integers.
    win_type: str
        Name of the tapering window type (hanning, flat-hanning)

    Returns
    -------
    w2d: array-like
        A two-dimensional numpy array containing the 2D tapering function.
    """

    if len(win_size) != 2:
        raise ValueError("win_size is not a two-element tuple")

    if win_type == "hanning":
        w1dr = np.hanning(win_size[0])
        w1dc = np.hanning(win_size[1])

    elif win_type == "flat-hanning":
        T = win_size[0] / 4.0
        W = win_size[0] / 2.0
        B = np.linspace(-W, W, int(2 * W))
        R = np.abs(B) - T
        R[R < 0] = 0.0
        A = 0.5 * (1.0 + np.cos(np.pi * R / T))
        A[np.abs(B) > (2 * T)] = 0.0
        w1dr = A

        T = win_size[1] / 4.0
        W = win_size[1] / 2.0
        B = np.linspace(-W, W, int(2 * W))
        R = np.abs(B) - T
        R[R < 0] = 0.0
        A = 0.5 * (1.0 + np.cos(np.pi * R / T))
        A[np.abs(B) > (2 * T)] = 0.0
        w1dc = A

    elif win_type == "rectangular":
        w1dr = np.ones(win_size[0])
        w1dc = np.ones(win_size[1])

    else:
        raise ValueError("unknown win_type %s" % win_type)

    # Expand to 2-D
    # w2d = np.sqrt(np.outer(w1dr,w1dc))
    w2d = np.outer(w1dr, w1dc)

    # Set nans to zero
    if np.any(np.isnan(w2d)):
        w2d[np.isnan(w2d)] = np.min(w2d[w2d > 0])

    w2d[w2d < 1e-3] = 1e-3

    return w2d
Produces two-dimensional tapering function for rectangular fields.

Parameters
----------
win_size: tuple of int
Size of the tapering window as two-element tuple of integers.
win_type: str
Name of the tapering window type (hanning, flat-hanning)

Returns
-------
w2d: array-like
A two-dimensional numpy array containing the 2D tapering function.
pysteps/nowcasts/sseps.py