From 170048a86fd07bca0f31244dd54c167dd3b8d74a Mon Sep 17 00:00:00 2001 From: Shrivaths Shyam Date: Tue, 4 Jun 2024 22:51:55 -0700 Subject: [PATCH 1/4] Add menu item for deleting instances beyond frame limit --- sleap/gui/app.py | 6 ++++++ sleap/gui/commands.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/sleap/gui/app.py b/sleap/gui/app.py index becc1d83a..2450a076e 100644 --- a/sleap/gui/app.py +++ b/sleap/gui/app.py @@ -788,6 +788,12 @@ def new_instance_menu_action(): "Delete Predictions beyond Max Instances...", self.commands.deleteInstanceLimitPredictions, ) + add_menu_item( + labelMenu, + "delete frame limit predictions new item", + "Delete Predictions beyond Frame Limit new item...", + self.commands.deleteFrameLimitPredictions, + ) ### Tracks Menu ### diff --git a/sleap/gui/commands.py b/sleap/gui/commands.py index 342ceec26..45bf2a05e 100644 --- a/sleap/gui/commands.py +++ b/sleap/gui/commands.py @@ -494,6 +494,10 @@ def deleteInstanceLimitPredictions(self): """Gui for deleting instances beyond some number in each frame.""" self.execute(DeleteInstanceLimitPredictions) + def deleteFrameLimitPredictions(self): + """Gui for deleting instances beyond some frame number.""" + self.execute(DeleteFrameLimitPredictions) + def completeInstanceNodes(self, instance: Instance): """Adds missing nodes to given instance.""" self.execute(AddMissingInstanceNodes, instance=instance) @@ -2468,6 +2472,34 @@ def ask(cls, context: CommandContext, params: dict) -> bool: return super().ask(context, params) +class DeleteFrameLimitPredictions(InstanceDeleteCommand): + @staticmethod + def get_frame_instance_list(context: CommandContext, params: Dict): + predicted_instances = [] + # Select the instances to be deleted + for lf in context.labels.find(context.state["video"]): + if lf.frame_idx >= params["frame_idx_threshold"]: + predicted_instances.extend( + [(lf, inst) for inst in lf.predicted_instances] + ) + return predicted_instances + + @classmethod + def ask(cls, context: CommandContext, params: Dict) -> bool: + current_video = context.state["video"] + frame_idx_thresh, okay = QtWidgets.QInputDialog.getInt( + context.app, + "Delete Instance beyond Frame Number...", + "Frame number after which instances to be deleted:", + 1, + 1, + len(current_video), + ) + if okay: + params["frame_idx_threshold"] = frame_idx_thresh + return super().ask(context, params) + + class TransposeInstances(EditCommand): topics = [UpdateTopic.project_instances, UpdateTopic.tracks] From b336e9f2774686ff5101f3d07c3ebac24400be69 Mon Sep 17 00:00:00 2001 From: Shrivaths Shyam Date: Wed, 12 Jun 2024 00:46:04 -0700 Subject: [PATCH 2/4] Add test function to test the instances returned --- sleap/gui/app.py | 4 ++-- sleap/gui/commands.py | 4 +++- tests/gui/test_commands.py | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/sleap/gui/app.py b/sleap/gui/app.py index 2450a076e..3d1f7c443 100644 --- a/sleap/gui/app.py +++ b/sleap/gui/app.py @@ -790,8 +790,8 @@ def new_instance_menu_action(): ) add_menu_item( labelMenu, - "delete frame limit predictions new item", - "Delete Predictions beyond Frame Limit new item...", + "delete frame limit predictions", + "Delete Predictions beyond Frame Limit...", self.commands.deleteFrameLimitPredictions, ) diff --git a/sleap/gui/commands.py b/sleap/gui/commands.py index 45bf2a05e..ef8932df7 100644 --- a/sleap/gui/commands.py +++ b/sleap/gui/commands.py @@ -2475,9 +2475,11 @@ def ask(cls, context: CommandContext, params: dict) -> bool: class DeleteFrameLimitPredictions(InstanceDeleteCommand): @staticmethod def get_frame_instance_list(context: CommandContext, params: Dict): + """Called from the parent `InstanceDeleteCommand` class. Returns a list of + instances to be deleted.""" predicted_instances = [] # Select the instances to be deleted - for lf in context.labels.find(context.state["video"]): + for lf in context.labels.labeled_frames: if lf.frame_idx >= params["frame_idx_threshold"]: predicted_instances.extend( [(lf, inst) for inst in lf.predicted_instances] diff --git a/tests/gui/test_commands.py b/tests/gui/test_commands.py index 899b1f4a0..cc9267858 100644 --- a/tests/gui/test_commands.py +++ b/tests/gui/test_commands.py @@ -16,6 +16,7 @@ ReplaceVideo, OpenSkeleton, SaveProjectAs, + DeleteFrameLimitPredictions, get_new_version_filename, ) from sleap.instance import Instance, LabeledFrame @@ -847,6 +848,27 @@ def load_and_assert_changes(new_video_path: Path): shutil.move(new_video_path, expected_video_path) +def test_DeleteFrameLimitPredictions( + centered_pair_predictions: Labels, centered_pair_vid: Video +): + """Test deleting instances beyond a certain frame limit.""" + labels = centered_pair_predictions + + # Set-up command context + context = CommandContext.from_labels(labels) + context.state["video"] = centered_pair_vid + + # Set-up params for the command + params = {"frame_idx_threshold": 900} + + expected_instances = 423 + predicted_instances = DeleteFrameLimitPredictions.get_frame_instance_list( + context, params + ) + + assert len(predicted_instances) == expected_instances + + @pytest.mark.parametrize("export_extension", [".json.zip", ".slp"]) def test_exportLabelsPackage(export_extension, centered_pair_labels: Labels, tmpdir): def assert_loaded_package_similar(path_to_pkg: Path, sugg=False, pred=False): From 4e6aed28d2559fe941d4598941226caf1360d521 Mon Sep 17 00:00:00 2001 From: Shrivaths Shyam Date: Wed, 12 Jun 2024 09:43:58 -0700 Subject: [PATCH 3/4] typos --- sleap/gui/commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sleap/gui/commands.py b/sleap/gui/commands.py index ef8932df7..a647580de 100644 --- a/sleap/gui/commands.py +++ b/sleap/gui/commands.py @@ -2475,7 +2475,7 @@ def ask(cls, context: CommandContext, params: dict) -> bool: class DeleteFrameLimitPredictions(InstanceDeleteCommand): @staticmethod def get_frame_instance_list(context: CommandContext, params: Dict): - """Called from the parent `InstanceDeleteCommand` class. Returns a list of + """Called from the parent `InstanceDeleteCommand.ask` class. Returns a list of instances to be deleted.""" predicted_instances = [] # Select the instances to be deleted From 4102ef1081e4f02d76f28e3815d1df5d0dd9d0f3 Mon Sep 17 00:00:00 2001 From: Shrivaths Shyam Date: Wed, 12 Jun 2024 15:55:58 -0700 Subject: [PATCH 4/4] Update docstring --- sleap/gui/commands.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sleap/gui/commands.py b/sleap/gui/commands.py index a647580de..9c92a409e 100644 --- a/sleap/gui/commands.py +++ b/sleap/gui/commands.py @@ -2475,8 +2475,11 @@ def ask(cls, context: CommandContext, params: dict) -> bool: class DeleteFrameLimitPredictions(InstanceDeleteCommand): @staticmethod def get_frame_instance_list(context: CommandContext, params: Dict): - """Called from the parent `InstanceDeleteCommand.ask` class. Returns a list of - instances to be deleted.""" + """Called from the parent `InstanceDeleteCommand.ask` method. + + Returns: + List of instances to be deleted. + """ predicted_instances = [] # Select the instances to be deleted for lf in context.labels.labeled_frames: