Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GMTDataArrayAccessor: Fallback to default grid registration and gtype if the grid source file doesn't exist #2009

Merged
merged 15 commits into from
Feb 20, 2023
Merged
8 changes: 7 additions & 1 deletion pygmt/accessors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""
GMT accessor methods.
"""
from pathlib import Path

import xarray as xr
from pygmt.exceptions import GMTInvalidInput
from pygmt.src.grdinfo import grdinfo
Expand Down Expand Up @@ -52,12 +54,16 @@ def __init__(self, xarray_obj):
self._obj = xarray_obj
try:
self._source = self._obj.encoding["source"] # filepath to NetCDF source
if not Path(self._source).exists():
raise FileNotFoundError(
f"Grid source file {self._source} doesn't exist."
)
# Get grid registration and grid type from the last two columns of
# the shortened summary information of `grdinfo`.
self._registration, self._gtype = map(
int, grdinfo(self._source, per_column="n").split()[-2:]
)
except (KeyError, ValueError):
except (KeyError, ValueError, FileNotFoundError):
self._registration = 0 # Default to Gridline registration
self._gtype = 0 # Default to Cartesian grid type
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should change these lines to the following codes, which I think are more readable:

        self._source = self._obj.encoding.get("source")
        if self._source is not None and Path(self._source).exists():
            try:
                # Get grid registration and grid type from the last two columns of
                # the shortened summary information of `grdinfo`.
                self._registration, self._gtype = map(
                    int, grdinfo(self._source, per_column="n").split()[-2:]
                )
            except ValueError:
                self._registration = 0
                self._gtype = 0
        else:
            self._registration = 0
            self._gtype = 0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we will silently fallback to registration=0 and gtype=0 if grdinfo cannot determine the grid registration and type? Ok I guess, but please add the code comments back 🙂


Expand Down
31 changes: 31 additions & 0 deletions pygmt/tests/test_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
"""
import os
import sys
from pathlib import Path

import pytest
import xarray as xr
from packaging.version import Version
from pygmt import __gmt_version__, which
from pygmt.datasets import load_earth_relief
from pygmt.exceptions import GMTInvalidInput


Expand Down Expand Up @@ -101,3 +103,32 @@ def test_accessor_sliced_datacube():
assert grid.gmt.gtype == 1 # geographic coordinate type
finally:
os.remove(fname)


def test_accessor_grid_source_file_not_exist():
"""
Check that the accessor fallbacks to the default registration and gtype
when the grid source file (i.e., grid.encoding["source"]) doesn't exists.
seisman marked this conversation as resolved.
Show resolved Hide resolved
"""
# load the 05m earth relief grid, which is stored as tiles
seisman marked this conversation as resolved.
Show resolved Hide resolved
grid = load_earth_relief(
resolution="05m", region=[0, 5, -5, 5], registration="pixel"
)
# registration and gtype are correct
seisman marked this conversation as resolved.
Show resolved Hide resolved
assert grid.gmt.registration == 1
assert grid.gmt.gtype == 1
# the source grid file is defined but doesn't exists
seisman marked this conversation as resolved.
Show resolved Hide resolved
assert len(grid.encoding["source"]) > 0
seisman marked this conversation as resolved.
Show resolved Hide resolved
assert not Path(grid.encoding["source"]).exists()

# For a sliced grid, fallback to default registration and gtype,
# because the source grid file doesn't exists.
seisman marked this conversation as resolved.
Show resolved Hide resolved
sliced_grid = grid[1:3, 1:3]
assert sliced_grid.gmt.registration == 0
assert sliced_grid.gmt.gtype == 0

# Still possible to manually set registration and gtype
sliced_grid.gmt.registration = 1
sliced_grid.gmt.gtype = 1
assert sliced_grid.gmt.registration == 1
assert sliced_grid.gmt.gtype == 1