Trends and signals

Trend <smart-trend>

Trend is a historian trend chart for process data.

<smart-trend> · 25 properties, 16 methods, 5 events · source/modules/smart.trend.js

Usage in Angular

The Angular wrapper is TrendComponent from TrendModule: every property is an input, every event an output named on<Event>, and the methods are called on the component reference from @ViewChild. A method that returns a value returns a Promise of it, resolved once the component has rendered; its ...Sync() twin returns the value at once, or null before the component has rendered. Unknown bindings are rejected at compile time.

import { TrendModule, TrendComponent } from 'smart-industrial/angular/trend';

<smart-trend #trend [showBands]="true"
    (onHistoryRequest)="onHistoryRequest($event)"></smart-trend>

@ViewChild('trend', { read: TrendComponent }) trend!: TrendComponent;
// methods are called on the component reference; this one returns a Promise
const result = await this.trend.push({});

Properties

InputType, defaultDescription
[pens]
pens
arraySets or retrieves the pens as [{ field, label, unit, min, max, color, visible, precision, quality, qualityField }]. field is the key under which each record carries the value; min and max are the engineering range the pen is scaled against, and a pen without them is scaled to the data on screen. quality is the tag's current quality - good, uncertain, bad or stale, or an OPC UA status code - and applies to the latest reading; qualityField names the record field that carries each sample's own quality (a word or a status code), read at the cursor too. A reading whose quality is not good says so beside the value, in the readout and in the accessible names. Items that are not objects, or have no field, are skipped. Assign a new array to update the component.
[data]
data
arraySets or retrieves the records held by the trend as { timestamp, field: value, .. }, in time order. Assigning the property replaces the records; push and pushMany add to them. A record without a timestamp is stamped with the current time.
[timeField]
timeField
string
timestamp
Sets or retrieves the key a record carries its time under, a timestamp in milliseconds or a Date.
[bands]
bands
arraySets or retrieves the prediction bands, one per pen, as [{ field, label, confidence, color, records }], where records is [{ timestamp, expected, lower, upper }] in time order and confidence is the confidence level as a fraction (0.95 for a 95% interval). A band is drawn under its pen and scaled against the pen's range, and the readout shows the expected value and the interval at the cursor. The model that produces the band is part of the application. Assign a new array to update the component.
[markers]
markers
arraySets or retrieves the anomaly markers as [{ id, field, timestamp, timestampEnd, severity, score, label, description }]. severity is advisory, warning or critical (other values are treated as warning) and score is the model's confidence from 0 to 1, shown with the marker. A marker with a field is placed on that pen's line; a marker without a field spans the plot. A marker with a timestampEnd is an interval and is drawn as a band of time. Markers can be stepped through with N and P, are read out at the cursor, and are reported by the markerClick event. Assign a new array to update the component. Items that are not objects (null, for example) are skipped with a console warning.
[showBands]
showBands
boolean
true
Determines whether the prediction bands are drawn and read out. The bands are kept either way.
[showMarkers]
showMarkers
boolean
true
Determines whether the anomaly markers are drawn, read out and stepped through. The markers are kept either way.
[timeSpan]
timeSpan
number
900000
Sets or retrieves the window's width in milliseconds.
[end]
end
numberSets or retrieves the right edge of the window as a timestamp, while the trend is not live. The value is clamped to the newest sample, so the window cannot be moved into the future.
[live]
live
boolean
true
Determines whether the window follows the newest sample. Dragging, zooming, setWindow and pan turn it off; goLive turns it back on.
[scaleMode]
scaleMode
TrendScaleMode
percent
Sets or retrieves how the pens share the plot. percent draws every pen from 0 to 100% of its own range, as a historian does, which compares signals by shape; value draws all pens on one axis in engineering units, from min to max or from the data, for pens that share a unit.
[min]
min
numberSets or retrieves the bottom of the shared value axis in value mode. null follows the data.
[max]
max
numberSets or retrieves the top of the shared value axis in value mode. null follows the data.
[gapAfter]
gapAfter
numberSets or retrieves the maximum interval between two samples, in milliseconds, before the line is broken between them and valueAt returns NaN inside the gap. null (the default) works it out from the data: five times the median interval between records, so a late or missed poll is still joined and an outage is a gap, not a slope. 0 never breaks the line. With historian data that is stored on change (compressed), where long intervals are normal, set it to the longest interval that is not an outage, or 0. NaN or a negative value is ignored with a console warning and the interval is worked out from the data.
[historyLength]
historyLength
number
100000
Sets or retrieves the number of records kept, 100 000 by default; the oldest records are dropped beyond it, but never a record inside the window on screen (or the one just before it), so a window wider than the bound keeps everything it shows. 0 keeps every record. When records assigned through data are dropped, a console warning says how many. NaN or a negative value keeps 100 000.
[staleAfter]
staleAfter
numberSets or retrieves how long, in milliseconds, a pen may go without a new sample while the trend is live before its latest reading is marked stale - in the pens panel, the readout and their accessible names. null (the default) uses the gap interval (gapAfter, or the one worked out from the data), and never less than 2 s. 0 never marks a pen stale. The time is counted from when a sample arrived through push(), pushMany() or data, so a source clock that is off does not matter; history pages older than the newest sample held do not count as new.
[cursor]
cursor
numberSets or retrieves the cursor as a timestamp. null hides it. With a cursor, the readout and the pens panel show the interpolated value of every pen at that time; without a cursor they show the newest values.
[showPens]
showPens
boolean
true
Determines whether the pens panel is shown next to the plot. The panel has one button per pen with its label, range and value, which shows or hides the pen.
[showReadout]
showReadout
boolean
true
Determines whether the readout under the plot, the instant and every visible pen's value at it, is shown.
[showGrid]
showGrid
boolean
true
Determines whether grid lines are drawn at the value and time ticks.
[showTimeAxis]
showTimeAxis
boolean
true
Determines whether the time axis is labelled under the plot, seconds on a short window, minutes on an hour, the date on a day.
[interactive]
interactive
boolean
true
Determines whether the plot responds to the pointer and keyboard: drag pans, wheel zooms around the pointer, click places the cursor, double-click returns to live, and with focus the arrow keys move the cursor, plus and minus zoom, L returns to live and Escape clears the cursor. Off for a trend embedded in a scrolling page. The plot is then role="application" with a focusable tab stop and announces what the cursor reads; with interactive off it is role="img" and not a tab stop.
[label]
label
stringSets or retrieves the trend's name, shown in the header and in the accessible name.
[precisionDigits]
precisionDigits
number
2
Sets or retrieves how many decimal places a value is printed with, for pens that do not set their own. Clamped to 0-20 when formatting.
[lineWidth]
lineWidth
number
1.5
Sets or retrieves the width of a pen in pixels.

Methods

MethodDescription
push(record: any): Promise<any>
and pushSync(record: any): boolean
Appends one record and redraws. Returns false when there was nothing to add.
record object { timestamp, field: value, .. }. A record without a timestamp is stamped on arrival.
pushMany(records: any): Promise<any>
and pushManySync(records: any): boolean
Appends a batch of records, either live samples or a page of history, merged in time order, so that history arriving after live samples is placed correctly. Returns false when there was nothing to add.
records array The records.
clear(): voidRemoves every record.
snapshot(): Promise<any>
and snapshotSync(): any
Returns a copy of the records held, oldest first.
valueAt(field: any, time: any): Promise<any>
and valueAtSync(field: any, time: any): number
Returns a pen's value at an instant, interpolated between the samples either side, or NaN outside the record, inside a gap (two samples further apart than gapAfter, or than the interval worked out from the data when gapAfter is null), next to a sample with no reading, or for a pen with no samples.
field string The pen's field.
time number A timestamp.
bandAt(field: any, time: any): Promise<any>
and bandAtSync(field: any, time: any): any
Returns the expected value and interval of a band for a pen at a time, interpolated between the two band records on either side, as { expected, lower, upper, confidence, label }, or null when the pen has no band at that time.
field string The pen's field.
time number A timestamp.
markersAt(time: any): Promise<any>
and markersAtSync(time: any): any
Returns the markers at a time: an interval marker that contains the time, or an instant marker within one pixel column of it, so that a cursor placed with the pointer selects the marker.
time number A timestamp.
nextMarker(): Promise<any>
and nextMarkerSync(): any
Moves the cursor to the next marker on screen after the cursor (or to the first marker when there is no cursor or the cursor is past the last one), announces it and returns it. Returns null when there are no markers on screen.
previousMarker(): Promise<any>
and previousMarkerSync(): any
Moves the cursor to the previous marker on screen, wrapping to the last one, announces it and returns it. Returns null when there are no markers on screen.
toCSV(): Promise<any>
and toCSVSync(): string
Returns the visible window as CSV, an ISO timestamp column and one column per visible pen, for a spreadsheet.
goLive(): voidReturns to live mode and follows the newest sample.
setWindow(from: number, to: number): voidShows the given time interval and leaves live mode.
from number A timestamp.
to number A timestamp.
zoom(factor: number, around?: number): voidZooms the window by a factor, keeping one time in place, and leaves live mode.
factor number Above 1 zooms in, below 1 zooms out.
around number A timestamp to keep in place; defaults to the window's centre.
pan(delta: number): voidMoves the window by a time interval and leaves live mode. The window stops at the newest sample.
delta number Milliseconds; negative moves back into the record.
togglePen(index: number, visible?: boolean): voidShows or hides one pen and raises the penVisibilityChange event.
index number Which pen.
visible boolean Force a state instead of toggling.
invalidate(): voidRedraws the plot on the next animation frame, so that many pushes between two frames cost one draw.

Events

The data of an event is in event.detail. The trend moves its own window, cursor or pen visibility and then raises windowChange, cursorChange or penVisibilityChange; pointer and keyboard input count only while interactive is true. historyRequest is a request for older samples that the application answers with pushMany(), and markerClick reports the marker under the cursor.

OutputDescription and detail
(onWindowChange)
windowChange
This event is triggered when the interval on screen changes, by a drag, a zoom, a pan, setWindow, goLive, or a new sample while live.
from number The window's start, as a timestamp.
to number The window's end, as a timestamp.
live boolean Whether the window follows the newest sample.
(onHistoryRequest)
historyRequest
This event is triggered when the window reaches a time before the earliest record held, once per interval rather than once per pixel of a drag. The application responds with pushMany; Smart.Industrial.Connect.trend responds from the history of a session.
from number The start of the interval needed, as a timestamp.
to number The end of the interval needed, the earliest record held, or the window's end.
fields any[] The pens' fields.
(onCursorChange)
cursorChange
This event is triggered when the cursor is placed, moved or cleared through the pointer or keyboard.
time number The cursor's timestamp, or null when cleared.
values object Every pen's value at the cursor, keyed by field; NaN where there is none.
(onMarkerClick)
markerClick
This event is triggered when a marker is clicked, or Enter is pressed with the cursor on one. The cursor has already moved to the marker. A host that wants the operator's verdict on the model, a true or a false positive, asks for it here.
marker object The marker, as it was given.
time number The time under the pointer or cursor.
(onPenVisibilityChange)
penVisibilityChange
This event is triggered when a pen is shown or hidden from the pens panel or through togglePen.
index number Which pen.
field string The pen's field.
visible boolean Whether it is now drawn.

Types

type TrendScaleMode

'percent' | 'value'

CSS variables

The component declares 4 CSS variables; the CSS page shows how to set them.

--smart-trend-height --smart-trend-pens-width --smart-trend-plot-background --smart-trend-grid-color