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 conversion
Expand source code
def unit2unit_matrix(source_unit: Unit, target_unit: Unit) -> np.array: """ Matrix for unit 2 unit conversion. Parameters ---------- source_unit: Unit Source unit target_unit: Unit Target unit Returns ------- matrix: `np.array` matrix for conversion """ matrix: np.array = np.identity(3) if source_unit == Unit.UNDEFINED or target_unit == Unit.UNDEFINED: return matrix if source_unit not in CONVERSION_SCALAR: raise ValueError('Source unit not supported.') if target_unit not in CONVERSION_SCALAR[source_unit]: raise ValueError('Target unit not supported.') matrix[0, 0] = CONVERSION_SCALAR[source_unit][target_unit] matrix[1, 1] = CONVERSION_SCALAR[source_unit][target_unit] return matrix
def virtual_resolution_for_si_unit(source_unit: Unit) ‑> float
-
Calculate a virtual resolution for source unit.
Parameters
source_unit
:unit
- Source unit
Returns
resolution
:float
- Virtual resolution
Expand source code
def virtual_resolution_for_si_unit(source_unit: Unit) -> float: """ Calculate a virtual resolution for source unit. Parameters ---------- source_unit: unit Source unit Returns ------- resolution: `float` Virtual resolution """ si: Unit = si_unit(source_unit) if si == Unit.UNDEFINED: return 1. return 1. / CONVERSION_SCALAR[source_unit][si]
Classes
class DataType (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
Data types for channels.
Expand source code
class DataType(Enum): """Data types for channels.""" BOOLEAN = 0 FLOAT32 = 1 FLOAT64 = 2 INT32 = 3 INT64 = 4 UINT32 = 5 UINT64 = 6
Ancestors
- enum.Enum
Class variables
var BOOLEAN
var FLOAT32
var FLOAT64
var INT32
var INT64
var UINT32
var UINT64
class Environment (env_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None)
-
Environment
The class
Environment
represents for the virtual environment in which the sensor data has been produced, e.g,:- os.name - Name of the operating system - os.version.name - Name of the version - os.version.release - Release build number - wacom.ink.sdk.name - Name of the Wacom Ink technology - wacom.ink.sdk.version - Version number of the SDK
Parameters
env_id
:UUID
- Internal environment UUID
properties
:List[Tuple[str, str]]
- Properties of the environment
Examples
>>> from uim.model.inkinput.inputdata import Environment >>> # Create an environment >>> env: Environment = Environment() >>> env.properties.append(("env.name", "My Environment")) >>> env.properties.append(("os.id", "98765")) >>> env.properties.append(("os.name", "Windows")) >>> env.properties.append(("os.version", "10.0.18362.239")) >>> env.properties.append(("os.build", "239")) >>> env.properties.append(("os.platform", "whatever"))
Expand source code
class Environment(HashIdentifier): """ Environment =========== The class `Environment` represents for the virtual environment in which the sensor data has been produced, e.g,: - os.name - Name of the operating system - os.version.name - Name of the version - os.version.release - Release build number - wacom.ink.sdk.name - Name of the Wacom Ink technology - wacom.ink.sdk.version - Version number of the SDK Parameters ---------- env_id: `UUID` Internal environment UUID properties: List[Tuple[str, str]] Properties of the environment Examples -------- >>> from uim.model.inkinput.inputdata import Environment >>> # Create an environment >>> env: Environment = Environment() >>> env.properties.append(("env.name", "My Environment")) >>> env.properties.append(("os.id", "98765")) >>> env.properties.append(("os.name", "Windows")) >>> env.properties.append(("os.version", "10.0.18362.239")) >>> env.properties.append(("os.build", "239")) >>> env.properties.append(("os.platform", "whatever")) """ def __init__(self, env_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None): super().__init__(env_id) self.__properties = properties or [] def __tokenize__(self) -> List[Any]: token: List[Any] = ['Environment', self.properties] return token @property def properties(self) -> List[Tuple[str, str]]: """Environment properties. (`List[Tuple[str, str]]`, read-only) """ return self.__properties def add_environment_property(self, key: str, value: str): """ Adding a property for environment. Parameters ---------- key: str Name of the property value: str Value of the property """ self.properties.append((key, value)) def __repr__(self): return '<Environment: [id:={}, #properties:={}>'.format(self.id.hex, self.properties)
Ancestors
- 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 device
Parameters
provider_id
:UUID
- internal id or input data name.
input_type
:InkInputType -
- type of used hardware - PEN, TOUCH, MOUSE, or CONTROLLER.
properties
:List[Tuple[str, str]] -
- Properties assigned to ink input provider
Examples
>>> from uim.model.inkinput.inputdata import InkInputProvider >>> # Ink input provider can be pen, mouse or touch. >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE) >>> provider.properties.append(("pen.id", "1234567"))
Expand source code
class InkInputProvider(HashIdentifier): """ InkInputProvider ================ The class InkInputProvider stands for the generic input data source - it identifies how the data has been generated (using touch input, mouse, stylus, hardware controller, etc). The properties which can be used to describe the InkInputProvider: - pen.type - Type of the pen device Parameters ---------- provider_id: UUID internal id or input data name. input_type: InkInputType - type of used hardware - PEN, TOUCH, MOUSE, or CONTROLLER. properties: List[Tuple[str, str]] - Properties assigned to ink input provider Examples -------- >>> from uim.model.inkinput.inputdata import InkInputProvider >>> # Ink input provider can be pen, mouse or touch. >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE) >>> provider.properties.append(("pen.id", "1234567")) """ def __init__(self, provider_id: uuid.UUID = None, input_type: InkInputType = None, properties: List[Tuple[str, str]] = None): super().__init__(provider_id) self.__type: InkInputType = input_type self.__properties: List[Tuple[str, str]] = properties or [] def __tokenize__(self): return ['InkInputProvider', TOKEN_MAP[self.type], self.properties] @property def type(self) -> InkInputType: """Input provider type. (`InkInputType`, read-only)""" return self.__type @property def properties(self) -> List[Tuple[str, str]]: """Properties of input data provider. (`List[Tuple[str, str]]`, read-only)""" return self.__properties def __repr__(self): return '<InkInputProvider: [id:={}, type:={}, properties:={}]>'.format(self.id, self.type, self.properties)
Ancestors
- 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 instances
Parameters
input_contexts
:List[InputContext] -
- List of input data contexts
ink_input_providers
:List[InkInputProvider]
- List of input data providers
input_devices
:List[InputDevice]
- List of input data devices
environments
:List[Environment]
- List of environment setups
sensor_contexts
:List[SensorContext]
- List of sensor contexts
Expand source code
class InputContextRepository(ABC): """ InputContext Repository ======================= The InputContext Repository is a data repository responsible for storing information about where the raw input data-frame originates from, by allowing unique identification of the exact input source. The repository stores information about the device itself, the environment and the on-board device sensors for each data point. The repository holds the following data collections: - **ink_input_providers** - a collection of InkInputProvider instances - **input_devices** - a collection of InputDevice instances - **environments** - a collection of Environment instances - **sensor_contexts** - a collection of SensorContext instances - **input_contexts** - a collection of InputContext instances Parameters ---------- input_contexts: List[InputContext] - List of input data contexts ink_input_providers: List[InkInputProvider] List of input data providers input_devices: List[InputDevice] List of input data devices environments: List[Environment] List of environment setups sensor_contexts: List[SensorContext] List of sensor contexts """ def __init__(self, input_contexts: List[InputContext] = None, ink_input_providers: List[InkInputProvider] = None, input_devices: List[InputDevice] = None, environments: List[Environment] = None, sensor_contexts: List[SensorContext] = None): self.__input_contexts: List[InputContext] = input_contexts or [] self.__ink_input_providers: List[InkInputProvider] = ink_input_providers or [] self.__input_devices: List[InputDevice] = input_devices or [] self.__environments: List[Environment] = environments or [] self.__sensor_contexts: List[SensorContext] = sensor_contexts or [] def add_ink_device(self, ink_device: InputDevice): """ Adding input device. Parameters ---------- ink_device: `InputDevice` Adds an input device """ self.__input_devices.append(ink_device) @property def devices(self) -> List[InputDevice]: """ Input devices. (`List[InputDevice]`)""" return self.__input_devices def add_input_context(self, input_context: InputContext): """ Adding context. Parameters ---------- input_context: `InputContext` Input context instance """ self.__input_contexts.append(input_context) @property def input_contexts(self) -> List[InputContext]: """ List of input contexts. (`List[InputContext]`, read-only)""" return self.__input_contexts def get_input_context(self, ctx_id: uuid.UUID) -> InputContext: """ Returns the InputContext. Parameters ---------- ctx_id: `UUID` Input context id Returns ------- context: InputContext Input context Raises ------ InkModelException If the `InputContext` for the id is not available. """ for ctx in self.input_contexts: if ctx.id == ctx_id: return ctx raise InkModelException('No input context with id:={}.'.format(ctx_id)) def get_input_device(self, device_id: uuid.UUID) -> InputDevice: """ Returns the InputDevice. Parameters ---------- device_id: `UUID` Input device id Returns ------- context: InputDevice Input device Raises ------ InkModelException If the `InputDevice` for the id is not available. """ for dev in self.devices: if dev.id == device_id: return dev raise InkModelException('No input device with id:={}.'.format(device_id)) def get_sensor_context(self, ctx_id: uuid.UUID) -> SensorContext: """ Returns the `SensorContext` for the id. Parameters ---------- ctx_id: `UUID`input context id Returns -------- instance: `SensorContext` `SensorContext` instance Raises ------ InkModelException If the `SensorContext` for the id is not available """ for ctx in self.sensor_contexts: if ctx.id == ctx_id: return ctx raise InkModelException('No sensor context with id:={}.'.format(ctx_id)) def add_input_provider(self, input_provider: InkInputProvider): """ Adding input data provider. Parameters ---------- input_provider: `InkInputProvider` Input data provider instance """ self.__ink_input_providers.append(input_provider) @property def ink_input_providers(self) -> List[InkInputProvider]: """List of `InkInputProvider`s. (`List[InkInputProvider]`, read-only)""" return self.__ink_input_providers def add_environment(self, environment: Environment): """ Adding environment. Parameters ---------- environment: Environment Environment instance """ self.environments.append(environment) @property def environments(self) -> List[Environment]: """List of Environments. (`List[Environment]`, read-only)""" return self.__environments def add_sensor_context(self, sensor_context: SensorContext): """ Adding sensor context. Parameters ---------- sensor_context: `SensorContext` Instance of `SensorContext` """ self.__sensor_contexts.append(sensor_context) @property def sensor_contexts(self) -> List[SensorContext]: """List of SensorContexts. (`List[SensorContext]`)""" return self.__sensor_contexts def has_configuration(self) -> bool: """Check if any configuration is available. Returns ------- flag: bool Flag if either ink input provide, input device, or sensor context are defined """ return len(self.input_contexts) > 0 or len(self.sensor_contexts) > 0 or len(self.ink_input_providers) > 0 or \ len(self.devices) > 0 or len(self.environments) def __repr__(self): return '<InputContextData: [#context:={}, #providers:={}, #devices:={}, #environments:={}, #sensors:={}]>' \ .format(len(self.input_contexts), len(self.ink_input_providers), len(self.devices), len(self.environments), len(self.sensor_contexts))
Ancestors
- abc.ABC
Instance variables
var devices : List[InputDevice]
-
Input devices. (
List[InputDevice]
)Expand source code
@property def devices(self) -> List[InputDevice]: """ Input devices. (`List[InputDevice]`)""" return self.__input_devices
var environments : List[Environment]
-
List of Environments. (
List[Environment]
, read-only)Expand source code
@property def environments(self) -> List[Environment]: """List of Environments. (`List[Environment]`, read-only)""" return self.__environments
var ink_input_providers : List[InkInputProvider]
-
List of
InkInputProvider
s. (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
InputContext
for the id is not available.
Expand source code
def get_input_context(self, ctx_id: uuid.UUID) -> InputContext: """ Returns the InputContext. Parameters ---------- ctx_id: `UUID` Input context id Returns ------- context: InputContext Input context Raises ------ InkModelException If the `InputContext` for the id is not available. """ for ctx in self.input_contexts: if ctx.id == ctx_id: return ctx raise InkModelException('No input context with id:={}.'.format(ctx_id))
def get_input_device(self, device_id: uuid.UUID) ‑> InputDevice
-
Returns the InputDevice.
Parameters
device_id
:UUID
- Input device id
Returns
context
:InputDevice
- Input device
Raises
InkModelException
- If the
InputDevice
for the id is not available.
Expand source code
def get_input_device(self, device_id: uuid.UUID) -> InputDevice: """ Returns the InputDevice. Parameters ---------- device_id: `UUID` Input device id Returns ------- context: InputDevice Input device Raises ------ InkModelException If the `InputDevice` for the id is not available. """ for dev in self.devices: if dev.id == device_id: return dev raise InkModelException('No input device with id:={}.'.format(device_id))
def get_sensor_context(self, ctx_id: uuid.UUID) ‑> SensorContext
-
Returns the
SensorContext
for the id.Parameters
ctx_id
:UUID</code>input context id
Returns
instance
:SensorContext
SensorContext
instance
Raises
InkModelException
- If the
SensorContext
for the id is not available
Expand source code
def get_sensor_context(self, ctx_id: uuid.UUID) -> SensorContext: """ Returns the `SensorContext` for the id. Parameters ---------- ctx_id: `UUID`input context id Returns -------- instance: `SensorContext` `SensorContext` instance Raises ------ InkModelException If the `SensorContext` for the id is not available """ for ctx in self.sensor_contexts: if ctx.id == ctx_id: return ctx raise InkModelException('No sensor context with id:={}.'.format(ctx_id))
def has_configuration(self) ‑> bool
-
Check if any configuration is available.
Returns
flag
:bool
- Flag if either ink input provide, input device, or sensor context are defined
Expand source code
def has_configuration(self) -> bool: """Check if any configuration is available. Returns ------- flag: bool Flag if either ink input provide, input device, or sensor context are defined """ return len(self.input_contexts) > 0 or len(self.sensor_contexts) > 0 or len(self.ink_input_providers) > 0 or \ len(self.devices) > 0 or len(self.environments)
class InputDevice (device_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None)
-
InputDevice
The class
InputDevice
represents the hardware device, on which the sensor data has been produced (touch enabled mobile device, touch capable monitor, digitizer, etc). InputDevice with properties.The properties can contain:
- Communication Protocol: USB, BTC, BLE, SPP, WIFI,
- Communication ID: VID, PID; MAC; UID; COM_PORT,
- Device Name: Wacom Intuos Pro M, Apple iPad 8, Samsung GalaxyTab 10,
- PenID,
- Serial number,
- Firmware Version (MCU),
- Secondary Firmware Version (BT, WIFI) - different modules provides version for itself,
- Orientation: PORTRAIT, LANDSCAPE, PORTRAIT_REVERSE, LANDSCAPE_REVERSE or 0, 90, 180, 270,
- Sensor size.
Parameters
device_id
:UUID
- Internal input device id
properties
:List[Tuple[str, str]]
- Properties of the input device
Examples
>>> from uim.model.inkinput.inputdata import InputDevice >>> # Input device is the sensor (pen tablet, screen, etc.) >>> input_device: InputDevice = InputDevice() >>> input_device.properties.append(("dev.id", "123454321")) >>> input_device.properties.append(("dev.manufacturer", "Wacom")) >>> input_device.properties.append(("dev.model", "Mobile Studio Pro")) >>> input_device.properties.append(("dev.cpu", "Intel")) >>> input_device.properties.append(("dev.graphics.display", "Dell 1920x1080 32bit")) >>> input_device.properties.append(("dev.graphics.adapter", "NVidia"))
Expand source code
class InputDevice(HashIdentifier): """ InputDevice =========== The class `InputDevice` represents the hardware device, on which the sensor data has been produced (touch enabled mobile device, touch capable monitor, digitizer, etc). InputDevice with properties. The properties can contain: - Communication Protocol: USB, BTC, BLE, SPP, WIFI, - Communication ID: VID, PID; MAC; UID; COM_PORT, - Device Name: Wacom Intuos Pro M, Apple iPad 8, Samsung GalaxyTab 10, - PenID, - Serial number, - Firmware Version (MCU), - Secondary Firmware Version (BT, WIFI) - different modules provides version for itself, - Orientation: PORTRAIT, LANDSCAPE, PORTRAIT_REVERSE, LANDSCAPE_REVERSE or 0, 90, 180, 270, - Sensor size. Parameters ---------- device_id: `UUID` Internal input device id properties: List[Tuple[str, str]] Properties of the input device Examples -------- >>> from uim.model.inkinput.inputdata import InputDevice >>> # Input device is the sensor (pen tablet, screen, etc.) >>> input_device: InputDevice = InputDevice() >>> input_device.properties.append(("dev.id", "123454321")) >>> input_device.properties.append(("dev.manufacturer", "Wacom")) >>> input_device.properties.append(("dev.model", "Mobile Studio Pro")) >>> input_device.properties.append(("dev.cpu", "Intel")) >>> input_device.properties.append(("dev.graphics.display", "Dell 1920x1080 32bit")) >>> input_device.properties.append(("dev.graphics.adapter", "NVidia")) """ def __init__(self, device_id: uuid.UUID = None, properties: List[Tuple[str, str]] = None): super().__init__(device_id) self.__properties: List[Tuple[str, str]] = properties or [] @property def properties(self) -> List[Tuple[str, str]]: """Properties of the InputDevice. (` List[Tuple[str, str]]`, read-only)""" return self.__properties def add_property(self, key: str, value): """Adding property. Parameters ---------- key: str Name of the property value: str Value of the property """ self.__properties.append((key, value)) def __tokenize__(self): return ['InputDevice', self.properties] def __repr__(self): return '<InputDevice : [id:={}, num properties:={}>'.format(self.id, self.properties)
Ancestors
- 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
SensorChannel
represents a generic sensor channel definition, which has the following properties:- type - URI uniquely identifying the type of the sensor channel
- metric - The type of the data to the SI metric system
- resolution - A factor multiplication value (power of 10) used to convert the stored data values to the specified SI metric
- min, max - Lower and upper bounds of the reported values range
- precision - The precision of the sensor when reporting floating-point values (defined as an int value, used as a power of 10 during the serialization/deserialization phase)
Parameters
channel_id
:UUID
- Sensor channel descriptor. If no channel_id is set the MD5 hashing is generating the id
- channel_type:
InkSensorType
- Indicates metric used in calculating the resolution for the data item.
metric
:InkSensorMetricType
- Indicates metric used in calculating the resolution for the data item.
resolution
:float
- Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the physical unit is in m and input data units. Resolution is 100000, then the value 150 would be 0.0015 m.
channel_min
:float
- Minimal value of the channel
channel_max
:float
- Maximal value of the channel
precision
:int
- Precision of integer encoding, needed for encoded float values
index
:int
- Index of the channel
name
:str
- Name of the channel
data_type
:DataType
- Type of data within the channel
ink_input_provider_id
:UUID
- Reference to the ink input provider
input_device_id
:UUID
- Reference to the ink input device
Examples
>>> from uim.model.inkinput.inputdata import SensorChannel, InkSensorType >>> # Create a group of sensor channels >>> sensor_channels_tablet: list = [ >>> SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0) >>> ]
Expand source code
class SensorChannel(HashIdentifier): """ SensorChannel ============= The `SensorChannel` represents a generic sensor channel definition, which has the following properties: - **type** - URI uniquely identifying the type of the sensor channel - **metric** - The type of the data to the SI metric system - **resolution** - A factor multiplication value (power of 10) used to convert the stored data values to the specified SI metric - **min, max** - Lower and upper bounds of the reported values range - **precision** - The precision of the sensor when reporting floating-point values (defined as an int value, used as a power of 10 during the serialization/deserialization phase) Parameters ---------- channel_id: `UUID` Sensor channel descriptor. If no channel_id is set the MD5 hashing is generating the id channel_type:`InkSensorType` Indicates metric used in calculating the resolution for the data item. metric: `InkSensorMetricType` Indicates metric used in calculating the resolution for the data item. resolution: `float` Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the physical unit is in m and input data units. Resolution is 100000, then the value 150 would be 0.0015 m. channel_min: `float` Minimal value of the channel channel_max: `float` Maximal value of the channel precision: `int` Precision of integer encoding, needed for encoded float values index: `int` Index of the channel name: `str` Name of the channel data_type: `DataType` Type of data within the channel ink_input_provider_id: `UUID` Reference to the ink input provider input_device_id: `UUID` Reference to the ink input device Examples -------- >>> from uim.model.inkinput.inputdata import SensorChannel, InkSensorType >>> # Create a group of sensor channels >>> sensor_channels_tablet: list = [ >>> SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0) >>> ] """ def __init__(self, channel_id: uuid.UUID = None, channel_type: InkSensorType = None, metric: InkSensorMetricType = None, resolution: float = 1., channel_min: float = 0., channel_max: float = 0., precision: int = 2, index: int = 0, name: str = None, data_type: DataType = DataType.FLOAT32, ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None): super().__init__(channel_id) self.__type: InkSensorType = channel_type self.__metric: InkSensorMetricType = metric self.__resolution: float = float(resolution) self.__min: float = float(channel_min) self.__max: float = float(channel_max) self.__precision: int = precision self.__index: int = index self.__name: str = name self.__data_type: DataType = data_type self.__ink_input_provider: uuid.UUID = ink_input_provider_id self.__input_device_id: uuid.UUID = input_device_id def __tokenize__(self) -> list: return ["SensorChannel", self.__ink_input_provider, self.__input_device_id, TOKEN_MAP[self.type], TOKEN_MAP[self.metric], self.resolution, self.min, self.max, self.precision] @property def ink_input_provider(self) -> uuid.UUID: """Reference to the `InkInputProvider` of the channel. (`UUID`)""" return self.__ink_input_provider @ink_input_provider.setter def ink_input_provider(self, value: uuid.UUID): self.__ink_input_provider = value @property def input_device_id(self) -> uuid.UUID: """Reference to the `InputDevice` of the channel. (`UUID`)""" return self.__input_device_id @input_device_id.setter def input_device_id(self, value: uuid.UUID): self.__input_device_id = value @property def type(self) -> InkSensorType: """Type of the sensor channel.(`InkSensorType`, read-only) """ return self.__type @property def metric(self) -> InkSensorMetricType: """Metric of the sensor channel. (`InkSensorMetricType`)""" return self.__metric @property def resolution(self) -> float: """Resolution. Is a decimal number giving the number of data item increments. Per physical unit., e.g. if the physical unit is in m and input data units. (`float`, read-only)""" return self.__resolution @property def min(self) -> float: """Minimal value of the channel. (`float`, read-only)""" return self.__min @property def max(self) -> float: """Maximum value of the channel. (`float`, read-only)""" return self.__max @property def precision(self) -> int: """Precision of integer encoding, needed for encoded float values. (`int`, read-only)""" return self.__precision @property def index(self) -> int: """Index within a list of values, e.g. used in InkML encoding. (`int`, read-only)""" return self.__index @property def name(self) -> str: """Name of the channel. (`str`, read-only)""" return self.__name @property def data_type(self) -> DataType: """ Data type encoding. (`DataType`, read-only)""" return self.__data_type def __repr__(self): return '<SensorChannel: [id:={}, type:={}, metric:={}, resolution:={}, min:={}, max:={}, ' \ 'precision:={}, index:={}, name:={}>'.format(self.id.hex, self.__type, self.__metric, self.__resolution, self.__min, self.__max, self.__precision, self.__index, self.__name)
Ancestors
- 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
InkInputProvider
of the channel. (UUID
)Expand source code
@property def ink_input_provider(self) -> uuid.UUID: """Reference to the `InkInputProvider` of the channel. (`UUID`)""" return self.__ink_input_provider
var input_device_id : uuid.UUID
-
Reference to the
InputDevice
of the channel. (UUID
)Expand source code
@property def input_device_id(self) -> uuid.UUID: """Reference to the `InputDevice` of the channel. (`UUID`)""" return self.__input_device_id
var max : float
-
Maximum value of the channel. (
float
, read-only)Expand source code
@property def max(self) -> float: """Maximum value of the channel. (`float`, read-only)""" return self.__max
var 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
SensorChannelsContext
is defined as an unique combination of:- An <code><a title="uim.model.inkinput.inputdata.InkInputProvider" href="#uim.model.inkinput.inputdata.InkInputProvider">InkInputProvider</a></code> instance - An <code><a title="uim.model.inkinput.inputdata.InputDevice" href="#uim.model.inkinput.inputdata.InputDevice">InputDevice</a></code> instance and - A list of sensor channel definitions (by holding a collection of <code><a title="uim.model.inkinput.inputdata.SensorChannel" href="#uim.model.inkinput.inputdata.SensorChannel">SensorChannel</a></code> instances)
Parameters
sid
:str
- Group that provides X and Y channels is the one that is referred from StrokeRelation and it's id could be always XY.
channels
:List[SensorChannel]
- A list of sensor channel descriptors.
sampling_rate_hint
:int
- Optional hint for the intended sampling rate of the sensor.[Optional].
latency
:int
- Latency measure in milliseconds [Optional].
ink_input_provider_id
:str
- Reference to the 'InkInputProvider`.
input_device_id
:str
- Reference to the
InputDevice
.
Notes
Once a SensorChannelsContext instance is added to the InputContext repository, it is considered immutable. The SensorChannelsContext identifier is unique in the scope of the InkModel and is auto-generated based on the MD5-hash based Unique Identifier Generation Algorithm using tag "SensorChannelsContext" and the following components:
- Identifier of the InkInputProvider instance - Identifier of the InputDevice instance - List of the identifiers of the SensorChannel instances contained within the current SensorChannelsContext
Examples
>>> from uim.model.inkinput.inputdata import InkInputProvider, InkInputType, SensorChannel, >>> InkSensorType, InkSensorMetricType, SensorChannelsContext, SensorContext >>> # Ink input provider can be pen, mouse or touch. >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE) >>> provider.properties.append(("pen.id", "1234567")) >>> >>> # We can create an additional input device, for example one providing pressure via Bluetooth >>> input_device: InputDevice = InputDevice() >>> input_device.properties.append(("dev.id", "345456567")) >>> input_device.properties.append(("dev.manufacturer", "Apple")) >>> >>> # Create a group of sensor channels >>> sensor_channels_tablet: list = [ >>> SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0) >>> ] >>> >>> scc_tablet: SensorChannelsContext = SensorChannelsContext(channels=sensor_channels_tablet, >>> ink_input_provider_id=provider.id, >>> input_device_id=input_device.id)
Expand source code
class SensorChannelsContext(HashIdentifier): """ SensorChannelsContext ===================== The class `SensorChannelsContext` is defined as an unique combination of: - An `InkInputProvider` instance - An `InputDevice` instance and - A list of sensor channel definitions (by holding a collection of `SensorChannel` instances) Parameters ---------- sid: `str` Group that provides X and Y channels is the one that is referred from StrokeRelation and it's id could be always XY. channels: `List[SensorChannel]` A list of sensor channel descriptors. sampling_rate_hint: `int` Optional hint for the intended sampling rate of the sensor.[Optional]. latency: `int` Latency measure in milliseconds [Optional]. ink_input_provider_id: `str` Reference to the 'InkInputProvider`. input_device_id: `str` Reference to the `InputDevice`. Notes ------ Once a SensorChannelsContext instance is added to the InputContext repository, it is considered immutable. The SensorChannelsContext identifier is unique in the scope of the InkModel and is auto-generated based on the MD5-hash based Unique Identifier Generation Algorithm using tag "SensorChannelsContext" and the following components: - Identifier of the InkInputProvider instance - Identifier of the InputDevice instance - List of the identifiers of the SensorChannel instances contained within the current SensorChannelsContext Examples -------- >>> from uim.model.inkinput.inputdata import InkInputProvider, InkInputType, SensorChannel, \ >>> InkSensorType, InkSensorMetricType, SensorChannelsContext, SensorContext >>> # Ink input provider can be pen, mouse or touch. >>> provider: InkInputProvider = InkInputProvider(input_type=InkInputType.MOUSE) >>> provider.properties.append(("pen.id", "1234567")) >>> >>> # We can create an additional input device, for example one providing pressure via Bluetooth >>> input_device: InputDevice = InputDevice() >>> input_device.properties.append(("dev.id", "345456567")) >>> input_device.properties.append(("dev.manufacturer", "Apple")) >>> >>> # Create a group of sensor channels >>> sensor_channels_tablet: list = [ >>> SensorChannel(channel_type=InkSensorType.TIMESTAMP, metric=InkSensorMetricType.TIME, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.X, metric=InkSensorMetricType.LENGTH, resolution=1.0), >>> SensorChannel(channel_type=InkSensorType.Y, metric=InkSensorMetricType.LENGTH, resolution=1.0) >>> ] >>> >>> scc_tablet: SensorChannelsContext = SensorChannelsContext(channels=sensor_channels_tablet, >>> ink_input_provider_id=provider.id, >>> input_device_id=input_device.id) """ def __init__(self, sid: uuid.UUID = None, channels: List[SensorChannel] = None, sampling_rate_hint: int = None, latency: int = None, ink_input_provider_id: uuid.UUID = None, input_device_id: uuid.UUID = None): super().__init__(sid) self.__channels: List[SensorChannel] = channels or [] self.__sampling_rate_hint: int = sampling_rate_hint self.__latency: int = latency self.__ink_input_provider_id: uuid.UUID = ink_input_provider_id self.__input_device_id: uuid.UUID = input_device_id # Set bind channels to input provider and input device for c in self.__channels: c.ink_input_provider = ink_input_provider_id c.input_device_id = input_device_id def __tokenize__(self) -> list: token: list = ["SensorChannelsContext"] token.extend([c.id for c in self.channels]) token.append(self.sampling_rate) token.append(self.latency) token.append(self.input_provider_id) token.append(self.input_device_id) return token @property def channels(self) -> List[SensorChannel]: """Array of the `SensorChannel`s associated with the context. (`List[SensorChannel]`, read-only) """ return self.__channels @property def sampling_rate(self) -> int: """Hint for sampling rate valid for all channels. (`int`, read-only)""" return self.__sampling_rate_hint @property def latency(self) -> int: """Gets the latency measurement in milliseconds. (`int`, read-only)""" return self.__latency @property def input_provider_id(self) -> uuid.UUID: """Reference id to the ink `InputProvider` that produces the ink. (`UUID`, read-only)""" return self.__ink_input_provider_id @property def input_device_id(self) -> uuid.UUID: """Reference to `InkInputDevice`. (`UUID`, read-only)""" return self.__input_device_id def add_sensor_channel(self, channel: SensorChannel): """ Adding a channel. Parameters ---------- channel: `SensorChannel` sensor channel """ self.__channels.append(channel) def has_channel_type(self, channel_type: InkSensorType): """ Checks if channel types is available. Parameters ---------- channel_type: `InkSensorType` sensor type Returns ------- flag: `boolean` True if available, False if not """ for c in self.channels: if c.type == channel_type: return True return False def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel: """Returns instance of Channel. Parameters ---------- channel_type: `InkSensorType` type of the channel Returns ------- instance: SensorChannel Instance of the `SensorChannel` for the `InkSensorType` Raises ------ InkModelException If the `SensorChannel` is not available. """ for c in self.__channels: if c.type == channel_type: return c raise InkModelException(f'No channel available for the type: {channel_type}') def __repr__(self): return '<SensorChannelsContext: [id:={}, sampling rate hint:={}, latency:={}, input data provider id:={}, ' \ 'input data id:={}>'.format(self.id_h_form, self.sampling_rate, self.latency, UUIDIdentifier.uimid_to_h_form(self.input_provider_id), UUIDIdentifier.uimid_to_h_form(self.input_device_id))
Ancestors
- HashIdentifier
- Identifier
- abc.ABC
Class variables
var SEPARATOR : str
Instance variables
var channels : List[SensorChannel]
-
Array of the
SensorChannel
s associated with the context. (List[SensorChannel]
, read-only)Expand source code
@property def channels(self) -> List[SensorChannel]: """Array of the `SensorChannel`s associated with the context. (`List[SensorChannel]`, read-only) """ return self.__channels
var input_device_id : uuid.UUID
-
Reference to
InkInputDevice
. (UUID
, read-only)Expand source code
@property def input_device_id(self) -> uuid.UUID: """Reference to `InkInputDevice`. (`UUID`, read-only)""" return self.__input_device_id
var input_provider_id : uuid.UUID
-
Reference id to the ink
InputProvider
that produces the ink. (UUID
, read-only)Expand source code
@property def input_provider_id(self) -> uuid.UUID: """Reference id to the ink `InputProvider` that produces the ink. (`UUID`, read-only)""" return self.__ink_input_provider_id
var latency : int
-
Gets the latency measurement in milliseconds. (
int
, read-only)Expand source code
@property def latency(self) -> int: """Gets the latency measurement in milliseconds. (`int`, read-only)""" return self.__latency
var sampling_rate : int
-
Hint for sampling rate valid for all channels. (
int
, read-only)Expand source code
@property def sampling_rate(self) -> int: """Hint for sampling rate valid for all channels. (`int`, read-only)""" return self.__sampling_rate_hint
Methods
def add_sensor_channel(self, channel: SensorChannel)
-
Expand source code
def add_sensor_channel(self, channel: SensorChannel): """ Adding a channel. Parameters ---------- channel: `SensorChannel` sensor channel """ self.__channels.append(channel)
def get_channel_by_type(self, channel_type: InkSensorType) ‑> SensorChannel
-
Returns instance of Channel.
Parameters
channel_type
:InkSensorType
- type of the channel
Returns
instance
:SensorChannel
- Instance of the
SensorChannel
for theInkSensorType
Raises
InkModelException
- If the
SensorChannel
is not available.
Expand source code
def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel: """Returns instance of Channel. Parameters ---------- channel_type: `InkSensorType` type of the channel Returns ------- instance: SensorChannel Instance of the `SensorChannel` for the `InkSensorType` Raises ------ InkModelException If the `SensorChannel` is not available. """ for c in self.__channels: if c.type == channel_type: return c raise InkModelException(f'No channel available for the type: {channel_type}')
def has_channel_type(self, channel_type: InkSensorType)
-
Checks if channel types is available.
Parameters
channel_type
:InkSensorType
- sensor type
Returns
flag
:boolean
- True if available, False if not
Expand source code
def has_channel_type(self, channel_type: InkSensorType): """ Checks if channel types is available. Parameters ---------- channel_type: `InkSensorType` sensor type Returns ------- flag: `boolean` True if available, False if not """ for c in self.channels: if c.type == channel_type: return True return False
Inherited members
class SensorContext (context_id: uuid.UUID = None, sensor_channels_contexts: List[SensorChannelsContext] = None)
-
SensorContext
Each input data has a SensorContext describing the available sensors of a input data. One file can contains Ink data from two input data of the same type with a shared context.
Parameters
context_id
:UUID
- Id of the context
sensor_channels_contexts
:List[SensorChannelsContext]
- List of
SensorChannelsContext
Constructor.
Expand source code
class SensorContext(HashIdentifier): """ SensorContext ============= Each input data has a SensorContext describing the available sensors of a input data. One file can contains Ink data from two input data of the same type with a shared context. Parameters ----------- context_id: UUID Id of the context sensor_channels_contexts: `List[SensorChannelsContext]` List of `SensorChannelsContext` """ def __init__(self, context_id: uuid.UUID = None, sensor_channels_contexts: List[SensorChannelsContext] = None): """Constructor. """ super().__init__(context_id) self.__sensor_channels_contexts: List[SensorChannelsContext] = sensor_channels_contexts or [] def __tokenize__(self) -> list: token: list = ["SensorContext"] token.extend([c.id for c in self.sensor_channels_contexts]) return token @property def sensor_channels_contexts(self) -> List[SensorChannelsContext]: """ List of channel contexts. (`List[SensorChannelsContext]`, read-only)""" return self.__sensor_channels_contexts def add_sensor_channels_context(self, channel_ctx: SensorChannelsContext): """Adding a sensor. Parameters ---------- channel_ctx: `SensorChannelsContext` Adding a channel """ self.__sensor_channels_contexts.append(channel_ctx) def has_channel_type(self, channel_type: InkSensorType) -> bool: """ Check if the SensorContext has a channel with type. Parameters ---------- channel_type: `InkSensorType` type of channel Returns ------- flag: `bool` True if channel exists, False if not """ for c in self.__sensor_channels_contexts: if c.has_channel_type(channel_type): return True return False def get_channel_by_id(self, channel_id: uuid.UUID) -> SensorChannel: """ Returns the channel for a specific id. Parameters ---------- channel_id: bytes - id of channel Returns ------- instance: `SensorChannel` Instance of `SensorChannel` Raises ------ InkModelException: Raised if no channel for channel id. """ for cs in self.sensor_channels_contexts: for c in cs.channels: if c.id == channel_id: return c raise InkModelException('No channel with channel id: {}.'.format(channel_id)) def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel: """ Returns the channel for a specific `InkSensorType`. Parameters ---------- channel_type: `InkSensorType` Channel type Returns ------- instance: `SensorChannel` Instance of channel Raises ------ InkModelException Raised if no `SensorChannel` for the id is not available. """ for c in self.__sensor_channels_contexts: if c.has_channel_type(channel_type): return c.get_channel_by_type(channel_type) raise InkModelException('No channel with channel type: {}.'.format(channel_type)) def __repr__(self): return '<SensorContext: [context_id:={}, sensor_channels_contexts:={}]>'.format(self.id, self.sensor_channels_contexts)
Ancestors
- 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
SensorChannel
for the id is not available.
Expand source code
def get_channel_by_type(self, channel_type: InkSensorType) -> SensorChannel: """ Returns the channel for a specific `InkSensorType`. Parameters ---------- channel_type: `InkSensorType` Channel type Returns ------- instance: `SensorChannel` Instance of channel Raises ------ InkModelException Raised if no `SensorChannel` for the id is not available. """ for c in self.__sensor_channels_contexts: if c.has_channel_type(channel_type): return c.get_channel_by_type(channel_type) raise InkModelException('No channel with channel type: {}.'.format(channel_type))
def has_channel_type(self, channel_type: InkSensorType) ‑> bool
-
Check if the SensorContext has a channel with type.
Parameters
channel_type
:InkSensorType
- type of channel
Returns
flag
:bool
- True if channel exists, False if not
Expand source code
def has_channel_type(self, channel_type: InkSensorType) -> bool: """ Check if the SensorContext has a channel with type. Parameters ---------- channel_type: `InkSensorType` type of channel Returns ------- flag: `bool` True if channel exists, False if not """ for c in self.__sensor_channels_contexts: if c.has_channel_type(channel_type): return True return False
Inherited members
class Unit (value, names=None, *, module=None, qualname=None, type=None, start=1)
-
An enumeration.
Expand source code
class Unit(Enum): # Lengths units UNDEFINED = 0 """Undefined unit""" M = 10 """meters""" CM = 11 """centimeters""" MM = 12 """millimeters""" IN = 13 """inches""" PT = 14 """points (1pt = 1/72 in)""" PC = 15 """picas (1pc = 1/22 pt)""" DIP = 16 """device independent pixel (1DIP = 1/96 in)""" # Time units S = 20 """seconds""" MS = 21 """milliseconds""" NS = 22 """nanoseconds""" # Force units N = 30 """Newtons""" # Angle RAD = 42 """radians""" DEG = 41 """degrees""" # General PERCENTAGE = 50 """percentage, expressed as a fraction (1.0 = 100%) relative to max-min""" LOGICAL_VALUE = 60 """logical value"""
Ancestors
- enum.Enum
Class variables
var CM
-
centimeters
var DEG
-
degrees
var DIP
-
device independent pixel (1DIP = 1/96 in)
var IN
-
inches
var LOGICAL_VALUE
-
logical value
var M
-
meters
var MM
-
millimeters
var MS
-
milliseconds
var N
-
Newtons
var NS
-
nanoseconds
var PC
-
picas (1pc = 1/22 pt)
var PERCENTAGE
-
percentage, expressed as a fraction (1.0 = 100%) relative to max-min
var PT
-
points (1pt = 1/72 in)
var RAD
-
radians
var S
-
seconds
var UNDEFINED
-
Undefined unit