From 6d4037119a4f67493d6b2c39c6e37b39255c0de8 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 9 Dec 2022 06:01:53 -0500 Subject: [PATCH 1/8] initial commit for earth_free_air_anomaly.py --- pygmt/datasets/__init__.py | 1 + pygmt/datasets/earth_free_air_anomaly.py | 69 ++++++++++++++++++++++++ pygmt/datasets/load_remote_dataset.py | 20 +++++++ 3 files changed, 90 insertions(+) create mode 100644 pygmt/datasets/earth_free_air_anomaly.py diff --git a/pygmt/datasets/__init__.py b/pygmt/datasets/__init__.py index 25f29b67af5..0da120b21c7 100644 --- a/pygmt/datasets/__init__.py +++ b/pygmt/datasets/__init__.py @@ -3,6 +3,7 @@ # Load sample data included with GMT (downloaded from the GMT cache server). from pygmt.datasets.earth_age import load_earth_age +from pygmt.datasets.earth_free_air_anomaly import load_earth_free_air_anomaly from pygmt.datasets.earth_magnetic_anomaly import load_earth_magnetic_anomaly from pygmt.datasets.earth_relief import load_earth_relief from pygmt.datasets.samples import ( diff --git a/pygmt/datasets/earth_free_air_anomaly.py b/pygmt/datasets/earth_free_air_anomaly.py new file mode 100644 index 00000000000..a8b051da1a6 --- /dev/null +++ b/pygmt/datasets/earth_free_air_anomaly.py @@ -0,0 +1,69 @@ +""" +Function to download the IGPP Global Earth Free-Air Anomaly datasets from the +GMT data server, and load as :class:`xarray.DataArray`. + +The grids are available in various resolutions. +""" +from pygmt.datasets.load_remote_dataset import _load_remote_dataset +from pygmt.helpers import kwargs_to_strings + + +@kwargs_to_strings(region="sequence") +def load_earth_free_air_anomaly(resolution="01d", region=None, registration=None): + r""" + Load an Earth Free-Air Anomaly grid in various resolutions. + + The grids are downloaded to a user data directory + (usually ``~/.gmt/server/earth/earth_faa/``) 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 + **@earth_faa**\_\ *res*\[_\ *reg*] to any grid plotting/processing + function. *res* is the grid resolution (see below), and *reg* is grid + registration type (**p** for pixel registration or **g** for gridline + registration). + + Refer to :gmt-datasets:`earth-faa.html` for more details. + + Parameters + ---------- + resolution : str + The grid resolution. The suffix ``d`` and ``m`` stand for + arc-degree and arc-minute. It can be ``"01d"``, ``"30m"``, + ``"20m"``, ``"15m"``, ``"10m"``, ``"06m"``, ``"05m"``, ``"04m"``, + ``"03m"``, ``"02m"``, or ``"01m"``. + + region : str or list + The subregion of the grid to load, in the forms of a list + [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. + Required for grids with resolutions higher than 5 + arc-minute (i.e., ``"05m"``). + + registration : str + Grid registration type. Either ``"pixel"`` for pixel registration or + ``"gridline"`` for gridline registration. Default is ``None``, where + a pixel-registered grid is returned unless only the + gridline-registered grid is available. + + Returns + ------- + grid : :class:`xarray.DataArray` + The Earth free-air anomaly grid. Coordinates are latitude and + longitude in degrees. Units are in mGal. + + Note + ---- + The :class:`xarray.DataArray` grid doesn't support slice operation, for + Earth free-air anomaly with resolutions of 5 arc-minutes or higher, + which are stored as smaller tiles. + """ + dataset_prefix = "earth_faa_" + grid = _load_remote_dataset( + dataset_name="earth_free_air_anomaly", + dataset_prefix=dataset_prefix, + resolution=resolution, + region=region, + registration=registration, + ) + return grid diff --git a/pygmt/datasets/load_remote_dataset.py b/pygmt/datasets/load_remote_dataset.py index 309bc324542..357df2c46e0 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -127,6 +127,26 @@ class GMTRemoteDataset(NamedTuple): "02m": Resolution(["pixel"], True), }, ), + "earth_free_air_anomaly": GMTRemoteDataset( + title="free air anomaly", + name="free_air_anomaly", + long_name="IGPP Global Earth Free-Air Anomaly", + units="mGal", + extra_attributes={"horizontal_datum": "WGS84"}, + resolutions={ + "01d": Resolution(["pixel", "gridline"], False), + "30m": Resolution(["pixel", "gridline"], False), + "20m": Resolution(["pixel", "gridline"], False), + "15m": Resolution(["pixel", "gridline"], False), + "10m": Resolution(["pixel", "gridline"], False), + "06m": Resolution(["pixel", "gridline"], False), + "05m": Resolution(["pixel", "gridline"], True), + "04m": Resolution(["pixel", "gridline"], True), + "03m": Resolution(["pixel", "gridline"], True), + "02m": Resolution(["pixel", "gridline"], True), + "01m": Resolution(["gridline"], True), + }, + ), } From bb5afd58e2b6e1e10720b9087f1c700e493948c8 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 9 Dec 2022 06:04:29 -0500 Subject: [PATCH 2/8] add faa to index.rst --- doc/api/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/api/index.rst b/doc/api/index.rst index 68b8aed08ae..ca89ee655c8 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -222,6 +222,7 @@ and store them in GMT's user data directory. datasets.list_sample_data datasets.load_earth_age + datasets.load_earth_free_air_anomaly datasets.load_earth_magnetic_anomaly datasets.load_earth_relief datasets.load_sample_data From a167275d334b8a55af632d4ca4ccdb3c55c2cf0a Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 9 Dec 2022 06:16:53 -0500 Subject: [PATCH 3/8] add tests and cache files for free-air anomaly --- pygmt/helpers/testing.py | 3 + .../test_datasets_earth_free_air_anomaly.py | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 pygmt/tests/test_datasets_earth_free_air_anomaly.py diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index 29d1e5f1f8b..957499667d8 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -183,6 +183,9 @@ def download_test_data(): # Earth magnetic anomaly grids "@earth_mag_01d_g.grd" "@S90W180.earth_mag_05m_g.nc" # Specific grid for 05m test + # Earth free-air anomaly grids + "@earth_faa_01d_g.grd", + "@S90W180.earth_faa_05m_g.nc", # Specific grid for 05m test # Other cache files "@capitals.gmt", "@earth_relief_20m_holes.grd", diff --git a/pygmt/tests/test_datasets_earth_free_air_anomaly.py b/pygmt/tests/test_datasets_earth_free_air_anomaly.py new file mode 100644 index 00000000000..ca359994723 --- /dev/null +++ b/pygmt/tests/test_datasets_earth_free_air_anomaly.py @@ -0,0 +1,82 @@ +""" +Test basic functionality for loading Earth free air anomaly datasets. +""" +import numpy as np +import numpy.testing as npt +import pytest +from pygmt.datasets import load_earth_free_air_anomaly, load_earth_magnetic_anomaly +from pygmt.exceptions import GMTInvalidInput + + +def test_earth_faa_fails(): + """ + Make sure earth_free_air_anomaly fails for invalid resolutions. + """ + resolutions = "1m 1d bla 60d 001m 03".split() + resolutions.append(60) + for resolution in resolutions: + with pytest.raises(GMTInvalidInput): + load_earth_free_air_anomaly(resolution=resolution) + + +def test_earth_faa_incorrect_registration(): + """ + Test loading earth_free_air_anomaly with incorrect registration type. + """ + with pytest.raises(GMTInvalidInput): + load_earth_free_air_anomaly(registration="improper_type") + + +def test_earth_faa_01d(): + """ + Test some properties of the free air anomaly 01d data. + """ + data = load_earth_free_air_anomaly(resolution="01d", registration="gridline") + assert data.name == "free_air_anomaly" + assert data.attrs["long_name"] == "IGPP Global Earth Free-Air Anomaly" + assert data.attrs["units"] == "mGal" + assert data.attrs["horizontal_datum"] == "WGS84" + assert data.shape == (181, 361) + 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(), -275.75) + npt.assert_allclose(data.max(), 308.375) + + +def test_earth_faa_01d_with_region(): + """ + Test loading low-resolution earth free air anomaly with 'region'. + """ + data = load_earth_free_air_anomaly( + resolution="01d", region=[-10, 10, -5, 5], registration="gridline" + ) + assert data.shape == (11, 21) + 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(), -58.75) + npt.assert_allclose(data.max(), 69.524994) + + +def test_earth_faa_05m_with_region(): + """ + Test loading a subregion of high-resolution earth free air anomaly data. + """ + data = load_earth_free_air_anomaly( + resolution="05m", region=[-115, -112, 4, 6], registration="gridline" + ) + assert data.shape == (25, 37) + assert data.lat.min() == 4 + assert data.lat.max() == 6 + assert data.lon.min() == -115 + assert data.lon.max() == -112 + npt.assert_allclose(data.min(), -20.5) + npt.assert_allclose(data.max(), -3.9500122) + + +def test_earth_faa_05m_without_region(): + """ + Test loading high-resolution earth free air anomaly without passing + 'region'. + """ + with pytest.raises(GMTInvalidInput): + load_earth_free_air_anomaly("05m") From ad5d3afb0b33159003743ea0d4b36df770fac09d Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Fri, 9 Dec 2022 06:24:12 -0500 Subject: [PATCH 4/8] remove unused import --- pygmt/tests/test_datasets_earth_free_air_anomaly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/tests/test_datasets_earth_free_air_anomaly.py b/pygmt/tests/test_datasets_earth_free_air_anomaly.py index ca359994723..f2351e24c11 100644 --- a/pygmt/tests/test_datasets_earth_free_air_anomaly.py +++ b/pygmt/tests/test_datasets_earth_free_air_anomaly.py @@ -4,7 +4,7 @@ import numpy as np import numpy.testing as npt import pytest -from pygmt.datasets import load_earth_free_air_anomaly, load_earth_magnetic_anomaly +from pygmt.datasets import load_earth_free_air_anomaly from pygmt.exceptions import GMTInvalidInput From f1db41ff3fda53125e60a7de39a55708437dca1e Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Sun, 11 Dec 2022 06:57:49 -0500 Subject: [PATCH 5/8] Update pygmt/datasets/load_remote_dataset.py Co-authored-by: Dongdong Tian --- 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 562ec152da2..f5825948d12 100644 --- a/pygmt/datasets/load_remote_dataset.py +++ b/pygmt/datasets/load_remote_dataset.py @@ -164,7 +164,7 @@ class GMTRemoteDataset(NamedTuple): "04m": Resolution(["pixel", "gridline"], True), "03m": Resolution(["pixel", "gridline"], True), "02m": Resolution(["pixel", "gridline"], True), - "01m": Resolution(["gridline"], True), + "01m": Resolution(["pixel"], True), }, ), } From 17908b9d7f90f98a130e9a18a5f811965bfdd1a8 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Tue, 13 Dec 2022 17:03:51 -0500 Subject: [PATCH 6/8] Apply suggestions from code review Co-authored-by: Dongdong Tian --- pygmt/datasets/earth_free_air_anomaly.py | 3 +-- pygmt/helpers/testing.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pygmt/datasets/earth_free_air_anomaly.py b/pygmt/datasets/earth_free_air_anomaly.py index a8b051da1a6..d60096aa43f 100644 --- a/pygmt/datasets/earth_free_air_anomaly.py +++ b/pygmt/datasets/earth_free_air_anomaly.py @@ -58,10 +58,9 @@ def load_earth_free_air_anomaly(resolution="01d", region=None, registration=None Earth free-air anomaly with resolutions of 5 arc-minutes or higher, which are stored as smaller tiles. """ - dataset_prefix = "earth_faa_" grid = _load_remote_dataset( dataset_name="earth_free_air_anomaly", - dataset_prefix=dataset_prefix, + dataset_prefix="earth_faa_", resolution=resolution, region=region, registration=registration, diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index 262f67b152a..c89ef96f373 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -184,10 +184,10 @@ def download_test_data(): "@earth_geoid_01d_g.grd", "@S90W180.earth_geoid_05m_g.nc", # Specific grid for 05m test # Earth magnetic anomaly grids - "@earth_mag_01d_g.grd", + "@earth_mag_01d_g", "@S90W180.earth_mag_05m_g.nc", # Specific grid for 05m test # Earth free-air anomaly grids - "@earth_faa_01d_g.grd", + "@earth_faa_01d_g", "@S90W180.earth_faa_05m_g.nc", # Specific grid for 05m test # Other cache files "@capitals.gmt", From 6babbbf670885390a39462e505f58ae01ff82d84 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Tue, 13 Dec 2022 17:05:25 -0500 Subject: [PATCH 7/8] remove .grd suffice from earth_geoid_01d_g --- pygmt/helpers/testing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/helpers/testing.py b/pygmt/helpers/testing.py index c89ef96f373..870a9426668 100644 --- a/pygmt/helpers/testing.py +++ b/pygmt/helpers/testing.py @@ -181,7 +181,7 @@ def download_test_data(): "@earth_age_01d_g", "@S90W180.earth_age_05m_g.nc", # Specific grid for 05m test # Earth geoid grids - "@earth_geoid_01d_g.grd", + "@earth_geoid_01d_g", "@S90W180.earth_geoid_05m_g.nc", # Specific grid for 05m test # Earth magnetic anomaly grids "@earth_mag_01d_g", From b276c7c3bdf3d95ee16c0f8de8ac1a563a185341 Mon Sep 17 00:00:00 2001 From: Will Schlitzer Date: Thu, 15 Dec 2022 06:27:57 -0500 Subject: [PATCH 8/8] Update pygmt/datasets/earth_free_air_anomaly.py Co-authored-by: Michael Grund <23025878+michaelgrund@users.noreply.github.com> --- pygmt/datasets/earth_free_air_anomaly.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pygmt/datasets/earth_free_air_anomaly.py b/pygmt/datasets/earth_free_air_anomaly.py index d60096aa43f..b13f9fc4103 100644 --- a/pygmt/datasets/earth_free_air_anomaly.py +++ b/pygmt/datasets/earth_free_air_anomaly.py @@ -38,7 +38,7 @@ def load_earth_free_air_anomaly(resolution="01d", region=None, registration=None The subregion of the grid to load, in the forms of a list [*xmin*, *xmax*, *ymin*, *ymax*] or a string *xmin/xmax/ymin/ymax*. Required for grids with resolutions higher than 5 - arc-minute (i.e., ``"05m"``). + arc-minutes (i.e., ``"05m"``). registration : str Grid registration type. Either ``"pixel"`` for pixel registration or