Pre-submission checklist
Bug summary
While a point is selected in the Points layer, switching the current keypoint has no effect — via the dropdown, the next/previous-keypoint shortcuts, or the automatic advance after placing a point. There is no error; the current keypoint just stays put, so the next point gets labeled as the previous bodypart. It looks like "the label won't stick" or "the label goes to the wrong bodypart."
Root cause: the three "current keypoint" setters in KeypointStore (current_keypoint, current_label, current_id) are guarded by if not len(layer.selected_data):, which skips the whole update whenever any point is selected.
Steps to reproduce
In the GUI:
- Open an image folder + config.yaml and start labeling.
- Place a keypoint (e.g.
ear_left).
- Click that point to select it (this leaves
selected_data non-empty).
- Try to switch to another bodypart via the dropdown or the next/previous-keypoint shortcut.
- The current keypoint does not change; any point placed now gets the old bodypart's label.
Minimal reproduction (no GUI, only napari + numpy) — isolates the setter logic from keypoints.py:282-288 (v0.3.1.2):
import numpy as np
from napari.layers import Points
layer = Points(
np.array([[0, 10, 10]], dtype=float),
properties={"label": np.array(["nose"], dtype=object),
"id": np.array([""], dtype=object)},
)
def set_current_label(label):
if not len(layer.selected_data): # the guard under test
cp = layer.current_properties
cp["label"] = np.asarray([label])
layer.current_properties = cp
def current_label():
return layer.current_properties["label"][0]
layer.selected_data = set()
set_current_label("ear_left")
print(current_label()) # -> 'ear_left' (OK)
layer.selected_data = {0}
set_current_label("tail")
print(current_label()) # -> 'nose' (BUG: switch ignored while a point is selected)
Expected behavior
Selecting a different bodypart (dropdown / next / previous keypoint) should switch the current keypoint even when a point is currently selected, so the next point I place is labeled with the bodypart I chose.
Actual behavior
When a point is selected, the switch is silently ignored: the current keypoint stays on the previous bodypart, and the next placed point is labeled with that old bodypart. No error or warning is shown.
Data type
Single-animal
How are you running napari?
From within the DeepLabCut GUI
Additional context
Suggested fix: clear the point selection first, then update current_properties — this keeps the guard's original intent while allowing the switch:
if len(layer.selected_data):
layer.selected_data = set()
current_properties = layer.current_properties
current_properties["label"] = np.asarray([keypoint.label])
current_properties["id"] = np.asarray([keypoint.id])
layer.current_properties = current_properties
The same applies to current_label and current_id.
Why not just drop the guard: in napari, assigning current_properties while a point is selected also rewrites that selected point's properties, so removing the check would silently relabel the selected point. Clearing the selection first avoids that.
I verified on a real napari Points layer that (1) the switch now works while a point is selected, (2) the previously selected point's label is unchanged, (3) behavior is unchanged with nothing selected. The existing core/test_keypoints.py suite still passes (11/11), and test_widgets.py results are identical before and after.
Line numbers/verification are against current main (v0.3.1.2, commit 635a585).
Possibly related (same symptom, different root cause): #130 / DeepLabCut#2387 (closed by #137, a different error), DeepLabCut#2303 (a loading failure), #99 / #160 (Keypoint Selection Window not shown). #184 lists a distinct LOOP-mode frame-advance bug. Also: if the W/S keypoint-switch shortcuts in #225 go through the same setters, they'd inherit this guard.
Debug log (highly recommended)
I couldn't run the in-app "Generate napari-dlc log" from the original labeling session, but here are the package versions from the same conda environment where the bug occurs:
- OS: Windows
- Python: 3.10.20
- napari-deeplabcut: 0.3.1.2
- napari: 0.7.1
- PySide6: 6.11.1
- QtPy: 2.4.3
- numpy: 1.26.4
- pydantic: 2.13.4
The bug is pure-Python logic (the selected_data guard), and the minimal reproduction above only needs napari + numpy, so it's reproducible without the original session's log.
Pre-submission checklist
Bug summary
While a point is selected in the Points layer, switching the current keypoint has no effect — via the dropdown, the next/previous-keypoint shortcuts, or the automatic advance after placing a point. There is no error; the current keypoint just stays put, so the next point gets labeled as the previous bodypart. It looks like "the label won't stick" or "the label goes to the wrong bodypart."
Root cause: the three "current keypoint" setters in
KeypointStore(current_keypoint,current_label,current_id) are guarded byif not len(layer.selected_data):, which skips the whole update whenever any point is selected.Steps to reproduce
In the GUI:
ear_left).selected_datanon-empty).Minimal reproduction (no GUI, only
napari+numpy) — isolates the setter logic from keypoints.py:282-288 (v0.3.1.2):import numpy as np
from napari.layers import Points
layer = Points(
np.array([[0, 10, 10]], dtype=float),
properties={"label": np.array(["nose"], dtype=object),
"id": np.array([""], dtype=object)},
)
def set_current_label(label):
if not len(layer.selected_data): # the guard under test
cp = layer.current_properties
cp["label"] = np.asarray([label])
layer.current_properties = cp
def current_label():
return layer.current_properties["label"][0]
layer.selected_data = set()
set_current_label("ear_left")
print(current_label()) # -> 'ear_left' (OK)
layer.selected_data = {0}
set_current_label("tail")
print(current_label()) # -> 'nose' (BUG: switch ignored while a point is selected)
Expected behavior
Selecting a different bodypart (dropdown / next / previous keypoint) should switch the current keypoint even when a point is currently selected, so the next point I place is labeled with the bodypart I chose.
Actual behavior
When a point is selected, the switch is silently ignored: the current keypoint stays on the previous bodypart, and the next placed point is labeled with that old bodypart. No error or warning is shown.
Data type
Single-animal
How are you running napari?
From within the DeepLabCut GUI
Additional context
Suggested fix: clear the point selection first, then update current_properties — this keeps the guard's original intent while allowing the switch:
The same applies to current_label and current_id.
Why not just drop the guard: in napari, assigning current_properties while a point is selected also rewrites that selected point's properties, so removing the check would silently relabel the selected point. Clearing the selection first avoids that.
I verified on a real napari Points layer that (1) the switch now works while a point is selected, (2) the previously selected point's label is unchanged, (3) behavior is unchanged with nothing selected. The existing core/test_keypoints.py suite still passes (11/11), and test_widgets.py results are identical before and after.
Line numbers/verification are against current main (v0.3.1.2, commit 635a585).
Possibly related (same symptom, different root cause): #130 / DeepLabCut#2387 (closed by #137, a different error), DeepLabCut#2303 (a loading failure), #99 / #160 (Keypoint Selection Window not shown). #184 lists a distinct LOOP-mode frame-advance bug. Also: if the W/S keypoint-switch shortcuts in #225 go through the same setters, they'd inherit this guard.
Debug log (highly recommended)
I couldn't run the in-app "Generate napari-dlc log" from the original labeling session, but here are the package versions from the same conda environment where the bug occurs:
The bug is pure-Python logic (the
selected_dataguard), and the minimal reproduction above only needs napari + numpy, so it's reproducible without the original session's log.