Matplotlib 使用 `imshow` 设置 `axes` 对象会导致 y 轴变为可变 [英] Matplotlib setting `axes` object with `imshow` causes y-axis to become variable

查看:66
本文介绍了Matplotlib 使用 `imshow` 设置 `axes` 对象会导致 y 轴变为可变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说明

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

I have began refactoring some code based on the future warning of matplotlib, to re-use the initially defined axes object. However, I noticed that whenever I was re-using my axes object, the image size would be variable. Since, I have managed to isolate the problem to the axes.imshow method as after using imshow, the y-axis of any subsequent drawing on that axes has a y-axis that seems to rescale.

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

The feeling I have is that the y-axis scale is retained from the initial image that is plotted using imshow (I thought that axes.clear should reset this). Specifically in the below examples, shuffling plots some data spanning ~ 9.90 to 10.10 but because the original image spanned form 0 to 50 the y-axis is barely visible.

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

Below are first two screenshots of the expected and then 'bugged' behaviour, followed by an MVCE that has two sections that can be toggled to get the expected or 'bugged' behaviour:

图片

  1. 没有 imshow 的飞溅:

"Foo-> Shuffle"(预期行为)后的屏幕:

Screen after 'Foo -> Shuffle' (Expected behaviour):

imshow 一起飞溅:

'Foo -> Shuffle' 后的屏幕(意外行为):

Screen after 'Foo -> Shuffle' (unexpected behaviour):

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

问题

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

What is going on here, specifically what is causing the image to appear so differently and what can be done about it?

推荐答案

如果没有为 aspect 提供任何参数,则默认为 None .从文档:

When no argument is given for aspect, it defaults to None. From the documentation:

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

If None, default to rc image.aspect value

因此,如果不给 imshow 提供任何参数,它将使用image.aspect"的 rcParam 是什么,您可以通过执行以下操作找到:

Therefore if no argument is given to imshow, it will use whatever the rcParam for "image.aspect" is, which you can find by doing:

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

解决您的问题的方法是在您的 shuffle 函数中使用 axes.set_aspect() 将其设置为自动":

A fix to your problem would be to set it to "auto" in your shuffle function using 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 = 参数:

If you don't mind changing the aspect ratio of imshow, there is also an aspect= argument:

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

这篇关于Matplotlib 使用 `imshow` 设置 `axes` 对象会导致 y 轴变为可变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆