def generate_noise_2d_fft_filter(
    F, randstate=None, seed=None, fft_method=None, domain="spatial"
):
    """
    Produces a field of correlated noise using global Fourier filtering.

    Parameters
    ----------
    F: dict
        A filter object returned by
        :py:func:`pysteps.noise.fftgenerators.initialize_param_2d_fft_filter` or
        :py:func:`pysteps.noise.fftgenerators.initialize_nonparam_2d_fft_filter`.
        All values in the filter array are required to be finite.
    randstate: mtrand.RandomState
        Optional random generator to use. If set to None, use numpy.random.
    seed: int
        Value to set a seed for the generator. None will not set the seed.
    fft_method: str or tuple
        A string or a (function,kwargs) tuple defining the FFT method to use
        (see "FFT methods" in :py:func:`pysteps.utils.interface.get_method`).
        Defaults to "numpy".
    domain: {"spatial", "spectral"}
        The domain for the computations: If "spatial", the noise is generated
        in the spatial domain and transformed back to spatial domain after the
        Fourier filtering. If "spectral", the noise field is generated and kept
        in the spectral domain.

    Returns
    -------
    N: array-like
        A two-dimensional field of stationary correlated noise. The noise field
        is normalized to zero mean and unit variance.

    """
    if domain not in ["spatial", "spectral"]:
        raise ValueError(
            "invalid value %s for the 'domain' argument: must be 'spatial' or 'spectral'"
            % str(domain)
        )

    input_shape = F["input_shape"]
    use_full_fft = F["use_full_fft"]
    F = F["field"]

    if len(F.shape) != 2:
        raise ValueError("field is not two-dimensional array")
    if np.any(~np.isfinite(F)):
        raise ValueError(
            "field contains non-finite values, this typically happens when the input\n"
            + "precipitation field provided to pysteps contains (mostly)zero values.\n"
            + "To prevent this error please call pysteps.utils.check_norain first,\n"
            + "using the same win_fun as used in this method (tukey by default)\n"
            + "and then only call this method if that check fails."
        )

    if randstate is None:
        randstate = np.random

    # set the seed
    if seed is not None:
        randstate.seed(seed)

    if fft_method is None:
        fft = utils.get_method("numpy", shape=input_shape)
    else:
        if type(fft_method) == str:
            fft = utils.get_method(fft_method, shape=input_shape)
        else:
            fft = fft_method

    # produce fields of white noise
    if domain == "spatial":
        N = randstate.randn(input_shape[0], input_shape[1])
    else:
        if use_full_fft:
            size = (input_shape[0], input_shape[1])
        else:
            size = (input_shape[0], int(input_shape[1] / 2) + 1)
        theta = randstate.uniform(low=0.0, high=2.0 * np.pi, size=size)
        if input_shape[0] % 2 == 0:
            theta[int(input_shape[0] / 2) + 1 :, 0] = -theta[
                1 : int(input_shape[0] / 2), 0
            ][::-1]
        else:
            theta[int(input_shape[0] / 2) + 1 :, 0] = -theta[
                1 : int(input_shape[0] / 2) + 1, 0
            ][::-1]
        N = np.cos(theta) + 1.0j * np.sin(theta)

    # apply the global Fourier filter to impose a correlation structure
    if domain == "spatial":
        if use_full_fft:
            fN = fft.fft2(N)
        else:
            fN = fft.rfft2(N)
    else:
        fN = N
    fN *= F
    if domain == "spatial":
        if use_full_fft:
            N = np.array(fft.ifft2(fN).real)
        else:
            N = np.array(fft.irfft2(fN))
        N = (N - N.mean()) / N.std()
    else:
        N = fN
        N[0, 0] = 0.0
        N /= utils.spectral.std(N, input_shape, use_full_fft=use_full_fft)

    return N
Produces a field of correlated noise using global Fourier filtering.

Parameters
----------
F: dict
A filter object returned by
:py:func:`pysteps.noise.fftgenerators.initialize_param_2d_fft_filter` or
:py:func:`pysteps.noise.fftgenerators.initialize_nonparam_2d_fft_filter`.
All values in the filter array are required to be finite.
randstate: mtrand.RandomState
Optional random generator to use. If set to None, use numpy.random.
seed: int
Value to set a seed for the generator. None will not set the seed.
fft_method: str or tuple
A string or a (function,kwargs) tuple defining the FFT method to use
(see "FFT methods" in :py:func:`pysteps.utils.interface.get_method`).
Defaults to "numpy".
domain: {"spatial", "spectral"}
The domain for the computations: If "spatial", the noise is generated
in the spatial domain and transformed back to spatial domain after the
Fourier filtering. If "spectral", the noise field is generated and kept
in the spectral domain.

Returns
-------
N: array-like
A two-dimensional field of stationary correlated noise. The noise field
is normalized to zero mean and unit variance.
pysteps/noise/fftgenerators.py