From 85f6c8be1ce4e4f231c60f1db4cca7a73de19ccf Mon Sep 17 00:00:00 2001 From: David Hassell Date: Tue, 1 Apr 2025 14:17:09 +0100 Subject: [PATCH 1/3] Fix bug that caused wrong directions from cf.DimensionCoordinate.direction --- Changelog.rst | 3 +++ cf/dimensioncoordinate.py | 14 +++++++------- docs/source/recipes/plot_13_recipe.py | 1 - 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Changelog.rst b/Changelog.rst index f0d5f95692..a274abce9b 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -16,6 +16,9 @@ version 3.17.0 * Fix bug that caused `Data._axes` to be incorrect after a call to `cf.Field.collapse` (https://github.com/NCAS-CMS/cf-python/issues/857) +* Fix bug that caused wrong directions from + `cf.DimensionCoordinate.direction` + (https://github.com/NCAS-CMS/cf-python/issues/859) * Changed dependency: ``Python>=3.9.0`` * Changed dependency: ``numpy>=2.0.0`` * Changed dependency: ``cfdm>=1.12.0.0, <1.12.1.0`` diff --git a/cf/dimensioncoordinate.py b/cf/dimensioncoordinate.py index 3b16f053a8..a70e0ffeae 100644 --- a/cf/dimensioncoordinate.py +++ b/cf/dimensioncoordinate.py @@ -131,9 +131,9 @@ def _infer_direction(self): """Return True if a coordinate is increasing, otherwise return False. - A dimension coordinate construct is considered to be increasing if - its data array values are increasing in index space, or if it has - no data nor bounds. + A dimension coordinate construct is considered to be + increasing if its data array values are not strictly + decreasing in index space, or if it has no data nor bounds. If the direction can not be inferred from the data not bounds then the coordinate's units are used. @@ -168,12 +168,12 @@ def _infer_direction(self): c = data._get_cached_elements() if c: try: - return bool(c.get(0) < c.get(1)) + return bool(c.get(0) <= c.get(1)) except TypeError: pass data = data[:2].compute() - return bool(data.item(0) < data.item(1)) + return bool(data.item(0) <= data.item(1)) # Still here? data = self.get_bounds_data(None, _fill_value=False) @@ -182,12 +182,12 @@ def _infer_direction(self): c = data._get_cached_elements() if c: try: - return bool(c.get(0) < c.get(1)) + return bool(c.get(0) <= c.get(1)) except TypeError: pass b = data[0].compute() - return bool(b.item(0) < b.item(1)) + return bool(b.item(0) <= b.item(1)) # Still here? Then infer the direction from the units. return not self.Units.ispressure diff --git a/docs/source/recipes/plot_13_recipe.py b/docs/source/recipes/plot_13_recipe.py index bf0398713e..4758525c5b 100644 --- a/docs/source/recipes/plot_13_recipe.py +++ b/docs/source/recipes/plot_13_recipe.py @@ -24,7 +24,6 @@ import cf - # %% # 2. Read and select the SST by index and look at its contents: sst = cf.read("~/recipes/ERA5_monthly_averaged_SST.nc")[0] From e01dbd902cac38a71b719918144a86fc5617e198 Mon Sep 17 00:00:00 2001 From: David Hassell Date: Tue, 1 Apr 2025 14:18:33 +0100 Subject: [PATCH 2/3] Fix bug that caused wrong directions from cf.DimensionCoordinate.direction --- docs/source/recipes/plot_13_recipe.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/recipes/plot_13_recipe.py b/docs/source/recipes/plot_13_recipe.py index 4758525c5b..bf0398713e 100644 --- a/docs/source/recipes/plot_13_recipe.py +++ b/docs/source/recipes/plot_13_recipe.py @@ -24,6 +24,7 @@ import cf + # %% # 2. Read and select the SST by index and look at its contents: sst = cf.read("~/recipes/ERA5_monthly_averaged_SST.nc")[0] From 0e24f3b4a20307fbde7cb859674f59c06bd4eee5 Mon Sep 17 00:00:00 2001 From: David Hassell Date: Tue, 1 Apr 2025 16:10:14 +0100 Subject: [PATCH 3/3] add test for cf.DimensionCoordinate.direction --- cf/test/test_DimensionCoordinate.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/cf/test/test_DimensionCoordinate.py b/cf/test/test_DimensionCoordinate.py index 35694b6aeb..19cf90fa3d 100644 --- a/cf/test/test_DimensionCoordinate.py +++ b/cf/test/test_DimensionCoordinate.py @@ -809,6 +809,30 @@ def test_DimensionCoordinate_anchor(self): self.assertEqual(e[0].array, d[0].array - 360) + def test_DimensionCoordinate_direction(self): + """Test DimensionCoordinate.direction""" + d = self.dim.copy() + + # Test the use case of + # https://github.com/NCAS-CMS/cf-python/issues/859 + # + # Create a coordinate with all equal values + d.data[...] = d[0].array + for i, x in enumerate(d.array): + d.bounds.data[i, :] = x + + d._custom["direction"] = None # Force a re-calculation of direction + self.assertTrue(d.direction()) + d._custom["direction"] = None + self.assertTrue(d[0].direction()) + + d.del_bounds() + d._custom["direction"] = None + self.assertTrue(d.direction()) + d._custom["direction"] = None + self.assertTrue(d[0].direction()) + + if __name__ == "__main__": print("Run date:", datetime.datetime.now()) cf.environment()