Formulas and conditions

Formulas and conditions let you evaluate and combine signal data using Python syntax. They are available in operations such as Add calculated signal and Slice files by condition.

Only a subset of Python features is supported. NumPy functions and Data Operator utility functions can be used for additional calculations.

Supported Python syntax

The following Python keywords are supported:

and, elif, else, if, in, is, not, or, return.

The predefined time value provides the time values associated with the signal data.

NumPy is available using the np. prefix.

Example:

np.sqrt(signalName)

Note  

When combining Boolean conditions on signals, use the element-wise operators & and | instead of and and or. Enclose each individual condition in parentheses. Using and or or to combine signal conditions can result in the error The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

Validation

Formulas and conditions are not validated while editing. Errors are reported when the job is executed.

Signal names

Signal IDs used in formulas and conditions must be valid Python identifiers:

  • Start with a letter or underscore.

  • Contain only letters, digits, and underscores.

  • Do not contain spaces or special characters such as @, #, !, or \.

  • Do not use Python reserved keywords as signal names.

In Add calculated signal formulas, use the Signals control to map a valid signal ID to the signal you want to use. These mappings belong to an individual formula. For conditions, use the Rename signals or Map signal names operation to create a signal with a valid name.

Signal mappings for calculated formulas

Formula-specific mappings let you use signals with device names or other characters that are not valid in Python identifiers. In the formula, refer to the signal ID; the associated candidate signal identifies the source signal. The Signals control in Add calculated signal opens the Signal mappings dialog, where you can view, add, edit, and delete these mappings.

For example, to use EngineSpeed\ECU1, select it from formula autocomplete. Data Operator inserts a valid ID such as EngineSpeed__ECU1 and maps it to the selected signal. You can then write np.sqrt(EngineSpeed__ECU1) in the formula. The mapping is specific to that formula, and the formula text is changed automatically only when you select an autocomplete suggestion.

When creating an ID, backslashes are replaced with __ and other characters that are not valid in an identifier are replaced with _. If an ID is already in use, Data Operator adds a suffix such as _1 or _2 to make it unique. Signal IDs must follow the identifier rules above and must not be Python reserved keywords.

Data Operator utility functions

Data Operator provides utility functions for common calculations on measurement signals. Call these functions using the do. prefix.

Utility functions can be combined with other expressions and nested to define more complex calculations or conditions.

do.detect_rising_edge(condition)

Detects transitions from false to true in a Boolean condition.

The returned Boolean signal is true at the sample at which the condition first becomes true.

Example:

do.detect_rising_edge(vehicleAcceleration < 0)

Marks the start of each period in which vehicleAcceleration < 0.

do.detect_falling_edge(condition)

Detects transitions from true to false in a Boolean condition.

The returned Boolean signal marks the end of each true region.

Example:

do.detect_falling_edge(engineSpeed > 4000)

Marks the end of each period in which engineSpeed > 4000.

do.shift_edges(condition, start_offset, end_offset)

Changes the start and end of the true regions in a Boolean condition. The offsets are specified in seconds.

condition: Boolean expression or signal that defines the original true regions.

start_offset: Defines how the start of each true region is shifted:

  • A negative value moves the start earlier and includes data before the condition becomes true.

  • A positive value moves the start later and excludes data at the beginning of the original true region.

  • A value of 0 keeps the original start.

end_offset: Defines how the end of each true region is shifted:

  • A positive value moves the end later and includes data after the condition becomes false.

  • A negative value moves the end earlier and shortens the original true region.

  • A value of 0 keeps the original end.

Examples:

do.shift_edges(vehicleSpeed > 50, start_offset=0, end_offset=10)

The condition remains true for 10 seconds after vehicleSpeed > 50 becomes false.

do.shift_edges(vehicleSpeed > 50, start_offset=-10, end_offset=0)

The condition becomes true 10 seconds before vehicleSpeed > 50 becomes true.

do.shift_edges(vehicleSpeed > 50, start_offset=10, end_offset=0)

The first 10 seconds of each period in which vehicleSpeed > 50 are excluded.

do.moving_average(signal, time, duration)

Calculates the average signal value over a moving time window.

duration: Defines the length of the time window in seconds. For each sample, the function considers the samples within the specified duration up to and including the current sample.

The result has the same number of samples as the input signal. Non-equidistant sampling is supported.

Example:

do.moving_average(vehicleSpeed, time, 10)

Returns the average vehicle speed over the previous 10 seconds for each sample.

do.moving_max(signal, time, duration)

Calculates the maximum signal value over a moving time window.

duration: Defines the length of the time window in seconds. For each sample, the function considers the samples within the specified duration up to and including the current sample.

The result has the same number of samples as the input signal. Non-equidistant sampling is supported.

Example:

do.moving_max(vehicleSpeed, time, 10)

Returns the maximum vehicle speed measured during the previous 10 seconds for each sample.

do.moving_min(signal, time, duration)

Calculates the minimum signal value over a moving time window.

duration: Defines the length of the time window in seconds. For each sample, the function considers the samples within the specified duration up to and including the current sample.

The result has the same number of samples as the input signal. Non-equidistant sampling is supported.

Example:

do.moving_min(vehicleSpeed, time, 10)

Returns the minimum vehicle speed measured during the previous 10 seconds for each sample.

do.time_offset(signal, time, offset_in_s, fill)

Shifts the signal values in time without changing the time values. The offset is specified in seconds.

  • A positive offset delays the signal. The value returned for the current time corresponds to an earlier value of the input signal.

  • A negative offset advances the signal. The value returned for the current time corresponds to a later value of the input signal.

The function uses the signal timestamps when determining the shifted values and supports non-equidistant samples.

If a positive offset refers to a time before the first available sample, the result is NaN. If a negative offset extends beyond the last available sample, the last signal value is retained.

Example:

vehicleSpeed < 0.5 * do.time_offset(vehicleSpeed, time, 10)

The condition is true where the current vehicle speed is less than half the vehicle speed 10 seconds earlier.

do.sample_offset(signal, offset)

Shifts the signal values by a specified number of samples instead of a time duration.

  • A positive offset delays the signal by the specified number of samples.

  • A negative offset advances the signal by the specified number of samples.

Positions at the beginning of a positively shifted signal for which no source sample is available contain NaN. If a negative offset extends beyond the available samples, the last signal value is retained.

Use a sample offset when the required comparison is based on sample positions rather than elapsed time.

Example:

engineSpeed > do.sample_offset(engineSpeed, 1)

The condition is true where the current engine speed is greater than the engine speed at the previous sample.

do.differentiate(signal, time)

Calculates the numerical derivative of a signal with respect to time.

The function provides a simplified form of np.gradient(signal, time).

Example:

do.differentiate(vehicleSpeed, time)

Calculates vehicle acceleration from vehicle speed.

do.integrate(signal, time)

Calculates the cumulative integral of a signal with respect to time.

The result has the same number of samples as the input signal.

Example:

do.integrate(vehicleSpeed, time)

Integrates vehicle speed over time, for example to derive traveled distance when the signal units are suitable.