napari_track_edit.application_menus.copy_from_source_widget
Attributes
Classes
QSvgWidget that fills the available width and keeps the aspect ratio of the |
|
Widget to copy detections from a source layer into the current tracks. |
Module Contents
- napari_track_edit.application_menus.copy_from_source_widget.COPY_ILLUSTRATION
- class napari_track_edit.application_menus.copy_from_source_widget.ScaledSvgWidget(path: str)
Bases:
qtpy.QtSvgWidgets.QSvgWidgetQSvgWidget that fills the available width and keeps the aspect ratio of the drawing, so the illustration adapts to the width of the menu panel.
- _ratio
- hasHeightForWidth() → bool
- heightForWidth(width: int) → int
- sizeHint() → qtpy.QtCore.QSize
- class napari_track_edit.application_menus.copy_from_source_widget.CopyFromSourceWidget(viewer: napari.Viewer)
Bases:
qtpy.QtWidgets.QWidgetWidget to copy detections from a source layer into the current tracks.
A Points or Labels layer holding detections can be connected as a copy source (the chain button). While connected, right-clicking a detection on the target track layer copies the detection under the cursor from the source layer into the tracks: onto the background it is added with the current tracklet id, on top of an existing label it replaces that label unless preserve labels is active.
- viewer
- tracks_viewer
- _source_layer = None
- _target_layer = None
- _target_callback = None
- _mode = None
- _synced_tracks = None
- source_layer_dropdown
- chain_btn
- copy_controls_box
- auto_new_track_checkbox
- channel_hint
- illustration
- _set_chain_icon(connected: bool) → None
Show a closed chain icon when connected, an open (broken) chain when not.
- _reset_chain() → None
Set the chain button back to the disconnected (unchecked) state without triggering a toggle.
- _update_source_controls() → None
Enable the chain button whenever there are tracks to copy detections into.
- _sync_to_tracks(*args) → None
Keep the chain button and the allowed source layer type in sync with the current tracks object. Whenever the tracks object changes (a different tracking result is selected), derive the mode from it - ‘labels’ if it has a segmentation, else ‘points’ - and drop any stale source connection.
- _on_source_dropdown_changed(name=None) → None
React to the user picking a different source layer. Selecting a layer other than the currently connected one disconnects the old source and resets the chain button to its unchecked state, so the user can connect the newly selected layer with a fresh click.
- _on_chain_toggled(checked: bool) → None
Connect (closed chain) or disconnect (open chain) the selected source layer.
- _setup_source_connection(source_layer: napari.layers.Labels | napari.layers.Points) → None
Keep the detections layer visible and attach a right-click callback to the target track layer that copies the detection under the cursor into the tracks.
- _teardown_source_connection() → None
Disconnect the right-click callback from the previously connected target layer.
- _make_target_callback() → callable
Create the mouse callback that copies a detection on right-click.
- _copy_detection(event) → None
Copy the label or point that is under the cursor in the source layer into the tracks as a new node with the current tracklet id.
The event may come from the target layer in the main viewer or from one of its orthogonal-view copies; the source layer is always looked up by the event’s world position, which the orthogonal views share with the main viewer.
- _leading_axes(layer: napari.layers.Labels | napari.layers.Points) → int
Return how many leading axes the source layer has that the tracks do not.
A source layer may hold several ‘channels’: alternative segmentations of the same objects, stacked on extra axes in front of the ones the tracks use. Napari aligns layers on their trailing dimensions, so those axes come directly in front of the tracks’ axes in the viewer (see TracksDims), and their sliders pick which of the alternatives a copy reads from. This count is in the layer’s own data axes, as returned by world_to_data.
- _copy_label(layer: napari.layers.Labels, event) → None
Copy the label under the cursor (in the clicked time point) into the target segmentation via an UserUpdateSegmentation action.The label is read from the source data at the clicked coordinates.
If the source carries extra leading axes, the click reads from the one the sliders are on, so which segmentation option gets copied follows the channel the user has selected.
- _clicked_track_label(event) → int
Return the node id at the clicked location in the target segmentation, or 0 if the click was on the background (or outside the data).
- _copy_point(layer: napari.layers.Points, event) → None
Copy the point under the cursor into the tracks as a point node via an UserAddNode action.
The point is looked up by the clicked coordinates (the closest point of the clicked time point, within its own radius).
- _add_node(t: int, position: numpy.ndarray) → None
Add a point node to the tracks with the current tracklet id, at the given position (used for Points sources).
- _add_segmentation_node(t: int, spatial_coords: tuple[numpy.ndarray, ...], clicked_value: int = 0) → None
Copy a label into the target segmentation at time
t.What a copy does depends on what was under the cursor in the target segmentation and on the ‘preserve labels’ setting of the target TrackLabels layer:
Clicked on an existing label (
clicked_value != 0): that label is replaced by the copied one, even where the copied pixels do not fully cover it, and the result belongs to the currently active tracklet (see_replace_label). With ‘preserve labels’ on, replacing is not allowed and nothing is copied.Clicked on the background (
clicked_value == 0): the copied label is added with the current tracklet id, either in full (‘preserve labels’ off, existing labels are overwritten) or only where the target is still empty (‘preserve labels’ on).
- Parameters:
t (int) – The time point of the copied label.
spatial_coords (tuple[np.ndarray, ...]) – The spatial (non-time) coordinates of the label pixels, as returned by
np.whereon a single time frame.clicked_value (int) – The node id at the clicked location in the target segmentation, or 0 if the click was on the background.
- _replace_label(t: int, spatial_coords: tuple[numpy.ndarray, ...], node: int, preserve: bool) → None
Replace the label that was clicked on with the copied one.
The copy always belongs to the currently active tracklet. Which node ends up holding the copied pixels depends on the active tracklet:
the clicked node is the active tracklet’s node in this frame: it keeps its id (and with it its edges) and its pixels become exactly the copied ones.
the active tracklet has no node in this frame: the clicked node is deleted and the copied pixels become a new node of the active tracklet.
the active tracklet has a different node in this frame: the clicked node is deleted and, since a tracklet can only have one node per frame, the copied pixels either grow that node or, with ‘automatically start new tracks’ on, become a new node with a new tracklet id.
With ‘preserve labels’ on, only a label of the active tracklet may be replaced - the labels of other tracklets are protected.
A segmentation update can only paint with a single value, so replacing takes more than one action: the copied pixels are painted first, so the node is never momentarily empty, and whatever the copy does not cover is deleted or erased afterwards. The actions are committed together, so one undo reverts the copy.
- _add_label(t: int, spatial_coords: tuple[numpy.ndarray, ...], preserve: bool) → None
Copy a label onto the background with the current tracklet id.
With ‘preserve labels’ on, only the pixels that are not part of an existing label are copied. The copy grows the current tracklet’s node in this frame if it has one, unless ‘automatically start new tracks’ is checked: then it starts a new track.
- _commit(actions: list, node_to_select: int | None) → None
Record the actions of one copy as a single undoable step, refresh the views and select the node the copy landed in.
The actions are created with
_top_level=Falseso that a copy that takes more than one segmentation update (replacing a label needs a paint and an erase) is still undone in one go.
- _paint(t: int, spatial_coords: tuple[numpy.ndarray, ...], new_value: int, track_id: int) → list | None
Paint the given pixels of frame
twithnew_value, creating the node if it does not exist yet and shrinking (or deleting) the nodes that are overwritten.Returns the actions that were performed, for the caller to commit (see
_commit); the list is empty if there was nothing to paint. Returns None if the paint was not allowed or the user declined to force it, so the caller can revert what it already did.
- _erase_outside(t: int, spatial_coords: tuple[numpy.ndarray, ...], node: int, track_id: int) → list
Erase the pixels of
nodein frametthat are not among the copied ones, so that the node is left with exactly the copied pixels.Returns the actions that were performed, for the caller to commit (see
_commit); the list is empty if the copy covered the whole label already.
- _current_track_node(t: int, track_id: int) → int | None
Return the node of
track_idpresent in framet, or None if there is none.
- _get_target_layer() → napari.layers.Labels | napari.layers.Points | None
Return the track layer that copies go into, based on the active mode: the TrackLabels layer for ‘labels’, the TrackPoints layer for ‘points’.
- _update_copy_controls_visibility(event=None) → None
Show the copy controls while a source layer is connected, and tell the user about the extra axes of a multi-channel source.