Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animating p9 figures using ArtistAnimation class of matplotlib #45

Closed
gokceneraslan opened this issue Aug 14, 2017 · 2 comments
Closed

Comments

@gokceneraslan
Copy link
Contributor

Hi,

I'm trying to make animations using p9 figures, but I end up with matplotlib exceptions. I was wondering whether there is a convenient way to make animations out of plotnine plots.

Here is what I've tried so far:

from plotnine import *
from plotnine.data import *

from matplotlib.animation import ArtistAnimation
import matplotlib.pyplot as plt
import numpy as np

def plot1(y):
    return plt.scatter(y[:, 0], y[:, 1], c='black'),

def plot2(y):
    return (qplot(y[:, 0], y[:, 1], xlab='x', ylab='y') +
            theme_minimal()).draw(),

# Use mtcars as toy data
X = mtcars[['disp', 'hp']].as_matrix()

# Add little noise to make animation cool
data = [X+np.random.normal(0, 1, (X.shape[0], X.shape[1])) for _ in range(50)]

fig = plt.figure(figsize=(8, 8))
artists = [plot1(x) for x in data]
ani = ArtistAnimation(fig, artists, interval=100, repeat_delay=500)
ani.save('/tmp/animation.mp4')

fig = plt.figure(figsize=(8, 8))
artists = [plot2(x) for x in data]
ani = ArtistAnimation(fig, artists, interval=100, repeat_delay=500)
ani.save('/tmp/animation2.mp4')

Here is the exception I get:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-39-98cef8b8381e> in <module>()
     25 artists = [plot2(x) for x in data]
     26 ani = ArtistAnimation(fig, artists, interval=100, repeat_delay=500)
---> 27 ani.save('/tmp/animation2.mp4')

~/.miniconda3/lib/python3.6/site-packages/matplotlib/animation.py in save(self, filename, writer, fps, dpi, codec, bitrate, extra_args, metadata, extra_anim, savefig_kwargs)
   1055                 for anim in all_anim:
   1056                     # Clear the initial frame
-> 1057                     anim._init_draw()
   1058                 for data in zip(*[a.new_saved_frame_seq()
   1059                                   for a in all_anim]):

~/.miniconda3/lib/python3.6/site-packages/matplotlib/animation.py in _init_draw(self)
   1374         # Flush the needed figures
   1375         for fig in figs:
-> 1376             fig.canvas.draw_idle()
   1377 
   1378     def _pre_draw(self, framedata, blit):

AttributeError: 'NoneType' object has no attribute 'canvas'

Is there a way to get "proper" artists for ArtistAnimation class?

@gokceneraslan
Copy link
Contributor Author

Here is how the result of plot1() looks like:
animation

@has2k1
Copy link
Owner

has2k1 commented Aug 14, 2017

I have not tried to do animations, may be this issue can help straighten that out.

The problem with the plot2 function is that, ggplot.draw() returns a figure. That means you get 50 figures, since plotnine creates the figures. When you have a figure you can obtain the artists with figure.get_children(), but I think that is a catch-all for every artist not just those for the data. And, I think you cannot easily move artists from one figure to another.

So, I do not think ArtistAnimation can be used. Need to think of a nice way of going about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants