3
votes

Hej,

I'm using the PyPlot package in Julia, and have a bit of an issue that I couldn't find an answer to.

Essentially, I want to have a plot window that gets update during an iterative calculation. ( I don't use Atom's plotting panel, but rather an external matplotlib-style plotting window with interactive controls for zooming panning etc.)

My code is roughly as follows

import PyPlot
const plt = PyPlot
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)
...
while (x < y)
    ... calculation of x and y...
    ax1.plot(x)
    ax2.plot(y)
end

This works, more or less, as expected: Initially, a window with all the subplots but no curves opens. Once the calculation is running, it plots my curves and I can see them. So far, so good. However, while the calculation is running the plot window gets locked down and I cannot use the 'interactive' tools. Once an iteration is finished, it will update the plot and any input i made during the 'freeze' period will get performed. But for practical purposes, it's like a 10 second (or longer, depending on how long an interation takes) pause before I get a response.

Is there any way to keep the window responsive while the calculation is running, or is it a build-in freeze that cannot be prevented?

Thanks for any hints and sorry if it's a duplicate.

Best, pohly

1

1 Answers

2
votes

If I understand your question correctly one of the approaches you can use is to use the pause function:

help?> plt.pause

Pause for *interval* seconds.

If there is an active figure, it will be updated and displayed before the
pause, and the GUI event loop (if any) will run during the pause.

This can be used for crude animation.  For more complex animation, see
:mod:`matplotlib.animation`.

Notes
-----
This function is experimental; its behavior may be changed or extended in a
future release.

Here is an example code:

import PyPlot

const plt = PyPlot

ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)

x = rand(1)
y = rand(1)
for i in 1:100
    push!(x, rand())
    push!(y, rand())
    ax1.plot(x)
    ax2.plot(y)
    plt.pause(0.01)
end

is this what you wanted?

EDIT

If your computation is expensive then you can use multi threading to get what you want. Here is an example (function f is computation heavy and it should be run in a separate thread):

import PyPlot

function f()
    for i in 1:10^9 # just run some expensive task
        rand()
    end
    return rand()
end

const plt = PyPlot

ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)

x = rand(1)
y = rand(1)
for i in 1:10
    t = Threads.@spawn f()
    push!(x, fetch(t))
    push!(y, rand())
    ax1.plot(x)
    ax2.plot(y)
    plt.pause(0.0001)
end