-
Notifications
You must be signed in to change notification settings - Fork 228
load_tile_map: Add the new parameter 'crs' to set the CRS of the returned dataarray #3554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3304104
cfb69d2
00e2605
3265240
7660e2c
421c167
8346af7
4ed799c
6733e19
c1d55b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,25 +3,29 @@ | |
:class:`xarray.DataArray`. | ||
""" | ||
|
||
import contextlib | ||
from collections.abc import Sequence | ||
from typing import Literal | ||
|
||
from packaging.version import Version | ||
|
||
try: | ||
import contextily | ||
from rasterio.crs import CRS | ||
from xyzservices import TileProvider | ||
|
||
_HAS_CONTEXTILY = True | ||
except ImportError: | ||
CRS = None | ||
Comment on lines
+13
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe put the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rasterio is also a dependency of |
||
TileProvider = None | ||
_HAS_CONTEXTILY = False | ||
|
||
with contextlib.suppress(ImportError): | ||
# rioxarray is needed to register the rio accessor | ||
try: | ||
import rioxarray # noqa: F401 | ||
|
||
_HAS_RIOXARRAY = True | ||
except ImportError: | ||
_HAS_RIOXARRAY = False | ||
|
||
import numpy as np | ||
import xarray as xr | ||
|
||
|
@@ -33,6 +37,7 @@ | |
zoom: int | Literal["auto"] = "auto", | ||
source: TileProvider | str | None = None, | ||
lonlat: bool = True, | ||
crs: str | CRS = "EPSG:3857", | ||
wait: int = 0, | ||
max_retries: int = 2, | ||
zoom_adjust: int | None = None, | ||
|
@@ -42,7 +47,8 @@ | |
|
||
The tiles that compose the map are merged and georeferenced into an | ||
:class:`xarray.DataArray` image with 3 bands (RGB). Note that the returned image is | ||
in a Spherical Mercator (EPSG:3857) coordinate reference system. | ||
in a Spherical Mercator (EPSG:3857) coordinate reference system (CRS) by default, | ||
but can be customized using the ``crs`` parameter. | ||
|
||
Parameters | ||
---------- | ||
|
@@ -80,6 +86,10 @@ | |
lonlat | ||
If ``False``, coordinates in ``region`` are assumed to be Spherical Mercator as | ||
opposed to longitude/latitude. | ||
crs | ||
Coordinate reference system (CRS) of the returned :class:`xarray.DataArray` | ||
image. Default is ``"EPSG:3857"`` (i.e., Spherical Mercator). The CRS can be in | ||
either string or :class:`rasterio.crs.CRS` format. | ||
wait | ||
If the tile API is rate-limited, the number of seconds to wait between a failed | ||
request and the next try. | ||
|
@@ -128,6 +138,10 @@ | |
... raster.rio.crs.to_string() | ||
'EPSG:3857' | ||
""" | ||
# The CRS of the source tile provider. If the source is a TileProvider object, use | ||
# its crs attribute if available. Otherwise, default to EPSG:3857. | ||
_source_crs = getattr(source, "crs", "EPSG:3857") | ||
|
||
if not _HAS_CONTEXTILY: | ||
msg = ( | ||
"Package `contextily` is required to be installed to use this function. " | ||
|
@@ -136,28 +150,34 @@ | |
) | ||
raise ImportError(msg) | ||
|
||
contextily_kwargs = {} | ||
if crs != _source_crs and not _HAS_RIOXARRAY: | ||
msg = ( | ||
f"Package `rioxarray` is required if CRS is not '{_source_crs}'. " | ||
"Please use `python -m pip install rioxarray` or " | ||
"`mamba install -c conda-forge rioxarray` to install the package." | ||
) | ||
raise ImportError(msg) | ||
|
||
# Keyword arguments for contextily.bounds2img | ||
contextily_kwargs = { | ||
"zoom": zoom, | ||
"source": source, | ||
"ll": lonlat, | ||
"wait": wait, | ||
"max_retries": max_retries, | ||
} | ||
if zoom_adjust is not None: | ||
contextily_kwargs["zoom_adjust"] = zoom_adjust | ||
if Version(contextily.__version__) < Version("1.5.0"): | ||
msg = ( | ||
"The `zoom_adjust` parameter requires `contextily>=1.5.0` to work. " | ||
"Please upgrade contextily, or manually set the `zoom` level instead." | ||
) | ||
raise TypeError(msg) | ||
raise ValueError(msg) | ||
contextily_kwargs["zoom_adjust"] = zoom_adjust | ||
|
||
west, east, south, north = region | ||
image, extent = contextily.bounds2img( | ||
w=west, | ||
s=south, | ||
e=east, | ||
n=north, | ||
zoom=zoom, | ||
source=source, | ||
ll=lonlat, | ||
wait=wait, | ||
max_retries=max_retries, | ||
**contextily_kwargs, | ||
w=west, s=south, e=east, n=north, **contextily_kwargs | ||
) | ||
|
||
# Turn RGBA img from channel-last to channel-first and get 3-band RGB only | ||
|
@@ -176,8 +196,12 @@ | |
dims=("band", "y", "x"), | ||
) | ||
|
||
# If rioxarray is installed, set the coordinate reference system | ||
# If rioxarray is installed, set the coordinate reference system. | ||
seisman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if hasattr(dataarray, "rio"): | ||
dataarray = dataarray.rio.write_crs(input_crs="EPSG:3857") | ||
dataarray = dataarray.rio.write_crs(input_crs=_source_crs) | ||
|
||
# Reproject raster image from the source CRS to the specified CRS. | ||
if crs != _source_crs: | ||
dataarray = dataarray.rio.reproject(dst_crs=crs) | ||
|
||
return dataarray |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,13 +9,9 @@ | |
from pygmt.helpers import build_arg_list, fmt_docstring, kwargs_to_strings, use_alias | ||
|
||
try: | ||
import rioxarray # noqa: F401 | ||
from xyzservices import TileProvider | ||
|
||
_HAS_RIOXARRAY = True | ||
except ImportError: | ||
TileProvider = None | ||
_HAS_RIOXARRAY = False | ||
|
||
|
||
@fmt_docstring | ||
|
@@ -111,39 +107,21 @@ def tilemap( | |
|
||
kwargs : dict | ||
Extra keyword arguments to pass to :meth:`pygmt.Figure.grdimage`. | ||
|
||
Raises | ||
------ | ||
ImportError | ||
If ``rioxarray`` is not installed. Follow | ||
:doc:`install instructions for rioxarray <rioxarray:installation>`, (e.g. via | ||
``python -m pip install rioxarray``) before using this function. | ||
""" | ||
kwargs = self._preprocess(**kwargs) | ||
|
||
if not _HAS_RIOXARRAY: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
msg = ( | ||
"Package `rioxarray` is required to be installed to use this function. " | ||
"Please use `python -m pip install rioxarray` or " | ||
"`mamba install -c conda-forge rioxarray` to install the package." | ||
) | ||
raise ImportError(msg) | ||
|
||
raster = load_tile_map( | ||
region=region, | ||
zoom=zoom, | ||
source=source, | ||
lonlat=lonlat, | ||
crs="OGC:CRS84" if lonlat is True else "EPSG:3857", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
wait=wait, | ||
max_retries=max_retries, | ||
zoom_adjust=zoom_adjust, | ||
) | ||
|
||
# Reproject raster from Spherical Mercator (EPSG:3857) to lonlat (OGC:CRS84) if | ||
# bounding box region was provided in lonlat | ||
if lonlat and raster.rio.crs == "EPSG:3857": | ||
raster = raster.rio.reproject(dst_crs="OGC:CRS84") | ||
raster.gmt.gtype = 1 # set to geographic type | ||
if lonlat: | ||
raster.gmt.gtype = 1 # Set to geographic type | ||
|
||
# Only set region if no_clip is None or False, so that plot is clipped to exact | ||
# bounding box region | ||
|
Uh oh!
There was an error while loading. Please reload this page.