jabs-behavior-classifier 0.44.2__tar.gz → 0.46.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jabs_behavior_classifier-0.46.0/LICENSE +21 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/PKG-INFO +20 -17
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/README.md +11 -11
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/pyproject.toml +15 -5
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/classifier/__init__.py +16 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/base.py +342 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/classifier.py +411 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/classifier_utils.py +405 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/cross_validation.py +324 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/factories.py +160 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/mlflow_logging.py +347 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/multi_class_classifier.py +552 -0
- jabs_behavior_classifier-0.46.0/src/jabs/classifier/training_report.py +465 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/features.py +59 -3
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/lixit.py +98 -19
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/__init__.py +4 -2
- jabs_behavior_classifier-0.46.0/src/jabs/project/export_training.py +206 -0
- jabs_behavior_classifier-0.46.0/src/jabs/project/parallel_workers.py +407 -0
- jabs_behavior_classifier-0.46.0/src/jabs/project/prediction_manager.py +217 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project.py +625 -161
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/read_training.py +71 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/settings_manager.py +67 -1
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/video_labels.py +62 -0
- jabs_behavior_classifier-0.46.0/src/jabs/resources/docs/LICENSE +21 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/classifier-types.md +2 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/cli-tools.md +230 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/features.md +4 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/file-formats.md +54 -52
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/gui.md +28 -2
- jabs_behavior_classifier-0.46.0/src/jabs/resources/docs/user_guide/imgs/video-context-menu.png +0 -0
- jabs_behavior_classifier-0.46.0/src/jabs/resources/docs/user_guide/multi-class.md +64 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/nwb-export.md +64 -55
- jabs_behavior_classifier-0.46.0/src/jabs/scripts/classify.py +513 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/cli.py +203 -62
- jabs_behavior_classifier-0.46.0/src/jabs/scripts/cli/compute_features.py +151 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/convert_to_nwb.py +95 -7
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/cross_validation.py +76 -1
- jabs_behavior_classifier-0.46.0/src/jabs/scripts/cli/update_labels.py +535 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/update_pose.py +98 -34
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/generate_features.py +6 -6
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/gui_entrypoint.py +0 -4
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/__init__.py +19 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/behavior_timeline_widget.py +888 -0
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/frame_labels_widget.py → jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/frame_ruler_widget.py +3 -3
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/__init__.py +14 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/behavior_probability_detail_bar.py +58 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/class_prediction_detail_bar.py +200 -0
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/manual_label_widget.py → jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/label_detail_bar.py +116 -78
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/label_overview_bar.py +376 -0
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/label_overview_widget.py → jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/label_track_widget.py +60 -16
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/per_class_prediction_track_widget.py +25 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/prediction_track_widget.py +56 -0
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/label_overview_util.py → jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/timeline_util.py +62 -15
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/classification_thread.py +51 -39
- jabs_behavior_classifier-0.46.0/src/jabs/ui/classify_strategy.py +183 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/colors.py +149 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/constants.py +0 -2
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/about_dialog.py +1 -1
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/progress_dialog.py +8 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/user_guide_dialog.py +6 -1
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/export_training_thread.py +25 -11
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/label_count_widget.py +29 -4
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/main_control_widget.py +90 -23
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/central_widget.py +502 -72
- jabs_behavior_classifier-0.46.0/src/jabs/ui/main_window/central_widget_mode.py +128 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/main_window.py +11 -21
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/menu_builder.py +47 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/menu_handlers.py +116 -33
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/video_list_widget.py +87 -24
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/frame_with_overlays.py +21 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/annotation_overlay.py +4 -2
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/floating_id_overlay.py +2 -2
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/label_overlay.py +14 -7
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/overlay.py +0 -7
- jabs_behavior_classifier-0.46.0/src/jabs/ui/player_widget/overlays/pose_overlay.py +70 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/player_widget.py +107 -2
- jabs_behavior_classifier-0.46.0/src/jabs/ui/player_widget/pose_drawing.py +109 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/settings_dialog/classifier_mode_settings_group.py +103 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/collapsible_section.py +17 -6
- jabs_behavior_classifier-0.46.0/src/jabs/ui/settings_dialog/cross_validation_settings_group.py +337 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/settings_dialog.py +162 -4
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/settings_group.py +12 -0
- jabs_behavior_classifier-0.46.0/src/jabs/ui/training_strategy.py +347 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/training_thread.py +43 -42
- jabs_behavior_classifier-0.44.2/src/jabs/classifier/classifier.py +0 -666
- jabs_behavior_classifier-0.44.2/src/jabs/classifier/classifier_utils.py +0 -215
- jabs_behavior_classifier-0.44.2/src/jabs/classifier/cross_validation.py +0 -101
- jabs_behavior_classifier-0.44.2/src/jabs/classifier/factories.py +0 -62
- jabs_behavior_classifier-0.44.2/src/jabs/classifier/training_report.py +0 -320
- jabs_behavior_classifier-0.44.2/src/jabs/project/export_training.py +0 -112
- jabs_behavior_classifier-0.44.2/src/jabs/project/parallel_workers.py +0 -285
- jabs_behavior_classifier-0.44.2/src/jabs/project/prediction_manager.py +0 -134
- jabs_behavior_classifier-0.44.2/src/jabs/resources/docs/LICENSE +0 -223
- jabs_behavior_classifier-0.44.2/src/jabs/scripts/classify.py +0 -372
- jabs_behavior_classifier-0.44.2/src/jabs/ui/colors.py +0 -32
- jabs_behavior_classifier-0.44.2/src/jabs/ui/player_widget/overlays/pose_overlay.py +0 -128
- jabs_behavior_classifier-0.44.2/src/jabs/ui/settings_dialog/cross_validation_settings_group.py +0 -104
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/__init__.py +0 -12
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/__init__.py +0 -18
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/predicted_label_widget.py +0 -161
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/prediction_overview_widget.py +0 -43
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/timeline_label_widget.py +0 -259
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/timeline_prediction_widget.py +0 -65
- jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/stacked_timeline_widget.py +0 -483
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/behavior_search/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/behavior_search/behavior_search_util.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/classifier/protocols.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/angle_index.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/angles.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/angular_velocity.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/base_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/centroid_velocity.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/pairwise_distances.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/point_speeds.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/point_velocities.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/feature_base_class.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/feature_group_base_class.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/corner.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/food_hopper.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/landmark_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/hu_moments.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/moment_cache.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/moments.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/segment_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/shape_descriptors.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/closest_distances.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/closest_fov_angles.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/closest_fov_distances.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/pairwise_social_distances.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/social_distance.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/social_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/window_operations/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/window_operations/signal_stats.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/window_operations/window_stats.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v2.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v3.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v4.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v5.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v6.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v7.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v8.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/feature_manager.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_merge.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_paths.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_pruning.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_utils.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/session_tracker.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/timeline_annotations.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/track_labels.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/video_manager.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/behavior-search.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/StackedImgs.svg +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/bbox-identity-overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/centroid-identity-overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/classifier_controls.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/floating-identity-overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/identity_gaps.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/identity_gaps_with_label.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/keypoint_legend.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/label_viz.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/main_window.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/minimalist-identity-overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/pose_overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/search-dialog.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/selecting_frames.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/stacked_timeline.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/timeline_menu.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/track_overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/video-control-overlay.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/video-control-overlay.svg +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/keyboard-shortcuts.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/labeling.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/overview.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/postprocessing.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/project-setup.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/eartag_images/s2.svg +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/eartag_images/s3.svg +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/eartag_images/s4.svg +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/fail_whale.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/icon.png +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/schema/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/schema/metadata.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/convert_parquet.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/postprocessing.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/sample_frames.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/sample_pose_intervals.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/initialize_project.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/merge_projects.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/annotation_edit_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/annotation_info_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/archive_behavior_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/behavior_search_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/license_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/message_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/project_pruning_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/training_report.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/update_check_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/video_info_dialog.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/ear_tag_icons.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/exceptions.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/k_fold_slider_widget.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/README.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/constants.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/bounding_box.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/control_overlay.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/player_thread.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/project_loader_thread.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/search_bar_widget.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/README.md +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/cache_format_settings_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/postprocessing_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/postprocessing_settings/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/session_tracking_group.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/util.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/utils/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/utils/update_checker.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/version/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/__init__.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/frame_annotation.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/utilities.py +0 -0
- {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/video_reader.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-2026 The Jackson Laboratory
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: jabs-behavior-classifier
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.46.0
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Glen Beane, Brian Geuther, Keith Sheppard, Alexander Berger-Liedtka
|
|
6
|
-
License:
|
|
7
|
-
|
|
8
|
-
Requires-Dist: jabs-
|
|
9
|
-
Requires-Dist: jabs-
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: jabs-behavior==0.46.0
|
|
9
|
+
Requires-Dist: jabs-core==0.46.0
|
|
10
|
+
Requires-Dist: jabs-io==0.46.0
|
|
10
11
|
Requires-Dist: h5py>=3.10.0,<4.0.0
|
|
11
12
|
Requires-Dist: markdown2>=2.5.1,<3.0.0
|
|
12
13
|
Requires-Dist: numpy>=2.0.0,<3.0.0
|
|
@@ -29,11 +30,13 @@ Requires-Dist: click>=8.2.1
|
|
|
29
30
|
Requires-Dist: argparse-formatter>=1.4
|
|
30
31
|
Requires-Dist: distinctipy>=1.3.4
|
|
31
32
|
Requires-Dist: catboost>=1.2.8
|
|
33
|
+
Requires-Dist: mlflow>=3.8.1 ; extra == 'mlflow'
|
|
32
34
|
Requires-Dist: jabs-io[nwb] ; extra == 'nwb'
|
|
33
35
|
Requires-Dist: pyyaml>=6.0.0 ; extra == 'yaml'
|
|
34
36
|
Requires-Python: >=3.10, <3.15
|
|
35
37
|
Project-URL: Issues, https://github.com/KumarLabJax/JABS-behavior-classifier/issues
|
|
36
38
|
Project-URL: Repository, https://github.com/KumarLabJax/JABS-behavior-classifier
|
|
39
|
+
Provides-Extra: mlflow
|
|
37
40
|
Provides-Extra: nwb
|
|
38
41
|
Provides-Extra: yaml
|
|
39
42
|
Description-Content-Type: text/markdown
|
|
@@ -42,18 +45,20 @@ Description-Content-Type: text/markdown
|
|
|
42
45
|
|
|
43
46
|
# JAX Animal Behavior System (JABS)
|
|
44
47
|
|
|
48
|
+
## JABS Behavior Classifier
|
|
49
|
+
|
|
45
50
|
**An open-source platform for standardized mouse behavioral phenotyping.**
|
|
46
51
|
|
|
47
52
|
[](https://www.python.org/downloads/)
|
|
48
53
|
[](https://pypi.org/project/jabs-behavior-classifier/)
|
|
49
|
-
[](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/LICENSE)
|
|
50
55
|
[](https://doi.org/10.7554/eLife.107259.2)
|
|
51
56
|
|
|
52
|
-
[Documentation](https://jabs-tutorial.readthedocs.io/) · [User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
57
|
+
[Documentation](https://jabs-tutorial.readthedocs.io/) · [User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/docs/user-guide/overview.md) · [Sample Data](https://doi.org/10.5281/zenodo.16697331) · [Contact Us](mailto:jabs@jax.org)
|
|
53
58
|
|
|
54
59
|
---
|
|
55
60
|
|
|
56
|
-

|
|
57
62
|
|
|
58
63
|
</div>
|
|
59
64
|
|
|
@@ -183,7 +188,7 @@ JABS requires pose files generated from the Kumar Lab's mouse pose estimation ne
|
|
|
183
188
|
|
|
184
189
|
We provide Singularity/Apptainer definition files and SLURM batch scripts for running
|
|
185
190
|
JABS on Linux compute clusters. See
|
|
186
|
-
[vm/README.md](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
191
|
+
[vm/README.md](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/vm/README.md)
|
|
187
192
|
for build instructions and usage details.
|
|
188
193
|
|
|
189
194
|
## Project Portability
|
|
@@ -219,14 +224,14 @@ JABS uses four version numbers to track compatibility:
|
|
|
219
224
|
## Documentation
|
|
220
225
|
|
|
221
226
|
- **[ReadTheDocs Tutorial](https://jabs-tutorial.readthedocs.io/)** — Complete user guide and tutorials
|
|
222
|
-
- **[User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
227
|
+
- **[User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/docs/user-guide/overview.md)** — Markdown documentation
|
|
223
228
|
- **[Sample Data](https://doi.org/10.5281/zenodo.16697331)** — Test datasets for demonstration
|
|
224
229
|
|
|
225
230
|
## Contributing
|
|
226
231
|
|
|
227
232
|
Interested in contributing? Check out our:
|
|
228
|
-
- [Contributing Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
229
|
-
- [Development Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
233
|
+
- [Contributing Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/CONTRIBUTING.md)
|
|
234
|
+
- [Development Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/docs/development/development.md)
|
|
230
235
|
|
|
231
236
|
## Citation
|
|
232
237
|
|
|
@@ -236,11 +241,9 @@ If you use JABS in your research, please cite:
|
|
|
236
241
|
|
|
237
242
|
## License
|
|
238
243
|
|
|
239
|
-
Copyright 2023 The Jackson Laboratory
|
|
240
|
-
|
|
241
|
-
JABS is licensed under a **non-commercial use license**. See [LICENSE](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.44.2/LICENSE) for details.
|
|
244
|
+
Copyright (c) 2023-2026 The Jackson Laboratory.
|
|
242
245
|
|
|
243
|
-
|
|
246
|
+
The JABS Behavior Classifier is released under the [MIT License](LICENSE).
|
|
244
247
|
|
|
245
248
|
## Acknowledgements
|
|
246
249
|
|
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
# JAX Animal Behavior System (JABS)
|
|
4
4
|
|
|
5
|
+
## JABS Behavior Classifier
|
|
6
|
+
|
|
5
7
|
**An open-source platform for standardized mouse behavioral phenotyping.**
|
|
6
8
|
|
|
7
9
|
[](https://www.python.org/downloads/)
|
|
8
10
|
[](https://pypi.org/project/jabs-behavior-classifier/)
|
|
9
|
-
[](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/LICENSE)
|
|
10
12
|
[](https://doi.org/10.7554/eLife.107259.2)
|
|
11
13
|
|
|
12
|
-
[Documentation](https://jabs-tutorial.readthedocs.io/) · [User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
14
|
+
[Documentation](https://jabs-tutorial.readthedocs.io/) · [User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/docs/user-guide/overview.md) · [Sample Data](https://doi.org/10.5281/zenodo.16697331) · [Contact Us](mailto:jabs@jax.org)
|
|
13
15
|
|
|
14
16
|
---
|
|
15
17
|
|
|
16
|
-

|
|
17
19
|
|
|
18
20
|
</div>
|
|
19
21
|
|
|
@@ -143,7 +145,7 @@ JABS requires pose files generated from the Kumar Lab's mouse pose estimation ne
|
|
|
143
145
|
|
|
144
146
|
We provide Singularity/Apptainer definition files and SLURM batch scripts for running
|
|
145
147
|
JABS on Linux compute clusters. See
|
|
146
|
-
[vm/README.md](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
148
|
+
[vm/README.md](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/vm/README.md)
|
|
147
149
|
for build instructions and usage details.
|
|
148
150
|
|
|
149
151
|
## Project Portability
|
|
@@ -179,14 +181,14 @@ JABS uses four version numbers to track compatibility:
|
|
|
179
181
|
## Documentation
|
|
180
182
|
|
|
181
183
|
- **[ReadTheDocs Tutorial](https://jabs-tutorial.readthedocs.io/)** — Complete user guide and tutorials
|
|
182
|
-
- **[User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
184
|
+
- **[User Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/docs/user-guide/overview.md)** — Markdown documentation
|
|
183
185
|
- **[Sample Data](https://doi.org/10.5281/zenodo.16697331)** — Test datasets for demonstration
|
|
184
186
|
|
|
185
187
|
## Contributing
|
|
186
188
|
|
|
187
189
|
Interested in contributing? Check out our:
|
|
188
|
-
- [Contributing Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
189
|
-
- [Development Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.
|
|
190
|
+
- [Contributing Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/CONTRIBUTING.md)
|
|
191
|
+
- [Development Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/docs/development/development.md)
|
|
190
192
|
|
|
191
193
|
## Citation
|
|
192
194
|
|
|
@@ -196,11 +198,9 @@ If you use JABS in your research, please cite:
|
|
|
196
198
|
|
|
197
199
|
## License
|
|
198
200
|
|
|
199
|
-
Copyright 2023 The Jackson Laboratory
|
|
200
|
-
|
|
201
|
-
JABS is licensed under a **non-commercial use license**. See [LICENSE](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.44.2/LICENSE) for details.
|
|
201
|
+
Copyright (c) 2023-2026 The Jackson Laboratory.
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
The JABS Behavior Classifier is released under the [MIT License](LICENSE).
|
|
204
204
|
|
|
205
205
|
## Acknowledgements
|
|
206
206
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "jabs-behavior-classifier"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.46.0"
|
|
4
4
|
description = ""
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10,<3.15"
|
|
7
|
-
license =
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
8
9
|
|
|
9
10
|
authors = [
|
|
10
11
|
{ name = "Glen Beane" },
|
|
@@ -14,9 +15,9 @@ authors = [
|
|
|
14
15
|
]
|
|
15
16
|
|
|
16
17
|
dependencies = [
|
|
17
|
-
"jabs-behavior==0.
|
|
18
|
-
"jabs-core==0.
|
|
19
|
-
"jabs-io==0.
|
|
18
|
+
"jabs-behavior==0.46.0",
|
|
19
|
+
"jabs-core==0.46.0",
|
|
20
|
+
"jabs-io==0.46.0",
|
|
20
21
|
"h5py>=3.10.0,<4.0.0",
|
|
21
22
|
"markdown2>=2.5.1,<3.0.0",
|
|
22
23
|
"numpy>=2.0.0,<3.0.0",
|
|
@@ -44,6 +45,7 @@ dependencies = [
|
|
|
44
45
|
[project.optional-dependencies]
|
|
45
46
|
nwb = ["jabs-io[nwb]"]
|
|
46
47
|
yaml = ["pyyaml>=6.0.0"]
|
|
48
|
+
mlflow = ["mlflow>=3.8.1"]
|
|
47
49
|
|
|
48
50
|
[tool.uv.sources]
|
|
49
51
|
jabs-behavior = { workspace = true }
|
|
@@ -91,3 +93,11 @@ build-backend = "uv_build"
|
|
|
91
93
|
[tool.uv.build-backend]
|
|
92
94
|
namespace = true
|
|
93
95
|
module-name = "jabs"
|
|
96
|
+
|
|
97
|
+
[tool.pytest.ini_options]
|
|
98
|
+
# Default to the application test suite under tests/. The reusable library packages
|
|
99
|
+
# under packages/* have their own test suites and are run separately (e.g.
|
|
100
|
+
# `pytest packages/jabs-core/tests`); collecting them together from the repo root
|
|
101
|
+
# fails on cross-package test-module name collisions, which is why CI runs each
|
|
102
|
+
# suite separately. Explicit path arguments override this default.
|
|
103
|
+
testpaths = ["tests"]
|
{jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/classifier/__init__.py
RENAMED
|
@@ -7,20 +7,36 @@ Gradient Boosting, and XGBoost), utilities for feature management, data splittin
|
|
|
7
7
|
|
|
8
8
|
from .classifier import Classifier
|
|
9
9
|
from .cross_validation import run_leave_one_group_out_cv
|
|
10
|
+
from .mlflow_logging import (
|
|
11
|
+
MlflowLoggingError,
|
|
12
|
+
log_cross_validation_to_mlflow,
|
|
13
|
+
mlflow_available,
|
|
14
|
+
parse_kv_tags,
|
|
15
|
+
)
|
|
16
|
+
from .multi_class_classifier import MultiClassClassifier
|
|
10
17
|
from .protocols import ClassifierProtocol
|
|
11
18
|
from .training_report import (
|
|
19
|
+
BinaryCVResult,
|
|
12
20
|
CrossValidationResult,
|
|
21
|
+
MultiClassCVResult,
|
|
13
22
|
TrainingReportData,
|
|
14
23
|
generate_markdown_report,
|
|
15
24
|
save_training_report,
|
|
16
25
|
)
|
|
17
26
|
|
|
18
27
|
__all__ = [
|
|
28
|
+
"BinaryCVResult",
|
|
19
29
|
"Classifier",
|
|
20
30
|
"ClassifierProtocol",
|
|
21
31
|
"CrossValidationResult",
|
|
32
|
+
"MlflowLoggingError",
|
|
33
|
+
"MultiClassCVResult",
|
|
34
|
+
"MultiClassClassifier",
|
|
22
35
|
"TrainingReportData",
|
|
23
36
|
"generate_markdown_report",
|
|
37
|
+
"log_cross_validation_to_mlflow",
|
|
38
|
+
"mlflow_available",
|
|
39
|
+
"parse_kv_tags",
|
|
24
40
|
"run_leave_one_group_out_cv",
|
|
25
41
|
"save_training_report",
|
|
26
42
|
]
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"""Shared infrastructure for behavior classifiers.
|
|
2
|
+
|
|
3
|
+
``BaseClassifier`` consolidates persistence, identity properties, factory
|
|
4
|
+
dispatch, feature cleaning, and feature-importance reporting that are common
|
|
5
|
+
to both binary and multi-class classifiers. Subclasses provide the train and
|
|
6
|
+
predict implementations that determine the actual learning behavior.
|
|
7
|
+
|
|
8
|
+
The class is concrete (not abstract): subclasses are not required to
|
|
9
|
+
override anything to instantiate. Public surface for classifier *consumers*
|
|
10
|
+
is governed by :class:`jabs.classifier.ClassifierProtocol`, which both
|
|
11
|
+
subclasses satisfy structurally.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import typing
|
|
17
|
+
import warnings
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import ClassVar
|
|
20
|
+
|
|
21
|
+
import joblib
|
|
22
|
+
import numpy as np
|
|
23
|
+
import numpy.typing as npt
|
|
24
|
+
import pandas as pd
|
|
25
|
+
from sklearn.exceptions import InconsistentVersionWarning
|
|
26
|
+
|
|
27
|
+
from jabs.core.enums import ClassifierType
|
|
28
|
+
from jabs.core.utils import hash_file
|
|
29
|
+
|
|
30
|
+
from . import classifier_utils, factories
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BaseClassifier:
|
|
34
|
+
"""Shared persistence and identity machinery for JABS classifiers.
|
|
35
|
+
|
|
36
|
+
Class attributes that subclasses must set:
|
|
37
|
+
``_VERSION``: pickled-format version integer for this subclass.
|
|
38
|
+
``_MULTICLASS``: True if this subclass operates in multi-class mode.
|
|
39
|
+
``_PERSISTED_REQUIRED``: tuple of instance attribute names that ``load``
|
|
40
|
+
must restore from the pickled instance.
|
|
41
|
+
``_PERSISTED_OPTIONAL``: tuple of instance attribute names that
|
|
42
|
+
``load`` should restore if present on the pickled instance (default
|
|
43
|
+
to ``None`` otherwise). Used to support older pickles that may not
|
|
44
|
+
have all attributes the live class now declares.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
_VERSION: ClassVar[int] = 0
|
|
48
|
+
_MULTICLASS: ClassVar[bool] = False
|
|
49
|
+
_PERSISTED_REQUIRED: ClassVar[tuple[str, ...]] = ()
|
|
50
|
+
_PERSISTED_OPTIONAL: ClassVar[tuple[str, ...]] = ()
|
|
51
|
+
|
|
52
|
+
def __init__(self, classifier_type: ClassifierType, n_jobs: int = 1) -> None:
|
|
53
|
+
self._classifier_type = classifier_type
|
|
54
|
+
self._classifier: typing.Any = None
|
|
55
|
+
self._project_settings: dict | None = None
|
|
56
|
+
self._feature_names: list[str] | None = None
|
|
57
|
+
self._n_jobs = n_jobs
|
|
58
|
+
self._version = self._VERSION
|
|
59
|
+
|
|
60
|
+
self._classifier_file: str | None = None
|
|
61
|
+
self._classifier_hash: str | None = None
|
|
62
|
+
self._classifier_source: str | None = None
|
|
63
|
+
|
|
64
|
+
self._supported_classifiers = self._supported_classifier_choices()
|
|
65
|
+
if classifier_type not in self._supported_classifiers:
|
|
66
|
+
raise ValueError("Invalid classifier type")
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def classifier_name(self) -> str:
|
|
70
|
+
"""Return the name of the underlying algorithm."""
|
|
71
|
+
return self._classifier_type.value
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def classifier_type(self) -> ClassifierType:
|
|
75
|
+
"""Return the underlying classifier algorithm enum value."""
|
|
76
|
+
return self._classifier_type
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def classifier_file(self) -> str | None:
|
|
80
|
+
"""Return the filename of the saved classifier, if any."""
|
|
81
|
+
return self._classifier_file
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def classifier_hash(self) -> str | None:
|
|
85
|
+
"""Return the content hash of the saved classifier, if any."""
|
|
86
|
+
return self._classifier_hash
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def project_settings(self) -> dict:
|
|
90
|
+
"""Return a copy of the classifier's training settings."""
|
|
91
|
+
if self._project_settings is not None:
|
|
92
|
+
return dict(self._project_settings)
|
|
93
|
+
return {}
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def version(self) -> int:
|
|
97
|
+
"""Return the serialized classifier format version."""
|
|
98
|
+
return self._version
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def feature_names(self) -> list[str] | None:
|
|
102
|
+
"""Return the list of feature names used to train this classifier."""
|
|
103
|
+
return self._feature_names
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def _supported_classifier_choices(cls) -> set[ClassifierType]:
|
|
107
|
+
"""Return classifier types available in the current environment.
|
|
108
|
+
|
|
109
|
+
Resolved per-call so that test code can patch
|
|
110
|
+
:func:`jabs.classifier.factories.supported_classifier_types` or this
|
|
111
|
+
method on the subclass without freezing state at import time.
|
|
112
|
+
"""
|
|
113
|
+
return factories.supported_classifier_types(multiclass=cls._MULTICLASS)
|
|
114
|
+
|
|
115
|
+
def set_classifier(self, classifier: ClassifierType) -> None:
|
|
116
|
+
"""Switch the underlying classifier algorithm.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
classifier: The classifier type to switch to.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
ValueError: If the classifier type is not supported.
|
|
123
|
+
"""
|
|
124
|
+
if classifier not in self._supported_classifier_choices():
|
|
125
|
+
raise ValueError("Invalid Classifier Type")
|
|
126
|
+
self._classifier_type = classifier
|
|
127
|
+
|
|
128
|
+
def set_dict_settings(self, settings: dict) -> None:
|
|
129
|
+
"""Assign classifier settings from a dictionary.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
settings: dict of settings (same structure as
|
|
133
|
+
``project.settings_manager.get_behavior``).
|
|
134
|
+
"""
|
|
135
|
+
self._project_settings = dict(settings)
|
|
136
|
+
|
|
137
|
+
def classifier_choices(self) -> dict[ClassifierType, str]:
|
|
138
|
+
"""Return the available classifier types as a sorted display map.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
dict mapping ``ClassifierType`` enum values to their string names.
|
|
142
|
+
"""
|
|
143
|
+
return {t: t.value for t in sorted(self._supported_classifiers, key=lambda t: t.value)}
|
|
144
|
+
|
|
145
|
+
def _create_classifier(self, random_seed: int | None = None) -> typing.Any:
|
|
146
|
+
"""Instantiate the underlying sklearn/xgboost/catboost classifier."""
|
|
147
|
+
factory = factories.get_factory(self._classifier_type, multiclass=self._MULTICLASS)
|
|
148
|
+
return factory(self._n_jobs, random_seed)
|
|
149
|
+
|
|
150
|
+
def _clean_features(self, features: pd.DataFrame) -> pd.DataFrame:
|
|
151
|
+
"""Replace ±inf/NaN in feature matrix per classifier type."""
|
|
152
|
+
return classifier_utils.clean_features(features, self._classifier_type)
|
|
153
|
+
|
|
154
|
+
def _get_features_to_classify(self, features: pd.DataFrame) -> pd.DataFrame:
|
|
155
|
+
"""Reorder/select feature columns to match the trained model.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
features: DataFrame of feature data to filter.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
DataFrame containing only the columns the trained model expects,
|
|
162
|
+
in the order the model expects them.
|
|
163
|
+
|
|
164
|
+
Raises:
|
|
165
|
+
RuntimeError: If feature names cannot be obtained from the model.
|
|
166
|
+
"""
|
|
167
|
+
if self._classifier_type == ClassifierType.XGBOOST:
|
|
168
|
+
classifier_columns = self._classifier.get_booster().feature_names
|
|
169
|
+
elif hasattr(self._classifier, "feature_names_in_"):
|
|
170
|
+
classifier_columns = list(self._classifier.feature_names_in_)
|
|
171
|
+
elif hasattr(self._classifier, "feature_names_"):
|
|
172
|
+
classifier_columns = list(self._classifier.feature_names_)
|
|
173
|
+
else:
|
|
174
|
+
raise RuntimeError("Error obtaining feature names from classifier.")
|
|
175
|
+
return features[classifier_columns]
|
|
176
|
+
|
|
177
|
+
@staticmethod
|
|
178
|
+
def combine_data(per_frame: pd.DataFrame, window: pd.DataFrame) -> pd.DataFrame:
|
|
179
|
+
"""Combine per-frame and window feature DataFrames into one."""
|
|
180
|
+
return classifier_utils.combine_data(per_frame, window)
|
|
181
|
+
|
|
182
|
+
@staticmethod
|
|
183
|
+
def derive_predictions(
|
|
184
|
+
probabilities: npt.NDArray[np.floating],
|
|
185
|
+
) -> tuple[npt.NDArray[np.int8], npt.NDArray[np.floating]]:
|
|
186
|
+
"""Derive class predictions and confidence from class probabilities.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
probabilities: Array of shape ``(n_frames, n_classes)`` of predicted
|
|
190
|
+
class probabilities.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
Tuple ``(predictions, confidence)`` where ``predictions`` is the
|
|
194
|
+
argmax class index per frame (``-1`` if confidence is zero,
|
|
195
|
+
indicating no pose) and ``confidence`` is the probability of the
|
|
196
|
+
chosen class.
|
|
197
|
+
"""
|
|
198
|
+
predictions = np.argmax(probabilities, axis=1).astype(np.int8)
|
|
199
|
+
confidence = probabilities[np.arange(len(probabilities)), predictions]
|
|
200
|
+
predictions[confidence == 0] = -1
|
|
201
|
+
return predictions, confidence
|
|
202
|
+
|
|
203
|
+
def get_feature_importance(self, limit: int = 20) -> list[tuple[str, float]]:
|
|
204
|
+
"""Return ranked feature importances, highest first.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
limit: Maximum number of features to return.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
List of ``(feature_name, importance)`` tuples sorted by importance
|
|
211
|
+
descending. Returns an empty list if the classifier is untrained or
|
|
212
|
+
does not expose feature importances.
|
|
213
|
+
"""
|
|
214
|
+
if self._classifier is None or self._feature_names is None:
|
|
215
|
+
return []
|
|
216
|
+
if not hasattr(self._classifier, "feature_importances_"):
|
|
217
|
+
return []
|
|
218
|
+
importances = list(np.asarray(self._classifier.feature_importances_).reshape(-1))
|
|
219
|
+
feature_importance = [
|
|
220
|
+
(feature, round(importance, 2))
|
|
221
|
+
for feature, importance in zip(self._feature_names, importances, strict=True)
|
|
222
|
+
]
|
|
223
|
+
feature_importance.sort(key=lambda x: x[1], reverse=True)
|
|
224
|
+
return feature_importance[:limit]
|
|
225
|
+
|
|
226
|
+
def reset_persistence_identity(self) -> None:
|
|
227
|
+
"""Clear the recorded file identity (path, hash, source).
|
|
228
|
+
|
|
229
|
+
``save()`` only (re)computes ``_classifier_hash`` when
|
|
230
|
+
``_classifier_file`` is ``None``, so an already-persisted classifier
|
|
231
|
+
keeps its previous hash even if its contents change. Call this after
|
|
232
|
+
mutating persisted state (e.g. renaming a class) so the next ``save()``
|
|
233
|
+
records a hash matching the rewritten file. ``train()`` performs the
|
|
234
|
+
same null-out after refitting.
|
|
235
|
+
"""
|
|
236
|
+
self._classifier_file = None
|
|
237
|
+
self._classifier_hash = None
|
|
238
|
+
self._classifier_source = None
|
|
239
|
+
|
|
240
|
+
def save(self, path: Path) -> None:
|
|
241
|
+
"""Serialize the classifier to disk using joblib.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
path: Destination file path.
|
|
245
|
+
"""
|
|
246
|
+
joblib.dump(self, path)
|
|
247
|
+
if self._classifier_file is None:
|
|
248
|
+
self._classifier_file = Path(path).name
|
|
249
|
+
self._classifier_hash = hash_file(Path(path))
|
|
250
|
+
self._classifier_source = "serialized"
|
|
251
|
+
|
|
252
|
+
@classmethod
|
|
253
|
+
def from_pickle(cls, path: Path) -> BaseClassifier:
|
|
254
|
+
"""Load a classifier from a pickle file with full validation and metadata backfill.
|
|
255
|
+
|
|
256
|
+
Applies the same version, classifier-type, and metadata checks as
|
|
257
|
+
:meth:`load`, but as a classmethod factory so no dummy instance is
|
|
258
|
+
required. The class of the returned object is determined by the
|
|
259
|
+
calling class - ``Classifier.from_pickle(...)`` rejects pickled
|
|
260
|
+
``MultiClassClassifier`` instances and vice versa.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
path: Path to the saved classifier pickle file.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Loaded and validated classifier instance of type ``cls``.
|
|
267
|
+
|
|
268
|
+
Raises:
|
|
269
|
+
ValueError: If the file is not an instance of ``cls``, was trained
|
|
270
|
+
with an incompatible sklearn or JABS version, or uses an
|
|
271
|
+
unsupported classifier type.
|
|
272
|
+
"""
|
|
273
|
+
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
274
|
+
warnings.simplefilter("always", InconsistentVersionWarning)
|
|
275
|
+
c = joblib.load(path)
|
|
276
|
+
for warning in caught_warnings:
|
|
277
|
+
if issubclass(warning.category, InconsistentVersionWarning):
|
|
278
|
+
raise ValueError("Classifier trained with different version of sklearn.")
|
|
279
|
+
warnings.warn(warning.message, warning.category, stacklevel=2)
|
|
280
|
+
|
|
281
|
+
if not isinstance(c, cls):
|
|
282
|
+
raise ValueError(f"{path} is not an instance of {cls.__name__}")
|
|
283
|
+
|
|
284
|
+
if c._version != cls._VERSION:
|
|
285
|
+
raise ValueError(
|
|
286
|
+
f"Unable to deserialize pickled classifier. "
|
|
287
|
+
f"File version {c._version}, expected {cls._VERSION}."
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
if c._classifier_type not in cls._supported_classifier_choices():
|
|
291
|
+
raise ValueError("Invalid classifier type")
|
|
292
|
+
|
|
293
|
+
if c._classifier_file is None:
|
|
294
|
+
c._classifier_file = Path(path).name
|
|
295
|
+
c._classifier_hash = hash_file(Path(path))
|
|
296
|
+
c._classifier_source = "pickle"
|
|
297
|
+
|
|
298
|
+
return c
|
|
299
|
+
|
|
300
|
+
def load(self, path: Path) -> None:
|
|
301
|
+
"""Deserialize a classifier from disk, updating this instance in place.
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
path: Source file path.
|
|
305
|
+
|
|
306
|
+
Raises:
|
|
307
|
+
ValueError: If the file is not an instance of this class, was saved
|
|
308
|
+
with a different version, or uses an unsupported classifier type.
|
|
309
|
+
"""
|
|
310
|
+
with warnings.catch_warnings(record=True) as caught_warnings:
|
|
311
|
+
warnings.simplefilter("always", InconsistentVersionWarning)
|
|
312
|
+
c = joblib.load(path)
|
|
313
|
+
for warning in caught_warnings:
|
|
314
|
+
if issubclass(warning.category, InconsistentVersionWarning):
|
|
315
|
+
raise ValueError("Classifier trained with different version of sklearn.")
|
|
316
|
+
warnings.warn(warning.message, warning.category, stacklevel=2)
|
|
317
|
+
|
|
318
|
+
if not isinstance(c, type(self)):
|
|
319
|
+
raise ValueError(f"{path} is not an instance of {type(self).__name__}")
|
|
320
|
+
|
|
321
|
+
if c._version != self._VERSION:
|
|
322
|
+
raise ValueError(
|
|
323
|
+
f"Unable to deserialize pickled classifier. "
|
|
324
|
+
f"File version {c._version}, expected {self._VERSION}."
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
if c._classifier_type not in self._supported_classifiers:
|
|
328
|
+
raise ValueError("Invalid classifier type")
|
|
329
|
+
|
|
330
|
+
for attr in self._PERSISTED_REQUIRED:
|
|
331
|
+
setattr(self, attr, getattr(c, attr))
|
|
332
|
+
for attr in self._PERSISTED_OPTIONAL:
|
|
333
|
+
setattr(self, attr, getattr(c, attr, None))
|
|
334
|
+
|
|
335
|
+
if c._classifier_file is not None:
|
|
336
|
+
self._classifier_file = c._classifier_file
|
|
337
|
+
self._classifier_hash = c._classifier_hash
|
|
338
|
+
self._classifier_source = c._classifier_source
|
|
339
|
+
else:
|
|
340
|
+
self._classifier_file = Path(path).name
|
|
341
|
+
self._classifier_hash = hash_file(Path(path))
|
|
342
|
+
self._classifier_source = "pickle"
|