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 queriedconst warmedIntegratorDS = leakyIntegrator (dataSource , 4, 20)
lineSegments
The lineSegments
operator turns a Queryable's events into a position, then creates LineSegment
s 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 LineSegment
s 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 })