Python/Matplotlib - 快速更新轴上的文本 [英] Python/Matplotlib - Quickly Updating Text on Axes

查看:15
本文介绍了Python/Matplotlib - 快速更新轴上的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 wxpython 窗口中有一个 matplotlib 图形/画布.当鼠标四处移动时,我想更新有关图的一些信息.我已连接到motion_notify_event"以获取此信息.

I have a matplotlib figure/canvas in a wxpython window. I want to update some information on the plot as the mouse moves around. I've connected to 'motion_notify_event' to get this information.

在下面的代码中,绘制了大量随机数据,然后在窗口的状态栏中显示光标的 x,y 位置.这非常流畅,效果很好.但是,我真的很想在图的顶部显示此信息.如果您取消注释 cbUpdateCursor 的最后两行,就会显示我想要的行为.但是,当这样做时,移动光标的响应时间非常慢(因为 draw 被调用并且有很多数据,但必须调用 draw 否则文本不会更新).

In the code below, a lot of random data is plotted and then the x,y location of the cursor is displayed in the statusbar of the window. This is very smooth and works well. However, I really want to display this information at the top of the plot. The behavior I want is shown if you uncomment the last two lines of cbUpdateCursor. However, when this is done, the response time to moving the cursor is terribly slow (because draw gets called and there is a lot of data, but draw must be called or the text doesn't get updated).

我怎样才能加快速度以便光标位置可以显示在绘图上,但又不会减慢这么多?我想我可能需要对 bbox 做些什么?

How can I speed this up so the cursor position can be displayed on the plot, but not slow it down so much? I think I might need to do something with bbox?

代码:

import wx
import numpy as np
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.widgets import Cursor
from matplotlib.backends.backend_wxagg import \
   FigureCanvasWxAgg as FigCanvas, \
   NavigationToolbar2WxAgg as NavigationToolbar

class wxPlotting(wx.Frame):
   title = 'Test'
   def __init__(self):
      wx.Frame.__init__(self, None, -1, self.title)
      self.time = np.arange(10000)
      self.data = np.random.random(10000)
      self.sb = self.CreateStatusBar()
      self.create_main_panel()
      self.axes.plot(self.time, self.data)
      self.canvas.draw()

   def create_main_panel(self):
      self.panel = wx.Panel(self)
      self.fig = Figure((5.0, 4.0), dpi=100)
      self.canvas = FigCanvas(self.panel, -1, self.fig)
      self.axes = self.fig.add_subplot(111)
      self.text = self.axes.text(0., 1.005, '', transform = self.axes.transAxes)
      self.cursor = Cursor(self.axes, useblit=True, color='red')
      self.canvas.mpl_connect('motion_notify_event', self.cbUpdateCursor)
      self.vbox = wx.BoxSizer(wx.VERTICAL)
      self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
      self.panel.SetSizer(self.vbox)
      self.vbox.Fit(self)

   def cbUpdateCursor(self, event):
      if event.inaxes:
         text = 'x = %5.4f, y = %5.4f' % (event.xdata, event.ydata)
         self.sb.SetStatusText(text)
         #self.text.set_text(text)
         #self.canvas.draw()

if __name__ == '__main__':
   app = wx.PySimpleApp()
   app.frame = wxPlotting()
   app.frame.Show()
   app.MainLoop()

基本上我想要一些类似于使用 pyplot 显示的文本的东西,即运行下面的代码时的右下角:

Basically I want something similar to the text that gets displayed using pyplot, i.e. the bottom right corner when the code below is run:

代码:

import matplotlib.pyplot as plt
plt.plot(range(10000), range(10000))
plt.show()

编辑:

在我的实际程序中,我希望静态文本位于 matplotlib 轴内,而不是真正位于其上方.所以我不认为我可以只使用 wxpython statictext 来显示它.

In my actual program, I want the static text to be within the matplotlib axes, not really above it. So I don't think I can just use a wxpython statictext to display it.

推荐答案

您可以使用 blitting,类似于动画示例 这里.

You could use blitting, similar to the animation examples here.

在这种情况下,这会导致非常的性能差异,因为只需要重新绘制窗口的一小部分.

This make a very large performance difference in this case, as only a small portion of the window needs to be redrawn.

不幸的是,我无法弄清楚如何在重绘文本时在文本后面获得灰色背景,以匹配其后面的默认图形背景......不过,性能非常好.

Unfortunately, I can't figure out how to get a gray background behind the text when it's redrawn, to match the default figure background behind it... The performance is excellent, though.

作为基于上述代码的独立示例:

As a stand-alone example based on your code above:

import wx
import numpy as np
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.widgets import Cursor
from matplotlib.backends.backend_wxagg import \
   FigureCanvasWxAgg as FigCanvas, \
   NavigationToolbar2WxAgg as NavigationToolbar

class wxPlotting(wx.Frame):
   title = 'Test'
   def __init__(self):
      wx.Frame.__init__(self, None, -1, self.title)
      self.time = np.arange(10000)
      self.data = np.random.random(10000)
      self.sb = self.CreateStatusBar()
      self.create_main_panel()
      self.axes.plot(self.time, self.data)
      self.background = self.canvas.copy_from_bbox(self.fig.bbox)
      self.canvas.draw()

   def create_main_panel(self):
      self.panel = wx.Panel(self)
      self.fig = Figure((5.0, 4.0), dpi=100)
      self.canvas = FigCanvas(self.panel, -1, self.fig)
      self.axes = self.fig.add_subplot(111)
      self.text = self.axes.text(0., 1.005, '', transform = self.axes.transAxes, animated=True)
      self.cursor = Cursor(self.axes, useblit=True, color='red')
      self.canvas.mpl_connect('motion_notify_event', self.cbUpdateCursor)
      self.vbox = wx.BoxSizer(wx.VERTICAL)
      self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
      self.panel.SetSizer(self.vbox)
      self.vbox.Fit(self)

   def cbUpdateCursor(self, event):
      if event.inaxes:
         text = 'x = %5.4f, y = %5.4f' % (event.xdata, event.ydata)
         self.sb.SetStatusText(text)

         self.canvas.restore_region(self.background)
         self.text.set_text(text)
         self.axes.draw_artist(self.text)
         self.canvas.blit(self.text.get_window_extent())

if __name__ == '__main__':
   app = wx.PySimpleApp()
   app.frame = wxPlotting()
   app.frame.Show()
   app.MainLoop()

这篇关于Python/Matplotlib - 快速更新轴上的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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