Interactive Animated PyPlot in IJulia

1,176 views
Skip to first unread message

Christoph Ortner

unread,
Nov 27, 2014, 6:20:54 AM11/27/14
to julia...@googlegroups.com
I could not find it, but apologies if this has previously been discussed.

I am interested in outputting numerical results on the fly - not in generating movie files. (I have found some nice examples on how to do the latter.) The following code snippet, run in IJulia opens an external plot window and then displays the animation I want to see.

using PyPlot
pygui(true)
x = linspace(0,1,100)
PyPlot.hold(false)
for t = -1:.1:1
    plot(x, t*(1-x).*x)
    axis([0,1, -.3, .3])
    PyPlot.draw()
end

But if I change to pygui(false)  to see the plots within IJulia, then I only get the final graph. Can it be done? What am I missing?

(Strangly, I think I did have it working before, but somehow broke it and cannot figure out again what I did.)

Many thanks,
   Christoph


Christoph Ortner

unread,
Nov 27, 2014, 6:28:23 AM11/27/14
to julia...@googlegroups.com

UPDATE: I did find a discussion on this / copied below. So my new question is: 

Can I achieve what I want *without* modifying the pyplot source code?

Thanks,
    Christoph


OK This worked (after modifying by hand matplotlib/pyplot.py to change plt.show(block=False) to plt.ion(), possibly updating matplotlib would work):

PyPlot.show()

for k=1:20
    PyPlot.plot([1:10],1+k*[1:10])
    PyPlot.draw()
    PyPlot.pause(0.05)
end
- hide quoted text -


On 20 Aug 2014, at 4:02 am, Steven G. Johnson <steve...@gmail.com> wrote:



On Tuesday, August 19, 2014 11:09:21 AM UTC-4, ggggg wrote:
You could try adapting this python stack overflow answer.  I've only ever done it with qt4 and the matplotlib api from python, but it is certainly possible.


The key suggestions seem to be
  1. Call plt.ion() in order to enable interactive plotting. plt.show(block=False) is no longer available.
  2. Call plt.show() initially, then update the plot with plt.draw()

In PyPlot, use pygui(true) to switch to the Python GUI if you are using IJulia. 


Cristóvão Duarte Sousa

unread,
Nov 27, 2014, 9:09:27 AM11/27/14
to julia...@googlegroups.com
Hi,

I was able to do it using Interact, Reactive and Winston in IJulia.

For example, in one input cell run

using Interact, Reactive, Winston

p
= Input(0.0:0.0)
function f(x)
    plot
(sin(5*x), sin(2π*x))
    xlim
(-1, 1)
    ylim
(-1, 1)
end
lift
(f, p)



and then, in another cell, run your updating loop:

for i=0:0.05:10
    sleep
(1/60)
    push
!(p, 0.0:0.01:i)
end

I'm pretty sure this is inefficient and can be very slow for more elaborated plots though.

Steven G. Johnson

unread,
Nov 27, 2014, 9:20:36 AM11/27/14
to julia...@googlegroups.com
using PyPlot, Interact

f = figure()
@manipulate for p in 1:10
withfig(f) do
...plot commands with parameter p...
end
end

There are some other plotting examples with @manipulate in the Interact docs.

Christoph Ortner

unread,
Nov 27, 2014, 10:36:28 AM11/27/14
to julia...@googlegroups.com


Thank you both for your replies. 

Since the purpose is to plot the current state of a numerical simulation every few iterations (of some nonlinear iteration or time-stepping scheme) I don't think either these are suitable though. 

Re the @manipulate approach: I just get a slider this way? I've tried to follow the examples in the @manipulate docs, but no luck really to get these to run either. + All this is much too complicated for my test.

Is there no way to simple force IJulia to draw the current plot command?

Thanks,
    Christoph

Christoph Ortner

unread,
Nov 27, 2014, 11:21:40 AM11/27/14
to julia...@googlegroups.com
On second thought, the scheme using `Input` might actually work for this. I'll have a go.
     Christoph

Christoph Ortner

unread,
Nov 27, 2014, 12:11:47 PM11/27/14
to julia...@googlegroups.com
A naive attempt at this failed I just replaced Winston.plot with PyPlot.plot in Cristovao's example; see below. The result is that Pyplot plots in the [2] output instead of the [1] output.

Why is it ok with Winston but not with PyPlot?

I am obsessing about PyPlot because I need the 3D plotting capabilities.

Thank you,
Christoph

  
In [1] 
using Gadfly,Reactive,Interact,PyPlot
function myplot(data)
    PyPlot.plot(data[1], data[2])
    axis([0,1,-.3,.3])
end
x = linspace(0,1,100)
myinput=Input((x,0*x))
lift(myplot, my input)

In [2]
x = linspace(0,1,100)
for t = -1:.1:1
    y = t * x .*(1-x)
    push!(myinput,(x, y))
end

Steven G. Johnson

unread,
Nov 27, 2014, 2:04:12 PM11/27/14
to julia...@googlegroups.com
PyPlot, like the Python package of the same name, plots as a side effect. You can use the withfig function to wrap PyPlot commands and make them functional (returning the figure object as the withfig return value rather than displaying it as a side effect). This allows Pyplot to be used with @manipulate, but should also work with other Reactive functions.

Christoph Ortner

unread,
Nov 27, 2014, 4:11:22 PM11/27/14
to julia...@googlegroups.com
Hi Steven,

That worked! Thank you.

(Though admittedly I did not fully understand your explanation.)

All the best, 
    Christoph

Christoph Ortner

unread,
Nov 27, 2014, 4:12:14 PM11/27/14
to julia...@googlegroups.com
And here is the working code:

[1]
using Gadfly,Reactive,Interact,PyPlot
myfig = figure()
function myplot(data)
    withfig(myfig) do
        PyPlot.plot(data[1], data[2])
        axis([0,1,-.3,.3])
    end
end
x = linspace(0,1,100)
myinput=Input((x,0*x))
lift(myplot, myinput)

[2]
x = linspace(0,1,100)
for t = -1:.1:1
    y = t * x .*(1-x)
    push!(myinput,(x, y))
end


Thomas Hudson

unread,
Jul 25, 2016, 9:23:23 AM7/25/16
to julia-users
Since Julia 0.4.6, this solution no longer seems to work: the code reverts to plotting only the final frame calculated.

Does anyone have any idea how to tweak the code and get identical on-the-fly plotting behaviour with PyPlot under Julia 0.4.6?

Thanks for any help you can give,

Tom

Thomas Hudson

unread,
Jul 28, 2016, 6:42:16 PM7/28/16
to julia-users
Just to say, this is not simply a case of replacing deprecated lift and Input; the push! fails for me; does anyone else have this problem?

In the end, I succeeded in getting the results I wanted by tweaking the code in OP's first post; see two versions (interactive and non-interactive) below.

Interactive version:
using PyPlot
pygui(true)
x = linspace(0,1,100)
PyPlot.hold(false)
for t = -1:.1:1
    IJulia.clear_output(true)
    p = plot(x, t*(1-x).*x)

    axis([0,1, -.3, .3])
    PyPlot.draw()
end

Inline version:
using PyPlot
pygui(false)
x = linspace(0,1,100)
PyPlot.hold(false)

for t = -1:.1:1
    IJulia.clear_output(true)

    plot(x, t*(1-x).*x)
    axis([0,1, -.3, .3])
    display(gcf())
end

Thomas Hudson

unread,
Jul 28, 2016, 6:42:16 PM7/28/16
to julia-users
I managed to work out a solution in the end, using the clear_output command and forcing IJulia to display the plot. If anyone knows of a fancier solution with the Reactive and Interact packages, I'd still be interested.

Inline version: (really slow for me)

using PyPlot
pygui(false)
x = linspace(0,1,100)
PyPlot.hold(false)
for t = -1:.1:1
    IJulia.clear_output(true)

    plot(x, t*(1-x).*x)
    axis([0,1, -.3, .3])
    display(gcf())
end

Interactive version:

using PyPlot
pygui(true)
x = linspace(0,1,100)
PyPlot.hold(false)
for t = -1:.1:1
    IJulia.clear_output(true)
    p = plot(x, t*(1-x).*x)

    axis([0,1, -.3, .3])
    PyPlot.draw()
end

On Monday, 25 July 2016 15:23:23 UTC+2, Thomas Hudson wrote:

Christoph Ortner

unread,
Jul 29, 2016, 11:03:11 AM7/29/16
to julia-users
Thanks for figuring this out, Tom.  I'd also be interested in a Reactive and Interact solution.
Message has been deleted

Josef Heinen

unread,
Jul 30, 2016, 3:24:56 AM7/30/16
to julia-users
This is probably what you are looking for. If you need special Matplotlib features, you can even mix GR and PyPlot (see slides 10 and 13 from my SciPy 2016 talk which demonstrate the performance and interoperability)

Thomas Hudson

unread,
Jul 30, 2016, 5:12:43 AM7/30/16
to julia...@googlegroups.com
This isn't quite what I want: as with the discussion above, while the example code has a sequence of predetermined graphs to be plotted, what I'm really interested in is plotting the results of a more intensive calculation frame by frame as it runs, rather than doing the calculation of the entire trajectory, and plotting a manipulable plot after the fact.

Nevertheless, it's useful to know that you can do some fancy plot manipulation in this way!

Josef Heinen

unread,
Jul 30, 2016, 11:25:44 AM7/30/16
to julia-users
The first animation (slide 10) updates a 3d surface frame by frame - the noise added could also be the result of an intensive calculation or a real-time signal. There is a demo in the GR example section showing a 3d power spectrum calculated from the microphone audio input ...

Christoph Ortner

unread,
Aug 1, 2016, 9:10:28 AM8/1/16
to julia-users
Just played with the examples in GR.jl/examples. Works really well. Thank you!
Reply all
Reply to author
Forward
0 new messages