Skip to content

Commit 3134188

Browse files
Remote datasets: Add load_earth_deflection to load "IGPP Earth east-west and north-south deflection" datasets (#3728)
1 parent 1256d15 commit 3134188

File tree

6 files changed

+267
-0
lines changed

6 files changed

+267
-0
lines changed

doc/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ and store them in GMT's user data directory.
235235
datasets.load_black_marble
236236
datasets.load_blue_marble
237237
datasets.load_earth_age
238+
datasets.load_earth_deflection
238239
datasets.load_earth_dist
239240
datasets.load_earth_free_air_anomaly
240241
datasets.load_earth_geoid

pygmt/datasets/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from pygmt.datasets.earth_age import load_earth_age
88
from pygmt.datasets.earth_day import load_blue_marble
9+
from pygmt.datasets.earth_deflection import load_earth_deflection
910
from pygmt.datasets.earth_dist import load_earth_dist
1011
from pygmt.datasets.earth_free_air_anomaly import load_earth_free_air_anomaly
1112
from pygmt.datasets.earth_geoid import load_earth_geoid

pygmt/datasets/earth_deflection.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""
2+
Function to download the IGPP Earth east-west and north-south deflection datasets from
3+
the GMT data server, and load as :class:`xarray.DataArray`.
4+
5+
The grids are available in various resolutions.
6+
"""
7+
8+
from collections.abc import Sequence
9+
from typing import Literal
10+
11+
import xarray as xr
12+
from pygmt.datasets.load_remote_dataset import _load_remote_dataset
13+
14+
__doctest_skip__ = ["load_earth_deflection"]
15+
16+
17+
def load_earth_deflection(
18+
resolution: Literal[
19+
"01d", "30m", "20m", "15m", "10m", "06m", "05m", "04m", "03m", "02m", "01m"
20+
] = "01d",
21+
region: Sequence[float] | str | None = None,
22+
registration: Literal["gridline", "pixel", None] = None,
23+
component: Literal["east", "north"] = "east",
24+
) -> xr.DataArray:
25+
r"""
26+
Load the IGPP Earth east-west and north-south deflection datasets in various
27+
resolutions.
28+
29+
.. list-table::
30+
:widths: 50 50
31+
:header-rows: 1
32+
33+
* - IGPP Earth east-west deflection
34+
- IGPP Earth north-south deflection
35+
* - .. figure:: https://www.generic-mapping-tools.org/remote-datasets/_images/GMT_earth_edefl.jpg
36+
- .. figure:: https://www.generic-mapping-tools.org/remote-datasets/_images/GMT_earth_ndefl.jpg
37+
38+
The grids are downloaded to a user data directory (usually
39+
``~/.gmt/server/earth/earth_edefl/`` and ``~/.gmt/server/earth/earth_ndefl/`` the
40+
first time you invoke this function. Afterwards, it will load the grid from the
41+
data directory. So you'll need an internet connection the first time around.
42+
43+
These grids can also be accessed by passing in the file name
44+
**@**\ *earth_defl_type*\_\ *res*\[_\ *reg*] to any grid processing function or
45+
plotting method. *earth_defl_type* is the GMT name for the dataset. The available
46+
options are **earth_edefl** and **earth_ndefl**. *res* is the grid resolution (see
47+
below), and *reg* is the grid registration type (**p** for pixel registration or
48+
**g** for gridline registration).
49+
50+
The default color palette table (CPTs) for this dataset is *@earth_defl.cpt*. It's
51+
implicitly used when passing in the file name of the dataset to any grid plotting
52+
method if no CPT is explicitly specified. When the dataset is loaded and plotted as
53+
an :class:`xarray.DataArray` object, the default CPT is ignored, and GMT's default
54+
CPT (*turbo*) is used. To use the dataset-specific CPT, you need to explicitly set
55+
``cmap="@earth_defl.cpt"``.
56+
57+
Refer to :gmt-datasets:`earth-edefl.html` and :gmt-datasets:`earth-ndefl.html` for
58+
more details about available datasets, including version information and references.
59+
60+
Parameters
61+
----------
62+
resolution
63+
The grid resolution. The suffix ``d`` and ``m`` stand for arc-degrees and
64+
arc-minutes.
65+
region
66+
The subregion of the grid to load, in the form of a sequence [*xmin*, *xmax*,
67+
*ymin*, *ymax*] or an ISO country code. Required for grids with resolutions
68+
higher than 5 arc-minutes (i.e., ``"05m"``).
69+
registration
70+
Grid registration type. Either ``"pixel"`` for pixel registration or
71+
``"gridline"`` for gridline registration. Default is ``None``, which means
72+
``"gridline"`` for all resolutions except ``"01m"`` which is ``"pixel"`` only.
73+
component
74+
By default, the east-west deflection (``component="east"``) is returned,
75+
set ``component="north"`` to return the north-south deflection.
76+
77+
Returns
78+
-------
79+
grid
80+
The Earth east-west or north-south deflection grid. Coordinates are latitude
81+
and longitude in degrees. Deflection values are in micro-radians, where
82+
positive (negative) values indicate a deflection to the east or north (west
83+
or south).
84+
85+
Note
86+
----
87+
The registration and coordinate system type of the returned
88+
:class:`xarray.DataArray` grid can be accessed via the GMT accessors (i.e.,
89+
``grid.gmt.registration`` and ``grid.gmt.gtype`` respectively). However, these
90+
properties may be lost after specific grid operations (such as slicing) and will
91+
need to be manually set before passing the grid to any PyGMT data processing or
92+
plotting functions. Refer to :class:`pygmt.GMTDataArrayAccessor` for detailed
93+
explanations and workarounds.
94+
95+
Examples
96+
--------
97+
98+
>>> from pygmt.datasets import load_earth_deflection
99+
>>> # load the default grid for east-west deflection (gridline-registered
100+
>>> # 1 arc-degree grid)
101+
>>> grid = load_earth_deflection()
102+
>>> # load the default grid for north-south deflection
103+
>>> grid = load_earth_deflection(component="north")
104+
>>> # load the 30 arc-minutes grid with "gridline" registration
105+
>>> grid = load_earth_deflection(resolution="30m", registration="gridline")
106+
>>> # load high-resolution (5 arc-minutes) grid for a specific region
107+
>>> grid = load_earth_deflection(
108+
... resolution="05m", region=[120, 160, 30, 60], registration="gridline"
109+
... )
110+
"""
111+
prefix = "earth_ndefl" if component == "north" else "earth_edefl"
112+
grid = _load_remote_dataset(
113+
name=prefix,
114+
prefix=prefix,
115+
resolution=resolution,
116+
region=region,
117+
registration=registration,
118+
)
119+
return grid

pygmt/datasets/load_remote_dataset.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ class GMTRemoteDataset(NamedTuple):
110110
"01m": Resolution("01m", registrations=["gridline"], tiled=True),
111111
},
112112
),
113+
"earth_edefl": GMTRemoteDataset(
114+
description="IGPP Earth east-west deflection",
115+
units="micro-radians",
116+
extra_attributes={"horizontal_datum": "WGS84"},
117+
resolutions={
118+
"01d": Resolution("01d"),
119+
"30m": Resolution("30m"),
120+
"20m": Resolution("20m"),
121+
"15m": Resolution("15m"),
122+
"10m": Resolution("10m"),
123+
"06m": Resolution("06m"),
124+
"05m": Resolution("05m", tiled=True),
125+
"04m": Resolution("04m", tiled=True),
126+
"03m": Resolution("03m", tiled=True),
127+
"02m": Resolution("02m", tiled=True),
128+
"01m": Resolution("01m", registrations=["pixel"], tiled=True),
129+
},
130+
),
113131
"earth_faa": GMTRemoteDataset(
114132
description="IGPP Earth free-air anomaly",
115133
units="mGal",
@@ -295,6 +313,24 @@ class GMTRemoteDataset(NamedTuple):
295313
"07m": Resolution("07m", registrations=["gridline"]),
296314
},
297315
),
316+
"earth_ndefl": GMTRemoteDataset(
317+
description="IGPP Earth north-south deflection",
318+
units="micro-radians",
319+
extra_attributes={"horizontal_datum": "WGS84"},
320+
resolutions={
321+
"01d": Resolution("01d"),
322+
"30m": Resolution("30m"),
323+
"20m": Resolution("20m"),
324+
"15m": Resolution("15m"),
325+
"10m": Resolution("10m"),
326+
"06m": Resolution("06m"),
327+
"05m": Resolution("05m", tiled=True),
328+
"04m": Resolution("04m", tiled=True),
329+
"03m": Resolution("03m", tiled=True),
330+
"02m": Resolution("02m", tiled=True),
331+
"01m": Resolution("01m", registrations=["pixel"], tiled=True),
332+
},
333+
),
298334
"earth_vgg": GMTRemoteDataset(
299335
description="IGPP Earth vertical gravity gradient",
300336
units="Eotvos",

pygmt/helpers/caching.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def cache_data():
1515
"@earth_age_01d_g",
1616
"@earth_day_01d",
1717
"@earth_dist_01d",
18+
"@earth_edefl_01d",
1819
"@earth_faa_01d_g",
1920
"@earth_faaerror_01d_g",
2021
"@earth_gebco_01d_g",
@@ -27,6 +28,7 @@ def cache_data():
2728
"@earth_mdt_01d_g",
2829
"@earth_mdt_07m_g",
2930
"@earth_mss_01d_g",
31+
"@earth_ndefl_01d",
3032
"@earth_night_01d",
3133
"@earth_relief_01d_g",
3234
"@earth_relief_01d_p",
@@ -51,12 +53,14 @@ def cache_data():
5153
"@N30E060.earth_age_01m_g.nc",
5254
"@N30E090.earth_age_01m_g.nc",
5355
"@N00W030.earth_dist_01m_g.nc",
56+
"@N00W030.earth_edefl_01m_p.nc",
5457
"@N00W030.earth_faa_01m_p.nc",
5558
"@N00W030.earth_faaerror_01m_p.nc",
5659
"@N00W030.earth_geoid_01m_g.nc",
5760
"@S30W060.earth_mag_02m_p.nc",
5861
"@S30W120.earth_mag4km_02m_p.nc",
5962
"@N30E090.earth_mss_01m_g.nc",
63+
"@N30E090.earth_ndefl_01m_p.nc",
6064
"@N00W090.earth_relief_03m_p.nc",
6165
"@N00E135.earth_relief_30s_g.nc",
6266
"@N00W010.earth_relief_15s_p.nc",
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""
2+
Test basic functionality for loading IGPP Earth east-west and south-north deflection
3+
datasets.
4+
"""
5+
6+
import numpy as np
7+
import numpy.testing as npt
8+
from pygmt.datasets import load_earth_deflection
9+
10+
11+
def test_earth_edefl_01d():
12+
"""
13+
Test some properties of the Earth east-west deflection 01d data.
14+
"""
15+
data = load_earth_deflection(resolution="01d")
16+
assert data.name == "z"
17+
assert data.attrs["long_name"] == "edefl (microradians)"
18+
assert data.attrs["description"] == "IGPP Earth east-west deflection"
19+
assert data.attrs["units"] == "micro-radians"
20+
assert data.attrs["horizontal_datum"] == "WGS84"
21+
assert data.shape == (181, 361)
22+
assert data.gmt.registration == 0
23+
npt.assert_allclose(data.lat, np.arange(-90, 91, 1))
24+
npt.assert_allclose(data.lon, np.arange(-180, 181, 1))
25+
npt.assert_allclose(data.min(), -142.64, atol=0.04)
26+
npt.assert_allclose(data.max(), 178.32, atol=0.04)
27+
28+
29+
def test_earth_edefl_01d_with_region():
30+
"""
31+
Test loading low-resolution Earth east-west deflection with "region".
32+
"""
33+
data = load_earth_deflection(resolution="01d", region=[-10, 10, -5, 5])
34+
assert data.shape == (11, 21)
35+
assert data.gmt.registration == 0
36+
npt.assert_allclose(data.lat, np.arange(-5, 6, 1))
37+
npt.assert_allclose(data.lon, np.arange(-10, 11, 1))
38+
npt.assert_allclose(data.min(), -28.92, atol=0.04)
39+
npt.assert_allclose(data.max(), 24.72, atol=0.04)
40+
41+
42+
def test_earth_edefl_01m_default_registration():
43+
"""
44+
Test that the grid returned by default for the 1 arc-minute resolution has a "pixel"
45+
registration.
46+
"""
47+
data = load_earth_deflection(resolution="01m", region=[-10, -9, 3, 5])
48+
assert data.shape == (120, 60)
49+
assert data.gmt.registration == 1
50+
npt.assert_allclose(data.coords["lat"].data.min(), 3.008333333)
51+
npt.assert_allclose(data.coords["lat"].data.max(), 4.991666666)
52+
npt.assert_allclose(data.coords["lon"].data.min(), -9.99166666)
53+
npt.assert_allclose(data.coords["lon"].data.max(), -9.00833333)
54+
npt.assert_allclose(data.min(), -62.24, atol=0.04)
55+
npt.assert_allclose(data.max(), 15.52, atol=0.04)
56+
57+
58+
def test_earth_ndefl_01d():
59+
"""
60+
Test some properties of the Earth north-south deflection 01d data.
61+
"""
62+
data = load_earth_deflection(resolution="01d", component="north")
63+
assert data.name == "z"
64+
assert data.attrs["long_name"] == "ndefl (microradians)"
65+
assert data.attrs["description"] == "IGPP Earth north-south deflection"
66+
assert data.attrs["units"] == "micro-radians"
67+
assert data.attrs["horizontal_datum"] == "WGS84"
68+
assert data.shape == (181, 361)
69+
assert data.gmt.registration == 0
70+
npt.assert_allclose(data.lat, np.arange(-90, 91, 1))
71+
npt.assert_allclose(data.lon, np.arange(-180, 181, 1))
72+
npt.assert_allclose(data.min(), -214.8, atol=0.04)
73+
npt.assert_allclose(data.max(), 163.04, atol=0.04)
74+
75+
76+
def test_earth_ndefl_01d_with_region():
77+
"""
78+
Test loading low-resolution Earth north-south deflection with "region".
79+
"""
80+
data = load_earth_deflection(
81+
resolution="01d", region=[-10, 10, -5, 5], component="north"
82+
)
83+
assert data.shape == (11, 21)
84+
assert data.gmt.registration == 0
85+
npt.assert_allclose(data.lat, np.arange(-5, 6, 1))
86+
npt.assert_allclose(data.lon, np.arange(-10, 11, 1))
87+
npt.assert_allclose(data.min(), -48.08, atol=0.04)
88+
npt.assert_allclose(data.max(), 18.92, atol=0.04)
89+
90+
91+
def test_earth_ndefl_01m_default_registration():
92+
"""
93+
Test that the grid returned by default for the 1 arc-minute resolution has a "pixel"
94+
registration.
95+
"""
96+
data = load_earth_deflection(
97+
resolution="01m", region=[-10, -9, 3, 5], component="north"
98+
)
99+
assert data.shape == (120, 60)
100+
assert data.gmt.registration == 1
101+
npt.assert_allclose(data.coords["lat"].data.min(), 3.008333333)
102+
npt.assert_allclose(data.coords["lat"].data.max(), 4.991666666)
103+
npt.assert_allclose(data.coords["lon"].data.min(), -9.99166666)
104+
npt.assert_allclose(data.coords["lon"].data.max(), -9.00833333)
105+
npt.assert_allclose(data.min(), -107.04, atol=0.04)
106+
npt.assert_allclose(data.max(), 20.28, atol=0.04)

0 commit comments

Comments
 (0)