Search Operators
The search operators consume a Collection of Events and select a singular Event if possible, otherwise returning null
.
If a non-collection queryable is passed as the input, the operator implicitly wraps it with a window
operator, selecting the authoritative domain's window length of data.
Unary search operators
The unary search operators select an Event from a Collection based on static parameters.
first
The first
operator collects events and maintains the top-1 item as defined by an arbitrary order. By default the ordering is by time.
The example below finds the earliest event in the bounding box defined by the mouse.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { first , collectBoundingBox } from '@electricui/dataflow' const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const selected = collectBoundingBox (dataSource , mouseSignal , { positionAccessor : (data , time , tags ) => ({ x : data .x , y : data .y }), searchBoundingBoxAccessor : (data , time , tags ) => { if (data .hasDragged ) { return ({ xMin : data .dragXMin , xMax : data .dragXMax , yMin : data .dragYMin , yMax : data .dragYMax }) } return null }, }) const firstEvent = first (selected ) return firstEvent })
Alternatively, a top-N Collection can be maintained with the head
operator.
last
The last
operator collects events and maintains the bottom-1 item as defined by an arbitrary order. By default the ordering is by time.
It's usage is identical to the first
operator above.
Alternatively, a bottom-N Collection can be maintained with the tail
operator.
firstAndLast
The firstAndLast
operator collects events and maintains both the top-1 and bottom-1 items as defined by an arbitrary order. By default the ordering is by time. If either event cannot be found, the entire result is null
. If there is only one event, they will be presented as both first
and last
.
It's usage is identical to the first
and last
operators above, except the returned keyed by first
or last
.
The example below finds the first and events in the bounding box defined by the mouse.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { firstAndLast , collectBoundingBox } from '@electricui/dataflow' const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const selected = collectBoundingBox (dataSource , mouseSignal , { positionAccessor : (data , time , tags ) => ({ x : data .x , y : data .y }), searchBoundingBoxAccessor : (data , time , tags ) => { if (data .hasDragged ) { return ({ xMin : data .dragXMin , xMax : data .dragXMax , yMin : data .dragYMin , yMax : data .dragYMax }) } return null }, }) const firstEvent = firstAndLast (selected ) return firstEvent })
Alternatively, a bottom-N Collection can be maintained with the tail
operator.
Binary search operators
The binary search operators utilise an external source of data to drive the 'selection' of events.
closestTemporally
The closestTemporally
operator finds the closest Event to a target time.
The timeSourceAccessor
is used to define the search time.
The method
can be set to closest
(the default), before
or after
. The search is exclusive of the search time if set to before
or after
.
The resulting event can be remapped with the mapResult
and tagResult
methods.
The example below finds the closest event before the mouse x coordinate.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { closestTemporally } from '@electricui/dataflow' const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const closest = closestTemporally (dataSource , mouseSignal , { // The mouse x position is the time to search for timeSourceAccessor : (data , time , tags ) => data .x , // only search for Events 'before' the mouse position method : 'before', // map the result directly to the data, the default case mapResult : (data , time , tags , searchData , searchTags , searchTime ) => data }) return closest })
closestSpatially
The closestSpatially
operator finds the closest Event to a target time.
The positionAccessor
defines the position of the Queryable's Events. Returning a null
skips ingesting this Event.
The searchPositionAccessor
defines the search point. Pass chartAspectRatio
to modify the aspect ratio for perceptual distance adjustment. Mouse data sources contain this information so that the distance is in the pixel domain, rather than the data domain.
The predicate
can be used to exclude candidates from the search result.
The maxDistance
parameter can be used to limit the distance to search for.
The resulting event can be remapped with the mapResult
and tagResult
methods.
The example below finds the closest event to the mouse.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { closestSpatially } from '@electricui/dataflow' const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const closest = closestSpatially (dataSource , mouseSignal , { // Use the Event coordinates as the position positionAccessor : (data , time , tags ) => ({x : data .x , y : data .y }), // The mouse x position is the time to search for searchPositionAccessor : (data , time , tags ) => ({ x : data .x , y : data .y , chartAspectRatio : data .chartAspectRatio }), // only search within 250 data units of the mouse maxDistance : 250, // Throw away odd numbered voltages predicate : ( data , time , tags , position , searchData , searchTags , searchPoint , distance , ) => data .voltage % 2 === 0, // map the result directly to the data, the default case mapResult : (data , time , tags , searchData , searchTags , searchTime ) => data , }) return closest })
closestByValue
The closestByValue
operator finds the closest Event ordered by an arbitrary value to a search value.
The valueAccessor
defines the position of the Queryable's Events. Returning a null
skips ingesting this Event.
The searchValueAccessor
defines the search point. Returning a null
resets the search.
The order
method is used to totally order the Value. The distance
method is used to calculate the distance between a pair of values.
The method
can be set to closest
(the default), below
or above
. The search is exclusive of the search value if set to below
or above
.
The predicate
can be used to exclude candidates from the search result.
The resulting event can be remapped with the mapResult
and tagResult
methods.
The example below finds the event with the closest voltage to the mouse y
coordinate.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { closestByValue } from '@electricui/dataflow' const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const closest = closestByValue (dataSource , mouseSignal , { // Index the events by their voltage valueAccessor : (data , time , tags ) => data .voltage , // The mouse y position is the value to search for searchValueAccessor : (data , time , tags ) => data .y , // map the result directly to the data, the default case mapResult : (data , time , tags , value , searchData , searchTags , searchValue , distance ) => data , }) return closest })
closestPointOnLineSegment
The closestPointOnLineSegment
operator finds the closest point on an LineSegment
accessed from the indexed Queryable, to a point defined by the search queryable.
The lineSegmentAccessor
defines the LineSegment
from the Queryable's Events. Returning a null
skips ingesting this LineSegment
.
The searchPositionAccessor
defines the search point. Returning a null
resets the search.
The predicate
can be used to exclude candidates from the search result.
The maxDistance
parameter can be used to limit the distance to search for.
The resulting event can be remapped with the mapResult
and tagResult
methods.
The example below finds the closest interpolated point on the line segments generated by a number over time signal.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { closestPointOnLineSegment , lineSegments } from '@electricui/dataflow' const dataSource = useMessageDataSource <number>('signal') const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const segments = lineSegments (dataSource , (data , time , tags ) => ({x : time , y : data })) const closest = closestPointOnLineSegment (segments , mouseSignal , { // Index the lineSegments directly lineSegmentAccessor : (data , time , tags ) => data , // The mouse position can be used directly as it contains x, y, chartAspectRatio keys searchPositionAccessor : (data , time , tags ) => data , // search up to 250 units away maxDistance : 250, // Return only the closest point mapResult : ( data , time , tags , lineSegment , searchData , searchTags , searchPoint , closestPoint , distance ) => closestPoint , }) return closest })
If the data is made of 2D points, lineSegments
can also be used.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { closestPointOnLineSegment , mapWithPrevious , lineSegments } from '@electricui/dataflow' const dataSource = useMessageDataSource <{x : number, y : number, voltage : number}>('samples')const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const segments = lineSegments (dataSource , (data , time , tags ) => ({ x : data .x , y : data .y })) const closest = closestPointOnLineSegment (segments , mouseSignal , { // Index the lineSegments directly lineSegmentAccessor : (data , time , tags ) => data , // The mouse position can be used directly as it contains x, y, chartAspectRatio keys searchPositionAccessor : (data , time , tags ) => data , // Return only the closest point mapResult : ( data , time , tags , lineSegment , searchData , searchTags , searchPoint , closestPoint , distance ) => closestPoint , }) return closest })
closestLineSegmentIntersection
The closestLineSegmentIntersection
operator finds the intersection of a LineSegment
accessed from the indexed Queryable, to a LineSegment
provided by the search queryable, closest to a point provided by the search queryable.
The lineSegmentAccessor
defines the LineSegment
from the Queryable's Events. Returning a null
skips ingesting this LineSegment
.
The searchLineSegmentAccessor
defines the search LineSegment
. Returning a null
resets the search.
The searchPositionAccessor
defines the search point. Returning a null
resets the search.
The predicate
can be used to exclude candidates from the search result.
The maxDistance
parameter can be used to limit the distance to search for.
The resulting event can be remapped with the mapResult
and tagResult
methods.
The example below finds the closest interpolated point on the line segments generated by a number over time signal, searching horizontally left from the mouse position.
import { useDataTransformer } from '@electricui/timeseries-react'import { useMouseSignal , MouseData } from '@electricui/components-desktop-charts'import { closestLineSegmentIntersection , lineSegments } from '@electricui/dataflow' const dataSource = useMessageDataSource <number>('signal') const [mouseSignal , captureRef ] = useMouseSignal () const dataTransformer = useDataTransformer (() => { const segments = lineSegments (dataSource , (data , time , tags ) => ({x : time , y : data })) const closest = closestLineSegmentIntersection (segments , mouseSignal , { // Index the lineSegments directly lineSegmentAccessor : (data , time , tags ) => data , // Search from the chart xMin to the x value of the mouse, at the y value of the mouse searchLineSegmentAccessor : (data , time , tags ) => ({ x1 : data .chartXMin , x2 : data .x , y1 : data .y , y2 : data .y , }), // Find the closest intersection to the mouse position, which contains x, y, chartAspectRatio keys searchPositionAccessor : (data , time , tags ) => data , // Return only the intersection point mapResult : ( data , time , tags , lineSegment , searchData , searchTags , searchLineSegment , searchPoint , intersectionPoint , distance , ) => intersectionPoint , }) return closest })