# Buggy code
def __init__(
    self,
    data,
    *,
    properties=None,
    graph=None,
    tail_width=2,
    tail_length=30,
    name=None,
    metadata=None,
    scale=None,
    translate=None,
    opacity=1,
    blending="additive",
    visible=True,
    colormap="turbo",
    color_by="track_id",
    colormaps_dict=None,
):
    # if not provided with any data, set up an empty layer in 2D+t
    if data is None:
        data = np.empty((0, 4))
    else:
        # convert data to a numpy array if it is not already one
        data = np.asarray(data)

    # in absence of properties make the default an empty dict
    if properties is None:
        properties = {}

    # set the track data dimensions (remove ID from data)
    ndim = data.shape[1] - 1

    super().__init__(
        data,
        ndim,
        name=name,
        metadata=metadata,
        scale=scale,
        translate=translate,
        opacity=opacity,
        blending=blending,
        visible=visible,
    )

    self.events.add(
        tail_width=Event,
        tail_length=Event,
        display_id=Event,
        display_tail=Event,
        display_graph=Event,
        color_by=Event,
        colormap=Event,
        properties=Event,
        rebuild_tracks=Event,
        rebuild_graph=Event,
    )

    # track manager deals with data slicing, graph building and properties
    self._manager = TrackManager()
    self._track_colors = None
    self._colormaps_dict = colormaps_dict or {}  # additional colormaps
    self._color_by = color_by  # default color by ID
    self._colormap = colormap

    # use this to update shaders when the displayed dims change
    self._current_displayed_dims = None

    # track display properties
    self.tail_width = tail_width
    self.tail_length = tail_length
    self.display_id = False
    self.display_tail = True
    self.display_graph = True

    # set the data, properties and graph
    self.data = data
    self.properties = properties
    self.graph = graph or {}

    self.color_by = color_by
    self.colormap = colormap

    self._update_dims()

    # reset the display before returning
    self._current_displayed_dims = None


# Traceback (AttributeError)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-05f52b983105> in <module>
1 v = napari.Viewer()
----> 2 v.add_tracks(tracks, name='ilastik tracks')

<string> in add_tracks(self, data, properties, graph, tail_width, tail_length, name, metadata, scale, translate, opacity, blending, visible, colormap, color_by, colormaps_dict)

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/components/add_layers_mixin.py in add_layer(self, layer)
48         layer.events.cursor_size.connect(self._update_cursor_size)
49         layer.events.data.connect(self._on_layers_change)
---> 50         self.layers.append(layer)
51         self._update_layers(layers=[layer])
52

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/utils/list/_model.py in append(self, obj)
57     def append(self, obj):
58         TypedList.append(self, obj)
---> 59         self.events.added(item=obj, index=len(self) - 1)
60
61     def pop(self, key):

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/utils/events/event.py in __call__(self, *args, **kwargs)
512                     continue
513
--> 514                 self._invoke_callback(cb, event)
515                 if event.blocked:
516                     break

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/utils/events/event.py in _invoke_callback(self, cb, event)
533                 self.print_callback_errors,
534                 self,
--> 535                 cb_event=(cb, event),
536             )
537

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/utils/events/event.py in _invoke_callback(self, cb, event)
527     def _invoke_callback(self, cb, event):
528         try:
--> 529             cb(event)
530         except Exception:
531             _handle_exception(

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/_qt/qt_viewer.py in _add_layer(self, event)
281         layers = event.source
282         layer = event.item
--> 283         vispy_layer = create_vispy_visual(layer)
284         vispy_layer.node.parent = self.view.scene
285         vispy_layer.order = len(layers) - 1

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/_vispy/utils.py in create_vispy_visual(layer)
32     for layer_type, visual in layer_to_visual.items():
33         if isinstance(layer, layer_type):
---> 34             return visual(layer)
35
36     raise TypeError(

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/_vispy/vispy_tracks_layer.py in __init__(self, layer)
48         self._reset_base()
49
---> 50         self._on_data_change()
51         self._on_appearance_change()
52

~/miniconda3/envs/fastai/lib/python3.7/site-packages/napari/_vispy/vispy_tracks_layer.py in _on_data_change(self, event)
66         self.node.update()
67         # Call to update order of translation values with new dims:
---> 68         self._on_scale_change()
69         self._on_translate_change()
70

AttributeError: 'VispyTracksLayer' object has no attribute '_on_scale_change'

# Fixed code
def __init__(
    self,
    data,
    *,
    properties=None,
    graph=None,
    tail_width=2,
    tail_length=30,
    name=None,
    metadata=None,
    scale=None,
    translate=None,
    rotate=None,
    shear=None,
    affine=None,
    opacity=1,
    blending="additive",
    visible=True,
    colormap="turbo",
    color_by="track_id",
    colormaps_dict=None,
):
    # if not provided with any data, set up an empty layer in 2D+t
    if data is None:
        data = np.empty((0, 4))
    else:
        # convert data to a numpy array if it is not already one
        data = np.asarray(data)

    # in absence of properties make the default an empty dict
    if properties is None:
        properties = {}

    # set the track data dimensions (remove ID from data)
    ndim = data.shape[1] - 1

    super().__init__(
        data,
        ndim,
        name=name,
        metadata=metadata,
        scale=scale,
        translate=translate,
        rotate=rotate,
        shear=shear,
        affine=affine,
        opacity=opacity,
        blending=blending,
        visible=visible,
    )

    self.events.add(
        tail_width=Event,
        tail_length=Event,
        display_id=Event,
        display_tail=Event,
        display_graph=Event,
        color_by=Event,
        colormap=Event,
        properties=Event,
        rebuild_tracks=Event,
        rebuild_graph=Event,
    )

    # track manager deals with data slicing, graph building and properties
    self._manager = TrackManager()
    self._track_colors = None
    self._colormaps_dict = colormaps_dict or {}  # additional colormaps
    self._color_by = color_by  # default color by ID
    self._colormap = colormap

    # use this to update shaders when the displayed dims change
    self._current_displayed_dims = None

    # track display properties
    self.tail_width = tail_width
    self.tail_length = tail_length
    self.display_id = False
    self.display_tail = True
    self.display_graph = True

    # set the data, properties and graph
    self.data = data
    self.properties = properties
    self.graph = graph or {}

    self.color_by = color_by
    self.colormap = colormap

    self._update_dims()

    # reset the display before returning
    self._current_displayed_dims = None