[Matplotlib-users] Real-time graph, redrawing a changing Y axis
John Ladasky
jladasky at itu.edu
Wed Jun 29 22:30:18 EDT 2016
Hi Thomas,
Thanks for your reply.
self.ax.figure.canvas.draw_idle()
> which will schedule a full re-draw the next time that the GUI repaints
> (and requests the the GUI do so 'some time soon'). Depending on your
> data-rates this may allow multiple draws to be squashed into one. This
> assumes that each of your axes is in it's own figure.
Alas, at least for now, each of my five axes is contained in a single
Figure. I suppose that I could refactor my code and embed five separate
FigureCanvas objects, each containing one axes, in my PyQt object. If, as
you say, I would gain very little by getting fancy with the redrawing of
this one object, that may be the way to go.
I like your idea of blitting the empty region, though. Is anyone aware of
any example code that shows this being done?
On Wed, Jun 29, 2016 at 6:15 PM, Thomas Caswell <tcaswell at gmail.com> wrote:
> If you are re-computing the limits and re-drawing the yticks anyway, you
> are not getting much benefit from being fancy about re-drawing. You might
> as well do
>
> self.plot.set_data(self.x[:size], self.y[:size])
> lo = self.y[:size].min()
> hi = self.y[:size].max()
> if hi - lo > 150:
> self.ax.set_ylim(lo-25, hi+25)
> else:
> mid = self.y[:size].mean()
> self.ax.set_ylim(mid-100, mid+100)
> self.ax.relim()
> self.ax.autoscale_view(None, False, True)
> self.ax.figure.canvas.draw_idle()
>
> which will schedule a full re-draw the next time that the GUI repaints
> (and requests the the GUI do so 'some time soon'). Depending on your
> data-rates this may allow multiple draws to be squashed into one. This
> assumes that each of your axes is in it's own figure.
>
> Failing that, you will have to do something like, on first draw / or
> resize turn off the y-ticks, use `copy_from_bbox` to grab the empty region
> and the use blit to restore it before drawing the next frame.
>
> You might also get away with just keeping better track of when the view
> limits _need_ to change and then only triggering the `draw_idle` for that.
>
> Tom
>
> On Wed, Jun 29, 2016 at 7:23 PM John Ladasky <jladasky at itu.edu> wrote:
>
>> Hi Jody,
>>
>> Thanks for your reply. I'm aware of Matplotlib's animation API. I'm not
>> sure that it would help me.
>>
>> As far as I can tell, the purpose of animation.FuncAnimation() is to
>> connect a data generating function to the update function of a MPL object,
>> and to drive it all with a timer. It's an event loop, for people who
>> aren't already writing event-driven code (which I am, I have 1,200 lines of
>> mostly-working PyQt5). What actually gets done in the MPL update method is
>> what I think is important to me. I want to change only what needs to be
>> changed.
>>
>> My approach is best described by this article:
>>
>> http://bastibe.de/2013-05-30-speeding-up-matplotlib.html
>>
>> The article is a few years old, I know. Still, using the advice I found
>> in articles like this one, I limited redrawing, and everything updates in
>> under 10 milliseconds, a 15-fold improvement over my original
>> redraw-everything approach. In total, I have five live graphs on the
>> screen. It's only this one self-adjusting time series graph that is
>> misbehaving for me.
>>
>> On Wed, Jun 29, 2016 at 3:36 PM, Jody Klymak <jklymak at uvic.ca> wrote:
>>
>>>
>>> On Jun 29, 2016, at 15:12 PM, John Ladasky <jladasky at itu.edu> wrote:
>>>
>>> I am using MPL 1.4.2, Python 3.4, and Ubuntu 15.04. I am developing a
>>> program which displays real-time data. On each update cycle, the graph
>>> needs to adjust the y-axis scale. I have code that mostly works, but when
>>> it re-renders the y-axis, it is not completely erasing the old one. I get
>>> tick labels written on top of each other, until everything is an unreadable
>>> smear, like this:
>>>
>>>
>>> I think thats because `redraw_in_frame()` doesn’t update any of the axes
>>> data…
>>>
>>> Have you looked into the animation API? Its meant for this sort of
>>> thing, and seems pretty snappy. Most of what you are doing below would
>>> just go into the `animate` function.
>>>
>>> http://matplotlib.org/examples/animation/simple_anim.html
>>>
>>> Cheers, Jody
>>>
>>>
>>>
>>>
>>> <For matplotlib-users.png>
>>>
>>> Here is the relevant part of my update method:
>>>
>>> self.plot.set_data(self.x[:size], self.y[:size])
>>> lo = self.y[:size].min()
>>> hi = self.y[:size].max()
>>> if hi - lo > 150:
>>> self.ax.set_ylim(lo-25, hi+25)
>>> else:
>>> mid = self.y[:size].mean()
>>> self.ax.set_ylim(mid-100, mid+100)
>>> self.ax.relim()
>>> self.ax.autoscale_view(None, False, True)
>>> self.ax.redraw_in_frame()
>>> # Something which erases the Y axis should go here?
>>> self.ax.get_yaxis().draw(self.parent.get_renderer())
>>>
>>>
>>> I think that the details of setting the Y limits are unimportant, but
>>> I've included that code anyway, so that you can see my set_data() method
>>> call at the top, and you can also see that I'm continually adjusting the Y
>>> range to track the data.
>>>
>>> I think that I am searching for a method in the axis class which would
>>> erase the previously drawn tick marks and labels. So far, I haven't found
>>> one. It would replace the comment line in my code.
>>>
>>> I am trying to avoid redrawing the entire canvas on which this plot is
>>> embedded, since there are several other live data plots besides the one I
>>> have shown. The first version of my program did a full redraw, and it took
>>> over 150 milliseconds to complete an update call. That's too slow for my
>>> needs.
>>>
>>> Thanks for any help you can provide!
>>>
>>> --
>>> *John J. Ladasky Jr., Ph.D.*
>>> *Research Scientist*
>>> *International Technological University*
>>> *2711 N. First St, San Jose, CA 95134 USA*
>>> _______________________________________________
>>> Matplotlib-users mailing list
>>> Matplotlib-users at python.org
>>> https://mail.python.org/mailman/listinfo/matplotlib-users
>>>
>>>
>>>
>>
>>
>> --
>> *John J. Ladasky Jr., Ph.D.*
>> *Research Scientist*
>> *International Technological University*
>> *2711 N. First St, San Jose, CA 95134 USA*
>> _______________________________________________
>> Matplotlib-users mailing list
>> Matplotlib-users at python.org
>> https://mail.python.org/mailman/listinfo/matplotlib-users
>>
>
--
*John J. Ladasky Jr., Ph.D.*
*Research Scientist*
*International Technological University*
*2711 N. First St, San Jose, CA 95134 USA*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20160629/eb69956f/attachment-0001.html>
More information about the Matplotlib-users
mailing list