Skip to content

Commit 7544245

Browse files
authored
Correctly reserve the grid data dtype by converting ctypes array to numpy array with np.ctypeslib.as_array (#3446)
1 parent f7110e2 commit 7544245

File tree

3 files changed

+42
-41
lines changed

3 files changed

+42
-41
lines changed

pygmt/datatypes/grid.py

+32-30
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,15 @@ class _GMT_GRID(ctp.Structure): # noqa: N801
4040
... print(header.pad[:])
4141
... print(header.mem_layout, header.nan_value, header.xy_off)
4242
... # The x and y coordinates
43-
... print(grid.x[: header.n_columns])
44-
... print(grid.y[: header.n_rows])
43+
... x = np.ctypeslib.as_array(grid.x, shape=(header.n_columns,)).copy()
44+
... y = np.ctypeslib.as_array(grid.y, shape=(header.n_rows,)).copy()
4545
... # The data array (with paddings)
46-
... data = np.reshape(
47-
... grid.data[: header.mx * header.my], (header.my, header.mx)
48-
... )
46+
... data = np.ctypeslib.as_array(
47+
... grid.data, shape=(header.my, header.mx)
48+
... ).copy()
4949
... # The data array (without paddings)
5050
... pad = header.pad[:]
5151
... data = data[pad[2] : header.my - pad[3], pad[0] : header.mx - pad[1]]
52-
... print(data)
5352
14 8 1
5453
[-55.0, -47.0, -24.0, -10.0] 190.0 981.0 [1.0, 1.0]
5554
1.0 0.0
@@ -61,22 +60,26 @@ class _GMT_GRID(ctp.Structure): # noqa: N801
6160
18 1 12 18
6261
[2, 2, 2, 2]
6362
b'' nan 0.5
64-
[-54.5, -53.5, -52.5, -51.5, -50.5, -49.5, -48.5, -47.5]
65-
[-10.5, -11.5, -12.5, -13.5, -14.5, -15.5, ..., -22.5, -23.5]
66-
[[347.5 331.5 309. 282. 190. 208. 299.5 348. ]
67-
[349. 313. 325.5 247. 191. 225. 260. 452.5]
68-
[345.5 320. 335. 292. 207.5 247. 325. 346.5]
69-
[450.5 395.5 366. 248. 250. 354.5 550. 797.5]
70-
[494.5 488.5 357. 254.5 286. 484.5 653.5 930. ]
71-
[601. 526.5 535. 299. 398.5 645. 797.5 964. ]
72-
[308. 595.5 555.5 556. 580. 770. 927. 920. ]
73-
[521.5 682.5 796. 886. 571.5 638.5 739.5 881.5]
74-
[310. 521.5 757. 570.5 538.5 524. 686.5 794. ]
75-
[561.5 539. 446.5 481.5 439.5 553. 726.5 981. ]
76-
[557. 435. 385.5 345.5 413.5 496. 519.5 833.5]
77-
[373. 367.5 349. 352.5 419.5 428. 570. 667.5]
78-
[383. 284.5 344.5 394. 491. 556.5 578.5 618.5]
79-
[347.5 344.5 386. 640.5 617. 579. 646.5 671. ]]
63+
>>> x
64+
array([-54.5, -53.5, -52.5, -51.5, -50.5, -49.5, -48.5, -47.5])
65+
>>> y
66+
array([-10.5, -11.5, -12.5, -13.5, ..., -20.5, -21.5, -22.5, -23.5])
67+
>>> data
68+
array([[347.5, 331.5, 309. , 282. , 190. , 208. , 299.5, 348. ],
69+
[349. , 313. , 325.5, 247. , 191. , 225. , 260. , 452.5],
70+
[345.5, 320. , 335. , 292. , 207.5, 247. , 325. , 346.5],
71+
[450.5, 395.5, 366. , 248. , 250. , 354.5, 550. , 797.5],
72+
[494.5, 488.5, 357. , 254.5, 286. , 484.5, 653.5, 930. ],
73+
[601. , 526.5, 535. , 299. , 398.5, 645. , 797.5, 964. ],
74+
[308. , 595.5, 555.5, 556. , 580. , 770. , 927. , 920. ],
75+
[521.5, 682.5, 796. , 886. , 571.5, 638.5, 739.5, 881.5],
76+
[310. , 521.5, 757. , 570.5, 538.5, 524. , 686.5, 794. ],
77+
[561.5, 539. , 446.5, 481.5, 439.5, 553. , 726.5, 981. ],
78+
[557. , 435. , 385.5, 345.5, 413.5, 496. , 519.5, 833.5],
79+
[373. , 367.5, 349. , 352.5, 419.5, 428. , 570. , 667.5],
80+
[383. , 284.5, 344.5, 394. , 491. , 556.5, 578.5, 618.5],
81+
[347.5, 344.5, 386. , 640.5, 617. , 579. , 646.5, 671. ]],
82+
dtype=float32)
8083
"""
8184

8285
_fields_: ClassVar = [
@@ -126,7 +129,8 @@ def to_dataarray(self) -> xr.DataArray:
126129
[450.5, 395.5, 366. , 248. , 250. , 354.5, 550. , 797.5],
127130
[345.5, 320. , 335. , 292. , 207.5, 247. , 325. , 346.5],
128131
[349. , 313. , 325.5, 247. , 191. , 225. , 260. , 452.5],
129-
[347.5, 331.5, 309. , 282. , 190. , 208. , 299.5, 348. ]])
132+
[347.5, 331.5, 309. , 282. , 190. , 208. , 299.5, 348. ]],
133+
dtype=float32)
130134
Coordinates:
131135
* lat (lat) float64... -23.5 -22.5 -21.5 -20.5 ... -12.5 -11.5 -10.5
132136
* lon (lon) float64... -54.5 -53.5 -52.5 -51.5 -50.5 -49.5 -48.5 -47.5
@@ -169,16 +173,14 @@ def to_dataarray(self) -> xr.DataArray:
169173
# Get dimensions and their attributes from the header.
170174
dims, dim_attrs = header.dims, header.dim_attrs
171175
# The coordinates, given as a tuple of the form (dims, data, attrs)
172-
coords = [
173-
(dims[0], self.y[: header.n_rows], dim_attrs[0]),
174-
(dims[1], self.x[: header.n_columns], dim_attrs[1]),
175-
]
176+
x = np.ctypeslib.as_array(self.x, shape=(header.n_columns,)).copy()
177+
y = np.ctypeslib.as_array(self.y, shape=(header.n_rows,)).copy()
178+
coords = [(dims[0], y, dim_attrs[0]), (dims[1], x, dim_attrs[1])]
176179

177180
# The data array without paddings
181+
data = np.ctypeslib.as_array(self.data, shape=(header.my, header.mx)).copy()
178182
pad = header.pad[:]
179-
data = np.reshape(self.data[: header.mx * header.my], (header.my, header.mx))[
180-
pad[2] : header.my - pad[3], pad[0] : header.mx - pad[1]
181-
]
183+
data = data[pad[2] : header.my - pad[3], pad[0] : header.mx - pad[1]]
182184

183185
# Create the xarray.DataArray object
184186
grid = xr.DataArray(

pygmt/datatypes/image.py

+9-10
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,12 @@ class _GMT_IMAGE(ctp.Structure): # noqa: N801
3838
... # Image-specific attributes.
3939
... print(image.type, image.n_indexed_colors)
4040
... # The x and y coordinates
41-
... x = image.x[: header.n_columns]
42-
... y = image.y[: header.n_rows]
41+
... x = np.ctypeslib.as_array(image.x, shape=(header.n_columns,)).copy()
42+
... y = np.ctypeslib.as_array(image.y, shape=(header.n_rows,)).copy()
4343
... # The data array (with paddings)
44-
... data = np.reshape(
45-
... image.data[: header.n_bands * header.mx * header.my],
46-
... (header.my, header.mx, header.n_bands),
47-
... )
44+
... data = np.ctypeslib.as_array(
45+
... image.data, shape=(header.my, header.mx, header.n_bands)
46+
... ).copy()
4847
... # The data array (without paddings)
4948
... pad = header.pad[:]
5049
... data = data[pad[2] : header.my - pad[3], pad[0] : header.mx - pad[1], :]
@@ -60,10 +59,10 @@ class _GMT_IMAGE(ctp.Structure): # noqa: N801
6059
[2, 2, 2, 2]
6160
b'BRPa' 0.5
6261
1 0
63-
>>> x
64-
[-179.5, -178.5, ..., 178.5, 179.5]
65-
>>> y
66-
[89.5, 88.5, ..., -88.5, -89.5]
62+
>>> x # doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS
63+
array([-179.5, -178.5, ..., 178.5, 179.5])
64+
>>> y # doctest: +NORMALIZE_WHITESPACE, +ELLIPSIS
65+
array([ 89.5, 88.5, ..., -88.5, -89.5])
6766
>>> data.shape
6867
(180, 360, 3)
6968
>>> data.min(), data.max()

pygmt/tests/test_sphinterpolate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ def test_sphinterpolate_no_outgrid(mars):
4141
npt.assert_allclose(temp_grid.max(), 14628.144)
4242
npt.assert_allclose(temp_grid.min(), -6908.1987)
4343
npt.assert_allclose(temp_grid.median(), 118.96849)
44-
npt.assert_allclose(temp_grid.mean(), 272.60578)
44+
npt.assert_allclose(temp_grid.mean(), 272.60593)

0 commit comments

Comments
 (0)