load β review β export Β· Three steps to close the loop
pip install tlabelimport tlabel
# 1οΈβ£ Load β auto-detect sensor format
data = tlabel.load("gelsight_force.pkl") # GelSight / DIGIT
data = tlabel.load("paxini_episode.h5") # PaXini
data = tlabel.load("daimon_data/") # Daimon (directory or .parquet)
# 2οΈβ£ Annotate β interactive Jupyter panel
data.review() # Chinese UI
data.review(lang="en") # English UI
# 3οΈβ£ Export
data.export("output.json") # TLabel Format v2 JSON
data.export("output.csv") # CSV flat tableπ₯ Try with demo data
pip install tlabel
python -c "
import json, urllib.request
from tlabel.core.types import TLabelFrame, TLabelData
url = 'https://raw.githubusercontent.com/liesliy/tlabel/main/examples/data/demo_gelsight.json'
raw = json.loads(urllib.request.urlopen(url).read())
frames = [TLabelFrame(f['frame_idx'], f['timestamp_s'], f['tlabel_v2'], f.get('manipulation_phase','idle'), f.get('confidence',1.0)) for f in raw['frames']]
data = TLabelData(frames, raw['sensor'], raw['episode'], raw['capabilities'])
data.review()
"| Sensor | Format | Dimensions | Optical Flow | Status |
|---|---|---|---|---|
| GelSight Mini | .pkl |
22 | β | β Stable |
| DIGIT | .pkl |
22 | β | β Stable |
| Daimon DM-TacClaw | .parquet / dir |
22 (video) / 20 (no video) | β / β | β Stable |
| PaXini PXCap | .h5 / .hdf5 |
20 | β | β Stable |
Force-type sensors (PaXini) lack optical images and don't support optical flow features, yielding 20 dimensions. Image-type sensors output all 22 dimensions. Daimon gracefully degrades to 20 dims when no video file is present.
# Minimal (numpy only)
pip install tlabel
# Per-sensor optional dependencies
pip install tlabel[gelsight] # GelSight / DIGIT β opencv-python
pip install tlabel[paxini] # PaXini β h5py
pip install tlabel[daimon] # Daimon β pyarrow + opencv-python
# Everything
pip install tlabel[all]- π¨ Color-coded timeline: green = contact Β· red = slip Β· gray = no contact
- πΈ 22-dim radar chart: full TLabel Format v2 visualization with bilingual labels
- βοΈ Frame & batch patching: select a range, modify in one click
- π Cascade rules: setting
contact=0auto-zeroes 7 related fields + resetsmanipulation_phaseβidle - π Bilingual toggle: Chinese / English, one click in the top-right corner
- π€ Export: JSON / CSV, auto-detected by file extension
| # | Key | Description |
|---|---|---|
| 1 | contact |
Binary contact flag |
| 2 | deformation_magnitude |
Surface deformation intensity |
| 3 | force_magnitude |
Normal force magnitude |
| 4 | force_peak |
Peak force in episode window |
| 5 | force_direction |
Force vector angle (Β°) |
| 6 | slip_entropy |
Uncertainty of slip detection |
| 7 | slip_event |
Binary slip event flag |
| 8 | texture_energy |
Surface texture frequency energy |
| 9 | edge_density |
Contact edge pixel ratio |
| 10 | contact_area |
Contact region area ratio |
| 11 | centroid_x |
Contact centroid x-position |
| 12 | normal_field_magnitude |
Normal pressure field magnitude |
| 13 | normal_field_variance |
Normal field spatial variance |
| 14 | shear_field_magnitude |
Shear stress magnitude |
| 15 | shear_field_direction |
Shear direction angle (Β°) |
| 16 | delta_force_normal |
Frame-to-frame ΞF_normal |
| 17 | delta_force_shear |
Frame-to-frame ΞF_shear |
| 18 | friction_cone_ratio |
Tangential/normal force ratio |
| # | Key | Image-type | Force-type | Description |
|---|---|---|---|---|
| 19 | optical_flow_magnitude |
β | β | Inter-frame motion magnitude (Farneback) |
| 20 | optical_flow_direction |
β | β | Optical flow angle (Β°) |
| 21 | temporal_deformation_rate |
β | β | Rate of deformation change |
| 22 | contact_transition |
β | β | Contact state transition probability |
import tlabel
# ββ Loading ββ
data = tlabel.load(path) # Auto-detect sensor format
data = tlabel.load(path, format="gelsight") # Force specific adapter
# ββ Properties ββ
data.num_frames # int β total frame count
data.duration_s # float β episode duration
data.sensor_type # str β sensor identifier
data.dimension_keys # list β all dimension keys for this sensor
data.modified_count # int β frames with manual patches
# ββ Frame Access ββ
frame = data[0] # Index access
frame = data.get_frame(42) # By frame_idx
frame.contact # Contact value
frame.slip_event # Slip event value
frame.is_modified # Has patches?
# ββ Patching ββ
frame.patch("contact", 0) # Single frame (cascade=True)
frame.patch("contact", 0, cascade=False) # No cascade
data.batch_patch(10, 50, "contact", 0) # Range patch
# ββ Review & Export ββ
data.review() # Jupyter panel (Chinese)
data.review(lang="en") # English
data.export("output.json") # JSON (TLabel Format v2)
data.export("output.csv") # CSVWhen contact is set to 0, these fields are automatically zeroed:
| Auto-zeroed Field | Condition |
|---|---|
force_magnitude |
always |
force_peak |
always |
slip_event |
always |
delta_force_normal |
always |
delta_force_shear |
always |
contact_area |
always |
contact_transition |
only if value > 0.5 |
manipulation_phase |
β "idle" (if not already) |
tlabel/
βββ core/
β βββ types.py # TLabelFrame / TLabelData containers
β βββ loader.py # Auto-detect & dispatch loading
β βββ registry.py # Adapter registry
βββ adapters/
β βββ base.py # BaseAdapter interface
β βββ gelsight.py # GelSight Mini / DIGIT
β βββ paxini.py # PaXini PXCap
β βββ daimon.py # Daimon DM-TacClaw (+ video decoding)
βββ viewer/
β βββ panel.py # Jupyter _repr_html_ renderer
β βββ templates.py # HTML + JS + CSS template engine
βββ export/
βββ writer.py # JSON / CSV export + NumpyEncoder
We welcome contributions! See CONTRIBUTING.md for guidelines.
Good first issues:
- π Add a new sensor adapter (e.g., SynTouch, XELA)
- π Improve radar chart UI (dark mode, interactive hover)
- π Add more language support (ζ₯ζ¬θͺ, νκ΅μ΄)
- π§ͺ Add integration tests for edge cases
MIT Β© Niuzu Tech
Star us β if it helps your research!
