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
@@ -0,0 +1,542 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import pytest
4
+ import numpy as np
5
+ from vispy import scene
6
+
7
+ from vispy.testing import (TestingCanvas, requires_application,
8
+ run_tests_if_main, requires_pyopengl,
9
+ raises)
10
+ from vispy.testing.image_tester import assert_image_approved, downsample
11
+ from vispy.testing.rendered_array_tester import compare_render, max_for_dtype
12
+
13
+
14
+ @requires_pyopengl()
15
+ def test_volume():
16
+ vol = np.zeros((20, 20, 20), 'float32')
17
+ vol[8:16, 8:16, :] = 1.0
18
+
19
+ # Create
20
+ V = scene.visuals.Volume(vol)
21
+ assert V.clim == (0, 1)
22
+ assert V.method == 'mip'
23
+ assert V.interpolation == 'linear'
24
+
25
+ # Set wrong data
26
+ with raises(ValueError):
27
+ V.set_data(np.zeros((20, 20), 'float32'))
28
+
29
+ # Clim
30
+ V.set_data(vol, (0.5, 0.8))
31
+ assert V.clim == (0.5, 0.8)
32
+ with raises(ValueError):
33
+ V.set_data((0.5, 0.8, 1.0))
34
+
35
+ # Method
36
+ V.method = 'iso'
37
+ assert V.method == 'iso'
38
+
39
+ # Interpolation
40
+ V.interpolation = 'nearest'
41
+ assert V.interpolation == 'nearest'
42
+
43
+ # Step size
44
+ V.relative_step_size = 1.1
45
+ assert V.relative_step_size == 1.1
46
+ # Disallow 0 step size to avoid GPU stalling
47
+ with raises(ValueError):
48
+ V.relative_step_size = 0
49
+
50
+
51
+ @requires_pyopengl()
52
+ def test_volume_bounds():
53
+ vol = np.zeros((20, 30, 40), 'float32')
54
+ vol[8:16, 8:16, :] = 1.0
55
+
56
+ # Create
57
+ V = scene.visuals.Volume(vol)
58
+ assert V._compute_bounds(0, V) == (0, 40) # x
59
+ assert V._compute_bounds(1, V) == (0, 30) # y
60
+ assert V._compute_bounds(2, V) == (0, 20) # z
61
+
62
+
63
+ @requires_pyopengl()
64
+ @requires_application()
65
+ def test_volume_draw():
66
+ with TestingCanvas(bgcolor='k', size=(100, 100)) as c:
67
+ v = c.central_widget.add_view()
68
+ v.camera = 'turntable'
69
+ v.camera.fov = 70
70
+ # Create
71
+ np.random.seed(2376)
72
+ vol = np.random.normal(size=(20, 20, 20), loc=0.5, scale=0.2)
73
+ vol[8:16, 8:16, :] += 1.0
74
+ scene.visuals.Volume(vol, parent=v.scene) # noqa
75
+ v.camera.set_range()
76
+ assert_image_approved(c.render(), 'visuals/volume.png')
77
+
78
+
79
+ @requires_pyopengl()
80
+ @requires_application()
81
+ @pytest.mark.parametrize('clim_on_init', [False, True])
82
+ @pytest.mark.parametrize('texture_format', [None, '__dtype__', 'auto'])
83
+ @pytest.mark.parametrize('input_dtype', [np.uint8, np.uint16, np.float32, np.float64])
84
+ def test_volume_clims_and_gamma(texture_format, input_dtype, clim_on_init):
85
+ """Test volume visual with clims and gamma on shader.
86
+
87
+ Test is parameterized based on ``texture_format`` and should produce
88
+ relatively the same results for each format.
89
+
90
+ Currently just using np.ones since the angle of view made more complicated samples
91
+ challenging, but this confirms gamma and clims works in the shader.
92
+ The VolumeVisual defaults to the "grays" colormap so although we compare
93
+ data using RGBA arrays, each R/G/B channel should be the same.
94
+
95
+ """
96
+ size = (40, 40)
97
+ if texture_format == '__dtype__':
98
+ texture_format = input_dtype
99
+ np.random.seed(0) # make tests the same every time
100
+ data = _make_test_data(size[:1] * 3, input_dtype)
101
+ clim = (0, 1)
102
+ new_clim = (0.3, 0.8)
103
+ max = max_for_dtype(input_dtype)
104
+ if max != 1:
105
+ clim = (clim[0] * max, clim[1] * max)
106
+ new_clim = (new_clim[0] * max, new_clim[1] * max)
107
+
108
+ kwargs = {}
109
+ if clim_on_init:
110
+ kwargs['clim'] = clim
111
+ with TestingCanvas(size=size, bgcolor="k") as c:
112
+ v = c.central_widget.add_view(border_width=0)
113
+ volume = scene.visuals.Volume(
114
+ data,
115
+ interpolation='nearest',
116
+ parent=v.scene,
117
+ method='mip',
118
+ texture_format=texture_format,
119
+ **kwargs
120
+ )
121
+ v.camera = 'arcball'
122
+ v.camera.fov = 0
123
+ v.camera.scale_factor = 40.0
124
+ v.camera.center = (19.5, 19.5, 19.5)
125
+
126
+ rendered = c.render()
127
+ _dtype = rendered.dtype
128
+ shape_ratio = rendered.shape[0] // data.shape[0]
129
+ rendered1 = downsample(rendered, shape_ratio, axis=(0, 1)).astype(_dtype)
130
+ predicted = data.max(axis=1)
131
+ compare_render(predicted, rendered1)
132
+
133
+ # adjust contrast limits
134
+ volume.clim = new_clim
135
+ rendered2 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype)
136
+ scaled_data = (np.clip(data, new_clim[0], new_clim[1]) - new_clim[0]) / (new_clim[1] - new_clim[0])
137
+ predicted = scaled_data.max(axis=1)
138
+ compare_render(predicted, rendered2, previous_render=rendered)
139
+
140
+ # adjust gamma
141
+ volume.gamma = 2
142
+ rendered3 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype)
143
+ predicted = (scaled_data ** 2).max(axis=1)
144
+ compare_render(predicted, rendered3, previous_render=rendered2)
145
+
146
+
147
+ @requires_pyopengl()
148
+ @requires_application()
149
+ @pytest.mark.parametrize('method_name', scene.visuals.Volume._rendering_methods.keys())
150
+ def test_all_render_methods(method_name):
151
+ """Test that render methods don't produce any errors."""
152
+ size = (40, 40)
153
+ np.random.seed(0) # make tests the same every time
154
+ data = _make_test_data(size[:1] * 3, np.float32)
155
+ # modify the data for 'minip' method so that there is at least one segment
156
+ # of the volume with no 'empty'/zero space
157
+ data[:, :, 40 // 3: 2 * 40 // 3] = 1.0
158
+ clim = (0, 1)
159
+ kwargs = {}
160
+ with TestingCanvas(size=size, bgcolor="k") as c:
161
+ v = c.central_widget.add_view(border_width=0)
162
+ volume = scene.visuals.Volume(
163
+ data,
164
+ interpolation='nearest',
165
+ clim=clim,
166
+ parent=v.scene,
167
+ method=method_name,
168
+ **kwargs
169
+ )
170
+ v.camera = 'arcball'
171
+ v.camera.fov = 0
172
+ v.camera.scale_factor = 40.0
173
+ v.camera.center = (19.5, 19.5, 19.5)
174
+
175
+ assert volume.method == method_name
176
+ rendered = c.render()[..., :3]
177
+ # not all black
178
+ assert rendered.sum() != 0
179
+ # not all white
180
+ assert rendered.sum() != 255 * rendered.size
181
+
182
+
183
+ @requires_pyopengl()
184
+ @requires_application()
185
+ @pytest.mark.parametrize('texture_format', [None, 'auto'])
186
+ def test_equal_clims(texture_format):
187
+ """Test that equal clims produce a min cmap value."""
188
+ size = (40, 40)
189
+ np.random.seed(0) # make tests the same every time
190
+ data = _make_test_data(size[:1] * 3, np.float32)
191
+ with TestingCanvas(size=size, bgcolor="k") as c:
192
+ v = c.central_widget.add_view(border_width=0)
193
+ scene.visuals.Volume(
194
+ data,
195
+ interpolation='nearest',
196
+ clim=(128.0, 128.0), # equal clims
197
+ cmap='viridis', # something with a non-black min value
198
+ parent=v.scene,
199
+ method='mip',
200
+ texture_format=texture_format,
201
+ )
202
+ v.camera = 'arcball'
203
+ v.camera.fov = 0
204
+ v.camera.scale_factor = 40.0
205
+ v.camera.center = (19.5, 19.5, 19.5)
206
+
207
+ rendered = c.render()[..., :3]
208
+ # not all black
209
+ assert rendered.sum() != 0
210
+ # not all white
211
+ assert rendered.sum() != 255 * rendered.size
212
+ # should be all the same value
213
+ r_unique = np.unique(rendered[..., 0])
214
+ g_unique = np.unique(rendered[..., 1])
215
+ b_unique = np.unique(rendered[..., 2])
216
+ assert r_unique.size == 1
217
+ assert g_unique.size == 1
218
+ assert b_unique.size == 1
219
+
220
+
221
+ def _make_test_data(shape, input_dtype):
222
+ one_third = shape[0] // 3
223
+ two_third = 2 * one_third
224
+ data = np.zeros(shape, dtype=np.float64)
225
+ # 0.00 | 1.00 | 0.00
226
+ # 0.50 | 0.00 | 0.25
227
+ # 0.00 | 0.00 | 0.00
228
+ data[:, :one_third, one_third:two_third] = 1.0
229
+ data[:, one_third:two_third, :one_third] = 0.5
230
+ data[:, one_third:two_third, two_third:] = 0.25
231
+ max_val = max_for_dtype(input_dtype)
232
+ if max_val != 1:
233
+ data *= max_val
234
+ data = data.astype(input_dtype)
235
+ return data
236
+
237
+
238
+ @requires_pyopengl()
239
+ def test_set_data_does_not_change_input():
240
+ # Create volume
241
+ V = scene.visuals.Volume(np.zeros((20, 20, 20), dtype=np.float32))
242
+
243
+ # calling Volume.set_data() should NOT alter the values of the input array
244
+ # regardless of data type
245
+ vol = np.random.randint(0, 200, (20, 20, 20))
246
+ for dtype in ['uint8', 'int16', 'uint16', 'float32', 'float64']:
247
+ vol_copy = np.array(vol, dtype=dtype, copy=True)
248
+ # setting clim so that normalization would otherwise change the data
249
+ V.set_data(vol_copy, clim=(0, 200))
250
+ assert np.allclose(vol, vol_copy)
251
+
252
+ # dtype has to be the same as the one used to init the texture, or it will
253
+ # be first coerced to the same dtype as the init
254
+
255
+ vol2 = np.array(vol, dtype=np.float32, copy=True)
256
+ assert np.allclose(vol, vol2)
257
+ # we explicitly create a copy when data would be altered by the texture,
258
+ # no matter what the user asks, so the data outside should never change
259
+ V.set_data(vol2, clim=(0, 200), copy=False)
260
+ assert np.allclose(vol, vol2)
261
+
262
+
263
+ @requires_pyopengl()
264
+ def test_set_data_changes_shape():
265
+ dtype = np.float32
266
+ # Create initial volume
267
+ V = scene.visuals.Volume(np.zeros((20, 20, 20), dtype=dtype))
268
+
269
+ # Sending new three dimensional data of different shape should alter volume shape
270
+ vol = np.zeros((25, 25, 10), dtype=dtype)
271
+ V.set_data(vol)
272
+ assert V._vol_shape == (25, 25, 10)
273
+
274
+ # Sending data of dimension other than 3 should raise a ValueError
275
+ vol2 = np.zeros((20, 20), dtype=dtype)
276
+ with pytest.raises(ValueError):
277
+ V.set_data(vol2)
278
+
279
+ vol2 = np.zeros((20, 20, 20, 20), dtype=dtype)
280
+ with pytest.raises(ValueError):
281
+ V.set_data(vol2)
282
+
283
+
284
+ @requires_pyopengl()
285
+ @requires_application()
286
+ def test_changing_cmap():
287
+ """Test that changing colormaps updates the display."""
288
+ size = (40, 40)
289
+ np.random.seed(0) # make tests the same every time
290
+ data = _make_test_data(size[:1] * 3, np.float32)
291
+ cmap = 'grays'
292
+ test_cmaps = ('reds', 'greens', 'blues')
293
+ clim = (0, 1)
294
+ kwargs = {}
295
+ with TestingCanvas(size=size, bgcolor="k") as c:
296
+ v = c.central_widget.add_view(border_width=0)
297
+ volume = scene.visuals.Volume(
298
+ data,
299
+ interpolation='nearest',
300
+ clim=clim,
301
+ cmap=cmap,
302
+ parent=v.scene,
303
+ **kwargs
304
+ )
305
+ v.camera = 'arcball'
306
+ v.camera.fov = 0
307
+ v.camera.scale_factor = 40.0
308
+
309
+ # render with grays colormap
310
+ grays = c.render()
311
+
312
+ # update cmap, compare rendered array with the grays cmap render
313
+ for cmap in test_cmaps:
314
+ volume.cmap = cmap
315
+ current_cmap = c.render()
316
+ with pytest.raises(AssertionError):
317
+ np.testing.assert_allclose(grays, current_cmap)
318
+
319
+
320
+ @requires_pyopengl()
321
+ @requires_application()
322
+ def test_plane_depth():
323
+ with TestingCanvas(size=(80, 80)) as c:
324
+ v = c.central_widget.add_view(border_width=0)
325
+ v.camera = 'arcball'
326
+ v.camera.fov = 0
327
+ v.camera.center = (40, 40, 40)
328
+ v.camera.scale_factor = 80.0
329
+
330
+ # two planes at 45 degrees relative to the camera. If depth is set correctly, we should see one half
331
+ # of the screen red and the other half white
332
+ scene.visuals.Volume(
333
+ np.ones((80, 80, 80), dtype=np.uint8),
334
+ interpolation="nearest",
335
+ clim=(0, 1),
336
+ cmap="grays",
337
+ raycasting_mode="plane",
338
+ plane_normal=(0, 1, 1),
339
+ parent=v.scene,
340
+ )
341
+
342
+ scene.visuals.Volume(
343
+ np.ones((80, 80, 80), dtype=np.uint8),
344
+ interpolation="nearest",
345
+ clim=(0, 1),
346
+ cmap="reds",
347
+ raycasting_mode="plane",
348
+ plane_normal=(0, 1, -1),
349
+ parent=v.scene,
350
+ )
351
+
352
+ # render with grays colormap
353
+ rendered = c.render()
354
+ left = rendered[40, 20]
355
+ right = rendered[40, 60]
356
+ assert np.array_equal(left, [255, 0, 0, 255])
357
+ assert np.array_equal(right, [255, 255, 255, 255])
358
+
359
+
360
+ @requires_pyopengl()
361
+ @requires_application()
362
+ def test_volume_depth():
363
+ """Check that depth setting is properly performed for the volume visual
364
+
365
+ Render a volume with a blue ball in front of a red plane in front of a
366
+ blue plane, checking that the output image contains both red and blue pixels.
367
+ """
368
+ # A blue strip behind a red strip
369
+ # If depth is set correctly, we should see only red pixels
370
+ # the screen
371
+ blue_vol = np.zeros((80, 80, 80), dtype=np.uint8)
372
+ blue_vol[:, -1, :] = 1 # back plane blue
373
+ blue_vol[30:50, 30:50, 30:50] = 1 # blue in center
374
+
375
+ red_vol = np.zeros((80, 80, 80), dtype=np.uint8)
376
+ red_vol[:, -5, :] = 1 # red plane in front of blue plane
377
+
378
+ with TestingCanvas(size=(80, 80)) as c:
379
+ v = c.central_widget.add_view(border_width=0)
380
+ v.camera = 'arcball'
381
+ v.camera.fov = 0
382
+ v.camera.center = (40, 40, 40)
383
+ v.camera.scale_factor = 80.0
384
+
385
+ scene.visuals.Volume(
386
+ red_vol,
387
+ interpolation="nearest",
388
+ clim=(0, 1),
389
+ cmap="reds",
390
+ parent=v.scene,
391
+ )
392
+
393
+ scene.visuals.Volume(
394
+ blue_vol,
395
+ interpolation="nearest",
396
+ clim=(0, 1),
397
+ cmap="blues",
398
+ parent=v.scene,
399
+ )
400
+
401
+ # render
402
+ rendered = c.render()
403
+ reds = np.sum(rendered[:, :, 0])
404
+ greens = np.sum(rendered[:, :, 1])
405
+ blues = np.sum(rendered[:, :, 2])
406
+ assert reds > 0
407
+ np.testing.assert_allclose(greens, 0)
408
+ assert blues > 0
409
+
410
+
411
+ @requires_pyopengl()
412
+ @requires_application()
413
+ def test_mip_cutoff():
414
+ """
415
+ Ensure fragments are properly discarded based on the mip_cutoff
416
+ for the mip and attenuated_mip rendering methods
417
+ """
418
+ with TestingCanvas(size=(80, 80)) as c:
419
+ v = c.central_widget.add_view(border_width=0)
420
+ v.camera = 'arcball'
421
+ v.camera.fov = 0
422
+ v.camera.center = (40, 40, 40)
423
+ v.camera.scale_factor = 80.0
424
+
425
+ vol = scene.visuals.Volume(
426
+ np.ones((80, 80, 80), dtype=np.uint8),
427
+ interpolation="nearest",
428
+ clim=(0, 1),
429
+ cmap="grays",
430
+ parent=v.scene,
431
+ )
432
+
433
+ # we should see white
434
+ rendered = c.render()
435
+ assert np.array_equal(rendered[40, 40], [255, 255, 255, 255])
436
+
437
+ vol.mip_cutoff = 10
438
+ # we should see black
439
+ rendered = c.render()
440
+ assert np.array_equal(rendered[40, 40], [0, 0, 0, 255])
441
+
442
+ # repeat for attenuated_mip
443
+ vol.method = 'attenuated_mip'
444
+ vol.mip_cutoff = None
445
+
446
+ # we should see white
447
+ rendered = c.render()
448
+ assert np.array_equal(rendered[40, 40], [255, 255, 255, 255])
449
+
450
+ vol.mip_cutoff = 10
451
+ # we should see black
452
+ rendered = c.render()
453
+ assert np.array_equal(rendered[40, 40], [0, 0, 0, 255])
454
+
455
+
456
+ @requires_pyopengl()
457
+ @requires_application()
458
+ def test_minip_cutoff():
459
+ """
460
+ Ensure fragments are properly discarded based on the minip_cutoff
461
+ for the minip rendering method
462
+ """
463
+ with TestingCanvas(size=(80, 80)) as c:
464
+ v = c.central_widget.add_view(border_width=0)
465
+ v.camera = 'arcball'
466
+ v.camera.fov = 0
467
+ v.camera.center = (40, 40, 40)
468
+ v.camera.scale_factor = 120.0
469
+
470
+ # just surface of the cube is ones, but it should win over the twos inside
471
+ data = np.ones((80, 80, 80), dtype=np.uint8)
472
+ data[1:-1, 1:-1, 1:-1] = 2
473
+
474
+ vol = scene.visuals.Volume(
475
+ data,
476
+ interpolation="nearest",
477
+ method='minip',
478
+ clim=(0, 2),
479
+ cmap="grays",
480
+ parent=v.scene,
481
+ )
482
+
483
+ # we should see gray (half of cmap)
484
+ rendered = c.render()
485
+ assert np.array_equal(rendered[40, 40], [128, 128, 128, 255])
486
+
487
+ # discard fragments above -10 (everything)
488
+ vol.minip_cutoff = -10
489
+ # we should see black
490
+ rendered = c.render()
491
+ assert np.array_equal(rendered[40, 40], [0, 0, 0, 255])
492
+
493
+
494
+ @requires_pyopengl()
495
+ @requires_application()
496
+ def test_volume_set_data_different_dtype():
497
+ size = (80, 80)
498
+ data = np.array([[[0, 127]]], dtype=np.int8)
499
+ left = (40, 10)
500
+ right = (40, 70)
501
+ white = (255, 255, 255, 255)
502
+ black = (0, 0, 0, 255)
503
+
504
+ with TestingCanvas(size=size[::-1], bgcolor="w") as c:
505
+ view = c.central_widget.add_view()
506
+ view.camera = 'arcball'
507
+ view.camera.fov = 0
508
+ view.camera.center = 0.5, 0, 0
509
+ view.camera.scale_factor = 2
510
+ volume = scene.visuals.Volume(
511
+ data,
512
+ cmap='grays',
513
+ clim=[0, 127],
514
+ parent=view.scene
515
+ )
516
+
517
+ render = c.render()
518
+ assert np.allclose(render[left], black)
519
+ assert np.allclose(render[right], white)
520
+
521
+ # same data as float should change nothing
522
+ volume.set_data(data.astype(np.float32))
523
+ render = c.render()
524
+ assert np.allclose(render[left], black)
525
+ assert np.allclose(render[right], white)
526
+
527
+ # something inverted, different dtype
528
+ new_data = np.array([[[127, 0]]], dtype=np.float16)
529
+ volume.set_data(new_data)
530
+ render = c.render()
531
+ assert np.allclose(render[left], white)
532
+ assert np.allclose(render[right], black)
533
+
534
+ # out of bounds should clip (2000 > 127)
535
+ new_data = np.array([[[0, 2000]]], dtype=np.float64)
536
+ volume.set_data(new_data)
537
+ render = c.render()
538
+ assert np.allclose(render[left], black)
539
+ assert np.allclose(render[right], white)
540
+
541
+
542
+ run_tests_if_main()
@@ -0,0 +1,33 @@
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
+ from vispy.scene.visuals import Windbarb
7
+ from vispy.testing import (requires_application, TestingCanvas,
8
+ run_tests_if_main)
9
+ from vispy.testing.image_tester import assert_image_approved
10
+
11
+ length = 15.
12
+ gridx = np.arange(length, 376, length * 2, dtype=np.float32)
13
+ gridy = np.ones_like(gridx) * length
14
+ grid = np.stack((gridx, gridy), axis=-1)
15
+ origin = (length, length)
16
+ vectors = (grid - origin).astype(np.float32)
17
+ vectors[:] /= length // 2
18
+ vectors[:, 1] *= -1
19
+
20
+
21
+ @requires_application()
22
+ def test_windbarb_draw():
23
+ """Test drawing arrows without transforms"""
24
+ with TestingCanvas(size=(250, 33), bgcolor='white') as c:
25
+
26
+ Windbarb(pos=grid, wind=vectors,
27
+ trig=False,
28
+ edge_color='black',
29
+ face_color='black',
30
+ size=length, parent=c.scene)
31
+ assert_image_approved(c.render(), 'visuals/windbarb.png')
32
+
33
+ run_tests_if_main()
@@ -0,0 +1,7 @@
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
+ from .text import TextVisual # noqa
@@ -0,0 +1,110 @@
1
+ # cython: language_level=3, boundscheck=False, cdivision=True, wraparound=False, initializedcheck=False, nonecheck=False
2
+ # A Cython implementation of the "eight-points signed sequential Euclidean
3
+ # distance transform algorithm" (8SSEDT)
4
+
5
+ import numpy as np
6
+ cimport numpy as np
7
+ from libc.math cimport sqrt
8
+ cimport cython
9
+
10
+ __all__ = ['_get_distance_field']
11
+
12
+ dtype = np.float32
13
+ dtype_c = np.complex64
14
+ ctypedef np.float32_t DTYPE_t
15
+ ctypedef np.complex64_t DTYPE_ct
16
+
17
+ cdef DTYPE_ct MAX_VAL = (1e6 + 1e6j)
18
+
19
+
20
+ def _calc_distance_field(np.ndarray[DTYPE_t, ndim=2] pixels,
21
+ int w, int h, DTYPE_t sp_f):
22
+ # initialize grids
23
+ cdef np.ndarray[DTYPE_ct, ndim=2] g0_arr = np.zeros((h, w), dtype_c)
24
+ cdef np.ndarray[DTYPE_ct, ndim=2] g1_arr = np.zeros((h, w), dtype_c)
25
+ cdef DTYPE_ct[:, ::1] g0 = g0_arr
26
+ cdef DTYPE_ct[:, ::1] g1 = g1_arr
27
+ cdef DTYPE_t[:, :] pixels_view = pixels
28
+ cdef Py_ssize_t y, x
29
+ for y in range(h):
30
+ g0[y, 0] = MAX_VAL
31
+ g0[y, w-1] = MAX_VAL
32
+ g1[y, 0] = MAX_VAL
33
+ g1[y, w-1] = MAX_VAL
34
+ for x in range(1, w-1):
35
+ if pixels_view[y, x] > 0:
36
+ g0[y, x] = MAX_VAL
37
+ if pixels_view[y, x] < 1:
38
+ g1[y, x] = MAX_VAL
39
+ for x in range(w):
40
+ g0[0, x] = MAX_VAL
41
+ g0[h-1, x] = MAX_VAL
42
+ g1[0, x] = MAX_VAL
43
+ g1[h-1, x] = MAX_VAL
44
+
45
+ # Propagate grids
46
+ _propagate(g0)
47
+ _propagate(g1)
48
+
49
+ # Subtracting and normalizing
50
+ cdef DTYPE_t r_sp_f_2 = 1. / (sp_f * 2.)
51
+ for y in range(1, h-1):
52
+ for x in range(1, w-1):
53
+ pixels_view[y, x] = sqrt(dist(g0[y, x])) - sqrt(dist(g1[y, x]))
54
+ if pixels_view[y, x] < 0:
55
+ pixels_view[y, x] = (pixels_view[y, x] + sp_f) * r_sp_f_2
56
+ else:
57
+ pixels_view[y, x] = 0.5 + pixels_view[y, x] * r_sp_f_2
58
+ pixels_view[y, x] = max(min(pixels_view[y, x], 1), 0)
59
+
60
+
61
+ cdef inline Py_ssize_t compare(DTYPE_ct *cell, DTYPE_ct xy, DTYPE_t *current) noexcept nogil:
62
+ cdef DTYPE_t val = dist(xy)
63
+ if val < current[0]:
64
+ cell[0] = xy
65
+ current[0] = val
66
+
67
+
68
+ cdef DTYPE_t dist(DTYPE_ct val) noexcept nogil:
69
+ return val.real*val.real + val.imag*val.imag
70
+
71
+
72
+ cdef void _propagate(DTYPE_ct[:, :] grid) noexcept nogil:
73
+ cdef Py_ssize_t height = grid.shape[0]
74
+ cdef Py_ssize_t width = grid.shape[1]
75
+ cdef Py_ssize_t y, x
76
+ cdef DTYPE_t current
77
+ cdef DTYPE_ct a0, a1, a2, a3
78
+ a0 = -1
79
+ a1 = -1j
80
+ a2 = -1 - 1j
81
+ a3 = 1 - 1j
82
+ cdef DTYPE_ct b0=1
83
+ cdef DTYPE_ct c0=1, c1=1j, c2=-1+1j, c3=1+1j
84
+ cdef DTYPE_ct d0=-1
85
+ height -= 1
86
+ width -= 1
87
+ for y in range(1, height):
88
+ for x in range(1, width):
89
+ current = dist(grid[y, x])
90
+ # (-1, +0), (+0, -1), (-1, -1), (+1, -1)
91
+ compare(&grid[y, x], grid[y, x-1] + a0, &current)
92
+ compare(&grid[y, x], grid[y-1, x] + a1, &current)
93
+ compare(&grid[y, x], grid[y-1, x-1] + a2, &current)
94
+ compare(&grid[y, x], grid[y-1, x+1] + a3, &current)
95
+ for x in range(width - 1, 0, -1):
96
+ current = dist(grid[y, x])
97
+ # (+1, +0)
98
+ compare(&grid[y, x], grid[y, x+1] + b0, &current)
99
+ for y in range(height - 1, 0, -1):
100
+ for x in range(width - 1, 0, -1):
101
+ current = dist(grid[y, x])
102
+ # (+1, +0), (+0, +1), (-1, +1), (+1, +1)
103
+ compare(&grid[y, x], grid[y, x+1] + c0, &current)
104
+ compare(&grid[y, x], grid[y+1, x] + c1, &current)
105
+ compare(&grid[y, x], grid[y+1, x-1] + c2, &current)
106
+ compare(&grid[y, x], grid[y+1, x+1] + c3, &current)
107
+ for x in range(1, width):
108
+ current = dist(grid[y, x])
109
+ # (-1, +0)
110
+ compare(&grid[y, x], grid[y, x-1] + d0, &current)