def reproject_geodata(geodata, t_proj4str, return_grid=None):
    """
    Reproject geodata and optionally create a grid in a new projection.

    Parameters
    ----------
    geodata: dictionary
        Dictionary containing geographical information about the field.
        It must contain the attributes projection, x1, x2, y1, y2, xpixelsize,
        ypixelsize, as defined in the documentation of pysteps.io.importers.
    t_proj4str: str
        The target PROJ.4-compatible projection string (fallback).
    return_grid: {None, 'coords', 'quadmesh'}, optional
        Whether to return the coordinates of the projected grid.
        The default return_grid=None does not compute the grid,
        return_grid='coords' returns the centers of projected grid points,
        return_grid='quadmesh' returns the coordinates of the quadrilaterals
        (e.g. to be used by pcolormesh).

    Returns
    -------
    geodata: dictionary
        Dictionary containing the reprojected geographical information
        and optionally the required X_grid and Y_grid.

        It also includes a fixed boolean attribute regular_grid=False to indicate
        that the reprojected grid has no regular spacing.
    """
    if not PYPROJ_IMPORTED:
        raise MissingOptionalDependency(
            "pyproj package is required for reproject_geodata function utility"
            " but it is not installed"
        )

    geodata = geodata.copy()
    s_proj4str = geodata["projection"]
    extent = (geodata["x1"], geodata["x2"], geodata["y1"], geodata["y2"])
    shape = (
        int((geodata["y2"] - geodata["y1"]) / geodata["ypixelsize"]),
        int((geodata["x2"] - geodata["x1"]) / geodata["xpixelsize"]),
    )

    s_srs = pyproj.Proj(s_proj4str)
    t_srs = pyproj.Proj(t_proj4str)

    x1 = extent[0]
    x2 = extent[1]
    y1 = extent[2]
    y2 = extent[3]

    # Reproject grid on fall-back projection
    if return_grid is not None:
        if return_grid == "coords":
            y_coord = (
                np.linspace(y1, y2, shape[0], endpoint=False)
                + geodata["ypixelsize"] / 2.0
            )
            x_coord = (
                np.linspace(x1, x2, shape[1], endpoint=False)
                + geodata["xpixelsize"] / 2.0
            )
        elif return_grid == "quadmesh":
            y_coord = np.linspace(y1, y2, shape[0] + 1)
            x_coord = np.linspace(x1, x2, shape[1] + 1)
        else:
            raise ValueError("unknown return_grid value %s" % return_grid)

        x_grid, y_grid = np.meshgrid(x_coord, y_coord)

        x_grid, y_grid = pyproj.transform(
            s_srs, t_srs, x_grid.flatten(), y_grid.flatten()
        )
        x_grid = x_grid.reshape((y_coord.size, x_coord.size))
        y_grid = y_grid.reshape((y_coord.size, x_coord.size))
        geodata["X_grid"] = x_grid
        geodata["Y_grid"] = y_grid

    # Reproject extent on fall-back projection
    x1, y1 = pyproj.transform(s_srs, t_srs, x1, y1)
    x2, y2 = pyproj.transform(s_srs, t_srs, x2, y2)

    # update geodata
    geodata["projection"] = t_proj4str
    geodata["x1"] = x1
    geodata["x2"] = x2
    geodata["y1"] = y1
    geodata["y2"] = y2
    geodata["regular_grid"] = False
    geodata["xpixelsize"] = None
    geodata["ypixelsize"] = None

    return geodata
Reproject geodata and optionally create a grid in a new projection.

Parameters
----------
geodata: dictionary
Dictionary containing geographical information about the field.
It must contain the attributes projection, x1, x2, y1, y2, xpixelsize,
ypixelsize, as defined in the documentation of pysteps.io.importers.
t_proj4str: str
The target PROJ.4-compatible projection string (fallback).
return_grid: {None, 'coords', 'quadmesh'}, optional
Whether to return the coordinates of the projected grid.
The default return_grid=None does not compute the grid,
return_grid='coords' returns the centers of projected grid points,
return_grid='quadmesh' returns the coordinates of the quadrilaterals
(e.g. to be used by pcolormesh).

Returns
-------
geodata: dictionary
Dictionary containing the reprojected geographical information
and optionally the required X_grid and Y_grid.

It also includes a fixed boolean attribute regular_grid=False to indicate
that the reprojected grid has no regular spacing.
pysteps/visualization/utils.py