Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimizing matplotlib pyplot: plotting for many small plots

I want to make a movie of some plotted points moving around for a rudimentary traffic simulation. Plotting takes forever, though--~10 frames takes 7s!! What's up with that?

Python code:

import numpy as np
import matplotlib.pyplot as plt
import cProfile

def slowww_plot():
    for i in range(10):
        plt.plot(0, 0, 'bo')
        plt.savefig('%03i.png' % i)
        plt.clf()
        plt.plot(0, 0, 'ro')   
        plt.savefig('%03i.png' % (i+1))
        plt.clf()

cProfile.run('slowww_plot()', sort = 'cumulative'

produces

In [35]: %run test.py
         2035814 function calls (2011194 primitive calls) in 7.322 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    7.322    7.322 <string>:1(<module>)
        1    0.000    0.000    7.322    7.322 test.py:5(slowww_plot)
       40    0.006    0.000    3.615    0.090 axes.py:821(cla)
1440/1120    0.044    0.000    3.278    0.003 axis.py:62(__init__)
       20    0.000    0.000    3.049    0.152 pyplot.py:468(savefig)
       20    0.000    0.000    3.049    0.152 figure.py:1077(savefig)
       20    0.001    0.000    3.048    0.152 backend_bases.py:1892(print_figure)
  520/360    0.015    0.000    2.523    0.007 axis.py:697(cla)
       20    0.010    0.001    2.506    0.125 backend_bases.py:1791(print_png)
       20    0.003    0.000    2.495    0.125 backend_agg.py:444(print_png)
  520/360    0.006    0.000    2.475    0.007 axis.py:732(reset_ticks)
     4340    0.172    0.000    2.373    0.001 lines.py:128(__init__)
       20    0.000    0.000    2.198    0.110 pyplot.py:2449(plot)
       20    0.000    0.000    2.149    0.107 pyplot.py:683(gca)
       20    0.000    0.000    2.149    0.107 figure.py:1030(gca)
       20    0.001    0.000    2.149    0.107 figure.py:710(add_subplot)
       20    0.000    0.000    2.146    0.107 axes.py:8327(__init__)
       20    0.002    0.000    2.139    0.107 axes.py:359(__init__)
       20    0.000    0.000    2.075    0.104 pyplot.py:439(clf)
       20    0.001    0.000    2.074    0.104 figure.py:782(clf)
    20240    0.189    0.000    1.941    0.000 markers.py:114(_recache)
  720/560    0.003    0.000    1.720    0.003 axis.py:1803(_get_tick)
       80    0.002    0.000    1.600    0.020 axis.py:830(set_clip_path)
      160    0.000    0.000    1.592    0.010 spines.py:153(cla)
  720/560    0.003    0.000    1.564    0.003 axis.py:1543(_get_tick)
      120    0.004    0.000    1.278    0.011 axis.py:1183(get_major_ticks)
       20    1.267    0.063    1.267    0.063 {built-in method write_png}
       20    0.000    0.000    1.224    0.061 backend_agg.py:394(draw)
  1520/20    0.013    0.000    1.200    0.060 artist.py:53(draw_wrapper)
       20    0.002    0.000    1.199    0.060 figure.py:815(draw)
       20    0.002    0.000    1.175    0.059 axes.py:1866(draw)
       40    0.002    0.000    1.100    0.028 axis.py:1029(draw)
    10120    0.017    0.000    1.078    0.000 markers.py:132(set_fillstyle)
     5780    0.013    0.000    1.032    0.000 markers.py:109(__init__)

How can I optimize this? I've tried using the PdfPages backend and switching from the stateful wrapper to just using Axis.plot but everything is still slow.

like image 842
aresnick Avatar asked Dec 22 '22 03:12

aresnick


1 Answers

You're doing it very inefficiently if you want an animation.

Instead of making a new figure each time, just set the new data and redraw the existing figure.

For example:

import matplotlib.pyplot as plt
import numpy as np

xy = 100 * np.random.random((2,10))
x, y = xy

fig, ax = plt.subplots()
points, = ax.plot(x, y, 'bo')

for i in range(10):
    xy += np.random.random(xy.shape) - 0.5
    points.set_data(xy)
    fig.savefig('%03i.png' % i)
like image 197
Joe Kington Avatar answered Feb 23 '23 00:02

Joe Kington