@@ -29,6 +29,7 @@ class Animation:
29
29
animation
30
30
a matplotlib animation returned from FuncAnimation
31
31
"""
32
+
32
33
def __init__ (self , blocks , timeline = None , fig = None ):
33
34
self .fig = plt .gcf () if fig is None else fig
34
35
@@ -45,8 +46,9 @@ def _animate(self, blocks, timeline):
45
46
_len_time = len (self .timeline )
46
47
for block in blocks :
47
48
if len (block ) != _len_time :
48
- raise ValueError ("All blocks must animate for the same amount "
49
- "of time" )
49
+ raise ValueError (
50
+ "All blocks must animate for the same amount " "of time"
51
+ )
50
52
51
53
self .blocks = blocks
52
54
self ._has_slider = False
@@ -62,21 +64,25 @@ def update_all(i):
62
64
self .timeline ._update ()
63
65
return updates
64
66
65
- return FuncAnimation (self .fig , update_all , frames = self .timeline ._len ,
66
- interval = 1000 / self .timeline .fps )
67
+ return FuncAnimation (
68
+ self .fig ,
69
+ update_all ,
70
+ frames = self .timeline ._len ,
71
+ interval = 1000 / self .timeline .fps ,
72
+ )
67
73
68
74
@property
69
75
def _controls_gridspec (self ):
70
76
if self ._controls_gridspec_object is None :
71
77
# make the bottom of the subplots grid lower to fit the controls in
72
- adjust_plot = {' bottom' : 0.03 }
78
+ adjust_plot = {" bottom" : 0.03 }
73
79
plt .subplots_adjust (** adjust_plot )
74
80
75
81
controls_height = 0.2
76
82
77
83
fig_gridspecs = self .fig ._gridspecs
78
84
if len (fig_gridspecs ) > 1 :
79
- raise ValueError (' multiple gridspecs found in figure' )
85
+ raise ValueError (" multiple gridspecs found in figure" )
80
86
gs = fig_gridspecs [0 ]
81
87
nrows , ncols = gs .get_geometry ()
82
88
height_ratios = gs .get_height_ratios ()
@@ -85,17 +91,17 @@ def _controls_gridspec(self):
85
91
if height_ratios is None :
86
92
# if height_ratios is None, all rows on the original gridspec
87
93
# are the same height
88
- height_ratios = [(1. - controls_height )/ nrows
89
- for i in range (nrows )]
94
+ height_ratios = [(1.0 - controls_height ) / nrows for i in range (nrows )]
90
95
else :
91
- height_ratios = [r * (1. - controls_height ) for r in height_ratios ]
96
+ height_ratios = [r * (1.0 - controls_height ) for r in height_ratios ]
92
97
height_ratios .append (controls_height )
93
98
gs ._nrows += 1
94
99
gs .set_height_ratios (height_ratios )
95
100
96
101
# make a sub-grid in the bottom row
97
102
self ._controls_gridspec_object = gs [- 1 , :].subgridspec (
98
- 1 ,3 , width_ratios = [.07 , .65 , .28 ], wspace = 0. , hspace = 0. )
103
+ 1 , 3 , width_ratios = [0.07 , 0.65 , 0.28 ], wspace = 0.0 , hspace = 0.0
104
+ )
99
105
gs .update ()
100
106
101
107
return self ._controls_gridspec_object
@@ -112,17 +118,24 @@ def toggle(self, ax=None):
112
118
try :
113
119
button_subplotspec = self ._controls_gridspec [0 , 2 ]
114
120
button_gridspec = button_subplotspec .subgridspec (
115
- 3 , 3 , width_ratios = [0.45 , 0.45 , 0.1 ],
116
- height_ratios = [.05 , .5 , .45 ], wspace = 0. , hspace = 0. )
117
- self .button_ax = self .fig .add_subplot (button_gridspec [1 ,1 ])
121
+ 3 ,
122
+ 3 ,
123
+ width_ratios = [0.45 , 0.45 , 0.1 ],
124
+ height_ratios = [0.05 , 0.5 , 0.45 ],
125
+ wspace = 0.0 ,
126
+ hspace = 0.0 ,
127
+ )
128
+ self .button_ax = self .fig .add_subplot (button_gridspec [1 , 1 ])
118
129
except :
119
130
# editing the gridspec did not work for some reason, fall back to
120
131
# subplots_adjust
121
- print ('warning: adding play/pause button to gridspec failed, '
122
- 'adding in independent axes. tight_layout() will ignore '
123
- 'the button.' )
124
- adjust_plot = {'bottom' : .2 }
125
- left , bottom , width , height = (.78 , .03 , .1 , .07 )
132
+ print (
133
+ "warning: adding play/pause button to gridspec failed, "
134
+ "adding in independent axes. tight_layout() will ignore "
135
+ "the button."
136
+ )
137
+ adjust_plot = {"bottom" : 0.2 }
138
+ left , bottom , width , height = (0.78 , 0.03 , 0.1 , 0.07 )
126
139
rect = (left , bottom , width , height )
127
140
128
141
plt .subplots_adjust (** adjust_plot )
@@ -132,10 +145,12 @@ def toggle(self, ax=None):
132
145
133
146
self .button = Button (self .button_ax , "Pause" )
134
147
self .button .label2 = self .button_ax .text (
135
- x = 0.5 , y = 0.5 , s = 'Play' ,
136
- verticalalignment = 'center' ,
137
- horizontalalignment = 'center' ,
138
- transform = self .button_ax .transAxes
148
+ x = 0.5 ,
149
+ y = 0.5 ,
150
+ s = "Play" ,
151
+ verticalalignment = "center" ,
152
+ horizontalalignment = "center" ,
153
+ transform = self .button_ax .transAxes ,
139
154
)
140
155
self .button .label2 .set_visible (False )
141
156
@@ -150,9 +165,10 @@ def pause(event):
150
165
self .button .label2 .set_visible (True )
151
166
self .fig .canvas .draw ()
152
167
self ._pause ^= True
168
+
153
169
self .button .on_clicked (pause )
154
170
155
- def timeline_slider (self , text = ' Time' , ax = None , valfmt = None , color = None ):
171
+ def timeline_slider (self , text = " Time" , ax = None , valfmt = None , color = None ):
156
172
"""Creates a timeline slider.
157
173
158
174
Parameters
@@ -171,30 +187,33 @@ def timeline_slider(self, text='Time', ax=None, valfmt=None, color=None):
171
187
try :
172
188
slider_subplotspec = self ._controls_gridspec [0 , 1 ]
173
189
slider_gridspec = slider_subplotspec .subgridspec (
174
- 3 , 1 , height_ratios = [.2 , .2 , .6 ], wspace = 0. ,
175
- hspace = 0. )
190
+ 3 , 1 , height_ratios = [0 .2 , 0 .2 , 0 .6 ], wspace = 0.0 , hspace = 0.0
191
+ )
176
192
self .slider_ax = self .fig .add_subplot (slider_gridspec [1 , 0 ])
177
193
except :
178
194
# editing the gridspec did not work for some reason, fall back to
179
195
# subplots_adjust
180
- print ('warning: adding timeline slider to gridspec failed, '
181
- 'adding in independent axes. tight_layout() will ignore '
182
- 'the slider.' )
183
- adjust_plot = {'bottom' : .2 }
184
- rect = [.18 , .05 , .5 , .03 ]
196
+ print (
197
+ "warning: adding timeline slider to gridspec failed, "
198
+ "adding in independent axes. tight_layout() will ignore "
199
+ "the slider."
200
+ )
201
+ adjust_plot = {"bottom" : 0.2 }
202
+ rect = [0.18 , 0.05 , 0.5 , 0.03 ]
185
203
plt .subplots_adjust (** adjust_plot )
186
204
self .slider_ax = plt .axes (rect )
187
205
else :
188
206
self .slider_ax = ax
189
207
190
208
if valfmt is None :
191
- if (np .issubdtype (self .timeline .t .dtype , np .datetime64 )
192
- or np .issubdtype (self .timeline .t .dtype , np .timedelta64 )):
193
- valfmt = '%s'
209
+ if np .issubdtype (self .timeline .t .dtype , np .datetime64 ) or np .issubdtype (
210
+ self .timeline .t .dtype , np .timedelta64
211
+ ):
212
+ valfmt = "%s"
194
213
else :
195
- valfmt = ' %1.2f'
214
+ valfmt = " %1.2f"
196
215
if self .timeline .log :
197
- valfmt = ' $10^{%s}$' % valfmt
216
+ valfmt = " $10^{%s}$" % valfmt
198
217
199
218
if ax is None :
200
219
# Try to intelligently decide slider width to avoid overlap
@@ -208,16 +227,18 @@ def text_width(txt):
208
227
extents = self .fig .transFigure .inverted ().transform (bbox )
209
228
return extents [1 ][0 ] - extents [0 ][0 ]
210
229
211
- text_val_width = max (text_width (valfmt % (self .timeline [i ]))
212
- for i in range (len (self .timeline )))
230
+ text_val_width = max (
231
+ text_width (valfmt % (self .timeline [i ]))
232
+ for i in range (len (self .timeline ))
233
+ )
213
234
label_width = text_width (text )
214
235
215
236
# Calculate width of slider
216
237
default_button_width = 0.1
217
238
width = 0.73 - text_val_width - label_width - default_button_width
218
239
219
- adjust_plot = {' bottom' : .2 }
220
- left , bottom , height = (.18 , .05 , .03 )
240
+ adjust_plot = {" bottom" : 0 .2 }
241
+ left , bottom , height = (0 .18 , 0 .05 , 0 .03 )
221
242
rect = (left , bottom , width , height )
222
243
223
244
plt .subplots_adjust (** adjust_plot )
@@ -226,18 +247,23 @@ def text_width(txt):
226
247
self .slider_ax = ax
227
248
228
249
self .slider = Slider (
229
- self .slider_ax , label = text , valmin = 0 , valmax = self .timeline ._len - 1 ,
250
+ self .slider_ax ,
251
+ label = text ,
252
+ valmin = 0 ,
253
+ valmax = self .timeline ._len - 1 ,
230
254
valinit = 0 ,
231
- valfmt = (valfmt + self .timeline .units ),
232
- valstep = 1 , color = color
255
+ valfmt = (valfmt + self .timeline .units ),
256
+ valstep = 1 ,
257
+ color = color ,
233
258
)
234
259
self ._has_slider = True
235
260
236
261
def set_time (new_slider_val ):
237
262
# Update slider value and text on each step
238
263
self .timeline .index = int (new_slider_val )
239
264
self .slider .valtext .set_text (
240
- self .slider .valfmt % (self .timeline [self .timeline .index ]))
265
+ self .slider .valfmt % (self .timeline [self .timeline .index ])
266
+ )
241
267
242
268
if self ._pause :
243
269
for block in self .blocks :
@@ -273,8 +299,9 @@ def save_gif(self, filename):
273
299
the name of the file to be created without the file extension
274
300
"""
275
301
self .timeline .index -= 1 # required for proper starting point for save
276
- self .animation .save (filename + '.gif' ,
277
- writer = PillowWriter (fps = self .timeline .fps ))
302
+ self .animation .save (
303
+ filename + ".gif" , writer = PillowWriter (fps = self .timeline .fps )
304
+ )
278
305
279
306
def save (self , * args , ** kwargs ):
280
307
"""Saves an animation
@@ -312,9 +339,11 @@ def add(self, new):
312
339
313
340
for i , block in enumerate (new_blocks ):
314
341
if not isinstance (block , Block ):
315
- raise TypeError (f"Block number { i } passed is of type "
316
- f"{ type (block )} , not of type "
317
- f"animatplot.blocks.Block (or a subclass)" )
342
+ raise TypeError (
343
+ f"Block number { i } passed is of type "
344
+ f"{ type (block )} , not of type "
345
+ f"animatplot.blocks.Block (or a subclass)"
346
+ )
318
347
319
348
self .blocks .append (block )
320
349
0 commit comments