Matplotlib用`imshow`设置`axes`对象导致y轴变为变量

时间:2018-09-06 11:09:56

标签: python-3.x matplotlib tkinter tkinter-canvas

说明

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

我的感觉是y轴比例尺保留了使用imshow绘制的初始图像(我认为axes.clear应该重设此坐标)。特别是在以下示例中,混洗绘制了一些数据,范围从〜9.90到10.10,但是由于原始图像的范围从0到50,所以y轴几乎看不见。

下面是预期行为的第二张屏幕截图,然后是“错误的”行为,其次是MVCE,其中有两个部分可以切换以获取预期的或“错误的”行为:

图片

  1. 没有imshow的飞溅: enter image description here

  2. “ Foo-> Shuffle”(预期行为)后的屏幕: enter image description here

  3. imshow开头: enter image description here

  4. “ Foo-> Shuffle”(意外行为)后的屏幕: enter image description here

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()

问题

这是怎么回事,特别是是什么导致图像看起来如此不同以及可以采取什么措施?

1 个答案:

答案 0 :(得分:1)

如果没有为aspect提供参数,则默认为None。从documentation

  

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

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

print (plt.rcParams["image.aspect"])  # default is "equal"

解决此问题的方法是使用shuffleaxes.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")