diff --git a/CHANGES.md b/CHANGES.md index ff2704325..f8919f7ca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,8 @@ ## Version 2.0.0.dev24 +* Fixed failing download of Sea-Ice CCI data (ValueError: The truth value of an array with more than one element is ambiguous) + [#832](https://github.com/CCI-Tools/cate/issues/832) * A set of related data access issues that all occurred if data was downloaded from ODP using a spatial subset has hopefully been addressed in one go. Issues include: - Cannot download SST dataset - I/O error. [#823](https://github.com/CCI-Tools/cate/issues/823) diff --git a/cate/core/opimpl.py b/cate/core/opimpl.py index cc9a3c753..e55797f26 100644 --- a/cate/core/opimpl.py +++ b/cate/core/opimpl.py @@ -145,11 +145,15 @@ def _normalize_lat_lon_2d(ds: xr.Dataset) -> xr.Dataset: equal_lat = np.allclose(lat_data_1, lat_data_2, equal_nan=True) equal_lon = np.allclose(lon_data_1, lon_data_2, equal_nan=True) - if not (equal_lat and equal_lon): - return ds + + # Drop lat lon in any case. If note qual_lat and equal_lon subset_spatial_impl will subsequently + # fail with a ValidationError ds = ds.drop(['lon', 'lat']) + if not (equal_lat and equal_lon): + return ds + ds = ds.rename({ x_dim_name: 'lon', y_dim_name: 'lat', @@ -805,6 +809,16 @@ def subset_spatial_impl(ds: xr.Dataset, :param monitor: optional progress monitor :return: Subset dataset """ + + # Validate whether lat and lon exists. + + if not hasattr(ds, 'lon') or not hasattr(ds, 'lat'): + raise ValidationError('Cannot apply regional subset. No (valid) geocoding found.') + + if hasattr(ds, 'lon') and len(ds.lon.shape) != 1 \ + or hasattr(ds, 'lat') and len(ds.lat.shape) != 1: + raise ValidationError('Geocoding not recognised. Variables "lat" and/or "lon" have more than one dimension.') + monitor.start('Subset', 10) # Validate input try: diff --git a/test/ops/test_subset.py b/test/ops/test_subset.py index f5a04f8e6..f6e5e5005 100644 --- a/test/ops/test_subset.py +++ b/test/ops/test_subset.py @@ -6,8 +6,11 @@ import numpy as np import xarray as xr +import pandas as pd from cate.core.op import OP_REGISTRY +from cate.core.opimpl import subset_spatial_impl +from cate.core.types import ValidationError from cate.ops import subset from cate.util.misc import object_to_qualified_name @@ -19,7 +22,44 @@ def assert_dataset_equal(expected, actual): assert expected.equals(actual), (expected, actual) +def get_test_subset_non_valid_lat_lon_dataset(): + temp = np.random.randn(2, 2, 3) + precip = np.random.rand(2, 2, 3) + lon = [[-40, 40], [-40, 40]] + lat = [[-50, 50], [-50, 50]] + return xr.Dataset({'temp': (['x', 'y', 'time'], temp), + 'precip': (['x', 'y', 'time'], precip)}, + coords={'lon': (['x', 'y'], lon), + 'lat': (['x', 'y'], lat), + 'time': pd.date_range('2014-09-06', periods=3)}) + + class TestSubsetSpatial(TestCase): + def test_subset_non_valid_lat_lon(self): + """ + Test whether lat and/or lon exist and if they exist whether they have dimension = 1 + :return: void + """ + + # Test whether lat lon exist + dataset = xr.Dataset({ + 'first': (['xc', 'yc', 'time'], np.ones([180, 360, 6])), + 'second': (['xc', 'yc', 'time'], np.ones([180, 360, 6])), + 'xc': np.linspace(-89.5, 89.5, 180), + 'yc': np.linspace(-179.5, 179.5, 360), + }) + + with self.assertRaises(ValidationError) as error: + subset_spatial_impl(dataset, (-40, 40, -50, 50)) + self.assertIn('No (valid) geocoding found', str(error.exception)) + + # test whether lat lon has the wrong dimension (!=1) + dataset = get_test_subset_non_valid_lat_lon_dataset() + + with self.assertRaises(ValidationError) as error: + subset_spatial_impl(dataset, (-40, 40, -50, 50)) + self.assertIn('Geocoding not recognised', str(error.exception)) + def test_nominal(self): """ Test general 'most expected' use case functionality.