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.
Files changed (237) hide show
  1. jabs_behavior_classifier-0.46.0/LICENSE +21 -0
  2. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/PKG-INFO +20 -17
  3. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/README.md +11 -11
  4. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/pyproject.toml +15 -5
  5. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/classifier/__init__.py +16 -0
  6. jabs_behavior_classifier-0.46.0/src/jabs/classifier/base.py +342 -0
  7. jabs_behavior_classifier-0.46.0/src/jabs/classifier/classifier.py +411 -0
  8. jabs_behavior_classifier-0.46.0/src/jabs/classifier/classifier_utils.py +405 -0
  9. jabs_behavior_classifier-0.46.0/src/jabs/classifier/cross_validation.py +324 -0
  10. jabs_behavior_classifier-0.46.0/src/jabs/classifier/factories.py +160 -0
  11. jabs_behavior_classifier-0.46.0/src/jabs/classifier/mlflow_logging.py +347 -0
  12. jabs_behavior_classifier-0.46.0/src/jabs/classifier/multi_class_classifier.py +552 -0
  13. jabs_behavior_classifier-0.46.0/src/jabs/classifier/training_report.py +465 -0
  14. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/features.py +59 -3
  15. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/lixit.py +98 -19
  16. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/__init__.py +4 -2
  17. jabs_behavior_classifier-0.46.0/src/jabs/project/export_training.py +206 -0
  18. jabs_behavior_classifier-0.46.0/src/jabs/project/parallel_workers.py +407 -0
  19. jabs_behavior_classifier-0.46.0/src/jabs/project/prediction_manager.py +217 -0
  20. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project.py +625 -161
  21. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/read_training.py +71 -0
  22. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/settings_manager.py +67 -1
  23. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/video_labels.py +62 -0
  24. jabs_behavior_classifier-0.46.0/src/jabs/resources/docs/LICENSE +21 -0
  25. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/classifier-types.md +2 -0
  26. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/cli-tools.md +230 -0
  27. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/features.md +4 -0
  28. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/file-formats.md +54 -52
  29. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/gui.md +28 -2
  30. jabs_behavior_classifier-0.46.0/src/jabs/resources/docs/user_guide/imgs/video-context-menu.png +0 -0
  31. jabs_behavior_classifier-0.46.0/src/jabs/resources/docs/user_guide/multi-class.md +64 -0
  32. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/nwb-export.md +64 -55
  33. jabs_behavior_classifier-0.46.0/src/jabs/scripts/classify.py +513 -0
  34. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/cli.py +203 -62
  35. jabs_behavior_classifier-0.46.0/src/jabs/scripts/cli/compute_features.py +151 -0
  36. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/convert_to_nwb.py +95 -7
  37. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/cross_validation.py +76 -1
  38. jabs_behavior_classifier-0.46.0/src/jabs/scripts/cli/update_labels.py +535 -0
  39. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/update_pose.py +98 -34
  40. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/generate_features.py +6 -6
  41. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/gui_entrypoint.py +0 -4
  42. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/__init__.py +19 -0
  43. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/behavior_timeline_widget.py +888 -0
  44. 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
  45. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/__init__.py +14 -0
  46. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/behavior_probability_detail_bar.py +58 -0
  47. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/class_prediction_detail_bar.py +200 -0
  48. 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
  49. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/label_overview_bar.py +376 -0
  50. 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
  51. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/per_class_prediction_track_widget.py +25 -0
  52. jabs_behavior_classifier-0.46.0/src/jabs/ui/behavior_timeline/track_widgets/prediction_track_widget.py +56 -0
  53. 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
  54. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/classification_thread.py +51 -39
  55. jabs_behavior_classifier-0.46.0/src/jabs/ui/classify_strategy.py +183 -0
  56. jabs_behavior_classifier-0.46.0/src/jabs/ui/colors.py +149 -0
  57. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/constants.py +0 -2
  58. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/about_dialog.py +1 -1
  59. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/progress_dialog.py +8 -0
  60. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/user_guide_dialog.py +6 -1
  61. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/export_training_thread.py +25 -11
  62. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/label_count_widget.py +29 -4
  63. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/main_control_widget.py +90 -23
  64. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/central_widget.py +502 -72
  65. jabs_behavior_classifier-0.46.0/src/jabs/ui/main_window/central_widget_mode.py +128 -0
  66. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/main_window.py +11 -21
  67. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/menu_builder.py +47 -0
  68. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/menu_handlers.py +116 -33
  69. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/video_list_widget.py +87 -24
  70. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/frame_with_overlays.py +21 -0
  71. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/annotation_overlay.py +4 -2
  72. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/floating_id_overlay.py +2 -2
  73. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/label_overlay.py +14 -7
  74. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/overlay.py +0 -7
  75. jabs_behavior_classifier-0.46.0/src/jabs/ui/player_widget/overlays/pose_overlay.py +70 -0
  76. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/player_widget.py +107 -2
  77. jabs_behavior_classifier-0.46.0/src/jabs/ui/player_widget/pose_drawing.py +109 -0
  78. jabs_behavior_classifier-0.46.0/src/jabs/ui/settings_dialog/classifier_mode_settings_group.py +103 -0
  79. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/collapsible_section.py +17 -6
  80. jabs_behavior_classifier-0.46.0/src/jabs/ui/settings_dialog/cross_validation_settings_group.py +337 -0
  81. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/settings_dialog.py +162 -4
  82. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/settings_group.py +12 -0
  83. jabs_behavior_classifier-0.46.0/src/jabs/ui/training_strategy.py +347 -0
  84. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/training_thread.py +43 -42
  85. jabs_behavior_classifier-0.44.2/src/jabs/classifier/classifier.py +0 -666
  86. jabs_behavior_classifier-0.44.2/src/jabs/classifier/classifier_utils.py +0 -215
  87. jabs_behavior_classifier-0.44.2/src/jabs/classifier/cross_validation.py +0 -101
  88. jabs_behavior_classifier-0.44.2/src/jabs/classifier/factories.py +0 -62
  89. jabs_behavior_classifier-0.44.2/src/jabs/classifier/training_report.py +0 -320
  90. jabs_behavior_classifier-0.44.2/src/jabs/project/export_training.py +0 -112
  91. jabs_behavior_classifier-0.44.2/src/jabs/project/parallel_workers.py +0 -285
  92. jabs_behavior_classifier-0.44.2/src/jabs/project/prediction_manager.py +0 -134
  93. jabs_behavior_classifier-0.44.2/src/jabs/resources/docs/LICENSE +0 -223
  94. jabs_behavior_classifier-0.44.2/src/jabs/scripts/classify.py +0 -372
  95. jabs_behavior_classifier-0.44.2/src/jabs/ui/colors.py +0 -32
  96. jabs_behavior_classifier-0.44.2/src/jabs/ui/player_widget/overlays/pose_overlay.py +0 -128
  97. jabs_behavior_classifier-0.44.2/src/jabs/ui/settings_dialog/cross_validation_settings_group.py +0 -104
  98. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/__init__.py +0 -12
  99. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/__init__.py +0 -18
  100. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/predicted_label_widget.py +0 -161
  101. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/prediction_overview_widget.py +0 -43
  102. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/timeline_label_widget.py +0 -259
  103. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/label_overview_widget/timeline_prediction_widget.py +0 -65
  104. jabs_behavior_classifier-0.44.2/src/jabs/ui/stacked_timeline_widget/stacked_timeline_widget.py +0 -483
  105. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/behavior_search/__init__.py +0 -0
  106. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/behavior_search/behavior_search_util.py +0 -0
  107. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/classifier/protocols.py +0 -0
  108. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/__init__.py +0 -0
  109. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/angle_index.py +0 -0
  110. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/__init__.py +0 -0
  111. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/angles.py +0 -0
  112. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/angular_velocity.py +0 -0
  113. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/base_group.py +0 -0
  114. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/centroid_velocity.py +0 -0
  115. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/pairwise_distances.py +0 -0
  116. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/point_speeds.py +0 -0
  117. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/base_features/point_velocities.py +0 -0
  118. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/feature_base_class.py +0 -0
  119. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/feature_group_base_class.py +0 -0
  120. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/__init__.py +0 -0
  121. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/corner.py +0 -0
  122. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/food_hopper.py +0 -0
  123. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/landmark_features/landmark_group.py +0 -0
  124. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/__init__.py +0 -0
  125. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/hu_moments.py +0 -0
  126. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/moment_cache.py +0 -0
  127. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/moments.py +0 -0
  128. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/segment_group.py +0 -0
  129. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/segmentation_features/shape_descriptors.py +0 -0
  130. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/__init__.py +0 -0
  131. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/closest_distances.py +0 -0
  132. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/closest_fov_angles.py +0 -0
  133. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/closest_fov_distances.py +0 -0
  134. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/pairwise_social_distances.py +0 -0
  135. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/social_distance.py +0 -0
  136. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/social_features/social_group.py +0 -0
  137. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/window_operations/__init__.py +0 -0
  138. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/window_operations/signal_stats.py +0 -0
  139. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/feature_extraction/window_operations/window_stats.py +0 -0
  140. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/__init__.py +0 -0
  141. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v2.py +0 -0
  142. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v3.py +0 -0
  143. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v4.py +0 -0
  144. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v5.py +0 -0
  145. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v6.py +0 -0
  146. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v7.py +0 -0
  147. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/pose_estimation/pose_est_v8.py +0 -0
  148. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/feature_manager.py +0 -0
  149. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_merge.py +0 -0
  150. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_paths.py +0 -0
  151. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_pruning.py +0 -0
  152. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/project_utils.py +0 -0
  153. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/session_tracker.py +0 -0
  154. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/timeline_annotations.py +0 -0
  155. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/track_labels.py +0 -0
  156. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/project/video_manager.py +0 -0
  157. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/__init__.py +0 -0
  158. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/behavior-search.md +0 -0
  159. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/StackedImgs.svg +0 -0
  160. {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
  161. {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
  162. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/classifier_controls.png +0 -0
  163. {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
  164. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/identity_gaps.png +0 -0
  165. {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
  166. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/keypoint_legend.png +0 -0
  167. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/label_viz.png +0 -0
  168. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/main_window.png +0 -0
  169. {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
  170. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/pose_overlay.png +0 -0
  171. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/search-dialog.png +0 -0
  172. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/selecting_frames.png +0 -0
  173. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/stacked_timeline.png +0 -0
  174. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/timeline_menu.png +0 -0
  175. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/imgs/track_overlay.png +0 -0
  176. {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
  177. {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
  178. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/keyboard-shortcuts.md +0 -0
  179. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/labeling.md +0 -0
  180. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/overview.md +0 -0
  181. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/postprocessing.md +0 -0
  182. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/docs/user_guide/project-setup.md +0 -0
  183. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/eartag_images/s2.svg +0 -0
  184. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/eartag_images/s3.svg +0 -0
  185. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/eartag_images/s4.svg +0 -0
  186. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/fail_whale.png +0 -0
  187. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/resources/icon.png +0 -0
  188. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/schema/__init__.py +0 -0
  189. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/schema/metadata.py +0 -0
  190. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/__init__.py +0 -0
  191. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/__init__.py +0 -0
  192. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/convert_parquet.py +0 -0
  193. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/postprocessing.py +0 -0
  194. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/sample_frames.py +0 -0
  195. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/cli/sample_pose_intervals.py +0 -0
  196. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/initialize_project.py +0 -0
  197. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/scripts/merge_projects.py +0 -0
  198. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/__init__.py +0 -0
  199. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/__init__.py +0 -0
  200. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/annotation_edit_dialog.py +0 -0
  201. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/annotation_info_dialog.py +0 -0
  202. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/archive_behavior_dialog.py +0 -0
  203. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/behavior_search_dialog.py +0 -0
  204. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/license_dialog.py +0 -0
  205. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/message_dialog.py +0 -0
  206. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/project_pruning_dialog.py +0 -0
  207. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/training_report.py +0 -0
  208. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/update_check_dialog.py +0 -0
  209. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/dialogs/video_info_dialog.py +0 -0
  210. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/ear_tag_icons.py +0 -0
  211. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/exceptions.py +0 -0
  212. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_control_widget/__init__.py +0 -0
  213. {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
  214. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/README.md +0 -0
  215. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/__init__.py +0 -0
  216. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/main_window/constants.py +0 -0
  217. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/__init__.py +0 -0
  218. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/__init__.py +0 -0
  219. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/bounding_box.py +0 -0
  220. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/overlays/control_overlay.py +0 -0
  221. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/player_widget/player_thread.py +0 -0
  222. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/project_loader_thread.py +0 -0
  223. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/search_bar_widget.py +0 -0
  224. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/README.md +0 -0
  225. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/__init__.py +0 -0
  226. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/cache_format_settings_group.py +0 -0
  227. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/postprocessing_group.py +0 -0
  228. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/postprocessing_settings/__init__.py +0 -0
  229. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/settings_dialog/session_tracking_group.py +0 -0
  230. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/ui/util.py +0 -0
  231. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/utils/__init__.py +0 -0
  232. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/utils/update_checker.py +0 -0
  233. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/version/__init__.py +0 -0
  234. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/__init__.py +0 -0
  235. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/frame_annotation.py +0 -0
  236. {jabs_behavior_classifier-0.44.2 → jabs_behavior_classifier-0.46.0}/src/jabs/video_reader/utilities.py +0 -0
  237. {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.3
1
+ Metadata-Version: 2.4
2
2
  Name: jabs-behavior-classifier
3
- Version: 0.44.2
3
+ Version: 0.46.0
4
4
  Summary:
5
5
  Author: Glen Beane, Brian Geuther, Keith Sheppard, Alexander Berger-Liedtka
6
- License: Proprietary
7
- Requires-Dist: jabs-behavior==0.44.2
8
- Requires-Dist: jabs-core==0.44.2
9
- Requires-Dist: jabs-io==0.44.2
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
  [![Python 3.10-3.14](https://img.shields.io/badge/python-3.10--3.14-blue.svg)](https://www.python.org/downloads/)
48
53
  [![PyPI version](https://img.shields.io/pypi/v/jabs-behavior-classifier.svg)](https://pypi.org/project/jabs-behavior-classifier/)
49
- [![License: Non-Commercial](https://img.shields.io/badge/license-non--commercial-orange.svg)](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.44.2/LICENSE)
54
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/LICENSE)
50
55
  [![DOI](https://img.shields.io/badge/DOI-10.7554%2FeLife.107259.2-green.svg)](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.44.2/docs/user-guide/overview.md) · [Sample Data](https://doi.org/10.5281/zenodo.16697331) · [Contact Us](mailto:jabs@jax.org)
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
- ![JABS Screenshot](https://raw.githubusercontent.com/KumarLabJax/JABS-behavior-classifier/v0.44.2/docs/assets/images/jabs_screenshot.png)
61
+ ![JABS Screenshot](https://raw.githubusercontent.com/KumarLabJax/JABS-behavior-classifier/v0.46.0/docs/assets/images/jabs_screenshot.png)
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.44.2/vm/README.md)
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.44.2/docs/user-guide/overview.md)** — Markdown documentation
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.44.2/CONTRIBUTING.md)
229
- - [Development Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.44.2/docs/development/development.md)
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 — All rights reserved.
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
- For commercial licensing inquiries, [contact us](mailto:jabs@jax.org).
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
  [![Python 3.10-3.14](https://img.shields.io/badge/python-3.10--3.14-blue.svg)](https://www.python.org/downloads/)
8
10
  [![PyPI version](https://img.shields.io/pypi/v/jabs-behavior-classifier.svg)](https://pypi.org/project/jabs-behavior-classifier/)
9
- [![License: Non-Commercial](https://img.shields.io/badge/license-non--commercial-orange.svg)](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.44.2/LICENSE)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.46.0/LICENSE)
10
12
  [![DOI](https://img.shields.io/badge/DOI-10.7554%2FeLife.107259.2-green.svg)](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.44.2/docs/user-guide/overview.md) · [Sample Data](https://doi.org/10.5281/zenodo.16697331) · [Contact Us](mailto:jabs@jax.org)
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
- ![JABS Screenshot](https://raw.githubusercontent.com/KumarLabJax/JABS-behavior-classifier/v0.44.2/docs/assets/images/jabs_screenshot.png)
18
+ ![JABS Screenshot](https://raw.githubusercontent.com/KumarLabJax/JABS-behavior-classifier/v0.46.0/docs/assets/images/jabs_screenshot.png)
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.44.2/vm/README.md)
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.44.2/docs/user-guide/overview.md)** — Markdown documentation
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.44.2/CONTRIBUTING.md)
189
- - [Development Guide](https://github.com/KumarLabJax/JABS-behavior-classifier/blob/v0.44.2/docs/development/development.md)
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 — All rights reserved.
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
- For commercial licensing inquiries, [contact us](mailto:jabs@jax.org).
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.44.2"
3
+ version = "0.46.0"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10,<3.15"
7
- license = { text = "Proprietary" }
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.44.2",
18
- "jabs-core==0.44.2",
19
- "jabs-io==0.44.2",
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"]
@@ -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"