Signals
Signals form the crux of data transfer in the openDAQ™ SDK. They, alongside Input Ports and Connections, form data paths through which data is transferred in the form of Packets. Signals are part of Devices, Function blocks, and Channels, all of which define a set of output Signals that contain the data they produce.
For example, a Statistics Function block might output a signal that averages the samples of an input Signal. A physical data acquisition device will output Signals that contain analog input data. A Function block that performs a Fourier analysis will output a signal containing vector samples that represent the frequency spectrum of the data.
As shown in the examples below, Signals are designed to allow for flexible descriptions of different kinds of data of different dimensions (scalar, vector, matrix, or higher dimensionality) and various data types (integers, strings, floating point numbers,…). In this article we provide an overview of the structure of a Signal, and what sort of data varieties openDAQ™ signals can describe.
Domain Signals
A Signal is often referred to as either the "Value" Signal or the "Domain" Signal. In actuality, what this refers to is that any Signal can have a reference to another Signal that carries Domain data that the signal is supposed to be read with.
Domain data represents points in measurement that can be used to determine the relative distance between Value Signal samples, or their absolute position within the chosen physical domain. In openDAQ™ most often the Time domain is used, where the Time Domain Signal carries timestamps that are relative to an Origin (most often the UNIX Epoch).
Other examples of possible domains include:
-
Number of rotations,
-
Distance,
-
Angle,
-
Automotive track lap count…
When a signal sends data via Packets, they usually contain a reference to the Domain Signal’s corresponding Packet that carries the Domain data required for analysis. As such, both the Value and corresponding Domain Signal must have the same sampling rate, and their Packets should be of equal size.
Properties
As with other Components, a Signal has access to the Property Object features where it can define a set of custom Properties with metadata and values. These Properties allow for user-customizable features to be added to Signals such as a custom user-defined name, or description.
By default, a signal has a "Name" pre-defined Property that can be configured by users. Doing so will send a notification to all Input Ports connected to the Signal, notifying them of the change.
Other metadata of a Signal is accessible through its Data Descriptor
Data Descriptor
The Data Descriptor defines the sort of data that is sent by Signals. It allows anyone receiving the data to interpret the raw buffers and make sense of their contents. Descriptors are immutable objects of which individual fields (eg. SampleType) cannot be modified. To change the Descriptor of a Signal, the entire Descriptor object must be replaced. Changing the Descriptor of a Signal triggers an Event Packet to be sent to all connected Input Ports.
The following fields are part of a Data Descriptor, with some containing further explanations in later sections.
Name |
A descriptive name of the data being described. For example, when the values describe the amplitude of spectrum data, the name would be Amplitude. |
Dimensions |
A list of Signal Dimension. A sample descriptor can have 0 or more dimensions. A signal with 1 dimension has vector data. A signal with 2 dimensions has matrix data, while a signal with 0 has a single value for each sample. |
Sample Type |
An enum value that specifies the underlying data type (eg. Float64, Int32, String,…) |
Unit |
The Unit of the data in the Signal’s Packets. |
Value Range |
The Value Range of the data in a Signal’s Packets defines the lowest and highest expected values. The range is not enforced by openDAQ™. |
Data Rule |
The Data Rule that defines how a Signal value is calculated from an implicit initialization value when the rule type is not Explicit. |
Origin |
Defines the starting point of the Signal. If set, all values of the Signal are relative to the Origin. |
Tick Resolution |
Used to scale Signal ticks into their physical unit. For example, a Tick Resolution of 1/1000 with the unit being "seconds" states that a value of 1 correlates to 1 millisecond. |
Post Scaling |
Defines a scaling transformation, which should be applied to data carried by the Signal’s Packets when read. If Post Scaling is used, the Rule must be Explicit, and Tick Resolution and Origin must not be configured. The Sample Type must match the Output Data Type of the Post Scaling. |
Struct Fields |
A list of Data Descriptors. The descriptor list is used to define complex data samples. When defined, the sample buffer is laid out so that the data described by the first Data Descriptor is at the start, followed by the data described by the second, and so on. If the list is not empty, all Descriptor parameters except for Name and Dimensions should not be configured. |
Metadata |
A dictionary of key-value pairs. The metadata dictionary is used to add any additional information required to correctly interpret the data. This information is not interpreted by openDAQ core. |
Data Rule
The Data Rule can be defined for data of a signal to be calculated implicitly. When
the Rule Type is configured to a type other than Explicit
, the data buffers of
Packets will not contain any data.
To obtain data from Packets of Signals with an Implicit
Data Rule, the values are
calculated depending on the Rule type. Currently, two rules are available in openDAQ:
-
Linear Rule: The Rule parameters include a
delta
andstart
numbers. The values are calculated according to the following equation:PacketOffset + SampleIndex * delta + start
, where thePacketOffset
is available on the Packet carrying the data and theSampleIndex
represents the index of the data entry being calculated within a given packet. -
Constant Rule: All values of the signal are equal to the
constant
defined in the packet.
Dimensions
The list of Dimensions within a Data Descriptor defines whether the data in the signal is a Scalar, Vector, Matrix, or a higher-dimension structure. The number of Dimension objects in the list defines the data rank:
-
0 Dimensions = Scalar data
-
1 Dimension = Vector data
-
2 Dimensions = Matrix data
-
n Dimensions = n rank data
A singular Dimension is defined via its Size and Rule. The Size defines the number of samples per Dimension. For example, data samples of a Signal with 1 Dimension of size 1024 would have 1024 values per sample (Vector). A Signal with 2 Dimensions of sizes 16 and 32 would have 16 * 32 = 512 values per sample (Matrix).
The Dimension Rule defines the Labels of each given Dimension. The Labels are used to interpret the meaning of each value within higher-rank data. For example, a frequency spectrum sample of 1024 values could span the frequency range from 0 Hz to 4096 Hz. The labels allow us to interpret the physical meaning of a value within a sample. For example, the 10th value of a sample within the spectrum Signal described above would correspond to the amplitude at the 40Hz frequency band.
To define the Labels, the following Rule types are available:
Linear |
The Rule parameters contain a |
Logarithmic |
The Rule parameters contain a |
List |
The Rule parameters contain a |
Post Scaling
Post Scaling allows for a Rule to be defined as to how Signal data should be scaled to the appropriate physical Unit as defined by the Data Descriptor. When Post Scaling is configured, the Packet buffers of a Signal will contain raw data that should be scaled by anyone reading the data by applying the Post Scaling Rule.
When the Post Scalign is configured, the Origin and Tick Resolution cannot be part of the Data Descriptor, and the Data Rule must be "Explicit". |
Post Scaling defines an input and output Sample Type, where the input defines the raw Sample Type of data in Packet buffers, while the output type should match the Data Descriptor’s Sample Type, and defines the type into which raw data is scaled by applying the Rule.
As the input and output Sample Types can be different, Post Scaling allows Devices
to reduce bandwidth usage by sending data in lower bit-count types (eg. Int32
) that
is then scaled to different data types with higher bit-count (eg. double
) by clients.
Currently, openDAQ™ provides only the Linear Post Scaling rule:
Linear Post Scaling |
The parameters contain a |
Origin and Tick Resolution
The Origin and Tick Resolution allow for accurate definitions of absolute time (domain) values. The origin defines the starting point of all data within a Signal. All data sent within its packets is relative to the Origin value. As such the absolute value of the data is calculated as Origin + DataValue. A common Origin is the UNIX Epoch of "1970-00-00T00:00:00Z" specified in the format of the ISO 8601 standard.
The Tick Resolution represents a ratio used to scale Signal data (ticks) into their Physical unit. It allows us to circumvent the loss of accuracy when using floating-point numbers to represent fractions of domain values (eg. fractions of a second) by presenting data in the form of ticks that are scaled when read.
For example, a Signal with the Unit set to "seconds", with a Tick Resolution of 1/1000 states that a Tick value of 1 correlates to 1 millisecond.
Struct data
Data Descriptors allow for complex structures of data to be defined. This can be achieved through the usage of the Struct Fields list component. It allows for the nesting of Data Descriptors. When the Struct Fields list is filled, Packet buffers are constructed in the following manner: the data described by the first Data Descriptor is at the start, followed by the data described by the second, and so on.
When configuring a Data Descriptor with Struct Fields, the Name must be configured,
and additionally, only the Dimensions can be configured. Dimensions function the same way as with normal
Signal data, where each Sample will contain n structs, depending on the Dimension sizes.
|