Skip to content

Commit

Permalink
Merge pull request #142 from AllenCell/home-directory-curation
Browse files Browse the repository at this point in the history
Home directory curation
  • Loading branch information
yrkim98 authored Oct 12, 2023
2 parents b1bdabc + f3f7669 commit 2d82239
Show file tree
Hide file tree
Showing 11 changed files with 350 additions and 139 deletions.
Empty file.
14 changes: 7 additions & 7 deletions src/allencell_ml_segmenter/constants.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
CYTO_DL_HOME_PATH = "/Users/chrishu/dev/code/test2/cyto-dl"
USER_EXPERIMENTS_PATH = (
"/Users/chrishu/dev/code/test2/allencell-ml-segmenter/logs/train/runs"
)

# CYTO_DL_HOME_PATH = "/Users/brian.kim/Desktop/work/cyto-dl"
# CYTO_DL_HOME_PATH = "/Users/chrishu/dev/code/test2/cyto-dl"
# USER_EXPERIMENTS_PATH = (
# "/Users/brian.kim/Desktop/work/cyto-dl/cyto_dl/logs/train/runs"
# "/Users/chrishu/dev/code/test2/allencell-ml-segmenter/logs/train/runs"
# )

CYTO_DL_HOME_PATH = "/Users/brian.kim/Desktop/work/cyto-dl"
USER_EXPERIMENTS_PATH = (
"/Users/brian.kim/Desktop/work/allencell-ml-segmenter/logs/train/runs"
)
5 changes: 5 additions & 0 deletions src/allencell_ml_segmenter/core/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class Event(Enum):
# Action events. This signals a change in the UI. These are a direct result of a user action
ACTIOIN_REFRESH = "refresh"
ACTION_CHANGE_VIEW = "change_view"
# Training
ACTION_START_TRAINING = "start_training"
# Prediction
ACTION_PREDICTION_MODEL_FILE = "model_file"
ACTION_PREDICTION_PREPROCESSING_METHOD = "preprocessing_method"
ACTION_PREDICTION_POSTPROCESSING_METHOD = "postprocessing_method"
Expand All @@ -29,9 +31,12 @@ class Event(Enum):
ACTION_PREDICTION_POSTPROCESSING_AUTO_THRESHOLD = (
"postprocessing_auto_threshold"
)
# Curation
ACTION_CURATION_RAW_SELECTED = "curation_raw_selected"
ACTION_CURATION_SEG1_SELECTED = "curation_seg1_selected"
ACTION_CURATION_SEG2_SELECTED = "curation_seg2_selected"
# Experiment related
ACTION_EXPERIMENT_SELECTED = "experiment_selected"

# View selection events. These can stem from a user action, or from a process (i.e. prediction process ends, and a new view is shown automatically).
VIEW_SELECTION_TRAINING = "training_selected"
Expand Down
84 changes: 69 additions & 15 deletions src/allencell_ml_segmenter/curation/curation_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CurationModel(Publisher):
Stores state relevant to prediction processes.
"""

def __init__(self):
def __init__(self) -> None:
super().__init__()
self.current_view = None

Expand All @@ -29,73 +29,127 @@ def __init__(self):
self._seg1_image_channel_count: int = None
self._seg2_image_channel_count: int = None

def set_raw_directory(self, dir: Path):
def set_raw_directory(self, dir: Path) -> None:
"""
Set the raw image directory path
"""
self._raw_directory = dir
self._raw_image_channel_count = self.get_total_num_channels(
self._raw_directory
)
self.dispatch(Event.ACTION_CURATION_RAW_SELECTED)

def get_raw_directory(self) -> Path:
"""
Get the raw image directory path
"""
return self._raw_directory

def set_seg1_directory(self, dir: Path):
def set_seg1_directory(self, dir: Path) -> None:
"""
Set the seg1 image directory path
"""
self._seg1_directory = dir
self._seg1_image_channel_count = self.get_total_num_channels(
self._seg1_directory
)
self.dispatch(Event.ACTION_CURATION_SEG1_SELECTED)

def get_seg1_directory(self) -> Path:
"""
Get the seg1 image directory path
"""
return self._seg1_directory

def set_seg2_directory(self, dir: Path):
def set_seg2_directory(self, dir: Path) -> None:
"""
Set the seg2 image directory path
"""
self._seg2_directory = dir
self._seg2_image_channel_count = self.get_total_num_channels(
self._seg2_directory
)
self.dispatch(Event.ACTION_CURATION_SEG2_SELECTED)

def get_seg2_directory(self) -> Path:
"""
Get the seg2 image directory path
"""
return self._seg2_directory

def set_raw_channel(self, channel: int):
def set_raw_channel(self, channel: int) -> None:
"""
Set the raw image channel
"""
self._raw_image_channel = channel

def get_raw_channel(self) -> int:
"""
Get the raw image channel
"""
return self._raw_image_channel

def set_seg1_channel(self, channel: int):
def set_seg1_channel(self, channel: int) -> None:
"""
Set the seg1 image channel
"""
self._seg1_image_channel = channel

def get_seg1_channel(self) -> int:
"""
get the seg1 image channel
"""
return self._seg1_image_channel

def set_seg2_channel(self, channel: int):
def set_seg2_channel(self, channel: int) -> None:
"""
Set the seg2 image channel
"""
self._seg2_image_channel = channel

def get_seg2_channel(self) -> int:
"""
Get the seg2 image channel
"""
return self._seg2_image_channel

def set_view(self):
def set_view(self) -> None:
"""
Set current curation view
"""
self.dispatch(Event.PROCESS_CURATION_INPUT_STARTED)

def get_view(self):
def get_view(self) -> str:
"""
Get current curation view
"""
return self.current_view

def get_total_num_channels_raw(self):
def get_total_num_channels_raw(self) -> int:
"""
Get total number of raw channels
"""
return self._raw_image_channel_count

def get_total_num_channels_seg1(self):
def get_total_num_channels_seg1(self) -> int:
"""
Get total number of seg1 channels
"""
return self._seg1_image_channel_count

def get_total_num_channels_seg2(self):
def get_total_num_channels_seg2(self) -> int:
"""
Get total number of seg2 channels
"""
return self._seg2_image_channel_count

def get_total_num_channels(self, path) -> int:
def get_total_num_channels(self, path: Path) -> int:
"""
Determine total number of channels for image in a set folder
"""
# we expect user to have the same number of channels for all images in their folders
# and that only images are stored in those folders
first_image = path.iterdir().__next__()
img = AICSImage(str(first_image.resolve()))
first_image: Path = path.iterdir().__next__()
img: AICSImage = AICSImage(str(first_image.resolve()))
# return num channel
return img.dims.C
31 changes: 24 additions & 7 deletions src/allencell_ml_segmenter/curation/curation_widget.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Dict

from qtpy.QtWidgets import (
QVBoxLayout,
QSizePolicy,
Expand All @@ -14,6 +16,7 @@
import napari
from napari.utils.notifications import show_info

from allencell_ml_segmenter.main.experiments_model import ExperimentsModel
from allencell_ml_segmenter.main.main_model import MainModel


Expand All @@ -27,23 +30,31 @@ class CurationUiMeta(type(QStackedWidget), type(Subscriber)):


class CurationWidget(QStackedWidget, Subscriber, metaclass=CurationUiMeta):
def __init__(self, viewer: napari.Viewer, main_model: MainModel):
def __init__(
self,
viewer: napari.Viewer,
main_model: MainModel,
experiments_model: ExperimentsModel,
) -> None:
super().__init__()
self.main_model = main_model
self.main_model: MainModel = main_model
self.viewer: napari.Viewer = viewer
self.view_to_index = dict()
self.curation_model = CurationModel()
self.experiments_model: ExperimentsModel = experiments_model
self.view_to_index: Dict[View, int] = dict()
self.curation_model: CurationModel = CurationModel()

# basic styling
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)
self.setLayout(QVBoxLayout())
self.layout().setContentsMargins(0, 0, 0, 0)

self.curation_input_view = CurationInputView(self.curation_model)
self.curation_input_view: CurationInputView = CurationInputView(
self.curation_model
)
self.initialize_view(self.curation_input_view)

self.curation_main_view = CurationMainView(
self.viewer, self.curation_model
self.curation_main_view: CurationMainView = CurationMainView(
self.viewer, self.curation_model, self.experiments_model
)
self.initialize_view(self.curation_main_view)

Expand All @@ -55,6 +66,9 @@ def __init__(self, viewer: napari.Viewer, main_model: MainModel):
)

def go_to_main_view(self, view: View) -> None:
"""
Switch to main curation view
"""
if (
self.curation_model.get_raw_directory() is not None
and self.curation_model.get_raw_channel() is not None
Expand All @@ -73,6 +87,9 @@ def set_view(self, view: View) -> None:
self.setCurrentIndex(self.view_to_index[view])

def initialize_view(self, view: View) -> None:
"""
Initialize views. This is necessary because QStackedWidget requires all child widgets to be added
"""
# QStackedWidget count method keeps track of how many child widgets have been added
self.view_to_index[view] = self.count()
self.addWidget(view)
Loading

0 comments on commit 2d82239

Please sign in to comment.