Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some fixes #317

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
163b6e1
checkpoint for computer switching
tzukpolinsky Nov 1, 2023
914aef2
1. added the directionality by body part to the config creation
tzukpolinsky Nov 8, 2023
9559069
Merge remote-tracking branch 'origin/master'
tzukpolinsky Nov 8, 2023
4b98366
preventing error in config creation
tzukpolinsky Nov 12, 2023
1094983
preventing error in seaborn when creating plots, because in seabrom 0…
tzukpolinsky Nov 12, 2023
c4ffdac
I create my body part directionality in a sub folder inside the body_…
tzukpolinsky Nov 13, 2023
219f7cf
I create my body part directionality in a sub folder inside the body_…
tzukpolinsky Nov 13, 2023
ec25329
I create my body part directionality in a sub folder inside the body_…
tzukpolinsky Nov 13, 2023
b374433
changes:
tzukpolinsky Dec 3, 2023
29c3f10
changes:
tzukpolinsky Dec 7, 2023
8d4888c
added max depth and cleaned duplicated values in enums
tzukpolinsky Dec 21, 2023
b965472
Merge pull request #1
tzukpolinsky Dec 21, 2023
6c6bc80
Merge remote-tracking branch 'upstream/master'
tzukpolinsky Dec 21, 2023
d7c31ff
trying to merge
tzukpolinsky Dec 21, 2023
0163e02
Merge branch 'master' of https://github.com/tzukpolinsky/simba
tzukpolinsky Dec 21, 2023
a43553b
trying to merge
tzukpolinsky Dec 23, 2023
0a54a82
Merge branch 'master' of https://github.com/sgoldenlab/simba
tzukpolinsky Dec 23, 2023
e826fda
Merge branch 'master' of https://github.com/sgoldenlab/simba
tzukpolinsky Jan 1, 2024
3899965
fixing missing files paths for app visibility
tzukpolinsky Jan 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions simba/SimBA.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import os.path
import warnings

from simba.ui.pop_ups.append_bodypart_directionality_features_pop_up import AppendBodyPartDirectionalityFeaturesPopUp

warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=DeprecationWarning)
from simba.ui.pop_ups.direction_animal_to_bodypart_settings_pop_up import DirectionAnimalToBodyPartSettingsPopUp
Expand Down Expand Up @@ -140,7 +142,7 @@

# from simba.unsupervised.unsupervised_ui import UnsupervisedGUI

sys.setrecursionlimit(10**6)
sys.setrecursionlimit(10 ** 6)
currentPlatform = platform.system()


Expand Down Expand Up @@ -597,6 +599,14 @@ def activate(box, *args):
config_path=self.config_path
),
)
append_body_part_directionality_features = Button(
roi_feature_frm,
text="APPEND BODY PART DIRECTIONALITY DATA TO FEATURES (CAUTION)",
fg="green",
command=lambda: AppendBodyPartDirectionalityFeaturesPopUp(
config_path=self.config_path
),
)
# remove_roi_features_from_feature_set = Button(
# roi_feature_frm,
# text="REMOVE ROI FEATURES FROM FEATURE SET",
Expand Down Expand Up @@ -1145,6 +1155,7 @@ def activate(box, *args):
roi_feature_frm.grid(row=1, column=0, sticky=NW)
append_roi_features_by_animal.grid(row=0, column=0, sticky=NW)
append_roi_features_by_body_part.grid(row=1, column=0, sticky=NW)
append_body_part_directionality_features.grid(row=2, column=0, sticky=NW)
# remove_roi_features_from_feature_set.grid(row=2, column=0, sticky=NW)

feature_tools_frm.grid(row=2, column=0, sticky=NW)
Expand Down Expand Up @@ -1255,7 +1266,6 @@ def directing_other_animals_analysis(self):
def directing_animal_to_bp_analysis(self):
_ = DirectionAnimalToBodyPartSettingsPopUp(config_path=self.config_path)


def directing_other_animals_visualizer(self):
_ = DirectingOtherAnimalsVisualizerPopUp(config_path=self.config_path)

Expand Down
13 changes: 7 additions & 6 deletions simba/data_processors/directing_animal_to_bodypart.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def create_directionality_dfs(self):
for animal_permutation, permutation_data in video_data.items():
for bp_name, bp_data in permutation_data.items():
directing_df = (
bp_data#[bp_data["Directing_BOOL"] == 1]
bp_data # [bp_data["Directing_BOOL"] == 1]
.reset_index()
.rename(
columns={
Expand Down Expand Up @@ -194,14 +194,15 @@ def save_directionality_dfs(self):
-------
None
"""
if not os.path.exists(self.body_part_directionality_df_dir):
os.makedirs(self.body_part_directionality_df_dir)
output_dir = os.path.join(self.body_part_directionality_df_dir, self.bodypart_direction)
if not os.path.exists(output_dir):
os.makedirs(output_dir)
for video_name, video_data in self.directionality_df_dict.items():
save_name = os.path.join(self.body_part_directionality_df_dir, video_name + ".csv")
save_name = os.path.join(output_dir, video_name + ".csv")
video_data.to_csv(save_name)
print(f"Detailed directional data saved for video {video_name}...")
stdout_success(
msg=f"All detailed directional data saved in the {self.body_part_directionality_df_dir} directory"
msg=f"All detailed directional data saved in the {output_dir} directory"

)

Expand Down Expand Up @@ -238,7 +239,7 @@ def summary_statistics(self):
.set_index("Video")
)
self.save_path = os.path.join(
self.logs_path, "Body_part_directions_data_{}.csv".format(str(self.datetime))
self.logs_path, "Body_part_directions_data_{}_{}.csv".format(str(self.bodypart_direction, self.datetime))
)
self.summary_df.to_csv(self.save_path)
self.timer.stop_timer()
Expand Down
88 changes: 56 additions & 32 deletions simba/mixins/pop_up_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ class PopUpMixin(object):
"""

def __init__(
self,
title: str,
config_path: Optional[str] = None,
size: Tuple[int, int] = (960,720),
self,
title: str,
config_path: Optional[str] = None,
size: Tuple[int, int] = (960, 720),
):
self.root = Toplevel()
self.root.minsize(size[0], size[1])
Expand Down Expand Up @@ -92,7 +92,7 @@ def create_clf_checkboxes(self, main_frm: Frame, clfs: List[str]):
self.choose_clf_frm.grid(row=self.children_cnt_main(), column=0, sticky=NW)

def create_cb_frame(
self, main_frm: Frame, cb_titles: List[str], frm_title: str
self, main_frm: Frame, cb_titles: List[str], frm_title: str
) -> Dict[str, BooleanVar]:
cb_frm = LabelFrame(
main_frm, text=frm_title, font=Formats.LABELFRAME_HEADER_FORMAT.value
Expand All @@ -106,11 +106,11 @@ def create_cb_frame(
return cb_dict

def create_dropdown_frame(
self,
main_frm: Frame,
drop_down_titles: List[str],
drop_down_options: List[str],
frm_title: str,
self,
main_frm: Frame,
drop_down_titles: List[str],
drop_down_options: List[str],
frm_title: str,
):
dropdown_frm = LabelFrame(
main_frm, text=frm_title, font=Formats.LABELFRAME_HEADER_FORMAT.value
Expand Down Expand Up @@ -209,8 +209,33 @@ def create_run_frm(self, run_function: object, title: str = "RUN"):
self.run_frm.grid(row=self.children_cnt_main() + 1, column=0, sticky=NW)
self.run_btn.grid(row=0, column=0, sticky=NW)

def create_choose_number_of_body_parts_directionality_frm(
self, path_to_directionality_dir: str, run_function: object
):
self.bp_cnt_frm = LabelFrame(
self.main_frm,
text="SELECT DIR",
font=Formats.LABELFRAME_HEADER_FORMAT.value,
)
root, types_of_directionality, files = list(os.walk(path_to_directionality_dir))[0]
self.bp_cnt_dropdown = DropDownMenu(
self.bp_cnt_frm,
"# of body-parts directionality",
list(types_of_directionality),
"20",
)
self.bp_cnt_dropdown.setChoices(types_of_directionality[0])
self.bp_cnt_confirm_btn = Button(
self.bp_cnt_frm,
text="Confirm",
command=lambda: run_function,
)
self.bp_cnt_frm.grid(row=0, sticky=NW)
self.bp_cnt_dropdown.grid(row=0, column=0, sticky=NW)
self.bp_cnt_confirm_btn.grid(row=0, column=1, sticky=NW)

def create_choose_number_of_body_parts_frm(
self, project_body_parts: List[str], run_function: object
self, project_body_parts: List[str], run_function: object
):
self.bp_cnt_frm = LabelFrame(
self.main_frm,
Expand Down Expand Up @@ -244,7 +269,7 @@ def add_value_to_listbox(self, list_box: Listbox, value: float):
list_box.insert(0, value)

def add_values_to_several_listboxes(
self, list_boxes: List[Listbox], values: List[float]
self, list_boxes: List[Listbox], values: List[float]
):
if len(list_boxes) != len(values):
raise CountError(msg="Value count and listboxes count are not equal")
Expand All @@ -270,7 +295,7 @@ def create_choose_bp_frm(self, project_body_parts, run_function):
for bp_cnt in range(int(self.bp_cnt_dropdown.getChoices())):
self.body_parts_dropdowns[bp_cnt] = DropDownMenu(
self.body_part_frm,
f"Body-part {str(bp_cnt+1)}:",
f"Body-part {str(bp_cnt + 1)}:",
project_body_parts,
"25",
)
Expand Down Expand Up @@ -326,7 +351,7 @@ def choose_bp_threshold_frm(self, parent: LabelFrame):
self.probability_entry.grid(row=0, column=0, sticky=NW)

def enable_dropdown_from_checkbox(
self, check_box_var: BooleanVar, dropdown_menus: List[DropDownMenu]
self, check_box_var: BooleanVar, dropdown_menus: List[DropDownMenu]
):
if check_box_var.get():
for menu in dropdown_menus:
Expand All @@ -336,13 +361,13 @@ def enable_dropdown_from_checkbox(
menu.disable()

def create_entry_boxes_from_entrybox(
self, count: int, parent: Frame, current_entries: list
self, count: int, parent: Frame, current_entries: list
):
check_int(name="CLASSIFIER COUNT", value=count, min_value=1)
for entry in current_entries:
entry.destroy()
for clf_cnt in range(int(count)):
entry = Entry_Box(parent, f"Classifier {str(clf_cnt+1)}:", labelwidth=15)
entry = Entry_Box(parent, f"Classifier {str(clf_cnt + 1)}:", labelwidth=15)
current_entries.append(entry)
entry.grid(row=clf_cnt + 2, column=0, sticky=NW)

Expand All @@ -353,12 +378,12 @@ def create_animal_names_entry_boxes(self, animal_cnt: str):
if not hasattr(self, "multi_animal_id_list"):
self.multi_animal_id_list = []
for i in range(int(animal_cnt)):
self.multi_animal_id_list.append(f"Animal {i+1}")
self.multi_animal_id_list.append(f"Animal {i + 1}")
self.animal_names_frm = Frame(self.animal_settings_frm, pady=5, padx=5)
self.animal_name_entry_boxes = {}
for i in range(int(animal_cnt)):
self.animal_name_entry_boxes[i + 1] = Entry_Box(
self.animal_names_frm, f"Animal {str(i+1)} name: ", "25"
self.animal_names_frm, f"Animal {str(i + 1)} name: ", "25"
)
if i <= len(self.multi_animal_id_list) - 1:
self.animal_name_entry_boxes[i + 1].entry_set(
Expand All @@ -369,10 +394,10 @@ def create_animal_names_entry_boxes(self, animal_cnt: str):
self.animal_names_frm.grid(row=1, column=0, sticky=NW)

def enable_entrybox_from_checkbox(
self,
check_box_var: BooleanVar,
entry_boxes: List[Entry_Box],
reverse: bool = False,
self,
check_box_var: BooleanVar,
entry_boxes: List[Entry_Box],
reverse: bool = False,
):
if reverse:
if check_box_var.get():
Expand All @@ -390,16 +415,16 @@ def enable_entrybox_from_checkbox(
box.set_state("disable")

def create_import_pose_menu(
self, parent_frm: Frame, idx_row: int = 0, idx_column: int = 0
self, parent_frm: Frame, idx_row: int = 0, idx_column: int = 0
):
def run_call(
data_type: str,
interpolation: str,
smoothing: str,
smoothing_window: str,
animal_names: dict,
data_path: str,
tracking_data_type: str or None = None,
data_type: str,
interpolation: str,
smoothing: str,
smoothing_window: str,
animal_names: dict,
data_path: str,
tracking_data_type: str or None = None,
):
smooth_settings = {}
smooth_settings["Method"] = smoothing
Expand Down Expand Up @@ -880,7 +905,7 @@ def import_menu(data_type_choice: str):
self.data_type_dropdown.grid(row=0, column=0, sticky=NW)

def create_import_videos_menu(
self, parent_frm: Frame, idx_row: int = 0, idx_column: int = 0
self, parent_frm: Frame, idx_row: int = 0, idx_column: int = 0
):
def run_import(multiple_videos: bool):
if multiple_videos:
Expand Down Expand Up @@ -991,7 +1016,6 @@ def run_import(multiple_videos: bool):
# #self.main_frm.config(width=e.x_root, height=e.y_root)
# #self.main_frm.update()


# test = PopUpMixin(config_path='/Users/simon/Desktop/envs/troubleshooting/two_animals_16bp_032023/project_folder/project_config.ini',
# title='ss')
# test.create_import_pose_menu(parent_frm=test.main_frm)
Expand Down
2 changes: 2 additions & 0 deletions simba/pose_configurations/bp_names/bp_names.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ Ear_left_1,Ear_right_1,Nose_1,Tail_base_1,Ear_left_2,Right_ear_2,Nose_2,Tail_bas
Ear_left_1,Ear_right_1,Nose_1,Center_1,Lat_left_1,Lat_right_1,Tail_base_1,Ear_left_2,Ear_right_2,Nose_2,Center_2,Lat_left_2,Lat_right_2,Tail_base_2,,
Ear_left_1,Ear_right_1,Nose_1,Center_1,Lat_left_1,Lat_right_1,Tail_base_1,Tail_end_1,Ear_left_2,Ear_right_2,Nose_2,Center_2,Lat_left_2,Lat_right_2,Tail_base_2,Tail_end_2
3D,,,,,,,,,,,,,,,
nose,left_ear,right_ear,tail_base,bug_center
nose,right_hand,left_hand,right_leg,left_leg,tail_base
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove these two lines and revert to original bp_names.csv otherwise others get to see your body-part configs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, my bad

Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ Multi-animals; 4 body-parts
Multi-animals; 7 body-parts
Multi-animals; 8 body-parts
3D tracking
mouse_and_bug
from_below
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, my bad

2 changes: 2 additions & 0 deletions simba/pose_configurations/no_animals/no_animals.csv
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
2
2
1
1
1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, my bad

13 changes: 7 additions & 6 deletions simba/pose_importers/dlc_importer_csv.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻 I know in development this FileExistError can be a bit of a headache :) but a bit nervous about about letting users overwrite previous data by mistake.

Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@ def import_dlc_csv(config_path: Union[str, os.PathLike], source: str) -> List[st
new_file_name_wo_ext = new_file_name.split(".")[0]
video_basename = os.path.basename(file_path)
print(f"Importing {video_name} to SimBA project...")
if new_file_name_wo_ext in imported_file_names:
raise FileExistError(
"SIMBA IMPORT ERROR: {} already exist in project. Remove file from project or rename imported video file name before importing.".format(
new_file_name
)
)
#if new_file_name_wo_ext in imported_file_names:
# raise FileExistError(
# "SIMBA IMPORT ERROR: {} already exist in project. Remove file from project or rename imported video file name before importing.".format(
# new_file_name
# )
# )

shutil.copy(file_path, input_csv_dir)
shutil.copy(file_path, original_file_name_dir)
os.rename(
Expand Down
59 changes: 59 additions & 0 deletions simba/ui/pop_ups/append_bodypart_directionality_features_pop_up.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
__author__ = "Tzuk Polinsky"

import glob
import os

import pandas

from simba.mixins.config_reader import ConfigReader
from simba.mixins.pop_up_mixin import PopUpMixin
from simba.roi_tools.ROI_feature_analyzer import ROIFeatureCreator
from simba.utils.errors import NoROIDataError


class AppendBodyPartDirectionalityFeaturesPopUp(PopUpMixin, ConfigReader):
def __init__(self, config_path: str):
PopUpMixin.__init__(self, config_path=config_path, title="APPEND BODY PART DIRECTIONALITY FEATURES")
ConfigReader.__init__(self, config_path=config_path)
if not os.path.isfile(self.roi_coordinates_path):
raise NoROIDataError(
msg="SIMBA ERROR: No ROIs have been defined. Please define ROIs before appending ROI-based features"
)
self.create_choose_number_of_body_parts_directionality_frm(
path_to_directionality_dir=self.body_part_directionality_df_dir, run_function=self.run
)
# self.main_frm.mainloop()

def run(self):
settings = {}
settings["body_parts_directionality"] = {}
for bp_cnt, bp_dropdown in self.bp_cnt_dropdown.items():
settings["body_parts_directionality"] = bp_dropdown.getChoices()
directionality_data_path = os.path.join(self.body_part_directionality_df_dir,
settings["body_parts_directionality"])
data_dic = {}
for root, dirs, files in os.walk(directionality_data_path):
for file in files:
data = pandas.read_csv(os.path.join(root, file))["Directing_BOOL"]
data_dic[file] = data
files_found = glob.glob(
self.outlier_corrected_dir + "/*." + self.file_type
)
concatenate_data = {}
for file in files_found:
data = pandas.read_csv(os.path.join(root, file))
c_data = pandas.concat([data, data_dic[file]])
concatenate_data[file] = c_data
for file_name, data in concatenate_data.items():
save_path = os.path.join(
self.features_dir, file_name + "." + self.file_type
)
data.to_csv(save_path)

# roi_feature_creator = ROIFeatureCreator(
# config_path=self.config_path, settings=settings
# )
# roi_feature_creator.run()
# roi_feature_creator.save()

# _ = AppendROIFeaturesByBodyPartPopUp(config_path='/Users/simon/Desktop/envs/troubleshooting/two_animals_16bp_032023/project_folder/project_config.ini')