itasc.correction.labels

Label correction operations on a single (H, W) segmentation frame.

All functions accept a 2-D seg array and modify it in-place. They return True on success and False when the operation is rejected (e.g. labels don’t touch, result too small, background click).

Functions

add_cell(seg, pos, *, new_label[, radius, ...])

Spawn a new cell at pos in empty space.

best_overlapping_label(target_labels, ...)

Return the non-zero target label with most overlap against source_label.

carve_into_selected(seg, positions, *, ...)

Cut neighbouring cells along the drawn line and annex the near pieces.

clean_stranded_pixels(seg[, min_size, exclude])

Remove disconnected same-label fragments, keeping each label's largest component.

draw_cell_path(seg, positions, *[, ...])

Draw a closed region from the user's stroke and fill its interior.

erase_cell(seg[, pos, label])

Set all pixels of the label under pos (or label) to 0.

expand_label_to_foreground(seg, foreground, ...)

Expand label into connected foreground background pixels in-place.

fill_label_holes(labels[, radius])

Fill background holes enclosed within a single cell.

fix_label_semiholes(labels[, radius, ...])

Fill a hole enclosed by a single cell except for a narrow image-edge opening.

frame_view_2d(arr, t)

Return a 2D frame view from a time-indexed label stack.

merge_cells(seg, pos_start, pos_end, *[, ...])

Merge the cell at pos_start into the cell at pos_end.

relabel_cell(seg, pos, new_label)

Assign new_label to the cell at pos in seg (in-place).

split_across(seg, img, pos_start, pos_end, *)

Watershed-split the cell under pos_start using two seeds.

split_draw(seg, positions, *[, curlabel, ...])

Split a cell along a manually drawn line.

swap_labels(seg, pos_a, pos_b)

Swap the label values at the two click positions across the whole frame.

itasc.correction.labels.frame_view_2d(arr, t)[source]

Return a 2D frame view from a time-indexed label stack.

Return type:

ndarray | None

Parameters:
itasc.correction.labels.best_overlapping_label(target_labels, source_labels, t, source_label)[source]

Return the non-zero target label with most overlap against source_label.

Return type:

int

Parameters:
itasc.correction.labels.expand_label_to_foreground(seg, foreground, label, *, max_distance)[source]

Expand label into connected foreground background pixels in-place.

Returns the number of newly labelled pixels. A max_distance of 0 means no distance cap.

Return type:

int

Parameters:
itasc.correction.labels.erase_cell(seg, pos=None, *, label=None)[source]

Set all pixels of the label under pos (or label) to 0.

Return type:

bool

Parameters:
itasc.correction.labels.add_cell(seg, pos, *, new_label, radius=6, image=None, protected_mask=None)[source]

Spawn a new cell at pos in empty space.

When image (a nucleus/intensity frame the same shape as seg) carries a clear local signal the new cell snaps to it; otherwise a disk of radius is stamped. Only background pixels are written — existing cells and any protected_mask pixels are never overwritten — so the result can’t clobber neighbours. Returns False when pos is on an existing cell or nothing paintable remains.

Return type:

bool

Parameters:
itasc.correction.labels.merge_cells(seg, pos_start, pos_end, *, label_a=None, label_b=None)[source]

Merge the cell at pos_start into the cell at pos_end.

Return type:

bool

Parameters:
itasc.correction.labels.split_across(seg, img, pos_start, pos_end, *, new_label=None)[source]

Watershed-split the cell under pos_start using two seeds.

Return type:

bool

Parameters:
itasc.correction.labels.split_draw(seg, positions, *, curlabel=None, new_label=None)[source]

Split a cell along a manually drawn line.

Return type:

bool

Parameters:
itasc.correction.labels.carve_into_selected(seg, positions, *, selected_label)[source]

Cut neighbouring cells along the drawn line and annex the near pieces.

The user draws a line through one or more neighbouring cells, starting from (or towards) the selected cell. Every other cell the line crosses end to end is split along that line — exactly like the Shift+Right split gesture of the nucleus widget — into two fragments. The fragment that touches the selected cell is then merged into it; if both fragments touch, the smaller one is taken so the neighbour keeps its bulk. A cell the line only clips (without dividing it in two) is left alone.

Cells are merged iteratively: a fragment that is not adjacent to the selection at first can become adjacent once a cell between them has been annexed, so each pass re-checks adjacency against the grown selection until no further fragment touches it. Only one fragment per neighbour is ever annexed, so the cell label set stays in lock-step with the nuclei — no label is created, deleted or renumbered.

Cutting clean through the selected cell takes priority and is exclusive: if the line divides the selection in two, its smaller piece is removed entirely (set to background), the larger piece stays as the selected cell, and no neighbour is annexed on that stroke.

A line that divides nothing (e.g. a straight swipe over background, or a stroke that never fully crosses a cell) is a no-op. Returns True if any pixel changed.

Return type:

bool

Parameters:
itasc.correction.labels.draw_cell_path(seg, positions, *, curlabel=None, new_label=None, protected_mask=None)[source]

Draw a closed region from the user’s stroke and fill its interior.

Return type:

bool

Parameters:
itasc.correction.labels.swap_labels(seg, pos_a, pos_b)[source]

Swap the label values at the two click positions across the whole frame.

Return type:

bool

Parameters:
itasc.correction.labels.relabel_cell(seg, pos, new_label)[source]

Assign new_label to the cell at pos in seg (in-place).

If new_label already exists in the frame, the two cells are swapped so no label is lost. Returns False when pos hits background, already has new_label, or new_label is 0.

Return type:

bool

Parameters:
itasc.correction.labels.fill_label_holes(labels, radius=5)[source]

Fill background holes enclosed within a single cell.

A “hole” is a background component that does not touch the image border and is surrounded by exactly one label; it is filled with that label. Background bordered by two or more cells is an inter-cellular gap, not a hole, and is left untouched (so cells are never expanded into the space between them). radius caps the hole depth: a hole is only filled when its deepest pixel lies within radius of the surrounding cell. radius <= 0 is a no-op.

Return type:

ndarray

Parameters:
itasc.correction.labels.fix_label_semiholes(labels, radius=5, max_opening=3)[source]

Fill a hole enclosed by a single cell except for a narrow image-edge opening.

Like fill_label_holes(), but for background that escapes to the image border through a thin gap (up to max_opening pixels of edge contact). The opening’s edge flanks are ignored; the hole is filled only when its interior is enclosed by exactly one label, so cells are never expanded into inter-cellular gaps. radius caps the hole depth as in fill_label_holes(). radius <= 0 or max_opening <= 0 is a no-op.

Return type:

ndarray

Parameters:
itasc.correction.labels.clean_stranded_pixels(seg, min_size=4, *, exclude=None)[source]

Remove disconnected same-label fragments, keeping each label’s largest component.

Fragments are cleared and then expand_labels is used to propose a new label. The proposal is only accepted (written back) when the reassigned fragment pixels are 8-connected to an existing component of that same label — this prevents expand_labels from recreating a disconnected fragment.

Labels in exclude are left untouched. This is used by merge_cells to preserve a merge target whose components are intentionally disconnected (e.g. after merging a fragmented nucleus).

Return type:

int

Parameters: