11"""
2- GMT accessor methods .
2+ GMT accessor for :class:`xarray.DataArray` .
33"""
44from pathlib import Path
55
1111@xr .register_dataarray_accessor ("gmt" )
1212class GMTDataArrayAccessor :
1313 """
14- GMT extension for :class:`xarray.DataArray`.
14+ GMT accessor for :class:`xarray.DataArray`.
1515
16- The extension provides easy ways to access and change the GMT specific
17- properties about grids. Currently, two properties are available:
16+ The accessor extends :class:`xarray.DataArray` to store GMT-specific
17+ properties about grids, which are important for PyGMT to correctly process
18+ and plot the grids.
1819
19- - ``registration``: Gridline (0) or Pixel (1) registration
20- - ``gtype``: Cartesian (0) or Geographic (1) coordinate system
20+ Attributes
21+ ----------
2122
22- You can access these GMT specific properties about your grid as follows:
23+ registration : int
24+ Registration type of the grid, either 0 (Gridline) or 1 (Pixel).
25+ gtype : int
26+ Coordinate system type of the grid, either 0 (Cartesian) or 1
27+ (Geographic).
28+
29+ Notes
30+ -----
31+
32+ Due to the limitations of xarray accessors, the GMT accessors are created
33+ once per :class:`xarray.DataArray` instance. You may lose these
34+ GMT-specific properties when manipulating grids (e.g., arithmetic and slice
35+ operations) or when accessing a :class:`xarray.DataArray` from a
36+ :class:`xarray.Dataset`. In these cases, you need to manually set these
37+ properties before passing the grid to PyGMT.
38+
39+ Examples
40+ --------
41+
42+ For GMT's built-in remote datasets, these GMT-specific properties are
43+ automatically determined and you can access them as follows:
2344
2445 >>> from pygmt.datasets import load_earth_relief
2546 >>> # Use the global Earth relief grid with 1 degree spacing
@@ -31,7 +52,10 @@ class GMTDataArrayAccessor:
3152 >>> grid.gmt.gtype
3253 1
3354
34- You can also set the GMT specific properties for grids created by yourself:
55+ For :class:`xarray.DataArray` grids created by yourself, grid properties
56+ ``registration`` and ``gtype`` default to 0 (i.e., a gridline-registered,
57+ Cartesian grid). You need to set the correct properties before
58+ passing it to PyGMT functions:
3559
3660 >>> import numpy as np
3761 >>> import pygmt
@@ -45,9 +69,58 @@ class GMTDataArrayAccessor:
4569 >>> grid = xr.DataArray(
4670 ... data, coords=[("latitude", lat), ("longitude", lon)]
4771 ... )
72+ >>> # default to a gridline-registrated Cartesian grid
73+ >>> grid.gmt.registration, grid.gmt.gtype
74+ (0, 0)
4875 >>> # set it to a gridline-registered geographic grid
4976 >>> grid.gmt.registration = 0
5077 >>> grid.gmt.gtype = 1
78+ >>> grid.gmt.registration, grid.gmt.gtype
79+ (0, 1)
80+
81+ Note that the accessors are created once per :class:`xarray.DataArray`
82+ instance, so you may lose these GMT-specific properties after manipulating
83+ your grid.
84+
85+ Inplace assignment operators like ``*=`` don't create new instances, so the
86+ properties are still kept:
87+
88+ >>> grid *= 2.0
89+ >>> grid.gmt.registration, grid.gmt.gtype
90+ (0, 1)
91+
92+ Other grid operations (e.g., arithmetic or slice operations) create new
93+ instances, so the properties will be lost:
94+
95+ >>> # grid2 is a slice of the original grid
96+ >>> grid2 = grid[0:30, 50:80]
97+ >>> # properties are reset to the default values for new instance
98+ >>> grid2.gmt.registration, grid2.gmt.gtype
99+ (0, 0)
100+ >>> # need to set these properties before passing the grid to PyGMT
101+ >>> grid2.gmt.registration = grid.gmt.registration
102+ >>> grid2.gmt.gtype = grid.gmt.gtype
103+ >>> grid2.gmt.registration, grid2.gmt.gtype
104+ (0, 1)
105+
106+ Accesing a :class:`xarray.DataArray` from a :class:`xarray.Dataset` always
107+ creates new instances, so these properties are always lost. The workaround
108+ is to assign the :class:`xarray.DataArray` into a variable:
109+
110+ >>> ds = xr.Dataset({"zval": grid})
111+ >>> ds.zval.gmt.registration, ds.zval.gmt.gtype
112+ (0, 0)
113+ >>> # manually set these properties won't work as expected
114+ >>> ds.zval.gmt.registration, ds.zval.gmt.gtype = 0, 1
115+ >>> ds.zval.gmt.registration, ds.zval.gmt.gtype
116+ (0, 0)
117+ >>> # workaround: assign the DataArray into a variable
118+ >>> zval = ds.zval
119+ >>> zval.gmt.registration, zval.gmt.gtype
120+ (0, 0)
121+ >>> zval.gmt.registration, zval.gmt.gtype = 0, 1
122+ >>> zval.gmt.registration, zval.gmt.gtype
123+ (0, 1)
51124 """
52125
53126 def __init__ (self , xarray_obj ):
@@ -72,34 +145,32 @@ def __init__(self, xarray_obj):
72145 @property
73146 def registration (self ):
74147 """
75- Registration type of the grid, either Gridline (0 ) or Pixel (1 ).
148+ Registration type of the grid, either 0 (Gridline ) or 1 (Pixel ).
76149 """
77150 return self ._registration
78151
79152 @registration .setter
80153 def registration (self , value ):
81- if value in (0 , 1 ):
82- self ._registration = value
83- else :
154+ if value not in (0 , 1 ):
84155 raise GMTInvalidInput (
85156 f"Invalid grid registration value: { value } , should be either "
86157 "0 for Gridline registration or 1 for Pixel registration."
87158 )
159+ self ._registration = value
88160
89161 @property
90162 def gtype (self ):
91163 """
92- Coordinate system type of the grid, either Cartesian (0 ) or Geographic
93- (1 ).
164+ Coordinate system type of the grid, either 0 (Cartesian ) or 1
165+ (Geographic ).
94166 """
95167 return self ._gtype
96168
97169 @gtype .setter
98170 def gtype (self , value ):
99- if value in (0 , 1 ):
100- self ._gtype = value
101- else :
171+ if value not in (0 , 1 ):
102172 raise GMTInvalidInput (
103173 f"Invalid coordinate system type: { value } , should be "
104174 "either 0 for Cartesian or 1 for Geographic."
105175 )
176+ self ._gtype = value
0 commit comments