From 9f7b72c05faa316d5e8ae92c06d4b9fb4ac9a4a9 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 14:56:13 -0600 Subject: [PATCH 01/13] Update test to look at longitude --- tests/test_remap.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_remap.py b/tests/test_remap.py index 7d2ac4f3..fd633473 100644 --- a/tests/test_remap.py +++ b/tests/test_remap.py @@ -90,6 +90,11 @@ def test_combine_da_da(): }, ) + # Longitude normalization introduces floating point error + x_ = (x + 180) % 360 - 180 + assert not (x_ == x).any() + assert np.abs(x_ - x).max() < 5e-14 + # Combine (find closest model grid cell to each obs point) # NOTE: to use `merge`, must have matching `level` dims new = combine_da_to_da(model, obs, merge=False, interp_time=False) @@ -100,8 +105,12 @@ def test_combine_da_da(): assert float(new.longitude.max()) == pytest.approx(0.9) assert float(new.latitude.min()) == pytest.approx(0.1) assert float(new.latitude.max()) == pytest.approx(0.9) + assert (obs.longitude.values == x).all(), "preserved" assert (new.latitude.isel(x=0).values == obs.latitude.values).all() - assert np.allclose(new.longitude.isel(y=0).values, obs.longitude.values) + + # FIXME + assert not (new.longitude.isel(y=0).values == obs.longitude.values).all() + assert (new.longitude.isel(y=0).values == x_).all() # Use orthogonal selection to get track a = new.data.values[:, new.y, new.x] From 564f4405706f45ac3abfbb320e355a507f924103 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 15:43:43 -0600 Subject: [PATCH 02/13] Add inplace option, defaulting to false For many cases, this is not necessary, since rename creates a new ds obj, but if no renames have occurred, longitude in the original `dset` will be modified --- monet/monet_accessor.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 47b260e4..980271c4 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -62,7 +62,13 @@ def _monet_to_latlon(da): return dset -def _dataset_to_monet(dset, lat_name="latitude", lon_name="longitude", latlon2d=False): +def _dataset_to_monet( + dset, + lat_name="latitude", + lon_name="longitude", + latlon2d=False, + inplace=False, +): """Rename xarray DataArray or Dataset coordinate variables for use with monet functions, returning a new xarray object. @@ -77,6 +83,9 @@ def _dataset_to_monet(dset, lat_name="latitude", lon_name="longitude", latlon2d= latlon2d : bool Whether the latitude and longitude data is two-dimensional. """ + if not inplace: + dset = dset.copy() + if "grid_xt" in dset.dims: # GFS v16 file try: @@ -123,10 +132,7 @@ def _dataset_to_monet(dset, lat_name="latitude", lon_name="longitude", latlon2d= else: dset = _rename_to_monet_latlon(dset) latlon2d = True - # print(len(dset[lat_name].shape)) - # print(dset) if len(dset[lat_name].shape) < 2: - # print(dset[lat_name].shape) latlon2d = False if latlon2d is False: try: From 48939c78675c4656446097630520b66c0888dadd Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 15:56:58 -0600 Subject: [PATCH 03/13] Instead, ensure rename returning new obj even if nothing renamed --- monet/monet_accessor.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 980271c4..8a809e72 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -67,7 +67,6 @@ def _dataset_to_monet( lat_name="latitude", lon_name="longitude", latlon2d=False, - inplace=False, ): """Rename xarray DataArray or Dataset coordinate variables for use with monet functions, returning a new xarray object. @@ -83,8 +82,6 @@ def _dataset_to_monet( latlon2d : bool Whether the latitude and longitude data is two-dimensional. """ - if not inplace: - dset = dset.copy() if "grid_xt" in dset.dims: # GFS v16 file @@ -177,7 +174,7 @@ def _rename_to_monet_latlon(ds): elif "XLAT" in check_list: return ds.rename({"XLAT": "latitude", "XLONG": "longitude"}) else: - return ds + return ds.copy() def _coards_to_netcdf(dset, lat_name="lat", lon_name="lon"): From 423a4e6a6fb6a153b05951c46fa94ea7174695a4 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:01:03 -0600 Subject: [PATCH 04/13] Fix passing latlon2d before it was just ignored --- monet/monet_accessor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 8a809e72..def5067b 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -66,7 +66,7 @@ def _dataset_to_monet( dset, lat_name="latitude", lon_name="longitude", - latlon2d=False, + latlon2d=None, ): """Rename xarray DataArray or Dataset coordinate variables for use with monet functions, returning a new xarray object. @@ -79,8 +79,9 @@ def _dataset_to_monet( Name of the latitude array. lon_name : str Name of the longitude array. - latlon2d : bool + latlon2d : bool, optional Whether the latitude and longitude data is two-dimensional. + If unset, guess based on dim count. """ if "grid_xt" in dset.dims: @@ -128,10 +129,9 @@ def _dataset_to_monet( else: dset = _rename_to_monet_latlon(dset) - latlon2d = True - if len(dset[lat_name].shape) < 2: - latlon2d = False - if latlon2d is False: + if latlon2d is None: + latlon2d = dset[lat_name].ndim >= 2 + if not latlon2d: try: if isinstance(dset, xr.DataArray): dset = _dataarray_coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) From 92f21cd1b0f2ed3ce4d170700cc678e93dcfd6bc Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:18:03 -0600 Subject: [PATCH 05/13] lon180 option --- monet/monet_accessor.py | 51 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index def5067b..7e1b3006 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -67,6 +67,7 @@ def _dataset_to_monet( lat_name="latitude", lon_name="longitude", latlon2d=None, + lon180=None, ): """Rename xarray DataArray or Dataset coordinate variables for use with monet functions, returning a new xarray object. @@ -81,7 +82,12 @@ def _dataset_to_monet( Name of the longitude array. latlon2d : bool, optional Whether the latitude and longitude data is two-dimensional. - If unset, guess based on dim count. + If unset (``None``), guess based on dim count. + lon180 : bool, optional + Whether the longitude values are in the range [-180, 180) already. + If true, longitude wrapping/normalization, + which can introduce small floating point errors, will be skipped. + If unset (``None``), compute min/max to determine. """ if "grid_xt" in dset.dims: @@ -120,31 +126,30 @@ def _dataset_to_monet( except ValueError: print("dset must be an Xarray.DataArray or Xarray.Dataset") - # Unstructured Grid - # lat & lon are not coordinate variables in unstructured grid - if dset.attrs.get("mio_has_unstructured_grid", False): - # only call rename and wrap_longitudes - dset = _rename_to_monet_latlon(dset) - dset["longitude"] = wrap_longitudes(dset["longitude"]) + dset = _rename_to_monet_latlon(dset) - else: - dset = _rename_to_monet_latlon(dset) - if latlon2d is None: - latlon2d = dset[lat_name].ndim >= 2 - if not latlon2d: - try: - if isinstance(dset, xr.DataArray): - dset = _dataarray_coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) - elif isinstance(dset, xr.Dataset): - dset = _coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) - else: - raise ValueError - except ValueError: - print("dset must be an Xarray.DataArray or Xarray.Dataset") - else: - dset = _rename_to_monet_latlon(dset) + if lon180 is None: + lon180 = dset["longitude"].min() >= -180 and dset["longitude"].max() < 180 + if not lon180: dset["longitude"] = wrap_longitudes(dset["longitude"]) + # lat & lon are not coordinate variables in unstructured grid, so we're done + if dset.attrs.get("mio_has_unstructured_grid", False): + return dset + + if latlon2d is None: + latlon2d = dset[lat_name].ndim >= 2 + if not latlon2d: + try: + if isinstance(dset, xr.DataArray): + dset = _dataarray_coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) + elif isinstance(dset, xr.Dataset): + dset = _coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) + else: + raise ValueError + except ValueError: + print("dset must be an Xarray.DataArray or Xarray.Dataset") + return dset From 00793ebfc0c7235b6aa2f584d979fb995b7ddbc7 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:29:16 -0600 Subject: [PATCH 06/13] Use normalized names after rename --- monet/monet_accessor.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 7e1b3006..510136f2 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -126,8 +126,12 @@ def _dataset_to_monet( except ValueError: print("dset must be an Xarray.DataArray or Xarray.Dataset") - dset = _rename_to_monet_latlon(dset) + # Rename lat/lon coordinates to 'latitude'/'longitude' + dset = _rename_to_monet_latlon(dset) # common cases + if not {"latitude", "longitude"} <= set(dset.variables): + dset = dset.rename({lat_name: "latitude", lon_name: "longitude"}) + # Maybe wrap longitudes if lon180 is None: lon180 = dset["longitude"].min() >= -180 and dset["longitude"].max() < 180 if not lon180: @@ -137,14 +141,15 @@ def _dataset_to_monet( if dset.attrs.get("mio_has_unstructured_grid", False): return dset + # Maybe convert 1-D lat/lon coords to 2-D if latlon2d is None: - latlon2d = dset[lat_name].ndim >= 2 + latlon2d = dset["latitude"].ndim >= 2 if not latlon2d: try: if isinstance(dset, xr.DataArray): - dset = _dataarray_coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) + dset = _dataarray_coards_to_netcdf(dset, lat_name="latitude", lon_name="longitude") elif isinstance(dset, xr.Dataset): - dset = _coards_to_netcdf(dset, lat_name=lat_name, lon_name=lon_name) + dset = _coards_to_netcdf(dset, lat_name="latitude", lon_name="longitude") else: raise ValueError except ValueError: From c90a8b4becf87c8c691b3cff4a60ba9d5fb82d15 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:33:10 -0600 Subject: [PATCH 07/13] Move type check earlier and raise TypeError --- monet/monet_accessor.py | 68 ++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 510136f2..334a8d64 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -89,42 +89,33 @@ def _dataset_to_monet( which can introduce small floating point errors, will be skipped. If unset (``None``), compute min/max to determine. """ + if not isinstance(dset, (xr.DataArray, xr.Dataset)): + raise TypeError("dset must be an xarray.DataArray or xarray.Dataset") - if "grid_xt" in dset.dims: - # GFS v16 file - try: - if isinstance(dset, xr.DataArray): - dset = _dataarray_coards_to_netcdf(dset, lat_name="grid_yt", lon_name="grid_xt") - elif isinstance(dset, xr.Dataset): - dset = _dataarray_coards_to_netcdf(dset, lat_name="grid_yt", lon_name="grid_xt") - else: - raise ValueError - except ValueError: - print("dset must be an xarray.DataArray or xarray.Dataset") + if "grid_xt" in dset.dims: # GFS v16 file + if isinstance(dset, xr.DataArray): + dset = _dataarray_coards_to_netcdf(dset, lat_name="grid_yt", lon_name="grid_xt") + elif isinstance(dset, xr.Dataset): + dset = _dataarray_coards_to_netcdf(dset, lat_name="grid_yt", lon_name="grid_xt") if "south_north" in dset.dims: # WRF WPS file dset = dset.rename(dict(south_north="y", west_east="x")) - try: - if isinstance(dset, xr.Dataset): - if "XLAT_M" in dset.data_vars: - dset["XLAT_M"] = dset.XLAT_M.squeeze() - dset["XLONG_M"] = dset.XLONG_M.squeeze() - dset = dset.set_coords(["XLAT_M", "XLONG_M"]) - elif "XLAT" in dset.data_vars: - dset["XLAT"] = dset.XLAT.squeeze() - dset["XLONG"] = dset.XLONG.squeeze() - dset = dset.set_coords(["XLAT", "XLONG"]) - elif isinstance(dset, xr.DataArray): - if "XLAT_M" in dset.coords: - dset["XLAT_M"] = dset.XLAT_M.squeeze() - dset["XLONG_M"] = dset.XLONG_M.squeeze() - elif "XLAT" in dset.coords: - dset["XLAT"] = dset.XLAT.squeeze() - dset["XLONG"] = dset.XLONG.squeeze() - else: - raise ValueError - except ValueError: - print("dset must be an Xarray.DataArray or Xarray.Dataset") + if isinstance(dset, xr.Dataset): + if "XLAT_M" in dset.data_vars: + dset["XLAT_M"] = dset.XLAT_M.squeeze() + dset["XLONG_M"] = dset.XLONG_M.squeeze() + dset = dset.set_coords(["XLAT_M", "XLONG_M"]) + elif "XLAT" in dset.data_vars: + dset["XLAT"] = dset.XLAT.squeeze() + dset["XLONG"] = dset.XLONG.squeeze() + dset = dset.set_coords(["XLAT", "XLONG"]) + elif isinstance(dset, xr.DataArray): + if "XLAT_M" in dset.coords: + dset["XLAT_M"] = dset.XLAT_M.squeeze() + dset["XLONG_M"] = dset.XLONG_M.squeeze() + elif "XLAT" in dset.coords: + dset["XLAT"] = dset.XLAT.squeeze() + dset["XLONG"] = dset.XLONG.squeeze() # Rename lat/lon coordinates to 'latitude'/'longitude' dset = _rename_to_monet_latlon(dset) # common cases @@ -145,15 +136,10 @@ def _dataset_to_monet( if latlon2d is None: latlon2d = dset["latitude"].ndim >= 2 if not latlon2d: - try: - if isinstance(dset, xr.DataArray): - dset = _dataarray_coards_to_netcdf(dset, lat_name="latitude", lon_name="longitude") - elif isinstance(dset, xr.Dataset): - dset = _coards_to_netcdf(dset, lat_name="latitude", lon_name="longitude") - else: - raise ValueError - except ValueError: - print("dset must be an Xarray.DataArray or Xarray.Dataset") + if isinstance(dset, xr.DataArray): + dset = _dataarray_coards_to_netcdf(dset, lat_name="latitude", lon_name="longitude") + elif isinstance(dset, xr.Dataset): + dset = _coards_to_netcdf(dset, lat_name="latitude", lon_name="longitude") return dset From 06f9f3cecbc9994bcbba3b2c3b92e40d9af5489d Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:37:21 -0600 Subject: [PATCH 08/13] Explicit target lon too don't see why not --- monet/monet_accessor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 334a8d64..86af06eb 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -1222,6 +1222,7 @@ def remap_nearest(self, data, **kwargs): result = r.get_sample_from_neighbour_info(source_data) result.name = source_data.name result["latitude"] = target_data.latitude + result["longitude"] = target_data.longitude elif isinstance(source_data, xr.Dataset): results = {} @@ -1544,6 +1545,7 @@ def remap_nearest(self, data, radius_of_influence=1e6): result = r.get_sample_from_neighbour_info(source_data) result.name = source_data.name result["latitude"] = target_data.latitude + result["longitude"] = target_data.longitude elif isinstance(source_data, xr.Dataset): results = {} From 5b783fefa51f6516087032afb4446a4eac1c6d81 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:45:44 -0600 Subject: [PATCH 09/13] cleanup remap_nearest calls dataset-to-monet on both target and source internally --- monet/monet_accessor.py | 12 ++---------- monet/util/combinetool.py | 11 ++++++----- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 86af06eb..a43d6016 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -1212,6 +1212,7 @@ def remap_nearest(self, data, **kwargs): # from .grids import get_generic_projection_from_proj4 # check to see if grid is supplied + source_data = _dataset_to_monet(data) target_data = _dataset_to_monet(self._obj) source = self._get_CoordinateDefinition(data=source_data) @@ -1525,16 +1526,7 @@ def remap_nearest(self, data, radius_of_influence=1e6): # from .grids import get_generic_projection_from_proj4 # check to see if grid is supplied - try: - check_error = False - if isinstance(data, xr.DataArray) or isinstance(data, xr.Dataset): - check_error = False - else: - check_error = True - if check_error: - raise TypeError - except TypeError: - print("data must be either an Xarray.DataArray or Xarray.Dataset") + source_data = _dataset_to_monet(data) target_data = _dataset_to_monet(self._obj) source = self._get_CoordinateDefinition(source_data) diff --git a/monet/util/combinetool.py b/monet/util/combinetool.py index f4072793..71188634 100644 --- a/monet/util/combinetool.py +++ b/monet/util/combinetool.py @@ -71,7 +71,7 @@ def combine_da_to_da(source, target, *, merge=True, interp_time=False, **kwargs) ---------- source : xarray.DataArray or xarray.Dataset Gridded data. - target : xarray.DataArray + target : xarray.DataArray or xarray.Dataset Point observations. merge : bool If false, only return the interpolated source data. @@ -87,13 +87,14 @@ def combine_da_to_da(source, target, *, merge=True, interp_time=False, **kwargs) """ from ..monet_accessor import _dataset_to_monet - target_fixed = _dataset_to_monet(target) - source_fixed = _dataset_to_monet(source) - output = target_fixed.monet.remap_nearest(source_fixed, **kwargs) + output = target.monet.remap_nearest(source, **kwargs) + if interp_time: output = output.interp(time=target.time) + if merge: - output = xr.merge([target_fixed, output]) + output = xr.merge([_dataset_to_monet(target), output]) + return output From fe185e163dcb7552d8701efaf3d6c9e04cc0a57b Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 16:51:03 -0600 Subject: [PATCH 10/13] consistency --- monet/monet_accessor.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index a43d6016..e9898b0a 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -1190,7 +1190,7 @@ def _get_CoordinateDefinition(self, data=None): g = geo.CoordinateDefinition(lats=self._obj.latitude, lons=self._obj.longitude) return g - def remap_nearest(self, data, **kwargs): + def remap_nearest(self, data, radius_of_influence=1e6, **kwargs): """Remap `data` from another grid to the current self grid using pyresample nearest-neighbor interpolation. @@ -1215,9 +1215,11 @@ def remap_nearest(self, data, **kwargs): source_data = _dataset_to_monet(data) target_data = _dataset_to_monet(self._obj) - source = self._get_CoordinateDefinition(data=source_data) - target = self._get_CoordinateDefinition(data=target_data) - r = kd_tree.XArrayResamplerNN(source, target, **kwargs) + source = self._get_CoordinateDefinition(source_data) + target = self._get_CoordinateDefinition(target_data) + r = kd_tree.XArrayResamplerNN( + source, target, radius_of_influence=radius_of_influence, **kwargs + ) r.get_neighbour_info() if isinstance(source_data, xr.DataArray): result = r.get_sample_from_neighbour_info(source_data) @@ -1505,7 +1507,7 @@ def _get_CoordinateDefinition(self, data=None): g = geo.CoordinateDefinition(lats=self._obj.latitude, lons=self._obj.longitude) return g - def remap_nearest(self, data, radius_of_influence=1e6): + def remap_nearest(self, data, radius_of_influence=1e6, **kwargs): """Remap `data` from another grid to the current self grid using pyresample nearest-neighbor interpolation. @@ -1531,7 +1533,9 @@ def remap_nearest(self, data, radius_of_influence=1e6): target_data = _dataset_to_monet(self._obj) source = self._get_CoordinateDefinition(source_data) target = self._get_CoordinateDefinition(target_data) - r = kd_tree.XArrayResamplerNN(source, target, radius_of_influence=radius_of_influence) + r = kd_tree.XArrayResamplerNN( + source, target, radius_of_influence=radius_of_influence, **kwargs + ) r.get_neighbour_info() if isinstance(source_data, xr.DataArray): result = r.get_sample_from_neighbour_info(source_data) From ca1880b8b369ca7bde7cd69da5897329a97f56d1 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 17:13:06 -0600 Subject: [PATCH 11/13] Don't wrap lon in coards conversion Note COARDS and CF seem to both allow longitudes other than [-180, 180) format --- monet/monet_accessor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index e9898b0a..9bbab26b 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -188,7 +188,7 @@ def _coards_to_netcdf(dset, lat_name="lat", lon_name="lon"): """ from numpy import arange, meshgrid - lon = wrap_longitudes(dset[lon_name]) + lon = dset[lon_name] lat = dset[lat_name] lons, lats = meshgrid(lon, lat) x = arange(len(lon)) @@ -217,7 +217,7 @@ def _dataarray_coards_to_netcdf(dset, lat_name="lat", lon_name="lon"): """ from numpy import arange, meshgrid - lon = wrap_longitudes(dset[lon_name]) + lon = dset[lon_name] lat = dset[lat_name] lons, lats = meshgrid(lon, lat) x = arange(len(lon)) From 9404e3f79199198104b2ef2ee820d938231f96bd Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 17:16:35 -0600 Subject: [PATCH 12/13] Update test --- tests/test_remap.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/test_remap.py b/tests/test_remap.py index fd633473..a37ea73c 100644 --- a/tests/test_remap.py +++ b/tests/test_remap.py @@ -105,12 +105,10 @@ def test_combine_da_da(): assert float(new.longitude.max()) == pytest.approx(0.9) assert float(new.latitude.min()) == pytest.approx(0.1) assert float(new.latitude.max()) == pytest.approx(0.9) - assert (obs.longitude.values == x).all(), "preserved" - assert (new.latitude.isel(x=0).values == obs.latitude.values).all() - # FIXME - assert not (new.longitude.isel(y=0).values == obs.longitude.values).all() - assert (new.longitude.isel(y=0).values == x_).all() + assert (obs.longitude.values == x).all(), "preserved" + assert (new.latitude.isel(x=0).values == obs.latitude.values).all(), "same as target" + assert (new.longitude.isel(y=0).values == obs.longitude.values).all(), "same as target" # Use orthogonal selection to get track a = new.data.values[:, new.y, new.x] From 1dc5a8b55e7f5903ca199916f60ceec77e3ee615 Mon Sep 17 00:00:00 2001 From: zmoon Date: Mon, 18 Nov 2024 17:23:19 -0600 Subject: [PATCH 13/13] Fix dataset-to-monet for da --- monet/monet_accessor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/monet/monet_accessor.py b/monet/monet_accessor.py index 9bbab26b..4b1ab9e9 100644 --- a/monet/monet_accessor.py +++ b/monet/monet_accessor.py @@ -119,7 +119,9 @@ def _dataset_to_monet( # Rename lat/lon coordinates to 'latitude'/'longitude' dset = _rename_to_monet_latlon(dset) # common cases - if not {"latitude", "longitude"} <= set(dset.variables): + if (isinstance(dset, xr.Dataset) and not {"latitude", "longitude"} <= set(dset.variables)) or ( + isinstance(dset, xr.DataArray) and not {"latitude", "longitude"} <= set(dset.coords) + ): dset = dset.rename({lat_name: "latitude", lon_name: "longitude"}) # Maybe wrap longitudes