def test_select_single_vertice(self): """ Test with a polygon that encloses a single pixel vertice, but no centers. That is, crosses four pixels """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) poly = ((25, 2), (27, 40), (58, 38), (54, 4)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([2, 2, 3])), 'second': (['lat', 'lon', 'time'], np.ones([2, 2, 3])), 'lat': [15., 45.], 'lon': [15., 45.], 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_non_geospatial_variable(self): """ Test that subsetting a dataset that contains a non-geospatial dataset skips such a dataset """ dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'third': (['time'], np.ones([6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360), 'time': np.array([0, 1, 2, 3, 4, 5])}) actual = subset.subset_spatial(dataset, "-20, -10, 20, 10") expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([22, 42, 6])), 'second': (['lat', 'lon', 'time'], np.ones([22, 42, 6])), 'third': (['time'], np.ones([6])), 'lat': np.linspace(-10.5, 10.5, 22), 'lon': np.linspace(-20.5, 20.5, 42), 'time': np.array([0, 1, 2, 3, 4, 5])}) assert_dataset_equal(expected, actual) poly = "POLYGON ((6.609745636041873 45.391851854914776, 19.720614826531428 45.391851854914776, 19.720614826531428 37.06301149556095, 6.609745636041874 37.06301149556095, 6.609745636041873 45.391851854914776))" actual = subset.subset_spatial(dataset, poly, mask=True) xr.testing.assert_equal(expected.third, actual.third)
def test_select_1d_lon(self): """ Test with a polygon that runs over pixel boundaries in the longitude direction. E.g., selects a single row """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) poly = ((-28, 32), (-26, 58), (28, 52), (25, 33)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 2, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 2, 3])), 'lat': [45.], 'lon': [-15., 15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_select_1d_lat(self): """ Test with a polyon that runs over pixel boundaries in the latitude direction, resulting in selecting a single column """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) poly = ((25, 2), (27, 47), (12, 50), (10, 4)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([2, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([2, 1, 3])), 'lat': [15., 45.], 'lon': [15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_select_single_vertice(self): """ Test with a polygon that encloses a single pixel vertice, but no centers. That is, crosses four pixels """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) poly = ((25, 2), (27, 40), (58, 38), (54, 4)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([2, 2, 3])), 'second': (['lat', 'lon', 'time'], np.ones([2, 2, 3])), 'lat': [15., 45.], 'lon': [15., 45.], 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_select_1d_lat(self): """ Test with a polyon that runs over pixel boundaries in the latitude direction, resulting in selecting a single column """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) poly = ((25, 2), (27, 47), (12, 50), (10, 4)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([2, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([2, 1, 3])), 'lat': [15., 45.], 'lon': [15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_select_1d_lon(self): """ Test with a polygon that runs over pixel boundaries in the longitude direction. E.g., selects a single row """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) poly = ((-28, 32), (-26, 58), (28, 52), (25, 33)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 2, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 2, 3])), 'lat': [45.], 'lon': [-15., 15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_select_single_center(self): """ Test subset spatial with a polygon that completely fits inside pixel bounds """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) poly = ((32, 2), (34, 28), (58, 29), (54, 4)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'lat': [15.], 'lon': [45.], 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_antimeridian_arbitrary_inverted(self): antimeridian_pol = str('POLYGON((' '162.0703125 39.639537564366705,' '-155.390625 39.774769485295465,' '-155.56640625 12.726084296948184,' '162.24609375 12.897489183755905,' '161.89453125 26.745610382199025,' '162.0703125 39.639537564366705' '))') # Inverted lat dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(89.5, -89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) with self.assertRaises(Exception) as cm: subset.subset_spatial(dataset, antimeridian_pol) self.assertEqual( str(cm.exception), "Spatial subsets crossing the anti-meridian are currently implemented for simple, " "rectangular polygons only.")
def test_select_single_center(self): """ Test subset spatial with a polygon that completely fits inside pixel bounds """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'second': (['lat', 'lon', 'time'], np.ones([6, 12, 3])), 'lat': np.linspace(-75, 75, 6), 'lon': np.linspace(-165, 165, 12), 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) poly = ((32, 2), (34, 28), (58, 29), (54, 4)) actual = subset.subset_spatial(dataset, region=poly) expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'lat': [15.], 'lon': [45.], 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) assert_dataset_equal(expected, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(expected, actual)
def test_non_geospatial_variable(self): """ Test that subsetting a dataset that contains a non-geospatial dataset skips such a dataset """ dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'third': (['time'], np.ones([6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360), 'time': np.array([0, 1, 2, 3, 4, 5]) }) actual = subset.subset_spatial(dataset, "-20, -10, 20, 10") expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([22, 42, 6])), 'second': (['lat', 'lon', 'time'], np.ones([22, 42, 6])), 'third': (['time'], np.ones([6])), 'lat': np.linspace(-10.5, 10.5, 22), 'lon': np.linspace(-20.5, 20.5, 42), 'time': np.array([0, 1, 2, 3, 4, 5]) }) assert_dataset_equal(expected, actual) poly = "POLYGON ((6.609745636041873 45.391851854914776, 19.720614826531428 45.391851854914776, 19.720614826531428 37.06301149556095, 6.609745636041874 37.06301149556095, 6.609745636041873 45.391851854914776))" actual = subset.subset_spatial(dataset, poly, mask=True) xr.testing.assert_equal(expected.third, actual.third)
def test_generic_masked_inverted(self): """ Test using a generic Polygon and masking """ # Africa a = str('POLYGON((-10.8984375 35.60371874069731,-19.16015625 ' '23.885837699861995,-20.56640625 17.14079039331665,-18.6328125 ' '7.536764322084079,-10.72265625 0.7031073524364783,10.37109375 ' '0.3515602939922709,10.37109375 -22.268764039073965,22.8515625 ' '-42.29356419217007,37.79296875 -27.21555620902968,49.39453125 ' '-3.5134210456400323,54.4921875 14.093957177836236,18.984375 ' '35.88905007936091,-10.8984375 35.60371874069731))') # Inverted lat dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(89.5, -89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360)}) actual = subset.subset_spatial(dataset, a) # Gulf of Guinea gog = actual.sel(method='nearest', **{'lon': 1.2, 'lat': -1.4}) self.assertTrue(np.isnan(gog['first']).all()) # Africa self.assertTrue(1 == actual.sel(method='nearest', **{'lon': 20.7, 'lat': 6.15}))
def anomaly_internal(ds: xr.Dataset, time_range: TimeRangeLike.TYPE = None, region: PolygonLike.TYPE = None, monitor: Monitor = Monitor.NONE) -> xr.Dataset: """ Calculate anomaly using as reference data the mean of an optional region and time slice from the given dataset. If no time slice/spatial region is given, the operation will calculate anomaly using the mean of the whole dataset as the reference. This is done for each data array in the dataset. :param ds: The dataset to calculate anomalies from :param time_range: Time range to use for reference data :param region: Spatial region to use for reference data :param monitor: a progress monitor. :return: The anomaly dataset """ ref = ds.copy() if time_range: time_range = TimeRangeLike.convert(time_range) ref = subset_temporal(ref, time_range) if region: region = PolygonLike.convert(region) ref = subset_spatial(ref, region) with monitor.observing("Calculating anomaly"): ref = ref.mean(keep_attrs=True, skipna=True) diff = ds - ref return diff
def test_generic_masked(self): """ Test using a generic Polygon and masking """ # Africa a = str( 'POLYGON((-10.8984375 35.60371874069731,-19.16015625 ' '23.885837699861995,-20.56640625 17.14079039331665,-18.6328125 ' '7.536764322084079,-10.72265625 0.7031073524364783,10.37109375 ' '0.3515602939922709,10.37109375 -22.268764039073965,22.8515625 ' '-42.29356419217007,37.79296875 -27.21555620902968,49.39453125 ' '-3.5134210456400323,54.4921875 14.093957177836236,18.984375 ' '35.88905007936091,-10.8984375 35.60371874069731))') dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) actual = subset.subset_spatial(dataset, a) # Gulf of Guinea gog = actual.sel(method='nearest', **{'lon': 1.2, 'lat': -1.4}) self.assertTrue(np.isnan(gog['first']).all()) # Africa self.assertTrue( 1 == actual.sel(method='nearest', **{ 'lon': 20.7, 'lat': 6.15 }))
def test_antimeridian_simple(self): dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) # With masking actual = subset.subset_spatial(dataset, '170, -5, -170, 5', mask=True) masked = actual.sel(method='nearest', **{'lon': 0, 'lat': 0}) self.assertTrue(np.isnan(masked['first']).all()) # With dropping actual = subset.subset_spatial(dataset, '170, -5, -170, 5', mask=False) self.assertEqual(20, len(actual.lon))
def test_antimeridian_arbitrary(self): antimeridian_pol = str('POLYGON((' '162.0703125 39.639537564366705,' '-155.390625 39.774769485295465,' '-155.56640625 12.726084296948184,' '162.24609375 12.897489183755905,' '161.89453125 26.745610382199025,' '162.0703125 39.639537564366705' '))') dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360)}) with self.assertRaises(Exception) as cm: subset.subset_spatial(dataset, antimeridian_pol) self.assertIn('anti-meridian', str(cm.exception))
def test_select_from_single_pixel(self): """ Test subset spatial where the input dataset has only one pixel """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'lat': [45.], 'lon': [15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) poly = ((-28, 32), (-26, 58), (28, 52), (25, 33)) actual = subset.subset_spatial(dataset, region=poly) assert_dataset_equal(dataset, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(dataset, actual)
def test_antimeridian_arbitrary(self): pol = str( 'POLYGON((162.0703125 39.639537564366705,-155.390625' '39.774769485295465,-155.56640625 12.726084296948184,162.24609375' '12.897489183755905,161.89453125 26.745610382199025,162.0703125' '39.639537564366705))') dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) with self.assertRaises(Exception) as err: subset.subset_spatial(dataset, pol) self.assertEqual('cannot convert geometry to a valid Polygon: ' + pol, str(err.exception))
def test_select_from_single_pixel(self): """ Test subset spatial where the input dataset has only one pixel """ # Masked dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'lat': [45.], 'lon': [15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) poly = ((-28, 32), (-26, 58), (28, 52), (25, 33)) actual = subset.subset_spatial(dataset, region=poly) assert_dataset_equal(dataset, actual) # Not masked actual = subset.subset_spatial(dataset, region=poly, mask=False) assert_dataset_equal(dataset, actual)
def test_antimeridian_simple(self): dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360)}) # With masking actual = subset.subset_spatial(dataset, '170, -5, -170, 5', mask=True) masked = actual.sel(method='nearest', **{'lon': 0, 'lat': 0}) self.assertTrue(np.isnan(masked['first']).all())
def test_out_of_bounds(self): """ Test that an appropriate error is raised when the polygon wouldn't select any data from the original dataset """ dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'lat': [45.], 'lon': [15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)]}) poly = ((32, 32), (34, 58), (56, 56), (58, 33)) with self.assertRaises(ValueError) as err: subset.subset_spatial(dataset, region=poly) self.assertIn('Can not select', str(err.exception)) # Not masked with self.assertRaises(ValueError) as err: subset.subset_spatial(dataset, region=poly, mask=False) self.assertIn('Can not select', str(err.exception))
def test_antimeridian_arbitrary(self): antimeridian_pol = str('POLYGON((' '162.0703125 39.639537564366705,' '-155.390625 39.774769485295465,' '-155.56640625 12.726084296948184,' '162.24609375 12.897489183755905,' '161.89453125 26.745610382199025,' '162.0703125 39.639537564366705' '))') dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) with self.assertRaises(Exception) as cm: subset.subset_spatial(dataset, antimeridian_pol) self.assertIn('anti-meridian', str(cm.exception))
def test_out_of_bounds(self): """ Test that an appropriate error is raised when the polygon wouldn't select any data from the original dataset """ dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'second': (['lat', 'lon', 'time'], np.ones([1, 1, 3])), 'lat': [45.], 'lon': [15.], 'time': [datetime(2000, x, 1) for x in range(1, 4)] }) poly = ((32, 32), (34, 58), (56, 56), (58, 33)) with self.assertRaises(ValueError) as err: subset.subset_spatial(dataset, region=poly) self.assertIn('Can not select', str(err.exception)) # Not masked with self.assertRaises(ValueError) as err: subset.subset_spatial(dataset, region=poly, mask=False) self.assertIn('Can not select', str(err.exception))
def test_antimeridian_arbitrary(self): pol = str( 'POLYGON((162.0703125 39.639537564366705,-155.390625' '39.774769485295465,-155.56640625 12.726084296948184,162.24609375' '12.897489183755905,161.89453125 26.745610382199025,162.0703125' '39.639537564366705))') dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) with self.assertRaises(Exception) as cm: subset.subset_spatial(dataset, pol) self.assertEqual( str(cm.exception), "input 'region' for operation 'cate.ops.subset.subset_spatial': " "cannot convert value <POLYGON((162.0703125 39.63953756436670...> to PolygonLike" )
def test_nominal(self): """ Test general 'most expected' use case functionality. """ dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360)}) actual = subset.subset_spatial(dataset, "-20, -10, 20, 10") expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([22, 42, 6])), 'second': (['lat', 'lon', 'time'], np.ones([22, 42, 6])), 'lat': np.linspace(-10.5, 10.5, 22), 'lon': np.linspace(-20.5, 20.5, 42)}) assert_dataset_equal(expected, actual)
def test_inverted_dims_nominal(self): """ Test if the implementation is dimension order agnostic. """ # Inverted lat dataset = xr.Dataset({ 'first': (['lon', 'lat', 'time'], np.ones([360, 180, 6])), 'second': (['lon', 'lat', 'time'], np.ones([360, 180, 6])), 'lat': np.linspace(89.5, -89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360)}) actual = subset.subset_spatial(dataset, "-20, -10, 20, 10") expected = xr.Dataset({ 'first': (['lon', 'lat', 'time'], np.ones([42, 22, 6])), 'second': (['lon', 'lat', 'time'], np.ones([42, 22, 6])), 'lat': np.linspace(10.5, -10.5, 22), 'lon': np.linspace(-20.5, 20.5, 42)}) assert_dataset_equal(expected, actual)
def _generic_index_calculation( ds: xr.Dataset, var: VarName.TYPE, region: PolygonLike.TYPE, window: int, file: str, name: str, threshold: float = None, monitor: Monitor = Monitor.NONE) -> pd.DataFrame: """ A generic index calculation. Where an index is defined as an anomaly against the given reference of a moving average of the given window size of the given given region of the given variable of the given dataset. :param ds: Dataset from which to calculate the index :param var: Variable from which to calculate index :param region: Spatial subset from which to calculate the index :param window: Window size for the moving average :param file: Path to the reference file :param threshold: Absolute threshold that indicates an ENSO event :param name: Name of the index :param monitor: a progress monitor. :return: A dataset that contains the index timeseries """ var = VarName.convert(var) region = PolygonLike.convert(region) with monitor.starting("Calculate the index", total_work=2): ds = select_var(ds, var) ds_subset = subset_spatial(ds, region) anom = anomaly_external(ds_subset, file, monitor=monitor.child(1)) with monitor.child(1).observing("Calculate mean"): ts = anom.mean(dim=['lat', 'lon']) df = pd.DataFrame(data=ts[var].values, columns=[name], index=ts.time.values) retval = df.rolling(window=window, center=True).mean().dropna() if threshold is None: return retval retval['El Nino'] = pd.Series((retval[name] > threshold), index=retval.index) retval['La Nina'] = pd.Series((retval[name] < -threshold), index=retval.index) return retval
def _generic_index_calculation(ds: xr.Dataset, var: VarName.TYPE, region: PolygonLike.TYPE, window: int, file: str, name: str, threshold: float = None, monitor: Monitor = Monitor.NONE) -> pd.DataFrame: """ A generic index calculation. Where an index is defined as an anomaly against the given reference of a moving average of the given window size of the given given region of the given variable of the given dataset. :param ds: Dataset from which to calculate the index :param var: Variable from which to calculate index :param region: Spatial subset from which to calculate the index :param window: Window size for the moving average :param file: Path to the reference file :param threshold: Absolute threshold that indicates an ENSO event :param name: Name of the index :param monitor: a progress monitor. :return: A dataset that contains the index timeseries """ var = VarName.convert(var) region = PolygonLike.convert(region) with monitor.starting("Calculate the index", total_work=2): ds = select_var(ds, var) ds_subset = subset_spatial(ds, region) anom = anomaly_external(ds_subset, file, monitor=monitor.child(1)) with monitor.child(1).observing("Calculate mean"): ts = anom.mean(dim=['lat', 'lon']) df = pd.DataFrame(data=ts[var].values, columns=[name], index=ts.time) retval = df.rolling(window=window, center=True).mean().dropna() if threshold is None: return retval retval['El Nino'] = pd.Series((retval[name] > threshold), index=retval.index) retval['La Nina'] = pd.Series((retval[name] < -threshold), index=retval.index) return retval
def test_inverted_dims(self): """ Test if the implementation is dimension order agnostic. """ dataset = xr.Dataset({ 'first': (['lon', 'lat', 'time'], np.ones([360, 180, 6])), 'second': (['lon', 'lat', 'time'], np.ones([360, 180, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) actual = subset.subset_spatial(dataset, "-20, -10, 20, 10") expected = xr.Dataset({ 'first': (['lon', 'lat', 'time'], np.ones([40, 20, 6])), 'second': (['lon', 'lat', 'time'], np.ones([40, 20, 6])), 'lat': np.linspace(-9.5, 9.5, 20), 'lon': np.linspace(-19.5, 19.5, 40) }) assert_dataset_equal(expected, actual)
def test_nominal(self): """ Test general 'most expected' use case functionality. """ dataset = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'second': (['lat', 'lon', 'time'], np.ones([180, 360, 6])), 'lat': np.linspace(-89.5, 89.5, 180), 'lon': np.linspace(-179.5, 179.5, 360) }) actual = subset.subset_spatial(dataset, "-20, -10, 20, 10") expected = xr.Dataset({ 'first': (['lat', 'lon', 'time'], np.ones([20, 40, 6])), 'second': (['lat', 'lon', 'time'], np.ones([20, 40, 6])), 'lat': np.linspace(-9.5, 9.5, 20), 'lon': np.linspace(-19.5, 19.5, 40) }) assert_dataset_equal(expected, actual)