Module uim.model.inkinput.inputdata

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 abc import ABC
from enum import Enum
from typing import List, Tuple, Any

import numpy as np

import uim.codec.format.UIM_3_0_0_pb2 as uim
from uim.model.base import HashIdentifier, Identifier, UUIDIdentifier, InkModelException


class DataType(Enum):
    """Data types for channels."""
    BOOLEAN = 0
    FLOAT32 = 1
    FLOAT64 = 2
    INT32 = 3
    INT64 = 4
    UINT32 = 5
    UINT64 = 6


class InkInputType(Enum):
    """
    Defining the different types of input data.
    """
    PEN = uim.PEN
    """Stylus, smart pens, pen displays, signature capturing input data, ..."""
    TOUCH = uim.TOUCH
    """Touch controller input data: Finger or passive stylus."""
    MOUSE = uim.MOUSE
    """Mouse input data."""
    CONTROLLER = uim.CONTROLLER
    """3-DOF or 6-DOF input data devices."""


class InkSensorMetricType(Enum):
    """Metric for the channel."""
    LENGTH = uim.LENGTH
    """Length; underling si unit is meter"""
    TIME = uim.TIME
    """Time; underling  si unit is second"""
    FORCE = uim.FORCE
    """Force; underling si unit is newton"""
    ANGLE = uim.ANGLE
    """Angle; underling si unit is radian"""
    NORMALIZED = uim.NORMALIZED
    """Normalized; percentage, expressed as a fraction(1.0 = 100 %) relative to max - min"""


class Unit(Enum):
    # Lengths units
    UNDEFINED = 0
    """Undefined unit"""
    M = 10
    """meters"""
    CM = 11
    """centimeters"""
    MM = 12
    """millimeters"""
    IN = 13
    """inches"""
    PT = 14
    """points (1pt = 1/72 in)"""
    PC = 15
    """picas (1pc = 1/22 pt)"""
    DIP = 16
    """device independent pixel (1DIP = 1/96 in)"""
    # Time units
    S = 20
    """seconds"""
    MS = 21
    """milliseconds"""
    NS = 22
    """nanoseconds"""
    # Force units
    N = 30
    """Newtons"""
    # Angle
    RAD = 42
    """radians"""
    DEG = 41
    """degrees"""
    # General
    PERCENTAGE = 50
    """percentage, expressed as a fraction (1.0 = 100%) relative to max-min"""
    LOGICAL_VALUE = 60
    """logical value"""


# --------------------------------- Conversion values ------------------------------------------------------------------

CONVERSION_SCALAR = {
    # Length units
    Unit.M: {
        Unit.M: 1.,
        Unit.CM: 100,
        Unit.MM: 1000,
        Unit.IN: 39.3701,
        Unit.PT: 2834.65,
        Unit.PC: 236.222,
        Unit.DIP: (39.3701 * 96.)
    },
    Unit.CM: {
        Unit.M: 0.01,
        Unit.CM: 1.,
        Unit.MM: 10.,
        Unit.IN: 0.393701,
        Unit.PT: 28.3465,
        Unit.PC: 2.36222,
        Unit.DIP: (0.393701 * 96.)
    },
    Unit.MM: {
        Unit.M: 0.001,
        Unit.CM: 0.1,
        Unit.MM: 1.,
        Unit.IN: 0.0393701,
        Unit.PT: 2.83465,
        Unit.PC: 0.236222,
        Unit.DIP: (0.0393701 * 96.)
    },
    Unit.IN: {
        Unit.M: 0.0254,
        Unit.CM: 2.54,
        Unit.MM: 25.4,
        Unit.IN: 1.,
        Unit.PT: 72,
        Unit.PC: 6.,
        Unit.DIP: (1. * 96.)
    },
    Unit.PT: {
        Unit.M: 0.000352778,
        Unit.CM: 0.0352778,
        Unit.MM: 0.352778,
        Unit.IN: 0.0138888889,
        Unit.PT: 1.,
        Unit.PC: 0.08333333,
        Unit.DIP: (0.0138888889 * 96.)
    },
    Unit.PC: {
        Unit.M: 0.0042333333,
        Unit.CM: 0.4233333333,
        Unit.MM: 4.2333333333,
        Unit.IN: 0.166665,
        Unit.PT: 12.,
        Unit.PC: 1.,
        Unit.DIP: (0.166665 * 96.)
    },
    Unit.DIP: {
        Unit.M: (0.0254 / 96.),
        Unit.CM: (2.54 / 96.),
        Unit.MM: (25.4 / 96.),
        Unit.IN: (1. / 96.),
        Unit.PT: (72 / 96.),
        Unit.PC: (6. / 96.),
        Unit.DIP: 1.
    },
    # Time unit
    Unit.S: {
        Unit.S: 1.,
        Unit.MS: 1000.,
        Unit.NS: 1000000000.
    },
    Unit.MS: {
        Unit.S: 0.001,
        Unit.MS: 1.,
        Unit.NS: 1000000.
    },
    Unit.NS: {
        Unit.S: 0.000000001,
        Unit.MS: 0.000001,
        Unit.NS: 1.
    }
}
"""Mapping containing the factors to convert from one unit: <source-unit> into the other: <target-unit>."""


class InkSensorType(Enum):
    """
        Pre-defined SensorData types.
    """

    X = 'will://input/3.0/channel/X'
    """X coordinate. This is the horizontal pen position on the writing surface."""
    Y = 'will://input/3.0/channel/Y'
    """Y coordinate. This is the vertical position on the writing surface. """
    Z = 'will://input/3.0/channel/Z'
    """Z coordinate. This is the height of pen above the writing surface."""
    TIMESTAMP = 'will://input/3.0/channel/Timestamp'
    """Time (of the sample point)"""
    PRESSURE = 'will://input/3.0/channel/Pressure'
    """Input pressure."""
    RADIUS_X = 'will://input/3.0/channel/RadiusX'
    """Touch radius by X"""
    RADIUS_Y = 'will://input/3.0/channel/RadiusY'
    """Touch radius by Y"""
    AZIMUTH = 'will://input/3.0/channel/Azimuth'
    """Azimuth angle of the pen (yaw)"""
    ALTITUDE = 'will://input/3.0/channel/Altitude'
    """Elevation angle of the pen (pitch)"""
    ROTATION = 'will://input/3.0/channel/Rotation'
    """Rotation (counter-clockwise rotation about pen axis)"""


# --------------------------------- Token mapping ----------------------------------------------------------------------


TOKEN_MAP: dict = {
    InkInputType.PEN: InkInputType.PEN.name,
    InkInputType.MOUSE: InkInputType.MOUSE.name,
    InkInputType.TOUCH: InkInputType.TOUCH.name,
    InkInputType.CONTROLLER: InkInputType.CONTROLLER.name,
    InkSensorMetricType.TIME: InkSensorMetricType.TIME.name,
    InkSensorMetricType.LENGTH: InkSensorMetricType.LENGTH.name,
    InkSensorMetricType.FORCE: InkSensorMetricType.FORCE.name,
    InkSensorMetricType.ANGLE: InkSensorMetricType.ANGLE.name,
    InkSensorMetricType.NORMALIZED: InkSensorMetricType.NORMALIZED.name,
    InkSensorType.X: InkSensorType.X.value,
    InkSensorType.Y: InkSensorType.Y.value,
    InkSensorType.Z: InkSensorType.Z.value,
    InkSensorType.TIMESTAMP: InkSensorType.TIMESTAMP.value,
    InkSensorType.PRESSURE: InkSensorType.PRESSURE.value,
    InkSensorType.RADIUS_X: InkSensorType.RADIUS_X.value,
    InkSensorType.RADIUS_Y: InkSensorType.RADIUS_Y.value,
    InkSensorType.AZIMUTH: InkSensorType.AZIMUTH.value,
    InkSensorType.ALTITUDE: InkSensorType.ALTITUDE.value,
    InkSensorType.ROTATION: InkSensorType.ROTATION.value
}

# --------------------------------- Conversion functions ---------------------------------------------------------------


def virtual_resolution_for_si_unit(source_unit: Unit) -> float:
    """
    Calculate a virtual resolution for source unit.

    Parameters
    ----------
    source_unit: unit
        Source unit
    Returns
    -------
    resolution: `float`
        Virtual resolution
    """
    si: Unit = si_unit(source_unit)
    if si == Unit.UNDEFINED:
        return 1.
    return 1. / CONVERSION_SCALAR[source_unit][si]


def si_unit(unit_type: Unit) -> Unit:
    """
    Return the SI unit for a specific unit type.

    Parameters
    ----------
    unit_type: `Unit`
        Unit

    Returns
    -------
    si_unit: Unit
        SI unit for a unit, e.g., for a lengths unit cm the SI unit is m.
    """
    # SI unit for length is m
    if unit_type in [Unit.M, Unit.CM, Unit.MM, Unit.IN, Unit.PT, Unit.PC, Unit.DIP]:
        return Unit.M
    # SI unit for time is s
    if unit_type in [Unit.S, Unit.MS, Unit.NS]:
        return Unit.S
    return Unit.UNDEFINED


def unit2unit(source_unit: Unit, target_unit: Unit, value: float) -> float:
    """
    Convert value with a source unit to the target unit.

    Parameters
    ----------
    source_unit: Unit
        Source unit
    target_unit: Unit
        Target unit
    value: float
        Value in source unit

    Returns
    -------
    value: `float`
        value converted to target unit

    Raises
    ------
    ValueError:
        Unit is not supported
    """
    if source_unit == Unit.UNDEFINED or target_unit == Unit.UNDEFINED:
        return value
    if source_unit not in CONVERSION_SCALAR:
        raise ValueError('Source unit not supported. Unit:={}'.format(source_unit))
    if target_unit not in CONVERSION_SCALAR[source_unit]:
        raise ValueError('Target unit not supported. Unit:={}'.format(target_unit))
    return CONVERSION_SCALAR[source_unit][target_unit] * value


def unit2unit_matrix(source_unit: Unit, target_unit: Unit) -> np.array:
    """
    Matrix for unit 2 unit conversion.

    Parameters
    ----------
    source_unit: Unit
        Source unit
    target_unit: Unit
        Target unit

    Returns
    -------
        matrix: `np.array`
            matrix for conversion
    """
    matrix: np.array = np.identity(3)
    if source_unit == Unit.UNDEFINED or target_unit == Unit.UNDEFINED:
        return matrix
    if source_unit not in CONVERSION_SCALAR:
        raise ValueError('Source unit not supported.')
    if target_unit not in CONVERSION_SCALAR[source_unit]:
        raise ValueError('Target unit not supported.')
    matrix[0, 0] = CONVERSION_SCALAR[source_unit][target_unit]
    matrix[1, 1] = CONVERSION_SCALAR[source_unit][target_unit]
    return matrix


# --------------------------------- Data context --------------------------------------------------------------------


class InputDevice(HashIdentifier):
    """
    InputDevice
    ===========
    The class `InputDevice` represents the hardware device, on which the sensor data has been produced
    (touch enabled mobile device, touch capable monitor, digitizer, etc).
    InputDevice with properties.

    The properties can contain:

      - Communication Protocol: USB, BTC, BLE, SPP, WIFI,
      - Communication ID: VID, PID; MAC; UID; COM_PORT,
      - Device Name: Wacom Intuos Pro M, Apple iPad 8, Samsung GalaxyTab 10,
      - PenID,
      - Serial number,
      - Firmware Version (MCU),
      - Secondary Firmware Version (BT, WIFI) - different modules provides version for itself,
      - Orientation: PORTRAIT, LANDSCAPE, PORTRAIT_REVERSE, LANDSCAPE_REVERSE or 0, 90, 180, 270,
      - Sensor size.

    Parameters
    ----------
    device_id: `UUID`
        Internal input device id
    properties: List[Tuple[str, str]]
        Properties of the input device

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import InputDevice
    >>> # Input device is the sensor (pen tablet, screen, etc.)
    >>> input_device: InputDevice = InputDevice()
    >>> input_device.properties.append(("dev.id", "123454321"))
    >>> input_device.properties.append(("dev.manufacturer", "Wacom"))
    >>> input_device.properties.append(("dev.model", "Mobile Studio Pro"))
    >>> input_device.properties.append(("dev.cpu", "Intel"))
    >>> input_device.properties.append(("dev.graphics.display", "Dell 1920x1080 32bit"))
    >>> input_device.properties.append(("dev.graphics.adapter", "NVidia"))
    """

    def __init__(self, device_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None):
        super().__init__(device_id)
        self.__properties: List[Tuple[str, str]] = properties or []

    @property
    def properties(self) -> List[Tuple[str, str]]:
        """Properties of the InputDevice. (` List[Tuple[str, str]]`, read-only)"""
        return self.__properties

    def add_property(self, key: str, value):
        """Adding property.

        Parameters
        ----------
        key: str
            Name of the property
        value: str
            Value of the property
        """
        self.__properties.append((key, value))

    def __tokenize__(self):
        return ['InputDevice', self.properties]

    def __repr__(self):
        return '<InputDevice : [id:={}, num properties:={}>'.format(self.id, self.properties)


class InputContext(HashIdentifier):
    """
    InputContext
    ============
    Capturing context of the uim input data with reference to the Environment and the SensorContext.

    Parameters
    ----------
    ctx_id: `UUID`
        Internal id
    environment_id: `UUID`
        Reference to environment
    sensor_context_id: `UUID`
        Rendering to sensor context
    """

    def __init__(self, ctx_id: uuid.UUID = None, environment_id: uuid.UUID = None, sensor_context_id: uuid.UUID = None):
        super().__init__(ctx_id)
        self.__environment_id = environment_id
        self.__sensor_context_id = sensor_context_id

    def __tokenize__(self) -> list:
        return ["InputContext", self.environment_id, self.sensor_context_id]

    @property
    def environment_id(self) -> uuid.UUID:
        """Reference to environment. (`UUID`, read-only)"""
        return self.__environment_id

    @property
    def sensor_context_id(self) -> uuid.UUID:
        """Reference for sensor context. (`UUID`, read-only)"""
        return self.__sensor_context_id

    def __repr__(self):
        env_id: str = Identifier.uimid_to_s_form(self.environment_id)
        sc_id: str = Identifier.uimid_to_s_form(self.sensor_context_id)
        return '<InputContext : [id:={}, environment id:={}, sensor context id:={}>'.format(self.id_h_form,
                                                                                            env_id, sc_id)


class Environment(HashIdentifier):
    """
    Environment
    ===========
    The class `Environment` represents for the virtual environment in which the sensor data has been produced, e.g,:

        - os.name - Name of the operating system
        - os.version.name - Name of the version
        - os.version.release - Release build number
        - wacom.ink.sdk.name - Name of the Wacom Ink technology
        - wacom.ink.sdk.version - Version number of the SDK

    Parameters
    ----------
    env_id: `UUID`
        Internal environment UUID
    properties: List[Tuple[str, str]]
        Properties of the environment

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import Environment
    >>> # Create an environment
    >>> env: Environment = Environment()
    >>> env.properties.append(("env.name", "My Environment"))
    >>> env.properties.append(("os.id", "98765"))
    >>> env.properties.append(("os.name", "Windows"))
    >>> env.properties.append(("os.version", "10.0.18362.239"))
    >>> env.properties.append(("os.build", "239"))
    >>> env.properties.append(("os.platform", "whatever"))
    """

    def __init__(self, env_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None):
        super().__init__(env_id)
        self.__properties = properties or []

    def __tokenize__(self) -> List[Any]:
        token: List[Any] = ['Environment', self.properties]
        return token

    @property
    def properties(self) -> List[Tuple[str, str]]:
        """Environment properties. (`List[Tuple[str, str]]`, read-only) """
        return self.__properties

    def add_environment_property(self, key: str, value: str):
        """
        Adding a property for environment.

        Parameters
        ----------
        key: str
            Name of the property
        value: str
            Value of the property
        """
        self.properties.append((key, value))

    def __repr__(self):
        return '<Environment: [id:={}, #properties:={}>'.format(self.id.hex, self.properties)


class InkInputProvider(HashIdentifier):
    """
    InkInputProvider
    ================
    The class InkInputProvider stands for the generic input data source - it identifies how the data has been generated
    (using touch input, mouse, stylus, hardware controller, etc).

    The properties which can be used to describe the InkInputProvider:

        - pen.type - Type of the pen device

    Parameters
    ----------
    provider_id: UUID
        internal id or input data name.
    input_type: InkInputType -
        type of used hardware - PEN, TOUCH, MOUSE, or CONTROLLER.
    properties: List[Tuple[str, str]] -
        Properties assigned to ink input provider

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import InkInputProvider
    >>> # Ink input provider can be pen, mouse or touch.
    >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE)
    >>> provider.properties.append(("pen.id", "1234567"))
    """

    def __init__(self, provider_id: uuid.UUID = None, input_type: InkInputType = None,
                 properties: List[Tuple[str, str]] = None):
        super().__init__(provider_id)
        self.__type: InkInputType = input_type
        self.__properties: List[Tuple[str, str]] = properties or []

    def __tokenize__(self):
        return ['InkInputProvider', TOKEN_MAP[self.type], self.properties]

    @property
    def type(self) -> InkInputType:
        """Input provider type. (`InkInputType`,  read-only)"""
        return self.__type

    @property
    def properties(self) -> List[Tuple[str, str]]:
        """Properties of input data provider. (`List[Tuple[str, str]]`, read-only)"""
        return self.__properties

    def __repr__(self):
        return '<InkInputProvider: [id:={}, type:={}, properties:={}]>'.format(self.id, self.type, self.properties)


class SensorChannel(HashIdentifier):
    """
    SensorChannel
    =============
    The `SensorChannel` represents a generic sensor channel definition, which has the following properties:

    - **type** - URI uniquely identifying the type of the sensor channel
    - **metric** - The type of the data to the SI metric system
    - **resolution** - A factor multiplication value (power of 10) used to convert the stored data values to the
                      specified SI metric
    - **min, max** - Lower and upper bounds of the reported values range
    - **precision** - The precision of the sensor when reporting floating-point values (defined as an int value,
                      used as a power of 10 during the serialization/deserialization phase)
    
    Parameters
    ----------
    channel_id: `UUID`
        Sensor channel descriptor. If no channel_id is set the MD5 hashing is generating the id
    channel_type:`InkSensorType`
        Indicates metric used in calculating the resolution for the data item.
    metric: `InkSensorMetricType`
        Indicates metric used in calculating the resolution for the data item.
    resolution: `float`
        Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the
        physical unit is in m and input data units. Resolution is 100000, then the value 150 would be
        0.0015 m.
    channel_min: `float`
        Minimal value of the channel
    channel_max: `float`
        Maximal value of the channel
    precision: `int`
        Precision of integer encoding, needed for encoded float values
    index: `int`
        Index of the channel
    name: `str`
        Name of the channel
    data_type: `DataType`
        Type of data within the channel
    ink_input_provider_id: `UUID`
        Reference to the ink input provider
    input_device_id: `UUID`
        Reference to the ink input device

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import SensorChannel, InkSensorType
    >>> # Create a group of sensor channels
    >>> sensor_channels_tablet: list = [
    >>>     SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0)
    >>> ]
    """

    def __init__(self, channel_id: uuid.UUID = None,
                 channel_type: InkSensorType = None, metric: InkSensorMetricType = None,
                 resolution: float = 1., channel_min: float = 0., channel_max: float = 0.,
                 precision: int = 2, index: int = 0, name: str = None, data_type: DataType = DataType.FLOAT32,
                 ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None):
        super().__init__(channel_id)
        self.__type: InkSensorType = channel_type
        self.__metric: InkSensorMetricType = metric
        self.__resolution: float = float(resolution)
        self.__min: float = float(channel_min)
        self.__max: float = float(channel_max)
        self.__precision: int = precision
        self.__index: int = index
        self.__name: str = name
        self.__data_type: DataType = data_type
        self.__ink_input_provider: uuid.UUID = ink_input_provider_id
        self.__input_device_id: uuid.UUID = input_device_id

    def __tokenize__(self) -> list:
        return ["SensorChannel", self.__ink_input_provider, self.__input_device_id, TOKEN_MAP[self.type],
                TOKEN_MAP[self.metric], self.resolution, self.min, self.max, self.precision]

    @property
    def ink_input_provider(self) -> uuid.UUID:
        """Reference to the `InkInputProvider` of the channel. (`UUID`)"""
        return self.__ink_input_provider

    @ink_input_provider.setter
    def ink_input_provider(self, value: uuid.UUID):
        self.__ink_input_provider = value

    @property
    def input_device_id(self) -> uuid.UUID:
        """Reference to the `InputDevice` of the channel. (`UUID`)"""
        return self.__input_device_id

    @input_device_id.setter
    def input_device_id(self, value: uuid.UUID):
        self.__input_device_id = value

    @property
    def type(self) -> InkSensorType:
        """Type of the sensor channel.(`InkSensorType`, read-only) """
        return self.__type

    @property
    def metric(self) -> InkSensorMetricType:
        """Metric of the sensor channel. (`InkSensorMetricType`)"""
        return self.__metric

    @property
    def resolution(self) -> float:
        """Resolution. Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the
        physical unit is in m and input data units. (`float`, read-only)"""
        return self.__resolution

    @property
    def min(self) -> float:
        """Minimal value of the channel. (`float`, read-only)"""
        return self.__min

    @property
    def max(self) -> float:
        """Maximum value of the channel. (`float`, read-only)"""
        return self.__max

    @property
    def precision(self) -> int:
        """Precision of integer encoding, needed for encoded float values. (`int`, read-only)"""
        return self.__precision

    @property
    def index(self) -> int:
        """Index within a list of values, e.g. used in InkML encoding. (`int`, read-only)"""
        return self.__index

    @property
    def name(self) -> str:
        """Name of the channel. (`str`, read-only)"""
        return self.__name

    @property
    def data_type(self) -> DataType:
        """ Data type encoding. (`DataType`, read-only)"""
        return self.__data_type

    def __repr__(self):
        return '<SensorChannel: [id:={}, type:={}, metric:={}, resolution:={}, min:={}, max:={}, ' \
               'precision:={}, index:={}, name:={}>'.format(self.id.hex, self.__type, self.__metric, self.__resolution,
                                                            self.__min, self.__max, self.__precision, self.__index,
                                                            self.__name)


class SensorChannelsContext(HashIdentifier):
    """
    SensorChannelsContext
    =====================

    The class `SensorChannelsContext` is defined as an unique combination of:
    
        - An `InkInputProvider` instance
        - An `InputDevice` instance and
        - A list of sensor channel definitions (by holding a collection of `SensorChannel` instances)
        
    Parameters
    ----------
    sid: `str`
        Group that provides X and Y channels is the one that is referred from StrokeRelation and it's id could be
        always XY.
    channels: `List[SensorChannel]`
        A list of sensor channel descriptors.
    sampling_rate_hint: `int`
        Optional hint for the intended sampling rate of the sensor.[Optional].
    latency: `int`
        Latency measure in milliseconds [Optional].
    ink_input_provider_id: `str`
        Reference to the 'InkInputProvider`.
    input_device_id: `str`
        Reference to the `InputDevice`.

    Notes
    ------
    Once a SensorChannelsContext instance is added to the InputContext repository, it is considered immutable.
    The SensorChannelsContext identifier is unique in the scope of the InkModel and is auto-generated based on the
    MD5-hash based Unique Identifier Generation Algorithm using tag "SensorChannelsContext" and the
    following components:

        - Identifier of the InkInputProvider instance
        - Identifier of the InputDevice instance
        - List of the identifiers of the SensorChannel instances contained within the current SensorChannelsContext

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import InkInputProvider, InkInputType, SensorChannel, \
    >>>       InkSensorType, InkSensorMetricType, SensorChannelsContext, SensorContext
    >>> # Ink input provider can be pen, mouse or touch.
    >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE)
    >>> provider.properties.append(("pen.id", "1234567"))
    >>>
    >>> # We can create an additional input device, for example one providing pressure via Bluetooth
    >>> input_device: InputDevice = InputDevice()
    >>> input_device.properties.append(("dev.id", "345456567"))
    >>> input_device.properties.append(("dev.manufacturer", "Apple"))
    >>>
    >>> # Create a group of sensor channels
    >>> sensor_channels_tablet: list = [
    >>>     SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0)
    >>> ]
    >>>
    >>> scc_tablet: SensorChannelsContext = SensorChannelsContext(channels=sensor_channels_tablet,
    >>>                                                           ink_input_provider_id=provider.id,
    >>>                                                           input_device_id=input_device.id)
    """

    def __init__(self, sid: uuid.UUID = None, channels: List[SensorChannel] = None, sampling_rate_hint: int = None,
                 latency: int = None, ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None):
        super().__init__(sid)
        self.__channels: List[SensorChannel] = channels or []
        self.__sampling_rate_hint: int = sampling_rate_hint
        self.__latency: int = latency
        self.__ink_input_provider_id: uuid.UUID = ink_input_provider_id
        self.__input_device_id: uuid.UUID = input_device_id
        # Set bind channels to input provider and input device
        for c in self.__channels:
            c.ink_input_provider = ink_input_provider_id
            c.input_device_id = input_device_id

    def __tokenize__(self) -> list:
        token: list = ["SensorChannelsContext"]
        token.extend([c.id for c in self.channels])
        token.append(self.sampling_rate)
        token.append(self.latency)
        token.append(self.input_provider_id)
        token.append(self.input_device_id)
        return token

    @property
    def channels(self) -> List[SensorChannel]:
        """Array of the `SensorChannel`s associated with the context. (`List[SensorChannel]`, read-only) """
        return self.__channels

    @property
    def sampling_rate(self) -> int:
        """Hint for sampling rate valid for all channels. (`int`, read-only)"""
        return self.__sampling_rate_hint

    @property
    def latency(self) -> int:
        """Gets the latency measurement in milliseconds. (`int`, read-only)"""
        return self.__latency

    @property
    def input_provider_id(self) -> uuid.UUID:
        """Reference id to the ink `InputProvider` that produces the ink. (`UUID`, read-only)"""
        return self.__ink_input_provider_id

    @property
    def input_device_id(self) -> uuid.UUID:
        """Reference to `InkInputDevice`. (`UUID`, read-only)"""
        return self.__input_device_id

    def add_sensor_channel(self, channel: SensorChannel):
        """
        Adding a channel.

        Parameters
        ----------
        channel: `SensorChannel`
            sensor channel
        """
        self.__channels.append(channel)

    def has_channel_type(self, channel_type: InkSensorType):
        """
        Checks if channel types is available.

        Parameters
        ----------
        channel_type: `InkSensorType`
            sensor type

        Returns
        -------
        flag: `boolean`
            True if available, False if not
        """
        for c in self.channels:
            if c.type == channel_type:
                return True
        return False

    def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel:
        """Returns instance of Channel.

        Parameters
        ----------
        channel_type: `InkSensorType`
            type  of the channel

        Returns
        -------
        instance: SensorChannel
            Instance of the `SensorChannel` for the `InkSensorType`

        Raises
        ------
        InkModelException
            If the `SensorChannel` is not available.
        """
        for c in self.__channels:
            if c.type == channel_type:
                return c
        raise InkModelException(f'No channel available for the type: {channel_type}')

    def __repr__(self):
        return '<SensorChannelsContext: [id:={}, sampling rate hint:={}, latency:={}, input data provider id:={}, ' \
               'input data id:={}>'.format(self.id_h_form, self.sampling_rate, self.latency,
                                           UUIDIdentifier.uimid_to_h_form(self.input_provider_id),
                                           UUIDIdentifier.uimid_to_h_form(self.input_device_id))


class SensorContext(HashIdentifier):
    """
    SensorContext
    =============
    Each input data has a SensorContext describing the available sensors of a input data.
    One file can contains Ink data from two input data of the same type with a shared context.

    Parameters
    -----------
    context_id: UUID
        Id of the context
    sensor_channels_contexts: `List[SensorChannelsContext]`
        List of `SensorChannelsContext`
    """

    def __init__(self, context_id: uuid.UUID = None, sensor_channels_contexts: List[SensorChannelsContext] = None):
        """Constructor.

        """
        super().__init__(context_id)
        self.__sensor_channels_contexts: List[SensorChannelsContext] = sensor_channels_contexts or []

    def __tokenize__(self) -> list:
        token: list = ["SensorContext"]
        token.extend([c.id for c in self.sensor_channels_contexts])
        return token

    @property
    def sensor_channels_contexts(self) -> List[SensorChannelsContext]:
        """
        List of channel contexts. (`List[SensorChannelsContext]`, read-only)"""
        return self.__sensor_channels_contexts

    def add_sensor_channels_context(self, channel_ctx: SensorChannelsContext):
        """Adding a sensor.

        Parameters
        ----------
        channel_ctx: `SensorChannelsContext`
            Adding a channel
        """
        self.__sensor_channels_contexts.append(channel_ctx)

    def has_channel_type(self, channel_type: InkSensorType) -> bool:
        """
        Check if the SensorContext has a channel with type.

        Parameters
        ----------
        channel_type: `InkSensorType`
            type of channel

        Returns
        -------
        flag: `bool`
            True if channel exists, False if not
        """
        for c in self.__sensor_channels_contexts:
            if c.has_channel_type(channel_type):
                return True
        return False

    def get_channel_by_id(self, channel_id: uuid.UUID) -> SensorChannel:
        """
         Returns the channel for a specific id.

         Parameters
         ----------
        channel_id: bytes -
            id of channel

        Returns
        -------
        instance: `SensorChannel`
            Instance of `SensorChannel`

        Raises
        ------
            InkModelException: Raised if no channel for channel id.
        """
        for cs in self.sensor_channels_contexts:
            for c in cs.channels:
                if c.id == channel_id:
                    return c
        raise InkModelException('No channel with channel id: {}.'.format(channel_id))

    def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel:
        """
        Returns the channel for a specific `InkSensorType`.
        
        Parameters
        ----------
        channel_type: `InkSensorType`
            Channel type
        
        Returns
        -------
        instance: `SensorChannel`
            Instance of channel
            
        Raises
        ------
        InkModelException
            Raised if no `SensorChannel` for the id is not available.
        """
        for c in self.__sensor_channels_contexts:
            if c.has_channel_type(channel_type):
                return c.get_channel_by_type(channel_type)
        raise InkModelException('No channel with channel type: {}.'.format(channel_type))

    def __repr__(self):
        return '<SensorContext: [context_id:={}, sensor_channels_contexts:={}]>'.format(self.id,
                                                                                        self.sensor_channels_contexts)


class InputContextRepository(ABC):
    """
    InputContext Repository
    =======================

    The InputContext Repository is a data repository responsible for storing information about where the raw input
    data-frame originates from, by allowing unique identification of the exact input source. The repository stores
    information about the device itself, the environment and the on-board device sensors for each data point.

    The repository holds the following data collections:

        - **ink_input_providers** - a collection of InkInputProvider instances
        - **input_devices** - a collection of InputDevice instances
        - **environments** - a collection of Environment instances
        - **sensor_contexts** - a collection of SensorContext instances
        - **input_contexts** - a collection of InputContext instances
        
    Parameters
    ----------
    input_contexts: List[InputContext] -
        List of input data contexts
    ink_input_providers: List[InkInputProvider]
        List of input data providers
    input_devices: List[InputDevice]
        List of input data devices
    environments: List[Environment]
        List of environment setups
    sensor_contexts: List[SensorContext]
        List of sensor contexts
    """

    def __init__(self, input_contexts: List[InputContext] = None, ink_input_providers: List[InkInputProvider] = None,
                 input_devices: List[InputDevice] = None, environments: List[Environment] = None,
                 sensor_contexts: List[SensorContext] = None):
        self.__input_contexts: List[InputContext] = input_contexts or []
        self.__ink_input_providers: List[InkInputProvider] = ink_input_providers or []
        self.__input_devices: List[InputDevice] = input_devices or []
        self.__environments: List[Environment] = environments or []
        self.__sensor_contexts: List[SensorContext] = sensor_contexts or []

    def add_ink_device(self, ink_device: InputDevice):
        """
        Adding input device.

        Parameters
        ----------
        ink_device: `InputDevice`
            Adds an input device
        """
        self.__input_devices.append(ink_device)

    @property
    def devices(self) -> List[InputDevice]:
        """
        Input devices. (`List[InputDevice]`)"""
        return self.__input_devices

    def add_input_context(self, input_context: InputContext):
        """
        Adding context.

        Parameters
        ----------
        input_context: `InputContext`
            Input context instance
        """
        self.__input_contexts.append(input_context)

    @property
    def input_contexts(self) -> List[InputContext]:
        """ List of input contexts. (`List[InputContext]`, read-only)"""
        return self.__input_contexts

    def get_input_context(self, ctx_id: uuid.UUID) -> InputContext:
        """
        Returns the InputContext.

        Parameters
        ----------
        ctx_id: `UUID`
            Input context id

        Returns
        -------
        context: InputContext
            Input  context

        Raises
        ------
        InkModelException
            If the `InputContext` for the id is not available.
        """
        for ctx in self.input_contexts:
            if ctx.id == ctx_id:
                return ctx
        raise InkModelException('No input context with id:={}.'.format(ctx_id))

    def get_input_device(self, device_id: uuid.UUID) -> InputDevice:
        """
        Returns the InputDevice.

        Parameters
        ----------
        device_id: `UUID`
            Input device id

        Returns
        -------
        context: InputDevice
            Input  device

        Raises
        ------
        InkModelException
            If the `InputDevice` for the id is not available.
        """
        for dev in self.devices:
            if dev.id == device_id:
                return dev
        raise InkModelException('No input device with id:={}.'.format(device_id))

    def get_sensor_context(self, ctx_id: uuid.UUID) -> SensorContext:
        """
        Returns the `SensorContext` for the id.

        Parameters
        ----------
        ctx_id: `UUID`input context id

        Returns
        --------
        instance: `SensorContext`
            `SensorContext` instance

        Raises
        ------
        InkModelException
            If the `SensorContext` for the id is not available
        """
        for ctx in self.sensor_contexts:
            if ctx.id == ctx_id:
                return ctx
        raise InkModelException('No sensor context with id:={}.'.format(ctx_id))

    def add_input_provider(self, input_provider: InkInputProvider):
        """
        Adding input data provider.

        Parameters
        ----------
        input_provider: `InkInputProvider`
            Input data provider instance
        """
        self.__ink_input_providers.append(input_provider)

    @property
    def ink_input_providers(self) -> List[InkInputProvider]:
        """List of `InkInputProvider`s. (`List[InkInputProvider]`, read-only)"""
        return self.__ink_input_providers

    def add_environment(self, environment: Environment):
        """
        Adding environment.

        Parameters
        ----------
        environment: Environment
            Environment instance
        """
        self.environments.append(environment)

    @property
    def environments(self) -> List[Environment]:
        """List of Environments. (`List[Environment]`, read-only)"""
        return self.__environments

    def add_sensor_context(self, sensor_context: SensorContext):
        """
        Adding sensor context.

        Parameters
        ----------
        sensor_context: `SensorContext`
            Instance of `SensorContext`
        """
        self.__sensor_contexts.append(sensor_context)

    @property
    def sensor_contexts(self) -> List[SensorContext]:
        """List of SensorContexts. (`List[SensorContext]`)"""
        return self.__sensor_contexts

    def has_configuration(self) -> bool:
        """Check if any configuration is available.

        Returns
        -------
        flag: bool
            Flag if either ink input provide, input device, or sensor context are defined
        """
        return len(self.input_contexts) > 0 or len(self.sensor_contexts) > 0 or len(self.ink_input_providers) > 0 or \
            len(self.devices) > 0 or len(self.environments)

    def __repr__(self):
        return '<InputContextData: [#context:={}, #providers:={}, #devices:={}, #environments:={}, #sensors:={}]>' \
            .format(len(self.input_contexts), len(self.ink_input_providers), len(self.devices),
                    len(self.environments), len(self.sensor_contexts))

Global variables

var CONVERSION_SCALAR

Mapping containing the factors to convert from one unit: into the other: .

Functions

def si_unit(unit_type: Unit) ‑> Unit

Return the SI unit for a specific unit type.

Parameters

unit_type : Unit
Unit

Returns

si_unit : Unit
SI unit for a unit, e.g., for a lengths unit cm the SI unit is m.
Expand source code
def si_unit(unit_type: Unit) -> Unit:
    """
    Return the SI unit for a specific unit type.

    Parameters
    ----------
    unit_type: `Unit`
        Unit

    Returns
    -------
    si_unit: Unit
        SI unit for a unit, e.g., for a lengths unit cm the SI unit is m.
    """
    # SI unit for length is m
    if unit_type in [Unit.M, Unit.CM, Unit.MM, Unit.IN, Unit.PT, Unit.PC, Unit.DIP]:
        return Unit.M
    # SI unit for time is s
    if unit_type in [Unit.S, Unit.MS, Unit.NS]:
        return Unit.S
    return Unit.UNDEFINED
def unit2unit(source_unit: Unit, target_unit: Unit, value: float) ‑> float

Convert value with a source unit to the target unit.

Parameters

source_unit : Unit
Source unit
target_unit : Unit
Target unit
value : float
Value in source unit

Returns

value : float
value converted to target unit

Raises

Valueerror

Unit is not supported

Expand source code
def unit2unit(source_unit: Unit, target_unit: Unit, value: float) -> float:
    """
    Convert value with a source unit to the target unit.

    Parameters
    ----------
    source_unit: Unit
        Source unit
    target_unit: Unit
        Target unit
    value: float
        Value in source unit

    Returns
    -------
    value: `float`
        value converted to target unit

    Raises
    ------
    ValueError:
        Unit is not supported
    """
    if source_unit == Unit.UNDEFINED or target_unit == Unit.UNDEFINED:
        return value
    if source_unit not in CONVERSION_SCALAR:
        raise ValueError('Source unit not supported. Unit:={}'.format(source_unit))
    if target_unit not in CONVERSION_SCALAR[source_unit]:
        raise ValueError('Target unit not supported. Unit:={}'.format(target_unit))
    return CONVERSION_SCALAR[source_unit][target_unit] * value
def unit2unit_matrix(source_unit: Unit, target_unit: Unit) ‑> 

Matrix for unit 2 unit conversion.

Parameters

source_unit : Unit
Source unit
target_unit : Unit
Target unit

Returns

matrix: <code>np.array</code>
    matrix for conversion
Expand source code
def unit2unit_matrix(source_unit: Unit, target_unit: Unit) -> np.array:
    """
    Matrix for unit 2 unit conversion.

    Parameters
    ----------
    source_unit: Unit
        Source unit
    target_unit: Unit
        Target unit

    Returns
    -------
        matrix: `np.array`
            matrix for conversion
    """
    matrix: np.array = np.identity(3)
    if source_unit == Unit.UNDEFINED or target_unit == Unit.UNDEFINED:
        return matrix
    if source_unit not in CONVERSION_SCALAR:
        raise ValueError('Source unit not supported.')
    if target_unit not in CONVERSION_SCALAR[source_unit]:
        raise ValueError('Target unit not supported.')
    matrix[0, 0] = CONVERSION_SCALAR[source_unit][target_unit]
    matrix[1, 1] = CONVERSION_SCALAR[source_unit][target_unit]
    return matrix
def virtual_resolution_for_si_unit(source_unit: Unit) ‑> float

Calculate a virtual resolution for source unit.

Parameters

source_unit : unit
Source unit

Returns

resolution : float
Virtual resolution
Expand source code
def virtual_resolution_for_si_unit(source_unit: Unit) -> float:
    """
    Calculate a virtual resolution for source unit.

    Parameters
    ----------
    source_unit: unit
        Source unit
    Returns
    -------
    resolution: `float`
        Virtual resolution
    """
    si: Unit = si_unit(source_unit)
    if si == Unit.UNDEFINED:
        return 1.
    return 1. / CONVERSION_SCALAR[source_unit][si]

Classes

class DataType (value, names=None, *, module=None, qualname=None, type=None, start=1)

Data types for channels.

Expand source code
class DataType(Enum):
    """Data types for channels."""
    BOOLEAN = 0
    FLOAT32 = 1
    FLOAT64 = 2
    INT32 = 3
    INT64 = 4
    UINT32 = 5
    UINT64 = 6

Ancestors

  • enum.Enum

Class variables

var BOOLEAN
var FLOAT32
var FLOAT64
var INT32
var INT64
var UINT32
var UINT64
class Environment (env_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None)

Environment

The class Environment represents for the virtual environment in which the sensor data has been produced, e.g,:

- os.name - Name of the operating system
- os.version.name - Name of the version
- os.version.release - Release build number
- wacom.ink.sdk.name - Name of the Wacom Ink technology
- wacom.ink.sdk.version - Version number of the SDK

Parameters

env_id : UUID
Internal environment UUID
properties : List[Tuple[str, str]]
Properties of the environment

Examples

>>> from uim.model.inkinput.inputdata import Environment
>>> # Create an environment
>>> env: Environment = Environment()
>>> env.properties.append(("env.name", "My Environment"))
>>> env.properties.append(("os.id", "98765"))
>>> env.properties.append(("os.name", "Windows"))
>>> env.properties.append(("os.version", "10.0.18362.239"))
>>> env.properties.append(("os.build", "239"))
>>> env.properties.append(("os.platform", "whatever"))
Expand source code
class Environment(HashIdentifier):
    """
    Environment
    ===========
    The class `Environment` represents for the virtual environment in which the sensor data has been produced, e.g,:

        - os.name - Name of the operating system
        - os.version.name - Name of the version
        - os.version.release - Release build number
        - wacom.ink.sdk.name - Name of the Wacom Ink technology
        - wacom.ink.sdk.version - Version number of the SDK

    Parameters
    ----------
    env_id: `UUID`
        Internal environment UUID
    properties: List[Tuple[str, str]]
        Properties of the environment

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import Environment
    >>> # Create an environment
    >>> env: Environment = Environment()
    >>> env.properties.append(("env.name", "My Environment"))
    >>> env.properties.append(("os.id", "98765"))
    >>> env.properties.append(("os.name", "Windows"))
    >>> env.properties.append(("os.version", "10.0.18362.239"))
    >>> env.properties.append(("os.build", "239"))
    >>> env.properties.append(("os.platform", "whatever"))
    """

    def __init__(self, env_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None):
        super().__init__(env_id)
        self.__properties = properties or []

    def __tokenize__(self) -> List[Any]:
        token: List[Any] = ['Environment', self.properties]
        return token

    @property
    def properties(self) -> List[Tuple[str, str]]:
        """Environment properties. (`List[Tuple[str, str]]`, read-only) """
        return self.__properties

    def add_environment_property(self, key: str, value: str):
        """
        Adding a property for environment.

        Parameters
        ----------
        key: str
            Name of the property
        value: str
            Value of the property
        """
        self.properties.append((key, value))

    def __repr__(self):
        return '<Environment: [id:={}, #properties:={}>'.format(self.id.hex, self.properties)

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var properties : List[Tuple[str, str]]

Environment properties. (List[Tuple[str, str]], read-only)

Expand source code
@property
def properties(self) -> List[Tuple[str, str]]:
    """Environment properties. (`List[Tuple[str, str]]`, read-only) """
    return self.__properties

Methods

def add_environment_property(self, key: str, value: str)

Adding a property for environment.

Parameters

key : str
Name of the property
value : str
Value of the property
Expand source code
def add_environment_property(self, key: str, value: str):
    """
    Adding a property for environment.

    Parameters
    ----------
    key: str
        Name of the property
    value: str
        Value of the property
    """
    self.properties.append((key, value))

Inherited members

class InkInputProvider (provider_id: uuid.UUID = None, input_type: InkInputType = None, properties: List[Tuple[str, str]] = None)

InkInputProvider

The class InkInputProvider stands for the generic input data source - it identifies how the data has been generated (using touch input, mouse, stylus, hardware controller, etc).

The properties which can be used to describe the InkInputProvider:

- pen.type - Type of the pen device

Parameters

provider_id : UUID
internal id or input data name.
input_type : InkInputType -
type of used hardware - PEN, TOUCH, MOUSE, or CONTROLLER.
properties : List[Tuple[str, str]] -
Properties assigned to ink input provider

Examples

>>> from uim.model.inkinput.inputdata import InkInputProvider
>>> # Ink input provider can be pen, mouse or touch.
>>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE)
>>> provider.properties.append(("pen.id", "1234567"))
Expand source code
class InkInputProvider(HashIdentifier):
    """
    InkInputProvider
    ================
    The class InkInputProvider stands for the generic input data source - it identifies how the data has been generated
    (using touch input, mouse, stylus, hardware controller, etc).

    The properties which can be used to describe the InkInputProvider:

        - pen.type - Type of the pen device

    Parameters
    ----------
    provider_id: UUID
        internal id or input data name.
    input_type: InkInputType -
        type of used hardware - PEN, TOUCH, MOUSE, or CONTROLLER.
    properties: List[Tuple[str, str]] -
        Properties assigned to ink input provider

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import InkInputProvider
    >>> # Ink input provider can be pen, mouse or touch.
    >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE)
    >>> provider.properties.append(("pen.id", "1234567"))
    """

    def __init__(self, provider_id: uuid.UUID = None, input_type: InkInputType = None,
                 properties: List[Tuple[str, str]] = None):
        super().__init__(provider_id)
        self.__type: InkInputType = input_type
        self.__properties: List[Tuple[str, str]] = properties or []

    def __tokenize__(self):
        return ['InkInputProvider', TOKEN_MAP[self.type], self.properties]

    @property
    def type(self) -> InkInputType:
        """Input provider type. (`InkInputType`,  read-only)"""
        return self.__type

    @property
    def properties(self) -> List[Tuple[str, str]]:
        """Properties of input data provider. (`List[Tuple[str, str]]`, read-only)"""
        return self.__properties

    def __repr__(self):
        return '<InkInputProvider: [id:={}, type:={}, properties:={}]>'.format(self.id, self.type, self.properties)

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var properties : List[Tuple[str, str]]

Properties of input data provider. (List[Tuple[str, str]], read-only)

Expand source code
@property
def properties(self) -> List[Tuple[str, str]]:
    """Properties of input data provider. (`List[Tuple[str, str]]`, read-only)"""
    return self.__properties
var typeInkInputType

Input provider type. (InkInputType, read-only)

Expand source code
@property
def type(self) -> InkInputType:
    """Input provider type. (`InkInputType`,  read-only)"""
    return self.__type

Inherited members

class InkInputType (value, names=None, *, module=None, qualname=None, type=None, start=1)

Defining the different types of input data.

Expand source code
class InkInputType(Enum):
    """
    Defining the different types of input data.
    """
    PEN = uim.PEN
    """Stylus, smart pens, pen displays, signature capturing input data, ..."""
    TOUCH = uim.TOUCH
    """Touch controller input data: Finger or passive stylus."""
    MOUSE = uim.MOUSE
    """Mouse input data."""
    CONTROLLER = uim.CONTROLLER
    """3-DOF or 6-DOF input data devices."""

Ancestors

  • enum.Enum

Class variables

var CONTROLLER

3-DOF or 6-DOF input data devices.

var MOUSE

Mouse input data.

var PEN

Stylus, smart pens, pen displays, signature capturing input data, …

var TOUCH

Touch controller input data: Finger or passive stylus.

class InkSensorMetricType (value, names=None, *, module=None, qualname=None, type=None, start=1)

Metric for the channel.

Expand source code
class InkSensorMetricType(Enum):
    """Metric for the channel."""
    LENGTH = uim.LENGTH
    """Length; underling si unit is meter"""
    TIME = uim.TIME
    """Time; underling  si unit is second"""
    FORCE = uim.FORCE
    """Force; underling si unit is newton"""
    ANGLE = uim.ANGLE
    """Angle; underling si unit is radian"""
    NORMALIZED = uim.NORMALIZED
    """Normalized; percentage, expressed as a fraction(1.0 = 100 %) relative to max - min"""

Ancestors

  • enum.Enum

Class variables

var ANGLE

Angle; underling si unit is radian

var FORCE

Force; underling si unit is newton

var LENGTH

Length; underling si unit is meter

var NORMALIZED

Normalized; percentage, expressed as a fraction(1.0 = 100 %) relative to max - min

var TIME

Time; underling si unit is second

class InkSensorType (value, names=None, *, module=None, qualname=None, type=None, start=1)

Pre-defined SensorData types.

Expand source code
class InkSensorType(Enum):
    """
        Pre-defined SensorData types.
    """

    X = 'will://input/3.0/channel/X'
    """X coordinate. This is the horizontal pen position on the writing surface."""
    Y = 'will://input/3.0/channel/Y'
    """Y coordinate. This is the vertical position on the writing surface. """
    Z = 'will://input/3.0/channel/Z'
    """Z coordinate. This is the height of pen above the writing surface."""
    TIMESTAMP = 'will://input/3.0/channel/Timestamp'
    """Time (of the sample point)"""
    PRESSURE = 'will://input/3.0/channel/Pressure'
    """Input pressure."""
    RADIUS_X = 'will://input/3.0/channel/RadiusX'
    """Touch radius by X"""
    RADIUS_Y = 'will://input/3.0/channel/RadiusY'
    """Touch radius by Y"""
    AZIMUTH = 'will://input/3.0/channel/Azimuth'
    """Azimuth angle of the pen (yaw)"""
    ALTITUDE = 'will://input/3.0/channel/Altitude'
    """Elevation angle of the pen (pitch)"""
    ROTATION = 'will://input/3.0/channel/Rotation'
    """Rotation (counter-clockwise rotation about pen axis)"""

Ancestors

  • enum.Enum

Class variables

var ALTITUDE

Elevation angle of the pen (pitch)

var AZIMUTH

Azimuth angle of the pen (yaw)

var PRESSURE

Input pressure.

var RADIUS_X

Touch radius by X

var RADIUS_Y

Touch radius by Y

var ROTATION

Rotation (counter-clockwise rotation about pen axis)

var TIMESTAMP

Time (of the sample point)

var X

X coordinate. This is the horizontal pen position on the writing surface.

var Y

Y coordinate. This is the vertical position on the writing surface.

var Z

Z coordinate. This is the height of pen above the writing surface.

class InputContext (ctx_id: uuid.UUID = None, environment_id: uuid.UUID = None, sensor_context_id: uuid.UUID = None)

InputContext

Capturing context of the uim input data with reference to the Environment and the SensorContext.

Parameters

ctx_id : UUID
Internal id
environment_id : UUID
Reference to environment
sensor_context_id : UUID
Rendering to sensor context
Expand source code
class InputContext(HashIdentifier):
    """
    InputContext
    ============
    Capturing context of the uim input data with reference to the Environment and the SensorContext.

    Parameters
    ----------
    ctx_id: `UUID`
        Internal id
    environment_id: `UUID`
        Reference to environment
    sensor_context_id: `UUID`
        Rendering to sensor context
    """

    def __init__(self, ctx_id: uuid.UUID = None, environment_id: uuid.UUID = None, sensor_context_id: uuid.UUID = None):
        super().__init__(ctx_id)
        self.__environment_id = environment_id
        self.__sensor_context_id = sensor_context_id

    def __tokenize__(self) -> list:
        return ["InputContext", self.environment_id, self.sensor_context_id]

    @property
    def environment_id(self) -> uuid.UUID:
        """Reference to environment. (`UUID`, read-only)"""
        return self.__environment_id

    @property
    def sensor_context_id(self) -> uuid.UUID:
        """Reference for sensor context. (`UUID`, read-only)"""
        return self.__sensor_context_id

    def __repr__(self):
        env_id: str = Identifier.uimid_to_s_form(self.environment_id)
        sc_id: str = Identifier.uimid_to_s_form(self.sensor_context_id)
        return '<InputContext : [id:={}, environment id:={}, sensor context id:={}>'.format(self.id_h_form,
                                                                                            env_id, sc_id)

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var environment_id : uuid.UUID

Reference to environment. (UUID, read-only)

Expand source code
@property
def environment_id(self) -> uuid.UUID:
    """Reference to environment. (`UUID`, read-only)"""
    return self.__environment_id
var sensor_context_id : uuid.UUID

Reference for sensor context. (UUID, read-only)

Expand source code
@property
def sensor_context_id(self) -> uuid.UUID:
    """Reference for sensor context. (`UUID`, read-only)"""
    return self.__sensor_context_id

Inherited members

class InputContextRepository (input_contexts: List[InputContext] = None, ink_input_providers: List[InkInputProvider] = None, input_devices: List[InputDevice] = None, environments: List[Environment] = None, sensor_contexts: List[SensorContext] = None)

InputContext Repository

The InputContext Repository is a data repository responsible for storing information about where the raw input data-frame originates from, by allowing unique identification of the exact input source. The repository stores information about the device itself, the environment and the on-board device sensors for each data point.

The repository holds the following data collections:

- **ink_input_providers** - a collection of InkInputProvider instances
- **input_devices** - a collection of InputDevice instances
- **environments** - a collection of Environment instances
- **sensor_contexts** - a collection of SensorContext instances
- **input_contexts** - a collection of InputContext instances

Parameters

input_contexts : List[InputContext] -
List of input data contexts
ink_input_providers : List[InkInputProvider]
List of input data providers
input_devices : List[InputDevice]
List of input data devices
environments : List[Environment]
List of environment setups
sensor_contexts : List[SensorContext]
List of sensor contexts
Expand source code
class InputContextRepository(ABC):
    """
    InputContext Repository
    =======================

    The InputContext Repository is a data repository responsible for storing information about where the raw input
    data-frame originates from, by allowing unique identification of the exact input source. The repository stores
    information about the device itself, the environment and the on-board device sensors for each data point.

    The repository holds the following data collections:

        - **ink_input_providers** - a collection of InkInputProvider instances
        - **input_devices** - a collection of InputDevice instances
        - **environments** - a collection of Environment instances
        - **sensor_contexts** - a collection of SensorContext instances
        - **input_contexts** - a collection of InputContext instances
        
    Parameters
    ----------
    input_contexts: List[InputContext] -
        List of input data contexts
    ink_input_providers: List[InkInputProvider]
        List of input data providers
    input_devices: List[InputDevice]
        List of input data devices
    environments: List[Environment]
        List of environment setups
    sensor_contexts: List[SensorContext]
        List of sensor contexts
    """

    def __init__(self, input_contexts: List[InputContext] = None, ink_input_providers: List[InkInputProvider] = None,
                 input_devices: List[InputDevice] = None, environments: List[Environment] = None,
                 sensor_contexts: List[SensorContext] = None):
        self.__input_contexts: List[InputContext] = input_contexts or []
        self.__ink_input_providers: List[InkInputProvider] = ink_input_providers or []
        self.__input_devices: List[InputDevice] = input_devices or []
        self.__environments: List[Environment] = environments or []
        self.__sensor_contexts: List[SensorContext] = sensor_contexts or []

    def add_ink_device(self, ink_device: InputDevice):
        """
        Adding input device.

        Parameters
        ----------
        ink_device: `InputDevice`
            Adds an input device
        """
        self.__input_devices.append(ink_device)

    @property
    def devices(self) -> List[InputDevice]:
        """
        Input devices. (`List[InputDevice]`)"""
        return self.__input_devices

    def add_input_context(self, input_context: InputContext):
        """
        Adding context.

        Parameters
        ----------
        input_context: `InputContext`
            Input context instance
        """
        self.__input_contexts.append(input_context)

    @property
    def input_contexts(self) -> List[InputContext]:
        """ List of input contexts. (`List[InputContext]`, read-only)"""
        return self.__input_contexts

    def get_input_context(self, ctx_id: uuid.UUID) -> InputContext:
        """
        Returns the InputContext.

        Parameters
        ----------
        ctx_id: `UUID`
            Input context id

        Returns
        -------
        context: InputContext
            Input  context

        Raises
        ------
        InkModelException
            If the `InputContext` for the id is not available.
        """
        for ctx in self.input_contexts:
            if ctx.id == ctx_id:
                return ctx
        raise InkModelException('No input context with id:={}.'.format(ctx_id))

    def get_input_device(self, device_id: uuid.UUID) -> InputDevice:
        """
        Returns the InputDevice.

        Parameters
        ----------
        device_id: `UUID`
            Input device id

        Returns
        -------
        context: InputDevice
            Input  device

        Raises
        ------
        InkModelException
            If the `InputDevice` for the id is not available.
        """
        for dev in self.devices:
            if dev.id == device_id:
                return dev
        raise InkModelException('No input device with id:={}.'.format(device_id))

    def get_sensor_context(self, ctx_id: uuid.UUID) -> SensorContext:
        """
        Returns the `SensorContext` for the id.

        Parameters
        ----------
        ctx_id: `UUID`input context id

        Returns
        --------
        instance: `SensorContext`
            `SensorContext` instance

        Raises
        ------
        InkModelException
            If the `SensorContext` for the id is not available
        """
        for ctx in self.sensor_contexts:
            if ctx.id == ctx_id:
                return ctx
        raise InkModelException('No sensor context with id:={}.'.format(ctx_id))

    def add_input_provider(self, input_provider: InkInputProvider):
        """
        Adding input data provider.

        Parameters
        ----------
        input_provider: `InkInputProvider`
            Input data provider instance
        """
        self.__ink_input_providers.append(input_provider)

    @property
    def ink_input_providers(self) -> List[InkInputProvider]:
        """List of `InkInputProvider`s. (`List[InkInputProvider]`, read-only)"""
        return self.__ink_input_providers

    def add_environment(self, environment: Environment):
        """
        Adding environment.

        Parameters
        ----------
        environment: Environment
            Environment instance
        """
        self.environments.append(environment)

    @property
    def environments(self) -> List[Environment]:
        """List of Environments. (`List[Environment]`, read-only)"""
        return self.__environments

    def add_sensor_context(self, sensor_context: SensorContext):
        """
        Adding sensor context.

        Parameters
        ----------
        sensor_context: `SensorContext`
            Instance of `SensorContext`
        """
        self.__sensor_contexts.append(sensor_context)

    @property
    def sensor_contexts(self) -> List[SensorContext]:
        """List of SensorContexts. (`List[SensorContext]`)"""
        return self.__sensor_contexts

    def has_configuration(self) -> bool:
        """Check if any configuration is available.

        Returns
        -------
        flag: bool
            Flag if either ink input provide, input device, or sensor context are defined
        """
        return len(self.input_contexts) > 0 or len(self.sensor_contexts) > 0 or len(self.ink_input_providers) > 0 or \
            len(self.devices) > 0 or len(self.environments)

    def __repr__(self):
        return '<InputContextData: [#context:={}, #providers:={}, #devices:={}, #environments:={}, #sensors:={}]>' \
            .format(len(self.input_contexts), len(self.ink_input_providers), len(self.devices),
                    len(self.environments), len(self.sensor_contexts))

Ancestors

  • abc.ABC

Instance variables

var devices : List[InputDevice]

Input devices. (List[InputDevice])

Expand source code
@property
def devices(self) -> List[InputDevice]:
    """
    Input devices. (`List[InputDevice]`)"""
    return self.__input_devices
var environments : List[Environment]

List of Environments. (List[Environment], read-only)

Expand source code
@property
def environments(self) -> List[Environment]:
    """List of Environments. (`List[Environment]`, read-only)"""
    return self.__environments
var ink_input_providers : List[InkInputProvider]

List of InkInputProviders. (List[InkInputProvider], read-only)

Expand source code
@property
def ink_input_providers(self) -> List[InkInputProvider]:
    """List of `InkInputProvider`s. (`List[InkInputProvider]`, read-only)"""
    return self.__ink_input_providers
var input_contexts : List[InputContext]

List of input contexts. (List[InputContext], read-only)

Expand source code
@property
def input_contexts(self) -> List[InputContext]:
    """ List of input contexts. (`List[InputContext]`, read-only)"""
    return self.__input_contexts
var sensor_contexts : List[SensorContext]

List of SensorContexts. (List[SensorContext])

Expand source code
@property
def sensor_contexts(self) -> List[SensorContext]:
    """List of SensorContexts. (`List[SensorContext]`)"""
    return self.__sensor_contexts

Methods

def add_environment(self, environment: Environment)

Adding environment.

Parameters

environment : Environment
Environment instance
Expand source code
def add_environment(self, environment: Environment):
    """
    Adding environment.

    Parameters
    ----------
    environment: Environment
        Environment instance
    """
    self.environments.append(environment)
def add_ink_device(self, ink_device: InputDevice)

Adding input device.

Parameters

ink_device : InputDevice
Adds an input device
Expand source code
def add_ink_device(self, ink_device: InputDevice):
    """
    Adding input device.

    Parameters
    ----------
    ink_device: `InputDevice`
        Adds an input device
    """
    self.__input_devices.append(ink_device)
def add_input_context(self, input_context: InputContext)

Adding context.

Parameters

input_context : InputContext
Input context instance
Expand source code
def add_input_context(self, input_context: InputContext):
    """
    Adding context.

    Parameters
    ----------
    input_context: `InputContext`
        Input context instance
    """
    self.__input_contexts.append(input_context)
def add_input_provider(self, input_provider: InkInputProvider)

Adding input data provider.

Parameters

input_provider : InkInputProvider
Input data provider instance
Expand source code
def add_input_provider(self, input_provider: InkInputProvider):
    """
    Adding input data provider.

    Parameters
    ----------
    input_provider: `InkInputProvider`
        Input data provider instance
    """
    self.__ink_input_providers.append(input_provider)
def add_sensor_context(self, sensor_context: SensorContext)

Adding sensor context.

Parameters

sensor_context : SensorContext
Instance of SensorContext
Expand source code
def add_sensor_context(self, sensor_context: SensorContext):
    """
    Adding sensor context.

    Parameters
    ----------
    sensor_context: `SensorContext`
        Instance of `SensorContext`
    """
    self.__sensor_contexts.append(sensor_context)
def get_input_context(self, ctx_id: uuid.UUID) ‑> InputContext

Returns the InputContext.

Parameters

ctx_id : UUID
Input context id

Returns

context : InputContext
Input context

Raises

InkModelException
If the InputContext for the id is not available.
Expand source code
def get_input_context(self, ctx_id: uuid.UUID) -> InputContext:
    """
    Returns the InputContext.

    Parameters
    ----------
    ctx_id: `UUID`
        Input context id

    Returns
    -------
    context: InputContext
        Input  context

    Raises
    ------
    InkModelException
        If the `InputContext` for the id is not available.
    """
    for ctx in self.input_contexts:
        if ctx.id == ctx_id:
            return ctx
    raise InkModelException('No input context with id:={}.'.format(ctx_id))
def get_input_device(self, device_id: uuid.UUID) ‑> InputDevice

Returns the InputDevice.

Parameters

device_id : UUID
Input device id

Returns

context : InputDevice
Input device

Raises

InkModelException
If the InputDevice for the id is not available.
Expand source code
def get_input_device(self, device_id: uuid.UUID) -> InputDevice:
    """
    Returns the InputDevice.

    Parameters
    ----------
    device_id: `UUID`
        Input device id

    Returns
    -------
    context: InputDevice
        Input  device

    Raises
    ------
    InkModelException
        If the `InputDevice` for the id is not available.
    """
    for dev in self.devices:
        if dev.id == device_id:
            return dev
    raise InkModelException('No input device with id:={}.'.format(device_id))
def get_sensor_context(self, ctx_id: uuid.UUID) ‑> SensorContext

Returns the SensorContext for the id.

Parameters

ctx_id : UUID</code>input context id
 

Returns

instance : SensorContext
SensorContext instance

Raises

InkModelException
If the SensorContext for the id is not available
Expand source code
def get_sensor_context(self, ctx_id: uuid.UUID) -> SensorContext:
    """
    Returns the `SensorContext` for the id.

    Parameters
    ----------
    ctx_id: `UUID`input context id

    Returns
    --------
    instance: `SensorContext`
        `SensorContext` instance

    Raises
    ------
    InkModelException
        If the `SensorContext` for the id is not available
    """
    for ctx in self.sensor_contexts:
        if ctx.id == ctx_id:
            return ctx
    raise InkModelException('No sensor context with id:={}.'.format(ctx_id))
def has_configuration(self) ‑> bool

Check if any configuration is available.

Returns

flag : bool
Flag if either ink input provide, input device, or sensor context are defined
Expand source code
def has_configuration(self) -> bool:
    """Check if any configuration is available.

    Returns
    -------
    flag: bool
        Flag if either ink input provide, input device, or sensor context are defined
    """
    return len(self.input_contexts) > 0 or len(self.sensor_contexts) > 0 or len(self.ink_input_providers) > 0 or \
        len(self.devices) > 0 or len(self.environments)
class InputDevice (device_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None)

InputDevice

The class InputDevice represents the hardware device, on which the sensor data has been produced (touch enabled mobile device, touch capable monitor, digitizer, etc). InputDevice with properties.

The properties can contain:

  • Communication Protocol: USB, BTC, BLE, SPP, WIFI,
  • Communication ID: VID, PID; MAC; UID; COM_PORT,
  • Device Name: Wacom Intuos Pro M, Apple iPad 8, Samsung GalaxyTab 10,
  • PenID,
  • Serial number,
  • Firmware Version (MCU),
  • Secondary Firmware Version (BT, WIFI) - different modules provides version for itself,
  • Orientation: PORTRAIT, LANDSCAPE, PORTRAIT_REVERSE, LANDSCAPE_REVERSE or 0, 90, 180, 270,
  • Sensor size.

Parameters

device_id : UUID
Internal input device id
properties : List[Tuple[str, str]]
Properties of the input device

Examples

>>> from uim.model.inkinput.inputdata import InputDevice
>>> # Input device is the sensor (pen tablet, screen, etc.)
>>> input_device: InputDevice = InputDevice()
>>> input_device.properties.append(("dev.id", "123454321"))
>>> input_device.properties.append(("dev.manufacturer", "Wacom"))
>>> input_device.properties.append(("dev.model", "Mobile Studio Pro"))
>>> input_device.properties.append(("dev.cpu", "Intel"))
>>> input_device.properties.append(("dev.graphics.display", "Dell 1920x1080 32bit"))
>>> input_device.properties.append(("dev.graphics.adapter", "NVidia"))
Expand source code
class InputDevice(HashIdentifier):
    """
    InputDevice
    ===========
    The class `InputDevice` represents the hardware device, on which the sensor data has been produced
    (touch enabled mobile device, touch capable monitor, digitizer, etc).
    InputDevice with properties.

    The properties can contain:

      - Communication Protocol: USB, BTC, BLE, SPP, WIFI,
      - Communication ID: VID, PID; MAC; UID; COM_PORT,
      - Device Name: Wacom Intuos Pro M, Apple iPad 8, Samsung GalaxyTab 10,
      - PenID,
      - Serial number,
      - Firmware Version (MCU),
      - Secondary Firmware Version (BT, WIFI) - different modules provides version for itself,
      - Orientation: PORTRAIT, LANDSCAPE, PORTRAIT_REVERSE, LANDSCAPE_REVERSE or 0, 90, 180, 270,
      - Sensor size.

    Parameters
    ----------
    device_id: `UUID`
        Internal input device id
    properties: List[Tuple[str, str]]
        Properties of the input device

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import InputDevice
    >>> # Input device is the sensor (pen tablet, screen, etc.)
    >>> input_device: InputDevice = InputDevice()
    >>> input_device.properties.append(("dev.id", "123454321"))
    >>> input_device.properties.append(("dev.manufacturer", "Wacom"))
    >>> input_device.properties.append(("dev.model", "Mobile Studio Pro"))
    >>> input_device.properties.append(("dev.cpu", "Intel"))
    >>> input_device.properties.append(("dev.graphics.display", "Dell 1920x1080 32bit"))
    >>> input_device.properties.append(("dev.graphics.adapter", "NVidia"))
    """

    def __init__(self, device_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None):
        super().__init__(device_id)
        self.__properties: List[Tuple[str, str]] = properties or []

    @property
    def properties(self) -> List[Tuple[str, str]]:
        """Properties of the InputDevice. (` List[Tuple[str, str]]`, read-only)"""
        return self.__properties

    def add_property(self, key: str, value):
        """Adding property.

        Parameters
        ----------
        key: str
            Name of the property
        value: str
            Value of the property
        """
        self.__properties.append((key, value))

    def __tokenize__(self):
        return ['InputDevice', self.properties]

    def __repr__(self):
        return '<InputDevice : [id:={}, num properties:={}>'.format(self.id, self.properties)

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var properties : List[Tuple[str, str]]

Properties of the InputDevice. ( List[Tuple[str, str]], read-only)

Expand source code
@property
def properties(self) -> List[Tuple[str, str]]:
    """Properties of the InputDevice. (` List[Tuple[str, str]]`, read-only)"""
    return self.__properties

Methods

def add_property(self, key: str, value)

Adding property.

Parameters

key : str
Name of the property
value : str
Value of the property
Expand source code
def add_property(self, key: str, value):
    """Adding property.

    Parameters
    ----------
    key: str
        Name of the property
    value: str
        Value of the property
    """
    self.__properties.append((key, value))

Inherited members

class SensorChannel (channel_id: uuid.UUID = None, channel_type: InkSensorType = None, metric: InkSensorMetricType = None, resolution: float = 1.0, channel_min: float = 0.0, channel_max: float = 0.0, precision: int = 2, index: int = 0, name: str = None, data_type: DataType = DataType.FLOAT32, ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None)

SensorChannel

The SensorChannel represents a generic sensor channel definition, which has the following properties:

  • type - URI uniquely identifying the type of the sensor channel
  • metric - The type of the data to the SI metric system
  • resolution - A factor multiplication value (power of 10) used to convert the stored data values to the specified SI metric
  • min, max - Lower and upper bounds of the reported values range
  • precision - The precision of the sensor when reporting floating-point values (defined as an int value, used as a power of 10 during the serialization/deserialization phase)

Parameters

channel_id : UUID
Sensor channel descriptor. If no channel_id is set the MD5 hashing is generating the id
channel_type:InkSensorType
Indicates metric used in calculating the resolution for the data item.
metric : InkSensorMetricType
Indicates metric used in calculating the resolution for the data item.
resolution : float
Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the physical unit is in m and input data units. Resolution is 100000, then the value 150 would be 0.0015 m.
channel_min : float
Minimal value of the channel
channel_max : float
Maximal value of the channel
precision : int
Precision of integer encoding, needed for encoded float values
index : int
Index of the channel
name : str
Name of the channel
data_type : DataType
Type of data within the channel
ink_input_provider_id : UUID
Reference to the ink input provider
input_device_id : UUID
Reference to the ink input device

Examples

>>> from uim.model.inkinput.inputdata import SensorChannel, InkSensorType
>>> # Create a group of sensor channels
>>> sensor_channels_tablet: list = [
>>>     SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0),
>>>     SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0),
>>>     SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0)
>>> ]
Expand source code
class SensorChannel(HashIdentifier):
    """
    SensorChannel
    =============
    The `SensorChannel` represents a generic sensor channel definition, which has the following properties:

    - **type** - URI uniquely identifying the type of the sensor channel
    - **metric** - The type of the data to the SI metric system
    - **resolution** - A factor multiplication value (power of 10) used to convert the stored data values to the
                      specified SI metric
    - **min, max** - Lower and upper bounds of the reported values range
    - **precision** - The precision of the sensor when reporting floating-point values (defined as an int value,
                      used as a power of 10 during the serialization/deserialization phase)
    
    Parameters
    ----------
    channel_id: `UUID`
        Sensor channel descriptor. If no channel_id is set the MD5 hashing is generating the id
    channel_type:`InkSensorType`
        Indicates metric used in calculating the resolution for the data item.
    metric: `InkSensorMetricType`
        Indicates metric used in calculating the resolution for the data item.
    resolution: `float`
        Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the
        physical unit is in m and input data units. Resolution is 100000, then the value 150 would be
        0.0015 m.
    channel_min: `float`
        Minimal value of the channel
    channel_max: `float`
        Maximal value of the channel
    precision: `int`
        Precision of integer encoding, needed for encoded float values
    index: `int`
        Index of the channel
    name: `str`
        Name of the channel
    data_type: `DataType`
        Type of data within the channel
    ink_input_provider_id: `UUID`
        Reference to the ink input provider
    input_device_id: `UUID`
        Reference to the ink input device

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import SensorChannel, InkSensorType
    >>> # Create a group of sensor channels
    >>> sensor_channels_tablet: list = [
    >>>     SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0)
    >>> ]
    """

    def __init__(self, channel_id: uuid.UUID = None,
                 channel_type: InkSensorType = None, metric: InkSensorMetricType = None,
                 resolution: float = 1., channel_min: float = 0., channel_max: float = 0.,
                 precision: int = 2, index: int = 0, name: str = None, data_type: DataType = DataType.FLOAT32,
                 ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None):
        super().__init__(channel_id)
        self.__type: InkSensorType = channel_type
        self.__metric: InkSensorMetricType = metric
        self.__resolution: float = float(resolution)
        self.__min: float = float(channel_min)
        self.__max: float = float(channel_max)
        self.__precision: int = precision
        self.__index: int = index
        self.__name: str = name
        self.__data_type: DataType = data_type
        self.__ink_input_provider: uuid.UUID = ink_input_provider_id
        self.__input_device_id: uuid.UUID = input_device_id

    def __tokenize__(self) -> list:
        return ["SensorChannel", self.__ink_input_provider, self.__input_device_id, TOKEN_MAP[self.type],
                TOKEN_MAP[self.metric], self.resolution, self.min, self.max, self.precision]

    @property
    def ink_input_provider(self) -> uuid.UUID:
        """Reference to the `InkInputProvider` of the channel. (`UUID`)"""
        return self.__ink_input_provider

    @ink_input_provider.setter
    def ink_input_provider(self, value: uuid.UUID):
        self.__ink_input_provider = value

    @property
    def input_device_id(self) -> uuid.UUID:
        """Reference to the `InputDevice` of the channel. (`UUID`)"""
        return self.__input_device_id

    @input_device_id.setter
    def input_device_id(self, value: uuid.UUID):
        self.__input_device_id = value

    @property
    def type(self) -> InkSensorType:
        """Type of the sensor channel.(`InkSensorType`, read-only) """
        return self.__type

    @property
    def metric(self) -> InkSensorMetricType:
        """Metric of the sensor channel. (`InkSensorMetricType`)"""
        return self.__metric

    @property
    def resolution(self) -> float:
        """Resolution. Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the
        physical unit is in m and input data units. (`float`, read-only)"""
        return self.__resolution

    @property
    def min(self) -> float:
        """Minimal value of the channel. (`float`, read-only)"""
        return self.__min

    @property
    def max(self) -> float:
        """Maximum value of the channel. (`float`, read-only)"""
        return self.__max

    @property
    def precision(self) -> int:
        """Precision of integer encoding, needed for encoded float values. (`int`, read-only)"""
        return self.__precision

    @property
    def index(self) -> int:
        """Index within a list of values, e.g. used in InkML encoding. (`int`, read-only)"""
        return self.__index

    @property
    def name(self) -> str:
        """Name of the channel. (`str`, read-only)"""
        return self.__name

    @property
    def data_type(self) -> DataType:
        """ Data type encoding. (`DataType`, read-only)"""
        return self.__data_type

    def __repr__(self):
        return '<SensorChannel: [id:={}, type:={}, metric:={}, resolution:={}, min:={}, max:={}, ' \
               'precision:={}, index:={}, name:={}>'.format(self.id.hex, self.__type, self.__metric, self.__resolution,
                                                            self.__min, self.__max, self.__precision, self.__index,
                                                            self.__name)

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var data_typeDataType

Data type encoding. (DataType, read-only)

Expand source code
@property
def data_type(self) -> DataType:
    """ Data type encoding. (`DataType`, read-only)"""
    return self.__data_type
var index : int

Index within a list of values, e.g. used in InkML encoding. (int, read-only)

Expand source code
@property
def index(self) -> int:
    """Index within a list of values, e.g. used in InkML encoding. (`int`, read-only)"""
    return self.__index
var ink_input_provider : uuid.UUID

Reference to the InkInputProvider of the channel. (UUID)

Expand source code
@property
def ink_input_provider(self) -> uuid.UUID:
    """Reference to the `InkInputProvider` of the channel. (`UUID`)"""
    return self.__ink_input_provider
var input_device_id : uuid.UUID

Reference to the InputDevice of the channel. (UUID)

Expand source code
@property
def input_device_id(self) -> uuid.UUID:
    """Reference to the `InputDevice` of the channel. (`UUID`)"""
    return self.__input_device_id
var max : float

Maximum value of the channel. (float, read-only)

Expand source code
@property
def max(self) -> float:
    """Maximum value of the channel. (`float`, read-only)"""
    return self.__max
var metricInkSensorMetricType

Metric of the sensor channel. (InkSensorMetricType)

Expand source code
@property
def metric(self) -> InkSensorMetricType:
    """Metric of the sensor channel. (`InkSensorMetricType`)"""
    return self.__metric
var min : float

Minimal value of the channel. (float, read-only)

Expand source code
@property
def min(self) -> float:
    """Minimal value of the channel. (`float`, read-only)"""
    return self.__min
var name : str

Name of the channel. (str, read-only)

Expand source code
@property
def name(self) -> str:
    """Name of the channel. (`str`, read-only)"""
    return self.__name
var precision : int

Precision of integer encoding, needed for encoded float values. (int, read-only)

Expand source code
@property
def precision(self) -> int:
    """Precision of integer encoding, needed for encoded float values. (`int`, read-only)"""
    return self.__precision
var resolution : float

Resolution. Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the physical unit is in m and input data units. (float, read-only)

Expand source code
@property
def resolution(self) -> float:
    """Resolution. Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the
    physical unit is in m and input data units. (`float`, read-only)"""
    return self.__resolution
var typeInkSensorType

Type of the sensor channel.(InkSensorType, read-only)

Expand source code
@property
def type(self) -> InkSensorType:
    """Type of the sensor channel.(`InkSensorType`, read-only) """
    return self.__type

Inherited members

class SensorChannelsContext (sid: uuid.UUID = None, channels: List[SensorChannel] = None, sampling_rate_hint: int = None, latency: int = None, ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None)

SensorChannelsContext

The class SensorChannelsContext is defined as an unique combination of:

- An <code><a title="uim.model.inkinput.inputdata.InkInputProvider" href="#uim.model.inkinput.inputdata.InkInputProvider">InkInputProvider</a></code> instance
- An <code><a title="uim.model.inkinput.inputdata.InputDevice" href="#uim.model.inkinput.inputdata.InputDevice">InputDevice</a></code> instance and
- A list of sensor channel definitions (by holding a collection of <code><a title="uim.model.inkinput.inputdata.SensorChannel" href="#uim.model.inkinput.inputdata.SensorChannel">SensorChannel</a></code> instances)

Parameters

sid : str
Group that provides X and Y channels is the one that is referred from StrokeRelation and it's id could be always XY.
channels : List[SensorChannel]
A list of sensor channel descriptors.
sampling_rate_hint : int
Optional hint for the intended sampling rate of the sensor.[Optional].
latency : int
Latency measure in milliseconds [Optional].
ink_input_provider_id : str
Reference to the 'InkInputProvider`.
input_device_id : str
Reference to the InputDevice.

Notes

Once a SensorChannelsContext instance is added to the InputContext repository, it is considered immutable. The SensorChannelsContext identifier is unique in the scope of the InkModel and is auto-generated based on the MD5-hash based Unique Identifier Generation Algorithm using tag "SensorChannelsContext" and the following components:

- Identifier of the InkInputProvider instance
- Identifier of the InputDevice instance
- List of the identifiers of the SensorChannel instances contained within the current SensorChannelsContext

Examples

>>> from uim.model.inkinput.inputdata import InkInputProvider, InkInputType, SensorChannel,     >>>       InkSensorType, InkSensorMetricType, SensorChannelsContext, SensorContext
>>> # Ink input provider can be pen, mouse or touch.
>>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE)
>>> provider.properties.append(("pen.id", "1234567"))
>>>
>>> # We can create an additional input device, for example one providing pressure via Bluetooth
>>> input_device: InputDevice = InputDevice()
>>> input_device.properties.append(("dev.id", "345456567"))
>>> input_device.properties.append(("dev.manufacturer", "Apple"))
>>>
>>> # Create a group of sensor channels
>>> sensor_channels_tablet: list = [
>>>     SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0),
>>>     SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0),
>>>     SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0)
>>> ]
>>>
>>> scc_tablet: SensorChannelsContext = SensorChannelsContext(channels=sensor_channels_tablet,
>>>                                                           ink_input_provider_id=provider.id,
>>>                                                           input_device_id=input_device.id)
Expand source code
class SensorChannelsContext(HashIdentifier):
    """
    SensorChannelsContext
    =====================

    The class `SensorChannelsContext` is defined as an unique combination of:
    
        - An `InkInputProvider` instance
        - An `InputDevice` instance and
        - A list of sensor channel definitions (by holding a collection of `SensorChannel` instances)
        
    Parameters
    ----------
    sid: `str`
        Group that provides X and Y channels is the one that is referred from StrokeRelation and it's id could be
        always XY.
    channels: `List[SensorChannel]`
        A list of sensor channel descriptors.
    sampling_rate_hint: `int`
        Optional hint for the intended sampling rate of the sensor.[Optional].
    latency: `int`
        Latency measure in milliseconds [Optional].
    ink_input_provider_id: `str`
        Reference to the 'InkInputProvider`.
    input_device_id: `str`
        Reference to the `InputDevice`.

    Notes
    ------
    Once a SensorChannelsContext instance is added to the InputContext repository, it is considered immutable.
    The SensorChannelsContext identifier is unique in the scope of the InkModel and is auto-generated based on the
    MD5-hash based Unique Identifier Generation Algorithm using tag "SensorChannelsContext" and the
    following components:

        - Identifier of the InkInputProvider instance
        - Identifier of the InputDevice instance
        - List of the identifiers of the SensorChannel instances contained within the current SensorChannelsContext

    Examples
    --------
    >>> from uim.model.inkinput.inputdata import InkInputProvider, InkInputType, SensorChannel, \
    >>>       InkSensorType, InkSensorMetricType, SensorChannelsContext, SensorContext
    >>> # Ink input provider can be pen, mouse or touch.
    >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE)
    >>> provider.properties.append(("pen.id", "1234567"))
    >>>
    >>> # We can create an additional input device, for example one providing pressure via Bluetooth
    >>> input_device: InputDevice = InputDevice()
    >>> input_device.properties.append(("dev.id", "345456567"))
    >>> input_device.properties.append(("dev.manufacturer", "Apple"))
    >>>
    >>> # Create a group of sensor channels
    >>> sensor_channels_tablet: list = [
    >>>     SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0),
    >>>     SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0)
    >>> ]
    >>>
    >>> scc_tablet: SensorChannelsContext = SensorChannelsContext(channels=sensor_channels_tablet,
    >>>                                                           ink_input_provider_id=provider.id,
    >>>                                                           input_device_id=input_device.id)
    """

    def __init__(self, sid: uuid.UUID = None, channels: List[SensorChannel] = None, sampling_rate_hint: int = None,
                 latency: int = None, ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None):
        super().__init__(sid)
        self.__channels: List[SensorChannel] = channels or []
        self.__sampling_rate_hint: int = sampling_rate_hint
        self.__latency: int = latency
        self.__ink_input_provider_id: uuid.UUID = ink_input_provider_id
        self.__input_device_id: uuid.UUID = input_device_id
        # Set bind channels to input provider and input device
        for c in self.__channels:
            c.ink_input_provider = ink_input_provider_id
            c.input_device_id = input_device_id

    def __tokenize__(self) -> list:
        token: list = ["SensorChannelsContext"]
        token.extend([c.id for c in self.channels])
        token.append(self.sampling_rate)
        token.append(self.latency)
        token.append(self.input_provider_id)
        token.append(self.input_device_id)
        return token

    @property
    def channels(self) -> List[SensorChannel]:
        """Array of the `SensorChannel`s associated with the context. (`List[SensorChannel]`, read-only) """
        return self.__channels

    @property
    def sampling_rate(self) -> int:
        """Hint for sampling rate valid for all channels. (`int`, read-only)"""
        return self.__sampling_rate_hint

    @property
    def latency(self) -> int:
        """Gets the latency measurement in milliseconds. (`int`, read-only)"""
        return self.__latency

    @property
    def input_provider_id(self) -> uuid.UUID:
        """Reference id to the ink `InputProvider` that produces the ink. (`UUID`, read-only)"""
        return self.__ink_input_provider_id

    @property
    def input_device_id(self) -> uuid.UUID:
        """Reference to `InkInputDevice`. (`UUID`, read-only)"""
        return self.__input_device_id

    def add_sensor_channel(self, channel: SensorChannel):
        """
        Adding a channel.

        Parameters
        ----------
        channel: `SensorChannel`
            sensor channel
        """
        self.__channels.append(channel)

    def has_channel_type(self, channel_type: InkSensorType):
        """
        Checks if channel types is available.

        Parameters
        ----------
        channel_type: `InkSensorType`
            sensor type

        Returns
        -------
        flag: `boolean`
            True if available, False if not
        """
        for c in self.channels:
            if c.type == channel_type:
                return True
        return False

    def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel:
        """Returns instance of Channel.

        Parameters
        ----------
        channel_type: `InkSensorType`
            type  of the channel

        Returns
        -------
        instance: SensorChannel
            Instance of the `SensorChannel` for the `InkSensorType`

        Raises
        ------
        InkModelException
            If the `SensorChannel` is not available.
        """
        for c in self.__channels:
            if c.type == channel_type:
                return c
        raise InkModelException(f'No channel available for the type: {channel_type}')

    def __repr__(self):
        return '<SensorChannelsContext: [id:={}, sampling rate hint:={}, latency:={}, input data provider id:={}, ' \
               'input data id:={}>'.format(self.id_h_form, self.sampling_rate, self.latency,
                                           UUIDIdentifier.uimid_to_h_form(self.input_provider_id),
                                           UUIDIdentifier.uimid_to_h_form(self.input_device_id))

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var channels : List[SensorChannel]

Array of the SensorChannels associated with the context. (List[SensorChannel], read-only)

Expand source code
@property
def channels(self) -> List[SensorChannel]:
    """Array of the `SensorChannel`s associated with the context. (`List[SensorChannel]`, read-only) """
    return self.__channels
var input_device_id : uuid.UUID

Reference to InkInputDevice. (UUID, read-only)

Expand source code
@property
def input_device_id(self) -> uuid.UUID:
    """Reference to `InkInputDevice`. (`UUID`, read-only)"""
    return self.__input_device_id
var input_provider_id : uuid.UUID

Reference id to the ink InputProvider that produces the ink. (UUID, read-only)

Expand source code
@property
def input_provider_id(self) -> uuid.UUID:
    """Reference id to the ink `InputProvider` that produces the ink. (`UUID`, read-only)"""
    return self.__ink_input_provider_id
var latency : int

Gets the latency measurement in milliseconds. (int, read-only)

Expand source code
@property
def latency(self) -> int:
    """Gets the latency measurement in milliseconds. (`int`, read-only)"""
    return self.__latency
var sampling_rate : int

Hint for sampling rate valid for all channels. (int, read-only)

Expand source code
@property
def sampling_rate(self) -> int:
    """Hint for sampling rate valid for all channels. (`int`, read-only)"""
    return self.__sampling_rate_hint

Methods

def add_sensor_channel(self, channel: SensorChannel)

Adding a channel.

Parameters

channel : SensorChannel
sensor channel
Expand source code
def add_sensor_channel(self, channel: SensorChannel):
    """
    Adding a channel.

    Parameters
    ----------
    channel: `SensorChannel`
        sensor channel
    """
    self.__channels.append(channel)
def get_channel_by_type(self, channel_type: InkSensorType) ‑> SensorChannel

Returns instance of Channel.

Parameters

channel_type : InkSensorType
type of the channel

Returns

instance : SensorChannel
Instance of the SensorChannel for the InkSensorType

Raises

InkModelException
If the SensorChannel is not available.
Expand source code
def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel:
    """Returns instance of Channel.

    Parameters
    ----------
    channel_type: `InkSensorType`
        type  of the channel

    Returns
    -------
    instance: SensorChannel
        Instance of the `SensorChannel` for the `InkSensorType`

    Raises
    ------
    InkModelException
        If the `SensorChannel` is not available.
    """
    for c in self.__channels:
        if c.type == channel_type:
            return c
    raise InkModelException(f'No channel available for the type: {channel_type}')
def has_channel_type(self, channel_type: InkSensorType)

Checks if channel types is available.

Parameters

channel_type : InkSensorType
sensor type

Returns

flag : boolean
True if available, False if not
Expand source code
def has_channel_type(self, channel_type: InkSensorType):
    """
    Checks if channel types is available.

    Parameters
    ----------
    channel_type: `InkSensorType`
        sensor type

    Returns
    -------
    flag: `boolean`
        True if available, False if not
    """
    for c in self.channels:
        if c.type == channel_type:
            return True
    return False

Inherited members

class SensorContext (context_id: uuid.UUID = None, sensor_channels_contexts: List[SensorChannelsContext] = None)

SensorContext

Each input data has a SensorContext describing the available sensors of a input data. One file can contains Ink data from two input data of the same type with a shared context.

Parameters

context_id : UUID
Id of the context
sensor_channels_contexts : List[SensorChannelsContext]
List of SensorChannelsContext

Constructor.

Expand source code
class SensorContext(HashIdentifier):
    """
    SensorContext
    =============
    Each input data has a SensorContext describing the available sensors of a input data.
    One file can contains Ink data from two input data of the same type with a shared context.

    Parameters
    -----------
    context_id: UUID
        Id of the context
    sensor_channels_contexts: `List[SensorChannelsContext]`
        List of `SensorChannelsContext`
    """

    def __init__(self, context_id: uuid.UUID = None, sensor_channels_contexts: List[SensorChannelsContext] = None):
        """Constructor.

        """
        super().__init__(context_id)
        self.__sensor_channels_contexts: List[SensorChannelsContext] = sensor_channels_contexts or []

    def __tokenize__(self) -> list:
        token: list = ["SensorContext"]
        token.extend([c.id for c in self.sensor_channels_contexts])
        return token

    @property
    def sensor_channels_contexts(self) -> List[SensorChannelsContext]:
        """
        List of channel contexts. (`List[SensorChannelsContext]`, read-only)"""
        return self.__sensor_channels_contexts

    def add_sensor_channels_context(self, channel_ctx: SensorChannelsContext):
        """Adding a sensor.

        Parameters
        ----------
        channel_ctx: `SensorChannelsContext`
            Adding a channel
        """
        self.__sensor_channels_contexts.append(channel_ctx)

    def has_channel_type(self, channel_type: InkSensorType) -> bool:
        """
        Check if the SensorContext has a channel with type.

        Parameters
        ----------
        channel_type: `InkSensorType`
            type of channel

        Returns
        -------
        flag: `bool`
            True if channel exists, False if not
        """
        for c in self.__sensor_channels_contexts:
            if c.has_channel_type(channel_type):
                return True
        return False

    def get_channel_by_id(self, channel_id: uuid.UUID) -> SensorChannel:
        """
         Returns the channel for a specific id.

         Parameters
         ----------
        channel_id: bytes -
            id of channel

        Returns
        -------
        instance: `SensorChannel`
            Instance of `SensorChannel`

        Raises
        ------
            InkModelException: Raised if no channel for channel id.
        """
        for cs in self.sensor_channels_contexts:
            for c in cs.channels:
                if c.id == channel_id:
                    return c
        raise InkModelException('No channel with channel id: {}.'.format(channel_id))

    def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel:
        """
        Returns the channel for a specific `InkSensorType`.
        
        Parameters
        ----------
        channel_type: `InkSensorType`
            Channel type
        
        Returns
        -------
        instance: `SensorChannel`
            Instance of channel
            
        Raises
        ------
        InkModelException
            Raised if no `SensorChannel` for the id is not available.
        """
        for c in self.__sensor_channels_contexts:
            if c.has_channel_type(channel_type):
                return c.get_channel_by_type(channel_type)
        raise InkModelException('No channel with channel type: {}.'.format(channel_type))

    def __repr__(self):
        return '<SensorContext: [context_id:={}, sensor_channels_contexts:={}]>'.format(self.id,
                                                                                        self.sensor_channels_contexts)

Ancestors

Class variables

var SEPARATOR : str

Instance variables

var sensor_channels_contexts : List[SensorChannelsContext]

List of channel contexts. (List[SensorChannelsContext], read-only)

Expand source code
@property
def sensor_channels_contexts(self) -> List[SensorChannelsContext]:
    """
    List of channel contexts. (`List[SensorChannelsContext]`, read-only)"""
    return self.__sensor_channels_contexts

Methods

def add_sensor_channels_context(self, channel_ctx: SensorChannelsContext)

Adding a sensor.

Parameters

channel_ctx : SensorChannelsContext
Adding a channel
Expand source code
def add_sensor_channels_context(self, channel_ctx: SensorChannelsContext):
    """Adding a sensor.

    Parameters
    ----------
    channel_ctx: `SensorChannelsContext`
        Adding a channel
    """
    self.__sensor_channels_contexts.append(channel_ctx)
def get_channel_by_id(self, channel_id: uuid.UUID) ‑> SensorChannel

Returns the channel for a specific id.

Parameters


channel_id: bytes - id of channel

Returns

instance : SensorChannel
Instance of SensorChannel

Raises

InkModelException: Raised if no channel for channel id.
Expand source code
def get_channel_by_id(self, channel_id: uuid.UUID) -> SensorChannel:
    """
     Returns the channel for a specific id.

     Parameters
     ----------
    channel_id: bytes -
        id of channel

    Returns
    -------
    instance: `SensorChannel`
        Instance of `SensorChannel`

    Raises
    ------
        InkModelException: Raised if no channel for channel id.
    """
    for cs in self.sensor_channels_contexts:
        for c in cs.channels:
            if c.id == channel_id:
                return c
    raise InkModelException('No channel with channel id: {}.'.format(channel_id))
def get_channel_by_type(self, channel_type: InkSensorType) ‑> SensorChannel

Returns the channel for a specific InkSensorType.

Parameters

channel_type : InkSensorType
Channel type

Returns

instance : SensorChannel
Instance of channel

Raises

InkModelException
Raised if no SensorChannel for the id is not available.
Expand source code
def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel:
    """
    Returns the channel for a specific `InkSensorType`.
    
    Parameters
    ----------
    channel_type: `InkSensorType`
        Channel type
    
    Returns
    -------
    instance: `SensorChannel`
        Instance of channel
        
    Raises
    ------
    InkModelException
        Raised if no `SensorChannel` for the id is not available.
    """
    for c in self.__sensor_channels_contexts:
        if c.has_channel_type(channel_type):
            return c.get_channel_by_type(channel_type)
    raise InkModelException('No channel with channel type: {}.'.format(channel_type))
def has_channel_type(self, channel_type: InkSensorType) ‑> bool

Check if the SensorContext has a channel with type.

Parameters

channel_type : InkSensorType
type of channel

Returns

flag : bool
True if channel exists, False if not
Expand source code
def has_channel_type(self, channel_type: InkSensorType) -> bool:
    """
    Check if the SensorContext has a channel with type.

    Parameters
    ----------
    channel_type: `InkSensorType`
        type of channel

    Returns
    -------
    flag: `bool`
        True if channel exists, False if not
    """
    for c in self.__sensor_channels_contexts:
        if c.has_channel_type(channel_type):
            return True
    return False

Inherited members

class Unit (value, names=None, *, module=None, qualname=None, type=None, start=1)

An enumeration.

Expand source code
class Unit(Enum):
    # Lengths units
    UNDEFINED = 0
    """Undefined unit"""
    M = 10
    """meters"""
    CM = 11
    """centimeters"""
    MM = 12
    """millimeters"""
    IN = 13
    """inches"""
    PT = 14
    """points (1pt = 1/72 in)"""
    PC = 15
    """picas (1pc = 1/22 pt)"""
    DIP = 16
    """device independent pixel (1DIP = 1/96 in)"""
    # Time units
    S = 20
    """seconds"""
    MS = 21
    """milliseconds"""
    NS = 22
    """nanoseconds"""
    # Force units
    N = 30
    """Newtons"""
    # Angle
    RAD = 42
    """radians"""
    DEG = 41
    """degrees"""
    # General
    PERCENTAGE = 50
    """percentage, expressed as a fraction (1.0 = 100%) relative to max-min"""
    LOGICAL_VALUE = 60
    """logical value"""

Ancestors

  • enum.Enum

Class variables

var CM

centimeters

var DEG

degrees

var DIP

device independent pixel (1DIP = 1/96 in)

var IN

inches

var LOGICAL_VALUE

logical value

var M

meters

var MM

millimeters

var MS

milliseconds

var N

Newtons

var NS

nanoseconds

var PC

picas (1pc = 1/22 pt)

var PERCENTAGE

percentage, expressed as a fraction (1.0 = 100%) relative to max-min

var PT

points (1pt = 1/72 in)

var RAD

radians

var S

seconds

var UNDEFINED

Undefined unit