6
6
from pathlib import Path
7
7
8
8
import xarray as xr
9
+ from pygmt .enums import GridReg , GridType
9
10
from pygmt .exceptions import GMTInvalidInput
10
11
from pygmt .src .grdinfo import grdinfo
11
12
@@ -15,110 +16,131 @@ class GMTDataArrayAccessor:
15
16
"""
16
17
GMT accessor for :class:`xarray.DataArray`.
17
18
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``.
21
31
22
32
Notes
23
33
-----
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.
31
39
32
40
Examples
33
41
--------
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:
37
44
38
45
>>> from pygmt.datasets import load_earth_relief
39
46
>>> # Use the global Earth relief grid with 1 degree spacing
40
47
>>> 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
42
49
>>> 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
45
52
>>> grid.gmt.gtype
46
- 1
53
+ <GridType.GEOGRAPHIC: 1>
47
54
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
51
58
passing it to PyGMT functions:
52
59
53
60
>>> import numpy as np
54
- >>> import pygmt
55
61
>>> 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)
57
65
>>> interval = 2.5
58
66
>>> lat = np.arange(90, -90 - interval, -interval)
59
67
>>> lon = np.arange(0, 360 + interval, interval)
60
68
>>> longrid, latgrid = np.meshgrid(lon, lat)
61
69
>>> data = np.sin(np.deg2rad(longrid)) * np.cos(np.deg2rad(latgrid))
62
70
>>> 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.
75
86
76
87
Inplace assignment operators like ``*=`` don't create new instances, so the
77
88
properties are still kept:
78
89
79
90
>>> 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>
82
95
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:
85
98
86
99
>>> # grid2 is a slice of the original grid
87
100
>>> 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
92
107
>>> grid2.gmt.registration = grid.gmt.registration
93
108
>>> 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>
96
113
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:
100
117
101
118
>>> 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
102
126
>>> 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>)
108
128
>>> # workaround: assign the DataArray into a variable
109
129
>>> zval = ds.zval
110
130
>>> 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
113
134
>>> zval.gmt.registration, zval.gmt.gtype
114
- (0, 1 )
135
+ (<GridReg.GRIDLINE: 0>, <GridType.GEOGRAPHIC: 1> )
115
136
"""
116
137
117
138
def __init__ (self , xarray_obj ):
118
139
self ._obj = xarray_obj
140
+
119
141
# 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
122
144
123
145
# If the source file exists, get grid registration and grid type from the last
124
146
# two columns of the shortened summary information of grdinfo.
@@ -131,33 +153,39 @@ def __init__(self, xarray_obj):
131
153
@property
132
154
def registration (self ):
133
155
"""
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``.
135
158
"""
136
159
return self ._registration
137
160
138
161
@registration .setter
139
162
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 :
141
166
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 ."
144
169
)
145
170
raise GMTInvalidInput (msg )
146
- self ._registration = value
171
+ self ._registration = GridReg ( value )
147
172
148
173
@property
149
174
def gtype (self ):
150
175
"""
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``.
152
178
"""
153
179
return self ._gtype
154
180
155
181
@gtype .setter
156
182
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 :
158
186
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 ."
161
189
)
162
190
raise GMTInvalidInput (msg )
163
- self ._gtype = value
191
+ self ._gtype = GridType ( value )
0 commit comments