Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# JAX Animal Behavior System (JABS)

## ReadTheDocs Tutorial

https://jabs-tutorial.readthedocs.io/en/latest/index.html

## Copyright

Copyright 2021 The Jackson Laboratory -- All rights reserved.
Copyright 2023 The Jackson Laboratory -- All rights reserved.

## Contact

Expand All @@ -24,10 +25,10 @@ training data and prediction output, are forthcoming.
## Pose Files

JABS requires pose files generated from the Kumar Lab's mouse pose
estimation neural network. Contact us for more information.
estimation neural networks. Single mouse pose files are generated from [this repository](https://github.com/KumarLabJax/deep-hrnet-mouse). Multi-mouse is still under development. Contact us for more information.

## Requirements
Developed and tested on Python 3.7, 3.8, and 3.9. See the `requirements.txt`
Developed and tested on Python 3.10. See the `requirements.txt`
for a list of required Python packages. These packages are available from the
Python Package Index (PyPI)

Expand Down Expand Up @@ -66,17 +67,6 @@ The virtual environment can be deactivated if you no longer need it:
deactivate
```

### Installing on Apple M1/M2 Silicone

To install the app on Apple's newer M1/M2 macbooks, the user needs to install via [anaconda](https://www.anaconda.com/download#macos)
using the following instructions:

```commandline
conda env create -n jabs -f environment_jabs.yml
conda activate jabs
python app.py
```

#### Enabling XGBoost Classifier

The XGBoost Classifier has a dependency on the OpenMP library. This does
Expand All @@ -87,7 +77,7 @@ can't use Homebrew, but this is beyond the scope of this Readme.

### Windows

Make sure that a compatible version of Python is installed (3.7, 3.8, or 3.9).
Make sure that a compatible version of Python is installed (3.10).

#### Windows Scripts

Expand Down Expand Up @@ -123,3 +113,8 @@ directory and run the following commands:
jabs.venv\Scripts\activate.bat
python app.py
```

### Singularity/Linux

We supply a tested pair of singularity definition files. The [first vm](vm/behavior-classifier-vm.def) is indended for command-line use on compute clusters when scaling inferences. The [second vm](vm/behavior-classifier-gui-vm.def) is designed for interacting with the GUI in a portable environment. Please inspect the definition files for related linux packages to run the software.

9 changes: 2 additions & 7 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@
import argparse
import sys

#### For Mac M1 compatibility ######
import os
os.environ['QT_MAC_WANTS_LAYER'] = '1'
####################################

from PySide2 import QtWidgets
from PySide6 import QtWidgets

from src import APP_NAME, APP_NAME_LONG
from src.ui import MainWindow
Expand All @@ -36,7 +31,7 @@ def main():
main_window.show()
if main_window.show_license_dialog() == QtWidgets.QDialog.Accepted:
# user accepted license terms, run the main application loop
sys.exit(app.exec_())
sys.exit(app.exec())

# user rejected license terms
sys.exit(1)
Expand Down
86 changes: 0 additions & 86 deletions environment_jabs.yml

This file was deleted.

32 changes: 16 additions & 16 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
h5py==3.1.0
joblib==1.0.1
markdown2==2.4.2
numpy==1.21
opencv-python-headless==4.5.1.48
pip-licenses==3.3.1
h5py==3.9.0
joblib==1.3.1
markdown2==2.4.9
numpy==1.25
opencv-python-headless==4.8.0.74
pip-licenses==4.3.2
PTable==0.9.2
PySide2==5.15.2
PySide6==6.2.4
PyYAML==6.0
scikit-learn==0.24.1
scipy==1.6.1
Shapely==1.7.1
shiboken2==5.15.2
six==1.14.0
tabulate==0.8.8
threadpoolctl==2.1.0
unittest-xml-reporting==3.0.2
xgboost==1.2.1
scikit-learn==1.3.0
scipy==1.11.1
Shapely==2.0.1
shiboken6==6.2.4
six==1.16.0
tabulate==0.9.0
threadpoolctl==3.2.0
unittest-xml-reporting==3.2.0
xgboost==1.7.6
2 changes: 1 addition & 1 deletion src/classifier/classifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from src.project import TrackLabels
from src.project import ProjectDistanceUnit

_VERSION = 3
_VERSION = 4


class ClassifierType(IntEnum):
Expand Down
2 changes: 1 addition & 1 deletion src/feature_extraction/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .landmark_features import LandmarkFeatureGroup


FEATURE_VERSION = 4
FEATURE_VERSION = 5

_FEATURE_MODULES = [
BaseFeatureGroup,
Expand Down
2 changes: 1 addition & 1 deletion src/project/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def __init__(self, project_path, use_cache=True, enable_video_check=True):
pose_versions.append(get_pose_file_major_version(pose_path))
static_object_sets.append(set(get_static_objects_in_file(pose_path)))
self._min_pose_version = min(pose_versions) if len(pose_versions) else 0
self._supported_static_objects = set.intersection(*static_object_sets)
self._supported_static_objects = set.intersection(*static_object_sets) if len(static_object_sets) else []

# determine if this project can use social features or not
# if all pose files are V3 or greater, enable social features for this
Expand Down
4 changes: 2 additions & 2 deletions src/ui/about_dialog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from PySide2.QtWidgets import QVBoxLayout, QDialog, QLabel, QPushButton
from PySide2.QtCore import Qt
from PySide6.QtWidgets import QVBoxLayout, QDialog, QLabel, QPushButton
from PySide6.QtCore import Qt

from src.version import version_str

Expand Down
4 changes: 2 additions & 2 deletions src/ui/archive_behavior_dialog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from PySide2.QtWidgets import QVBoxLayout, QHBoxLayout, QDialog, QCheckBox, QPushButton, QComboBox
from PySide2 import QtCore
from PySide6.QtWidgets import QVBoxLayout, QHBoxLayout, QDialog, QCheckBox, QPushButton, QComboBox
from PySide6 import QtCore


class ArchiveBehaviorDialog(QDialog):
Expand Down
2 changes: 1 addition & 1 deletion src/ui/central_widget.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys

import numpy as np
from PySide2 import QtWidgets, QtCore, QtGui
from PySide6 import QtWidgets, QtCore, QtGui
from shapely.geometry import Point

from src.classifier.classifier import Classifier
Expand Down
2 changes: 1 addition & 1 deletion src/ui/classification_thread.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import numpy as np
from PySide2 import QtCore
from PySide6 import QtCore

from src.project import ProjectDistanceUnit
from src.feature_extraction import IdentityFeatures
Expand Down
8 changes: 4 additions & 4 deletions src/ui/frame_labels_widget.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from PySide2.QtCore import QSize, Qt
from PySide2.QtGui import QPainter, QFont, QFontMetrics
from PySide2.QtWidgets import QWidget, QSizePolicy, QApplication
from PySide6.QtCore import QSize, Qt
from PySide6.QtGui import QPainter, QFont, QFontMetrics
from PySide6.QtWidgets import QWidget, QSizePolicy, QApplication


class FrameLabelsWidget(QWidget):
Expand Down Expand Up @@ -90,7 +90,7 @@ def _draw_ticks(self, painter, start, end):
painter.drawRect(offset, 0, 2, 8)

label_text = f"{i}"
label_width = self._font_metrics.width(label_text)
label_width = self._font_metrics.horizontalAdvance(label_text)
painter.setPen(QApplication.palette().text().color())
painter.drawText(offset - label_width/2 + 1,
self._font_height + 8, label_text)
Expand Down
4 changes: 2 additions & 2 deletions src/ui/global_inference_widget.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np
from PySide2.QtCore import Qt
from PySide2.QtGui import QPainter, QPixmap, QColor
from PySide6.QtCore import Qt
from PySide6.QtGui import QPainter, QPixmap, QColor

from src.project import TrackLabels
from .timeline_label_widget import TimelineLabelWidget
Expand Down
2 changes: 1 addition & 1 deletion src/ui/identity_combo_box.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from PySide2 import QtWidgets, QtCore
from PySide6 import QtWidgets, QtCore


class IdentityComboBox(QtWidgets.QComboBox):
Expand Down
4 changes: 2 additions & 2 deletions src/ui/k_fold_slider_widget.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from PySide2 import QtWidgets, QtCore
from PySide2.QtCore import Qt, Signal
from PySide6 import QtWidgets, QtCore
from PySide6.QtCore import Qt, Signal


class KFoldSliderWidget(QtWidgets.QWidget):
Expand Down
4 changes: 2 additions & 2 deletions src/ui/label_count_widget.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import sys


from PySide2 import QtWidgets, QtGui
from PySide2.QtCore import Qt
from PySide6 import QtWidgets, QtGui
from PySide6.QtCore import Qt


class FrameLabelCountWidget(QtWidgets.QWidget):
Expand Down
4 changes: 2 additions & 2 deletions src/ui/license_dialog.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from PySide2.QtCore import Qt
from PySide2.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
QPushButton)

from src import APP_NAME, APP_NAME_LONG
Expand Down
2 changes: 1 addition & 1 deletion src/ui/main_control_widget.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys

from PySide2 import QtWidgets, QtCore
from PySide6 import QtWidgets, QtCore

from src.classifier import Classifier

Expand Down
Loading