From c8d5b7f350bef1666bdab70f599752c85dd11de6 Mon Sep 17 00:00:00 2001 From: Lukas Riedel <34276446+peanutfun@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:26:10 +0100 Subject: [PATCH] Try to read event coordinate as date --- climada/hazard/base.py | 24 +++++++++++++++++++++++- climada/hazard/test/test_base_xarray.py | 21 +++++++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/climada/hazard/base.py b/climada/hazard/base.py index db54fd4f7..683677f2c 100644 --- a/climada/hazard/base.py +++ b/climada/hazard/base.py @@ -826,6 +826,24 @@ def date_to_ordinal_accessor( ) return np.zeros(array.shape) + def year_month_day_accessor( + array: xr.DataArray, strict: bool = True + ) -> np.ndarray: + """Take an array and return am array of YYYY-MM-DD strings""" + try: + return array.dt.strftime("%Y-%m-%d").values + + # Handle access errors + except (ValueError, TypeError) as err: + if strict: + raise err + + LOGGER.warning( + "Failed to read values of '%s' as dates. Hazard.event_name will be " + "empty strings" % array.name + ) + return np.full(array.shape, "") + def maybe_repeat(values: np.ndarray, times: int) -> np.ndarray: """Return the array or repeat a single-valued array @@ -855,7 +873,11 @@ def maybe_repeat(values: np.ndarray, times: int) -> np.ndarray: None, np.ones(num_events), np.array(range(num_events), dtype=int) + 1, - [""] * num_events, + list( + year_month_day_accessor( + data[coords["event"]], strict=False + ).flat + ), date_to_ordinal_accessor(data[coords["event"]], strict=False), ], # The accessor for the data in the Dataset diff --git a/climada/hazard/test/test_base_xarray.py b/climada/hazard/test/test_base_xarray.py index f917100af..a96643ef4 100644 --- a/climada/hazard/test/test_base_xarray.py +++ b/climada/hazard/test/test_base_xarray.py @@ -71,9 +71,8 @@ def _assert_default_values(self, hazard): self.assertEqual(hazard.haz_type, "") self.assertEqual(hazard.units, "") np.testing.assert_array_equal(hazard.event_id, [1, 2]) - np.testing.assert_array_equal(hazard.event_name, ["", ""]) np.testing.assert_array_equal( - hazard.date, [val.toordinal() for val in self.time] + hazard.event_name, [x.strftime("%Y-%m-%d") for x in self.time] ) np.testing.assert_array_equal(hazard.frequency, np.ones(hazard.event_id.size)) @@ -177,8 +176,12 @@ def test_event_no_time(self): with self.assertLogs("climada.hazard.base", "WARNING") as cm: hazard = Hazard.from_xarray_raster(dataset, "", "") np.testing.assert_array_equal(hazard.date, np.zeros(size)) + np.testing.assert_array_equal(hazard.event_name, np.full(size, "")) + self.assertIn( + "Failed to read values of 'time' as dates.", cm.output[0] + ) self.assertIn( - "Failed to read values of 'time' as dates or ordinals.", cm.output[0] + "Failed to read values of 'time' as dates or ordinals.", cm.output[1] ) def test_data_vars(self): @@ -361,7 +364,9 @@ def test_missing_dims(self): ds = ds.isel(time=0).squeeze() hazard = Hazard.from_xarray_raster(ds, "", "") self._assert_default_types(hazard) - np.testing.assert_array_equal(hazard.event_name, [""]) + np.testing.assert_array_equal( + hazard.event_name, [self.time[0].strftime("%Y-%m-%d")] + ) np.testing.assert_array_equal(hazard.date, [self.time[0].toordinal()]) np.testing.assert_array_equal(hazard.centroids.lat, [0, 0, 0, 1, 1, 1]) np.testing.assert_array_equal(hazard.centroids.lon, [0, 1, 2, 0, 1, 2]) @@ -383,7 +388,9 @@ def test_missing_dims(self): ds = ds.expand_dims(time=[np.datetime64("2022-01-01")]) hazard = Hazard.from_xarray_raster(ds, "", "") self._assert_default_types(hazard) - np.testing.assert_array_equal(hazard.event_name, [""]) + np.testing.assert_array_equal( + hazard.event_name, ["2022-01-01"] + ) np.testing.assert_array_equal( hazard.date, [dt.datetime(2022, 1, 1).toordinal()] ) @@ -563,7 +570,9 @@ def test_2D_time(self): np.testing.assert_array_equal( hazard.date, [val.toordinal() for val in time.flat] ) - np.testing.assert_array_equal(hazard.event_name, [""] * 4) + np.testing.assert_array_equal( + hazard.event_name, ["1999-01-01", "1999-02-01", "2000-01-01", "2000-02-01"] + ) def test_errors(self): """Check if expected errors are thrown"""