vispy 0.14.0__cp312-cp312-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 (519) 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 +968 -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 +1134 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +352 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1542 -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 +134 -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 +698 -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 +506 -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 +566 -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 +1816 -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 +1045 -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 +106 -0
  274. vispy/scene/cameras/base_camera.py +538 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +308 -0
  278. vispy/scene/cameras/perspective.py +333 -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 +173 -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 +446 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +473 -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 +17 -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 +4 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +485 -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 +163 -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 +796 -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 +105 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +688 -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 +810 -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_histogram.py +24 -0
  477. vispy/visuals/tests/test_image.py +390 -0
  478. vispy/visuals/tests/test_image_complex.py +36 -0
  479. vispy/visuals/tests/test_infinite_line.py +53 -0
  480. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  481. vispy/visuals/tests/test_isosurface.py +22 -0
  482. vispy/visuals/tests/test_linear_region.py +152 -0
  483. vispy/visuals/tests/test_markers.py +54 -0
  484. vispy/visuals/tests/test_mesh.py +261 -0
  485. vispy/visuals/tests/test_mesh_normals.py +218 -0
  486. vispy/visuals/tests/test_polygon.py +112 -0
  487. vispy/visuals/tests/test_rectangle.py +163 -0
  488. vispy/visuals/tests/test_regular_polygon.py +111 -0
  489. vispy/visuals/tests/test_scalable_textures.py +180 -0
  490. vispy/visuals/tests/test_sdf.py +73 -0
  491. vispy/visuals/tests/test_spectrogram.py +42 -0
  492. vispy/visuals/tests/test_text.py +95 -0
  493. vispy/visuals/tests/test_volume.py +542 -0
  494. vispy/visuals/tests/test_windbarb.py +33 -0
  495. vispy/visuals/text/__init__.py +7 -0
  496. vispy/visuals/text/_sdf_cpu.cpython-312-aarch64-linux-gnu.so +0 -0
  497. vispy/visuals/text/_sdf_cpu.pyx +110 -0
  498. vispy/visuals/text/_sdf_gpu.py +316 -0
  499. vispy/visuals/text/text.py +675 -0
  500. vispy/visuals/transforms/__init__.py +34 -0
  501. vispy/visuals/transforms/_util.py +191 -0
  502. vispy/visuals/transforms/base_transform.py +233 -0
  503. vispy/visuals/transforms/chain.py +300 -0
  504. vispy/visuals/transforms/interactive.py +98 -0
  505. vispy/visuals/transforms/linear.py +564 -0
  506. vispy/visuals/transforms/nonlinear.py +398 -0
  507. vispy/visuals/transforms/tests/__init__.py +0 -0
  508. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  509. vispy/visuals/transforms/transform_system.py +339 -0
  510. vispy/visuals/tube.py +173 -0
  511. vispy/visuals/visual.py +923 -0
  512. vispy/visuals/volume.py +1335 -0
  513. vispy/visuals/windbarb.py +291 -0
  514. vispy/visuals/xyz_axis.py +34 -0
  515. vispy-0.14.0.dist-info/LICENSE.txt +36 -0
  516. vispy-0.14.0.dist-info/METADATA +218 -0
  517. vispy-0.14.0.dist-info/RECORD +519 -0
  518. vispy-0.14.0.dist-info/WHEEL +6 -0
  519. vispy-0.14.0.dist-info/top_level.txt +1 -0
vispy/util/wrappers.py ADDED
@@ -0,0 +1,155 @@
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
+ Some wrappers to avoid circular imports, or make certain calls easier.
6
+
7
+ The idea of a 'global' vispy.use function is that although vispy.app
8
+ and vispy.gloo.gl can be used independently, they are not complely
9
+ independent for some configureation. E.g. when using real ES 2.0,
10
+ the app backend should use EGL and not a desktop OpenGL context. Also,
11
+ we probably want it to be easy to configure vispy to use the ipython
12
+ notebook backend, which requires specific config of both app and gl.
13
+
14
+ This module does not have to be aware of the available app and gl
15
+ backends, but it should be(come) aware of (in)compatibilities between
16
+ them.
17
+ """
18
+
19
+ import subprocess
20
+ from .config import _get_args
21
+
22
+
23
+ def use(app=None, gl=None):
24
+ """Set the usage options for vispy
25
+
26
+ Specify what app backend and GL backend to use.
27
+
28
+ Parameters
29
+ ----------
30
+ app : str
31
+ The app backend to use (case insensitive). Standard backends:
32
+ * 'PyQt4': use Qt widget toolkit via PyQt4.
33
+ * 'PyQt5': use Qt widget toolkit via PyQt5.
34
+ * 'PyQt6': use Qt widget toolkit via PyQt6.
35
+ * 'PySide': use Qt widget toolkit via PySide.
36
+ * 'PySide2': use Qt widget toolkit via PySide2.
37
+ * 'PySide6': use Qt widget toolkit via PySide6.
38
+ * 'PyGlet': use Pyglet backend.
39
+ * 'Glfw': use Glfw backend (successor of Glut). Widely available
40
+ on Linux.
41
+ * 'SDL2': use SDL v2 backend.
42
+ * 'osmesa': Use OSMesa backend
43
+ Additional backends:
44
+ * 'jupyter_rfb': show vispy canvases in Jupyter lab/notebook
45
+ (depends on the jupyter_rfb library).
46
+
47
+ gl : str
48
+ The gl backend to use (case insensitive). Options are:
49
+ * 'gl2': use Vispy's desktop OpenGL API.
50
+ * 'pyopengl2': use PyOpenGL's desktop OpenGL API. Mostly for
51
+ testing.
52
+ * 'es2': (TO COME) use real OpenGL ES 2.0 on Windows via Angle.
53
+ Availability of ES 2.0 is larger for Windows, since it relies
54
+ on DirectX.
55
+ * 'gl+': use the full OpenGL functionality available on
56
+ your system (via PyOpenGL).
57
+
58
+ Notes
59
+ -----
60
+ If the app option is given, ``vispy.app.use_app()`` is called. If
61
+ the gl option is given, ``vispy.gloo.use_gl()`` is called.
62
+
63
+ If an app backend name is provided, and that backend could not be
64
+ loaded, an error is raised.
65
+
66
+ If no backend name is provided, Vispy will first check if the GUI
67
+ toolkit corresponding to each backend is already imported, and try
68
+ that backend first. If this is unsuccessful, it will try the
69
+ 'default_backend' provided in the vispy config. If still not
70
+ succesful, it will try each backend in a predetermined order.
71
+
72
+ See Also
73
+ --------
74
+ vispy.app.use_app
75
+ vispy.gloo.gl.use_gl
76
+ """
77
+ if app is None and gl is None:
78
+ raise TypeError('Must specify at least one of "app" or "gl".')
79
+
80
+ if app == 'osmesa':
81
+ from ..util.osmesa_gl import fix_osmesa_gl_lib
82
+ fix_osmesa_gl_lib()
83
+ if gl is not None:
84
+ raise ValueError("Do not specify gl when using osmesa")
85
+
86
+ # Apply now
87
+ if gl:
88
+ from .. import gloo, config
89
+ config['gl_backend'] = gl
90
+ gloo.gl.use_gl(gl)
91
+ if app:
92
+ from ..app import use_app
93
+ use_app(app)
94
+
95
+
96
+ def run_subprocess(command, return_code=False, **kwargs):
97
+ """Run command using subprocess.Popen
98
+
99
+ Run command and wait for command to complete. If the return code was zero
100
+ then return, otherwise raise CalledProcessError.
101
+ By default, this will also add stdout= and stderr=subproces.PIPE
102
+ to the call to Popen to suppress printing to the terminal.
103
+
104
+ Parameters
105
+ ----------
106
+ command : list of str
107
+ Command to run as subprocess (see subprocess.Popen documentation).
108
+ return_code : bool
109
+ If True, the returncode will be returned, and no error checking
110
+ will be performed (so this function should always return without
111
+ error).
112
+ **kwargs : dict
113
+ Additional kwargs to pass to ``subprocess.Popen``.
114
+
115
+ Returns
116
+ -------
117
+ stdout : str
118
+ Stdout returned by the process.
119
+ stderr : str
120
+ Stderr returned by the process.
121
+ code : int
122
+ The command exit code. Only returned if ``return_code`` is True.
123
+ """
124
+ # code adapted with permission from mne-python
125
+ use_kwargs = dict(stderr=subprocess.PIPE, stdout=subprocess.PIPE)
126
+ use_kwargs.update(kwargs)
127
+
128
+ p = subprocess.Popen(command, **use_kwargs)
129
+ output = p.communicate()
130
+
131
+ # communicate() may return bytes, str, or None depending on the kwargs
132
+ # passed to Popen(). Convert all to unicode str:
133
+ output = ['' if s is None else s for s in output]
134
+ output = [s.decode('utf-8') if isinstance(s, bytes) else s for s in output]
135
+ output = tuple(output)
136
+
137
+ if not return_code and p.returncode:
138
+ print(output[0])
139
+ print(output[1])
140
+ err_fun = subprocess.CalledProcessError.__init__
141
+ if 'output' in _get_args(err_fun):
142
+ raise subprocess.CalledProcessError(p.returncode, command, output)
143
+ else:
144
+ raise subprocess.CalledProcessError(p.returncode, command)
145
+ if return_code:
146
+ output = output + (p.returncode,)
147
+ return output
148
+
149
+
150
+ def test(*args, **kwargs):
151
+ """Proxy function to delay `.testing` import"""
152
+ from vispy.testing import test as _test # noqa
153
+ return _test(*args, **kwargs)
154
+
155
+ test.__test__ = False # no discover test function as test
vispy/version.py ADDED
@@ -0,0 +1,4 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ __version__ = version = '0.14.0'
4
+ __version_tuple__ = version_tuple = (0, 14, 0)
@@ -0,0 +1,50 @@
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
+ This module provides a library of Visual classes, which are drawable objects
6
+ intended to encapsulate simple graphic objects such as lines, meshes, points,
7
+ 2D shapes, images, text, etc.
8
+
9
+ These classes define only the OpenGL machinery and connot be used directly in
10
+ a scenegraph. For scenegraph use, see the complementary Visual+Node classes
11
+ defined in vispy.scene.
12
+ """
13
+
14
+ from .axis import AxisVisual # noqa
15
+ from .box import BoxVisual # noqa
16
+ from .cube import CubeVisual # noqa
17
+ from .ellipse import EllipseVisual # noqa
18
+ from .gridlines import GridLinesVisual # noqa
19
+ from .image import ImageVisual # noqa
20
+ from .image_complex import ComplexImageVisual # noqa
21
+ from .gridmesh import GridMeshVisual # noqa
22
+ from .histogram import HistogramVisual # noqa
23
+ from .infinite_line import InfiniteLineVisual # noqa
24
+ from .instanced_mesh import InstancedMeshVisual # noqa
25
+ from .isocurve import IsocurveVisual # noqa
26
+ from .isoline import IsolineVisual # noqa
27
+ from .isosurface import IsosurfaceVisual # noqa
28
+ from .line import LineVisual, ArrowVisual # noqa
29
+ from .linear_region import LinearRegionVisual # noqa
30
+ from .line_plot import LinePlotVisual # noqa
31
+ from .markers import MarkersVisual # noqa
32
+ from .mesh import MeshVisual # noqa
33
+ from .mesh_normals import MeshNormalsVisual # noqa
34
+ from .plane import PlaneVisual # noqa
35
+ from .polygon import PolygonVisual # noqa
36
+ from .rectangle import RectangleVisual # noqa
37
+ from .regular_polygon import RegularPolygonVisual # noqa
38
+ from .scrolling_lines import ScrollingLinesVisual # noqa
39
+ from .spectrogram import SpectrogramVisual # noqa
40
+ from .sphere import SphereVisual # noqa
41
+ from .surface_plot import SurfacePlotVisual # noqa
42
+ from .text import TextVisual # noqa
43
+ from .tube import TubeVisual # noqa
44
+ from .visual import BaseVisual, Visual, CompoundVisual # noqa
45
+ from .volume import VolumeVisual # noqa
46
+ from .xyz_axis import XYZAxisVisual # noqa
47
+ from .border import _BorderVisual # noqa
48
+ from .colorbar import ColorBarVisual # noqa
49
+ from .graphs import GraphVisual # noqa
50
+ from .windbarb import WindbarbVisual # noqa
@@ -0,0 +1,485 @@
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
+ import warnings
5
+
6
+ import numpy as np
7
+
8
+ from vispy.gloo.texture import Texture2D, Texture3D, convert_dtype_and_clip
9
+
10
+
11
+ def get_default_clim_from_dtype(dtype):
12
+ """Get min and max color limits based on the range of the dtype."""
13
+ # assume floating point data is pre-normalized to 0 and 1
14
+ if np.issubdtype(dtype, np.floating):
15
+ return 0, 1
16
+ # assume integer RGBs fill the whole data space
17
+ dtype_info = np.iinfo(dtype)
18
+ dmin = dtype_info.min
19
+ dmax = dtype_info.max
20
+ return dmin, dmax
21
+
22
+
23
+ def get_default_clim_from_data(data):
24
+ """Compute a reasonable clim from the min and max, taking nans into account.
25
+
26
+ If there are no non-finite values (nan, inf, -inf) this is as fast as it can be.
27
+ Otherwise, this functions is about 3x slower.
28
+ """
29
+ # Fast
30
+ min_value = data.min()
31
+ max_value = data.max()
32
+
33
+ # Need more work? The nan-functions are slower
34
+ min_finite = np.isfinite(min_value)
35
+ max_finite = np.isfinite(max_value)
36
+ if not (min_finite and max_finite):
37
+ finite_data = data[np.isfinite(data)]
38
+ if finite_data.size:
39
+ min_value = finite_data.min()
40
+ max_value = finite_data.max()
41
+ else:
42
+ min_value = max_value = 0 # no finite values in the data
43
+
44
+ return min_value, max_value
45
+
46
+
47
+ class _ScaledTextureMixin:
48
+ """Mixin class to make a texture aware of color limits.
49
+
50
+ This class contains the shared functionality for the CPU and GPU mixin
51
+ classes below. In some cases this class provides a "generic"
52
+ implementation of a specific method and is then overridden by one of the
53
+ subclasses.
54
+
55
+ Parameters
56
+ ----------
57
+ data : ndarray | tuple | None
58
+ Texture data in the form of a numpy array. A tuple of the shape of the
59
+ texture can also be given. However, some subclasses may benefit from
60
+ or even require a numpy array to make decisions based on shape **and**
61
+ dtype.
62
+ **texture_kwargs
63
+ Any other keyword arguments to pass to the parent TextureXD class.
64
+
65
+ """
66
+
67
+ def __init__(self, data=None, **texture_kwargs):
68
+ self._clim = None
69
+ self._data_dtype = None
70
+ data, texture_kwargs = self.init_scaling_texture(data, **texture_kwargs)
71
+ # Call the __init__ of the TextureXD class
72
+ super().__init__(data, **texture_kwargs)
73
+
74
+ def init_scaling_texture(self, data=None, internalformat=None, **texture_kwargs):
75
+ """Initialize scaling properties and create a representative array."""
76
+ self._data_dtype = getattr(data, 'dtype', None)
77
+ data = self._create_rep_array(data)
78
+ internalformat = self._get_texture_format_for_data(
79
+ data,
80
+ internalformat)
81
+ texture_kwargs['internalformat'] = internalformat
82
+ return data, texture_kwargs
83
+
84
+ def _get_texture_format_for_data(self, data, internalformat):
85
+ return internalformat
86
+
87
+ @property
88
+ def clim(self):
89
+ """Color limits of the texture's data."""
90
+ return self._clim
91
+
92
+ def set_clim(self, clim):
93
+ """Set clim and return if a texture update is needed.
94
+
95
+ In this default implementation, it is assumed changing the color limit
96
+ never requires re-uploading the data to the texture (always return
97
+ ``False``).
98
+
99
+ """
100
+ need_texture_upload = False
101
+ if isinstance(clim, str):
102
+ if clim != 'auto':
103
+ raise ValueError('clim must be "auto" if a string')
104
+ self._clim = clim
105
+ else:
106
+ try:
107
+ cmin, cmax = clim
108
+ except (ValueError, TypeError):
109
+ raise ValueError('clim must have two elements')
110
+ self._clim = (cmin, cmax)
111
+ return need_texture_upload
112
+
113
+ @property
114
+ def clim_normalized(self):
115
+ """Normalize current clims to match texture data inside the shader.
116
+
117
+ If data is scaled on the CPU then the texture data will be in the range
118
+ 0-1 in the _build_texture() method. Inside the fragment shader the
119
+ final contrast adjustment will be applied based on this normalized
120
+ ``clim``.
121
+
122
+ """
123
+ if isinstance(self.clim, str) and self.clim == "auto":
124
+ raise RuntimeError("Can't return 'auto' normalized color limits "
125
+ "until data has been set. Call "
126
+ "'scale_and_set_data' first.")
127
+ if self._data_dtype is None:
128
+ raise RuntimeError("Can't return normalized color limits until "
129
+ "data has been set. Call "
130
+ "'scale_and_set_data' first.")
131
+ if self.clim[0] == self.clim[1]:
132
+ return self.clim[0], np.inf
133
+ # if the internalformat of the texture is normalized we need to
134
+ # also normalize the clims so they match in-shader
135
+ clim_min = self.normalize_value(self.clim[0], self._data_dtype)
136
+ clim_max = self.normalize_value(self.clim[1], self._data_dtype)
137
+ return clim_min, clim_max
138
+
139
+ @property
140
+ def is_normalized(self):
141
+ """Whether the in-shader representation of this texture is normalized or not.
142
+
143
+ Formats ending in 'f' (float), 'ui' (unsigned integer), or 'i'
144
+ (signed integer) are not normalized in the GPU. Formats ending in "_snorm"
145
+ are normalized on the range [-1, 1] based on the data type of the
146
+ input data (ex. 0-255 for uint8). Formats with no data type suffix are
147
+ normalized on the range [0, 1]. See
148
+ https://www.khronos.org/opengl/wiki/Image_Format for more information.
149
+
150
+ This property can be used to determine if input shader variables
151
+ (uniforms, template variables) need to also be normalized. See
152
+ :meth:`~BaseTexture.normalize_value` below.
153
+
154
+ """
155
+ if self.internalformat is None:
156
+ return True
157
+ return self.internalformat[-1] not in ('f', 'i')
158
+
159
+ def normalize_value(self, val, input_data_dtype):
160
+ """Normalize values to match in-shader representation of this shader.
161
+
162
+ Parameters
163
+ ----------
164
+ val : int | float | ndarray
165
+ Value(s) to normalize.
166
+ input_data_dtype : numpy.dtype
167
+ Data type of input data. The assumption is that the provided
168
+ values to be normalized are in the same range as the input
169
+ texture data and must be normalized in the same way.
170
+
171
+ """
172
+ if not self.is_normalized:
173
+ return val
174
+ dtype_info = np.iinfo(input_data_dtype)
175
+ dmin = dtype_info.min
176
+ dmax = dtype_info.max
177
+ val = (val - dmin) / (dmax - dmin)
178
+ # XXX: Do we need to handle _snorm differently?
179
+ # Not currently supported in vispy.
180
+ return val
181
+
182
+ def _data_num_channels(self, data):
183
+ # if format == 'luminance':
184
+ # num_channels = 1
185
+ if data is not None:
186
+ # array or shape tuple
187
+ ndim = getattr(data, 'ndim', len(data))
188
+ # Ex. (M, N, 3) in Texture2D (ndim=2) -> 3 channels
189
+ num_channels = data.shape[-1] if ndim == self._ndim + 1 else 1
190
+ else:
191
+ num_channels = 4
192
+ return num_channels
193
+
194
+ def _create_rep_array(self, data):
195
+ """Get a representative array with an initial shape.
196
+
197
+ Data will be filled in and the texture resized later.
198
+
199
+ """
200
+ dtype = getattr(data, 'dtype', np.float32)
201
+ num_channels = self._data_num_channels(data)
202
+ init_shape = (10,) * self._ndim + (num_channels,)
203
+ return np.zeros(init_shape).astype(dtype)
204
+
205
+ def check_data_format(self, data):
206
+ """Check if provided data will cause issues if set later."""
207
+ # this texture type has no limitations
208
+ return
209
+
210
+ def scale_and_set_data(self, data, offset=None, copy=False):
211
+ """Upload new data to the GPU."""
212
+ # we need to call super here or we get infinite recursion
213
+ return super().set_data(data, offset=offset, copy=copy)
214
+
215
+ def set_data(self, data, offset=None, copy=False):
216
+ self.scale_and_set_data(data, offset=offset, copy=copy)
217
+
218
+
219
+ class CPUScaledTextureMixin(_ScaledTextureMixin):
220
+ """Texture mixin class for smarter scaling decisions.
221
+
222
+ This class wraps the logic to normalize data on the CPU before sending
223
+ it to the GPU (the texture). Pre-scaling on the CPU can be helpful in
224
+ cases where OpenGL 2/ES requirements limit the texture storage to an
225
+ 8-bit normalized integer internally.
226
+
227
+ This class includes optimizations where image data is not re-normalized
228
+ if the previous normalization can still be used to visualize the data
229
+ with the new color limits.
230
+
231
+ This class should only be used internally. For similar features where
232
+ scaling occurs on the GPU see
233
+ :class:`vispy.visuals._scalable_textures.GPUScaledTextureMixin`.
234
+
235
+ To use this mixin, a subclass should be created to combine this mixin with
236
+ the texture class being used. Existing subclasses already exist in this
237
+ module. Note that this class **must** appear first in the subclass's parent
238
+ classes so that its ``__init__`` method is called instead of the parent
239
+ Texture class.
240
+
241
+ """
242
+
243
+ def __init__(self, data=None, **texture_kwargs):
244
+ self._data_limits = None
245
+ # Call the __init__ of the mixin base class
246
+ super().__init__(data, **texture_kwargs)
247
+
248
+ def _clim_outside_data_limits(self, cmin, cmax):
249
+ if self._data_limits is None:
250
+ return False
251
+ return cmin < self._data_limits[0] or cmax > self._data_limits[1]
252
+
253
+ def set_clim(self, clim):
254
+ """Set clim and return if a texture update is needed."""
255
+ need_texture_upload = False
256
+ # NOTE: Color limits are not checked against data type limits
257
+ if isinstance(clim, str):
258
+ if clim != 'auto':
259
+ raise ValueError('clim must be "auto" if a string')
260
+ need_texture_upload = True
261
+ self._clim = clim
262
+ else:
263
+ try:
264
+ cmin, cmax = clim
265
+ except (ValueError, TypeError):
266
+ raise ValueError('clim must have two elements')
267
+ if self._clim_outside_data_limits(cmin, cmax):
268
+ need_texture_upload = True
269
+ self._clim = (cmin, cmax)
270
+ return need_texture_upload
271
+
272
+ @property
273
+ def clim_normalized(self):
274
+ """Normalize current clims to match texture data inside the shader.
275
+
276
+ If data is scaled on the CPU then the texture data will be in the range
277
+ 0-1 in the _build_texture() method. Inside the fragment shader the
278
+ final contrast adjustment will be applied based on this normalized
279
+ ``clim``.
280
+
281
+ """
282
+ if isinstance(self.clim, str) and self.clim == "auto":
283
+ raise RuntimeError("Can't return 'auto' normalized color limits "
284
+ "until data has been set. Call "
285
+ "'scale_and_set_data' first.")
286
+ if self._data_limits is None:
287
+ raise RuntimeError("Can't return normalized color limits until "
288
+ "data has been set. Call "
289
+ "'scale_and_set_data' first.")
290
+
291
+ range_min, range_max = self._data_limits
292
+ clim_min, clim_max = self.clim
293
+ if clim_min == clim_max:
294
+ return 0, np.inf
295
+ clim_min = (clim_min - range_min) / (range_max - range_min)
296
+ clim_max = (clim_max - range_min) / (range_max - range_min)
297
+ return clim_min, clim_max
298
+
299
+ @staticmethod
300
+ def _scale_data_on_cpu(data, clim, copy=True):
301
+ data = np.array(data, dtype=np.float32, copy=copy)
302
+ if clim[0] != clim[1]:
303
+ # we always must copy the data if we change it here, otherwise it might change
304
+ # unexpectedly the data held outside of here
305
+ if not copy:
306
+ data = data.copy()
307
+ data -= clim[0]
308
+ data *= 1 / (clim[1] - clim[0])
309
+ return data
310
+
311
+ def scale_and_set_data(self, data, offset=None, copy=True):
312
+ """Upload new data to the GPU, scaling if necessary."""
313
+ if self._data_dtype is None:
314
+ data.dtype == self._data_dtype
315
+
316
+ # ensure dtype is the same as it was before, or funny things happen
317
+ # no copy is performed unless asked for or necessary
318
+ data = convert_dtype_and_clip(data, self._data_dtype, copy=copy)
319
+
320
+ clim = self._clim
321
+ is_auto = isinstance(clim, str) and clim == 'auto'
322
+ if data.ndim == self._ndim or data.shape[self._ndim] == 1:
323
+ if is_auto:
324
+ clim = get_default_clim_from_data(data)
325
+ data = self._scale_data_on_cpu(data, clim, copy=False)
326
+ data_limits = clim
327
+ else:
328
+ data_limits = get_default_clim_from_dtype(data.dtype)
329
+ if is_auto:
330
+ clim = data_limits
331
+
332
+ self._clim = float(clim[0]), float(clim[1])
333
+ self._data_limits = data_limits
334
+ return super().scale_and_set_data(data, offset=offset, copy=False)
335
+
336
+
337
+ class GPUScaledTextureMixin(_ScaledTextureMixin):
338
+ """Texture class for smarter scaling and internalformat decisions.
339
+
340
+ This texture class uses internal formats that are not supported by
341
+ strict OpenGL 2/ES drivers without additional extensions. By using
342
+ this texture we upload data to the GPU in a format as close to
343
+ the original data type as possible (32-bit floats on the CPU are 32-bit
344
+ floats on the GPU). No normalization/scaling happens on the CPU and
345
+ all of it happens on the GPU. This should avoid unnecessary data copies
346
+ as well as provide the highest precision for the final visualization.
347
+
348
+ The texture format may either be a GL enum string (ex. 'r32f'), a numpy
349
+ dtype object (ex. np.float32), or 'auto' which means the texture will
350
+ try to pick the best format for the provided data. By using 'auto' you
351
+ also give the texture permission to change formats in the future if
352
+ new data is provided with a different data type.
353
+
354
+ This class should only be used internally. For similar features where
355
+ scaling occurs on the CPU see
356
+ :class:`vispy.visuals._scalable_textures.CPUScaledTextureMixin`.
357
+
358
+ To use this mixin, a subclass should be created to combine this mixin with
359
+ the texture class being used. Existing subclasses already exist in this
360
+ module. Note that this class **must** appear first in the subclass's parent
361
+ classes so that its ``__init__`` method is called instead of the parent
362
+ Texture class.
363
+
364
+ """
365
+
366
+ # dtype -> internalformat
367
+ # 'r' will be replaced (if needed) with rgb or rgba depending on number of bands
368
+ _texture_dtype_format = {
369
+ np.float32: 'r32f',
370
+ np.float64: 'r32f',
371
+ np.uint8: 'r8', # uint8 normalized
372
+ np.uint16: 'r16', # uint16 normalized
373
+ # np.int8: 'r8', # not supported, there are no signed-integer norm formats
374
+ # np.int16: 'r16',
375
+ # np.uint32: 'r32ui', # not supported, no normal formats for 32bit ints
376
+ # np.int32: 'r32i',
377
+ }
378
+ # instance variable that will be used later on
379
+ _auto_texture_format = False
380
+
381
+ def _handle_auto_texture_format(self, texture_format, data):
382
+ if isinstance(texture_format, str) and texture_format == 'auto':
383
+ if data is None:
384
+ warnings.warn("'texture_format' set to 'auto' but no data "
385
+ "provided. Falling back to CPU scaling.")
386
+ texture_format = None
387
+ else:
388
+ texture_format = data.dtype.type
389
+ self._auto_texture_format = True
390
+ return texture_format
391
+
392
+ def _get_gl_tex_format(self, texture_format, num_channels):
393
+ if texture_format and not isinstance(texture_format, str):
394
+ texture_format = np.dtype(texture_format).type
395
+ if texture_format not in self._texture_dtype_format:
396
+ raise ValueError("Can't determine internal texture format for '{}'".format(texture_format))
397
+ texture_format = self._texture_dtype_format[texture_format]
398
+ # adjust internalformat for format of data (RGBA vs L)
399
+ texture_format = texture_format.replace('r', 'rgba'[:num_channels])
400
+ return texture_format
401
+
402
+ def _get_texture_format_for_data(self, data, internalformat):
403
+ if internalformat is None:
404
+ raise ValueError("'internalformat' must be provided for GPU scaled textures.")
405
+ num_channels = self._data_num_channels(data)
406
+ texture_format = self._handle_auto_texture_format(internalformat, data)
407
+ texture_format = self._get_gl_tex_format(texture_format, num_channels)
408
+ return texture_format
409
+
410
+ def _compute_clim(self, data):
411
+ clim = self._clim
412
+ is_auto = isinstance(clim, str) and clim == 'auto'
413
+ if data.ndim == self._ndim or data.shape[2] == 1:
414
+ if is_auto:
415
+ clim = get_default_clim_from_data(data)
416
+ elif is_auto:
417
+ # assume that RGB data is already scaled (0, 1)
418
+ clim = get_default_clim_from_dtype(data.dtype)
419
+ return float(clim[0]), float(clim[1])
420
+
421
+ def _internalformat_will_change(self, data):
422
+ shape_repr = self._create_rep_array(data)
423
+ new_if = self._get_gl_tex_format(data.dtype, shape_repr.shape[-1])
424
+ return new_if != self.internalformat
425
+
426
+ def check_data_format(self, data):
427
+ """Check if provided data will cause issues if set later."""
428
+ if self._internalformat_will_change(data) and not self._auto_texture_format:
429
+ raise ValueError("Data being set would cause a format change "
430
+ "in the texture. This is only allowed when "
431
+ "'texture_format' is set to 'auto'.")
432
+
433
+ def _reformat_if_necessary(self, data):
434
+ if not self._internalformat_will_change(data):
435
+ return
436
+ if self._auto_texture_format:
437
+ shape_repr = self._create_rep_array(data)
438
+ internalformat = self._get_gl_tex_format(data.dtype, shape_repr.shape[-1])
439
+ self._resize(data.shape, internalformat=internalformat)
440
+ else:
441
+ raise RuntimeError("'internalformat' needs to change but "
442
+ "'texture_format' was not 'auto'.")
443
+
444
+ def scale_and_set_data(self, data, offset=None, copy=False):
445
+ """Upload new data to the GPU, scaling if necessary."""
446
+ self._reformat_if_necessary(data)
447
+ self._data_dtype = np.dtype(data.dtype)
448
+ self._clim = self._compute_clim(data)
449
+ return super().scale_and_set_data(data, offset=offset, copy=copy)
450
+
451
+
452
+ class CPUScaledTexture2D(CPUScaledTextureMixin, Texture2D):
453
+ """Texture class with clim scaling handling builtin.
454
+
455
+ See :class:`vispy.visuals._scalable_textures.CPUScaledTextureMixin` for
456
+ more information.
457
+
458
+ """
459
+
460
+
461
+ class GPUScaledTexture2D(GPUScaledTextureMixin, Texture2D):
462
+ """Texture class with clim scaling handling builtin.
463
+
464
+ See :class:`vispy.visuals._scalable_textures.GPUScaledTextureMixin` for
465
+ more information.
466
+
467
+ """
468
+
469
+
470
+ class CPUScaledTexture3D(CPUScaledTextureMixin, Texture3D):
471
+ """Texture class with clim scaling handling builtin.
472
+
473
+ See :class:`vispy.visuals._scalable_textures.CPUScaledTextureMixin` for
474
+ more information.
475
+
476
+ """
477
+
478
+
479
+ class GPUScaledTextured3D(GPUScaledTextureMixin, Texture3D):
480
+ """Texture class with clim scaling handling builtin.
481
+
482
+ See :class:`vispy.visuals._scalable_textures.GPUScaledTextureMixin` for
483
+ more information.
484
+
485
+ """