1+ #!/usr/bin/env python3
2+ """
3+ Example script demonstrating the new codec abstraction system.
4+
5+ This shows how to use different raw data codecs for non-image data:
6+ 1. pickle_raw (legacy behavior) - each data point is pickled individually
7+ 2. pyarrow_batch - batches data points for better seeking performance
8+ """
9+
10+ import numpy as np
11+ import tempfile
12+ import os
13+ from pathlib import Path
14+
15+ # Add the project directory to the Python path
16+ import sys
17+ sys .path .insert (0 , str (Path (__file__ ).parent ))
18+
19+ from robodm import Trajectory , FeatureType
20+ from robodm .backend .codec_config import CodecConfig
21+
22+ def demo_pickle_codec ():
23+ """Demonstrate the pickle-based raw codec (legacy behavior)"""
24+ print ("=== Pickle Raw Codec Demo ===" )
25+
26+ with tempfile .TemporaryDirectory () as temp_dir :
27+ path = os .path .join (temp_dir , "pickle_demo.vla" )
28+
29+ # Create trajectory with pickle-based raw codec
30+ traj = Trajectory (path , mode = "w" , video_codec = "rawvideo_pickle" )
31+
32+ # Add some test data
33+ for i in range (10 ):
34+ # Non-image data - will use raw codec
35+ vector_data = np .random .rand (5 ).astype (np .float32 )
36+ joint_positions = np .array ([i , i + 1 , i + 2 ], dtype = np .float32 )
37+
38+ traj .add ("sensor/vector" , vector_data , timestamp = i * 100 )
39+ traj .add ("robot/joints" , joint_positions , timestamp = i * 100 )
40+
41+ traj .close ()
42+
43+ # Read back and verify
44+ traj_read = Trajectory (path , mode = "r" )
45+ data = traj_read .load ()
46+ traj_read .close ()
47+
48+ print (f"Loaded { len (data )} features:" )
49+ for key , values in data .items ():
50+ print (f" { key } : shape={ values .shape } , dtype={ values .dtype } " )
51+
52+ file_size = os .path .getsize (path )
53+ print (f"File size: { file_size } bytes" )
54+
55+ return file_size
56+
57+
58+ def demo_pyarrow_codec ():
59+ """Demonstrate the PyArrow-based raw codec with batching"""
60+ print ("\n === PyArrow Batch Codec Demo ===" )
61+
62+ try :
63+ import pyarrow # Check if PyArrow is available
64+ except ImportError :
65+ print ("PyArrow not available - skipping demo" )
66+ return None
67+
68+ with tempfile .TemporaryDirectory () as temp_dir :
69+ path = os .path .join (temp_dir , "pyarrow_demo.vla" )
70+
71+ # Create trajectory with PyArrow-based raw codec
72+ traj = Trajectory (path , mode = "w" , video_codec = "rawvideo_pyarrow" )
73+
74+ # Add the same test data
75+ for i in range (10 ):
76+ # Non-image data - will use raw codec
77+ vector_data = np .random .rand (5 ).astype (np .float32 )
78+ joint_positions = np .array ([i , i + 1 , i + 2 ], dtype = np .float32 )
79+
80+ traj .add ("sensor/vector" , vector_data , timestamp = i * 100 )
81+ traj .add ("robot/joints" , joint_positions , timestamp = i * 100 )
82+
83+ traj .close ()
84+
85+ # Read back and verify
86+ traj_read = Trajectory (path , mode = "r" )
87+ data = traj_read .load ()
88+ traj_read .close ()
89+
90+ print (f"Loaded { len (data )} features:" )
91+ for key , values in data .items ():
92+ print (f" { key } : shape={ values .shape } , dtype={ values .dtype } " )
93+
94+ file_size = os .path .getsize (path )
95+ print (f"File size: { file_size } bytes" )
96+
97+ return file_size
98+
99+
100+ def demo_mixed_data ():
101+ """Demonstrate mixed RGB image and raw data with different codecs"""
102+ print ("\n === Mixed Data Demo ===" )
103+
104+ with tempfile .TemporaryDirectory () as temp_dir :
105+ path = os .path .join (temp_dir , "mixed_demo.vla" )
106+
107+ # Create trajectory with default codec selection
108+ traj = Trajectory (path , mode = "w" , video_codec = "auto" )
109+
110+ # Add mixed data
111+ for i in range (5 ):
112+ # RGB image - will use video codec
113+ rgb_image = np .random .randint (0 , 255 , (64 , 64 , 3 ), dtype = np .uint8 )
114+
115+ # Non-image data - will use raw codec
116+ vector_data = np .random .rand (10 ).astype (np .float32 )
117+ depth_data = np .random .rand (32 , 32 ).astype (np .float32 ) # Grayscale
118+
119+ traj .add ("camera/rgb" , rgb_image , timestamp = i * 100 )
120+ traj .add ("sensor/vector" , vector_data , timestamp = i * 100 )
121+ traj .add ("camera/depth" , depth_data , timestamp = i * 100 )
122+
123+ traj .close ()
124+
125+ # Read back and verify
126+ traj_read = Trajectory (path , mode = "r" )
127+ data = traj_read .load ()
128+ traj_read .close ()
129+
130+ print (f"Loaded { len (data )} features:" )
131+ for key , values in data .items ():
132+ print (f" { key } : shape={ values .shape } , dtype={ values .dtype } " )
133+
134+ file_size = os .path .getsize (path )
135+ print (f"File size: { file_size } bytes" )
136+
137+ return file_size
138+
139+
140+ def demo_codec_config ():
141+ """Demonstrate custom codec configuration"""
142+ print ("\n === Custom Codec Configuration Demo ===" )
143+
144+ # Create custom codec config
145+ config = CodecConfig (codec = "rawvideo_pyarrow" , options = {
146+ "batch_size" : 50 , # Smaller batches
147+ "compression" : "lz4" # Different compression
148+ })
149+
150+ with tempfile .TemporaryDirectory () as temp_dir :
151+ path = os .path .join (temp_dir , "custom_config_demo.vla" )
152+
153+ # Create trajectory with custom config
154+ traj = Trajectory (path , mode = "w" , codec_config = config )
155+
156+ # Add test data
157+ for i in range (20 ):
158+ vector_data = np .random .rand (8 ).astype (np .float32 )
159+ traj .add ("sensor/data" , vector_data , timestamp = i * 50 )
160+
161+ traj .close ()
162+
163+ # Read back and verify
164+ traj_read = Trajectory (path , mode = "r" )
165+ data = traj_read .load ()
166+ traj_read .close ()
167+
168+ print (f"Loaded { len (data )} features:" )
169+ for key , values in data .items ():
170+ print (f" { key } : shape={ values .shape } , dtype={ values .dtype } " )
171+
172+ file_size = os .path .getsize (path )
173+ print (f"File size: { file_size } bytes" )
174+
175+ return file_size
176+
177+
178+ if __name__ == "__main__" :
179+ print ("Codec Abstraction System Demo" )
180+ print ("=" * 50 )
181+
182+ pickle_size = demo_pickle_codec ()
183+ pyarrow_size = demo_pyarrow_codec ()
184+ mixed_size = demo_mixed_data ()
185+ custom_size = demo_codec_config ()
186+
187+ print ("\n === Summary ===" )
188+ print (f"Pickle codec file size: { pickle_size } bytes" )
189+ if pyarrow_size is not None :
190+ print (f"PyArrow codec file size: { pyarrow_size } bytes" )
191+ if pickle_size :
192+ compression_ratio = pickle_size / pyarrow_size
193+ print (f"Compression ratio: { compression_ratio :.2f} x" )
194+ print (f"Mixed data file size: { mixed_size } bytes" )
195+ print (f"Custom config file size: { custom_size } bytes" )
196+
197+ print ("\n Demo completed successfully!" )
0 commit comments