vispy 0.9.5__cp38-cp38-win_amd64.whl → 0.14.0__cp38-cp38-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.

Files changed (103) hide show
  1. vispy/app/backends/_glfw.py +2 -2
  2. vispy/app/backends/_pyglet.py +8 -2
  3. vispy/app/backends/_qt.py +88 -63
  4. vispy/app/backends/_wx.py +6 -1
  5. vispy/app/canvas.py +4 -2
  6. vispy/app/tests/test_canvas.py +52 -1
  7. vispy/app/tests/test_context.py +5 -3
  8. vispy/color/color_array.py +8 -1
  9. vispy/color/colormap.py +5 -25
  10. vispy/geometry/meshdata.py +76 -38
  11. vispy/geometry/rect.py +6 -0
  12. vispy/geometry/tests/test_meshdata.py +72 -0
  13. vispy/gloo/buffer.py +12 -0
  14. vispy/gloo/gl/_constants.py +9 -5
  15. vispy/gloo/gl/_es2.py +8 -4
  16. vispy/gloo/gl/_gl2.py +2 -3
  17. vispy/gloo/gl/_proxy.py +1 -1
  18. vispy/gloo/gl/_pyopengl2.py +12 -7
  19. vispy/gloo/gl/tests/test_names.py +3 -0
  20. vispy/gloo/glir.py +26 -13
  21. vispy/gloo/program.py +39 -22
  22. vispy/gloo/tests/test_program.py +9 -2
  23. vispy/gloo/tests/test_texture.py +19 -2
  24. vispy/gloo/texture.py +46 -16
  25. vispy/gloo/wrappers.py +4 -2
  26. vispy/glsl/build_spatial_filters.py +241 -293
  27. vispy/glsl/misc/spatial-filters.frag +1299 -254
  28. vispy/io/_data/spatial-filters.npy +0 -0
  29. vispy/io/datasets.py +2 -2
  30. vispy/io/image.py +1 -1
  31. vispy/io/stl.py +3 -3
  32. vispy/scene/cameras/base_camera.py +6 -2
  33. vispy/scene/cameras/panzoom.py +10 -14
  34. vispy/scene/cameras/perspective.py +6 -0
  35. vispy/scene/cameras/tests/test_cameras.py +27 -0
  36. vispy/scene/cameras/tests/test_perspective.py +37 -0
  37. vispy/scene/cameras/turntable.py +39 -23
  38. vispy/scene/canvas.py +9 -5
  39. vispy/scene/events.py +9 -0
  40. vispy/scene/node.py +19 -2
  41. vispy/scene/tests/test_canvas.py +30 -1
  42. vispy/scene/tests/test_visuals.py +113 -0
  43. vispy/scene/visuals.py +6 -1
  44. vispy/scene/widgets/viewbox.py +3 -2
  45. vispy/testing/_runners.py +6 -12
  46. vispy/testing/_testing.py +3 -4
  47. vispy/util/check_environment.py +4 -4
  48. vispy/util/gallery_scraper.py +50 -32
  49. vispy/util/tests/test_gallery_scraper.py +2 -0
  50. vispy/util/transforms.py +1 -1
  51. vispy/util/wrappers.py +1 -1
  52. vispy/version.py +2 -3
  53. vispy/visuals/__init__.py +2 -0
  54. vispy/visuals/_scalable_textures.py +20 -17
  55. vispy/visuals/collections/array_list.py +3 -3
  56. vispy/visuals/collections/base_collection.py +1 -1
  57. vispy/visuals/ellipse.py +1 -1
  58. vispy/visuals/filters/__init__.py +3 -2
  59. vispy/visuals/filters/base_filter.py +120 -0
  60. vispy/visuals/filters/clipping_planes.py +24 -12
  61. vispy/visuals/filters/markers.py +28 -0
  62. vispy/visuals/filters/mesh.py +61 -6
  63. vispy/visuals/filters/tests/test_primitive_picking_filters.py +70 -0
  64. vispy/visuals/graphs/graph.py +1 -1
  65. vispy/visuals/image.py +114 -26
  66. vispy/visuals/image_complex.py +130 -0
  67. vispy/visuals/instanced_mesh.py +152 -0
  68. vispy/visuals/isocurve.py +1 -1
  69. vispy/visuals/line/dash_atlas.py +46 -41
  70. vispy/visuals/line/line.py +2 -5
  71. vispy/visuals/markers.py +310 -384
  72. vispy/visuals/mesh.py +2 -2
  73. vispy/visuals/shaders/function.py +3 -0
  74. vispy/visuals/shaders/tests/test_function.py +6 -0
  75. vispy/visuals/tests/test_axis.py +2 -2
  76. vispy/visuals/tests/test_image.py +92 -2
  77. vispy/visuals/tests/test_image_complex.py +36 -0
  78. vispy/visuals/tests/test_instanced_mesh.py +50 -0
  79. vispy/visuals/tests/test_markers.py +6 -0
  80. vispy/visuals/tests/test_mesh.py +17 -0
  81. vispy/visuals/tests/test_text.py +11 -0
  82. vispy/visuals/tests/test_volume.py +218 -12
  83. vispy/visuals/text/_sdf_cpu.cp38-win_amd64.pyd +0 -0
  84. vispy/visuals/text/_sdf_cpu.pyx +21 -23
  85. vispy/visuals/text/text.py +9 -3
  86. vispy/visuals/tube.py +2 -2
  87. vispy/visuals/visual.py +144 -3
  88. vispy/visuals/volume.py +300 -131
  89. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/LICENSE.txt +1 -1
  90. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/METADATA +218 -198
  91. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/RECORD +93 -96
  92. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/WHEEL +1 -1
  93. vispy/glsl/antialias/__init__.py +0 -0
  94. vispy/glsl/arrowheads/__init__.py +0 -0
  95. vispy/glsl/arrows/__init__.py +0 -0
  96. vispy/glsl/collections/__init__.py +0 -0
  97. vispy/glsl/colormaps/__init__.py +0 -0
  98. vispy/glsl/lines/__init__.py +0 -0
  99. vispy/glsl/markers/__init__.py +0 -0
  100. vispy/glsl/math/__init__.py +0 -0
  101. vispy/glsl/misc/__init__.py +0 -0
  102. vispy/glsl/transforms/__init__.py +0 -0
  103. {vispy-0.9.5.dist-info → vispy-0.14.0.dist-info}/top_level.txt +0 -0
vispy/visuals/markers.py CHANGED
@@ -5,14 +5,13 @@
5
5
  # -----------------------------------------------------------------------------
6
6
  """Marker Visual and shader definitions."""
7
7
 
8
- import warnings
9
-
10
8
  import numpy as np
11
9
 
12
10
  from ..color import ColorArray
13
- from ..gloo import VertexBuffer, _check_valid
11
+ from ..gloo import VertexBuffer
14
12
  from .shaders import Function, Variable
15
13
  from .visual import Visual
14
+ from ..util.event import Event
16
15
 
17
16
 
18
17
  _VERTEX_SHADER = """
@@ -26,34 +25,46 @@ attribute vec4 a_fg_color;
26
25
  attribute vec4 a_bg_color;
27
26
  attribute float a_edgewidth;
28
27
  attribute float a_size;
28
+ attribute float a_symbol;
29
29
 
30
30
  varying vec4 v_fg_color;
31
31
  varying vec4 v_bg_color;
32
32
  varying float v_edgewidth;
33
33
  varying float v_depth_middle;
34
34
  varying float v_alias_ratio;
35
+ varying float v_symbol;
35
36
 
36
37
  float big_float = 1e10; // prevents numerical imprecision
37
38
 
38
39
  void main (void) {
39
40
  v_fg_color = a_fg_color;
40
41
  v_bg_color = a_bg_color;
42
+ // fluctuations can mess "fake integers" up, so we do +0.5 and floor to make sure it's right
43
+ v_symbol = a_symbol + 0.5;
41
44
 
42
45
  vec4 pos = vec4(a_position, 1);
43
46
  vec4 fb_pos = $visual_to_framebuffer(pos);
47
+ vec4 x;
48
+ vec4 size_vec;
44
49
  gl_Position = $framebuffer_to_render(fb_pos);
45
50
 
46
51
  // NOTE: gl_stuff uses framebuffer coords!
47
-
48
- if (u_scaling == true) {
49
- // calculate point size from visual to framebuffer coords to determine size
50
- vec4 x = $framebuffer_to_visual(fb_pos + vec4(big_float, 0, 0, 0));
52
+ if (u_scaling) {
53
+ // scaling == "scene": scale marker using entire visual -> framebuffer set of transforms
54
+ // scaling == "visual": scale marker using only the Visual's transform
55
+ pos = $framebuffer_to_scene_or_visual(fb_pos);
56
+ x = $framebuffer_to_scene_or_visual(fb_pos + vec4(big_float, 0, 0, 0));
51
57
  x = (x - pos);
52
- vec4 size_vec = $visual_to_framebuffer(pos + normalize(x) * a_size);
58
+ // multiply that direction by the size and add it to the position
59
+ // this gives us the position of the edge of the point, which we convert in screen space
60
+ size_vec = $scene_or_visual_to_framebuffer(pos + normalize(x) * a_size);
61
+ // divide by `w` for perspective, and subtract pos
62
+ // this gives us the actual screen-space size of the point
53
63
  $v_size = size_vec.x / size_vec.w - fb_pos.x / fb_pos.w;
54
64
  v_edgewidth = ($v_size / a_size) * a_edgewidth;
55
65
  }
56
66
  else {
67
+ // scaling == "fixed": marker is always the same number of pixels
57
68
  $v_size = a_size * u_px_scale;
58
69
  v_edgewidth = a_edgewidth * u_px_scale;
59
70
  }
@@ -62,12 +73,13 @@ void main (void) {
62
73
  gl_PointSize = $v_size + 4. * (v_edgewidth + 1.5 * u_antialias);
63
74
 
64
75
  if (u_spherical == true) {
76
+ // similar as above for scaling, but in towards the screen direction
65
77
  // Get the framebuffer z direction relative to this sphere in visual coords
66
- vec4 z = $framebuffer_to_visual(fb_pos + vec4(0, 0, big_float, 0));
78
+ vec4 z = $framebuffer_to_scene_or_visual(fb_pos + vec4(0, 0, big_float, 0));
67
79
  z = (z - pos);
68
80
  // Get the depth of the sphere in its middle point on the screen
69
81
  // size/2 because we need the radius, not the diameter
70
- vec4 depth_z_vec = $visual_to_framebuffer(pos + normalize(z) * a_size / 2);
82
+ vec4 depth_z_vec = $scene_or_visual_to_framebuffer(pos + normalize(z) * a_size / 2);
71
83
  v_depth_middle = depth_z_vec.z / depth_z_vec.w - fb_pos.z / fb_pos.w;
72
84
  // size ratio between aliased and non-aliased, needed for correct depth
73
85
  v_alias_ratio = gl_PointSize / $v_size;
@@ -89,6 +101,7 @@ varying vec4 v_bg_color;
89
101
  varying float v_edgewidth;
90
102
  varying float v_depth_middle;
91
103
  varying float v_alias_ratio;
104
+ varying float v_symbol;
92
105
 
93
106
  void main()
94
107
  {
@@ -102,7 +115,7 @@ void main()
102
115
  // factor 6 for acute edge angles that need room as for star marker
103
116
 
104
117
  // The marker function needs to be linked with this shader
105
- float r = $marker(gl_PointCoord, size);
118
+ float r = $marker(gl_PointCoord, size, int(v_symbol));
106
119
 
107
120
  // it takes into account an antialising layer
108
121
  // of size u_antialias inside the edge
@@ -198,351 +211,280 @@ void main()
198
211
  """
199
212
 
200
213
  disc = """
201
- float disc(vec2 pointcoord, float size)
202
- {
203
- float r = length((pointcoord.xy - vec2(0.5,0.5))*size);
204
- r -= $v_size/2.;
205
- return r;
206
- }
214
+ float r = length((pointcoord.xy - vec2(0.5,0.5))*size);
215
+ r -= $v_size/2.;
216
+ return r;
207
217
  """
208
218
 
209
219
 
210
220
  arrow = """
211
221
  const float sqrt2 = sqrt(2.);
212
- float rect(vec2 pointcoord, float size)
213
- {
214
- float half_size = $v_size/2.;
215
- float ady = abs(pointcoord.y -.5)*size;
216
- float dx = (pointcoord.x -.5)*size;
217
- float r1 = abs(dx) + ady - half_size;
218
- float r2 = dx + 0.25*$v_size + ady - half_size;
219
- float r = max(r1,-r2);
220
- return r/sqrt2;//account for slanted edge and correct for width
221
- }
222
+ float half_size = $v_size/2.;
223
+ float ady = abs(pointcoord.y -.5)*size;
224
+ float dx = (pointcoord.x -.5)*size;
225
+ float r1 = abs(dx) + ady - half_size;
226
+ float r2 = dx + 0.25*$v_size + ady - half_size;
227
+ float r = max(r1,-r2);
228
+ return r/sqrt2;//account for slanted edge and correct for width
222
229
  """
223
230
 
224
231
 
225
232
  ring = """
226
- float ring(vec2 pointcoord, float size)
227
- {
228
- float r1 = length((pointcoord.xy - vec2(0.5,0.5))*size) - $v_size/2.;
229
- float r2 = length((pointcoord.xy - vec2(0.5,0.5))*size) - $v_size/4.;
230
- float r = max(r1,-r2);
231
- return r;
232
- }
233
+ float r1 = length((pointcoord.xy - vec2(0.5,0.5))*size) - $v_size/2.;
234
+ float r2 = length((pointcoord.xy - vec2(0.5,0.5))*size) - $v_size/4.;
235
+ float r = max(r1,-r2);
236
+ return r;
233
237
  """
234
238
 
235
239
  clobber = """
236
240
  const float sqrt3 = sqrt(3.);
237
- float clobber(vec2 pointcoord, float size)
238
- {
239
- const float PI = 3.14159265358979323846264;
240
- const float t1 = -PI/2;
241
- float circle_radius = 0.32 * $v_size;
242
- float center_shift = 0.36/sqrt3 * $v_size;
243
- //total size (horizontal) = 2*circle_radius + sqrt3*center_shirt = $v_size
244
- vec2 c1 = vec2(cos(t1),sin(t1))*center_shift;
245
- const float t2 = t1+2*PI/3;
246
- vec2 c2 = vec2(cos(t2),sin(t2))*center_shift;
247
- const float t3 = t2+2*PI/3;
248
- vec2 c3 = vec2(cos(t3),sin(t3))*center_shift;
249
- //xy is shift to center marker vertically
250
- vec2 xy = (pointcoord.xy-vec2(0.5,0.5))*size + vec2(0.,-0.25*center_shift);
251
- float r1 = length(xy - c1) - circle_radius;
252
- float r2 = length(xy - c2) - circle_radius;
253
- float r3 = length(xy - c3) - circle_radius;
254
- float r = min(min(r1,r2),r3);
255
- return r;
256
- }
241
+ const float PI = 3.14159265358979323846264;
242
+ const float t1 = -PI/2;
243
+ float circle_radius = 0.32 * $v_size;
244
+ float center_shift = 0.36/sqrt3 * $v_size;
245
+ //total size (horizontal) = 2*circle_radius + sqrt3*center_shirt = $v_size
246
+ vec2 c1 = vec2(cos(t1),sin(t1))*center_shift;
247
+ const float t2 = t1+2*PI/3;
248
+ vec2 c2 = vec2(cos(t2),sin(t2))*center_shift;
249
+ const float t3 = t2+2*PI/3;
250
+ vec2 c3 = vec2(cos(t3),sin(t3))*center_shift;
251
+ //xy is shift to center marker vertically
252
+ vec2 xy = (pointcoord.xy-vec2(0.5,0.5))*size + vec2(0.,-0.25*center_shift);
253
+ float r1 = length(xy - c1) - circle_radius;
254
+ float r2 = length(xy - c2) - circle_radius;
255
+ float r3 = length(xy - c3) - circle_radius;
256
+ float r = min(min(r1,r2),r3);
257
+ return r;
257
258
  """
258
259
 
259
260
 
260
261
  square = """
261
- float square(vec2 pointcoord, float size)
262
- {
263
- float r = max(abs(pointcoord.x -.5)*size, abs(pointcoord.y -.5)*size);
264
- r -= $v_size/2.;
265
- return r;
266
- }
262
+ float r = max(abs(pointcoord.x -.5)*size, abs(pointcoord.y -.5)*size);
263
+ r -= $v_size/2.;
264
+ return r;
267
265
  """
268
266
 
269
- x_ = """
270
- float x_(vec2 pointcoord, float size)
271
- {
272
- vec2 rotcoord = vec2((pointcoord.x + pointcoord.y - 1.) / sqrt(2.),
273
- (pointcoord.y - pointcoord.x) / sqrt(2.));
274
- //vbar
275
- float r1 = abs(rotcoord.x)*size - $v_size/6.;
276
- float r2 = abs(rotcoord.y)*size - $v_size/2.;
277
- float vbar = max(r1,r2);
278
- //hbar
279
- float r3 = abs(rotcoord.y)*size - $v_size/6.;
280
- float r4 = abs(rotcoord.x)*size - $v_size/2.;
281
- float hbar = max(r3,r4);
282
- return min(vbar, hbar);
283
- }
267
+ x = """
268
+ vec2 rotcoord = vec2((pointcoord.x + pointcoord.y - 1.) / sqrt(2.),
269
+ (pointcoord.y - pointcoord.x) / sqrt(2.));
270
+ //vbar
271
+ float r1 = abs(rotcoord.x)*size - $v_size/6.;
272
+ float r2 = abs(rotcoord.y)*size - $v_size/2.;
273
+ float vbar = max(r1,r2);
274
+ //hbar
275
+ float r3 = abs(rotcoord.y)*size - $v_size/6.;
276
+ float r4 = abs(rotcoord.x)*size - $v_size/2.;
277
+ float hbar = max(r3,r4);
278
+ return min(vbar, hbar);
284
279
  """
285
280
 
286
281
 
287
282
  diamond = """
288
- float diamond(vec2 pointcoord, float size)
289
- {
290
- float r = abs(pointcoord.x -.5)*size + abs(pointcoord.y -.5)*size;
291
- r -= $v_size/2.;
292
- return r / sqrt(2.);//account for slanted edge and correct for width
293
- }
283
+ float r = abs(pointcoord.x -.5)*size + abs(pointcoord.y -.5)*size;
284
+ r -= $v_size/2.;
285
+ return r / sqrt(2.);//account for slanted edge and correct for width
294
286
  """
295
287
 
296
288
 
297
289
  vbar = """
298
- float vbar(vec2 pointcoord, float size)
299
- {
300
- float r1 = abs(pointcoord.x - 0.5)*size - $v_size/6.;
301
- float r3 = abs(pointcoord.y - 0.5)*size - $v_size/2.;
302
- float r = max(r1,r3);
303
- return r;
304
- }
290
+ float r1 = abs(pointcoord.x - 0.5)*size - $v_size/6.;
291
+ float r3 = abs(pointcoord.y - 0.5)*size - $v_size/2.;
292
+ float r = max(r1,r3);
293
+ return r;
305
294
  """
306
295
 
307
296
  hbar = """
308
- float rect(vec2 pointcoord, float size)
309
- {
310
- float r2 = abs(pointcoord.y - 0.5)*size - $v_size/6.;
311
- float r3 = abs(pointcoord.x - 0.5)*size - $v_size/2.;
312
- float r = max(r2,r3);
313
- return r;
314
- }
297
+ float r2 = abs(pointcoord.y - 0.5)*size - $v_size/6.;
298
+ float r3 = abs(pointcoord.x - 0.5)*size - $v_size/2.;
299
+ float r = max(r2,r3);
300
+ return r;
315
301
  """
316
302
 
317
303
  cross = """
318
- float cross(vec2 pointcoord, float size)
319
- {
320
- //vbar
321
- float r1 = abs(pointcoord.x - 0.5)*size - $v_size/6.;
322
- float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2.;
323
- float vbar = max(r1,r2);
324
- //hbar
325
- float r3 = abs(pointcoord.y - 0.5)*size - $v_size/6.;
326
- float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2.;
327
- float hbar = max(r3,r4);
328
- return min(vbar, hbar);
329
- }
304
+ //vbar
305
+ float r1 = abs(pointcoord.x - 0.5)*size - $v_size/6.;
306
+ float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2.;
307
+ float vbar = max(r1,r2);
308
+ //hbar
309
+ float r3 = abs(pointcoord.y - 0.5)*size - $v_size/6.;
310
+ float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2.;
311
+ float hbar = max(r3,r4);
312
+ return min(vbar, hbar);
330
313
  """
331
314
 
332
315
 
333
316
  tailed_arrow = """
334
317
  const float sqrt2 = sqrt(2.);
335
- float rect(vec2 pointcoord, float size)
318
+ float half_size = $v_size/2.;
319
+ float ady = abs(pointcoord.y -.5)*size;
320
+ float dx = (pointcoord.x -.5)*size;
321
+ float r1 = abs(dx) + ady - half_size;
322
+ float r2 = dx + 0.25*$v_size + ady - half_size;
323
+ float arrow = max(r1,-r2);
324
+ //hbar
325
+ float upper_bottom_edges = ady - $v_size/8./sqrt2;
326
+ float left_edge = -dx - half_size;
327
+ float right_edge = dx + ady - half_size;
328
+ float hbar = max(upper_bottom_edges, left_edge);
329
+ float scale = 1.; //rescaling for slanted edge
330
+ if (right_edge >= hbar)
336
331
  {
337
- float half_size = $v_size/2.;
338
- float ady = abs(pointcoord.y -.5)*size;
339
- float dx = (pointcoord.x -.5)*size;
340
- float r1 = abs(dx) + ady - half_size;
341
- float r2 = dx + 0.25*$v_size + ady - half_size;
342
- float arrow = max(r1,-r2);
343
- //hbar
344
- float upper_bottom_edges = ady - $v_size/8./sqrt2;
345
- float left_edge = -dx - half_size;
346
- float right_edge = dx + ady - half_size;
347
- float hbar = max(upper_bottom_edges, left_edge);
348
- float scale = 1.; //rescaling for slanted edge
349
- if (right_edge >= hbar)
350
- {
351
- hbar = right_edge;
352
- scale = sqrt2;
353
- }
354
- if (arrow <= hbar)
355
- {
356
- return arrow / sqrt2;//account for slanted edge and correct for width
357
- }
358
- else
359
- {
360
- return hbar / scale;
361
- }
332
+ hbar = right_edge;
333
+ scale = sqrt2;
334
+ }
335
+ if (arrow <= hbar)
336
+ {
337
+ return arrow / sqrt2;//account for slanted edge and correct for width
338
+ }
339
+ else
340
+ {
341
+ return hbar / scale;
362
342
  }
363
343
  """
364
344
 
365
345
 
366
346
  triangle_up = """
367
- float rect(vec2 pointcoord, float size)
368
- {
369
- float height = $v_size*sqrt(3.)/2.;
370
- float bottom = ((pointcoord.y - 0.5)*size - height/2.);
371
- float rotated_y = sqrt(3.)/2. * (pointcoord.x - 0.5) * size
372
- - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
373
- float right_edge = (rotated_y - height/2.);
374
- float cc_rotated_y = -sqrt(3.)/2. * (pointcoord.x - 0.5)*size
375
- - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
376
- float left_edge = (cc_rotated_y - height/2.);
377
- float slanted_edges = max(right_edge, left_edge);
378
- return max(slanted_edges, bottom);
379
- }
347
+ float height = $v_size*sqrt(3.)/2.;
348
+ float bottom = ((pointcoord.y - 0.5)*size - height/2.);
349
+ float rotated_y = sqrt(3.)/2. * (pointcoord.x - 0.5) * size
350
+ - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
351
+ float right_edge = (rotated_y - height/2.);
352
+ float cc_rotated_y = -sqrt(3.)/2. * (pointcoord.x - 0.5)*size
353
+ - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
354
+ float left_edge = (cc_rotated_y - height/2.);
355
+ float slanted_edges = max(right_edge, left_edge);
356
+ return max(slanted_edges, bottom);
380
357
  """
381
358
 
382
359
  triangle_down = """
383
- float rect(vec2 pointcoord, float size)
384
- {
385
- float height = -$v_size*sqrt(3.)/2.;
386
- float bottom = -((pointcoord.y - 0.5)*size - height/2.);
387
- float rotated_y = sqrt(3.)/2. * (pointcoord.x - 0.5) * size
388
- - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
389
- float right_edge = -(rotated_y - height/2.);
390
- float cc_rotated_y = -sqrt(3.)/2. * (pointcoord.x - 0.5)*size
391
- - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
392
- float left_edge = -(cc_rotated_y - height/2.);
393
- float slanted_edges = max(right_edge, left_edge);
394
- return max(slanted_edges, bottom);
395
- }
360
+ float height = -$v_size*sqrt(3.)/2.;
361
+ float bottom = -((pointcoord.y - 0.5)*size - height/2.);
362
+ float rotated_y = sqrt(3.)/2. * (pointcoord.x - 0.5) * size
363
+ - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
364
+ float right_edge = -(rotated_y - height/2.);
365
+ float cc_rotated_y = -sqrt(3.)/2. * (pointcoord.x - 0.5)*size
366
+ - 0.5 * ((pointcoord.y - 0.5)*size - height/6.) + height/6.;
367
+ float left_edge = -(cc_rotated_y - height/2.);
368
+ float slanted_edges = max(right_edge, left_edge);
369
+ return max(slanted_edges, bottom);
396
370
  """
397
371
 
398
372
 
399
373
  star = """
400
- float rect(vec2 pointcoord, float size)
374
+ float star = -10000.;
375
+ const float PI2_5 = 3.141592653589*2./5.;
376
+ const float PI2_20 = 3.141592653589/10.; //PI*2/20
377
+ // downwards shift to that the marker center is halfway vertically
378
+ // between the top of the upward spike (y = -v_size/2.)
379
+ // and the bottom of one of two downward spikes
380
+ // (y = +v_size/2.*cos(2.*pi/10.) approx +v_size/2.*0.8)
381
+ // center is at -v_size/2.*0.1
382
+ float shift_y = -0.05*$v_size;
383
+ // first spike upwards,
384
+ // rotate spike by 72 deg four times to complete the star
385
+ for (int i = 0; i <= 4; i++)
401
386
  {
402
- float star = -10000.;
403
- const float PI2_5 = 3.141592653589*2./5.;
404
- const float PI2_20 = 3.141592653589/10.; //PI*2/20
405
- // downwards shift to that the marker center is halfway vertically
406
- // between the top of the upward spike (y = -v_size/2.)
407
- // and the bottom of one of two downward spikes
408
- // (y = +v_size/2.*cos(2.*pi/10.) approx +v_size/2.*0.8)
409
- // center is at -v_size/2.*0.1
410
- float shift_y = -0.05*$v_size;
411
- // first spike upwards,
412
- // rotate spike by 72 deg four times to complete the star
413
- for (int i = 0; i <= 4; i++)
414
- {
415
- //if not the first spike, rotate it upwards
416
- float x = (pointcoord.x - 0.5)*size;
417
- float y = (pointcoord.y - 0.5)*size;
418
- float spike_rot_angle = float(i) * PI2_5;
419
- float cosangle = cos(spike_rot_angle);
420
- float sinangle = sin(spike_rot_angle);
421
- float spike_x = x;
422
- float spike_y = y + shift_y;
423
- if (i > 0)
424
- {
425
- spike_x = cosangle * x - sinangle * (y + shift_y);
426
- spike_y = sinangle * x + cosangle * (y + shift_y);
427
- }
428
- // in the frame where the spike is upwards:
429
- // rotate 18 deg the zone x < 0 around the top of the star
430
- // (point whose coords are -s/2, 0 where s is the size of the marker)
431
- // compute y coordonates as well because
432
- // we do a second rotation to put the spike at its final position
433
- float rot_center_y = -$v_size/2.;
434
- float rot18x = cos(PI2_20) * spike_x
435
- - sin(PI2_20) * (spike_y - rot_center_y);
436
- //rotate -18 deg the zone x > 0 arount the top of the star
437
- float rot_18x = cos(PI2_20) * spike_x
438
- + sin(PI2_20) * (spike_y - rot_center_y);
439
- float bottom = spike_y - $v_size/10.;
440
- // max(left edge, right edge)
441
- float spike = max(bottom, max(rot18x, -rot_18x));
442
- if (i == 0)
443
- {// first spike, skip the rotation
444
- star = spike;
445
- }
446
- else // i > 0
447
- {
448
- star = min(star, spike);
449
- }
450
- }
451
- return star;
452
- }
453
- """
454
-
455
- # the following two markers needs x and y sizes
456
- rect = """
457
- float rect(vec2 pointcoord, float size)
387
+ //if not the first spike, rotate it upwards
388
+ float x = (pointcoord.x - 0.5)*size;
389
+ float y = (pointcoord.y - 0.5)*size;
390
+ float spike_rot_angle = float(i) * PI2_5;
391
+ float cosangle = cos(spike_rot_angle);
392
+ float sinangle = sin(spike_rot_angle);
393
+ float spike_x = x;
394
+ float spike_y = y + shift_y;
395
+ if (i > 0)
458
396
  {
459
- float x_boundaries = abs(pointcoord.x - 0.5)*size - $v_size.x/2.;
460
- float y_boundaries = abs(pointcoord.y - 0.5)*size - $v_size.y/2.;
461
- return max(x_boundaries, y_boundaries);
397
+ spike_x = cosangle * x - sinangle * (y + shift_y);
398
+ spike_y = sinangle * x + cosangle * (y + shift_y);
462
399
  }
463
- """
464
-
465
- ellipse = """
466
- float rect(vec2 pointcoord, float size)
400
+ // in the frame where the spike is upwards:
401
+ // rotate 18 deg the zone x < 0 around the top of the star
402
+ // (point whose coords are -s/2, 0 where s is the size of the marker)
403
+ // compute y coordonates as well because
404
+ // we do a second rotation to put the spike at its final position
405
+ float rot_center_y = -$v_size/2.;
406
+ float rot18x = cos(PI2_20) * spike_x
407
+ - sin(PI2_20) * (spike_y - rot_center_y);
408
+ //rotate -18 deg the zone x > 0 arount the top of the star
409
+ float rot_18x = cos(PI2_20) * spike_x
410
+ + sin(PI2_20) * (spike_y - rot_center_y);
411
+ float bottom = spike_y - $v_size/10.;
412
+ // max(left edge, right edge)
413
+ float spike = max(bottom, max(rot18x, -rot_18x));
414
+ if (i == 0)
415
+ {// first spike, skip the rotation
416
+ star = spike;
417
+ }
418
+ else // i > 0
467
419
  {
468
- float x = (pointcoord.x - 0.5)*size;
469
- float y = (pointcoord.y - 0.5)*size;
470
- // normalise radial distance (for edge and antialising to remain isotropic)
471
- // Scaling factor is the norm of the gradient of the function defining
472
- // the surface taken at a well chosen point on the edge of the ellipse
473
- // f(x, y) = (sqrt(x^2/a^2 + y^2/b^2) = 0.5 in this case
474
- // where a = v_size.x and b = v_size.y)
475
- // The well chosen point on the edge of the ellipse should be the point
476
- // whose normal points towards the current point.
477
- // Below we choose a different point whose computation
478
- // is simple enough to fit here.
479
- float f = length(vec2(x / $v_size.x, y / $v_size.y));
480
- // We set the default value of the norm so that
481
- // - near the axes (x=0 or y=0 +/- 1 pixel), the norm is correct
482
- // (the computation below is unstable near the axes)
483
- // - if the ellipse is a circle, the norm is correct
484
- // - if we are deep in the interior of the ellipse the norm
485
- // is set to an arbitrary value (but is not used)
486
- float norm = abs(x) < 1. ? 1./$v_size.y : 1./$v_size.x;
487
- if (f > 1e-3 && abs($v_size.x - $v_size.y) > 1e-3
488
- && abs(x) > 1. && abs(y) > 1.)
489
- {
490
- // Find the point x0, y0 on the ellipse which has the same hyperbola
491
- // coordinate in the elliptic coordinate system linked to the ellipse
492
- // (finding the right 'well chosen' point is too complicated)
493
- // Visually it's nice, even at high eccentricities, where
494
- // the approximation is visible but not ugly.
495
- float a = $v_size.x/2.;
496
- float b = $v_size.y/2.;
497
- float C = max(a, b);
498
- float c = min(a, b);
499
- float focal_length = sqrt(C*C - c*c);
500
- float fl2 = focal_length*focal_length;
501
- float x2 = x*x;
502
- float y2 = y*y;
503
- float tmp = fl2 + x2 + y2;
504
- float x0 = 0;
505
- float y0 = 0;
506
- if ($v_size.x > $v_size.y)
507
- {
508
- float cos2v = 0.5 * (tmp - sqrt(tmp*tmp - 4.*fl2*x2)) / fl2;
509
- cos2v = fract(cos2v);
510
- x0 = a * sqrt(cos2v);
511
- // v_size.x = focal_length*cosh m where m is the ellipse coordinate
512
- y0 = b * sqrt(1-cos2v);
513
- // v_size.y = focal_length*sinh m
514
- }
515
- else // $v_size.x < $v_size.y
516
- {//exchange x and y axis for elliptic coordinate
517
- float cos2v = 0.5 * (tmp - sqrt(tmp*tmp - 4.*fl2*y2)) / fl2;
518
- cos2v = fract(cos2v);
519
- x0 = a * sqrt(1-cos2v);
520
- // v_size.x = focal_length*sinh m where m is the ellipse coordinate
521
- y0 = b * sqrt(cos2v);
522
- // v_size.y = focal_length*cosh m
523
- }
524
- vec2 normal = vec2(2.*x0/v_size.x/v_size.x, 2.*y0/v_size.y/v_size.y);
525
- norm = length(normal);
526
- }
527
- return (f - 0.5) / norm;
420
+ star = min(star, spike);
421
+ }
528
422
  }
423
+ return star;
529
424
  """
530
425
 
531
426
  cross_lines = """
532
- float cross(vec2 pointcoord, float size)
533
- {
534
- //vbar
535
- float r1 = abs(pointcoord.x - 0.5)*size;
536
- float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2;
537
- float vbar = max(r1,r2);
538
- //hbar
539
- float r3 = abs(pointcoord.y - 0.5)*size;
540
- float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2;
541
- float hbar = max(r3,r4);
542
- return min(vbar, hbar);
543
- }
427
+ //vbar
428
+ float r1 = abs(pointcoord.x - 0.5)*size;
429
+ float r2 = abs(pointcoord.y - 0.5)*size - $v_size/2;
430
+ float vbar = max(r1,r2);
431
+ //hbar
432
+ float r3 = abs(pointcoord.y - 0.5)*size;
433
+ float r4 = abs(pointcoord.x - 0.5)*size - $v_size/2;
434
+ float hbar = max(r3,r4);
435
+ return min(vbar, hbar);
544
436
  """
545
437
 
438
+ symbol_shaders = {
439
+ 'disc': disc,
440
+ 'arrow': arrow,
441
+ 'ring': ring,
442
+ 'clobber': clobber,
443
+ 'square': square,
444
+ 'x': x,
445
+ 'diamond': diamond,
446
+ 'vbar': vbar,
447
+ 'hbar': hbar,
448
+ 'cross': cross,
449
+ 'tailed_arrow': tailed_arrow,
450
+ 'triangle_up': triangle_up,
451
+ 'triangle_down': triangle_down,
452
+ 'star': star,
453
+ 'cross_lines': cross_lines,
454
+ }
455
+
456
+ # combine all the symbol shaders in a big if-else statement
457
+ symbol_func = f"""
458
+ float symbol(vec2 pointcoord, float size, int symbol) {{
459
+ {' else'.join(
460
+ f''' if (symbol == {i}) {{
461
+ // {name}
462
+ {shader}
463
+ }}'''
464
+ for i, (name, shader) in enumerate(symbol_shaders.items())
465
+ )}
466
+ }}"""
467
+
468
+ # aliases
469
+ symbol_aliases = {
470
+ 'o': 'disc',
471
+ '+': 'cross',
472
+ '++': 'cross_lines',
473
+ 's': 'square',
474
+ '-': 'hbar',
475
+ '|': 'vbar',
476
+ '->': 'tailed_arrow',
477
+ '>': 'arrow',
478
+ '^': 'triangle_up',
479
+ 'v': 'triangle_down',
480
+ '*': 'star',
481
+ }
482
+
483
+ symbol_shader_values = {name: i for i, name in enumerate(symbol_shaders)}
484
+ symbol_shader_values.update({
485
+ **{alias: symbol_shader_values[name] for alias, name in symbol_aliases.items()},
486
+ })
487
+
546
488
 
547
489
  class MarkersVisual(Visual):
548
490
  """Visual displaying marker symbols.
@@ -562,10 +504,22 @@ class MarkersVisual(Visual):
562
504
  The color used to draw each symbol outline.
563
505
  face_color : Color | ColorArray
564
506
  The color used to draw each symbol interior.
565
- symbol : str
566
- The style of symbol to draw (see Notes).
567
- scaling : bool
568
- If set to True, marker scales when rezooming.
507
+ symbol : str or array
508
+ The style of symbol used to draw each marker (see Notes).
509
+ scaling : str | bool
510
+ Scaling method of individual markers. If set to "fixed" (default) then
511
+ no scaling is done and markers will always be the same number of
512
+ pixels on the screen. If set to "scene" then the chain of transforms
513
+ from the Visual's transform to the transform mapping to the OpenGL
514
+ framebuffer are used to scaling the marker. This has the effect of the
515
+ marker staying the same size in the "scene" coordinate space and
516
+ changing size as the visualization is zoomed in and out. If set to
517
+ "visual" the marker is scaled only using the transform of the Visual
518
+ and not the rest of the scene/camera. This means that something like
519
+ a camera changing the view will not affect the size of the marker, but
520
+ the user can still scale it using the Visual's transform. For
521
+ backwards compatibility this can be set to the boolean ``False`` for
522
+ "fixed" or ``True`` for "scene".
569
523
  alpha : float
570
524
  The opacity level of the visual.
571
525
  antialias : float
@@ -585,60 +539,37 @@ class MarkersVisual(Visual):
585
539
  vbar, hbar, cross, tailed_arrow, x, triangle_up, triangle_down,
586
540
  and star.
587
541
  """
588
- _marker_funcs = {
589
- 'disc': disc,
590
- 'arrow': arrow,
591
- 'ring': ring,
592
- 'clobber': clobber,
593
- 'square': square,
594
- 'diamond': diamond,
595
- 'vbar': vbar,
596
- 'hbar': hbar,
597
- 'cross': cross,
598
- 'tailed_arrow': tailed_arrow,
599
- 'x': x_,
600
- 'triangle_up': triangle_up,
601
- 'triangle_down': triangle_down,
602
- 'star': star,
603
- # aliases
604
- 'o': disc,
605
- '+': cross,
606
- '++': cross_lines,
607
- 's': square,
608
- '-': hbar,
609
- '|': vbar,
610
- '->': tailed_arrow,
611
- '>': arrow,
612
- '^': triangle_up,
613
- 'v': triangle_down,
614
- '*': star,
615
- }
616
542
 
617
543
  _shaders = {
618
544
  'vertex': _VERTEX_SHADER,
619
545
  'fragment': _FRAGMENT_SHADER,
620
546
  }
547
+ _symbol_shader_values = symbol_shader_values
548
+ _symbol_shader = symbol_func
621
549
 
622
- def __init__(self, symbol='o', scaling=False, alpha=1, antialias=1, spherical=False,
550
+ def __init__(self, scaling="fixed", alpha=1, antialias=1, spherical=False,
623
551
  light_color='white', light_position=(1, -1, 1), light_ambient=0.3, **kwargs):
624
552
  self._vbo = VertexBuffer()
625
- self._marker_fun = None
626
- self._symbol = None
627
553
  self._data = None
554
+ self._scaling = "fixed"
628
555
 
629
556
  Visual.__init__(self, vcode=self._shaders['vertex'], fcode=self._shaders['fragment'])
557
+ self._symbol_func = Function(self._symbol_shader)
558
+ self.shared_program.frag['marker'] = self._symbol_func
630
559
  self._v_size_var = Variable('varying float v_size')
631
560
  self.shared_program.vert['v_size'] = self._v_size_var
632
561
  self.shared_program.frag['v_size'] = self._v_size_var
562
+ self._symbol_func['v_size'] = self._v_size_var
633
563
 
634
564
  self.set_gl_state(depth_test=True, blend=True,
635
565
  blend_func=('src_alpha', 'one_minus_src_alpha'))
636
566
  self._draw_mode = 'points'
637
567
 
568
+ self.events.add(data_updated=Event)
569
+
638
570
  if len(kwargs) > 0:
639
571
  self.set_data(**kwargs)
640
572
 
641
- self.symbol = symbol
642
573
  self.scaling = scaling
643
574
  self.antialias = antialias
644
575
  self.light_color = light_color
@@ -651,7 +582,7 @@ class MarkersVisual(Visual):
651
582
 
652
583
  def set_data(self, pos=None, size=10., edge_width=1., edge_width_rel=None,
653
584
  edge_color='black', face_color='white',
654
- symbol=None, scaling=None):
585
+ symbol='o'):
655
586
  """Set the data used to display this visual.
656
587
 
657
588
  Parameters
@@ -669,6 +600,8 @@ class MarkersVisual(Visual):
669
600
  The color used to draw each symbol outline.
670
601
  face_color : Color | ColorArray
671
602
  The color used to draw each symbol interior.
603
+ symbol : str or array
604
+ The style of symbol used to draw each marker (see Notes).
672
605
  """
673
606
  if (edge_width is not None) + (edge_width_rel is not None) != 1:
674
607
  raise ValueError('exactly one of edge_width and edge_width_rel '
@@ -683,21 +616,9 @@ class MarkersVisual(Visual):
683
616
  if np.any(edge_width_rel < 0):
684
617
  raise ValueError('edge_width_rel cannot be negative')
685
618
 
686
- if scaling is not None:
687
- warnings.warn(
688
- "The scaling parameter is deprecated. Use MarkersVisual.scaling instead",
689
- DeprecationWarning,
690
- stacklevel=2,
691
- )
692
- self.scaling = scaling
693
-
694
619
  if symbol is not None:
695
- warnings.warn(
696
- "The symbol parameter is deprecated. Use MarkersVisual.symbol instead",
697
- DeprecationWarning,
698
- stacklevel=2,
699
- )
700
- self.symbol = symbol
620
+ if not np.all(np.isin(np.asarray(symbol), self.symbols)):
621
+ raise ValueError(f'symbols must one of {self.symbols}')
701
622
 
702
623
  edge_color = ColorArray(edge_color).rgba
703
624
  if len(edge_color) == 1:
@@ -716,7 +637,8 @@ class MarkersVisual(Visual):
716
637
  ('a_fg_color', np.float32, 4),
717
638
  ('a_bg_color', np.float32, 4),
718
639
  ('a_size', np.float32),
719
- ('a_edgewidth', np.float32)])
640
+ ('a_edgewidth', np.float32),
641
+ ('a_symbol', np.float32)])
720
642
  data['a_fg_color'] = edge_color
721
643
  data['a_bg_color'] = face_color
722
644
  if edge_width is not None:
@@ -725,49 +647,43 @@ class MarkersVisual(Visual):
725
647
  data['a_edgewidth'] = size * edge_width_rel
726
648
  data['a_position'][:, :pos.shape[1]] = pos
727
649
  data['a_size'] = size
650
+
651
+ data['a_symbol'] = np.vectorize(self._symbol_shader_values.get)(symbol)
652
+
728
653
  self._data = data
729
- if self._symbol is not None:
730
- # If we have no symbol set, we skip drawing (_prepare_draw
731
- # returns False). This causes the GLIR queue to not flush,
732
- # and thus the GLIR queue fills with VBO DATA commands, resulting
733
- # in a "memory leak". Thus only set the VertexBuffer data if we
734
- # are actually going to draw.
735
- self._vbo.set_data(data)
736
- self.shared_program.bind(self._vbo)
654
+ self._vbo.set_data(data)
655
+ self.shared_program.bind(self._vbo)
737
656
 
657
+ self.events.data_updated()
738
658
  self.update()
739
659
 
740
660
  @property
741
661
  def symbols(self):
742
- return list(self._marker_funcs)
662
+ return list(self._symbol_shader_values)
743
663
 
744
664
  @property
745
665
  def symbol(self):
746
- return self._symbol
666
+ if self._data is None:
667
+ return None
668
+ value_to_symbol = {v: k for k, v in self._symbol_shader_values.items()}
669
+ return np.vectorize(value_to_symbol.get)(self._data['a_symbol'])
747
670
 
748
671
  @symbol.setter
749
- def symbol(self, symbol):
750
- if symbol == self._symbol:
751
- return
752
- if (symbol is not None and self._symbol is None and
753
- self._data is not None):
754
- # Allow user to configure symbol after a set_data call with
755
- # symbol=None. This can break down if the user does a consecutive
756
- # marker.symbol = 'disc'
757
- # marker.symbol = None
758
- # without drawing. At this point the memory leaking ensues
759
- # but this case is unlikely/makes no sense.
760
- self._vbo.set_data(self._data)
761
- self.shared_program.bind(self._vbo)
762
- self._symbol = symbol
763
- if symbol is None:
764
- self._marker_fun = None
672
+ def symbol(self, value):
673
+ if self._data is not None:
674
+ rec_to_kw = {
675
+ 'a_position': 'pos',
676
+ 'a_fg_color': 'edge_color',
677
+ 'a_bg_color': 'face_color',
678
+ 'a_size': 'size',
679
+ 'a_edgewidth': 'edge_width',
680
+ 'a_symbol': 'symbol',
681
+ }
682
+ kwargs = {kw: self._data[rec] for rec, kw in rec_to_kw.items()}
765
683
  else:
766
- _check_valid('symbol', symbol, self._marker_funcs.keys())
767
- self._marker_fun = Function(self._marker_funcs[symbol])
768
- self._marker_fun['v_size'] = self._v_size_var
769
- self.shared_program.frag['marker'] = self._marker_fun
770
- self.update()
684
+ kwargs = {}
685
+ kwargs['symbol'] = value
686
+ self.set_data(**kwargs)
771
687
 
772
688
  @property
773
689
  def scaling(self):
@@ -778,9 +694,18 @@ class MarkersVisual(Visual):
778
694
 
779
695
  @scaling.setter
780
696
  def scaling(self, value):
781
- value = bool(value)
782
- self.shared_program['u_scaling'] = value
783
- self._scaling = value
697
+ scaling_modes = {
698
+ False: "fixed",
699
+ True: "scene",
700
+ "fixed": "fixed",
701
+ "scene": "scene",
702
+ "visual": "visual",
703
+ }
704
+ if value not in scaling_modes:
705
+ possible_options = ", ".join(repr(opt) for opt in scaling_modes)
706
+ raise ValueError(f"Unknown scaling option {value!r}, expected one of: {possible_options}")
707
+ self._scaling = scaling_modes[value]
708
+ self.shared_program['u_scaling'] = self._scaling != "fixed"
784
709
  self.update()
785
710
 
786
711
  @property
@@ -865,14 +790,15 @@ class MarkersVisual(Visual):
865
790
 
866
791
  def _prepare_transforms(self, view):
867
792
  view.view_program.vert['visual_to_framebuffer'] = view.get_transform('visual', 'framebuffer')
868
- view.view_program.vert['framebuffer_to_visual'] = view.get_transform('framebuffer', 'visual')
869
793
  view.view_program.vert['framebuffer_to_render'] = view.get_transform('framebuffer', 'render')
794
+ scaling = view._scaling if view._scaling != "fixed" else "scene"
795
+ view.view_program.vert['framebuffer_to_scene_or_visual'] = view.get_transform('framebuffer', scaling)
796
+ view.view_program.vert['scene_or_visual_to_framebuffer'] = view.get_transform(scaling, 'framebuffer')
870
797
 
871
798
  def _prepare_draw(self, view):
872
- if self._data is None or self._symbol is None:
799
+ if self._data is None:
873
800
  return False
874
801
  view.view_program['u_px_scale'] = view.transforms.pixel_scale
875
- view.view_program['u_scaling'] = self.scaling
876
802
 
877
803
  def _compute_bounds(self, axis, view):
878
804
  pos = self._data['a_position']