Sift | Docs

Calculated Channels

Overview

Calculated Channels in Sift enable real-time transformation of time-series sensor data for precise anomaly detection, root cause analysis, and predictive maintenance. Engineers can extract actionable insights by applying expressions defined using CEL (Common Expression Language) directly to raw telemetry streams, known as Channels. This allows you to define custom metrics, derive new signals, or apply logic without modifying the original data. Sift supports the following two types of transformations that work across all supported data types:

  • Stateless transformations: Stateless transformations process each data point independently, making them ideal for real-time computations like unit conversions or threshold checks.
  • Stateful transformations: Stateful transformations retain context over time, enabling engineers to analyze historical trends, detect gradual system degradation, identify performance shifts, and uncover evolving failure patterns.
  • Unlike Rules, which enforce logic and trigger automated actions, Calculated Channels refine raw sensor data for deeper analysis. This distinction allows engineers to identify trends, compare system behaviors, and make data-driven decisions before failures occur.
  • Calculated Channels can be created through the UI and API.

Settings

To create a Calculated Channel, you must define its properties (settings), including which Assets it applies to, which Channels it uses, and the logic (expression) it follows. The following table describes each setting available when creating a Calculated Channel:

FieldRequiredDescription
NameYesThe display name for the Calculated Channel. Must be between 1 and 253 ASCII characters.
DescriptionNoOptional field to describe the purpose or logic behind the Calculated Channel.
AssetsYesSpecifies which Assets the Calculated Channel applies to. You can select specific Assets, use a tag filter, or apply it to all Assets.
Input ChannelsYesChannels used as inputs in the calculation. Each selected Channel is automatically assigned a shorthand variable (for example, $1, $2) for use in the query expression.
Query (expression syntax)YesThe CEL-based expression that defines the calculation logic. References shorthand variables (for example, $1) assigned to input Channels.
UnitsNoThe unit of measurement shown for the result of the calculated Channel (for example, Celsius).

Expression syntax

Calculated Channels are defined by expressions written in Common Expression Language (CEL). These expressions describe how raw telemetry should be transformed, using logic that is evaluated on each incoming row of data. An expression can include references to input Channels (for example, $1), constants, operators, and functions. Expressions may return numeric or string results and are used to compute derived values, apply thresholds, or combine multiple inputs in real time.

This section explains how expressions work in Sift, including how to reference Channels, use timestamps, apply math and logic, and work with built-in and User-defined Functions. Examples are provided using the CreateCalculatedChannel REST API endpoint to illustrate how expressions are structured when programmatically defining a Calculated Channel.

Channel references

When configuring a Calculated Channel, each selected input Channel is automatically assigned a shorthand variable such as $1, $2, $3, and so on, based on the order in which the Channels are chosen in the input Channels field. These variables act as placeholders in the expression editor and can be used to define transformation logic using CEL.

...
"queryConfiguration": {
  "sel": {
    "expression": "$1 * 1.8 + 32",
    "expressionChannelReferences": [
      {
        "channelReference": "$1",
        "channelIdentifier": "TEMPERATURE.CELSIUS"
      }
    ]
  }
}
...
  • This example shows how to define a Channel reference using the Sift REST API's CreateCalculatedChannel endpoint. While Calculated Channels can also be created through the UI or gRPC API, this format reflects the REST-specific schema for mapping input Channels to shorthand variables like $1. The snippet focuses on the queryConfiguration section of the request; other fields such as authorization, metadata, and asset selection are omitted for clarity.
  • This example defines a Calculated Channel that converts temperature from Celsius to Fahrenheit. The expression uses the shorthand variable $1 to reference the input Channel TEMPERATURE.CELSIUS, and applies the formula $1 * 1.8 + 32 to transform each data point. The expressionChannelReferences field links $1 to the actual input Channel used in the calculation.

Bitfield Channels are not supported as inputs for Calculated Channels.

Current t timestamp (ms)

When defining the expression of a Calculated Channel, the special variable t is always available. It represents the timestamp of the current telemetry point, expressed in milliseconds. This can be used in conjunction with functions like previous() to calculate time-based metrics such as sampling rate. Below is a focused example of the queryConfiguration section that computes the time difference between consecutive data points. This example maps $1 to a pressure Channel and calculates the time delta between the current and previous telemetry point. The rest of the request payload is omitted for clarity.

...
"queryConfiguration": {
  "sel": {
    "expression": "t - previous(t)",
    "expressionChannelReferences": [
      {
        "channelReference": "$1",
        "channelIdentifier": "PRESSURE.PSI"
      }
    ]
  }
}
...

Static scalar values

Calculated Channels support static scalar values such as numbers, strings, and booleans. These constants can be embedded directly in CEL expressions to define fixed thresholds, nominal baselines, or comparison values. The following example demonstrates how to subtract a static numeric value (100) from the input Channel $1 within a Calculated Channel expression.

"queryConfiguration": {
  "sel": {
    "expression": "$1 - 100",
    "expressionChannelReferences": [
      {
        "channelReference": "$1",
        "channelIdentifier": "PRESSURE.PSI"
      }
    ]
  }
}

Mathematical operators

Calculated Channels support standard arithmetic (+, -, *, /), comparison (>, <, >=, <=, ==, !=), boolean (!, &&, ||), and ternary (? :) operators in CEL expressions. These allow you to define rich, row-wise transformations across telemetry data. The following examples use the CreateCalculatedChannel REST API endpoint to demonstrate how these operators can be applied.

Arithmetic

You can use arithmetic operators to combine numeric Channels using +, -, *, and /. For powers and remainders, use the pow() and mod() functions respectively. In the example below, the voltage and current input Channels are assigned to $1 and $2, and multiplied to calculate power.

...
"queryConfiguration": {
  "sel": {
    "expression": "$1 * $2",
    "expressionChannelReferences": [
      { "channelReference": "$1", 
        "channelIdentifier": "VOLTAGE.VOLTS" 
      },
      { "channelReference": "$2", 
        "channelIdentifier": "CURRENT.AMPERES" 
      }
    ]
  }
}
...

Boolean and comparison

You can combine multiple logical and comparison operators to define complex conditions. In the example below, two Channels are used: temperature and pressure. Temperature is assigned to $1, and pressure to $2. The expression checks whether the temperature is between 20 and 30 degrees Celsius and whether the pressure is between 90 and 110 PSI. If all conditions are met, the result is true.

...
"queryConfiguration": {
  "sel": {
    "expression": "$1 >= 20 && $1 <= 30 && $2 >= 90 && $2 <= 110",
    "expressionChannelReferences": [
      { "channelReference": "$1", 
        "channelIdentifier": "TEMPERATURE.CELSIUS" 
      },
      { "channelReference": "$2", 
        "channelIdentifier": "PRESSURE.PSI" 
      }
    ]
  }
}
...

Ternary

The ternary operator uses the syntax condition ? option_1 : option_2 to return one of two values based on a boolean condition. In the example below, the temperature Channel is assigned to $1. The expression checks whether the temperature is greater than 30°C. If the condition is true, it returns High; otherwise, it returns Normal.

...
"queryConfiguration": {
  "sel": {
    "expression": "$1 > 30 ? 'High' : 'Normal'",
    "expressionChannelReferences": [
      { "channelReference": "$1", 
        "channelIdentifier": "TEMPERATURE.CELSIUS" 
      }
    ]
  }
}
...

Combining multiple time series with different timestamps

When an expression involves multiple time series, such as $1 + $2, Sift must join those series to compute each result. In typical systems, this would require exact timestamp matches between data points, meaning any values without aligned timestamps would be excluded from the calculation.

Sift uses an As Of join strategy to handle timestamp differences. Instead of requiring perfect alignment, it evaluates each unique timestamp across all input Channels and uses the most recent available value from each series as of that point in time. This approach allows expressions to compute meaningful results even when data streams arrive at different rates or with gaps. The example expression below adds the energy usage from two systems, regardless of whether their telemetry points are recorded at the exact same times.

...
"queryConfiguration": {
  "sel": {
    "expression": "$1 + $2",
    "expressionChannelReferences": [
      { "channelReference": "$1", 
        "channelIdentifier": "ENERGY.SYSTEM1.KWH" 
      },
      { "channelReference": "$2", 
        "channelIdentifier": "ENERGY.SYSTEM2.KWH" 
      }
    ]
  }
}
...

Functions

Calculated Channels support a wide range of functions that can be used in expressions to process and analyze time-series data. These functions allow you to transform raw inputs, evaluate conditions, and compute derived values in real time. They are organized into several categories based on the type of data or operation they target. You can view the full list of available functions directly in the expression editor when creating or editing a Calculated Channel.

CategoryDescriptionExample
Math functionsThese functions handle numeric calculations including trigonometry, rounding, powers, roots, logarithms, and bitwise operations. They are used to transform or compare numerical input values directly within expressions.pow($1, 2)
String functionsThese functions allow you to manipulate and evaluate string values. You can check for substrings, match regular expressions, and calculate string length.contains($1, "error")
List functionsThese functions operate on lists, such as checking whether a list contains a specific value. Useful when working with sets of known values.contains(["a", "b", "c"], $1)
Iteration functionsThese functions apply an expression conditionally based on a logical test. They are used to include or exclude results based on a dynamic condition.filter($1, $1 > 0)
Stateful functionsThese functions compute values over time using rolling windows or past data. They are used to calculate moving averages, rates of change, or time-based aggregates.avg($1, rolling(300))
User-defined FunctionsThese are custom functions defined in your environment. They allow you to reuse complex logic across multiple Calculated Channels.function($1)
OtherThese functions provide utility behavior such as accessing the current timestamp or converting data types like enum or numeric formats.t, double(x), enumKeyValue(x)

Math functions

These functions handle numeric calculations including trigonometry, rounding, powers, roots, logarithms, and bitwise operations. They are used to transform or compare numerical input values directly within expressions.

FunctionDescriptionExample expression
sin(x)Returns the sine of x (in radians)sin($1)
sinh(x)Returns the hyperbolic sine of xsinh($1)
asin(x)Returns the arcsine of x as an angle in radiansasin($1)
asinh(x)Returns the inverse hyperbolic sine of xasinh($1)
cos(x)Returns the cosine of x (in radians)cos($1)
cosh(x)Returns the hyperbolic cosine of xcosh($1)
acos(x)Returns the arccosine of x as an angle in radiansacos($1)
acosh(x)Returns the inverse hyperbolic cosine of xacosh($1)
tan(x)Returns the tangent of x (in radians)tan($1)
tanh(x)Returns the hyperbolic tangent of xtanh($1)
atan(x)Returns the arctangent of x as an angle in radiansatan($1)
atanh(x)Returns the inverse hyperbolic tangent of xatanh($1)
atan2(x, y)Returns the arctangent of y/x, preserving quadrantatan2($2, $1)
abs(x)Returns the absolute (non-negative) value of xabs($1)
ceil(x)Rounds x up to the nearest whole numberceil($1)
floor(x)Rounds x down to the nearest whole numberfloor($1)
round(x)Rounds x to the nearest whole numberround($1)
sqrt(x)Returns the square root of xsqrt($1)
cbrt(x)Returns the cube root of xcbrt($1)
log(x)Returns the natural logarithm (base e) of xlog($1)
log10(x)Returns the base-10 logarithm of xlog10($1)
exp(x)Returns e raised to the power of xexp($1)
pow(x, y)Raises x to the power of y (that is, x^y)pow($1, 2)
mod(x, y)Returns the remainder of x divided by ymod($1, 2)
min(...args)Returns the smallest value among the inputsmin($1, $2, $3)
max(...args)Returns the largest value among the inputsmax($1, $2, $3)
bitand(x, y)Performs a bitwise AND operation on x & ybitand($1, 0x04)
bitor(x, y)Performs a bitwise OR operation on x | ybitor($1, 0xF0)
bitxor(x, y)Performs a bitwise XOR operation on x ^ ybitxor($1, 8)
piMathematical constant πpi
eMathematical constant ee

String fuctions

These functions allow you to manipulate and evaluate string values. You can check for substrings, match regular expressions, and calculate string length.

FunctionDescriptionExample expression
contains(x, y)Returns true if string x contains substring ycontains($1, "error")
startsWith(x, y)Returns true if string x begins with ystartsWith($1, "TEMP:")
endsWith(x, y)Returns true if string x ends with yendsWith($1, ".log")
length(x)Returns the number of characters in string xlength($1) > 20
matches(x, y)Returns true if string x matches the regular expression ymatches($1, "^[A-Z]+[0-9]{3}$")

List functions

These functions operate on lists, such as checking whether a list contains a specific value. Useful when working with sets of known values.

FunctionDescriptionExample expression
contains(x, y)Returns true if list x contains value ycontains(["red", "blue", "green"], $1)

Iteration functions

These functions apply an expression conditionally based on a logical test. They are used to include or exclude results based on a dynamic condition.

FunctionDescriptionExample expression
filter(expression, condition)Evaluates the expression and emits its value only when the condition is true. No value is emitted when the condition is false.filter($1, $1 > 0)

Stateful functions

These functions compute values over time using rolling windows or past data. They are used to calculate moving averages, rates of change, or time-based aggregates.

FunctionDescriptionExample expression
avg(x, rolling(y))x is averaged over the past y duration (in seconds or time string)avg($1, rolling(300))
median(x, rolling(y))Computes the median of x values seen within the rolling y windowmedian($1, rolling(60))
min(x, rolling(y))Returns the minimum of x over the last y durationmin($1, rolling(10))
max(x, rolling(y))Returns the maximum of x over the last y durationmax($1, rolling(10))
stdev(x, rolling(y))Computes the standard deviation of x over a rolling window of ystdev($1, rolling(10))
sum(x, rolling(y))Calculates the total sum of x within the last y secondssum($1, rolling(60))
count(x, rolling(y))Counts how many values of x have appeared in the past ycount($1, rolling(10))
all(x, rolling(y))Returns true if all x values in the last y period are trueall($1, rolling(5))
any(x, rolling(y))Returns true if any value of x is true within the past yany($1, rolling(5))
first(x, rolling(y))Returns the first value of x in the most recent y secondsfirst($1, rolling(60))
last(x, rolling(y))Returns the last observed value of x in the past y secondslast($1, rolling(60))
rolling(y)Defines a rolling window of y seconds or a duration string (that is, "5m10s") to use with stateful functionsrolling("5m30s")
previous(x)Returns the value of x from the row immediately before the current oneprevious($1)
delta(x)Computes the difference between the current and previous values of xdelta($1)
deriv(x)Calculates the rate of change of x per millisecondderiv($1)
persistence(x, y)Returns true if x has remained true for at least y durationpersistence($1, "10s")
  • Aggregation windows: Rolling windows used in stateful functions can be up to 10 minutes long and apply only to rows that come before the current row. Future values are never included.
  • Aggregations: All stateful functions require an input and a window definition, such as avg($1 + 10, rolling(5)). Only rolling windows are supported at this time.

User-defined Functions

User-defined Functions in Sift are reusable Common Expression Language (CEL) expressions that can be used in both Calculated Channels and Rules. They allow teams to define shared logic in one place and reference it across multiple expressions to ensure consistency and reduce duplication. To learn more, see User-defined Functions.

Other

These functions provide utility behavior such as accessing the current timestamp or converting data types like enum or numeric formats.

FunctionDescriptionExample expression
tReturns the timestamp of the current row in millisecondst
enumKeyValue(x)Returns the underlying numeric value of an enum inputenumKeyValue($1)
double(x)Converts a numeric value x to double precisiondouble($1)