sleap icon indicating copy to clipboard operation
sleap copied to clipboard

Error occurs during creation of subsequent training configurations and merging predictions in SLEAP GUI

Open amblypatty opened this issue 3 years ago • 5 comments

Bug description

Hi,

I am attempting to create multiple training configuration files with different parameter settings in the SLEAP GUI to export them to a .zip file for remote training. The first training file exports as expected. Then, when I select "Predict>Run Training..." a second time, no window pops up and conda provides an error message:

Traceback (most recent call last):
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\app.py", line 817, in <lambda>
    lambda: self._show_learning_dialog("training"),
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\app.py", line 1696, in _show_learning_dialog
    self._child_windows[mode].skeleton = self.labels.skeleton
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\io\dataset.py", line 565, in skeleton
    "Labels.skeleton can only be used when there is only a single skeleton "
ValueError: Labels.skeleton can only be used when there is only a single skeleton saved in the labels. Use Labels.skeletons instead.

I am confused because there has not been any new skeleton saved. If I close out of the GUI entirely and restart, then I can export another single training configuration file and the second time the same issue arises again. I have experienced this since versions 1.26-1.2.9

The same error occurs when attempting to merge predictions:

Traceback (most recent call last):
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\commands.py", line 554, in mergeProject
    self.execute(MergeProject, filenames=filenames)
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\commands.py", line 240, in execute
    command().execute(context=self, params=kwargs)
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\commands.py", line 133, in execute
    self.ask_and_do(context, params)
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\commands.py", line 2520, in ask_and_do
    MergeDialog(base_labels=context.labels, new_labels=new_labels).exec_()
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\dialogs\merge.py", line 48, in __init__
    if self.base_labels.skeleton.node_names != self.new_labels.skeleton.node_names:
  File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\io\dataset.py", line 565, in skeleton
    "Labels.skeleton can only be used when there is only a single skeleton "
ValueError: Labels.skeleton can only be used when there is only a single skeleton saved in the labels. Use Labels.skeletons instead.

Expected behaviour

Multiple training configurations should be able to be exported

Actual behaviour

Your personal set up

  • OS: Windows 10
  • Version(s): SLEAP v1.2.6-1.2.9
Environment packages
# packages in environment at C:\ProgramData\Anaconda2\envs\sleap129:
#
# Name                    Version                   Build  Channel
absl-py                   0.15.0                   pypi_0    pypi
aom                       3.5.0                h63175ca_0    conda-forge
astunparse                1.6.3                    pypi_0    pypi
attrs                     21.2.0                   pypi_0    pypi
backports-zoneinfo        0.2.1                    pypi_0    pypi
bzip2                     1.0.8                h8ffe710_4    conda-forge
ca-certificates           2022.12.7            h5b45459_0    conda-forge
cached-property           1.5.2                hd8ed1ab_1    conda-forge
cached_property           1.5.2              pyha770c72_1    conda-forge
cachetools                4.2.4                    pypi_0    pypi
cattrs                    1.1.1                    pypi_0    pypi
certifi                   2021.10.8                pypi_0    pypi
charset-normalizer        2.0.12                   pypi_0    pypi
clang                     5.0                      pypi_0    pypi
colorama                  0.4.6                    pypi_0    pypi
commonmark                0.9.1                    pypi_0    pypi
cuda-nvcc                 11.3.58              hb8d16a4_0    nvidia
cudatoolkit               11.3.1              hf2f0253_11    conda-forge
cudnn                     8.2.1.32             h754d62a_0    conda-forge
cycler                    0.11.0                   pypi_0    pypi
efficientnet              1.0.0                    pypi_0    pypi
expat                     2.5.0                h1537add_0    conda-forge
ffmpeg                    5.1.2           gpl_h5b1d025_105    conda-forge
flatbuffers               1.12                     pypi_0    pypi
font-ttf-dejavu-sans-mono 2.37                 hab24e00_0    conda-forge
font-ttf-inconsolata      3.000                h77eed37_0    conda-forge
font-ttf-source-code-pro  2.038                h77eed37_0    conda-forge
font-ttf-ubuntu           0.83                 hab24e00_0    conda-forge
fontconfig                2.14.1               hbde0cde_0    conda-forge
fonts-conda-ecosystem     1                             0    conda-forge
fonts-conda-forge         1                             0    conda-forge
fonttools                 4.38.0                   pypi_0    pypi
freetype                  2.12.1               h546665d_1    conda-forge
gast                      0.4.0                    pypi_0    pypi
geos                      3.9.1                h39d44d4_2    conda-forge
google-auth               1.35.0                   pypi_0    pypi
google-auth-oauthlib      0.4.6                    pypi_0    pypi
google-pasta              0.2.0                    pypi_0    pypi
grpcio                    1.44.0                   pypi_0    pypi
h5py                      3.1.0           nompi_py37h19fda09_100    conda-forge
hdf5                      1.10.6          nompi_he0bbb20_101    conda-forge
hdmf                      3.4.7                    pypi_0    pypi
idna                      3.3                      pypi_0    pypi
image-classifiers         1.0.0                    pypi_0    pypi
imageio                   2.15.0                   pypi_0    pypi
imgaug                    0.4.0                    pypi_0    pypi
imgstore                  0.2.9                    pypi_0    pypi
importlib-metadata        4.11.1                   pypi_0    pypi
importlib-resources       5.10.0                   pypi_0    pypi
intel-openmp              2023.0.0         h57928b3_25922    conda-forge
joblib                    1.2.0                    pypi_0    pypi
jpeg                      9e                   h8ffe710_2    conda-forge
jsmin                     3.0.1                    pypi_0    pypi
jsonpickle                1.2                      pypi_0    pypi
jsonschema                4.17.0                   pypi_0    pypi
keras                     2.6.0                    pypi_0    pypi
keras-applications        1.0.8                    pypi_0    pypi
keras-preprocessing       1.1.2                    pypi_0    pypi
kiwisolver                1.4.4                    pypi_0    pypi
lcms2                     2.12                 h2a16943_0    conda-forge
lerc                      3.0                  h0e60522_0    conda-forge
libblas                   3.9.0              16_win64_mkl    conda-forge
libcblas                  3.9.0              16_win64_mkl    conda-forge
libdeflate                1.10                 h8ffe710_0    conda-forge
libhwloc                  2.8.0                h039e092_1    conda-forge
libiconv                  1.17                 h8ffe710_0    conda-forge
liblapack                 3.9.0              16_win64_mkl    conda-forge
libpng                    1.6.39               h19919ed_0    conda-forge
libsqlite                 3.40.0               hcfcfb64_0    conda-forge
libtiff                   4.3.0                hc4061b1_4    conda-forge
libxml2                   2.10.3               hc3477c8_0    conda-forge
libzlib                   1.2.13               hcfcfb64_4    conda-forge
m2w64-gcc-libgfortran     5.3.0                         6    conda-forge
m2w64-gcc-libs            5.3.0                         7    conda-forge
m2w64-gcc-libs-core       5.3.0                         7    conda-forge
m2w64-gmp                 6.1.0                         2    conda-forge
m2w64-libwinpthread-git   5.0.0.4634.697f757               2    conda-forge
markdown                  3.3.6                    pypi_0    pypi
matplotlib                3.5.3                    pypi_0    pypi
mkl                       2022.1.0           h6a75c08_874    conda-forge
msys2-conda-epoch         20160418                      1    conda-forge
ndx-pose                  0.1.1                    pypi_0    pypi
networkx                  2.6.3                    pypi_0    pypi
numpy                     1.19.5           py37h4c2b6ed_3    conda-forge
oauthlib                  3.2.0                    pypi_0    pypi
olefile                   0.46               pyh9f0ad1d_1    conda-forge
opencv-python             4.5.5.62                 pypi_0    pypi
opencv-python-headless    4.5.5.62                 pypi_0    pypi
openh264                  2.3.1                h63175ca_1    conda-forge
openjpeg                  2.5.0                hb211442_0    conda-forge
openssl                   3.0.7                hcfcfb64_1    conda-forge
opt-einsum                3.3.0                    pypi_0    pypi
packaging                 21.3                     pypi_0    pypi
pandas                    1.3.5            py37h9386db6_0    conda-forge
pillow                    8.4.0            py37hd7d9ad0_0    conda-forge
pip                       22.3.1             pyhd8ed1ab_0    conda-forge
pkgutil-resolve-name      1.3.10                   pypi_0    pypi
protobuf                  3.19.4                   pypi_0    pypi
psutil                    5.9.4                    pypi_0    pypi
pthreads-win32            2.9.1                hfa6e2cd_3    conda-forge
pyasn1                    0.4.8                    pypi_0    pypi
pyasn1-modules            0.2.8                    pypi_0    pypi
pygments                  2.13.0                   pypi_0    pypi
pykalman                  0.9.5                    pypi_0    pypi
pynwb                     2.2.0                    pypi_0    pypi
pyparsing                 3.0.6                    pypi_0    pypi
pyreadline                2.1             py37h03978a9_1006    conda-forge
pyrsistent                0.19.2                   pypi_0    pypi
pyside2                   5.14.1                   pypi_0    pypi
python                    3.7.12          h900ac77_100_cpython    conda-forge
python-dateutil           2.8.2              pyhd8ed1ab_0    conda-forge
python-rapidjson          1.9                      pypi_0    pypi
python_abi                3.7                     3_cp37m    conda-forge
pytz                      2022.7             pyhd8ed1ab_0    conda-forge
pytz-deprecation-shim     0.1.0.post0              pypi_0    pypi
pywavelets                1.3.0                    pypi_0    pypi
pyzmq                     24.0.1                   pypi_0    pypi
qimage2ndarray            1.9.0                    pypi_0    pypi
qtpy                      2.3.0              pyhd8ed1ab_0    conda-forge
requests                  2.27.1                   pypi_0    pypi
requests-oauthlib         1.3.1                    pypi_0    pypi
rich                      10.16.1                  pypi_0    pypi
ruamel-yaml               0.17.21                  pypi_0    pypi
ruamel-yaml-clib          0.2.7                    pypi_0    pypi
scikit-image              0.19.3                   pypi_0    pypi
scikit-learn              1.0.2                    pypi_0    pypi
scikit-video              1.1.11                   pypi_0    pypi
scipy                     1.7.3            py37hb6553fb_0    conda-forge
seaborn                   0.12.1                   pypi_0    pypi
segmentation-models       1.0.1                    pypi_0    pypi
setuptools                59.8.0           py37h03978a9_1    conda-forge
setuptools-scm            6.3.2                    pypi_0    pypi
shapely                   1.7.1            py37hc520ffa_5    conda-forge
shiboken2                 5.14.1                   pypi_0    pypi
six                       1.15.0             pyh9f0ad1d_0    conda-forge
sleap                     1.2.9                    pypi_0    pypi
sqlite                    3.40.0               hcfcfb64_0    conda-forge
svt-av1                   1.4.1                h63175ca_0    conda-forge
tbb                       2021.7.0             h91493d7_1    conda-forge
tensorboard               2.6.0                    pypi_0    pypi
tensorboard-data-server   0.6.1                    pypi_0    pypi
tensorboard-plugin-wit    1.8.1                    pypi_0    pypi
tensorflow                2.6.3                    pypi_0    pypi
tensorflow-estimator      2.6.0                    pypi_0    pypi
termcolor                 1.1.0                    pypi_0    pypi
threadpoolctl             3.1.0                    pypi_0    pypi
tifffile                  2021.11.2                pypi_0    pypi
tk                        8.6.12               h8ffe710_0    conda-forge
tomli                     2.0.1                    pypi_0    pypi
typing-extensions         3.10.0.2                 pypi_0    pypi
tzdata                    2022.6                   pypi_0    pypi
tzlocal                   4.2                      pypi_0    pypi
ucrt                      10.0.22621.0         h57928b3_0    conda-forge
urllib3                   1.26.8                   pypi_0    pypi
vc                        14.3                 h3d8a991_9    conda-forge
vs2015_runtime            14.32.31332          h1d6e394_9    conda-forge
werkzeug                  2.0.3                    pypi_0    pypi
wheel                     0.38.4             pyhd8ed1ab_0    conda-forge
wrapt                     1.12.1                   pypi_0    pypi
x264                      1!164.3095           h8ffe710_2    conda-forge
x265                      3.5                  h2d74725_3    conda-forge
xz                        5.2.6                h8d14728_0    conda-forge
zipp                      3.7.0                    pypi_0    pypi
zlib                      1.2.13               hcfcfb64_4    conda-forge
zstd                      1.5.2                h7755175_4    conda-forge
Logs Anaconda terminal log ``` Traceback (most recent call last): File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\app.py", line 817, in lambda: self._show_learning_dialog("training"), File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\gui\app.py", line 1696, in _show_learning_dialog self._child_windows[mode].skeleton = self.labels.skeleton File "C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\io\dataset.py", line 565, in skeleton "Labels.skeleton can only be used when there is only a single skeleton " ValueError: Labels.skeleton can only be used when there is only a single skeleton saved in the labels. Use Labels.skeletons instead. ```
Logs sleap-diagnostic
(sleap129) C:\Users\psych>sleap-diagnostic

==========SYSTEM==========

utc:                    2022-12-21 20:20:15.505595
python:                 3.7.12
system:                 Windows, AMD64, 10, 10.0.19041
path:                   C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\PySide2;C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\cv2\../../x64/vc14/bin;C:\ProgramData\Anaconda2\envs\sleap129;C:\ProgramData\Anaconda2\envs\sleap129\Library\mingw-w64\bin;C:\ProgramData\Anaconda2\envs\sleap129\Library\usr\bin;C:\ProgramData\Anaconda2\envs\sleap129\Library\bin;C:\ProgramData\Anaconda2\envs\sleap129\Scripts;C:\ProgramData\Anaconda2\envs\sleap129\bin;C:\ProgramData\Anaconda2\condabin;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\libnvvp;C:\Program Files (x86)\Intel\iCLS Client;C:\Program Files\Intel\iCLS Client;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\WINDOWS\System32\OpenSSH;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\WINDOWS\System32\OpenSSH;C:\Program Files\MATLAB\R2022a\bin;.;C:\Program Files\MEGA11;C:\Users\psych\AppData\Local\Microsoft\WindowsApps;C:\PAUP4;C:\ffmpeg;.;C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\scipy\.libs

==========IMPORTS==========

sleap import:                   True
sleap path:                     C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\sleap\__init__.py
sleap version:                  1.2.9
pyside2 import:                 True
pyside path:                    C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\PySide2\__init__.py
call to C:\ProgramData\Anaconda2\envs\sleap129\python.exe failed
C:\ProgramData\Anaconda2\envs\sleap129\python.exe: can't open file 'C:\ProgramData\Anaconda2\envs\sleap129\Scripts\sleap-diagnostic': [Errno 2] No such file or directory

pyside6 import:                 False
cv2 import:                     True

==========GIT==========

unable to locate git
unable to locate git

==========TENSORFLOW==========

tensorflow import:                      True
tensorflow version:                     2.6.3
tensorflow path:                        C:\ProgramData\Anaconda2\envs\sleap129\lib\site-packages\tensorflow\__init__.py
gpus:                   [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

==========CONDA==========

unable to locate conda

==========PIP==========

absl-py==0.15.0
astunparse==1.6.3
attrs==21.2.0
backports.zoneinfo==0.2.1
cached-property @ file:///home/conda/feedstock_root/build_artifacts/cached_property_1615209429212/work
cachetools==4.2.4
cattrs==1.1.1
certifi==2021.10.8
charset-normalizer==2.0.12
clang==5.0
colorama==0.4.6
commonmark==0.9.1
cycler==0.11.0
efficientnet==1.0.0
flatbuffers==1.12
fonttools==4.38.0
gast==0.4.0
google-auth==1.35.0
google-auth-oauthlib==0.4.6
google-pasta==0.2.0
grpcio==1.44.0
h5py @ file:///D:/bld/h5py_1604753757907/work
hdmf==3.4.7
idna==3.3
image-classifiers==1.0.0
imageio==2.15.0
imgaug==0.4.0
imgstore==0.2.9
importlib-metadata==4.11.1
importlib-resources==5.10.0
joblib==1.2.0
jsmin==3.0.1
jsonpickle==1.2
jsonschema==4.17.0
keras==2.6.0
Keras-Applications==1.0.8
Keras-Preprocessing==1.1.2
kiwisolver==1.4.4
Markdown==3.3.6
matplotlib==3.5.3
ndx-pose==0.1.1
networkx==2.6.3
numpy @ file:///D:/bld/numpy_1649281563521/work
oauthlib==3.2.0
olefile @ file:///home/conda/feedstock_root/build_artifacts/olefile_1602866521163/work
opencv-python @ git+https://github.com/talmolab/wrap_opencv-python-headless.git@ede49f6a23a73033216339f29515e59d594ba921
opencv-python-headless==4.5.5.62
opt-einsum==3.3.0
packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1670530880680/work
pandas @ file:///D:/bld/pandas_1639398349358/work
Pillow @ file:///D:/bld/pillow_1636559064986/work
pkgutil_resolve_name==1.3.10
protobuf==3.19.4
psutil==5.9.4
pyasn1==0.4.8
pyasn1-modules==0.2.8
Pygments==2.13.0
pykalman==0.9.5
pynwb==2.2.0
pyparsing==3.0.7
pyreadline @ file:///D:/bld/pyreadline_1655703530615/work
pyrsistent==0.19.2
PySide2==5.14.1
python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1626286286081/work
python-rapidjson==1.9
pytz @ file:///home/conda/feedstock_root/build_artifacts/pytz_1671365381334/work
pytz-deprecation-shim==0.1.0.post0
PyWavelets==1.3.0
PyYAML==6.0
pyzmq==24.0.1
qimage2ndarray==1.9.0
QtPy @ file:///home/conda/feedstock_root/build_artifacts/qtpy_1667873092748/work
requests==2.27.1
requests-oauthlib==1.3.1
rich==10.16.1
rsa==4.8
ruamel.yaml==0.17.21
ruamel.yaml.clib==0.2.7
scikit-image==0.19.3
scikit-learn==1.0.2
scikit-video==1.1.11
scipy @ file:///C:/bld/scipy_1637806996411/work
seaborn==0.12.1
segmentation-models==1.0.1
setuptools-scm==6.4.2
Shapely==1.7.1
shiboken2==5.14.1
six @ file:///home/conda/feedstock_root/build_artifacts/six_1590081179328/work
sleap==1.2.9
tensorboard==2.6.0
tensorboard-data-server==0.6.1
tensorboard-plugin-wit==1.8.1
tensorflow==2.6.3
tensorflow-estimator==2.6.0
termcolor==1.1.0
threadpoolctl==3.1.0
tifffile==2021.11.2
tomli==2.0.1
typing-extensions==3.10.0.2
tzdata==2022.6
tzlocal==4.2
urllib3==1.26.8
Werkzeug==2.0.3
wrapt==1.12.1
zipp==3.7.0


==========NVIDIA==========

unable to locate nvidia-smi

Screenshots

How to reproduce

  1. In SLEAP GUI, Go to 'Predict'
  2. Click on 'Run Training...'
  3. In Training Configuration window, Click on 'Export training job package...'
  4. In SLEAP GUI, Go to 'Predict'
  5. Click on 'Run Training...'
  6. See error in Conda terminal

For Import Predictions:

  1. In SLEAP GUI, Go to 'Merge into Project...'
  2. Select Predictions file and click 'Open'
  3. See error in Conda terminal

amblypatty avatar Dec 21 '22 22:12 amblypatty

Hi @amblypatty,

I am having a bit of trouble replicating the issue. Are you able/willing to share your troublesome project (slp, videos/images) with [email protected] for troubleshooting purposes?

Thanks for writing the very thorough report! Liezl

roomrys avatar Dec 22 '22 22:12 roomrys

Hi @roomrys,

I will send the project package file and video. Thank you for the reply.

Cheers, Patrick

amblypatty avatar Dec 23 '22 00:12 amblypatty

Hi @amblypatty,

The problem

It seems that your project does indeed have two skeletons in it: image which was caused by an old bug that seems to keep haunting us. We will need to develop an automatic script to help users get past this error (but that might mask the root cause if there are any other entry points for the bug).

Previously, the "Load Skeleton" button allowed users to load more than one skeletons into a project - which SLEAP is not ready for yet (different species). Do you recall using the "Load Skeleton" button at any point in the lifetime of the project? Another possible culprit is the "Merge labels into project...", but I did not find the error in that section of code after a first-pass.

I will remove the redundant skeleton and send you back both the slp file and the script used to remove the skeleton.

Why does the Training Pipeline pop-up the first time?

The reason the Training Pipeline pops up the first time is due to this conditional: https://github.com/talmolab/sleap/blob/9ae2941649c81ca5b8e8301ccd99725732599fa5/sleap/gui/app.py#L1616-L1625 where we create a new LearningDialog the first time around which just uses the first Skeleton in the list of Labels.skeletons: https://github.com/talmolab/sleap/blob/9ae2941649c81ca5b8e8301ccd99725732599fa5/sleap/gui/learning/dialog.py#L66-L67 The Training Pipeline fails the second time around because we head into the later part of the conditional: https://github.com/talmolab/sleap/blob/9ae2941649c81ca5b8e8301ccd99725732599fa5/sleap/gui/app.py#L1626-L1635 which references labels.skeleton resulting in an error if there are multiple Skeletons in labels.skeletons.

Related Issues

  • #713
  • #913
  • #1066 (#1063)
  • #1144

Thanks, Liezl

roomrys avatar Jan 12 '23 23:01 roomrys

The script to remove redundant skeletons:

WARNING(S)

I have not tested the case where multiple skeletons are actually used by instances. Always save to an output_path different from the original slp_path - otherwise, you will overwrite your current project.

"""Get rid of redundant Skeletons."""

from typing import Dict, List
from itertools import permutations

import sleap
from sleap import Skeleton, Instance, Labels


def resolve_skeleton_conflicts(
    slp_path, output_path: str = "resolved_skeletons.slp", save: bool = True
) -> Labels:
    """Resolve multiple skeleton conflicts in SLEAP project.

    Args:
        slp_path: The path to the SLEAP project (.slp).
        output_path: The path to save the SLEAP project to if `save` is True (use a
            different path than `slp_path`).
        save: Option to save to a new SLEAP project at `output_path`.

    Raises:
        ValueError: if the script detects that the `Skeleton` conflict was not resolved
            by running this function. If this is raised contact SLEAP support through
            https://github.com/talmolab/sleap for help.

    Returns:
        The `Labels` object with `Skeleton` conflicts resolved.
    """
    # Load the troublesome SLEAP project
    labels = sleap.load_file(slp_path)
    if len(labels.skeletons) <= 1:
        print(
            "\nThere is only one (or less) skeleton(s) in this project. "
            "Nothing to resolve."
        )
        return labels

    # Create a dictionary of all the skeletons in the project
    skeleton_dict: Dict[Skeleton, List[Instance]] = {
        skeleton: [] for skeleton in labels.skeletons
    }

    # Find all instances that use each skeleton
    for lf in labels.labeled_frames:
        for inst in lf.instances:
            skeleton_dict[inst.skeleton].append(inst)

    # Remove unused skeletons from labels
    for skeleton in list(labels.skeletons):
        if len(skeleton_dict[skeleton]) == 0:
            skeleton_dict.pop(skeleton)
            labels.skeletons.pop(labels.skeletons.index(skeleton))
            print(f"\nRemoved unused skeleton:\n{skeleton}")

    if len(labels.skeletons) > 1:
        # Ensure that the skeletons are identical
        for skeleton_a, skeleton_b in permutations(labels.skeletons, 2):
            if not skeleton_a.matches(skeleton_b):
                raise ValueError(
                    "Oh no!"
                    "The skeletons in your project don't have the same nodes!"
                    "Recieved:\n"
                    f"{skeleton_a}\nand:\n"
                    f"{skeleton_b}\n"
                    "Contact SLEAP support through https://github.com/talmolab/sleap for help"
                )

        # Check which Skeleton has the greater number of instances labeled
        n_instances = {}
        max_inst_skeleton = None
        for skeleton, instances in skeleton_dict.items():
            n_instances[skeleton] = len(instances)
            if n_instances[skeleton] >= n_instances.get(skeleton, -1):
                max_inst_skeleton = skeleton

        # Keep the skeleton with the maximum number of instances
        skeleton_dict.pop(max_inst_skeleton, None)
        print(f"\nKeeping skeleton with max number of instances:\n{max_inst_skeleton}")

        # Replace all the skeletons
        for skeleton, instances in skeleton_dict.items():
            for inst in instances:
                inst.skeleton = skeleton
            labels.skeletons.pop(labels.skeletons.index(skeleton))

    try:
        print(f"\nThe remaining skeleton is:\n{labels.skeleton}")
    except Exception as e:
        raise ValueError(
            "Oh no! This script has a bug somewhere... you still have multiple skeletons"
        ) from e

    # Save the new SLEAP project
    if save:
        labels.save_file(labels, output_path)
        print(f"\nSuccess! SLEAP project saved to: {output_path}")

    return labels


if __name__ == "__main__":
    import os

    ds = os.environ["ds-patty"]  # Replace with path to slp file.

    resolve_skeleton_conflicts(ds)

roomrys avatar Jan 13 '23 01:01 roomrys

Flagging this suspicious piece of code (called in Labels.finish_complex_merge) for further inspection: https://github.com/talmolab/sleap/blob/833c2d5bdcf4cfef4e0adc7569b8e2245494a8fa/sleap/io/dataset.py#L469-L479

roomrys avatar Feb 01 '23 23:02 roomrys