Skip to content

Allow passing region to GMTBackendEntrypoint.open_dataset #3932

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

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

weiji14
Copy link
Member

@weiji14 weiji14 commented Apr 29, 2025

Description of proposed changes

Support passing in a region as a Sequence [xmin, xmax, ymin, ymax] or ISO country code to xarray.open_dataset when using engine="gmt".

Usage:

import numpy.testing as npt
import xarray as xr

da = xr.open_dataarray("@static_earth_relief.nc", engine="gmt", raster_kind="grid", region=[-52, -48, -18, -12])
assert da.sizes == {"lat": 6, "lon": 4}
npt.assert_allclose(da.lat, [-17.5, -16.5, -15.5, -14.5, -13.5, -12.5])
npt.assert_allclose(da.lon, [-51.5, -50.5, -49.5, -48.5])

This PR also refactors the internals of _load_remote_dataset to use xr.load_dataarray(engine="gmt", ...) instead of low-level calls to clib functions.

Extends #3919, adapted from #3673

Preview:

Reminders

  • Run make format and make check to make sure the code follows the style guide.
  • Add tests for new features or tests that would have caught the bug that you're fixing.
  • Add new public functions/methods/classes to doc/api/index.rst.
  • Write detailed docstrings for all functions/methods.
  • If wrapping a new module, open a 'Wrap new GMT module' issue and submit reasonably-sized PRs.
  • If adding new functionality, add an example to docstrings or tutorials.

Slash Commands

You can write slash commands (/command) in the first line of a comment to perform
specific operations. Supported slash command is:

  • /format: automatically format and lint the code

Support passing in a region as a Sequence [xmin, xmax, ymin, ymax] or ISO country code to `xarray.open_dataset` when using `engine="gmt"`.
@weiji14 weiji14 added the enhancement Improving an existing feature label Apr 29, 2025
@weiji14 weiji14 added this to the 0.16.0 milestone Apr 29, 2025
@weiji14 weiji14 self-assigned this Apr 29, 2025
Remove duplicated code calling GMT read, since `xr.load_dataarray(engine="gmt")` now works with region argument.
Ensure that passing engine='gmt' to xarray.open_dataarray works for opening GeoTIFF
images.
Ensure that passing engine='gmt' to xarray.open_dataarray works to open a GeoTIFF
image.
"""
with xr.open_dataarray("@earth_day_01d", engine="gmt", raster_kind="image") as da:
assert da.sizes == {"band": 3, "y": 180, "x": 360}
Copy link
Member Author

Choose a reason for hiding this comment

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

Coordinate names are y/x when region=None, but lat/lon when region is not None at L90 below. Need to fix this inconsistency.

Comment on lines +147 to 148
# The source grid file is undefined for tiled grids.
assert grid.encoding.get("source") is None
Copy link
Member Author

Choose a reason for hiding this comment

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

Should we keep grid.encoding["source"] as undefined/None for tiled grids (xref #3673 (comment))? Or select the first tile (e.g. S90E000.earth_relief_05m_p.nc)? May need to update this test depending on what we decide.

Comment on lines +120 to 123
source: str | list = which(fname=filename_or_obj)
raster.encoding["source"] = (
source[0] if isinstance(source, list) else source
)
Copy link
Member Author

Choose a reason for hiding this comment

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

Do we actually need the _ = raster.gmt line at L124 to load GMTDataArray accessor info, since lib.virtualfile_to_raster already calls self.read_virtualfile(vfname, kind=kind).contents.to_xarray() which sets the registration and gtype based on the header?

# Set GMT accessors.
# Must put at the end, otherwise info gets lost after certain grid operations.
grid.gmt.registration = header.registration
grid.gmt.gtype = header.gtype
return grid

Copy link
Member

Choose a reason for hiding this comment

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

that's a good point. please try remove it and see if everything works fine.

Copy link
Member Author

@weiji14 weiji14 Apr 30, 2025

Choose a reason for hiding this comment

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

There is one extra test failure at https://github.com/GenericMappingTools/pygmt/actions/runs/14743641047/job/41386753150#step:10:1049:

_____________ [doctest] pygmt.xarray.accessor.GMTDataArrayAccessor _____________
026     Examples
027     --------
028     For GMT's built-in remote datasets, these GMT-specific properties are automatically
029     determined and you can access them as follows:
030 
031     >>> from pygmt.datasets import load_earth_relief
032     >>> # Use the global Earth relief grid with 1 degree spacing
033     >>> grid = load_earth_relief(resolution="01d", registration="pixel")
034     >>> # See if grid uses Gridline or Pixel registration
035     >>> grid.gmt.registration
Expected:
    <GridRegistration.PIXEL: 1>
Got:
    1

I think this might be because the _GMT_GRID_HEADER.registration property returns an int instead of an enum?

# Grid registration, 0 for gridline and 1 for pixel
("registration", ctp.c_uint32),

and we overrode grid.gmt.registration with 1 instead of <GridRegistration.PIXEL: 1>. Should be a quick fix we can do in a separate PR. Edit: no, the GMTDataArrayAccessor registration property should always return an enum, not an int, something else in this PR seems to be affecting this doctest...

GMTDataArrayAccessor info should already be loaded by calling`virtualfile_to_raster` which calls `self.read_virtualfile(vfname, kind=kind).contents.to_xarray()` that sets registration and gtype from the header.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Improving an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants