Skip to content

delete

sleap.gui.dialogs.delete

Dialog for deleting various subsets of instances in dataset.

Classes:

Name Description
DeleteDialog

Dialog for deleting various subsets of instances in dataset.

DeleteDialog

Bases: QDialog

Dialog for deleting various subsets of instances in dataset.

Parameters:

Name Type Description Default
context CommandContext

The CommandContext from which this dialog is being shown. The context provides both a labels (Labels) and a state (GuiState).

required

Methods:

Name Description
get_frames_instances

Get list of instances based on drop-down menu options selected.

Source code in sleap/gui/dialogs/delete.py
class DeleteDialog(QtWidgets.QDialog):
    """
    Dialog for deleting various subsets of instances in dataset.

    Args:
        context: The `CommandContext` from which this dialog is being
            shown. The context provides both a `labels` (`Labels`) and a
            `state` (`GuiState`).

    """

    # NOTE: use type by name (rather than importing CommandContext) to avoid
    # circular includes.
    def __init__(
        self,
        context: "CommandContext",
        *args,
        **kwargs,
    ):
        super(DeleteDialog, self).__init__(*args, **kwargs)

        self.context = context

        # Layout for main form and buttons
        self.form_widget = self._make_form_widget()
        buttons_layout_widget = self._make_button_widget()

        # Layout for entire dialog
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.form_widget)
        layout.addWidget(buttons_layout_widget)

        self.setLayout(layout)

        self.accepted.connect(self.delete)

    def _make_form_widget(self):
        self.tracks = self.context.labels.tracks

        widget = QtWidgets.QGroupBox()
        layout = QtWidgets.QFormLayout()

        self.instance_type_menu = formbuilder.FieldComboWidget()
        self.frames_menu = formbuilder.FieldComboWidget()
        self.tracks_menu = formbuilder.FieldComboWidget()

        instance_type_options = [
            "predicted instances",
            "user instances",
            "all instances",
        ]

        frame_options = [
            "current frame",
            "current video",
        ]
        if len(self.context.labels.videos) > 1:
            frame_options.append("all videos")
        if self.context.state["has_frame_range"]:
            frame_options.extend(
                ["selected clip", "current video except for selected clip"]
            )

        if self.tracks:
            track_options = [
                "any track identity (including none)",
                "no track identity set",
            ]
            self._track_idx_offset = len(track_options)
            track_options.extend([track.name for track in self.tracks])
        else:
            self._track_idx_offset = 0
            track_options = []

        self.instance_type_menu.set_options(instance_type_options)
        self.frames_menu.set_options(frame_options)
        self.tracks_menu.set_options(track_options)

        layout.addRow("Delete", self.instance_type_menu)
        layout.addRow("in", self.frames_menu)

        if self.tracks:
            layout.addRow("with", self.tracks_menu)

        widget.setLayout(layout)
        return widget

    def _make_button_widget(self):
        # Layout for buttons
        buttons = QtWidgets.QDialogButtonBox()
        self.cancel_button = buttons.addButton(QtWidgets.QDialogButtonBox.Cancel)
        self.delete_button = buttons.addButton(
            "Delete", QtWidgets.QDialogButtonBox.AcceptRole
        )

        buttons_layout = QtWidgets.QHBoxLayout()
        buttons_layout.addWidget(buttons, alignment=QtCore.Qt.AlignTop)

        buttons_layout_widget = QtWidgets.QWidget()
        buttons_layout_widget.setLayout(buttons_layout)

        # Connect actions for buttons
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        return buttons_layout_widget

    def get_selected_track(self):
        track_menu_idx = self.tracks_menu.currentIndex()
        track_idx = track_menu_idx - self._track_idx_offset

        if 0 <= track_idx < len(self.tracks):
            return self.tracks[track_idx]

        return None

    def get_frames_instances(
        self, instance_type_value: Text, frames_value: Text, tracks_value: Text
    ) -> List[Tuple[LabeledFrame, Instance]]:
        """Get list of instances based on drop-down menu options selected."""

        def inst_condition(inst):
            if instance_type_value.startswith("predicted"):
                if not hasattr(inst, "score"):
                    return False
            elif instance_type_value.startswith("user"):
                if hasattr(inst, "score"):
                    return False

            if tracks_value.startswith("any"):
                # print("match any track")
                pass
            elif tracks_value.startswith("no"):
                # print("match None track")
                if inst.track is not None:
                    return False
            else:
                track_to_match = self.get_selected_track()
                if track_to_match:
                    if inst.track != track_to_match:
                        return False

            return True

        labels = self.context.labels

        lf_list = []
        if frames_value == "current frame":
            lf_list = labels.find(
                video=self.context.state["video"],
                frame_idx=self.context.state["frame_idx"],
            )
        elif frames_value == "current video":
            lf_list = labels.find(
                video=self.context.state["video"],
            )
        elif frames_value == "all videos":
            lf_list = labels.labeled_frames
        elif frames_value == "selected clip":
            clip_range = range(*self.context.state["frame_range"])
            print(clip_range)
            lf_list = labels.find(
                video=self.context.state["video"], frame_idx=clip_range
            )
        elif frames_value == "current video except for selected clip":
            clip_range = range(*self.context.state["frame_range"])
            lf_list = [
                lf
                for lf in labels.labeled_frames
                if (
                    lf.video != self.context.state["video"]
                    or lf.frame_idx not in clip_range
                )
            ]
        else:
            raise ValueError(f"Invalid frames_value: {frames_value}")

        lf_inst_list = [
            (lf, inst) for lf in lf_list for inst in lf if inst_condition(inst)
        ]

        return lf_inst_list

    def delete(self):
        instance_type_value = self.instance_type_menu.value()
        frames_value = self.frames_menu.value()
        tracks_value = self.tracks_menu.value()

        lf_inst_list = self.get_frames_instances(
            instance_type_value=instance_type_value,
            frames_value=frames_value,
            tracks_value=tracks_value,
        )

        # print(len(lf_inst_list))
        # print(instance_type_value)
        # print(frames_value)
        # print(tracks_value)
        self._delete(lf_inst_list)

    def _delete(self, lf_inst_list: List[Tuple[LabeledFrame, Instance]]):
        # Delete the instances
        for lf, inst in lf_inst_list:
            remove_instance(self.context.labels, instance=inst, lf=lf)
        self.context.labels.clean()
        # self.context.labels.update()

        # # Update caches since we skipped doing this after each deletion
        # self.context.labels.update_cache()

        # Log update
        self.context.changestack_push("delete instances")

get_frames_instances(instance_type_value, frames_value, tracks_value)

Get list of instances based on drop-down menu options selected.

Source code in sleap/gui/dialogs/delete.py
def get_frames_instances(
    self, instance_type_value: Text, frames_value: Text, tracks_value: Text
) -> List[Tuple[LabeledFrame, Instance]]:
    """Get list of instances based on drop-down menu options selected."""

    def inst_condition(inst):
        if instance_type_value.startswith("predicted"):
            if not hasattr(inst, "score"):
                return False
        elif instance_type_value.startswith("user"):
            if hasattr(inst, "score"):
                return False

        if tracks_value.startswith("any"):
            # print("match any track")
            pass
        elif tracks_value.startswith("no"):
            # print("match None track")
            if inst.track is not None:
                return False
        else:
            track_to_match = self.get_selected_track()
            if track_to_match:
                if inst.track != track_to_match:
                    return False

        return True

    labels = self.context.labels

    lf_list = []
    if frames_value == "current frame":
        lf_list = labels.find(
            video=self.context.state["video"],
            frame_idx=self.context.state["frame_idx"],
        )
    elif frames_value == "current video":
        lf_list = labels.find(
            video=self.context.state["video"],
        )
    elif frames_value == "all videos":
        lf_list = labels.labeled_frames
    elif frames_value == "selected clip":
        clip_range = range(*self.context.state["frame_range"])
        print(clip_range)
        lf_list = labels.find(
            video=self.context.state["video"], frame_idx=clip_range
        )
    elif frames_value == "current video except for selected clip":
        clip_range = range(*self.context.state["frame_range"])
        lf_list = [
            lf
            for lf in labels.labeled_frames
            if (
                lf.video != self.context.state["video"]
                or lf.frame_idx not in clip_range
            )
        ]
    else:
        raise ValueError(f"Invalid frames_value: {frames_value}")

    lf_inst_list = [
        (lf, inst) for lf in lf_list for inst in lf if inst_condition(inst)
    ]

    return lf_inst_list