Question

Hi, I'm pretty impressed with the abilities of

    > matplotlib. But, I want to do dynamic plotting in
    > python. So does this tool support dynamic plotting? I
    > didn't see any snapshots or demo for dynamic plotting.

    > Please let me know if I can do dynamic plotting or not,
    > and if I can, how? Is there any tutorial on it?

Hi,

Thanks for the email. In the future if you post the question to the
mailing list I'll be more likely to see it quickly and others can help
you as well
http://lists.sourceforge.net/mailman/listinfo/matplotlib-users.

Now, on to your question. Yes, matplotlib does support dynamic
plotting, if I understand your question correctly. You can update the
graphs in an animated fashion using either the gtk timer or idle
functionality.

See examples/system_monitor.py in the src distribution. Let me know
if you need something other than this functionality, and I'll see
about getting it incorporated.

John Hunter

A slightly different approach to live plotting. I have a numerical
program that calls a status function every run through the main loop. It
allows the user to define a status function and pass it that function
(defaulting to just a one-line report on sys.err).

Using GTK idle slowed things down way too much, because GTK was always
idle, even though the number cruncher wasn't. GTK timeout didn't work
either. Using threads was too complicated and error prone, for no gain.
What I wanted was a meter that updated every second or so.

Here is my status function. It shows traces for the best score so far, and
the current score. If enough time has elapsed, it plots (thus scheduling
GTK events), otherwise no. So the gtk.events_pending() call near the end
is usually false.

It rescales the graph too, as required. You can ignore the "interrupted"
stuff -- that allows me to send a "stop" signal to the numerical routine,
saying "Ok, it looks to me like you've converged, stop now."

  -Charles

···

----------

def my_status_func(*args, **kwargs):

    """ Gather info from a running snob, and plot it.

    It expects the final arg to be a dictionary with
    the following keyword arguments:
          fig -- the matplot figure for drawing to
          ax -- the matplot axes in that figure
          t1 -- a list of length 1, with timestamp of last refresh
          iteratns -- sequence of all iteration #s to date (x axis)
          currlens -- sequence of all current lengths to date
          bestlens -- sequence of all best lenghts to date
    All of these kwargs will be modified, at least sometimes.

    """

    #global currlens, bestlens, iteratns, t
    UPDATE_INTERVAL = 1 # how long in s to wait before updating graph

    itr = args[0] + 1
    max_itr = args[1]
    cl = int (args[2][0] / N.log(2))
    bl = int (args[3][0] / N.log(2))
    #cl = int (curr[0] / N.log(2))
    #bl = int (best[0] / N.log(2))

    # Extract variables from kwargs
    t1 = kwargs['t1']
    iteratns = kwargs['iteratns']
    currlens = kwargs['currlens']
    bestlens = kwargs['bestlens']

    iteratns.append (itr)
    currlens.append (cl)
    bestlens.append (bl)

    if itr == 1:
        print "Original length: ", cl

    delta = time.time() - t1[0]

    if (itr > 1) and ( (delta > UPDATE_INTERVAL) or (itr >= max_itr) ):
        # matplot has trouble if we plot just a single data point
        # so we wait for itr > 1

# if not ShowOn().get():
# ShowOn().set(True)

        fig = kwargs['fig']
        ax = kwargs['ax']

        xlo, xhi = ax.get_xlim()
        xlo = max ( 0, xlo) # Check bc original call is ignored
        xhi = max (50, xhi) # Likewise
        if itr > xhi:
            xhi *= 2

        ax.set_xlim ([xlo, xhi])
        ax.set_ylim ( [ min(currlens), max(currlens) ] )
        plot(iteratns, currlens, 'b',
             iteratns, bestlens, 'r')

        fig.draw() # schedule a refresh
        t1[0] = time.time()

    # Display any updates to the figure
    while gtk.events_pending():
        gtk.mainiteration() # if running in normal gtk thread

    global interrupted
    if interrupted:
        return 1

    return snob.default_status_func(*args)