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/Altitude'
"""Azimuth angle of the pen (yaw)"""
ALTITUDE = 'will://input/3.0/channel/Azimuth'
"""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
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
Returns
matrix: <code>np.array</code> matrix for conversionExpand 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 = 6Ancestors
- enum.Enum
Class variables
var BOOLEANvar FLOAT32var FLOAT64var INT32var INT64var UINT32var UINT64
class Environment (env_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None)-
Environment
The class
Environmentrepresents 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 SDKParameters
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
- HashIdentifier
- Identifier
- abc.ABC
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 deviceParameters
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
- HashIdentifier
- Identifier
- abc.ABC
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 type : InkInputType-
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/Altitude' """Azimuth angle of the pen (yaw)""" ALTITUDE = 'will://input/3.0/channel/Azimuth' """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
- HashIdentifier
- Identifier
- abc.ABC
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 instancesParameters
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)-
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)-
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)-
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)-
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
InputContextfor 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
InputDevicefor 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
SensorContextfor the id.Parameters
ctx_id:UUID</code>input context id
Returns
instance:SensorContextSensorContextinstance
Raises
InkModelException- If the
SensorContextfor 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
InputDevicerepresents 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
- HashIdentifier
- Identifier
- abc.ABC
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
SensorChannelrepresents 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
- HashIdentifier
- Identifier
- abc.ABC
Class variables
var SEPARATOR : str
Instance variables
var data_type : DataType-
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
InkInputProviderof 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
InputDeviceof 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 metric : InkSensorMetricType-
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 type : InkSensorType-
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
SensorChannelsContextis 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 SensorChannelsContextExamples
>>> 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
- HashIdentifier
- Identifier
- abc.ABC
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
InputProviderthat 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)-
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
SensorChannelfor theInkSensorType
Raises
InkModelException- If the
SensorChannelis 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
- HashIdentifier
- Identifier
- abc.ABC
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)-
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
SensorChannelfor 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