diff --git a/pygmt/datasets/load_remote_dataset.py b/pygmt/datasets/load_remote_dataset.py index 72668a7a467..67f3f73842d 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -3,32 +3,35 @@ """ from __future__ import annotations -from typing import NamedTuple +from typing import TYPE_CHECKING, ClassVar, NamedTuple from pygmt.exceptions import GMTInvalidInput from pygmt.helpers import kwargs_to_strings from pygmt.io import load_dataarray from pygmt.src import grdcut, which +if TYPE_CHECKING: + import xarray as xr + class Resolution(NamedTuple): """ - The available grid registrations for a given resolution and whether it is a tiled - grid. + Resolution code, the available grid registrations and whether it is tiled. Attributes ---------- + code : str + The resolution code. E.g., "01d", "30m", "01s". registrations : list - A list of the accepted registrations for a given resolution. - Can be either "pixel" or "gridline". - + A list of the accepted registrations for a given resolution. Can be either + "pixel" or "gridline". tiled : bool - States if the given resolution is tiled, which requires an - argument for ``region``. + States if the grid is tiled, which requires an argument for ``region``. """ - registrations: list - tiled: bool + code: str + registrations: ClassVar[list] = ["gridline", "pixel"] + tiled: bool = False class GMTRemoteDataset(NamedTuple): @@ -39,20 +42,14 @@ class GMTRemoteDataset(NamedTuple): ---------- title : str The title of the dataset, used in error messages. - name : str The name assigned as an attribute to the DataArray. - long_name : str The long name assigned as an attribute to the DataArray. - units : str The units of the values in the DataArray. - resolutions : dict - Dictionary of available resolution as keys and the values are - Resolution objects. - + Dictionary of available resolution as keys and Resolution objects as values. extra_attributes : dict A dictionary of extra or unique attributes of the dataset. """ @@ -73,17 +70,17 @@ class GMTRemoteDataset(NamedTuple): units="Myr", extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline", "pixel"], True), - "02m": Resolution(["gridline", "pixel"], True), - "01m": Resolution(["gridline"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", tiled=True), + "02m": Resolution("02m", tiled=True), + "01m": Resolution("01m", registrations=["gridline"], tiled=True), }, ), "earth_free_air_anomaly": GMTRemoteDataset( @@ -93,17 +90,17 @@ class GMTRemoteDataset(NamedTuple): units="mGal", extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline", "pixel"], True), - "02m": Resolution(["gridline", "pixel"], True), - "01m": Resolution(["pixel"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", tiled=True), + "02m": Resolution("02m", tiled=True), + "01m": Resolution("01m", registrations=["pixel"], tiled=True), }, ), "earth_geoid": GMTRemoteDataset( @@ -113,17 +110,17 @@ class GMTRemoteDataset(NamedTuple): units="m", extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline", "pixel"], True), - "02m": Resolution(["gridline", "pixel"], True), - "01m": Resolution(["gridline"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", tiled=True), + "02m": Resolution("02m", tiled=True), + "01m": Resolution("01m", registrations=["gridline"], tiled=True), }, ), "earth_magnetic_anomaly": GMTRemoteDataset( @@ -133,16 +130,16 @@ class GMTRemoteDataset(NamedTuple): units="nT", extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline", "pixel"], True), - "02m": Resolution(["pixel"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", tiled=True), + "02m": Resolution("02m", registrations=["pixel"], tiled=True), }, ), "earth_mask": GMTRemoteDataset( @@ -152,19 +149,19 @@ class GMTRemoteDataset(NamedTuple): units=None, extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], False), - "04m": Resolution(["gridline", "pixel"], False), - "03m": Resolution(["gridline", "pixel"], False), - "02m": Resolution(["gridline", "pixel"], False), - "01m": Resolution(["gridline", "pixel"], False), - "30s": Resolution(["gridline", "pixel"], False), - "15s": Resolution(["gridline", "pixel"], False), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m"), + "04m": Resolution("04m"), + "03m": Resolution("03m"), + "02m": Resolution("02m"), + "01m": Resolution("01m"), + "30s": Resolution("30s"), + "15s": Resolution("15s"), }, ), "earth_relief": GMTRemoteDataset( @@ -174,21 +171,21 @@ class GMTRemoteDataset(NamedTuple): units="meters", extra_attributes={"vertical_datum": "EGM96", "horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline", "pixel"], True), - "02m": Resolution(["gridline", "pixel"], True), - "01m": Resolution(["gridline", "pixel"], True), - "30s": Resolution(["gridline", "pixel"], True), - "15s": Resolution(["pixel"], True), - "03s": Resolution(["gridline"], True), - "01s": Resolution(["gridline"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", tiled=True), + "02m": Resolution("02m", tiled=True), + "01m": Resolution("01m", tiled=True), + "30s": Resolution("30s", tiled=True), + "15s": Resolution("15s", registrations=["pixel"], tiled=True), + "03s": Resolution("03s", registrations=["gridline"], tiled=True), + "01s": Resolution("01s", registrations=["gridline"], tiled=True), }, ), "earth_vgg": GMTRemoteDataset( @@ -198,17 +195,17 @@ class GMTRemoteDataset(NamedTuple): units="Eotvos", extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline", "pixel"], True), - "02m": Resolution(["gridline", "pixel"], True), - "01m": Resolution(["pixel"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", tiled=True), + "02m": Resolution("02m", tiled=True), + "01m": Resolution("01m", registrations=["pixel"], tiled=True), }, ), "earth_wdmam": GMTRemoteDataset( @@ -218,15 +215,15 @@ class GMTRemoteDataset(NamedTuple): units="nT", extra_attributes={"horizontal_datum": "WGS84"}, resolutions={ - "01d": Resolution(["gridline", "pixel"], False), - "30m": Resolution(["gridline", "pixel"], False), - "20m": Resolution(["gridline", "pixel"], False), - "15m": Resolution(["gridline", "pixel"], False), - "10m": Resolution(["gridline", "pixel"], False), - "06m": Resolution(["gridline", "pixel"], False), - "05m": Resolution(["gridline", "pixel"], True), - "04m": Resolution(["gridline", "pixel"], True), - "03m": Resolution(["gridline"], True), + "01d": Resolution("01d"), + "30m": Resolution("30m"), + "20m": Resolution("20m"), + "15m": Resolution("15m"), + "10m": Resolution("10m"), + "06m": Resolution("06m"), + "05m": Resolution("05m", tiled=True), + "04m": Resolution("04m", tiled=True), + "03m": Resolution("03m", registrations=["gridline"], tiled=True), }, ), } @@ -234,33 +231,33 @@ class GMTRemoteDataset(NamedTuple): @kwargs_to_strings(region="sequence") def _load_remote_dataset( - dataset_name, dataset_prefix, resolution, region, registration -): + dataset_name: str, + dataset_prefix: str, + resolution: str, + region: str | list, + registration: str, +) -> xr.DataArray: r""" Load GMT remote datasets. Parameters ---------- - dataset_name : str + dataset_name The name for the dataset in the 'datasets' dictionary. - - dataset_prefix : str + dataset_prefix The prefix for the dataset that will be passed to the GMT C API. - - resolution : str - The grid resolution. The suffix ``d``, ``m``, and ``s`` stand for - arc-degrees, arc-minutes, and arc-seconds, respectively. - - region : str or list + resolution + The grid resolution. The suffix ``d``, ``m``, and ``s`` stand for arc-degrees, + arc-minutes, and arc-seconds, respectively. + region The subregion of the grid to load, in the form of a list [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. Required for tiled grids. - - registration : str + registration Grid registration type. Either ``"pixel"`` for pixel registration or ``"gridline"`` for gridline registration. Default is ``None``, where - a gridline-registered grid is returned unless only the - pixel-registered grid is available. + a gridline-registered grid is returned unless only the pixel-registered grid + is available. Returns ------- @@ -269,35 +266,34 @@ def _load_remote_dataset( Note ---- - The returned :class:`xarray.DataArray` doesn't support slice operation for - tiled grids. + The returned :class:`xarray.DataArray` doesn't support slice operation for tiled + grids. """ dataset = datasets[dataset_name] - # check resolution if resolution not in dataset.resolutions: - raise GMTInvalidInput(f"Invalid resolution '{resolution}'.") + raise GMTInvalidInput( + f"Invalid resolution '{resolution}' for {dataset.title} dataset. " + f"Available resolutions are: {', '.join(dataset.resolutions)}." + ) # check registration + valid_registrations = dataset.resolutions[resolution].registrations if registration is None: # use gridline registration unless only pixel registration is available - registration = "gridline" - if "gridline" not in dataset.resolutions[resolution].registrations: - registration = "pixel" + registration = "gridline" if "gridline" in valid_registrations else "pixel" elif registration in ("pixel", "gridline"): - if registration not in dataset.resolutions[resolution].registrations: + if registration not in valid_registrations: raise GMTInvalidInput( f"{registration} registration is not available for the " f"{resolution} {dataset.title} dataset. Only " - f"{dataset.resolutions[resolution].registrations[0]}" - " registration is available." + f"{valid_registrations[0]} registration is available." ) else: raise GMTInvalidInput( - f"Invalid grid registration: '{registration}', should be either " - "'pixel', 'gridline' or None. Default is None, where a " - "gridline-registered grid is returned unless only the " - "pixel-registered grid is available." + f"Invalid grid registration: '{registration}', should be either 'pixel', " + "'gridline' or None. Default is None, where a gridline-registered grid is " + "returned unless only the pixel-registered grid is available." ) reg = f"_{registration[0]}" @@ -321,9 +317,8 @@ def _load_remote_dataset( grid.attrs["units"] = dataset.units for key, value in dataset.extra_attributes.items(): grid.attrs[key] = value - # Remove the actual range because it gets outdated when indexing the grid, - # which causes problems when exporting it to netCDF for usage on the - # command-line. + # Remove the actual range because it gets outdated when indexing the grid, which + # causes problems when exporting it to netCDF for usage on the command-line. grid.attrs.pop("actual_range", None) for coord in grid.coords: grid[coord].attrs.pop("actual_range", None)