Skip to content

Commit 7c1d343

Browse files
talmosmidmkant
authored
Bump to v1.1.4 (#563)
* Set Twine version to fix pypi uploads on build - twine v3.4.x and greater seems to have issues with our build system since we have an older version of `importlib_metadata` * Revert changes from merge into main * Bump version to 1.1.3 * Update docs * fix code samples in documentation (#535) The code samples to render properly have to be valid rst literal blocks (https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#literal-blocks). The most affected are multi-line code samples that are joined to a singe line, see https://sleap.ai/api/sleap.io.dataset.html. * Minor typo fixed (#538) * Add CLI options for specifying the GPU when training (#547) * Add GPU specification to training CLI * Update CLI docs * Set linter version * Minor QOL update (#562) * Add score metadata to the exported HDF5 analysis files * Fix and add test for labels.numpy() * Add some tweaks and docs to video rendering * Add model describer to sleap-inspect CLI * Minor logging * CLI tweak * Tweak visual indicator of not-visible points * Color untracked instances consistently * Track removal utilities - Add menu option: Tracks -> Delete All Tracks - Add Labels.remove_all_tracks() method - Tests * Try adding token to codecov action * Pin black formatter version and relint * Bump minor version * Update minor version in docs * Disable verbose coverage uploading * Update codecov badge branch Co-authored-by: Matěj Šmíd <[email protected]> Co-authored-by: Darío Hereñú <[email protected]>
1 parent 08bee64 commit 7c1d343

31 files changed

+468
-138
lines changed

.github/workflows/ci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
python-version: 3.6
3737
- name: Install Dependencies
3838
run: |
39-
pip install black
39+
pip install black==20.8b1
4040
- name: Run Black
4141
run: |
4242
black --check sleap tests
@@ -90,4 +90,8 @@ jobs:
9090
xvfb-run pytest --cov=sleap --cov-report=xml tests/
9191
- name: Upload coverage
9292
uses: codecov/codecov-action@v1
93-
if: matrix.os == 'ubuntu-18.04'
93+
if: matrix.os == 'ubuntu-18.04'
94+
with:
95+
token: ${{ secrets.CODECOV_TOKEN }}
96+
fail_ci_if_error: true
97+
verbose: false

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
:alt: Continuous integration status
77

88
.. |Coverage| image::
9-
https://codecov.io/gh/murthylab/sleap/branch/tf23/graph/badge.svg?token=YWQYBN6820
9+
https://codecov.io/gh/murthylab/sleap/branch/develop/graph/badge.svg?token=YWQYBN6820
1010
:target: https://codecov.io/gh/murthylab/sleap
1111
:alt: Coverage
1212

@@ -99,7 +99,7 @@ Contributors
9999
* **Joshua Shaevitz**, Physics and Lewis-Sigler Institute, Princeton University
100100
* **Mala Murthy**, Princeton Neuroscience Institute, Princeton University
101101

102-
SLEAP is developed in the `Murthy <https://murthylab.princeton.edu>`_ and `Shaevitz <https://shaevitzlab.princeton.edu>`_ labs at the `Princeton Neuroscience Institute <https://pni.princeton.edu>`_ at Princeton University. This work was made possible through our funding sources, including: NIH BRAIN Initative R01 NS104899 and Princeton Innovation Accelerator Fund.
102+
SLEAP is developed in the `Murthy <https://murthylab.princeton.edu>`_ and `Shaevitz <https://shaevitzlab.princeton.edu>`_ labs at the `Princeton Neuroscience Institute <https://pni.princeton.edu>`_ at Princeton University. This work was made possible through our funding sources, including: NIH BRAIN Initiative R01 NS104899 and Princeton Innovation Accelerator Fund.
103103

104104
.. end-inclusion-marker-do-not-remove
105105

dev_requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ furo
77
sphinx-copybutton
88
myst-nb
99
sphinx-autobuild
10-
black
10+
black==21.6b0
1111
pre-commit
1212
twine==3.3.0
1313
PyGithub

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@
2727
copyright = "2019–2021, Murthy Lab @ Princeton University"
2828

2929
# The short X.Y version
30-
version = "1.1.3"
30+
version = "1.1.4"
3131

3232
# Get the sleap version
3333
# with open("../sleap/version.py") as f:
3434
# version_file = f.read()
3535
# version = re.search("\d.+(?=['\"])", version_file).group(0)
3636

3737
# Release should be the full branch name
38-
release = "v1.1.3"
38+
release = "v1.1.4"
3939

4040
html_title = f"SLEAP ({release})"
4141
html_short_title = "SLEAP"

docs/guides/cli.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ Training
6666
name settings.
6767
--prefix PREFIX Prefix to prepend to run name.
6868
--suffix SUFFIX Suffix to append to run name.
69+
--cpu Run training only on CPU. If not specified, will use
70+
available GPU.
71+
--first-gpu Run training on the first GPU, if available.
72+
--last-gpu Run training on the last GPU, if available.
73+
--gpu GPU Run training on the i-th GPU on the system.
6974
7075
7176
Inference and Tracking
@@ -232,13 +237,14 @@ Dataset files
232237
233238
:code:`sleap-inspect` gives you various information about a SLEAP dataset file such as a list of videos and a count of the frames with labels. If you're inspecting a predictions dataset (i.e., the output from running :code:`sleap-track` or inference in the GUI) it will also include details about how those predictions were created (i.e., the models, the version of SLEAP, and any inference parameters).
234239

240+
You can also specify a model folder to get a quick summary of the configuration and metrics (if available).
235241

236242
.. code-block:: none
237243
238244
usage: sleap-inspect [-h] [--verbose] data_path
239245
240246
positional arguments:
241-
data_path Path to labels json file
247+
data_path Path to labels file (.slp) or model folder
242248
243249
optional arguments:
244250
-h, --help show this help message and exit

docs/installation.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ different projects, mitigating issues of managing complex dependencies. To creat
3232

3333
::
3434

35-
(base) C:\> conda create -n sleap -c defaults -c sleap sleap=1.1.3 python=3.6 -y
35+
(base) C:\> conda create -n sleap -c defaults -c sleap sleap=1.1.4 python=3.6 -y
3636

3737
Once the environment is finished installing, it can be activated using the following command:
3838

@@ -76,7 +76,7 @@ You can then install SLEAP by running:
7676

7777
::
7878

79-
pip install sleap==1.1.3
79+
pip install sleap==1.1.4
8080

8181
**SLEAP** is now installed, you can run the labeling GUI:
8282

docs/notebooks/Training_and_inference_on_an_example_dataset.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
},
5252
"outputs": [],
5353
"source": [
54-
"!pip install sleap==1.1.3"
54+
"!pip install sleap==1.1.4"
5555
]
5656
},
5757
{

docs/notebooks/Training_and_inference_using_Google_Drive.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
},
4949
"outputs": [],
5050
"source": [
51-
"!pip install sleap==1.1.3"
51+
"!pip install sleap==1.1.4"
5252
]
5353
},
5454
{

sleap/gui/app.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,8 +635,6 @@ def new_instance_menu_action():
635635

636636
tracksMenu = self.menuBar().addMenu("Tracks")
637637
self.track_menu = tracksMenu.addMenu("Set Instance Track")
638-
self.delete_tracks_menu = tracksMenu.addMenu("Delete Track")
639-
self.delete_tracks_menu.setEnabled(False)
640638
add_menu_check_item(
641639
tracksMenu, "propagate track labels", "Propagate Track Labels"
642640
).setToolTip(
@@ -649,12 +647,25 @@ def new_instance_menu_action():
649647
"Transpose Instance Tracks",
650648
self.commands.transposeInstance,
651649
)
650+
651+
tracksMenu.addSeparator()
652+
652653
add_menu_item(
653654
tracksMenu,
654655
"delete track",
655656
"Delete Instance and Track",
656657
self.commands.deleteSelectedInstanceTrack,
657658
)
659+
self.delete_tracks_menu = tracksMenu.addMenu("Delete Track")
660+
self.delete_tracks_menu.setEnabled(False)
661+
add_menu_item(
662+
tracksMenu,
663+
"delete all tracks",
664+
"Delete All Tracks",
665+
self.commands.deleteAllTracks,
666+
).setToolTip(
667+
"Delete all tracks and update instances. Instances are not removed."
668+
)
658669

659670
tracksMenu.addSeparator()
660671

sleap/gui/color.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,11 @@ def get_pseudo_track_index(self, instance: "Instance") -> Union[Track, int]:
151151
if not instance.frame:
152152
return 0
153153

154-
non_track_instances = [
155-
inst for inst in instance.frame.instances_to_show if inst.track is None
154+
untracked_instances = [
155+
inst for inst in instance.frame.user_instances if inst.track is None
156156
]
157157

158-
return len(self.tracks) + non_track_instances.index(instance)
158+
return len(self.tracks) + untracked_instances.index(instance)
159159

160160
def get_track_color(self, track: Union[Track, int]) -> ColorTupleType:
161161
"""Returns the color to use for a given track.

sleap/gui/commands.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,10 @@ def deleteTrack(self, track: "Track"):
505505
"""Delete a track and remove from all instances."""
506506
self.execute(DeleteTrack, track=track)
507507

508+
def deleteAllTracks(self):
509+
"""Delete all tracks."""
510+
self.execute(DeleteAllTracks)
511+
508512
def setTrackName(self, track: "Track", name: str):
509513
"""Sets name for track."""
510514
self.execute(SetTrackName, track=track, name=name)
@@ -1939,6 +1943,14 @@ def do_action(context: CommandContext, params: dict):
19391943
context.labels.remove_track(track)
19401944

19411945

1946+
class DeleteAllTracks(EditCommand):
1947+
topics = [UpdateTopic.tracks]
1948+
1949+
@staticmethod
1950+
def do_action(context: CommandContext, params: dict):
1951+
context.labels.remove_all_tracks()
1952+
1953+
19421954
class SetTrackName(EditCommand):
19431955
topics = [UpdateTopic.tracks, UpdateTopic.frame]
19441956

sleap/gui/dialogs/formbuilder.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@
66
a little more convenient (it provides methods for adding a message for the
77
dialog and for getting the results when the dialog is closed).
88
9-
Example of form widget:
9+
Example of form widget: ::
1010
11-
>>> widget = YamlFormWidget(yaml_file="example.yaml")
12-
>>> widget.mainAction.connect(my_function)
11+
>>> widget = YamlFormWidget(yaml_file="example.yaml")
12+
>>> widget.mainAction.connect(my_function)
1313
1414
my_function will get called with form data when user clicks the main button
1515
(main button has type "button" and default "main action")
1616
17-
Example of modal dialog:
17+
Example of modal dialog: ::
1818
19-
>>> results = FormBuilderModalDialog(form_name="example").get_results()
19+
>>> results = FormBuilderModalDialog(form_name="example").get_results()
2020
2121
The results will be empty dictionary if the user hit "cancel", otherwise it
2222
will contain all data from form (dict keys matching names of fields).
@@ -43,9 +43,9 @@ class YamlFormWidget(QtWidgets.QGroupBox):
4343
4444
Typically you'll want to save the YAML in `sleap/config/` and use the
4545
:py:meth:`from_name` method to make the form (e.g., if your form data is in
46-
`sleap/config/foo.yaml`, then you can create form like so:
46+
`sleap/config/foo.yaml`, then you can create form like so: ::
4747
48-
>>> widget = YamlFormWidget.from_name("foo")
48+
>>> widget = YamlFormWidget.from_name("foo")
4949
5050
Args:
5151
yaml_file: filename of YAML file to load.

sleap/gui/dialogs/importvideos.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""
22
Interface to handle the UI for importing videos.
33
4-
Usage:
4+
Usage: ::
55
6-
>>> import_list = ImportVideos().ask()
6+
>>> import_list = ImportVideos().ask()
77
88
This will show the user a file-selection dialog, and then a second dialog
99
to select the import parameters for each file.
@@ -14,9 +14,9 @@
1414
to the relevant method of :class:`Video`.
1515
1616
For each `item` in `import_list`, we can load the video by calling this
17-
method while passing the user-selected params as the named parameters:
17+
method while passing the user-selected params as the named parameters: ::
1818
19-
>>> vid = item["video_class"](**item["params"])
19+
>>> vid = item["video_class"](**item["params"])
2020
2121
"""
2222

sleap/gui/overlays/confmaps.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
current frame) and then uses a `ConfMapsPlot` object to show the resulting
66
confidence maps.
77
8-
Example:
8+
Example: ::
9+
910
>>> cm = ConfMapsPlot(conf_data.get_frame(0))
1011
>>> window.view.scene.addItem(cm)
12+
1113
"""
1214

1315
from PySide2 import QtWidgets, QtCore, QtGui

sleap/gui/widgets/multicheck.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
"""
22
Module for Qt Widget to show multiple checkboxes for selecting.
33
4-
Example:
4+
Example: ::
5+
56
>>> mc = MultiCheckWidget(count=5, selected=[0,1],title="My Items")
67
>>> mc.selectionChanged.connect(window.plot)
78
>>> window.layout.addWidget(mc)
9+
810
"""
911

1012
from typing import List, Optional

sleap/gui/widgets/video.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
44
All interactions should go through `QtVideoPlayer`.
55
6-
Example usage:
6+
Example usage: ::
7+
78
>>> my_video = Video(...)
89
>>> my_instance = Instance(...)
910
@@ -523,8 +524,9 @@ def onSequenceSelect(
523524
selection), the `on_failure` callback is called (if given).
524525
525526
Note:
526-
If successful, we call
527-
>>> on_success(list_of_instances)
527+
If successful, we call ::
528+
529+
>>> on_success(list_of_instances)
528530
529531
Args:
530532
seq_len: Number of instances we want to collect in sequence.
@@ -1218,24 +1220,31 @@ def adjustStyle(self):
12181220
complete_color = (
12191221
QColor(80, 194, 159) if self.node.point.complete else QColor(232, 45, 32)
12201222
)
1223+
missing_color = QColor(128, 128, 128)
12211224

12221225
if self.predicted:
12231226
self._base_font.setBold(False)
1227+
self._base_font.setItalic(False)
12241228
self.setFont(self._base_font)
12251229
self.setDefaultTextColor(QColor(128, 128, 128))
12261230
elif not self.node.point.visible:
1227-
self._base_font.setBold(False)
1231+
self._base_font.setBold(True)
1232+
self._base_font.setItalic(True)
12281233
self.setFont(self._base_font)
1229-
# self.setDefaultTextColor(self.node.pen().color())
1230-
self.setDefaultTextColor(complete_color)
1234+
self.setPlainText(f"{self.node.name}*")
1235+
self.setDefaultTextColor(missing_color)
12311236
elif self.node.point.complete:
12321237
self._base_font.setBold(True)
1238+
self._base_font.setItalic(False)
1239+
self.setPlainText(f"{self.node.name}")
12331240
self.setFont(self._base_font)
12341241
self.setDefaultTextColor(complete_color) # greenish
12351242
# FIXME: Adjust style of node here as well?
12361243
# self.node.setBrush(complete_color)
12371244
else:
12381245
self._base_font.setBold(False)
1246+
self._base_font.setItalic(False)
1247+
self.setPlainText(f"{self.node.name}")
12391248
self.setFont(self._base_font)
12401249
self.setDefaultTextColor(complete_color) # redish
12411250

@@ -1352,10 +1361,10 @@ def __init__(
13521361
self.pen_default.setCosmetic(
13531362
True
13541363
) # https://stackoverflow.com/questions/13120486/adjusting-qpen-thickness-when-scaling-qgraphicsview
1355-
self.pen_missing = QPen(line_color, 1)
1364+
self.pen_missing = QPen(line_color, 1) # thin border
13561365
self.pen_missing.setCosmetic(True)
13571366
self.brush = QBrush(QColor(*self.color, a=128))
1358-
self.brush_missing = QBrush(QColor(*self.color, a=0))
1367+
self.brush_missing = QBrush(QColor(*self.color, a=0)) # no fill
13591368

13601369
self.setPos(self.point.x, self.point.y)
13611370
self.updatePoint(user_change=False)
@@ -1371,7 +1380,7 @@ def visible_radius(self):
13711380
if self.point.visible:
13721381
return self.radius / self.player.view.zoomFactor
13731382
else:
1374-
return self.radius / (2.0 * self.player.view.zoomFactor)
1383+
return self.radius / (2.0 * self.player.view.zoomFactor) # smaller marker
13751384

13761385
def updatePoint(self, user_change: bool = False):
13771386
"""
@@ -1395,7 +1404,7 @@ def updatePoint(self, user_change: bool = False):
13951404
self.setPen(self.pen_default)
13961405
self.setBrush(self.brush)
13971406
else:
1398-
radius = self.radius / 2.0
1407+
radius = self.radius / 2.0 # smaller marker
13991408
self.setPen(self.pen_missing)
14001409
self.setBrush(self.brush_missing)
14011410
if not self.show_non_visible:

0 commit comments

Comments
 (0)