vispy 0.14.0__cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of vispy might be problematic. Click here for more details.
- 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-312-aarch64-linux-gnu.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 +6 -0
- vispy-0.14.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,447 @@
|
|
|
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
|
+
from __future__ import division # just to be safe...
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
|
|
10
|
+
from ..util import logger
|
|
11
|
+
from ._color_dict import _color_dict
|
|
12
|
+
from .color_space import (_hex_to_rgba, _rgb_to_hex, _rgb_to_hsv, # noqa
|
|
13
|
+
_hsv_to_rgb, _rgb_to_lab, _lab_to_rgb) # noqa
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
###############################################################################
|
|
17
|
+
# User-friendliness helpers
|
|
18
|
+
|
|
19
|
+
def _string_to_rgb(color):
|
|
20
|
+
"""Convert user string or hex color to color array (length 3 or 4)"""
|
|
21
|
+
if not color.startswith('#'):
|
|
22
|
+
if color.lower() not in _color_dict:
|
|
23
|
+
raise ValueError('Color "%s" unknown' % color)
|
|
24
|
+
color = _color_dict[color.lower()]
|
|
25
|
+
assert color[0] == '#'
|
|
26
|
+
# hex color
|
|
27
|
+
color = color[1:]
|
|
28
|
+
lc = len(color)
|
|
29
|
+
if lc in (3, 4):
|
|
30
|
+
color = ''.join(c + c for c in color)
|
|
31
|
+
lc = len(color)
|
|
32
|
+
if lc not in (6, 8):
|
|
33
|
+
raise ValueError('Hex color must have exactly six or eight '
|
|
34
|
+
'elements following the # sign')
|
|
35
|
+
color = np.array([int(color[i:i+2], 16) / 255. for i in range(0, lc, 2)])
|
|
36
|
+
return color
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _user_to_rgba(color, expand=True, clip=False):
|
|
40
|
+
"""Convert color(s) from any set of fmts (str/hex/arr) to RGB(A) array"""
|
|
41
|
+
if color is None:
|
|
42
|
+
color = np.zeros(4, np.float32)
|
|
43
|
+
if isinstance(color, str):
|
|
44
|
+
color = _string_to_rgb(color)
|
|
45
|
+
elif isinstance(color, ColorArray):
|
|
46
|
+
color = color.rgba
|
|
47
|
+
# We have to treat this specially
|
|
48
|
+
elif isinstance(color, (list, tuple)):
|
|
49
|
+
if any(isinstance(c, (str, ColorArray)) for c in color):
|
|
50
|
+
color = [_user_to_rgba(c, expand=expand, clip=clip) for c in color]
|
|
51
|
+
if any(len(c) > 1 for c in color):
|
|
52
|
+
raise RuntimeError('could not parse colors, are they nested?')
|
|
53
|
+
color = [c[0] for c in color]
|
|
54
|
+
color = np.atleast_2d(color).astype(np.float32)
|
|
55
|
+
if color.shape[1] not in (3, 4):
|
|
56
|
+
raise ValueError('color must have three or four elements')
|
|
57
|
+
if expand and color.shape[1] == 3: # only expand if requested
|
|
58
|
+
color = np.concatenate((color, np.ones((color.shape[0], 1))),
|
|
59
|
+
axis=1)
|
|
60
|
+
if color.min() < 0 or color.max() > 1:
|
|
61
|
+
if clip:
|
|
62
|
+
color = np.clip(color, 0, 1)
|
|
63
|
+
else:
|
|
64
|
+
raise ValueError("Color values must be between 0 and 1 (or use "
|
|
65
|
+
"clip=True to automatically clip the values).")
|
|
66
|
+
return color
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _array_clip_val(val):
|
|
70
|
+
"""Helper to turn val into array and clip between 0 and 1"""
|
|
71
|
+
val = np.array(val)
|
|
72
|
+
if val.max() > 1 or val.min() < 0:
|
|
73
|
+
logger.warning('value will be clipped between 0 and 1')
|
|
74
|
+
val[...] = np.clip(val, 0, 1)
|
|
75
|
+
return val
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
###############################################################################
|
|
79
|
+
# Color Array
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ColorArray(object):
|
|
83
|
+
"""An array of colors
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
color : str | tuple | list of colors
|
|
88
|
+
If str, can be any of the names in ``vispy.color.get_color_names``.
|
|
89
|
+
Can also be a hex value if it starts with ``'#'`` as ``'#ff0000'``.
|
|
90
|
+
If array-like, it must be an Nx3 or Nx4 array-like object.
|
|
91
|
+
Can also be a list of colors, such as
|
|
92
|
+
``['red', '#00ff00', ColorArray('blue')]``.
|
|
93
|
+
alpha : float | None
|
|
94
|
+
If no alpha is not supplied in ``color`` entry and ``alpha`` is None,
|
|
95
|
+
then this will default to 1.0 (opaque). If float, it will override
|
|
96
|
+
any alpha values in ``color``, if provided.
|
|
97
|
+
clip : bool
|
|
98
|
+
Clip the color value.
|
|
99
|
+
color_space : 'rgb' | 'hsv'
|
|
100
|
+
'rgb' (default) : color tuples are interpreted as (r, g, b) components.
|
|
101
|
+
'hsv' : color tuples are interpreted as (h, s, v) components.
|
|
102
|
+
|
|
103
|
+
Examples
|
|
104
|
+
--------
|
|
105
|
+
There are many ways to define colors. Here are some basic cases:
|
|
106
|
+
|
|
107
|
+
>>> from vispy.color import ColorArray
|
|
108
|
+
>>> r = ColorArray('red') # using string name
|
|
109
|
+
>>> r
|
|
110
|
+
<ColorArray: 1 color ((1.0, 0.0, 0.0, 1.0))>
|
|
111
|
+
>>> g = ColorArray((0, 1, 0, 1)) # RGBA tuple
|
|
112
|
+
>>> b = ColorArray('#0000ff') # hex color
|
|
113
|
+
>>> w = ColorArray() # defaults to black
|
|
114
|
+
>>> w.rgb = r.rgb + g.rgb + b.rgb
|
|
115
|
+
>>>hsv_color = ColorArray(color_space="hsv", color=(0, 0, 0.5))
|
|
116
|
+
>>>hsv_color
|
|
117
|
+
<ColorArray: 1 color ((0.5, 0.5, 0.5, 1.0))>
|
|
118
|
+
>>> w == ColorArray('white')
|
|
119
|
+
True
|
|
120
|
+
>>> w.alpha = 0
|
|
121
|
+
>>> w
|
|
122
|
+
<ColorArray: 1 color ((1.0, 1.0, 1.0, 0.0))>
|
|
123
|
+
>>> rgb = ColorArray(['r', (0, 1, 0), '#0000FFFF'])
|
|
124
|
+
>>> rgb
|
|
125
|
+
<ColorArray: 3 colors ((1.0, 0.0, 0.0, 1.0) ... (1.0, 0.0, 0.0, 1.0))>
|
|
126
|
+
>>> rgb == ColorArray(['red', '#00ff00', ColorArray('blue')])
|
|
127
|
+
True
|
|
128
|
+
|
|
129
|
+
Notes
|
|
130
|
+
-----
|
|
131
|
+
Under the hood, this class stores data in RGBA format suitable for use
|
|
132
|
+
on the GPU.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
def __init__(self, color=(0., 0., 0.), alpha=None,
|
|
136
|
+
clip=False, color_space='rgb'):
|
|
137
|
+
|
|
138
|
+
# if color is RGB, then set the default color to black
|
|
139
|
+
color = (0,) * 4 if color is None else color
|
|
140
|
+
if color_space == 'hsv':
|
|
141
|
+
# if the color space is hsv, convert hsv to rgb
|
|
142
|
+
color = _hsv_to_rgb(color)
|
|
143
|
+
elif color_space != 'rgb':
|
|
144
|
+
raise ValueError('color_space should be either "rgb" or'
|
|
145
|
+
'"hsv", it is ' + color_space)
|
|
146
|
+
|
|
147
|
+
# Parse input type, and set attribute"""
|
|
148
|
+
rgba = _user_to_rgba(color, clip=clip)
|
|
149
|
+
|
|
150
|
+
if alpha is not None:
|
|
151
|
+
rgba[:, 3] = alpha
|
|
152
|
+
self._rgba = None
|
|
153
|
+
self.rgba = rgba
|
|
154
|
+
|
|
155
|
+
###########################################################################
|
|
156
|
+
# Builtins and utilities
|
|
157
|
+
def copy(self):
|
|
158
|
+
"""Return a copy"""
|
|
159
|
+
return deepcopy(self)
|
|
160
|
+
|
|
161
|
+
@classmethod
|
|
162
|
+
def _name(cls):
|
|
163
|
+
"""Helper to get the class name once it's been created"""
|
|
164
|
+
return cls.__name__
|
|
165
|
+
|
|
166
|
+
def __array__(self, dtype=None):
|
|
167
|
+
"""Get a standard numpy array representing RGBA."""
|
|
168
|
+
rgba = self.rgba
|
|
169
|
+
if dtype is not None:
|
|
170
|
+
rgba = rgba.astype(dtype)
|
|
171
|
+
return rgba
|
|
172
|
+
|
|
173
|
+
def __len__(self):
|
|
174
|
+
return self._rgba.shape[0]
|
|
175
|
+
|
|
176
|
+
def __repr__(self):
|
|
177
|
+
nice_str = str(tuple(self._rgba[0]))
|
|
178
|
+
plural = ''
|
|
179
|
+
if len(self) > 1:
|
|
180
|
+
plural = 's'
|
|
181
|
+
nice_str += ' ... ' + str(tuple(self.rgba[-1]))
|
|
182
|
+
# use self._name() here instead of hard-coding name in case
|
|
183
|
+
# we eventually subclass this class
|
|
184
|
+
return ('<%s: %i color%s (%s)>' % (self._name(), len(self),
|
|
185
|
+
plural, nice_str))
|
|
186
|
+
|
|
187
|
+
def __eq__(self, other):
|
|
188
|
+
return np.array_equal(self._rgba, other._rgba)
|
|
189
|
+
|
|
190
|
+
###########################################################################
|
|
191
|
+
def __getitem__(self, item):
|
|
192
|
+
if isinstance(item, tuple):
|
|
193
|
+
raise ValueError('ColorArray indexing is only allowed along '
|
|
194
|
+
'the first dimension.')
|
|
195
|
+
subrgba = self._rgba[item]
|
|
196
|
+
if subrgba.ndim == 1:
|
|
197
|
+
assert len(subrgba) == 4
|
|
198
|
+
elif subrgba.ndim == 2:
|
|
199
|
+
assert subrgba.shape[1] in (3, 4)
|
|
200
|
+
return ColorArray(subrgba)
|
|
201
|
+
|
|
202
|
+
def __setitem__(self, item, value):
|
|
203
|
+
if isinstance(item, tuple):
|
|
204
|
+
raise ValueError('ColorArray indexing is only allowed along '
|
|
205
|
+
'the first dimension.')
|
|
206
|
+
# value should be a RGBA array, or a ColorArray instance
|
|
207
|
+
if isinstance(value, ColorArray):
|
|
208
|
+
value = value.rgba
|
|
209
|
+
self._rgba[item] = value
|
|
210
|
+
|
|
211
|
+
def extend(self, colors):
|
|
212
|
+
"""Extend a ColorArray with new colors
|
|
213
|
+
|
|
214
|
+
Parameters
|
|
215
|
+
----------
|
|
216
|
+
colors : instance of ColorArray
|
|
217
|
+
The new colors.
|
|
218
|
+
"""
|
|
219
|
+
colors = ColorArray(colors)
|
|
220
|
+
self._rgba = np.vstack((self._rgba, colors._rgba))
|
|
221
|
+
return self
|
|
222
|
+
|
|
223
|
+
# RGB(A)
|
|
224
|
+
@property
|
|
225
|
+
def rgba(self):
|
|
226
|
+
"""Nx4 array of RGBA floats"""
|
|
227
|
+
return self._rgba.copy()
|
|
228
|
+
|
|
229
|
+
@rgba.setter
|
|
230
|
+
def rgba(self, val):
|
|
231
|
+
"""Set the color using an Nx4 array of RGBA floats"""
|
|
232
|
+
# Note: all other attribute sets get routed here!
|
|
233
|
+
# This method is meant to do the heavy lifting of setting data
|
|
234
|
+
rgba = _user_to_rgba(val, expand=False)
|
|
235
|
+
if self._rgba is None:
|
|
236
|
+
self._rgba = rgba # only on init
|
|
237
|
+
else:
|
|
238
|
+
self._rgba[:, :rgba.shape[1]] = rgba
|
|
239
|
+
|
|
240
|
+
@property
|
|
241
|
+
def rgb(self):
|
|
242
|
+
"""Nx3 array of RGB floats"""
|
|
243
|
+
return self._rgba[:, :3].copy()
|
|
244
|
+
|
|
245
|
+
@rgb.setter
|
|
246
|
+
def rgb(self, val):
|
|
247
|
+
"""Set the color using an Nx3 array of RGB floats"""
|
|
248
|
+
self.rgba = val
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def RGBA(self):
|
|
252
|
+
"""Nx4 array of RGBA uint8s"""
|
|
253
|
+
return (self._rgba * 255).astype(np.uint8)
|
|
254
|
+
|
|
255
|
+
@RGBA.setter
|
|
256
|
+
def RGBA(self, val):
|
|
257
|
+
"""Set the color using an Nx4 array of RGBA uint8 values"""
|
|
258
|
+
# need to convert to normalized float
|
|
259
|
+
val = np.atleast_1d(val).astype(np.float32) / 255
|
|
260
|
+
self.rgba = val
|
|
261
|
+
|
|
262
|
+
@property
|
|
263
|
+
def RGB(self):
|
|
264
|
+
"""Nx3 array of RGBA uint8s"""
|
|
265
|
+
return np.round(self._rgba[:, :3] * 255).astype(int)
|
|
266
|
+
|
|
267
|
+
@RGB.setter
|
|
268
|
+
def RGB(self, val):
|
|
269
|
+
"""Set the color using an Nx3 array of RGB uint8 values"""
|
|
270
|
+
# need to convert to normalized float
|
|
271
|
+
val = np.atleast_1d(val).astype(np.float32) / 255.
|
|
272
|
+
self.rgba = val
|
|
273
|
+
|
|
274
|
+
@property
|
|
275
|
+
def alpha(self):
|
|
276
|
+
"""Length-N array of alpha floats"""
|
|
277
|
+
return self._rgba[:, 3]
|
|
278
|
+
|
|
279
|
+
@alpha.setter
|
|
280
|
+
def alpha(self, val):
|
|
281
|
+
"""Set the color using alpha"""
|
|
282
|
+
self._rgba[:, 3] = _array_clip_val(val)
|
|
283
|
+
|
|
284
|
+
###########################################################################
|
|
285
|
+
# HEX
|
|
286
|
+
@property
|
|
287
|
+
def hex(self):
|
|
288
|
+
"""Numpy array with N elements, each one a hex triplet string"""
|
|
289
|
+
return _rgb_to_hex(self._rgba)
|
|
290
|
+
|
|
291
|
+
@hex.setter
|
|
292
|
+
def hex(self, val):
|
|
293
|
+
"""Set the color values using a list of hex strings"""
|
|
294
|
+
self.rgba = _hex_to_rgba(val)
|
|
295
|
+
|
|
296
|
+
###########################################################################
|
|
297
|
+
# HSV
|
|
298
|
+
@property
|
|
299
|
+
def hsv(self):
|
|
300
|
+
"""Nx3 array of HSV floats"""
|
|
301
|
+
return self._hsv
|
|
302
|
+
|
|
303
|
+
@hsv.setter
|
|
304
|
+
def hsv(self, val):
|
|
305
|
+
"""Set the color values using an Nx3 array of HSV floats"""
|
|
306
|
+
self.rgba = _hsv_to_rgb(val)
|
|
307
|
+
|
|
308
|
+
@property
|
|
309
|
+
def _hsv(self):
|
|
310
|
+
"""Nx3 array of HSV floats"""
|
|
311
|
+
# this is done privately so that overriding functions work
|
|
312
|
+
return _rgb_to_hsv(self._rgba[:, :3])
|
|
313
|
+
|
|
314
|
+
@property
|
|
315
|
+
def value(self):
|
|
316
|
+
"""Length-N array of color HSV values"""
|
|
317
|
+
return self._hsv[:, 2]
|
|
318
|
+
|
|
319
|
+
@value.setter
|
|
320
|
+
def value(self, val):
|
|
321
|
+
"""Set the color using length-N array of (from HSV)"""
|
|
322
|
+
hsv = self._hsv
|
|
323
|
+
hsv[:, 2] = _array_clip_val(val)
|
|
324
|
+
self.rgba = _hsv_to_rgb(hsv)
|
|
325
|
+
|
|
326
|
+
def lighter(self, dv=0.1, copy=True):
|
|
327
|
+
"""Produce a lighter color (if possible)
|
|
328
|
+
|
|
329
|
+
Parameters
|
|
330
|
+
----------
|
|
331
|
+
dv : float
|
|
332
|
+
Amount to increase the color value by.
|
|
333
|
+
copy : bool
|
|
334
|
+
If False, operation will be carried out in-place.
|
|
335
|
+
|
|
336
|
+
Returns
|
|
337
|
+
-------
|
|
338
|
+
color : instance of ColorArray
|
|
339
|
+
The lightened Color.
|
|
340
|
+
"""
|
|
341
|
+
color = self.copy() if copy else self
|
|
342
|
+
color.value += dv
|
|
343
|
+
return color
|
|
344
|
+
|
|
345
|
+
def darker(self, dv=0.1, copy=True):
|
|
346
|
+
"""Produce a darker color (if possible)
|
|
347
|
+
|
|
348
|
+
Parameters
|
|
349
|
+
----------
|
|
350
|
+
dv : float
|
|
351
|
+
Amount to decrease the color value by.
|
|
352
|
+
copy : bool
|
|
353
|
+
If False, operation will be carried out in-place.
|
|
354
|
+
|
|
355
|
+
Returns
|
|
356
|
+
-------
|
|
357
|
+
color : instance of ColorArray
|
|
358
|
+
The darkened Color.
|
|
359
|
+
"""
|
|
360
|
+
color = self.copy() if copy else self
|
|
361
|
+
color.value -= dv
|
|
362
|
+
return color
|
|
363
|
+
|
|
364
|
+
###########################################################################
|
|
365
|
+
# Lab
|
|
366
|
+
@property
|
|
367
|
+
def lab(self):
|
|
368
|
+
return _rgb_to_lab(self._rgba[:, :3])
|
|
369
|
+
|
|
370
|
+
@lab.setter
|
|
371
|
+
def lab(self, val):
|
|
372
|
+
self.rgba = _lab_to_rgb(val)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
class Color(ColorArray):
|
|
376
|
+
"""A single color
|
|
377
|
+
|
|
378
|
+
Parameters
|
|
379
|
+
----------
|
|
380
|
+
color : str | tuple
|
|
381
|
+
If str, can be any of the names in ``vispy.color.get_color_names``.
|
|
382
|
+
Can also be a hex value if it starts with ``'#'`` as ``'#ff0000'``.
|
|
383
|
+
If array-like, it must be an 1-dimensional array with 3 or 4 elements.
|
|
384
|
+
alpha : float | None
|
|
385
|
+
If no alpha is not supplied in ``color`` entry and ``alpha`` is None,
|
|
386
|
+
then this will default to 1.0 (opaque). If float, it will override
|
|
387
|
+
the alpha value in ``color``, if provided.
|
|
388
|
+
clip : bool
|
|
389
|
+
If True, clip the color values.
|
|
390
|
+
"""
|
|
391
|
+
|
|
392
|
+
def __init__(self, color='black', alpha=None, clip=False):
|
|
393
|
+
"""Parse input type, and set attribute"""
|
|
394
|
+
if isinstance(color, (list, tuple)):
|
|
395
|
+
color = np.array(color, np.float32)
|
|
396
|
+
rgba = _user_to_rgba(color, clip=clip)
|
|
397
|
+
if rgba.shape[0] != 1:
|
|
398
|
+
raise ValueError('color must be of correct shape')
|
|
399
|
+
if alpha is not None:
|
|
400
|
+
rgba[:, 3] = alpha
|
|
401
|
+
self._rgba = None
|
|
402
|
+
self.rgba = rgba.ravel()
|
|
403
|
+
|
|
404
|
+
@ColorArray.rgba.getter
|
|
405
|
+
def rgba(self):
|
|
406
|
+
return super(Color, self).rgba[0]
|
|
407
|
+
|
|
408
|
+
@ColorArray.rgb.getter
|
|
409
|
+
def rgb(self):
|
|
410
|
+
return super(Color, self).rgb[0]
|
|
411
|
+
|
|
412
|
+
@ColorArray.RGBA.getter
|
|
413
|
+
def RGBA(self):
|
|
414
|
+
return super(Color, self).RGBA[0]
|
|
415
|
+
|
|
416
|
+
@ColorArray.RGB.getter
|
|
417
|
+
def RGB(self):
|
|
418
|
+
return super(Color, self).RGB[0]
|
|
419
|
+
|
|
420
|
+
@ColorArray.alpha.getter
|
|
421
|
+
def alpha(self):
|
|
422
|
+
return super(Color, self).alpha[0]
|
|
423
|
+
|
|
424
|
+
@ColorArray.hex.getter
|
|
425
|
+
def hex(self):
|
|
426
|
+
return super(Color, self).hex[0]
|
|
427
|
+
|
|
428
|
+
@ColorArray.hsv.getter
|
|
429
|
+
def hsv(self):
|
|
430
|
+
return super(Color, self).hsv[0]
|
|
431
|
+
|
|
432
|
+
@ColorArray.value.getter
|
|
433
|
+
def value(self):
|
|
434
|
+
return super(Color, self).value[0]
|
|
435
|
+
|
|
436
|
+
@ColorArray.lab.getter
|
|
437
|
+
def lab(self):
|
|
438
|
+
return super(Color, self).lab[0]
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def is_blank(self):
|
|
442
|
+
"""Boolean indicating whether the color is invisible."""
|
|
443
|
+
return self.rgba[3] == 0
|
|
444
|
+
|
|
445
|
+
def __repr__(self):
|
|
446
|
+
nice_str = str(tuple(self._rgba[0]))
|
|
447
|
+
return ('<%s: %s>' % (self._name(), nice_str))
|
|
@@ -0,0 +1,181 @@
|
|
|
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
|
+
from __future__ import division # just to be safe...
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
###############################################################################
|
|
11
|
+
# Utility functions
|
|
12
|
+
def _check_color_dim(val):
|
|
13
|
+
"""Ensure val is Nx(n_col), usually Nx3"""
|
|
14
|
+
val = np.atleast_2d(val)
|
|
15
|
+
if val.shape[1] not in (3, 4):
|
|
16
|
+
raise RuntimeError('Value must have second dimension of size 3 or 4')
|
|
17
|
+
return val, val.shape[1]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
###############################################################################
|
|
21
|
+
# RGB<->HEX conversion
|
|
22
|
+
|
|
23
|
+
def _hex_to_rgba(hexs):
|
|
24
|
+
"""Convert hex to rgba, permitting alpha values in hex"""
|
|
25
|
+
hexs = np.atleast_1d(np.array(hexs, '|U9'))
|
|
26
|
+
out = np.ones((len(hexs), 4), np.float32)
|
|
27
|
+
for hi, h in enumerate(hexs):
|
|
28
|
+
assert isinstance(h, str)
|
|
29
|
+
off = 1 if h[0] == '#' else 0
|
|
30
|
+
assert len(h) in (6+off, 8+off)
|
|
31
|
+
e = (len(h)-off) // 2
|
|
32
|
+
out[hi, :e] = [int(h[i:i+2], 16) / 255.
|
|
33
|
+
for i in range(off, len(h), 2)]
|
|
34
|
+
return out
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _rgb_to_hex(rgbs):
|
|
38
|
+
"""Convert rgb to hex triplet"""
|
|
39
|
+
rgbs, n_dim = _check_color_dim(rgbs)
|
|
40
|
+
return np.array(['#%02x%02x%02x' % tuple((255*rgb[:3]).astype(np.uint8))
|
|
41
|
+
for rgb in rgbs], '|U7')
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
###############################################################################
|
|
45
|
+
# RGB<->HSV conversion
|
|
46
|
+
|
|
47
|
+
def _rgb_to_hsv(rgbs):
|
|
48
|
+
"""Convert Nx3 or Nx4 rgb to hsv"""
|
|
49
|
+
rgbs, n_dim = _check_color_dim(rgbs)
|
|
50
|
+
hsvs = list()
|
|
51
|
+
for rgb in rgbs:
|
|
52
|
+
rgb = rgb[:3] # don't use alpha here
|
|
53
|
+
idx = np.argmax(rgb)
|
|
54
|
+
val = rgb[idx]
|
|
55
|
+
c = val - np.min(rgb)
|
|
56
|
+
if c == 0:
|
|
57
|
+
hue = 0
|
|
58
|
+
sat = 0
|
|
59
|
+
else:
|
|
60
|
+
if idx == 0: # R == max
|
|
61
|
+
hue = ((rgb[1] - rgb[2]) / c) % 6
|
|
62
|
+
elif idx == 1: # G == max
|
|
63
|
+
hue = (rgb[2] - rgb[0]) / c + 2
|
|
64
|
+
else: # B == max
|
|
65
|
+
hue = (rgb[0] - rgb[1]) / c + 4
|
|
66
|
+
hue *= 60
|
|
67
|
+
sat = c / val
|
|
68
|
+
hsv = [hue, sat, val]
|
|
69
|
+
hsvs.append(hsv)
|
|
70
|
+
hsvs = np.array(hsvs, dtype=np.float32)
|
|
71
|
+
if n_dim == 4:
|
|
72
|
+
hsvs = np.concatenate((hsvs, rgbs[:, 3]), axis=1)
|
|
73
|
+
return hsvs
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _hsv_to_rgb(hsvs):
|
|
77
|
+
"""Convert Nx3 or Nx4 hsv to rgb"""
|
|
78
|
+
hsvs, n_dim = _check_color_dim(hsvs)
|
|
79
|
+
# In principle, we *might* be able to vectorize this, but might as well
|
|
80
|
+
# wait until a compelling use case appears
|
|
81
|
+
rgbs = list()
|
|
82
|
+
for hsv in hsvs:
|
|
83
|
+
c = hsv[1] * hsv[2]
|
|
84
|
+
m = hsv[2] - c
|
|
85
|
+
hp = hsv[0] / 60
|
|
86
|
+
x = c * (1 - abs(hp % 2 - 1))
|
|
87
|
+
if 0 <= hp < 1:
|
|
88
|
+
r, g, b = c, x, 0
|
|
89
|
+
elif hp < 2:
|
|
90
|
+
r, g, b = x, c, 0
|
|
91
|
+
elif hp < 3:
|
|
92
|
+
r, g, b = 0, c, x
|
|
93
|
+
elif hp < 4:
|
|
94
|
+
r, g, b = 0, x, c
|
|
95
|
+
elif hp < 5:
|
|
96
|
+
r, g, b = x, 0, c
|
|
97
|
+
else:
|
|
98
|
+
r, g, b = c, 0, x
|
|
99
|
+
rgb = [r + m, g + m, b + m]
|
|
100
|
+
rgbs.append(rgb)
|
|
101
|
+
rgbs = np.array(rgbs, dtype=np.float32)
|
|
102
|
+
if n_dim == 4:
|
|
103
|
+
rgbs = np.concatenate((rgbs, hsvs[:, 3]), axis=1)
|
|
104
|
+
return rgbs
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
###############################################################################
|
|
108
|
+
# RGB<->CIELab conversion
|
|
109
|
+
|
|
110
|
+
# These numbers are adapted from MIT-licensed MATLAB code for
|
|
111
|
+
# Lab<->RGB conversion. They provide an XYZ<->RGB conversion matrices,
|
|
112
|
+
# w/D65 white point normalization built in.
|
|
113
|
+
|
|
114
|
+
# _rgb2xyz = np.array([[0.412453, 0.357580, 0.180423],
|
|
115
|
+
# [0.212671, 0.715160, 0.072169],
|
|
116
|
+
# [0.019334, 0.119193, 0.950227]])
|
|
117
|
+
# _white_norm = np.array([0.950456, 1.0, 1.088754])
|
|
118
|
+
# _rgb2xyz /= _white_norm[:, np.newaxis]
|
|
119
|
+
# _rgb2xyz_norm = _rgb2xyz.T
|
|
120
|
+
_rgb2xyz_norm = np.array([[0.43395276, 0.212671, 0.01775791],
|
|
121
|
+
[0.37621941, 0.71516, 0.10947652],
|
|
122
|
+
[0.18982783, 0.072169, 0.87276557]])
|
|
123
|
+
|
|
124
|
+
# _xyz2rgb = np.array([[3.240479, -1.537150, -0.498535],
|
|
125
|
+
# [-0.969256, 1.875992, 0.041556],
|
|
126
|
+
# [0.055648, -0.204043, 1.057311]])
|
|
127
|
+
# _white_norm = np.array([0.950456, 1., 1.088754])
|
|
128
|
+
# _xyz2rgb *= _white_norm[np.newaxis, :]
|
|
129
|
+
_xyz2rgb_norm = np.array([[3.07993271, -1.53715, -0.54278198],
|
|
130
|
+
[-0.92123518, 1.875992, 0.04524426],
|
|
131
|
+
[0.05289098, -0.204043, 1.15115158]])
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _rgb_to_lab(rgbs):
|
|
135
|
+
rgbs, n_dim = _check_color_dim(rgbs)
|
|
136
|
+
# convert RGB->XYZ
|
|
137
|
+
xyz = rgbs[:, :3].copy() # a misnomer for now but will end up being XYZ
|
|
138
|
+
over = xyz > 0.04045
|
|
139
|
+
xyz[over] = ((xyz[over] + 0.055) / 1.055) ** 2.4
|
|
140
|
+
xyz[~over] /= 12.92
|
|
141
|
+
xyz = np.dot(xyz, _rgb2xyz_norm)
|
|
142
|
+
over = xyz > 0.008856
|
|
143
|
+
xyz[over] = xyz[over] ** (1. / 3.)
|
|
144
|
+
xyz[~over] = 7.787 * xyz[~over] + 0.13793103448275862
|
|
145
|
+
|
|
146
|
+
# Convert XYZ->LAB
|
|
147
|
+
L = (116. * xyz[:, 1]) - 16
|
|
148
|
+
a = 500 * (xyz[:, 0] - xyz[:, 1])
|
|
149
|
+
b = 200 * (xyz[:, 1] - xyz[:, 2])
|
|
150
|
+
labs = [L, a, b]
|
|
151
|
+
# Append alpha if necessary
|
|
152
|
+
if n_dim == 4:
|
|
153
|
+
labs.append(np.atleast1d(rgbs[:, 3]))
|
|
154
|
+
labs = np.array(labs, order='F').T # Becomes 'C' order b/c of .T
|
|
155
|
+
return labs
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _lab_to_rgb(labs):
|
|
159
|
+
"""Convert Nx3 or Nx4 lab to rgb"""
|
|
160
|
+
# adapted from BSD-licensed work in MATLAB by Mark Ruzon
|
|
161
|
+
# Based on ITU-R Recommendation BT.709 using the D65
|
|
162
|
+
labs, n_dim = _check_color_dim(labs)
|
|
163
|
+
|
|
164
|
+
# Convert Lab->XYZ (silly indexing used to preserve dimensionality)
|
|
165
|
+
y = (labs[:, 0] + 16.) / 116.
|
|
166
|
+
x = (labs[:, 1] / 500.) + y
|
|
167
|
+
z = y - (labs[:, 2] / 200.)
|
|
168
|
+
xyz = np.concatenate(([x], [y], [z])) # 3xN
|
|
169
|
+
over = xyz > 0.2068966
|
|
170
|
+
xyz[over] = xyz[over] ** 3.
|
|
171
|
+
xyz[~over] = (xyz[~over] - 0.13793103448275862) / 7.787
|
|
172
|
+
|
|
173
|
+
# Convert XYZ->LAB
|
|
174
|
+
rgbs = np.dot(_xyz2rgb_norm, xyz).T
|
|
175
|
+
over = rgbs > 0.0031308
|
|
176
|
+
rgbs[over] = 1.055 * (rgbs[over] ** (1. / 2.4)) - 0.055
|
|
177
|
+
rgbs[~over] *= 12.92
|
|
178
|
+
if n_dim == 4:
|
|
179
|
+
rgbs = np.concatenate((rgbs, labs[:, 3]), axis=1)
|
|
180
|
+
rgbs = np.clip(rgbs, 0., 1.)
|
|
181
|
+
return rgbs
|