Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Share and unshare axes after creation.#9923

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
lkjell wants to merge7 commits intomatplotlib:masterfromlkjell:sharexy
Closed
Show file tree
Hide file tree
Changes from1 commit
Commits
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
NextNext commit
Implementing shareaxis.
Sharexy use Weakref instead of cbook.GrouperAdd a share/unshare function to share/unshare both x,y,z axisremove() unshare axes successfully.Revert to Grouper. But now grouper remove will also remove from other sets.unshare will also remove parent/master axes.unshare also remove parent axes in the orphan axes.Adding unshare and share tests.Add what is new.Adding unshare axis demo.Revert "Revert to Grouper. But now grouper remove will also remove from other sets."Converting Weakset to list and back during pickle.Adding pickle test.Update tests to use Weakset backend.Add example of how to share 3D plot.Add an API breakage message.change twinx, twiny to use the new share api.Adding an is sharing axes method.Fix overline in example too short.Use the new is_sharing_[x,y]_axes when appropriateupdate tests to use is sharing axes methodsSimplify share and unsharing code to one.remove crufts.Change quotation marks.Update descriptions.Update docs. Unshare axes if related.Sharing will implicit set adjustable to datalim.Copy major and minor when unshare axes.If unshare a parent axes its children will copy a new major minor.
  • Loading branch information
@lkjell
lkjell committedJun 24, 2018
commite157edce1002906f1ca9f77824713a355422b195
26 changes: 26 additions & 0 deletionsdoc/api/api_changes/2017-12-06-KL.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
Change return value of Axes.get_shared_[x,y,z]_axes()
-----------------------------------------------

The method `matplotlib.Axes.get_shared_x_axes` (and y and z) used to return `~.cbook.Grouper` objects.
Now it returns a `~.weakref.WeakSet` object.

Workarounds:
* If the intention is to get siblings as previous then the WeakSet contains all the siblings.
An example::

sharedx = ax.get_shared_x_axes().get_siblings()
# is now
sharedx = list(ax.get_shared_x_axes())

* If the intention was to use `join` then there is a new share axes method. An example::

ax1.get_shared_x_axes().join(ax1, ax2)
# is now
ax1.share_x_axes(ax2)

* If the intention was to check if two elements are in the same group then use the `in` operator. An example::

ax1.get_shared_x_axes().joined(ax1, ax2)
# is now
ax2 in ax1.get_shared_x_axes()

View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
Share and unshare `axes` after creation
---------------------------------------

`~.Axes` have `~.Axes.unshare_x_axes`, `~.Axes.unshare_y_axes`, `~.Axes.unshare_z_axes` and `~.Axes.unshare_axes` methods to unshare axes.
Similiar there are `~.Axes.share_x_axes`, `~.Axes.share_y_axes`, `~.Axes.share_z_axes` and `~.Axes.share_axes` methods to share axes.

Unshare an axis will decouple the viewlimits for further changes.
Share an axis will couple the viewlimits.
39 changes: 39 additions & 0 deletionsexamples/mplot3d/share_unshare_3d_axes.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
"""
============================================
Parametric Curve with Share and Unshare Axes
============================================

This example demonstrates plotting a parametric curve in 3D,
and how to share and unshare 3D plot axes.
"""
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt

mpl.rcParams['legend.fontsize'] = 10

# Prepare arrays x, y, z
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z ** 2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)

fig = plt.figure()
ax = fig.add_subplot(311, projection='3d')

ax.plot(x, y, z, label='parametric curve')
ax.legend()

ax1 = fig.add_subplot(312)
ax1.plot(range(10))
ax1.share_axes(ax)

ax2 = fig.add_subplot(313, projection='3d', sharex=ax)
ax2.plot(x, y, z)

ax2.unshare_x_axes(ax)
ax2.share_z_axes(ax)

plt.show()
36 changes: 36 additions & 0 deletionsexamples/subplots_axes_and_figures/unshare_axis_demo.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
"""
======================
Unshare and share axis
======================

The example shows how to share and unshare axes after they are created.
"""

import matplotlib.pyplot as plt
import numpy as np

t = np.arange(0.01, 5.0, 0.01)
s1 = np.sin(2 * np.pi * t)
s2 = np.exp(-t)
s3 = np.sin(4 * np.pi * t)

ax1 = plt.subplot(311)
plt.plot(t, s1)

ax2 = plt.subplot(312)
plt.plot(t, s2)

ax3 = plt.subplot(313)
plt.plot(t, s3)

ax1.share_x_axes(ax2)
ax1.share_y_axes(ax2)

# Share both axes.
ax3.share_axes(ax1)
plt.xlim(0.01, 5.0)

ax3.unshare_y_axes()
ax2.unshare_x_axes()
Copy link
Member

Choose a reason for hiding this comment

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

I didn't try to run this, but its hard to imagine this actually demos anything in a non-interactive session.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

You do not create share as usual by setting a share parent axes. Sharing is set after the creation of the axes.

Copy link
Member

Choose a reason for hiding this comment

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

I think demos should be readily readable by users since they are one of the primary ways we document Matplotlib. I find this demo is very cryptic. Why are you un-sharing? Just to show that these functions exist? What effect does this have on the example? The description of the demo should state the usual way of sharing, and this alternate way.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

hm... no comment.


plt.show()
167 changes: 145 additions & 22 deletionslib/matplotlib/axes/_base.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
from collections import OrderedDict
from weakref import WeakSet
import copy
import itertools
import logging
import math
Expand DownExpand Up@@ -400,8 +402,6 @@ class _AxesBase(martist.Artist):
"""
name = "rectilinear"

_shared_x_axes = cbook.Grouper()
_shared_y_axes = cbook.Grouper()
_twinned_axes = cbook.Grouper()

def __str__(self):
Expand DownExpand Up@@ -482,12 +482,18 @@ def __init__(self, fig, rect,
self._aspect = 'auto'
self._adjustable = 'box'
self._anchor = 'C'
#Adding yourself to shared xy axes. Reflexive.
self._shared_x_axes = WeakSet([self])
self._shared_y_axes = WeakSet([self])
self._sharex = sharex
self._sharey = sharey

if sharex is not None:
self._shared_x_axes.join(self, sharex)
self.share_x_axes(sharex)

if sharey is not None:
self._shared_y_axes.join(self, sharey)
self.share_y_axes(sharey)

self.set_label(label)
self.set_figure(fig)

Expand DownExpand Up@@ -571,10 +577,14 @@ def __getstate__(self):
state.pop('_layoutbox')
state.pop('_poslayoutbox')

state['_shared_x_axes'] = list(self._shared_x_axes)
state['_shared_y_axes'] = list(self._shared_y_axes)
return state

def __setstate__(self, state):
self.__dict__ = state
self._shared_x_axes = WeakSet(state['_shared_x_axes'])
self._shared_y_axes = WeakSet(state['_shared_y_axes'])
self._stale = True
self._layoutbox = None
self._poslayoutbox = None
Expand DownExpand Up@@ -989,6 +999,7 @@ def cla(self):
self.ignore_existing_data_limits = True
self.callbacks = cbook.CallbackRegistry()


if self._sharex is not None:
# major and minor are axis.Ticker class instances with
# locator and formatter attributes
Expand DownExpand Up@@ -1102,8 +1113,6 @@ def cla(self):
self.xaxis.set_clip_path(self.patch)
self.yaxis.set_clip_path(self.patch)

self._shared_x_axes.clean()
self._shared_y_axes.clean()
if self._sharex:
self.xaxis.set_visible(xaxis_visible)
self.patch.set_visible(patch_visible)
Expand DownExpand Up@@ -1335,8 +1344,7 @@ def set_adjustable(self, adjustable, share=False):
if adjustable not in ('box', 'datalim', 'box-forced'):
raise ValueError("argument must be 'box', or 'datalim'")
if share:
axes = set(self._shared_x_axes.get_siblings(self)
+ self._shared_y_axes.get_siblings(self))
axes = set(self._shared_x_axes | self._shared_y_axes)
else:
axes = [self]
for ax in axes:
Expand DownExpand Up@@ -1403,8 +1411,7 @@ def set_anchor(self, anchor, share=False):
raise ValueError('argument must be among %s' %
', '.join(mtransforms.Bbox.coefs))
if share:
axes = set(self._shared_x_axes.get_siblings(self)
+ self._shared_y_axes.get_siblings(self))
axes = set(self._shared_x_axes | self._shared_y_axes)
else:
axes = [self]
for ax in axes:
Expand DownExpand Up@@ -1556,8 +1563,8 @@ def apply_aspect(self, position=None):
xm = 0
ym = 0

shared_x = self in self._shared_x_axes
shared_y = self in self._shared_y_axes
shared_x = self.is_sharing_x_axes()
shared_y = self.is_sharing_y_axes()
# Not sure whether we need this check:
if shared_x and shared_y:
raise RuntimeError("adjustable='datalim' is not allowed when both"
Expand DownExpand Up@@ -2389,8 +2396,7 @@ def handle_single_axis(scale, autoscaleon, shared_axes, interval,
if not (scale and autoscaleon):
return # nothing to do...

shared = shared_axes.get_siblings(self)
dl = [ax.dataLim for ax in shared]
dl = [ax.dataLim for ax in shared_axes]
# ignore non-finite data limits if good limits exist
finite_dl = [d for d in dl if np.isfinite(d).all()]
if len(finite_dl):
Expand DownExpand Up@@ -3126,7 +3132,7 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False,
if emit:
self.callbacks.process('xlim_changed', self)
# Call all of the other x-axes that are shared with this one
for other in self._shared_x_axes.get_siblings(self):
for other in self._shared_x_axes:
if other is not self:
other.set_xlim(self.viewLim.intervalx,
emit=False, auto=auto)
Expand DownExpand Up@@ -3165,8 +3171,7 @@ def set_xscale(self, value, **kwargs):

matplotlib.scale.LogisticTransform : logit transform
"""
g = self.get_shared_x_axes()
for ax in g.get_siblings(self):
for ax in self._shared_x_axes:
ax.xaxis._set_scale(value, **kwargs)
ax._update_transScale()
ax.stale = True
Expand DownExpand Up@@ -3459,7 +3464,7 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
if emit:
self.callbacks.process('ylim_changed', self)
# Call all of the other y-axes that are shared with this one
for other in self._shared_y_axes.get_siblings(self):
for other in self._shared_y_axes:
if other is not self:
other.set_ylim(self.viewLim.intervaly,
emit=False, auto=auto)
Expand DownExpand Up@@ -3498,8 +3503,7 @@ def set_yscale(self, value, **kwargs):

matplotlib.scale.LogisticTransform : logit transform
"""
g = self.get_shared_y_axes()
for ax in g.get_siblings(self):
for ax in self._shared_y_axes:
ax.yaxis._set_scale(value, **kwargs)
ax._update_transScale()
ax.stale = True
Expand DownExpand Up@@ -4231,9 +4235,128 @@ def twiny(self):
return ax2

def get_shared_x_axes(self):
"""Return areference to the shared axesGrouper object for x axes."""
"""Return acopy of the shared axesWeakset object for x axes"""
return self._shared_x_axes

def get_shared_y_axes(self):
"""Return areference to the shared axesGrouper object for y axes."""
"""Return acopy of the shared axesWeakset object for y axes"""
return self._shared_y_axes

def is_sharing_x_axes(self):
return len(self.get_shared_x_axes()) > 1

def is_sharing_y_axes(self):
return len(self.get_shared_y_axes()) > 1

def _unshare_axes(self, shared_axes, parent):
children = []

for ax in getattr(self, shared_axes):
if getattr(ax, parent) is self:
setattr(ax, parent, None)
children.append(ax)

getattr(self, shared_axes).remove(self)
setattr(self, shared_axes, WeakSet([self]))
setattr(self, parent, None)

return children

@staticmethod
def _copy_axis_major_minor(axis):
major = axis.major
minor = axis.minor

axis.major = copy.deepcopy(major)
axis.minor = copy.deepcopy(minor)

axis.major.set_axis(axis)
axis.minor.set_axis(axis)

def unshare_x_axes(self, axes=None):
"""
Unshare x axis.

Parameters
----------
axes: Axes
Axes to unshare, if related. None will unshare itself.
"""
if axes is None or axes is self:
children = self._unshare_axes('_shared_x_axes', '_sharex')
for ax in children:
self._copy_axis_major_minor(ax.xaxis)
self._copy_axis_major_minor(self.xaxis)
elif axes in self._shared_x_axes:
axes.unshare_x_axes()

def unshare_y_axes(self, axes=None):
"""
Unshare y axis.

Parameters
----------
axes: Axes
Axes to unshare, if related. None will unshare itself.
"""
if axes is None or axes is self:
children = self._unshare_axes('_shared_y_axes', '_sharey')
for ax in children:
self._copy_axis_major_minor(ax.yaxis)
self._copy_axis_major_minor(self.yaxis)
elif axes in self._shared_y_axes:
axes.unshare_y_axes()

def unshare_axes(self, axes=None):
"""
Unshare both x and y axes.

Parameters
----------
axes: Axes
Axes to unshare, if related. None will unshare itself.
"""
self.unshare_x_axes(axes)
self.unshare_y_axes(axes)

def _share_axes(self, axes, shared_axes):
shared = getattr(self, shared_axes)
shared |= getattr(axes, shared_axes)

for ax in shared:
setattr(ax, shared_axes, shared)
ax._adjustable = 'datalim'

def share_x_axes(self, axes):
"""
Share x axis.

Parameters
----------
axes: Axes
Axes to share.
"""
self._share_axes(axes, '_shared_x_axes')

def share_y_axes(self, axes):
"""
Share y axis.

Parameters
----------
axes: Axes
Axes to share.
"""
self._share_axes(axes, '_shared_y_axes')

def share_axes(self, axes):
"""
Share both x and y axes.

Parameters
----------
axes: Axes
Axes to share.
"""
self.share_x_axes(axes)
self.share_y_axes(axes)
Loading

[8]ページ先頭

©2009-2025 Movatter.jp