vispy 0.15.0__cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

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.

Potentially problematic release.


This version of vispy might be problematic. Click here for more details.

Files changed (521) hide show
  1. vispy/__init__.py +33 -0
  2. vispy/app/__init__.py +15 -0
  3. vispy/app/_default_app.py +76 -0
  4. vispy/app/_detect_eventloop.py +148 -0
  5. vispy/app/application.py +263 -0
  6. vispy/app/backends/__init__.py +52 -0
  7. vispy/app/backends/_egl.py +264 -0
  8. vispy/app/backends/_glfw.py +513 -0
  9. vispy/app/backends/_jupyter_rfb.py +278 -0
  10. vispy/app/backends/_offscreen_util.py +121 -0
  11. vispy/app/backends/_osmesa.py +235 -0
  12. vispy/app/backends/_pyglet.py +451 -0
  13. vispy/app/backends/_pyqt4.py +36 -0
  14. vispy/app/backends/_pyqt5.py +36 -0
  15. vispy/app/backends/_pyqt6.py +40 -0
  16. vispy/app/backends/_pyside.py +37 -0
  17. vispy/app/backends/_pyside2.py +52 -0
  18. vispy/app/backends/_pyside6.py +53 -0
  19. vispy/app/backends/_qt.py +1003 -0
  20. vispy/app/backends/_sdl2.py +444 -0
  21. vispy/app/backends/_template.py +244 -0
  22. vispy/app/backends/_test.py +8 -0
  23. vispy/app/backends/_tk.py +800 -0
  24. vispy/app/backends/_wx.py +476 -0
  25. vispy/app/backends/tests/__init__.py +0 -0
  26. vispy/app/backends/tests/test_offscreen_util.py +52 -0
  27. vispy/app/backends/tests/test_rfb.py +77 -0
  28. vispy/app/base.py +294 -0
  29. vispy/app/canvas.py +828 -0
  30. vispy/app/qt.py +92 -0
  31. vispy/app/tests/__init__.py +0 -0
  32. vispy/app/tests/qt-designer.ui +58 -0
  33. vispy/app/tests/test_app.py +442 -0
  34. vispy/app/tests/test_backends.py +164 -0
  35. vispy/app/tests/test_canvas.py +122 -0
  36. vispy/app/tests/test_context.py +92 -0
  37. vispy/app/tests/test_qt.py +47 -0
  38. vispy/app/tests/test_simultaneous.py +134 -0
  39. vispy/app/timer.py +174 -0
  40. vispy/color/__init__.py +17 -0
  41. vispy/color/_color_dict.py +193 -0
  42. vispy/color/color_array.py +447 -0
  43. vispy/color/color_space.py +181 -0
  44. vispy/color/colormap.py +1213 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +378 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1522 -0
  50. vispy/ext/cubehelix.py +138 -0
  51. vispy/ext/egl.py +375 -0
  52. vispy/ext/fontconfig.py +118 -0
  53. vispy/ext/gdi32plus.py +206 -0
  54. vispy/ext/osmesa.py +105 -0
  55. vispy/geometry/__init__.py +23 -0
  56. vispy/geometry/_triangulation_debugger.py +171 -0
  57. vispy/geometry/calculations.py +162 -0
  58. vispy/geometry/curves.py +399 -0
  59. vispy/geometry/generation.py +643 -0
  60. vispy/geometry/isocurve.py +175 -0
  61. vispy/geometry/isosurface.py +465 -0
  62. vispy/geometry/meshdata.py +700 -0
  63. vispy/geometry/normals.py +78 -0
  64. vispy/geometry/parametric.py +56 -0
  65. vispy/geometry/polygon.py +137 -0
  66. vispy/geometry/rect.py +210 -0
  67. vispy/geometry/tests/__init__.py +0 -0
  68. vispy/geometry/tests/test_calculations.py +23 -0
  69. vispy/geometry/tests/test_generation.py +56 -0
  70. vispy/geometry/tests/test_meshdata.py +106 -0
  71. vispy/geometry/tests/test_triangulation.py +594 -0
  72. vispy/geometry/torusknot.py +142 -0
  73. vispy/geometry/triangulation.py +876 -0
  74. vispy/gloo/__init__.py +56 -0
  75. vispy/gloo/buffer.py +505 -0
  76. vispy/gloo/context.py +272 -0
  77. vispy/gloo/framebuffer.py +257 -0
  78. vispy/gloo/gl/__init__.py +234 -0
  79. vispy/gloo/gl/_constants.py +332 -0
  80. vispy/gloo/gl/_es2.py +986 -0
  81. vispy/gloo/gl/_gl2.py +1365 -0
  82. vispy/gloo/gl/_proxy.py +499 -0
  83. vispy/gloo/gl/_pyopengl2.py +362 -0
  84. vispy/gloo/gl/dummy.py +24 -0
  85. vispy/gloo/gl/es2.py +62 -0
  86. vispy/gloo/gl/gl2.py +98 -0
  87. vispy/gloo/gl/glplus.py +168 -0
  88. vispy/gloo/gl/pyopengl2.py +97 -0
  89. vispy/gloo/gl/tests/__init__.py +0 -0
  90. vispy/gloo/gl/tests/test_basics.py +282 -0
  91. vispy/gloo/gl/tests/test_functionality.py +568 -0
  92. vispy/gloo/gl/tests/test_names.py +246 -0
  93. vispy/gloo/gl/tests/test_use.py +71 -0
  94. vispy/gloo/glir.py +1824 -0
  95. vispy/gloo/globject.py +101 -0
  96. vispy/gloo/preprocessor.py +67 -0
  97. vispy/gloo/program.py +543 -0
  98. vispy/gloo/tests/__init__.py +0 -0
  99. vispy/gloo/tests/test_buffer.py +558 -0
  100. vispy/gloo/tests/test_context.py +119 -0
  101. vispy/gloo/tests/test_framebuffer.py +195 -0
  102. vispy/gloo/tests/test_glir.py +307 -0
  103. vispy/gloo/tests/test_globject.py +35 -0
  104. vispy/gloo/tests/test_program.py +302 -0
  105. vispy/gloo/tests/test_texture.py +732 -0
  106. vispy/gloo/tests/test_use_gloo.py +187 -0
  107. vispy/gloo/tests/test_util.py +60 -0
  108. vispy/gloo/tests/test_wrappers.py +261 -0
  109. vispy/gloo/texture.py +1046 -0
  110. vispy/gloo/util.py +129 -0
  111. vispy/gloo/wrappers.py +762 -0
  112. vispy/glsl/__init__.py +42 -0
  113. vispy/glsl/antialias/antialias.glsl +7 -0
  114. vispy/glsl/antialias/cap-butt.glsl +31 -0
  115. vispy/glsl/antialias/cap-round.glsl +29 -0
  116. vispy/glsl/antialias/cap-square.glsl +30 -0
  117. vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
  118. vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
  119. vispy/glsl/antialias/cap.glsl +67 -0
  120. vispy/glsl/antialias/caps.glsl +67 -0
  121. vispy/glsl/antialias/filled.glsl +50 -0
  122. vispy/glsl/antialias/outline.glsl +40 -0
  123. vispy/glsl/antialias/stroke.glsl +43 -0
  124. vispy/glsl/arrowheads/angle.glsl +99 -0
  125. vispy/glsl/arrowheads/arrowheads.frag +60 -0
  126. vispy/glsl/arrowheads/arrowheads.glsl +12 -0
  127. vispy/glsl/arrowheads/arrowheads.vert +83 -0
  128. vispy/glsl/arrowheads/curved.glsl +48 -0
  129. vispy/glsl/arrowheads/inhibitor.glsl +26 -0
  130. vispy/glsl/arrowheads/stealth.glsl +46 -0
  131. vispy/glsl/arrowheads/triangle.glsl +97 -0
  132. vispy/glsl/arrowheads/util.glsl +13 -0
  133. vispy/glsl/arrows/angle-30.glsl +12 -0
  134. vispy/glsl/arrows/angle-60.glsl +12 -0
  135. vispy/glsl/arrows/angle-90.glsl +12 -0
  136. vispy/glsl/arrows/arrow.frag +39 -0
  137. vispy/glsl/arrows/arrow.vert +49 -0
  138. vispy/glsl/arrows/arrows.glsl +17 -0
  139. vispy/glsl/arrows/common.glsl +187 -0
  140. vispy/glsl/arrows/curved.glsl +63 -0
  141. vispy/glsl/arrows/stealth.glsl +50 -0
  142. vispy/glsl/arrows/triangle-30.glsl +12 -0
  143. vispy/glsl/arrows/triangle-60.glsl +12 -0
  144. vispy/glsl/arrows/triangle-90.glsl +12 -0
  145. vispy/glsl/arrows/util.glsl +98 -0
  146. vispy/glsl/build_spatial_filters.py +660 -0
  147. vispy/glsl/collections/agg-fast-path.frag +20 -0
  148. vispy/glsl/collections/agg-fast-path.vert +78 -0
  149. vispy/glsl/collections/agg-glyph.frag +60 -0
  150. vispy/glsl/collections/agg-glyph.vert +33 -0
  151. vispy/glsl/collections/agg-marker.frag +35 -0
  152. vispy/glsl/collections/agg-marker.vert +48 -0
  153. vispy/glsl/collections/agg-path.frag +55 -0
  154. vispy/glsl/collections/agg-path.vert +166 -0
  155. vispy/glsl/collections/agg-point.frag +21 -0
  156. vispy/glsl/collections/agg-point.vert +35 -0
  157. vispy/glsl/collections/agg-segment.frag +32 -0
  158. vispy/glsl/collections/agg-segment.vert +75 -0
  159. vispy/glsl/collections/marker.frag +38 -0
  160. vispy/glsl/collections/marker.vert +48 -0
  161. vispy/glsl/collections/raw-path.frag +15 -0
  162. vispy/glsl/collections/raw-path.vert +24 -0
  163. vispy/glsl/collections/raw-point.frag +14 -0
  164. vispy/glsl/collections/raw-point.vert +31 -0
  165. vispy/glsl/collections/raw-segment.frag +18 -0
  166. vispy/glsl/collections/raw-segment.vert +26 -0
  167. vispy/glsl/collections/raw-triangle.frag +13 -0
  168. vispy/glsl/collections/raw-triangle.vert +26 -0
  169. vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
  170. vispy/glsl/collections/sdf-glyph.frag +80 -0
  171. vispy/glsl/collections/sdf-glyph.vert +59 -0
  172. vispy/glsl/collections/tick-labels.vert +71 -0
  173. vispy/glsl/colormaps/autumn.glsl +20 -0
  174. vispy/glsl/colormaps/blues.glsl +20 -0
  175. vispy/glsl/colormaps/color-space.glsl +17 -0
  176. vispy/glsl/colormaps/colormaps.glsl +24 -0
  177. vispy/glsl/colormaps/cool.glsl +20 -0
  178. vispy/glsl/colormaps/fire.glsl +21 -0
  179. vispy/glsl/colormaps/gray.glsl +20 -0
  180. vispy/glsl/colormaps/greens.glsl +20 -0
  181. vispy/glsl/colormaps/hot.glsl +22 -0
  182. vispy/glsl/colormaps/ice.glsl +20 -0
  183. vispy/glsl/colormaps/icefire.glsl +23 -0
  184. vispy/glsl/colormaps/parse.py +40 -0
  185. vispy/glsl/colormaps/reds.glsl +20 -0
  186. vispy/glsl/colormaps/spring.glsl +20 -0
  187. vispy/glsl/colormaps/summer.glsl +20 -0
  188. vispy/glsl/colormaps/user.glsl +22 -0
  189. vispy/glsl/colormaps/util.glsl +41 -0
  190. vispy/glsl/colormaps/wheel.glsl +21 -0
  191. vispy/glsl/colormaps/winter.glsl +20 -0
  192. vispy/glsl/lines/agg.frag +320 -0
  193. vispy/glsl/lines/agg.vert +241 -0
  194. vispy/glsl/markers/arrow.glsl +12 -0
  195. vispy/glsl/markers/asterisk.glsl +16 -0
  196. vispy/glsl/markers/chevron.glsl +14 -0
  197. vispy/glsl/markers/clover.glsl +20 -0
  198. vispy/glsl/markers/club.glsl +31 -0
  199. vispy/glsl/markers/cross.glsl +17 -0
  200. vispy/glsl/markers/diamond.glsl +12 -0
  201. vispy/glsl/markers/disc.glsl +9 -0
  202. vispy/glsl/markers/ellipse.glsl +67 -0
  203. vispy/glsl/markers/hbar.glsl +9 -0
  204. vispy/glsl/markers/heart.glsl +15 -0
  205. vispy/glsl/markers/infinity.glsl +15 -0
  206. vispy/glsl/markers/marker-sdf.frag +74 -0
  207. vispy/glsl/markers/marker-sdf.vert +41 -0
  208. vispy/glsl/markers/marker.frag +36 -0
  209. vispy/glsl/markers/marker.vert +46 -0
  210. vispy/glsl/markers/markers.glsl +24 -0
  211. vispy/glsl/markers/pin.glsl +18 -0
  212. vispy/glsl/markers/ring.glsl +11 -0
  213. vispy/glsl/markers/spade.glsl +28 -0
  214. vispy/glsl/markers/square.glsl +10 -0
  215. vispy/glsl/markers/tag.glsl +11 -0
  216. vispy/glsl/markers/triangle.glsl +14 -0
  217. vispy/glsl/markers/vbar.glsl +9 -0
  218. vispy/glsl/math/circle-through-2-points.glsl +30 -0
  219. vispy/glsl/math/constants.glsl +48 -0
  220. vispy/glsl/math/double.glsl +114 -0
  221. vispy/glsl/math/functions.glsl +20 -0
  222. vispy/glsl/math/point-to-line-distance.glsl +31 -0
  223. vispy/glsl/math/point-to-line-projection.glsl +29 -0
  224. vispy/glsl/math/signed-line-distance.glsl +27 -0
  225. vispy/glsl/math/signed-segment-distance.glsl +30 -0
  226. vispy/glsl/misc/regular-grid.frag +244 -0
  227. vispy/glsl/misc/spatial-filters.frag +1407 -0
  228. vispy/glsl/misc/viewport-NDC.glsl +20 -0
  229. vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
  230. vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
  231. vispy/glsl/transforms/hammer.glsl +44 -0
  232. vispy/glsl/transforms/identity.glsl +6 -0
  233. vispy/glsl/transforms/identity_forward.glsl +23 -0
  234. vispy/glsl/transforms/identity_inverse.glsl +23 -0
  235. vispy/glsl/transforms/linear-scale.glsl +127 -0
  236. vispy/glsl/transforms/log-scale.glsl +126 -0
  237. vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
  238. vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
  239. vispy/glsl/transforms/panzoom.glsl +10 -0
  240. vispy/glsl/transforms/polar.glsl +41 -0
  241. vispy/glsl/transforms/position.glsl +44 -0
  242. vispy/glsl/transforms/power-scale.glsl +139 -0
  243. vispy/glsl/transforms/projection.glsl +7 -0
  244. vispy/glsl/transforms/pvm.glsl +13 -0
  245. vispy/glsl/transforms/rotate.glsl +45 -0
  246. vispy/glsl/transforms/trackball.glsl +15 -0
  247. vispy/glsl/transforms/translate.glsl +35 -0
  248. vispy/glsl/transforms/transverse_mercator.glsl +38 -0
  249. vispy/glsl/transforms/viewport-clipping.glsl +14 -0
  250. vispy/glsl/transforms/viewport-transform.glsl +16 -0
  251. vispy/glsl/transforms/viewport.glsl +50 -0
  252. vispy/glsl/transforms/x.glsl +24 -0
  253. vispy/glsl/transforms/y.glsl +19 -0
  254. vispy/glsl/transforms/z.glsl +14 -0
  255. vispy/io/__init__.py +20 -0
  256. vispy/io/_data/spatial-filters.npy +0 -0
  257. vispy/io/datasets.py +94 -0
  258. vispy/io/image.py +231 -0
  259. vispy/io/mesh.py +122 -0
  260. vispy/io/stl.py +167 -0
  261. vispy/io/tests/__init__.py +0 -0
  262. vispy/io/tests/test_image.py +47 -0
  263. vispy/io/tests/test_io.py +121 -0
  264. vispy/io/wavefront.py +350 -0
  265. vispy/plot/__init__.py +36 -0
  266. vispy/plot/fig.py +58 -0
  267. vispy/plot/plotwidget.py +522 -0
  268. vispy/plot/tests/__init__.py +0 -0
  269. vispy/plot/tests/test_plot.py +46 -0
  270. vispy/scene/__init__.py +43 -0
  271. vispy/scene/cameras/__init__.py +27 -0
  272. vispy/scene/cameras/_base.py +38 -0
  273. vispy/scene/cameras/arcball.py +105 -0
  274. vispy/scene/cameras/base_camera.py +551 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +311 -0
  278. vispy/scene/cameras/perspective.py +338 -0
  279. vispy/scene/cameras/tests/__init__.py +0 -0
  280. vispy/scene/cameras/tests/test_cameras.py +27 -0
  281. vispy/scene/cameras/tests/test_link.py +53 -0
  282. vispy/scene/cameras/tests/test_perspective.py +122 -0
  283. vispy/scene/cameras/turntable.py +183 -0
  284. vispy/scene/canvas.py +639 -0
  285. vispy/scene/events.py +85 -0
  286. vispy/scene/node.py +644 -0
  287. vispy/scene/subscene.py +20 -0
  288. vispy/scene/tests/__init__.py +0 -0
  289. vispy/scene/tests/test_canvas.py +119 -0
  290. vispy/scene/tests/test_node.py +142 -0
  291. vispy/scene/tests/test_visuals.py +141 -0
  292. vispy/scene/visuals.py +276 -0
  293. vispy/scene/widgets/__init__.py +18 -0
  294. vispy/scene/widgets/anchor.py +25 -0
  295. vispy/scene/widgets/axis.py +88 -0
  296. vispy/scene/widgets/colorbar.py +176 -0
  297. vispy/scene/widgets/console.py +351 -0
  298. vispy/scene/widgets/grid.py +509 -0
  299. vispy/scene/widgets/label.py +50 -0
  300. vispy/scene/widgets/tests/__init__.py +0 -0
  301. vispy/scene/widgets/tests/test_colorbar.py +47 -0
  302. vispy/scene/widgets/viewbox.py +199 -0
  303. vispy/scene/widgets/widget.py +478 -0
  304. vispy/testing/__init__.py +51 -0
  305. vispy/testing/_runners.py +448 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +494 -0
  308. vispy/testing/rendered_array_tester.py +85 -0
  309. vispy/testing/tests/__init__.py +0 -0
  310. vispy/testing/tests/test_testing.py +20 -0
  311. vispy/util/__init__.py +32 -0
  312. vispy/util/bunch.py +15 -0
  313. vispy/util/check_environment.py +57 -0
  314. vispy/util/config.py +490 -0
  315. vispy/util/dpi/__init__.py +19 -0
  316. vispy/util/dpi/_linux.py +69 -0
  317. vispy/util/dpi/_quartz.py +26 -0
  318. vispy/util/dpi/_win32.py +34 -0
  319. vispy/util/dpi/tests/__init__.py +0 -0
  320. vispy/util/dpi/tests/test_dpi.py +16 -0
  321. vispy/util/eq.py +41 -0
  322. vispy/util/event.py +774 -0
  323. vispy/util/fetching.py +276 -0
  324. vispy/util/filter.py +44 -0
  325. vispy/util/fonts/__init__.py +14 -0
  326. vispy/util/fonts/_freetype.py +73 -0
  327. vispy/util/fonts/_quartz.py +192 -0
  328. vispy/util/fonts/_triage.py +36 -0
  329. vispy/util/fonts/_vispy_fonts.py +20 -0
  330. vispy/util/fonts/_win32.py +105 -0
  331. vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
  332. vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
  333. vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
  334. vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
  335. vispy/util/fonts/tests/__init__.py +0 -0
  336. vispy/util/fonts/tests/test_font.py +45 -0
  337. vispy/util/fourier.py +69 -0
  338. vispy/util/frozen.py +25 -0
  339. vispy/util/gallery_scraper.py +268 -0
  340. vispy/util/keys.py +91 -0
  341. vispy/util/logs.py +358 -0
  342. vispy/util/osmesa_gl.py +17 -0
  343. vispy/util/profiler.py +135 -0
  344. vispy/util/ptime.py +16 -0
  345. vispy/util/quaternion.py +229 -0
  346. vispy/util/svg/__init__.py +18 -0
  347. vispy/util/svg/base.py +20 -0
  348. vispy/util/svg/color.py +219 -0
  349. vispy/util/svg/element.py +51 -0
  350. vispy/util/svg/geometry.py +478 -0
  351. vispy/util/svg/group.py +66 -0
  352. vispy/util/svg/length.py +81 -0
  353. vispy/util/svg/number.py +25 -0
  354. vispy/util/svg/path.py +332 -0
  355. vispy/util/svg/shapes.py +57 -0
  356. vispy/util/svg/style.py +59 -0
  357. vispy/util/svg/svg.py +40 -0
  358. vispy/util/svg/transform.py +223 -0
  359. vispy/util/svg/transformable.py +28 -0
  360. vispy/util/svg/viewport.py +73 -0
  361. vispy/util/tests/__init__.py +0 -0
  362. vispy/util/tests/test_config.py +58 -0
  363. vispy/util/tests/test_docstring_parameters.py +123 -0
  364. vispy/util/tests/test_emitter_group.py +262 -0
  365. vispy/util/tests/test_event_emitter.py +743 -0
  366. vispy/util/tests/test_fourier.py +35 -0
  367. vispy/util/tests/test_gallery_scraper.py +112 -0
  368. vispy/util/tests/test_import.py +127 -0
  369. vispy/util/tests/test_key.py +22 -0
  370. vispy/util/tests/test_logging.py +45 -0
  371. vispy/util/tests/test_run.py +14 -0
  372. vispy/util/tests/test_transforms.py +42 -0
  373. vispy/util/tests/test_vispy.py +48 -0
  374. vispy/util/transforms.py +201 -0
  375. vispy/util/wrappers.py +155 -0
  376. vispy/version.py +21 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +487 -0
  379. vispy/visuals/axis.py +678 -0
  380. vispy/visuals/border.py +208 -0
  381. vispy/visuals/box.py +79 -0
  382. vispy/visuals/collections/__init__.py +30 -0
  383. vispy/visuals/collections/agg_fast_path_collection.py +219 -0
  384. vispy/visuals/collections/agg_path_collection.py +197 -0
  385. vispy/visuals/collections/agg_point_collection.py +52 -0
  386. vispy/visuals/collections/agg_segment_collection.py +142 -0
  387. vispy/visuals/collections/array_list.py +401 -0
  388. vispy/visuals/collections/base_collection.py +482 -0
  389. vispy/visuals/collections/collection.py +253 -0
  390. vispy/visuals/collections/path_collection.py +23 -0
  391. vispy/visuals/collections/point_collection.py +19 -0
  392. vispy/visuals/collections/polygon_collection.py +25 -0
  393. vispy/visuals/collections/raw_path_collection.py +119 -0
  394. vispy/visuals/collections/raw_point_collection.py +113 -0
  395. vispy/visuals/collections/raw_polygon_collection.py +77 -0
  396. vispy/visuals/collections/raw_segment_collection.py +112 -0
  397. vispy/visuals/collections/raw_triangle_collection.py +78 -0
  398. vispy/visuals/collections/segment_collection.py +19 -0
  399. vispy/visuals/collections/triangle_collection.py +16 -0
  400. vispy/visuals/collections/util.py +168 -0
  401. vispy/visuals/colorbar.py +699 -0
  402. vispy/visuals/cube.py +41 -0
  403. vispy/visuals/ellipse.py +162 -0
  404. vispy/visuals/filters/__init__.py +10 -0
  405. vispy/visuals/filters/base_filter.py +242 -0
  406. vispy/visuals/filters/clipper.py +60 -0
  407. vispy/visuals/filters/clipping_planes.py +122 -0
  408. vispy/visuals/filters/color.py +181 -0
  409. vispy/visuals/filters/markers.py +28 -0
  410. vispy/visuals/filters/mesh.py +801 -0
  411. vispy/visuals/filters/picking.py +60 -0
  412. vispy/visuals/filters/tests/__init__.py +3 -0
  413. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  414. vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
  415. vispy/visuals/glsl/__init__.py +1 -0
  416. vispy/visuals/glsl/antialiasing.py +133 -0
  417. vispy/visuals/glsl/color.py +63 -0
  418. vispy/visuals/graphs/__init__.py +1 -0
  419. vispy/visuals/graphs/graph.py +240 -0
  420. vispy/visuals/graphs/layouts/__init__.py +55 -0
  421. vispy/visuals/graphs/layouts/circular.py +49 -0
  422. vispy/visuals/graphs/layouts/force_directed.py +211 -0
  423. vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
  424. vispy/visuals/graphs/layouts/random.py +52 -0
  425. vispy/visuals/graphs/tests/__init__.py +1 -0
  426. vispy/visuals/graphs/tests/test_layouts.py +139 -0
  427. vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
  428. vispy/visuals/graphs/util.py +120 -0
  429. vispy/visuals/gridlines.py +161 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +701 -0
  433. vispy/visuals/image_complex.py +130 -0
  434. vispy/visuals/infinite_line.py +199 -0
  435. vispy/visuals/instanced_mesh.py +152 -0
  436. vispy/visuals/isocurve.py +213 -0
  437. vispy/visuals/isoline.py +241 -0
  438. vispy/visuals/isosurface.py +113 -0
  439. vispy/visuals/line/__init__.py +6 -0
  440. vispy/visuals/line/arrow.py +289 -0
  441. vispy/visuals/line/dash_atlas.py +90 -0
  442. vispy/visuals/line/line.py +545 -0
  443. vispy/visuals/line_plot.py +135 -0
  444. vispy/visuals/linear_region.py +199 -0
  445. vispy/visuals/markers.py +819 -0
  446. vispy/visuals/mesh.py +373 -0
  447. vispy/visuals/mesh_normals.py +159 -0
  448. vispy/visuals/plane.py +54 -0
  449. vispy/visuals/polygon.py +145 -0
  450. vispy/visuals/rectangle.py +196 -0
  451. vispy/visuals/regular_polygon.py +56 -0
  452. vispy/visuals/scrolling_lines.py +197 -0
  453. vispy/visuals/shaders/__init__.py +17 -0
  454. vispy/visuals/shaders/compiler.py +206 -0
  455. vispy/visuals/shaders/expression.py +99 -0
  456. vispy/visuals/shaders/function.py +788 -0
  457. vispy/visuals/shaders/multiprogram.py +145 -0
  458. vispy/visuals/shaders/parsing.py +140 -0
  459. vispy/visuals/shaders/program.py +161 -0
  460. vispy/visuals/shaders/shader_object.py +162 -0
  461. vispy/visuals/shaders/tests/__init__.py +0 -0
  462. vispy/visuals/shaders/tests/test_function.py +486 -0
  463. vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
  464. vispy/visuals/shaders/tests/test_parsing.py +57 -0
  465. vispy/visuals/shaders/variable.py +272 -0
  466. vispy/visuals/spectrogram.py +169 -0
  467. vispy/visuals/sphere.py +80 -0
  468. vispy/visuals/surface_plot.py +192 -0
  469. vispy/visuals/tests/__init__.py +0 -0
  470. vispy/visuals/tests/test_arrows.py +109 -0
  471. vispy/visuals/tests/test_axis.py +120 -0
  472. vispy/visuals/tests/test_collections.py +15 -0
  473. vispy/visuals/tests/test_colorbar.py +179 -0
  474. vispy/visuals/tests/test_colormap.py +97 -0
  475. vispy/visuals/tests/test_ellipse.py +122 -0
  476. vispy/visuals/tests/test_gridlines.py +30 -0
  477. vispy/visuals/tests/test_histogram.py +24 -0
  478. vispy/visuals/tests/test_image.py +392 -0
  479. vispy/visuals/tests/test_image_complex.py +36 -0
  480. vispy/visuals/tests/test_infinite_line.py +53 -0
  481. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  482. vispy/visuals/tests/test_isosurface.py +22 -0
  483. vispy/visuals/tests/test_linear_region.py +152 -0
  484. vispy/visuals/tests/test_markers.py +54 -0
  485. vispy/visuals/tests/test_mesh.py +261 -0
  486. vispy/visuals/tests/test_mesh_normals.py +218 -0
  487. vispy/visuals/tests/test_polygon.py +112 -0
  488. vispy/visuals/tests/test_rectangle.py +163 -0
  489. vispy/visuals/tests/test_regular_polygon.py +111 -0
  490. vispy/visuals/tests/test_scalable_textures.py +196 -0
  491. vispy/visuals/tests/test_sdf.py +73 -0
  492. vispy/visuals/tests/test_spectrogram.py +42 -0
  493. vispy/visuals/tests/test_surface_plot.py +57 -0
  494. vispy/visuals/tests/test_text.py +95 -0
  495. vispy/visuals/tests/test_volume.py +542 -0
  496. vispy/visuals/tests/test_windbarb.py +33 -0
  497. vispy/visuals/text/__init__.py +7 -0
  498. vispy/visuals/text/_sdf_cpu.cpython-313-aarch64-linux-gnu.so +0 -0
  499. vispy/visuals/text/_sdf_cpu.pyx +112 -0
  500. vispy/visuals/text/_sdf_gpu.py +316 -0
  501. vispy/visuals/text/text.py +675 -0
  502. vispy/visuals/transforms/__init__.py +34 -0
  503. vispy/visuals/transforms/_util.py +191 -0
  504. vispy/visuals/transforms/base_transform.py +233 -0
  505. vispy/visuals/transforms/chain.py +300 -0
  506. vispy/visuals/transforms/interactive.py +98 -0
  507. vispy/visuals/transforms/linear.py +564 -0
  508. vispy/visuals/transforms/nonlinear.py +398 -0
  509. vispy/visuals/transforms/tests/__init__.py +0 -0
  510. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  511. vispy/visuals/transforms/transform_system.py +339 -0
  512. vispy/visuals/tube.py +173 -0
  513. vispy/visuals/visual.py +923 -0
  514. vispy/visuals/volume.py +1366 -0
  515. vispy/visuals/windbarb.py +291 -0
  516. vispy/visuals/xyz_axis.py +34 -0
  517. vispy-0.15.0.dist-info/METADATA +243 -0
  518. vispy-0.15.0.dist-info/RECORD +521 -0
  519. vispy-0.15.0.dist-info/WHEEL +6 -0
  520. vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
  521. vispy-0.15.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -----------------------------------------------------------------------------
3
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
4
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
5
+ # -----------------------------------------------------------------------------
6
+
7
+ import os
8
+ from os import path as op
9
+ import warnings
10
+
11
+
12
+ from ctypes import (cast, byref, sizeof, create_unicode_buffer,
13
+ c_void_p, c_wchar_p)
14
+ from ...ext.gdi32plus import (gdiplus, gdi32, user32, winreg, LOGFONT,
15
+ OUTLINETEXTMETRIC, GM_ADVANCED, FW_NORMAL,
16
+ FW_BOLD, LF_FACESIZE, DEFAULT_CHARSET,
17
+ TRUETYPE_FONTTYPE, FONTENUMPROC, BOOL)
18
+
19
+
20
+ # Inspired by:
21
+ # http://forums.codeguru.com/showthread.php?90792-How-to-get-a-system-
22
+ # font-file-name-given-a-LOGFONT-face-name
23
+
24
+ # XXX This isn't perfect, but it should work for now...
25
+
26
+ def find_font(face, bold, italic, orig_face=None):
27
+ style_dict = {'Regular': 0, 'Bold': 1, 'Italic': 2, 'Bold Italic': 3}
28
+
29
+ # Figure out which font to actually use by trying to instantiate by name
30
+ dc = user32.GetDC(0) # noqa, analysis:ignore
31
+ gdi32.SetGraphicsMode(dc, GM_ADVANCED) # only TT and OT fonts
32
+ logfont = LOGFONT()
33
+ logfont.lfHeight = -12 # conv point to pixels
34
+ logfont.lfWeight = FW_BOLD if bold else FW_NORMAL
35
+ logfont.lfItalic = italic
36
+ logfont.lfFaceName = face # logfont needs Unicode
37
+ hfont = gdi32.CreateFontIndirectW(byref(logfont))
38
+ original = gdi32.SelectObject(dc, hfont)
39
+ n_byte = gdi32.GetOutlineTextMetricsW(dc, 0, None)
40
+ assert n_byte > 0
41
+ metrics = OUTLINETEXTMETRIC()
42
+ assert sizeof(metrics) >= n_byte
43
+ assert gdi32.GetOutlineTextMetricsW(dc, n_byte, byref(metrics))
44
+ gdi32.SelectObject(dc, original)
45
+ user32.ReleaseDC(None, dc)
46
+ use_face = cast(byref(metrics, metrics.otmpFamilyName), c_wchar_p).value
47
+ if use_face != face:
48
+ warnings.warn('Could not find face match "%s", falling back to "%s"'
49
+ % (orig_face or face, use_face))
50
+ use_style = cast(byref(metrics, metrics.otmpStyleName), c_wchar_p).value
51
+ use_style = style_dict.get(use_style, 'Regular')
52
+ # AK: I get "Standaard" for use_style, which is Dutch for standard/regular
53
+
54
+ # Now we match by creating private font collections until we find
55
+ # the one that was used
56
+ font_dir = op.join(os.environ['WINDIR'], 'Fonts')
57
+ reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
58
+ key = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts'
59
+ reg_vals = winreg.OpenKey(reg, key)
60
+ n_values = winreg.QueryInfoKey(reg_vals)[1]
61
+ fname = None
62
+ for vi in range(n_values):
63
+ name, ff = winreg.EnumValue(reg_vals, vi)[:2]
64
+ if name.endswith('(TrueType)'):
65
+ ff = op.join(font_dir, ff) if op.basename(ff) == ff else ff
66
+ assert op.isfile(ff)
67
+ pc = c_void_p()
68
+ assert gdiplus.GdipNewPrivateFontCollection(byref(pc)) == 0
69
+ gdiplus.GdipPrivateAddFontFile(pc, ff)
70
+ family = c_void_p()
71
+ if gdiplus.GdipCreateFontFamilyFromName(use_face, pc,
72
+ byref(family)) == 0:
73
+ val = BOOL()
74
+ assert gdiplus.GdipIsStyleAvailable(family, use_style,
75
+ byref(val)) == 0
76
+ if val.value:
77
+ buf = create_unicode_buffer(LF_FACESIZE)
78
+ assert gdiplus.GdipGetFamilyName(family, buf, 0) == 0
79
+ assert buf.value == use_face
80
+ fname = ff
81
+ break
82
+ fname = fname or find_font('', bold, italic, face) # fall back to default
83
+ return fname
84
+
85
+
86
+ def _list_fonts():
87
+ dc = user32.GetDC(0)
88
+ gdi32.SetGraphicsMode(dc, GM_ADVANCED) # only TT and OT fonts
89
+ logfont = LOGFONT()
90
+ logfont.lfCharSet = DEFAULT_CHARSET
91
+ logfont.lfFaceName = ''
92
+ logfont.lfPitchandFamily = 0
93
+ fonts = list()
94
+
95
+ def enum_fun(lp_logfont, lp_text_metric, font_type, l_param):
96
+ # Only support TTF for now (silly Windows shortcomings)
97
+ if font_type == TRUETYPE_FONTTYPE:
98
+ font = lp_logfont.contents.lfFaceName
99
+ if not font.startswith('@') and font not in fonts:
100
+ fonts.append(font)
101
+ return 1
102
+
103
+ gdi32.EnumFontFamiliesExW(dc, byref(logfont), FONTENUMPROC(enum_fun), 0, 0)
104
+ user32.ReleaseDC(None, dc)
105
+ return fonts
Binary file
File without changes
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+
5
+ import numpy as np
6
+ import warnings
7
+
8
+ from vispy.testing import assert_in, run_tests_if_main
9
+ from vispy.util.fonts import list_fonts, _load_glyph, _vispy_fonts
10
+ import pytest
11
+
12
+ known_bad_fonts = set([
13
+ 'Noto Color Emoji', # https://github.com/vispy/vispy/issues/1771
14
+ 'Bahnschrift', # https://github.com/vispy/vispy/pull/1974
15
+ ])
16
+
17
+ # try both a vispy and system font <--- what does this mean???
18
+ sys_fonts = set(list_fonts()) - set(_vispy_fonts)
19
+
20
+
21
+ def test_font_list():
22
+ """Test font listing"""
23
+ f = list_fonts()
24
+ assert len(f) > 0
25
+ for font in _vispy_fonts:
26
+ assert_in(font, f)
27
+
28
+
29
+ @pytest.mark.parametrize('face', ['OpenSans'] + sorted(sys_fonts))
30
+ def test_font_glyph(face):
31
+ """Test loading glyphs"""
32
+ if face in known_bad_fonts or face.split(" ")[0] in known_bad_fonts:
33
+ pytest.xfail()
34
+ font_dict = dict(face=face, size=12, bold=False, italic=False)
35
+ glyphs_dict = dict()
36
+ chars = 'foobar^C&#'
37
+ for char in chars:
38
+ # Warning that Arial might not exist
39
+ with warnings.catch_warnings(record=True):
40
+ warnings.simplefilter('always')
41
+ _load_glyph(font_dict, char, glyphs_dict)
42
+ assert len(glyphs_dict) == np.unique([c for c in chars]).size
43
+
44
+
45
+ run_tests_if_main()
vispy/util/fourier.py ADDED
@@ -0,0 +1,69 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+
5
+ import numpy as np
6
+
7
+
8
+ def stft(x, n_fft=1024, step=512, fs=2*np.pi, window='hann'):
9
+ """Compute the STFT
10
+
11
+ Parameters
12
+ ----------
13
+ x : array-like
14
+ 1D signal to operate on. ``If len(x) < n_fft``, x will be zero-padded
15
+ to length ``n_fft``.
16
+ n_fft : int
17
+ Number of FFT points. Much faster for powers of two.
18
+ step : int | None
19
+ Step size between calculations. If None, ``n_fft // 2``
20
+ will be used.
21
+ fs : float
22
+ The sample rate of the data.
23
+ window : str | None
24
+ Window function to use. Can be ``'hann'`` for Hann window, or None
25
+ for no windowing.
26
+
27
+ Returns
28
+ -------
29
+ stft : ndarray
30
+ Spectrogram of the data, shape (n_freqs, n_steps).
31
+
32
+ See also
33
+ --------
34
+ fft_freqs
35
+ """
36
+ x = np.asarray(x, float)
37
+ if x.ndim != 1:
38
+ raise ValueError('x must be 1D')
39
+ if window is not None:
40
+ if window not in ('hann',):
41
+ raise ValueError('window must be "hann" or None')
42
+ w = np.hanning(n_fft)
43
+ else:
44
+ w = np.ones(n_fft)
45
+ n_fft = int(n_fft)
46
+ step = max(n_fft // 2, 1) if step is None else int(step)
47
+ fs = float(fs)
48
+ zero_pad = n_fft - len(x)
49
+ if zero_pad > 0:
50
+ x = np.concatenate((x, np.zeros(zero_pad, float)))
51
+ n_freqs = n_fft // 2 + 1
52
+ n_estimates = (len(x) - n_fft) // step + 1
53
+ result = np.empty((n_freqs, n_estimates), np.complex128)
54
+ for ii in range(n_estimates):
55
+ result[:, ii] = np.fft.rfft(w * x[ii * step:ii * step + n_fft]) / n_fft
56
+ return result
57
+
58
+
59
+ def fft_freqs(n_fft, fs):
60
+ """Return frequencies for DFT
61
+
62
+ Parameters
63
+ ----------
64
+ n_fft : int
65
+ Number of points in the FFT.
66
+ fs : float
67
+ The sampling rate.
68
+ """
69
+ return np.arange(0, (n_fft // 2 + 1)) / float(n_fft) * float(fs)
vispy/util/frozen.py ADDED
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+
5
+
6
+ # Class adapted from:
7
+ # http://stackoverflow.com/questions/3603502/
8
+
9
+ class Frozen(object):
10
+ __isfrozen = False
11
+
12
+ def __setattr__(self, key, value):
13
+ if self.__isfrozen and not hasattr(self, key):
14
+ raise AttributeError('%r is not an attribute of class %s. Call '
15
+ '"unfreeze()" to allow addition of new '
16
+ 'attributes' % (key, self))
17
+ object.__setattr__(self, key, value)
18
+
19
+ def freeze(self):
20
+ """Freeze the object so that only existing properties can be set"""
21
+ self.__isfrozen = True
22
+
23
+ def unfreeze(self):
24
+ """Unfreeze the object so that additional properties can be added"""
25
+ self.__isfrozen = False
@@ -0,0 +1,268 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+ """Scraper for sphinx-gallery.
5
+
6
+ This is used to collect screenshots from the examples when executed via
7
+ sphinx-gallery. This can be included in any project wanting to take
8
+ advantage of this by adding the following to your sphinx ``conf.py``:
9
+
10
+ .. code-block:: python
11
+
12
+ sphinx_gallery_conf = {
13
+ ...
14
+ 'image_scrapers': ('vispy',)
15
+ }
16
+
17
+ The scraper is provided to sphinx-gallery via the
18
+ ``vispy._get_sg_image_scraper()`` function.
19
+
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import os
25
+ import time
26
+ import shutil
27
+ from vispy.io import imsave
28
+ from vispy.gloo.util import _screenshot
29
+ from vispy.scene import SceneCanvas
30
+
31
+ from sphinx_gallery.scrapers import optipng, figure_rst
32
+
33
+
34
+ class VisPyGalleryScraper:
35
+ """Custom sphinx-gallery scraper to save the current Canvas to an image."""
36
+
37
+ def __repr__(self):
38
+ return self.__class__.__name__
39
+
40
+ def __call__(self, block, block_vars, gallery_conf):
41
+ """Scrape VisPy Canvases and applications.
42
+
43
+ Parameters
44
+ ----------
45
+ block : tuple
46
+ A tuple containing the (label, content, line_number) of the block.
47
+ block_vars : dict
48
+ Dict of block variables.
49
+ gallery_conf : dict
50
+ Contains the configuration of Sphinx-Gallery
51
+
52
+ Returns
53
+ -------
54
+ rst : str
55
+ The ReSTructuredText that will be rendered to HTML containing
56
+ the images. This is often produced by
57
+ :func:`sphinx_gallery.scrapers.figure_rst`.
58
+
59
+ """
60
+ example_fn = block_vars["src_file"]
61
+ frame_num_list = self._get_frame_list_from_source(example_fn)
62
+ image_path_iterator = block_vars['image_path_iterator']
63
+ canvas_or_widget = get_canvaslike_from_globals(block_vars["example_globals"])
64
+ if not frame_num_list:
65
+ image_paths = []
66
+ elif isinstance(frame_num_list[0], str):
67
+ # example produces an image/animation as output
68
+ image_paths = []
69
+ for frame_image, image_path in zip(frame_num_list, image_path_iterator):
70
+ image_path = os.path.splitext(image_path)[0] + os.path.splitext(frame_image)[1]
71
+ shutil.move(frame_image, image_path)
72
+ image_paths.append(image_path)
73
+ else:
74
+ image_paths = self._save_example_to_files(
75
+ canvas_or_widget, frame_num_list, gallery_conf, image_path_iterator)
76
+
77
+ fig_titles = "" # alt text
78
+ # FUTURE: Handle non-images (ex. MP4s) with raw HTML
79
+ return figure_rst(image_paths, gallery_conf['src_dir'], fig_titles)
80
+
81
+ def _save_example_to_files(self, canvas_or_widget, frame_num_list, gallery_conf, image_path_iterator):
82
+ image_path = next(image_path_iterator)
83
+ frame_grabber = FrameGrabber(canvas_or_widget, frame_num_list)
84
+ frame_grabber.collect_frames()
85
+ if len(frame_num_list) > 1:
86
+ # let's make an animation
87
+ # FUTURE: mp4 with imageio?
88
+ image_path = os.path.splitext(image_path)[0] + ".gif"
89
+ frame_grabber.save_animation(image_path)
90
+ else:
91
+ frame_grabber.save_frame(image_path)
92
+ frame_grabber.cleanup()
93
+ if 'images' in gallery_conf['compress_images']:
94
+ optipng(image_path, gallery_conf['compress_images_args'])
95
+ return [image_path]
96
+
97
+ def _get_frame_list_from_source(self, filename):
98
+ lines = open(filename, 'rb').read().decode('utf-8').splitlines()
99
+ for line in lines[:10]:
100
+ if not line.startswith("# vispy:"):
101
+ continue
102
+ if "gallery-exports" in line:
103
+ _frames = line.split('gallery-exports')[1].split(',')[0].strip()
104
+ frames = self._frame_exports_to_list(_frames)
105
+ break
106
+ if "gallery " in line:
107
+ # Get what frames to grab
108
+ _frames = line.split('gallery')[1].split(',')[0].strip()
109
+ frames = self._frame_specifier_to_list(_frames)
110
+ break
111
+ else:
112
+ # no frame number hint - don't grab any frames
113
+ frames = []
114
+ return frames
115
+
116
+ def _frame_specifier_to_list(self, frame_specifier):
117
+ _frames = frame_specifier or '0'
118
+ frames = [int(i) for i in _frames.split(':')]
119
+ if not frames:
120
+ frames = [5]
121
+ if len(frames) > 1:
122
+ frames = list(range(*frames))
123
+ return frames
124
+
125
+ def _frame_exports_to_list(self, frame_specifier):
126
+ frames = frame_specifier.split(" ")
127
+ frame_paths = []
128
+ for frame_fn in frames:
129
+ # existing image file created by the example
130
+ if not os.path.isfile(frame_fn):
131
+ raise FileNotFoundError(
132
+ "Example gallery frame specifier must be a frame number, "
133
+ "frame range, or relative filename produced by the example.")
134
+ frame_paths.append(frame_fn)
135
+ return frame_paths
136
+
137
+
138
+ def get_canvaslike_from_globals(globals_dict):
139
+ qt_widget = _get_qt_top_parent(globals_dict)
140
+ if qt_widget is not None:
141
+ return qt_widget
142
+
143
+ # Get canvas
144
+ if "canvas" in globals_dict:
145
+ return globals_dict["canvas"]
146
+ if "Canvas" in globals_dict:
147
+ return globals_dict["Canvas"]()
148
+ if "fig" in globals_dict:
149
+ return globals_dict["fig"]
150
+ return None
151
+
152
+
153
+ def _get_qt_top_parent(globals_dict):
154
+ if "QWidget" not in globals_dict and "QMainWindow" not in globals_dict and "QtWidgets" not in globals_dict:
155
+ return None
156
+
157
+ qtwidgets = globals_dict.get("QtWidgets")
158
+ qmainwindow = globals_dict.get("QMainWindow", getattr(qtwidgets, "QMainWindow", None))
159
+ qwidget = globals_dict.get("QWidget", getattr(qtwidgets, "QWidget", qmainwindow))
160
+ all_qt_widgets = [widget for widget in globals_dict.values()
161
+ if isinstance(widget, qwidget) and widget is not None]
162
+ all_qt_mains = [widget for widget in all_qt_widgets if isinstance(widget, qmainwindow)]
163
+ if all_qt_mains:
164
+ return all_qt_mains[0]
165
+ if all_qt_widgets:
166
+ return all_qt_widgets[0]
167
+ return None
168
+
169
+
170
+ class FrameGrabber:
171
+ """Helper to grab a series of screenshots from the current Canvas-like object."""
172
+
173
+ def __init__(self, canvas_obj, frame_grab_list: list[int]):
174
+ self._canvas = canvas_obj
175
+ self._done = False
176
+ self._current_frame = -1
177
+ self._collected_images = []
178
+ self._frames_to_grab = frame_grab_list[:] # copy so original list is preserved
179
+
180
+ def cleanup(self):
181
+ from PyQt5.QtWidgets import QApplication
182
+ for child_widget in QApplication.allWidgets():
183
+ if hasattr(child_widget, 'close'):
184
+ child_widget.close()
185
+ QApplication.processEvents()
186
+
187
+ def on_draw(self, _):
188
+ if self._done:
189
+ return # Grab only once
190
+ self._current_frame += 1
191
+ if self._current_frame in self._frames_to_grab:
192
+ self._frames_to_grab.remove(self._current_frame)
193
+ if isinstance(self._canvas, SceneCanvas):
194
+ im = self._canvas.render(alpha=True)
195
+ else:
196
+ im = _screenshot()
197
+ self._collected_images.append(im)
198
+ if not self._frames_to_grab or self._current_frame > self._frames_to_grab[0]:
199
+ self._done = True
200
+
201
+ def collect_frames(self):
202
+ """Show current Canvas and render and collect all frames requested."""
203
+ if self._is_qt_widget():
204
+ self._grab_qt_screenshot()
205
+ else:
206
+ self._grab_vispy_screenshots()
207
+
208
+ def _is_qt_widget(self):
209
+ try:
210
+ from PyQt5.QtWidgets import QWidget
211
+ except ImportError:
212
+ return False
213
+ return isinstance(self._canvas, QWidget)
214
+
215
+ def _grab_qt_screenshot(self):
216
+ from PyQt5.QtWidgets import QApplication
217
+ from PyQt5.QtCore import QTimer
218
+ self._canvas.show()
219
+ # Qt is going to grab from the screen so we need the window on top
220
+ self._canvas.raise_()
221
+ # We need to give the GUI event loop and OS time to draw everything
222
+ time.sleep(1.5)
223
+ QApplication.processEvents()
224
+ QTimer.singleShot(1000, self._grab_widget_screenshot)
225
+ time.sleep(1.5)
226
+ QApplication.processEvents()
227
+
228
+ def _grab_widget_screenshot(self):
229
+ from PyQt5.QtWidgets import QApplication
230
+ screen = QApplication.screenAt(self._canvas.pos())
231
+ screenshot = screen.grabWindow(int(self._canvas.windowHandle().winId()))
232
+ arr = self._qpixmap_to_ndarray(screenshot)
233
+ self._collected_images.append(arr)
234
+
235
+ @staticmethod
236
+ def _qpixmap_to_ndarray(pixmap):
237
+ from PyQt5 import QtGui
238
+ import numpy as np
239
+ im = pixmap.toImage().convertToFormat(QtGui.QImage.Format.Format_RGB32)
240
+ size = pixmap.size()
241
+ width = size.width()
242
+ height = size.height()
243
+ im_bits = im.constBits()
244
+ im_bits.setsize(height * width * 4)
245
+ # Convert 0xffRRGGBB buffer -> (B, G, R, 0xff) -> (R, G, B)
246
+ return np.array(im_bits).reshape((height, width, 4))[:, :, 2::-1]
247
+
248
+ def _grab_vispy_screenshots(self):
249
+ os.environ['VISPY_IGNORE_OLD_VERSION'] = 'true'
250
+ self._canvas.events.draw.connect(self.on_draw, position='last')
251
+ with self._canvas as c:
252
+ self._collect_frames(c)
253
+
254
+ def _collect_frames(self, canvas, limit=10000):
255
+ n = 0
256
+ while not self._done and n < limit:
257
+ canvas.update()
258
+ canvas.app.process_events()
259
+ n += 1
260
+ if n >= limit or len(self._frames_to_grab) > 0:
261
+ raise RuntimeError("Could not collect any images")
262
+
263
+ def save_frame(self, filename, frame_index=0):
264
+ imsave(filename, self._collected_images[frame_index])
265
+
266
+ def save_animation(self, filename):
267
+ import imageio # multiple gif not properly supported yet
268
+ imageio.mimsave(filename, self._collected_images)
vispy/util/keys.py ADDED
@@ -0,0 +1,91 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) Vispy Development Team. All Rights Reserved.
3
+ # Distributed under the (new) BSD License. See LICENSE.txt for more info.
4
+
5
+ """Define constants for keys.
6
+
7
+ Each key constant is defined as a Key object, which allows comparison with
8
+ strings (e.g. 'A', 'Escape', 'Shift'). This enables handling of key events
9
+ without using the key constants explicitly (e.g. ``if ev.key == 'Left':``).
10
+
11
+ In addition, key objects that represent characters can be matched to
12
+ the integer ordinal (e.g. 32 for space, 65 for A). This behavior is mainly
13
+ intended as a compatibility measure.
14
+
15
+ """
16
+
17
+
18
+ class Key(object):
19
+ """Represent the identity of a certain key.
20
+
21
+ This represents one or more names that the key in question is known by.
22
+
23
+ A Key object can be compared to one of its string names (case
24
+ insensitive), to the integer ordinal of the key (only for keys that
25
+ represent characters), and to another Key instance.
26
+ """
27
+
28
+ def __init__(self, *names):
29
+ self._names = names
30
+ self._names_upper = tuple([v.upper() for v in names])
31
+
32
+ @property
33
+ def name(self):
34
+ """The primary name of the key."""
35
+ return self._names[0]
36
+
37
+ def __hash__(self):
38
+ return self._names[0].__hash__()
39
+
40
+ def __repr__(self):
41
+ return "<Key %s>" % ', '.join([repr(v) for v in self._names])
42
+
43
+ def __eq__(self, other):
44
+ if isinstance(other, str):
45
+ return other.upper() in self._names_upper
46
+ elif isinstance(other, Key):
47
+ return self._names[0] == other
48
+ elif isinstance(other, int):
49
+ return other in [ord(v) for v in self._names_upper if len(v) == 1]
50
+ elif other is None:
51
+ return False
52
+ else:
53
+ raise ValueError('Key can only be compared to str, int and Key.')
54
+
55
+
56
+ SHIFT = Key('Shift')
57
+ CONTROL = Key('Control')
58
+ ALT = Key('Alt')
59
+ META = Key('Meta') # That Mac thingy
60
+
61
+ UP = Key('Up')
62
+ DOWN = Key('Down')
63
+ LEFT = Key('Left')
64
+ RIGHT = Key('Right')
65
+ PAGEUP = Key('PageUp')
66
+ PAGEDOWN = Key('PageDown')
67
+
68
+ INSERT = Key('Insert')
69
+ DELETE = Key('Delete')
70
+ HOME = Key('Home')
71
+ END = Key('End')
72
+
73
+ ESCAPE = Key('Escape')
74
+ BACKSPACE = Key('Backspace')
75
+
76
+ F1 = Key('F1')
77
+ F2 = Key('F2')
78
+ F3 = Key('F3')
79
+ F4 = Key('F4')
80
+ F5 = Key('F5')
81
+ F6 = Key('F6')
82
+ F7 = Key('F7')
83
+ F8 = Key('F8')
84
+ F9 = Key('F9')
85
+ F10 = Key('F10')
86
+ F11 = Key('F11')
87
+ F12 = Key('F12')
88
+
89
+ SPACE = Key('Space', ' ')
90
+ ENTER = Key('Enter', 'Return', '\n')
91
+ TAB = Key('Tab', '\t')