8000 Sticky margins by anntzer · Pull Request #7476 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Sticky margins #7476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Dec 4, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
change stickies to sticky_edges; clarify edge calculation in contour
  • Loading branch information
efiring committed Nov 25, 2016
commit 36fcfe5324a5b1810677957fa94cdd88095865a8
2 changes: 1 addition & 1 deletion doc/api/artist_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Margins and Autoscaling
:toctree: _as_gen
:nosignatures:

Artist.stickies
Artist.sticky_edges

Clipping
--------
Expand Down
6 changes: 3 additions & 3 deletions lib/matplotlib/artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def __init__(self):
self._snap = None
self._sketch = rcParams['path.sketch']
self._path_effects = rcParams['path.effects']
self._stickies = _XYPair([], [])
self._sticky_edges = _XYPair([], [])

def __getstate__(self):
d = self.__dict__.copy()
Expand Down Expand Up @@ -929,14 +929,14 @@ def set_zorder(self, level):
self.stale = True

@property
def stickies(self):
def sticky_edges(self):
"""
The `x` and `y` sticky lists for the artist.

This attribute cannot be assigned to; however, the `x` and `y` lists
can be modified in place as needed.
"""
return self._stickies
return self._sticky_edges

def update_from(self, other):
'Copy properties from *other* to *self*.'
Expand Down
20 changes: 10 additions & 10 deletions lib/matplotlib/axes/_axes.py
8000
Original file line number Diff line number Diff line change
Expand Up @@ -2125,9 +2125,9 @@ def make_iterable(x):
r.update(kwargs)
r.get_path()._interpolation_steps = 100
if orientation == 'vertical':
r.stickies.y.append(0)
r.sticky_edges.y.append(0)
elif orientation == 'horizontal':
r.stickies.x.append(0)
r.sticky_edges.x.append(0)
self.add_patch(r)
patches.append(r)

Expand Down Expand Up @@ -5483,8 +5483,8 @@ def pcolor(self, *args, **kwargs):

self.add_collection(collection, autolim=False)
corners = (minx, miny), (maxx, maxy)
collection.stickies.x[:] = [minx, maxx]
collection.stickies.y[:] = [miny, maxy]
collection.sticky_edges.x[:] = [minx, maxx]
collection.sticky_edges.y[:] = [miny, maxy]
self.update_datalim(corners)
self.autoscale_view()
return collection
Expand Down Expand Up @@ -5635,8 +5635,8 @@ def pcolormesh(self, *args, **kwargs):

self.add_collection(collection, autolim=False)
corners = (minx, miny), (maxx, maxy)
collection.stickies.x[:] = [minx, maxx]
collection.stickies.y[:] = [miny, maxy]
collection.sticky_edges.x[:] = [minx, maxx]
collection.sticky_edges.y[:] = [miny, maxy]
self.update_datalim(corners)
self.autoscale_view()
return collection
Expand Down Expand Up @@ -5825,8 +5825,8 @@ def pcolorfast(self, *args, **kwargs):
ret.set_clim(vmin, vmax)
else:
ret.autoscale_None()
ret.stickies.x[:] = [xl, xr]
ret.stickies.y[:] = [yb, yt]
ret.sticky_edges.x[:] = [xl, xr]
ret.sticky_edges.y[:] = [yb, yt]
self.update_datalim(np.array([[xl, yb], [xr, yt]]))
self.autoscale_view(tight=True)
return ret
Expand Down Expand Up @@ -6379,9 +6379,9 @@ def _normalize_input(inp, ename='input'):
for patch_list in patches:
for patch in patch_list:
if orientation == 'vertical':
patch.stickies.y.append(minimum)
patch.sticky_edges.y.append(minimum)
elif orientation == 'horizontal':
patch.stickies.x.append(minimum)
patch.sticky_edges.x.append(minimum)

# we return patches, so put it back in the expected order
patches.reverse()
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2203,7 +2203,7 @@ def autoscale_view(self, tight=None, scalex=True, scaley=True):
self._tight = bool(tight)

if self._xmargin or self._ymargin:
stickies = [artist.stickies for artist in self.get_children()]
stickies = [artist.sticky_edges for artist in self.get_children()]
x_stickies = sum([sticky.x for sticky in stickies], [])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this better written as

x_stickies = [x for sticky in stickies for x in sticky.x]

?

685C

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is 🚲 🏠 ing, treat as such

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably best to use np.concatenate.

y_stickies = sum([sticky.y for sticky in stickies], [])
if self.get_xscale().lower() == 'log':
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the presence of negative stickies with log scale raise an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not any more than negative values in a plot do, I think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think it is a bug that we tolerate this :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NelleV, you think that if a histogram plot is switched to a log scale it should fail rather than yielding a plot? In other words, simply bumping the "L" key when a histogram plot is active should raise an exception?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it means that the following code raises an error, then yes I think it should.
I think the fact that matplotlib accepts log scale when the user provides negative value is at high risk of having unintended bugs, and leads to wrong results and interpretation of analysis.
On the other hand, I'd be fine if the error was caught internally when in interactive mode.

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
ax.set_yscale("log")
ax.plot(np.arange(0, 10))
ax.plot(np.arange(-100, 0))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the behavior proposed by @NelleV is reasonable but this should not be handled by the sticky system (nor block this PR) -- it should affect all plots, including those who do not set sticky margins.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree.

Expand Down
23 changes: 10 additions & 13 deletions lib/matplotlib/contour.py
Original file line number Diff line number Diff line change
Expand Up @@ -964,11 +964,10 @@ def __init__(self, ax, *args, **kwargs):
self.ax.add_collection(col, autolim=False)
self.collections.append(col)

mins, maxs = self._stickies
for col in self.collections:
col.stickies.x[:] = [mins[0], maxs[0]]
col.stickies.y[:] = [mins[1], maxs[1]]
self.ax.update_datalim([mins, maxs])
col.sticky_edges.x[:] = [self._mins[0], self._maxs[0]]
col.sticky_edges.y[:] = [self._mins[1], self._maxs[1]]
self.ax.update_datalim([self._mins, self._maxs])
self.ax.autoscale_view(tight=True)

self.changed() # set the colors
Expand Down Expand Up @@ -1076,13 +1075,9 @@ def _process_args(self, *args, **kwargs):
raise ValueError('allkinds has different length to allsegs')

# Determine x,y bounds and update axes data limits.
mins = np.min(
[np.min(seg, axis=0) for segs in self.allsegs for seg in segs],
axis=0)
maxs = np.max(
[np.max(seg, axis=0) for segs in self.allsegs for seg in segs],
axis=0)
self._stickies = [mins, maxs]
points = np.concatenate(self.allsegs, axis=0)
self._mins = points.min(axis=0)
self._maxs = points.max(axis=0)

def _get_allsegs_and_allkinds(self):
"""
Expand Down Expand Up @@ -1437,7 +1432,8 @@ def _process_args(self, *args, **kwargs):
contour_generator = args[0].Cntr
else:
contour_generator = args[0]._contour_generator
self._stickies = args[0]._stickies
self._mins = args[0]._mins
self._maxs = args[0]._maxs
else:
self._corner_mask = kwargs.get('corner_mask', None)
if self._corner_mask is None:
Expand Down Expand Up @@ -1470,7 +1466,8 @@ def _process_args(self, *args, **kwargs):
x = transformed_pts[..., 0]
y = transformed_pts[..., 1]

self._stickies = [(ma.min(x), ma.min(y)), (ma.max(x), ma.max(y))]
self._mins = [ma.min(x), ma.min(y)]
self._maxs = [ma.max(x), ma.max(y)]

if self._corner_mask == 'legacy':
self.Cntr = contour_generator
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,8 +740,8 @@ def set_extent(self, extent):
xmin, xmax, ymin, ymax = extent
corners = (xmin, ymin), (xmax, ymax)
self.axes.update_datalim(corners)
self.stickies.x[:] = [xmin, xmax]
self.stickies.y[:] = [ymin, ymax]
self.sticky_edges.x[:] = [xmin, xmax]
self.sticky_edges.y[:] = [ymin, ymax]
if self.axes._autoscaleXon:
self.axes.set_xlim((xmin, xmax), auto=None)
if self.axes._autoscaleYon:
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/stackplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def stackplot(axes, x, *args, **kwargs):
coll = axes.fill_between(x, first_line, stack[0, :],
facecolor=color, label=six.next(labels, None),
**kwargs)
coll.stickies.y[:] = [0]
coll.sticky_edges.y[:] = [0]
r = [coll]

# Color between array i-1 and array i
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/streamplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ def streamplot(axes, x, y, u, v, density=1, linewidth=None, color=None,

lc = mcollections.LineCollection(
streamlines, transform=transform, **line_kw)
lc.stickies.x[:] = [grid.x_origin, grid.x_origin + grid.width]
lc.stickies.y[:] = [grid.y_origin, grid.y_origin + grid.height]
lc.sticky_edges.x[:] = [grid.x_origin, grid.x_origin + grid.width]
lc.sticky_edges.y[:] = [grid.y_origin, grid.y_origin + grid.height]
if use_multicolor_lines:
lc.set_array(np.ma.hstack(line_colors))
lc.set_cmap(cmap)
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/tri/tricontour.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ def _process_args(self, *args, **kwargs):
else:
tri, z = self._contour_args(args, kwargs)
C = _tri.TriContourGenerator(tri.get_cpp_triangulation(), z)
self._stickies = [(tri.x.min(), tri.y.min()),
(tri.x.max(), tri.y.max())]
self._mins = [tri.x.min(), tri.y.min()]
self._maxs = [tri.x.max(), tri.y.max()]
self.ax.autoscale_view()

self.cppContourGenerator = C
Expand Down
0