def NQ_transform(R, metadata=None, inverse=False, **kwargs):
    """
    The normal quantile transformation as in Bogner et al (2012).
    Zero rain vales are set to zero in norm space.

    Parameters
    ----------
    R: array-like
        Array of any shape to be transformed.
    metadata: dict, optional
        Metadata dictionary containing the transform, zerovalue and threshold
        attributes as described in the documentation of
        :py:mod:`pysteps.io.importers`.
    inverse: bool, optional
        If set to True, it performs the inverse transform. False by default.

    Other Parameters
    ----------------
    a: float, optional
        The offset fraction to be used for plotting positions;
        typically in (0,1).
        The default is 0., that is, it spaces the points evenly in the uniform
        distribution.

    Returns
    -------
    R: array-like
        Array of any shape containing the (back-)transformed units.
    metadata: dict
        The metadata with updated attributes.

    References
    ----------
    Bogner, K., Pappenberger, F., and Cloke, H. L.: Technical Note: The normal
    quantile transformation and its application in a flood forecasting system,
    Hydrol. Earth Syst. Sci., 16, 1085-1094,
    https://doi.org/10.5194/hess-16-1085-2012, 2012.
    """

    # defaults
    a = kwargs.get("a", 0.0)

    R = R.copy()
    shape0 = R.shape
    R = R.ravel().astype(float)
    idxNan = np.isnan(R)
    R_ = R[~idxNan]

    if metadata is None:
        if inverse:
            metadata = {"transform": "NQT"}
        else:
            metadata = {"transform": None}
        metadata["zerovalue"] = np.min(R_)

    else:
        metadata = metadata.copy()

    if not inverse:
        # Plotting positions
        # https://en.wikipedia.org/wiki/Q%E2%80%93Q_plot#Plotting_position
        n = R_.size
        Rpp = ((np.arange(n) + 1 - a) / (n + 1 - 2 * a)).reshape(R_.shape)

        # NQ transform
        Rqn = scipy_stats.norm.ppf(Rpp)
        R__ = np.interp(R_, R_[np.argsort(R_)], Rqn)

        # set zero rain to 0 in norm space
        R__[R[~idxNan] == metadata["zerovalue"]] = 0

        # build inverse transform
        metadata["inqt"] = interp1d(
            Rqn, R_[np.argsort(R_)], bounds_error=False, fill_value=(R_.min(), R_.max())
        )

        metadata["transform"] = "NQT"
        metadata["zerovalue"] = 0
        metadata["threshold"] = R__[R__ > 0].min()

    else:
        f = metadata.pop("inqt")
        R__ = f(R_)
        metadata["transform"] = None
        metadata["zerovalue"] = R__.min()
        metadata["threshold"] = R__[R__ > R__.min()].min()

    R[~idxNan] = R__

    return R.reshape(shape0), metadata
The normal quantile transformation as in Bogner et al (2012).
Zero rain vales are set to zero in norm space.

Parameters
----------
R: array-like
Array of any shape to be transformed.
metadata: dict, optional
Metadata dictionary containing the transform, zerovalue and threshold
attributes as described in the documentation of
:py:mod:`pysteps.io.importers`.
inverse: bool, optional
If set to True, it performs the inverse transform. False by default.

Other Parameters
----------------
a: float, optional
The offset fraction to be used for plotting positions;
typically in (0,1).
The default is 0., that is, it spaces the points evenly in the uniform
distribution.

Returns
-------
R: array-like
Array of any shape containing the (back-)transformed units.
metadata: dict
The metadata with updated attributes.

References
----------
Bogner, K., Pappenberger, F., and Cloke, H. L.: Technical Note: The normal
quantile transformation and its application in a flood forecasting system,
Hydrol. Earth Syst. Sci., 16, 1085-1094,
https://doi.org/10.5194/hess-16-1085-2012, 2012.
pysteps/utils/transformation.py