Turnkey Transformers

instantaneous-derivative

Computes the first-derivative of the input datasource.

Relies on the DataSource's time values being accurate to the signal's properties, as the deltaTime is calculated internally. Otherwise, irregular packet arrival timing may cause artifacts.

import { instantaneousDerivative } from '@electricui/dataflow'
 
const rate = instantaneousDerivative(dataSource)

integral

The integral operator calculates the trapazoidal area under the curve.

import { useDataTransformer } from '@electricui/timeseries-react'
import { integral } from '@electricui/dataflow'
 
const dataSource = useMessageDataSource<number>('fuelUsage')
 
const dataTransformer = useDataTransformer(() => {
const area = integral(dataSource)
 
return area
})

leaky-integrator

An implementation of the common first-order low-pass filter commonly called a leaky-integrator or an exponentially weighted moving average filter (EWMA).

Each iteration is described mathematically as:

(newValue - previousValue) / smoothingFactor + lastValue

A datasource (with optional accessor) and smoothingFactor number are required arguments.

Factor of 0 represents the XXX signal, where 1 is the YYY signal.

import { leakyIntegrator } from '@electricui/dataflow'
 
const leakyIntegratorDs = leakyIntegrator(dataSource, 4)

Because the filter requires samples to 'start up' an optional prefetch argument accepts a number duration in milliseconds which mutates the query using a prepare step.

// 20ms additional data is queried
const warmedIntegratorDS = leakyIntegrator(dataSource, 4, 20)

lineSegments

The lineSegments operator turns a Queryable's events into a position, then creates LineSegments between them over time.

The first argument is the positionAccessor. An {x: number, y: number} point or null must be returned. If a null is returned, that point is skipped, causing a continuity break in the line. By default this is {x: time, y: data}, allowing simple signals to be plugged in with no argument.

The second argument is an optional tagger, given the previous and current data, the resulting LineSegment can be tagged with additional information.

The example below produces LineSegments from an XY data source, then tags it with additional information from the latest event. It then feeds it into a closestPointOnLineSegment and finds the closest line segment to the mouse.

import { useDataTransformer } from '@electricui/timeseries-react'
import { useMouseSignal, MouseData } from '@electricui/components-desktop-charts'
import { lineSegments, closestPointOnLineSegment } from '@electricui/dataflow'
 
const dataSource = useMessageDataSource<{x: number, y: number, voltage: number}>('samples')
 
const [mouseSignal, captureRef] = useMouseSignal()
 
const dataTransformer = useDataTransformer(() => {
const segments = lineSegments(
dataSource,
// Extract the x and y coordinates from the source
(data, time, tags) => ({
x: data.x,
y: data.y
}),
// tag with the voltages
(dataPrev, dataCurr) => ({ voltageStart: dataPrev.voltage, voltageEnd: dataCurr.voltage })
)
 
const closest = closestPointOnLineSegment(segments, mouseSignal, {
// Return only the closest point
mapResult: (
data,
time,
tags,
lineSegment,
searchData,
searchTags,
searchPoint,
closestPoint,
distance
) => closestPoint,
// Tagged with the voltages (this passthrough is the default)
tagResult: (
data,
time,
tags,
lineSegment,
searchData,
searchTags,
searchPoint,
closestPoint,
distance
) => tags,
})
 
return closest
})