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

Let load_earth_relief() support all resolutions and optional subregion #542

Merged
merged 11 commits into from
Jul 23, 2020

Conversation

seisman
Copy link
Member

@seisman seisman commented Jul 22, 2020

Description of proposed changes

See #489 for the reason of the function redesign. In summary, Earth relief data >05m are stored as single grids, and we can use the which function to get its full path and load it as DataArray. It doesn't work for earth relief data <=05m, which are split into smaller tiles. As suggested in #489, it's easier to use grdcut @earth_relief_xxy -Rregion -Goutput.grd. The grdcut function works for all resolutions, but due to the issue #524, the DataArray returned doesn't support slice operations.

Changes in this PR:

  • For grid>05m, use the which function. The returned DataArray still supports slice operations, so all tests pass
  • For grids<=05m, use the grdcut function. The returned DataArray doesn't support slice operation (see GMTDataArrayAccessor doesn't work for temporary files that have been sliced #524). The bug is also documented.
  • For grids<=05m, users have to pass the region argument to select a subregion.
  • Remove the unused function _shape_from_resolution
  • Use two lists tiled_resolutions and non_tiled_resolutions, instead of the old _is_valid_resolution function
  • Remove 01s and 03s from the test, because these two resolutions are valid
  • Add a few examples
  • Add tests for high resolution grids

Fixes #489.

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 adding new functionality, add an example to docstrings or tutorials.

@weiji14 weiji14 added the enhancement Improving an existing feature label Jul 22, 2020
@weiji14 weiji14 added this to the 0.2.x milestone Jul 22, 2020
@seisman seisman force-pushed the load_earth_relief_region branch from 924862e to eab3c58 Compare July 23, 2020 00:47
@vercel vercel bot temporarily deployed to Preview July 23, 2020 00:47 Inactive
@vercel vercel bot temporarily deployed to Preview July 23, 2020 00:47 Inactive
@seisman seisman force-pushed the load_earth_relief_region branch from 1a91063 to d5f8ce0 Compare July 23, 2020 00:50
@seisman seisman changed the title WIP: Redesign the load_earth_relief function Redesign the load_earth_relief function Jul 23, 2020
@seisman seisman marked this pull request as ready for review July 23, 2020 01:40
@seisman
Copy link
Member Author

seisman commented Jul 23, 2020

@weiji14 I think the PR is ready for review, but the grdcut call is not tested, because it means we have to cache at least a subset of high-resolution grids.

I need some help with:

  1. I added example to this functions, but they're not corrected rendered (https://pygmt-8ovwmg7oz.vercel.app/api/generated/pygmt.datasets.load_earth_relief.html#pygmt.datasets.load_earth_relief)
  2. There is a styling error which I don't understand.

Copy link
Member

@weiji14 weiji14 left a comment

Choose a reason for hiding this comment

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

@weiji14 I think the PR is ready for review, but the grdcut call is not tested, because it means we have to cache at least a subset of high-resolution grids.

We could add the 05m grid to the cache perhaps? They're 'only' 13MB, and with #530 in place it shouldn't be too hard.

pygmt/datasets/earth_relief.py Outdated Show resolved Hide resolved
pygmt/datasets/earth_relief.py Outdated Show resolved Hide resolved
@vercel vercel bot temporarily deployed to Preview July 23, 2020 02:13 Inactive
Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com>
@vercel vercel bot temporarily deployed to Preview July 23, 2020 02:16 Inactive
@seisman seisman requested a review from weiji14 July 23, 2020 03:09
Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com>
Comment on lines 87 to 99
if resolution in non_tiled_resolutions:
fname = which(f"@earth_relief_{resolution}{reg}", download="a")
with xr.open_dataarray(fname) as dataarray:
grid = dataarray.load()
_ = grid.gmt # load GMTDataArray accessor information
elif resolution in tiled_resolutions:
# Titled grid can't be sliced.
# See https://github.com/GenericMappingTools/pygmt/issues/524
if region is None:
raise GMTInvalidInput(
"region is required for high resolution (<='05m') Earth relief grid"
)
grid = grdcut(f"@earth_relief_{resolution}{reg}", region=region)
Copy link
Member

@weiji14 weiji14 Jul 23, 2020

Choose a reason for hiding this comment

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

Sorry, one more thing. What if a user wants to get a non_tiled_resolution grid with a region? The current code doesn't seem to handle this case.

Copy link
Member Author

Choose a reason for hiding this comment

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

The initial design was to allow users to specify a subregion for all resolutions. However, due to #524, the returned grids can't support slice operation, which makes three or more tests fail. So I have to do different ways for tiled and non-tiled resolutions, to keep all tests pass.

Copy link
Member Author

Choose a reason for hiding this comment

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

If a user really want it, they need to call load_earth_relief, then grdcut, or using xarray slice operation.

I'm also OK to add "region" to all resolutions, and declare that "load_earth_relief() grids don't support slice operation" as a bug.

Copy link
Member

Choose a reason for hiding this comment

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

Right, that's tricky. But, an unsuspecting user might pass in a region argument for resolutions 06m and above, and it would just be silently ignored (and a full grid is returned)! We should at least raise a warning or NotImplementedError for this case.

Copy link
Member

@weiji14 weiji14 Jul 23, 2020

Choose a reason for hiding this comment

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

Sorry, slow reply. A workaround might be to just set the registration and gtype directly after calling grdcut, since we know it from the user input to load_earth_relief.

Copy link
Member Author

Choose a reason for hiding this comment

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

that 05m(and higher resolution) grids which are grdcut won't work with grdimage or grdview, but we can fix this before doing a proper release.

I don't understand it. Why do you say it doesn't work?

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand it. Why do you say it doesn't work?

Sorry, it will work actually, I forgot for a second that we applied the workaround in #539.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, if we remove/pop the temp.nc file from grid.encoding["source"] after running grdcut, we can then set the registration and gtype without getting an error. Do you think it's wise to apply this hack?

You mean applying the hack only in load_earth_relief() function? Sounds a good idea.

Copy link
Member Author

@seisman seisman Jul 23, 2020

Choose a reason for hiding this comment

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

Implemented locally, but I'm getting this error:

_________________________________________ [doctest] pygmt.clib.conversion.dataarray_to_matrix _________________________________________
060     >>> matrix.flags.c_contiguous
061     True
062     >>> # Using a slice of the grid, the matrix will be copied to guarantee
063     >>> # that it's C-contiguous in memory. The increment should be unchanged.
064     >>> matrix, region, inc = dataarray_to_matrix(grid[10:41,30:101])
065     >>> matrix.flags.c_contiguous
066     True
067     >>> print(matrix.shape)
068     (31, 71)
069     >>> print(region)
Expected:
    [-150.0, -79.0, -80.0, -49.0]
Got:
    [-149.5, -79.5, -79.5, -49.5]

This is because grid.encoding["source"] is removed, then the sliced new grid has the default registration and gtype.

Copy link
Member

Choose a reason for hiding this comment

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

I don't see an easy fix for #524. Perhaps the best compromise is

raise a warning or NotImplementedError for this case.

RIght, let's just raise a warning here then, having layers and layers of workarounds isn't good anyway.

@seisman seisman changed the title Redesign the load_earth_relief function Let load_earth_relief() support all resolutions and optional subregion Jul 23, 2020
@seisman seisman merged commit 32c4d4a into master Jul 23, 2020
@seisman seisman deleted the load_earth_relief_region branch July 23, 2020 06:00
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.

Redesign of the load_earth_relief() function
2 participants