-
Notifications
You must be signed in to change notification settings - Fork 422
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
Implement gwfs function from GEMPAK #911
Conversation
Since NumPy 1.15 came out, we have been getting pages and pages of warnings about our use of non-tuple based indexing. This commit converts all of our previous list-based indexing to tuple-based indexing. This doesn't yet clear out all the warnings (some of them are upstream in Pint and scipy), but it does drop the number down from 600-something to 10-something.
This commit wraps the gaussian_filter function from SciPy so that it emulates the GWFS function from GEMPAK as closely as possible. The key difference is that GEMPAK adds the leftover weights from outside the averaging window to the center point, but there is no option for gaussian_filter to do this. Left unfinished is restoring metadata to the result. For instance, an xarray.DataArray provided as input becomes a lowly numpy.ndarray on output.
This commit adds a few basic tests for the metpy.calc.gwfs function, and also updates the GEMPAK compatibility table. I'm not sure how to add new documentation to the MetPy API section.
metpy/calc/basic.py
Outdated
------- | ||
`pint.Quantity` | ||
The filtered 2D scalar grid | ||
|
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.
W293 blank line contains whitespace
metpy/calc/basic.py
Outdated
|
||
where N > 1. If N <= 1, N = 2 is assumed. For example, if N = 4, | ||
then the 4 delta x wave length is passed with approximate response | ||
1/e. |
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.
W291 trailing whitespace
metpy/calc/basic.py
Outdated
n = int(round(n)) | ||
if n < 2: | ||
n = 2 | ||
sgma = n / (2*np.pi) |
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.
E226 missing whitespace around arithmetic operator
metpy/calc/basic.py
Outdated
if n < 2: | ||
n = 2 | ||
sgma = n / (2*np.pi) | ||
res = gaussian_filter(scalar_grid, sgma, truncate=2*np.sqrt(2)) |
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.
E226 missing whitespace around arithmetic operator
metpy/calc/basic.py
Outdated
res = gaussian_filter(scalar_grid, sgma, truncate=2*np.sqrt(2)) | ||
return res | ||
|
||
|
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.
W293 blank line contains whitespace
metpy/calc/tests/test_basic.py
Outdated
30.40077472, 41.40077472, 54.40077472, 69.31520047, 82.67898913], | ||
[ 6.20489127, 7.39627081, 10.40077472, 15.40077472, 22.40077472, | ||
31.40077472, 42.40077472, 55.40077472, 70.31520047, 83.67898913], | ||
[ 7.20489127, 8.39627081, 11.40077472, 16.40077472, 23.40077472, |
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.
E201 whitespace after '['
E241 multiple spaces after ','
metpy/calc/tests/test_basic.py
Outdated
31.40077472, 42.40077472, 55.40077472, 70.31520047, 83.67898913], | ||
[ 7.20489127, 8.39627081, 11.40077472, 16.40077472, 23.40077472, | ||
32.40077472, 43.40077472, 56.40077472, 71.31520047, 84.67898913], | ||
[ 8.20038736, 9.3917669, 12.39627081, 17.39627081, 24.39627081, |
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.
E201 whitespace after '['
E241 multiple spaces after ','
metpy/calc/tests/test_basic.py
Outdated
32.40077472, 43.40077472, 56.40077472, 71.31520047, 84.67898913], | ||
[ 8.20038736, 9.3917669, 12.39627081, 17.39627081, 24.39627081, | ||
33.39627081, 44.39627081, 57.39627081, 72.31069656, 85.67448522], | ||
[ 9.00900782, 10.20038736, 13.20489127, 18.20489127, 25.20489127, |
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.
E201 whitespace after '['
metpy/calc/tests/test_basic.py
Outdated
34.20489127, 45.20489127, 58.20489127, 73.11931702, 86.48310568]]) | ||
assert_array_almost_equal(s, s_true) | ||
|
||
def test_gwfs_small_n(): |
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.
E302 expected 2 blank lines, found 1
metpy/calc/tests/test_basic.py
Outdated
[2.00708990, 3.01417981, 6.01417981, 11.0141798, 17.9503707], | ||
[3.00708990, 4.01417981, 7.01417981, 12.0141798, 18.9503707], | ||
[4.00000000, 5.00708990, 8.00708990, 13.0070899, 19.9432808]] | ||
print(s-s_true) |
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.
E226 missing whitespace around arithmetic operator
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.
Thanks for the contribution, one more step towards GEMPAK!
My only real concern is with the naming of the function, especially in this case where I can't even figure out definitively what gwfs
even stands for.
Also, you'll need to update metpy.calc.rst
to include this function in the list of calculations in the docs.
metpy/calc/basic.py
Outdated
if n < 2: | ||
n = 2 | ||
sgma = n / (2 * np.pi) | ||
res = gaussian_filter(scalar_grid, sgma, truncate=2 * np.sqrt(2)) |
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.
Could just be return gaussian_filter(scalar_grid, sgma, truncate=2 * np.sqrt(2))
metpy/calc/basic.py
Outdated
@@ -614,6 +615,90 @@ def sigma_to_pressure(sigma, psfc, ptop): | |||
return sigma * (psfc - ptop) + ptop | |||
|
|||
|
|||
@exporter.export | |||
@preprocess_xarray | |||
def gwfs(scalar_grid, n): |
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.
We need a name for this--replicating GEMPAK functionality is a big 👍 . Replicating naming from the 80's when you had to pay per-character (or so it seems) is something I'd like to not replicate. 😁
How about gaussian_smooth
?
Also, is n
the most sensible argument for this function? Personally, I'd like to be able to specify the kernel width in some kind of physical units as well, but we don't have to do this right now. If this is the most sensible interface to you the user, then I'm happy to just roll with it.
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.
Yes, gwfs
is more of a placeholder name to make it clear what GEMPAK function it corresponds to. Looking ahead to eventual implementations of GEMPAK's sm5s
and sm9s
, maybe all of these should start with 'smooth', so smooth_gaussian
, smooth_5pt
, etc.?
Regarding n
, it sounds like you are wanting the related GEMPAK function RDFS (Resolution Dependent Filter for Scalar), which takes dx
instead of n
as the second argument, and then behind the scenes computes an appropriate n
based on dx
and calls GWFS. But I suppose just because they are two separate GEMPAK functions doesn't mean they have to be separate MetPy functions.
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.
smooth_gaussian
sounds good to me.
If both GWFS and RDFS are doing the same calculation, just tweaking the parameter, I’d lean towards putting all of the functionality in smooth_gaussian
, and just look at the arguments passed in to determine the proper course of action. That doesn’t have to be implemented in this PR, though—I’d be happy just to merge the GWFS equivalent.
@kgoebber, you've written another version of this previously--I'd love to have your input on this and if it would do everything you need it to do. |
Can you update the function to maintain the units of the input array? Then this PR would close #664 . |
Fix non-tuple NumPy indexing in MetPy
I have just used the gaussian_filter - this is a nice warp to that which will present slightly less verbose syntax. |
(See #659 for the 5- and 9-point smoothers.) |
I do want the function to maintain units, just need to figure it out. I'd also like to make sure it only smooths in the horizontal direction if given an array with more than two dimensions. This would match GEMPAK semantics, where even when you are creating a cross section or time series plot, calling GWFS as part of the function to plot smooths each vertical level or time independently. |
So to maintain units, what you want to do is: if hasattr(scalar_grid, ‘units’):
res = res * scalar_grid.units Putting that block after the call to |
This commit wraps the gaussian_filter function from SciPy so that it emulates the GWFS function from GEMPAK as closely as possible. The key difference is that GEMPAK adds the leftover weights from outside the averaging window to the center point, but there is no option for gaussian_filter to do this. Left unfinished is restoring metadata to the result. For instance, an xarray.DataArray provided as input becomes a lowly numpy.ndarray on output.
This commit adds a few basic tests for the metpy.calc.gwfs function, and also updates the GEMPAK compatibility table. I'm not sure how to add new documentation to the MetPy API section.
gwfs is extended to preserve units and ensure that only horizontal directions are smoothed (assuming last two axes are horizontal). Documentation is updated so that this function appears.
One place was overlooked when changing gwfs() to smooth_gaussian(). This corrects the oversight.
Thanks for the pointer on the units. I'll leave the alternate, |
Thanks for the contribution @sgdecker ! |
This PR adds the GEMPAK GWFS function by wrapping the SciPy function gaussian_filter. As far as I can tell, there is no way to make gaussian_filter act exactly identical to what GEMPAK does, but the result is awfully close:


This is a work in progress. A few things I haven't figured out: