Source code for simba.ui.create_project_ui

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

import os
import tkinter.ttk as ttk
from copy import deepcopy
from tkinter import *

import pandas as pd
import PIL.Image
from PIL import ImageTk

import simba
from simba.ui.import_pose_frame import ImportPoseFrame
from simba.ui.import_videos_frame import ImportVideosFrame
from simba.ui.ml_settings_frm import GetMLSettingsFrame
from simba.ui.pop_ups.clf_add_remove_print_pop_up import PoseResetterPopUp
from simba.ui.pop_ups.create_user_defined_pose_configuration_pop_up import \
    CreateUserDefinedPoseConfigurationPopUp
from simba.ui.tkinter_functions import (CreateLabelFrameWithIcon, Entry_Box,
                                        FolderSelect, SimbaButton,
                                        SimBADropDown, hxtScrollbar)
from simba.utils.checks import check_if_dir_exists, check_str
from simba.utils.config_creator import ProjectConfigCreator
from simba.utils.enums import Formats, Keys, Links, Methods, Options, Paths
from simba.utils.errors import DuplicationError, MissingProjectConfigEntryError
from simba.utils.lookups import (get_body_part_configurations,
                                 get_bp_config_codes, get_icons_paths)
from simba.video_processors.video_processing import \
    extract_frames_from_all_videos_in_directory


[docs]class ProjectCreatorPopUp(): """ Mixin for GUI pop-up windows that accept user-inputs for creating a SimBA project. .. image:: _static/img/ProjectCreatorPopUp.webp :alt: Project Creator Pop Up :width: 800 :align: center :example: >>> ProjectCreatorPopUp() """ def __init__(self): self.main_frm = Toplevel() self.main_frm.minsize(750, 800) self.main_frm.wm_title("PROJECT CONFIGURATION") self.main_frm.columnconfigure(0, weight=1) self.main_frm.rowconfigure(0, weight=1) parent_tab = ttk.Notebook(hxtScrollbar(self.main_frm)) self.btn_icons = get_icons_paths() for k in self.btn_icons.keys(): self.btn_icons[k]["img"] = ImageTk.PhotoImage(image=PIL.Image.open(os.path.join(os.path.dirname("__file__"), self.btn_icons[k]["icon_path"]))) self.main_frm.iconphoto(False, self.btn_icons['settings']['img']) self.create_project_tab = ttk.Frame(parent_tab) self.import_videos_tab = ttk.Frame(parent_tab) self.import_data_tab = ttk.Frame(parent_tab) parent_tab.add(self.create_project_tab, text=f'{"[ Create project config ]": ^20s}', compound="left", image=self.btn_icons["create"]["img"]) parent_tab.add(self.import_videos_tab, text=f'{"[ Import videos ]": ^20s}', compound="left", image=self.btn_icons["video"]["img"]) parent_tab.add(self.import_data_tab, text=f'{"[ Import tracking data ]": ^20s}', compound="left", image=self.btn_icons["pose"]["img"]) parent_tab.grid(row=0, column=0, sticky=NW) self.settings_frm = CreateLabelFrameWithIcon(parent=self.create_project_tab, header="SETTINGS", icon_name=Keys.DOCUMENTATION.value, icon_link=Links.CREATE_PROJECT.value) self.general_settings_frm = CreateLabelFrameWithIcon(parent=self.settings_frm, header="GENERAL PROJECT SETTINGS", icon_name='settings', icon_link=Links.CREATE_PROJECT.value, padx=5, pady=5, relief='solid') self.project_dir_select = FolderSelect(self.general_settings_frm, "PROJECT DIRECTORY:", lblwidth=35, entry_width=35, font=Formats.FONT_REGULAR.value, lbl_icon='browse', tooltip_key='CREATE_PROJECT_DIR') self.project_name_eb = Entry_Box(self.general_settings_frm, "PROJECT NAME:", labelwidth=35, entry_box_width=35, img='id_card_2', justify='center', tooltip_key='CREATE_PROJECT_NAME') self.file_type_dropdown = SimBADropDown(parent=self.general_settings_frm, dropdown_options=Options.WORKFLOW_FILE_TYPE_OPTIONS.value, label='WORKFLOW FILE TYPE:', label_width=35, dropdown_width=35, value=Options.WORKFLOW_FILE_TYPE_OPTIONS.value[0], img='file_type', tooltip_key='CREATE_PROJECT_FILE_TYPE') self.ml_settings_frm = GetMLSettingsFrame(parent=self.create_project_tab, lbl_width=35, bx_width=22) self.animal_settings_frm = CreateLabelFrameWithIcon(parent=self.create_project_tab, header="ANIMAL SETTINGS", icon_name='pose', icon_link=Links.CREATE_PROJECT.value, font=Formats.FONT_HEADER.value, padx=5, pady=5, relief='solid') self.tracking_type_dropdown = SimBADropDown(parent=self.animal_settings_frm, dropdown_options=Options.TRACKING_TYPE_OPTIONS.value, label='TYPE OF TRACKING', label_width=35, dropdown_width=35, value=Options.TRACKING_TYPE_OPTIONS.value[0], command=self.update_body_part_dropdown, img='category', tooltip_key='CREATE_PROJECT_TRACKING_TYPE') project_animal_cnt_path = os.path.join(os.path.dirname(simba.__file__), Paths.SIMBA_NO_ANIMALS_PATH.value) self.animal_count_lst = list(pd.read_csv(project_animal_cnt_path, header=None)[0]) self.bp_lu = get_body_part_configurations() self.bp_config_codes = get_bp_config_codes() self.classical_tracking_options = deepcopy(Options.CLASSICAL_TRACKING_OPTIONS.value) self.multi_tracking_options = deepcopy(Options.MULTI_ANIMAL_TRACKING_OPTIONS.value) self.three_dim_tracking_options = deepcopy(Options.THREE_DIM_TRACKING_OPTIONS.value) self.user_defined_options = [x for x in list(self.bp_lu.keys()) if x not in self.classical_tracking_options and x not in self.multi_tracking_options and x not in self.three_dim_tracking_options] for k in self.bp_lu.keys(): self.bp_lu[k]["img"] = ImageTk.PhotoImage(file=os.path.join(os.path.dirname("__file__"), self.bp_lu[k]["img_path"])) self.classical_tracking_option_dict = {k: self.bp_lu[k] for k in self.classical_tracking_options} self.multi_tracking_option_dict = {k: self.bp_lu[k] for k in self.multi_tracking_options} self.classical_tracking_options.append(Methods.CREATE_POSE_CONFIG.value) self.multi_tracking_options.append(Methods.CREATE_POSE_CONFIG.value) self.three_dim_tracking_options.append(Methods.CREATE_POSE_CONFIG.value) self.classical_tracking_options.extend(self.user_defined_options) self.multi_tracking_options.extend(self.user_defined_options) self.three_dim_tracking_options.extend(self.user_defined_options) self.selected_tracking_dropdown = SimBADropDown(parent=self.animal_settings_frm, dropdown_options=Options.CLASSICAL_TRACKING_OPTIONS.value, label='BODY-PART CONFIGURATION: ', img='pose_2', label_width=35, dropdown_width=35, value=self.classical_tracking_options[0], command=self.update_img, tooltip_key='CREATE_PROJECT_BP_CONFIG') self.img_lbl = Label(self.animal_settings_frm, image=self.bp_lu[self.classical_tracking_options[0]]["img"], font=Formats.FONT_REGULAR.value) reset_btn = SimbaButton(parent=self.animal_settings_frm, txt="RESET USER DEFINED POSE-CONFIGS", txt_clr='red', img='clean', cmd=PoseResetterPopUp, tooltip_key='CREATE_PROJECT_RESET_POSE_CONFIGS') run_frm = CreateLabelFrameWithIcon(parent=self.create_project_tab, header="CREATE PROJECT CONFIG", icon_name='create', icon_link=Links.CREATE_PROJECT.value) create_project_btn = SimbaButton(parent=run_frm, txt="CREATE PROJECT CONFIG", txt_clr='navy', img='create', font=Formats.FONT_HEADER.value, hover_font=Formats.FONT_HEADER.value, cmd=self.run) self.settings_frm.grid(row=0, column=0, sticky=NW) self.general_settings_frm.grid(row=0, column=0, sticky=NW, pady=5) self.project_dir_select.grid(row=0, column=0, sticky=NW) self.project_name_eb.grid(row=1, column=0, sticky=NW) self.file_type_dropdown.grid(row=2, column=0, sticky=NW) self.animal_settings_frm.grid(row=2, column=0, sticky=NW, pady=5) self.tracking_type_dropdown.grid(row=0, column=0, sticky=NW) self.selected_tracking_dropdown.grid(row=1, column=0, sticky=NW) self.img_lbl.grid(row=2, column=0, sticky=NW) reset_btn.grid(row=0, column=1, sticky=NW) run_frm.grid(row=3, column=0, sticky=NW) create_project_btn.grid(row=0, column=0, sticky=NW) ImportVideosFrame(parent_frm=self.import_videos_tab, config_path=None, idx_row=0, idx_column=0) ImportPoseFrame(parent_frm=self.import_data_tab, config_path=None, idx_row=0, idx_column=0) self.update_body_part_dropdown(Methods.CLASSIC_TRACKING.value) self.main_frm.mainloop()
[docs] def update_body_part_dropdown(self, selected_value): self.selected_tracking_dropdown.destroy() if selected_value == Methods.MULTI_TRACKING.value: self.selected_tracking_dropdown = SimBADropDown(parent=self.animal_settings_frm, dropdown_options=self.multi_tracking_options, label='BODY-PART CONFIGURATION: ', label_width=35, dropdown_width=35, value=self.multi_tracking_options[0], command=self.update_img, img='pose_2', tooltip_key='CREATE_PROJECT_BP_CONFIG') self.selected_tracking_dropdown.grid(row=1, column=0, sticky=NW) elif selected_value == Methods.CLASSIC_TRACKING.value: self.selected_tracking_dropdown = SimBADropDown(parent=self.animal_settings_frm, dropdown_options=self.classical_tracking_options, label='BODY-PART CONFIGURATION: ', label_width=35, dropdown_width=35, value=self.classical_tracking_options[0], command=self.update_img, img='pose_2', tooltip_key='CREATE_PROJECT_BP_CONFIG') self.selected_tracking_dropdown.grid(row=1, column=0, sticky=NW) elif selected_value == Methods.THREE_D_TRACKING.value: self.selected_tracking_dropdown = SimBADropDown(parent=self.animal_settings_frm, dropdown_options=self.three_dim_tracking_options, label='BODY-PART CONFIGURATION: ', label_width=35, dropdown_width=35, value=self.three_dim_tracking_options[0], command=self.update_img, img='pose_2', tooltip_key='CREATE_PROJECT_BP_CONFIG') self.selected_tracking_dropdown.grid(row=1, column=0, sticky=NW) self.update_img(self.selected_tracking_dropdown.getChoices())
[docs] def update_img(self, selected_value): if selected_value != Methods.CREATE_POSE_CONFIG.value: self.img_lbl.config(image=self.bp_lu[selected_value]["img"]) else: _ = CreateUserDefinedPoseConfigurationPopUp(master=self.main_frm, project_config_class=ProjectCreatorPopUp)
[docs] def extract_frames(self): if not hasattr(self, "config_path"): raise MissingProjectConfigEntryError(msg="Create PROJECT CONFIG before extracting frames") video_dir = os.path.join(os.path.dirname(self.config_path), "videos") extract_frames_from_all_videos_in_directory(config_path=self.config_path, directory=video_dir)
[docs] def run(self): project_dir = self.project_dir_select.folder_path check_if_dir_exists(in_dir=project_dir) project_name = self.project_name_eb.entry_get check_str(name="PROJECT NAME", value=project_name, allow_blank=False) target_list = [] for number, entry_box in enumerate(self.ml_settings_frm.clf_entry_boxes): target_list.append(entry_box.entry_get.strip()) if len(list(set(target_list))) != len(self.ml_settings_frm.clf_entry_boxes): raise DuplicationError(msg="ALL classifier NAMES have to be UNIQUE!") selected_config = self.selected_tracking_dropdown.getChoices() if selected_config in self.bp_config_codes.keys(): config_code = self.bp_config_codes[selected_config] else: config_code = Methods.USER_DEFINED.value config_idx = None for cnt, k in enumerate(self.bp_lu.keys()): if k == selected_config: config_idx = cnt animal_cnt = self.animal_count_lst[config_idx] config_creator = ProjectConfigCreator(project_path=project_dir, project_name=project_name, target_list=target_list, pose_estimation_bp_cnt=config_code, body_part_config_idx=config_idx, animal_cnt=animal_cnt, file_type=self.file_type_dropdown.getChoices()) self.config_path = config_creator.config_path ImportPoseFrame(parent_frm=self.import_data_tab, idx_row=0, idx_column=0, config_path=self.config_path) ImportVideosFrame(parent_frm=self.import_videos_tab, config_path=self.config_path, idx_row=0, idx_column=0)
#ProjectCreatorPopUp()