Matplotlib 使用 imshow 设置 axes 对象导致 y 轴变为变量
Matplotlib setting `axes` object with `imshow` causes y-axis to become variable
描述
我已经开始根据 matplotlib 的未来警告重构一些代码,以重新使用最初定义的 axes
对象。但是,我注意到每当我重新使用我的 axes
对象时,图像大小都是可变的。因为,在使用 imshow
之后,我设法将问题隔离到 axes.imshow
方法,该轴上任何后续绘图的 y 轴都有一个似乎重新缩放的 y 轴。
我的感觉是使用 imshow
绘制的初始图像保留了 y 轴比例(我认为 axes.clear
应该重置它)。具体来说,在下面的例子中,洗牌绘制了一些跨越 9.90 到 10.10 的数据,但由于原始图像跨越 0 到 50,所以 y 轴几乎不可见。
下面是预期行为的前两个屏幕截图,然后是 'bugged' 行为,然后是一个 MVCE,它有两个部分可以切换以获得预期或 'bugged' 行为:
图片
飞溅没有imshow
:
'Foo -> Shuffle' 之后的屏幕(预期行为):
与imshow
一起飞溅:
'Foo -> Shuffle' 之后的屏幕(意外行为):
MVCE
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg
)
import tkinter as tk
from matplotlib import image, figure
from numpy import random, linspace
from os import path, getcwd
from pylab import get_cmap
class Foo(object):
@classmethod
def run(cls):
root = tk.Tk()
Foo(root)
root.mainloop()
def __init__(self, master):
# Figure & canvas
self.fig = figure.Figure(figsize=(5,5))
self.axes = self.fig.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.fig, master=master)
self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=tk.YES)
# Splash image (This 'bugs')
Z = random.random((50,50))
self.axes.imshow(Z, cmap=get_cmap("Spectral"), interpolation='nearest')
self.canvas.draw()
# Dummy start data (This Works)
#self.axes.plot(random.normal(10,0.05,100))
#self.canvas.draw()
# MENU
menu = tk.Menu(master)
master.config(menu=menu)
test_menu = tk.Menu(menu, tearoff=0)
menu.add_cascade(label="Foo", menu=test_menu)
test_menu.add_command(label="Shuffle",
command=self.shuffle)
test_menu.add_command(label="Add",
command=self.add)
def add(self):
x_data = linspace(0,10, 1000)
y_data = random.normal(x_data)
self.axes.plot(x_data, y_data)
self.canvas.draw()
def shuffle(self):
self.axes.clear()
self.axes.plot(random.normal(10,0.05,100))
self.canvas.draw()
if __name__ == "__main__":
Foo.run()
问题
这是怎么回事,具体是什么导致图像看起来如此不同,可以采取什么措施?
当 aspect
没有给出参数时,它默认为 None
。来自 documentation:
If None, default to rc image.aspect value
因此,如果没有给 imshow 参数,它将使用 "image.aspect" 的任何 rcParam,您可以通过以下方式找到:
print (plt.rcParams["image.aspect"]) # default is "equal"
解决您的问题的方法是在您的 shuffle
函数中使用 axes.set_aspect()
:
将其设置为 "auto"
def shuffle(self):
self.axes.clear()
self.axes.plot(random.normal(10,0.05,100))
self.axes.set_aspect("auto")
self.canvas.draw()
如果不介意改变imshow的纵横比,还有一个aspect=
参数:
self.axes.imshow(Z, cmap=get_cmap("Spectral"), interpolation='nearest', aspect="auto")
描述
我已经开始根据 matplotlib 的未来警告重构一些代码,以重新使用最初定义的 axes
对象。但是,我注意到每当我重新使用我的 axes
对象时,图像大小都是可变的。因为,在使用 imshow
之后,我设法将问题隔离到 axes.imshow
方法,该轴上任何后续绘图的 y 轴都有一个似乎重新缩放的 y 轴。
我的感觉是使用 imshow
绘制的初始图像保留了 y 轴比例(我认为 axes.clear
应该重置它)。具体来说,在下面的例子中,洗牌绘制了一些跨越 9.90 到 10.10 的数据,但由于原始图像跨越 0 到 50,所以 y 轴几乎不可见。
下面是预期行为的前两个屏幕截图,然后是 'bugged' 行为,然后是一个 MVCE,它有两个部分可以切换以获得预期或 'bugged' 行为:
图片
飞溅没有
imshow
:'Foo -> Shuffle' 之后的屏幕(预期行为):
与
imshow
一起飞溅:'Foo -> Shuffle' 之后的屏幕(意外行为):
MVCE
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg
)
import tkinter as tk
from matplotlib import image, figure
from numpy import random, linspace
from os import path, getcwd
from pylab import get_cmap
class Foo(object):
@classmethod
def run(cls):
root = tk.Tk()
Foo(root)
root.mainloop()
def __init__(self, master):
# Figure & canvas
self.fig = figure.Figure(figsize=(5,5))
self.axes = self.fig.add_subplot(111)
self.canvas = FigureCanvasTkAgg(self.fig, master=master)
self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=tk.YES)
# Splash image (This 'bugs')
Z = random.random((50,50))
self.axes.imshow(Z, cmap=get_cmap("Spectral"), interpolation='nearest')
self.canvas.draw()
# Dummy start data (This Works)
#self.axes.plot(random.normal(10,0.05,100))
#self.canvas.draw()
# MENU
menu = tk.Menu(master)
master.config(menu=menu)
test_menu = tk.Menu(menu, tearoff=0)
menu.add_cascade(label="Foo", menu=test_menu)
test_menu.add_command(label="Shuffle",
command=self.shuffle)
test_menu.add_command(label="Add",
command=self.add)
def add(self):
x_data = linspace(0,10, 1000)
y_data = random.normal(x_data)
self.axes.plot(x_data, y_data)
self.canvas.draw()
def shuffle(self):
self.axes.clear()
self.axes.plot(random.normal(10,0.05,100))
self.canvas.draw()
if __name__ == "__main__":
Foo.run()
问题
这是怎么回事,具体是什么导致图像看起来如此不同,可以采取什么措施?
当 aspect
没有给出参数时,它默认为 None
。来自 documentation:
If None, default to rc image.aspect value
因此,如果没有给 imshow 参数,它将使用 "image.aspect" 的任何 rcParam,您可以通过以下方式找到:
print (plt.rcParams["image.aspect"]) # default is "equal"
解决您的问题的方法是在您的 shuffle
函数中使用 axes.set_aspect()
:
def shuffle(self):
self.axes.clear()
self.axes.plot(random.normal(10,0.05,100))
self.axes.set_aspect("auto")
self.canvas.draw()
如果不介意改变imshow的纵横比,还有一个aspect=
参数:
self.axes.imshow(Z, cmap=get_cmap("Spectral"), interpolation='nearest', aspect="auto")