Skip to content

Commit 7674087

Browse files
Fix s-grid rendering on Matplotlib 3.11
1 parent a775479 commit 7674087

2 files changed

Lines changed: 63 additions & 1 deletion

File tree

‎control/grid.py‎

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import mpl_toolkits.axisartist.angle_helper as angle_helper
1414
import numpy as np
1515
from matplotlib.projections import PolarAxes
16-
from matplotlib.transforms import Affine2D
16+
from matplotlib.transforms import Affine2D, Bbox
1717
from mpl_toolkits.axisartist import SubplotHost
1818
from mpl_toolkits.axisartist.grid_helper_curvelinear import \
1919
GridHelperCurveLinear
@@ -37,6 +37,12 @@ class ModifiedExtremeFinderCycle(angle_helper.ExtremeFinderCycle):
3737
https://matplotlib.org/_modules/mpl_toolkits/axisartist/angle_helper.html#ExtremeFinderCycle.__call__
3838
"""
3939
def __call__(self, transform_xy, x1, y1, x2, y2):
40+
# Matplotlib 3.11 moved this calculation to
41+
# _find_transformed_bbox(), which is also called directly by
42+
# GridFinder. Keep the legacy implementation for older releases.
43+
if hasattr(super(), '_find_transformed_bbox'):
44+
return super().__call__(transform_xy, x1, y1, x2, y2)
45+
4046
x, y = np.meshgrid(
4147
np.linspace(x1, x2, self.nx), np.linspace(y1, y2, self.ny))
4248
lon, lat = transform_xy(np.ravel(x), np.ravel(y))
@@ -77,6 +83,44 @@ def __call__(self, transform_xy, x1, y1, x2, y2):
7783

7884
return lon_min, lon_max, lat_min, lat_max
7985

86+
def _find_transformed_bbox(self, trans, bbox):
87+
"""Find grid extremes using the Matplotlib 3.11 interface."""
88+
grid = np.reshape(np.meshgrid(
89+
np.linspace(bbox.x0, bbox.x1, self.nx),
90+
np.linspace(bbox.y0, bbox.y1, self.ny)), (2, -1)).T
91+
lon, lat = trans.transform(grid).T
92+
93+
with np.errstate(invalid='ignore'):
94+
if self.lon_cycle is not None:
95+
lon0 = np.nanmin(lon)
96+
# Changed from 180 to 360 to be able to span only
97+
# 90-270 (left hand side)
98+
lon -= 360. * ((lon - lon0) > 360.)
99+
if self.lat_cycle is not None: # pragma: no cover
100+
lat0 = np.nanmin(lat)
101+
lat -= 360. * ((lat - lat0) > 180.)
102+
103+
transformed_bbox = Bbox.null()
104+
transformed_bbox.update_from_data_xy(np.column_stack([lon, lat]))
105+
transformed_bbox = transformed_bbox.expanded(
106+
1 + 2 / self.nx, 1 + 2 / self.ny)
107+
lon_min, lat_min, lon_max, lat_max = transformed_bbox.extents
108+
109+
if self.lon_cycle:
110+
lon_max = min(lon_max, lon_min + self.lon_cycle)
111+
if self.lat_cycle: # pragma: no cover
112+
lat_max = min(lat_max, lat_min + self.lat_cycle)
113+
114+
if self.lon_minmax is not None:
115+
lon_min = max(self.lon_minmax[0], lon_min)
116+
lon_max = min(self.lon_minmax[1], lon_max)
117+
118+
if self.lat_minmax is not None:
119+
lat_min = max(self.lat_minmax[0], lat_min)
120+
lat_max = min(self.lat_minmax[1], lat_max)
121+
122+
return Bbox.from_extents(lon_min, lat_min, lon_max, lat_max)
123+
80124

81125
def sgrid(subplot=(1, 1, 1), scaling=None):
82126
# From matplotlib demos:

‎control/tests/grid_test.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import numpy as np
2+
from matplotlib.transforms import Affine2D, Bbox
3+
4+
from control.grid import ModifiedExtremeFinderCycle
5+
6+
7+
def test_modified_extreme_finder_cycle():
8+
finder = ModifiedExtremeFinderCycle(
9+
20, 20, lon_cycle=360, lat_cycle=None,
10+
lon_minmax=(90, 270), lat_minmax=(0, np.inf))
11+
12+
limits = finder(lambda x, y: (x, y), 90, 0, 270, 1)
13+
np.testing.assert_allclose(limits, (90, 270, 0, 1.05))
14+
15+
transformed_bbox = finder._find_transformed_bbox(
16+
Affine2D(), Bbox.from_extents(90, 0, 270, 1))
17+
np.testing.assert_allclose(
18+
transformed_bbox.extents, (90, 0, 270, 1.05))

0 commit comments

Comments
 (0)