uim.model.inkinput.sensordata API documentation

# Module `uim.model.inkinput.sensordata`

Expand source code

    # -*- coding: utf-8 -*-
    # Copyright © 2021 Wacom Authors. All Rights Reserved.
    #
    #  Licensed under the Apache License, Version 2.0 (the "License");
    #  you may not use this file except in compliance with the License.
    #  You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    #  Unless required by applicable law or agreed to in writing, software
    #  distributed under the License is distributed on an "AS IS" BASIS,
    #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    #  See the License for the specific language governing permissions and
    #  limitations under the License.
    import uuid
    from enum import Enum
    from typing import List

    from uim.model.base import UUIDIdentifier
    from uim.model.inkinput.inputdata import InkSensorType, SensorChannel, Unit, unit2unit

    class InkState(Enum):
        """
             The uim input data state defines the state of the Ink input data.
             WILL 3.0 supports different modes:
              - Writing on a plane,
               - Hovering above a surface,
               - Moving in air (VR/AR/MR) interaction,
               - Only hovering in the air.
        """
        PLANE = 0              # Ink input data is writing on a surface.
        HOVERING = 1           # Hovering over a surface.
        IN_VOLUME = 2          # Using the uim input data in the air, with active inking.
        VOLUME_HOVERING = 3    # Moving the pen in the air with disabled inking.
        START_TRACKING = 4     # For Hovering and VR entering the proximity sensor needs to be flagged, as well ...
        STOP_TRACKING = 5      # As leaving the proximity sensor respectively VR tracking.

    class ChannelData(UUIDIdentifier):
        """
            List of data items.
        """
        def __init__(self, sensor_channel_id: uuid.UUID, values: list = None):
            """
            Constructs channel data object.
            :param sensor_channel_id: Referencing InkSensorChannel via id.
            :param values: Sample values delta encoded with provided precision.
            """
            super().__init__(sensor_channel_id)
            self.__values: list = values or []

        @property
        def values(self) -> list:
            """Sample values delta encoded with provided precision.

            :return: values
            """
            return self.__values

        @values.setter
        def values(self, values: list):
            self.__values = values

        def __repr__(self):
            return '<ChannelData : [id:={}, num channels:={}]>'.format(self.id, len(self.values))

    class SensorData(UUIDIdentifier):
        """
        SensorData
        ----------
        The SensorData Repository is a data repository, which holds a collection of SensorData instances.

        A data-frame structure represents a collection of raw input data sequences, produced by one or more on-board
        device sensors, including data points, re-sampling information, and input sources from fingerprints and metadata.

        Remark:
        --------
        Once a SensorData instance is added to the SensorData repository, it is considered immutable.
        """
        def __init__(self, sid: uuid.UUID = None, input_context_id: uuid.UUID = None, state: InkState = None,
                     timestamp: int = None):
            """
            Constructs a sensor data item.
            :param sid: bytes -
                Sensor data identifier.
            :param input_context_id: bytes -
                Referencing the InputContext via id.
            :param state: InkState -
                The state of the input provider during the capturing of this data frame.
            :param timestamp: int -
                Timestamp for first sample of the stroke, measured in milliseconds.
            """
            super().__init__(sid)
            self.__input_context_id: uuid.UUID = input_context_id
            self.__state: InkState = state
            self.__timestamp: int = timestamp
            self.__map_channels: dict = {}
            self.__map_idx: dict = {}

        @property
        def input_context_id(self) -> uuid.UUID:
            """Id of the input context.

            :return: reference id for the input context
            """
            return self.__input_context_id

        @property
        def state(self) -> InkState:
            """State of the uim sensor sequence.

            :return: InkState enum instance
            """
            return self.__state

        @property
        def timestamp(self) -> int:
            """Timestamp of the first data sample in this sequence.

            :return: long timestamp
            """
            return self.__timestamp

        @property
        def data_channels(self) -> List[ChannelData]:
            """List of the different channels.

            :return: list of DataChannel instances
            """
            return [self.__map_channels[self.__map_idx[idx]] for idx in sorted(self.__map_idx.keys())]

        def get_data_by_id(self, channel_id: uuid.UUID) -> ChannelData:
            """Returns data channel.
            :param channel_id: bytes -
                id of the DataChannel
            :return : data channel
            """
            if channel_id in self.__map_channels:
                return self.__map_channels[channel_id]
            # Create channel data if not existing
            channel: ChannelData = ChannelData(channel_id)
            self.__map_channels[channel_id] = channel
            self.__map_idx[len(self.__map_channels) - 1] = channel_id
            return channel

        def add_timestamp_data(self, sensor_channel: SensorChannel, values: List[float]):
            """
            Adding timestamp data.
            :param sensor_channel: SensorChannel -
                The sensor channel which sourced the data.
            :param values:
                A list of timestamp values with the configured unit type.
            :raises:
                ValueError: Issue with the parameter
            """
            if sensor_channel is None:
                raise ValueError("Sensor channel is null")

            if sensor_channel.type != InkSensorType.TIMESTAMP:
                raise ValueError(f"The specified sensor channel must be of the {InkSensorType.Timestamp} type")

            if values is None:
                raise ValueError()

            if len(values) == 0:
                return
            channel_data: ChannelData = self.get_data_by_id(sensor_channel.id)
            channel_data.values = values
            self.__timestamp = round(unit2unit(Unit.S, Unit.MS, values[0]))

        def add_data(self, sensor_channel: SensorChannel, values: List[float]):
            """
           Adding data.
           :param sensor_channel: SensorChannel -
               The sensor channel which sourced the data.
           :param values:
               A list of values.
           :raises:
               ValueError: Issue with the parameter
           """
            if sensor_channel is None:
                raise ValueError("Sensor channel is null")

            if values is None:
                raise ValueError()

            if len(values) == 0:
                return
            channel_data: ChannelData = self.get_data_by_id(sensor_channel.id)
            channel_data.values = values

        def __eq__(self, other):
            if not isinstance(other, SensorData):
                return False
            if len(self.data_channels) != len(other.data_channels):
                return False
            if self.input_context_id != other.input_context_id:
                return False
            if self.id != other.id:
                return False
            return True

        def __repr__(self):
            return '<SensorData : [id:={}, num channels:={}]>'.format(self.id_h_form, len(self.data_channels))

## Classes

`class ChannelData (sensor_channel_id: uuid.UUID, values: list = None)`

  List of data items.

  Constructs channel data object. :param sensor_channel_id: Referencing InkSensorChannel via id. :param values: Sample values delta encoded with provided precision.

  Expand source code

      class ChannelData(UUIDIdentifier):
          """
              List of data items.
          """
          def __init__(self, sensor_channel_id: uuid.UUID, values: list = None):
              """
              Constructs channel data object.
              :param sensor_channel_id: Referencing InkSensorChannel via id.
              :param values: Sample values delta encoded with provided precision.
              """
              super().__init__(sensor_channel_id)
              self.__values: list = values or []

          @property
          def values(self) -> list:
              """Sample values delta encoded with provided precision.

              :return: values
              """
              return self.__values

          @values.setter
          def values(self, values: list):
              self.__values = values

          def __repr__(self):
              return '<ChannelData : [id:={}, num channels:={}]>'.format(self.id, len(self.values))

  ### Ancestors

  - UUIDIdentifier
  - Identifier
  - abc.ABC

  ### Class variables

  `var SEPARATOR : str`

  ### Instance variables

  `var values : list`

    Sample values delta encoded with provided precision.

    :return: values

    Expand source code

        @property
        def values(self) -> list:
            """Sample values delta encoded with provided precision.

            :return: values
            """
            return self.__values

  ### Inherited members

  - `UUIDIdentifier`:
    - `from_bytes`
    - `id`
    - `id_generator`
    - `id_h_form`
    - `id_s_form`
    - `str_to_uimid`
    - `uimid_to_h_form`
    - `uimid_to_s_form`
`class InkState (value, names=None, *, module=None, qualname=None, type=None, start=1)`

  The uim input data state defines the state of the Ink input data. WILL 3.0 supports different modes: - Writing on a plane, - Hovering above a surface, - Moving in air (VR/AR/MR) interaction, - Only hovering in the air.

  Expand source code

      class InkState(Enum):
          """
               The uim input data state defines the state of the Ink input data.
               WILL 3.0 supports different modes:
                - Writing on a plane,
                 - Hovering above a surface,
                 - Moving in air (VR/AR/MR) interaction,
                 - Only hovering in the air.
          """
          PLANE = 0              # Ink input data is writing on a surface.
          HOVERING = 1           # Hovering over a surface.
          IN_VOLUME = 2          # Using the uim input data in the air, with active inking.
          VOLUME_HOVERING = 3    # Moving the pen in the air with disabled inking.
          START_TRACKING = 4     # For Hovering and VR entering the proximity sensor needs to be flagged, as well ...
          STOP_TRACKING = 5      # As leaving the proximity sensor respectively VR tracking.

  ### Ancestors

  - enum.Enum

  ### Class variables

  `var HOVERING`
  `var IN_VOLUME`
  `var PLANE`
  `var START_TRACKING`
  `var STOP_TRACKING`
  `var VOLUME_HOVERING`
`class SensorData (sid: uuid.UUID = None, input_context_id: uuid.UUID = None, state: InkState = None, timestamp: int = None)`

  ## Sensordata

  The SensorData Repository is a data repository, which holds a collection of SensorData instances.

  A data-frame structure represents a collection of raw input data sequences, produced by one or more on-board device sensors, including data points, re-sampling information, and input sources from fingerprints and metadata.

  ## Remark:

  Once a SensorData instance is added to the SensorData repository, it is considered immutable.

  Constructs a sensor data item. :param sid: bytes - Sensor data identifier. :param input_context_id: bytes - Referencing the InputContext via id. :param state: InkState - The state of the input provider during the capturing of this data frame. :param timestamp: int - Timestamp for first sample of the stroke, measured in milliseconds.

  Expand source code

      class SensorData(UUIDIdentifier):
          """
          SensorData
          ----------
          The SensorData Repository is a data repository, which holds a collection of SensorData instances.

          A data-frame structure represents a collection of raw input data sequences, produced by one or more on-board
          device sensors, including data points, re-sampling information, and input sources from fingerprints and metadata.

          Remark:
          --------
          Once a SensorData instance is added to the SensorData repository, it is considered immutable.
          """
          def __init__(self, sid: uuid.UUID = None, input_context_id: uuid.UUID = None, state: InkState = None,
                       timestamp: int = None):
              """
              Constructs a sensor data item.
              :param sid: bytes -
                  Sensor data identifier.
              :param input_context_id: bytes -
                  Referencing the InputContext via id.
              :param state: InkState -
                  The state of the input provider during the capturing of this data frame.
              :param timestamp: int -
                  Timestamp for first sample of the stroke, measured in milliseconds.
              """
              super().__init__(sid)
              self.__input_context_id: uuid.UUID = input_context_id
              self.__state: InkState = state
              self.__timestamp: int = timestamp
              self.__map_channels: dict = {}
              self.__map_idx: dict = {}

          @property
          def input_context_id(self) -> uuid.UUID:
              """Id of the input context.

              :return: reference id for the input context
              """
              return self.__input_context_id

          @property
          def state(self) -> InkState:
              """State of the uim sensor sequence.

              :return: InkState enum instance
              """
              return self.__state

          @property
          def timestamp(self) -> int:
              """Timestamp of the first data sample in this sequence.

              :return: long timestamp
              """
              return self.__timestamp

          @property
          def data_channels(self) -> List[ChannelData]:
              """List of the different channels.

              :return: list of DataChannel instances
              """
              return [self.__map_channels[self.__map_idx[idx]] for idx in sorted(self.__map_idx.keys())]

          def get_data_by_id(self, channel_id: uuid.UUID) -> ChannelData:
              """Returns data channel.
              :param channel_id: bytes -
                  id of the DataChannel
              :return : data channel
              """
              if channel_id in self.__map_channels:
                  return self.__map_channels[channel_id]
              # Create channel data if not existing
              channel: ChannelData = ChannelData(channel_id)
              self.__map_channels[channel_id] = channel
              self.__map_idx[len(self.__map_channels) - 1] = channel_id
              return channel

          def add_timestamp_data(self, sensor_channel: SensorChannel, values: List[float]):
              """
              Adding timestamp data.
              :param sensor_channel: SensorChannel -
                  The sensor channel which sourced the data.
              :param values:
                  A list of timestamp values with the configured unit type.
              :raises:
                  ValueError: Issue with the parameter
              """
              if sensor_channel is None:
                  raise ValueError("Sensor channel is null")

              if sensor_channel.type != InkSensorType.TIMESTAMP:
                  raise ValueError(f"The specified sensor channel must be of the {InkSensorType.Timestamp} type")

              if values is None:
                  raise ValueError()

              if len(values) == 0:
                  return
              channel_data: ChannelData = self.get_data_by_id(sensor_channel.id)
              channel_data.values = values
              self.__timestamp = round(unit2unit(Unit.S, Unit.MS, values[0]))

          def add_data(self, sensor_channel: SensorChannel, values: List[float]):
              """
             Adding data.
             :param sensor_channel: SensorChannel -
                 The sensor channel which sourced the data.
             :param values:
                 A list of values.
             :raises:
                 ValueError: Issue with the parameter
             """
              if sensor_channel is None:
                  raise ValueError("Sensor channel is null")

              if values is None:
                  raise ValueError()

              if len(values) == 0:
                  return
              channel_data: ChannelData = self.get_data_by_id(sensor_channel.id)
              channel_data.values = values

          def __eq__(self, other):
              if not isinstance(other, SensorData):
                  return False
              if len(self.data_channels) != len(other.data_channels):
                  return False
              if self.input_context_id != other.input_context_id:
                  return False
              if self.id != other.id:
                  return False
              return True

          def __repr__(self):
              return '<SensorData : [id:={}, num channels:={}]>'.format(self.id_h_form, len(self.data_channels))

  ### Ancestors

  - UUIDIdentifier
  - Identifier
  - abc.ABC

  ### Class variables

  `var SEPARATOR : str`

  ### Instance variables

  `var data_channels : List[ChannelData]`

    List of the different channels.

    :return: list of DataChannel instances

    Expand source code

        @property
        def data_channels(self) -> List[ChannelData]:
            """List of the different channels.

            :return: list of DataChannel instances
            """
            return [self.__map_channels[self.__map_idx[idx]] for idx in sorted(self.__map_idx.keys())]

  `var input_context_id : uuid.UUID`

    Id of the input context.

    :return: reference id for the input context

    Expand source code

        @property
        def input_context_id(self) -> uuid.UUID:
            """Id of the input context.

            :return: reference id for the input context
            """
            return self.__input_context_id

  `var state : InkState`

    State of the uim sensor sequence.

    :return: InkState enum instance

    Expand source code

        @property
        def state(self) -> InkState:
            """State of the uim sensor sequence.

            :return: InkState enum instance
            """
            return self.__state

  `var timestamp : int`

    Timestamp of the first data sample in this sequence.

    :return: long timestamp

    Expand source code

        @property
        def timestamp(self) -> int:
            """Timestamp of the first data sample in this sequence.

            :return: long timestamp
            """
            return self.__timestamp

  ### Methods

  `def add_data(self, sensor_channel: SensorChannel, values: List[float])`

    Adding data. :param sensor_channel: SensorChannel - The sensor channel which sourced the data. :param values: A list of values. :raises: ValueError: Issue with the parameter

    Expand source code

        def add_data(self, sensor_channel: SensorChannel, values: List[float]):
            """
           Adding data.
           :param sensor_channel: SensorChannel -
               The sensor channel which sourced the data.
           :param values:
               A list of values.
           :raises:
               ValueError: Issue with the parameter
           """
            if sensor_channel is None:
                raise ValueError("Sensor channel is null")

            if values is None:
                raise ValueError()

            if len(values) == 0:
                return
            channel_data: ChannelData = self.get_data_by_id(sensor_channel.id)
            channel_data.values = values

  `def add_timestamp_data(self, sensor_channel: SensorChannel, values: List[float])`

    Adding timestamp data. :param sensor_channel: SensorChannel - The sensor channel which sourced the data. :param values: A list of timestamp values with the configured unit type. :raises: ValueError: Issue with the parameter

    Expand source code

        def add_timestamp_data(self, sensor_channel: SensorChannel, values: List[float]):
            """
            Adding timestamp data.
            :param sensor_channel: SensorChannel -
                The sensor channel which sourced the data.
            :param values:
                A list of timestamp values with the configured unit type.
            :raises:
                ValueError: Issue with the parameter
            """
            if sensor_channel is None:
                raise ValueError("Sensor channel is null")

            if sensor_channel.type != InkSensorType.TIMESTAMP:
                raise ValueError(f"The specified sensor channel must be of the {InkSensorType.Timestamp} type")

            if values is None:
                raise ValueError()

            if len(values) == 0:
                return
            channel_data: ChannelData = self.get_data_by_id(sensor_channel.id)
            channel_data.values = values
            self.__timestamp = round(unit2unit(Unit.S, Unit.MS, values[0]))

  `def get_data_by_id(self, channel_id: uuid.UUID) ‑> ChannelData`

    Returns data channel. :param channel_id: bytes - id of the DataChannel :return : data channel

    Expand source code

        def get_data_by_id(self, channel_id: uuid.UUID) -> ChannelData:
            """Returns data channel.
            :param channel_id: bytes -
                id of the DataChannel
            :return : data channel
            """
            if channel_id in self.__map_channels:
                return self.__map_channels[channel_id]
            # Create channel data if not existing
            channel: ChannelData = ChannelData(channel_id)
            self.__map_channels[channel_id] = channel
            self.__map_idx[len(self.__map_channels) - 1] = channel_id
            return channel

  ### Inherited members

  - `UUIDIdentifier`:
    - `from_bytes`
    - `id`
    - `id_generator`
    - `id_h_form`
    - `id_s_form`
    - `str_to_uimid`
    - `uimid_to_h_form`
    - `uimid_to_s_form`