Matplotlib:使对象被轴自动缩放忽略
Matplotlib: make objects ignored by axis autoscaling
是否可以创建一个被 Axes 自动缩放器忽略的绘图对象?
我经常需要添加垂直线,或为绘图区域添加阴影以显示所需的数据范围(作为查看器的参考框架),但随后我必须设置坐标轴自动缩放 x/ylimits 回到它们之前的位置 - 或将 lines/shading 截断为当前轴限制,或其他各种 fandangos。
如果这些 shader/vertical 线充当绘图上的“背景”对象,被自动缩放器忽略,会容易得多,所以只有我的真实数据影响了自动缩放。
举个例子:
这个图是真实世界的数据,我想看看每天的数据是否在期望的范围内。
我想在 -50 nm ≤ Y ≤ +50 nm 范围内对第 3 轴图进行着色。
我很想简单地从 -50 --> +50nm 添加一个巨大的半透明矩形,但让自动缩放忽略它。
例如。像这样(我在绘图程序中手动添加了红色阴影。):
此外,您可以看到我使用这样的代码手动添加了垂直线(我真的应该只使用垂直网格线位置...):
ax1.set_ylim(ymin, ymax)
ax1.vlines( self.Dates , color="grey", alpha=0.05, ymin=ax1.get_ylim()[0], ymax=ax1.get_ylim()[1] )
您可以在第 2 轴和第 3 轴中看到,VLine 将 AutoScaling 向外推,因此现在 VLine 和 Axis 之间存在间隙。目前我需要欺骗调用 fig.tight_layout()
和 ax2/ax3.plot()
的顺序,或者转换为手动设置 X-Tick locations/gridlines 等 - 但如果这些 VLines 是甚至没有被视为数据,所以自动缩放忽略了它们。
是否可以让自动缩放“忽略”某些对象?
autoscale_view
主要使用轴的 dataLim
属性来计算轴限制。反过来,数据限制由 _update_image_limits
、_update_line_limits
或 _update_patch_limits
等轴方法设置。这些方法都使用这些艺术家的基本属性来计算新的数据限制(例如路径),因此为“背景”艺术家覆盖它们是行不通的。所以不,严格来说,我不认为自动缩放可以忽略某些对象,只要它们是可见的。
但是,除了目前提到的选项之外,还有其他选项可以保留数据视图。
使用不影响数据限制的艺术家,例如axhline
和 axvline
或使用 add_artist
.
添加补丁(和派生 类)
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.randn(2, 1000)
fig, ax = plt.subplots()
ax.scatter(x, y, zorder=2)
ax.add_artist(plt.Rectangle((0,0), 6, 6, alpha=0.1, zorder=1))
ax.axhline(0)
ax.axvline(0)
您可以绘制前景对象,然后关闭自动缩放。
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.randn(2, 1000)
fig, ax = plt.subplots()
ax.scatter(x, y, zorder=2)
ax.autoscale_view() # force auto-scale to update data limits based on scatter
ax.set_autoscale_on(False)
ax.add_patch(plt.Rectangle((0,0), 6, 6, alpha=0.1, zorder=1))
我唯一的其他想法是猴子补丁 Axes.relim()
来检查 background
属性(这可能是最接近您想象的):
import numpy as np
import matplotlib.axes
import matplotlib.transforms as mtransforms
import matplotlib.image as mimage
import matplotlib.lines as mlines
import matplotlib.patches as mpatches
class PatchedAxis(matplotlib.axes.Axes):
def relim(self, visible_only=False):
"""
Recompute the data limits based on current artists.
At present, `.Collection` instances are not supported.
Parameters
----------
visible_only : bool, default: False
Whether to exclude invisible artists.
"""
# Collections are deliberately not supported (yet); see
# the TODO note in artists.py.
self.dataLim.ignore(True)
self.dataLim.set_points(mtransforms.Bbox.null().get_points())
self.ignore_existing_data_limits = True
for artist in self._children:
if not visible_only or artist.get_visible():
if not hasattr(artist, "background"):
if isinstance(artist, mlines.Line2D):
self._update_line_limits(artist)
elif isinstance(artist, mpatches.Patch):
self._update_patch_limits(artist)
elif isinstance(artist, mimage.AxesImage):
self._update_image_limits(artist)
matplotlib.axes.Axes = PatchedAxis
import matplotlib.pyplot as plt
x, y = np.random.randn(2, 1000)
fig, ax = plt.subplots()
ax.scatter(x, y, zorder=2)
rect = plt.Rectangle((0,0), 6, 6, alpha=0.1, zorder=1)
rect.background = True
ax.add_patch(rect)
ax.relim()
ax.autoscale_view()
但是,由于某些原因,在调用 relim
时 ax._children
未填充。也许其他人可以弄清楚 ax._children
属性是在什么条件下创建的。
是否可以创建一个被 Axes 自动缩放器忽略的绘图对象?
我经常需要添加垂直线,或为绘图区域添加阴影以显示所需的数据范围(作为查看器的参考框架),但随后我必须设置坐标轴自动缩放 x/ylimits 回到它们之前的位置 - 或将 lines/shading 截断为当前轴限制,或其他各种 fandangos。
如果这些 shader/vertical 线充当绘图上的“背景”对象,被自动缩放器忽略,会容易得多,所以只有我的真实数据影响了自动缩放。
举个例子: 这个图是真实世界的数据,我想看看每天的数据是否在期望的范围内。
我想在 -50 nm ≤ Y ≤ +50 nm 范围内对第 3 轴图进行着色。
我很想简单地从 -50 --> +50nm 添加一个巨大的半透明矩形,但让自动缩放忽略它。
例如。像这样(我在绘图程序中手动添加了红色阴影。):
此外,您可以看到我使用这样的代码手动添加了垂直线(我真的应该只使用垂直网格线位置...):
ax1.set_ylim(ymin, ymax)
ax1.vlines( self.Dates , color="grey", alpha=0.05, ymin=ax1.get_ylim()[0], ymax=ax1.get_ylim()[1] )
您可以在第 2 轴和第 3 轴中看到,VLine 将 AutoScaling 向外推,因此现在 VLine 和 Axis 之间存在间隙。目前我需要欺骗调用 fig.tight_layout()
和 ax2/ax3.plot()
的顺序,或者转换为手动设置 X-Tick locations/gridlines 等 - 但如果这些 VLines 是甚至没有被视为数据,所以自动缩放忽略了它们。
是否可以让自动缩放“忽略”某些对象?
autoscale_view
主要使用轴的 dataLim
属性来计算轴限制。反过来,数据限制由 _update_image_limits
、_update_line_limits
或 _update_patch_limits
等轴方法设置。这些方法都使用这些艺术家的基本属性来计算新的数据限制(例如路径),因此为“背景”艺术家覆盖它们是行不通的。所以不,严格来说,我不认为自动缩放可以忽略某些对象,只要它们是可见的。
但是,除了目前提到的选项之外,还有其他选项可以保留数据视图。
使用不影响数据限制的艺术家,例如axhline
和 axvline
或使用 add_artist
.
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.randn(2, 1000)
fig, ax = plt.subplots()
ax.scatter(x, y, zorder=2)
ax.add_artist(plt.Rectangle((0,0), 6, 6, alpha=0.1, zorder=1))
ax.axhline(0)
ax.axvline(0)
您可以绘制前景对象,然后关闭自动缩放。
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
x, y = np.random.randn(2, 1000)
fig, ax = plt.subplots()
ax.scatter(x, y, zorder=2)
ax.autoscale_view() # force auto-scale to update data limits based on scatter
ax.set_autoscale_on(False)
ax.add_patch(plt.Rectangle((0,0), 6, 6, alpha=0.1, zorder=1))
我唯一的其他想法是猴子补丁 Axes.relim()
来检查 background
属性(这可能是最接近您想象的):
import numpy as np
import matplotlib.axes
import matplotlib.transforms as mtransforms
import matplotlib.image as mimage
import matplotlib.lines as mlines
import matplotlib.patches as mpatches
class PatchedAxis(matplotlib.axes.Axes):
def relim(self, visible_only=False):
"""
Recompute the data limits based on current artists.
At present, `.Collection` instances are not supported.
Parameters
----------
visible_only : bool, default: False
Whether to exclude invisible artists.
"""
# Collections are deliberately not supported (yet); see
# the TODO note in artists.py.
self.dataLim.ignore(True)
self.dataLim.set_points(mtransforms.Bbox.null().get_points())
self.ignore_existing_data_limits = True
for artist in self._children:
if not visible_only or artist.get_visible():
if not hasattr(artist, "background"):
if isinstance(artist, mlines.Line2D):
self._update_line_limits(artist)
elif isinstance(artist, mpatches.Patch):
self._update_patch_limits(artist)
elif isinstance(artist, mimage.AxesImage):
self._update_image_limits(artist)
matplotlib.axes.Axes = PatchedAxis
import matplotlib.pyplot as plt
x, y = np.random.randn(2, 1000)
fig, ax = plt.subplots()
ax.scatter(x, y, zorder=2)
rect = plt.Rectangle((0,0), 6, 6, alpha=0.1, zorder=1)
rect.background = True
ax.add_patch(rect)
ax.relim()
ax.autoscale_view()
但是,由于某些原因,在调用 relim
时 ax._children
未填充。也许其他人可以弄清楚 ax._children
属性是在什么条件下创建的。