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 Vue
Vue uses the custom element directly. A property is bound with :kebab-name; an array or an object needs the .prop modifier so that Vue sets the property rather than an attribute. Events are listened to with @eventName; methods are called on the element through a template ref.
import 'smart-industrial/source/modules/smart.trend.js';
<smart-trend ref="trend" :show-bands="true"
@historyRequest="onEvent"></smart-trend>
// methods are called on the element the ref holds
trend.value.push({});
// an array or an object is set as a property, not converted to an attribute: use .prop
<smart-trend :pens.prop="pens"></smart-trend>
Properties
| Binding | Type, default | Description |
|---|---|---|
:pens | array | Sets 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 | array | Sets 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. |
:time-field | string | Sets or retrieves the key a record carries its time under, a timestamp in milliseconds or a Date. |
:bands | array | Sets 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 | array | Sets 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. |
:show-bands | boolean | Determines whether the prediction bands are drawn and read out. The bands are kept either way. |
:show-markers | boolean | Determines whether the anomaly markers are drawn, read out and stepped through. The markers are kept either way. |
:time-span | number | Sets or retrieves the window's width in milliseconds. |
:end | number | Sets 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 | boolean | Determines whether the window follows the newest sample. Dragging, zooming, setWindow and pan turn it off; goLive turns it back on. |
:scale-mode | TrendScaleMode | 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 | number | Sets or retrieves the bottom of the shared value axis in value mode. null follows the data. |
:max | number | Sets or retrieves the top of the shared value axis in value mode. null follows the data. |
:gap-after | number | Sets 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. |
:history-length | number | 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. |
:stale-after | number | Sets 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 | number | Sets 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. |
:show-pens | boolean | 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. |
:show-readout | boolean | Determines whether the readout under the plot, the instant and every visible pen's value at it, is shown. |
:show-grid | boolean | Determines whether grid lines are drawn at the value and time ticks. |
:show-time-axis | boolean | 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 | boolean | 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 | string | Sets or retrieves the trend's name, shown in the header and in the accessible name. |
:precision-digits | number | 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. |
:line-width | number | Sets or retrieves the width of a pen in pixels. |
Methods
| Method | Description |
|---|---|
push(record: object): 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: array): 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(): void | Removes every record. |
snapshot(): array | Returns a copy of the records held, oldest first. |
valueAt(field: string, time: number): 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: string, time: number): 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: number): 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(): 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(): 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(): string | Returns the visible window as CSV, an ISO timestamp column and one column per visible pen, for a spreadsheet. |
goLive(): void | Returns to live mode and follows the newest sample. |
setWindow(from: number, to: number): void | Shows the given time interval and leaves live mode.from number A timestamp.to number A timestamp. |
zoom(factor: number, around?: number): void | Zooms 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): void | Moves 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): void | Shows or hides one pen and raises the penVisibilityChange event.index number Which pen.visible boolean Force a state instead of toggling. |
invalidate(): void | Redraws 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.
| Event | Description and detail |
|---|---|
@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. |
@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. |
@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. |
@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. |
@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