Skip to content

Commit

Permalink
Processor docs
Browse files Browse the repository at this point in the history
  • Loading branch information
aelefebv committed Oct 3, 2024
1 parent 6467da5 commit 7cc6405
Showing 1 changed file with 163 additions and 0 deletions.
163 changes: 163 additions & 0 deletions nellie_napari/nellie_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,96 @@


class NellieProcessor(QWidget):
"""
The NellieProcessor class manages the different steps of the Nellie pipeline such as preprocessing, segmentation,
mocap marking, tracking, voxel reassignment, and feature extraction. It provides an interface to run each step
individually or as part of a full pipeline within a napari viewer.
Attributes
----------
nellie : object
Reference to the Nellie instance managing the pipeline.
viewer : napari.viewer.Viewer
Reference to the napari viewer instance.
im_info_list : list of ImInfo or None
List of ImInfo objects for the selected files. Contains metadata and file information.
current_im_info : ImInfo or None
The current image's information and metadata object.
status_label : QLabel
Label displaying the current status of the process.
status : str or None
The current status of the process (e.g., "preprocessing", "segmentation").
num_ellipses : int
Counter to manage the ellipsis effect on the status label during execution.
status_timer : QTimer
Timer that periodically updates the status label during pipeline execution.
open_dir_button : QPushButton
Button to open the output directory of the current image file.
run_button : QPushButton
Button to run the full Nellie pipeline.
preprocess_button : QPushButton
Button to run only the preprocessing step of the pipeline.
segment_button : QPushButton
Button to run only the segmentation step of the pipeline.
mocap_button : QPushButton
Button to run only the mocap marking step of the pipeline.
track_button : QPushButton
Button to run only the tracking step of the pipeline.
reassign_button : QPushButton
Button to run only the voxel reassignment step of the pipeline.
feature_export_button : QPushButton
Button to run only the feature extraction step of the pipeline.
initialized : bool
Flag indicating whether the processor has been initialized.
pipeline : bool
Flag indicating whether the full pipeline is being run.
Methods
-------
set_ui()
Initializes and sets the layout and UI components for the NellieProcessor.
post_init()
Post-initialization method to load image information and check file existence.
check_file_existence()
Checks the existence of necessary files for each step of the pipeline and enables/disables buttons accordingly.
run_nellie()
Runs the entire Nellie pipeline starting from preprocessing to feature extraction.
run_preprocessing()
Runs the preprocessing step of the Nellie pipeline.
run_segmentation()
Runs the segmentation step of the Nellie pipeline.
run_mocap()
Runs the mocap marking step of the Nellie pipeline.
run_tracking()
Runs the tracking step of the Nellie pipeline.
run_reassign()
Runs the voxel reassignment step of the Nellie pipeline.
run_feature_export()
Runs the feature extraction step of the Nellie pipeline.
set_status()
Sets the status to indicate that a process has started, and starts the status update timer.
update_status()
Updates the status label with the current process and an ellipsis effect while the process is running.
reset_status()
Resets the status label to indicate that no process is running.
turn_off_buttons()
Disables all buttons to prevent multiple processes from running simultaneously.
open_directory()
Opens the output directory where the current image results are saved.
"""
def __init__(self, napari_viewer: 'napari.viewer.Viewer', nellie, parent=None):
"""
Initializes the NellieProcessor class, setting up the user interface and preparing for running various steps of the pipeline.
Parameters
----------
napari_viewer : napari.viewer.Viewer
Reference to the napari viewer instance.
nellie : object
Reference to the Nellie instance that manages the pipeline.
parent : QWidget, optional
Optional parent widget (default is None).
"""
super().__init__(parent)
self.nellie = nellie
self.viewer = napari_viewer
Expand Down Expand Up @@ -82,6 +171,10 @@ def __init__(self, napari_viewer: 'napari.viewer.Viewer', nellie, parent=None):
self.pipeline = False

def set_ui(self):
"""
Initializes and sets the layout and user interface components for the NellieProcessor. This includes the status label,
buttons for running individual steps, and the button for running the entire pipeline.
"""
main_layout = QVBoxLayout()

# Status group
Expand Down Expand Up @@ -116,6 +209,10 @@ def set_ui(self):
self.setLayout(main_layout)

def post_init(self):
"""
Post-initialization method that checks the state of the selected images. It determines whether the pipeline
steps have already been completed and enables/disables the corresponding buttons accordingly.
"""
if self.nellie.im_info_list is None:
self.im_info_list = [self.nellie.im_info]
self.current_im_info = self.nellie.im_info
Expand All @@ -127,6 +224,10 @@ def post_init(self):
self.open_dir_button.setEnabled(os.path.exists(self.current_im_info.file_info.output_dir))

def check_file_existence(self):
"""
Checks the existence of files required for each step of the pipeline (e.g., preprocessed images, segmented labels).
Enables or disables buttons based on the existence of these files.
"""
self.nellie.visualizer.check_file_existence()

# set all other buttons to disabled first
Expand Down Expand Up @@ -199,6 +300,9 @@ def check_file_existence(self):

@thread_worker
def _run_preprocessing(self):
"""
Runs the preprocessing step in a separate thread. Filters the image to remove noise or unwanted edges before segmentation.
"""
self.status = "preprocessing"
for im_num, im_info in enumerate(self.im_info_list):
show_info(f"Nellie is running: Preprocessing file {im_num + 1}/{len(self.im_info_list)}")
Expand All @@ -209,6 +313,10 @@ def _run_preprocessing(self):
preprocessing.run()

def run_preprocessing(self):
"""
Starts the preprocessing step and updates the UI to reflect that preprocessing is running.
If the full pipeline is running, it automatically proceeds to segmentation after preprocessing is finished.
"""
worker = self._run_preprocessing()
worker.started.connect(self.turn_off_buttons)
if self.pipeline:
Expand All @@ -220,6 +328,9 @@ def run_preprocessing(self):

@thread_worker
def _run_segmentation(self):
"""
Runs the segmentation step in a separate thread. Labels and segments regions of interest in the preprocessed image.
"""
self.status = "segmentation"
for im_num, im_info in enumerate(self.im_info_list):
show_info(f"Nellie is running: Segmentation file {im_num + 1}/{len(self.im_info_list)}")
Expand All @@ -230,6 +341,10 @@ def _run_segmentation(self):
networking.run()

def run_segmentation(self):
"""
Starts the segmentation step and updates the UI to reflect that segmentation is running.
If the full pipeline is running, it automatically proceeds to mocap marking after segmentation is finished.
"""
worker = self._run_segmentation()
worker.started.connect(self.turn_off_buttons)
if self.pipeline:
Expand All @@ -241,6 +356,9 @@ def run_segmentation(self):

@thread_worker
def _run_mocap(self):
"""
Runs the mocap marking step in a separate thread. Marks the motion capture points within the segmented regions.
"""
self.status = "mocap marking"
for im_num, im_info in enumerate(self.im_info_list):
show_info(f"Nellie is running: Mocap Marking file {im_num + 1}/{len(self.im_info_list)}")
Expand All @@ -249,6 +367,10 @@ def _run_mocap(self):
mocap_marking.run()

def run_mocap(self):
"""
Starts the mocap marking step and updates the UI to reflect that mocap marking is running.
If the full pipeline is running, it automatically proceeds to tracking after mocap marking is finished.
"""
worker = self._run_mocap()
worker.started.connect(self.turn_off_buttons)
if self.pipeline:
Expand All @@ -261,6 +383,9 @@ def run_mocap(self):

@thread_worker
def _run_tracking(self):
"""
Runs the tracking step in a separate thread. Tracks the motion of the marked points over time.
"""
self.status = "tracking"
for im_num, im_info in enumerate(self.im_info_list):
show_info(f"Nellie is running: Tracking file {im_num + 1}/{len(self.im_info_list)}")
Expand All @@ -269,6 +394,10 @@ def _run_tracking(self):
hu_tracking.run()

def run_tracking(self):
"""
Starts the tracking step and updates the UI to reflect that tracking is running.
If the full pipeline is running, it automatically proceeds to voxel reassignment or feature extraction depending on the settings.
"""
worker = self._run_tracking()
worker.started.connect(self.turn_off_buttons)
if self.pipeline:
Expand All @@ -283,6 +412,9 @@ def run_tracking(self):

@thread_worker
def _run_reassign(self):
"""
Runs the voxel reassignment step in a separate thread. Reassigns voxel labels based on the tracked motion.
"""
self.status = "voxel reassignment"
for im_num, im_info in enumerate(self.im_info_list):
show_info(f"Nellie is running: Voxel Reassignment file {im_num + 1}/{len(self.im_info_list)}")
Expand All @@ -291,6 +423,10 @@ def _run_reassign(self):
vox_reassign.run()

def run_reassign(self):
"""
Starts the voxel reassignment step and updates the UI to reflect that voxel reassignment is running.
If the full pipeline is running, it automatically proceeds to feature extraction after voxel reassignment is finished.
"""
worker = self._run_reassign()
worker.started.connect(self.turn_off_buttons)
if self.pipeline:
Expand All @@ -303,6 +439,9 @@ def run_reassign(self):

@thread_worker
def _run_feature_export(self):
"""
Runs the feature extraction step in a separate thread. Extracts various features from the processed image data for analysis.
"""
self.status = "feature export"
for im_num, im_info in enumerate(self.im_info_list):
show_info(f"Nellie is running: Feature export file {im_num + 1}/{len(self.im_info_list)}")
Expand All @@ -320,6 +459,9 @@ def _run_feature_export(self):
self.nellie.analyzer.rewrite_dropdown()

def run_feature_export(self):
"""
Starts the feature extraction step and updates the UI to reflect that feature extraction is running.
"""
worker = self._run_feature_export()
worker.started.connect(self.turn_off_buttons)
worker.finished.connect(self.check_file_existence)
Expand All @@ -329,30 +471,48 @@ def run_feature_export(self):
worker.start()

def turn_off_pipeline(self):
"""
Turns off the pipeline flag to indicate that the full pipeline is no longer running.
"""
self.pipeline = False

def run_nellie(self):
"""
Starts the entire Nellie pipeline from preprocessing to feature extraction.
"""
self.pipeline = True
self.run_preprocessing()

def set_status(self):
"""
Sets the status of the processor to indicate that a process is running, and starts the status update timer.
"""
self.running = True
self.status_timer.start(500) # Update every 250 ms

def update_status(self):
"""
Updates the status label with an ellipsis effect to indicate ongoing processing.
"""
if self.running:
self.status_label.setText(f"Running {self.status}{'.' * (self.num_ellipses % 4)}")
self.num_ellipses += 1
else:
self.status_timer.stop()

def reset_status(self):
"""
Resets the status label to indicate that no process is running.
"""
self.running = False
self.status_label.setText("Awaiting your input")
self.num_ellipses = 1
self.status_timer.stop()

def turn_off_buttons(self):
"""
Disables all buttons to prevent multiple processes from running simultaneously.
"""
self.run_button.setEnabled(False)
self.preprocess_button.setEnabled(False)
self.segment_button.setEnabled(False)
Expand All @@ -362,6 +522,9 @@ def turn_off_buttons(self):
self.feature_export_button.setEnabled(False)

def open_directory(self):
"""
Opens the output directory of the current image in the system file explorer.
"""
directory = self.current_im_info.file_info.output_dir
if os.path.exists(directory):
if os.name == 'nt': # For Windows
Expand Down

0 comments on commit 7cc6405

Please sign in to comment.