vispy 0.14.1__cp311-cp311-macosx_11_0_arm64.whl → 0.14.3__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/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,5 +1,10 @@
1
+ vispy-0.14.3.dist-info/RECORD,,
2
+ vispy-0.14.3.dist-info/WHEEL,sha256=sieEctgmsyAnWfDYOiunmkigyyjGmYuUaApm_YItwoI,110
3
+ vispy-0.14.3.dist-info/top_level.txt,sha256=mciStn1SI48jYwEhJXlrMJ3HaJ90XOr5ZGJ8YdFI674,6
4
+ vispy-0.14.3.dist-info/LICENSE.txt,sha256=L7orAx3saMGRPfxOnpOKfVQ6JKCc5XtadZSWrPSuW0A,1774
5
+ vispy-0.14.3.dist-info/METADATA,sha256=B_Jf7eW8JW4R4qZxYjGSCn4CbjPj1Q4zsZ_JpshpnSg,8394
1
6
  vispy/conftest.py,sha256=1qkMPiB5SHGll3Sbvz9iBIAVeyaIuW7YDw8VpfKTMzk,489
2
- vispy/version.py,sha256=2Ctgubb5b_lxFG2ixV07ZYKw5eto45wRlKsBIObkGsg,413
7
+ vispy/version.py,sha256=3mnQHEW9gizHocB0ULApMUw7E4CZd4qai5GsjMH_Vo4,413
3
8
  vispy/__init__.py,sha256=Sm3hzOs_-fXTikZnwAFZoLOvETmFCw8BsSoAguXvhdY,902
4
9
  vispy/app/_detect_eventloop.py,sha256=hMht958_W6MVGEfJS7UMTRnIHyoODeJ6oVCaDXJZ5H8,6474
5
10
  vispy/app/timer.py,sha256=zIQwcF-XmowAHqe25z4nMwiRTMaNOnjz4IeTQClE8bg,5754
@@ -15,7 +20,7 @@ vispy/app/backends/_pyside6.py,sha256=bihad8zmp1UsjGdeLyGnYlmHZivGe99H4h3A-UJG0j
15
20
  vispy/app/backends/_glfw.py,sha256=xTXcH1oms8XoZeAOKJ19yRcR7N63BVjaqEQCtKy-nyc,17021
16
21
  vispy/app/backends/_pyglet.py,sha256=vx8GsKA30APkn9U2_UVghJfVo5uuskt_cPxehAgP7Dw,15110
17
22
  vispy/app/backends/_pyqt6.py,sha256=w3_ky9vIxTfviVMnm4kqv3m_xhleIqMYTgwXXENFSqo,1422
18
- vispy/app/backends/_qt.py,sha256=-Frs4Cmjwo-3pqIVV385gX6FDRNE3NcsUr23ECsB1B8,35449
23
+ vispy/app/backends/_qt.py,sha256=hiFOdyM_aR9nDdpU9pHXtIuQ8lqRp2wL3cEmC61ZLdg,35456
19
24
  vispy/app/backends/__init__.py,sha256=qyQxLmnTb8cVjuNxAyG4kC9mqV5gz7w8NwcRUzy6wOU,1837
20
25
  vispy/app/backends/_template.py,sha256=9h7LFYTuIiFALaS6viYJ1bPtfijJh7pATvujFlFQuN0,7953
21
26
  vispy/app/backends/_test.py,sha256=GPHQS3RyjqIHDIwudfmmvl11a97UOHtf9FknVsGorHU,251
@@ -41,7 +46,7 @@ vispy/app/tests/test_backends.py,sha256=keMBQWTDpfRbAN5nAW7L9HpancsodUptH4oEOvN7
41
46
  vispy/app/tests/test_app.py,sha256=XpGn6gfT19t_FqfCcL7tpz-eGQCusl9CD6nNxnNQJdY,15781
42
47
  vispy/plot/fig.py,sha256=9pDwHkK_-BmrNLI_CW3xL8L3lbZAYgtKXdPXf3zmtcU,1733
43
48
  vispy/plot/__init__.py,sha256=7JS6JkVu0ZU_VcNRih0LkoP1WIJP8whVZ6nNOPPU4k0,1003
44
- vispy/plot/plotwidget.py,sha256=eHdBQQX_dNnwhY3Xe7dVWXY2r1tbHGcfuPfpKfLDr2I,18595
49
+ vispy/plot/plotwidget.py,sha256=6-KQrTzAe8of0VizNDfU2W1d8onLD0DnLJnOWjmB3nQ,18598
45
50
  vispy/plot/tests/test_plot.py,sha256=nDijZb1YG-ANmD9JEQdhwzjVvYH-9A49i69oBv1Gm9A,1714
46
51
  vispy/plot/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
52
  vispy/util/bunch.py,sha256=u-c4mSRQWSdgTCD3aAyNFtTBF4H3z5VE9lTAE2KZ0Lc,430
@@ -52,7 +57,7 @@ vispy/util/ptime.py,sha256=7RHg21z-msNvkOCFh1Erbbryd5Rhe3oyhDexa9MAqYU,493
52
57
  vispy/util/check_environment.py,sha256=QD-D2swX5JAOfp4BRhsvYiuMiZN3EasEe3MHescu7Dc,1754
53
58
  vispy/util/quaternion.py,sha256=y-6Eyd4RpN4uV30IpO3tqhbqcRNuqZbRDSYd4C7x1SM,6776
54
59
  vispy/util/eq.py,sha256=GGbEZCxj9cAw-3GE9jitgAy7UrMqkcWBDhse4n-1JW0,1100
55
- vispy/util/__init__.py,sha256=m9vuqDITob_PuidKdaUlRuq51LqLiVVhFCMaXGZ9GVM,701
60
+ vispy/util/__init__.py,sha256=onztfB9EufnRPDimoyIGcGPV68Ah4Des1EWX5iMBtYQ,1289
56
61
  vispy/util/fetching.py,sha256=6WirJTJIlXHZUfzvUNyfKUiPQosl2QcPeQFQuSSxMSk,10304
57
62
  vispy/util/keys.py,sha256=qEy7e0icUg-cUHv8a_RSmg5sLT4_yt3-2T-LKfWASSM,2443
58
63
  vispy/util/frozen.py,sha256=KYpO-5s71zGMLLinnlImvSwRV6E2ws61yDiTS2nSpqc,891
@@ -110,15 +115,15 @@ vispy/util/fonts/data/OpenSans-Bold.ttf,sha256=WJSjZJshPPWy1nO256hxgV_R0SD6aKRjW
110
115
  vispy/util/fonts/data/OpenSans-Regular.ttf,sha256=5k5QiyqiiA-QfkcMRVCYDsTAaU0QOkPzYVCsP5MYm-4,217360
111
116
  vispy/util/fonts/data/OpenSans-BoldItalic.ttf,sha256=PKaA8kRMyeUER9BXwAZGRWbpLy53sLbiZJHlvXV-1Oc,213292
112
117
  vispy/gloo/globject.py,sha256=Lpfhws2E8nQ3WaZDdVF8pm4LioqeFgHPRvQnYijN0bs,3912
113
- vispy/gloo/glir.py,sha256=vpx_2Q_kuK6o_AsyeteArRctPmigzM9ADd7HrHOfIz4,66041
118
+ vispy/gloo/glir.py,sha256=kCvfcpIEYSDyH-OpHVT8bCG7byIIAZwQTx-d8oPzFes,66439
114
119
  vispy/gloo/util.py,sha256=teg0SbQheFdFIz6KpI2FfCyb_9eI7KOcXwJc-a2EC_s,4419
115
120
  vispy/gloo/__init__.py,sha256=5WufpLo64kGzkZCyCvjm-DN_Cvd4Ihuxsn7sJUbREJ0,2022
116
121
  vispy/gloo/preprocessor.py,sha256=dclY2vLpfLRLfezct3O2s5wk8XMvoqvEfLABZNUa1g8,2291
117
122
  vispy/gloo/context.py,sha256=cFlSfTlr-WQLWfksOqFXjqCel2F5kk9nR1RTdjLhyPM,8640
118
123
  vispy/gloo/wrappers.py,sha256=38_YO3Td70B_CNFKysff61jfAyMaaDu_lteIeotVu0c,26460
119
124
  vispy/gloo/framebuffer.py,sha256=77lIv9iojJ3tPm6ZsE8hRS0Iv9UdyoCRDC0RtxKTR-o,9350
120
- vispy/gloo/buffer.py,sha256=P7zC2JsVMr_ng6rOWJgL93iQWfPJqCJofaoEh8EZ0cg,16746
121
- vispy/gloo/texture.py,sha256=u8dWlGa0zj0CAh84sfUhvd0DJNZHdBjObtUlNSmYN18,38422
125
+ vispy/gloo/buffer.py,sha256=uZkAqm5_mV9Nryyu5wSXgdY2KZxf-JsEAGQ7_qTtJt0,16795
126
+ vispy/gloo/texture.py,sha256=9e8t1aUl1X7MbEF6thAFsH2korrb2WqvBVhVTDYRr_c,38456
122
127
  vispy/gloo/program.py,sha256=fsrl5kJ5aLX46M7cwPBl9QuZ4DP55Oa0I0QUprKUvok,22324
123
128
  vispy/gloo/tests/test_glir.py,sha256=e8hiifOuNehzDAqg4x5zqNKB-pzcPe-lP_RL4ZpLKoo,9644
124
129
  vispy/gloo/tests/test_buffer.py,sha256=RMbQeeKSG2lO2gxqmHx2CfMP841MbnbYDYNb6SxLc40,19819
@@ -146,7 +151,7 @@ vispy/gloo/gl/tests/test_names.py,sha256=v0Mnl8T1KKE9VJSCweDkuBxBy0WV2JZALEvS1cX
146
151
  vispy/gloo/gl/tests/test_basics.py,sha256=jTnERZwk3Qeg86__8N7oBfu3A02OHVfoT204cn_k3cQ,9223
147
152
  vispy/gloo/gl/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
148
153
  vispy/gloo/gl/tests/test_use.py,sha256=C4S4BXTg2_2snJnwISvJecufesxVgC6zfqicTZINGb8,1838
149
- vispy/gloo/gl/tests/test_functionality.py,sha256=3OTTA_SHwiq-3fxNQKwQV8doAnr4Xe-BFmeqr93Xu3o,17340
154
+ vispy/gloo/gl/tests/test_functionality.py,sha256=Q4DMHIczjHBEgl4-0-IUCLhHqYbJk7Kfyhl9ed6zrbE,17327
150
155
  vispy/color/colormap.py,sha256=Xp7e05oaJausMOvl1UciqDagPuq61GJA9iJq4wpdMfw,42586
151
156
  vispy/color/__init__.py,sha256=aePQV4OX_2QsRcILIHdzlirVfGvfAxFgmaajLFqMjXo,644
152
157
  vispy/color/color_space.py,sha256=WcVdx-Bio8GSC9-VTcjpXBZ970uE3OZGgDF27MpBFX0,6051
@@ -314,9 +319,9 @@ vispy/glsl/colormaps/winter.glsl,sha256=jBZ2kMyaquZpy2Jo_C5va6FrvAff7-pTVW8nX1pF
314
319
  vispy/glsl/colormaps/greens.glsl,sha256=MwyQWRI2g8XGbvMcWLXs4LQeybmGJwZdOp7hnpAVKEQ,639
315
320
  vispy/glsl/colormaps/wheel.glsl,sha256=J1Yyv8w5flWe5Jt7FNcoOtN5sT3b4Cb2d-KY5X905QI,719
316
321
  vispy/glsl/colormaps/colormaps.glsl,sha256=rHkMnlGW8hT-NDVgoW2tyH12nWxXM0497gLDQaMRbHE,781
317
- vispy/testing/image_tester.py,sha256=So3SAqEvs_9q6Dklvf9cb1NhtjTv-fy2PAru4Rewaok,17414
322
+ vispy/testing/image_tester.py,sha256=jIWc2NSssUSaHmKHRRfCod9UqfqFewdhyK3nRytd9zw,18011
318
323
  vispy/testing/__init__.py,sha256=k7KagAl3LhX_2EblFK6x_ekO23Un_9CAIuHdEgHdmps,2437
319
- vispy/testing/_runners.py,sha256=Sgu8AEEFrKzfbWMdrx79f9JVbbWVZ3ZdloLq-HPSpJI,15903
324
+ vispy/testing/_runners.py,sha256=Qte6dMbYNGYGMcID35ZhIoiy55Q2s2d2Fo-YE-d-YWA,16071
320
325
  vispy/testing/rendered_array_tester.py,sha256=aK_wUjyk7M3_eXPJkTLgfjt-cLPAf10u9PSGSdp_0rg,2770
321
326
  vispy/testing/_testing.py,sha256=e6iw11e2VSsBqeQ40UCu12GimkTdsZY1PNFxHnxELAc,12302
322
327
  vispy/testing/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -336,22 +341,22 @@ vispy/visuals/windbarb.py,sha256=SXO3DNmXinkzeAJBAgCJL-vTBXs_O1j1f4Jxnliv_Rg,930
336
341
  vispy/visuals/linear_region.py,sha256=XUc80U7Mt4VTAXHqs03IwCcQifQJvop7AGXbXRt7vQQ,6614
337
342
  vispy/visuals/__init__.py,sha256=rVc88pQhwxpfdoa8H034MxfQOV9lipAW1sGIgDt_UWI,2228
338
343
  vispy/visuals/mesh.py,sha256=8dwELjgrY42GCBZK4xyP9YNqi5FD1hhH7mSubRDXZJk,11967
339
- vispy/visuals/_scalable_textures.py,sha256=Wtp1ecnEoLrKOSZY9Cm2rqmU9izQlKxyuPE_0Jqdebc,19651
340
- vispy/visuals/volume.py,sha256=0JA2AU5p9kXsxMsghFZXfuNtK46p7TUMFKGpmU9qxSg,49129
344
+ vispy/visuals/_scalable_textures.py,sha256=y2pJNnV1wsKeNr3RyJ8Wws8g0TGi3GVfuPAZ0etm_g4,19713
345
+ vispy/visuals/volume.py,sha256=0lX0en71Tn4Kl-NUN9QuZm_2sZrztwKjntx7j-awZt0,50740
341
346
  vispy/visuals/infinite_line.py,sha256=A5D8zn_6M_4U0SCa2JacRIxmofBGgQMxa4gn8f3wgAk,6006
342
347
  vispy/visuals/gridmesh.py,sha256=It0s6Mj4A5kVuDVy6-xkUqC0Yq1mgoqH8JF9uN02zf8,3346
343
- vispy/visuals/surface_plot.py,sha256=hwKaTVJW0ty9zXp2HCI4NWr2irUYuasI7IknQwreG8U,7279
348
+ vispy/visuals/surface_plot.py,sha256=D7AI6g2RUjtrM-IQk1Pb721kxryAEl_QDYd2H0Zt5eU,7316
344
349
  vispy/visuals/cube.py,sha256=Cly3BjLLr436IUrQdRuL8FmSxXO0siKrxpCVaDxM-6U,1723
345
- vispy/visuals/markers.py,sha256=EsjarX9enN1CzfEN5JyGihX7sPbj_36eadvPglrF29I,26898
350
+ vispy/visuals/markers.py,sha256=DalqkcXTFRuxTZEhSDBkG0M1A4KbYE2jWdyIfOx003c,27384
346
351
  vispy/visuals/rectangle.py,sha256=r7eKBo1HH0WAGTxeXFBfHJN0Zvjfue7JcDFTdcMiWmU,6664
347
352
  vispy/visuals/visual.py,sha256=Oo-skll6aDN1lkzMgrxeSPN4Xjf9OwRoOGD9YF_58vU,29791
348
- vispy/visuals/ellipse.py,sha256=jG_fryPB4mDEJtzeX8YhK7xf_Jz-oAjIqXNu87S8S2Y,5092
353
+ vispy/visuals/ellipse.py,sha256=pJGcwF4sVuCJkLOleFs-A7ReIZhHmGTQ1xs0hkXd_mk,5074
349
354
  vispy/visuals/line_plot.py,sha256=eqV9Trg8kU8t2C9dXfINAIsM7QK4BeAgWG2QMkqde-E,4882
350
355
  vispy/visuals/spectrogram.py,sha256=cf8PfG_hHZ3aUM8SExpIG5Tmr57N9gEF0-R6jPQ2K00,4940
351
356
  vispy/visuals/gridlines.py,sha256=0Tiub9xZtLOD8n-QYEKsdj-11YW8ddXOlZ0rHnFBdeY,3521
352
357
  vispy/visuals/xyz_axis.py,sha256=ZwqRecj0FvCWsELd3dg8voVxjzgR--hH9ndEH_fv5kk,957
353
358
  vispy/visuals/plane.py,sha256=pZGzHVBwh6AgAC-7jKyMzMGbk8mo1DwFcCPhl2S6XN4,2203
354
- vispy/visuals/image.py,sha256=t7-YfU1YvsPa_GsxstUWdqSoWIvypvdaBEpMyspLrqo,26610
359
+ vispy/visuals/image.py,sha256=U_iYuVRRF7JRmpxlrLhVwEXdf7Yw5mNAs6QMTyhTs3A,26668
355
360
  vispy/visuals/border.py,sha256=fkhYCFdaYSVpGNJ8Sb4-MZhAFq9ki1gAlvs7NDoLd3k,6877
356
361
  vispy/visuals/sphere.py,sha256=CpV8Syhp1Ujp8lafmuWcdABc-2lwAns91h8X142uS8Q,3091
357
362
  vispy/visuals/isosurface.py,sha256=r3PsFKDXd8T-HrtWo5MboRdJusrIwzj5JaBwEla3oP0,3900
@@ -380,6 +385,7 @@ vispy/visuals/tests/test_regular_polygon.py,sha256=0HVB2ua1wT-U_czvOT_Sv6VmyCHjh
380
385
  vispy/visuals/tests/test_image.py,sha256=_GEc4AfOPrwNVii5yZQkYkEVS43upkjo8WTMRUwCKdI,13955
381
386
  vispy/visuals/tests/test_image_complex.py,sha256=vavgRlBjLcfoP3ieyxu-idyGtR6mRASRol0NwfrEz1M,1451
382
387
  vispy/visuals/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
388
+ vispy/visuals/tests/test_surface_plot.py,sha256=GbQU9zKs23VUkIKNqeTWs4IlvNwl203ntXAD5WvEm0U,1534
383
389
  vispy/visuals/tests/test_colorbar.py,sha256=Gfv9Rt8DPZMWSQwLAJcq3tnyKBwkn2ziI2BZEjmkRIQ,5987
384
390
  vispy/visuals/tests/test_polygon.py,sha256=S3pnd_Nx8ZBL8ysPbwqEkDPCESmImxK0gjknE0BNl-4,4157
385
391
  vispy/visuals/tests/test_markers.py,sha256=wowzm_OwPUXHq0r7VWEKcq9QlD9GgSdA9DpQy9FLVm8,1724
@@ -435,8 +441,8 @@ vispy/visuals/graphs/layouts/force_directed.py,sha256=uEquUaboL_26QG3IeIhN20AzAS
435
441
  vispy/visuals/graphs/layouts/random.py,sha256=ox3JXQ1ysTGYHYYicIDBAZzNzzIKBbFln2yY1dNRtz8,1674
436
442
  vispy/visuals/graphs/layouts/circular.py,sha256=hEKjN2ow9mtQRZCslOpIkZWMTp5QM_HI9NuObNH0P7g,1559
437
443
  vispy/visuals/graphs/layouts/networkx_layout.py,sha256=pqF1JClCUYj-Cjf-tcphzo4Z3Ym_ha5Arxo68tYj-es,3583
438
- vispy/visuals/text/_sdf_cpu.cpython-311-darwin.so,sha256=8TBPhEx8JAD7u9AEu2t1Ly1deBaKDOMNhk_Tv0rUULw,209115
439
- vispy/visuals/text/_sdf_cpu.pyx,sha256=_P7SWbsPwKpEg3d7L0P-Rgw3l-YoClF6dOrtsahxZUk,3791
444
+ vispy/visuals/text/_sdf_cpu.cpython-311-darwin.so,sha256=5i4x8OonRy_gbjReZ0vbxKY4c152ANiA9hHdQ58BMtU,205008
445
+ vispy/visuals/text/_sdf_cpu.pyx,sha256=uXBK9RDoLGfkNjfUvrTbkfdBQ3K06ReReswwN8bKN7M,3810
440
446
  vispy/visuals/text/__init__.py,sha256=XyFi9zGWKpgWKC6xm0uMQZD1yzWU5TBi3jzoIehZ-dM,357
441
447
  vispy/visuals/text/text.py,sha256=nyenaB3kj0YI6EpO9PCMH9RHMa4l9G1OoygZbOwksaE,25253
442
448
  vispy/visuals/text/_sdf_gpu.py,sha256=uQwtOfH0tzZSlOP7uSY28SUK4_yk-dWwmmJRPXVAgD0,10480
@@ -454,7 +460,7 @@ vispy/visuals/collections/raw_triangle_collection.py,sha256=f2K8-Aj6GPesVOpPonF0
454
460
  vispy/visuals/collections/base_collection.py,sha256=g0yWPNAEv-owvmADHw0Jd_ehc2kvTYUSbLgMDdz4iJ8,16739
455
461
  vispy/visuals/collections/raw_polygon_collection.py,sha256=2ax1mWVS10gm07TsEqNbggSqRsQfFR74saWbvCYgz8I,2672
456
462
  vispy/visuals/collections/path_collection.py,sha256=ZFmuNy4_7EtiIOmXxMwvEvNSoA2RZBFU9Rg1clo_8dI,992
457
- vispy/visuals/collections/array_list.py,sha256=hbRKxRvogOln9AJKRJE4o3IsqJuVvNEMvWCYvMiQUTY,14098
463
+ vispy/visuals/collections/array_list.py,sha256=sZrKoLeFyqEWYb8oKyAgwCRO3z-7o2nQyuacxUdWPaI,14050
458
464
  vispy/visuals/collections/segment_collection.py,sha256=sHaxBiA4CQ9bBBe1tzWO_15wJwVRbdVmm7GiSf_120w,797
459
465
  vispy/visuals/collections/collection.py,sha256=a-NomLwYKzHwQkUSTbK9d61dYtPxNjv8R6fAQuY2q2A,8924
460
466
  vispy/visuals/collections/agg_point_collection.py,sha256=NAQfPjrgAknCvlECU4EHHQ4AcU3qmW3XF4vqvOK2kCI,1714
@@ -464,15 +470,15 @@ vispy/geometry/isocurve.py,sha256=ChKH1vL1yLyvhjjCnMQgS8lY7xoLusqYfedWk68CrVg,57
464
470
  vispy/geometry/generation.py,sha256=vT7JvjSDB4j3jNI-9qBjrqXZ-yb7aHN1-R6Y5c2cVlU,20941
465
471
  vispy/geometry/meshdata.py,sha256=fXYlvVNfc40YVFMwPMv7cMG0R_5BdBNfPtMG4UVqrBc,26830
466
472
  vispy/geometry/polygon.py,sha256=lq14n_ftvtCM31-CU-6pUX7qZI5vB2wIMfS_IFvGUKo,4201
467
- vispy/geometry/__init__.py,sha256=T7LcEs3PKEmr_nSC2vYbT0EzihkPJ4EM7ZBQnnFnnI8,1069
468
- vispy/geometry/calculations.py,sha256=o7jGjMEop1ppKmOJZmvV8casLjwUq2oDWP4ppeIo8LI,4245
473
+ vispy/geometry/__init__.py,sha256=EYyu3uN22nLfOFkgt0K4R1Vt9sMD2qMtXkUG00hPrkY,1080
474
+ vispy/geometry/calculations.py,sha256=s9zQP1FthrLNBzWkFr07_BcvSMPpNcnQiL0wUY2T8tk,4988
469
475
  vispy/geometry/rect.py,sha256=uzCJibtsD1M8oR86fzB79Qookw5suwAnhs06kKVmrB0,5684
470
476
  vispy/geometry/_triangulation_debugger.py,sha256=zvQlPkTIuoB-96T3lomOa26NjG-pp-OcTNnbL-vCXKo,5130
471
477
  vispy/geometry/curves.py,sha256=vZ3ZdH6lozUTyAPq7_0sjT6U20WPkUu8OjZWVyktQj4,13145
472
478
  vispy/geometry/torusknot.py,sha256=09D8aAU-0BsHZ57pnKYQ0_jQ1IMnLD88VieqR53jXlM,4262
473
479
  vispy/geometry/normals.py,sha256=U6cDCSpnUey5xXL2sDEvs6iY91zaToOjqXhFQURR3tk,2436
474
480
  vispy/geometry/isosurface.py,sha256=w-3aIM2BwjinptFP31mEM5jx44Clkfx9XSwE3HcEydk,20651
475
- vispy/geometry/triangulation.py,sha256=31Ne55l0SqvXp6CfLw4I5nCmqZQPCAzEC0c4aZ4nG24,31968
481
+ vispy/geometry/triangulation.py,sha256=Gcx1o0StWDNq4JcdTPbz_5W4j2b1NzZ1b-f7nBrJ31Y,32011
476
482
  vispy/geometry/tests/test_meshdata.py,sha256=fgTGmoOyPHtQcH5tp8KVFmeWmAWKCxjvrSdohUxIOTo,4229
477
483
  vispy/geometry/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
478
484
  vispy/geometry/tests/test_calculations.py,sha256=KXUvAM5hzF_0bx8Dz1hlfS_wxW-IbM12M4uThBCukik,1038
@@ -512,8 +518,3 @@ vispy/scene/widgets/viewbox.py,sha256=gZekx8GSoJj8vRvqJ7Hw5Y5L1kVCmQQrF_f5YQOkkE
512
518
  vispy/scene/widgets/label.py,sha256=2ynsXsQNgIRFFkLzftVr1p94nLYLRlr_WWATDuJq7-8,1308
513
519
  vispy/scene/widgets/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
514
520
  vispy/scene/widgets/tests/test_colorbar.py,sha256=Yp1A_nZKC9NTSzdTM6OYKAcMEk0QH1CYUlhpMuxmQ3A,1362
515
- vispy-0.14.1.dist-info/RECORD,,
516
- vispy-0.14.1.dist-info/WHEEL,sha256=eaDTbMedWofVq8IZjew9qeAkoA5Sw2MOU2ppdIRr1Jg,110
517
- vispy-0.14.1.dist-info/top_level.txt,sha256=mciStn1SI48jYwEhJXlrMJ3HaJ90XOr5ZGJ8YdFI674,6
518
- vispy-0.14.1.dist-info/LICENSE.txt,sha256=SyGjHD8uWIdCicPnNsCNMhwjJomQCArryMh7QGkD3JI,1774
519
- vispy-0.14.1.dist-info/METADATA,sha256=Vt-xn1cUKPE2l5nMUHr51wtiVUW7_sY0afAVkNwL7nU,8328
@@ -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-macosx_11_0_arm64
5
5