Python 3.x Matplotlib设置带有“imshow”的“axes”对象会导致y轴变为变量

Python 3.x Matplotlib设置带有“imshow”的“axes”对象会导致y轴变为变量,python-3.x,matplotlib,tkinter,tkinter-canvas,Python 3.x,Matplotlib,Tkinter,Tkinter Canvas,说明 我已经开始根据matplotlib的未来警告重构一些代码,以重用最初定义的轴对象。然而,我注意到每当我重新使用我的轴对象时,图像大小都是可变的。因为,在使用imshow之后,我成功地将问题隔离到axes.imshow方法,该轴上任何后续图形的y轴都有一个y轴,似乎可以重新缩放 我的感觉是y轴比例保留在使用imshow绘制的初始图像中(我认为axes.clear应该重置此设置)。具体来说,在下面的示例中,混洗绘制了一些跨越9.90到10.10的数据,但由于原始图像跨越了0到50的范围,y轴几

说明

我已经开始根据matplotlib的未来警告重构一些代码,以重用最初定义的
对象。然而,我注意到每当我重新使用我的
对象时,图像大小都是可变的。因为,在使用
imshow
之后,我成功地将问题隔离到
axes.imshow
方法,该轴上任何后续图形的y轴都有一个y轴,似乎可以重新缩放

我的感觉是y轴比例保留在使用
imshow
绘制的初始图像中(我认为
axes.clear
应该重置此设置)。具体来说,在下面的示例中,混洗绘制了一些跨越9.90到10.10的数据,但由于原始图像跨越了0到50的范围,y轴几乎不可见

下面是预期行为和“被窃听”行为的前两个屏幕截图,然后是一个MVCE,它有两个部分可以切换以获得预期行为或“被窃听”行为:

图像

  • 不带
    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()
    
    问题


    这里发生了什么,特别是什么导致图像看起来如此不同,以及可以对其采取什么措施?

    当没有为
    方面
    提供参数时,它默认为
    无。从:

    如果没有,则默认为rc image.aspect值

    因此,如果imshow没有参数,它将使用“image.aspect”的rcParam,您可以通过以下操作找到:

    print (plt.rcParams["image.aspect"])  # default is "equal"
    
    解决问题的方法是使用
    轴在
    shuffle
    函数中将其设置为“auto”。set_aspect()

    如果您不介意更改imshow的纵横比,还有一个
    aspect=
    参数:

    self.axes.imshow(Z, cmap=get_cmap("Spectral"), interpolation='nearest', aspect="auto")
    

    我没有意识到,
    imshow
    改变了外观,这确实造成了问题。但是,我选择在初始的
    imshow
    行中设置它,如下所示:
    self.axes.imshow(Z,aspect='auto')
    @BasJansen是,这也是一个选项。我更新了答案,在大多数情况下,matplotlib中的
    None
    表示“默认值”。对于
    imshow
    ,默认方面是
    “相等”
    。纵横比通过轴传播。一旦设置了轴方面,它将保持该设置,直到您再次更改它。这就是这个答案通过
    self.axes.set_aspect(“auto”)
    @ImportanceOfBeingErnest所做的,所以如果
    imshow
    默认为“equal”,这是否意味着它会覆盖
    rcParams[“image.aspect”]
    ?不,抱歉。它默认为
    rcParams[“image.aspect”]
    ,默认情况下是
    “equal”
    self.axes.imshow(Z, cmap=get_cmap("Spectral"), interpolation='nearest', aspect="auto")