Skip to content

python(feat): add TDMS client-side detect_config#538

Merged
wei-qlu merged 16 commits into
mainfrom
python/add-tdms-client-support
Apr 17, 2026
Merged

python(feat): add TDMS client-side detect_config#538
wei-qlu merged 16 commits into
mainfrom
python/add-tdms-client-support

Conversation

@wei-qlu
Copy link
Copy Markdown
Contributor

@wei-qlu wei-qlu commented Apr 14, 2026

What was changed

Implement TDMS detect_config client-side and update TDMS data import models to reflect proto changes.

Detection handles waveform channels, dedicated time channels (TimeStamp type, xchannel property, common names), complex-valued channel splitting, enum detection, and fallback behavior for channels missing timing info, matching the existing backend implementation.

Model updates: added TdmsFallbackMethod, TdmsComplexComponent enums, TdmsDataColumn type, and expanded TdmsImportConfig with new proto fields plus _to_proto/_from_proto support.

Verification

Unit tests and manual testing with a local script, verifying the full import process succeeded:

  • Creating a config and importing
  • Calling detect_config, making adjustments, and importing

Example import workflow

import os
from dotenv import load_dotenv

from sift_client import SiftClient, SiftConnectionConfig
from sift_client.sift_types.channel import ChannelDataType
from sift_client.sift_types.data_import import (
    TdmsImportConfig,
    TdmsDataColumn,
    TdmsComplexComponent,
    TdmsFallbackMethod,
)

load_dotenv()

TDMS_FILE = "all_types.tdms"
ASSET_NAME = "tdms_all_types_example"


def get_client() -> SiftClient:
    return SiftClient(
        connection_config=SiftConnectionConfig(
            api_key=os.getenv("SIFT_API_KEY"),
            grpc_url=os.getenv("GRPC_API_URL"),
            rest_url=os.getenv("REST_API_URL"),
            use_ssl=False,
        )
    )


def main():
    client = get_client()

    config = TdmsImportConfig(
        asset_name=ASSET_NAME,
        run_name="all-types-manual-run",
        fallback_method=TdmsFallbackMethod.FAIL_ON_ERROR,
        data=[
            # Waveform group
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_bool",
                name="waveform.ch_bool",
                data_type=ChannelDataType.BOOL,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_int8",
                name="waveform.ch_int8",
                data_type=ChannelDataType.INT_32,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_int16",
                name="waveform.ch_int16",
                data_type=ChannelDataType.INT_32,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_int32",
                name="waveform.ch_int32",
                data_type=ChannelDataType.INT_32,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_int64",
                name="waveform.ch_int64",
                data_type=ChannelDataType.INT_64,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_uint8",
                name="waveform.ch_uint8",
                data_type=ChannelDataType.UINT_32,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_uint16",
                name="waveform.ch_uint16",
                data_type=ChannelDataType.UINT_32,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_uint32",
                name="waveform.ch_uint32",
                data_type=ChannelDataType.UINT_32,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_uint64",
                name="waveform.ch_uint64",
                data_type=ChannelDataType.UINT_64,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_float32",
                name="waveform.ch_float32",
                data_type=ChannelDataType.FLOAT,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_float64",
                name="waveform.ch_float64",
                data_type=ChannelDataType.DOUBLE,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_string",
                name="waveform.ch_string",
                data_type=ChannelDataType.STRING,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_timestamp",
                name="waveform.ch_timestamp",
                data_type=ChannelDataType.INT_64,
            ),
            # Complex channels must be split into real and imaginary components.
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_complex64",
                name="waveform.ch_complex64.real",
                data_type=ChannelDataType.FLOAT,
                complex_component=TdmsComplexComponent.REAL,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_complex64",
                name="waveform.ch_complex64.imag",
                data_type=ChannelDataType.FLOAT,
                complex_component=TdmsComplexComponent.IMAGINARY,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_complex128",
                name="waveform.ch_complex128.real",
                data_type=ChannelDataType.DOUBLE,
                complex_component=TdmsComplexComponent.REAL,
            ),
            TdmsDataColumn(
                group_name="waveform_channels",
                channel_name="ch_complex128",
                name="waveform.ch_complex128.imag",
                data_type=ChannelDataType.DOUBLE,
                complex_component=TdmsComplexComponent.IMAGINARY,
            ),
            # Time-channel group
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_bool",
                name="time_group.ch_bool",
                data_type=ChannelDataType.BOOL,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_int8",
                name="time_group.ch_int8",
                data_type=ChannelDataType.INT_32,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_int16",
                name="time_group.ch_int16",
                data_type=ChannelDataType.INT_32,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_int32",
                name="time_group.ch_int32",
                data_type=ChannelDataType.INT_32,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_int64",
                name="time_group.ch_int64",
                data_type=ChannelDataType.INT_64,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_uint8",
                name="time_group.ch_uint8",
                data_type=ChannelDataType.UINT_32,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_uint16",
                name="time_group.ch_uint16",
                data_type=ChannelDataType.UINT_32,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_uint32",
                name="time_group.ch_uint32",
                data_type=ChannelDataType.UINT_32,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_uint64",
                name="time_group.ch_uint64",
                data_type=ChannelDataType.UINT_64,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_float32",
                name="time_group.ch_float32",
                data_type=ChannelDataType.FLOAT,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_float64",
                name="time_group.ch_float64",
                data_type=ChannelDataType.DOUBLE,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_string",
                name="time_group.ch_string",
                data_type=ChannelDataType.STRING,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_timestamp",
                name="time_group.ch_timestamp",
                data_type=ChannelDataType.INT_64,
                time_channel_name="time",
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_complex64",
                name="time_group.ch_complex64.real",
                data_type=ChannelDataType.FLOAT,
                time_channel_name="time",
                complex_component=TdmsComplexComponent.REAL,
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_complex64",
                name="time_group.ch_complex64.imag",
                data_type=ChannelDataType.FLOAT,
                time_channel_name="time",
                complex_component=TdmsComplexComponent.IMAGINARY,
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_complex128",
                name="time_group.ch_complex128.real",
                data_type=ChannelDataType.DOUBLE,
                time_channel_name="time",
                complex_component=TdmsComplexComponent.REAL,
            ),
            TdmsDataColumn(
                group_name="time_channel_group",
                channel_name="ch_complex128",
                name="time_group.ch_complex128.imag",
                data_type=ChannelDataType.DOUBLE,
                time_channel_name="time",
                complex_component=TdmsComplexComponent.IMAGINARY,
            ),
        ],
    )
    
    job = client.data_import.import_from_path(
        file_path=TDMS_FILE,
        asset=ASSET_NAME,
        config=config,
        show_progress=True,
    )

    result = job.wait_until_complete()

    run = result.get_import_run()
    print(f"Run: {run.name} | {run.start_time} -> {run.stop_time}")


if __name__ == "__main__":
    main()

@wei-qlu wei-qlu force-pushed the python/add-tdms-client-support branch from 2008319 to e4ece74 Compare April 16, 2026 19:20
@wei-qlu wei-qlu marked this pull request as ready for review April 17, 2026 05:36
Comment thread python/lib/sift_client/_internal/util/tdms.py Outdated
Comment thread python/lib/sift_client/_tests/_internal/test_tdms.py Outdated
Comment thread python/lib/sift_client/resources/data_imports.py Outdated
Comment thread python/lib/sift_client/sift_types/data_import.py Outdated
Comment thread python/lib/sift_client/sift_types/data_import.py
@wei-qlu wei-qlu requested a review from marc-sift April 17, 2026 19:53
@wei-qlu wei-qlu enabled auto-merge (squash) April 17, 2026 21:38
@wei-qlu wei-qlu merged commit 1af5972 into main Apr 17, 2026
22 checks passed
@wei-qlu wei-qlu deleted the python/add-tdms-client-support branch April 17, 2026 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants