vispy 0.14.0__cp311-cp311-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.
- vispy/__init__.py +33 -0
- vispy/app/__init__.py +15 -0
- vispy/app/_default_app.py +76 -0
- vispy/app/_detect_eventloop.py +148 -0
- vispy/app/application.py +263 -0
- vispy/app/backends/__init__.py +52 -0
- vispy/app/backends/_egl.py +264 -0
- vispy/app/backends/_glfw.py +513 -0
- vispy/app/backends/_jupyter_rfb.py +278 -0
- vispy/app/backends/_offscreen_util.py +121 -0
- vispy/app/backends/_osmesa.py +235 -0
- vispy/app/backends/_pyglet.py +451 -0
- vispy/app/backends/_pyqt4.py +36 -0
- vispy/app/backends/_pyqt5.py +36 -0
- vispy/app/backends/_pyqt6.py +40 -0
- vispy/app/backends/_pyside.py +37 -0
- vispy/app/backends/_pyside2.py +52 -0
- vispy/app/backends/_pyside6.py +53 -0
- vispy/app/backends/_qt.py +968 -0
- vispy/app/backends/_sdl2.py +444 -0
- vispy/app/backends/_template.py +244 -0
- vispy/app/backends/_test.py +8 -0
- vispy/app/backends/_tk.py +800 -0
- vispy/app/backends/_wx.py +476 -0
- vispy/app/backends/tests/__init__.py +0 -0
- vispy/app/backends/tests/test_offscreen_util.py +52 -0
- vispy/app/backends/tests/test_rfb.py +77 -0
- vispy/app/base.py +294 -0
- vispy/app/canvas.py +828 -0
- vispy/app/qt.py +92 -0
- vispy/app/tests/__init__.py +0 -0
- vispy/app/tests/qt-designer.ui +58 -0
- vispy/app/tests/test_app.py +442 -0
- vispy/app/tests/test_backends.py +164 -0
- vispy/app/tests/test_canvas.py +122 -0
- vispy/app/tests/test_context.py +92 -0
- vispy/app/tests/test_qt.py +47 -0
- vispy/app/tests/test_simultaneous.py +134 -0
- vispy/app/timer.py +174 -0
- vispy/color/__init__.py +17 -0
- vispy/color/_color_dict.py +193 -0
- vispy/color/color_array.py +447 -0
- vispy/color/color_space.py +181 -0
- vispy/color/colormap.py +1134 -0
- vispy/color/tests/__init__.py +0 -0
- vispy/color/tests/test_color.py +352 -0
- vispy/conftest.py +12 -0
- vispy/ext/__init__.py +0 -0
- vispy/ext/cocoapy.py +1542 -0
- vispy/ext/cubehelix.py +138 -0
- vispy/ext/egl.py +375 -0
- vispy/ext/fontconfig.py +118 -0
- vispy/ext/gdi32plus.py +206 -0
- vispy/ext/osmesa.py +105 -0
- vispy/geometry/__init__.py +23 -0
- vispy/geometry/_triangulation_debugger.py +171 -0
- vispy/geometry/calculations.py +134 -0
- vispy/geometry/curves.py +399 -0
- vispy/geometry/generation.py +643 -0
- vispy/geometry/isocurve.py +175 -0
- vispy/geometry/isosurface.py +465 -0
- vispy/geometry/meshdata.py +698 -0
- vispy/geometry/normals.py +78 -0
- vispy/geometry/parametric.py +56 -0
- vispy/geometry/polygon.py +137 -0
- vispy/geometry/rect.py +210 -0
- vispy/geometry/tests/__init__.py +0 -0
- vispy/geometry/tests/test_calculations.py +23 -0
- vispy/geometry/tests/test_generation.py +56 -0
- vispy/geometry/tests/test_meshdata.py +106 -0
- vispy/geometry/tests/test_triangulation.py +506 -0
- vispy/geometry/torusknot.py +142 -0
- vispy/geometry/triangulation.py +876 -0
- vispy/gloo/__init__.py +56 -0
- vispy/gloo/buffer.py +505 -0
- vispy/gloo/context.py +272 -0
- vispy/gloo/framebuffer.py +257 -0
- vispy/gloo/gl/__init__.py +234 -0
- vispy/gloo/gl/_constants.py +332 -0
- vispy/gloo/gl/_es2.py +986 -0
- vispy/gloo/gl/_gl2.py +1365 -0
- vispy/gloo/gl/_proxy.py +499 -0
- vispy/gloo/gl/_pyopengl2.py +362 -0
- vispy/gloo/gl/dummy.py +24 -0
- vispy/gloo/gl/es2.py +62 -0
- vispy/gloo/gl/gl2.py +98 -0
- vispy/gloo/gl/glplus.py +168 -0
- vispy/gloo/gl/pyopengl2.py +97 -0
- vispy/gloo/gl/tests/__init__.py +0 -0
- vispy/gloo/gl/tests/test_basics.py +282 -0
- vispy/gloo/gl/tests/test_functionality.py +566 -0
- vispy/gloo/gl/tests/test_names.py +246 -0
- vispy/gloo/gl/tests/test_use.py +71 -0
- vispy/gloo/glir.py +1816 -0
- vispy/gloo/globject.py +101 -0
- vispy/gloo/preprocessor.py +67 -0
- vispy/gloo/program.py +543 -0
- vispy/gloo/tests/__init__.py +0 -0
- vispy/gloo/tests/test_buffer.py +558 -0
- vispy/gloo/tests/test_context.py +119 -0
- vispy/gloo/tests/test_framebuffer.py +195 -0
- vispy/gloo/tests/test_glir.py +307 -0
- vispy/gloo/tests/test_globject.py +35 -0
- vispy/gloo/tests/test_program.py +302 -0
- vispy/gloo/tests/test_texture.py +732 -0
- vispy/gloo/tests/test_use_gloo.py +187 -0
- vispy/gloo/tests/test_util.py +60 -0
- vispy/gloo/tests/test_wrappers.py +261 -0
- vispy/gloo/texture.py +1045 -0
- vispy/gloo/util.py +129 -0
- vispy/gloo/wrappers.py +762 -0
- vispy/glsl/__init__.py +42 -0
- vispy/glsl/antialias/antialias.glsl +7 -0
- vispy/glsl/antialias/cap-butt.glsl +31 -0
- vispy/glsl/antialias/cap-round.glsl +29 -0
- vispy/glsl/antialias/cap-square.glsl +30 -0
- vispy/glsl/antialias/cap-triangle-in.glsl +30 -0
- vispy/glsl/antialias/cap-triangle-out.glsl +30 -0
- vispy/glsl/antialias/cap.glsl +67 -0
- vispy/glsl/antialias/caps.glsl +67 -0
- vispy/glsl/antialias/filled.glsl +50 -0
- vispy/glsl/antialias/outline.glsl +40 -0
- vispy/glsl/antialias/stroke.glsl +43 -0
- vispy/glsl/arrowheads/angle.glsl +99 -0
- vispy/glsl/arrowheads/arrowheads.frag +60 -0
- vispy/glsl/arrowheads/arrowheads.glsl +12 -0
- vispy/glsl/arrowheads/arrowheads.vert +83 -0
- vispy/glsl/arrowheads/curved.glsl +48 -0
- vispy/glsl/arrowheads/inhibitor.glsl +26 -0
- vispy/glsl/arrowheads/stealth.glsl +46 -0
- vispy/glsl/arrowheads/triangle.glsl +97 -0
- vispy/glsl/arrowheads/util.glsl +13 -0
- vispy/glsl/arrows/angle-30.glsl +12 -0
- vispy/glsl/arrows/angle-60.glsl +12 -0
- vispy/glsl/arrows/angle-90.glsl +12 -0
- vispy/glsl/arrows/arrow.frag +39 -0
- vispy/glsl/arrows/arrow.vert +49 -0
- vispy/glsl/arrows/arrows.glsl +17 -0
- vispy/glsl/arrows/common.glsl +187 -0
- vispy/glsl/arrows/curved.glsl +63 -0
- vispy/glsl/arrows/stealth.glsl +50 -0
- vispy/glsl/arrows/triangle-30.glsl +12 -0
- vispy/glsl/arrows/triangle-60.glsl +12 -0
- vispy/glsl/arrows/triangle-90.glsl +12 -0
- vispy/glsl/arrows/util.glsl +98 -0
- vispy/glsl/build_spatial_filters.py +660 -0
- vispy/glsl/collections/agg-fast-path.frag +20 -0
- vispy/glsl/collections/agg-fast-path.vert +78 -0
- vispy/glsl/collections/agg-glyph.frag +60 -0
- vispy/glsl/collections/agg-glyph.vert +33 -0
- vispy/glsl/collections/agg-marker.frag +35 -0
- vispy/glsl/collections/agg-marker.vert +48 -0
- vispy/glsl/collections/agg-path.frag +55 -0
- vispy/glsl/collections/agg-path.vert +166 -0
- vispy/glsl/collections/agg-point.frag +21 -0
- vispy/glsl/collections/agg-point.vert +35 -0
- vispy/glsl/collections/agg-segment.frag +32 -0
- vispy/glsl/collections/agg-segment.vert +75 -0
- vispy/glsl/collections/marker.frag +38 -0
- vispy/glsl/collections/marker.vert +48 -0
- vispy/glsl/collections/raw-path.frag +15 -0
- vispy/glsl/collections/raw-path.vert +24 -0
- vispy/glsl/collections/raw-point.frag +14 -0
- vispy/glsl/collections/raw-point.vert +31 -0
- vispy/glsl/collections/raw-segment.frag +18 -0
- vispy/glsl/collections/raw-segment.vert +26 -0
- vispy/glsl/collections/raw-triangle.frag +13 -0
- vispy/glsl/collections/raw-triangle.vert +26 -0
- vispy/glsl/collections/sdf-glyph-ticks.vert +69 -0
- vispy/glsl/collections/sdf-glyph.frag +80 -0
- vispy/glsl/collections/sdf-glyph.vert +59 -0
- vispy/glsl/collections/tick-labels.vert +71 -0
- vispy/glsl/colormaps/autumn.glsl +20 -0
- vispy/glsl/colormaps/blues.glsl +20 -0
- vispy/glsl/colormaps/color-space.glsl +17 -0
- vispy/glsl/colormaps/colormaps.glsl +24 -0
- vispy/glsl/colormaps/cool.glsl +20 -0
- vispy/glsl/colormaps/fire.glsl +21 -0
- vispy/glsl/colormaps/gray.glsl +20 -0
- vispy/glsl/colormaps/greens.glsl +20 -0
- vispy/glsl/colormaps/hot.glsl +22 -0
- vispy/glsl/colormaps/ice.glsl +20 -0
- vispy/glsl/colormaps/icefire.glsl +23 -0
- vispy/glsl/colormaps/parse.py +40 -0
- vispy/glsl/colormaps/reds.glsl +20 -0
- vispy/glsl/colormaps/spring.glsl +20 -0
- vispy/glsl/colormaps/summer.glsl +20 -0
- vispy/glsl/colormaps/user.glsl +22 -0
- vispy/glsl/colormaps/util.glsl +41 -0
- vispy/glsl/colormaps/wheel.glsl +21 -0
- vispy/glsl/colormaps/winter.glsl +20 -0
- vispy/glsl/lines/agg.frag +320 -0
- vispy/glsl/lines/agg.vert +241 -0
- vispy/glsl/markers/arrow.glsl +12 -0
- vispy/glsl/markers/asterisk.glsl +16 -0
- vispy/glsl/markers/chevron.glsl +14 -0
- vispy/glsl/markers/clover.glsl +20 -0
- vispy/glsl/markers/club.glsl +31 -0
- vispy/glsl/markers/cross.glsl +17 -0
- vispy/glsl/markers/diamond.glsl +12 -0
- vispy/glsl/markers/disc.glsl +9 -0
- vispy/glsl/markers/ellipse.glsl +67 -0
- vispy/glsl/markers/hbar.glsl +9 -0
- vispy/glsl/markers/heart.glsl +15 -0
- vispy/glsl/markers/infinity.glsl +15 -0
- vispy/glsl/markers/marker-sdf.frag +74 -0
- vispy/glsl/markers/marker-sdf.vert +41 -0
- vispy/glsl/markers/marker.frag +36 -0
- vispy/glsl/markers/marker.vert +46 -0
- vispy/glsl/markers/markers.glsl +24 -0
- vispy/glsl/markers/pin.glsl +18 -0
- vispy/glsl/markers/ring.glsl +11 -0
- vispy/glsl/markers/spade.glsl +28 -0
- vispy/glsl/markers/square.glsl +10 -0
- vispy/glsl/markers/tag.glsl +11 -0
- vispy/glsl/markers/triangle.glsl +14 -0
- vispy/glsl/markers/vbar.glsl +9 -0
- vispy/glsl/math/circle-through-2-points.glsl +30 -0
- vispy/glsl/math/constants.glsl +48 -0
- vispy/glsl/math/double.glsl +114 -0
- vispy/glsl/math/functions.glsl +20 -0
- vispy/glsl/math/point-to-line-distance.glsl +31 -0
- vispy/glsl/math/point-to-line-projection.glsl +29 -0
- vispy/glsl/math/signed-line-distance.glsl +27 -0
- vispy/glsl/math/signed-segment-distance.glsl +30 -0
- vispy/glsl/misc/regular-grid.frag +244 -0
- vispy/glsl/misc/spatial-filters.frag +1407 -0
- vispy/glsl/misc/viewport-NDC.glsl +20 -0
- vispy/glsl/transforms/azimuthal-equal-area.glsl +32 -0
- vispy/glsl/transforms/azimuthal-equidistant.glsl +38 -0
- vispy/glsl/transforms/hammer.glsl +44 -0
- vispy/glsl/transforms/identity.glsl +6 -0
- vispy/glsl/transforms/identity_forward.glsl +23 -0
- vispy/glsl/transforms/identity_inverse.glsl +23 -0
- vispy/glsl/transforms/linear-scale.glsl +127 -0
- vispy/glsl/transforms/log-scale.glsl +126 -0
- vispy/glsl/transforms/mercator-transverse-forward.glsl +40 -0
- vispy/glsl/transforms/mercator-transverse-inverse.glsl +40 -0
- vispy/glsl/transforms/panzoom.glsl +10 -0
- vispy/glsl/transforms/polar.glsl +41 -0
- vispy/glsl/transforms/position.glsl +44 -0
- vispy/glsl/transforms/power-scale.glsl +139 -0
- vispy/glsl/transforms/projection.glsl +7 -0
- vispy/glsl/transforms/pvm.glsl +13 -0
- vispy/glsl/transforms/rotate.glsl +45 -0
- vispy/glsl/transforms/trackball.glsl +15 -0
- vispy/glsl/transforms/translate.glsl +35 -0
- vispy/glsl/transforms/transverse_mercator.glsl +38 -0
- vispy/glsl/transforms/viewport-clipping.glsl +14 -0
- vispy/glsl/transforms/viewport-transform.glsl +16 -0
- vispy/glsl/transforms/viewport.glsl +50 -0
- vispy/glsl/transforms/x.glsl +24 -0
- vispy/glsl/transforms/y.glsl +19 -0
- vispy/glsl/transforms/z.glsl +14 -0
- vispy/io/__init__.py +20 -0
- vispy/io/_data/spatial-filters.npy +0 -0
- vispy/io/datasets.py +94 -0
- vispy/io/image.py +231 -0
- vispy/io/mesh.py +122 -0
- vispy/io/stl.py +167 -0
- vispy/io/tests/__init__.py +0 -0
- vispy/io/tests/test_image.py +47 -0
- vispy/io/tests/test_io.py +121 -0
- vispy/io/wavefront.py +350 -0
- vispy/plot/__init__.py +36 -0
- vispy/plot/fig.py +58 -0
- vispy/plot/plotwidget.py +522 -0
- vispy/plot/tests/__init__.py +0 -0
- vispy/plot/tests/test_plot.py +46 -0
- vispy/scene/__init__.py +43 -0
- vispy/scene/cameras/__init__.py +27 -0
- vispy/scene/cameras/_base.py +38 -0
- vispy/scene/cameras/arcball.py +106 -0
- vispy/scene/cameras/base_camera.py +538 -0
- vispy/scene/cameras/fly.py +474 -0
- vispy/scene/cameras/magnify.py +163 -0
- vispy/scene/cameras/panzoom.py +308 -0
- vispy/scene/cameras/perspective.py +333 -0
- vispy/scene/cameras/tests/__init__.py +0 -0
- vispy/scene/cameras/tests/test_cameras.py +27 -0
- vispy/scene/cameras/tests/test_link.py +53 -0
- vispy/scene/cameras/tests/test_perspective.py +122 -0
- vispy/scene/cameras/turntable.py +173 -0
- vispy/scene/canvas.py +639 -0
- vispy/scene/events.py +85 -0
- vispy/scene/node.py +644 -0
- vispy/scene/subscene.py +20 -0
- vispy/scene/tests/__init__.py +0 -0
- vispy/scene/tests/test_canvas.py +119 -0
- vispy/scene/tests/test_node.py +142 -0
- vispy/scene/tests/test_visuals.py +141 -0
- vispy/scene/visuals.py +276 -0
- vispy/scene/widgets/__init__.py +18 -0
- vispy/scene/widgets/anchor.py +25 -0
- vispy/scene/widgets/axis.py +88 -0
- vispy/scene/widgets/colorbar.py +176 -0
- vispy/scene/widgets/console.py +351 -0
- vispy/scene/widgets/grid.py +509 -0
- vispy/scene/widgets/label.py +50 -0
- vispy/scene/widgets/tests/__init__.py +0 -0
- vispy/scene/widgets/tests/test_colorbar.py +47 -0
- vispy/scene/widgets/viewbox.py +199 -0
- vispy/scene/widgets/widget.py +478 -0
- vispy/testing/__init__.py +51 -0
- vispy/testing/_runners.py +446 -0
- vispy/testing/_testing.py +416 -0
- vispy/testing/image_tester.py +473 -0
- vispy/testing/rendered_array_tester.py +85 -0
- vispy/testing/tests/__init__.py +0 -0
- vispy/testing/tests/test_testing.py +20 -0
- vispy/util/__init__.py +17 -0
- vispy/util/bunch.py +15 -0
- vispy/util/check_environment.py +57 -0
- vispy/util/config.py +490 -0
- vispy/util/dpi/__init__.py +19 -0
- vispy/util/dpi/_linux.py +69 -0
- vispy/util/dpi/_quartz.py +26 -0
- vispy/util/dpi/_win32.py +34 -0
- vispy/util/dpi/tests/__init__.py +0 -0
- vispy/util/dpi/tests/test_dpi.py +16 -0
- vispy/util/eq.py +41 -0
- vispy/util/event.py +774 -0
- vispy/util/fetching.py +276 -0
- vispy/util/filter.py +44 -0
- vispy/util/fonts/__init__.py +14 -0
- vispy/util/fonts/_freetype.py +73 -0
- vispy/util/fonts/_quartz.py +192 -0
- vispy/util/fonts/_triage.py +36 -0
- vispy/util/fonts/_vispy_fonts.py +20 -0
- vispy/util/fonts/_win32.py +105 -0
- vispy/util/fonts/data/OpenSans-Bold.ttf +0 -0
- vispy/util/fonts/data/OpenSans-BoldItalic.ttf +0 -0
- vispy/util/fonts/data/OpenSans-Italic.ttf +0 -0
- vispy/util/fonts/data/OpenSans-Regular.ttf +0 -0
- vispy/util/fonts/tests/__init__.py +0 -0
- vispy/util/fonts/tests/test_font.py +45 -0
- vispy/util/fourier.py +69 -0
- vispy/util/frozen.py +25 -0
- vispy/util/gallery_scraper.py +268 -0
- vispy/util/keys.py +91 -0
- vispy/util/logs.py +358 -0
- vispy/util/osmesa_gl.py +17 -0
- vispy/util/profiler.py +135 -0
- vispy/util/ptime.py +16 -0
- vispy/util/quaternion.py +229 -0
- vispy/util/svg/__init__.py +18 -0
- vispy/util/svg/base.py +20 -0
- vispy/util/svg/color.py +219 -0
- vispy/util/svg/element.py +51 -0
- vispy/util/svg/geometry.py +478 -0
- vispy/util/svg/group.py +66 -0
- vispy/util/svg/length.py +81 -0
- vispy/util/svg/number.py +25 -0
- vispy/util/svg/path.py +332 -0
- vispy/util/svg/shapes.py +57 -0
- vispy/util/svg/style.py +59 -0
- vispy/util/svg/svg.py +40 -0
- vispy/util/svg/transform.py +223 -0
- vispy/util/svg/transformable.py +28 -0
- vispy/util/svg/viewport.py +73 -0
- vispy/util/tests/__init__.py +0 -0
- vispy/util/tests/test_config.py +58 -0
- vispy/util/tests/test_docstring_parameters.py +123 -0
- vispy/util/tests/test_emitter_group.py +262 -0
- vispy/util/tests/test_event_emitter.py +743 -0
- vispy/util/tests/test_fourier.py +35 -0
- vispy/util/tests/test_gallery_scraper.py +112 -0
- vispy/util/tests/test_import.py +127 -0
- vispy/util/tests/test_key.py +22 -0
- vispy/util/tests/test_logging.py +45 -0
- vispy/util/tests/test_run.py +14 -0
- vispy/util/tests/test_transforms.py +42 -0
- vispy/util/tests/test_vispy.py +48 -0
- vispy/util/transforms.py +201 -0
- vispy/util/wrappers.py +155 -0
- vispy/version.py +4 -0
- vispy/visuals/__init__.py +50 -0
- vispy/visuals/_scalable_textures.py +485 -0
- vispy/visuals/axis.py +678 -0
- vispy/visuals/border.py +208 -0
- vispy/visuals/box.py +79 -0
- vispy/visuals/collections/__init__.py +30 -0
- vispy/visuals/collections/agg_fast_path_collection.py +219 -0
- vispy/visuals/collections/agg_path_collection.py +197 -0
- vispy/visuals/collections/agg_point_collection.py +52 -0
- vispy/visuals/collections/agg_segment_collection.py +142 -0
- vispy/visuals/collections/array_list.py +401 -0
- vispy/visuals/collections/base_collection.py +482 -0
- vispy/visuals/collections/collection.py +253 -0
- vispy/visuals/collections/path_collection.py +23 -0
- vispy/visuals/collections/point_collection.py +19 -0
- vispy/visuals/collections/polygon_collection.py +25 -0
- vispy/visuals/collections/raw_path_collection.py +119 -0
- vispy/visuals/collections/raw_point_collection.py +113 -0
- vispy/visuals/collections/raw_polygon_collection.py +77 -0
- vispy/visuals/collections/raw_segment_collection.py +112 -0
- vispy/visuals/collections/raw_triangle_collection.py +78 -0
- vispy/visuals/collections/segment_collection.py +19 -0
- vispy/visuals/collections/triangle_collection.py +16 -0
- vispy/visuals/collections/util.py +168 -0
- vispy/visuals/colorbar.py +699 -0
- vispy/visuals/cube.py +41 -0
- vispy/visuals/ellipse.py +163 -0
- vispy/visuals/filters/__init__.py +10 -0
- vispy/visuals/filters/base_filter.py +242 -0
- vispy/visuals/filters/clipper.py +60 -0
- vispy/visuals/filters/clipping_planes.py +122 -0
- vispy/visuals/filters/color.py +181 -0
- vispy/visuals/filters/markers.py +28 -0
- vispy/visuals/filters/mesh.py +796 -0
- vispy/visuals/filters/picking.py +60 -0
- vispy/visuals/filters/tests/__init__.py +3 -0
- vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
- vispy/visuals/filters/tests/test_wireframe_filter.py +16 -0
- vispy/visuals/glsl/__init__.py +1 -0
- vispy/visuals/glsl/antialiasing.py +133 -0
- vispy/visuals/glsl/color.py +63 -0
- vispy/visuals/graphs/__init__.py +1 -0
- vispy/visuals/graphs/graph.py +240 -0
- vispy/visuals/graphs/layouts/__init__.py +55 -0
- vispy/visuals/graphs/layouts/circular.py +49 -0
- vispy/visuals/graphs/layouts/force_directed.py +211 -0
- vispy/visuals/graphs/layouts/networkx_layout.py +87 -0
- vispy/visuals/graphs/layouts/random.py +52 -0
- vispy/visuals/graphs/tests/__init__.py +1 -0
- vispy/visuals/graphs/tests/test_layouts.py +139 -0
- vispy/visuals/graphs/tests/test_networkx_layout.py +47 -0
- vispy/visuals/graphs/util.py +120 -0
- vispy/visuals/gridlines.py +105 -0
- vispy/visuals/gridmesh.py +98 -0
- vispy/visuals/histogram.py +58 -0
- vispy/visuals/image.py +688 -0
- vispy/visuals/image_complex.py +130 -0
- vispy/visuals/infinite_line.py +199 -0
- vispy/visuals/instanced_mesh.py +152 -0
- vispy/visuals/isocurve.py +213 -0
- vispy/visuals/isoline.py +241 -0
- vispy/visuals/isosurface.py +113 -0
- vispy/visuals/line/__init__.py +6 -0
- vispy/visuals/line/arrow.py +289 -0
- vispy/visuals/line/dash_atlas.py +90 -0
- vispy/visuals/line/line.py +545 -0
- vispy/visuals/line_plot.py +135 -0
- vispy/visuals/linear_region.py +199 -0
- vispy/visuals/markers.py +810 -0
- vispy/visuals/mesh.py +373 -0
- vispy/visuals/mesh_normals.py +159 -0
- vispy/visuals/plane.py +54 -0
- vispy/visuals/polygon.py +145 -0
- vispy/visuals/rectangle.py +196 -0
- vispy/visuals/regular_polygon.py +56 -0
- vispy/visuals/scrolling_lines.py +197 -0
- vispy/visuals/shaders/__init__.py +17 -0
- vispy/visuals/shaders/compiler.py +206 -0
- vispy/visuals/shaders/expression.py +99 -0
- vispy/visuals/shaders/function.py +788 -0
- vispy/visuals/shaders/multiprogram.py +145 -0
- vispy/visuals/shaders/parsing.py +140 -0
- vispy/visuals/shaders/program.py +161 -0
- vispy/visuals/shaders/shader_object.py +162 -0
- vispy/visuals/shaders/tests/__init__.py +0 -0
- vispy/visuals/shaders/tests/test_function.py +486 -0
- vispy/visuals/shaders/tests/test_multiprogram.py +78 -0
- vispy/visuals/shaders/tests/test_parsing.py +57 -0
- vispy/visuals/shaders/variable.py +272 -0
- vispy/visuals/spectrogram.py +169 -0
- vispy/visuals/sphere.py +80 -0
- vispy/visuals/surface_plot.py +192 -0
- vispy/visuals/tests/__init__.py +0 -0
- vispy/visuals/tests/test_arrows.py +109 -0
- vispy/visuals/tests/test_axis.py +120 -0
- vispy/visuals/tests/test_collections.py +15 -0
- vispy/visuals/tests/test_colorbar.py +179 -0
- vispy/visuals/tests/test_colormap.py +97 -0
- vispy/visuals/tests/test_ellipse.py +122 -0
- vispy/visuals/tests/test_histogram.py +24 -0
- vispy/visuals/tests/test_image.py +390 -0
- vispy/visuals/tests/test_image_complex.py +36 -0
- vispy/visuals/tests/test_infinite_line.py +53 -0
- vispy/visuals/tests/test_instanced_mesh.py +50 -0
- vispy/visuals/tests/test_isosurface.py +22 -0
- vispy/visuals/tests/test_linear_region.py +152 -0
- vispy/visuals/tests/test_markers.py +54 -0
- vispy/visuals/tests/test_mesh.py +261 -0
- vispy/visuals/tests/test_mesh_normals.py +218 -0
- vispy/visuals/tests/test_polygon.py +112 -0
- vispy/visuals/tests/test_rectangle.py +163 -0
- vispy/visuals/tests/test_regular_polygon.py +111 -0
- vispy/visuals/tests/test_scalable_textures.py +180 -0
- vispy/visuals/tests/test_sdf.py +73 -0
- vispy/visuals/tests/test_spectrogram.py +42 -0
- vispy/visuals/tests/test_text.py +95 -0
- vispy/visuals/tests/test_volume.py +542 -0
- vispy/visuals/tests/test_windbarb.py +33 -0
- vispy/visuals/text/__init__.py +7 -0
- vispy/visuals/text/_sdf_cpu.cpython-311-darwin.so +0 -0
- vispy/visuals/text/_sdf_cpu.pyx +110 -0
- vispy/visuals/text/_sdf_gpu.py +316 -0
- vispy/visuals/text/text.py +675 -0
- vispy/visuals/transforms/__init__.py +34 -0
- vispy/visuals/transforms/_util.py +191 -0
- vispy/visuals/transforms/base_transform.py +233 -0
- vispy/visuals/transforms/chain.py +300 -0
- vispy/visuals/transforms/interactive.py +98 -0
- vispy/visuals/transforms/linear.py +564 -0
- vispy/visuals/transforms/nonlinear.py +398 -0
- vispy/visuals/transforms/tests/__init__.py +0 -0
- vispy/visuals/transforms/tests/test_transforms.py +243 -0
- vispy/visuals/transforms/transform_system.py +339 -0
- vispy/visuals/tube.py +173 -0
- vispy/visuals/visual.py +923 -0
- vispy/visuals/volume.py +1335 -0
- vispy/visuals/windbarb.py +291 -0
- vispy/visuals/xyz_axis.py +34 -0
- vispy-0.14.0.dist-info/LICENSE.txt +36 -0
- vispy-0.14.0.dist-info/METADATA +218 -0
- vispy-0.14.0.dist-info/RECORD +519 -0
- vispy-0.14.0.dist-info/WHEEL +5 -0
- vispy-0.14.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Tests for texture-based colormap
|
|
5
|
+
All images are of size (100,100) to keep a small file size
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from vispy.scene.visuals import Image
|
|
11
|
+
from vispy.testing import (requires_application, TestingCanvas,
|
|
12
|
+
run_tests_if_main)
|
|
13
|
+
from vispy.testing.image_tester import assert_image_approved
|
|
14
|
+
from vispy.color import Colormap
|
|
15
|
+
|
|
16
|
+
size = (100, 100)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@requires_application()
|
|
20
|
+
def test_colormap():
|
|
21
|
+
"""Test colormap support for non-uniformly distributed control-points"""
|
|
22
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
23
|
+
idata = np.linspace(255, 0, size[0]*size[1]).astype(np.ubyte)
|
|
24
|
+
data = idata.reshape((size[0], size[1]))
|
|
25
|
+
image = Image(cmap=Colormap(colors=['k', 'w', 'r'],
|
|
26
|
+
controls=[0.0, 0.1, 1.0]),
|
|
27
|
+
clim='auto', parent=c.scene)
|
|
28
|
+
image.set_data(data)
|
|
29
|
+
assert_image_approved(c.render(), "visuals/colormap_kwr.png")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@requires_application()
|
|
33
|
+
def test_colormap_discrete():
|
|
34
|
+
"""Test discrete RGB colormap"""
|
|
35
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
36
|
+
idata = np.linspace(255, 0, size[0]*size[1]).astype(np.ubyte)
|
|
37
|
+
data = idata.reshape((size[0], size[1]))
|
|
38
|
+
image = Image(cmap=Colormap(colors=['r', 'g', 'b'],
|
|
39
|
+
interpolation='zero'),
|
|
40
|
+
clim='auto', parent=c.scene)
|
|
41
|
+
image.set_data(data)
|
|
42
|
+
assert_image_approved(c.render(), "visuals/colormap_rgb.png")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@requires_application()
|
|
46
|
+
def test_colormap_discrete_nu():
|
|
47
|
+
"""Test discrete colormap with non-uniformly distributed control-points"""
|
|
48
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
49
|
+
idata = np.linspace(255, 0, size[0]*size[1]).astype(np.ubyte)
|
|
50
|
+
data = idata.reshape((size[0], size[1]))
|
|
51
|
+
image = Image(cmap=Colormap(np.array([[0, .75, 0], [.75, .25, .5]]),
|
|
52
|
+
[0., .25, 1.], interpolation='zero'),
|
|
53
|
+
clim='auto', parent=c.scene)
|
|
54
|
+
image.set_data(data)
|
|
55
|
+
assert_image_approved(c.render(), "visuals/colormap_nu.png")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@requires_application()
|
|
59
|
+
def test_colormap_single_hue():
|
|
60
|
+
"""Test colormap support using a single hue()"""
|
|
61
|
+
from vispy.color.colormap import SingleHue
|
|
62
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
63
|
+
idata = np.linspace(255, 0, size[0]*size[1]).astype(np.ubyte)
|
|
64
|
+
data = idata.reshape((size[0], size[1]))
|
|
65
|
+
cmap = SingleHue(255)
|
|
66
|
+
image = Image(cmap=cmap,
|
|
67
|
+
clim='auto', parent=c.scene)
|
|
68
|
+
image.set_data(data)
|
|
69
|
+
assert_image_approved(c.render(), "visuals/colormap_hue.png")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@requires_application()
|
|
73
|
+
def test_colormap_coolwarm():
|
|
74
|
+
"""Test colormap support using coolwarm preset colormap"""
|
|
75
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
76
|
+
idata = np.linspace(255, 0, size[0]*size[1]).astype(np.ubyte)
|
|
77
|
+
data = idata.reshape((size[0], size[1]))
|
|
78
|
+
image = Image(cmap='coolwarm', clim='auto', parent=c.scene)
|
|
79
|
+
image.set_data(data)
|
|
80
|
+
assert_image_approved(c.render(), "visuals/colormap_coolwarm.png")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@requires_application()
|
|
84
|
+
def test_colormap_CubeHelix():
|
|
85
|
+
"""Test colormap support using cubehelix colormap in only blues"""
|
|
86
|
+
from vispy.color.colormap import CubeHelixColormap
|
|
87
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
88
|
+
idata = np.linspace(255, 0, size[0]*size[1]).astype(np.ubyte)
|
|
89
|
+
data = idata.reshape((size[0], size[1]))
|
|
90
|
+
cmap = CubeHelixColormap(rot=0, start=0)
|
|
91
|
+
image = Image(cmap=cmap,
|
|
92
|
+
clim='auto', parent=c.scene)
|
|
93
|
+
image.set_data(data)
|
|
94
|
+
assert_image_approved(c.render(), "visuals/colormap_cubehelix.png")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
run_tests_if_main()
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) Vispy Development Team. All Rights Reserved.
|
|
3
|
+
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
Tests for EllipseVisual
|
|
7
|
+
All images are of size (100,100) to keep a small file size
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from vispy.scene import visuals, transforms
|
|
11
|
+
from vispy.testing import (requires_application, TestingCanvas,
|
|
12
|
+
run_tests_if_main)
|
|
13
|
+
from vispy.testing.image_tester import assert_image_approved
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@requires_application()
|
|
17
|
+
def test_circle_draw():
|
|
18
|
+
"""Test drawing circles without transform using EllipseVisual"""
|
|
19
|
+
with TestingCanvas() as c:
|
|
20
|
+
ellipse = visuals.Ellipse(center=(75, 35, 0), radius=20,
|
|
21
|
+
color=(1, 0, 0, 1),
|
|
22
|
+
parent=c.scene)
|
|
23
|
+
assert_image_approved(c.render(), 'visuals/circle1.png')
|
|
24
|
+
|
|
25
|
+
ellipse.parent = None
|
|
26
|
+
ellipse = visuals.Ellipse(center=(75, 35, 0), radius=20,
|
|
27
|
+
color=(1, 0, 0, 1),
|
|
28
|
+
border_color=(0, 1, 1, 1),
|
|
29
|
+
parent=c.scene)
|
|
30
|
+
assert_image_approved(c.render(), 'visuals/circle2.png')
|
|
31
|
+
|
|
32
|
+
ellipse.parent = None
|
|
33
|
+
ellipse = visuals.Ellipse(center=(75, 35, 0), radius=20,
|
|
34
|
+
border_color=(0, 1, 1, 1),
|
|
35
|
+
parent=c.scene)
|
|
36
|
+
|
|
37
|
+
# low corr here because borders have some variability
|
|
38
|
+
# esp. w/HiDPI
|
|
39
|
+
assert_image_approved(c.render(), 'visuals/circle3.png',
|
|
40
|
+
min_corr=0.7)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@requires_application()
|
|
44
|
+
def test_ellipse_draw():
|
|
45
|
+
"""Test drawing transformed ellipses using EllipseVisual"""
|
|
46
|
+
with TestingCanvas() as c:
|
|
47
|
+
ellipse = visuals.Ellipse(center=(0., 0.), radius=(20, 15),
|
|
48
|
+
color=(0, 0, 1, 1),
|
|
49
|
+
parent=c.scene)
|
|
50
|
+
ellipse.transform = transforms.STTransform(scale=(2.0, 3.0),
|
|
51
|
+
translate=(50, 50))
|
|
52
|
+
assert_image_approved(c.render(), 'visuals/ellipse1.png')
|
|
53
|
+
|
|
54
|
+
ellipse.parent = None
|
|
55
|
+
ellipse = visuals.Ellipse(center=(0., 0.), radius=(20, 15),
|
|
56
|
+
color=(0, 0, 1, 1),
|
|
57
|
+
border_color=(1, 0, 0, 1),
|
|
58
|
+
parent=c.scene)
|
|
59
|
+
ellipse.transform = transforms.STTransform(scale=(2.0, 3.0),
|
|
60
|
+
translate=(50, 50))
|
|
61
|
+
assert_image_approved(c.render(), 'visuals/ellipse2.png')
|
|
62
|
+
|
|
63
|
+
ellipse.parent = None
|
|
64
|
+
ellipse = visuals.Ellipse(center=(0., 0.), radius=(20, 15),
|
|
65
|
+
border_color=(1, 0, 0, 1),
|
|
66
|
+
parent=c.scene)
|
|
67
|
+
ellipse.transform = transforms.STTransform(scale=(2.0, 3.0),
|
|
68
|
+
translate=(50, 50))
|
|
69
|
+
assert_image_approved(c.render(), 'visuals/ellipse3.png',
|
|
70
|
+
min_corr=0.7)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@requires_application()
|
|
74
|
+
def test_arc_draw1():
|
|
75
|
+
"""Test drawing arcs using EllipseVisual"""
|
|
76
|
+
with TestingCanvas() as c:
|
|
77
|
+
ellipse = visuals.Ellipse(center=(50., 50.), radius=(20, 15),
|
|
78
|
+
start_angle=150., span_angle=120.,
|
|
79
|
+
color=(0, 0, 1, 1),
|
|
80
|
+
parent=c.scene)
|
|
81
|
+
assert_image_approved(c.render(), 'visuals/arc1.png')
|
|
82
|
+
|
|
83
|
+
ellipse.parent = None
|
|
84
|
+
ellipse = visuals.Ellipse(center=(50., 50.), radius=(20, 15),
|
|
85
|
+
start_angle=150., span_angle=120.,
|
|
86
|
+
border_color=(1, 0, 0, 1),
|
|
87
|
+
parent=c.scene)
|
|
88
|
+
assert_image_approved(c.render(), 'visuals/arc2.png',
|
|
89
|
+
min_corr=0.6)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@requires_application()
|
|
93
|
+
def test_reactive_draw():
|
|
94
|
+
"""Test reactive ellipse attributes"""
|
|
95
|
+
with TestingCanvas() as c:
|
|
96
|
+
ellipse = visuals.Ellipse(center=[75, 35, 0.], radius=[20, 15],
|
|
97
|
+
color='yellow',
|
|
98
|
+
parent=c.scene)
|
|
99
|
+
|
|
100
|
+
ellipse.center = [70, 40, 0.]
|
|
101
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse1.png')
|
|
102
|
+
|
|
103
|
+
ellipse.radius = 25
|
|
104
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse2.png')
|
|
105
|
+
|
|
106
|
+
ellipse.color = 'red'
|
|
107
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse3.png')
|
|
108
|
+
|
|
109
|
+
ellipse.border_color = 'yellow'
|
|
110
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse4.png')
|
|
111
|
+
|
|
112
|
+
ellipse.start_angle = 140.
|
|
113
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse5.png')
|
|
114
|
+
|
|
115
|
+
ellipse.span_angle = 100.
|
|
116
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse6.png')
|
|
117
|
+
|
|
118
|
+
ellipse.num_segments = 10.
|
|
119
|
+
assert_image_approved(c.render(), 'visuals/reactive_ellipse7.png')
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
run_tests_if_main()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from vispy.visuals.transforms import STTransform
|
|
5
|
+
from vispy.scene.visuals import Histogram
|
|
6
|
+
from vispy.testing import (requires_application, TestingCanvas,
|
|
7
|
+
run_tests_if_main)
|
|
8
|
+
from vispy.testing.image_tester import assert_image_approved
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@requires_application()
|
|
12
|
+
def test_histogram():
|
|
13
|
+
"""Test histogram visual"""
|
|
14
|
+
size = (200, 100)
|
|
15
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
16
|
+
np.random.seed(2397)
|
|
17
|
+
data = np.random.normal(size=100)
|
|
18
|
+
hist = Histogram(data, bins=20, color='k', parent=c.scene)
|
|
19
|
+
hist.transform = STTransform((size[0] // 10, -size[1] // 20, 1),
|
|
20
|
+
(100, size[1]))
|
|
21
|
+
assert_image_approved(c.render(), "visuals/histogram.png")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
run_tests_if_main()
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
from vispy.scene import Image, PanZoomCamera
|
|
5
|
+
from vispy.testing import (requires_application, TestingCanvas,
|
|
6
|
+
run_tests_if_main, IS_CI)
|
|
7
|
+
from vispy.testing.image_tester import assert_image_approved, downsample
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from vispy.testing.rendered_array_tester import compare_render, max_for_dtype
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@requires_application()
|
|
16
|
+
@pytest.mark.parametrize('is_3d', [True, False])
|
|
17
|
+
def test_image(is_3d):
|
|
18
|
+
"""Test image visual"""
|
|
19
|
+
size = (100, 50)
|
|
20
|
+
with TestingCanvas(size=size, bgcolor='w') as c:
|
|
21
|
+
image = Image(cmap='grays', clim=[0, 1], parent=c.scene)
|
|
22
|
+
shape = (size[1]-10, size[0]-10) + ((3,) if is_3d else ())
|
|
23
|
+
np.random.seed(379823)
|
|
24
|
+
data = np.random.rand(*shape)
|
|
25
|
+
image.set_data(data)
|
|
26
|
+
assert_image_approved(c.render(), "visuals/image%s.png" %
|
|
27
|
+
("_rgb" if is_3d else "_mono"))
|
|
28
|
+
|
|
29
|
+
# change to auto clims after first draw
|
|
30
|
+
image.clim = "auto"
|
|
31
|
+
assert_image_approved(c.render(), "visuals/image%s.png" %
|
|
32
|
+
("_rgb" if is_3d else "_mono"))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@requires_application()
|
|
36
|
+
@pytest.mark.parametrize('gamma', [None, -0.5, "0.5"])
|
|
37
|
+
def test_bad_init_gamma(gamma):
|
|
38
|
+
"""Test creating an Image with a bad gamma value."""
|
|
39
|
+
with TestingCanvas(size=(100, 50)) as c:
|
|
40
|
+
pytest.raises((TypeError, ValueError), Image, gamma=gamma, parent=c.scene)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _make_test_data(shape, input_dtype):
|
|
44
|
+
data = np.random.random_sample(shape)
|
|
45
|
+
if data.ndim == 3 and data.shape[-1] == 4:
|
|
46
|
+
# RGBA - make alpha fully opaque
|
|
47
|
+
data[..., -1] = 1.0
|
|
48
|
+
max_val = max_for_dtype(input_dtype)
|
|
49
|
+
if max_val != 1:
|
|
50
|
+
data *= max_val
|
|
51
|
+
data = data.astype(input_dtype)
|
|
52
|
+
return data
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _set_image_data(image, data, should_fail):
|
|
56
|
+
if should_fail:
|
|
57
|
+
pytest.raises(ValueError, image.set_data, data)
|
|
58
|
+
return
|
|
59
|
+
image.set_data(data)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _get_orig_and_new_clims(input_dtype):
|
|
63
|
+
new_clim = (0.3, 0.8)
|
|
64
|
+
max_val = max_for_dtype(input_dtype)
|
|
65
|
+
if np.issubdtype(input_dtype, np.integer):
|
|
66
|
+
new_clim = (int(new_clim[0] * max_val), int(new_clim[1] * max_val))
|
|
67
|
+
return (0, max_val), new_clim
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@requires_application()
|
|
71
|
+
@pytest.mark.parametrize('data_on_init', [False, True])
|
|
72
|
+
@pytest.mark.parametrize('clim_on_init', [False, True])
|
|
73
|
+
@pytest.mark.parametrize('num_channels', [0, 1, 3, 4])
|
|
74
|
+
@pytest.mark.parametrize('texture_format', [None, '__dtype__', 'auto'])
|
|
75
|
+
@pytest.mark.parametrize('input_dtype', [np.uint8, np.uint16, np.float32, np.float64])
|
|
76
|
+
def test_image_clims_and_gamma(input_dtype, texture_format, num_channels,
|
|
77
|
+
clim_on_init, data_on_init):
|
|
78
|
+
"""Test image visual with clims and gamma on shader."""
|
|
79
|
+
size = (80, 80)
|
|
80
|
+
if texture_format == '__dtype__':
|
|
81
|
+
texture_format = input_dtype
|
|
82
|
+
shape = size + (num_channels,) if num_channels > 0 else size
|
|
83
|
+
np.random.seed(0)
|
|
84
|
+
data = _make_test_data(shape, input_dtype)
|
|
85
|
+
orig_clim, new_clim = _get_orig_and_new_clims(input_dtype)
|
|
86
|
+
# 16-bit integers and above seem to have precision loss when scaled on the CPU
|
|
87
|
+
is_16int_cpu_scaled = (np.dtype(input_dtype).itemsize >= 2 and
|
|
88
|
+
np.issubdtype(input_dtype, np.integer) and
|
|
89
|
+
texture_format is None)
|
|
90
|
+
clim_atol = 2 if is_16int_cpu_scaled else 1
|
|
91
|
+
gamma_atol = 3 if is_16int_cpu_scaled else 2
|
|
92
|
+
|
|
93
|
+
kwargs = {}
|
|
94
|
+
if clim_on_init:
|
|
95
|
+
kwargs['clim'] = orig_clim
|
|
96
|
+
if data_on_init:
|
|
97
|
+
kwargs['data'] = data
|
|
98
|
+
# default is RGBA, anything except auto requires reformat
|
|
99
|
+
set_data_fails = (num_channels != 4 and
|
|
100
|
+
texture_format is not None and
|
|
101
|
+
texture_format != 'auto')
|
|
102
|
+
|
|
103
|
+
with TestingCanvas(size=size[::-1], bgcolor="w") as c:
|
|
104
|
+
image = Image(cmap='grays', texture_format=texture_format,
|
|
105
|
+
parent=c.scene, **kwargs)
|
|
106
|
+
if not data_on_init:
|
|
107
|
+
_set_image_data(image, data, set_data_fails)
|
|
108
|
+
if set_data_fails:
|
|
109
|
+
return
|
|
110
|
+
rendered = c.render()
|
|
111
|
+
_dtype = rendered.dtype
|
|
112
|
+
shape_ratio = rendered.shape[0] // data.shape[0]
|
|
113
|
+
rendered1 = downsample(rendered, shape_ratio, axis=(0, 1)).astype(_dtype)
|
|
114
|
+
compare_render(data, rendered1)
|
|
115
|
+
|
|
116
|
+
# adjust color limits
|
|
117
|
+
image.clim = new_clim
|
|
118
|
+
rendered2 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype)
|
|
119
|
+
scaled_data = (np.clip(data, new_clim[0], new_clim[1]) - new_clim[0]) / (new_clim[1] - new_clim[0])
|
|
120
|
+
compare_render(scaled_data, rendered2, rendered1, atol=clim_atol)
|
|
121
|
+
|
|
122
|
+
# adjust gamma
|
|
123
|
+
image.gamma = 2
|
|
124
|
+
rendered3 = downsample(c.render(), shape_ratio, axis=(0, 1)).astype(_dtype)
|
|
125
|
+
compare_render(scaled_data ** 2, rendered3, rendered2, atol=gamma_atol)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@pytest.mark.xfail(IS_CI, reason="CI environments sometimes treat NaN as 0")
|
|
129
|
+
@requires_application()
|
|
130
|
+
@pytest.mark.parametrize('texture_format', [None, 'auto'])
|
|
131
|
+
def test_image_nan_single_band(texture_format):
|
|
132
|
+
size = (40, 40)
|
|
133
|
+
data = np.ones((40, 40))
|
|
134
|
+
data[:5, :5] = np.nan
|
|
135
|
+
data[:5, -5:] = 0
|
|
136
|
+
|
|
137
|
+
expected = (np.ones((40, 40, 4)) * 255).astype(np.uint8)
|
|
138
|
+
# black square
|
|
139
|
+
expected[:5, -5:, :3] = 0
|
|
140
|
+
if texture_format is None:
|
|
141
|
+
# CPU scaling's NaNs get converted to 0s
|
|
142
|
+
expected[:5, :5, :3] = 0
|
|
143
|
+
else:
|
|
144
|
+
# GPU receives NaNs
|
|
145
|
+
# nan - transparent square
|
|
146
|
+
expected[:5, :5, 0] = 0
|
|
147
|
+
expected[:5, :5, 1] = 255 # match the 'green' background
|
|
148
|
+
expected[:5, :5, 2] = 0
|
|
149
|
+
|
|
150
|
+
with TestingCanvas(size=size[::-1], bgcolor=(0, 1, 0)) as c:
|
|
151
|
+
Image(data, cmap='grays',
|
|
152
|
+
texture_format=texture_format, parent=c.scene)
|
|
153
|
+
rendered = c.render()
|
|
154
|
+
np.testing.assert_allclose(rendered, expected)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@requires_application()
|
|
158
|
+
@pytest.mark.parametrize('num_bands', [3, 4])
|
|
159
|
+
@pytest.mark.parametrize('texture_format', [None, 'auto'])
|
|
160
|
+
def test_image_nan_rgb(texture_format, num_bands):
|
|
161
|
+
size = (40, 40)
|
|
162
|
+
data = np.ones((40, 40, num_bands))
|
|
163
|
+
data[:5, :5, :3] = np.nan # upper left - RGB all NaN
|
|
164
|
+
data[:5, 20:25, 0] = np.nan # upper middle - R NaN
|
|
165
|
+
data[:5, -5:, :3] = 0 # upper right - opaque RGB black square
|
|
166
|
+
data[-5:, -5:, :] = np.nan # lower right RGBA all NaN
|
|
167
|
+
if num_bands == 4:
|
|
168
|
+
data[-5:, :5, 3] = np.nan # lower left - Alpha NaN
|
|
169
|
+
|
|
170
|
+
expected = (np.ones((40, 40, 4)) * 255).astype(np.uint8)
|
|
171
|
+
# upper left - NaN goes to opaque black
|
|
172
|
+
expected[:5, :5, :3] = 0
|
|
173
|
+
# upper middle -> NaN R goes to 0
|
|
174
|
+
expected[:5, 20:25, 0] = 0
|
|
175
|
+
# upper right - opaque RGB black square
|
|
176
|
+
expected[:5, -5:, :3] = 0
|
|
177
|
+
# lower right - NaN RGB/A goes to 0
|
|
178
|
+
# RGBA case - we see the green background behind the image
|
|
179
|
+
expected[-5:, -5:, 0] = 0
|
|
180
|
+
expected[-5:, -5:, 2] = 0
|
|
181
|
+
if num_bands == 3:
|
|
182
|
+
# RGB case - opaque black because Alpha defaults 1
|
|
183
|
+
expected[-5:, -5:, 1] = 0
|
|
184
|
+
# lower left - NaN Alpha goes to 0
|
|
185
|
+
if num_bands == 4:
|
|
186
|
+
# see the green background behind the image
|
|
187
|
+
expected[-5:, :5, 0] = 0
|
|
188
|
+
expected[-5:, :5, 2] = 0
|
|
189
|
+
|
|
190
|
+
with TestingCanvas(size=size[::-1], bgcolor=(0, 1, 0)) as c:
|
|
191
|
+
Image(data, cmap='grays',
|
|
192
|
+
texture_format=texture_format, parent=c.scene)
|
|
193
|
+
rendered = c.render()
|
|
194
|
+
np.testing.assert_allclose(rendered, expected)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@requires_application()
|
|
198
|
+
@pytest.mark.parametrize('num_channels', [0, 1, 3, 4])
|
|
199
|
+
@pytest.mark.parametrize('texture_format', [None, 'auto'])
|
|
200
|
+
def test_image_equal_clims(texture_format, num_channels):
|
|
201
|
+
"""Test image visual with equal clims."""
|
|
202
|
+
size = (40, 40)
|
|
203
|
+
input_dtype = np.uint8
|
|
204
|
+
shape = size + (num_channels,) if num_channels > 0 else size
|
|
205
|
+
np.random.seed(0)
|
|
206
|
+
data = _make_test_data(shape, input_dtype)
|
|
207
|
+
with TestingCanvas(size=size[::-1], bgcolor="w") as c:
|
|
208
|
+
Image(data, cmap='viridis',
|
|
209
|
+
texture_format=texture_format,
|
|
210
|
+
clim=(128.0, 128.0),
|
|
211
|
+
parent=c.scene)
|
|
212
|
+
rendered = c.render()[..., :3]
|
|
213
|
+
|
|
214
|
+
if num_channels >= 3:
|
|
215
|
+
# RGBs don't have colormaps
|
|
216
|
+
assert rendered.sum() == 0
|
|
217
|
+
return
|
|
218
|
+
|
|
219
|
+
# not all black
|
|
220
|
+
assert rendered.sum() != 0
|
|
221
|
+
# not all white
|
|
222
|
+
assert rendered.sum() != 255 * rendered.size
|
|
223
|
+
# should be all the same value
|
|
224
|
+
r_unique = np.unique(rendered[..., 0])
|
|
225
|
+
g_unique = np.unique(rendered[..., 1])
|
|
226
|
+
b_unique = np.unique(rendered[..., 2])
|
|
227
|
+
assert r_unique.size == 1
|
|
228
|
+
assert g_unique.size == 1
|
|
229
|
+
assert b_unique.size == 1
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@requires_application()
|
|
233
|
+
def test_image_vertex_updates():
|
|
234
|
+
"""Test image visual coordinates are only built when needed."""
|
|
235
|
+
size = (40, 40)
|
|
236
|
+
with TestingCanvas(size=size, bgcolor="w") as c:
|
|
237
|
+
shape = size + (3,)
|
|
238
|
+
np.random.seed(0)
|
|
239
|
+
image = Image(cmap='grays', clim=[0, 1], parent=c.scene)
|
|
240
|
+
with mock.patch.object(
|
|
241
|
+
image, '_build_vertex_data',
|
|
242
|
+
wraps=image._build_vertex_data) as build_vertex_mock:
|
|
243
|
+
data = np.random.rand(*shape)
|
|
244
|
+
image.set_data(data)
|
|
245
|
+
c.render()
|
|
246
|
+
build_vertex_mock.assert_called_once()
|
|
247
|
+
build_vertex_mock.reset_mock() # reset the count to 0
|
|
248
|
+
|
|
249
|
+
# rendering again shouldn't cause vertex coordinates to be built
|
|
250
|
+
c.render()
|
|
251
|
+
build_vertex_mock.assert_not_called()
|
|
252
|
+
|
|
253
|
+
# changing to data of the same shape shouldn't cause it
|
|
254
|
+
data = np.zeros_like(data)
|
|
255
|
+
image.set_data(data)
|
|
256
|
+
c.render()
|
|
257
|
+
build_vertex_mock.assert_not_called()
|
|
258
|
+
|
|
259
|
+
# changing to another shape should
|
|
260
|
+
data = data[:-5, :-5]
|
|
261
|
+
image.set_data(data)
|
|
262
|
+
c.render()
|
|
263
|
+
build_vertex_mock.assert_called_once()
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@requires_application()
|
|
267
|
+
@pytest.mark.parametrize(
|
|
268
|
+
("dtype", "init_clim"),
|
|
269
|
+
[
|
|
270
|
+
(np.float32, "auto"),
|
|
271
|
+
(np.float32, (0, 5)),
|
|
272
|
+
(np.uint8, "auto"),
|
|
273
|
+
(np.uint8, (0, 5)),
|
|
274
|
+
]
|
|
275
|
+
)
|
|
276
|
+
def test_change_clim_float(dtype, init_clim):
|
|
277
|
+
"""Test that with an image of floats, clim is correctly set from the first try.
|
|
278
|
+
|
|
279
|
+
See https://github.com/vispy/vispy/pull/2245.
|
|
280
|
+
"""
|
|
281
|
+
size = (40, 40)
|
|
282
|
+
np.random.seed(0)
|
|
283
|
+
data = (np.random.rand(*size) * 100).astype(dtype)
|
|
284
|
+
|
|
285
|
+
with TestingCanvas(size=size[::-1], bgcolor="w") as c:
|
|
286
|
+
image = Image(data=data, clim=init_clim, parent=c.scene)
|
|
287
|
+
|
|
288
|
+
# needed to properly initialize the canvas
|
|
289
|
+
c.render()
|
|
290
|
+
|
|
291
|
+
image.clim = 0, 10
|
|
292
|
+
rendered1 = c.render()
|
|
293
|
+
# set clim to same values
|
|
294
|
+
image.clim = 0, 10
|
|
295
|
+
rendered2 = c.render()
|
|
296
|
+
|
|
297
|
+
assert np.allclose(rendered1, rendered2)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
@requires_application()
|
|
301
|
+
def test_image_interpolation():
|
|
302
|
+
"""Test different interpolations"""
|
|
303
|
+
size = (81, 81)
|
|
304
|
+
data = np.array([[0, 1]], dtype=int)
|
|
305
|
+
left = (40, 0)
|
|
306
|
+
right = (40, 80)
|
|
307
|
+
center_left = (40, 39)
|
|
308
|
+
center = (40, 40)
|
|
309
|
+
center_right = (40, 41)
|
|
310
|
+
white = (255, 255, 255, 255)
|
|
311
|
+
black = (0, 0, 0, 255)
|
|
312
|
+
gray = (128, 128, 128, 255)
|
|
313
|
+
|
|
314
|
+
with TestingCanvas(size=size[::-1], bgcolor="w") as c:
|
|
315
|
+
view = c.central_widget.add_view(border_width=0)
|
|
316
|
+
view.camera = PanZoomCamera((0, 0, 2, 1))
|
|
317
|
+
image = Image(data=data, cmap='grays',
|
|
318
|
+
parent=view.scene)
|
|
319
|
+
|
|
320
|
+
# needed to properly initialize the canvas
|
|
321
|
+
render = c.render()
|
|
322
|
+
|
|
323
|
+
image.interpolation = 'nearest'
|
|
324
|
+
render = c.render()
|
|
325
|
+
assert np.allclose(render[left], black)
|
|
326
|
+
assert np.allclose(render[right], white)
|
|
327
|
+
assert np.allclose(render[center_left], black)
|
|
328
|
+
assert np.allclose(render[center_right], white)
|
|
329
|
+
|
|
330
|
+
image.interpolation = 'bilinear'
|
|
331
|
+
render = c.render()
|
|
332
|
+
assert np.allclose(render[left], black)
|
|
333
|
+
assert np.allclose(render[right], white)
|
|
334
|
+
assert np.allclose(render[center], gray, atol=5) # we just want gray, this is not quantitative
|
|
335
|
+
|
|
336
|
+
image.interpolation = 'custom'
|
|
337
|
+
image.custom_kernel = np.array([[0]]) # no sampling
|
|
338
|
+
render = c.render()
|
|
339
|
+
assert np.allclose(render[left], black)
|
|
340
|
+
assert np.allclose(render[right], black)
|
|
341
|
+
assert np.allclose(render[center], black)
|
|
342
|
+
|
|
343
|
+
image.custom_kernel = np.array([[1]]) # same as linear
|
|
344
|
+
render = c.render()
|
|
345
|
+
assert np.allclose(render[left], black)
|
|
346
|
+
assert np.allclose(render[right], white)
|
|
347
|
+
assert np.allclose(render[center], gray, atol=5) # we just want gray, this is not quantitative
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@requires_application()
|
|
351
|
+
def test_image_set_data_different_dtype():
|
|
352
|
+
size = (80, 80)
|
|
353
|
+
data = np.array([[0, 127]], dtype=np.int8)
|
|
354
|
+
left = (40, 10)
|
|
355
|
+
right = (40, 70)
|
|
356
|
+
white = (255, 255, 255, 255)
|
|
357
|
+
black = (0, 0, 0, 255)
|
|
358
|
+
|
|
359
|
+
with TestingCanvas(size=size[::-1], bgcolor="w") as c:
|
|
360
|
+
view = c.central_widget.add_view()
|
|
361
|
+
view.camera = PanZoomCamera((0, 0, 2, 1))
|
|
362
|
+
image = Image(data=data, cmap='grays', clim=[0, 127],
|
|
363
|
+
parent=view.scene)
|
|
364
|
+
|
|
365
|
+
render = c.render()
|
|
366
|
+
assert np.allclose(render[left], black)
|
|
367
|
+
assert np.allclose(render[right], white)
|
|
368
|
+
|
|
369
|
+
# same data as float should change nothing
|
|
370
|
+
image.set_data(data.astype(np.float32))
|
|
371
|
+
render = c.render()
|
|
372
|
+
assert np.allclose(render[left], black)
|
|
373
|
+
assert np.allclose(render[right], white)
|
|
374
|
+
|
|
375
|
+
# something inverted, different dtype
|
|
376
|
+
new_data = np.array([[127, 0]], dtype=np.float16)
|
|
377
|
+
image.set_data(new_data)
|
|
378
|
+
render = c.render()
|
|
379
|
+
assert np.allclose(render[left], white)
|
|
380
|
+
assert np.allclose(render[right], black)
|
|
381
|
+
|
|
382
|
+
# out of bounds should clip (2000 > 127)
|
|
383
|
+
new_data = np.array([[0, 2000]], dtype=np.float64)
|
|
384
|
+
image.set_data(new_data)
|
|
385
|
+
render = c.render()
|
|
386
|
+
assert np.allclose(render[left], black)
|
|
387
|
+
assert np.allclose(render[right], white)
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
run_tests_if_main()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from vispy.scene.visuals import ComplexImage
|
|
2
|
+
from vispy.visuals.image_complex import CPU_COMPLEX_TRANSFORMS
|
|
3
|
+
from vispy.testing import requires_application, TestingCanvas
|
|
4
|
+
from vispy.testing.image_tester import downsample
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from vispy.testing.rendered_array_tester import compare_render
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# we add the np.float32 case to test that ComplexImage falls back to Image behavior
|
|
13
|
+
# if the data is not complex
|
|
14
|
+
@requires_application()
|
|
15
|
+
@pytest.mark.parametrize("input_dtype", [np.complex64, np.complex128, np.float32])
|
|
16
|
+
@pytest.mark.parametrize("complex_mode", ["magnitude", "real", "imaginary", "phase"])
|
|
17
|
+
def test_image_complex(input_dtype, complex_mode):
|
|
18
|
+
"""Test rendering of complex-valued image data."""
|
|
19
|
+
shape = (40, 40)
|
|
20
|
+
np.random.seed(0)
|
|
21
|
+
data = np.random.random(shape).astype(input_dtype)
|
|
22
|
+
if np.iscomplexobj(data):
|
|
23
|
+
data.imag = np.random.random(shape)
|
|
24
|
+
|
|
25
|
+
with TestingCanvas(size=shape, bgcolor="w") as c:
|
|
26
|
+
ComplexImage(data, cmap="grays", complex_mode=complex_mode, parent=c.scene)
|
|
27
|
+
# render to canvas
|
|
28
|
+
rendered = c.render()
|
|
29
|
+
shape_ratio = rendered.shape[0] // data.shape[0]
|
|
30
|
+
rendered = downsample(rendered, shape_ratio, axis=(0, 1))
|
|
31
|
+
|
|
32
|
+
# perform (auto-clim) rendering on cpu
|
|
33
|
+
exp = CPU_COMPLEX_TRANSFORMS[complex_mode](data) if np.iscomplexobj(data) else data
|
|
34
|
+
exp -= exp.min()
|
|
35
|
+
exp /= exp.max()
|
|
36
|
+
compare_render(exp, rendered)
|