Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 474f6c5

Browse filesBrowse files
authored
Merge pull request #13980 from anntzer/polarzero
Don't let margins expand polar plots to negative radii by default.
2 parents 4236b57 + 0911f8a commit 474f6c5
Copy full SHA for 474f6c5

File tree

Expand file treeCollapse file tree

4 files changed

+76
-29
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+76
-29
lines changed
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Change in the application of ``Artist.sticky_edges``
2+
````````````````````````````````````````````````````
3+
4+
Previously, the ``sticky_edges`` attribute of artists was a list of values such
5+
that if an axis limit coincides with a sticky edge, it would not be expanded by
6+
the axes margins (this is the mechanism that e.g. prevents margins from being
7+
added around images).
8+
9+
``sticky_edges`` now have an additional effect on margins application: even if
10+
an axis limit did not coincide with a sticky edge, it cannot *cross* a sticky
11+
edge through margin application -- instead, the margins will only expand the
12+
axis limit until it bumps against the sticky edge.
13+
14+
This change improves the margins of axes displaying a `~Axes.streamplot`:
15+
16+
- if the streamplot goes all the way to the edges of the vector field, then the
17+
axis limits are set to match exactly the vector field limits (whereas they
18+
would be sometimes be off by a small floating point error previously).
19+
- if the streamplot does not reach the edges of the vector field (e.g., due to
20+
the use of ``start_points`` and ``maxlength``), then margins expansion will
21+
not cross the the vector field limits anymore.
22+
23+
This change is also used internally to ensure that polar plots don't display
24+
negative *r* values unless the user really passes in a negative value.

‎lib/matplotlib/axes/_base.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_base.py
+28-23Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,14 +2402,14 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True):
24022402
(self._xmargin and scalex and self._autoscaleXon) or
24032403
(self._ymargin and scaley and self._autoscaleYon)):
24042404
stickies = [artist.sticky_edges for artist in self.get_children()]
2405-
x_stickies = np.array([x for sticky in stickies for x in sticky.x])
2406-
y_stickies = np.array([y for sticky in stickies for y in sticky.y])
2407-
if self.get_xscale().lower() == 'log':
2408-
x_stickies = x_stickies[x_stickies > 0]
2409-
if self.get_yscale().lower() == 'log':
2410-
y_stickies = y_stickies[y_stickies > 0]
24112405
else: # Small optimization.
2412-
x_stickies, y_stickies = [], []
2406+
stickies = []
2407+
x_stickies = np.sort([x for sticky in stickies for x in sticky.x])
2408+
y_stickies = np.sort([y for sticky in stickies for y in sticky.y])
2409+
if self.get_xscale().lower() == 'log':
2410+
x_stickies = x_stickies[x_stickies > 0]
2411+
if self.get_yscale().lower() == 'log':
2412+
y_stickies = y_stickies[y_stickies > 0]
24132413

24142414
def handle_single_axis(scale, autoscaleon, shared_axes, interval,
24152415
minpos, axis, margin, stickies, set_bound):
@@ -2450,29 +2450,34 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
24502450
locator = axis.get_major_locator()
24512451
x0, x1 = locator.nonsingular(x0, x1)
24522452

2453+
# Prevent margin addition from crossing a sticky value. Small
2454+
# tolerances (whose values come from isclose()) must be used due to
2455+
# floating point issues with streamplot.
2456+
def tol(x): return 1e-5 * abs(x) + 1e-8
2457+
# Index of largest element < x0 + tol, if any.
2458+
i0 = stickies.searchsorted(x0 + tol(x0)) - 1
2459+
x0bound = stickies[i0] if i0 != -1 else None
2460+
# Index of smallest element > x1 - tol, if any.
2461+
i1 = stickies.searchsorted(x1 - tol(x1))
2462+
x1bound = stickies[i1] if i1 != len(stickies) else None
2463+
24532464
# Add the margin in figure space and then transform back, to handle
24542465
# non-linear scales.
24552466
minpos = getattr(bb, minpos)
24562467
transform = axis.get_transform()
24572468
inverse_trans = transform.inverted()
2458-
# We cannot use exact equality due to floating point issues e.g.
2459-
# with streamplot.
2460-
do_lower_margin = not np.any(np.isclose(x0, stickies))
2461-
do_upper_margin = not np.any(np.isclose(x1, stickies))
24622469
x0, x1 = axis._scale.limit_range_for_scale(x0, x1, minpos)
24632470
x0t, x1t = transform.transform([x0, x1])
2464-
2465-
if np.isfinite(x1t) and np.isfinite(x0t):
2466-
delta = (x1t - x0t) * margin
2467-
else:
2468-
# If at least one bound isn't finite, set margin to zero
2469-
delta = 0
2470-
2471-
if do_lower_margin:
2472-
x0t -= delta
2473-
if do_upper_margin:
2474-
x1t += delta
2475-
x0, x1 = inverse_trans.transform([x0t, x1t])
2471+
delta = (x1t - x0t) * margin
2472+
if not np.isfinite(delta):
2473+
delta = 0 # If a bound isn't finite, set margin to zero.
2474+
x0, x1 = inverse_trans.transform([x0t - delta, x1t + delta])
2475+
2476+
# Apply sticky bounds.
2477+
if x0bound is not None:
2478+
x0 = max(x0, x0bound)
2479+
if x1bound is not None:
2480+
x1 = min(x1, x1bound)
24762481

24772482
if not self._tight:
24782483
x0, x1 = locator.view_limits(x0, x1)

‎lib/matplotlib/tests/test_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_axes.py
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,12 @@ def test_polar_rlim_bottom(fig_test, fig_ref):
797797
ax.set_rmin(.5)
798798

799799

800+
def test_polar_rlim_zero():
801+
ax = plt.figure().add_subplot(projection='polar')
802+
ax.plot(np.arange(10), np.arange(10) + .01)
803+
assert ax.get_ylim()[0] == 0
804+
805+
800806
@image_comparison(baseline_images=['axvspan_epoch'])
801807
def test_axvspan_epoch():
802808
from datetime import datetime

‎lib/matplotlib/tests/test_streamplot.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_streamplot.py
+18-6Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@ def test_linewidth():
5555
X, Y, U, V = velocity_field()
5656
speed = np.hypot(U, V)
5757
lw = 5 * speed / speed.max()
58-
df = 25 / 30 # Compatibility factor for old test image
59-
plt.streamplot(X, Y, U, V, density=[0.5 * df, 1. * df], color='k',
60-
linewidth=lw)
58+
# Compatibility for old test image
59+
df = 25 / 30
60+
ax = plt.figure().subplots()
61+
ax.set(xlim=(-3.0, 2.9999999999999947),
62+
ylim=(-3.0000000000000004, 2.9999999999999947))
63+
ax.streamplot(X, Y, U, V, density=[0.5 * df, 1. * df], color='k',
64+
linewidth=lw)
6165

6266

6367
@image_comparison(baseline_images=['streamplot_masks_and_nans'],
@@ -69,16 +73,24 @@ def test_masks_and_nans():
6973
mask[40:60, 40:60] = 1
7074
U[:20, :20] = np.nan
7175
U = np.ma.array(U, mask=mask)
76+
# Compatibility for old test image
77+
ax = plt.figure().subplots()
78+
ax.set(xlim=(-3.0, 2.9999999999999947),
79+
ylim=(-3.0000000000000004, 2.9999999999999947))
7280
with np.errstate(invalid='ignore'):
73-
plt.streamplot(X, Y, U, V, color=U, cmap=plt.cm.Blues)
81+
ax.streamplot(X, Y, U, V, color=U, cmap=plt.cm.Blues)
7482

7583

7684
@image_comparison(baseline_images=['streamplot_maxlength'],
7785
extensions=['png'], remove_text=True, style='mpl20')
7886
def test_maxlength():
7987
x, y, U, V = swirl_velocity_field()
80-
plt.streamplot(x, y, U, V, maxlength=10., start_points=[[0., 1.5]],
81-
linewidth=2, density=2)
88+
ax = plt.figure().subplots()
89+
ax.streamplot(x, y, U, V, maxlength=10., start_points=[[0., 1.5]],
90+
linewidth=2, density=2)
91+
assert ax.get_xlim()[-1] == ax.get_ylim()[-1] == 3
92+
# Compatibility for old test image
93+
ax.set(xlim=(None, 3.2555988021882305), ylim=(None, 3.078326760195413))
8294

8395

8496
@image_comparison(baseline_images=['streamplot_direction'],

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.