From 55b089eb64ca4b1f8da21f16d6a3334041c87706 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 3 Dec 2023 19:37:41 +0800 Subject: [PATCH 1/5] Add load_mars_relief to load Mars relief dataset in various resolutions and registrations --- doc/api/index.rst | 1 + pygmt/datasets/__init__.py | 1 + pygmt/datasets/load_remote_dataset.py | 23 +++++ pygmt/datasets/mars_relief.py | 110 +++++++++++++++++++++++ pygmt/helpers/testing.py | 3 + pygmt/tests/test_datasets_mars_relief.py | 51 +++++++++++ 6 files changed, 189 insertions(+) create mode 100644 pygmt/datasets/mars_relief.py create mode 100644 pygmt/tests/test_datasets_mars_relief.py diff --git a/doc/api/index.rst b/doc/api/index.rst index 8e63c016502..db7acb9aae6 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -226,6 +226,7 @@ and store them in GMT's user data directory. datasets.load_earth_mask datasets.load_earth_relief datasets.load_earth_vertical_gravity_gradient + datasets.load_mars_relief datasets.load_sample_data In addition, there is also a special function to load XYZ tile maps via diff --git a/pygmt/datasets/__init__.py b/pygmt/datasets/__init__.py index 7aba16154be..dbda07a5b32 100644 --- a/pygmt/datasets/__init__.py +++ b/pygmt/datasets/__init__.py @@ -13,5 +13,6 @@ from pygmt.datasets.earth_vertical_gravity_gradient import ( load_earth_vertical_gravity_gradient, ) +from pygmt.datasets.mars_relief import load_mars_relief from pygmt.datasets.samples import list_sample_data, load_sample_data from pygmt.datasets.tile_map import load_tile_map diff --git a/pygmt/datasets/load_remote_dataset.py b/pygmt/datasets/load_remote_dataset.py index 6f75946aea8..2ce46ae233b 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -229,6 +229,29 @@ class GMTRemoteDataset(NamedTuple): "03m": Resolution(["gridline"], True), }, ), + "mars_relief": GMTRemoteDataset( + title="Mars relief", + name="mars relief", + long_name="Mars relief", + units="meters", + extra_attributes={}, + 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(["gridline", "pixel"], True), + "12s": Resolution(["pixel"], True), + }, + ), } diff --git a/pygmt/datasets/mars_relief.py b/pygmt/datasets/mars_relief.py new file mode 100644 index 00000000000..01111ccc871 --- /dev/null +++ b/pygmt/datasets/mars_relief.py @@ -0,0 +1,110 @@ +""" +Function to download the Mars relief dataset from the GMT data server, and load +as :class:`xarray.DataArray`. + +The grids are available in various resolutions. +""" +from typing import Literal + +from pygmt.datasets.load_remote_dataset import _load_remote_dataset +from pygmt.helpers import kwargs_to_strings + +__doctest_skip__ = ["load_mars_relief"] + + +@kwargs_to_strings(region="sequence") +def load_mars_relief( + resolution="01d", + region=None, + registration: Literal["gridline", "pixel", None] = None, +): + r""" + Load the Mars relief dataset in various resolutions. + + .. figure:: https://www.generic-mapping-tools.org/remote-datasets/_images/GMT_mars_relief.jpg + :width: 80% + :align: center + + Mars relief dataset. + + The grids are downloaded to a user data directory + (usually ``~/.gmt/server/mars/mars_relief/``) the first time you invoke + this function. Afterwards, it will load the grid from the data directory. + So you'll need an internet connection the first time around. + + These grids can also be accessed by passing in the file name + **@mars_relief**\_\ *res*\[_\ *reg*] to any grid processing function or + plotting method. *res* is the grid resolution (see below), and *reg* is the + grid registration type (**p** for pixel registration or **g** for gridline + registration). + + The default color palette table (CPT) for this dataset is + *@mars_relief.cpt*. It's implicitly used when passing in the file name of + the dataset to any grid plotting method if no CPT is explicitly specified. + When the dataset is loaded and plotted as an :class:`xarray.DataArray` + object, the default CPT is ignored, and GMT's default CPT (*turbo*) is + used. To use the dataset-specific CPT, you need to explicitly set + ``cmap="@mars_relief.cpt"``. + + Refer to :gmt-datasets:`mars-relief.html` for more details about available + datasets, including version information and references. + + Parameters + ---------- + resolution : str + The grid resolution. The suffix ``d``, ``m`` and ``s`` stand for + arc-degrees, arc-minutes and arc-seconds. It can be ``"01d"``, + ``"30m"``, ``"20m"``, ``"15m"``, ``"10m"``, ``"06m"``, ``"05m"``, + ``"04m"``, ``"03m"``, ``"02m"``, ``"01m"``, ``"30s"``, ``"15s"``, and + ``"14s"``. + region : str or list + 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 grids with resolutions higher than 5 arc-minutes + (i.e., ``"05m"``). + registration + Grid registration type. Either ``"pixel"`` for pixel registration or + ``"gridline"`` for gridline registration. Default is ``None``, means + ``"gridline"`` for all resolutions except for ``"12s"`` which is + ``"pixel"`` only. + + Returns + ------- + grid : :class:`xarray.DataArray` + The Mars relief grid. Coordinates are latitude and longitude in + degrees. Relief is in meters. + + Note + ---- + The registration and coordinate system type of the returned + :class:`xarray.DataArray` grid can be accessed via the GMT accessors + (i.e., ``grid.gmt.registration`` and ``grid.gmt.gtype`` respectively). + However, these properties may be lost after specific grid operations (such + as slicing) and will need to be manually set before passing the grid to any + PyGMT data processing or plotting functions. Refer to + :class:`pygmt.GMTDataArrayAccessor` for detailed explanations and + workarounds. + + Examples + -------- + + >>> from pygmt.datasets import load_mars_relief + >>> # load the default grid (gridline-registered 1 arc-degree grid) + >>> grid = load_mars_relief() + >>> # load the 30 arc-minutes grid with "gridline" registration + >>> grid = load_mars_relief(resolution="30m", registration="gridline") + >>> # load high-resolution (5 arc-minutes) grid for a specific region + >>> grid = load_mars_relief( + ... resolution="05m", + ... region=[120, 160, 30, 60], + ... registration="gridline", + ... ) + """ + grid = _load_remote_dataset( + dataset_name="mars_relief", + dataset_prefix="mars_relief_", + resolution=resolution, + region=region, + registration=registration, + ) + return grid diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index 10c10f4c6d3..2ae00fe5e0b 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -200,6 +200,9 @@ def download_test_data(): # Earth WDMAM grids "@earth_wdmam_01d_g", "@S90E000.earth_wdmam_03m_g.nc", # Specific grid for 03m test + # Mars relief grids + "@mars_relief_01d_g", + "@N00W030.mars_relief_01m_g.nc", # Specific grid for 01m test # Other cache files "@capitals.gmt", "@earth_relief_20m_holes.grd", diff --git a/pygmt/tests/test_datasets_mars_relief.py b/pygmt/tests/test_datasets_mars_relief.py new file mode 100644 index 00000000000..613fdf6c14e --- /dev/null +++ b/pygmt/tests/test_datasets_mars_relief.py @@ -0,0 +1,51 @@ +""" +Test basic functionality for loading Mars relief datasets. +""" +import numpy as np +import numpy.testing as npt +from pygmt.datasets import load_mars_relief + + +def test_mars_relief_01d(): + """ + Test some properties of the Mars relief 01d data. + """ + data = load_mars_relief(resolution="01d") + assert data.name == "mars relief" + assert data.attrs["units"] == "meters" + assert data.attrs["long_name"] == "Mars relief" + assert data.shape == (181, 361) + assert data.gmt.registration == 0 + npt.assert_allclose(data.lat, np.arange(-90, 91, 1)) + npt.assert_allclose(data.lon, np.arange(-180, 181, 1)) + npt.assert_allclose(data.min(), -7421.0, atol=0.5) + npt.assert_allclose(data.max(), 19587.5, atol=0.5) + + +def test_mars_relief_01d_with_region(): + """ + Test loading low-resolution Mars relief with 'region'. + """ + data = load_mars_relief(resolution="01d", region=[-10, 10, -5, 5]) + assert data.shape == (11, 21) + assert data.gmt.registration == 0 + npt.assert_allclose(data.lat, np.arange(-5, 6, 1)) + npt.assert_allclose(data.lon, np.arange(-10, 11, 1)) + npt.assert_allclose(data.min(), -2502.0, atol=0.5) + npt.assert_allclose(data.max(), -135.5, atol=0.5) + + +def test_mars_relief_01m_default_registration(): + """ + Test that the grid returned by default for the 1 arc-minute resolution has + a "gridline" registration. + """ + data = load_mars_relief(resolution="01m", region=[-10, -9, 3, 5]) + assert data.shape == (121, 61) + assert data.gmt.registration == 0 + assert data.coords["lat"].data.min() == 3.0 + assert data.coords["lat"].data.max() == 5.0 + assert data.coords["lon"].data.min() == -10.0 + assert data.coords["lon"].data.max() == -9.0 + npt.assert_allclose(data.min(), -3374.0, atol=0.5) + npt.assert_allclose(data.max(), -1181.0, atol=0.5) From 7913f57c913453ae4d7726d432d63c674088559c Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 26 Dec 2023 15:18:26 +0800 Subject: [PATCH 2/5] Use candidate server --- pygmt/datasets/mars_relief.py | 2 +- pygmt/tests/test_datasets_mars_relief.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pygmt/datasets/mars_relief.py b/pygmt/datasets/mars_relief.py index 01111ccc871..9f163b573fa 100644 --- a/pygmt/datasets/mars_relief.py +++ b/pygmt/datasets/mars_relief.py @@ -56,7 +56,7 @@ def load_mars_relief( arc-degrees, arc-minutes and arc-seconds. It can be ``"01d"``, ``"30m"``, ``"20m"``, ``"15m"``, ``"10m"``, ``"06m"``, ``"05m"``, ``"04m"``, ``"03m"``, ``"02m"``, ``"01m"``, ``"30s"``, ``"15s"``, and - ``"14s"``. + ``"12s"``. region : str or list The subregion of the grid to load, in the form of a list [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. diff --git a/pygmt/tests/test_datasets_mars_relief.py b/pygmt/tests/test_datasets_mars_relief.py index 613fdf6c14e..0525c1e02a9 100644 --- a/pygmt/tests/test_datasets_mars_relief.py +++ b/pygmt/tests/test_datasets_mars_relief.py @@ -3,9 +3,15 @@ """ import numpy as np import numpy.testing as npt +import pytest from pygmt.datasets import load_mars_relief +@pytest.fixture(autouse=True) +def _use_candidate_server(monkeypatch): + monkeypatch.setenv("GMT_DATA_SERVER", "candidate") + + def test_mars_relief_01d(): """ Test some properties of the Mars relief 01d data. From 5a31d10283b035e920cb587ad47feff75af2e720 Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Wed, 17 Jan 2024 12:34:39 +0800 Subject: [PATCH 3/5] Updates --- pygmt/datasets/load_remote_dataset.py | 28 ++++----- pygmt/datasets/mars_relief.py | 72 +++++++++++------------- pygmt/tests/test_datasets_mars_relief.py | 6 -- 3 files changed, 47 insertions(+), 59 deletions(-) diff --git a/pygmt/datasets/load_remote_dataset.py b/pygmt/datasets/load_remote_dataset.py index 53a0c1756ca..fe4f25601f9 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -233,20 +233,20 @@ class GMTRemoteDataset(NamedTuple): units="meters", extra_attributes={}, 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(["gridline", "pixel"], True), - "12s": 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", tiled=True), + "30s": Resolution("30s", tiled=True), + "15s": Resolution("15s", tiled=True), + "12s": Resolution("12s", registrations=["pixel"], tiled=True), }, ), } diff --git a/pygmt/datasets/mars_relief.py b/pygmt/datasets/mars_relief.py index 9f163b573fa..1d4ae06ee4d 100644 --- a/pygmt/datasets/mars_relief.py +++ b/pygmt/datasets/mars_relief.py @@ -1,6 +1,6 @@ """ -Function to download the Mars relief dataset from the GMT data server, and load -as :class:`xarray.DataArray`. +Function to download the Mars relief dataset from the GMT data server, and load as +:class:`xarray.DataArray`. The grids are available in various resolutions. """ @@ -27,67 +27,61 @@ def load_mars_relief( Mars relief dataset. - The grids are downloaded to a user data directory - (usually ``~/.gmt/server/mars/mars_relief/``) the first time you invoke - this function. Afterwards, it will load the grid from the data directory. - So you'll need an internet connection the first time around. + The grids are downloaded to a user data directory (usually + ``~/.gmt/server/mars/mars_relief/``) the first time you invoke this function. + Afterwards, it will load the grid from the data directory. So you'll need an + internet connection the first time around. These grids can also be accessed by passing in the file name - **@mars_relief**\_\ *res*\[_\ *reg*] to any grid processing function or - plotting method. *res* is the grid resolution (see below), and *reg* is the - grid registration type (**p** for pixel registration or **g** for gridline - registration). - - The default color palette table (CPT) for this dataset is - *@mars_relief.cpt*. It's implicitly used when passing in the file name of - the dataset to any grid plotting method if no CPT is explicitly specified. - When the dataset is loaded and plotted as an :class:`xarray.DataArray` - object, the default CPT is ignored, and GMT's default CPT (*turbo*) is - used. To use the dataset-specific CPT, you need to explicitly set + **@mars_relief**\_\ *res*\[_\ *reg*] to any grid processing function or plotting + method. *res* is the grid resolution (see below), and *reg* is the grid registration + type (**p** for pixel registration or **g** for gridline registration). + + The default color palette table (CPT) for this dataset is *@mars_relief.cpt*. It's + implicitly used when passing in the file name of the dataset to any grid plotting + method if no CPT is explicitly specified. When the dataset is loaded and plotted as + an :class:`xarray.DataArray` object, the default CPT is ignored, and GMT's default + CPT (*turbo*) is used. To use the dataset-specific CPT, you need to explicitly set ``cmap="@mars_relief.cpt"``. - Refer to :gmt-datasets:`mars-relief.html` for more details about available - datasets, including version information and references. + Refer to :gmt-datasets:`mars-relief.html` for more details about available datasets, + including version information and references. Parameters ---------- resolution : str - The grid resolution. The suffix ``d``, ``m`` and ``s`` stand for - arc-degrees, arc-minutes and arc-seconds. It can be ``"01d"``, - ``"30m"``, ``"20m"``, ``"15m"``, ``"10m"``, ``"06m"``, ``"05m"``, - ``"04m"``, ``"03m"``, ``"02m"``, ``"01m"``, ``"30s"``, ``"15s"``, and - ``"12s"``. + The grid resolution. The suffix ``d``, ``m`` and ``s`` stand for arc-degrees, + arc-minutes and arc-seconds. It can be ``"01d"``, ``"30m"``, ``"20m"``, + ``"15m"``, ``"10m"``, ``"06m"``, ``"05m"``, ``"04m"``, ``"03m"``, ``"02m"``, + ``"01m"``, ``"30s"``, ``"15s"``, and ``"12s"``. region : str or list 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 grids with resolutions higher than 5 arc-minutes - (i.e., ``"05m"``). + [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. Required for + grids with resolutions higher than 5 arc-minutes (i.e., ``"05m"``). registration Grid registration type. Either ``"pixel"`` for pixel registration or ``"gridline"`` for gridline registration. Default is ``None``, means - ``"gridline"`` for all resolutions except for ``"12s"`` which is - ``"pixel"`` only. + ``"gridline"`` for all resolutions except for ``"12s"`` which is ``"pixel"`` + only. Returns ------- grid : :class:`xarray.DataArray` - The Mars relief grid. Coordinates are latitude and longitude in - degrees. Relief is in meters. + The Mars relief grid. Coordinates are latitude and longitude in degrees. Relief + is in meters. Note ---- The registration and coordinate system type of the returned - :class:`xarray.DataArray` grid can be accessed via the GMT accessors - (i.e., ``grid.gmt.registration`` and ``grid.gmt.gtype`` respectively). - However, these properties may be lost after specific grid operations (such - as slicing) and will need to be manually set before passing the grid to any - PyGMT data processing or plotting functions. Refer to - :class:`pygmt.GMTDataArrayAccessor` for detailed explanations and - workarounds. + :class:`xarray.DataArray` grid can be accessed via the GMT accessors (i.e., + ``grid.gmt.registration`` and ``grid.gmt.gtype`` respectively). However, these + properties may be lost after specific grid operations (such as slicing) and will + need to be manually set before passing the grid to any PyGMT data processing or + plotting functions. Refer to :class:`pygmt.GMTDataArrayAccessor` for detailed + explanations and workarounds. Examples -------- - >>> from pygmt.datasets import load_mars_relief >>> # load the default grid (gridline-registered 1 arc-degree grid) >>> grid = load_mars_relief() diff --git a/pygmt/tests/test_datasets_mars_relief.py b/pygmt/tests/test_datasets_mars_relief.py index 0525c1e02a9..613fdf6c14e 100644 --- a/pygmt/tests/test_datasets_mars_relief.py +++ b/pygmt/tests/test_datasets_mars_relief.py @@ -3,15 +3,9 @@ """ import numpy as np import numpy.testing as npt -import pytest from pygmt.datasets import load_mars_relief -@pytest.fixture(autouse=True) -def _use_candidate_server(monkeypatch): - monkeypatch.setenv("GMT_DATA_SERVER", "candidate") - - def test_mars_relief_01d(): """ Test some properties of the Mars relief 01d data. From 8f1d03259e057759d06c93bfcd3bcccdeb45934f Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Sun, 21 Jan 2024 12:44:39 +0800 Subject: [PATCH 4/5] Update pygmt/datasets/load_remote_dataset.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Yvonne Fröhlich <94163266+yvonnefroehlich@users.noreply.github.com> --- pygmt/datasets/load_remote_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/datasets/load_remote_dataset.py b/pygmt/datasets/load_remote_dataset.py index fe4f25601f9..94401449844 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -228,7 +228,7 @@ class GMTRemoteDataset(NamedTuple): ), "mars_relief": GMTRemoteDataset( title="Mars relief", - name="mars relief", + name="mars_relief", long_name="Mars relief", units="meters", extra_attributes={}, From 8d0b91e453e4b2d4061246ba7c6c8984ec1de8ec Mon Sep 17 00:00:00 2001 From: Dongdong Tian Date: Tue, 23 Jan 2024 16:27:55 +0800 Subject: [PATCH 5/5] Updates --- pygmt/datasets/load_remote_dataset.py | 2 +- pygmt/tests/test_datasets_mars_relief.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pygmt/datasets/load_remote_dataset.py b/pygmt/datasets/load_remote_dataset.py index 94401449844..243e5d6253a 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -229,7 +229,7 @@ class GMTRemoteDataset(NamedTuple): "mars_relief": GMTRemoteDataset( title="Mars relief", name="mars_relief", - long_name="Mars relief", + long_name="NASA Mars (MOLA) relief", units="meters", extra_attributes={}, resolutions={ diff --git a/pygmt/tests/test_datasets_mars_relief.py b/pygmt/tests/test_datasets_mars_relief.py index 613fdf6c14e..4857c695cce 100644 --- a/pygmt/tests/test_datasets_mars_relief.py +++ b/pygmt/tests/test_datasets_mars_relief.py @@ -11,9 +11,9 @@ def test_mars_relief_01d(): Test some properties of the Mars relief 01d data. """ data = load_mars_relief(resolution="01d") - assert data.name == "mars relief" + assert data.name == "mars_relief" assert data.attrs["units"] == "meters" - assert data.attrs["long_name"] == "Mars relief" + assert data.attrs["long_name"] == "NASA Mars (MOLA) relief" assert data.shape == (181, 361) assert data.gmt.registration == 0 npt.assert_allclose(data.lat, np.arange(-90, 91, 1))