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.
Files changed (70) hide show
  1. {diplotocus-0.6.0 → diplotocus-0.6.4}/PKG-INFO +1 -1
  2. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/GUI.ipynb +1 -1
  3. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/animations.ipynb +93 -3
  4. diplotocus-0.6.4/src/diplotocus/_version.py +1 -0
  5. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/animations.py +127 -88
  6. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/PKG-INFO +1 -1
  7. diplotocus-0.6.0/src/diplotocus/_version.py +0 -1
  8. {diplotocus-0.6.0 → diplotocus-0.6.4}/.gitattributes +0 -0
  9. {diplotocus-0.6.0 → diplotocus-0.6.4}/.gitignore +0 -0
  10. {diplotocus-0.6.0 → diplotocus-0.6.4}/.readthedocs.yaml +0 -0
  11. {diplotocus-0.6.0 → diplotocus-0.6.4}/LICENSE +0 -0
  12. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/Makefile +0 -0
  13. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/_static/force-light.css +0 -0
  14. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/_static/force-light.js +0 -0
  15. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/make.bat +0 -0
  16. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/requirements.txt +0 -0
  17. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/Web_GUI.png +0 -0
  18. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/button.svg +0 -0
  19. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/demo.mp4 +0 -0
  20. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/favicon.ico +0 -0
  21. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/force-light.css +0 -0
  22. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/force-light.js +0 -0
  23. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/logo.mp4 +0 -0
  24. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/_static/logo.svg +0 -0
  25. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/api/core.rst +0 -0
  26. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/api/index.rst +0 -0
  27. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/conf.py +0 -0
  28. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/index.rst +0 -0
  29. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/easings.ipynb +0 -0
  30. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/index.ipynb +0 -0
  31. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/installation.ipynb +0 -0
  32. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/plot_objects.ipynb +0 -0
  33. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/quick-start.ipynb +0 -0
  34. {diplotocus-0.6.0 → diplotocus-0.6.4}/docs/source/notebooks/timeline.ipynb +0 -0
  35. {diplotocus-0.6.0 → diplotocus-0.6.4}/logo.png +0 -0
  36. {diplotocus-0.6.0 → diplotocus-0.6.4}/pyproject.toml +0 -0
  37. {diplotocus-0.6.0 → diplotocus-0.6.4}/readme.md +0 -0
  38. {diplotocus-0.6.0 → diplotocus-0.6.4}/setup.cfg +0 -0
  39. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/GUI.html +0 -0
  40. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/__init__.py +0 -0
  41. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/app.js +0 -0
  42. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/server.py +0 -0
  43. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/bg.png +0 -0
  44. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Draw.png +0 -0
  45. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Morph.png +0 -0
  46. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Rotate.png +0 -0
  47. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Scale.png +0 -0
  48. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Sequence.png +0 -0
  49. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Translate.png +0 -0
  50. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_Tween.png +0 -0
  51. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/btn/btn_bg_default.png +0 -0
  52. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/favicon.ico +0 -0
  53. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/src/logo_bg.png +0 -0
  54. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/GUI/style.css +0 -0
  55. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/__init__.py +0 -0
  56. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/core.py +0 -0
  57. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus/easings.py +0 -0
  58. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/SOURCES.txt +0 -0
  59. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/dependency_links.txt +0 -0
  60. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/requires.txt +0 -0
  61. {diplotocus-0.6.0 → diplotocus-0.6.4}/src/diplotocus.egg-info/top_level.txt +0 -0
  62. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test.py +0 -0
  63. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test10.py +0 -0
  64. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test2.py +0 -0
  65. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test3.py +0 -0
  66. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test4.py +0 -0
  67. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test5.py +0 -0
  68. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test6.py +0 -0
  69. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test7.py +0 -0
  70. {diplotocus-0.6.0 → diplotocus-0.6.4}/tests/test8.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diplotocus
3
- Version: 0.6.0
3
+ Version: 0.6.4
4
4
  Summary: A python package to generate animations of matplotlib objects.
5
5
  Author-email: Tristan Boin <tristan.boin@obspm.fr>
6
6
  License-Expression: MIT
@@ -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 encounters.\n",
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": null,
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": "e81b7a3356ae4f16a27fae17363df670",
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=449\" type=\"video/mp4\">\n",
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
- #First pass to get frame if sequencing
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
- if len(data_x.shape) == 1:
169
- data_x = data_x.reshape((-1,1))
170
- data_y = data_y.reshape((-1,1))
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'] != 'draw':
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
- if anim['reverse']:
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 > 0:
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
- kwargs = self.resize_kwargs(kwargs,list(range(i_max)))
204
- elif i_max == 0:
205
- data_x = []
206
- data_y = []
207
- kwargs = self.resize_kwargs(kwargs,None)
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
- if sort is not None:
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':'sequence',
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.collections.Collection:
937
- offsets = self.obj.get_offsets()
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.Circle
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.Circle
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.Circle
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.Circle
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.Circle
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.Circle
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.Circle
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diplotocus
3
- Version: 0.6.0
3
+ Version: 0.6.4
4
4
  Summary: A python package to generate animations of matplotlib objects.
5
5
  Author-email: Tristan Boin <tristan.boin@obspm.fr>
6
6
  License-Expression: MIT
@@ -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