66from pathlib import Path
77
88import xarray as xr
9+ from pygmt .enums import GridRegistration , GridType
910from pygmt .exceptions import GMTInvalidInput
1011from pygmt .src .grdinfo import grdinfo
1112
@@ -15,110 +16,122 @@ 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. The *gmt* accessor contains the following properties:
2122
22- Notes
23- -----
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.
23+ - ``registration``: Grid registration type :class:`pygmt.enums.GridRegistration`.
24+ - ``gtype``: Grid coordinate system type :class:`pygmt.enums.GridType`.
3125
3226 Examples
3327 --------
34-
35- For GMT's built-in remote datasets, these GMT-specific properties are
36- automatically determined and you can access them as follows:
28+ For GMT's built-in remote datasets, these GMT-specific properties are automatically
29+ determined and you can access them as follows:
3730
3831 >>> from pygmt.datasets import load_earth_relief
3932 >>> # Use the global Earth relief grid with 1 degree spacing
4033 >>> grid = load_earth_relief(resolution="01d", registration="pixel")
41- >>> # See if grid uses Gridline (0) or Pixel (1) registration
34+ >>> # See if grid uses Gridline or Pixel registration
4235 >>> grid.gmt.registration
43- 1
44- >>> # See if grid uses Cartesian (0) or Geographic (1) coordinate system
36+ <GridRegistration.PIXEL: 1>
37+ >>> # See if grid is in Cartesian or Geographic coordinate system
4538 >>> grid.gmt.gtype
46- 1
39+ <GridType.GEOGRAPHIC: 1>
4740
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
51- passing it to PyGMT functions:
41+ For :class:`xarray.DataArray` grids created by yourself, ``registration`` and
42+ ``gtype `` default to ``GridRegistration.GRIDLINE `` and ``GridType.CARTESIAN`` (i.e.,
43+ a gridline-registered, Cartesian grid). You need to set the correct properties
44+ before passing it to PyGMT functions:
5245
5346 >>> import numpy as np
54- >>> import pygmt
5547 >>> import xarray as xr
56- >>> # create a DataArray in gridline coordinates of sin(lon) * cos(lat)
48+ >>> import pygmt
49+ >>> from pygmt.enums import GridRegistration, GridType
50+ >>> # Create a DataArray in gridline coordinates of sin(lon) * cos(lat)
5751 >>> interval = 2.5
5852 >>> lat = np.arange(90, -90 - interval, -interval)
5953 >>> lon = np.arange(0, 360 + interval, interval)
6054 >>> longrid, latgrid = np.meshgrid(lon, lat)
6155 >>> data = np.sin(np.deg2rad(longrid)) * np.cos(np.deg2rad(latgrid))
6256 >>> 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.
57+ >>> # Default to a gridline-registered Cartesian grid
58+ >>> grid.gmt.registration
59+ <GridRegistration.GRIDLINE: 0>
60+ >>> grid.gmt.gtype
61+ <GridType.CARTESIAN: 0>
62+ >>> # Manually set it to a gridline-registered geographic grid
63+ >>> grid.gmt.registration = GridRegistration.GRIDLINE
64+ >>> grid.gmt.gtype = GridType.GEOGRAPHIC
65+ >>> grid.gmt.registration
66+ <GridRegistration.GRIDLINE: 0>
67+ >>> grid.gmt.gtype
68+ <GridType.GEOGRAPHIC: 1>
69+
70+ Notes
71+ -----
72+ Due to the limitations of xarray accessors, the GMT accessors are created once per
73+ :class:`xarray.DataArray` instance. You may lose these GMT-specific properties when
74+ manipulating grids (e.g., arithmetic and slice operations) or when accessing a
75+ :class:`xarray.DataArray` from a :class:`xarray.Dataset`. In these cases, you need
76+ to manually set these properties before passing the grid to PyGMT.
7577
7678 Inplace assignment operators like ``*=`` don't create new instances, so the
7779 properties are still kept:
7880
7981 >>> grid *= 2.0
80- >>> grid.gmt.registration, grid.gmt.gtype
81- (0, 1)
82+ >>> grid.gmt.registration
83+ <GridRegistration.GRIDLINE: 0>
84+ >>> grid.gmt.gtype
85+ <GridType.GEOGRAPHIC: 1>
8286
83- Other grid operations (e.g., arithmetic or slice operations) create new
84- instances, so the properties will be lost:
87+ Other grid operations (e.g., arithmetic or slice operations) create new instances,
88+ so the properties will be lost:
8589
8690 >>> # grid2 is a slice of the original grid
8791 >>> 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
92+ >>> # Properties are reset to the default values for new instance
93+ >>> grid2.gmt.registration
94+ <GridRegistration.GRIDLINE: 0>
95+ >>> grid2.gmt.gtype
96+ <GridType.CARTESIAN: 0>
97+ >>> # Need to set these properties before passing the grid to PyGMT
9298 >>> grid2.gmt.registration = grid.gmt.registration
9399 >>> grid2.gmt.gtype = grid.gmt.gtype
94- >>> grid2.gmt.registration, grid2.gmt.gtype
95- (0, 1)
100+ >>> grid2.gmt.registration
101+ <GridRegistration.GRIDLINE: 0>
102+ >>> grid2.gmt.gtype
103+ <GridType.GEOGRAPHIC: 1>
96104
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:
105+ Accessing a :class:`xarray.DataArray` from a :class:`xarray.Dataset` always creates
106+ new instances, so these properties are always lost. The workaround is to assign the
107+ :class:`xarray.DataArray` into a variable:
100108
101109 >>> ds = xr.Dataset({"zval": grid})
110+ >>> ds.zval.gmt.registration
111+ <GridRegistration.GRIDLINE: 0>
112+ >>> ds.zval.gmt.gtype
113+ <GridType.CARTESIAN: 0>
114+ >>> # Manually set these properties won't work as expected
115+ >>> ds.zval.gmt.registration = GridRegistration.GRIDLINE
116+ >>> ds.zval.gmt.gtype = GridType.GEOGRAPHIC
102117 >>> 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)
118+ (<GridRegistration.GRIDLINE: 0>, <GridType.CARTESIAN: 0>)
108119 >>> # workaround: assign the DataArray into a variable
109120 >>> zval = ds.zval
110121 >>> zval.gmt.registration, zval.gmt.gtype
111- (0, 0)
112- >>> zval.gmt.registration, zval.gmt.gtype = 0, 1
122+ (<GridRegistration.GRIDLINE: 0>, <GridType.CARTESIAN: 0>)
123+ >>> zval.gmt.registration = GridRegistration.GRIDLINE
124+ >>> zval.gmt.gtype = GridType.GEOGRAPHIC
113125 >>> zval.gmt.registration, zval.gmt.gtype
114- (0, 1 )
126+ (<GridRegistration.GRIDLINE: 0>, <GridType.GEOGRAPHIC: 1> )
115127 """
116128
117129 def __init__ (self , xarray_obj ):
118130 self ._obj = xarray_obj
131+
119132 # Default to Gridline registration and Cartesian grid type
120- self ._registration = 0
121- self ._gtype = 0
133+ self ._registration = GridRegistration . GRIDLINE
134+ self ._gtype = GridType . CARTESIAN
122135
123136 # If the source file exists, get grid registration and grid type from the last
124137 # two columns of the shortened summary information of grdinfo.
@@ -131,33 +144,35 @@ def __init__(self, xarray_obj):
131144 @property
132145 def registration (self ):
133146 """
134- Registration type of the grid, either 0 (Gridline) or 1 (Pixel) .
147+ Grid registration type :class:`pygmt.enums.GridRegistration` .
135148 """
136149 return self ._registration
137150
138151 @registration .setter
139152 def registration (self , value ):
140- if value not in {0 , 1 }:
153+ # TODO(Python>=3.12): Simplify to `if value not in GridRegistration`.
154+ if value not in GridRegistration .__members__ .values ():
141155 msg = (
142- f"Invalid grid registration value: { value } , should be either "
143- "0 for Gridline registration or 1 for Pixel registration ."
156+ f"Invalid grid registration: ' { value } '. Should be either "
157+ "GridRegistration.GRIDLINE (0) or GridRegistration.PIXEL (1) ."
144158 )
145159 raise GMTInvalidInput (msg )
146- self ._registration = value
160+ self ._registration = GridRegistration ( value )
147161
148162 @property
149163 def gtype (self ):
150164 """
151- Coordinate system type of the grid, either 0 (Cartesian) or 1 (Geographic) .
165+ Grid coordinate system type :class:`pygmt.enums.GridType` .
152166 """
153167 return self ._gtype
154168
155169 @gtype .setter
156170 def gtype (self , value ):
157- if value not in {0 , 1 }:
171+ # TODO(Python>=3.12): Simplify to `if value not in GridType`.
172+ if value not in GridType .__members__ .values ():
158173 msg = (
159- f"Invalid coordinate system type: { value } , should be "
160- "either 0 for Cartesian or 1 for Geographic ."
174+ f"Invalid grid coordinate system type: ' { value } '. "
175+ "Should be either GridType.CARTESIAN (0) or GridType.GEOGRAPHIC (1) ."
161176 )
162177 raise GMTInvalidInput (msg )
163- self ._gtype = value
178+ self ._gtype = GridType ( value )
0 commit comments