Repository: napari/napari

Issue:
Tracks id not displaying
## 🐛 Bug

There is an [unanswered question](https://forum.image.sc/t/id-for-each-cell-in-napari-viewer-is-not-diplayed/59956) on the image.sc forum about track IDs not displaying. Indeed, when using the simple example from the docs, the IDs cannot be displayed and an error appears in the terminal which seems related to something deeper in vispy.

## To Reproduce

1. Run the demo code:
```python
import napari
from skimage import data

hubble_image = data.hubble_deep_field()

tracks_data = [
    [1, 0, 236, 0],
    [1, 1, 236, 100],
    [1, 2, 236, 200],
    [1, 3, 236, 500],
    [1, 4, 236, 1000],
    [2, 0, 436, 0],
    [2, 1, 436, 100],
    [2, 2, 436, 200],
    [2, 3, 436, 500],
    [2, 4, 436, 1000],
    [3, 0, 636, 0],
    [3, 1, 636, 100],
    [3, 2, 636, 200],
    [3, 3, 636, 500],
    [3, 4, 636, 1000]
]

viewer = napari.view_image(hubble_image, name='image')
viewer.add_tracks(tracks_data, name='tracks')
```
2. Try to activate the track IDs through the tick box. No IDs are displayed.
<img width="1059" alt="Screenshot 2021-11-16 at 11 01 42" src="https://user-images.githubusercontent.com/4622767/141964343-33fa2aad-02d3-4eea-a127-f3e117a43c68.png">

This is the error trace that appears in the terminal (but doesn't make napari crash):
```
Traceback (most recent call last):
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/app/backends/_qt.py", line 897, in paintGL
    self._vispy_canvas.events.draw(region=None)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/util/event.py", line 453, in __call__
    self._invoke_callback(cb, event)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/util/event.py", line 471, in _invoke_callback
    _handle_exception(self.ignore_callback_errors,
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/util/event.py", line 469, in _invoke_callback
    cb(event)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/scene/canvas.py", line 218, in on_draw
    self._draw_scene()
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/scene/canvas.py", line 277, in _draw_scene
    self.draw_visual(self.scene)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/scene/canvas.py", line 315, in draw_visual
    node.draw()
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/scene/visuals.py", line 99, in draw
    self._visual_superclass.draw(self)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/visuals/visual.py", line 605, in draw
    v.draw()
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/scene/visuals.py", line 99, in draw
    self._visual_superclass.draw(self)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/visuals/visual.py", line 451, in draw
    self._program.draw(self._vshare.draw_mode,
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/visuals/shaders/program.py", line 102, in draw
    Program.draw(self, *args, **kwargs)
  File "/Users/gw18g940/miniconda3/envs/napari-tutorial/lib/python3.9/site-packages/vispy/gloo/program.py", line 498, in draw
    raise RuntimeError('All attributes must have the same size, got:\n'
RuntimeError: All attributes must have the same size, got:
<VertexBuffer size=15 last_dim=1>: 15
<VertexBuffer size=48 last_dim=4>: 48
<DataBufferView on <VertexBuffer size=48 last_dim=None> at offset=0 size=48>: 48
<DataBufferView on <VertexBuffer size=48 last_dim=None> at offset=8 size=48>: 48
<VertexBuffer size=48 last_dim=1>: 48
<VertexBuffer size=48 last_dim=3>: 48
```

## Expected behavior

There's little documentation about the ```show ID``` feature (it's never used in the [documentation](https://napari.org/tutorials/fundamentals/tracks.html)) but from discussions in the PR implementing the layer, it looks like it should display the IDs.

## Environment

```
napari: 0.4.12
Platform: macOS-10.15.7-x86_64-i386-64bit
System: MacOS 10.15.7
Python: 3.9.7 (default, Sep 16 2021, 08:50:36) [Clang 10.0.0 ]
Qt: 5.15.2
PyQt5: 5.15.6
NumPy: 1.20.3
SciPy: 1.7.2
Dask: 2021.11.1
VisPy: 0.9.3

OpenGL:
- GL version: 2.1 INTEL-14.7.20
- MAX_TEXTURE_SIZE: 16384

Screens:
- screen 1: resolution 1440x900, scale 2.0

Plugins:
- cellpose-napari: 0.1.4
- console: 0.0.4
- scikit-image: 0.4.12
- svg: 0.1.5
```

## Additional context

<!-- Add any other context about the problem here. -->



Discussion:
This issue has been mentioned on **Image.sc Forum**. There might be relevant details there:

https://forum.image.sc/t/id-for-each-cell-in-napari-viewer-is-not-diplayed/59956/2

I'm also having issues with this. Did something change in a recent update?

```
WARNING: Error drawing visual <Text at 0x1553587f0>
WARNING: Error drawing visual <vispy.visuals.line.line._GLLineVisual object at 0x1552a1e80>
```
I don't have time to delve into this right now but I recommend running git-bisect on this. We did make a few updates to our text handling to fix other bugs, but it might have caused this one if it was not covered by a test.
Thanks @jni - I might try to take a look myself and see when this stopped working. In anycase, I've never used git-bisect, so I'm curious to try it!
I just had chance to try `git-bisect` on this, using  `examples/tracks_3d_with_graph.py`. The bad commit is:

```
5f1525c394606bfc5193a837f55f1c38cdcbeac7 is the first bad commit
commit 5f1525c394606bfc5193a837f55f1c38cdcbeac7
Author: Lorenzo Gaifas <brisvag@gmail.com>
Date:   Tue Sep 28 22:24:47 2021 +0200

    `_vispy` module cleanup (#3333)
```

so it looks like something got broken during the vispy module cleanup.
I think I've identified the source of the bug here (@brisvag - correct me if I'm wrong!).

In the cleanup of the _vispy module (#3333), the compound visual for the tracks layer had two separate shaders attached to the line visuals, and nothing to the text visual, whereas in the new version, a single shader is applied to all subvisuals:

https://github.com/napari/napari/blob/7d5707390e876746440e0af542982f8413ff4c5a/napari/_vispy/visuals/tracks.py#L18-L23

This is causing all of the VertexBuffer issues.
Yes, I think you're right! Actually, it seems that I wrote [a comment about this](https://github.com/napari/napari/pull/3333#issuecomment-915005470) in that PR asking about this, but got no feedback :P

If it's possible to attach the same filter to multiple visuals, we still don't need multiple filters; otherwise, we should split it out again.
Opened a PR to fix this at #3729. It seems that reusing the same filter works fine :)

Resolving patch:
diff --git a/napari/_vispy/layers/tracks.py b/napari/_vispy/layers/tracks.py
--- a/napari/_vispy/layers/tracks.py
+++ b/napari/_vispy/layers/tracks.py
@@ -37,6 +37,7 @@ def _on_data_change(self):
 
         # update the shaders
         self.node.tracks_filter.current_time = self.layer.current_time
+        self.node.graph_filter.current_time = self.layer.current_time
 
         # add text labels if they're visible
         if self.node._subvisuals[1].visible:
@@ -55,6 +56,9 @@ def _on_appearance_change(self):
         self.node.tracks_filter.use_fade = self.layer.use_fade
         self.node.tracks_filter.tail_length = self.layer.tail_length
         self.node.tracks_filter.head_length = self.layer.head_length
+        self.node.graph_filter.use_fade = self.layer.use_fade
+        self.node.graph_filter.tail_length = self.layer.tail_length
+        self.node.graph_filter.head_length = self.layer.head_length
 
         # set visibility of subvisuals
         self.node._subvisuals[0].visible = self.layer.display_tail
@@ -91,9 +95,9 @@ def _on_tracks_change(self):
     def _on_graph_change(self):
         """Update the shader when the graph data changes."""
 
-        self.node.tracks_filter.use_fade = self.layer.use_fade
-        self.node.tracks_filter.tail_length = self.layer.tail_length
-        self.node.tracks_filter.vertex_time = self.layer.track_times
+        self.node.graph_filter.use_fade = self.layer.use_fade
+        self.node.graph_filter.tail_length = self.layer.tail_length
+        self.node.graph_filter.vertex_time = self.layer.graph_times
 
         # if the user clears a graph after it has been created, vispy offers
         # no method to clear the data, therefore, we need to set private
diff --git a/napari/_vispy/visuals/tracks.py b/napari/_vispy/visuals/tracks.py
--- a/napari/_vispy/visuals/tracks.py
+++ b/napari/_vispy/visuals/tracks.py
@@ -17,10 +17,12 @@ class TracksVisual(ClippingPlanesMixin, Compound):
 
     def __init__(self):
         self.tracks_filter = TracksFilter()
+        self.graph_filter = TracksFilter()
 
         super().__init__([Line(), Text(), Line()])
 
-        self.attach(self.tracks_filter)
+        self._subvisuals[0].attach(self.tracks_filter)
+        self._subvisuals[2].attach(self.graph_filter)
 
         # text label properties
         self._subvisuals[1].color = 'white'


Test patch: