After generating a tracking result with this plugin it would be cool to visualize the lineage tree in Arboretum (napari-arboretum). Currently, if I open arboretum and double click on a track in the Tracks layer, for example track_ID = 5, I get the following output:
(cancer cell migration dataset from Tinevez, J. & Guillaume Jacquemet, G. licensed by CC BY 4.0)
And this Error message:
KeyError Traceback (most recent call last)
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\pandas\core\indexes\base.py:3802, in Index.get_loc(self=Index(['track_id'], dtype='object'), key='t', method=None, tolerance=None)
3801 try:
-> 3802 return self._engine.get_loc(casted_key)
casted_key = 't'
self = Index(['track_id'], dtype='object')
3803 except KeyError as err:
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\pandas\_libs\index.pyx:138, in pandas._libs.index.IndexEngine.get_loc()
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\pandas\_libs\index.pyx:165, in pandas._libs.index.IndexEngine.get_loc()
File pandas\_libs\hashtable_class_helper.pxi:5745, in pandas._libs.hashtable.PyObjectHashTable.get_item()
File pandas\_libs\hashtable_class_helper.pxi:5753, in pandas._libs.hashtable.PyObjectHashTable.get_item()
KeyError: 't'
The above exception was the direct cause of the following exception:
KeyError Traceback (most recent call last)
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\vispy\app\backends\_qt.py:522, in QtBaseCanvasBackend.mouseDoubleClickEvent(self=<vispy.app.backends._qt.CanvasBackendDesktop object>, ev=<PyQt5.QtGui.QMouseEvent object>)
520 if self._vispy_canvas is None:
521 return
--> 522 self._vispy_mouse_double_click(
self = <vispy.app.backends._qt.CanvasBackendDesktop object at 0x000002AFE690D430>
ev = <PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50>
BUTTONMAP = {0: 0, 1: 1, 2: 2, 4: 3, 8: 4, 16: 5}
523 native=ev,
524 pos=_get_event_xy(ev),
525 button=BUTTONMAP.get(ev.button(), 0),
526 modifiers=self._modifiers(ev),
527 )
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\vispy\app\base.py:239, in BaseCanvasBackend._vispy_mouse_double_click(self=<vispy.app.backends._qt.CanvasBackendDesktop object>, **kwargs={'button': 1, 'buttons': [], 'last_event': <MouseEvent blocked=False button=1 buttons=[] de...es=[] time=1684328528.1467497 type=mouse_release>, 'last_mouse_press': None, 'modifiers': (), 'native': <PyQt5.QtGui.QMouseEvent object>, 'pos': (560, 319), 'press_event': None})
235 def _vispy_mouse_double_click(self, **kwargs):
236 # default method for delivering double-click events to the canvas
237 kwargs.update(self._vispy_mouse_data)
--> 239 ev = self._vispy_canvas.events.mouse_double_click(**kwargs)
self._vispy_canvas.events.mouse_double_click = <vispy.util.event.EventEmitter object at 0x000002AFE69087F0>
kwargs = {'native': <PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50>, 'pos': (560, 319), 'button': 1, 'modifiers': (), 'buttons': [], 'press_event': None, 'last_event': <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=True last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50> pos=[560 319] press_event=MouseEvent source=None sources=[] time=1684328528.1467497 type=mouse_release>, 'last_mouse_press': None}
self = <vispy.app.backends._qt.CanvasBackendDesktop object at 0x000002AFE690D430>
self._vispy_canvas.events = <vispy.util.event.EmitterGroup object at 0x000002AFE69086D0>
self._vispy_canvas = <VispyCanvas (PyQt5) at 0x2afe68f09d0>
240 self._vispy_mouse_data['last_event'] = ev
241 return ev
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\vispy\util\event.py:453, in EventEmitter.__call__(self=<vispy.util.event.EventEmitter object>, *args=(), **kwargs={'button': 1, 'buttons': [], 'last_event': <MouseEvent blocked=False button=1 buttons=[] de...es=[] time=1684328528.1467497 type=mouse_release>, 'last_mouse_press': None, 'modifiers': (), 'native': <PyQt5.QtGui.QMouseEvent object>, 'pos': (560, 319), 'press_event': None})
450 if self._emitting > 1:
451 raise RuntimeError('EventEmitter loop detected!')
--> 453 self._invoke_callback(cb, event)
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50> pos=[560 319] press_event=None source=None sources=[] time=1684328528.2343628 type=mouse_double_click>
self = <vispy.util.event.EventEmitter object at 0x000002AFE69087F0>
cb = <bound method QtViewer.on_mouse_double_click of <napari._qt.qt_viewer.QtViewer object at 0x000002AFE68DACA0>>
454 if event.blocked:
455 break
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\vispy\util\event.py:471, in EventEmitter._invoke_callback(self=<vispy.util.event.EventEmitter object>, cb=<bound method QtViewer.on_mouse_double_click of <napari._qt.qt_viewer.QtViewer object>>, event=<MouseEvent blocked=False button=1 buttons=[] de... time=1684328528.2343628 type=mouse_double_click>)
469 cb(event)
470 except Exception:
--> 471 _handle_exception(self.ignore_callback_errors,
self = <vispy.util.event.EventEmitter object at 0x000002AFE69087F0>
cb = <bound method QtViewer.on_mouse_double_click of <napari._qt.qt_viewer.QtViewer object at 0x000002AFE68DACA0>>
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50> pos=[560 319] press_event=None source=None sources=[] time=1684328528.2343628 type=mouse_double_click>
(cb, event) = (<bound method QtViewer.on_mouse_double_click of <napari._qt.qt_viewer.QtViewer object at 0x000002AFE68DACA0>>, <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50> pos=[560 319] press_event=None source=None sources=[] time=1684328528.2343628 type=mouse_double_click>)
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\vispy\util\event.py:469, in EventEmitter._invoke_callback(self=<vispy.util.event.EventEmitter object>, cb=<bound method QtViewer.on_mouse_double_click of <napari._qt.qt_viewer.QtViewer object>>, event=<MouseEvent blocked=False button=1 buttons=[] de... time=1684328528.2343628 type=mouse_double_click>)
467 def _invoke_callback(self, cb, event):
468 try:
--> 469 cb(event)
cb = <bound method QtViewer.on_mouse_double_click of <napari._qt.qt_viewer.QtViewer object at 0x000002AFE68DACA0>>
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50> pos=[560 319] press_event=None source=None sources=[] time=1684328528.2343628 type=mouse_double_click>
470 except Exception:
471 _handle_exception(self.ignore_callback_errors,
472 self.print_callback_errors,
473 self, cb_event=(cb, event))
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari\_qt\qt_viewer.py:1057, in QtViewer.on_mouse_double_click(self=<napari._qt.qt_viewer.QtViewer object>, event=<MouseEvent blocked=False button=1 buttons=[] de... time=1684328528.2343628 type=mouse_double_click>)
1038 def on_mouse_double_click(self, event):
1039 """Called whenever a mouse double-click happen on the canvas
1040
1041 Parameters
(...)
1055 - mouse_release
1056 """
-> 1057 self._process_mouse_event(mouse_double_click_callbacks, event)
event = <MouseEvent blocked=False button=1 buttons=[] delta=[0. 0.] handled=False is_dragging=False last_event=MouseEvent modifiers=() native=<PyQt5.QtGui.QMouseEvent object at 0x000002AFE68DAE50> pos=[560 319] press_event=None source=None sources=[] time=1684328528.2343628 type=mouse_double_click>
self = <napari._qt.qt_viewer.QtViewer object at 0x000002AFE68DACA0>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari\_qt\qt_viewer.py:1026, in QtViewer._process_mouse_event(self=<napari._qt.qt_viewer.QtViewer object>, mouse_callbacks=<function mouse_double_click_callbacks>, event=<ReadOnlyWrapper at 0x000002AF883FBD40 for MouseEvent>)
1024 layer = self.viewer.layers.selection.active
1025 if layer is not None:
-> 1026 mouse_callbacks(layer, event)
event = <ReadOnlyWrapper at 0x000002AF883FBD40 for MouseEvent at 0x000002AF936B0E80>
layer = <Tracks layer 'Tracks' at 0x2af88827ca0>
mouse_callbacks = <function mouse_double_click_callbacks at 0x000002AFE285FE50>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari\utils\interactions.py:86, in mouse_double_click_callbacks(obj=<Tracks layer 'Tracks'>, event=<ReadOnlyWrapper at 0x000002AF883FBD40 for MouseEvent>)
80 if inspect.isgeneratorfunction(mouse_click_func):
81 raise ValueError(
82 trans._(
83 "Double-click actions can't be generators.", deferred=True
84 )
85 )
---> 86 mouse_click_func(obj, event)
mouse_click_func = <function Arboretum.append_mouse_callback.<locals>.show_tree at 0x000002AF88FAA040>
obj = <Tracks layer 'Tracks' at 0x2af88827ca0>
event = <ReadOnlyWrapper at 0x000002AF883FBD40 for MouseEvent at 0x000002AF936B0E80>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\plugin.py:105, in Arboretum.append_mouse_callback.<locals>.show_tree(tracks=<Tracks layer 'Tracks'>, event=<ReadOnlyWrapper at 0x000002AF883FBD40 for MouseEvent>)
101 track_id = tracks.get_value(cursor_position, world=True)
102 if track_id is not None:
103 # Setting this property automatically triggers re-drawing of the
104 # tree and property graph
--> 105 self.track_id = track_id
track_id = 1
self = <napari_arboretum.plugin.Arboretum object at 0x000002AFF0442F70>
106 self.draw_current_time_line()
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\util.py:35, in TrackPropertyMixin.track_id(self=<napari_arboretum.plugin.Arboretum object>, track_id=1)
32 @track_id.setter
33 def track_id(self, track_id: int) -> None:
34 self._track_id = track_id
---> 35 self.on_track_id_change()
self = <napari_arboretum.plugin.Arboretum object at 0x000002AFF0442F70>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\plugin.py:68, in Arboretum.on_track_id_change(self=<napari_arboretum.plugin.Arboretum object>)
66 def on_track_id_change(self):
67 self.plotter.track_id = self.track_id
---> 68 self.property_plotter.track_id = self.track_id
self = <napari_arboretum.plugin.Arboretum object at 0x000002AFF0442F70>
self.property_plotter = <napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object at 0x000002AF88EF18B0>
69 root_id = get_root_id(self.tracks, self.track_id)
70 self.title.setText(f"Lineage Tree #{root_id}")
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\util.py:35, in TrackPropertyMixin.track_id(self=<napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object>, track_id=1)
32 @track_id.setter
33 def track_id(self, track_id: int) -> None:
34 self._track_id = track_id
---> 35 self.on_track_id_change()
self = <napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object at 0x000002AF88EF18B0>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\visualisation\base_plotter.py:153, in PropertyPlotterBase.on_track_id_change(self=<napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object>)
152 def on_track_id_change(self) -> None:
--> 153 self.plot_property()
self = <napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object at 0x000002AF88EF18B0>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\visualisation\base_plotter.py:161, in PropertyPlotterBase.plot_property(self=<napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object>)
155 def plot_property(self) -> None:
156 """
157 Plot a property. The property is taken from the currently selected
158 layer, currently selected track_id, and the property used to 'color_by'
159 in the napari viewer.
160 """
--> 161 t, prop = self.get_track_properties()
self = <napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object at 0x000002AF88EF18B0>
163 self.clear()
164 self.plot(t, prop)
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\napari_arboretum\visualisation\base_plotter.py:184, in PropertyPlotterBase.get_track_properties(self=<napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object>)
182 all_props = pd.DataFrame(self.tracks.properties)
183 all_props = all_props.loc[all_props["track_id"] == self.track_id]
--> 184 return all_props["t"].values, all_props[self.tracks.color_by].values
all_props = track_id
6 1
7 1
8 1
9 1
53 1
54 1
55 1
56 1
57 1
105 1
106 1
107 1
108 1
109 1
153 1
154 1
155 1
156 1
157 1
199 1
200 1
201 1
202 1
203 1
247 1
248 1
249 1
250 1
251 1
295 1
296 1
297 1
298 1
299 1
343 1
344 1
345 1
346 1
347 1
389 1
390 1
391 1
392 1
393 1
404 1
405 1
406 1
445 1
self = <napari_arboretum.visualisation.matplotlib_plotter.MPLPropertyPlotter object at 0x000002AF88EF18B0>
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\pandas\core\frame.py:3807, in DataFrame.__getitem__(self= track_id
6 1
7 1
8 ... 1
405 1
406 1
445 1, key='t')
3805 if self.columns.nlevels > 1:
3806 return self._getitem_multilevel(key)
-> 3807 indexer = self.columns.get_loc(key)
key = 't'
indexer = None
self = track_id
6 1
7 1
8 1
9 1
53 1
54 1
55 1
56 1
57 1
105 1
106 1
107 1
108 1
109 1
153 1
154 1
155 1
156 1
157 1
199 1
200 1
201 1
202 1
203 1
247 1
248 1
249 1
250 1
251 1
295 1
296 1
297 1
298 1
299 1
343 1
344 1
345 1
346 1
347 1
389 1
390 1
391 1
392 1
393 1
404 1
405 1
406 1
445 1
3808 if is_integer(indexer):
3809 indexer = [indexer]
File ~\mambaforge\envs\laptrack_env2\lib\site-packages\pandas\core\indexes\base.py:3804, in Index.get_loc(self=Index(['track_id'], dtype='object'), key='t', method=None, tolerance=None)
3802 return self._engine.get_loc(casted_key)
3803 except KeyError as err:
-> 3804 raise KeyError(key) from err
key = 't'
3805 except TypeError:
3806 # If we have a listlike key, _check_indexing_error will raise
3807 # InvalidIndexError. Otherwise we fall through and re-raise
3808 # the TypeError.
3809 self._check_indexing_error(key)
KeyError: 't'
After generating a tracking result with this plugin it would be cool to visualize the lineage tree in Arboretum (napari-arboretum). Currently, if I open arboretum and double click on a track in the
Tracks
layer, for exampletrack_ID = 5
, I get the following output: (cancer cell migration dataset from Tinevez, J. & Guillaume Jacquemet, G. licensed by CC BY 4.0)And this Error message: