lavavu 1.9.9__tar.gz → 1.9.10__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 (154) hide show
  1. {lavavu-1.9.9 → lavavu-1.9.10}/Makefile +2 -1
  2. {lavavu-1.9.9/lavavu.egg-info → lavavu-1.9.10}/PKG-INFO +3 -2
  3. {lavavu-1.9.9 → lavavu-1.9.10}/README.md +1 -1
  4. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/LavaVuPython.py +5 -3
  5. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/webview.html +1 -1
  6. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/lavavu.py +94 -41
  7. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/tracers.py +19 -24
  8. {lavavu-1.9.9 → lavavu-1.9.10/lavavu.egg-info}/PKG-INFO +3 -2
  9. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu.egg-info/SOURCES.txt +0 -1
  10. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu.egg-info/requires.txt +1 -0
  11. {lavavu-1.9.9 → lavavu-1.9.10}/requirements.txt +1 -0
  12. {lavavu-1.9.9 → lavavu-1.9.10}/setup.py +2 -2
  13. {lavavu-1.9.9 → lavavu-1.9.10}/src/LavaVuPython_wrap.cxx +142 -139
  14. {lavavu-1.9.9 → lavavu-1.9.10}/src/OpenGLViewer.cpp +4 -8
  15. {lavavu-1.9.9 → lavavu-1.9.10}/src/OpenGLViewer.h +1 -0
  16. lavavu-1.9.10/src/version.cpp +2 -0
  17. lavavu-1.9.9/lavavu/osmesa/LavaVuPython.py +0 -561
  18. lavavu-1.9.9/src/version.cpp +0 -2
  19. {lavavu-1.9.9 → lavavu-1.9.10}/LICENSE.md +0 -0
  20. {lavavu-1.9.9 → lavavu-1.9.10}/MANIFEST.in +0 -0
  21. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/__init__.py +0 -0
  22. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/__main__.py +0 -0
  23. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/amalgamate.py +0 -0
  24. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/aserver.py +0 -0
  25. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/control.py +0 -0
  26. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/convert.py +0 -0
  27. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/dict.json +0 -0
  28. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/font.bin +0 -0
  29. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/LavaVu-amalgamated.css +0 -0
  30. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/OK-min.js +0 -0
  31. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/baseviewer.js +0 -0
  32. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/control.css +0 -0
  33. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/control.js +0 -0
  34. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/dat-gui-light-theme.css +0 -0
  35. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/dat.gui.min.js +0 -0
  36. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/draw.js +0 -0
  37. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/drawbox.js +0 -0
  38. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/emscripten-template.js +0 -0
  39. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/emscripten.css +0 -0
  40. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/favicon.ico +0 -0
  41. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/gl-matrix-min.js +0 -0
  42. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/gui.css +0 -0
  43. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/menu.js +0 -0
  44. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/server.js +0 -0
  45. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/stats.min.js +0 -0
  46. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/styles.css +0 -0
  47. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/html/webview-template.html +0 -0
  48. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/osmesa/__init__.py +0 -0
  49. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/points.py +0 -0
  50. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/server.py +0 -0
  51. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/default.frag +0 -0
  52. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/default.vert +0 -0
  53. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/fontShader.frag +0 -0
  54. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/fontShader.vert +0 -0
  55. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/lineShader.frag +0 -0
  56. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/lineShader.vert +0 -0
  57. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/pointShader.frag +0 -0
  58. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/pointShader.vert +0 -0
  59. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/triShader.frag +0 -0
  60. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/triShader.vert +0 -0
  61. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/volumeShader.frag +0 -0
  62. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/shaders/volumeShader.vert +0 -0
  63. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu/vutils.py +0 -0
  64. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu.egg-info/dependency_links.txt +0 -0
  65. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu.egg-info/entry_points.txt +0 -0
  66. {lavavu-1.9.9 → lavavu-1.9.10}/lavavu.egg-info/top_level.txt +0 -0
  67. {lavavu-1.9.9 → lavavu-1.9.10}/pyproject.toml +0 -0
  68. {lavavu-1.9.9 → lavavu-1.9.10}/setup.cfg +0 -0
  69. {lavavu-1.9.9 → lavavu-1.9.10}/src/ApplicationInterface.h +0 -0
  70. {lavavu-1.9.9 → lavavu-1.9.10}/src/ColourMap.cpp +0 -0
  71. {lavavu-1.9.9 → lavavu-1.9.10}/src/ColourMap.h +0 -0
  72. {lavavu-1.9.9 → lavavu-1.9.10}/src/Colours.cpp +0 -0
  73. {lavavu-1.9.9 → lavavu-1.9.10}/src/Colours.h +0 -0
  74. {lavavu-1.9.9 → lavavu-1.9.10}/src/Contour.cpp +0 -0
  75. {lavavu-1.9.9 → lavavu-1.9.10}/src/Contour.h +0 -0
  76. {lavavu-1.9.9 → lavavu-1.9.10}/src/DrawingObject.cpp +0 -0
  77. {lavavu-1.9.9 → lavavu-1.9.10}/src/DrawingObject.h +0 -0
  78. {lavavu-1.9.9 → lavavu-1.9.10}/src/Extensions.cpp +0 -0
  79. {lavavu-1.9.9 → lavavu-1.9.10}/src/Extensions.h +0 -0
  80. {lavavu-1.9.9 → lavavu-1.9.10}/src/FontLine.h +0 -0
  81. {lavavu-1.9.9 → lavavu-1.9.10}/src/FontSans.h +0 -0
  82. {lavavu-1.9.9 → lavavu-1.9.10}/src/GLUtils.cpp +0 -0
  83. {lavavu-1.9.9 → lavavu-1.9.10}/src/GLUtils.h +0 -0
  84. {lavavu-1.9.9 → lavavu-1.9.10}/src/Geometry.cpp +0 -0
  85. {lavavu-1.9.9 → lavavu-1.9.10}/src/Geometry.h +0 -0
  86. {lavavu-1.9.9 → lavavu-1.9.10}/src/GraphicsUtil.cpp +0 -0
  87. {lavavu-1.9.9 → lavavu-1.9.10}/src/GraphicsUtil.h +0 -0
  88. {lavavu-1.9.9 → lavavu-1.9.10}/src/Include.h +0 -0
  89. {lavavu-1.9.9 → lavavu-1.9.10}/src/InputInterface.h +0 -0
  90. {lavavu-1.9.9 → lavavu-1.9.10}/src/InteractiveViewer.cpp +0 -0
  91. {lavavu-1.9.9 → lavavu-1.9.10}/src/IsoSurface.cpp +0 -0
  92. {lavavu-1.9.9 → lavavu-1.9.10}/src/IsoSurface.h +0 -0
  93. {lavavu-1.9.9 → lavavu-1.9.10}/src/LavaVu.cpp +0 -0
  94. {lavavu-1.9.9 → lavavu-1.9.10}/src/LavaVu.h +0 -0
  95. {lavavu-1.9.9 → lavavu-1.9.10}/src/Lines.cpp +0 -0
  96. {lavavu-1.9.9 → lavavu-1.9.10}/src/LinesSorted.cpp +0 -0
  97. {lavavu-1.9.9 → lavavu-1.9.10}/src/Links.cpp +0 -0
  98. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/CGLViewer.cpp +0 -0
  99. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/CGLViewer.h +0 -0
  100. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/CocoaViewer.h +0 -0
  101. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/CocoaViewer.mm +0 -0
  102. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/EGLViewer.cpp +0 -0
  103. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/EGLViewer.h +0 -0
  104. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/GLFWViewer.cpp +0 -0
  105. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/GLFWViewer.h +0 -0
  106. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/OSMesaViewer.cpp +0 -0
  107. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/OSMesaViewer.h +0 -0
  108. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/X11Viewer.cpp +0 -0
  109. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/X11Viewer.h +0 -0
  110. {lavavu-1.9.9 → lavavu-1.9.10}/src/Main/main.cpp +0 -0
  111. {lavavu-1.9.9 → lavavu-1.9.10}/src/Model.cpp +0 -0
  112. {lavavu-1.9.9 → lavavu-1.9.10}/src/Model.h +0 -0
  113. {lavavu-1.9.9 → lavavu-1.9.10}/src/OutputInterface.h +0 -0
  114. {lavavu-1.9.9 → lavavu-1.9.10}/src/Points.cpp +0 -0
  115. {lavavu-1.9.9 → lavavu-1.9.10}/src/QuadSurfaces.cpp +0 -0
  116. {lavavu-1.9.9 → lavavu-1.9.10}/src/RenderContext.cpp +0 -0
  117. {lavavu-1.9.9 → lavavu-1.9.10}/src/RenderContext.h +0 -0
  118. {lavavu-1.9.9 → lavavu-1.9.10}/src/Session.cpp +0 -0
  119. {lavavu-1.9.9 → lavavu-1.9.10}/src/Session.h +0 -0
  120. {lavavu-1.9.9 → lavavu-1.9.10}/src/Shaders.cpp +0 -0
  121. {lavavu-1.9.9 → lavavu-1.9.10}/src/Shaders.h +0 -0
  122. {lavavu-1.9.9 → lavavu-1.9.10}/src/Shapes.cpp +0 -0
  123. {lavavu-1.9.9 → lavavu-1.9.10}/src/TimeStep.h +0 -0
  124. {lavavu-1.9.9 → lavavu-1.9.10}/src/Tracers.cpp +0 -0
  125. {lavavu-1.9.9 → lavavu-1.9.10}/src/TriSurfaces.cpp +0 -0
  126. {lavavu-1.9.9 → lavavu-1.9.10}/src/Triangles.cpp +0 -0
  127. {lavavu-1.9.9 → lavavu-1.9.10}/src/Util.cpp +0 -0
  128. {lavavu-1.9.9 → lavavu-1.9.10}/src/Util.h +0 -0
  129. {lavavu-1.9.9 → lavavu-1.9.10}/src/Vectors.cpp +0 -0
  130. {lavavu-1.9.9 → lavavu-1.9.10}/src/VideoEncoder.cpp +0 -0
  131. {lavavu-1.9.9 → lavavu-1.9.10}/src/VideoEncoder.h +0 -0
  132. {lavavu-1.9.9 → lavavu-1.9.10}/src/View.cpp +0 -0
  133. {lavavu-1.9.9 → lavavu-1.9.10}/src/View.h +0 -0
  134. {lavavu-1.9.9 → lavavu-1.9.10}/src/ViewerApp.h +0 -0
  135. {lavavu-1.9.9 → lavavu-1.9.10}/src/ViewerTypes.h +0 -0
  136. {lavavu-1.9.9 → lavavu-1.9.10}/src/Volumes.cpp +0 -0
  137. {lavavu-1.9.9 → lavavu-1.9.10}/src/base64.cpp +0 -0
  138. {lavavu-1.9.9 → lavavu-1.9.10}/src/base64.h +0 -0
  139. {lavavu-1.9.9 → lavavu-1.9.10}/src/fifo_map.hpp +0 -0
  140. {lavavu-1.9.9 → lavavu-1.9.10}/src/jpeg/jpgd.cpp +0 -0
  141. {lavavu-1.9.9 → lavavu-1.9.10}/src/jpeg/jpgd.h +0 -0
  142. {lavavu-1.9.9 → lavavu-1.9.10}/src/jpeg/jpge.cpp +0 -0
  143. {lavavu-1.9.9 → lavavu-1.9.10}/src/jpeg/jpge.h +0 -0
  144. {lavavu-1.9.9 → lavavu-1.9.10}/src/json.hpp +0 -0
  145. {lavavu-1.9.9 → lavavu-1.9.10}/src/linalg.h +0 -0
  146. {lavavu-1.9.9 → lavavu-1.9.10}/src/miniz/miniz.c +0 -0
  147. {lavavu-1.9.9 → lavavu-1.9.10}/src/miniz/miniz.h +0 -0
  148. {lavavu-1.9.9 → lavavu-1.9.10}/src/png/lodepng.cpp +0 -0
  149. {lavavu-1.9.9 → lavavu-1.9.10}/src/png/lodepng.h +0 -0
  150. {lavavu-1.9.9 → lavavu-1.9.10}/src/sqlite3/sqlite3.c +0 -0
  151. {lavavu-1.9.9 → lavavu-1.9.10}/src/sqlite3/sqlite3.h +0 -0
  152. {lavavu-1.9.9 → lavavu-1.9.10}/src/stb_image_resize.h +0 -0
  153. {lavavu-1.9.9 → lavavu-1.9.10}/src/tiny_obj_loader.h +0 -0
  154. {lavavu-1.9.9 → lavavu-1.9.10}/src/version.h +0 -0
@@ -256,8 +256,9 @@ endif
256
256
 
257
257
  .PHONY: swig
258
258
  swig : $(INC) src/LavaVuPython.i | paths
259
+ #NOTE: bug in swig requires pip install swig==4.2 until fixed
259
260
  swig -v -Wextra -python -py3 -ignoremissing -O -c++ -DSWIG_DO_NOT_WRAP -outdir $(PREFIX) src/LavaVuPython.i
260
- cd $(PREFIX)/osmesa; ln -sf ../LavaVuPython.py; touch __init__.py
261
+ cd $(PREFIX)/osmesa; touch __init__.py
261
262
 
262
263
  $(SWIGLIB) : $(LIBRARY) $(SWIGOBJ)
263
264
  -rm -f $(PREFIX)/_LavaVuPython.*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lavavu
3
- Version: 1.9.9
3
+ Version: 1.9.10
4
4
  Summary: Python interface to LavaVu OpenGL 3D scientific visualisation utilities
5
5
  Author-email: Owen Kaluza <owen@kaluza.id.au>
6
6
  License: ### Licensing
@@ -217,6 +217,7 @@ Requires-Dist: aiohttp
217
217
  Requires-Dist: jupyter_server_proxy
218
218
  Requires-Dist: matplotlib
219
219
  Requires-Dist: numpy-quaternion
220
+ Requires-Dist: pillow
220
221
  Dynamic: license-file
221
222
 
222
223
  ![# logo](http://owen.kaluza.id.au/Slides/2017-08-15/LavaVu.png)
@@ -224,7 +225,7 @@ Dynamic: license-file
224
225
  [![Build Status](https://github.com/lavavu/LavaVu/workflows/Test/badge.svg)](https://github.com/lavavu/LavaVu/actions?query=workflow:Test)
225
226
  [![Deploy Status](https://github.com/lavavu/LavaVu/workflows/Deploy/badge.svg?branch=1.7.3)](https://github.com/lavavu/LavaVu/actions?query=workflow:Deploy)
226
227
  [![DOI](https://zenodo.org/badge/45163055.svg)](https://zenodo.org/badge/latestdoi/45163055)
227
- [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.9)
228
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.10)
228
229
 
229
230
  A scientific visualisation tool with a python interface for fast and flexible visual analysis.
230
231
 
@@ -3,7 +3,7 @@
3
3
  [![Build Status](https://github.com/lavavu/LavaVu/workflows/Test/badge.svg)](https://github.com/lavavu/LavaVu/actions?query=workflow:Test)
4
4
  [![Deploy Status](https://github.com/lavavu/LavaVu/workflows/Deploy/badge.svg?branch=1.7.3)](https://github.com/lavavu/LavaVu/actions?query=workflow:Deploy)
5
5
  [![DOI](https://zenodo.org/badge/45163055.svg)](https://zenodo.org/badge/latestdoi/45163055)
6
- [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.9)
6
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.10)
7
7
 
8
8
  A scientific visualisation tool with a python interface for fast and flexible visual analysis.
9
9
 
@@ -5,12 +5,14 @@
5
5
  # the SWIG interface file instead.
6
6
 
7
7
  from sys import version_info as _swig_python_version_info
8
- # Import the low-level C/C++ module
9
- if __package__ or "." in __name__:
10
- from . import _LavaVuPython
8
+
9
+ import os
10
+ if 'osmesa' in os.environ.get('LV_CONTEXT', ''):
11
+ from osmesa import _LavaVuPython
11
12
  else:
12
13
  import _LavaVuPython
13
14
 
15
+
14
16
  try:
15
17
  import builtins as __builtin__
16
18
  except ImportError:
@@ -27,7 +27,7 @@
27
27
 
28
28
  <input id="fileinput" type="file" style="visibility:hidden" onchange="useFileInput(this)" />
29
29
 
30
- <script async src="https://cdn.jsdelivr.net/gh/lavavu/lavavu.github.io@1.9.9/LavaVu-amalgamated.min.js"></script>
30
+ <script async src="https://cdn.jsdelivr.net/gh/lavavu/lavavu.github.io@1.9.10/LavaVu-amalgamated.min.js"></script>
31
31
  <!--script src="dat.gui.min.js"></script>
32
32
  <script src="OK-min.js"></script>
33
33
 
@@ -59,6 +59,7 @@ import quaternion as quat
59
59
  import platform
60
60
  import matplotlib
61
61
  from pathlib import Path
62
+ from PIL import Image as PILImage
62
63
 
63
64
  if sys.version_info[0] < 3:
64
65
  print("Python 3 required. LavaVu no longer supports Python 2.7.")
@@ -101,10 +102,7 @@ if platform.system() == 'Linux':
101
102
  context = 'moderngl'
102
103
  except Exception as e:
103
104
  context = 'osmesa'
104
-
105
- if context == 'osmesa':
106
- #OSMesa fallback, CPU only, multicore
107
- from osmesa import LavaVuPython
105
+ os.environ['LV_CONTEXT'] = context
108
106
 
109
107
  #Default module if none already loaded
110
108
  try:
@@ -112,8 +110,6 @@ try:
112
110
  except:
113
111
  import LavaVuPython
114
112
 
115
- os.environ['LV_CONTEXT'] = context
116
-
117
113
  version = LavaVuPython.version
118
114
  server_ports = []
119
115
 
@@ -4194,7 +4190,7 @@ class Viewer(dict):
4194
4190
  from IPython.display import display,HTML,Javascript
4195
4191
  display(Javascript(js + code))
4196
4192
 
4197
- def video(self, filename="", resolution=(0,0), fps=30, quality=2, encoder="h264", embed=False, player=None, options={}, **kwargs):
4193
+ def video(self, filename="", resolution=(0,0), fps=30, quality=2, encoder=None, embed=False, player=None, options={}, **kwargs):
4198
4194
  """
4199
4195
  Record and show the generated video inline within an ipython notebook.
4200
4196
 
@@ -4220,7 +4216,7 @@ class Viewer(dict):
4220
4216
  encoding artifacts at cost of larger file size
4221
4217
  If omitted will use default settings, can fine tune settings in kwargs
4222
4218
  encoder : str
4223
- Name of encoder to use, eg: "h264" (default), "mpeg"
4219
+ Name of encoder to use, eg: "h264" (default for .mp4), default will be selected based on filename extension
4224
4220
  embed : bool
4225
4221
  Set to true to embed the video file rather than link to url
4226
4222
  Not recommended for large videos, default is False
@@ -4240,8 +4236,7 @@ class Viewer(dict):
4240
4236
  """
4241
4237
  return Video(self, filename, resolution, fps, quality, encoder, embed, player, options, **kwargs)
4242
4238
 
4243
- def video_steps(self, filename="", start=0, end=0, resolution=(0,0), fps=30, quality=2, encoder="h264", embed=False, player=None, options={}, **kwargs):
4244
- my_func.__doc__
4239
+ def video_steps(self, filename="", start=0, end=0, resolution=(0,0), fps=30, quality=2, encoder=None, embed=False, player=None, options={}, **kwargs):
4245
4240
  """
4246
4241
  Record a video of the model by looping through all time steps
4247
4242
 
@@ -5479,7 +5474,7 @@ class Video(object):
5479
5474
  ... lv.rotate('y', 10) # doctest: +SKIP
5480
5475
  ... lv.render() # doctest: +SKIP
5481
5476
  """
5482
- def __init__(self, viewer, filename="output.mp4", resolution=(0,0), framerate=30, quality=2, encoder="h264", embed=False, player=None, options={}, **kwargs):
5477
+ def __init__(self, viewer, filename="output.mp4", resolution=(0,0), framerate=30, quality=2, encoder=None, embed=False, player=None, options={}, **kwargs):
5483
5478
  """
5484
5479
  Record and show the generated video inline within an ipython notebook.
5485
5480
 
@@ -5505,7 +5500,7 @@ class Video(object):
5505
5500
  resolution : list or tuple
5506
5501
  Video resolution in pixels [x,y]
5507
5502
  encoder : str
5508
- Name of encoder to use, eg: "h264" (default), "mpeg"
5503
+ Name of encoder to use, eg: "h264" (default for .mp4), default will be selected based on filename extension
5509
5504
  embed : bool
5510
5505
  Set to true to embed the video file rather than link to url
5511
5506
  Not recommended for large videos, default is False
@@ -5555,6 +5550,22 @@ class Video(object):
5555
5550
  self.player = {}
5556
5551
  if embed:
5557
5552
  self.player["embed"] = True
5553
+ if encoder is None:
5554
+ if self.filename.suffix.lower() == '.mp4':
5555
+ encoder = 'h264'
5556
+ elif self.filename.suffix.lower() == '.webm':
5557
+ encoder = 'libvpx-vp9'
5558
+ elif self.filename.suffix.lower() == '.webp':
5559
+ encoder = 'libwebp_anim'
5560
+ options["lossless"] = "1"
5561
+ options['pix_fmt'] = "rgb32" #Required for lossless
5562
+ options["loop"] = "0" #This doesn't work, quality also has no effect
5563
+ options["quality"] = str(min(30 + self.quality * 20, 100))
5564
+ elif self.filename.suffix.lower() == '.gif':
5565
+ encoder = 'gif'
5566
+ options['pix_fmt'] = "rgb8"
5567
+ else:
5568
+ encoder = 'h264'
5558
5569
  self.encoder = encoder
5559
5570
  self.options = options
5560
5571
  #Also include extra args
@@ -5565,7 +5576,6 @@ class Video(object):
5565
5576
  """
5566
5577
  Start recording, all rendered frames will be added to the video
5567
5578
  """
5568
- #https://trac.ffmpeg.org/wiki/Encode/H.264
5569
5579
  # The range of the CRF scale is 0–51, where 0 is lossless (for 8 bit only, for 10 bit use -qp 0),
5570
5580
  # 23 is the default, and 51 is worst quality possible
5571
5581
  #Compression level, lower = high quality
@@ -5578,7 +5588,8 @@ class Video(object):
5578
5588
  return
5579
5589
 
5580
5590
  if self.encoder == 'h264' or self.encoder == 'libx265':
5581
- #Only have default options for h264/265 for now
5591
+ #https://trac.ffmpeg.org/wiki/Encode/H.264
5592
+ #options['pix_fmt'] = "yuv420"
5582
5593
  if self.quality == 1:
5583
5594
  options['qmin'] = '30' #'20' #'8'
5584
5595
  options['qmax'] = '35' #'41'
@@ -5596,21 +5607,26 @@ class Video(object):
5596
5607
  options["preset"] = 'veryfast' #'veryfast' 'medium' 'slow'
5597
5608
  options["tune"] = 'animation' #'film'
5598
5609
 
5599
- #Settings from our original c++ encoder
5600
- #self.options['i_quant_factor'] = '0.71'
5601
- #self.options['qcompress'] = '0.6'
5602
- #self.options['max_qdiff'] = '4'
5603
- #self.options['refs'] = '3'
5610
+ elif self.encoder == 'libvpx-vp9':
5611
+ #https://trac.ffmpeg.org/wiki/Encode/VP9
5612
+ options['crf'] = '15'
5613
+ options['b:v'] = '0' #Required for constant quality single pass
5614
+ if self.quality == 1:
5615
+ options['crf'] = '30' #'40'
5616
+ elif self.quality == 2:
5617
+ options['crf'] = '20' #'23'
5618
+ elif self.quality == 3:
5619
+ options['crf'] = '10' #'10'
5620
+ #options['pix_fmt'] = "yuv444p"
5604
5621
 
5605
5622
  #Merge user options, allowing override of above settings
5606
5623
  options.update(self.options)
5624
+ #print(options, self.encoder)
5607
5625
 
5608
- #print(options)
5609
5626
  self.container = av.open(str(self.filename), mode="w")
5610
5627
  self.stream = self.container.add_stream(self.encoder, rate=self.framerate, options=options)
5611
5628
  self.stream.width = self.resolution[0]
5612
5629
  self.stream.height = self.resolution[1]
5613
- self.stream.pix_fmt = "yuv420p"
5614
5630
  self.viewer.recording = self
5615
5631
 
5616
5632
  stream = self.stream
@@ -5620,14 +5636,52 @@ class Video(object):
5620
5636
  #print(stream.profiles)
5621
5637
  #print(stream.profile)
5622
5638
  #print(stream.options)
5639
+
5640
+ if 'pix_fmt' in options:
5641
+ self.stream.pix_fmt = options['pix_fmt']
5642
+ #Select higher quality colour where supported
5643
+ elif self.encoder == 'h264' or self.encoder == 'libx265' or self.encoder == 'libvpx-vp9':
5644
+ #Reduce chroma subsampling for better colour output
5645
+ if self.quality < 3:
5646
+ self.stream.pix_fmt = "yuv420p"
5647
+ else:
5648
+ self.stream.pix_fmt = "yuv422p"
5649
+ #10 bit formats
5650
+ #self.stream.pix_fmt = "yuv444p10le"
5651
+ #self.stream.pix_fmt = "yuv422p10le"
5652
+
5623
5653
  #Need to set profile here or it isn't applied
5624
- #(Default to main)
5625
- stream.profile = 'Main' #Baseline / High
5654
+ #(better chroma sampling requires the correct profile)
5655
+ if 'profile' in options:
5656
+ stream.profile = options['profile']
5657
+ elif self.encoder == 'h264' or self.encoder == 'libx265':
5658
+ #['Baseline', 'Constrained Baseline', 'Main', 'Extended',
5659
+ # 'High', 'High 10', 'High 10 Intra', 'High 4:2:2',
5660
+ # 'High 4:2:2 Intra', 'High 4:4:4', 'High 4:4:4 Predictive',
5661
+ # 'High 4:4:4 Intra', 'CAVLC 4:4:4', 'Multiview High', 'Stereo High']
5662
+ #stream.profile = 'High 4:4:4'
5663
+ if self.stream.pix_fmt == 'yuv420p':
5664
+ stream.profile = 'Main'
5665
+ elif 'yuv422' in self.stream.pix_fmt:
5666
+ stream.profile = 'High 4:2:2'
5667
+ elif 'yuv444' in self.stream.pix_fmt:
5668
+ stream.profile = 'High 4:4:4'
5669
+ elif self.encoder == 'libvpx-vp9':
5670
+ #Profile Color Depth Chroma Subsampling
5671
+ #0 8 bit/sample 4:2:0
5672
+ #1 8 bit 4:2:2,4:4:4
5673
+ #2 10 or 12 bit 4:2:0
5674
+ #3 10 or 12 bit 4:2:2, 4:4:4
5675
+ if self.stream.pix_fmt == 'yuv420p':
5676
+ stream.profile = 'Profile 0'
5677
+ elif 'yuv422' in self.stream.pix_fmt or 'yuv444' in self.stream.pix_fmt:
5678
+ stream.profile = 'Profile 1'
5679
+
5626
5680
  cc = stream.codec_context
5627
5681
  #print(cc.options)
5628
- #print(cc.profile)
5682
+ #print(cc.profile, stream.pix_fmt)
5629
5683
 
5630
- def frame(self):
5684
+ def frame(self, img=None):
5631
5685
  """
5632
5686
  Write a frame, called when viewer.render() is called
5633
5687
  while a recording is in progress
@@ -5639,10 +5693,17 @@ class Video(object):
5639
5693
  else:
5640
5694
  fn = self.filename / f"{self.framecount:06}_{self.basename}.{self.encoder}"
5641
5695
  self.framecount += 1
5642
- self.viewer.image(str(fn), resolution=self.resolution)
5696
+ if img:
5697
+ image = PILImage.fromarray(img)
5698
+ image.save(fn)
5699
+ image.save(fn, subsampling=0, quality=95)
5700
+ else:
5701
+ self.viewer.image(str(fn), resolution=self.resolution)
5643
5702
  else:
5644
- img = self.viewer.rawimage(resolution=self.resolution, channels=3)
5645
- frame = av.VideoFrame.from_ndarray(img.data, format="rgb24")
5703
+ if img is None:
5704
+ img = self.viewer.rawimage(resolution=self.resolution, channels=3).data
5705
+ frame = av.VideoFrame.from_ndarray(img, format="rgb24")
5706
+ #frame = av.VideoFrame.from_image(PILImage.fromarray(img)) #, format="rgb24")
5646
5707
  for packet in self.stream.encode(frame):
5647
5708
  self.container.mux(packet)
5648
5709
 
@@ -5697,23 +5758,16 @@ class Video(object):
5697
5758
  image = image.reshape(self.resolution[0], self.resolution[1], 4)
5698
5759
  image = image[::,::,:3] #Remove alpha channel
5699
5760
 
5700
- if self.encoder == 'jpg' or self.encoder == 'png':
5701
- from PIL import Image as PILImage
5702
- img = PILImage.fromarray(image)
5703
- fn = self.filename / f"{self.framecount:06}_{self.basename}.{self.encoder}"
5704
- self.framecount += 1
5705
- img.save(fn)
5706
- return
5707
-
5708
- frame = av.VideoFrame.from_ndarray(image, format="rgb24")
5709
- for packet in self.stream.encode(frame):
5710
- self.container.mux(packet)
5761
+ self.frame(image)
5711
5762
 
5712
5763
  def play(self):
5713
5764
  """
5714
5765
  Show the video in an inline player if in an interactive notebook
5715
5766
  """
5716
- if self.encoder == 'jpg' or self.encoder == 'png':
5767
+ if self.encoder == 'gif' or self.encoder == 'libwebp_anim':
5768
+ from IPython.display import display,Image
5769
+ display(Image(self.filename, **self.player))
5770
+ elif self.encoder == 'jpg' or self.encoder == 'png':
5717
5771
  from IPython.display import display,HTML
5718
5772
  display(HTML('<p>Video written to images, no player available</p>'))
5719
5773
  else:
@@ -5841,7 +5895,6 @@ class Image(object):
5841
5895
  """
5842
5896
  try:
5843
5897
  #Get array from PIL images
5844
- from PIL import Image as PILImage
5845
5898
  if isinstance(source, PILImage.Image):
5846
5899
  source = numpy.array(source)
5847
5900
  except (ImportError) as e:
@@ -24,7 +24,7 @@ def random_particles(count, lowerbound=[0,0,0], upperbound=[1,1,1], dims=3):
24
24
  return numpy.stack(p).T
25
25
 
26
26
  class Tracers():
27
- def __init__(self, grid, count=1000, lowerbound=None, upperbound=None, limit=None, age=4, respawn_chance=0.2, speed_multiply=1.0, height=0.0, label='', viewer=None):
27
+ def __init__(self, grid, count=1000, lowerbound=None, upperbound=None, limit=0, age=4, respawn_chance=0.2, speed_multiply=1.0, height=0.0, label='', viewer=None, seed=0):
28
28
  """
29
29
  Seed random particles into a vector field and trace their positions
30
30
 
@@ -40,10 +40,7 @@ class Tracers():
40
40
  upperbound : optional maximum vertex point defining particle bounding box,
41
41
  if not provided will be taken from grid upper corner
42
42
  limit : float
43
- Distance limit over which tracers are not connected,
44
- For example if using a periodic boundary, setting limit to
45
- half the bounding box size will prevent tracer lines being
46
- connected when passing through the boundary
43
+ Distance limit over which tracers are not drawn
47
44
  age : int
48
45
  Minimum particle age in steps after which particle can be deleted and respawned, defaults to 4
49
46
  respawn : float
@@ -56,6 +53,9 @@ class Tracers():
56
53
  Name label prefix for the visualisation objects when plotting
57
54
  viewer : lavavu.Viewer
58
55
  Viewer object for plotting functions
56
+ seed : int
57
+ Random seed for deterministic random particle positions, default=0, set to None to use
58
+ system time which will produce non-deterministic results (different each run)
59
59
  """
60
60
  if len(grid) == 2:
61
61
  self.gridx = grid[0]
@@ -108,20 +108,18 @@ class Tracers():
108
108
  self.arrows = None
109
109
  self.tracers = None
110
110
 
111
+ if seed is not None:
112
+ random.seed(seed)
111
113
 
112
114
  def respawn(self, r):
113
115
  #Dead or out of bounds particle, start at new position
114
116
  #Loop until new position further from current position than limit
115
117
  old_pos = self.positions[r]
116
118
  pos = numpy.array([0.] * self.dims)
117
- for i in range(10):
118
- pos = random_particles(1, self.lowerbound, self.upperbound, self.dims)
119
- dist = numpy.linalg.norm(old_pos - pos)
120
- if dist > self.limit*1.01:
121
- break
122
-
119
+ pos = random_particles(1, self.lowerbound, self.upperbound, self.dims)
123
120
  self.ages[r] = 0
124
121
  self.positions[r] = pos
122
+ self.velocities[r] = numpy.array([0.0] * self.dims)
125
123
 
126
124
  def update(self, vectors=None):
127
125
  #Interpolate velocity at all positions,
@@ -140,24 +138,21 @@ class Tracers():
140
138
 
141
139
  for r in range(len(self.velocities)):
142
140
  #Lookup velocity at this index, multiply by position to get delta and add
143
- self.speed[r] = numpy.linalg.norm(self.velocities[r])
144
- if numpy.isnan(self.speed[r]): self.speed[r] = 0.0
145
- if self.speed[r] == 0.0: #numpy.any(numpy.isinf(self.old_pos[r])) or numpy.any(numpy.isinf(self.positions[r])):
141
+ if self.ages[r] < 0:
146
142
  self.respawn(r)
147
143
  else:
144
+ self.speed[r] = numpy.linalg.norm(self.velocities[r])
145
+ if numpy.isnan(self.speed[r]) or numpy.isinf(self.speed[r]): self.speed[r] = 0.0
148
146
  self.positions[r] = self.positions[r] + self.speed_multiply * self.velocities[r]
149
147
  self.ages[r] += 1
150
148
 
151
- #Bounds checks
152
- #Chance of killing particle when over age, default 1 in 5 (0.2)
153
- if (any(self.positions[r] < self.lowerbound[0:self.dims]) or any(self.positions[r] > self.upperbound[0:self.dims])
154
- or (self.ages[r] > self.age and numpy.random.uniform() <= self.respawn_chance)):
155
- #if r < 20: print("Kill", r, self.speed[r], numpy.isnan(self.speed[r])) # [0] == numpy.nan)
156
- #self.positions[r] = numpy.array([numpy.inf] * self.dims)
157
- #self.positions[r] = numpy.array([numpy.nan] * self.dims)
158
- self.respawn(r)
159
- self.velocities[r] = numpy.array([0.0] * self.dims)
160
- self.speed[r] = 0.0
149
+ #Bounds checks
150
+ #Chance of killing particle when over age, default 1 in 5 (0.2)
151
+ if (any(self.positions[r] < self.lowerbound[0:self.dims]) or any(self.positions[r] > self.upperbound[0:self.dims])
152
+ or (self.ages[r] > self.age and numpy.random.uniform() <= self.respawn_chance)):
153
+ self.positions[r] = numpy.array([numpy.nan] * self.dims)
154
+ self.ages[r] = -1
155
+ self.velocities[r] = numpy.array([0.0] * self.dims)
161
156
 
162
157
  if self.lv:
163
158
  positions = self.get_positions()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lavavu
3
- Version: 1.9.9
3
+ Version: 1.9.10
4
4
  Summary: Python interface to LavaVu OpenGL 3D scientific visualisation utilities
5
5
  Author-email: Owen Kaluza <owen@kaluza.id.au>
6
6
  License: ### Licensing
@@ -217,6 +217,7 @@ Requires-Dist: aiohttp
217
217
  Requires-Dist: jupyter_server_proxy
218
218
  Requires-Dist: matplotlib
219
219
  Requires-Dist: numpy-quaternion
220
+ Requires-Dist: pillow
220
221
  Dynamic: license-file
221
222
 
222
223
  ![# logo](http://owen.kaluza.id.au/Slides/2017-08-15/LavaVu.png)
@@ -224,7 +225,7 @@ Dynamic: license-file
224
225
  [![Build Status](https://github.com/lavavu/LavaVu/workflows/Test/badge.svg)](https://github.com/lavavu/LavaVu/actions?query=workflow:Test)
225
226
  [![Deploy Status](https://github.com/lavavu/LavaVu/workflows/Deploy/badge.svg?branch=1.7.3)](https://github.com/lavavu/LavaVu/actions?query=workflow:Deploy)
226
227
  [![DOI](https://zenodo.org/badge/45163055.svg)](https://zenodo.org/badge/latestdoi/45163055)
227
- [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.9)
228
+ [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lavavu/LavaVu/1.9.10)
228
229
 
229
230
  A scientific visualisation tool with a python interface for fast and flexible visual analysis.
230
231
 
@@ -45,7 +45,6 @@ lavavu/html/stats.min.js
45
45
  lavavu/html/styles.css
46
46
  lavavu/html/webview-template.html
47
47
  lavavu/html/webview.html
48
- lavavu/osmesa/LavaVuPython.py
49
48
  lavavu/osmesa/__init__.py
50
49
  lavavu/shaders/default.frag
51
50
  lavavu/shaders/default.vert
@@ -3,3 +3,4 @@ aiohttp
3
3
  jupyter_server_proxy
4
4
  matplotlib
5
5
  numpy-quaternion
6
+ pillow
@@ -3,4 +3,5 @@ aiohttp
3
3
  jupyter_server_proxy
4
4
  matplotlib
5
5
  numpy-quaternion
6
+ pillow
6
7
 
@@ -19,7 +19,7 @@ import shutil
19
19
 
20
20
  #Current version
21
21
  #(must be of the form X.Y.Z to trigger wheel builds)
22
- version = "1.9.9"
22
+ version = "1.9.10"
23
23
 
24
24
  """
25
25
  To release a new verison:
@@ -368,7 +368,7 @@ if __name__ == "__main__":
368
368
  defines += [('HAVE_LIBTIFF', 1)]
369
369
  libs += ['tiff']
370
370
 
371
- if (find_library('avcodec') and find_library('avformat') and find_library('avutil')
371
+ if ("LV_VIDEO" in os.environ and find_library('avcodec') and find_library('avformat') and find_library('avutil')
372
372
  and check_libraries(['avcodec', 'avformat', 'avutil'],
373
373
  ['libavformat/avformat.h', 'libavcodec/avcodec.h', 'libavutil/mathematics.h',
374
374
  'libavutil/imgutils.h'])):