Series & Data โ
Learn how to work with data series in SciChart Engine.
Interactive Demo โ
Scroll to zoom โข Drag to pan โข Multiple series support
What is a Series? โ
A series represents a single dataset visualized on the chart. Each series has:
- ID: Unique identifier
- Type: How data is rendered (line, scatter, or both)
- Data: X and Y values as TypedArrays
- Style: Visual properties (color, width, etc.)
Creating Series โ
Line Series โ
chart.addSeries({
id: 'temperature',
type: 'line',
data: {
x: new Float32Array([0, 1, 2, 3, 4]),
y: new Float32Array([20, 22, 21, 23, 22]),
},
style: {
color: '#ff6b6b',
width: 2
},
})Scatter Series โ
chart.addSeries({
id: 'measurements',
type: 'scatter',
data: { x, y },
style: {
color: '#4ecdc4',
pointSize: 6
},
})Line with Points โ
chart.addSeries({
id: 'samples',
type: 'both',
data: { x, y },
style: {
color: '#ffe66d',
width: 1.5,
pointSize: 4
},
})Bar Series โ
chart.addBar({
id: 'sales',
data: {
x: new Float32Array([1, 2, 3, 4, 5]),
y: new Float32Array([120, 150, 180, 210, 190]),
},
style: {
color: '#00f2ff',
barWidth: 0.6
}
})Heatmap Series โ
chart.addHeatmap({
id: 'matrix',
data: {
xValues: [0, 1, 2],
yValues: [0, 1, 2],
zValues: new Float32Array([1, 2, 3, 4, 5, 6, 7, 8, 9])
},
style: {
colorScale: { name: 'viridis', min: 0, max: 10 }
}
})Candlestick Series โ
chart.addSeries({
id: 'stock-price',
type: 'candlestick',
data: {
x: timestamps,
open: openValues,
high: highValues,
low: lowValues,
close: closeValues,
},
style: {
bullishColor: '#26a69a', // Green
bearishColor: '#ef5350', // Red
barWidth: 0.8
}
})Stacked Series โ
Group multiple series together by using the same stackId. They will be rendered on top of each other.
chart.addSeries({
id: 'layer-1',
type: 'area', // Usually stacked as area/band
stackId: 'my-group',
data: { x, y: y1 },
style: { color: '#ff6b6b' }
})
chart.addSeries({
id: 'layer-2',
type: 'area',
stackId: 'my-group',
data: { x, y: y2 },
style: { color: '#4ecdc4' }
})Gauge Series (KPIs) โ
Visualize single values within a range.
chart.addSeries({
id: 'speed',
type: 'gauge',
data: { value: 65, min: 0, max: 120 },
style: {
label: 'Speed (km/h)',
needleColor: '#00ccff',
ranges: [
{ from: 0, to: 60, color: 'rgba(76, 175, 80, 0.4)' },
{ from: 90, to: 120, color: 'rgba(244, 67, 54, 0.4)' }
]
}
})Sankey Series (Flows) โ
Visualize distribution flows between categories.
chart.addSeries({
id: 'flow',
type: 'sankey',
data: {
nodes: [{ id: 'A', name: 'Source' }, { id: 'B', name: 'Target' }],
links: [{ source: 'A', target: 'B', value: 100 }]
}
})Data Requirements โ
TypedArrays Required
SciChart Engine requires Float32Array or Float64Array for data. Regular JavaScript arrays will cause errors.
// โ
Correct
const x = new Float32Array([1, 2, 3, 4, 5])
const y = new Float32Array([10, 20, 15, 25, 30])
// โ Wrong - will cause errors
const x = [1, 2, 3, 4, 5]
const y = [10, 20, 15, 25, 30]Why TypedArrays? โ
- Memory efficiency: Fixed-size, contiguous memory
- GPU upload: Direct transfer to WebGL buffers
- Performance: No type coercion overhead
- Precision: Float64 for scientific accuracy
Converting from Arrays โ
// From regular array
const regularArray = [1, 2, 3, 4, 5]
const typedArray = new Float32Array(regularArray)
// From generator
const n = 1000
const x = new Float32Array(n)
for (let i = 0; i < n; i++) {
x[i] = i
}Updating Data โ
Replace All Data โ
chart.updateSeries('temperature', {
x: newXData,
y: newYData,
})Append Data (Streaming) โ
// Add new points to existing data
chart.updateSeries('stream', {
x: new Float32Array([nextX]),
y: new Float32Array([nextY]),
append: true,
})Efficient Appending โ
For real-time data, pre-allocate and copy:
function appendPoints(prevX, prevY, newPoints) {
const newX = new Float32Array(prevX.length + newPoints.length)
const newY = new Float32Array(prevY.length + newPoints.length)
newX.set(prevX)
newY.set(prevY)
for (let i = 0; i < newPoints.length; i++) {
newX[prevX.length + i] = newPoints[i].x
newY[prevY.length + i] = newPoints[i].y
}
return { x: newX, y: newY }
}Managing Series โ
Get Series โ
const series = chart.getSeries('temperature')
// Series methods
series.getId() // 'temperature'
series.getType() // 'line'
series.getData() // { x: Float32Array, y: Float32Array }
series.getPointCount() // 5
series.getBounds() // { xMin, xMax, yMin, yMax }
series.isVisible() // trueGet All Series โ
const allSeries = chart.getAllSeries()
allSeries.forEach(s => {
console.log(`${s.getId()}: ${s.getPointCount()} points`)
})Remove Series โ
chart.removeSeries('temperature')Toggle Visibility โ
const series = chart.getSeries('temperature')
series.setVisible(false) // Hide
series.setVisible(true) // ShowChange Type Dynamically โ
const series = chart.getSeries('data')
series.setType('scatter') // Switch from line to scatterUpdate Style โ
const series = chart.getSeries('temperature')
series.setStyle({
color: '#00ff00',
width: 3
})Multiple Series โ
// Add multiple series
chart.addSeries({
id: 'sensor-1',
data: { x: time, y: sensor1Data },
style: { color: '#ff6b6b' },
})
chart.addSeries({
id: 'sensor-2',
data: { x: time, y: sensor2Data },
style: { color: '#4ecdc4' },
})
chart.addSeries({
id: 'sensor-3',
data: { x: time, y: sensor3Data },
style: { color: '#ffe66d' },
})Multiple Y-Axes โ
SciChart Engine supports multiple Y-axes. This is useful for comparing series with different units (e.g., Current and Potential).
1. Register Additional Axis โ
const chart = createChart({
container,
xAxis: { label: 'Time / s' },
yAxis: [
{ id: 'primary', label: 'Current / ยตA', position: 'left' },
{ id: 'secondary', label: 'Potential / V', position: 'right' }
]
})2. Link Series to Axis โ
Use the yAxisId property to specify which axis a series belongs to:
chart.addSeries({
id: 'current',
yAxisId: 'primary',
data: { x, y: currentData },
style: { color: '#00f2ff' }
})
chart.addSeries({
id: 'potential',
yAxisId: 'secondary',
data: { x, y: potentialData },
style: { color: '#ff6b6b' }
})3. Dynamic Axis Management โ
You can add or remove axes at runtime:
// Add a new axis
chart.addYAxis({
id: 'dynamic-axis',
label: 'New Unit',
position: 'right',
offset: 50 // Push axis further to the right
});
// Update an existing axis
chart.updateYAxis('primary', {
label: 'Updated Label',
auto: false,
min: 0,
max: 100
});Series Bounds โ
Each series calculates its data bounds:
const series = chart.getSeries('data')
const bounds = series.getBounds()
console.log(`X range: ${bounds.xMin} to ${bounds.xMax}`)
console.log(`Y range: ${bounds.yMin} to ${bounds.yMax}`)The chart uses these bounds for auto-scaling.
Best Practices โ
1. Use Meaningful IDs โ
// โ
Good
chart.addSeries({ id: 'temperature-sensor-1', ... })
// โ Bad
chart.addSeries({ id: 's1', ... })2. Pre-allocate for Large Data โ
// โ
Good - allocate once
const n = 1000000
const x = new Float32Array(n)
const y = new Float32Array(n)
// Fill data...
chart.addSeries({ id: 'big', data: { x, y } })3. Batch Updates โ
// โ
Good - update once with all new points
chart.updateSeries('stream', {
x: new Float32Array(100), // 100 new points
y: new Float32Array(100),
append: true,
})
// โ Bad - 100 separate updates
for (let i = 0; i < 100; i++) {
chart.updateSeries('stream', {
x: new Float32Array([point.x]),
y: new Float32Array([point.y]),
append: true,
})
}4. Clean Up Unused Series โ
// Remove series when no longer needed
chart.removeSeries('old-data')