diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 9b4ffdf..b6b117e 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -13,7 +13,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.10"] + python-version: ["3.10", "3.11", "3.12"] include: - os: ubuntu-latest path: ~/.cache/pip @@ -21,23 +21,27 @@ jobs: path: ~/Library/Caches/pip - os: windows-latest path: ~\AppData\Local\pip\Cache + exclude: + - os: windows-latest + python-version: "3.11" + - os: windows-latest + python-version: "3.12" steps: - name: Checkout code uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + - name: Install uv + uses: astral-sh/setup-uv@v6 with: + enable-cache: true + version: "0.9.5" python-version: ${{ matrix.python-version }} - - name: Set up Python - uses: conda-incubator/setup-miniconda@v3 - with: - channels: conda-forge,defaults - channel-priority: strict - python-version: ${{ matrix.python-version }} - + - name: Install the project + run: uv sync --all-extras --dev + shell: bash + - name: Install ffmpeg run: | if [ "$RUNNER_OS" == "Linux" ]; then @@ -49,27 +53,9 @@ jobs: choco install ffmpeg fi shell: bash - - - name: Install and test - shell: bash -el {0} # Important: activates the conda environment - run: | - conda install pytables==3.8.0 "numpy<2" - - - name: Install dependencies via Conda - shell: bash -el {0} - run: conda install -y "numpy>=1.26,<2.0" - - - name: Install Poetry - run: pip install --upgrade pip wheel poetry - - - name: Regenerate Poetry lock - run: poetry lock --no-cache - - - name: Install project dependencies - run: poetry install --with dev --extras "tf" --extras "pytorch" - name: Run DLC Live Tests - run: poetry run dlc-live-test --nodisplay + run: uv run dlc-live-test --nodisplay - name: Run Functional Benchmark Test - run: poetry run pytest tests/test_benchmark_script.py + run: uv run pytest tests/test_benchmark_script.py diff --git a/dlclive/display.py b/dlclive/display.py index 8a0bf03..0d1c924 100644 --- a/dlclive/display.py +++ b/dlclive/display.py @@ -5,10 +5,18 @@ Licensed under GNU Lesser General Public License v3.0 """ -from tkinter import Label, Tk +try: + from tkinter import Label, Tk + from PIL import ImageTk + _TKINTER_AVAILABLE = True +except ImportError: + _TKINTER_AVAILABLE = False + Label = None + Tk = None + ImageTk = None import colorcet as cc -from PIL import Image, ImageDraw, ImageTk +from PIL import Image, ImageDraw class Display: @@ -24,6 +32,10 @@ class Display: """ def __init__(self, cmap="bmy", radius=3, pcutoff=0.5): + if not _TKINTER_AVAILABLE: + raise ImportError( + "tkinter is not available. Display functionality requires tkinter. " + ) self.cmap = cmap self.colors = None self.radius = radius @@ -61,6 +73,9 @@ def display_frame(self, frame, pose=None): pose :class:`numpy.ndarray` the pose estimated by DeepLabCut for the image """ + if not _TKINTER_AVAILABLE: + raise ImportError("tkinter is not available. Cannot display frames.") + im_size = (frame.shape[1], frame.shape[0]) if pose is not None: img = Image.fromarray(frame) diff --git a/pyproject.toml b/pyproject.toml index dacfa90..951646b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,66 +1,90 @@ -[tool.poetry] +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + +[project] name = "deeplabcut-live" version = "1.1.0" description = "Class to load exported DeepLabCut networks and perform pose estimation on single frames (from a camera feed)" -authors = ["A. & M. Mathis Labs "] -license = "AGPL-3.0-or-later" readme = "README.md" -homepage = "https://github.com/DeepLabCut/DeepLabCut-live" -repository = "https://github.com/DeepLabCut/DeepLabCut-live" +requires-python = ">=3.10,<3.13" +license = { text = "GNU Affero General Public License v3 or later (AGPLv3+)" } +authors = [ + { name = "A. & M. Mathis Labs", email = "admin@deeplabcut.org" } +] + +keywords = ["deeplabcut", "pose-estimation", "real-time", "deep-learning"] + classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)", - "Operating System :: OS Independent" + "Operating System :: OS Independent", +] + +dependencies = [ + "numpy>=1.20,<2", + "ruamel.yaml>=0.17.20", + "colorcet>=3.0.0", + "einops>=0.6.1", + "Pillow>=8.0.0", + "py-cpuinfo>=5.0.0", + "tqdm>=4.62.3", + "pandas>=1.0.1,!=1.5.0", + "tables>=3.8", + "opencv-python-headless>=4.5", + "dlclibrary>=0.0.6", + "scipy>=1.9", + "pip", +] + +[project.optional-dependencies] +pytorch = [ + "timm>=1.0.7", + "torch>=2.0.0", + "torchvision>=0.15", ] + +tf = [ + "tensorflow>=2.7.0,<2.12; platform_system == 'Linux' and python_version < '3.11'", + "tensorflow>=2.12.0; platform_system == 'Linux' and python_version >= '3.11'", + "tensorflow-macos>=2.7.0,<2.12; platform_system == 'Darwin' and python_version < '3.11'", + "tensorflow-macos>=2.12.0; platform_system == 'Darwin' and python_version >= '3.11'", + # Tensorflow is not supported on Windows with Python >= 3.11 + "tensorflow>=2.7,<=2.10; platform_system == 'Windows' and python_version < '3.11'", + "tensorflow-io-gcs-filesystem==0.27; platform_system == 'Windows' and python_version < '3.11'", + "tensorflow-io-gcs-filesystem; platform_system != 'Windows'", +] + +[dependency-groups] +dev = [ + "pytest", + "black", + "ruff", +] + +# Keep only for backward compatibility with Poetry +# (without this section, Poetry assumes the wrong root directory of the project) +[tool.poetry] packages = [ { include = "dlclive" } ] -include = ["dlclive/check_install/*"] -[tool.poetry.scripts] +[project.scripts] dlc-live-test = "dlclive.check_install.check_install:main" dlc-live-benchmark = "dlclive.benchmark:main" -[tool.poetry.dependencies] -python = ">=3.10,<3.12" -numpy = ">=1.26,<2.0" -"ruamel.yaml" = "^0.17.20" -colorcet = "^3.0.0" -einops = ">=0.6.1" -Pillow = ">=8.0.0" -opencv-python-headless = ">=4.5.0,<5.0.0" -py-cpuinfo = ">=5.0.0" -tqdm = "^4.62.3" -pandas = ">=1.0.1,!=1.5.0" -tables = "^3.8" -pytest = "^8.0" -dlclibrary = ">=0.0.6" +[project.urls] +Homepage = "https://github.com/DeepLabCut/DeepLabCut-live" +Repository = "https://github.com/DeepLabCut/DeepLabCut-live" -# PyTorch models -scipy = ">=1.9" -timm = { version = ">=1.0.7", optional = true } -torch = { version = ">=2.0.0", optional = true } -torchvision = { version = ">=0.15", optional = true } -# TensorFlow models -tensorflow = [ - { version = "^2.7.0,<=2.10", optional = true, platform = "win32" }, - { version = "^2.7.0,<=2.12", optional = true, platform = "linux" }, -] -tensorflow-macos = { version = "^2.7.0,<=2.12", optional = true, markers = "sys_platform == 'darwin'" } -tensorflow-io-gcs-filesystem = [ - { version = "==0.27", optional = true, platform = "win32", python = ">=3.10,<3.11" }, - { version = "*", optional = true, platform = "linux" }, - { version = "*", optional = true, markers = "sys_platform == 'darwin'" } -] +[tool.setuptools] +include-package-data = true -[tool.poetry.extras] -tf = [ "tensorflow", "tensorflow-macos", "tensorflow-io-gcs-filesystem"] -pytorch = ["scipy", "timm", "torch", "torchvision"] +[tool.setuptools.packages.find] +include = ["dlclive*"] -[tool.poetry.group.dev.dependencies] - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" +[tool.setuptools.package-data] +dlclive = ["check_install/*"] \ No newline at end of file diff --git a/reinstall.sh b/reinstall.sh deleted file mode 100755 index 06d4954..0000000 --- a/reinstall.sh +++ /dev/null @@ -1,5 +0,0 @@ -poetry shell # activating current environment -poetry install # creating and installing current project -poetry build # creating the tarball -poetry publish # uploading to pypi -#poetry publish --username= --password= \ No newline at end of file