Custom trace synchronization¶
To integrate a custom trace synchronization, you can implement a Python script that follows the interface defined in the AbstractTraceSynchronization class. This Python script needs to fulfill several requirements to be available as a valid trace synchronization.
The script needs to be located in the
UserPyModulesfolder of the workspace.On the top level of the script, you must specify the variable MODULE_TYPE = ‘TRACE_SYNCHRONIZATION’.
The file needs to contain a class that defines two static class variables:
ID: that uniquely identifies the synchronization. Could be a generated uuid or a simple versioning schema like <class name>_v1
DISPLAY_NAME: that is used to display the synchronization in the user interface.
The class needs to implement the methods GetParameters, GetMasterSignals, GetRecordingSignals and Synchronize.
There must not be two synchronizations with the same ID.
Newly added synchronizations are available after refreshing the user libraries. You can do this in the menu “Extras”.
Info
The interface for custom trace synchronization is included in the
ecu.test Interface Python Library ecutest-interface.
AbstractTraceSynchronization¶
- class tts.interface.recording.userSynchronization.AbstractTraceSynchronization¶
Interface class for custom trace synchronization methods.
This abstract base class defines the contract for implementing synchronization algorithms that align recording signals with master signals in trace data. Subclasses must implement the Synchronize method and can override the class methods to specify required parameters and signals.
- Variables:
- ID : str
Unique ID of the synchronization method.
- DISPLAY_NAME : str
Human-readable name of the synchronization method.
- Attention:
You must define MODULE_TYPE at module level in your implementation Python file. Example:
from tts.interface.recording.userSynchronization import AbstractTraceSynchronization MODULE_TYPE = AbstractTraceSynchronization.MODULE_TYPE class MySync(AbstractTraceSynchronization): …
- classmethod GetParameters() list[ParameterDefinition]¶
Override this method to specify which parameters are needed for your synchronization implementation. By default, no parameters are required.
- Returns:
List of ParameterDefinition objects describing required parameters.
- abstractmethod classmethod GetMasterSignals() list[SignalDefinition]¶
Override this method to specify which master signals are required for synchronization.
- Returns:
List of SignalDefinition objects for master signals.
- Raises:
NotImplementedError – If not implemented in subclass.
- abstractmethod classmethod GetRecordingSignals() list[SignalDefinition]¶
Override this method to specify which recording signals are required for synchronization.
- Returns:
List of SignalDefinition objects for recording signals.
- Raises:
NotImplementedError – If not implemented in subclass.
- abstractmethod Synchronize(masterSignals: dict[str, Signal], recordingSignals: dict[str, Signal], parameters: dict[str, object]) float¶
- abstractmethod Synchronize(masterSignals: dict[str, Signal], recordingSignals: dict[str, Signal], parameters: dict[str, object], masterRecordingInfo: RecordingInfo, recordingInfo: RecordingInfo) float
Calculates the time offset in trace time (usually seconds) to synchronize the traces with the master signals.
- Deprecated:
Synchronize(masterSignals, recordingSignals, parameters) is deprecated as of version 2026.3 and will be removed in version 2027.1. Please use Synchronize(masterSignals, recordingSignals, parameters, masterRecordingInfo, recordingInfo) instead.
- Parameters:
- masterSignals: dict[str, Signal]¶
Dictionary of master signal names to Signal objects.
- recordingSignals: dict[str, Signal]¶
Dictionary of recording signal names to Signal objects.
- parameters: dict[str, object]¶
Dictionary of parameter names to their values.
- masterRecordingInfo: RecordingInfo
Master RecordingInfo object.
- recordingInfo: RecordingInfo
RecordingInfo object.
- Returns:
Calculated time offset for synchronization (in seconds).
- Raises:
NotImplementedError – If not implemented in subclass.
ParameterDefinition¶
- class tts.interface.recording.userSynchronization.ParameterDefinition¶
Represents a parameter definition for user synchronization.
- Variables:
- name : str
Name of the parameter.
- description : str
Description of the parameter.
- default : Any
Default value of the parameter.
SignalDefinition¶
- class tts.interface.recording.userSynchronization.SignalDefinition¶
Represents a signal definition used for describing a signal in the system.
- Variables:
- name : str
Name of the signal
- description : str
Description of the signal
- optional : bool
Whether the signal is optional
Signal¶
- class tts.interface.recording.userSynchronization.Signal¶
Represents a time-based signal for mapping items. Provides access to timestamps and corresponding values.
- abstractmethod GetMappingItemName() str¶
- Returns:
The mapping item name as a string.
- abstractmethod GetTimestamps() numpy.ndarray¶
- Returns:
A numpy.ndarray of timestamps (float64).
- abstractmethod GetValues() numpy.ndarray¶
- Returns:
A numpy.ndarray of tuples (timestamp, value).
RecordingInfo¶
- class tts.interface.recording.RecordingInfo¶
- abstractmethod GetPathList() list[str]¶
Returns the list of paths to the recordings.
- Returns:
The list of paths.
- abstractmethod GetFirstPath() str | None¶
Returns the first path of the path list of the recordings or None, if the list is empty.
- Returns:
The path.
-
abstractmethod GetPath(idx: int =
0) str | None¶ Returns the path at the specified index of the path list of the recordings or None, if the index is out of range or the list is empty.
- Parameters:
- idx: int =
0¶ The index of the path to retrieve.
- idx: int =
- Returns:
The path at the specified index or None if the index is out of range or the list is empty.
- abstractmethod GetRecordingName() str | None¶
Returns the name of the recording or None, if the name is not set.
: returns: The name of the recording or None.
- abstractmethod GetRecordingNumber() int¶
Returns the number of the recording within the associated recording group.
- Returns:
The number of the recording.
- abstractmethod GetRecordingType() str¶
Returns the type of the recording.
- Returns:
The type of the recording.
- abstractmethod GetStartTimeNs() int | None¶
Returns the start time of the recording in nanoseconds since 1970-01-01T00:00:00Z.
- Returns:
Start time in nanoseconds or None if the recording format does not support it.
Example¶
from __future__ import annotations
from typing import TYPE_CHECKING
from dataclasses import dataclass
MODULE_TYPE = 'TRACE_SYNCHRONIZATION'
# The AbstractTraceSynchronization defines the interface for all UserSynchronizations.
from tts.interface.recording.userSynchronization import (
AbstractTraceSynchronization,
ParameterDefinition,
SignalDefinition,
)
if TYPE_CHECKING:
from tts.interface.recording import RecordingInfo
from tts.interface.recording.userSynchronization import Signal
class ExpectedValueSync(AbstractTraceSynchronization):
DISPLAY_NAME = 'ExpectedValue'
ID = 'ExpectedValueSync_v1'
@classmethod
def GetParameters(cls) -> list[ParameterDefinition]:
return [
ParameterDefinition(
'expectedValue',
description='the description is shown as help text',
default='2.5',
),
]
@classmethod
def GetMasterSignals(cls) -> list[SignalDefinition]:
return [
SignalDefinition(
'SignalA', description='signal that value should match', optional=False
)
]
@classmethod
def GetRecordingSignals(cls) -> list[SignalDefinition]:
return [
SignalDefinition(
'SignalB', description='signal that value should match', optional=False
)
]
def Synchronize(
self,
masterSignals: dict[str, Signal],
recordingSignals: dict[str, Signal],
parameters: dict[str, object],
masterRecordingInfo: RecordingInfo,
recordingInfo: RecordingInfo,
) -> float:
tsMaster = self._FindValue(
parameters['expectedValue'],
masterSignals['SignalA'],
)
tsRec = self._FindValue(
parameters['expectedValue'],
recordingSignals['SignalB'],
)
if tsMaster is None or tsRec is None:
raise ValueError('Could not find value for one of the signals')
return tsMaster - tsRec
def _FindValue(self, expValue: float, signal: Signal):
for ts, value in zip(signal.GetTimestamps(), signal.GetValues()):
if value == expValue:
return ts
return None