diplotocus 0.5.0__tar.gz → 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {diplotocus-0.5.0 → diplotocus-0.6.0}/PKG-INFO +1 -1
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/index.rst +1 -1
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/GUI.ipynb +5 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/animations.ipynb +76 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/plot_objects.ipynb +1 -0
- diplotocus-0.6.0/src/diplotocus/_version.py +1 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/animations.py +398 -30
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/core.py +6 -4
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus.egg-info/PKG-INFO +1 -1
- diplotocus-0.5.0/src/diplotocus/_version.py +0 -1
- {diplotocus-0.5.0 → diplotocus-0.6.0}/.gitattributes +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/.gitignore +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/.readthedocs.yaml +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/LICENSE +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/Makefile +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/_static/force-light.css +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/_static/force-light.js +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/make.bat +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/requirements.txt +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/Web_GUI.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/button.svg +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/demo.mp4 +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/favicon.ico +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/force-light.css +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/force-light.js +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/logo.mp4 +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/_static/logo.svg +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/api/core.rst +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/api/index.rst +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/conf.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/easings.ipynb +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/index.ipynb +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/installation.ipynb +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/quick-start.ipynb +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/docs/source/notebooks/timeline.ipynb +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/logo.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/pyproject.toml +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/readme.md +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/setup.cfg +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/GUI.html +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/__init__.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/app.js +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/server.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/bg.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Draw.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Morph.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Rotate.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Scale.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Sequence.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Translate.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Tween.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_default.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/favicon.ico +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/src/logo_bg.png +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/GUI/style.css +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/__init__.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus/easings.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus.egg-info/SOURCES.txt +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus.egg-info/dependency_links.txt +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus.egg-info/requires.txt +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/src/diplotocus.egg-info/top_level.txt +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test10.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test2.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test3.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test4.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test5.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test6.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test7.py +0 -0
- {diplotocus-0.5.0 → diplotocus-0.6.0}/tests/test8.py +0 -0
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"\n",
|
|
12
12
|
"\n",
|
|
13
13
|
"\n",
|
|
14
|
+
"```{warning}\n",
|
|
15
|
+
"\n",
|
|
16
|
+
"The GUI might not be as stable as the python interface. Feel free to report any issues you encounters.\n",
|
|
17
|
+
"```\n",
|
|
18
|
+
"\n",
|
|
14
19
|
"When running diplotocus through this mode, you will make edit your animation through a local web page in your browser. This page communicates with a python server, which links the GUI and diplotocus objects in the background. Hence, everything you can do through python, you can do through the GUI, and vice versa.\n",
|
|
15
20
|
"\n",
|
|
16
21
|
"```{note}\n",
|
|
@@ -817,6 +817,82 @@
|
|
|
817
817
|
"tl.save_video('../_static/animations/axis_limits.mp4')"
|
|
818
818
|
]
|
|
819
819
|
},
|
|
820
|
+
{
|
|
821
|
+
"cell_type": "markdown",
|
|
822
|
+
"id": "463d3df9",
|
|
823
|
+
"metadata": {},
|
|
824
|
+
"source": [
|
|
825
|
+
"### Axis pos and size\n",
|
|
826
|
+
"\n",
|
|
827
|
+
"```{eval-rst}\n",
|
|
828
|
+
".. automethod:: diplotocus.animations.axis_pos_and_size\n",
|
|
829
|
+
" :noindex:\n",
|
|
830
|
+
"```"
|
|
831
|
+
]
|
|
832
|
+
},
|
|
833
|
+
{
|
|
834
|
+
"cell_type": "code",
|
|
835
|
+
"execution_count": 4,
|
|
836
|
+
"id": "c01a5513",
|
|
837
|
+
"metadata": {},
|
|
838
|
+
"outputs": [
|
|
839
|
+
{
|
|
840
|
+
"data": {
|
|
841
|
+
"application/vnd.jupyter.widget-view+json": {
|
|
842
|
+
"model_id": "0c53fc7065614884aba3cfb420806912",
|
|
843
|
+
"version_major": 2,
|
|
844
|
+
"version_minor": 0
|
|
845
|
+
},
|
|
846
|
+
"text/plain": [
|
|
847
|
+
" 0%| | 0/60 [00:00<?, ?it/s]"
|
|
848
|
+
]
|
|
849
|
+
},
|
|
850
|
+
"metadata": {},
|
|
851
|
+
"output_type": "display_data"
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
"data": {
|
|
855
|
+
"text/markdown": [
|
|
856
|
+
"Saved video ../_static/animations/axis_pos_and_size.mp4"
|
|
857
|
+
],
|
|
858
|
+
"text/plain": [
|
|
859
|
+
"<IPython.core.display.Markdown object>"
|
|
860
|
+
]
|
|
861
|
+
},
|
|
862
|
+
"metadata": {},
|
|
863
|
+
"output_type": "display_data"
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
"data": {
|
|
867
|
+
"text/html": [
|
|
868
|
+
"\n",
|
|
869
|
+
" <video width=\"640\" height=\"360\" autoplay loop muted playsinline>\n",
|
|
870
|
+
" <source src=\"../_static/animations/axis_pos_and_size.mp4?randId=4292\" type=\"video/mp4\">\n",
|
|
871
|
+
" </video>\n",
|
|
872
|
+
" "
|
|
873
|
+
],
|
|
874
|
+
"text/plain": [
|
|
875
|
+
"<IPython.core.display.HTML object>"
|
|
876
|
+
]
|
|
877
|
+
},
|
|
878
|
+
"metadata": {},
|
|
879
|
+
"output_type": "display_data"
|
|
880
|
+
}
|
|
881
|
+
],
|
|
882
|
+
"source": [
|
|
883
|
+
"import diplotocus as dpl\n",
|
|
884
|
+
"import matplotlib.pyplot as plt\n",
|
|
885
|
+
"\n",
|
|
886
|
+
"fig,ax = plt.subplots(1,2)\n",
|
|
887
|
+
"\n",
|
|
888
|
+
"tl = dpl.Timeline(fig=fig)\n",
|
|
889
|
+
"\n",
|
|
890
|
+
"a = dpl.axis_pos_and_size(start_width=0.0,end_width=0.4,duration=60,axis=ax[1])\n",
|
|
891
|
+
"\n",
|
|
892
|
+
"tl.animate(a)\n",
|
|
893
|
+
"tl.save_video('../_static/animations/axis_pos_and_size.mp4')"
|
|
894
|
+
]
|
|
895
|
+
},
|
|
820
896
|
{
|
|
821
897
|
"cell_type": "markdown",
|
|
822
898
|
"id": "bc66aa88",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.0"
|
|
@@ -83,8 +83,6 @@ class plotObject:
|
|
|
83
83
|
if self.mpl_obj_type is None:
|
|
84
84
|
return None
|
|
85
85
|
alias_map = self.mpl_obj_type._alias_map
|
|
86
|
-
if self.mpl_plot_type == plt.plot and False:
|
|
87
|
-
alias_map['color'] = ['c']
|
|
88
86
|
return alias_map
|
|
89
87
|
|
|
90
88
|
def get_possible_kwargs(self):
|
|
@@ -224,9 +222,13 @@ class plotObject:
|
|
|
224
222
|
new_data_x = []
|
|
225
223
|
new_data_y = []
|
|
226
224
|
for i in range(len(data_x)):
|
|
227
|
-
|
|
225
|
+
if anim['sequential']:
|
|
226
|
+
_t = self.get_sequential_t(i,x,len(data_x),anim)
|
|
227
|
+
else:
|
|
228
|
+
_t = t
|
|
229
|
+
new_data_x.append(data_x[i] + (anim['new_x'][i] - data_x[i])*_t)
|
|
228
230
|
if len(data_y) == len(anim['new_y']):
|
|
229
|
-
new_data_y.append(data_y[i] + (anim['new_y'][i] - data_y[i])*
|
|
231
|
+
new_data_y.append(data_y[i] + (anim['new_y'][i] - data_y[i])*_t)
|
|
230
232
|
data_x = new_data_x
|
|
231
233
|
data_y = new_data_y
|
|
232
234
|
|
|
@@ -234,26 +236,50 @@ class plotObject:
|
|
|
234
236
|
new_data_x_err = []
|
|
235
237
|
new_data_y_err = []
|
|
236
238
|
for i in range(len(kwargs['xerr'])):
|
|
237
|
-
|
|
238
|
-
|
|
239
|
+
if anim['sequential']:
|
|
240
|
+
_t = self.get_sequential_t(i,x,len(data_x),anim)
|
|
241
|
+
else:
|
|
242
|
+
_t = t
|
|
243
|
+
new_data_x_err.append(kwargs['xerr'][i] + (anim['new_x_err'][i] - kwargs['xerr'][i])*_t)
|
|
244
|
+
new_data_y_err.append(kwargs['yerr'][i] + (anim['new_y_err'][i] - kwargs['yerr'][i])*_t)
|
|
239
245
|
kwargs['xerr'] = new_data_x_err
|
|
240
246
|
kwargs['xerr'] = new_data_y_err
|
|
241
247
|
elif self.__class__.__name__ == 'fill_between':
|
|
242
248
|
new_y1 = []
|
|
243
249
|
new_y2 = []
|
|
244
250
|
for i in range(len(kwargs['y1'])):
|
|
245
|
-
|
|
246
|
-
|
|
251
|
+
if anim['sequential']:
|
|
252
|
+
_t = self.get_sequential_t(i,x,len(data_x),anim)
|
|
253
|
+
else:
|
|
254
|
+
_t = t
|
|
255
|
+
new_y1.append(kwargs['y1'][i] + (anim['new_y1'][i] - kwargs['y1'][i])*_t)
|
|
256
|
+
new_y2.append(kwargs['y2'][i] + (anim['new_y2'][i] - kwargs['y2'][i])*_t)
|
|
247
257
|
kwargs['y1'] = new_y1
|
|
248
258
|
kwargs['y2'] = new_y2
|
|
249
259
|
elif self.__class__.__name__ == 'fill_betweenx':
|
|
250
260
|
new_x1 = []
|
|
251
261
|
new_x2 = []
|
|
252
262
|
for i in range(len(kwargs['x1'])):
|
|
253
|
-
|
|
254
|
-
|
|
263
|
+
if anim['sequential']:
|
|
264
|
+
_t = self.get_sequential_t(i,x,len(data_x),anim)
|
|
265
|
+
else:
|
|
266
|
+
_t = t
|
|
267
|
+
new_x1.append(kwargs['x1'][i] + (anim['new_x1'][i] - kwargs['x1'][i])*_t)
|
|
268
|
+
new_x2.append(kwargs['x2'][i] + (anim['new_x2'][i] - kwargs['x2'][i])*_t)
|
|
255
269
|
kwargs['x1'] = new_x1
|
|
256
270
|
kwargs['x2'] = new_x2
|
|
271
|
+
elif self.__class__.__name__ == 'bar':
|
|
272
|
+
new_width = []
|
|
273
|
+
new_bottom = []
|
|
274
|
+
for i in range(len(data_x)):
|
|
275
|
+
if anim['sequential']:
|
|
276
|
+
_t = self.get_sequential_t(i,x,len(data_x),anim)
|
|
277
|
+
else:
|
|
278
|
+
_t = t
|
|
279
|
+
new_width.append(kwargs['width'][i] + (anim['new_width'][i] - kwargs['width'][i])*_t)
|
|
280
|
+
new_bottom.append(kwargs['bottom'][i] + (anim['new_bottom'][i] - kwargs['bottom'][i])*_t)
|
|
281
|
+
kwargs['width'] = new_width
|
|
282
|
+
kwargs['bottom'] = new_bottom
|
|
257
283
|
|
|
258
284
|
data_x = to_np_array(data_x)
|
|
259
285
|
data_y = to_np_array(data_y)
|
|
@@ -261,6 +287,19 @@ class plotObject:
|
|
|
261
287
|
if self.function is not None:
|
|
262
288
|
self.function(data_x,data_y,x,kwargs)
|
|
263
289
|
|
|
290
|
+
def get_sequential_t(self,i,x,size,anim):
|
|
291
|
+
delay = anim['delay'] + i/size*anim['duration']*(1-anim['subduration'])
|
|
292
|
+
duration = anim['duration']*anim['subduration']
|
|
293
|
+
if x < delay:
|
|
294
|
+
return 0
|
|
295
|
+
if x > delay + duration:
|
|
296
|
+
return 1
|
|
297
|
+
return self.get_t_from_x({
|
|
298
|
+
'delay':delay,
|
|
299
|
+
'duration':duration,
|
|
300
|
+
'easing':anim['easing'],
|
|
301
|
+
},x)
|
|
302
|
+
|
|
264
303
|
def initialize(self,timeline):
|
|
265
304
|
self.tl = timeline
|
|
266
305
|
if self.axis is None:
|
|
@@ -327,7 +366,7 @@ class plotObject:
|
|
|
327
366
|
self.compute_timings()
|
|
328
367
|
return self
|
|
329
368
|
|
|
330
|
-
def tween(self,property,start,end,duration,delay=0,easing=None,persistent=True):
|
|
369
|
+
def tween(self,property,start,end,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
331
370
|
"""Animate a change in a property of the plot object.
|
|
332
371
|
|
|
333
372
|
Parameters
|
|
@@ -344,10 +383,16 @@ class plotObject:
|
|
|
344
383
|
the number of frames after what the animation starts playing.
|
|
345
384
|
easing : callable, optional
|
|
346
385
|
the easing used for this animation. If None, a linear easing is applied.
|
|
386
|
+
persistent : bool, default=True
|
|
387
|
+
if True, the plot object will continue to be plotted after its last animation has played.
|
|
388
|
+
sequential : bool, default=False
|
|
389
|
+
if True, the morphing will happen gradually over the data length
|
|
390
|
+
subduration : float, default=0.1
|
|
391
|
+
if sequential=True, the fractional duration of animation of each data point, in units of total duration
|
|
347
392
|
"""
|
|
348
|
-
return self.tweens([property],[start],[end],duration,delay,easing,persistent=persistent)
|
|
393
|
+
return self.tweens([property],[start],[end],duration,delay,easing,persistent=persistent,sequential=sequential,subduration=subduration)
|
|
349
394
|
|
|
350
|
-
def tweens(self,properties,starts,ends,duration,delay=0,easing=None,persistent=True):
|
|
395
|
+
def tweens(self,properties,starts,ends,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
351
396
|
"""Animate multiple properties at once.
|
|
352
397
|
|
|
353
398
|
Parameters
|
|
@@ -364,6 +409,12 @@ class plotObject:
|
|
|
364
409
|
the number of frames after what the animation starts playing.
|
|
365
410
|
easing : callable, optional
|
|
366
411
|
the easing used for this animation. If None, a linear easing is applied.
|
|
412
|
+
persistent : bool, default=True
|
|
413
|
+
if True, the plot object will continue to be plotted after its last animation has played.
|
|
414
|
+
sequential : bool, default=False
|
|
415
|
+
if True, the morphing will happen gradually over the data length
|
|
416
|
+
subduration : float, default=0.1
|
|
417
|
+
if sequential=True, the fractional duration of animation of each data point, in units of total duration
|
|
367
418
|
"""
|
|
368
419
|
starts = [to_np_array(start) for start in starts]
|
|
369
420
|
ends = [to_np_array(end) for end in ends]
|
|
@@ -380,6 +431,8 @@ class plotObject:
|
|
|
380
431
|
'start':start,
|
|
381
432
|
'end':end,
|
|
382
433
|
'persistent':persistent,
|
|
434
|
+
'sequential':sequential,
|
|
435
|
+
'subduration':subduration,
|
|
383
436
|
'played':False
|
|
384
437
|
}
|
|
385
438
|
self.anims.append(new_anim)
|
|
@@ -436,16 +489,24 @@ class plotObject:
|
|
|
436
489
|
continue
|
|
437
490
|
if anim['name'] != 'tween':
|
|
438
491
|
continue
|
|
439
|
-
_x = min(x,anim['duration'] + anim['delay'])
|
|
440
|
-
t = self.get_t_from_x(anim,_x)
|
|
441
|
-
t = np.clip(t,0,1)
|
|
442
492
|
start = to_np_array(anim['start'])
|
|
443
493
|
end = to_np_array(anim['end'])
|
|
444
|
-
|
|
494
|
+
|
|
495
|
+
_x = min(x,anim['duration'] + anim['delay'])
|
|
496
|
+
|
|
497
|
+
if anim['sequential'] == False:
|
|
498
|
+
t = self.get_t_from_x(anim,_x)
|
|
499
|
+
t = np.clip(t,0,1)
|
|
500
|
+
current = start + (end - start)*t
|
|
501
|
+
else:
|
|
502
|
+
current = []
|
|
503
|
+
for i in range(len(self.x)):
|
|
504
|
+
_t = self.get_sequential_t(i,_x,len(self.x),anim)
|
|
505
|
+
current.append(start + (end - start)*_t)
|
|
445
506
|
kwargs[anim['property']] = current
|
|
446
507
|
return kwargs
|
|
447
508
|
|
|
448
|
-
def show(self,duration,delay=0,easing=None,persistent=True):
|
|
509
|
+
def show(self,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
449
510
|
"""Fade in plot objects.
|
|
450
511
|
|
|
451
512
|
This is a shorthand animation that fades in plot objects. It is equivalent to `tween('alpha',0,1)`.
|
|
@@ -460,10 +521,14 @@ class plotObject:
|
|
|
460
521
|
the easing used for this animation. If None, a linear easing is applied.
|
|
461
522
|
persistent : bool, default=True
|
|
462
523
|
if True, the plot object will continue to be plotted after its last animation has played.
|
|
524
|
+
sequential : bool, default=False
|
|
525
|
+
if True, the morphing will happen gradually over the data length
|
|
526
|
+
subduration : float, default=0.1
|
|
527
|
+
if sequential=True, the fractional duration of animation of each data point, in units of total duration
|
|
463
528
|
"""
|
|
464
|
-
return self.tween('alpha',start=0,end=1,duration=duration,delay=delay,easing=easing,persistent=persistent)
|
|
529
|
+
return self.tween('alpha',start=0,end=1,duration=duration,delay=delay,easing=easing,persistent=persistent,sequential=sequential,subduration=subduration)
|
|
465
530
|
|
|
466
|
-
def hide(self,duration,delay=0,easing=None,persistent=True):
|
|
531
|
+
def hide(self,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
467
532
|
"""Fade out plot objects.
|
|
468
533
|
|
|
469
534
|
This is a shorthand animation that fades out plot objects. It is equivalent to `tween('alpha',1,0)`.
|
|
@@ -478,8 +543,12 @@ class plotObject:
|
|
|
478
543
|
the easing used for this animation. If None, a linear easing is applied.
|
|
479
544
|
persistent : bool, default=True
|
|
480
545
|
if True, the plot object will continue to be plotted after its last animation has played.
|
|
546
|
+
sequential : bool, default=False
|
|
547
|
+
if True, the morphing will happen gradually over the data length
|
|
548
|
+
subduration : float, default=0.1
|
|
549
|
+
if sequential=True, the fractional duration of animation of each data point, in units of total duration
|
|
481
550
|
"""
|
|
482
|
-
return self.tween('alpha',start=1,end=0,duration=duration,delay=delay,easing=easing,persistent=persistent)
|
|
551
|
+
return self.tween('alpha',start=1,end=0,duration=duration,delay=delay,easing=easing,persistent=persistent,sequential=sequential,subduration=subduration)
|
|
483
552
|
|
|
484
553
|
def draw(self,duration,reverse=False,sort=None,delay=0,easing=None,persistent=True):
|
|
485
554
|
"""Animate the plot object by sequentially adding more points of the dataset.
|
|
@@ -705,7 +774,7 @@ class plotObject:
|
|
|
705
774
|
else:
|
|
706
775
|
o.set_transform(self.T + self.axis.transData)
|
|
707
776
|
|
|
708
|
-
def morph(self,new_x,new_y,duration,delay=0,easing=None,persistent=True):
|
|
777
|
+
def morph(self,new_x,new_y,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
709
778
|
"""Morph between the base dataset and a new dataset.
|
|
710
779
|
|
|
711
780
|
Parameters
|
|
@@ -722,6 +791,10 @@ class plotObject:
|
|
|
722
791
|
the easing used for this animation. If None, a linear easing is applied.
|
|
723
792
|
persistent : bool, default=True
|
|
724
793
|
if True, the plot object will continue to be plotted after its last animation has played.
|
|
794
|
+
sequential : bool, default=False
|
|
795
|
+
if True, the morphing will happen gradually over the data length
|
|
796
|
+
subduration : float, default=0.1
|
|
797
|
+
if sequential=True, the fractional duration of animation of each data point, in units of total duration
|
|
725
798
|
|
|
726
799
|
For plot objects that take 1D datasets (e.g. hist()), `morph()` only accepts `new_x`.
|
|
727
800
|
"""
|
|
@@ -740,6 +813,8 @@ class plotObject:
|
|
|
740
813
|
'new_x':new_x,
|
|
741
814
|
'new_y':new_y,
|
|
742
815
|
'persistent':persistent,
|
|
816
|
+
'sequential':sequential,
|
|
817
|
+
'subduration':subduration,
|
|
743
818
|
'played':False
|
|
744
819
|
})
|
|
745
820
|
self.compute_timings()
|
|
@@ -775,7 +850,9 @@ class plotObject:
|
|
|
775
850
|
def clean(self,x,clear_anims=True):
|
|
776
851
|
if self.obj is not None and self.base_color is None:
|
|
777
852
|
if isinstance(self.obj,(list,np.ndarray)):
|
|
778
|
-
self.base_color = self.obj[0].get_color()
|
|
853
|
+
self.base_color = self.obj[0].get_color()
|
|
854
|
+
elif isinstance(self.obj,mpl.container.BarContainer):
|
|
855
|
+
self.base_color = self.obj[0].get_fc()
|
|
779
856
|
elif hasattr(self.obj,'get_color'):
|
|
780
857
|
self.base_color = self.obj.get_color()
|
|
781
858
|
if 'color' not in self.kwargs and 'c' not in self.kwargs and self.base_color is not None:
|
|
@@ -789,7 +866,8 @@ class plotObject:
|
|
|
789
866
|
self.x = anim['new_x']
|
|
790
867
|
self.y = anim['new_y']
|
|
791
868
|
|
|
792
|
-
if x >= self.x_min-1 and x < self.x_max-1 and self.obj is not None:
|
|
869
|
+
#if x >= self.x_min-1 and x < self.x_max-1 and self.obj is not None:
|
|
870
|
+
if self.obj is not None:
|
|
793
871
|
if isinstance(self.obj,list):
|
|
794
872
|
for obj in self.obj:
|
|
795
873
|
try:
|
|
@@ -1005,6 +1083,94 @@ class axis_limits(plotObject):
|
|
|
1005
1083
|
ylim_top = anim['start_ylim'][1] + (anim['ylim'][1] - anim['start_ylim'][1])*t
|
|
1006
1084
|
self.axis.set_ylim(ylim_bottom,ylim_top)
|
|
1007
1085
|
|
|
1086
|
+
class axis_pos_and_size(plotObject):
|
|
1087
|
+
"""
|
|
1088
|
+
Resize the axis to a given position and size.
|
|
1089
|
+
|
|
1090
|
+
Parameters
|
|
1091
|
+
----------
|
|
1092
|
+
end_left : float
|
|
1093
|
+
Target left position
|
|
1094
|
+
end_bottom : float
|
|
1095
|
+
Target bottom position
|
|
1096
|
+
end_width : float
|
|
1097
|
+
Target width
|
|
1098
|
+
end_height : float
|
|
1099
|
+
Target height
|
|
1100
|
+
start_left = float
|
|
1101
|
+
Initial left position
|
|
1102
|
+
start_bottom : float
|
|
1103
|
+
Initial bottom position
|
|
1104
|
+
start_width : float
|
|
1105
|
+
Initial width
|
|
1106
|
+
start_height : float
|
|
1107
|
+
Initial height
|
|
1108
|
+
pos : array-like
|
|
1109
|
+
Target left and bottom position
|
|
1110
|
+
size : array-like
|
|
1111
|
+
Target width and height
|
|
1112
|
+
duration : float
|
|
1113
|
+
Duration of the animation
|
|
1114
|
+
delay : float, default=0
|
|
1115
|
+
Delay before starting
|
|
1116
|
+
easing : callable, optional
|
|
1117
|
+
Easing function
|
|
1118
|
+
axis : matplotlib.axes.Axes, optional
|
|
1119
|
+
Axis to plot on
|
|
1120
|
+
"""
|
|
1121
|
+
def __init__(self,duration,
|
|
1122
|
+
end_left=None,end_bottom=None,end_width=None,end_height=None,
|
|
1123
|
+
start_left=None,start_bottom=None,start_width=None,start_height=None,
|
|
1124
|
+
delay=0,easing=None,axis=None,*args,**kwargs):
|
|
1125
|
+
super().__init__(axis=axis,*args, **kwargs)
|
|
1126
|
+
self.anims = [{
|
|
1127
|
+
'name':'axis_move',
|
|
1128
|
+
'duration':duration,
|
|
1129
|
+
'delay':delay,
|
|
1130
|
+
'easing':easing,
|
|
1131
|
+
'persistent':True,
|
|
1132
|
+
'start':[start_left,start_bottom,start_width,start_height],
|
|
1133
|
+
'end':[end_left,end_bottom,end_width,end_height],
|
|
1134
|
+
'played':False
|
|
1135
|
+
}]
|
|
1136
|
+
self.compute_timings()
|
|
1137
|
+
|
|
1138
|
+
def init(self):
|
|
1139
|
+
left_i = self.axis.get_position().x0
|
|
1140
|
+
bottom_i = self.axis.get_position().y0
|
|
1141
|
+
width_i = self.axis.get_position().width
|
|
1142
|
+
height_i = self.axis.get_position().height
|
|
1143
|
+
if self.anims[0]['start'][0] is None:
|
|
1144
|
+
self.anims[0]['start'][0] = left_i
|
|
1145
|
+
if self.anims[0]['start'][1] is None:
|
|
1146
|
+
self.anims[0]['start'][1] = bottom_i
|
|
1147
|
+
if self.anims[0]['start'][2] is None:
|
|
1148
|
+
self.anims[0]['start'][2] = width_i
|
|
1149
|
+
if self.anims[0]['start'][3] is None:
|
|
1150
|
+
self.anims[0]['start'][3] = height_i
|
|
1151
|
+
if self.anims[0]['end'][0] is None:
|
|
1152
|
+
self.anims[0]['end'][0] = left_i
|
|
1153
|
+
if self.anims[0]['end'][1] is None:
|
|
1154
|
+
self.anims[0]['end'][1] = bottom_i
|
|
1155
|
+
if self.anims[0]['end'][2] is None:
|
|
1156
|
+
self.anims[0]['end'][2] = width_i
|
|
1157
|
+
if self.anims[0]['end'][3] is None:
|
|
1158
|
+
self.anims[0]['end'][3] = height_i
|
|
1159
|
+
|
|
1160
|
+
def function(self,data_x,data_y,x,kwargs):
|
|
1161
|
+
anim = self.anims[0]
|
|
1162
|
+
if x < anim['delay']:
|
|
1163
|
+
return
|
|
1164
|
+
_x = min(x,anim['duration'] + anim['delay']-1)
|
|
1165
|
+
t = self.get_t_from_x(anim,x)
|
|
1166
|
+
width = self.axis.get_xlim()[1]-self.axis.get_xlim()[0]
|
|
1167
|
+
height = self.axis.get_ylim()[1]-self.axis.get_ylim()[0]
|
|
1168
|
+
pos_x = anim['start'][0] + (anim['end'][0] - anim['start'][0])*t
|
|
1169
|
+
pos_y = anim['start'][1] + (anim['end'][1] - anim['start'][1])*t
|
|
1170
|
+
width = anim['start'][2] + (anim['end'][2] - anim['start'][2])*t
|
|
1171
|
+
height = anim['start'][3] + (anim['end'][3] - anim['start'][3])*t
|
|
1172
|
+
self.axis.set_position((pos_x,pos_y,width,height))
|
|
1173
|
+
|
|
1008
1174
|
class axis_move(plotObject):
|
|
1009
1175
|
"""
|
|
1010
1176
|
Move the center of the axis to a given position.
|
|
@@ -2113,6 +2279,7 @@ class fill_between(plotObject):
|
|
|
2113
2279
|
self.mpl_plot_type = plt.fill_between
|
|
2114
2280
|
y1 = to_np_array(y1).reshape(-1)
|
|
2115
2281
|
y2 = to_np_array(y2).reshape(-1)
|
|
2282
|
+
x = to_np_array(x)
|
|
2116
2283
|
if y1.size != x.size:
|
|
2117
2284
|
y1 = np.ones_like(x)*y1[0]
|
|
2118
2285
|
if y2.size != x.size:
|
|
@@ -2130,7 +2297,7 @@ class fill_between(plotObject):
|
|
|
2130
2297
|
self.kwargs['facecolor'] = self.base_color
|
|
2131
2298
|
super().clean(x,clear_anims)
|
|
2132
2299
|
|
|
2133
|
-
def morph(self,new_x,duration,new_y1=None,new_y2=None,delay=0,easing=None,persistent=True):
|
|
2300
|
+
def morph(self,new_x,duration,new_y1=None,new_y2=None,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
2134
2301
|
if new_y1 is None:
|
|
2135
2302
|
new_y1 = self.y1
|
|
2136
2303
|
if new_y2 is None:
|
|
@@ -2150,6 +2317,8 @@ class fill_between(plotObject):
|
|
|
2150
2317
|
'new_y1':new_y1,
|
|
2151
2318
|
'new_y2':new_y2,
|
|
2152
2319
|
'persistent':persistent,
|
|
2320
|
+
'sequential':sequential,
|
|
2321
|
+
'subduration':subduration,
|
|
2153
2322
|
'played':False
|
|
2154
2323
|
})
|
|
2155
2324
|
self.compute_timings()
|
|
@@ -2308,6 +2477,7 @@ class fill_betweenx(plotObject):
|
|
|
2308
2477
|
self.mpl_plot_type = plt.fill_betweenx
|
|
2309
2478
|
x1 = to_np_array(x1).reshape(-1)
|
|
2310
2479
|
x2 = to_np_array(x2).reshape(-1)
|
|
2480
|
+
y = to_np_array(y)
|
|
2311
2481
|
if x1.size != y.size:
|
|
2312
2482
|
x1 = np.ones_like(y)*x1[0]
|
|
2313
2483
|
if x2.size != y.size:
|
|
@@ -2325,7 +2495,7 @@ class fill_betweenx(plotObject):
|
|
|
2325
2495
|
self.kwargs['facecolor'] = self.base_color
|
|
2326
2496
|
super().clean(x,clear_anims)
|
|
2327
2497
|
|
|
2328
|
-
def morph(self,new_y,duration,new_x1=None,new_x2=None,delay=0,easing=None,persistent=True):
|
|
2498
|
+
def morph(self,new_y,duration,new_x1=None,new_x2=None,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
2329
2499
|
if new_x1 is None:
|
|
2330
2500
|
new_x1 = self.x1
|
|
2331
2501
|
if new_x2 is None:
|
|
@@ -2345,6 +2515,8 @@ class fill_betweenx(plotObject):
|
|
|
2345
2515
|
'new_x1':new_x1,
|
|
2346
2516
|
'new_x2':new_x2,
|
|
2347
2517
|
'persistent':persistent,
|
|
2518
|
+
'sequential':sequential,
|
|
2519
|
+
'subduration':subduration,
|
|
2348
2520
|
'played':False
|
|
2349
2521
|
})
|
|
2350
2522
|
self.compute_timings()
|
|
@@ -2778,7 +2950,7 @@ class errorbar(plotObject):
|
|
|
2778
2950
|
self.xerr = xerr
|
|
2779
2951
|
self.yerr = yerr
|
|
2780
2952
|
|
|
2781
|
-
def morph(self,new_x,new_y,duration,new_xerr=None,new_yerr=None,delay=0,easing=None,persistent=True):
|
|
2953
|
+
def morph(self,new_x,new_y,duration,new_xerr=None,new_yerr=None,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
2782
2954
|
if new_xerr is None:
|
|
2783
2955
|
new_xerr = self.xerr
|
|
2784
2956
|
if new_yerr is None:
|
|
@@ -2799,6 +2971,8 @@ class errorbar(plotObject):
|
|
|
2799
2971
|
'new_x_err':new_xerr,
|
|
2800
2972
|
'new_y_err':new_yerr,
|
|
2801
2973
|
'persistent':persistent,
|
|
2974
|
+
'sequential':sequential,
|
|
2975
|
+
'subduration':subduration,
|
|
2802
2976
|
'played':False
|
|
2803
2977
|
})
|
|
2804
2978
|
self.compute_timings()
|
|
@@ -3035,7 +3209,7 @@ class hist(plotObject):
|
|
|
3035
3209
|
self.kwargs['color'] = self.base_color
|
|
3036
3210
|
super().clean(x,clear_anims)
|
|
3037
3211
|
|
|
3038
|
-
def morph(self,new_x,duration,delay=0,easing=None,persistent=True,**kwargs):
|
|
3212
|
+
def morph(self,new_x,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1,**kwargs):
|
|
3039
3213
|
if isinstance(new_x,numbers.Number):
|
|
3040
3214
|
new_x = [new_x]
|
|
3041
3215
|
|
|
@@ -3047,6 +3221,8 @@ class hist(plotObject):
|
|
|
3047
3221
|
'new_x':new_x,
|
|
3048
3222
|
'new_y':np.zeros_like(self.y),
|
|
3049
3223
|
'persistent':persistent,
|
|
3224
|
+
'sequential':sequential,
|
|
3225
|
+
'subduration':subduration,
|
|
3050
3226
|
'played':False
|
|
3051
3227
|
})
|
|
3052
3228
|
self.compute_timings()
|
|
@@ -3530,7 +3706,7 @@ class contourf(plotObject):
|
|
|
3530
3706
|
self._y = np.array(self._y)
|
|
3531
3707
|
self.init_shape = z.shape
|
|
3532
3708
|
|
|
3533
|
-
def morph(self,new_z,duration,delay=0,easing=None,persistent=True,**kwargs):
|
|
3709
|
+
def morph(self,new_z,duration,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1,**kwargs):
|
|
3534
3710
|
self.anims.append({
|
|
3535
3711
|
'name':'morph',
|
|
3536
3712
|
'duration':duration,
|
|
@@ -3539,6 +3715,8 @@ class contourf(plotObject):
|
|
|
3539
3715
|
'new_x':np.ravel(new_z),
|
|
3540
3716
|
'new_y':np.ravel(new_z),
|
|
3541
3717
|
'persistent':persistent,
|
|
3718
|
+
'sequential':sequential,
|
|
3719
|
+
'subduration':subduration,
|
|
3542
3720
|
'played':False
|
|
3543
3721
|
})
|
|
3544
3722
|
self.compute_timings()
|
|
@@ -4390,4 +4568,194 @@ class Wedge(plotObject):
|
|
|
4390
4568
|
kwargs['theta2'] = kwargs['theta2'][0]
|
|
4391
4569
|
|
|
4392
4570
|
self.obj = mpl.patches.Wedge(**kwargs)
|
|
4393
|
-
self.axis.add_patch(self.obj)
|
|
4571
|
+
self.axis.add_patch(self.obj)
|
|
4572
|
+
|
|
4573
|
+
class bar(plotObject):
|
|
4574
|
+
"""
|
|
4575
|
+
Make a bar plot.
|
|
4576
|
+
|
|
4577
|
+
The bars are positioned at *x* with the given *align*ment. Their
|
|
4578
|
+
dimensions are given by *height* and *width*. The vertical baseline
|
|
4579
|
+
is *bottom* (default 0).
|
|
4580
|
+
|
|
4581
|
+
Many parameters can take either a single value applying to all bars
|
|
4582
|
+
or a sequence of values, one for each bar.
|
|
4583
|
+
|
|
4584
|
+
Parameters
|
|
4585
|
+
----------
|
|
4586
|
+
x : float or array-like
|
|
4587
|
+
The x coordinates of the bars. See also *align* for the
|
|
4588
|
+
alignment of the bars to the coordinates.
|
|
4589
|
+
|
|
4590
|
+
Bars are often used for categorical data, i.e. string labels below
|
|
4591
|
+
the bars. You can provide a list of strings directly to *x*.
|
|
4592
|
+
``bar(['A', 'B', 'C'], [1, 2, 3])`` is often a shorter and more
|
|
4593
|
+
convenient notation compared to
|
|
4594
|
+
``bar(range(3), [1, 2, 3], tick_label=['A', 'B', 'C'])``. They are
|
|
4595
|
+
equivalent as long as the names are unique. The explicit *tick_label*
|
|
4596
|
+
notation draws the names in the sequence given. However, when having
|
|
4597
|
+
duplicate values in categorical *x* data, these values map to the same
|
|
4598
|
+
numerical x coordinate, and hence the corresponding bars are drawn on
|
|
4599
|
+
top of each other.
|
|
4600
|
+
|
|
4601
|
+
height : float or array-like
|
|
4602
|
+
The height(s) of the bars.
|
|
4603
|
+
|
|
4604
|
+
Note that if *bottom* has units (e.g. datetime), *height* should be in
|
|
4605
|
+
units that are a difference from the value of *bottom* (e.g. timedelta).
|
|
4606
|
+
|
|
4607
|
+
width : float or array-like, default: 0.8
|
|
4608
|
+
The width(s) of the bars.
|
|
4609
|
+
|
|
4610
|
+
Note that if *x* has units (e.g. datetime), then *width* should be in
|
|
4611
|
+
units that are a difference (e.g. timedelta) around the *x* values.
|
|
4612
|
+
|
|
4613
|
+
bottom : float or array-like, default: 0
|
|
4614
|
+
The y coordinate(s) of the bottom side(s) of the bars.
|
|
4615
|
+
|
|
4616
|
+
Note that if *bottom* has units, then the y-axis will get a Locator and
|
|
4617
|
+
Formatter appropriate for the units (e.g. dates, or categorical).
|
|
4618
|
+
|
|
4619
|
+
align : {'center', 'edge'}, default: 'center'
|
|
4620
|
+
Alignment of the bars to the *x* coordinates:
|
|
4621
|
+
|
|
4622
|
+
- 'center': Center the base on the *x* positions.
|
|
4623
|
+
- 'edge': Align the left edges of the bars with the *x* positions.
|
|
4624
|
+
|
|
4625
|
+
To align the bars on the right edge pass a negative *width* and
|
|
4626
|
+
``align='edge'``.
|
|
4627
|
+
|
|
4628
|
+
Returns
|
|
4629
|
+
-------
|
|
4630
|
+
`.BarContainer`
|
|
4631
|
+
Container with all the bars and optionally errorbars.
|
|
4632
|
+
|
|
4633
|
+
Other Parameters
|
|
4634
|
+
----------------
|
|
4635
|
+
color : :mpltype:`color` or list of :mpltype:`color`, optional
|
|
4636
|
+
The colors of the bar faces. This is an alias for *facecolor*.
|
|
4637
|
+
If both are given, *facecolor* takes precedence.
|
|
4638
|
+
|
|
4639
|
+
facecolor : :mpltype:`color` or list of :mpltype:`color`, optional
|
|
4640
|
+
The colors of the bar faces.
|
|
4641
|
+
If both *color* and *facecolor are given, *facecolor* takes precedence.
|
|
4642
|
+
|
|
4643
|
+
edgecolor : :mpltype:`color` or list of :mpltype:`color`, optional
|
|
4644
|
+
The colors of the bar edges.
|
|
4645
|
+
|
|
4646
|
+
linewidth : float or array-like, optional
|
|
4647
|
+
Width of the bar edge(s). If 0, don't draw edges.
|
|
4648
|
+
|
|
4649
|
+
tick_label : str or list of str, optional
|
|
4650
|
+
The tick labels of the bars.
|
|
4651
|
+
Default: None (Use default numeric labels.)
|
|
4652
|
+
|
|
4653
|
+
label : str or list of str, optional
|
|
4654
|
+
A single label is attached to the resulting `.BarContainer` as a
|
|
4655
|
+
label for the whole dataset.
|
|
4656
|
+
If a list is provided, it must be the same length as *x* and
|
|
4657
|
+
labels the individual bars. Repeated labels are not de-duplicated
|
|
4658
|
+
and will cause repeated label entries, so this is best used when
|
|
4659
|
+
bars also differ in style (e.g., by passing a list to *color*.)
|
|
4660
|
+
|
|
4661
|
+
xerr, yerr : float or array-like of shape(N,) or shape(2, N), optional
|
|
4662
|
+
If not *None*, add horizontal / vertical errorbars to the bar tips.
|
|
4663
|
+
The values are +/- sizes relative to the data:
|
|
4664
|
+
|
|
4665
|
+
- scalar: symmetric +/- values for all bars
|
|
4666
|
+
- shape(N,): symmetric +/- values for each bar
|
|
4667
|
+
- shape(2, N): Separate - and + values for each bar. First row
|
|
4668
|
+
contains the lower errors, the second row contains the upper
|
|
4669
|
+
errors.
|
|
4670
|
+
- *None*: No errorbar. (Default)
|
|
4671
|
+
|
|
4672
|
+
See :doc:`/gallery/statistics/errorbar_features` for an example on
|
|
4673
|
+
the usage of *xerr* and *yerr*.
|
|
4674
|
+
|
|
4675
|
+
ecolor : :mpltype:`color` or list of :mpltype:`color`, default: 'black'
|
|
4676
|
+
The line color of the errorbars.
|
|
4677
|
+
|
|
4678
|
+
capsize : float, default: :rc:`errorbar.capsize`
|
|
4679
|
+
The length of the error bar caps in points.
|
|
4680
|
+
|
|
4681
|
+
error_kw : dict, optional
|
|
4682
|
+
Dictionary of keyword arguments to be passed to the
|
|
4683
|
+
`~.Axes.errorbar` method. Values of *ecolor* or *capsize* defined
|
|
4684
|
+
here take precedence over the independent keyword arguments.
|
|
4685
|
+
|
|
4686
|
+
log : bool, default: False
|
|
4687
|
+
If *True*, set the y-axis to be log scale.
|
|
4688
|
+
|
|
4689
|
+
data : indexable object, optional
|
|
4690
|
+
DATA_PARAMETER_PLACEHOLDER
|
|
4691
|
+
|
|
4692
|
+
**kwargs : `.Rectangle` properties
|
|
4693
|
+
|
|
4694
|
+
%(Rectangle:kwdoc)s
|
|
4695
|
+
|
|
4696
|
+
See Also
|
|
4697
|
+
--------
|
|
4698
|
+
barh : Plot a horizontal bar plot.
|
|
4699
|
+
|
|
4700
|
+
Notes
|
|
4701
|
+
-----
|
|
4702
|
+
Stacked bars can be achieved by passing individual *bottom* values per
|
|
4703
|
+
bar. See :doc:`/gallery/lines_bars_and_markers/bar_stacked`.
|
|
4704
|
+
"""
|
|
4705
|
+
def __init__(self,x,height,width=0.8,bottom=0,easing=None,axis=None, *args, **kwargs):
|
|
4706
|
+
#self.mpl_obj_type = mpl.container.BarContainer
|
|
4707
|
+
self.mpl_obj_type = mpl.patches.Rectangle
|
|
4708
|
+
self.mpl_plot_type = plt.bar
|
|
4709
|
+
if np.ravel(width).size == 1:
|
|
4710
|
+
width = np.ones_like(x)*width
|
|
4711
|
+
if np.ravel(height).size == 1:
|
|
4712
|
+
height = np.ones_like(x)*height
|
|
4713
|
+
if np.ravel(bottom).size == 1:
|
|
4714
|
+
bottom = np.ones_like(x)*bottom
|
|
4715
|
+
kwargs['width'] = width
|
|
4716
|
+
kwargs['bottom'] = bottom
|
|
4717
|
+
super().__init__(easing=easing,axis=axis,*args, **kwargs)
|
|
4718
|
+
self.x = x
|
|
4719
|
+
self.y = height
|
|
4720
|
+
|
|
4721
|
+
def morph(self,new_x,new_height,duration,new_width=None,new_bottom=None,delay=0,easing=None,persistent=True,sequential=False,subduration=0.1):
|
|
4722
|
+
if new_width is None:
|
|
4723
|
+
new_width = self.kwargs['width']
|
|
4724
|
+
elif np.ravel(new_width).size == 1:
|
|
4725
|
+
new_width = np.ones_like(new_x)*new_width
|
|
4726
|
+
if new_bottom is None:
|
|
4727
|
+
new_bottom = self.kwargs['bottom']
|
|
4728
|
+
elif np.ravel(new_bottom).size == 1:
|
|
4729
|
+
new_bottom = np.ones_like(new_x)*new_bottom
|
|
4730
|
+
if isinstance(new_x,numbers.Number):
|
|
4731
|
+
new_x = [new_x]
|
|
4732
|
+
new_height = [new_height]
|
|
4733
|
+
new_width = [new_width]
|
|
4734
|
+
new_bottom = [new_bottom]
|
|
4735
|
+
|
|
4736
|
+
self.anims.append({
|
|
4737
|
+
'name':'morph',
|
|
4738
|
+
'duration':duration,
|
|
4739
|
+
'delay':delay,
|
|
4740
|
+
'easing':easing,
|
|
4741
|
+
'new_x':new_x,
|
|
4742
|
+
'new_y':new_height,
|
|
4743
|
+
'new_width':new_width,
|
|
4744
|
+
'new_bottom':new_bottom,
|
|
4745
|
+
'persistent':persistent,
|
|
4746
|
+
'sequential':sequential,
|
|
4747
|
+
'subduration':subduration,
|
|
4748
|
+
'played':False
|
|
4749
|
+
})
|
|
4750
|
+
self.compute_timings()
|
|
4751
|
+
return self
|
|
4752
|
+
|
|
4753
|
+
def function(self,data_x,data_y,x,kwargs):
|
|
4754
|
+
#This is a hack because when plotting a bar with empty data, no children are stored
|
|
4755
|
+
#but the color cycler still triggers, so a color is assigned by we can't know what
|
|
4756
|
+
#it is. So instead we plot a single bar with height 0 and get its color.
|
|
4757
|
+
if len(data_x) == 0:
|
|
4758
|
+
data_x = [0]
|
|
4759
|
+
data_y = [0]
|
|
4760
|
+
obj = self.axis.bar(data_x,data_y,**kwargs)
|
|
4761
|
+
self.obj = obj
|
|
@@ -385,15 +385,17 @@ class Timeline:
|
|
|
385
385
|
f.write(self.timeline_str)
|
|
386
386
|
sequence_fn = self.name + '/' + self.name + '.txt'
|
|
387
387
|
|
|
388
|
+
ffmpeg_flags = '-hide_banner -loglevel error -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2"'
|
|
389
|
+
|
|
388
390
|
if '.mov' in video_fn:
|
|
389
391
|
if multialpha:
|
|
390
|
-
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -vf premultiply=inplace=1 -c:v prores_ks -profile:v 4 -pix_fmt yuva444p10le
|
|
392
|
+
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -vf premultiply=inplace=1 -c:v prores_ks -profile:v 4 -pix_fmt yuva444p10le {} {}'.format(sequence_fn,ffmpeg_flags,video_fn)
|
|
391
393
|
else:
|
|
392
|
-
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -c:v prores -pix_fmt yuva444p10le
|
|
394
|
+
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -c:v prores -pix_fmt yuva444p10le {} {}'.format(sequence_fn,ffmpeg_flags,video_fn)
|
|
393
395
|
elif is_gif:
|
|
394
|
-
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -lavfi "split[s0][s1];[s0]palettegen=reserve_transparent=1:stats_mode=diff[p];[s1][p]paletteuse=dither=sierra2_4a:alpha_threshold=128" -gifflags -offsetting -loop 0
|
|
396
|
+
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -lavfi "split[s0][s1];[s0]palettegen=reserve_transparent=1:stats_mode=diff[p];[s1][p]paletteuse=dither=sierra2_4a:alpha_threshold=128" -gifflags -offsetting -loop 0 {}'.format(sequence_fn,ffmpeg_flags,video_fn)
|
|
395
397
|
else:
|
|
396
|
-
command = ffmpeg_path + ' -f concat -safe 0 -i {} -c:v libx264 -pix_fmt yuv420p -c:a aac -movflags +faststart
|
|
398
|
+
command = ffmpeg_path + ' -f concat -safe 0 -i {} -y -c:v libx264 -pix_fmt yuv420p -c:a aac -movflags +faststart {} {}'.format(sequence_fn,ffmpeg_flags,video_fn)
|
|
397
399
|
subprocess.run(shlex.split(command))
|
|
398
400
|
if clean:
|
|
399
401
|
shutil.rmtree(self.name)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.5.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|