talmolab / sleap

A deep learning framework for multi-animal pose tracking.
https://sleap.ai
Other
435 stars 96 forks source link

Loading new skeleton from file causes labels to contain multiple conflicting skeletons #713

Closed e-velin closed 2 years ago

e-velin commented 2 years ago

Hi,

I'm trying to merge two sleap projects. In both of the projects I used the same skeleton but in the first project initially I annotated the head as well, later I decided I don't need that and deleted it. Now I can see that the skeleton file still contains the head but on the annotated frames they are not visible. When I'm trying to merge the two projects, I get the error message 'ValueError: Labels.skeleton can only be used when there is only a single skeleton saved in the labels. Use Labels.skeletons instead.' So I tried to load in into the first project a clean skeleton json file without that does not contain the head (the skeleton file that I saved from the second project). The skeleton number doesn't change in the GUI to the number of the loaded skeleton, but if I save the skeleton file into a new json file, the new, loaded skeleton number will appear. Yet, I get the same error message when I try to merge the two projects. However, when I close the first project and reopen it, it still contains the old skeleton file with the head node, even when I save the skeleton into a json file. Can you help with this please? This happens both is v1.1.5 and v1.2.2.

Similar to this: https://github.com/murthylab/sleap/issues/592

roomrys commented 2 years ago

Hi @e-velin,

I was able to replicate the error above - thanks for providing such detail. This seems like a bug on our part - i.e. not updating the skeleton in the Labels object when making changes to the skeleton in the GUI. I am still investigating and will let you know of fix as soon as I find one, but am posting the steps that lead to the error and the resulting error message below:

Project 1: Edit and Save Skeleton in GUI

  1. Open a project which was already labeled.
  2. Remove a node from the skeleton in the project.
  3. Save the project using "Save" in the GUI.
  4. Save the skeleton via "Save Skeleton" in the GUI.
  5. Load the skeleton that was just saved via "Load Skeleton" on the GUI.
  6. Save the project using "Save" in the GUI.

Project 2: New Project with Saved Skeleton

  1. Open sleap-label and imported a video via "Add Video".
  2. Load the skeleton that was saved in previous section via "Load Skeleton" in the GUI.
  3. Add a few instances of the skeleton.
  4. Save the project using "Save" in the GUI.
  5. (Attempt to) merge the project with Project 1 via "Merge into project" in the GUI.
  6. Obtain error message below.
Traceback (most recent call last):
  File "d:\social-leap-estimates-animal-poses\pull-requests\label-sug-speedup\sleap\sleap\gui\commands.py", line 537, in mergeProject
    self.execute(MergeProject, filenames=filenames)
  File "d:\social-leap-estimates-animal-poses\pull-requests\label-sug-speedup\sleap\sleap\gui\commands.py", line 236, in execute
    command().execute(context=self, params=kwargs)
  File "d:\social-leap-estimates-animal-poses\pull-requests\label-sug-speedup\sleap\sleap\gui\commands.py", line 129, in execute
    self.ask_and_do(context, params)
  File "d:\social-leap-estimates-animal-poses\pull-requests\label-sug-speedup\sleap\sleap\gui\commands.py", line 2111, in ask_and_do
    MergeDialog(base_labels=context.labels, new_labels=new_labels).exec_()
  File "d:\social-leap-estimates-animal-poses\pull-requests\label-sug-speedup\sleap\sleap\gui\dialogs\merge.py", line 48, in __init__
    if self.base_labels.skeleton.node_names != self.new_labels.skeleton.node_names:
  File "d:\social-leap-estimates-animal-poses\pull-requests\label-sug-speedup\sleap\sleap\io\dataset.py", line 560, 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.
roomrys commented 2 years ago

Hi @e-velin,

No code-based fix yet, but an update as to why the problem may be occurring.

I found that if I follow the steps above, but refrain from loading a new skeleton into the project (namely Project 1 steps 4-6), then I get no error messages. It seems the error is occurring because there is more than one skeleton in a single project. In the case that the skeletons are different in the two projects, then I get the following warning upon "Merge into Project":

image

but, the merge still completes successfully. Thus, it does not matter if the skeletons in the two projects are different (as the skeletons will be merged), but it does matter if a single project has more than one skeleton - see the error in previous comment.

I will keep you updated, Liezl

cosimogonnelli commented 2 years ago

Hi @roomrys,

I am getting the same error as above. In my case is happening when I try to add to my main project a `predictions.slp' file. I tried to: open a new project, load the same skeleton as my main project, and merge the predictions. This process works but now I have a new project made of predictions and my original project. I tried then to merge the new project into my main project but I still get the same error.

What I am try to do is to merge into my main project the prediction.slp file generated by using sleap-track, to be able to expand my dataset.

Could somebody help with this issue? Please let me know if you need more info.

Thanks

Screen Shot 2022-06-25 at 3 13 58 PM
roomrys commented 2 years ago

Hi @cosimogonnelli,

Can you try the above, but skip the manual loading of the skeleton. The preditions.slp and your main project will both already have skeletons which SLEAP will merge together when selecting the "Merge Into Project...". To be explicit, can you

  1. open your main project
  2. File > Merge Into Project... > predictions.slp
  3. finish the merging process using the merging dialog that should pop-up

Do not try to load in the skeleton beforehand. Please let us know if that helps.

Thanks, LIezl

cosimogonnelli commented 2 years ago

Hi @roomrys,

Thanks for your help!

I still have the same issue. Please let me know what I should try next to move forward.

This is what I tried:

1 - File > Open Project > labels.v002.slp 2 - File > Merge Into Project > predictions.slp

This is the code I used to generate the predictions

Screen Shot 2022-06-29 at 11 29 12 AM

roomrys commented 2 years ago

Hi @cosimogonnelli,

Based on your results, either labels.v002.slp or predictions.slp has multiple skeletons loaded. We can do a quick check in the CLI to determine which SLEAP project has the extra skeleton(s).

Open IPython

  1. Open a terminal
  2. Activate your sleap conda environment
  3. Open ipython by entering the command: ipython in your terminal

In IPython CLI

  1. Import the sleap library
    In [1]: import sleap
  2. Load a labels object from your SLEAP Project file
    In [2]: labels = sleap.Labels.load_file("D:\\the-path-to-your-slp\\labels.v001.slp")
  3. List the skeletons for the labels object (or just the length of the skeletons list)
    
    In [3]: labels.skeletons
    Out[3]: [Skeleton(name='Skeleton-0', nodes=['mouth', 'l_mouth', 'l_head', 'r_mouth', 'r_head'], edges=[('mouth', 'l_mouth'), ('mouth', 'l_head'), ('mouth', 'r_mouth'), ('mouth', 'r_head')], symmetries=[])]

In [4]: len(labels.skeletons) Out[4]: 1


4. Repeat for both SLEAP files you are attempting to merge until you find the SLEAP Project with 2 skeletons.

The `predictions.slp` should not have multiple skeletons unless it was modified after training.

Let us know if you need help and also please update with your findings.

Thanks,
Liezl
cosimogonnelli commented 2 years ago

Hi @roomrys,

So it turned out that I have 5 skeleton in my main project and 1 in the predictions.slp file. How did I managed to do that and how do I delete the extra skeletons? This is very useful staff to know thanks!

Screen Shot 2022-06-29 at 5 26 30 PM Screen Shot 2022-06-29 at 5 26 44 PM
roomrys commented 2 years ago

Hi @cosimogonnelli,

Ok, so we will first check which skeleton is used - hopefully only one skeleton is used (otherwise we have another bug on our hand that roots from #713).

In IPython CLI (after loading the labels)

  1. Find the skeletons which are used (we expect and hope only one is used)
    
    In [5]: skeletons_used = list(set([inst.skeleton for lf in labels.labeled_frames for inst in lf.instances]))

In [6]: skeletons_used Out[6]: [Skeleton(name='Skeleton-0', nodes=['head', 'f_dorsal', 'r_dorsal'], edges=[('f_dorsal', 'head'), ('f_dorsal', 'r_dorsal')], symmetries=[])]

2. Set the skeleton list in the labels object to include only the one skeleton use (if multiple are used we need a different workaround)
```python
In [7]: assert len(skeletons_used) == 1

In [8]: labels.skeletons = skeletons_used
  1. Save a new SLEAP Project .slp
    In [9]: labels.save("D:\\path-to-save-your-slp\\new_slp.slp")

Let us know how that goes.

Thanks, Liezl

cosimogonnelli commented 2 years ago

Hi @roomrys,

I suppose I have to import some module since I get the error: NameError: name 'lf' is not defined when running line [5]. What does 'lf' stand for? What module should I import?

Thanks for helping with this!

roomrys commented 2 years ago

Hi @cosimogonnelli,

Oof, my bad - I switched the ordering of the nested for loop in the list comprehension. I updated line In[5] above. I must have had a lf saved in my terminal when testing out the list comprehension the first time around. It should work now.

lf is just short for labeled frame and should be defined from the first loop for lf in labels.labeled_frames (but I had the ordering incorrect).

Thanks, Liezl

cosimogonnelli commented 2 years ago

Hi @roomrys,

Thanks for your help! it definitely helps to understand how SLEAP works. So The code you provided seems working correctly. Do you have any idea why I ended up with 5 skeletons? I am sure I created only one. Not totally sure but I might have had to modify it. If this is the case it might happen that anytime I made a change a new skeleton get created..

Screen Shot 2022-07-01 at 4 34 57 PM
roomrys commented 2 years ago

Hi @cosimogonnelli,

We have only seen this bug occur if the user elects to Load Skeleton when a project already has a skeleton. The Load Skeleton appends the skeleton to a list of skeletons (laying the ground work for supporting multi-skeleton projects - not yet a feature). However, much of our code asserts that the project should only have one skeleton loaded to ensure things work as expected (until we add support for multi-skeleton projects).

Editing the skeleton does not append a new skeleton to the Labels.skeletons list and should not cause this bug. Let us know if you experienced this issue without using the Load Skeleton button.

Thanks, Liezl

shwan19 commented 2 years ago

Hi @roomrys ,

I encountered this same problem when trying to merge a new project .slp with labels into my main project .slp, even when I open my main project .slp without loading the skeleton first. I checked the number and identity of skeletons using the code you provided above. It turns out that my main project has two skeletons, which have the same nodes and edges but with a slightly different edge order (see below). My main project uses one version of this skeleton, whereas the new project uses the other version of this skeleton (again, with otherwise identical nodes and identical edges).

In [2]: labels = sleap.Labels.load_file("/home/shuyu/SLEAP/2022-06-16-sleap-bottomup-11pt_D/labels.v005.slp"
   ...: )

In [3]: labels.skeletons
Out[3]: 
[Skeleton(name='Skeleton-6', nodes=['nose', 'leftEar', 'rightEar', 'spine1', 'spine2', 'spine3', 'leftHip', 'rightHip', 'tailBase', 'tailEnd', 'rump'], edges=[('spine1', 'nose'), ('spine1', 'leftEar'), ('spine1', 'rightEar'), ('spine1', 'spine2'), ('spine2', 'leftHip'), ('spine2', 'rightHip'), ('spine2', 'spine3'), ('spine3', 'rump'), ('spine3', 'tailBase'), ('tailBase', 'tailEnd')], symmetries=[]),
 Skeleton(name='Skeleton-6', nodes=['nose', 'leftEar', 'rightEar', 'spine1', 'spine2', 'spine3', 'leftHip', 'rightHip', 'tailBase', 'tailEnd', 'rump'], edges=[('spine1', 'nose'), ('spine1', 'leftEar'), ('spine1', 'rightEar'), ('spine1', 'spine2'), ('spine2', 'leftHip'), ('spine2', 'rightHip'), ('spine2', 'spine3'), ('spine3', 'tailBase'), ('tailBase', 'tailEnd'), ('spine3', 'rump')], symmetries=[])]

In [4]: len(labels.skeletons)
Out[4]: 2

In [5]: labels_new = sleap.Labels.load_file("/home/shuyu/SLEAP/2022-07-12-KL/labels_KL.v000.slp")

In [6]: labels_new.skeletons
Out[6]: [Skeleton(name='Skeleton-6', nodes=['nose', 'leftEar', 'rightEar', 'spine1', 'spine2', 'spine3', 'leftHip', 'rightHip', 'tailBase', 'tailEnd', 'rump'], edges=[('spine1', 'nose'), ('spine1', 'leftEar'), ('spine1', 'rightEar'), ('spine1', 'spine2'), ('spine2', 'leftHip'), ('spine2', 'rightHip'), ('spine2', 'spine3'), ('spine3', 'tailBase'), ('tailBase', 'tailEnd'), ('spine3', 'rump')], symmetries=[])]

In [7]: len(labels_new.skeletons)
Out[7]: 1

In [8]: skeletons_used = list(set([inst.skeleton for lf in labels.labeled_frames for inst in lf.instances]))
   ...: 

In [9]: skeletons_used
Out[9]: [Skeleton(name='Skeleton-6', nodes=['nose', 'leftEar', 'rightEar', 'spine1', 'spine2', 'spine3', 'leftHip', 'rightHip', 'tailBase', 'tailEnd', 'rump'], edges=[('spine1', 'nose'), ('spine1', 'leftEar'), ('spine1', 'rightEar'), ('spine1', 'spine2'), ('spine2', 'leftHip'), ('spine2', 'rightHip'), ('spine2', 'spine3'), ('spine3', 'rump'), ('spine3', 'tailBase'), ('tailBase', 'tailEnd')], symmetries=[])]

Additionally, I have some questions about merging practices. In order for labels in the source file (i.e. new project .slp) to be merged into the destination file (i.e. main project .slp), does the destination file already need to have the video added? As an alternative to merging, is there a way to copy and paste instances from one file to another?

Many, many thanks, Shuyu

roomrys commented 2 years ago

Hi @shwan19,

Thanks for reporting! Did you happen to use Load Skeleton at any point in your project? Just trying to narrow down possible entry points for this bug.

The video does not need to be added prior to merging (it will be added during the merge).

The merging takes care of merging skeletons whereas copy-pasting would recreate the multiple skeleton issue. Is there a specific goal you would like to accomplish with copy-paste style merging?

Thanks, Liezl

shwan19 commented 2 years ago

Hi @roomrys ,

I appreciate your quick response! Yes, I'm certain that I used Load Skeleton at some point in the project, as I had tested multiple skeletons before settling on the current one.

I only ask about copy-pasting because I have a not-huge number of instance labels I'm trying to merge. But if there's a more robust way to merge, I would gladly do that instead of copy-pasting. Do you recommend a specific work-around for merging (or its equivalent) given the multiple skeletons issue? (In my case, it's really the same skeleton, just the edge order is different between the two variants...)

Thanks again, Shuyu

roomrys commented 2 years ago

Hi @shwan19,

Ok thanks for clarifying - Load Skeleton remains to be the sole entry point for this specific bug then.

The merging should work after these steps:

  1. Set the labels.skeletons = skeletons_used for the project with multiple skeletons.
  2. Then you will need to labels.save("<path to you new slp>\new_slp.slp").
  3. Open up the new_slp.slp and merge using this project.

Let us know if you are having any trouble.

Thanks, Liezl

anoushehbsuroosh commented 2 years ago

Hello,

I was having a similar issue with multiple skeletons and followed the instructions above. However, we seem to be having an issue saving the corrected label file, as indicated below.

Python 3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:53)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sleap
>>> labels = sleap.Labels.load_file("/snlkt/spb_psilicon/Pilot_BehParameters/SLEAP/SLEAP_troubleshooting/tr_fsm_abs_mb_MedPC_p5_v42.slp")
>>> labels
Labels(labeled_frames=220, videos=5, skeletons=4, tracks=0)
>>> skeletons_used = list(set([inst.skeleton for lf in labels.labeled_frames for inst in lf.instances]))
>>> skeletons_used
[Skeleton(name='Skeleton-0', nodes=['nose', 'left_ear_tip', 'left_ear_base', 'right_ear_base', 'right_ear_tip', 'skull_base', 'shoulders', 'haunch', 'tail_base', 'tail_seg', 'left_arm', 'right_arm', 'right_leg', 'left_leg'], edges=[('nose', 'left_ear_base'), ('nose', 'right_ear_base'), ('right_ear_base', 'right_ear_tip'), ('left_ear_base', 'left_ear_tip'), ('left_ear_base', 'skull_base'), ('right_ear_base', 'skull_base'), ('skull_base', 'shoulders'), ('shoulders', 'left_arm'), ('shoulders', 'right_arm'), ('shoulders', 'haunch'), ('haunch', 'right_leg'), ('haunch', 'left_leg'), ('haunch', 'tail_base'), ('tail_base', 'tail_seg')], symmetries=[]), Skeleton(name='Skeleton-0', nodes=['nose', 'left_ear_tip', 'left_ear_base', 'right_ear_base', 'right_ear_tip', 'skull_base', 'shoulders', 'haunch', 'tail_base', 'tail_seg', 'left_arm', 'right_arm', 'right_leg', 'left_leg'], edges=[('nose', 'left_ear_base'), ('nose', 'right_ear_base'), ('right_ear_base', 'right_ear_tip'), ('left_ear_base', 'left_ear_tip'), ('left_ear_base', 'skull_base'), ('right_ear_base', 'skull_base'), ('skull_base', 'shoulders'), ('shoulders', 'left_arm'), ('shoulders', 'right_arm'), ('shoulders', 'haunch'), ('haunch', 'right_leg'), ('haunch', 'left_leg'), ('haunch', 'tail_base'), ('tail_base', 'tail_seg')], symmetries=[]), Skeleton(name='Skeleton-0', nodes=['nose', 'left_ear_tip', 'left_ear_base', 'right_ear_base', 'right_ear_tip', 'skull_base', 'shoulders', 'haunch', 'tail_base', 'tail_seg', 'left_arm', 'right_arm', 'right_leg', 'left_leg'], edges=[('nose', 'left_ear_base'), ('nose', 'right_ear_base'), ('right_ear_base', 'right_ear_tip'), ('left_ear_base', 'left_ear_tip'), ('left_ear_base', 'skull_base'), ('right_ear_base', 'skull_base'), ('skull_base', 'shoulders'), ('shoulders', 'left_arm'), ('shoulders', 'right_arm'), ('shoulders', 'haunch'), ('haunch', 'right_leg'), ('haunch', 'left_leg'), ('haunch', 'tail_base'), ('tail_base', 'tail_seg')], symmetries=[])]
>>> len(skeletons_used)
3
# Removing extra skeletons because set sees them each as unique for some unknown reason
>>> del skeletons_used[1:3]
>>> skeletons_used
[Skeleton(name='Skeleton-0', nodes=['nose', 'left_ear_tip', 'left_ear_base', 'right_ear_base', 'right_ear_tip', 'skull_base', 'shoulders', 'haunch', 'tail_base', 'tail_seg', 'left_arm', 'right_arm', 'right_leg', 'left_leg'], edges=[('nose', 'left_ear_base'), ('nose', 'right_ear_base'), ('right_ear_base', 'right_ear_tip'), ('left_ear_base', 'left_ear_tip'), ('left_ear_base', 'skull_base'), ('right_ear_base', 'skull_base'), ('skull_base', 'shoulders'), ('shoulders', 'left_arm'), ('shoulders', 'right_arm'), ('shoulders', 'haunch'), ('haunch', 'right_leg'), ('haunch', 'left_leg'), ('haunch', 'tail_base'), ('tail_base', 'tail_seg')], symmetries=[])]
>>> labels.skeletons = skeletons_used
>>> labels
Labels(labeled_frames=220, videos=5, skeletons=1, tracks=0)
>>> labels.save("/snlkt/spb_psilicon/Pilot_BehParameters/SLEAP/SLEAP_troubleshooting/tr_fsm_abs_mb_MedPC_p5_v42_oneskeleton.slp")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/abakhtisuroosh/anaconda3/envs/sleap/lib/python3.7/site-packages/sleap/io/dataset.py", line 2006, in save
    suggested=embed_suggested,
  File "/home/abakhtisuroosh/anaconda3/envs/sleap/lib/python3.7/site-packages/sleap/io/dataset.py", line 1971, in save_file
    write(filename, labels, *args, **kwargs)
  File "/home/abakhtisuroosh/anaconda3/envs/sleap/lib/python3.7/site-packages/sleap/io/format/main.py", line 162, in write
    return disp.write(filename, source_object, *args, **kwargs)
  File "/home/abakhtisuroosh/anaconda3/envs/sleap/lib/python3.7/site-packages/sleap/io/format/dispatch.py", line 78, in write
    return adaptor.write(filename, source_object, *args, **kwargs)
  File "/home/abakhtisuroosh/anaconda3/envs/sleap/lib/python3.7/site-packages/sleap/io/format/hdf5.py", line 459, in write
    skeleton_to_idx[instance.skeleton],
KeyError: Skeleton(name='Skeleton-0', nodes=['nose', 'left_ear_tip', 'left_ear_base', 'right_ear_base', 'right_ear_tip', 'skull_base', 'shoulders', 'haunch', 'tail_base', 'tail_seg', 'left_arm', 'right_arm', 'right_leg', 'left_leg'], edges=[('nose', 'left_ear_base'), ('nose', 'right_ear_base'), ('right_ear_base', 'right_ear_tip'), ('left_ear_base', 'left_ear_tip'), ('left_ear_base', 'skull_base'), ('right_ear_base', 'skull_base'), ('skull_base', 'shoulders'), ('shoulders', 'left_arm'), ('shoulders', 'right_arm'), ('shoulders', 'haunch'), ('haunch', 'right_leg'), ('haunch', 'left_leg'), ('haunch', 'tail_base'), ('tail_base', 'tail_seg')], symmetries=[])
>>>

Thank you for your assistance!

roomrys commented 2 years ago

Hi @anoushehbsuroosh,

Since multiple skeletons are used in the project (referenced by instances), you will need to set each instance to reference the last remaining skeleton before saving the project.

labels.skeleton = skeletons_used[-1]
for instance in labels.instances():
    instance.skeleton = labels.skeleton

Hope this helps! Let us know if you are still having trouble.

Thanks, Liezl

P.S. #913 deals with a similar issue.

e-velin commented 1 year ago

Hi, I'm having problems with merging different sleap projects again. I have a main project with multiple labeled videos, I trained the network on this dataset. Based on your previous suggestions here, I checked in ipython and this slp file uses one skeleton. I have multiple smaller slp project files with 10 videos, where I predicted the pose based on the training on the main project and the predictions were hand corrected. Now when I'm trying to merge these projects with the main project, I receive this error: Labels.skeleton can only be used when there is only a single skeleton saved in the labels. Use Labels.skeletons instead. These smaller project files with 10 videos use 10 skeletons, as I found out. They all have the same attributes (even names - "Skeleton-0", nodes, etc), yet they are considered as separate skeletons. I did not load in a skeleton file to these smaller projects I just did the inference on them.

roomrys commented 1 year ago

Hi @e-velin,

Thank you for your detailed background above. Do you mind providing me a few numbered steps to try and replicate (starting after you have the trained model, i.e. how are you running inference GUI -> local, GUI -> export -> Colab, CLI).

Also, for troubleshooting purposes, which SLEAP version are you on and how did you install (source, conda package, or pip)?

Thanks for your help! Liezl

e-velin commented 1 year ago

Hi @roomrys, I am running inference from GUI locally in v1.2.9 on a Mac m1, installed from source.

I also tried finding a workaround by exporting the corrected annotations from the smaller projects to h5 files and importing them into the main project, with adding the corresponding videos to the main project, then I get track=tracks[track_idx], IndexError: list index out of range. I deleted all tracks in all the project files, I'm using single pose estimation.

roomrys commented 1 year ago

Hi @e-velin,

Question

Did you run inference remotely and then have to merge in the predictions? We have our suspicions that the merging code might be causing duplicate skeletons.

Tracing

If this is a problem from just running inference (no merging), then... SLEAP determines which skeleton to use when running inference by looking at the config https://github.com/talmolab/sleap/blob/d05e2bf524cdb9813926a841886725644f00a218/sleap/nn/inference.py#L1533 However, when we create a Trainer.from_config, we overwrite the config skeletons with the skeletons in the training labels https://github.com/talmolab/sleap/blob/d05e2bf524cdb9813926a841886725644f00a218/sleap/nn/training.py#L677 Well, we use the index 0 to determine which skeleton to use here... is it possible that we use another index elsewhere to determine which skeleton? Yes, there is this suspect line https://github.com/talmolab/sleap/blob/d05e2bf524cdb9813926a841886725644f00a218/sleap/gui/app.py#L1480-L1481 from a commit titled Update the GUI skeleton after inference if it changed (https://github.com/talmolab/sleap/issues/414) - also very suspicious. So if merging is adding multiple skeletons, we choose to use the last skeleton in our GUI, but then use the first skeleton for adding predictions.

Another workaround

913 provides a workaround for the multiple duplicate skeletons:

Alright so the problem seems to be related to having a bunch of duplicated skeletons in your labels file. I was able to get it working by setting all instances to have the same skeleton:

import sleap
labels = sleap.load_file("edited100framescopy.slp")
skeleton = labels.skeletons[-1]
labels.skeletons = [skeleton]
for instance in labels.instances():
    instance.skeleton = skeleton
labels.save("fixed.slp")

You can run that in a python terminal or save it out as a fix.py file that you call with python fix.py.

Not sure how you ended up with a bunch of conflicting skeletons, but I'm guessing it's related to the M1 branch being on an older version of SLEAP (until recently).

Give it a go and let us know if you're having any issues. I also highly recommend updating to the newest M1 version as we've fixed a bunch of bugs since the previous one.

Cheers,

Talmo

Help with your workaround

SLEAP expects tracks_matrix to have a last dimension of 1 if len(labels.tracks) == 0, https://github.com/talmolab/sleap/blob/d05e2bf524cdb9813926a841886725644f00a218/sleap/info/write_tracking_h5.py#L86 https://github.com/talmolab/sleap/blob/d05e2bf524cdb9813926a841886725644f00a218/sleap/info/write_tracking_h5.py#L120-L122 but I wonder if the last two dimensions might be flipped, (x,y) and track_count. We can check the dimensions of the tracks_matrix via the analysis notebook (renamed locations).

Thanks, Liezl

e-velin commented 1 year ago

Hi @roomrys,

Answer to your question

Thanks for inspecting my problem. No, I didn't run inference remotely, but on my computer. So I have a big "merged" slp file, I trained the network on these annotations. I created multiple smaller slp files with 10 videos only (because at some point I had trouble opening slp files with more videos but I can solve that now by running "ulimit -n 2000" in command line after activating the sleap conda environment and before opening the gui). Then I opened these smaller slp files on the same computer, made inference immediately (without loading in a specific skeleton file first) with the network trained on the bigger slp file then I sent the smaller slp files to a different computer where they were corrected (sleap v 1.2.9, Mac pro intel) and now I'm trying to merge them into the bigger slp file and I receive this error message.

Feedback on the other workaround

I tried Talmo's suggestion and actually all the corrected annotations disappeared. They are present in the Instances menu but with 0/14 Points (so no body parts appear on the frames).

Feedback on help with my workaround

The shape of one of the videos' "locations" variable (based on the analysis notebook) from one of my smaller slp files is: (129, 14, 2, 1), if this is what you referred to. So "2" (x,y coordinates' number) and track_count is not flipped.