[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