diplotocus 0.6.0__tar.gz → 0.6.4__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.6.0 → diplotocus-0.6.4}/PKG-INFO +1 -1
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/GUI.ipynb +1 -1
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/animations.ipynb +93 -3
- diplotocus-0.6.4/src/diplotocus/_version.py +1 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/animations.py +127 -88
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/PKG-INFO +1 -1
- diplotocus-0.6.0/src/diplotocus/_version.py +0 -1
- {diplotocus-0.6.0 → diplotocus-0.6.4}/.gitattributes +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/.gitignore +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/.readthedocs.yaml +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/LICENSE +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/Makefile +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/_static/force-light.css +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/_static/force-light.js +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/make.bat +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/requirements.txt +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/Web_GUI.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/button.svg +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/demo.mp4 +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/favicon.ico +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/force-light.css +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/force-light.js +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/logo.mp4 +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/logo.svg +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/api/core.rst +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/api/index.rst +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/conf.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/index.rst +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/easings.ipynb +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/index.ipynb +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/installation.ipynb +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/plot_objects.ipynb +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/quick-start.ipynb +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/timeline.ipynb +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/logo.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/pyproject.toml +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/readme.md +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/setup.cfg +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/GUI.html +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/__init__.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/app.js +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/server.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/bg.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Draw.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Morph.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Rotate.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Scale.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Sequence.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Translate.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Tween.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_default.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/favicon.ico +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/logo_bg.png +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/style.css +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/__init__.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/core.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/easings.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/SOURCES.txt +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/dependency_links.txt +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/requires.txt +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/top_level.txt +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test10.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test2.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test3.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test4.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test5.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test6.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test7.py +0 -0
- {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test8.py +0 -0
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"\n",
|
|
14
14
|
"```{warning}\n",
|
|
15
15
|
"\n",
|
|
16
|
-
"The GUI might not be as stable as the python interface. Feel free to report any issues you
|
|
16
|
+
"The GUI might not be as stable as the python interface and is currently lacking recently added features. Feel free to report any issues you encounter or features you want to see be added in priority.\n",
|
|
17
17
|
"```\n",
|
|
18
18
|
"\n",
|
|
19
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",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"cell_type": "code",
|
|
42
|
-
"execution_count":
|
|
42
|
+
"execution_count": 2,
|
|
43
43
|
"id": "8292940a",
|
|
44
44
|
"metadata": {},
|
|
45
45
|
"outputs": [
|
|
46
46
|
{
|
|
47
47
|
"data": {
|
|
48
48
|
"application/vnd.jupyter.widget-view+json": {
|
|
49
|
-
"model_id": "
|
|
49
|
+
"model_id": "2eaf909a7fe44442baed97f7da7c03ed",
|
|
50
50
|
"version_major": 2,
|
|
51
51
|
"version_minor": 0
|
|
52
52
|
},
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"text/html": [
|
|
75
75
|
"\n",
|
|
76
76
|
" <video width=\"640\" height=\"360\" autoplay loop muted playsinline>\n",
|
|
77
|
-
" <source src=\"../_static/animations/anim_translate.mp4?randId=
|
|
77
|
+
" <source src=\"../_static/animations/anim_translate.mp4?randId=322\" type=\"video/mp4\">\n",
|
|
78
78
|
" </video>\n",
|
|
79
79
|
" "
|
|
80
80
|
],
|
|
@@ -503,6 +503,84 @@
|
|
|
503
503
|
"tl.save_video('../_static/animations/anim_morph.mp4')"
|
|
504
504
|
]
|
|
505
505
|
},
|
|
506
|
+
{
|
|
507
|
+
"cell_type": "markdown",
|
|
508
|
+
"id": "543e2a0d",
|
|
509
|
+
"metadata": {},
|
|
510
|
+
"source": [
|
|
511
|
+
"### Subdraw\n",
|
|
512
|
+
"\n",
|
|
513
|
+
"```{eval-rst}\n",
|
|
514
|
+
".. automethod:: diplotocus.animations.plotObject.subdraw\n",
|
|
515
|
+
" :noindex:\n",
|
|
516
|
+
"```"
|
|
517
|
+
]
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
"cell_type": "code",
|
|
521
|
+
"execution_count": 1,
|
|
522
|
+
"id": "46a8632c",
|
|
523
|
+
"metadata": {},
|
|
524
|
+
"outputs": [
|
|
525
|
+
{
|
|
526
|
+
"data": {
|
|
527
|
+
"application/vnd.jupyter.widget-view+json": {
|
|
528
|
+
"model_id": "9bfc289f510045839c333aefaa210fdc",
|
|
529
|
+
"version_major": 2,
|
|
530
|
+
"version_minor": 0
|
|
531
|
+
},
|
|
532
|
+
"text/plain": [
|
|
533
|
+
" 0%| | 0/60 [00:00<?, ?it/s]"
|
|
534
|
+
]
|
|
535
|
+
},
|
|
536
|
+
"metadata": {},
|
|
537
|
+
"output_type": "display_data"
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
"data": {
|
|
541
|
+
"text/markdown": [
|
|
542
|
+
"Saved video ../_static/animations/anim_subdraw.mp4"
|
|
543
|
+
],
|
|
544
|
+
"text/plain": [
|
|
545
|
+
"<IPython.core.display.Markdown object>"
|
|
546
|
+
]
|
|
547
|
+
},
|
|
548
|
+
"metadata": {},
|
|
549
|
+
"output_type": "display_data"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
"data": {
|
|
553
|
+
"text/html": [
|
|
554
|
+
"\n",
|
|
555
|
+
" <video width=\"640\" height=\"360\" autoplay loop muted playsinline>\n",
|
|
556
|
+
" <source src=\"../_static/animations/anim_subdraw.mp4?randId=2913\" type=\"video/mp4\">\n",
|
|
557
|
+
" </video>\n",
|
|
558
|
+
" "
|
|
559
|
+
],
|
|
560
|
+
"text/plain": [
|
|
561
|
+
"<IPython.core.display.HTML object>"
|
|
562
|
+
]
|
|
563
|
+
},
|
|
564
|
+
"metadata": {},
|
|
565
|
+
"output_type": "display_data"
|
|
566
|
+
}
|
|
567
|
+
],
|
|
568
|
+
"source": [
|
|
569
|
+
"import diplotocus as dpl\n",
|
|
570
|
+
"import numpy as np\n",
|
|
571
|
+
"\n",
|
|
572
|
+
"x = np.linspace(0,2*np.pi,60)\n",
|
|
573
|
+
"y = np.cos(x)\n",
|
|
574
|
+
"\n",
|
|
575
|
+
"tl = dpl.Timeline(xlim=(-1,7),ylim=(-2,2))\n",
|
|
576
|
+
"\n",
|
|
577
|
+
"p = dpl.plot(x=x,y=y)\n",
|
|
578
|
+
"p.subdraw(start_index=0,end_index=5,duration=60)\n",
|
|
579
|
+
"\n",
|
|
580
|
+
"tl.animate(p)\n",
|
|
581
|
+
"tl.save_video('../_static/animations/anim_subdraw.mp4')"
|
|
582
|
+
]
|
|
583
|
+
},
|
|
506
584
|
{
|
|
507
585
|
"cell_type": "markdown",
|
|
508
586
|
"id": "7d3c9b15",
|
|
@@ -513,6 +591,12 @@
|
|
|
513
591
|
"```{eval-rst}\n",
|
|
514
592
|
".. automethod:: diplotocus.animations.plotObject.draw\n",
|
|
515
593
|
" :noindex:\n",
|
|
594
|
+
"```\n",
|
|
595
|
+
"\n",
|
|
596
|
+
"```{note}\n",
|
|
597
|
+
"\n",
|
|
598
|
+
"`draw()` is a shorthand animation that subdraws every datapoint from 0 to the current_frame (or reversed if `reverse=True`). It is equivalent to `subdraw('start',0)`.\n",
|
|
599
|
+
"\n",
|
|
516
600
|
"```"
|
|
517
601
|
]
|
|
518
602
|
},
|
|
@@ -591,6 +675,12 @@
|
|
|
591
675
|
"```{eval-rst}\n",
|
|
592
676
|
".. automethod:: diplotocus.animations.plotObject.sequence\n",
|
|
593
677
|
" :noindex:\n",
|
|
678
|
+
"```\n",
|
|
679
|
+
"\n",
|
|
680
|
+
"```{note}\n",
|
|
681
|
+
"\n",
|
|
682
|
+
"`sequence()` is a shorthand animation that only subdraws the datapoint at the current frame index (or reversed if `reverse=True`). It is equivalent to `subdraw(0,0)`.\n",
|
|
683
|
+
"\n",
|
|
594
684
|
"```"
|
|
595
685
|
]
|
|
596
686
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.4"
|
|
@@ -27,6 +27,8 @@ def dealias(mpl_obj,kwargs):
|
|
|
27
27
|
return kwargs
|
|
28
28
|
|
|
29
29
|
def to_np_array(obj):
|
|
30
|
+
if type(obj) == np.ndarray:
|
|
31
|
+
return obj
|
|
30
32
|
obj = np.array(obj)
|
|
31
33
|
if obj.ndim == 0:
|
|
32
34
|
obj = np.ravel(obj)
|
|
@@ -155,56 +157,33 @@ class plotObject:
|
|
|
155
157
|
data_x = to_np_array(self.x)
|
|
156
158
|
data_y = to_np_array(self.y)
|
|
157
159
|
|
|
158
|
-
|
|
159
|
-
for anim in self.anims:
|
|
160
|
-
if anim['name'] != 'sequence':
|
|
161
|
-
continue
|
|
162
|
-
if self.x is None:
|
|
163
|
-
continue
|
|
164
|
-
if x < anim['delay'] or x > anim['delay'] + anim['duration']:
|
|
165
|
-
continue
|
|
166
|
-
t = self.get_t_from_x(anim,x)
|
|
160
|
+
i_min,i_max = -1,-1
|
|
167
161
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
_i = max(min(round(t*len(data_x)),len(data_x)-1),0)
|
|
173
|
-
data_x = data_x[_i]
|
|
174
|
-
data_y = data_y[_i]
|
|
175
|
-
kwargs = self.resize_kwargs(kwargs,_i)
|
|
162
|
+
if 'alpha' in kwargs:
|
|
163
|
+
alpha = to_np_array(kwargs['alpha'])
|
|
164
|
+
if np.sum(alpha) == 0:
|
|
165
|
+
kwargs['alpha'] = 1
|
|
176
166
|
|
|
177
|
-
#Second pass to cut points if drawing or erasing
|
|
178
|
-
i_max = -1
|
|
179
167
|
for anim in self.anims:
|
|
180
|
-
if anim['name'] != '
|
|
168
|
+
if anim['name'] != 'sample':
|
|
181
169
|
continue
|
|
182
170
|
if self.x is None:
|
|
183
171
|
continue
|
|
184
172
|
if x < anim['delay'] or x > anim['delay'] + anim['duration']:
|
|
185
173
|
continue
|
|
186
|
-
t = self.get_t_from_x(anim,x)
|
|
187
|
-
|
|
188
|
-
if 'alpha' in kwargs:
|
|
189
|
-
alpha = to_np_array(kwargs['alpha'])
|
|
190
|
-
if np.sum(alpha) == 0:
|
|
191
|
-
kwargs['alpha'] = 1
|
|
192
174
|
|
|
193
|
-
|
|
194
|
-
i_max = max(round((1-t)*len(data_x)),0)
|
|
195
|
-
else:
|
|
196
|
-
i_max = min(round(t*len(data_x)),len(data_x))
|
|
175
|
+
i_min,i_max = self.get_i_min_i_max_sample(anim,x,len(data_x))
|
|
197
176
|
break
|
|
198
177
|
|
|
199
|
-
if i_max
|
|
200
|
-
data_x = data_x[:i_max]
|
|
178
|
+
if i_min >= 0 and i_max >= 0:
|
|
179
|
+
data_x = data_x[i_min:i_max]
|
|
201
180
|
if data_y is not None:
|
|
202
|
-
data_y = data_y[:i_max]
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
kwargs = self.resize_kwargs(kwargs,
|
|
181
|
+
data_y = data_y[i_min:i_max]
|
|
182
|
+
if data_x.shape[0] == 1:
|
|
183
|
+
data_x = data_x.reshape(-1)
|
|
184
|
+
if data_y.shape[0] == 1:
|
|
185
|
+
data_y = data_y.reshape(-1)
|
|
186
|
+
kwargs = self.resize_kwargs(kwargs,list(range(i_min,i_max)))
|
|
208
187
|
|
|
209
188
|
#Third pass to morph
|
|
210
189
|
for anim in self.anims:
|
|
@@ -287,6 +266,26 @@ class plotObject:
|
|
|
287
266
|
if self.function is not None:
|
|
288
267
|
self.function(data_x,data_y,x,kwargs)
|
|
289
268
|
|
|
269
|
+
def get_i_min_i_max_sample(self,anim,x,len_data):
|
|
270
|
+
if anim['reverse']:
|
|
271
|
+
_x = anim['duration'] - (x - anim['delay'])
|
|
272
|
+
else:
|
|
273
|
+
_x = x - anim['delay']
|
|
274
|
+
if type(anim['min']) == str and anim['min'] == 'start':
|
|
275
|
+
i_min = 0
|
|
276
|
+
else:
|
|
277
|
+
i_min = int((_x + anim['min'])/anim['duration']*len_data)
|
|
278
|
+
i_min = max(i_min,0)
|
|
279
|
+
if type(anim['max']) == str and anim['max'] == 'end':
|
|
280
|
+
i_max = len_data - 1
|
|
281
|
+
else:
|
|
282
|
+
if anim['max'] == anim['min']:
|
|
283
|
+
i_max = i_min + 1
|
|
284
|
+
else:
|
|
285
|
+
i_max = int((_x + anim['max'])/anim['duration']*len_data)
|
|
286
|
+
i_max = min(i_max,len_data-1)
|
|
287
|
+
return i_min,i_max
|
|
288
|
+
|
|
290
289
|
def get_sequential_t(self,i,x,size,anim):
|
|
291
290
|
delay = anim['delay'] + i/size*anim['duration']*(1-anim['subduration'])
|
|
292
291
|
duration = anim['duration']*anim['subduration']
|
|
@@ -568,28 +567,7 @@ class plotObject:
|
|
|
568
567
|
persistent : bool, default=True
|
|
569
568
|
if True, the plot object will continue to be plotted after its last animation has played.
|
|
570
569
|
"""
|
|
571
|
-
|
|
572
|
-
if sort[-1] == 'x':
|
|
573
|
-
idx = np.argsort(self.x)
|
|
574
|
-
else:
|
|
575
|
-
idx = np.argsort(self.y)
|
|
576
|
-
if sort[0] == '-':
|
|
577
|
-
idx = idx[::-1]
|
|
578
|
-
self.x = self.x[idx]
|
|
579
|
-
self.y = self.y[idx]
|
|
580
|
-
self.kwargs = self.resize_kwargs(self.kwargs,idx)
|
|
581
|
-
|
|
582
|
-
self.anims.append({
|
|
583
|
-
'name':'draw',
|
|
584
|
-
'duration':duration,
|
|
585
|
-
'delay':delay,
|
|
586
|
-
'easing':easing,
|
|
587
|
-
'reverse':reverse,
|
|
588
|
-
'persistent':persistent,
|
|
589
|
-
'played':False
|
|
590
|
-
})
|
|
591
|
-
self.compute_timings()
|
|
592
|
-
return self
|
|
570
|
+
return self.subdraw('start',0,duration,reverse,sort,delay,easing,persistent)
|
|
593
571
|
|
|
594
572
|
def scale(self,start_scale,end_scale,duration,center=None,delay=0,easing=None,persistent=True):
|
|
595
573
|
"""Scale a plot object from one size to another.
|
|
@@ -820,13 +798,17 @@ class plotObject:
|
|
|
820
798
|
self.compute_timings()
|
|
821
799
|
return self
|
|
822
800
|
|
|
823
|
-
def sequence(self,duration,delay=0,easing=None,persistent=True):
|
|
801
|
+
def sequence(self,duration,reverse=False,sort=None,delay=0,easing=None,persistent=True):
|
|
824
802
|
"""Plot one datapoint or row of the dataset per frame.
|
|
825
803
|
|
|
826
804
|
Parameters
|
|
827
805
|
----------
|
|
828
806
|
duration : float
|
|
829
807
|
the number of frames the animation runs from.
|
|
808
|
+
reverse : bool, default=False
|
|
809
|
+
if True, removes points sequentially instead of adding points.
|
|
810
|
+
sort : str, default=None
|
|
811
|
+
sorts the data to draw it in order. Can be 'x','-x','y','-y' to sort in ascending or descending order.
|
|
830
812
|
delay : float, default=0
|
|
831
813
|
the number of frames after what the animation starts playing.
|
|
832
814
|
easing : callable, optional
|
|
@@ -836,11 +818,44 @@ class plotObject:
|
|
|
836
818
|
|
|
837
819
|
If the dataset is 1-dimensional, this plots a single datapoint per frame, if 2D, it will plot one row per frame. This animation can be used if you have a predefined list of datapoints you want to animate frame-by-frame.
|
|
838
820
|
"""
|
|
821
|
+
return self.subdraw(0,0,duration,reverse,sort,delay,easing,persistent)
|
|
822
|
+
|
|
823
|
+
def subdraw(self,start_index,end_index,duration,reverse=False,sort=None,delay=0,easing=None,persistent=True):
|
|
824
|
+
"""Plot multiple datapoints or rows of the dataset per frame, in the range
|
|
825
|
+
[current_frame_index - start_index;current_frame_index + end_index]
|
|
826
|
+
|
|
827
|
+
Parameters
|
|
828
|
+
----------
|
|
829
|
+
start_index : int or str
|
|
830
|
+
start index around the current frame index for the datapoints to plot. If str, can be 'start' to force
|
|
831
|
+
the range to start at 0 or 'end' to force it to end at the last datapoint.
|
|
832
|
+
end_index : int or str
|
|
833
|
+
end index around the current frame index for the datapoints to plot. If str, can be 'start' to force
|
|
834
|
+
the range to start at 0 or 'end' to force it to end at the last datapoint.
|
|
835
|
+
duration : float
|
|
836
|
+
the number of frames the animation runs from.
|
|
837
|
+
reverse : bool, default=False
|
|
838
|
+
if True, removes points sequentially instead of adding points.
|
|
839
|
+
sort : str, default=None
|
|
840
|
+
sorts the data to draw it in order. Can be 'x','-x','y','-y' to sort in ascending or descending order.
|
|
841
|
+
delay : float, default=0
|
|
842
|
+
the number of frames after what the animation starts playing.
|
|
843
|
+
easing : callable, optional
|
|
844
|
+
the easing used for this animation. If None, a linear easing is applied.
|
|
845
|
+
persistent : bool, default=True
|
|
846
|
+
if True, the plot object will continue to be plotted after its last animation has played.
|
|
847
|
+
"""
|
|
848
|
+
if sort is not None:
|
|
849
|
+
self.sort_data(sort)
|
|
850
|
+
|
|
839
851
|
self.anims.append({
|
|
840
|
-
'name':'
|
|
852
|
+
'name':'sample',
|
|
853
|
+
'min':start_index,
|
|
854
|
+
'max':end_index,
|
|
841
855
|
'duration':duration,
|
|
842
856
|
'delay':delay,
|
|
843
857
|
'easing':easing,
|
|
858
|
+
'reverse':reverse,
|
|
844
859
|
'persistent':persistent,
|
|
845
860
|
'played':False
|
|
846
861
|
})
|
|
@@ -851,6 +866,8 @@ class plotObject:
|
|
|
851
866
|
if self.obj is not None and self.base_color is None:
|
|
852
867
|
if isinstance(self.obj,(list,np.ndarray)):
|
|
853
868
|
self.base_color = self.obj[0].get_color()
|
|
869
|
+
elif isinstance(self.obj,mpl.patches.Polygon):
|
|
870
|
+
self.base_color = self.obj.get_fc()
|
|
854
871
|
elif isinstance(self.obj,mpl.container.BarContainer):
|
|
855
872
|
self.base_color = self.obj[0].get_fc()
|
|
856
873
|
elif hasattr(self.obj,'get_color'):
|
|
@@ -933,23 +950,8 @@ class plotObject:
|
|
|
933
950
|
bbox = mpl.transforms.Bbox.union(bboxes)
|
|
934
951
|
cx = (bbox.x0 + bbox.x1) / 2
|
|
935
952
|
cy = (bbox.y0 + bbox.y1) / 2
|
|
936
|
-
elif self.mpl_obj_type == mpl.
|
|
937
|
-
|
|
938
|
-
if len(offsets) == 0:
|
|
939
|
-
cx,cy = 0,0
|
|
940
|
-
else:
|
|
941
|
-
cx = np.mean(offsets[:, 0])
|
|
942
|
-
cy = np.mean(offsets[:, 1])
|
|
943
|
-
elif self.mpl_obj_type == mpl.collections.QuadMesh:
|
|
944
|
-
coords = self.obj.get_coordinates()
|
|
945
|
-
x0 = np.nanmin(coords[..., 0])
|
|
946
|
-
x1 = np.nanmax(coords[..., 0])
|
|
947
|
-
y0 = np.nanmin(coords[..., 1])
|
|
948
|
-
y1 = np.nanmax(coords[..., 1])
|
|
949
|
-
|
|
950
|
-
cx = 0.5 * (x0 + x1)
|
|
951
|
-
cy = 0.5 * (y0 + y1)
|
|
952
|
-
elif self.mpl_obj_type == mpl.patches.Rectangle:
|
|
953
|
+
elif self.mpl_obj_type == mpl.patches.Rectangle and \
|
|
954
|
+
(self.mpl_plot_type == plt.hist or self.mpl_plot_type == plt.bar):
|
|
953
955
|
rects = self.obj.patches
|
|
954
956
|
if isinstance(rects, list) and len(rects) > 0:
|
|
955
957
|
centers_x = []
|
|
@@ -966,15 +968,51 @@ class plotObject:
|
|
|
966
968
|
bbox = self.obj.get_bbox()
|
|
967
969
|
cx = (bbox.x0 + bbox.x1) / 2
|
|
968
970
|
cy = (bbox.y0 + bbox.y1) / 2
|
|
971
|
+
elif self.mpl_obj_type == mpl.patches.Polygon or \
|
|
972
|
+
self.mpl_obj_type == mpl.patches.Arrow or \
|
|
973
|
+
self.mpl_obj_type == mpl.patches.Rectangle or \
|
|
974
|
+
self.mpl_obj_type == mpl.patches.RegularPolygon or \
|
|
975
|
+
self.mpl_obj_type == mpl.patches.Wedge or \
|
|
976
|
+
self.mpl_obj_type == mpl.patches.FancyArrow:
|
|
977
|
+
bbox = self.obj.get_extents()
|
|
978
|
+
cx = (bbox.x0 + bbox.x1) / 2
|
|
979
|
+
cy = (bbox.y0 + bbox.y1) / 2
|
|
980
|
+
elif self.mpl_obj_type == mpl.collections.Collection:
|
|
981
|
+
offsets = self.obj.get_offsets()
|
|
982
|
+
if len(offsets) == 0:
|
|
983
|
+
cx,cy = 0,0
|
|
984
|
+
else:
|
|
985
|
+
cx = np.mean(offsets[:, 0])
|
|
986
|
+
cy = np.mean(offsets[:, 1])
|
|
987
|
+
elif self.mpl_obj_type == mpl.collections.QuadMesh:
|
|
988
|
+
coords = self.obj.get_coordinates()
|
|
989
|
+
x0 = np.nanmin(coords[..., 0])
|
|
990
|
+
x1 = np.nanmax(coords[..., 0])
|
|
991
|
+
y0 = np.nanmin(coords[..., 1])
|
|
992
|
+
y1 = np.nanmax(coords[..., 1])
|
|
993
|
+
|
|
994
|
+
cx = 0.5 * (x0 + x1)
|
|
995
|
+
cy = 0.5 * (y0 + y1)
|
|
969
996
|
elif self.mpl_obj_type == mpl.collections.FillBetweenPolyCollection:
|
|
970
997
|
bboxes = [p.get_extents() for p in self.obj.get_paths() if p.vertices.size]
|
|
971
998
|
bbox = mpl.transforms.Bbox.union(bboxes)
|
|
972
999
|
cx = 0.5 * (bbox.x0 + bbox.x1)
|
|
973
1000
|
cy = 0.5 * (bbox.y0 + bbox.y1)
|
|
974
|
-
elif self.mpl_obj_type == mpl.patches.Circle:
|
|
1001
|
+
elif self.mpl_obj_type == mpl.patches.Circle or self.mpl_obj_type == mpl.patches.Ellipse:
|
|
975
1002
|
cx,cy = self.obj.get_center()
|
|
976
1003
|
return (cx,cy)
|
|
977
1004
|
|
|
1005
|
+
def sort_data(self,sort):
|
|
1006
|
+
if sort[-1] == 'x':
|
|
1007
|
+
idx = np.argsort(self.x)
|
|
1008
|
+
else:
|
|
1009
|
+
idx = np.argsort(self.y)
|
|
1010
|
+
if sort[0] == '-':
|
|
1011
|
+
idx = idx[::-1]
|
|
1012
|
+
self.x = self.x[idx]
|
|
1013
|
+
self.y = self.y[idx]
|
|
1014
|
+
self.kwargs = self.resize_kwargs(self.kwargs,idx)
|
|
1015
|
+
|
|
978
1016
|
class axis_zoom(plotObject):
|
|
979
1017
|
"""
|
|
980
1018
|
Zooms into the axis given a zoom value.
|
|
@@ -2038,7 +2076,6 @@ class plot(plotObject):
|
|
|
2038
2076
|
self.mpl_obj_type = mpl.lines.Line2D
|
|
2039
2077
|
self.mpl_plot_type = plt.plot
|
|
2040
2078
|
super().__init__(easing=easing,axis=axis,*args, **kwargs)
|
|
2041
|
-
|
|
2042
2079
|
self.x = to_np_array(x)
|
|
2043
2080
|
self.y = to_np_array(y)
|
|
2044
2081
|
if self.x.size != self.y.size:
|
|
@@ -4298,7 +4335,7 @@ class Arrow(plotObject):
|
|
|
4298
4335
|
properties.
|
|
4299
4336
|
"""
|
|
4300
4337
|
def __init__(self,x,y,dx,dy,width=1.0,easing=None,axis=None, *args, **kwargs):
|
|
4301
|
-
self.mpl_obj_type = mpl.patches.
|
|
4338
|
+
self.mpl_obj_type = mpl.patches.Arrow
|
|
4302
4339
|
kwargs['x'] = x
|
|
4303
4340
|
kwargs['y'] = y
|
|
4304
4341
|
kwargs['dx'] = dx
|
|
@@ -4331,7 +4368,7 @@ class Ellipse(plotObject):
|
|
|
4331
4368
|
Rotation in degrees anti-clockwise.
|
|
4332
4369
|
"""
|
|
4333
4370
|
def __init__(self,xy,width,height,angle=0,easing=None,axis=None, *args, **kwargs):
|
|
4334
|
-
self.mpl_obj_type = mpl.patches.
|
|
4371
|
+
self.mpl_obj_type = mpl.patches.Ellipse
|
|
4335
4372
|
kwargs['xy'] = xy
|
|
4336
4373
|
kwargs['width'] = width
|
|
4337
4374
|
kwargs['height'] = height
|
|
@@ -4386,7 +4423,7 @@ class FancyArrow(plotObject):
|
|
|
4386
4423
|
length_includes_head=False,head_width=None,head_length=None,
|
|
4387
4424
|
shape='full',overhang=0,head_starts_at_zero=False,
|
|
4388
4425
|
easing=None,axis=None, *args, **kwargs):
|
|
4389
|
-
self.mpl_obj_type = mpl.patches.
|
|
4426
|
+
self.mpl_obj_type = mpl.patches.FancyArrow
|
|
4390
4427
|
kwargs['x'] = x
|
|
4391
4428
|
kwargs['y'] = y
|
|
4392
4429
|
kwargs['dx'] = dx
|
|
@@ -4429,7 +4466,7 @@ class Polygon(plotObject):
|
|
|
4429
4466
|
points).
|
|
4430
4467
|
"""
|
|
4431
4468
|
def __init__(self,xy,closed=True,easing=None,axis=None, *args, **kwargs):
|
|
4432
|
-
self.mpl_obj_type = mpl.patches.
|
|
4469
|
+
self.mpl_obj_type = mpl.patches.Polygon
|
|
4433
4470
|
kwargs['xy'] = xy
|
|
4434
4471
|
kwargs['closed'] = closed
|
|
4435
4472
|
super().__init__(easing=easing,axis=axis,*args, **kwargs)
|
|
@@ -4477,7 +4514,7 @@ class Rectangle(plotObject):
|
|
|
4477
4514
|
coordinate.
|
|
4478
4515
|
"""
|
|
4479
4516
|
def __init__(self,xy,width,height,angle=0.0,rotation_point='xy',easing=None,axis=None, *args, **kwargs):
|
|
4480
|
-
self.mpl_obj_type = mpl.patches.
|
|
4517
|
+
self.mpl_obj_type = mpl.patches.Rectangle
|
|
4481
4518
|
kwargs['xy'] = xy
|
|
4482
4519
|
kwargs['width'] = width
|
|
4483
4520
|
kwargs['height'] = height
|
|
@@ -4518,7 +4555,7 @@ class RegularPolygon(plotObject):
|
|
|
4518
4555
|
The polygon rotation angle (in radians).
|
|
4519
4556
|
"""
|
|
4520
4557
|
def __init__(self,xy,numVertices,radius=5,orientation=0,easing=None,axis=None, *args, **kwargs):
|
|
4521
|
-
self.mpl_obj_type = mpl.patches.
|
|
4558
|
+
self.mpl_obj_type = mpl.patches.RegularPolygon
|
|
4522
4559
|
kwargs['xy'] = xy
|
|
4523
4560
|
kwargs['numVertices'] = numVertices
|
|
4524
4561
|
kwargs['radius'] = radius
|
|
@@ -4548,7 +4585,7 @@ class Wedge(plotObject):
|
|
|
4548
4585
|
to outer radius *r*.
|
|
4549
4586
|
"""
|
|
4550
4587
|
def __init__(self,center,r,theta1,theta2,width=None,easing=None,axis=None, *args, **kwargs):
|
|
4551
|
-
self.mpl_obj_type = mpl.patches.
|
|
4588
|
+
self.mpl_obj_type = mpl.patches.Wedge
|
|
4552
4589
|
kwargs['center'] = center
|
|
4553
4590
|
kwargs['r'] = r
|
|
4554
4591
|
kwargs['theta1'] = theta1
|
|
@@ -4757,5 +4794,7 @@ class bar(plotObject):
|
|
|
4757
4794
|
if len(data_x) == 0:
|
|
4758
4795
|
data_x = [0]
|
|
4759
4796
|
data_y = [0]
|
|
4797
|
+
kwargs['width'] = [0]
|
|
4798
|
+
kwargs['bottom'] = [0]
|
|
4760
4799
|
obj = self.axis.bar(data_x,data_y,**kwargs)
|
|
4761
4800
|
self.obj = obj
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.6.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|