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()