示例#1
0
class MaskCategoriesMixin(AttrsMixin):
    """A mixin class supporting category information of a MaskSubcatalog.

    Attributes:
        categories: All the possible categories in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the category names as keys
            and the :class:`~tensorbay.label.supports.MaskCategoryInfo` as values.
        category_delimiter: The delimiter in category values indicating parent-child relationship.

    """

    category_delimiter: str = attr(is_dynamic=True, key=camel)
    categories: NameList[MaskCategoryInfo] = attr(is_dynamic=True)

    def get_category_to_index(self) -> Dict[str, int]:
        """Return the dict containing the conversion from category name to category id.

        Returns:
            A dict containing the conversion from category name to category id.

        """
        if not hasattr(self, "categories"):
            return {}

        return {item.name: item.category_id for item in self.categories}

    def get_index_to_category(self) -> Dict[int, str]:
        """Return the dict containing the conversion from category id to category name.

        Returns:
            A dict containing the conversion from category id to category name.

        """
        if not hasattr(self, "categories"):
            return {}

        return {item.category_id: item.name for item in self.categories}

    def add_category(self,
                     name: str,
                     category_id: int,
                     description: str = "") -> None:
        """Add a category to the Subcatalog.

        Arguments:
            name: The name of the category.
            category_id: The id of the category.
            description: The description of the category.

        """
        if not hasattr(self, "categories"):
            self.categories = NameList()

        self.categories.append(MaskCategoryInfo(name, category_id,
                                                description))
示例#2
0
class User(AttrsMixin, ReprMixin):
    """This class defines the basic concept of a user with an action.

    Arguments:
        name: The name of the user.
        date: The date of the user action.

    """

    _T = TypeVar("_T", bound="User")

    _repr_attrs = ("date",)

    name: str = attr()
    date: int = attr()

    def __init__(self, name: str, date: int) -> None:
        self.name = name
        self.date = date

    def _repr_head(self) -> str:
        return f'{self.__class__.__name__}("{self.name}")'

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`User` instance from the given contents.

        Arguments:
            contents: A dict containing all the information of the commit::

                    {
                        "name": <str>
                        "date": <int>
                    }

        Returns:
            A :class:`User` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the user information into a dict.

        Returns:
            A dict containing all the information of the user::

                {
                    "name": <str>
                    "date": <int>
                }

        """
        return self._dumps()
示例#3
0
class _LabelBase(AttrsMixin, ReprMixin):
    """This class defines the basic concept of label.

    :class:`_LabelBase` is the most basic label level in the TensorBay dataset structure,
    and is the base class for the following various types of label classes.

    Each :class:`_LabelBase` object
    contains one annotaion of a :class:`~tensorbay.dataset.data.Data` object.

    Arguments:
        category: The category of the label.
        attributes: The attributes of the label.
        instance: The instance id of the label.

    Attributes:
        category: The category of the label.
        attributes: The attributes of the label.
        instance: The instance id of the label.

    """

    _repr_attrs: Tuple[str, ...] = ("category", "attributes", "instance")

    category: str = attr(is_dynamic=True)
    attributes: AttributeType = attr(is_dynamic=True)
    instance: str = attr(is_dynamic=True)

    def __init__(
        self,
        category: Optional[str] = None,
        attributes: Optional[AttributeType] = None,
        instance: Optional[str] = None,
    ):
        if category:
            self.category = category
        if attributes:
            self.attributes = attributes
        if instance:
            self.instance = instance

    def dumps(self) -> Dict[str, Any]:
        """Dumps the label into a dict.

        Returns:
            A dict containing all the information of the label.
            See dict format details in ``dumps()`` of different label classes .

        """
        return self._dumps()
示例#4
0
class MaskCategoryInfo(CategoryInfo):
    """This class represents the information of a category, including name, id and description.

    Arguments:
        name: The name of the category.
        category_id: The id of the category.
        description: The description of the category.

    Attributes:
        name: The name of the category.
        category_id: The id of the category.
        description: The description of the category.

    Examples:
        >>> MaskCategoryInfo(name="example", category_id=1, description="This is an example")
        MaskCategoryInfo("example")(
          (category_id): 1
        )

    """

    _repr_attrs = ("category_id", )

    category_id: int = attr(key=camel)

    def __init__(self,
                 name: str,
                 category_id: int,
                 description: str = "") -> None:
        super().__init__(name, description)
        self.category_id = category_id
示例#5
0
class SubcatalogBase(ReprMixin, AttrsMixin):
    """This is the base class for different types of subcatalogs.

    It defines the basic concept of Subcatalog, which is the collection of the labels information.
    Subcatalog contains the features, fields and specific definitions of the labels.

    The Subcatalog format varies by label type.

    Arguments:
        description: The description of the entire subcatalog.

    Attributes:
        description: The description of the entire subcatalog.

    """

    _T = TypeVar("_T", bound="SubcatalogBase")

    _repr_type = ReprType.INSTANCE
    _repr_attrs: Tuple[str, ...] = (
        "is_sample",
        "sample_rate",
        "is_tracking",
        "keypoints",
        "category_delimiter",
        "categories",
        "attributes",
        "lexicon",
    )
    description: str = attr(default="")

    def __init__(self, description: str = "") -> None:
        self.description = description

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a subcatalog from a dict containing the information of the subcatalog.

        Arguments:
            contents: A dict containing the information of the subcatalog.

        Returns:
            The loaded :class:`SubcatalogBase` object.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the information of the subcatalog into a dict.

        Returns:
            A dict containing all the information of the subcatalog.

        """
        return self._dumps()
示例#6
0
class TeamInfo(NameMixin):
    """This class defines the basic concept of a TensorBay team.

    Arguments:
        name: The name of the team.
        email: The email of the team.
        description: The description of the team.

    """

    _T = TypeVar("_T", bound="TeamInfo")

    _repr_attrs = ("email",)

    email: Optional[str] = attr(default=None)

    def __init__(self, name: str, *, email: Optional[str] = None, description: str = "") -> None:
        super().__init__(name, description)
        self.email = email

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`TeamInfo` instance from the given contents.

        Arguments:
            contents: A dict containing all the information of the commit::

                    {
                        "name": <str>
                        "email": <str>
                        "description": <str>
                    }

        Returns:
            A :class:`TeamInfo` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the information into a dict.

        Returns:
            A dict containing all the information of the team::

                {
                        "name": <str>
                        "email": <str>
                        "description": <str>
                }

        """
        return self._dumps()
示例#7
0
class IsTrackingMixin(AttrsMixin):
    """A mixin class supporting tracking information of a subcatalog.

    Arguments:
        is_tracking: Whether the Subcatalog contains tracking information.

    Attributes:
        is_tracking: Whether the Subcatalog contains tracking information.

    """

    is_tracking: bool = attr(key=camel, default=False)

    def __init__(self, is_tracking: bool = False) -> None:
        self.is_tracking = is_tracking
示例#8
0
class DiffBase(AttrsMixin, ReprMixin):
    """This class defines the basic structure of a diff.

    Attributes:
        action: The concrete action.

    """

    _T = TypeVar("_T", bound="DiffBase")

    _repr_attrs: Tuple[str, ...] = ("action", )

    action: str = attr()

    def __init__(self, action: str) -> None:
        self.action = action

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`DiffBase` instance from the given contents.

        Arguments:
            contents: A dict containing all the information of the diff::

                    {
                        "action": <str>
                    }

        Returns:
            A :class:`DiffBase` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the information of the diff into a dict.

        Returns:
            A dict containing all the information of the diff::

                {
                    "action": <str>
                }

        """
        return self._dumps()
示例#9
0
class Commit(AttrsMixin, ReprMixin):
    """This class defines the structure of a commit.

    Arguments:
        commit_id: The commit id.
        parent_commit_id: The parent commit id.
        title: The commit title.
        description: The commit description.
        committer: The commit user.

    """

    _T = TypeVar("_T", bound="Commit")

    _repr_attrs: Tuple[str, ...] = ("parent_commit_id", "title", "committer")
    _repr_maxlevel = 2

    commit_id: str = attr(key=camel)
    parent_commit_id: Optional[str] = attr(key=camel)
    title: str = attr()
    description: str = attr(default="")
    committer: User = attr()

    def __init__(  # pylint: disable=too-many-arguments
        self,
        commit_id: str,
        parent_commit_id: Optional[str],
        title: str,
        description: str,
        committer: User,
    ) -> None:
        self.commit_id = commit_id
        self.parent_commit_id = parent_commit_id
        self.title = title
        self.description = description
        self.committer = committer

    def _repr_head(self) -> str:
        return f'{self.__class__.__name__}("{self.commit_id}")'

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`Commit` instance for the given contents.

        Arguments:
            contents: A dict containing all the information of the commit::

                    {
                        "commitId": <str>
                        "parentCommitId": <str> or None
                        "title": <str>
                        "description": <str>
                        "committer": {
                            "name": <str>
                            "date": <int>
                        }
                    }

        Returns:
            A :class:`Commit` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the commit information into a dict.

        Returns:
            A dict containing all the information of the commit::

                {
                    "commitId": <str>
                    "parentCommitId": <str> or None
                    "title": <str>
                    "description": <str>
                    "committer": {
                        "name": <str>
                        "date": <int>
                    }
                }

        """
        return self._dumps()
class Keypoints2DSubcatalog(SubcatalogBase, IsTrackingMixin, CategoriesMixin,
                            AttributesMixin):
    """This class defines the subcatalog for 2D keypoints type of labels.

    Arguments:
        is_tracking: A boolean value indicates whether the corresponding
            subcatalog contains tracking information.

    Attributes:
        description: The description of the entire 2D keypoints subcatalog.
        categories: All the possible categories in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the category names as keys
            and the :class:`~tensorbay.label.supports.CategoryInfo` as values.
        category_delimiter: The delimiter in category values indicating parent-child relationship.
        attributes: All the possible attributes in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the attribute names as keys
            and the :class:`~tensorbay.label.attribute.AttributeInfo` as values.
        is_tracking: Whether the Subcatalog contains tracking information.

    Examples:
        *Initialization Method 1:* Init from ``Keypoints2DSubcatalog.loads()`` method.

        >>> catalog = {
        ...     "KEYPOINTS2D": {
        ...         "isTracking": True,
        ...         "categories": [{"name": "0"}, {"name": "1"}],
        ...         "attributes": [{"name": "gender", "enum": ["male", "female"]}],
        ...         "keypoints": [
        ...             {
        ...                 "number": 2,
        ...                  "names": ["L_shoulder", "R_Shoulder"],
        ...                  "skeleton": [(0, 1)],
        ...             }
        ...         ],
        ...     }
        ... }
        >>> Keypoints2DSubcatalog.loads(catalog["KEYPOINTS2D"])
        Keypoints2DSubcatalog(
          (is_tracking): True,
          (keypoints): [...],
          (categories): NameList [...],
          (attributes): NameList [...]
        )

        *Initialization Method 2:* Init an empty Keypoints2DSubcatalog and then add the attributes.

        >>> from tensorbay.label import CategoryInfo, AttributeInfo, KeypointsInfo
        >>> from tensorbay.utility import NameList
        >>> categories = NameList()
        >>> categories.append(CategoryInfo("a"))
        >>> attributes = NameList()
        >>> attributes.append(AttributeInfo("gender", enum=["female", "male"]))
        >>> keypoints2d_subcatalog = Keypoints2DSubcatalog()
        >>> keypoints2d_subcatalog.is_tracking = True
        >>> keypoints2d_subcatalog.categories = categories
        >>> keypoints2d_subcatalog.attributes = attributes
        >>> keypoints2d_subcatalog.add_keypoints(
        ...     2,
        ...     names=["L_shoulder", "R_Shoulder"],
        ...     skeleton=[(0,1)],
        ...     visible="BINARY",
        ...     parent_categories="shoulder",
        ...     description="12345",
        ... )
        >>> keypoints2d_subcatalog
        Keypoints2DSubcatalog(
          (is_tracking): True,
          (keypoints): [...],
          (categories): NameList [...],
          (attributes): NameList [...]
        )

    """

    _keypoints: List[KeypointsInfo] = attr(key="keypoints")

    def __init__(self, is_tracking: bool = False) -> None:
        SubcatalogBase.__init__(self)
        IsTrackingMixin.__init__(self, is_tracking)
        self._keypoints: List[KeypointsInfo] = []

    @property
    def keypoints(self) -> List[KeypointsInfo]:
        """Return the KeypointsInfo of the Subcatalog.

        Returns:
            A list of :class:`~tensorbay.label.supports.KeypointsInfo`.

        Examples:
            >>> keypoints2d_subcatalog = Keypoints2DSubcatalog()
            >>> keypoints2d_subcatalog.add_keypoints(2)
            >>> keypoints2d_subcatalog.keypoints
            [KeypointsInfo(
              (number): 2
            )]

        """
        return self._keypoints

    def add_keypoints(
        self,
        number: int,
        *,
        names: Optional[Iterable[str]] = None,
        skeleton: Optional[Iterable[Iterable[int]]] = None,
        visible: Optional[str] = None,
        parent_categories: Union[None, str, Iterable[str]] = None,
        description: str = "",
    ) -> None:
        """Add a type of keypoints to the subcatalog.

        Arguments:
            number: The number of keypoints.
            names: All the names of keypoints.
            skeleton: The skeleton of the keypoints
                indicating which keypoint should connect with another.
            visible: The visible type of the keypoints, can only be 'BINARY' or 'TERNARY'.
                It determines the range of the
                :attr:`Keypoint2D.v<tensorbay.geometry.keypoint.Keypoint2D.v>`.
            parent_categories: The parent categories of the keypoints.
            description: The description of keypoints.

        Examples:
            >>> keypoints2d_subcatalog = Keypoints2DSubcatalog()
            >>> keypoints2d_subcatalog.add_keypoints(
            ...     2,
            ...     names=["L_shoulder", "R_Shoulder"],
            ...     skeleton=[(0,1)],
            ...     visible="BINARY",
            ...     parent_categories="shoulder",
            ...     description="12345",
            ... )
            >>> keypoints2d_subcatalog.keypoints
            [KeypointsInfo(
              (number): 2,
              (names): [...],
              (skeleton): [...],
              (visible): 'BINARY',
              (parent_categories): [...]
            )]

        """
        self._keypoints.append(
            KeypointsInfo(
                number=number,
                names=names,
                skeleton=skeleton,
                visible=visible,
                parent_categories=parent_categories,
                description=description,
            ))

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the information of the keypoints into a dict.

        Returns:
            A dict containing all the information of this Keypoints2DSubcatalog.

        Examples:
            >>> # keypoints2d_subcatalog is the instance initialized above.
            >>> keypoints2d_subcatalog.dumps()
            {
                'isTracking': True,
                'categories': [{'name': 'a'}],
                'attributes': [{'name': 'gender', 'enum': ['female', 'male']}],
                'keypoints': [
                    {
                        'number': 2,
                        'names': ['L_shoulder', 'R_Shoulder'],
                        'skeleton': [(0, 1)],
                    }
                ]
            }

        """
        return self._dumps()
class StorageConfig(AttrsMixin, ReprMixin):
    """This is a class stores the information of storage config.

    Arguments:
        name: The storage config name.
        file_path: Storage config path of the bucket.
        type_: Type of the storage provider, such as oss, s3, azure.
        is_graviti_storage: Whether the config is belong to graviti.

    """

    _T = TypeVar("_T", bound="StorageConfig")

    _repr_attrs = ("file_path", "type", "is_graviti_storage")

    name: str = attr()
    file_path: str = attr(key=camel)
    type: str = attr()
    is_graviti_storage: bool = attr(key=camel)

    def __init__(  # pylint: disable=too-many-arguments
        self,
        name: str,
        file_path: str,
        type_: str,
        is_graviti_storage: bool,
    ) -> None:
        self.name = name
        self.file_path = file_path
        self.type = type_
        self.is_graviti_storage = is_graviti_storage

    def _repr_head(self) -> str:
        return f'{self.__class__.__name__}("{self.name}")'

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`StorageConfig` instance from the given contents.

        Arguments:
            contents: The given dict containing the storage config::

                {
                    "name":                 <str>,
                    "filePath":             <str>,
                    "type":                 <str>,
                    "isGravitiStorage":     <boolean>
                }

        Returns:
            The loaded :class:`StorageConfig` instance.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps the storage config into a dict.

        Returns:
            A dict containing all the information of the StorageConfig::

                {
                    "name":                 <str>,
                    "filePath":             <str>,
                    "type":                 <str>,
                    "isGravitiStorage":     <boolean>
                }

        """
        return self._dumps()
示例#12
0
class AttributesMixin(AttrsMixin):
    """A mixin class supporting attribute information of a subcatalog.

    Attributes:
        attributes: All the possible attributes in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the attribute names as keys
            and the :class:`~tensorbay.label.attribute.AttributeInfo` as values.

    """

    attributes: NameList[AttributeInfo] = attr(is_dynamic=True)

    def add_attribute(
        self,
        name: str,
        *,
        type_: _ArgType = "",
        enum: Optional[Iterable[_EnumElementType]] = None,
        minimum: Optional[float] = None,
        maximum: Optional[float] = None,
        items: Optional[Items] = None,
        parent_categories: Union[None, str, Iterable[str]] = None,
        description: str = "",
    ) -> None:
        """Add an attribute to the Subcatalog.

        Arguments:
            name: The name of the attribute.
            type_: The type of the attribute value, could be a single type or multi-types.
                The type must be within the followings:
                - array
                - boolean
                - integer
                - number
                - string
                - null
                - instance
            enum: All the possible values of an enumeration attribute.
            minimum: The minimum value of number type attribute.
            maximum: The maximum value of number type attribute.
            items: The items inside array type attributes.
            parent_categories: The parent categories of the attribute.
            description: The description of the attributes.

        """
        attribute_info = AttributeInfo(
            name,
            type_=type_,
            enum=enum,
            minimum=minimum,
            maximum=maximum,
            items=items,
            parent_categories=parent_categories,
            description=description,
        )

        if not hasattr(self, "attributes"):
            self.attributes = NameList()

        self.attributes.append(attribute_info)
class Notes(AttrsMixin, ReprMixin):
    """This is a class stores the basic information of :class:`DatasetBase`.

    Arguments:
        is_continuous: Whether the data inside the dataset is time-continuous.
        bin_point_cloud_fields: The field names of the bin point cloud files in the dataset.

    """

    _T = TypeVar("_T", bound="Notes")

    _repr_attrs = ("is_continuous", "bin_point_cloud_fields")

    is_continuous: bool = attr(key=camel, default=False)
    bin_point_cloud_fields: Optional[List[str]] = attr(key=camel, default=None)

    def __init__(
            self,
            is_continuous: bool = False,
            bin_point_cloud_fields: Optional[Iterable[str]] = None) -> None:
        self.is_continuous = is_continuous
        self.bin_point_cloud_fields = (list(bin_point_cloud_fields)
                                       if bin_point_cloud_fields else None)

    def __getitem__(self, key: str) -> Any:
        try:
            return getattr(self, key)
        except AttributeError as error:
            raise KeyError(key) from error

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`Notes` instance from the given contents.

        Arguments:
            contents: The given dict containing the dataset notes::

                    {
                        "isContinuous":            <boolean>
                        "binPointCloudFields": [   <array> or null
                                <field_name>,      <str>
                                ...
                        ]
                    }

        Returns:
            The loaded :class:`Notes` instance.

        """
        return common_loads(cls, contents)

    def keys(self) -> KeysView[str]:
        """Return the valid keys within the notes.

        Returns:
            The valid keys within the notes.

        """
        return KeysView(self._repr_attrs)  # type: ignore[arg-type]

    def dumps(self) -> Dict[str, Any]:
        """Dumps the notes into a dict.

        Returns:
            A dict containing all the information of the Notes::

                {
                    "isContinuous":           <boolean>
                    "binPointCloudFields": [  <array> or null
                        <field_name>,         <str>
                        ...
                    ]
                }

        """
        return self._dumps()
class AttributeInfo(NameMixin, Items):
    """This class represents the information of an attribute.

    It refers to the `Json schema`_ method to describe an attribute.

    .. todo::
        The format of argument *type_* on the generated web page is incorrect.

    Arguments:
        name: The name of the attribute.
        type_: The type of the attribute value, could be a single type or multi-types.
            The type must be within the followings:

                - array
                - boolean
                - integer
                - number
                - string
                - null
                - instance

        enum: All the possible values of an enumeration attribute.
        minimum: The minimum value of number type attribute.
        maximum: The maximum value of number type attribute.
        items: The items inside array type attributes.
        parent_categories: The parent categories of the attribute.
        description: The description of the attribute.

    Attributes:
        type: The type of the attribute value, could be a single type or multi-types.
        enum: All the possible values of an enumeration attribute.
        minimum: The minimum value of number type attribute.
        maximum: The maximum value of number type attribute.
        items: The items inside array type attributes.
        parent_categories: The parent categories of the attribute.
        description: The description of the attribute.

    .. _Json schema: https://json-schema.org/

    Examples:
        >>> from tensorbay.label import Items
        >>> items = Items(type_="integer", enum=[1, 2, 3, 4, 5], minimum=1, maximum=5)
        >>> AttributeInfo(
        ...     name="example",
        ...     type_="array",
        ...     enum=[1, 2, 3, 4, 5],
        ...     items=items,
        ...     minimum=1,
        ...     maximum=5,
        ...     parent_categories=["parent_category_of_example"],
        ...     description="This is an example",
        ... )
        AttributeInfo("example")(
          (type): 'array',
          (enum): [
            1,
            2,
            3,
            4,
            5
          ],
          (minimum): 1,
          (maximum): 5,
          (items): Items(
            (type): 'integer',
            (enum): [...],
            (minimum): 1,
            (maximum): 5
          ),
          (parent_categories): [
            'parent_category_of_example'
          ]
        )

    """

    _T = TypeVar("_T", bound="AttributeInfo")

    _repr_attrs = Items._repr_attrs + ("parent_categories", )
    _repr_maxlevel = 2

    _attrs_base: Items = attr_base(key=None)
    parent_categories: List[str] = attr(is_dynamic=True, key=camel)

    def __init__(
        self,
        name: str,
        *,
        type_: _ArgType = "",
        enum: Optional[Iterable[_EnumElementType]] = None,
        minimum: Optional[float] = None,
        maximum: Optional[float] = None,
        items: Optional[Items] = None,
        parent_categories: Union[None, str, Iterable[str]] = None,
        description: str = "",
    ):
        NameMixin.__init__(self, name, description)
        Items.__init__(self,
                       type_=type_,
                       enum=enum,
                       minimum=minimum,
                       maximum=maximum,
                       items=items)

        if not parent_categories:
            return

        if isinstance(parent_categories, str):
            self.parent_categories = [parent_categories]
        else:
            self.parent_categories = list(parent_categories)

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Load an AttributeInfo from a dict containing the attribute information.

        Arguments:
            contents: A dict containing the information of the attribute.

        Returns:
            The loaded :class:`AttributeInfo` object.

        Examples:
            >>> contents = {
            ...     "name": "example",
            ...     "type": "array",
            ...     "items": {"type": "boolean"},
            ...     "description": "This is an example",
            ...     "parentCategories": ["parent_category_of_example"],
            ... }
            >>> AttributeInfo.loads(contents)
            AttributeInfo("example")(
              (type): 'array',
              (items): Items(
                (type): 'boolean',
              ),
              (parent_categories): [
                'parent_category_of_example'
              ]
            )

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps the information of this attribute into a dict.

        Returns:
            A dict containing all the information of this attribute.

        Examples:
            >>> from tensorbay.label import Items
            >>> items = Items(type_="integer", minimum=1, maximum=5)
            >>> attributeinfo = AttributeInfo(
            ...     name="example",
            ...     type_="array",
            ...     items=items,
            ...     parent_categories=["parent_category_of_example"],
            ...     description="This is an example",
            ... )
            >>> attributeinfo.dumps()
            {
                'name': 'example',
                'description': 'This is an example',
                'type': 'array',
                'items': {'type': 'integer', 'minimum': 1, 'maximum': 5},
                'parentCategories': ['parent_category_of_example'],
            }

        """
        return self._dumps()
示例#15
0
class CameraIntrinsics(ReprMixin, AttrsMixin):
    """CameraIntrinsics represents camera intrinsics.

    Camera intrinsic parameters including camera matrix and distortion coeffecients.
    They describe the mapping of the scene in front of the camera to the pixels in the final image.

    Arguments:
        fx: The x axis focal length expressed in pixels.
        fy: The y axis focal length expressed in pixels.
        cx: The x coordinate of the so called principal point that should be in the center of
            the image.
        cy: The y coordinate of the so called principal point that should be in the center of
            the image.
        skew: It causes shear distortion in the projected image.
        camera_matrix: A 3x3 Sequence of the camera matrix.
        **kwargs: Float values to initialize :class:`DistortionCoefficients`.

    Attributes:
        camera_matrix: A 3x3 Sequence of the camera matrix.
        distortion_coefficients: It is the deviation from rectilinear projection. It includes
        radial distortion and tangential distortion.

    Examples:
        >>> matrix = [[1, 3, 3],
        ...           [0, 2, 4],
        ...           [0, 0, 1]]

        *Initialization Method 1*: Init from 3x3 sequence array.

        >>> camera_intrinsics = CameraIntrinsics(camera_matrix=matrix, p1=5, k1=6)
        >>> camera_intrinsics
        CameraIntrinsics(
            (camera_matrix): CameraMatrix(
                    (fx): 1,
                    (fy): 2,
                    (cx): 3,
                    (cy): 4,
                    (skew): 3
                ),
            (distortion_coefficients): DistortionCoefficients(
                    (p1): 5,
                    (k1): 6
                )
        )

        *Initialization Method 2*: Init from camera calibration parameters, skew is optional.

        >>> camera_intrinsics = CameraIntrinsics(
        ...     fx=1,
        ...     fy=2,
        ...     cx=3,
        ...     cy=4,
        ...     p1=5,
        ...     k1=6,
        ...     skew=3
        ... )
        >>> camera_intrinsics
        CameraIntrinsics(
            (camera_matrix): CameraMatrix(
                (fx): 1,
                (fy): 2,
                (cx): 3,
                (cy): 4,
                (skew): 3
            ),
            (distortion_coefficients): DistortionCoefficients(
                (p1): 5,
                (k1): 6
            )
        )

    """

    _T = TypeVar("_T", bound="CameraIntrinsics")

    _repr_type = ReprType.INSTANCE
    _repr_attrs = ("camera_matrix", "distortion_coefficients")
    _repr_maxlevel = 2

    camera_matrix: CameraMatrix = attr(key=camel)
    distortion_coefficients: DistortionCoefficients = attr(is_dynamic=True,
                                                           key=camel)

    def __init__(  # pylint: disable=too-many-arguments
        self,
        fx: Optional[float] = None,
        fy: Optional[float] = None,
        cx: Optional[float] = None,
        cy: Optional[float] = None,
        skew: float = 0,
        *,
        camera_matrix: Optional[MatrixType] = None,
        **kwargs: float,
    ) -> None:
        self.camera_matrix = CameraMatrix(fx,
                                          fy,
                                          cx,
                                          cy,
                                          skew,
                                          matrix=camera_matrix)
        if kwargs:
            self.distortion_coefficients = DistortionCoefficients.loads(kwargs)

    @classmethod
    def loads(cls: Type[_T], contents: Mapping[str, Mapping[str,
                                                            float]]) -> _T:
        """Loads CameraIntrinsics from a dict containing the information.

        Arguments:
            contents: A dict containig camera matrix and distortion coefficients.

        Returns:
            A :class:`CameraIntrinsics` instance containing information from
            the contents dict.

        Examples:
            >>> contents = {
            ...     "cameraMatrix": {
            ...         "fx": 1,
            ...         "fy": 2,
            ...         "cx": 3,
            ...         "cy": 4,
            ...     },
            ...     "distortionCoefficients": {
            ...         "p1": 1,
            ...         "p2": 2,
            ...         "k1": 3,
            ...         "k2": 4
            ...     },
            ... }
            >>> camera_intrinsics = CameraIntrinsics.loads(contents)
            >>> camera_intrinsics
            CameraIntrinsics(
                (camera_matrix): CameraMatrix(
                    (fx): 1,
                    (fy): 2,
                    (cx): 3,
                    (cy): 4,
                    (skew): 0
                ),
                (distortion_coefficients): DistortionCoefficients(
                    (p1): 1,
                    (p2): 2,
                    (k1): 3,
                    (k2): 4
                )
            )

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Dict[str, float]]:
        """Dumps the camera intrinsics into a dict.

        Returns:
            A dict containing camera intrinsics.

        Examples:
            >>> camera_intrinsics.dumps()
            {'cameraMatrix': {'fx': 1, 'fy': 2, 'cx': 3, 'cy': 4, 'skew': 3},
            'distortionCoefficients': {'p1': 5, 'k1': 6}}

        """
        return self._dumps()

    def set_camera_matrix(  # pylint: disable=[too-many-arguments, invalid-name]
        self,
        fx: Optional[float] = None,
        fy: Optional[float] = None,
        cx: Optional[float] = None,
        cy: Optional[float] = None,
        skew: float = 0,
        *,
        matrix: Optional[MatrixType] = None,
    ) -> None:
        """Set camera matrix of the camera intrinsics.

        Arguments:
            fx: The x axis focal length expressed in pixels.
            fy: The y axis focal length expressed in pixels.
            cx: The x coordinate of the so called principal point that should be in the center of
                the image.
            cy: The y coordinate of the so called principal point that should be in the center of
                the image.
            skew: It causes shear distortion in the projected image.
            matrix: Camera matrix in 3x3 sequence.

        Examples:
            >>> camera_intrinsics.set_camera_matrix(fx=11, fy=12, cx=13, cy=14, skew=15)
            >>> camera_intrinsics
            CameraIntrinsics(
                (camera_matrix): CameraMatrix(
                    (fx): 11,
                    (fy): 12,
                    (cx): 13,
                    (cy): 14,
                    (skew): 15
                ),
                (distortion_coefficients): DistortionCoefficients(
                    (p1): 1,
                    (p2): 2,
                    (k1): 3,
                    (k2): 4
                )
            )

        """
        self.camera_matrix = CameraMatrix(fx, fy, cx, cy, skew, matrix=matrix)

    def set_distortion_coefficients(self, **kwargs: float) -> None:
        """Set distortion coefficients of the camera intrinsics.

        Arguments:
            **kwargs: Contains p1, p2, ..., k1, k2, ...

        Examples:
            >>> camera_intrinsics.set_distortion_coefficients(p1=11, p2=12, k1=13, k2=14)
            >>> camera_intrinsics
            CameraIntrinsics(
                (camera_matrix): CameraMatrix(
                    (fx): 11,
                    (fy): 12,
                    (cx): 13,
                    (cy): 14,
                    (skew): 15
                ),
                (distortion_coefficients): DistortionCoefficients(
                    (p1): 11,
                    (p2): 12,
                    (k1): 13,
                    (k2): 14
                )
            )

        """
        self.distortion_coefficients = DistortionCoefficients(**kwargs)

    def project(self,
                point: Sequence[float],
                is_fisheye: bool = False) -> Vector2D:
        """Project a point to the pixel coordinates.

        If distortion coefficients are provided, distort the point before projection.

        Arguments:
            point: A Sequence containing coordinates of the point to be projected.
            is_fisheye: Whether the sensor is fisheye camera, default is False.

        Returns:
            The coordinates on the pixel plane where the point is projected to.

        Examples:
            Project a point with 2 dimensions.

            >>> camera_intrinsics.project((1, 2))
            Vector2D(137.0, 510.0)

            Project a point with 3 dimensions.

            >>> camera_intrinsics.project((1, 2, 3))
            Vector2D(6.300411522633745, 13.868312757201647)

            Project a point with 2 dimensions, fisheye is True

            >>> camera_intrinsics.project((1, 2), is_fisheye=True)
            Vector2D(9.158401093771875, 28.633604375087504)

        """
        if hasattr(self, "distortion_coefficients"):
            point = self.distortion_coefficients.distort(point, is_fisheye)
        return self.camera_matrix.project(point)
class LabeledSentence(_LabelBase):
    """This class defines the concept of phonetic transcription lable.

    :class:`LabeledSentence` is the transcripted sentence type of label.
    which is often used for tasks such as automatic speech recognition.

    Arguments:
        sentence: A list of sentence.
        spell: A list of spell, only exists in Chinese language.
        phone: A list of phone.
        attributes: The attributes of the label.

    Attributes:
        sentence: The transcripted sentence.
        spell: The spell within the sentence, only exists in Chinese language.
        phone: The phone of the sentence label.
        attributes: The attributes of the label.

    Examples:
        >>> sentence = [Word(text="qi1shi2", begin=1, end=2)]
        >>> spell = [Word(text="qi1", begin=1, end=2)]
        >>> phone = [Word(text="q", begin=1, end=2)]
        >>> LabeledSentence(
        ...     sentence,
        ...     spell,
        ...     phone,
        ...     attributes={"key": "value"},
        ... )
        LabeledSentence(
          (sentence): [
            Word(
              (text): 'qi1shi2',
              (begin): 1,
              (end): 2
            )
          ],
          (spell): [
            Word(
              (text): 'qi1',
              (begin): 1,
              (end): 2
            )
          ],
          (phone): [
            Word(
              (text): 'q',
              (begin): 1,
              (end): 2
            )
          ],
          (attributes): {
            'key': 'value'
          }
        )

    """

    _T = TypeVar("_T", bound="LabeledSentence")

    _repr_attrs = ("sentence", "spell", "phone", "attributes")
    _repr_maxlevel = 3

    sentence: List[Word] = attr(is_dynamic=True)
    spell: List[Word] = attr(is_dynamic=True)
    phone: List[Word] = attr(is_dynamic=True)

    def __init__(
        self,
        sentence: Optional[Iterable[Word]] = None,
        spell: Optional[Iterable[Word]] = None,
        phone: Optional[Iterable[Word]] = None,
        *,
        attributes: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(attributes=attributes)
        if sentence:
            self.sentence = list(sentence)
        if spell:
            self.spell = list(spell)
        if phone:
            self.phone = list(phone)

    @staticmethod
    def _load_word(contents: Iterable[Dict[str, Any]]) -> List[Word]:
        return [Word.loads(word) for word in contents]

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a LabeledSentence from a dict containing the information of the label.

        Arguments:
            contents: A dict containing the information of the sentence label.

        Returns:
            The loaded :class:`LabeledSentence` object.

        Examples:
            >>> contents = {
            ...     "sentence": [{"text": "qi1shi2", "begin": 1, "end": 2}],
            ...     "spell": [{"text": "qi1", "begin": 1, "end": 2}],
            ...     "phone": [{"text": "q", "begin": 1, "end": 2}],
            ...     "attributes": {"key": "value"},
            ... }
            >>> LabeledSentence.loads(contents)
            LabeledSentence(
              (sentence): [
                Word(
                  (text): 'qi1shi2',
                  (begin): 1,
                  (end): 2
                )
              ],
              (spell): [
                Word(
                  (text): 'qi1',
                  (begin): 1,
                  (end): 2
                )
              ],
              (phone): [
                Word(
                  (text): 'q',
                  (begin): 1,
                  (end): 2
                )
              ],
              (attributes): {
                'key': 'value'
              }
            )

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps the current label into a dict.

        Returns:
            A dict containing all the information of the sentence label.

        Examples:
            >>> sentence = [Word(text="qi1shi2", begin=1, end=2)]
            >>> spell = [Word(text="qi1", begin=1, end=2)]
            >>> phone = [Word(text="q", begin=1, end=2)]
            >>> labeledsentence = LabeledSentence(
            ...     sentence,
            ...     spell,
            ...     phone,
            ...     attributes={"key": "value"},
            ... )
            >>> labeledsentence.dumps()
            {
                'attributes': {'key': 'value'},
                'sentence': [{'text': 'qi1shi2', 'begin': 1, 'end': 2}],
                'spell': [{'text': 'qi1', 'begin': 1, 'end': 2}],
                'phone': [{'text': 'q', 'begin': 1, 'end': 2}]
            }

        """
        return self._dumps()
示例#17
0
class UserInfo(NameMixin):
    """This class defines the basic concept of a TensorBay user.

    Arguments:
        name: The nickname of the user.
        email: The email of the user.
        mobile: The mobile of the user.
        description: The description of the user.
        team: The team of the user.

    """

    _T = TypeVar("_T", bound="UserInfo")

    _repr_attrs = ("email", "mobile", "team")

    _name: str = attr(key="nickname")
    email: Optional[str] = attr(default=None)
    mobile: Optional[str] = attr(default=None)
    team: Optional[TeamInfo] = attr(default=None)

    def __init__(
        self,
        name: str,
        *,
        email: Optional[str] = None,
        mobile: Optional[str] = None,
        description: str = "",
        team: Optional[TeamInfo] = None,
    ) -> None:
        super().__init__(name, description=description)
        self.email = email
        self.mobile = mobile
        self.team = team

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`UserInfo` instance from the given contents.

        Arguments:
            contents: A dict containing all the information of the commit::

                    {
                        "name": <str>
                        "email": <str>
                        "mobile": <str>
                        "description": <str>
                        "team": {  <dict>
                            "name": <str>
                            "email": <str>
                            "description": <str>
                        }
                    }

        Returns:
            A :class:`UserInfo` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the information into a dict.

        Returns:
            A dict containing all the information of the user::

                {
                        "name": <str>
                        "email": <str>
                        "mobile": <str>
                        "description": <str>
                        "team": {  <dict>
                            "name": <str>
                            "email": <str>
                            "description": <str>
                        }
                }

        """
        return self._dumps()
示例#18
0
class LabeledPolyline2D(_LabelBase, Polyline2D):
    """This class defines the concept of polyline2D label.

    :class:`LabeledPolyline2D` is the 2D polyline type of label,
    which is often used for CV tasks such as lane detection.

    Arguments:
        points: A list of 2D points representing the vertexes of the 2D polyline.
        category: The category of the label.
        attributes: The attributes of the label.
        instance: The instance id of the label.
        beizer_point_types: The beizer point types of the label.

    Attributes:
        category: The category of the label.
        attributes: The attributes of the label.
        instance: The instance id of the label.
        beizer_point_types: The beizer point types of the label.

    Examples:
        >>> LabeledPolyline2D(
        ...     [(1, 2), (2, 4), (2, 1)],
        ...     category="example",
        ...     attributes={"key": "value"},
        ...     instance="123",
        ...     beizer_point_types="LLL",
        ... )
        LabeledPolyline2D [
          Vector2D(1, 2),
          Vector2D(2, 4),
          Vector2D(2, 1)
        ](
          (beizer_point_types): 'LLL',
          (category): 'example',
          (attributes): {...},
          (instance): '123'
        )

    """

    _T = TypeVar("_T", bound="LabeledPolyline2D")

    _repr_type = ReprType.SEQUENCE
    _repr_attrs = ("beizer_point_types", ) + _LabelBase._repr_attrs
    _attrs_base: Polyline2D = attr_base(key="polyline2d")
    beizer_point_types: str = attr(is_dynamic=True, key=camel)

    def __init__(
        self,
        points: Optional[Iterable[Iterable[float]]] = None,
        *,
        category: Optional[str] = None,
        attributes: Optional[Dict[str, Any]] = None,
        instance: Optional[str] = None,
        beizer_point_types: Optional[str] = None,
    ):
        Polyline2D.__init__(self, points)  # type: ignore[arg-type]
        _LabelBase.__init__(self, category, attributes, instance)
        if beizer_point_types:
            self.beizer_point_types = beizer_point_types

    @classmethod
    def loads(cls: Type[_T],
              contents: Dict[str, Any]) -> _T:  # type: ignore[override]
        """Loads a LabeledPolyline2D from a dict containing the information of the label.

        Arguments:
            contents: A dict containing the information of the 2D polyline label.

        Returns:
            The loaded :class:`LabeledPolyline2D` object.

        Examples:
            >>> contents = {
            ...     "polyline2d": [{'x': 1, 'y': 2}, {'x': 2, 'y': 4}, {'x': 2, 'y': 1}],
            ...     "category": "example",
            ...     "attributes": {"key": "value"},
            ...     "instance": "12345",
            ...     "beizer_point_types": "LLL",
            ... }
            >>> LabeledPolyline2D.loads(contents)
            LabeledPolyline2D [
              Vector2D(1, 2),
              Vector2D(2, 4),
              Vector2D(2, 1)
            ](
              (beizer_point_types): 'LLL',
              (category): 'example',
              (attributes): {...},
              (instance): '12345'
            )

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:  # type: ignore[override]
        """Dumps the current 2D polyline label into a dict.

        Returns:
            A dict containing all the information of the 2D polyline label.

        Examples:
            >>> labeledpolyline2d = LabeledPolyline2D(
            ...     [(1, 2), (2, 4), (2, 1)],
            ...     category="example",
            ...     attributes={"key": "value"},
            ...     instance="123",
            ...     beizer_point_types="LLL",
            ... )
            >>> labeledpolyline2d.dumps()
            {
                'category': 'example',
                'attributes': {'key': 'value'},
                'instance': '123',
                'polyline2d': [{'x': 1, 'y': 2}, {'x': 2, 'y': 4}, {'x': 2, 'y': 1}],
                'beizerPointTypes': 'LLL',
            }

        """
        return self._dumps()
示例#19
0
class Polyline2DSubcatalog(SubcatalogBase, IsTrackingMixin, CategoriesMixin,
                           AttributesMixin):
    """This class defines the subcatalog for 2D polyline type of labels.

    Arguments:
        is_tracking: A boolean value indicates whether the corresponding
            subcatalog contains tracking information.
        is_beizer_curve: A boolean value indicates whether the corresponding
            subcatalog contains beizer curve information.

    Attributes:
        description: The description of the entire 2D polyline subcatalog.
        categories: All the possible categories in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the category names as keys
            and the :class:`~tensorbay.label.supports.CategoryInfo` as values.
        category_delimiter: The delimiter in category values indicating parent-child relationship.
        attributes: All the possible attributes in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the attribute names as keys
            and the :class:`~tensorbay.label.attribute.AttributeInfo` as values.
        is_tracking: Whether the Subcatalog contains tracking information.
        is_beizer_curve: Whether the Subcatalog contains beizer curve information.

    Examples:
        *Initialization Method 1:* Init from ``Polyline2DSubcatalog.loads()`` method.

        >>> catalog = {
        ...     "POLYLINE2D": {
        ...         "isTracking": True,
        ...         "isBeizerCurve": True,
        ...         "categories": [{"name": "0"}, {"name": "1"}],
        ...         "attributes": [{"name": "gender", "enum": ["male", "female"]}],
        ...     }
        ... }
        >>> Polyline2DSubcatalog.loads(catalog["POLYLINE2D"])
        Polyline2DSubcatalog(
          (is_beizer_curve): True,
          (is_tracking): True,
          (categories): NameList [...],
          (attributes): NameList [...]
        )

        *Initialization Method 2:* Init an empty Polyline2DSubcatalog and then add the attributes.

        >>> from tensorbay.label import CategoryInfo, AttributeInfo
        >>> from tensorbay.utility import NameList
        >>> categories = NameList()
        >>> categories.append(CategoryInfo("a"))
        >>> attributes = NameList()
        >>> attributes.append(AttributeInfo("gender", enum=["female", "male"]))
        >>> polyline2d_subcatalog = Polyline2DSubcatalog()
        >>> polyline2d_subcatalog.is_tracking = True
        >>> polyline2d_subcatalog.is_beizer_curve = True
        >>> polyline2d_subcatalog.categories = categories
        >>> polyline2d_subcatalog.attributes = attributes
        >>> polyline2d_subcatalog
        Polyline2DSubcatalog(
          (is_beizer_curve): True,
          (is_tracking): True,
          (categories): NameList [...],
          (attributes): NameList [...]
        )

    """

    _repr_attrs = ("is_beizer_curve", ) + SubcatalogBase._repr_attrs
    is_beizer_curve: bool = attr(key=camel, default=False)

    def __init__(self,
                 is_tracking: bool = False,
                 is_beizer_curve: bool = False) -> None:
        SubcatalogBase.__init__(self)
        IsTrackingMixin.__init__(self, is_tracking)
        self.is_beizer_curve = is_beizer_curve
示例#20
0
class DataDiff(DiffBase):
    """This class defines the basic structure of a diff statistic.

    Attributes:
        remote_path: The remote path.
        action: The action of data.
        file: The brief diff information of the file.
        label: The brief diff information of the labels.

    """

    _T = TypeVar("_T", bound="DataDiff")

    _repr_attrs = ("action", "file", "label")

    _repr_maxlevel = 2

    remote_path: str = attr(key=camel)
    file: FileDiff = attr()
    label: LabelDiff = attr()

    def _repr_head(self) -> str:
        return f'{self.__class__.__name__}("{self.remote_path}")'

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`DataDiff` instance from the given contents.

        Arguments:
            contents: A dict containing all the brief diff information of data::

                     {
                         "remotePath": <str>,
                         "action": <str>,
                         "file": {
                             "action": <str>
                         },
                         "label": {
                             "action": <str>
                         }
                     }

        Returns:
            A :class:`DataDiff` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the brief diff information of data into a dict.

        Returns:
            A dict containing all the brief diff information of data::

                 {
                     "remotePath": <str>,
                     "action": <str>,
                     "file": {
                         "action": <str>
                     },
                     "label": {
                         "action": <str>
                     }
                 }

        """
        return self._dumps()
示例#21
0
class _NamedCommit(Commit):
    """This class defines the structure of a named commit.

    :class:`_NamedCommit` is the base class of :class:`Tag` and :class:`Branch`.

    Arguments:
        name: The name of the named commit.
        commit_id: The commit id.
        parent_commit_id: The parent commit id.
        title: The commit title.
        description: The commit description.
        committer: The commit user.

    """

    _T = TypeVar("_T", bound="_NamedCommit")

    _repr_attrs = ("commit_id",) + Commit._repr_attrs

    name: str = attr()

    def __init__(  # pylint: disable=too-many-arguments
        self,
        name: str,
        commit_id: str,
        parent_commit_id: Optional[str],
        title: str,
        description: str,
        committer: User,
    ) -> None:
        super().__init__(commit_id, parent_commit_id, title, description, committer)
        self.name = name

    def _repr_head(self) -> str:
        return f'{self.__class__.__name__}("{self.name}")'

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`_NamedCommit` instance for the given contents.

        Arguments:
            contents: A dict containing all the information of the named commit::

                    {
                        "name": <str>
                        "commitId": <str>
                        "parentCommitId": <str> or None
                        "title": <str>
                        "description": <str>
                        "committer": {
                            "name": <str>
                            "date": <int>
                        }
                    }

        Returns:
            A :class:`_NamedCommit` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the named commit information into a dict.

        Returns:
            A dict containing all the information of the named commit::

                {
                    "name": <str>
                    "commitId": <str>
                    "parentCommitId": <str> or None
                    "title": <str>
                    "description": <str>
                    "committer": {
                        "name": <str>
                        "date": <int>
                    }
                }

        """
        return self._dumps()
示例#22
0
class Draft(AttrsMixin, ReprMixin):  # pylint: disable=too-many-instance-attributes
    """This class defines the basic structure of a draft.

    Arguments:
        number: The number of the draft.
        title: The title of the draft.
        branch_name: The branch name.
        status: The status of the draft.
        parent_commit_id: The parent commit id.
        author: The author of the draft.
        updated_at: The time of last update.
        description: The draft description.

    """

    _T = TypeVar("_T", bound="Draft")

    _repr_attrs = ("title", "status", "branch_name")

    number: int = attr()
    title: str = attr()
    branch_name: str = attr(key=camel)
    status: str = attr()
    parent_commit_id: str = attr(key=camel)
    author: User = attr()
    updated_at: int = attr(key=camel)
    description: str = attr(default="")

    def __init__(  # pylint: disable=too-many-arguments
        self,
        number: int,
        title: str,
        branch_name: str,
        status: str,
        parent_commit_id: str,
        author: User,
        updated_at: int,
        description: str = "",
    ) -> None:
        self.number = number
        self.title = title
        self.branch_name = branch_name
        self.status = status
        self.parent_commit_id = parent_commit_id
        self.author = author
        self.updated_at = updated_at
        self.description = description

    def _repr_head(self) -> str:
        return f"{self.__class__.__name__}({self.number})"

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a :class:`Draft` instance from the given contents.

        Arguments:
            contents: A dict containing all the information of the draft::

                    {
                        "number": <int>
                        "title": <str>
                        "branchName": <str>
                        "status": "OPEN", "CLOSED" or "COMMITTED"
                        "parentCommitId": <str>
                        "author": {
                            "name": <str>
                            "date": <int>
                        }
                        "updatedAt": <int>
                        "description": <str>
                    }

        Returns:
            A :class:`Draft` instance containing all the information in the given contents.

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the information of the draft into a dict.

        Returns:
            A dict containing all the information of the draft::

                {
                    "number": <int>
                    "title": <str>
                    "branchName": <str>
                    "status": "OPEN", "CLOSED" or "COMMITTED"
                    "parentCommitId": <str>
                    "author": {
                        "name": <str>
                        "date": <int>
                    }
                    "updatedAt": <int>
                    "description": <str>
                }

        """
        return self._dumps()
示例#23
0
class Job(AttrsMixin, ReprMixin):  # pylint: disable=too-many-instance-attributes
    """This class defines :class:`Job`.

    Arguments:
        client: The :class:`~tensorbay.client.requests.Client`.
        dataset_id: Dataset ID.
        job_updater: The function to update the information of the Job instance.
        title: Title of the Job.
        job_id: ID of the Job.
        arguments: Arguments of the Job.
        created_at: The time when the Job is created.
        started_at: The time when the Job is started.
        finished_at: The time when the Job is finished.
        status: The status of the Job.
        error_message: The error message of the Job.
        result: The result of the Job.
        description: The description of the Job.

    """

    _T = TypeVar("_T", bound="Job")

    _repr_type = ReprType.INSTANCE
    _repr_maxlevel = 2

    _repr_attrs: Tuple[str, ...] = (
        "title",
        "arguments",
        "created_at",
        "started_at",
        "finished_at",
        "status",
        "error_message",
    )

    title: str = attr()
    job_id: str = attr(key=camel)
    arguments: Dict[str, Any] = attr()
    created_at: int = attr(key=camel)
    started_at: Optional[int] = attr(key=camel, default=None)
    finished_at: Optional[int] = attr(key=camel, default=None)
    status: str = attr()
    error_message: str = attr(key=camel, default="")
    _result: Optional[Dict[str, Any]] = attr(key="result", default=None)
    description: Optional[str] = attr(default="")

    def __init__(  # pylint: disable=too-many-arguments
        self,
        client: Client,
        dataset_id: str,
        job_updater: Callable[[str], Dict[str, Any]],
        title: str,
        job_id: str,
        arguments: Dict[str, Any],
        created_at: int,
        started_at: Optional[int],
        finished_at: Optional[int],
        status: str,
        error_message: str,
        result: Optional[Dict[str, Any]],
        description: Optional[str] = "",
    ) -> None:
        self._client = client
        self._dataset_id = dataset_id
        self._job_updater = job_updater
        self.title = title
        self.job_id = job_id
        self.arguments = arguments
        self.created_at = created_at
        self.started_at = started_at
        self.finished_at = finished_at
        self.status = status
        self.error_message = error_message
        self._result = result
        self.description = description

    def _repr_head(self) -> str:
        return f'{self.__class__.__name__}("{self.job_id}")'

    @classmethod
    def from_response_body(
            cls: Type[_T],
            body: Dict[str, Any],
            *,
            client: Client,
            dataset_id: str,
            job_updater: Callable[[str], Dict[str, Any]],  # noqa: DAR101
    ) -> _T:
        """Loads a :class:`Job` object from a response body.

        Arguments:
            body: The response body which contains the information of a job,
                whose format should be like::

                    {
                        "title": <str>
                        "jobId": <str>
                        "arguments": <object>
                        "createdAt": <int>
                        "startedAt": <int>
                        "finishedAt": <int>
                        "status": <str>
                        "errorMessage": <str>
                        "result": <object>
                        "description": <str>
                    }
            client: The :class:`~tensorbay.client.requests.Client`.
            dataset_id: Dataset ID.
            job_updater: The function to update the information of the Job instance.

        Returns:
            The loaded :class:`Job` object.

        """
        job = common_loads(cls, body)
        job._client = client
        job._dataset_id = dataset_id
        job._job_updater = job_updater

        return job

    def update(self, until_complete: bool = False) -> None:
        """Update attrs of the Job instance.

        Arguments:
            until_complete: Whether to update job information until it is complete.

        """
        job_info = self._job_updater(self.job_id)

        if until_complete:
            while job_info["status"] in _JOB_NOT_COMPLETE_STATUS:
                sleep(_JOB_UPDATE_INTERVAL)
                job_info = self._job_updater(self.job_id)

        self.started_at = job_info.get("startedAt")
        self.finished_at = job_info.get("finishedAt")
        self.status = job_info["status"]
        self.error_message = job_info["errorMessage"]
        self._result = job_info.get("result")

    def abort(self) -> None:
        """Abort a :class:`Job`."""
        self._client.open_api_do("POST", f"jobs/{self.job_id}/abort",
                                 self._dataset_id)

    def retry(self) -> None:
        """Retry a :class:`Job`."""
        self._client.open_api_do("POST", f"jobs/{self.job_id}/retry",
                                 self._dataset_id)
class Word(ReprMixin, AttrsMixin):
    """This class defines the concept of word.

    :class:`Word` is a word within a phonetic transcription sentence,
    containing the content of the word, the start and end time in the audio.

    Arguments:
        text: The content of the word.
        begin: The begin time of the word in the audio.
        end: The end time of the word in the audio.

    Attributes:
        text: The content of the word.
        begin: The begin time of the word in the audio.
        end: The end time of the word in the audio.

    Examples:
        >>> Word(text="example", begin=1, end=2)
        Word(
          (text): 'example',
          (begin): 1,
          (end): 2
        )

    """

    _T = TypeVar("_T", bound="Word")

    _repr_attrs = ("text", "begin", "end")

    text: str = attr()
    begin: float = attr(is_dynamic=True)
    end: float = attr(is_dynamic=True)

    def __init__(
        self,
        text: str,
        begin: Optional[float] = None,
        end: Optional[float] = None,
    ):
        self.text = text
        if begin is not None:
            self.begin = begin
        if end is not None:
            self.end = end

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Union[str, float]]) -> _T:
        """Loads a Word from a dict containing the information of the word.

        Arguments:
            contents: A dict containing the information of the word

        Returns:
            The loaded :class:`Word` object.

        Examples:
            >>> contents = {"text": "Hello, World", "begin": 1, "end": 2}
            >>> Word.loads(contents)
            Word(
              (text): 'Hello, World',
              (begin): 1,
              (end): 2
            )

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, Union[str, float]]:
        """Dumps the current word into a dict.

        Returns:
            A dict containing all the information of the word

        Examples:
            >>> word = Word(text="example", begin=1, end=2)
            >>> word.dumps()
            {'text': 'example', 'begin': 1, 'end': 2}

        """
        return self._dumps()
示例#25
0
class KeypointsInfo(ReprMixin, AttrsMixin):
    """This class defines the structure of a set of keypoints.

    Arguments:
        number: The number of the set of keypoints.
        names: All the names of the keypoints.
        skeleton: The skeleton of the keypoints
            indicating which keypoint should connect with another.
        visible: The visible type of the keypoints, can only be 'BINARY' or 'TERNARY'.
            It determines the range of the
            :attr:`Keypoint2D.v<tensorbay.geometry.keypoint.Keypoint2D.v>`.
        parent_categories: The parent categories of the keypoints.
        description: The description of the keypoints.

    Attributes:
        number: The number of the set of keypoints.
        names: All the names of the keypoints.
        skeleton: The skeleton of the keypoints
            indicating which keypoint should connect with another.
        visible: The visible type of the keypoints, can only be 'BINARY' or 'TERNARY'.
            It determines the range of the
            :attr:`Keypoint2D.v<tensorbay.geometry.keypoint.Keypoint2D.v>`.
        parent_categories: The parent categories of the keypoints.
        description: The description of the keypoints.

    Examples:
        >>> KeypointsInfo(
        ...     2,
        ...     names=["L_Shoulder", "R_Shoulder"],
        ...     skeleton=[(0, 1)],
        ...     visible="BINARY",
        ...     parent_categories="people",
        ...     description="example",
        ... )
        KeypointsInfo(
          (number): 2,
          (names): [...],
          (skeleton): [...],
          (visible): 'BINARY',
          (parent_categories): [...]
        )

    """

    _T = TypeVar("_T", bound="KeypointsInfo")

    _repr_type = ReprType.INSTANCE
    _repr_attrs = (
        "number",
        "names",
        "skeleton",
        "visible",
        "parent_categories",
    )
    _number: int = attr(key="number")
    names: List[str] = attr(is_dynamic=True)
    skeleton: List[Tuple[int, int]] = attr(is_dynamic=True)
    visible: str = attr(is_dynamic=True)
    parent_categories: List[str] = attr(is_dynamic=True, key=camel)
    description: str = attr(default="")

    def __init__(
        self,
        number: int,
        *,
        names: Optional[Iterable[str]] = None,
        skeleton: Optional[Iterable[Iterable[int]]] = None,
        visible: Optional[str] = None,
        parent_categories: Union[None, str, Iterable[str]] = None,
        description: str = "",
    ):
        self._number = number
        if names:
            self.names = list(names)
        if skeleton:
            self.skeleton: List[Tuple[int, int]] = [
                tuple(line) for line in skeleton  # type: ignore[misc]
            ]
        if visible:
            try:
                self.visible = _VisibleType[visible.upper()].name
            except KeyError as error:
                raise ValueError(
                    "Visible can only be 'BINARY' or 'TERNARY'") from error

        self.description = description

        if not parent_categories:
            return

        if isinstance(parent_categories, str):
            self.parent_categories = [parent_categories]
        else:
            self.parent_categories = list(parent_categories)

    def _loads(self, contents: Dict[str, Any]) -> None:
        if "visible" in contents:
            _ = _VisibleType[contents["visible"]]
        super()._loads(contents)

    @classmethod
    def loads(cls: Type[_T], contents: Dict[str, Any]) -> _T:
        """Loads a KeypointsInfo from a dict containing the information of the keypoints.

        Arguments:
            contents: A dict containing all the information of the set of keypoints.

        Returns:
            The loaded :class:`KeypointsInfo` object.

        Examples:
            >>> contents = {
            ...     "number": 2,
            ...     "names": ["L", "R"],
            ...     "skeleton": [(0,1)],
            ...     "visible": "TERNARY",
            ...     "parentCategories": ["example"],
            ...     "description": "example",
            ... }
            >>> KeypointsInfo.loads(contents)
            KeypointsInfo(
              (number): 2,
              (names): [...],
              (skeleton): [...],
              (visible): 'TERNARY',
              (parent_categories): [...]
            )

        """
        return common_loads(cls, contents)

    @property
    def number(self) -> int:
        """Return the number of the keypoints.

        Returns:
            The number of the keypoints.

        Examples:
            >>> keypointsinfo = KeypointsInfo(5)
            >>> keypointsinfo.number
            5

        """
        return self._number

    def dumps(self) -> Dict[str, Any]:
        """Dumps all the keypoint information into a dict.

        Returns:
            A dict containing all the information of the keypoint.

        Examples:
            >>> keypointsinfo = KeypointsInfo(
            ...     2,
            ...     names=["L_Shoulder", "R_Shoulder"],
            ...     skeleton=[(0, 1)],
            ...     visible="BINARY",
            ...     parent_categories="people",
            ...     description="example",
            ... )
            >>> keypointsinfo.dumps()
            {
                'number': 2,
                'names': ['L_Shoulder', 'R_Shoulder'],
                'skeleton': [(0, 1)],
                'visible': 'BINARY',
                'parentCategories': ['people'],
                'description': 'example',
            }

        """
        return self._dumps()
class SentenceSubcatalog(SubcatalogBase, AttributesMixin):
    """This class defines the subcatalog for audio transcripted sentence type of labels.

    Arguments:
        is_sample: A boolen value indicates whether time format is sample related.
        sample_rate: The number of samples of audio carried per second.
        lexicon: A list consists all of text and phone.

    Attributes:
        description: The description of the entire sentence subcatalog.
        is_sample: A boolen value indicates whether time format is sample related.
        sample_rate: The number of samples of audio carried per second.
        lexicon: A list consists all of text and phone.
        attributes: All the possible attributes in the corresponding dataset
            stored in a :class:`~tensorbay.utility.name.NameList`
            with the attribute names as keys
            and the :class:`~tensorbay.label.attribute.AttributeInfo` as values.

    Raises:
        TypeError: When sample_rate is None and is_sample is True.

    Examples:
        *Initialization Method 1:* Init from ``SentenceSubcatalog.__init__()``.

        >>> SentenceSubcatalog(True, 16000, [["mean", "m", "iy", "n"]])
        SentenceSubcatalog(
          (is_sample): True,
          (sample_rate): 16000,
          (lexicon): [...]
        )

        *Initialization Method 2:* Init from ``SentenceSubcatalog.loads()`` method.

        >>> contents = {
        ...     "isSample": True,
        ...     "sampleRate": 16000,
        ...     "lexicon": [["mean", "m", "iy", "n"]],
        ...     "attributes": [{"name": "gender", "enum": ["male", "female"]}],
        ... }
        >>> SentenceSubcatalog.loads(contents)
        SentenceSubcatalog(
          (is_sample): True,
          (sample_rate): 16000,
          (attributes): NameList [...],
          (lexicon): [...]
        )

    """

    is_sample: bool = attr(key=camel, default=False)
    sample_rate: int = attr(is_dynamic=True, key=camel)
    lexicon: List[List[str]] = attr(is_dynamic=True)

    def __init__(
        self,
        is_sample: bool = False,
        sample_rate: Optional[int] = None,
        lexicon: Optional[List[List[str]]] = None,
    ) -> None:
        SubcatalogBase.__init__(self)
        if is_sample and not sample_rate:
            raise TypeError(
                f"Require 'sample_rate' to init {self.__class__.__name__} when is_sample is True"
            )

        self.is_sample = is_sample
        if sample_rate:
            self.sample_rate = sample_rate
        if lexicon:
            self.lexicon = lexicon

    def dumps(self) -> Dict[str, Any]:
        """Dumps the information of this SentenceSubcatalog into a dict.

        Returns:
            A dict containing all information of this SentenceSubcatalog.

        Examples:
            >>> sentence_subcatalog = SentenceSubcatalog(True, 16000, [["mean", "m", "iy", "n"]])
            >>> sentence_subcatalog.dumps()
            {'isSample': True, 'sampleRate': 16000, 'lexicon': [['mean', 'm', 'iy', 'n']]}

        """
        return self._dumps()

    def append_lexicon(self, lexemes: List[str]) -> None:
        """Add lexemes to lexicon.

        Arguments:
            lexemes: A list consists of text and phone.

        Examples:
            >>> sentence_subcatalog = SentenceSubcatalog(True, 16000, [["mean", "m", "iy", "n"]])
            >>> sentence_subcatalog.append_lexicon(["example"])
            >>> sentence_subcatalog.lexicon
            [['mean', 'm', 'iy', 'n'], ['example']]

        """
        if hasattr(self, "lexicon"):
            self.lexicon.append(lexemes)
        else:
            self.lexicon = [lexemes]
示例#27
0
class CameraMatrix(ReprMixin, AttrsMixin):
    """CameraMatrix represents camera matrix.

    Camera matrix describes the mapping of a pinhole camera model from 3D points in the world
    to 2D points in an image.

    Arguments:
        fx: The x axis focal length expressed in pixels.
        fy: The y axis focal length expressed in pixels.
        cx: The x coordinate of the so called principal point that should be in the center of
            the image.
        cy: The y coordinate of the so called principal point that should be in the center of
            the image.
        skew: It causes shear distortion in the projected image.
        matrix: A 3x3 Sequence of camera matrix.

    Attributes:
        fx: The x axis focal length expressed in pixels.
        fy: The y axis focal length expressed in pixels.
        cx: The x coordinate of the so called principal point that should be in the center of
            the image.
        cy: The y coordinate of the so called principal point that should be in the center of
            the image.
        skew: It causes shear distortion in the projected image.

    Raises:
        TypeError: When only keyword arguments with incorrect keys are provided,
            or when no arguments are provided.

    Examples:
        >>> matrix = [[1, 3, 3],
        ...           [0, 2, 4],
        ...           [0, 0, 1]]

        *Initialazation Method 1*: Init from 3x3 sequence array.

        >>> camera_matrix = CameraMatrix(matrix=matrix)
        >>> camera_matrix
        CameraMatrix(
            (fx): 1,
            (fy): 2,
            (cx): 3,
            (cy): 4,
            (skew): 3
        )

        *Initialazation Method 2*: Init from camera calibration parameters, skew is optional.

        >>> camera_matrix = CameraMatrix(fx=1, fy=2, cx=3, cy=4, skew=3)
        >>> camera_matrix
        CameraMatrix(
            (fx): 1,
            (fy): 2,
            (cx): 3,
            (cy): 4,
            (skew): 3
        )



    """

    _T = TypeVar("_T", bound="CameraMatrix")

    _repr_type = ReprType.INSTANCE
    _repr_attrs = ("fx", "fy", "cx", "cy", "skew")

    fx: float = attr()
    fy: float = attr()
    cx: float = attr()
    cy: float = attr()
    skew: float = attr(default=0)

    def __init__(  # pylint: disable=too-many-arguments
        self,
        fx: Optional[float] = None,
        fy: Optional[float] = None,
        cx: Optional[float] = None,
        cy: Optional[float] = None,
        skew: float = 0,
        *,
        matrix: Optional[MatrixType] = None,
    ) -> None:
        if matrix is not None:
            # pylint: disable=invalid-name
            self.fx: float = matrix[0][0]
            self.fy: float = matrix[1][1]
            self.cx: float = matrix[0][2]
            self.cy: float = matrix[1][2]
            self.skew: float = matrix[0][1]
            return

        if not (fx is None or fy is None or cx is None or cy is None):
            self.fx = fx
            self.fy = fy
            self.cx = cx
            self.cy = cy
            self.skew = skew
            return

        raise TypeError(
            f"Require 'fx', 'fy', 'cx', 'cy' or 3x3 matrix to initialize {self.__class__.__name__}"
        )

    @classmethod
    def loads(cls: Type[_T], contents: Mapping[str, float]) -> _T:
        """Loads CameraMatrix from a dict containing the information of the camera matrix.

        Arguments:
            contents: A dict containing the information of the camera matrix.

        Returns:
            A :class:`CameraMatrix` instance contains the information from the contents dict.

        Examples:
            >>> contents = {
            ...     "fx": 2,
            ...     "fy": 6,
            ...     "cx": 4,
            ...     "cy": 7,
            ...     "skew": 3
            ... }
            >>> camera_matrix = CameraMatrix.loads(contents)
            >>> camera_matrix
            CameraMatrix(
                (fx): 2,
                (fy): 6,
                (cx): 4,
                (cy): 7,
                (skew): 3
            )

        """
        return common_loads(cls, contents)

    def dumps(self) -> Dict[str, float]:
        """Dumps the camera matrix into a dict.

        Returns:
            A dict containing the information of the camera matrix.

        Examples:
            >>> camera_matrix.dumps()
            {'fx': 1, 'fy': 2, 'cx': 3, 'cy': 4, 'skew': 3}

        """
        return self._dumps()

    def as_matrix(self) -> np.ndarray:
        """Return the camera matrix as a 3x3 numpy array.

        Returns:
            A 3x3 numpy array representing the camera matrix.

        Examples:
            >>> numpy_array = camera_matrix.as_matrix()
            >>> numpy_array
            array([[1., 3., 3.],
                   [0., 4., 4.],
                   [0., 0., 1.]])

        """
        return np.array([
            [self.fx, self.skew, self.cx],
            [0.0, self.cy, self.cy],
            [0.0, 0.0, 1.0],
        ])

    def project(self, point: Sequence[float]) -> Vector2D:
        """Project a point to the pixel coordinates.

        Arguments:
            point: A Sequence containing the coordinates of the point to be projected.

        Returns:
            The pixel coordinates.

        Raises:
            TypeError: When the dimension of the input point is neither two nor three.

        Examples:
            Project a point in 2 dimensions

            >>> camera_matrix.project([1, 2])
            Vector2D(12, 19)

            Project a point in 3 dimensions

            >>> camera_matrix.project([1, 2, 4])
            Vector2D(6.0, 10.0)

        """
        if len(point) == 3:
            x = point[0] / point[2]
            y = point[1] / point[2]
        elif len(point) == 2:
            x = point[0]
            y = point[1]
        else:
            raise TypeError(
                "The point to be projected must have 2 or 3 dimensions")

        x = self.fx * x + self.skew * y + self.cx
        y = self.fy * y + self.cy
        return Vector2D(x, y)