Skip to content

Commit

Permalink
uml
Browse files Browse the repository at this point in the history
  • Loading branch information
sronilsson committed Mar 28, 2024
1 parent 500a031 commit 862fc54
Show file tree
Hide file tree
Showing 19 changed files with 644 additions and 1,008 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

setuptools.setup(
name="Simba-UW-tf-dev",
version="1.88.4",
version="1.88.5",
author="Simon Nilsson, Jia Jie Choong, Sophia Hwang",
author_email="sronilsson@gmail.com",
description="Toolkit for computer classification of behaviors in experimental animals",
Expand Down
4 changes: 3 additions & 1 deletion simba/SimBA.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,11 @@ def __init__(self, config_path: str):
processmovementdupLabel,
text="SPONTANEOUS ALTERNATION",
fg="navy",
command=lambda: SpontaneousAlternationPopUp(config_path=self.config_path),
command=lambda: threading.Thread(target=SpontaneousAlternationPopUp(config_path=self.config_path)).start(),
)



# organize
processmovementdupLabel.grid(row=0, column=3, sticky=NW)
analyze_distances_velocity_btn.grid(row=0, sticky=NW)
Expand Down
71 changes: 48 additions & 23 deletions simba/data_processors/spontaneous_alternation_calculator.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import os
import warnings
from typing import List, Optional, Union
import argparse

import numpy as np
import pandas as pd

warnings.filterwarnings("ignore")

from simba.mixins.config_reader import ConfigReader
from simba.mixins.feature_extraction_supplement_mixin import \
FeatureExtractionSupplemental
from simba.mixins.feature_extraction_supplement_mixin import FeatureExtractionSupplemental
from simba.mixins.geometry_mixin import GeometryMixin
from simba.utils.checks import (check_file_exist_and_readable, check_float,
check_if_dir_exists, check_int, check_str,
Expand All @@ -20,6 +20,8 @@
from simba.utils.read_write import (get_file_name_info_in_directory,
get_fn_ext, read_df)
from simba.utils.warnings import NoFileFoundWarning
import platform
import multiprocessing

TAIL_END = "tail_end"

Expand All @@ -46,7 +48,7 @@ class SpontaneousAlternationCalculator(ConfigReader):
:param Optional[float] threshold: Value between 0.0 and 1.0. Body-parts with detection probabilities below this value will be (if possible) filtered when constructing the animal geometry.
:param Optional[int] buffer: Millimeters area for which the animal geometry should be increased in size. Useful if the animal geometry does not fully cover the animal.
:param Optional[bool] detailed_data: If True, saves an additional CSV for each analyzed video with detailed data pertaining each error type and alternation sequence.
:param Optional[Union[str, os.PathLike]] data_path: Directory of path to the file sto be analyzed. If None, then ``project_folder/outlier_corrected_movement_location`` directory.
:param Optional[Union[str, os.PathLike]] data_path: Directory of path to the file to be analyzed. If None, then ``project_folder/outlier_corrected_movement_location`` directory.
:example:
>>> x = SpontaneousAlternationCalculator(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/spontenous_alternation/project_folder/project_config.ini', arm_names=['A', 'B', 'C'], center_name='Center', threshold=0.0, animal_area=100, buffer=2, detailed_data=True)
Expand Down Expand Up @@ -119,11 +121,7 @@ def __init__(
msg=f"{len(files_w_missing_rois)} file(s) at {data_path} are missing ROI definitions and will be skipped when performing spontaneous alternation calculations: {files_w_missing_rois}",
source=__class__.__name__,
)
check_video_has_rois(
roi_dict=self.roi_dict,
video_names=self.files_w_rois,
roi_names=arm_names + [center_name],
)
check_video_has_rois(roi_dict=self.roi_dict, video_names=self.files_w_rois, roi_names=arm_names + [center_name],)
self.file_paths = list(
{file_paths[k] for k in self.files_w_rois if k in file_paths}
)
Expand All @@ -148,9 +146,7 @@ def run(self):
_, self.video_name, _ = get_fn_ext(filepath=file_path)
_, px_per_mm, fps = self.read_video_info(video_name=self.video_name)

self.data_df = read_df(file_path=file_path, file_type=self.file_type).head(
5000
)
self.data_df = read_df(file_path=file_path, file_type=self.file_type)
bp_df = self.data_df[
[
x
Expand Down Expand Up @@ -197,9 +193,8 @@ def run(self):
frames_in_roi = np.zeros(pct_overlap.shape)
frames_in_roi[np.argwhere(pct_overlap >= self.animal_area)] = 1
self.roi_df[geo_name] = frames_in_roi
self.video_results = FeatureExtractionSupplemental.spontaneous_alternations(
data=self.roi_df, arm_names=self.arm_names, center_name=self.center_name
)

self.video_results = FeatureExtractionSupplemental.spontaneous_alternations(data=self.roi_df, arm_names=self.arm_names, center_name=self.center_name)
self.results[self.video_name] = self.video_results

def save(self):
Expand Down Expand Up @@ -267,17 +262,47 @@ def save(self):
msg=f"Detailed spontaneous alternation data for {len(list(self.results.keys()))} video(s) saved at {save_dir}"
)

# if __name__ == "__main__":
# parser = argparse.ArgumentParser(description='SimBA Custom Feature Extractor')
# parser.add_argument('--config_path', type=str, help='SimBA project config path')
# parser.add_argument('--arm_names', nargs='+', help='List of ROI arm names')
# parser.add_argument('--center_name', type=str, help='Name of ROI center')
# parser.add_argument('--animal_area', type=int, default=80, help='Size of animal geometry required for scored entry/exit')
# parser.add_argument('--threshold', type=float, default=0.0, help='Body-part threshold')
# parser.add_argument('--buffer', type=int, default=2, help='Added buffer to animal geometry')
# parser.add_argument('--verbose', type=bool, default=False, help='If process print outs')
# parser.add_argument('--detailed_data', default=False, type=bool, help='If to create additional detailed data')
# parser.add_argument('--data_path', type=bool, default=None, help='Path to directory or file.')
# args = parser.parse_args()
# x = SpontaneousAlternationCalculator(config_path=args.config_path,
# arm_names=args.arm_names,
# center_name=args.center_name,
# threshold=args.threshold,
# animal_area=args.animal_area,
# buffer=args.buffer,
# verbose=args.verbose,
# detailed_data=args.detailed_data,
# data_path=args.data_path)
# x.run()
# x.save()


# x = SpontaneousAlternationCalculator(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/spontenous_alternation/project_folder/project_config.ini',
# arm_names=['A', 'B', 'C'],
# center_name='Center',
# threshold=0.0,
# animal_area=100,
# buffer=2,
# detailed_data=True)
# config_path = '/Users/simon/Desktop/envs/simba/troubleshooting/spontenous_alternation/project_folder/project_config.ini'
# arm_names = ['A', 'B', 'C']
# center_name = 'Center'
# threshold = 0.0
# animal_area = 60
# buffer = 2
# verbose = True
#
# x = SpontaneousAlternationCalculator(config_path=config_path,
# arm_names=arm_names,
# center_name=center_name,
# threshold=threshold,
# animal_area=animal_area,
# buffer=buffer,
# verbose=verbose)
# x.run()
# x.save()

# spontaneous_alternations(config_path='/Users/simon/Desktop/envs/simba/troubleshooting/spontenous_alternation/project_folder/project_config.ini',
# roi_names=['A', 'B', 'C'], body_part='Center')

15 changes: 3 additions & 12 deletions simba/mixins/feature_extraction_supplement_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,18 +472,8 @@ def spontaneous_alternations(
>>> spontanous_alternations = FeatureExtractionSupplemental.spontaneous_alternations(data=df, shape_names=['left', 'top', 'right', 'bottom'])
"""

def get_sliding_alternation(
data: np.ndarray,
) -> Tuple[
Union[
Dict[int, List[int]], Dict[int, List[int]], Dict[Tuple[int], List[int]]
]
]:
stride, same_arm_return_cnt, alternate_arm_return_cnt = (
len(arm_names) - 1,
0,
0,
)
def get_sliding_alternation(data: np.ndarray) -> Tuple[Union[Dict[int, List[int]], Dict[int, List[int]], Dict[Tuple[int], List[int]]]]:
stride, same_arm_return_cnt, alternate_arm_return_cnt = (len(arm_names) - 1, 0, 0)
alternation_cnt = 0
alternations, same_arm_returns, alternate_arm_returns = {}, {}, {}
for i in list(itertools.permutations(arm_names)):
Expand Down Expand Up @@ -571,6 +561,7 @@ def get_sliding_alternation(
same_arm_return_cnt,
alternation_cnt,
) = get_sliding_alternation(data=arm_entry_sequence)

pct_alternation = alternation_cnt / (
arm_entry_sequence.shape[0] - (len(arm_names) - 1)
)
Expand Down

0 comments on commit 862fc54

Please sign in to comment.