26
26
from matplotlib import rcParams
27
27
28
28
# Other potential writing methods:
29
- # * ImageMagick convert: convert -set delay 3 -colorspace GRAY -colors 16 -dispose 1 -loop 0 -scale 50% *.png Output.gif
29
+ # * ImageMagick convert: convert -set delay 3 -colorspace GRAY -colors 16
30
+ # -dispose 1 -loop 0 -scale 50% *.png Output.gif
30
31
# * http://pymedia.org/
31
32
# * libmng (produces swf) python wrappers: https://github.com/libming/libming
32
- # * Wrap x264 API: http://stackoverflow.com/questions/2940671/how-to-encode-series-of-images-into-h264-using-x264-api-c-c
33
+ # * Wrap x264 API:
34
+ # http://stackoverflow.com/questions/2940671/how-to-encode-series-of-images-into-h264-using-x264-api-c-c
33
35
34
36
35
37
# A registry for available MovieWriter classes
@@ -60,6 +62,7 @@ def __getitem__(self, name):
60
62
61
63
writers = MovieWriterRegistry ()
62
64
65
+
63
66
class MovieWriter (object ):
64
67
'''
65
68
Base class for writing movies. Fundamentally, what a MovieWriter does
@@ -173,7 +176,8 @@ def _run(self):
173
176
output = sys .stdout
174
177
else :
175
178
output = subprocess .PIPE
176
- verbose .report ('MovieWriter.run: running command: %s' % ' ' .join (command ))
179
+ verbose .report ('MovieWriter.run: running command: %s' %
180
+ ' ' .join (command ))
177
181
self ._proc = subprocess .Popen (command , shell = False ,
178
182
stdout = output , stderr = output ,
179
183
stdin = subprocess .PIPE )
@@ -186,7 +190,8 @@ def grab_frame(self):
186
190
'''
187
191
Grab the image information from the figure and save as a movie frame.
188
192
'''
189
- verbose .report ('MovieWriter.grab_frame: Grabbing frame.' , level = 'debug' )
193
+ verbose .report ('MovieWriter.grab_frame: Grabbing frame.' ,
194
+ level = 'debug' )
190
195
try :
191
196
# Tell the figure to save its data to the sink, using the
192
197
# frame format and dpi.
@@ -208,7 +213,7 @@ def _args(self):
208
213
209
214
def cleanup (self ):
210
215
'Clean-up and collect the process used to write the movie file.'
211
- out ,err = self ._proc .communicate ()
216
+ out , err = self ._proc .communicate ()
212
217
verbose .report ('MovieWriter -- Command stdout:\n %s' % out ,
213
218
level = 'debug' )
214
219
verbose .report ('MovieWriter -- Command stderr:\n %s' % err ,
@@ -266,7 +271,7 @@ def setup(self, fig, outfile, dpi, frame_prefix='_tmp', clear_temp=True):
266
271
self .dpi = dpi
267
272
self .clear_temp = clear_temp
268
273
self .temp_prefix = frame_prefix
269
- self ._frame_counter = 0 # used for generating sequential file names
274
+ self ._frame_counter = 0 # used for generating sequential file names
270
275
self ._temp_names = list ()
271
276
self .fname_format_str = '%s%%07d.%s'
272
277
@@ -298,9 +303,10 @@ def _frame_sink(self):
298
303
# Save the filename so we can delete it later if necessary
299
304
self ._temp_names .append (fname )
300
305
verbose .report (
301
- 'FileMovieWriter.frame_sink: saving frame %d to fname=%s' % (self ._frame_counter , fname ),
306
+ 'FileMovieWriter.frame_sink: saving frame %d to fname=%s' %
307
+ (self ._frame_counter , fname ),
302
308
level = 'debug' )
303
- self ._frame_counter += 1 # Ensures each created name is 'unique'
309
+ self ._frame_counter += 1 # Ensures each created name is 'unique'
304
310
305
311
# This file returned here will be closed once it's used by savefig()
306
312
# because it will no longer be referenced and will be gc-ed.
@@ -310,7 +316,7 @@ def finish(self):
310
316
# Call run here now that all frame grabbing is done. All temp files
311
317
# are available to be assembled.
312
318
self ._run ()
313
- MovieWriter .finish (self ) # Will call clean-up
319
+ MovieWriter .finish (self ) # Will call clean-up
314
320
315
321
# Check error code for creating file here, since we just run
316
322
# the process here, rather than having an open pipe.
@@ -326,7 +332,8 @@ def cleanup(self):
326
332
if self .clear_temp :
327
333
import os
328
334
verbose .report (
329
- 'MovieWriter: clearing temporary fnames=%s' % str (self ._temp_names ),
335
+ 'MovieWriter: clearing temporary fnames=%s' %
336
+ str (self ._temp_names ),
330
337
level = 'debug' )
331
338
for fname in self ._temp_names :
332
339
os .remove (fname )
@@ -347,8 +354,8 @@ def output_args(self):
347
354
args .extend (['-b' , '%dk' % self .bitrate ])
348
355
if self .extra_args :
349
356
args .extend (self .extra_args )
350
- for k ,v in self .metadata .items ():
351
- args .extend (['-metadata' , '%s=%s' % (k ,v )])
357
+ for k , v in self .metadata .items ():
358
+ args .extend (['-metadata' , '%s=%s' % (k , v )])
352
359
353
360
return args + ['-y' , self .outfile ]
354
361
@@ -372,7 +379,9 @@ def _args(self):
372
379
#Combine FFMpeg options with temp file-based writing
373
380
@writers .register ('ffmpeg_file' )
374
381
class FFMpegFileWriter (FileMovieWriter , FFMpegBase ):
375
- supported_formats = ['png' , 'jpeg' , 'ppm' , 'tiff' , 'sgi' , 'bmp' , 'pbm' , 'raw' , 'rgba' ]
382
+ supported_formats = ['png' , 'jpeg' , 'ppm' , 'tiff' , 'sgi' , 'bmp' ,
383
+ 'pbm' , 'raw' , 'rgba' ]
384
+
376
385
def _args (self ):
377
386
# Returns the command line parameters for subprocess to use
378
387
# ffmpeg to create a movie using a collection of temp images
@@ -408,8 +417,8 @@ def output_args(self):
408
417
if self .extra_args :
409
418
args .extend (self .extra_args )
410
419
if self .metadata :
411
- args .extend (['-info' , ':' .join ('%s=%s' % (k ,v )
412
- for k ,v in self .metadata .items ()
420
+ args .extend (['-info' , ':' .join ('%s=%s' % (k , v )
421
+ for k , v in self .metadata .items ()
413
422
if k in self .allowed_metadata )])
414
423
return args
415
424
@@ -422,20 +431,23 @@ def _args(self):
422
431
# mencoder to create a movie
423
432
return [self .bin_path (), '-' , '-demuxer' , 'rawvideo' , '-rawvideo' ,
424
433
('w=%i:h=%i:' % self .frame_size +
425
- 'fps=%i:format=%s' % (self .fps , self .frame_format ))] + self .output_args
434
+ 'fps=%i:format=%s' % (self .fps ,
435
+ self .frame_format ))] + self .output_args
426
436
427
437
428
438
# Combine Mencoder options with temp file-based writing
429
439
@writers .register ('mencoder_file' )
430
440
class MencoderFileWriter (FileMovieWriter , MencoderBase ):
431
441
supported_formats = ['png' , 'jpeg' , 'tga' , 'sgi' ]
442
+
432
443
def _args (self ):
433
444
# Returns the command line parameters for subprocess to use
434
445
# mencoder to create a movie
435
446
return [self .bin_path (),
436
447
'mf://%s*.%s' % (self .temp_prefix , self .frame_format ),
437
448
'-frames' , str (self ._frame_counter ), '-mf' ,
438
- 'type=%s:fps=%d' % (self .frame_format , self .fps )] + self .output_args
449
+ 'type=%s:fps=%d' % (self .frame_format ,
450
+ self .fps )] + self .output_args
439
451
440
452
441
453
class Animation (object ):
@@ -473,7 +485,8 @@ def __init__(self, fig, event_source=None, blit=False):
473
485
474
486
# Connect to the figure's close_event so that we don't continue to
475
487
# fire events and try to draw to a deleted figure.
476
- self ._close_id = self ._fig .canvas .mpl_connect ('close_event' , self ._stop )
488
+ self ._close_id = self ._fig .canvas .mpl_connect ('close_event' ,
489
+ self ._stop )
477
490
if blit :
478
491
self ._setup_blit ()
479
492
@@ -488,7 +501,7 @@ def _start(self, *args):
488
501
self .event_source .add_callback (self ._step )
489
502
self .event_source .start ()
490
503
self ._fig .canvas .mpl_disconnect (self ._first_draw_id )
491
- self ._first_draw_id = None # So we can check on save
504
+ self ._first_draw_id = None # So we can check on save
492
505
493
506
def _stop (self , * args ):
494
507
# On stop we disconnect all of our events.
@@ -570,7 +583,9 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
570
583
571
584
all_anim = [self ]
572
585
if not extra_anim is None :
573
- all_anim .extend (anim for anim in extra_anim if anim ._fig is self ._fig )
586
+ all_anim .extend (anim
587
+ for anim
588
+ in extra_anim if anim ._fig is self ._fig )
574
589
575
590
# If we have the name of a writer, instantiate an instance of the
576
591
# registered class.
@@ -583,16 +598,18 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
583
598
warnings .warn ("MovieWriter %s unavailable" % writer )
584
599
writer = writers .list ()[0 ]
585
600
586
- verbose .report ('Animation.save using %s' % type (writer ), level = 'helpful' )
601
+ verbose .report ('Animation.save using %s' % type (writer ),
602
+ level = 'helpful' )
587
603
# Create a new sequence of frames for saved data. This is different
588
604
# from new_frame_seq() to give the ability to save 'live' generated
589
605
# frame information to be saved later.
590
- # TODO: Right now, after closing the figure, saving a movie won't
591
- # work since GUI widgets are gone. Either need to remove extra code
592
- # to allow for this non-existant use case or find a way to make it work.
606
+ # TODO: Right now, after closing the figure, saving a movie won't work
607
+ # since GUI widgets are gone. Either need to remove extra code to
608
+ # allow for this non-existant use case or find a way to make it work.
593
609
with writer .saving (self ._fig , filename , dpi ):
594
- for data in itertools .izip (* [a .new_saved_frame_seq () for a in all_anim ]):
595
- for anim ,d in zip (all_anim , data ):
610
+ for data in itertools .izip (* [a .new_saved_frame_seq ()
611
+ for a in all_anim ]):
612
+ for anim , d in zip (all_anim , data ):
596
613
#TODO: Need to see if turning off blit is really necessary
597
614
anim ._draw_next_frame (d , blit = False )
598
615
writer .grab_frame ()
@@ -703,7 +720,8 @@ def _handle_resize(self, *args):
703
720
self .event_source .stop ()
704
721
self ._blit_cache .clear ()
705
722
self ._init_draw ()
706
- self ._resize_id = self ._fig .canvas .mpl_connect ('draw_event' , self ._end_redraw )
723
+ self ._resize_id = self ._fig .canvas .mpl_connect ('draw_event' ,
724
+ self ._end_redraw )
707
725
708
726
def _end_redraw (self , evt ):
709
727
# Now that the redraw has happened, do the post draw flushing and
@@ -739,17 +757,19 @@ def __init__(self, fig, interval=200, repeat_delay=None, repeat=True,
739
757
event_source = fig .canvas .new_timer ()
740
758
event_source .interval = self ._interval
741
759
742
- Animation .__init__ (self , fig , event_source = event_source , * args , ** kwargs )
760
+ Animation .__init__ (self , fig , event_source = event_source ,
761
+ * args , ** kwargs )
743
762
744
763
def _step (self , * args ):
745
764
'''
746
765
Handler for getting events.
747
766
'''
748
767
# Extends the _step() method for the Animation class. If
749
- # Animation._step signals that it reached the end and we want to repeat,
750
- # we refresh the frame sequence and return True. If _repeat_delay is
751
- # set, change the event_source's interval to our loop delay and set the
752
- # callback to one which will then set the interval back.
768
+ # Animation._step signals that it reached the end and we want to
769
+ # repeat, we refresh the frame sequence and return True. If
770
+ # _repeat_delay is set, change the event_source's interval to our loop
771
+ # delay and set the callback to one which will then set the interval
772
+ # back.
753
773
still_going = Animation ._step (self , * args )
754
774
if not still_going and self .repeat :
755
775
self .frame_seq = self .new_frame_seq ()
@@ -831,6 +851,7 @@ def _draw_frame(self, artists):
831
851
for artist in artists :
832
852
artist .set_visible (True )
833
853
854
+
834
855
class FuncAnimation (TimedAnimation ):
835
856
'''
836
857
Makes an animation by repeatedly calling a function *func*, passing in
@@ -842,7 +863,7 @@ class FuncAnimation(TimedAnimation):
842
863
results of drawing from the first item in the frames sequence will be
843
864
used.
844
865
'''
845
- def __init__ (self , fig , func , frames = None , init_func = None , fargs = None ,
866
+ def __init__ (self , fig , func , frames = None , init_func = None , fargs = None ,
846
867
save_count = None , ** kwargs ):
847
868
if fargs :
848
869
self ._args = fargs
@@ -913,7 +934,8 @@ def _draw_frame(self, framedata):
913
934
# Save the data for potential saving of movies.
914
935
self ._save_seq .append (framedata )
915
936
916
- # Make sure to respect save_count (keep only the last save_count around)
937
+ # Make sure to respect save_count (keep only the last save_count
938
+ # around)
917
939
self ._save_seq = self ._save_seq [- self .save_count :]
918
940
919
941
# Call the func with framedata and args. If blitting is desired,
0 commit comments