-
Notifications
You must be signed in to change notification settings - Fork 48
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
Adding ESMF.LocStream capabilities to xESMF #81
Conversation
Codecov Report
@@ Coverage Diff @@
## master #81 +/- ##
==========================================
+ Coverage 95.76% 96.55% +0.78%
==========================================
Files 6 6
Lines 260 319 +59
==========================================
+ Hits 249 308 +59
Misses 11 11
Continue to review full report at Codecov.
|
xesmf/frontend.py
Outdated
class Regridder(object): | ||
def __init__(self, ds_in, ds_out, method, periodic=False, | ||
filename=None, reuse_weights=False, ignore_degenerate=None): | ||
filename=None, reuse_weights=False, ignore_degenerate=None, | ||
locstream_out=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
locstream
might also be input I think? (regridding locstream -> grid)
xesmf/frontend.py
Outdated
if len(lon.shape) > 2: | ||
raise ValueError("lon can only be 1d or 2d") | ||
if len(lat.shape) > 2: | ||
raise ValueError("lat can only be 1d or 2d") | ||
|
||
if len(lon.shape) == 2: | ||
lon = lon.flatten() | ||
if len(lat.shape) == 2: | ||
lat = lat.flatten() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better require strict 1-D shape which is the definition of locstream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with it! maybe the flexibility is not a good thing here actually.
Thanks very much for the PR! This is something that I've been wanting to add but never got time to actually do it. Also thanks for the unit test. What would be even more useful is an example notebook under doc/notebooks to show a use case. I am mostly thinking about how to have a consistent API to handle various cases:
Options are:
I was leaning towards no. 2, but your approach also makes sense. |
Another complication from LocStream is that this class can only be used for:
It cannot be used for conservative method, for either source or destination. |
xesmf/tests/test_frontend.py
Outdated
def test_build_regridder(method): | ||
regridder = xe.Regridder(ds_in, ds_out, method) | ||
@pytest.mark.parametrize('locstream', [True, False]) | ||
def test_build_regridder(method, locstream): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think locstream
can be used with conservative
method. Does it actually work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no I hacked it on line 57 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use more explicit expression and avoid overwriting method
internally:
@pytest.mark.parametrize(
"locstream,method", [
(False, method_list),
(True, ['bilinear', 'nearest_s2d', 'nearest_d2s']) # conservative method does not work for LocStream
])
About the more general comments:
I went for option 1 because that's in my opinion, the one that added the less code. Once the ESMF Fields are created, ESMF Regridder works the same (not allowing all types of regridding of course). I'm gonna put some more tests, the codecov for my PR is not very good. An example notebook with follow once we ironed out the API details. |
Yeah I think it is good to have both For the example notebook, it can be with synthetic data replicating advanced interpolation or with real data from |
@JiaweiZhuang sorry for the repeated commits, it's ready to be reviewed/merged. |
@JiaweiZhuang I realized that I have missed one of your comments. Fixed now and I also expanded the test_build_regridder to include locstream_in. Let me know if there's more that needs to be done. I'd really like to move fwd with it. |
@raphaeldussin Sorry I had a long backlog. A few more comments on the test code, and it should be good to go. |
xesmf/tests/test_frontend.py
Outdated
|
||
# ----------------------------------------- | ||
# testing locstream out | ||
regridder = xe.Regridder(ds_in, ds_locs, 'bilinear', locstream_out=True) | ||
ds_result = regridder(ds_in) | ||
# clean-up | ||
regridder.clean_weight_file() | ||
|
||
# ----------------------------------------- | ||
# testing locstream in | ||
regridder = xe.Regridder(ds_locs, ds_in, 'nearest_s2d', locstream_in=True) | ||
|
||
outdata = regridder(ds_locs) | ||
|
||
# clean-up | ||
regridder.clean_weight_file() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would separate out the tests for locstreams into different functions
|
||
outdata = regridder(ds_locs['lat']) | ||
|
||
# clean-up |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would separate out the tests for locstreams into different functions
xesmf/tests/test_frontend.py
Outdated
# ----------------------------------------- | ||
# testing locstream out | ||
regridder = xe.Regridder(ds_in, ds_locs, 'bilinear', locstream_out=True) | ||
|
||
indata = ds_in_chunked['data4D'].data | ||
outdata = regridder(indata) | ||
|
||
# clean-up | ||
regridder.clean_weight_file() | ||
|
||
# ----------------------------------------- | ||
# testing locstream in | ||
regridder = xe.Regridder(ds_locs, ds_in, 'nearest_s2d', locstream_in=True) | ||
|
||
outdata = regridder(ds_locs['lat'].data) | ||
|
||
# clean-up | ||
regridder.clean_weight_file() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would separate out the tests for locstreams into different functions
xesmf/tests/test_frontend.py
Outdated
# ----------------------------------------- | ||
# testing locstream in | ||
regridder = xe.Regridder(ds_locs, ds_in, 'nearest_s2d', locstream_in=True) | ||
|
||
outdata = regridder(ds_locs['lat'].values) # pure numpy array | ||
dr_out = regridder(ds_locs['lat']) # xarray DataArray | ||
|
||
# DataArray and numpy array should lead to the same result | ||
assert_equal(outdata, dr_out.values) | ||
|
||
# clean-up | ||
regridder.clean_weight_file() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would separate out the tests for locstreams into different functions
move the locstream tests into their own functions. |
Thanks @raphaeldussin! Added to 0.3.0 release. |
locstream dim name consistent with ds_out
@JiaweiZhuang this PR allows xESMF to use LocStream objects (sequence of geographical points).
This is particularly useful to interpolate onto ocean sections, creating open boundary conditions,...
I have made minimal inserts, that do not change any default behavior. Also added some testing.
Let me know if there's more to be done for the PR.
Best,
Raf