From 4c269730b8f565223512d97d0d7a7d11dec6dff4 Mon Sep 17 00:00:00 2001 From: Ryan May Date: Thu, 14 Mar 2024 17:46:40 -0600 Subject: [PATCH] ENH: Make coordinate detection more robust (Fixes #3416) This works around an issue where some ERA5 data had lat/lon with a "positive" attribute that, according to the CF specification, should indicate a vertical coordinate. We can fix this up by making sure each coordinate variable is only associated with a single option, and making use of Python's key-ordered dictionaries to prioritize the matching order. Having lat be y and lon be x is already handled by a later block. --- src/metpy/xarray.py | 9 +++++---- tests/test_xarray.py | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/metpy/xarray.py b/src/metpy/xarray.py index 2ccb36ce0ab..ab16f768024 100644 --- a/src/metpy/xarray.py +++ b/src/metpy/xarray.py @@ -338,15 +338,16 @@ def assign_coordinates(self, coordinates): def _generate_coordinate_map(self): """Generate a coordinate map via CF conventions and other methods.""" coords = self._data_array.coords.values() - # Parse all the coordinates, attempting to identify x, longitude, y, latitude, - # vertical, time - coord_lists = {'time': [], 'vertical': [], 'y': [], 'latitude': [], 'x': [], - 'longitude': []} + # Parse all the coordinates, attempting to identify longitude, latitude, x, y, + # time, vertical, in that order. + coord_lists = {'longitude': [], 'latitude': [], 'x': [], 'y': [], 'time': [], + 'vertical': []} for coord_var in coords: # Identify the coordinate type using check_axis helper for axis in coord_lists: if check_axis(coord_var, axis): coord_lists[axis].append(coord_var) + break # Ensure a coordinate variable only goes to one axis # Fill in x/y with longitude/latitude if x/y not otherwise present for geometric, graticule in (('y', 'latitude'), ('x', 'longitude')): diff --git a/tests/test_xarray.py b/tests/test_xarray.py index a5364f327b0..2571944f80f 100644 --- a/tests/test_xarray.py +++ b/tests/test_xarray.py @@ -273,6 +273,14 @@ def test_missing_grid_mapping_invalid(test_var_multidim_no_xy): assert 'metpy_crs' not in data_var.coords +def test_xy_not_vertical(test_ds): + """Test not detecting x/y as a vertical coordinate based on metadata.""" + test_ds.x.attrs['positive'] = 'up' + test_ds.y.attrs['positive'] = 'up' + data_var = test_ds.metpy.parse_cf('Temperature') + assert data_var.metpy.vertical.identical(data_var.coords['isobaric']) + + def test_missing_grid_mapping_var(caplog): """Test behavior when we can't find the variable pointed to by grid_mapping.""" x = xr.DataArray(np.arange(3),