Matplotlib图中的进度线 [英] Progress Line in Matplotlib Graphs

查看:52
本文介绍了Matplotlib图中的进度线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标:要绘制图形(x,y)并在图形w.r.t上移动一条垂直线到计时器.

Objective: To plot a graph(x,y) and move a vertical line over the graph w.r.t to timer.

我开始使用 matplotlib 来实现它.可以使用matplotlib的draw()功能来实现这一点,但是由于每次重新绘制时都会消耗cpu,并且不允许我与图形进行交互.所以我决定使用 matplotlib 的动画功能.在将来,我也想暂停移动路线.所以我不能使用 matplotlib.animation.FuncAnimatin

I started implementing this using matplotlib. Its possible to implement this using draw() feature of matplotlib , but it consumes cpu as it redraws every time and doesn't allow me to interact with the graph. so i decided to use animation feature of matplotlib. in Future i would aslo like to pause the moving line. So i cant use matplotlib.animation.FuncAnimatin

问题:我使用canvas.copy_from_bbox(ax.bbox),ax.draw_artist(line),canvas.blit(ax.bbox).但是,我无法将图形存储在后台并在其上移动一条线.当我尝试存储时,它以一种非常奇怪的方式覆盖.

Problem: I use canvas.copy_from_bbox(ax.bbox), ax.draw_artist(line),canvas.blit(ax.bbox). But, I am not able to store the graph in the background and move a line over it. When i try to store, it overwrites in a quite weird way.

这是我建立的代码.有人可以帮我吗?提前致谢.

This is the code i have built. Could any one please help me ? Thanks in advance.

import sys
import matplotlib.pyplot as p
import time
fig=p.figure();
ax = fig.add_subplot(1,1,1)

y=[];x=[];y1=[0,1000];x1=[0,0]
y=numpy.random.randn(1000,1)*100
x=numpy.arange(0,1000)
line1, = ax.plot(x,y,color='black');
ax.set_ylim(0, 1000);
line, = ax.plot(x1,y1,color='r',alpha=1,animated=True); # this is the line which i wanted to move over the graph w.r.t to time. ( i can also use axvline , but i guess its the same).
canvas = ax.figure.canvas
canvas.draw()
background = canvas.copy_from_bbox(ax.bbox); #my problem is here
starttime=time.time();
mytimer=0;
mytimer_ref=0;
def update(canvas,line,ax):
    canvas.restore_region(background) #my problem is here 
    t=time.time()-starttime;
    mytimer=t+mytimer_ref;
    x1=[mytimer,mytimer];
    line.set_xdata(x1);
    ax.draw_artist(line)
    canvas.blit(ax.bbox) #my problem is here

def onclick(event):
    global starttime
    starttime=time.time();
    global mytimer_ref;
    mytimer_ref=event.xdata;
    print "starttime",starttime;


cid=line1.figure.canvas.mpl_connect('button_press_event',onclick); # when i click the mouse over a point, line goes to that point and start moving from there. 
timer=fig.canvas.new_timer(interval=100);
args=[canvas,line,ax];
timer.add_callback(update,*args); # every 100ms it calls update function
timer.start();
p.show();

推荐答案

所以看起来您所指的非常奇怪的方式"本质上是使用您的 background = canvas.copy_from_bbox 捕获了错误的 bbox(ax.bbox).我相信这是大多数后端的已知问题,在这些后端中,添加工具栏等会影响bbox的位置以便进行blitting.

So it looks like the "quite weird way" you are referring to is essentially that the wrong bbox has been captured with your background = canvas.copy_from_bbox(ax.bbox). I believe this is a known problem with most of the backends where the addition of toolbars etc. affect the position of the bbox for blitting.

本质上,如果您可以在弹出窗口后 捕获背景,那么一切都应该对您有用.这可以通过多种方式完成,在您的情况下,最简单的方法是用 plt.show(block=False) 替换您的 canvas.draw() 命令,这将调出窗口,而不会使其成为阻塞命令.

Essentially, if you can capture the background after the window has popped up, then everything should be working for you. This can be done in a number of ways, in your case the simplest would be to replace your canvas.draw() command with a plt.show(block=False), which will bring up the window, without making it a blocking command.

稍微补充一下,我确定您知道在 python 代码中分号不是必需的,但是在我调试的过程中,我稍微整理了您的代码(还没有完全结束):

As a slight addition, I'm sure you are aware that semicolons are not necessary in python code, but while I was debugging, I tidied up your code a little (didn't quite get to the end):

import sys
import matplotlib.pyplot as plt
import time
import numpy


fig = plt.figure()
ax = fig.add_subplot(111)


max_height = 100
n_pts = 100
y1 = [0, max_height]
x1 = [0, 0]
y = numpy.random.randn(n_pts) * max_height
x = numpy.arange(0, n_pts)

# draw the data
line1, = ax.plot(x, y, color='black')

# fix the limits of the plot
ax.set_ylim(0, max_height)
ax.set_xlim(0, n_pts)

# draw the plot so that we can capture the background and then use blitting
plt.show(block=False)

# get the canvas object
canvas = ax.figure.canvas
background = canvas.copy_from_bbox(ax.bbox)

# add the progress line.
# XXX consider using axvline
line, = ax.plot(x1, y1, color='r', animated=True) 


starttime=time.time()
mytimer=0
mytimer_ref=0

def update(canvas, line, ax):
    # revert the canvas to the state before any progress line was drawn
    canvas.restore_region(background)

    # compute the distance that the progress line has made (based on running time) 
    t = time.time() - starttime
    mytimer = t + mytimer_ref
    x1 = [mytimer,mytimer]
    # update the progress line with its new position
    line.set_xdata(x1)
    # draw the line, and blit the axes
    ax.draw_artist(line)
    canvas.blit(ax.bbox)

def onclick(event):
    global starttime
    starttime=time.time()
    global mytimer_ref
    mytimer_ref=event.xdata
    print "starttime",starttime


cid=line1.figure.canvas.mpl_connect('button_press_event',onclick) # when i click the mouse over a point, line goes to that point and start moving from there. 
timer=fig.canvas.new_timer(interval=100)
args=[canvas,line,ax]
timer.add_callback(update,*args) # every 100ms it calls update function
timer.start()
plt.show()

HTH

这篇关于Matplotlib图中的进度线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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