From 236bb0625c68c19510901f65fcf10b2b9ebf7b88 Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 23 Sep 2025 13:41:51 +0200 Subject: [PATCH 1/2] remove deprecated infer_interval_breaks fcn --- mplotutils/__init__.py | 3 - mplotutils/_xrcompat.py | 89 ------------------- .../tests/test_infer_interval_breaks.py | 82 ----------------- mplotutils/tests/test_rename_modules.py | 1 - mplotutils/xrcompat.py | 8 -- 5 files changed, 183 deletions(-) delete mode 100644 mplotutils/_xrcompat.py delete mode 100644 mplotutils/tests/test_infer_interval_breaks.py delete mode 100644 mplotutils/xrcompat.py diff --git a/mplotutils/__init__.py b/mplotutils/__init__.py index b5029c0..ae5abf7 100644 --- a/mplotutils/__init__.py +++ b/mplotutils/__init__.py @@ -19,7 +19,6 @@ from mplotutils._map_layout import set_map_layout from mplotutils._mpl import _get_renderer from mplotutils._savefig import autodraw -from mplotutils._xrcompat import infer_interval_breaks autodraw(True) @@ -35,7 +34,6 @@ "hatch_map_global", "hatch_map", "hatch", - "infer_interval_breaks", "sample_data_map", "sample_dataarray", "set_map_layout", @@ -61,7 +59,6 @@ def __getattr__(attr): "colormaps", "map_layout", "mpl", - "xrcompat", ) import mplotutils diff --git a/mplotutils/_xrcompat.py b/mplotutils/_xrcompat.py deleted file mode 100644 index a6ec79d..0000000 --- a/mplotutils/_xrcompat.py +++ /dev/null @@ -1,89 +0,0 @@ -# code vendored from xarray under the conditions of their license -# see licenses/XARRAY_LICENSE - -import warnings - -import numpy as np - - -def infer_interval_breaks(x, y, clip=False): - """find edges of gridcells, given their centers""" - - # TODO: require cartopy >= 0.21 before removing this function - warnings.warn( - "It's no longer necessary to compute the edges of the array. This is now done " - "in matplotlib. This function will be removed from mplotutils in a future " - "version.", - FutureWarning, - ) - - if len(x.shape) == 1: - x = _infer_interval_breaks(x) - y = _infer_interval_breaks(y) - else: - # we have to infer the intervals on both axes - x = _infer_interval_breaks(x, axis=1) - x = _infer_interval_breaks(x, axis=0) - y = _infer_interval_breaks(y, axis=1) - y = _infer_interval_breaks(y, axis=0) - - if clip: - y = np.clip(y, -90, 90) - - return x, y - - -def _infer_interval_breaks(coord, axis=0): - """ - >>> _infer_interval_breaks(np.arange(5)) - array([-0.5, 0.5, 1.5, 2.5, 3.5, 4.5]) - >>> _infer_interval_breaks([[0, 1], [3, 4]], axis=1) - array([[-0.5, 0.5, 1.5], - [ 2.5, 3.5, 4.5]]) - """ - - if not _is_monotonic(coord, axis=axis): - raise ValueError( - "The input coordinate is not sorted in increasing " - f"order along axis {axis}. This can lead to unexpected " - "results. Consider calling the `sortby` method on " - "the input DataArray. To plot data with categorical " - "axes, consider using the `heatmap` function from " - "the `seaborn` statistical plotting library." - ) - - coord = np.asarray(coord) - deltas = 0.5 * np.diff(coord, axis=axis) - if deltas.size == 0: - deltas = np.array(0.0) - first = np.take(coord, [0], axis=axis) - np.take(deltas, [0], axis=axis) - last = np.take(coord, [-1], axis=axis) + np.take(deltas, [-1], axis=axis) - trim_last = tuple( - slice(None, -1) if n == axis else slice(None) for n in range(coord.ndim) - ) - return np.concatenate([first, coord[trim_last] + deltas, last], axis=axis) - - -def _is_monotonic(coord, axis=0): - """ - >>> _is_monotonic(np.array([0, 1, 2])) - np.True_ - >>> _is_monotonic(np.array([2, 1, 0])) - np.True_ - >>> _is_monotonic(np.array([0, 2, 1])) - np.False_ - """ - coord = np.asarray(coord) - - if coord.shape[axis] < 3: - return True - else: - n = coord.shape[axis] - delta_pos = coord.take(np.arange(1, n), axis=axis) >= coord.take( - np.arange(0, n - 1), axis=axis - ) - delta_neg = coord.take(np.arange(1, n), axis=axis) <= coord.take( - np.arange(0, n - 1), axis=axis - ) - - return np.all(delta_pos) or np.all(delta_neg) diff --git a/mplotutils/tests/test_infer_interval_breaks.py b/mplotutils/tests/test_infer_interval_breaks.py deleted file mode 100644 index affae52..0000000 --- a/mplotutils/tests/test_infer_interval_breaks.py +++ /dev/null @@ -1,82 +0,0 @@ -import numpy as np -import pytest -from numpy.testing import assert_array_equal # noqa: F401 - -from mplotutils._xrcompat import _infer_interval_breaks, infer_interval_breaks - - -def test_infer_interval_breaks_warns(): - with pytest.warns(FutureWarning): - infer_interval_breaks(np.array([1, 2, 3]), np.array([1, 2, 3])) - - -def test__infer_interval_breaks(): - assert_array_equal([-0.5, 0.5, 1.5], _infer_interval_breaks([0, 1])) - assert_array_equal( - [-0.5, 0.5, 5.0, 9.5, 10.5], _infer_interval_breaks([0, 1, 9, 10]) - ) - - # make a bounded 2D array that we will center and re-infer - xref, yref = np.meshgrid(np.arange(6), np.arange(5)) - cx = (xref[1:, 1:] + xref[:-1, :-1]) / 2 - cy = (yref[1:, 1:] + yref[:-1, :-1]) / 2 - x = _infer_interval_breaks(cx, axis=1) - x = _infer_interval_breaks(x, axis=0) - y = _infer_interval_breaks(cy, axis=1) - y = _infer_interval_breaks(y, axis=0) - np.testing.assert_allclose(xref, x) - np.testing.assert_allclose(yref, y) - - # test that warning is raised for non-monotonic inputs - # with raises(ValueError): - # _infer_interval_breaks(np.array([0, 2, 1])) - - -@pytest.mark.filterwarnings("ignore:It's no longer necessary") -def test_infer_interval_breaks(): - # 1D - lon = np.arange(5, 356, 10) - lat = np.arange(-85, 86, 10) - - lon_expected = np.arange(0, 361, 10) - lat_expected = np.arange(-90, 91, 10) - - lon_result, lat_result = infer_interval_breaks(lon, lat) - - np.testing.assert_allclose(lon_expected, lon_result) - np.testing.assert_allclose(lat_expected, lat_result) - - # 2D, as above - - xref, yref = np.meshgrid(np.arange(6), np.arange(5)) - cx = (xref[1:, 1:] + xref[:-1, :-1]) / 2 - cy = (yref[1:, 1:] + yref[:-1, :-1]) / 2 - - x, y = infer_interval_breaks(cx, cy) - - np.testing.assert_allclose(xref, x) - np.testing.assert_allclose(yref, y) - - -@pytest.mark.filterwarnings("ignore:It's no longer necessary") -def test_infer_interval_breaks_clip(): - # no clip - lon = np.arange(5, 356, 10) - lat = np.arange(-90, 91, 10) - - lon_expected = np.arange(0, 361, 10) - lat_expected = np.arange(-95, 96, 10) - - lon_result, lat_result = infer_interval_breaks(lon, lat) - - np.testing.assert_allclose(lon_expected, lon_result) - np.testing.assert_allclose(lat_expected, lat_result) - - # clip - lat_expected[0] = -90 - lat_expected[-1] = 90 - - lon_result, lat_result = infer_interval_breaks(lon, lat, clip=True) - - np.testing.assert_allclose(lon_expected, lon_result) - np.testing.assert_allclose(lat_expected, lat_result) diff --git a/mplotutils/tests/test_rename_modules.py b/mplotutils/tests/test_rename_modules.py index 08bf6ac..37031c2 100644 --- a/mplotutils/tests/test_rename_modules.py +++ b/mplotutils/tests/test_rename_modules.py @@ -17,7 +17,6 @@ "colormaps": ("from_levels_and_cmap",), "map_layout": ("set_map_layout",), "mpl": ("_get_renderer",), - "xrcompat": ("infer_interval_breaks",), } diff --git a/mplotutils/xrcompat.py b/mplotutils/xrcompat.py deleted file mode 100644 index 17fb0e5..0000000 --- a/mplotutils/xrcompat.py +++ /dev/null @@ -1,8 +0,0 @@ -from mplotutils import _xrcompat -from mplotutils._deprecate import _module_renamed_warning - - -def __getattr__(attr_name): - attr = getattr(_xrcompat, attr_name) - _module_renamed_warning(attr_name, "xrcompat") - return attr From aa0a8735f816a71ae857120201b36a17777a790a Mon Sep 17 00:00:00 2001 From: Mathias Hauser Date: Tue, 23 Sep 2025 13:45:04 +0200 Subject: [PATCH 2/2] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a094e99..0917e9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ | numpy | 1.24 | 1.26 | | xarray | 2023.9 | 2024.7 | + +- Removed `infer_interval_breaks` function deprecated in v0.3.0 ([#177](https://github.com/mpytools/mplotutils/pull/177)). + ### Enhancements - Add python 3.13 to list of supported versions ([#158](https://github.com/mpytools/mplotutils/pull/158)).