napari_track_edit.data_views.views.layers.contour_labels

Classes

ContourLabels

Extended labels layer that allows to show contours and filled labels simultaneously

Functions

left_only_draw(layer, event)

left_only_pick(layer, event)

get_contours(labels, thickness, background_label[, ...])

Computes the contours of a 2D label image.

Module Contents

napari_track_edit.data_views.views.layers.contour_labels.left_only_draw(layer, event)
napari_track_edit.data_views.views.layers.contour_labels.left_only_pick(layer, event)
napari_track_edit.data_views.views.layers.contour_labels.get_contours(labels: numpy.ndarray, thickness: int, background_label: int, filled_labels: list[int] | None = None)

Computes the contours of a 2D label image.

Parameters:
  • labels (array of integers) – An input labels image.

  • thickness (int) – It controls the thickness of the inner boundaries. The outside thickness is always 1. The final thickness of the contours will be thickness + 1.

  • background_label (int) – That label is used to fill everything outside the boundaries.

Return type:

A new label image in which only the boundaries of the input image are kept.

class napari_track_edit.data_views.views.layers.contour_labels.ContourLabels(data: numpy.array, name: str, opacity: float, scale: tuple, colormap: napari.utils.DirectLabelColormap)

Bases: napari.layers.Labels

Extended labels layer that allows to show contours and filled labels simultaneously

property _type_string: str
_filled_labels = []
property filled_labels: list[int] | None

List of labels in a group

_calculate_contour(labels: numpy.ndarray, data_slice: tuple[slice, ...]) → numpy.ndarray | None

Calculate the contour of a given label array within the specified data slice.

Parameters:
  • labels (np.ndarray) – The label array.

  • data_slice (Tuple[slice, ...]) – The slice of the label array on which to calculate the contour.

Returns:

The calculated contour as a boolean mask array. Returns None if the contour parameter is less than 1, or if the label array has more than 2 dimensions.

Return type:

Optional[np.ndarray]

set_opacity(labels: list[int], value: float) → None

Helper function to set the opacity of multiple labels to the same value. :param labels: list of labels to set the value for. :type labels: list[int] :param value: float alpha value to set. :type value: float

refresh_colormap()

Refresh the label colormap after in-place opacity/color changes.

set_opacity mutates the colormap’s color_dict alphas in place. Rather than constructing a new DirectLabelColormap (which re-validates every color via transform_color - ~0.2s for a 37k-label graph), clear the colormap’s cached value->color mapping and re-assign the same object so napari rebuilds only the GPU texture (~0.08s).

Setting colormap also emits selected_label, which triggers _ensure_valid_label and would rebuild the colormap a second time; that validation is only needed when the painting label changes, not on a highlight/opacity refresh, so block it here.

data_setitem(indices, value, refresh=True)

Override to handle read-only data (e.g. GraphArrayView).

When the underlying data does not support __setitem__ (read-only), accumulate paint atoms during a drag (respecting napari’s block_history mechanism) and only fire events.paint once when the drag completes. For writable arrays (numpy), fall back to the default implementation.

_paint_region_with_mask(slice_key, mask, new_label, dims_to_paint, refresh=True, region_data=None)

Override to handle read-only data (e.g. GraphArrayView).

napari ≥0.8 equivalent of data_setitem above. This method writes the painted bounding box straight back with self.data[slice_key] = region_data. Read-only data cannot take that write, so run the same steps napari does, minus the write-back: the region is materialized as a numpy copy, so painting into it records the undo atom (firing events.paint, which is what upstream code acts on) and updates the display, while the underlying array is left untouched.

undo()

Override undo for read-only data (e.g. GraphArrayView).

napari’s default Labels.undo() calls data_setitem() to restore old values. For read-only data, ContourLabels.data_setitem() cannot write to the underlying array and instead fires events.paint as a signal for upstream code to handle the change. Firing events.paint during an undo triggers the same paint-event callbacks that initiated the undo in the first place, causing a recursive loop and a TypeError.

This override breaks the loop by dropping the display buffer and re-slicing, without going through data_setitem or emitting any paint event. Only the display buffer was ever updated, the underlying array still holds the pre-stroke segmentation.

This method is called (via super().undo()) from TrackLabels in three situations: reverting a failed paint on the main layer, reverting a failed paint on an ortho-view copy of the layer, and rolling back an invalid action inside _on_paint error handling.

The undone item is dropped rather than handed to the redo queue: a paint that never reached the data cannot be re-applied by this layer, and what the user redoes is the funtracks action. Leaving the redo queue empty is also what

keeps napari’s own Labels.redo(), bound to Ctrl+Shift+Z, harmless here.

_abort_stroke()

Override for read-only data (e.g. GraphArrayView).

napari >= 0.8 stages the atoms of an encircle-and-fill stroke (right click in paint mode) instead of committing them one by one, and aborts the stroke when the tool is disabled mid-stroke, e.g. by a mode switch. Its abort walks the staged atoms backwards and writes each one back into the array, either directly or via _replay_masked_atom, which read-only data cannot take.

Nothing was ever written (see _paint_region_with_mask), so dropping the staged atoms and re-slicing is all the revert this layer needs, and, as in undo, it avoids emitting a paint event that would re-enter _on_paint.

redo()

Override redo for read-only data (e.g. GraphArrayView). There is nothing to do here in our use case, since we have our own history logic, but because napari binds Ctrl+Shift+Z to Labels.redo() we should override here in case the user tries to redo on an ortho-view, triggering the TypeError: ‘LazyArrayWrapper’ object does not support item assignment error.