Source code for simba.roi_tools.roi_ui

__author__ = "Simon Nilsson; sronilsson@gmail.com"

import os
import warnings
from typing import Any, Optional, Union

from simba.mixins.config_reader import ConfigReader
from simba.mixins.image_mixin import ImageMixin
from simba.mixins.pop_up_mixin import PopUpMixin
from simba.roi_tools.roi_ui_mixin import ROI_mixin
from simba.roi_tools.roi_utils import get_pose_for_roi_ui
from simba.ui.utils import position_window
from simba.utils.checks import (check_file_exist_and_readable,
                                check_if_dir_exists)
from simba.utils.enums import ROI_SETTINGS
from simba.utils.errors import InvalidInputError
from simba.utils.read_write import (find_all_videos_in_directory, get_fn_ext,
                                    get_video_meta_data)

warnings.filterwarnings("ignore")


WINDOW_SIZE = (775, 900)
SHOW_GRID_OVERLAY = 'SHOW_GRID_OVERLAY'

[docs]class ROI_ui(ROI_mixin, ConfigReader): """ Main entry-point for drawing ROIs on videos. .. note:: See ROI tutorial on `GitHub <https://github.com/sgoldenlab/simba/blob/master/docs/roi_tutorial_new_2025.md>`_ or `ReadTheDocs <https://simba-uw-tf-dev.readthedocs.io/en/latest/tutorials_rst/roi_tutorial_new_2025.html>`_ :param Union[str, os.PathLike] video_path: Path to the video file to draw ROIs on. :param Optional[Union[str, os.PathLike]] config_path: Path to the SimBA project config INI file. If None, then ``roi_coordinates_path`` and ``video_dir`` must be provided. :param Optional[Union[str, os.PathLike]] roi_coordinates_path: Path to an existing ROI definitions HDF5 file. Used when ``config_path`` is None. :param Optional[Union[str, os.PathLike]] pose_path: Path to pose-estimation data file. If provided, pose landmarks are overlaid on the video frame in the ROI interface. :param Optional[Union[str, os.PathLike]] video_dir: Directory containing project videos. Used to enable copying ROIs from other videos. Required when ``config_path`` is None. :param Optional[Any] roi_table_popup: Reference to the parent ROI table popup window. If provided, :meth:`refresh_window` is called on close. :example: >>> ROI_ui(config_path=r"C:\troubleshooting\mouse_open_field\project_folder\project_config.ini", video_path=r"C:\troubleshooting\mouse_open_field\project_folder\videos\Video1.mp4") >>> ROI_ui(config_path=r"/mnt/c/troubleshooting/mouse_open_field/project_folder/project_config.ini", video_path=r"/mnt/c/troubleshooting/mouse_open_field/project_folder/videos/Video1.mp4") """ def __init__(self, video_path: Union[str, os.PathLike], config_path: Optional[Union[str, os.PathLike]] = None, roi_coordinates_path: Optional[Union[str, os.PathLike]] = None, pose_path: Optional[Union[str, os.PathLike]] = None, video_dir: Optional[Union[str, os.PathLike]] = None, roi_table_popup: Optional[Any] = None): check_file_exist_and_readable(file_path=video_path) if config_path is None: if (video_dir is None) and (roi_coordinates_path is None): raise InvalidInputError(msg='If not passing a config path, then pass roi_coordinates_path AND video_dir', source=self.__class__.__name__) if config_path is not None: check_file_exist_and_readable(file_path=config_path) ConfigReader.__init__(self, config_path=config_path, read_video_info=False, create_logger=False) if roi_coordinates_path is not None: self.roi_coordinates_path = roi_coordinates_path if check_if_dir_exists(in_dir=video_dir, raise_error=False): self.video_dir = video_dir else: self.video_dir = None self.video_meta = get_video_meta_data(video_path=video_path, fps_as_int=False) if pose_path is not None: pose_data = get_pose_for_roi_ui(pose_path=pose_path, video_path=video_path) else: pose_data = None self.video_ext = get_fn_ext(filepath=video_path)[2][1:] self.roi_table_popup = roi_table_popup self.img, self.img_idx = ImageMixin.find_first_non_uniform_clr_frm(video_path=video_path) self.define_ui = PopUpMixin(title="REGION OF INTEREST (ROI) SETTINGS", size=WINDOW_SIZE, icon='shapes_small') ROI_mixin.__init__(self, video_path=video_path, config_path=config_path, img_idx=self.img_idx, main_frm=self.define_ui.root, roi_coordinates_path=self.roi_coordinates_path, pose_data=pose_data) if self.video_dir is not None: self.other_project_video_paths = find_all_videos_in_directory(directory=self.video_dir, as_dict=True).values() self.other_project_video_paths = [x for x in self.other_project_video_paths if x != video_path] self.other_project_video_names = [get_fn_ext(x)[1] for x in self.other_project_video_paths] else: self.other_project_video_names = [] self.settings = {item.name: item.value for item in ROI_SETTINGS} self.settings[SHOW_GRID_OVERLAY] = 'FALSE' self.get_video_info_panel(parent_frame=self.define_ui.main_frm, row_idx=0) self.get_select_img_panel(parent_frame=self.define_ui.main_frm, row_idx=1) self.get_select_shape_type_panel(parent_frame=self.define_ui.main_frm, row_idx=2) self.get_shape_attr_panel(parent_frame=self.define_ui.main_frm, row_idx=3) self.get_shape_name_panel(parent_frame=self.define_ui.main_frm, row_idx=4) self.get_interact_panel(parent_frame=self.define_ui.main_frm, row_idx=5, top_level=self.define_ui.root) self.get_draw_panel(parent_frame=self.define_ui.main_frm, row_idx=6, top_level=self.define_ui.root) self.get_shapes_from_other_video_panel(parent_frame=self.define_ui.main_frm, row_idx=7) self.get_save_roi_panel(parent_frame=self.define_ui.main_frm, row_idx=8) self.get_status_bar_panel(parent_frame=self.define_ui.main_frm, row_idx=9) self.get_file_menu(root=self.define_ui.root) self.set_selected_shape_type(shape_type='rectangle') self.define_ui.root.protocol("WM_DELETE_WINDOW", self._close) position_window(self.define_ui.root, position='top_left', lift=True, verbose=True, focus=True, after_ms=100) self.define_ui.main_frm.mainloop() def _close(self): try: self.close_img() except: pass self.define_ui.root.destroy() self.define_ui.root.quit() self.roi_table_popup.refresh_window()
# ROI_ui(roi_coordinates_path=r"D:\troubleshooting\mouse_open_field\project_folder\logs\measures\ROI_definitions.h5", # video_path=r"D:\troubleshooting\mouse_open_field\project_folder\videos\0_video.mp4") # # ROI_ui(config_path=r"C:\troubleshooting\open_field_below\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\open_field_below\project_folder\videos\raw_clip1.mp4") # # ROI_ui(video_dir=r'F:\troubleshooting\ares\videos', # video_path=r"F:\troubleshooting\ares\videos\2205202517811786_clip2.mp4", # roi_coordinates_path=r"F:\troubleshooting\ares\roi_coordinates\roi_coordinates.h5") # ROI_ui(config_path=None, # video_path=r"D:\ares\data\ant\ant.mp4", # roi_coordinates_path=r'D:\ares\data\ant\roi_coordinates.h5') # ROI_ui(config_path="/Users/simon/Desktop/envs/simba/troubleshooting/spontenous_alternation/project_folder/project_config.ini", # video_path="/Users/simon/Desktop/envs/simba/troubleshooting/spontenous_alternation/project_folder/videos/F1 HAB.mp4") # ROI_ui(config_path=None, # video_path=r'C:\troubleshooting\mouse_open_field\project_folder\videos\Video2.mp4', # roi_coordinates_path=r"C:\troubleshooting\mitra\project_folder\logs\measures\ROI_definitions.h5", # video_dir=r"C:\troubleshooting\mitra\test") # ROI_ui(config_path=r"C:\troubleshooting\RAT_NOR\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\RAT_NOR\project_folder\videos\03152021_NOB_IOT_8.mp4", # roi_coordinates_path=r"C:\troubleshooting\RAT_NOR\project_folder\logs\measures\ROI_definitions.h5", # pose_path=r"C:\troubleshooting\RAT_NOR\project_folder\csv\outlier_corrected_movement_location\03152021_NOB_IOT_8.csv") # # ROI_ui(config_path=r"C:\troubleshooting\cue_light\t1\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\cue_light\t1\project_folder\videos\2025-05-21 16-10-06_cropped.mp4", # roi_coordinates_path=r"C:\troubleshooting\cue_light\t1\project_folder\logs\measures\ROI_definitions.h5") # # ROI_ui(config_path=r"C:\troubleshooting\cue_light\t1\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\cue_light\t1\project_folder\videos\2025-05-21 16-10-06_cropped.mp4", # roi_coordinates_path=r"C:\troubleshooting\cue_light\t1\project_folder\logs\measures\ROI_definitions.h5") # # ROI_ui(config_path=r"C:\troubleshooting\mitra\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\mitra\project_folder\videos\501_MA142_Gi_CNO_0514.mp4") # # # #ROI_ui(config_path=r'/Users/simon/Desktop/envs/simba/troubleshooting/RAT_NOR/project_folder/project_config.ini', # video_path=r"/Users/simon/Desktop/envs/simba/troubleshooting/RAT_NOR/project_folder/videos/2022-06-20_NOB_DOT_4.mp4", # pose_path=r'/Users/simon/Desktop/envs/simba/troubleshooting/RAT_NOR/project_folder/csv/outlier_corrected_movement_location/2022-06-20_NOB_DOT_4.csv') # # ROI_ui(config_path=r'/Users/simon/Desktop/envs/simba/troubleshooting/open_field_below/project_folder/project_config.ini', # video_path=r"/Users/simon/Desktop/envs/simba/troubleshooting/open_field_below/project_folder/videos/raw_clip1.mp4", # pose_path=r'/Users/simon/Desktop/envs/simba/troubleshooting/open_field_below/project_folder/csv/outlier_corrected_movement_location/raw_clip1.csv') # ROI_ui(config_path=r"C:\troubleshooting\open_field_below\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\open_field_below\project_folder\videos\raw_clip1.mp4", # pose_path=r"C:\troubleshooting\open_field_below\project_folder\csv\outlier_corrected_movement_location\raw_clip1.csv") # # ROI_ui(config_path=r"C:\troubleshooting\open_field_below\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\open_field_below\project_folder\videos\raw_clip1.mp4") # ROI_ui(config_path=r"C:\troubleshooting\two_black_animals_14bp\project_folder\project_config.ini", # video_path=r"C:\troubleshooting\two_black_animals_14bp\project_folder\videos\Together_1.avi")