|
| 1 | +<!-- |
| 2 | +Copyright 2025-2026 NVIDIA Corporation |
| 3 | +SPDX-License-Identifier: Apache-2.0 |
| 4 | +--> |
| 5 | + |
| 6 | +# tsd_client |
| 7 | + |
| 8 | +Python client library for [TSD](https://github.com/NVIDIA/VisRTX) (VisRTX) render servers over TCP. |
| 9 | + |
| 10 | +Provides the base protocol, connection management, DataTree binary codec, |
| 11 | +scene graph abstraction, interactive Jupyter viewer widget, and reusable |
| 12 | +panels for TSD-based applications. |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +```bash |
| 17 | +pip install -e . |
| 18 | +``` |
| 19 | + |
| 20 | +## Usage |
| 21 | + |
| 22 | +### Base client (any TSD server) |
| 23 | + |
| 24 | +```python |
| 25 | +from tsd_client import TSDClient |
| 26 | + |
| 27 | +client = TSDClient("127.0.0.1", port=12345) |
| 28 | +client.start_rendering() |
| 29 | +client.send_frame_config(1920, 1080) |
| 30 | + |
| 31 | +# Fetch and inspect the scene |
| 32 | +sg = client.scene_graph |
| 33 | +sg.print_layers() |
| 34 | +sg.print_objects() |
| 35 | + |
| 36 | +# Modify a transform and push |
| 37 | +xfm = sg.transform_for_object(sg.ANARI_VOLUME, 0) |
| 38 | +if xfm: |
| 39 | + xfm.position = (0, 0, 0) |
| 40 | + xfm.scale = (100, 100, 100) |
| 41 | + xfm.commit(client) |
| 42 | + |
| 43 | +client.disconnect() |
| 44 | +``` |
| 45 | + |
| 46 | +### Extending for a specific application |
| 47 | + |
| 48 | +```python |
| 49 | +from enum import IntEnum |
| 50 | +from tsd_client import TSDClient, SceneGraph |
| 51 | + |
| 52 | +class MyAppMessageType(IntEnum): |
| 53 | + SET_ANIMATION_TIME = 100 |
| 54 | + REQUEST_STATUS = 101 |
| 55 | + STATUS_INFO = 102 |
| 56 | + |
| 57 | +class MyAppClient(TSDClient): |
| 58 | + def __init__(self, host="127.0.0.1", port=12345, **kwargs): |
| 59 | + super().__init__(host, port, **kwargs) |
| 60 | + |
| 61 | + def set_animation_time(self, t: float): |
| 62 | + import struct |
| 63 | + self.send(MyAppMessageType.SET_ANIMATION_TIME, struct.pack("<f", t)) |
| 64 | +``` |
| 65 | + |
| 66 | +### DataTree codec |
| 67 | + |
| 68 | +```python |
| 69 | +from tsd_client import DataTree |
| 70 | + |
| 71 | +# Deserialize a DataTree from binary (e.g. from a StructuredMessage payload) |
| 72 | +tree = DataTree.from_bytes(raw_bytes) |
| 73 | +tree.print() |
| 74 | + |
| 75 | +# Build and serialize |
| 76 | +tree = DataTree() |
| 77 | +tree.root["material"]["roughness"].set_float(0.4) |
| 78 | +data = tree.to_bytes() |
| 79 | +``` |
| 80 | + |
| 81 | +## Architecture |
| 82 | + |
| 83 | +``` |
| 84 | +tsd_client/ |
| 85 | +├── __init__.py # Public API surface |
| 86 | +├── protocol.py # MessageType enum, wire format constants |
| 87 | +├── connection.py # TCP socket, 8-byte framed messaging, recv thread |
| 88 | +├── anari_types.py # ANARI type IDs, sizes, pack/unpack |
| 89 | +├── datatree.py # DataTree/DataNode binary codec (mirrors tsd::core::DataTree) |
| 90 | +├── scene.py # SceneGraph, ObjectRef, TransformRef, LayerNodeInfo |
| 91 | +├── client.py # TSDClient base class with scene graph management |
| 92 | +├── viewer.py # AnyWidget-based Jupyter viewer (orbit, animation, detach) |
| 93 | +├── session.py # TSDSession convenience wrapper (client + viewer + panels) |
| 94 | +├── utils.py # Shared math, TF parsers, Jupyter helpers |
| 95 | +└── panels/ |
| 96 | + ├── datatree_panel.py # Hierarchical scene tree inspector |
| 97 | + ├── transfer_function_panel.py # Interactive colour-map & opacity editor |
| 98 | + ├── clip_planes_panel.py # Volume clip plane controls |
| 99 | + └── light_panel.py # Light parameter editor |
| 100 | +``` |
| 101 | + |
| 102 | +## Protocol |
| 103 | + |
| 104 | +The wire format matches the C++ `tsd::network::NetworkChannel`: |
| 105 | + |
| 106 | +- **Header (8 bytes):** `uint8 type | 3 bytes padding | uint32 payload_length` (little-endian) |
| 107 | +- **Payload:** variable-length raw bytes |
| 108 | + |
| 109 | +Message type values match `tsd::network::MessageType` in `RenderSession.hpp`. Application-specific extensions use values >= 100. |
| 110 | + |
| 111 | +## License |
| 112 | + |
| 113 | +Apache-2.0 |
0 commit comments