<commit_before>import abc

import numpy as np

from menpo.transform.base import Transformable
from menpo.visualize import LandmarkViewer
from menpo.visualize.base import Viewable


class Landmarkable(object):
    r"""
    Abstract interface for object that can have landmarks attached to them.
    Landmarkable objects have a public dictionary of landmarks which are
    managed by a :map:`LandmarkManager`. This means that
    different sets of landmarks can be attached to the same object.
    Landmarks can be N-dimensional and are expected to be some
    subclass of :map:`PointCloud`. These landmarks
    are wrapped inside a :map:`LandmarkGroup` object that performs
    useful tasks like label filtering and viewing.
    """

    __metaclass__ = abc.ABCMeta

    def __init__(self):
        super(Landmarkable, self).__init__()
        self._landmarks = LandmarkManager(self)

    @property
    def landmarks(self):
        return self._landmarks

    @landmarks.setter
    def landmarks(self, value):
        self._landmarks = value.copy()
        self._landmarks._target = self

    @property
    def n_landmark_groups(self):
        r"""
        The number of landmark groups on this object.

        :type: int
        """
        return self.landmarks.n_groups


class LandmarkManager(Transformable, Viewable):
    """
    Class for storing and manipulating Landmarks associated with an object.
    This involves managing the internal dictionary, as well as providing
    convenience functions for operations like viewing.

    Parameters
    ----------
    target : :class:`menpo.landmarks.base.Landmarkable`
        The parent object that owns these landmarks
    """

    def __init__(self, target):
        super(LandmarkManager, self).__init__()
        self.__target = target
        self._landmark_groups = {}

    def copy(self):
        r"""
        An efficient copy of this landmark manager.

        Note that the returned landmark manager will share the same target as
        self - the target will not be copied.

        Returns
        -------

        manager: :map:`LandmarkManager`
            A manager with an identical set of annotations to this one.

        """
        new_manager = LandmarkManager(self._target)
        new_manager._landmark_groups = {l: g.copy() for l, g in
                                        self._landmark_groups.iteritems()}
        return new_manager

    def __iter__(self):
        """
        Iterate over the internal landmark group dictionary
        """
        return iter(self._landmark_groups)

    def __setitem__(self, group_label, value):
        """
        Sets a new landmark group for the given label. This can be set using
        an existing landmark group, or using a PointCloud. Existing landmark
        groups will have their target reset. If a PointCloud is provided then
        all landmarks belong to a single label `all`.

        Parameters
        ----------
        group_label : String
            Label of new group.
        value : LandmarkGroup or PointCloud
            The new landmark group to set.

        Raises
        ------
        DimensionalityError
            If the landmarks and the shape are not of the same dimensionality.
        """
        from menpo.shape import PointCloud
        # firstly, make sure the dim is correct
        if value.n_dims != self._target.n_dims:
            raise ValueError(
                "Trying to set {}D landmarks on a "
                "{}D shape".format(value.n_dims, self._target.n_dims))
        if isinstance(value, PointCloud):
            # Copy the PointCloud so that we take ownership of the memory
            lmark_group = LandmarkGroup(
                self._target, group_label, value,
                {'all': np.ones(value.n_points, dtype=np.bool)})
        elif isinstance(value, LandmarkGroup):
            # Copy the landmark group so that we now own it
            lmark_group = value.copy()
            # check the target is set correctly
            lmark_group._group_label = group_label
            lmark_group._target = self._target
        else:
            raise ValueError('Valid types are PointCloud or LandmarkGroup')

        self._landmark_groups[group_label] = lmark_group

    def __getitem__(self, group_label=None):
        """
        Returns the group for the provided label.

        Parameters
        ---------
        group_label : String, optional
            The label of the group. If None is provided, and if there is only
            one group, the unambiguous group will be returned.

            Default: None

        Returns
        -------
        lmark_group : :class:`LandmarkGroup`
            The matching landmark group.
        """
        if group_label is None:
            if self.n_groups == 1:
                group_label = self.group_labels[0]
            else:
                raise ValueError("Cannot use None as a key as there are {} "
                                 "landmark groups".format(self.n_groups))
        return self._landmark_groups[group_label]

    @property
    def _target(self):
        return self.__target

    @_target.setter
    def _target(self, value):
        self.__target = value
        for group in self._landmark_groups.itervalues():
            group._target = self.__target

    @property
    def n_groups(self):
        """
        Total number of labels.

        :type: int
        """
        return len(self._landmark_groups)

    @property
    def has_landmarks(self):
        """
        Whether the object has landmarks or not<commit_msg>Add the del method to landmarks<commit_after>import abc

import numpy as np

from menpo.transform.base import Transformable
from menpo.visualize import LandmarkViewer
from menpo.visualize.base import Viewable


class Landmarkable(object):
    r"""
    Abstract interface for object that can have landmarks attached to them.
    Landmarkable objects have a public dictionary of landmarks which are
    managed by a :map:`LandmarkManager`. This means that
    different sets of landmarks can be attached to the same object.
    Landmarks can be N-dimensional and are expected to be some
    subclass of :map:`PointCloud`. These landmarks
    are wrapped inside a :map:`LandmarkGroup` object that performs
    useful tasks like label filtering and viewing.
    """

    __metaclass__ = abc.ABCMeta

    def __init__(self):
        super(Landmarkable, self).__init__()
        self._landmarks = LandmarkManager(self)

    @property
    def landmarks(self):
        return self._landmarks

    @landmarks.setter
    def landmarks(self, value):
        self._landmarks = value.copy()
        self._landmarks._target = self

    @property
    def n_landmark_groups(self):
        r"""
        The number of landmark groups on this object.

        :type: int
        """
        return self.landmarks.n_groups


class LandmarkManager(Transformable, Viewable):
    """
    Class for storing and manipulating Landmarks associated with an object.
    This involves managing the internal dictionary, as well as providing
    convenience functions for operations like viewing.

    Parameters
    ----------
    target : :class:`menpo.landmarks.base.Landmarkable`
        The parent object that owns these landmarks
    """

    def __init__(self, target):
        super(LandmarkManager, self).__init__()
        self.__target = target
        self._landmark_groups = {}

    def copy(self):
        r"""
        An efficient copy of this landmark manager.

        Note that the returned landmark manager will share the same target as
        self - the target will not be copied.

        Returns
        -------

        manager: :map:`LandmarkManager`
            A manager with an identical set of annotations to this one.

        """
        new_manager = LandmarkManager(self._target)
        new_manager._landmark_groups = {l: g.copy() for l, g in
                                        self._landmark_groups.iteritems()}
        return new_manager

    def __iter__(self):
        """
        Iterate over the internal landmark group dictionary
        """
        return iter(self._landmark_groups)

    def __setitem__(self, group_label, value):
        """
        Sets a new landmark group for the given label. This can be set using
        an existing landmark group, or using a PointCloud. Existing landmark
        groups will have their target reset. If a PointCloud is provided then
        all landmarks belong to a single label `all`.

        Parameters
        ----------
        group_label : String
            Label of new group.
        value : LandmarkGroup or PointCloud
            The new landmark group to set.

        Raises
        ------
        DimensionalityError
            If the landmarks and the shape are not of the same dimensionality.
        """
        from menpo.shape import PointCloud
        # firstly, make sure the dim is correct
        if value.n_dims != self._target.n_dims:
            raise ValueError(
                "Trying to set {}D landmarks on a "
                "{}D shape".format(value.n_dims, self._target.n_dims))
        if isinstance(value, PointCloud):
            # Copy the PointCloud so that we take ownership of the memory
            lmark_group = LandmarkGroup(
                self._target, group_label, value,
                {'all': np.ones(value.n_points, dtype=np.bool)})
        elif isinstance(value, LandmarkGroup):
            # Copy the landmark group so that we now own it
            lmark_group = value.copy()
            # check the target is set correctly
            lmark_group._group_label = group_label
            lmark_group._target = self._target
        else:
            raise ValueError('Valid types are PointCloud or LandmarkGroup')

        self._landmark_groups[group_label] = lmark_group

    def __getitem__(self, group_label=None):
        """
        Returns the group for the provided label.

        Parameters
        ---------
        group_label : String, optional
            The label of the group. If None is provided, and if there is only
            one group, the unambiguous group will be returned.

            Default: None

        Returns
        -------
        lmark_group : :class:`LandmarkGroup`
            The matching landmark group.
        """
        if group_label is None:
            if self.n_groups == 1:
                group_label = self.group_labels[0]
            else:
                raise ValueError("Cannot use None as a key as there are {} "
                                 "landmark groups".format(self.n_groups))
        return self._landmark_groups[group_label]

    def __delitem__(self, group_label):
        """
        Delete the group for the provided label.

        Parameters
        ---------
        group_label : String
            The label of the group.
        """
        del self._landmark_groups[group_label]

    @property
    def _target(self):
        return self.__target

    @_target.setter
    def _target(self, value):
        self.__target = value
        for group in self._landmark_groups.itervalues():
            group._target = self.__target

    @property
    def n_groups(self):
        """
        Total number of labels.

        :type: int
        """
        return len(self._landmark_groups)

    @property
    def has_landmarks(self):
        """
        Whether the object has landmarks or not
{'fraction_non_alphanumeric': 0.07329614781244553, 'fraction_numerical': 0.0003486142583231654, 'mean_word_length': 2.0070754716981134, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7021102', 'n_tokens_mistral': 2949, 'n_tokens_neox': 2835, 'n_words': 1042}