-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into refactor_for_editing
- Loading branch information
Showing
11 changed files
with
8,741 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import napari | ||
from motile_plugin.example_data import Fluo_N2DL_HeLa | ||
from motile_plugin.utils.load_tracks import tracks_from_csv | ||
from motile_plugin.widgets import TreeWidget | ||
|
||
if __name__ == "__main__": | ||
# load the example data | ||
raw_layer_info, labels_layer_info = Fluo_N2DL_HeLa() | ||
segmentation_arr = labels_layer_info[0] | ||
# the segmentation ids in this file correspond to the segmentation ids in the | ||
# example segmentation data, loaded above | ||
csvfile = "hela_example_tracks.csv" | ||
tracks = tracks_from_csv(csvfile, segmentation_arr) | ||
|
||
viewer = napari.Viewer() | ||
raw_data, raw_kwargs, _ = raw_layer_info | ||
viewer.add_image(raw_data, **raw_kwargs) | ||
labels_data, labels_kwargs, _ = labels_layer_info | ||
viewer.add_labels(labels_data, **labels_kwargs) | ||
widget = TreeWidget(viewer) | ||
widget.tracks_viewer.view_external_tracks(tracks, "example") | ||
viewer.window.add_dock_widget(widget, name="Lineage View", area="bottom") | ||
|
||
# Start the Napari GUI event loop | ||
napari.run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
from csv import DictReader | ||
|
||
import networkx as nx | ||
import numpy as np | ||
from motile_plugin.core import Tracks | ||
|
||
|
||
def tracks_from_csv(csvfile: str, segmentation: np.ndarray | None = None) -> Tracks: | ||
"""Assumes a csv similar to that created from "export tracks to csv" with columns: | ||
t,[z],y,x,id,parent_id,[seg_id] | ||
Cells without a parent_id will have an empty string or a -1 for the parent_id. | ||
Args: | ||
csvfile (str): | ||
path to the csv to load | ||
segmentation (np.ndarray | None, optional): | ||
An optional accompanying segmentation. | ||
If provided, assumes that the seg_id column in the csv file exists and | ||
corresponds to the label ids in the segmentation array | ||
Returns: | ||
Tracks: a tracks object ready to be visualized with | ||
TracksViewer.view_external_tracks | ||
""" | ||
graph = nx.DiGraph() | ||
with open(csvfile) as f: | ||
reader = DictReader(f) | ||
for row in reader: | ||
_id = row["id"] | ||
attrs = { | ||
"pos": [float(row["y"]), float(row["x"])], | ||
"time": int(row["t"]), | ||
} | ||
if "seg_id" in row: | ||
attrs["seg_id"] = int(row["seg_id"]) | ||
graph.add_node(_id, **attrs) | ||
parent_id = row["parent_id"].strip() | ||
if parent_id != "": | ||
parent_id = parent_id | ||
if parent_id != -1: | ||
assert parent_id in graph.nodes, f"{_id} {parent_id}" | ||
graph.add_edge(parent_id, _id) | ||
tracks = Tracks( | ||
graph=graph, segmentation=segmentation, pos_attr=("pos"), time_attr="time" | ||
) | ||
return tracks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import networkx as nx | ||
import numpy as np | ||
from motile_toolbox.candidate_graph.graph_attributes import NodeAttr | ||
|
||
|
||
def relabel_segmentation( | ||
solution_nx_graph: nx.DiGraph, | ||
segmentation: np.ndarray, | ||
) -> np.ndarray: | ||
"""Relabel a segmentation based on tracking results so that nodes in same | ||
track share the same id. IDs do change at division. | ||
Args: | ||
solution_nx_graph (nx.DiGraph): Networkx graph with the solution to use | ||
for relabeling. Nodes not in graph will be removed from seg. Original | ||
segmentation ids and hypothesis ids have to be stored in the graph so we | ||
can map them back. Assumes tracket ids have already been assigned. | ||
segmentation (np.ndarray): Original (potentially multi-hypothesis) | ||
segmentation with dimensions (t,h,[z],y,x), where h is 1 for single | ||
input segmentation. | ||
Returns: | ||
np.ndarray: Relabeled segmentation array where nodes in same track share same | ||
id with shape (t,1,[z],y,x) | ||
""" | ||
output_shape = (segmentation.shape[0], 1, *segmentation.shape[2:]) | ||
tracked_masks = np.zeros_like(segmentation, shape=output_shape) | ||
for node, _data in solution_nx_graph.nodes(data=True): | ||
time_frame = solution_nx_graph.nodes[node][NodeAttr.TIME.value] | ||
previous_seg_id = solution_nx_graph.nodes[node][NodeAttr.SEG_ID.value] | ||
assert previous_seg_id != 0 | ||
tracklet_id = solution_nx_graph.nodes[node]["tracklet_id"] | ||
hypothesis_id = solution_nx_graph.nodes[node].get(NodeAttr.SEG_HYPO.value, 0) | ||
previous_seg_mask = segmentation[time_frame, hypothesis_id] == previous_seg_id | ||
tracked_masks[time_frame, 0][previous_seg_mask] = tracklet_id | ||
return tracked_masks |