diplotocus 0.5.1__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.1 → diplotocus-0.6.0}/PKG-INFO +1 -1
- {diplotocus-0.5.1 → 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.1 → diplotocus-0.6.0}/src/diplotocus/animations.py +306 -30
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/core.py +6 -4
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus.egg-info/PKG-INFO +1 -1
- diplotocus-0.5.1/src/diplotocus/_version.py +0 -1
- {diplotocus-0.5.1 → diplotocus-0.6.0}/.gitattributes +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/.gitignore +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/.readthedocs.yaml +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/LICENSE +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/Makefile +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/_static/force-light.css +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/_static/force-light.js +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/make.bat +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/requirements.txt +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/Web_GUI.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/button.svg +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/demo.mp4 +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/favicon.ico +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/force-light.css +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/force-light.js +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/logo.mp4 +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/_static/logo.svg +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/api/core.rst +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/api/index.rst +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/conf.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/index.rst +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/GUI.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/animations.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/easings.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/index.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/installation.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/quick-start.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/docs/source/notebooks/timeline.ipynb +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/logo.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/pyproject.toml +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/readme.md +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/setup.cfg +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/GUI.html +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/__init__.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/app.js +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/server.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/bg.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Draw.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Morph.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Rotate.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Scale.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Sequence.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Translate.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_Tween.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/btn/btn_bg_default.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/favicon.ico +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/src/logo_bg.png +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/GUI/style.css +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/__init__.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus/easings.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus.egg-info/SOURCES.txt +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus.egg-info/dependency_links.txt +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus.egg-info/requires.txt +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/src/diplotocus.egg-info/top_level.txt +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test10.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test2.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test3.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test4.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test5.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test6.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test7.py +0 -0
- {diplotocus-0.5.1 → diplotocus-0.6.0}/tests/test8.py +0 -0
|
@@ -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:
|
|
@@ -1094,7 +1171,6 @@ class axis_pos_and_size(plotObject):
|
|
|
1094
1171
|
height = anim['start'][3] + (anim['end'][3] - anim['start'][3])*t
|
|
1095
1172
|
self.axis.set_position((pos_x,pos_y,width,height))
|
|
1096
1173
|
|
|
1097
|
-
|
|
1098
1174
|
class axis_move(plotObject):
|
|
1099
1175
|
"""
|
|
1100
1176
|
Move the center of the axis to a given position.
|
|
@@ -2221,7 +2297,7 @@ class fill_between(plotObject):
|
|
|
2221
2297
|
self.kwargs['facecolor'] = self.base_color
|
|
2222
2298
|
super().clean(x,clear_anims)
|
|
2223
2299
|
|
|
2224
|
-
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):
|
|
2225
2301
|
if new_y1 is None:
|
|
2226
2302
|
new_y1 = self.y1
|
|
2227
2303
|
if new_y2 is None:
|
|
@@ -2241,6 +2317,8 @@ class fill_between(plotObject):
|
|
|
2241
2317
|
'new_y1':new_y1,
|
|
2242
2318
|
'new_y2':new_y2,
|
|
2243
2319
|
'persistent':persistent,
|
|
2320
|
+
'sequential':sequential,
|
|
2321
|
+
'subduration':subduration,
|
|
2244
2322
|
'played':False
|
|
2245
2323
|
})
|
|
2246
2324
|
self.compute_timings()
|
|
@@ -2417,7 +2495,7 @@ class fill_betweenx(plotObject):
|
|
|
2417
2495
|
self.kwargs['facecolor'] = self.base_color
|
|
2418
2496
|
super().clean(x,clear_anims)
|
|
2419
2497
|
|
|
2420
|
-
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):
|
|
2421
2499
|
if new_x1 is None:
|
|
2422
2500
|
new_x1 = self.x1
|
|
2423
2501
|
if new_x2 is None:
|
|
@@ -2437,6 +2515,8 @@ class fill_betweenx(plotObject):
|
|
|
2437
2515
|
'new_x1':new_x1,
|
|
2438
2516
|
'new_x2':new_x2,
|
|
2439
2517
|
'persistent':persistent,
|
|
2518
|
+
'sequential':sequential,
|
|
2519
|
+
'subduration':subduration,
|
|
2440
2520
|
'played':False
|
|
2441
2521
|
})
|
|
2442
2522
|
self.compute_timings()
|
|
@@ -2870,7 +2950,7 @@ class errorbar(plotObject):
|
|
|
2870
2950
|
self.xerr = xerr
|
|
2871
2951
|
self.yerr = yerr
|
|
2872
2952
|
|
|
2873
|
-
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):
|
|
2874
2954
|
if new_xerr is None:
|
|
2875
2955
|
new_xerr = self.xerr
|
|
2876
2956
|
if new_yerr is None:
|
|
@@ -2891,6 +2971,8 @@ class errorbar(plotObject):
|
|
|
2891
2971
|
'new_x_err':new_xerr,
|
|
2892
2972
|
'new_y_err':new_yerr,
|
|
2893
2973
|
'persistent':persistent,
|
|
2974
|
+
'sequential':sequential,
|
|
2975
|
+
'subduration':subduration,
|
|
2894
2976
|
'played':False
|
|
2895
2977
|
})
|
|
2896
2978
|
self.compute_timings()
|
|
@@ -3127,7 +3209,7 @@ class hist(plotObject):
|
|
|
3127
3209
|
self.kwargs['color'] = self.base_color
|
|
3128
3210
|
super().clean(x,clear_anims)
|
|
3129
3211
|
|
|
3130
|
-
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):
|
|
3131
3213
|
if isinstance(new_x,numbers.Number):
|
|
3132
3214
|
new_x = [new_x]
|
|
3133
3215
|
|
|
@@ -3139,6 +3221,8 @@ class hist(plotObject):
|
|
|
3139
3221
|
'new_x':new_x,
|
|
3140
3222
|
'new_y':np.zeros_like(self.y),
|
|
3141
3223
|
'persistent':persistent,
|
|
3224
|
+
'sequential':sequential,
|
|
3225
|
+
'subduration':subduration,
|
|
3142
3226
|
'played':False
|
|
3143
3227
|
})
|
|
3144
3228
|
self.compute_timings()
|
|
@@ -3622,7 +3706,7 @@ class contourf(plotObject):
|
|
|
3622
3706
|
self._y = np.array(self._y)
|
|
3623
3707
|
self.init_shape = z.shape
|
|
3624
3708
|
|
|
3625
|
-
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):
|
|
3626
3710
|
self.anims.append({
|
|
3627
3711
|
'name':'morph',
|
|
3628
3712
|
'duration':duration,
|
|
@@ -3631,6 +3715,8 @@ class contourf(plotObject):
|
|
|
3631
3715
|
'new_x':np.ravel(new_z),
|
|
3632
3716
|
'new_y':np.ravel(new_z),
|
|
3633
3717
|
'persistent':persistent,
|
|
3718
|
+
'sequential':sequential,
|
|
3719
|
+
'subduration':subduration,
|
|
3634
3720
|
'played':False
|
|
3635
3721
|
})
|
|
3636
3722
|
self.compute_timings()
|
|
@@ -4482,4 +4568,194 @@ class Wedge(plotObject):
|
|
|
4482
4568
|
kwargs['theta2'] = kwargs['theta2'][0]
|
|
4483
4569
|
|
|
4484
4570
|
self.obj = mpl.patches.Wedge(**kwargs)
|
|
4485
|
-
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.1"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|