Skip to content

Commit

Permalink
NARR Example CF Parsing
Browse files Browse the repository at this point in the history
While I was working through examples, I noticed that the parse_cf
function, when applied to the full dataset of the NARR example, would
fail...the x and y coordinates would double in size, and many NaN's
appeared. This was because the lon and lat variables lacked a
grid_mapping attribute, and so, their x and y coordinates did not get
scaled from km to m like the other variables that did. Thus, they did
not line up when xarray tried to combine them back together in a
non-unit-aware fashion.

This commit fixes this by changing when _fixup_coords is called, so that
all x/y coordinates get scaled accordingly.
  • Loading branch information
jthielen committed Jul 24, 2018
1 parent ab04139 commit 2fe00b6
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 7 deletions.
13 changes: 13 additions & 0 deletions metpy/tests/test_xarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,16 @@ def test_check_axis_regular_expression_match(test_ds_generic, test_tuple):
"""Test the variety of possibilities for check_axis in the regular expression match."""
data = test_ds_generic.rename({'e': test_tuple[0]})
assert data.metpy.check_axis(data[test_tuple[0]], test_tuple[1])


def test_narr_example_variable_without_grid_mapping(test_ds):
"""Test that NARR example is parsed correctly, with x/y coordinates scaled the same."""
data = test_ds.metpy.parse_cf()
# Make sure that x and y coordinates are parsed correctly, rather than having unequal
# scaling based on whether that variable has the grid_mapping attribute. This would
# otherwise double the coordinates's shapes since xarray tries to combine the coordinates
# with different scaling from differing units.
assert test_ds['x'].shape == data['lon'].metpy.x.shape
assert test_ds['y'].shape == data['lon'].metpy.y.shape
assert data['lon'].metpy.x.identical(data['Temperature'].metpy.x)
assert data['lon'].metpy.y.identical(data['Temperature'].metpy.y)
17 changes: 10 additions & 7 deletions metpy/xarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ def parse_cf(self, varname=None, coordinates=None):
else:
var.coords['crs'] = CFProjection(proj_var.attrs)
var.attrs.pop('grid_mapping')
self._fixup_coords(var)

self._fixup_coords(var)

# Trying to guess whether we should be adding a crs to this variable's coordinates
# First make sure it's missing CRS but isn't lat/lon itself
Expand Down Expand Up @@ -253,15 +254,17 @@ def check_axis(cls, var, *axes):
def _fixup_coords(self, var):
"""Clean up the units on the coordinate variables."""
for coord_name, data_array in var.coords.items():
if self.check_axis(data_array, 'x', 'y'):
if (self.check_axis(data_array, 'x', 'y') and
not self.check_axis(data_array, 'lon', 'lat')):
try:
var.coords[coord_name].metpy.convert_units('meters')
except DimensionalityError: # Radians!
new_data_array = data_array.copy()
height = var.coords['crs'].item()['perspective_point_height']
scaled_vals = new_data_array.metpy.unit_array * (height * units.meters)
new_data_array.metpy.unit_array = scaled_vals.to('meters')
var.coords[coord_name] = new_data_array
if 'crs' in var.coords:
new_data_array = data_array.copy()
height = var.coords['crs'].item()['perspective_point_height']
scaled_vals = new_data_array.metpy.unit_array * (height * units.meters)
new_data_array.metpy.unit_array = scaled_vals.to('meters')
var.coords[coord_name] = new_data_array

def _generate_coordinate_map(self, coords):
"""Generate a coordinate map via CF conventions and other methods."""
Expand Down

0 comments on commit 2fe00b6

Please sign in to comment.