vispy 0.14.1__cp311-cp311-win_amd64.whl → 0.14.3__cp311-cp311-win_amd64.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/app/backends/_qt.py CHANGED
@@ -386,9 +386,9 @@ class QtBaseCanvasBackend(BaseCanvasBackend):
386
386
 
387
387
  # must set physical size before setting visible or fullscreen
388
388
  # operations may make the size invalid
389
- if hasattr(self, 'devicePixelRatio'):
389
+ if hasattr(self, 'devicePixelRatioF'):
390
390
  # handle high DPI displays in PyQt5
391
- ratio = self.devicePixelRatio()
391
+ ratio = self.devicePixelRatioF()
392
392
  else:
393
393
  ratio = 1
394
394
  self._physical_size = (p.size[0] * ratio, p.size[1] * ratio)
@@ -421,7 +421,7 @@ class QtBaseCanvasBackend(BaseCanvasBackend):
421
421
 
422
422
  If display resolutions are the same this is essentially a no-op except for the redraw.
423
423
  If the display resolutions differ (HiDPI versus regular displays) the canvas needs to
424
- be redrawn to reset the physical size based on the current `devicePixelRatio()` and
424
+ be redrawn to reset the physical size based on the current `devicePixelRatioF()` and
425
425
  redrawn with that new size.
426
426
 
427
427
  """
@@ -909,11 +909,11 @@ class CanvasBackendDesktop(QtBaseCanvasBackend, QGLWidget):
909
909
  def resizeGL(self, w, h):
910
910
  if self._vispy_canvas is None:
911
911
  return
912
- if hasattr(self, 'devicePixelRatio'):
913
- # We take into account devicePixelRatio, which is non-unity on
912
+ if hasattr(self, 'devicePixelRatioF'):
913
+ # We take into account devicePixelRatioF, which is non-unity on
914
914
  # e.g HiDPI displays.
915
- # self.devicePixelRatio() is a float and should have been in Qt5 according to the documentation
916
- ratio = self.devicePixelRatio()
915
+ # self.devicePixelRatioF() is a float and should have been in Qt5 according to the documentation
916
+ ratio = self.devicePixelRatioF()
917
917
  w = int(w * ratio)
918
918
  h = int(h * ratio)
919
919
  self._vispy_set_physical_size(w, h)
@@ -16,7 +16,7 @@ from .meshdata import MeshData # noqa
16
16
  from .rect import Rect # noqa
17
17
  from .triangulation import Triangulation, triangulate # noqa
18
18
  from .torusknot import TorusKnot # noqa
19
- from .calculations import (_calculate_normals, _fast_cross_3d, # noqa
19
+ from .calculations import (_calculate_normals, _cross_2d, _fast_cross_3d, # noqa
20
20
  resize) # noqa
21
21
  from .generation import (create_arrow, create_box, create_cone, # noqa
22
22
  create_cube, create_cylinder, create_grid_mesh, # noqa
@@ -7,8 +7,33 @@
7
7
  import numpy as np
8
8
 
9
9
 
10
- ###############################################################################
11
- # These fast normal calculation routines are adapted from mne-python
10
+ def _cross_2d(x, y):
11
+ """Compute the z-component of the cross product of (arrays of) 2D vectors.
12
+
13
+ This is meant to replicate the 2D functionality of np.cross(), which is
14
+ deprecated in numpy 2.0.
15
+
16
+ x and y must have broadcastable shapes, with the last dimension being 2.
17
+
18
+ Parameters
19
+ ----------
20
+ x : array
21
+ Input array 1, shape (..., 2).
22
+ y : array
23
+ Input array 2, shape (..., 2).
24
+
25
+ Returns
26
+ -------
27
+ z : array
28
+ z-component of cross products of x and y.
29
+
30
+ See: https://github.com/numpy/numpy/issues/26620
31
+ """
32
+ if x.shape[-1] != 2 or y.shape[-1] != 2:
33
+ raise ValueError("Input arrays must have shape (..., 2)")
34
+
35
+ return x[..., 0] * y[..., 1] - x[..., 1] * y[..., 0]
36
+
12
37
 
13
38
  def _fast_cross_3d(x, y):
14
39
  """Compute cross product between list of 3D vectors
@@ -47,6 +72,9 @@ def _fast_cross_3d(x, y):
47
72
  return np.cross(x, y)
48
73
 
49
74
 
75
+ ###############################################################################
76
+ # These fast normal calculation routines are adapted from mne-python
77
+
50
78
  def _calculate_normals(rr, tris):
51
79
  """Efficiently compute vertex normals for triangulated surface"""
52
80
  # ensure highest precision for our summation/vectorization "trick"
@@ -7,6 +7,8 @@ import numpy as np
7
7
 
8
8
  from collections import OrderedDict
9
9
 
10
+ from .calculations import _cross_2d
11
+
10
12
 
11
13
  class Triangulation(object):
12
14
  """Constrained delaunay triangulation
@@ -676,7 +678,7 @@ class Triangulation(object):
676
678
  A = self.pts[a]
677
679
  B = self.pts[b]
678
680
  C = self.pts[c]
679
- return np.cross(B-A, C-B) > 0
681
+ return _cross_2d(B - A, C - B) > 0
680
682
 
681
683
  def _edges_intersect(self, edge1, edge2):
682
684
  """Return 1 if edges intersect completely (endpoints excluded)"""
@@ -739,7 +741,7 @@ class Triangulation(object):
739
741
  """
740
742
  v1 = self.pts[point] - self.pts[edge[0]]
741
743
  v2 = self.pts[edge[1]] - self.pts[edge[0]]
742
- c = np.cross(v1, v2) # positive if v1 is CW from v2
744
+ c = _cross_2d(v1, v2) # positive if v1 is CW from v2
743
745
  return 1 if c > 0 else (-1 if c < 0 else 0)
744
746
 
745
747
  def _add_tri(self, a, b, c):
vispy/gloo/buffer.py CHANGED
@@ -10,7 +10,7 @@ from traceback import extract_stack, format_list
10
10
  import weakref
11
11
 
12
12
  from . globject import GLObject
13
- from ..util import logger
13
+ from ..util import logger, np_copy_if_needed
14
14
 
15
15
 
16
16
  # ------------------------------------------------------------ Buffer class ---
@@ -70,7 +70,7 @@ class Buffer(GLObject):
70
70
  data is actually uploaded to GPU memory.
71
71
  Asking explicitly for a copy will prevent this behavior.
72
72
  """
73
- data = np.array(data, copy=copy)
73
+ data = np.array(data, copy=copy or np_copy_if_needed)
74
74
  nbytes = data.nbytes
75
75
 
76
76
  if offset < 0:
@@ -98,7 +98,7 @@ class Buffer(GLObject):
98
98
  data is actually uploaded to GPU memory.
99
99
  Asking explicitly for a copy will prevent this behavior.
100
100
  """
101
- data = np.array(data, copy=copy)
101
+ data = np.array(data, copy=copy or np_copy_if_needed)
102
102
  nbytes = data.nbytes
103
103
 
104
104
  if nbytes != self._nbytes:
@@ -283,7 +283,7 @@ class DataBuffer(Buffer):
283
283
 
284
284
  # Make sure data is an array
285
285
  if not isinstance(data, np.ndarray):
286
- data = np.array(data, dtype=self.dtype, copy=False)
286
+ data = np.array(data, dtype=self.dtype)
287
287
 
288
288
  # Make sure data is big enough
289
289
  if data.size < stop - start:
@@ -192,8 +192,10 @@ quad = np.array([[0, 0, 0], [-1, 0, 0], [-1, -1, 0],
192
192
  N = quad.shape[0] * 4
193
193
 
194
194
  # buf3 contains coordinates in device coordinates for four quadrants
195
- buf3 = np.row_stack([quad + (0, 0, 0), quad + (0, 1, 0),
196
- quad + (1, 1, 0), quad + (1, 0, 0)]).astype(np.float32)
195
+ buf3 = np.vstack([
196
+ quad + (0, 0, 0), quad + (0, 1, 0),
197
+ quad + (1, 1, 0), quad + (1, 0, 0),
198
+ ]).astype(np.float32)
197
199
 
198
200
  # buf2 is texture coords. Note that this is a view on buf2
199
201
  buf2 = ((buf3+1.0)*0.5)[:, :2] # not C-contiguous
vispy/gloo/glir.py CHANGED
@@ -1045,6 +1045,9 @@ class GlirProgram(GlirObject):
1045
1045
  'vec2': (2, gl.GL_FLOAT, np.float32),
1046
1046
  'vec3': (3, gl.GL_FLOAT, np.float32),
1047
1047
  'vec4': (4, gl.GL_FLOAT, np.float32),
1048
+ 'ivec2': (2, gl.GL_INT, np.int32),
1049
+ 'ivec3': (3, gl.GL_INT, np.int32),
1050
+ 'ivec4': (4, gl.GL_INT, np.int32),
1048
1051
  'int': (1, gl.GL_INT, np.int32),
1049
1052
  'bool': (1, gl.GL_BOOL, np.int32)
1050
1053
  }
@@ -1280,8 +1283,13 @@ class GlirProgram(GlirObject):
1280
1283
  gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo_handle)
1281
1284
  gl.glEnableVertexAttribArray(attr_handle)
1282
1285
  func(attr_handle, *args)
1283
- if divisor is not None:
1284
- gl.glVertexAttribDivisor(attr_handle, divisor)
1286
+ if hasattr(gl, "glVertexAttribDivisor"):
1287
+ gl.glVertexAttribDivisor(attr_handle, divisor or 0)
1288
+ elif divisor is not None:
1289
+ logger.warning(
1290
+ 'Instanced rendering is not supported by the current'
1291
+ f'backend ("{gl.current_backend.__name__}")'
1292
+ )
1285
1293
  else:
1286
1294
  gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)
1287
1295
  gl.glDisableVertexAttribArray(attr_handle)
vispy/gloo/texture.py CHANGED
@@ -11,6 +11,7 @@ import warnings
11
11
 
12
12
  from .globject import GLObject
13
13
  from .util import check_enum
14
+ from ..util import np_copy_if_needed
14
15
 
15
16
 
16
17
  def get_dtype_limits(dtype):
@@ -29,7 +30,7 @@ def convert_dtype_and_clip(data, dtype, copy=False):
29
30
  new_min, new_max = get_dtype_limits(dtype)
30
31
  if new_max >= old_max and new_min <= old_min:
31
32
  # no need to clip
32
- return np.array(data, dtype=dtype, copy=copy)
33
+ return np.array(data, dtype=dtype, copy=copy or np_copy_if_needed)
33
34
  else:
34
35
  # to reduce copying, we clip into a pre-generated array of the right dtype
35
36
  new_data = np.empty_like(data, dtype=dtype)
@@ -158,7 +159,7 @@ class BaseTexture(GLObject):
158
159
  if data is not None:
159
160
  if shape is not None:
160
161
  raise ValueError('Texture needs data or shape, not both.')
161
- data = np.array(data, copy=False)
162
+ data = np.array(data)
162
163
  # So we can test the combination
163
164
  self._resize(data.shape, format, internalformat)
164
165
  self._set_data(data)
@@ -427,7 +428,7 @@ class BaseTexture(GLObject):
427
428
 
428
429
  # Make sure data is an array
429
430
  if not isinstance(data, np.ndarray):
430
- data = np.array(data, copy=False)
431
+ data = np.array(data)
431
432
  # Make sure data is big enough
432
433
  if data.shape != shape:
433
434
  data = np.resize(data, shape)
vispy/plot/plotwidget.py CHANGED
@@ -267,7 +267,7 @@ class PlotWidget(scene.Widget):
267
267
  if meshdata is not None:
268
268
  if not all(x is None for x in (vertices, faces, fname)):
269
269
  raise ValueError('vertices, faces, and fname must be None if '
270
- 'fname is not None')
270
+ 'meshdata is not None')
271
271
  else:
272
272
  meshdata = MeshData(vertices, faces, vertex_colors=vertex_colors,
273
273
  face_colors=face_colors)
vispy/testing/_runners.py CHANGED
@@ -164,7 +164,9 @@ def _flake():
164
164
  print('Running flake8... ') # if end='', first error gets ugly
165
165
  sys.stdout.flush()
166
166
  try:
167
- main()
167
+ # flake8 used to exit on failure, but instead `main` now returns an exit code
168
+ # see https://github.com/PyCQA/flake8/pull/1461
169
+ raise SystemExit(main())
168
170
  except SystemExit as ex:
169
171
  if ex.code in (None, 0):
170
172
  pass # do not exit yet, we want to print a success msg
@@ -157,6 +157,27 @@ def assert_image_approved(image, standard_file, message=None, **kwargs):
157
157
  _save_failed_test(image, std_image, standard_file)
158
158
  raise
159
159
 
160
+ # TODO: check for more properties of image
161
+ def assert_image_reasonable(image):
162
+ """Check that an image is reasonable.
163
+
164
+ The given image is checked to not be completely black or white.
165
+
166
+ Parameters:
167
+ -----------
168
+ image : (h, w, 4) ndarray or 'screenshot'
169
+ The test result to check
170
+ """
171
+ if isinstance(image, str) and image == "screenshot":
172
+ image = _screenshot(alpha=True)
173
+
174
+ # check dimensions
175
+ assert image.ndim == 3
176
+ assert image.shape[2] == 4
177
+
178
+ # check white or black
179
+ assert image[...,:3].max() > 0
180
+ assert image[...,:3].min() < 255
160
181
 
161
182
  def assert_image_match(im1, im2, min_corr=0.9, px_threshold=50.,
162
183
  px_count=None, max_px_diff=None, avg_px_diff=None,
vispy/util/__init__.py CHANGED
@@ -15,3 +15,18 @@ from . import fonts # noqa
15
15
  from . import transforms # noqa
16
16
  from .wrappers import use, run_subprocess # noqa
17
17
  from .bunch import SimpleBunch # noqa
18
+
19
+ from typing import Optional
20
+
21
+ import numpy as np
22
+
23
+ # `copy` keyword semantics changed in NumPy 2.0
24
+ # this maintains compatibility with older versions
25
+ # if/when NumPy 2.0 becomes the minimum version, we can remove this
26
+ # we don't worry about early dev versions of NumPy 2.0 (that may or may not have the kwarg) here
27
+ # see:
28
+ # https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keyword
29
+ # https://github.com/scipy/scipy/pull/20172
30
+ np_copy_if_needed: Optional[bool] = None
31
+ if np.lib.NumpyVersion(np.__version__) < "1.28.0":
32
+ np_copy_if_needed = False
vispy/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.14.1'
16
- __version_tuple__ = version_tuple = (0, 14, 1)
15
+ __version__ = version = '0.14.3'
16
+ __version_tuple__ = version_tuple = (0, 14, 3)
@@ -6,6 +6,7 @@ import warnings
6
6
  import numpy as np
7
7
 
8
8
  from vispy.gloo.texture import Texture2D, Texture3D, convert_dtype_and_clip
9
+ from vispy.util import np_copy_if_needed
9
10
 
10
11
 
11
12
  def get_default_clim_from_dtype(dtype):
@@ -298,7 +299,7 @@ class CPUScaledTextureMixin(_ScaledTextureMixin):
298
299
 
299
300
  @staticmethod
300
301
  def _scale_data_on_cpu(data, clim, copy=True):
301
- data = np.array(data, dtype=np.float32, copy=copy)
302
+ data = np.array(data, dtype=np.float32, copy=copy or np_copy_if_needed)
302
303
  if clim[0] != clim[1]:
303
304
  # we always must copy the data if we change it here, otherwise it might change
304
305
  # unexpectedly the data held outside of here
@@ -73,7 +73,7 @@ class ArrayList(object):
73
73
  if isinstance(data[0], (list, tuple)):
74
74
  itemsize = [len(sublist) for sublist in data]
75
75
  data = [item for sublist in data for item in sublist]
76
- self._data = np.array(data, copy=False)
76
+ self._data = np.array(data)
77
77
  self._size = self._data.size
78
78
 
79
79
  # Default is one group with all data inside
@@ -88,7 +88,7 @@ class ArrayList(object):
88
88
  _itemsize = np.ones(
89
89
  self._count, dtype=int) * (self._size // self._count)
90
90
  else:
91
- _itemsize = np.array(itemsize, copy=False)
91
+ _itemsize = np.array(itemsize)
92
92
  self._count = len(itemsize)
93
93
  if _itemsize.sum() != self._size:
94
94
  raise ValueError("Cannot partition data as requested")
@@ -302,7 +302,7 @@ class ArrayList(object):
302
302
  itemsize = [len(sublist) for sublist in data]
303
303
  data = [item for sublist in data for item in sublist]
304
304
 
305
- data = np.array(data, copy=False).ravel()
305
+ data = np.array(data).ravel()
306
306
  size = data.size
307
307
 
308
308
  # Check item size and get item number
@@ -313,7 +313,7 @@ class ArrayList(object):
313
313
  _count = size // itemsize
314
314
  _itemsize = np.ones(_count, dtype=int) * (size // _count)
315
315
  else:
316
- _itemsize = np.array(itemsize, copy=False)
316
+ _itemsize = np.array(itemsize)
317
317
  _count = len(itemsize)
318
318
  if _itemsize.sum() != size:
319
319
  raise ValueError("Cannot partition data as requested")
vispy/visuals/ellipse.py CHANGED
@@ -27,7 +27,7 @@ class EllipseVisual(PolygonVisual):
27
27
  The width of the border in pixels
28
28
  Line widths > 1px are only
29
29
  guaranteed to work when using `border_method='agg'` method.
30
- radius : float | tuple
30
+ radius : float | tuple | list | numpy.ndarray
31
31
  Radius or radii of the ellipse
32
32
  Defaults to (0.1, 0.1)
33
33
  start_angle : float
@@ -65,13 +65,12 @@ class EllipseVisual(PolygonVisual):
65
65
  @staticmethod
66
66
  def _generate_vertices(center, radius, start_angle, span_angle,
67
67
  num_segments):
68
- if isinstance(radius, (list, tuple)):
68
+ if isinstance(radius, (list, tuple, np.ndarray)):
69
69
  if len(radius) == 2:
70
70
  xr, yr = radius
71
71
  else:
72
- raise ValueError("radius must be float or 2 value tuple/list"
73
- " (got %s of length %d)" % (type(radius),
74
- len(radius)))
72
+ raise ValueError("radius must be float or 2 value tuple/list/numpy.ndarray "
73
+ f"(got {type(radius)} of length {len(radius)})")
75
74
  else:
76
75
  xr = yr = radius
77
76
 
vispy/visuals/image.py CHANGED
@@ -16,6 +16,7 @@ from .transforms import NullTransform
16
16
  from .visual import Visual
17
17
  from ..io import load_spatial_filters
18
18
  from ._scalable_textures import CPUScaledTexture2D, GPUScaledTexture2D
19
+ from ..util import np_copy_if_needed
19
20
 
20
21
 
21
22
  _VERTEX_SHADER = """
@@ -380,7 +381,7 @@ class ImageVisual(Visual):
380
381
  texture_format : str or None
381
382
 
382
383
  """
383
- data = np.array(image, copy=copy)
384
+ data = np.array(image, copy=copy or np_copy_if_needed)
384
385
  if np.iscomplexobj(data):
385
386
  raise TypeError(
386
387
  "Complex data types not supported. Please use 'ComplexImage' instead"
vispy/visuals/markers.py CHANGED
@@ -4,7 +4,6 @@
4
4
  # Distributed under the (new) BSD License. See LICENSE.txt for more info.
5
5
  # -----------------------------------------------------------------------------
6
6
  """Marker Visual and shader definitions."""
7
-
8
7
  import numpy as np
9
8
 
10
9
  from ..color import ColorArray
@@ -497,9 +496,11 @@ class MarkersVisual(Visual):
497
496
  The symbol size in screen (or data, if scaling is on) px.
498
497
  edge_width : float or array or None
499
498
  The width of the symbol outline in screen (or data, if scaling is on) px.
499
+ Defaults to 1.0 if None or not provided and ``edge_width_rel`` is not
500
+ provided.
500
501
  edge_width_rel : float or array or None
501
- The width as a fraction of marker size. Exactly one of
502
- `edge_width` and `edge_width_rel` must be supplied.
502
+ The width as a fraction of marker size. Can not be specified along with
503
+ edge_width. A ValueError will be raised if both are provided.
503
504
  edge_color : Color | ColorArray
504
505
  The color used to draw each symbol outline.
505
506
  face_color : Color | ColorArray
@@ -580,7 +581,7 @@ class MarkersVisual(Visual):
580
581
 
581
582
  self.freeze()
582
583
 
583
- def set_data(self, pos=None, size=10., edge_width=1., edge_width_rel=None,
584
+ def set_data(self, pos=None, size=10., edge_width=None, edge_width_rel=None,
584
585
  edge_color='black', face_color='white',
585
586
  symbol='o'):
586
587
  """Set the data used to display this visual.
@@ -593,9 +594,11 @@ class MarkersVisual(Visual):
593
594
  The symbol size in screen (or data, if scaling is on) px.
594
595
  edge_width : float or array or None
595
596
  The width of the symbol outline in screen (or data, if scaling is on) px.
597
+ Defaults to 1.0 if None or not provided and ``edge_width_rel`` is not
598
+ provided.
596
599
  edge_width_rel : float or array or None
597
- The width as a fraction of marker size. Exactly one of
598
- `edge_width` and `edge_width_rel` must be supplied.
600
+ The width as a fraction of marker size. Can not be specified along with
601
+ edge_width. A ValueError will be raised if both are provided.
599
602
  edge_color : Color | ColorArray
600
603
  The color used to draw each symbol outline.
601
604
  face_color : Color | ColorArray
@@ -603,9 +606,11 @@ class MarkersVisual(Visual):
603
606
  symbol : str or array
604
607
  The style of symbol used to draw each marker (see Notes).
605
608
  """
606
- if (edge_width is not None) + (edge_width_rel is not None) != 1:
607
- raise ValueError('exactly one of edge_width and edge_width_rel '
608
- 'must be non-None')
609
+ if edge_width is not None and edge_width_rel is not None:
610
+ raise ValueError("either edge_width or edge_width_rel "
611
+ "should be provided, not both")
612
+ elif edge_width is None and edge_width_rel is None:
613
+ edge_width = 1.0
609
614
 
610
615
  if edge_width is not None:
611
616
  edge_width = np.asarray(edge_width)
@@ -616,10 +621,6 @@ class MarkersVisual(Visual):
616
621
  if np.any(edge_width_rel < 0):
617
622
  raise ValueError('edge_width_rel cannot be negative')
618
623
 
619
- if symbol is not None:
620
- if not np.all(np.isin(np.asarray(symbol), self.symbols)):
621
- raise ValueError(f'symbols must one of {self.symbols}')
622
-
623
624
  edge_color = ColorArray(edge_color).rgba
624
625
  if len(edge_color) == 1:
625
626
  edge_color = edge_color[0]
@@ -648,7 +649,15 @@ class MarkersVisual(Visual):
648
649
  data['a_position'][:, :pos.shape[1]] = pos
649
650
  data['a_size'] = size
650
651
 
651
- data['a_symbol'] = np.vectorize(self._symbol_shader_values.get)(symbol)
652
+ if symbol is None:
653
+ data["a_symbol"] = np.array(None)
654
+ else:
655
+ if isinstance(symbol, str):
656
+ symbol = [symbol]
657
+ try:
658
+ data['a_symbol'] = np.array([self._symbol_shader_values[x] for x in symbol])
659
+ except KeyError:
660
+ raise ValueError(f'symbols must one of {self.symbols}')
652
661
 
653
662
  self._data = data
654
663
  self._vbo.set_data(data)
@@ -70,8 +70,8 @@ class SurfacePlotVisual(MeshVisual):
70
70
  if z is not None:
71
71
  if self._x is not None and z.shape[0] != len(self._x):
72
72
  raise TypeError('Z values must have shape (len(x), len(y))')
73
- if self._y is not None and z.shape[1] != len(self._y):
74
- raise TypeError('Z values must have shape (len(x), len(y))')
73
+ if self._y is not None and z.shape[1] != self._y.shape[-1]:
74
+ raise TypeError('Z values must have shape (len(x), len(y)) or (x.shape[0], y.shape[1])')
75
75
  self._z = z
76
76
  if (self.__vertices is not None and
77
77
  self._z.shape != self.__vertices.shape[:2]):
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ from vispy.scene.visuals import SurfacePlot
3
+ from vispy.scene import TurntableCamera
4
+ from vispy.color import get_colormap
5
+ from vispy.testing import requires_application, TestingCanvas, run_tests_if_main
6
+ from vispy.testing.image_tester import assert_image_reasonable
7
+
8
+ import numpy as np
9
+ import pytest
10
+
11
+
12
+ @requires_application()
13
+ @pytest.mark.parametrize('x1dim', [True, False])
14
+ @pytest.mark.parametrize('y1dim', [True, False])
15
+ def test_surface_plot(x1dim:bool, y1dim:bool):
16
+ """Test SurfacePlot visual"""
17
+ with TestingCanvas(bgcolor='w') as c:
18
+
19
+ # create data
20
+ nx, ny = (100, 150)
21
+ x = np.linspace(-2, 2, nx)
22
+ y = np.linspace(-3, 3, ny)
23
+ xv, yv = np.meshgrid(x, y, indexing="ij")
24
+ z = np.sin(xv**2 + yv**2)
25
+
26
+ view = c.central_widget.add_view()
27
+ view.camera = TurntableCamera(up='z', fov=60)
28
+
29
+ # color vertices
30
+ cnorm = z / abs(np.amax(z))
31
+ colormap = get_colormap("viridis").map(cnorm)
32
+ colormap.reshape(z.shape + (-1,))
33
+
34
+ # 1 or 2 dimensional x and y data
35
+ x_input = x if x1dim else xv
36
+ y_input = y if y1dim else yv
37
+
38
+ # create figure
39
+ surface = SurfacePlot(z=z,
40
+ x=x_input,
41
+ y=y_input,
42
+ shading=None)
43
+
44
+ surface.mesh_data.set_vertex_colors(colormap)
45
+
46
+ # c.draw_visual(surface)
47
+ view.add(surface)
48
+
49
+ assert_image_reasonable(c.render())
50
+
51
+
52
+ run_tests_if_main()
@@ -7,6 +7,8 @@ cimport numpy as np
7
7
  from libc.math cimport sqrt
8
8
  cimport cython
9
9
 
10
+ np.import_array()
11
+
10
12
  __all__ = ['_get_distance_field']
11
13
 
12
14
  dtype = np.float32
vispy/visuals/volume.py CHANGED
@@ -417,8 +417,8 @@ _ATTENUATED_MIP_SNIPPETS = dict(
417
417
  // Scale and clamp accumulation in `sumval` by contrast limits so that:
418
418
  // * attenuation value does not depend on data values
419
419
  // * negative values do not amplify instead of attenuate
420
- sumval = sumval + clamp((val - clim.x) / (clim.y - clim.x), 0.0, 1.0);
421
- scale = exp(-u_attenuation * (sumval - 1) / u_relative_step_size);
420
+ sumval = sumval + u_relative_step_size * clamp((val - clim.x) / (clim.y - clim.x), 0.0, 1.0);
421
+ scale = exp(-u_attenuation * (sumval - 1));
422
422
  if( maxval > scale * clim.y ) {
423
423
  // stop if no chance of finding a higher maxval
424
424
  iter = nsteps;
@@ -1165,9 +1165,40 @@ class VolumeVisual(Visual):
1165
1165
 
1166
1166
  @relative_step_size.setter
1167
1167
  def relative_step_size(self, value):
1168
+ """Set the relative step size used during raycasting.
1169
+
1170
+ Very small values give increased detail when rendering volumes with
1171
+ few voxels, but values that are too small give worse performance
1172
+ (framerate), in extreme cases causing a GPU hang and for the process
1173
+ to be killed by the OS. See discussion at:
1174
+
1175
+ https://github.com/vispy/vispy/pull/2587
1176
+
1177
+ For this reason, this setter issues a warning when the value is
1178
+ smaller than ``side_len / (2 * MAX_CANVAS_SIZE)``, where ``side_len``
1179
+ is the smallest side of the volume and ``MAX_CANVAS_SIZE`` is what
1180
+ we consider to be the largest likely monitor resolution along its
1181
+ longest side: 7680 pixels, equivalent to an 8K monitor.
1182
+
1183
+ This setter also raises a ValueError when the value is 0 or negative.
1184
+ """
1168
1185
  value = float(value)
1169
- if value < 0.1:
1170
- raise ValueError('relative_step_size cannot be smaller than 0.1')
1186
+ side_len = np.min(self._vol_shape)
1187
+ MAX_CANVAS_SIZE = 7680
1188
+ minimum_val = side_len / (2 * MAX_CANVAS_SIZE)
1189
+ if value <= 0:
1190
+ raise ValueError('relative_step_size cannot be 0 or negative.')
1191
+ elif value < minimum_val:
1192
+ warnings.warn(
1193
+ f'To display a volume of shape {self._vol_shape} without '
1194
+ f'artifacts, you need a step size no smaller than {side_len} /'
1195
+ f'(2 * {MAX_CANVAS_SIZE}) = {minimum_val:,.3g}. To prevent '
1196
+ 'extreme degradation in rendering performance, the provided '
1197
+ f'value of {value} is being clipped to {minimum_val:,.3g}. If '
1198
+ 'you believe you need a smaller step size, please raise an '
1199
+ 'issue at https://github.com/vispy/vispy/issues.'
1200
+ )
1201
+ value = minimum_val
1171
1202
  self._relative_step_size = value
1172
1203
  self.shared_program['u_relative_step_size'] = value
1173
1204
 
@@ -3,7 +3,7 @@ Vispy licensing terms
3
3
 
4
4
  Vispy is licensed under the terms of the (new) BSD license:
5
5
 
6
- Copyright (c) 2013-2023, Vispy Development Team. All rights reserved.
6
+ Copyright (c) 2013-2024, Vispy Development Team. All rights reserved.
7
7
 
8
8
  Redistribution and use in source and binary forms, with or without
9
9
  modification, are permitted provided that the following conditions are met:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vispy
3
- Version: 0.14.1
3
+ Version: 0.14.3
4
4
  Summary: Interactive visualization in Python
5
5
  Home-page: http://vispy.org
6
6
  Download-URL: https://pypi.python.org/pypi/vispy
@@ -19,13 +19,13 @@ Classifier: Operating System :: MacOS :: MacOS X
19
19
  Classifier: Operating System :: Microsoft :: Windows
20
20
  Classifier: Operating System :: POSIX
21
21
  Classifier: Programming Language :: Python
22
- Classifier: Programming Language :: Python :: 3.8
23
22
  Classifier: Programming Language :: Python :: 3.9
24
23
  Classifier: Programming Language :: Python :: 3.10
25
24
  Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
26
  Classifier: Framework :: IPython
27
27
  Provides: vispy
28
- Requires-Python: >=3.8
28
+ Requires-Python: >=3.9
29
29
  Description-Content-Type: text/x-rst
30
30
  License-File: LICENSE.txt
31
31
  Requires-Dist: numpy
@@ -42,6 +42,8 @@ Requires-Dist: myst-parser ; extra == 'doc'
42
42
  Requires-Dist: pillow ; extra == 'doc'
43
43
  Requires-Dist: pytest ; extra == 'doc'
44
44
  Requires-Dist: pyopengl ; extra == 'doc'
45
+ Provides-Extra: glfw
46
+ Requires-Dist: glfw ; extra == 'glfw'
45
47
  Provides-Extra: io
46
48
  Requires-Dist: meshio ; extra == 'io'
47
49
  Requires-Dist: Pillow ; extra == 'io'
@@ -205,7 +207,7 @@ External links
205
207
  - `Chat room <https://gitter.im/vispy/vispy>`__
206
208
  - `Developer chat room <https://gitter.im/vispy/vispy-dev>`__
207
209
  - `Wiki <http://github.com/vispy/vispy/wiki>`__
208
- - `Gallery <http://vispy.org/gallery.html>`__
210
+ - `Gallery <http://vispy.org/gallery/index.html>`__
209
211
  - `Documentation <http://vispy.readthedocs.org>`__
210
212
 
211
213
  .. |Build Status| image:: https://github.com/vispy/vispy/workflows/CI/badge.svg
@@ -1,6 +1,6 @@
1
1
  vispy/__init__.py,sha256=Q-ECX_hCYaK0N0nHaVUQM6bNTUf4A3uGTxGcnlY2FFU,935
2
2
  vispy/conftest.py,sha256=SUNIUsn7o-cQa0mDMAhxoyeU_ENZjqO5B_xTJSNi-yQ,501
3
- vispy/version.py,sha256=PmPMi-W0oYwFnGNPqq2XLCoXtDYpahw_1xhTDJEKPu8,429
3
+ vispy/version.py,sha256=KFGpPXFvW0paJWUPuXrMmn72yGv5mzyEp-ociMF1Hq4,429
4
4
  vispy/app/__init__.py,sha256=NDhvVlPpRUm5zkfs4L1VwbdE1Hhg7dGEkI28RYH2KTM,640
5
5
  vispy/app/_default_app.py,sha256=ACldZQfK7nl2zGInuJBsCm1sfFKZE-UFBgSeavG8gVo,2497
6
6
  vispy/app/_detect_eventloop.py,sha256=h7IMsSZXuIAz9M3bezB_gB2BQqcfiPcdpo5vAn8cd7Y,6622
@@ -22,7 +22,7 @@ vispy/app/backends/_pyqt6.py,sha256=Rgug7PyAevgYPzkxcsRGOKSuZxh9rdP_RFjl8Xzq97s,
22
22
  vispy/app/backends/_pyside.py,sha256=zljctUXPATBxgmMYCvnibRKN-OQC_lOWZGBTmSYQIoA,1371
23
23
  vispy/app/backends/_pyside2.py,sha256=qZpBbEVmrq6uXty8fn-cmitWQJyhPpuoAYC-MC43Cng,2017
24
24
  vispy/app/backends/_pyside6.py,sha256=3Tjd1WfxOGCvyhQgmo49_KGsfSfDgmWvSuD1LW9aKXw,1869
25
- vispy/app/backends/_qt.py,sha256=0Yru1QPN17guoZ-Xs4zShhFtUOfgY7qY0ZZWIIz1wS8,36417
25
+ vispy/app/backends/_qt.py,sha256=rNJOdkxwuqHyPxI79xmGjt40kLZLvDGHWTh1GODp1Kg,36424
26
26
  vispy/app/backends/_sdl2.py,sha256=6Rf6TOLuP-YLmA02rjBjxnMaZSQkSihryn6UDgjyxfc,15544
27
27
  vispy/app/backends/_template.py,sha256=zFzyc74YHyOvIL26zz2nb15M27OJ_iusTVTkUF_835A,8197
28
28
  vispy/app/backends/_test.py,sha256=JDzZW-aq-1eOM167zpf5aWWeIn2lw6F-k4RcDl7wM2E,259
@@ -53,9 +53,9 @@ vispy/ext/egl.py,sha256=K2vuBsbHUdomCNu74nXguoEms8Yi-FBBz9Q770esuYA,12535
53
53
  vispy/ext/fontconfig.py,sha256=DAGBvA1mN0RkKQ_QIRY1rWiPsT7HCwxpgmn4xtgvgyQ,4354
54
54
  vispy/ext/gdi32plus.py,sha256=VCwarTueydrPXCEqQmpJLJcp6afUUlpKJtNlVUMGBdE,6823
55
55
  vispy/ext/osmesa.py,sha256=hdRVI77OtZn-gbekZqWwmcCd7p2Ygol0e3KFCL0PHUw,3516
56
- vispy/geometry/__init__.py,sha256=RX_u729cTnISpRq32LHDmVGZnMdN6mkxyMbmstRwPqo,1092
56
+ vispy/geometry/__init__.py,sha256=hge__wDylvgQs54ojPcZuQ4gCG8X52qlQU3c4hWavfs,1103
57
57
  vispy/geometry/_triangulation_debugger.py,sha256=mOgnM6lGVH2PdwVflPyh7wNSABdABwEMDFk1Zs7y0Ak,5301
58
- vispy/geometry/calculations.py,sha256=zcQ0MpmhltCVX2vvByQfxOV5w9MFIzdHB1orJmJO3Aw,4379
58
+ vispy/geometry/calculations.py,sha256=6CiUB-mbNUoX7PYaWpmURrMK0WL5_LuPrUDPGMVTHDg,5150
59
59
  vispy/geometry/curves.py,sha256=aatBl8ArN1z_RumPHS4ZlCTXPUPOh8mGJ-jeKJ6LpXU,13544
60
60
  vispy/geometry/generation.py,sha256=eCJzZFJBz8dGwsPiN-Zzdq6vuP5JRFUhllPXayljMKg,21584
61
61
  vispy/geometry/isocurve.py,sha256=LNHyCpKDmtzITP1kvKQQvhmD__Pb25VYDn0fXbtJQTs,5971
@@ -66,21 +66,21 @@ vispy/geometry/parametric.py,sha256=1K2MoBwJJbWL46iqE3VM2LrgBqi08BW8r2qsMomlru4,
66
66
  vispy/geometry/polygon.py,sha256=VAgsEr4N7i1jhCUq7KBlm1juiueauNzh6a9S9WhSuxE,4338
67
67
  vispy/geometry/rect.py,sha256=m4rDnXT94nxggOGgdovgG1awqjzntaoMHlsa_xLuVTc,5894
68
68
  vispy/geometry/torusknot.py,sha256=iIQeIdkxVzEJPs6lx6a33C-Tlu5eFwozgA6FXbBvzA4,4404
69
- vispy/geometry/triangulation.py,sha256=TB3WRBO5pMWHVm1-6u93ISmqYqtuSGQuBLNRpVJRMic,32844
69
+ vispy/geometry/triangulation.py,sha256=N9ESaKS8MaoXAWpBPzIEmXEfAf8FiRiynJOMwQ6HvMY,32889
70
70
  vispy/geometry/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
71
  vispy/geometry/tests/test_calculations.py,sha256=vIskbDm-LJkNE7pQ1Ig8dq1QYjS4ka6mgsnuGNdlPZA,1061
72
72
  vispy/geometry/tests/test_generation.py,sha256=GXZE3U9W7fZ7wow3j2RXcNGDV9FytRvb6yRPErKF3wc,2166
73
73
  vispy/geometry/tests/test_meshdata.py,sha256=awAY1VmD81HHXIox-bGvSPRs71nCChOGIZCUwTk-pRg,4335
74
74
  vispy/geometry/tests/test_triangulation.py,sha256=IrwcANHEIyjeE-b-ZyeYm8K_JLyOfczLJ2AGRzEIIjw,13206
75
75
  vispy/gloo/__init__.py,sha256=zK8VDdY_d2sXDLe2ppCRkbXzqj9FrvKsuyU0SVa9OOU,2078
76
- vispy/gloo/buffer.py,sha256=0nE9huwI7l64KPxXgDIBVGIyt8FlpyA7beoALeAVaRQ,17251
76
+ vispy/gloo/buffer.py,sha256=aON7GEt0gU4K56b091TJ8MCvW05jaaYKg1fHDal04Tg,17300
77
77
  vispy/gloo/context.py,sha256=avyXSS9lpehlcjU1IG-3aaHEtVaU1peGEj_e54vvmSo,8912
78
78
  vispy/gloo/framebuffer.py,sha256=rG0fcM2NkED9jFF-GFk0vBDZfqriP63W8VSDr0gcVnM,9607
79
- vispy/gloo/glir.py,sha256=JPoIchay0FsZseejmRUProQi5gExDSkAxIIIUL3sc4A,67857
79
+ vispy/gloo/glir.py,sha256=aBjezLai48LCQ6ibgjnvImcx1cVQ06L8yqoLoKnupfY,68263
80
80
  vispy/gloo/globject.py,sha256=eMkpFZrqJYSHx8A5j1lH-uczqZk-IX2ZYb77E-b1DOM,4013
81
81
  vispy/gloo/preprocessor.py,sha256=lMp2OxCyZDb5gyLUYK3qLMhStrmbyIgnVYnmniWr-wE,2358
82
82
  vispy/gloo/program.py,sha256=Uvo4TN6EViPqaDHhbDmOQjKYm-K6c_WHnFgPEvqTscc,22867
83
- vispy/gloo/texture.py,sha256=ULvBx-iBNo7z7yWZuhweL1yW-uPsuRTObC8URR03_GU,39467
83
+ vispy/gloo/texture.py,sha256=n21fLkSOAsDKTWbGXRfdzbbAGCu48V8SkqQn9an69rw,39502
84
84
  vispy/gloo/util.py,sha256=sC1OM-L0iY3ymJIU4eNOk_9hzDKZVNiKKHOBT_6m500,4548
85
85
  vispy/gloo/wrappers.py,sha256=Buyf8Xl8oPREzH9cn9Ez6ltQ6eaSKDfRrVmuA3GHys0,27222
86
86
  vispy/gloo/gl/__init__.py,sha256=U4QjPJQQNkGFPW2IrDE-KenH4xgcz5D3ULc-Mro39wM,8186
@@ -96,7 +96,7 @@ vispy/gloo/gl/glplus.py,sha256=Rrteeo4uuq-kksV71OWUi1N0Meo3_rtep_ereMoOMK0,9442
96
96
  vispy/gloo/gl/pyopengl2.py,sha256=QbGRBgQ49x0eiCUXB2bz18gM10pWmM6t62W8TE3deH8,2764
97
97
  vispy/gloo/gl/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
98
  vispy/gloo/gl/tests/test_basics.py,sha256=QhMhaesWiOczpVoV8T3POzsltr3W7MiwnIMEV0evH7c,9505
99
- vispy/gloo/gl/tests/test_functionality.py,sha256=aCCxAUkbEVdHaFiRtEig-p4vsrjCyZ-sxggan-BjtW4,17906
99
+ vispy/gloo/gl/tests/test_functionality.py,sha256=2ERyZukhYX4oCN8mtGOJbpgAAc83How7mV_EcyNXrUg,17895
100
100
  vispy/gloo/gl/tests/test_names.py,sha256=b9ZzeDsj9ZlHVIKN8nmNi6GTtUXRF9bP_Qud_uOXgXk,11396
101
101
  vispy/gloo/gl/tests/test_use.py,sha256=kMjWov2cgJtMywy3VjtgFz6kMNQ0D--TkpAsNx3sFic,1909
102
102
  vispy/gloo/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -265,7 +265,7 @@ vispy/io/tests/test_image.py,sha256=a3tracSnOiX5CNf0eLW6Xpuh-D0xZ_tz_YX0dhc6r0M,
265
265
  vispy/io/tests/test_io.py,sha256=PlAUD9EmV4JxG4_Dqu7h7f2pooMoJOMU85fsxpli9r4,4344
266
266
  vispy/plot/__init__.py,sha256=72rwNedyZLreBwhBG12i33i5nzvvvnJbMGv7bVZl3gU,1039
267
267
  vispy/plot/fig.py,sha256=Mr7ta3PceD7wRGGr5FS1btiuxTPj8L7ER_EcDt_tlUI,1791
268
- vispy/plot/plotwidget.py,sha256=7zRjuSYGc3J6rpUmfMbI10j0kS0qEo0rzuN-3N1RaIw,19117
268
+ vispy/plot/plotwidget.py,sha256=yBjvgRRC2GXb_IwhYr1Tj0u1yaRQaD_70U77e_WdxnA,19120
269
269
  vispy/plot/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
270
270
  vispy/plot/tests/test_plot.py,sha256=KZYPQRC9dyr6mJebDSmEtW_mzT5gdLuhZGHpv1B9j3Y,1760
271
271
  vispy/scene/__init__.py,sha256=x8xRdezKIt0HKvqjEbMGkcpZ5ZGsF_athtHG0d7aOrQ,1530
@@ -303,13 +303,13 @@ vispy/scene/widgets/widget.py,sha256=489bq_DqHGGwBxtxfCSPBkfGlFjT6Zp37DCygmnKsRI
303
303
  vispy/scene/widgets/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
304
304
  vispy/scene/widgets/tests/test_colorbar.py,sha256=f1FeuORX6gNAlpOM8UwTTjbP1Wj4T9cX3W3q61OWkOw,1409
305
305
  vispy/testing/__init__.py,sha256=u0CuG-XtGGsOUwzCgMf6o7iLo-DVRjqDGFek1BGVO3c,2488
306
- vispy/testing/_runners.py,sha256=eT_5HoZ7Yhl7I6h0MOvUQ9ObCP9u5vri_xhnGZQz1Xw,16349
306
+ vispy/testing/_runners.py,sha256=R60ItTgYZtKBalCifN2TGJfBV_MPftt6PweEWEMdED8,16519
307
307
  vispy/testing/_testing.py,sha256=NCih_PxhLPxsUkZ4qCSqtPsoh3WJj6_iTcavx15IizU,12718
308
- vispy/testing/image_tester.py,sha256=CHu4a0OiRh2FuIX1C6HkWhc2Ygh9JunELTWw9s-O_QM,17887
308
+ vispy/testing/image_tester.py,sha256=S1JgnR--pukPINuw-TbXz_vM8DU14_yOoF0J4V_9G04,18505
309
309
  vispy/testing/rendered_array_tester.py,sha256=wAC7XN-mOHrgDaQfpiYiF7kNAzHUNF7AgaVAyfd9BT0,2855
310
310
  vispy/testing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
311
  vispy/testing/tests/test_testing.py,sha256=R2YGWKvj0nK7rWWDsp5BUj18k3eH2FmWgO7qejWns2E,805
312
- vispy/util/__init__.py,sha256=SDTPnd-LGr9pJuyYSZl-wXjC01BUcFQULQRPisGPp1Y,718
312
+ vispy/util/__init__.py,sha256=h8ZrWIgq3cVbM8rCWcF2SRWJN0RTwuC3vCa8y4age-I,1321
313
313
  vispy/util/bunch.py,sha256=1KtaQFKS2LWxza60u0WU2yRMqsI7TLiHnoS1mnnOIZc,445
314
314
  vispy/util/check_environment.py,sha256=Sjhh0-k3ZjF5FeTzpEMh1Yxjg-Q1OWHSq0UB0DkNcOM,1811
315
315
  vispy/util/config.py,sha256=w0s9g5B0zYibFJjg4eCmhyKnd39-FOMW2Nh3jL18DIs,15947
@@ -375,17 +375,17 @@ vispy/util/tests/test_run.py,sha256=m4MO_HygF_mk_aFK5zMp-5EDaxRcECJeRWc_x8Bv1ik,
375
375
  vispy/util/tests/test_transforms.py,sha256=LPX8AgB65LVO-sY2KxgBODzd_GmLDMwBpY4cjks17GA,1554
376
376
  vispy/util/tests/test_vispy.py,sha256=alCPm4Pc0pHyhLLrlflhmSVZWHNBjZ8LVx8QgOTWkb4,1542
377
377
  vispy/visuals/__init__.py,sha256=iCtogjsTpVVGd9GNFbpLHABetHoGEeTAJNP2MvXn-Jw,2278
378
- vispy/visuals/_scalable_textures.py,sha256=3ed0PAr4fuFzteC3KAWdPe9Ui6BP5IRqzxpvftbm1ho,20136
378
+ vispy/visuals/_scalable_textures.py,sha256=MF8LbK3ayS71_fgFQeN7TrEcbj9YaxVI8IIiDe65sxk,20199
379
379
  vispy/visuals/axis.py,sha256=D_kdZYJ5tzX1NOrywRn57iMiiOLJLbC59NW-dabFg30,24250
380
380
  vispy/visuals/border.py,sha256=of996lva-tNa-kRb544IWkzrcP-YVtHGEZPMjxgs2lI,7085
381
381
  vispy/visuals/box.py,sha256=2noQWXwjCPluy0YLzrugoeV-vKfSOSRabsAKrJVV_T4,2906
382
382
  vispy/visuals/colorbar.py,sha256=-1saUDIeP8jjG8LgkAugYoWoyHvI0m10_xNY45ceapg,24459
383
383
  vispy/visuals/cube.py,sha256=c_YgNz4EuhKW5z_H5Yl2zIOpmwdJU64H378RZkuWDSA,1764
384
- vispy/visuals/ellipse.py,sha256=xMGgYiziRuZtVz0vgkpKZXdOcXWAFVEHwtBbVL2U_sA,5255
384
+ vispy/visuals/ellipse.py,sha256=uqsSxUL74i2aiwXGHzuwbGbdnjLeKAlhageSpjc0mdw,5236
385
385
  vispy/visuals/gridlines.py,sha256=6VtSG-mhbRfhyqZTJgXvB8tVoy_c1bW_fOq9RwJLkPw,3626
386
386
  vispy/visuals/gridmesh.py,sha256=M9CBguUnFl97F-kNtchdkhXStuKPIwfJT1idugxV9Xo,3444
387
387
  vispy/visuals/histogram.py,sha256=LaTASUMj1XJHxTIL9tSATuFPIUitIxyUDKqfpQZqVt0,2122
388
- vispy/visuals/image.py,sha256=fffw3ml_0GW2-XVtYoKbBh2kxtaKENdpEXEgXeMXEFY,27298
388
+ vispy/visuals/image.py,sha256=Pnukq08pdBd6DwwLVkEZBfItuCD5pdZ8seWscuotWwE,27357
389
389
  vispy/visuals/image_complex.py,sha256=GPzlC57zP6UjAVXQvW8kUFAfW27AqGLAzmPnMm43S6k,5403
390
390
  vispy/visuals/infinite_line.py,sha256=vOKsbwe0AoytKHynB4CM9RtHE7hWlhdse0j0KzlBX7o,6205
391
391
  vispy/visuals/instanced_mesh.py,sha256=3NqIPWGDdcP9gIh5BJWVX2fD6aithsTbEvT_qAk3C_g,5841
@@ -394,7 +394,7 @@ vispy/visuals/isoline.py,sha256=Q6y524xuFUaHXTXXhVx52BPEeVaYsW0Re0ZTjlNe1IA,8749
394
394
  vispy/visuals/isosurface.py,sha256=BxcQRw9n0pdynvinB_WqpFCJzeVHC8RnGe4CJbgkiUw,4013
395
395
  vispy/visuals/line_plot.py,sha256=W9wZTANfV0_0EDbaCh4rCDM5xOn9VGiLGqU6juev-kU,5017
396
396
  vispy/visuals/linear_region.py,sha256=5CRd43NkV_hv2rUDQgumHyT7vgpWhbK5wRR5amagTk0,6813
397
- vispy/visuals/markers.py,sha256=MUUcVClc6oVoS_xY4JZWezZy30qH0kCnlZWGo8c95ww,27708
397
+ vispy/visuals/markers.py,sha256=vT8BecLF0sVgfFzNp1YM5g0tjzVLuA4U2ESLndMbWKk,28203
398
398
  vispy/visuals/mesh.py,sha256=nW_HYW7vXK_02jAv-UxWHfGquMi2SY1rkB-OUcWx74g,12340
399
399
  vispy/visuals/mesh_normals.py,sha256=mLZd7Ops19M2RqCzRTHa3o61zhvwu2umE7ud4gqvkaw,6513
400
400
  vispy/visuals/plane.py,sha256=U_FI8y5BejtjTnroGeKYkOTOdQPSUL1IlO1ZVXdfb-I,2257
@@ -404,10 +404,10 @@ vispy/visuals/regular_polygon.py,sha256=3ckoUHt5j1jrFrelM3e3Q_ieEV58mYeYhbx0OQRe
404
404
  vispy/visuals/scrolling_lines.py,sha256=Pkxp8JuH_4Fbd9tMctZN1W5BNkI4NYKSCsGYe_yEPYk,7262
405
405
  vispy/visuals/spectrogram.py,sha256=Dho8_mOxvxT8QzdUIbUqOGNdSJhtf4IeZjyVNp1ZtZM,5109
406
406
  vispy/visuals/sphere.py,sha256=2JMsmoyjQvO6F7G-W1Bg2wAUQjyyeoTPWCPTQs04B1U,3171
407
- vispy/visuals/surface_plot.py,sha256=0Po1no74ln5lE5ddtSkCyjiBkkraWldv_04lpskgZUY,7471
407
+ vispy/visuals/surface_plot.py,sha256=cM795YcJh49T9IzJqQlX8_nwbovgFJxPI8IofhnkEM0,7508
408
408
  vispy/visuals/tube.py,sha256=Attnn3Dtue0hTmONb3dDT0A56TAAkHoVumSMm26TyN8,6158
409
409
  vispy/visuals/visual.py,sha256=WnQQGr46ACEwiPnVDv_J0e3qEOSEkvZEdDwYEZpPvGM,30714
410
- vispy/visuals/volume.py,sha256=wZJYZGmX0_Qg24C5_mbWes7u7OiMpoM4R0IhdJfL81c,50464
410
+ vispy/visuals/volume.py,sha256=mzsrFQDFHqaiqFVhcriCrIlPrKB6imp9cLi-g0ACKHQ,52106
411
411
  vispy/visuals/windbarb.py,sha256=8mgIMTlzsp20EnY8_ZjX_jUAyciu1ErXY-Ta2Ec2FJo,9597
412
412
  vispy/visuals/xyz_axis.py,sha256=13Ni3QO8NYQsB5UzQXTZY7mF_TgQskzOZTPLKsHZIDw,991
413
413
  vispy/visuals/collections/__init__.py,sha256=tuanWMADPtUXijXdB7MNhHWbnfcKAcftdHaqX7PUfnM,1157
@@ -415,7 +415,7 @@ vispy/visuals/collections/agg_fast_path_collection.py,sha256=b1_b9yDOMdI_S6ylG4M
415
415
  vispy/visuals/collections/agg_path_collection.py,sha256=Gq2MDsFBL5cXr6bCFe1kuABd1L7jzVbh2OlWdOArLrg,6899
416
416
  vispy/visuals/collections/agg_point_collection.py,sha256=n8AnKxResRMXYjjN7UHVXL8vF_BVQXgG1-hwSg78jo4,1766
417
417
  vispy/visuals/collections/agg_segment_collection.py,sha256=S7A2yClTsMU7Gwzp8oFm_egUG0hctkQsI5kTP37yudM,4852
418
- vispy/visuals/collections/array_list.py,sha256=FsywsJisAfL1s_47ackeBgIAxyzcx5E71hKY7Ca_I-Y,14499
418
+ vispy/visuals/collections/array_list.py,sha256=gUV59OpLCk_KyMkXORiGUXX5xakg1-h9Vvpx5dF9bEw,14451
419
419
  vispy/visuals/collections/base_collection.py,sha256=LYv8yjycik7SoznF4OT3A5Qx2ldXB-FLmdglk46FosU,17221
420
420
  vispy/visuals/collections/collection.py,sha256=-Ptalveq5jFnkdLKQVveQdEBWs0BULWMKqRdsHUtpzU,9177
421
421
  vispy/visuals/collections/path_collection.py,sha256=8ChQe8cTucXsroOGpQQGWzVkXrz1_wrI24-J9TRBDv0,1015
@@ -494,12 +494,13 @@ vispy/visuals/tests/test_regular_polygon.py,sha256=pQNkBeXFqPcgpuPIMdxGZQdew5bny
494
494
  vispy/visuals/tests/test_scalable_textures.py,sha256=KkiErVdNDxvRG057yIbqMwxxVY-337nkSMoB69F5TXg,5301
495
495
  vispy/visuals/tests/test_sdf.py,sha256=MWlBi6UftWRx0TGcvnrtLcUY1ZaSztR5gTA9GA8kWGg,3010
496
496
  vispy/visuals/tests/test_spectrogram.py,sha256=odK-n1nYM-wBy2H3Z9f5Ykh4yBmxT9HQB7E-C53czSw,1376
497
+ vispy/visuals/tests/test_surface_plot.py,sha256=KHCvtjZIFdwVGrncTvHCYPE13Y8YX--u7-0aQ-s6k9M,1586
497
498
  vispy/visuals/tests/test_text.py,sha256=webfWtJcSgUkj3QBtZ4kggrs5OdkGZGb0byYc4mtraM,2895
498
499
  vispy/visuals/tests/test_volume.py,sha256=mepaB3ssWl0s4gFU_yYTlhsQ1TCCkg_KtdTkLvR2Brs,18120
499
500
  vispy/visuals/tests/test_windbarb.py,sha256=cqEEcAnPMf29ZloL2fWJo2N04lrJgmQnD-Kt8mXWEQA,1135
500
501
  vispy/visuals/text/__init__.py,sha256=qWgGDKR-ezH4ZzzGKfs72S_zOauVDn5snJ5uHnYv6LE,364
501
- vispy/visuals/text/_sdf_cpu.cp311-win_amd64.pyd,sha256=RiAYo70hyaTCBL9BKIl25pzVCNeFU-jXEuyVcOC1xmk,154112
502
- vispy/visuals/text/_sdf_cpu.pyx,sha256=HiFaCXt0FgauyWD8WPpqESjp6mt9qx8n_s_CMRx8brc,3901
502
+ vispy/visuals/text/_sdf_cpu.cp311-win_amd64.pyd,sha256=N6NjbFvZk6BNNtCM7pErNTcC5Be9gHhBceK-f4bbmOQ,154624
503
+ vispy/visuals/text/_sdf_cpu.pyx,sha256=ymPErgiHN9jhBFuj_GXnChAzTeDbGM-MUQl3lIlzENE,3922
503
504
  vispy/visuals/text/_sdf_gpu.py,sha256=XW5nKivmvUx7tA8LebC7u7N37QQfBcMSUrdPvkG9JU8,10796
504
505
  vispy/visuals/text/text.py,sha256=hK8oSjF34PfczzBa5V7nmsR6uCfI-eqcR3zUB73YpjA,25928
505
506
  vispy/visuals/transforms/__init__.py,sha256=BNbVO0GWBoQZShivY_RDrRHcey-zOmQoF1A47hXgua4,1264
@@ -512,8 +513,8 @@ vispy/visuals/transforms/nonlinear.py,sha256=oiHDhqoM9E4rBGMmqZtVSJVspt1FgZORig6
512
513
  vispy/visuals/transforms/transform_system.py,sha256=dKRMid1Gm0bhh9K_v1RiC-xxbmQF61OHz_0Ur8GdMmU,14098
513
514
  vispy/visuals/transforms/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
514
515
  vispy/visuals/transforms/tests/test_transforms.py,sha256=QbAo0I3g5VkaQzzsZ03zktP-ge2JiXQeD2rqV6_LK7o,7114
515
- vispy-0.14.1.dist-info/LICENSE.txt,sha256=oENMqsC-O8FBKA0sbJxkd_T1-rK5oVsTFdfC4IzuRIs,1810
516
- vispy-0.14.1.dist-info/METADATA,sha256=Kz8yWzyMHbCCID0uy0F-O6zcCrcmUlDbFGEPoOCvSWs,8546
517
- vispy-0.14.1.dist-info/WHEEL,sha256=badvNS-y9fEq0X-qzdZYvql_JFjI7Xfw-wR8FsjoK0I,102
518
- vispy-0.14.1.dist-info/top_level.txt,sha256=mciStn1SI48jYwEhJXlrMJ3HaJ90XOr5ZGJ8YdFI674,6
519
- vispy-0.14.1.dist-info/RECORD,,
516
+ vispy-0.14.3.dist-info/LICENSE.txt,sha256=WDEavemgKeEMcbfp2qjU8y8yrxcTIF7ZDAxySta62p8,1810
517
+ vispy-0.14.3.dist-info/METADATA,sha256=m7BeNoyrpxev9r_EMKI_oe7mIsvNw1z_sA9xSWd_iRk,8614
518
+ vispy-0.14.3.dist-info/WHEEL,sha256=nSybvzWlmdJnHiUQSY-d7V1ycwEVUTqXiTvr2eshg44,102
519
+ vispy-0.14.3.dist-info/top_level.txt,sha256=mciStn1SI48jYwEhJXlrMJ3HaJ90XOr5ZGJ8YdFI674,6
520
+ vispy-0.14.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.41.2)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp311-cp311-win_amd64
5
5