Skip to content

Commit 94086f7

Browse files
committed
Use enums GridReg and GridType in gmt accessors
1 parent 8c7f8f6 commit 94086f7

File tree

1 file changed

+95
-67
lines changed

1 file changed

+95
-67
lines changed

pygmt/accessors.py

Lines changed: 95 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pathlib import Path
77

88
import xarray as xr
9+
from pygmt.enums import GridReg, GridType
910
from pygmt.exceptions import GMTInvalidInput
1011
from pygmt.src.grdinfo import grdinfo
1112

@@ -15,110 +16,131 @@ class GMTDataArrayAccessor:
1516
"""
1617
GMT accessor for :class:`xarray.DataArray`.
1718
18-
The accessor extends :class:`xarray.DataArray` to store GMT-specific
19-
properties about grids, which are important for PyGMT to correctly process
20-
and plot the grids.
19+
The *gmt* accessor extends :class:`xarray.DataArray` to store GMT-specific
20+
properties for grids, which are important for PyGMT to correctly process and plot
21+
the grids.
22+
23+
The *gmt* accessor contains following properties:
24+
25+
- ``registration``: Grid registration type, either ``GridReg.GRIDLINE`` or
26+
``GridReg.PIXEL``.
27+
- ``gtype``: Grid coordinate system type, either ``GridType.CARTESIAN`` or
28+
``GridType.GEOGRAPHIC``.
29+
30+
and can be accessed like ``grid.gmt.registration`` and ``grid.gmt.gtype``.
2131
2232
Notes
2333
-----
24-
25-
Due to the limitations of xarray accessors, the GMT accessors are created
26-
once per :class:`xarray.DataArray` instance. You may lose these
27-
GMT-specific properties when manipulating grids (e.g., arithmetic and slice
28-
operations) or when accessing a :class:`xarray.DataArray` from a
29-
:class:`xarray.Dataset`. In these cases, you need to manually set these
30-
properties before passing the grid to PyGMT.
34+
Due to the limitations of xarray accessors, the GMT accessors are created once per
35+
:class:`xarray.DataArray` instance. You may lose these GMT-specific properties when
36+
manipulating grids (e.g., arithmetic and slice operations) or when accessing a
37+
:class:`xarray.DataArray` from a :class:`xarray.Dataset`. In these cases, you need
38+
to manually set these properties before passing the grid to PyGMT.
3139
3240
Examples
3341
--------
34-
35-
For GMT's built-in remote datasets, these GMT-specific properties are
36-
automatically determined and you can access them as follows:
42+
For GMT's built-in remote datasets, these GMT-specific properties are automatically
43+
determined and you can access them as follows:
3744
3845
>>> from pygmt.datasets import load_earth_relief
3946
>>> # Use the global Earth relief grid with 1 degree spacing
4047
>>> grid = load_earth_relief(resolution="01d", registration="pixel")
41-
>>> # See if grid uses Gridline (0) or Pixel (1) registration
48+
>>> # See if grid is Gridline or Pixel registration
4249
>>> grid.gmt.registration
43-
1
44-
>>> # See if grid uses Cartesian (0) or Geographic (1) coordinate system
50+
<GridReg.PIXEL: 1>
51+
>>> # See if grid is in Cartesian or Geographic coordinate system
4552
>>> grid.gmt.gtype
46-
1
53+
<GridType.GEOGRAPHIC: 1>
4754
48-
For :class:`xarray.DataArray` grids created by yourself, grid properties
49-
``registration`` and ``gtype`` default to 0 (i.e., a gridline-registered,
50-
Cartesian grid). You need to set the correct properties before
55+
For :class:`xarray.DataArray` grids created by yourself, ``registration`` and
56+
``gtype`` default to ``GridReg.GRIDLINE`` and ``GridType.CARTESIAN`` (i.e., a
57+
gridline-registered, Cartesian grid). You need to set the correct properties before
5158
passing it to PyGMT functions:
5259
5360
>>> import numpy as np
54-
>>> import pygmt
5561
>>> import xarray as xr
56-
>>> # create a DataArray in gridline coordinates of sin(lon) * cos(lat)
62+
>>> import pygmt
63+
>>> from pygmt.enums import GridReg, GridType
64+
>>> # Create a DataArray in gridline coordinates of sin(lon) * cos(lat)
5765
>>> interval = 2.5
5866
>>> lat = np.arange(90, -90 - interval, -interval)
5967
>>> lon = np.arange(0, 360 + interval, interval)
6068
>>> longrid, latgrid = np.meshgrid(lon, lat)
6169
>>> data = np.sin(np.deg2rad(longrid)) * np.cos(np.deg2rad(latgrid))
6270
>>> grid = xr.DataArray(data, coords=[("latitude", lat), ("longitude", lon)])
63-
>>> # default to a gridline-registered Cartesian grid
64-
>>> grid.gmt.registration, grid.gmt.gtype
65-
(0, 0)
66-
>>> # set it to a gridline-registered geographic grid
67-
>>> grid.gmt.registration = 0
68-
>>> grid.gmt.gtype = 1
69-
>>> grid.gmt.registration, grid.gmt.gtype
70-
(0, 1)
71-
72-
Note that the accessors are created once per :class:`xarray.DataArray`
73-
instance, so you may lose these GMT-specific properties after manipulating
74-
your grid.
71+
>>> # Default to a gridline-registrated Cartesian grid
72+
>>> grid.gmt.registration
73+
<GridReg.GRIDLINE: 0>
74+
>>> grid.gmt.gtype
75+
<GridType.CARTESIAN: 0>
76+
>>> # Manually set it to a gridline-registered geographic grid
77+
>>> grid.gmt.registration = GridReg.GRIDLINE
78+
>>> grid.gmt.gtype = GridType.GEOGRAPHIC
79+
>>> grid.gmt.registration
80+
<GridReg.GRIDLINE: 0>
81+
>>> grid.gmt.gtype
82+
<GridType.GEOGRAPHIC: 1>
83+
84+
Note that the accessors are created once per :class:`xarray.DataArray` instance, so
85+
you may lose these GMT-specific properties after manipulating your grid.
7586
7687
Inplace assignment operators like ``*=`` don't create new instances, so the
7788
properties are still kept:
7889
7990
>>> grid *= 2.0
80-
>>> grid.gmt.registration, grid.gmt.gtype
81-
(0, 1)
91+
>>> grid.gmt.registration
92+
<GridReg.GRIDLINE: 0>
93+
>>> grid.gmt.gtype
94+
<GridType.GEOGRAPHIC: 1>
8295
83-
Other grid operations (e.g., arithmetic or slice operations) create new
84-
instances, so the properties will be lost:
96+
Other grid operations (e.g., arithmetic or slice operations) create new instances,
97+
so the properties will be lost:
8598
8699
>>> # grid2 is a slice of the original grid
87100
>>> grid2 = grid[0:30, 50:80]
88-
>>> # properties are reset to the default values for new instance
89-
>>> grid2.gmt.registration, grid2.gmt.gtype
90-
(0, 0)
91-
>>> # need to set these properties before passing the grid to PyGMT
101+
>>> # Properties are reset to the default values for new instance
102+
>>> grid2.gmt.registration
103+
<GridReg.GRIDLINE: 0>
104+
>>> grid2.gmt.gtype
105+
<GridType.CARTESIAN: 0>
106+
>>> # Need to set these properties before passing the grid to PyGMT
92107
>>> grid2.gmt.registration = grid.gmt.registration
93108
>>> grid2.gmt.gtype = grid.gmt.gtype
94-
>>> grid2.gmt.registration, grid2.gmt.gtype
95-
(0, 1)
109+
>>> grid2.gmt.registration
110+
<GridReg.GRIDLINE: 0>
111+
>>> grid2.gmt.gtype
112+
<GridType.GEOGRAPHIC: 1>
96113
97-
Accessing a :class:`xarray.DataArray` from a :class:`xarray.Dataset` always
98-
creates new instances, so these properties are always lost. The workaround
99-
is to assign the :class:`xarray.DataArray` into a variable:
114+
Accessing a :class:`xarray.DataArray` from a :class:`xarray.Dataset` always creates
115+
new instances, so these properties are always lost. The workaround is to assign the
116+
:class:`xarray.DataArray` into a variable:
100117
101118
>>> ds = xr.Dataset({"zval": grid})
119+
>>> ds.zval.gmt.registration
120+
<GridReg.GRIDLINE: 0>
121+
>>> ds.zval.gmt.gtype
122+
<GridType.CARTESIAN: 0>
123+
>>> # Manually set these properties won't work as expected
124+
>>> ds.zval.gmt.registration = GridReg.GRIDLINE
125+
>>> ds.zval.gmt.gtype = GridType.GEOGRAPHIC
102126
>>> ds.zval.gmt.registration, ds.zval.gmt.gtype
103-
(0, 0)
104-
>>> # manually set these properties won't work as expected
105-
>>> ds.zval.gmt.registration, ds.zval.gmt.gtype = 0, 1
106-
>>> ds.zval.gmt.registration, ds.zval.gmt.gtype
107-
(0, 0)
127+
(<GridReg.GRIDLINE: 0>, <GridType.CARTESIAN: 0>)
108128
>>> # workaround: assign the DataArray into a variable
109129
>>> zval = ds.zval
110130
>>> zval.gmt.registration, zval.gmt.gtype
111-
(0, 0)
112-
>>> zval.gmt.registration, zval.gmt.gtype = 0, 1
131+
(<GridReg.GRIDLINE: 0>, <GridType.CARTESIAN: 0>)
132+
>>> zval.gmt.registration = GridReg.GRIDLINE
133+
>>> zval.gmt.gtype = GridType.GEOGRAPHIC
113134
>>> zval.gmt.registration, zval.gmt.gtype
114-
(0, 1)
135+
(<GridReg.GRIDLINE: 0>, <GridType.GEOGRAPHIC: 1>)
115136
"""
116137

117138
def __init__(self, xarray_obj):
118139
self._obj = xarray_obj
140+
119141
# Default to Gridline registration and Cartesian grid type
120-
self._registration = 0
121-
self._gtype = 0
142+
self._registration = GridReg.GRIDLINE
143+
self._gtype = GridType.CARTESIAN
122144

123145
# If the source file exists, get grid registration and grid type from the last
124146
# two columns of the shortened summary information of grdinfo.
@@ -131,33 +153,39 @@ def __init__(self, xarray_obj):
131153
@property
132154
def registration(self):
133155
"""
134-
Registration type of the grid, either 0 (Gridline) or 1 (Pixel).
156+
Registration type of the grid, either ``GridReg.GRIDLINE`` or
157+
``GridReg.PIXEL``.
135158
"""
136159
return self._registration
137160

138161
@registration.setter
139162
def registration(self, value):
140-
if value not in {0, 1}:
163+
if value in {"gridline", "pixel"}: # Support for string-type values
164+
value = GridReg[value.upper()]
165+
if value not in GridReg:
141166
msg = (
142-
f"Invalid grid registration value: {value}, should be either "
143-
"0 for Gridline registration or 1 for Pixel registration."
167+
f"Invalid grid registration: {value}. "
168+
"Should be either GridReg.GRIDLINE or GridReg.PIXEL."
144169
)
145170
raise GMTInvalidInput(msg)
146-
self._registration = value
171+
self._registration = GridReg(value)
147172

148173
@property
149174
def gtype(self):
150175
"""
151-
Coordinate system type of the grid, either 0 (Cartesian) or 1 (Geographic).
176+
Coordinate system type of the grid, either ``GridType.CARTESIAN`` or
177+
``GridType.GEOGRAPHIC``.
152178
"""
153179
return self._gtype
154180

155181
@gtype.setter
156182
def gtype(self, value):
157-
if value not in {0, 1}:
183+
if value in {"cartesian", "geographic"}: # Support for string-type values
184+
value = GridType[value.upper()]
185+
if value not in GridType:
158186
msg = (
159-
f"Invalid coordinate system type: {value}, should be "
160-
"either 0 for Cartesian or 1 for Geographic."
187+
f"Invalid grid coordinate system type: '{value}'. "
188+
"Should be either GridType.CARTESIAN or GridType.GEOGRAPHIC."
161189
)
162190
raise GMTInvalidInput(msg)
163-
self._gtype = value
191+
self._gtype = GridType(value)

0 commit comments

Comments
 (0)