vispy 0.15.0__cp313-cp313-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (521) hide show
  1. vispy/__init__.py +33 -0
  2. vispy/app/__init__.py +15 -0
  3. vispy/app/_default_app.py +76 -0
  4. vispy/app/_detect_eventloop.py +148 -0
  5. vispy/app/application.py +263 -0
  6. vispy/app/backends/__init__.py +52 -0
  7. vispy/app/backends/_egl.py +264 -0
  8. vispy/app/backends/_glfw.py +513 -0
  9. vispy/app/backends/_jupyter_rfb.py +278 -0
  10. vispy/app/backends/_offscreen_util.py +121 -0
  11. vispy/app/backends/_osmesa.py +235 -0
  12. vispy/app/backends/_pyglet.py +451 -0
  13. vispy/app/backends/_pyqt4.py +36 -0
  14. vispy/app/backends/_pyqt5.py +36 -0
  15. vispy/app/backends/_pyqt6.py +40 -0
  16. vispy/app/backends/_pyside.py +37 -0
  17. vispy/app/backends/_pyside2.py +52 -0
  18. vispy/app/backends/_pyside6.py +53 -0
  19. vispy/app/backends/_qt.py +1003 -0
  20. vispy/app/backends/_sdl2.py +444 -0
  21. vispy/app/backends/_template.py +244 -0
  22. vispy/app/backends/_test.py +8 -0
  23. vispy/app/backends/_tk.py +800 -0
  24. vispy/app/backends/_wx.py +476 -0
  25. vispy/app/backends/tests/__init__.py +0 -0
  26. vispy/app/backends/tests/test_offscreen_util.py +52 -0
  27. vispy/app/backends/tests/test_rfb.py +77 -0
  28. vispy/app/base.py +294 -0
  29. vispy/app/canvas.py +828 -0
  30. vispy/app/qt.py +92 -0
  31. vispy/app/tests/__init__.py +0 -0
  32. vispy/app/tests/qt-designer.ui +58 -0
  33. vispy/app/tests/test_app.py +442 -0
  34. vispy/app/tests/test_backends.py +164 -0
  35. vispy/app/tests/test_canvas.py +122 -0
  36. vispy/app/tests/test_context.py +92 -0
  37. vispy/app/tests/test_qt.py +47 -0
  38. vispy/app/tests/test_simultaneous.py +134 -0
  39. vispy/app/timer.py +174 -0
  40. vispy/color/__init__.py +17 -0
  41. vispy/color/_color_dict.py +193 -0
  42. vispy/color/color_array.py +447 -0
  43. vispy/color/color_space.py +181 -0
  44. vispy/color/colormap.py +1213 -0
  45. vispy/color/tests/__init__.py +0 -0
  46. vispy/color/tests/test_color.py +378 -0
  47. vispy/conftest.py +12 -0
  48. vispy/ext/__init__.py +0 -0
  49. vispy/ext/cocoapy.py +1522 -0
  50. vispy/ext/cubehelix.py +138 -0
  51. vispy/ext/egl.py +375 -0
  52. vispy/ext/fontconfig.py +118 -0
  53. vispy/ext/gdi32plus.py +206 -0
  54. vispy/ext/osmesa.py +105 -0
  55. vispy/geometry/__init__.py +23 -0
  56. vispy/geometry/_triangulation_debugger.py +171 -0
  57. vispy/geometry/calculations.py +162 -0
  58. vispy/geometry/curves.py +399 -0
  59. vispy/geometry/generation.py +643 -0
  60. vispy/geometry/isocurve.py +175 -0
  61. vispy/geometry/isosurface.py +465 -0
  62. vispy/geometry/meshdata.py +700 -0
  63. vispy/geometry/normals.py +78 -0
  64. vispy/geometry/parametric.py +56 -0
  65. vispy/geometry/polygon.py +137 -0
  66. vispy/geometry/rect.py +210 -0
  67. vispy/geometry/tests/__init__.py +0 -0
  68. vispy/geometry/tests/test_calculations.py +23 -0
  69. vispy/geometry/tests/test_generation.py +56 -0
  70. vispy/geometry/tests/test_meshdata.py +106 -0
  71. vispy/geometry/tests/test_triangulation.py +594 -0
  72. vispy/geometry/torusknot.py +142 -0
  73. vispy/geometry/triangulation.py +876 -0
  74. vispy/gloo/__init__.py +56 -0
  75. vispy/gloo/buffer.py +505 -0
  76. vispy/gloo/context.py +272 -0
  77. vispy/gloo/framebuffer.py +257 -0
  78. vispy/gloo/gl/__init__.py +234 -0
  79. vispy/gloo/gl/_constants.py +332 -0
  80. vispy/gloo/gl/_es2.py +986 -0
  81. vispy/gloo/gl/_gl2.py +1365 -0
  82. vispy/gloo/gl/_proxy.py +499 -0
  83. vispy/gloo/gl/_pyopengl2.py +362 -0
  84. vispy/gloo/gl/dummy.py +24 -0
  85. vispy/gloo/gl/es2.py +62 -0
  86. vispy/gloo/gl/gl2.py +98 -0
  87. vispy/gloo/gl/glplus.py +168 -0
  88. vispy/gloo/gl/pyopengl2.py +97 -0
  89. vispy/gloo/gl/tests/__init__.py +0 -0
  90. vispy/gloo/gl/tests/test_basics.py +282 -0
  91. vispy/gloo/gl/tests/test_functionality.py +568 -0
  92. vispy/gloo/gl/tests/test_names.py +246 -0
  93. vispy/gloo/gl/tests/test_use.py +71 -0
  94. vispy/gloo/glir.py +1824 -0
  95. vispy/gloo/globject.py +101 -0
  96. vispy/gloo/preprocessor.py +67 -0
  97. vispy/gloo/program.py +543 -0
  98. vispy/gloo/tests/__init__.py +0 -0
  99. vispy/gloo/tests/test_buffer.py +558 -0
  100. vispy/gloo/tests/test_context.py +119 -0
  101. vispy/gloo/tests/test_framebuffer.py +195 -0
  102. vispy/gloo/tests/test_glir.py +307 -0
  103. vispy/gloo/tests/test_globject.py +35 -0
  104. vispy/gloo/tests/test_program.py +302 -0
  105. vispy/gloo/tests/test_texture.py +732 -0
  106. vispy/gloo/tests/test_use_gloo.py +187 -0
  107. vispy/gloo/tests/test_util.py +60 -0
  108. vispy/gloo/tests/test_wrappers.py +261 -0
  109. vispy/gloo/texture.py +1046 -0
  110. vispy/gloo/util.py +129 -0
  111. vispy/gloo/wrappers.py +762 -0
  112. vispy/glsl/__init__.py +42 -0
  113. vispy/glsl/antialias/antialias.glsl +7 -0
  114. vispy/glsl/antialias/cap-butt.glsl +31 -0
  115. vispy/glsl/antialias/cap-round.glsl +29 -0
  116. vispy/glsl/antialias/cap-square.glsl +30 -0
  117. vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
  118. vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
  119. vispy/glsl/antialias/cap.glsl +67 -0
  120. vispy/glsl/antialias/caps.glsl +67 -0
  121. vispy/glsl/antialias/filled.glsl +50 -0
  122. vispy/glsl/antialias/outline.glsl +40 -0
  123. vispy/glsl/antialias/stroke.glsl +43 -0
  124. vispy/glsl/arrowheads/angle.glsl +99 -0
  125. vispy/glsl/arrowheads/arrowheads.frag +60 -0
  126. vispy/glsl/arrowheads/arrowheads.glsl +12 -0
  127. vispy/glsl/arrowheads/arrowheads.vert +83 -0
  128. vispy/glsl/arrowheads/curved.glsl +48 -0
  129. vispy/glsl/arrowheads/inhibitor.glsl +26 -0
  130. vispy/glsl/arrowheads/stealth.glsl +46 -0
  131. vispy/glsl/arrowheads/triangle.glsl +97 -0
  132. vispy/glsl/arrowheads/util.glsl +13 -0
  133. vispy/glsl/arrows/angle-30.glsl +12 -0
  134. vispy/glsl/arrows/angle-60.glsl +12 -0
  135. vispy/glsl/arrows/angle-90.glsl +12 -0
  136. vispy/glsl/arrows/arrow.frag +39 -0
  137. vispy/glsl/arrows/arrow.vert +49 -0
  138. vispy/glsl/arrows/arrows.glsl +17 -0
  139. vispy/glsl/arrows/common.glsl +187 -0
  140. vispy/glsl/arrows/curved.glsl +63 -0
  141. vispy/glsl/arrows/stealth.glsl +50 -0
  142. vispy/glsl/arrows/triangle-30.glsl +12 -0
  143. vispy/glsl/arrows/triangle-60.glsl +12 -0
  144. vispy/glsl/arrows/triangle-90.glsl +12 -0
  145. vispy/glsl/arrows/util.glsl +98 -0
  146. vispy/glsl/build_spatial_filters.py +660 -0
  147. vispy/glsl/collections/agg-fast-path.frag +20 -0
  148. vispy/glsl/collections/agg-fast-path.vert +78 -0
  149. vispy/glsl/collections/agg-glyph.frag +60 -0
  150. vispy/glsl/collections/agg-glyph.vert +33 -0
  151. vispy/glsl/collections/agg-marker.frag +35 -0
  152. vispy/glsl/collections/agg-marker.vert +48 -0
  153. vispy/glsl/collections/agg-path.frag +55 -0
  154. vispy/glsl/collections/agg-path.vert +166 -0
  155. vispy/glsl/collections/agg-point.frag +21 -0
  156. vispy/glsl/collections/agg-point.vert +35 -0
  157. vispy/glsl/collections/agg-segment.frag +32 -0
  158. vispy/glsl/collections/agg-segment.vert +75 -0
  159. vispy/glsl/collections/marker.frag +38 -0
  160. vispy/glsl/collections/marker.vert +48 -0
  161. vispy/glsl/collections/raw-path.frag +15 -0
  162. vispy/glsl/collections/raw-path.vert +24 -0
  163. vispy/glsl/collections/raw-point.frag +14 -0
  164. vispy/glsl/collections/raw-point.vert +31 -0
  165. vispy/glsl/collections/raw-segment.frag +18 -0
  166. vispy/glsl/collections/raw-segment.vert +26 -0
  167. vispy/glsl/collections/raw-triangle.frag +13 -0
  168. vispy/glsl/collections/raw-triangle.vert +26 -0
  169. vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
  170. vispy/glsl/collections/sdf-glyph.frag +80 -0
  171. vispy/glsl/collections/sdf-glyph.vert +59 -0
  172. vispy/glsl/collections/tick-labels.vert +71 -0
  173. vispy/glsl/colormaps/autumn.glsl +20 -0
  174. vispy/glsl/colormaps/blues.glsl +20 -0
  175. vispy/glsl/colormaps/color-space.glsl +17 -0
  176. vispy/glsl/colormaps/colormaps.glsl +24 -0
  177. vispy/glsl/colormaps/cool.glsl +20 -0
  178. vispy/glsl/colormaps/fire.glsl +21 -0
  179. vispy/glsl/colormaps/gray.glsl +20 -0
  180. vispy/glsl/colormaps/greens.glsl +20 -0
  181. vispy/glsl/colormaps/hot.glsl +22 -0
  182. vispy/glsl/colormaps/ice.glsl +20 -0
  183. vispy/glsl/colormaps/icefire.glsl +23 -0
  184. vispy/glsl/colormaps/parse.py +40 -0
  185. vispy/glsl/colormaps/reds.glsl +20 -0
  186. vispy/glsl/colormaps/spring.glsl +20 -0
  187. vispy/glsl/colormaps/summer.glsl +20 -0
  188. vispy/glsl/colormaps/user.glsl +22 -0
  189. vispy/glsl/colormaps/util.glsl +41 -0
  190. vispy/glsl/colormaps/wheel.glsl +21 -0
  191. vispy/glsl/colormaps/winter.glsl +20 -0
  192. vispy/glsl/lines/agg.frag +320 -0
  193. vispy/glsl/lines/agg.vert +241 -0
  194. vispy/glsl/markers/arrow.glsl +12 -0
  195. vispy/glsl/markers/asterisk.glsl +16 -0
  196. vispy/glsl/markers/chevron.glsl +14 -0
  197. vispy/glsl/markers/clover.glsl +20 -0
  198. vispy/glsl/markers/club.glsl +31 -0
  199. vispy/glsl/markers/cross.glsl +17 -0
  200. vispy/glsl/markers/diamond.glsl +12 -0
  201. vispy/glsl/markers/disc.glsl +9 -0
  202. vispy/glsl/markers/ellipse.glsl +67 -0
  203. vispy/glsl/markers/hbar.glsl +9 -0
  204. vispy/glsl/markers/heart.glsl +15 -0
  205. vispy/glsl/markers/infinity.glsl +15 -0
  206. vispy/glsl/markers/marker-sdf.frag +74 -0
  207. vispy/glsl/markers/marker-sdf.vert +41 -0
  208. vispy/glsl/markers/marker.frag +36 -0
  209. vispy/glsl/markers/marker.vert +46 -0
  210. vispy/glsl/markers/markers.glsl +24 -0
  211. vispy/glsl/markers/pin.glsl +18 -0
  212. vispy/glsl/markers/ring.glsl +11 -0
  213. vispy/glsl/markers/spade.glsl +28 -0
  214. vispy/glsl/markers/square.glsl +10 -0
  215. vispy/glsl/markers/tag.glsl +11 -0
  216. vispy/glsl/markers/triangle.glsl +14 -0
  217. vispy/glsl/markers/vbar.glsl +9 -0
  218. vispy/glsl/math/circle-through-2-points.glsl +30 -0
  219. vispy/glsl/math/constants.glsl +48 -0
  220. vispy/glsl/math/double.glsl +114 -0
  221. vispy/glsl/math/functions.glsl +20 -0
  222. vispy/glsl/math/point-to-line-distance.glsl +31 -0
  223. vispy/glsl/math/point-to-line-projection.glsl +29 -0
  224. vispy/glsl/math/signed-line-distance.glsl +27 -0
  225. vispy/glsl/math/signed-segment-distance.glsl +30 -0
  226. vispy/glsl/misc/regular-grid.frag +244 -0
  227. vispy/glsl/misc/spatial-filters.frag +1407 -0
  228. vispy/glsl/misc/viewport-NDC.glsl +20 -0
  229. vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
  230. vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
  231. vispy/glsl/transforms/hammer.glsl +44 -0
  232. vispy/glsl/transforms/identity.glsl +6 -0
  233. vispy/glsl/transforms/identity_forward.glsl +23 -0
  234. vispy/glsl/transforms/identity_inverse.glsl +23 -0
  235. vispy/glsl/transforms/linear-scale.glsl +127 -0
  236. vispy/glsl/transforms/log-scale.glsl +126 -0
  237. vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
  238. vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
  239. vispy/glsl/transforms/panzoom.glsl +10 -0
  240. vispy/glsl/transforms/polar.glsl +41 -0
  241. vispy/glsl/transforms/position.glsl +44 -0
  242. vispy/glsl/transforms/power-scale.glsl +139 -0
  243. vispy/glsl/transforms/projection.glsl +7 -0
  244. vispy/glsl/transforms/pvm.glsl +13 -0
  245. vispy/glsl/transforms/rotate.glsl +45 -0
  246. vispy/glsl/transforms/trackball.glsl +15 -0
  247. vispy/glsl/transforms/translate.glsl +35 -0
  248. vispy/glsl/transforms/transverse_mercator.glsl +38 -0
  249. vispy/glsl/transforms/viewport-clipping.glsl +14 -0
  250. vispy/glsl/transforms/viewport-transform.glsl +16 -0
  251. vispy/glsl/transforms/viewport.glsl +50 -0
  252. vispy/glsl/transforms/x.glsl +24 -0
  253. vispy/glsl/transforms/y.glsl +19 -0
  254. vispy/glsl/transforms/z.glsl +14 -0
  255. vispy/io/__init__.py +20 -0
  256. vispy/io/_data/spatial-filters.npy +0 -0
  257. vispy/io/datasets.py +94 -0
  258. vispy/io/image.py +231 -0
  259. vispy/io/mesh.py +122 -0
  260. vispy/io/stl.py +167 -0
  261. vispy/io/tests/__init__.py +0 -0
  262. vispy/io/tests/test_image.py +47 -0
  263. vispy/io/tests/test_io.py +121 -0
  264. vispy/io/wavefront.py +350 -0
  265. vispy/plot/__init__.py +36 -0
  266. vispy/plot/fig.py +58 -0
  267. vispy/plot/plotwidget.py +522 -0
  268. vispy/plot/tests/__init__.py +0 -0
  269. vispy/plot/tests/test_plot.py +46 -0
  270. vispy/scene/__init__.py +43 -0
  271. vispy/scene/cameras/__init__.py +27 -0
  272. vispy/scene/cameras/_base.py +38 -0
  273. vispy/scene/cameras/arcball.py +105 -0
  274. vispy/scene/cameras/base_camera.py +551 -0
  275. vispy/scene/cameras/fly.py +474 -0
  276. vispy/scene/cameras/magnify.py +163 -0
  277. vispy/scene/cameras/panzoom.py +311 -0
  278. vispy/scene/cameras/perspective.py +338 -0
  279. vispy/scene/cameras/tests/__init__.py +0 -0
  280. vispy/scene/cameras/tests/test_cameras.py +27 -0
  281. vispy/scene/cameras/tests/test_link.py +53 -0
  282. vispy/scene/cameras/tests/test_perspective.py +122 -0
  283. vispy/scene/cameras/turntable.py +183 -0
  284. vispy/scene/canvas.py +639 -0
  285. vispy/scene/events.py +85 -0
  286. vispy/scene/node.py +644 -0
  287. vispy/scene/subscene.py +20 -0
  288. vispy/scene/tests/__init__.py +0 -0
  289. vispy/scene/tests/test_canvas.py +119 -0
  290. vispy/scene/tests/test_node.py +142 -0
  291. vispy/scene/tests/test_visuals.py +141 -0
  292. vispy/scene/visuals.py +276 -0
  293. vispy/scene/widgets/__init__.py +18 -0
  294. vispy/scene/widgets/anchor.py +25 -0
  295. vispy/scene/widgets/axis.py +88 -0
  296. vispy/scene/widgets/colorbar.py +176 -0
  297. vispy/scene/widgets/console.py +351 -0
  298. vispy/scene/widgets/grid.py +509 -0
  299. vispy/scene/widgets/label.py +50 -0
  300. vispy/scene/widgets/tests/__init__.py +0 -0
  301. vispy/scene/widgets/tests/test_colorbar.py +47 -0
  302. vispy/scene/widgets/viewbox.py +199 -0
  303. vispy/scene/widgets/widget.py +478 -0
  304. vispy/testing/__init__.py +51 -0
  305. vispy/testing/_runners.py +448 -0
  306. vispy/testing/_testing.py +416 -0
  307. vispy/testing/image_tester.py +494 -0
  308. vispy/testing/rendered_array_tester.py +85 -0
  309. vispy/testing/tests/__init__.py +0 -0
  310. vispy/testing/tests/test_testing.py +20 -0
  311. vispy/util/__init__.py +32 -0
  312. vispy/util/bunch.py +15 -0
  313. vispy/util/check_environment.py +57 -0
  314. vispy/util/config.py +490 -0
  315. vispy/util/dpi/__init__.py +19 -0
  316. vispy/util/dpi/_linux.py +69 -0
  317. vispy/util/dpi/_quartz.py +26 -0
  318. vispy/util/dpi/_win32.py +34 -0
  319. vispy/util/dpi/tests/__init__.py +0 -0
  320. vispy/util/dpi/tests/test_dpi.py +16 -0
  321. vispy/util/eq.py +41 -0
  322. vispy/util/event.py +774 -0
  323. vispy/util/fetching.py +276 -0
  324. vispy/util/filter.py +44 -0
  325. vispy/util/fonts/__init__.py +14 -0
  326. vispy/util/fonts/_freetype.py +73 -0
  327. vispy/util/fonts/_quartz.py +192 -0
  328. vispy/util/fonts/_triage.py +36 -0
  329. vispy/util/fonts/_vispy_fonts.py +20 -0
  330. vispy/util/fonts/_win32.py +105 -0
  331. vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
  332. vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
  333. vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
  334. vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
  335. vispy/util/fonts/tests/__init__.py +0 -0
  336. vispy/util/fonts/tests/test_font.py +45 -0
  337. vispy/util/fourier.py +69 -0
  338. vispy/util/frozen.py +25 -0
  339. vispy/util/gallery_scraper.py +268 -0
  340. vispy/util/keys.py +91 -0
  341. vispy/util/logs.py +358 -0
  342. vispy/util/osmesa_gl.py +17 -0
  343. vispy/util/profiler.py +135 -0
  344. vispy/util/ptime.py +16 -0
  345. vispy/util/quaternion.py +229 -0
  346. vispy/util/svg/__init__.py +18 -0
  347. vispy/util/svg/base.py +20 -0
  348. vispy/util/svg/color.py +219 -0
  349. vispy/util/svg/element.py +51 -0
  350. vispy/util/svg/geometry.py +478 -0
  351. vispy/util/svg/group.py +66 -0
  352. vispy/util/svg/length.py +81 -0
  353. vispy/util/svg/number.py +25 -0
  354. vispy/util/svg/path.py +332 -0
  355. vispy/util/svg/shapes.py +57 -0
  356. vispy/util/svg/style.py +59 -0
  357. vispy/util/svg/svg.py +40 -0
  358. vispy/util/svg/transform.py +223 -0
  359. vispy/util/svg/transformable.py +28 -0
  360. vispy/util/svg/viewport.py +73 -0
  361. vispy/util/tests/__init__.py +0 -0
  362. vispy/util/tests/test_config.py +58 -0
  363. vispy/util/tests/test_docstring_parameters.py +123 -0
  364. vispy/util/tests/test_emitter_group.py +262 -0
  365. vispy/util/tests/test_event_emitter.py +743 -0
  366. vispy/util/tests/test_fourier.py +35 -0
  367. vispy/util/tests/test_gallery_scraper.py +112 -0
  368. vispy/util/tests/test_import.py +127 -0
  369. vispy/util/tests/test_key.py +22 -0
  370. vispy/util/tests/test_logging.py +45 -0
  371. vispy/util/tests/test_run.py +14 -0
  372. vispy/util/tests/test_transforms.py +42 -0
  373. vispy/util/tests/test_vispy.py +48 -0
  374. vispy/util/transforms.py +201 -0
  375. vispy/util/wrappers.py +155 -0
  376. vispy/version.py +21 -0
  377. vispy/visuals/__init__.py +50 -0
  378. vispy/visuals/_scalable_textures.py +487 -0
  379. vispy/visuals/axis.py +678 -0
  380. vispy/visuals/border.py +208 -0
  381. vispy/visuals/box.py +79 -0
  382. vispy/visuals/collections/__init__.py +30 -0
  383. vispy/visuals/collections/agg_fast_path_collection.py +219 -0
  384. vispy/visuals/collections/agg_path_collection.py +197 -0
  385. vispy/visuals/collections/agg_point_collection.py +52 -0
  386. vispy/visuals/collections/agg_segment_collection.py +142 -0
  387. vispy/visuals/collections/array_list.py +401 -0
  388. vispy/visuals/collections/base_collection.py +482 -0
  389. vispy/visuals/collections/collection.py +253 -0
  390. vispy/visuals/collections/path_collection.py +23 -0
  391. vispy/visuals/collections/point_collection.py +19 -0
  392. vispy/visuals/collections/polygon_collection.py +25 -0
  393. vispy/visuals/collections/raw_path_collection.py +119 -0
  394. vispy/visuals/collections/raw_point_collection.py +113 -0
  395. vispy/visuals/collections/raw_polygon_collection.py +77 -0
  396. vispy/visuals/collections/raw_segment_collection.py +112 -0
  397. vispy/visuals/collections/raw_triangle_collection.py +78 -0
  398. vispy/visuals/collections/segment_collection.py +19 -0
  399. vispy/visuals/collections/triangle_collection.py +16 -0
  400. vispy/visuals/collections/util.py +168 -0
  401. vispy/visuals/colorbar.py +699 -0
  402. vispy/visuals/cube.py +41 -0
  403. vispy/visuals/ellipse.py +162 -0
  404. vispy/visuals/filters/__init__.py +10 -0
  405. vispy/visuals/filters/base_filter.py +242 -0
  406. vispy/visuals/filters/clipper.py +60 -0
  407. vispy/visuals/filters/clipping_planes.py +122 -0
  408. vispy/visuals/filters/color.py +181 -0
  409. vispy/visuals/filters/markers.py +28 -0
  410. vispy/visuals/filters/mesh.py +801 -0
  411. vispy/visuals/filters/picking.py +60 -0
  412. vispy/visuals/filters/tests/__init__.py +3 -0
  413. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  414. vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
  415. vispy/visuals/glsl/__init__.py +1 -0
  416. vispy/visuals/glsl/antialiasing.py +133 -0
  417. vispy/visuals/glsl/color.py +63 -0
  418. vispy/visuals/graphs/__init__.py +1 -0
  419. vispy/visuals/graphs/graph.py +240 -0
  420. vispy/visuals/graphs/layouts/__init__.py +55 -0
  421. vispy/visuals/graphs/layouts/circular.py +49 -0
  422. vispy/visuals/graphs/layouts/force_directed.py +211 -0
  423. vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
  424. vispy/visuals/graphs/layouts/random.py +52 -0
  425. vispy/visuals/graphs/tests/__init__.py +1 -0
  426. vispy/visuals/graphs/tests/test_layouts.py +139 -0
  427. vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
  428. vispy/visuals/graphs/util.py +120 -0
  429. vispy/visuals/gridlines.py +161 -0
  430. vispy/visuals/gridmesh.py +98 -0
  431. vispy/visuals/histogram.py +58 -0
  432. vispy/visuals/image.py +701 -0
  433. vispy/visuals/image_complex.py +130 -0
  434. vispy/visuals/infinite_line.py +199 -0
  435. vispy/visuals/instanced_mesh.py +152 -0
  436. vispy/visuals/isocurve.py +213 -0
  437. vispy/visuals/isoline.py +241 -0
  438. vispy/visuals/isosurface.py +113 -0
  439. vispy/visuals/line/__init__.py +6 -0
  440. vispy/visuals/line/arrow.py +289 -0
  441. vispy/visuals/line/dash_atlas.py +90 -0
  442. vispy/visuals/line/line.py +545 -0
  443. vispy/visuals/line_plot.py +135 -0
  444. vispy/visuals/linear_region.py +199 -0
  445. vispy/visuals/markers.py +819 -0
  446. vispy/visuals/mesh.py +373 -0
  447. vispy/visuals/mesh_normals.py +159 -0
  448. vispy/visuals/plane.py +54 -0
  449. vispy/visuals/polygon.py +145 -0
  450. vispy/visuals/rectangle.py +196 -0
  451. vispy/visuals/regular_polygon.py +56 -0
  452. vispy/visuals/scrolling_lines.py +197 -0
  453. vispy/visuals/shaders/__init__.py +17 -0
  454. vispy/visuals/shaders/compiler.py +206 -0
  455. vispy/visuals/shaders/expression.py +99 -0
  456. vispy/visuals/shaders/function.py +788 -0
  457. vispy/visuals/shaders/multiprogram.py +145 -0
  458. vispy/visuals/shaders/parsing.py +140 -0
  459. vispy/visuals/shaders/program.py +161 -0
  460. vispy/visuals/shaders/shader_object.py +162 -0
  461. vispy/visuals/shaders/tests/__init__.py +0 -0
  462. vispy/visuals/shaders/tests/test_function.py +486 -0
  463. vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
  464. vispy/visuals/shaders/tests/test_parsing.py +57 -0
  465. vispy/visuals/shaders/variable.py +272 -0
  466. vispy/visuals/spectrogram.py +169 -0
  467. vispy/visuals/sphere.py +80 -0
  468. vispy/visuals/surface_plot.py +192 -0
  469. vispy/visuals/tests/__init__.py +0 -0
  470. vispy/visuals/tests/test_arrows.py +109 -0
  471. vispy/visuals/tests/test_axis.py +120 -0
  472. vispy/visuals/tests/test_collections.py +15 -0
  473. vispy/visuals/tests/test_colorbar.py +179 -0
  474. vispy/visuals/tests/test_colormap.py +97 -0
  475. vispy/visuals/tests/test_ellipse.py +122 -0
  476. vispy/visuals/tests/test_gridlines.py +30 -0
  477. vispy/visuals/tests/test_histogram.py +24 -0
  478. vispy/visuals/tests/test_image.py +392 -0
  479. vispy/visuals/tests/test_image_complex.py +36 -0
  480. vispy/visuals/tests/test_infinite_line.py +53 -0
  481. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  482. vispy/visuals/tests/test_isosurface.py +22 -0
  483. vispy/visuals/tests/test_linear_region.py +152 -0
  484. vispy/visuals/tests/test_markers.py +54 -0
  485. vispy/visuals/tests/test_mesh.py +261 -0
  486. vispy/visuals/tests/test_mesh_normals.py +218 -0
  487. vispy/visuals/tests/test_polygon.py +112 -0
  488. vispy/visuals/tests/test_rectangle.py +163 -0
  489. vispy/visuals/tests/test_regular_polygon.py +111 -0
  490. vispy/visuals/tests/test_scalable_textures.py +196 -0
  491. vispy/visuals/tests/test_sdf.py +73 -0
  492. vispy/visuals/tests/test_spectrogram.py +42 -0
  493. vispy/visuals/tests/test_surface_plot.py +57 -0
  494. vispy/visuals/tests/test_text.py +95 -0
  495. vispy/visuals/tests/test_volume.py +542 -0
  496. vispy/visuals/tests/test_windbarb.py +33 -0
  497. vispy/visuals/text/__init__.py +7 -0
  498. vispy/visuals/text/_sdf_cpu.cpython-313-darwin.so +0 -0
  499. vispy/visuals/text/_sdf_cpu.pyx +112 -0
  500. vispy/visuals/text/_sdf_gpu.py +316 -0
  501. vispy/visuals/text/text.py +675 -0
  502. vispy/visuals/transforms/__init__.py +34 -0
  503. vispy/visuals/transforms/_util.py +191 -0
  504. vispy/visuals/transforms/base_transform.py +233 -0
  505. vispy/visuals/transforms/chain.py +300 -0
  506. vispy/visuals/transforms/interactive.py +98 -0
  507. vispy/visuals/transforms/linear.py +564 -0
  508. vispy/visuals/transforms/nonlinear.py +398 -0
  509. vispy/visuals/transforms/tests/__init__.py +0 -0
  510. vispy/visuals/transforms/tests/test_transforms.py +243 -0
  511. vispy/visuals/transforms/transform_system.py +339 -0
  512. vispy/visuals/tube.py +173 -0
  513. vispy/visuals/visual.py +923 -0
  514. vispy/visuals/volume.py +1366 -0
  515. vispy/visuals/windbarb.py +291 -0
  516. vispy/visuals/xyz_axis.py +34 -0
  517. vispy-0.15.0.dist-info/METADATA +243 -0
  518. vispy-0.15.0.dist-info/RECORD +521 -0
  519. vispy-0.15.0.dist-info/WHEEL +6 -0
  520. vispy-0.15.0.dist-info/licenses/LICENSE.txt +36 -0
  521. vispy-0.15.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,211 @@
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
+ Force-Directed Graph Layout
6
+ ===========================
7
+
8
+ This module contains implementations for a force-directed layout, where the
9
+ graph is modelled like a collection of springs or as a collection of
10
+ particles attracting and repelling each other. The whole graph tries to
11
+ reach a state which requires the minimum energy.
12
+ """
13
+
14
+ import numpy as np
15
+
16
+ try:
17
+ from scipy.sparse import issparse
18
+ except ImportError:
19
+ def issparse(*args, **kwargs):
20
+ return False
21
+
22
+ from ..util import _straight_line_vertices, _rescale_layout
23
+
24
+
25
+ class fruchterman_reingold(object):
26
+ r"""Fruchterman-Reingold implementation adapted from NetworkX.
27
+
28
+ In the Fruchterman-Reingold algorithm, the whole graph is modelled as a
29
+ collection of particles, it runs a simplified particle simulation to
30
+ find a nice layout for the graph.
31
+
32
+ Parameters
33
+ ----------
34
+ optimal : number
35
+ Optimal distance between nodes. Defaults to :math:`1/\\sqrt{N}` where
36
+ N is the number of nodes.
37
+ iterations : int
38
+ Number of iterations to perform for layout calculation.
39
+ pos : array
40
+ Initial positions of the nodes
41
+
42
+ Notes
43
+ -----
44
+ The algorithm is explained in more detail in the original paper [1]_.
45
+
46
+ .. [1] Fruchterman, Thomas MJ, and Edward M. Reingold. "Graph drawing by
47
+ force-directed placement." Softw., Pract. Exper. 21.11 (1991),
48
+ 1129-1164.
49
+ """
50
+
51
+ def __init__(self, optimal=None, iterations=50, pos=None):
52
+ self.dim = 2
53
+ self.optimal = optimal
54
+ self.iterations = iterations
55
+ self.num_nodes = None
56
+ self.pos = pos
57
+
58
+ def __call__(self, adjacency_mat, directed=False):
59
+ """
60
+ Starts the calculation of the graph layout.
61
+
62
+ This is a generator, and after each iteration it yields the new
63
+ positions for the nodes, together with the vertices for the edges
64
+ and the arrows.
65
+
66
+ There are two solvers here: one specially adapted for SciPy sparse
67
+ matrices, and the other for larger networks.
68
+
69
+ Parameters
70
+ ----------
71
+ adjacency_mat : array
72
+ The graph adjacency matrix.
73
+ directed : bool
74
+ Wether the graph is directed or not. If this is True,
75
+ it will draw arrows for directed edges.
76
+
77
+ Yields
78
+ ------
79
+ layout : tuple
80
+ For each iteration of the layout calculation it yields a tuple
81
+ containing (node_vertices, line_vertices, arrow_vertices). These
82
+ vertices can be passed to the `MarkersVisual` and `ArrowVisual`.
83
+ """
84
+ if adjacency_mat.shape[0] != adjacency_mat.shape[1]:
85
+ raise ValueError("Adjacency matrix should be square.")
86
+
87
+ self.num_nodes = adjacency_mat.shape[0]
88
+
89
+ if issparse(adjacency_mat):
90
+ # Use the sparse solver
91
+ solver = self._sparse_fruchterman_reingold
92
+ else:
93
+ solver = self._fruchterman_reingold
94
+
95
+ for result in solver(adjacency_mat, directed):
96
+ yield result
97
+
98
+ def _fruchterman_reingold(self, adjacency_mat, directed=False):
99
+ if self.optimal is None:
100
+ self.optimal = 1 / np.sqrt(self.num_nodes)
101
+
102
+ if self.pos is None:
103
+ # Random initial positions
104
+ pos = np.asarray(
105
+ np.random.random((self.num_nodes, self.dim)),
106
+ dtype=np.float32
107
+ )
108
+ else:
109
+ pos = self.pos.astype(np.float32)
110
+
111
+ # Yield initial positions
112
+ line_vertices, arrows = _straight_line_vertices(adjacency_mat, pos,
113
+ directed)
114
+ yield pos, line_vertices, arrows
115
+
116
+ # The initial "temperature" is about .1 of domain area (=1x1)
117
+ # this is the largest step allowed in the dynamics.
118
+ t = 0.1
119
+
120
+ # Simple cooling scheme.
121
+ # Linearly step down by dt on each iteration so last iteration is
122
+ # size dt.
123
+ dt = t / float(self.iterations+1)
124
+ # The inscrutable (but fast) version
125
+ # This is still O(V^2)
126
+ # Could use multilevel methods to speed this up significantly
127
+ for iteration in range(self.iterations):
128
+ delta_pos = _calculate_delta_pos(adjacency_mat, pos, t,
129
+ self.optimal)
130
+ pos += delta_pos
131
+ _rescale_layout(pos)
132
+
133
+ # cool temperature
134
+ t -= dt
135
+
136
+ # Calculate edge vertices and arrows
137
+ line_vertices, arrows = _straight_line_vertices(adjacency_mat,
138
+ pos, directed)
139
+
140
+ yield pos, line_vertices, arrows
141
+
142
+ def _sparse_fruchterman_reingold(self, adjacency_mat, directed=False):
143
+ # Optimal distance between nodes
144
+ if self.optimal is None:
145
+ self.optimal = 1 / np.sqrt(self.num_nodes)
146
+
147
+ # Change to list of list format
148
+ # Also construct the matrix in COO format for easy edge construction
149
+ adjacency_arr = adjacency_mat.toarray()
150
+ adjacency_coo = adjacency_mat.tocoo()
151
+
152
+ if self.pos is None:
153
+ # Random initial positions
154
+ pos = np.asarray(
155
+ np.random.random((self.num_nodes, self.dim)),
156
+ dtype=np.float32
157
+ )
158
+ else:
159
+ pos = self.pos.astype(np.float32)
160
+
161
+ # Yield initial positions
162
+ line_vertices, arrows = _straight_line_vertices(adjacency_coo, pos,
163
+ directed)
164
+ yield pos, line_vertices, arrows
165
+
166
+ # The initial "temperature" is about .1 of domain area (=1x1)
167
+ # This is the largest step allowed in the dynamics.
168
+ t = 0.1
169
+ # Simple cooling scheme.
170
+ # Linearly step down by dt on each iteration so last iteration is
171
+ # size dt.
172
+ dt = t / float(self.iterations+1)
173
+ for iteration in range(self.iterations):
174
+ delta_pos = _calculate_delta_pos(adjacency_arr, pos, t,
175
+ self.optimal)
176
+ pos += delta_pos
177
+ _rescale_layout(pos)
178
+
179
+ # Cool temperature
180
+ t -= dt
181
+
182
+ # Calculate line vertices
183
+ line_vertices, arrows = _straight_line_vertices(adjacency_coo,
184
+ pos, directed)
185
+
186
+ yield pos, line_vertices, arrows
187
+
188
+
189
+ def _calculate_delta_pos(adjacency_arr, pos, t, optimal):
190
+ """Helper to calculate the delta position"""
191
+ # XXX eventually this should be refactored for the sparse case to only
192
+ # do the necessary pairwise distances
193
+ delta = pos[:, np.newaxis, :] - pos
194
+
195
+ # Distance between points
196
+ distance2 = (delta*delta).sum(axis=-1)
197
+ # Enforce minimum distance of 0.01
198
+ distance2 = np.where(distance2 < 0.0001, 0.0001, distance2)
199
+ distance = np.sqrt(distance2)
200
+ # Displacement "force"
201
+ displacement = np.zeros((len(delta), 2))
202
+ for ii in range(2):
203
+ displacement[:, ii] = (
204
+ delta[:, :, ii] *
205
+ ((optimal * optimal) / (distance*distance) -
206
+ (adjacency_arr * distance) / optimal)).sum(axis=1)
207
+
208
+ length = np.sqrt((displacement**2).sum(axis=1))
209
+ length = np.where(length < 0.01, 0.1, length)
210
+ delta_pos = displacement * t / length[:, np.newaxis]
211
+ return delta_pos
@@ -0,0 +1,87 @@
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.#!/usr/bin/env python3
4
+ from ..util import _straight_line_vertices, issparse
5
+ import numpy as np
6
+ try:
7
+ import networkx as nx
8
+ except ModuleNotFoundError:
9
+ nx = None
10
+
11
+
12
+ class NetworkxCoordinates:
13
+ def __init__(self, graph=None, layout=None, **kwargs):
14
+ """
15
+ Converts :graph: into a layout. Can be used in conjunction with networkx layouts or using raw 2D-numpy arrays.
16
+
17
+ Parameters
18
+ ----------
19
+ graph : a networkx graph.
20
+ layout : str or dict or iterable-object of float32, optional
21
+ - When :layout: is s string, a lookup will be performed in the networkx avaiable layouts.
22
+ - When :layout: is a dict, it will be assumed that it takes the shape (key, value) = (node_id, 2D-coordinate).
23
+ - When :layout: is numpy array it is assumed it takes the shape (number_of_nodes, 2).
24
+ kwargs: dict, optional
25
+ when layout is :str: :kwargs: will act as a setting dictionary for the layout function of networkx
26
+ """
27
+ if nx is None:
28
+ raise ValueError("networkx not found, please install networkx to use its layouts")
29
+ if isinstance(graph, type(None)):
30
+ raise ValueError("Requires networkx input")
31
+ self.graph = graph
32
+ self.positions = np.zeros((len(graph), 2), dtype=np.float32)
33
+ # default random positions
34
+ if isinstance(layout, type(None)):
35
+ self.positions = np.random.rand(*self.positions.shape)
36
+
37
+ # check for networkx
38
+ elif isinstance(layout, str):
39
+ if not layout.endswith("_layout"):
40
+ layout += "_layout" # append for nx
41
+ layout_function = getattr(nx, layout)
42
+ if layout_function:
43
+ self.positions = np.asarray(
44
+ [i for i in dict(layout_function(graph, **kwargs)).values()])
45
+ else:
46
+ raise ValueError("Check networkx for layouts")
47
+ # assume dict from networkx; values are 2-array
48
+ elif isinstance(layout, dict):
49
+ self.positions = np.asarray([i for i in layout.values()])
50
+
51
+ # assume given values
52
+ elif isinstance(layout, np.ndarray):
53
+ assert layout.ndim == 2
54
+ assert layout.shape[0] == len(graph)
55
+ self.positions = layout
56
+ else:
57
+ raise ValueError("Input not understood")
58
+
59
+ # normalize coordinates
60
+ self.positions = (self.positions - self.positions.min()) / \
61
+ (self.positions.max() - self.positions.min())
62
+ self.positions = self.positions.astype(np.float32)
63
+
64
+ def __call__(self, adjacency_mat, directed=False):
65
+ """
66
+ Parameters
67
+ ----------
68
+ adjacency_mat : sparse adjacency matrix.
69
+ directed : bool, default False
70
+
71
+ Returns
72
+ ---------
73
+ (node_vertices, line_vertices, arrow_vertices) : tuple
74
+ Yields the node and line vertices in a tuple. This layout only yields a
75
+ single time, and has no builtin animation
76
+ """
77
+ if issparse(adjacency_mat):
78
+ adjacency_mat = adjacency_mat.tocoo()
79
+ line_vertices, arrows = _straight_line_vertices(
80
+ adjacency_mat, self.positions, directed)
81
+
82
+ yield self.positions, line_vertices, arrows
83
+
84
+ @property
85
+ def adj(self):
86
+ """Convenient storage and holder of the adjacency matrix for the :scene.visuals.Graph: function."""
87
+ return nx.adjacency_matrix(self.graph)
@@ -0,0 +1,52 @@
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
+ Random Graph Layout
6
+ ====================
7
+
8
+ This layout positions the nodes at random
9
+ """
10
+
11
+ import numpy as np
12
+
13
+ from ..util import _straight_line_vertices, issparse
14
+
15
+
16
+ def random(adjacency_mat, directed=False, random_state=None):
17
+ """
18
+ Place the graph nodes at random places.
19
+
20
+ Parameters
21
+ ----------
22
+ adjacency_mat : matrix or sparse
23
+ The graph adjacency matrix
24
+ directed : bool
25
+ Whether the graph is directed. If this is True, is will also
26
+ generate the vertices for arrows, which can be passed to an
27
+ ArrowVisual.
28
+ random_state : instance of RandomState | int | None
29
+ Random state to use. Can be None to use ``np.random``.
30
+
31
+ Yields
32
+ ------
33
+ (node_vertices, line_vertices, arrow_vertices) : tuple
34
+ Yields the node and line vertices in a tuple. This layout only yields a
35
+ single time, and has no builtin animation
36
+ """
37
+ if random_state is None:
38
+ random_state = np.random
39
+ elif not isinstance(random_state, np.random.RandomState):
40
+ random_state = np.random.RandomState(random_state)
41
+
42
+ if issparse(adjacency_mat):
43
+ adjacency_mat = adjacency_mat.tocoo()
44
+
45
+ # Randomly place nodes, visual coordinate system is between 0 and 1
46
+ num_nodes = adjacency_mat.shape[0]
47
+ node_coords = random_state.rand(num_nodes, 2)
48
+
49
+ line_vertices, arrows = _straight_line_vertices(adjacency_mat,
50
+ node_coords, directed)
51
+
52
+ yield node_coords, line_vertices, arrows
@@ -0,0 +1 @@
1
+ __author__ = 'lucas'
@@ -0,0 +1,139 @@
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 numpy.testing import assert_allclose, assert_equal
7
+
8
+ from vispy.visuals.graphs.layouts import get_layout
9
+ from vispy.testing import (run_tests_if_main, assert_raises)
10
+
11
+
12
+ adjacency_mat = np.array([
13
+ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
14
+ [1, 0, 0, 0, 1, 0, 1, 1, 0, 0],
15
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
16
+ [0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
17
+ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
18
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
19
+ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
20
+ [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
21
+ [0, 0, 0, 1, 0, 0, 0, 0, 0, 1],
22
+ [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
23
+ ])
24
+
25
+
26
+ def test_get_layout():
27
+ from vispy.visuals.graphs.layouts.random import random
28
+
29
+ # Simple retrieval
30
+ assert_equal(random, get_layout('random'))
31
+
32
+ # Pass arguments
33
+ fruchterman_reingold = get_layout('force_directed', iterations=100)
34
+ assert_equal(fruchterman_reingold.iterations, 100)
35
+
36
+ # Check if layout exists
37
+ assert_raises(KeyError, get_layout, 'fdgdfgs_non_existent')
38
+
39
+
40
+ def test_random_layout():
41
+ layout = get_layout('random')
42
+
43
+ expected_pos = np.array([
44
+ [0.22270932715095826, 0.7728936927702302],
45
+ [0.6298054094517744, 0.21851589821484974],
46
+ [0.75002099889163, 0.5592076821676369],
47
+ [0.1786754307911973, 0.6442165368790972],
48
+ [0.5979199081208609, 0.615159318836822],
49
+ [0.46328431255222746, 0.3582897386994869],
50
+ [0.9595461883180398, 0.2350580044144016],
51
+ [0.094482942129406, 0.20584398882694932],
52
+ [0.5758593091748346, 0.8158957494444451],
53
+ [0.5908647616961652, 0.1584550825482285]
54
+ ])
55
+
56
+ expected_vertices = np.array([
57
+ [0.22270932715095826, 0.7728936927702302],
58
+ [0.6298054094517744, 0.21851589821484974],
59
+ [0.6298054094517744, 0.21851589821484974],
60
+ [0.22270932715095826, 0.7728936927702302],
61
+ [0.6298054094517744, 0.21851589821484974],
62
+ [0.5979199081208609, 0.615159318836822],
63
+ [0.6298054094517744, 0.21851589821484974],
64
+ [0.9595461883180398, 0.2350580044144016],
65
+ [0.6298054094517744, 0.21851589821484974],
66
+ [0.094482942129406, 0.20584398882694932],
67
+ [0.1786754307911973, 0.6442165368790972],
68
+ [0.5758593091748346, 0.8158957494444451],
69
+ [0.5979199081208609, 0.615159318836822],
70
+ [0.6298054094517744, 0.21851589821484974],
71
+ [0.9595461883180398, 0.2350580044144016],
72
+ [0.6298054094517744, 0.21851589821484974],
73
+ [0.094482942129406, 0.20584398882694932],
74
+ [0.6298054094517744, 0.21851589821484974],
75
+ [0.5758593091748346, 0.8158957494444451],
76
+ [0.1786754307911973, 0.6442165368790972],
77
+ [0.5758593091748346, 0.8158957494444451],
78
+ [0.5908647616961652, 0.1584550825482285],
79
+ [0.5908647616961652, 0.1584550825482285],
80
+ [0.5758593091748346, 0.8158957494444451]
81
+ ])
82
+
83
+ pos, line_vertices, arrows = next(layout(adjacency_mat,
84
+ random_state=0xDEADBEEF))
85
+
86
+ assert_allclose(pos, expected_pos, atol=1e-7)
87
+ assert_allclose(line_vertices, expected_vertices, atol=1e-7)
88
+
89
+
90
+ def test_circular_layout():
91
+ layout = get_layout('circular')
92
+
93
+ expected_pos = np.array([
94
+ [1.0, 0.5],
95
+ [0.9045084714889526, 0.7938926219940186],
96
+ [0.6545084714889526, 0.9755282402038574],
97
+ [0.3454914689064026, 0.9755282402038574],
98
+ [0.09549146890640259, 0.7938926219940186],
99
+ [0.0, 0.4999999701976776],
100
+ [0.09549152851104736, 0.20610731840133667],
101
+ [0.3454914689064026, 0.024471759796142578],
102
+ [0.6545085906982422, 0.024471759796142578],
103
+ [0.9045084714889526, 0.20610734820365906]
104
+ ])
105
+
106
+ expected_vertices = np.array([
107
+ [1.0, 0.5],
108
+ [0.9045084714889526, 0.7938926219940186],
109
+ [0.9045084714889526, 0.7938926219940186],
110
+ [1.0, 0.5],
111
+ [0.9045084714889526, 0.7938926219940186],
112
+ [0.09549146890640259, 0.7938926219940186],
113
+ [0.9045084714889526, 0.7938926219940186],
114
+ [0.09549152851104736, 0.20610731840133667],
115
+ [0.9045084714889526, 0.7938926219940186],
116
+ [0.3454914689064026, 0.024471759796142578],
117
+ [0.3454914689064026, 0.9755282402038574],
118
+ [0.6545085906982422, 0.024471759796142578],
119
+ [0.09549146890640259, 0.7938926219940186],
120
+ [0.9045084714889526, 0.7938926219940186],
121
+ [0.09549152851104736, 0.20610731840133667],
122
+ [0.9045084714889526, 0.7938926219940186],
123
+ [0.3454914689064026, 0.024471759796142578],
124
+ [0.9045084714889526, 0.7938926219940186],
125
+ [0.6545085906982422, 0.024471759796142578],
126
+ [0.3454914689064026, 0.9755282402038574],
127
+ [0.6545085906982422, 0.024471759796142578],
128
+ [0.9045084714889526, 0.20610734820365906],
129
+ [0.9045084714889526, 0.20610734820365906],
130
+ [0.6545085906982422, 0.024471759796142578]
131
+ ])
132
+
133
+ pos, line_vertices, arrows = next(layout(adjacency_mat))
134
+
135
+ assert_allclose(pos, expected_pos, atol=1e-4)
136
+ assert_allclose(line_vertices, expected_vertices, atol=1e-4)
137
+
138
+
139
+ run_tests_if_main()
@@ -0,0 +1,47 @@
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
+ from vispy import testing
5
+ from vispy.visuals.graphs.layouts import get_layout
6
+ from vispy.visuals.graphs.layouts.networkx_layout import NetworkxCoordinates
7
+ import numpy as np
8
+
9
+ # conditional import
10
+ try:
11
+ import networkx as nx
12
+ except ModuleNotFoundError:
13
+ nx = None
14
+
15
+
16
+ def test_networkx_layout_with_graph():
17
+ """Testing the various inputs to the networkx layout."""
18
+ settings = dict(name="networkx_layout")
19
+ if nx is None:
20
+ return testing.SkipTest("'networkx' required")
21
+
22
+ # empty input
23
+ # testing.assert_raises(ValueError("Requires networkx input"), get_layout(**settings))
24
+
25
+ # define graph
26
+ graph = nx.complete_graph(5)
27
+ # define positions
28
+ layout = np.random.rand(5, 2)
29
+ settings['graph'] = graph
30
+ settings['layout'] = layout
31
+
32
+ # test numpy array input
33
+ testing.assert_true(isinstance(
34
+ get_layout(**settings), NetworkxCoordinates))
35
+ # testing string input
36
+ settings['layout'] = 'circular'
37
+ testing.assert_true(isinstance(
38
+ get_layout(**settings), NetworkxCoordinates))
39
+ # testing dict input
40
+ settings['layout'] = nx.circular_layout(graph)
41
+ testing.assert_true(isinstance(
42
+ get_layout(**settings), NetworkxCoordinates))
43
+
44
+
45
+ def test_networkx_layout_no_networkx():
46
+ settings = dict(name="networkx_layout")
47
+ testing.assert_raises(ValueError, get_layout, **settings)
@@ -0,0 +1,120 @@
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
+ Graph utilities
6
+ ===============
7
+
8
+ A module containing several graph utility functions.
9
+ """
10
+
11
+ import numpy as np
12
+
13
+ try:
14
+ from scipy.sparse import issparse
15
+ from scipy import sparse
16
+ except ImportError:
17
+ def issparse(*args, **kwargs):
18
+ return False
19
+
20
+
21
+ def _get_edges(adjacency_mat):
22
+ func = _sparse_get_edges if issparse(adjacency_mat) else _ndarray_get_edges
23
+ return func(adjacency_mat)
24
+
25
+
26
+ def _sparse_get_edges(adjacency_mat):
27
+ return np.concatenate((adjacency_mat.row[:, np.newaxis],
28
+ adjacency_mat.col[:, np.newaxis]), axis=-1)
29
+
30
+
31
+ def _ndarray_get_edges(adjacency_mat):
32
+ # Get indices of all non zero values
33
+ i, j = np.where(adjacency_mat)
34
+
35
+ return np.concatenate((i[:, np.newaxis], j[:, np.newaxis]), axis=-1)
36
+
37
+
38
+ def _get_directed_edges(adjacency_mat):
39
+ func = _sparse_get_edges if issparse(adjacency_mat) else _ndarray_get_edges
40
+
41
+ if issparse(adjacency_mat):
42
+ triu = sparse.triu
43
+ tril = sparse.tril
44
+ else:
45
+ triu = np.triu
46
+ tril = np.tril
47
+
48
+ upper = triu(adjacency_mat)
49
+ lower = tril(adjacency_mat)
50
+
51
+ return np.concatenate((func(upper), func(lower)))
52
+
53
+
54
+ def _straight_line_vertices(adjacency_mat, node_coords, directed=False):
55
+ """
56
+ Generate the vertices for straight lines between nodes.
57
+
58
+ If it is a directed graph, it also generates the vertices which can be
59
+ passed to an :class:`ArrowVisual`.
60
+
61
+ Parameters
62
+ ----------
63
+ adjacency_mat : array
64
+ The adjacency matrix of the graph
65
+ node_coords : array
66
+ The current coordinates of all nodes in the graph
67
+ directed : bool
68
+ Wether the graph is directed. If this is true it will also generate
69
+ the vertices for arrows which can be passed to :class:`ArrowVisual`.
70
+
71
+ Returns
72
+ -------
73
+ vertices : tuple
74
+ Returns a tuple containing containing (`line_vertices`,
75
+ `arrow_vertices`)
76
+ """
77
+ if not issparse(adjacency_mat):
78
+ adjacency_mat = np.asarray(adjacency_mat, float)
79
+
80
+ if (adjacency_mat.ndim != 2 or adjacency_mat.shape[0] !=
81
+ adjacency_mat.shape[1]):
82
+ raise ValueError("Adjacency matrix should be square.")
83
+
84
+ arrow_vertices = np.array([])
85
+
86
+ edges = _get_edges(adjacency_mat)
87
+ line_vertices = node_coords[edges.ravel()]
88
+
89
+ if directed:
90
+ arrows = np.array(list(_get_directed_edges(adjacency_mat)))
91
+ arrow_vertices = node_coords[arrows.ravel()]
92
+ arrow_vertices = arrow_vertices.reshape((len(arrow_vertices)//2, 4))
93
+
94
+ return line_vertices, arrow_vertices
95
+
96
+
97
+ def _rescale_layout(pos, scale=1):
98
+ """
99
+ Normalize the given coordinate list to the range [0, `scale`].
100
+
101
+ Parameters
102
+ ----------
103
+ pos : array
104
+ Coordinate list
105
+ scale : number
106
+ The upperbound value for the coordinates range
107
+
108
+ Returns
109
+ -------
110
+ pos : array
111
+ The rescaled (normalized) coordinates in the range [0, `scale`].
112
+
113
+ Notes
114
+ -----
115
+ Changes `pos` in place.
116
+ """
117
+ pos -= pos.min(axis=0)
118
+ pos *= scale / pos.max()
119
+
120
+ return pos