Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…er-dev into main
  • Loading branch information
dummyindex committed Aug 4, 2023
2 parents b593978 + 8ea02c1 commit 2b4c52f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 37 deletions.
5 changes: 4 additions & 1 deletion livecell_tracker/core/napari_visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ def gen_trajectories_shapes(
all_scs.extend(scs)
all_status.extend([""] * len(traj_shapes))
properties = {"track_id": track_ids, "sc": all_scs, "status": all_status}

# Track ID can be UUID, so we need to map it to an integer
track_value_indices = [idx for idx, v in enumerate(track_ids)]
shape_layer = viewer.add_shapes(
all_shapes,
properties=properties,
face_color=NapariVisualizer.map_colors(properties["track_id"]),
face_color=NapariVisualizer.map_colors(track_value_indices),
face_colormap="viridis",
shape_type="polygon",
text=text_parameters,
Expand Down
21 changes: 12 additions & 9 deletions livecell_tracker/core/sct_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,11 @@ def create_scts_operator_viewer(
)
new_scts = SingleCellTrajectoryCollection()
for _, sct in sctc:
new_scts.add_trajectory(sct.subsct(time_span[0], time_span[1]))
new_scts.add_trajectory(sct.subsct(time_span[0], time_span[1], keep_track_id=True))
sctc = new_scts
main_info(
f"A new SCTC object with size {len(sctc)} is created by subsetting the original sctc with time span {time_span}"
)

# if the img_dataset is not None, then we can use it to determine the time span
if img_dataset is not None:
Expand Down Expand Up @@ -851,31 +854,31 @@ def _move_span(viewer, offset):
all_sc_set = set(single_cells)
for sc in sct_operator_scs:
if sc not in all_sc_set:
print("<add new sc>:", sc)
main_info("<add new sc>:", sc)
single_cells.append(sc)
for sc in single_cells:
if sc.timeframe < cur_idx or sc.timeframe > cur_idx + span_interval:
continue
if sc not in sct_operator_scs:
print("<remove sc>:", sc)
main_info("<remove sc>:", sc)
single_cells.remove(sc)
cur_idx += offset
cur_idx = min(cur_idx, max_time) # (max_time - span_interval) is acceptable as well here
cur_idx = max(cur_idx, 0)
points_layer.metadata["cur_idx"] = cur_idx
cur_span = (cur_idx, cur_idx + span_interval)
print("new span:", cur_span)
main_info("new span:", cur_span)
# if clear_prev_batch:
# sct_operator.close()
# sct_operator = create_scs_edit_viewer(single_cells, img_dataset = dic_dataset, viewer = viewer, time_span=cur_span)
if clear_prev_batch:
# TODO: shapes may be invisible, though select is sc/sct based and should be fine
sct_operator.clear_selection()
temp_sc_trajs_for_correct = create_sctc_from_scs(single_cells)
temp_sc_trajs_for_correct = filter_sctc_by_time_span(temp_sc_trajs_for_correct, cur_span)
print("len of temp_sc_trajs_for_correct:", len(temp_sc_trajs_for_correct))
if len(temp_sc_trajs_for_correct) != 0:
sct_operator.setup_from_sctc(temp_sc_trajs_for_correct)
temp_sc_trajs = create_sctc_from_scs(single_cells)
temp_sc_trajs = filter_sctc_by_time_span(temp_sc_trajs, cur_span)
main_info("len of temp_sc_trajs:", len(temp_sc_trajs))
if len(temp_sc_trajs) != 0:
sct_operator.setup_from_sctc(temp_sc_trajs)
else:
sct_operator.shape_layer.data = []
points_layer.metadata["cur_sct_operator"] = sct_operator
Expand Down
31 changes: 19 additions & 12 deletions livecell_tracker/core/single_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from livecell_tracker.core.datasets import LiveCellImageDataset, SingleImageDataset
from livecell_tracker.core.io_utils import LiveCellEncoder
from livecell_tracker.core.sc_key_manager import SingleCellMetaKeyManager as SCKM
from livecell_tracker.livecell_logger import main_warning
from livecell_tracker.livecell_logger import main_warning, main_exception


# TODO: possibly refactor load_from_json methods into a mixin class
Expand Down Expand Up @@ -467,8 +467,8 @@ def write_single_cells_json(single_cells: List["SingleCellStatic"], path: str, d
try:
json.dump(all_sc_jsons, f)
except TypeError as e:
print("sample sc:", all_sc_jsons[0])
print("Error writing json file. Check that all attributes are serializable.")
main_exception("sample sc:", all_sc_jsons[0])
main_exception("Error writing json file. Check that all attributes are serializable.")
raise e

def write_json(self, path=None, dataset_json_dir=None):
Expand Down Expand Up @@ -1037,7 +1037,7 @@ def copy(self):

return copy.deepcopy(self)

def subsct(self, min_time, max_time):
def subsct(self, min_time, max_time, track_id=None, keep_track_id=False):
"""return a subtrajectory of this trajectory, with timeframes between min_time and max_time. Mother and daugher info will be copied if the min_time and max_time are the start and end of the new trajectory, respectively."""
require_copy_mothers_info = False
require_copy_daughters_info = False
Expand All @@ -1048,8 +1048,9 @@ def subsct(self, min_time, max_time):
require_copy_mothers_info = True
if max_time == self_span[1]:
require_copy_daughters_info = True

sub_sct = SingleCellTrajectory(img_dataset=self.img_dataset, mask_dataset=self.mask_dataset)
if keep_track_id:
track_id = self.track_id
sub_sct = SingleCellTrajectory(img_dataset=self.img_dataset, mask_dataset=self.mask_dataset, track_id=track_id)
for timeframe, sc in self:
if timeframe >= min_time and timeframe <= max_time:
sub_sct.add_single_cell(timeframe, sc)
Expand Down Expand Up @@ -1233,18 +1234,24 @@ def _next_track_id(self):
return max(self.get_track_ids()) + 1


def create_sctc_from_scs(scs: List[SingleCellStatic]):
temp_sc_trajs_for_correct = SingleCellTrajectoryCollection()
def create_sctc_from_scs(scs: List[SingleCellStatic]) -> SingleCellTrajectoryCollection:
temp_sc_trajs = SingleCellTrajectoryCollection()
for idx, sc in enumerate(scs):
sct = SingleCellTrajectory(track_id=idx, timeframe_to_single_cell={sc.timeframe: sc})
temp_sc_trajs_for_correct.add_trajectory(sct)
return temp_sc_trajs_for_correct
temp_sc_trajs.add_trajectory(sct)
return temp_sc_trajs


def filter_sctc_by_time_span(sctc: SingleCellTrajectoryCollection = None, time_span=(0, np.inf)):
def filter_sctc_by_time_span(sctc: SingleCellTrajectoryCollection = None, time_span=(0, np.inf), keep_track_id=True):
new_sctc = SingleCellTrajectoryCollection()
track_id_counter = 0
for _, sct in sctc:
subsct = sct.subsct(time_span[0], time_span[1])
if keep_track_id:
track_id = sct.track_id
else:
track_id = track_id_counter
subsct = sct.subsct(time_span[0], time_span[1], track_id=track_id)
track_id_counter += 1
if subsct.num_scs() > 0:
new_sctc.add_trajectory(subsct)
return new_sctc
42 changes: 27 additions & 15 deletions notebooks/tutorial_mitosis_annotation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,6 @@
"# dataset_dir=\"./datasets/test_scs_EBSS_starvation/datasets\")\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"\n",
"\n",
"# dic_dataset, mask_dataset = tutorial_three_image_sys()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand All @@ -174,8 +163,16 @@
"# scs_path = \"./datasets/test_scs_EBSS_starvation/single_cells.json\"\n",
"# scs_path = \"./datasets/test_scs_EBSS_starvation/XY16/tmp_corrected_scs.json\"\n",
"# scs_path = \"./datasets/test_scs_EBSS_starvation/XY1/single_cells.json\"\n",
"scs_path = \"./datasets/test_scs_EBSS_starvation/XY1/corrected_scs.json\"\n",
"single_cells = SingleCellStatic.load_single_cells_json(path=scs_path)"
"# scs_path = \"./datasets/test_scs_EBSS_starvation/XY1/corrected_scs.json\"\n",
"# single_cells = SingleCellStatic.load_single_cells_json(path=scs_path)\n",
"# dic_dataset = single_cells[0].img_dataset\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"load sample tutorial 3-image data"
]
},
{
Expand All @@ -184,7 +181,9 @@
"metadata": {},
"outputs": [],
"source": [
"dic_dataset = single_cells[0].img_dataset"
"from livecell_tracker.segment.utils import prep_scs_from_mask_dataset\n",
"dic_dataset, mask_dataset = tutorial_three_image_sys()\n",
"single_cells = prep_scs_from_mask_dataset(mask_dataset, dic_dataset)"
]
},
{
Expand Down Expand Up @@ -228,7 +227,19 @@
"outputs": [],
"source": [
"from livecell_tracker.core.sct_operator import create_scs_edit_viewer, SctOperator, create_scs_edit_viewer_by_interval, _get_viewer_sct_operator\n",
"from livecell_tracker.core.single_cell import create_sctc_from_scs, filter_sctc_by_time_span\n"
"from livecell_tracker.core.single_cell import create_sctc_from_scs, filter_sctc_by_time_span"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# points_layer = viewer.layers[\"_lcx_sct_cur_idx\"]\n",
"# sct_operator: SctOperator = points_layer.metadata[\"cur_sct_operator\"]\n",
"# # sct_operator.traj_collection._next_track_id()\n",
"# sct_operator.traj_collection.get_all_trajectories()[0]"
]
},
{
Expand All @@ -238,6 +249,7 @@
"outputs": [],
"source": [
"# sct_operator = create_scs_edit_viewer(single_cells, img_dataset = dic_dataset)\n",
"span_interval = 10\n",
"viewer = create_scs_edit_viewer_by_interval(single_cells, img_dataset=dic_dataset, span_interval = 10, viewer = None)\n",
"# for i in range(0, len(single_cells), span_interval):\n",
"# sct_operator = create_scs_edit_viewer(single_cells, img_dataset = dic_dataset, viewer = viewer, time_span=(i, i+span_interval))\n",
Expand Down

0 comments on commit 2b4c52f

Please sign in to comment.