Tobii XR Devzone > Develop > Tobii Ocumen > Ocumen I/O > Python >

Ocumen I/O - Getting Started in Python

Ocumen I/O for Python allows you to process and create .ocumen streams from Python.

Tobii Ocumen I/O for Python allows you to interface with Ocumen Studio recordings, and export and import data via Python.

Introduction

The .ocumen format encapsulates XR recordings, such as head pose, gaze data and scene objects. Recordings are usually created simply by running a scene via Ocumen I/O for Unity and then processed with Ocumen I/O for Python. With it you can

  • Open recordings made with Ocumen I/O for Unity
  • Read and query data, e.g., gaze, head pose, objects, input, custom events
  • Create recordings from scratch, e.g., to import existing data for visualization

Getting Started

Using Ocumen I/O for Python consists of these steps:

  • To get Tobii Ocumen, please contact us via our contact form.
  • Install Python 3.8+ and an IDE (we recommend an IDE supporting type hints)
  • Download your Ocumen bundle.
  • Locate and open the ocumen_io Python tutorial folder
  • Run tutorial_01_hello_world.py to verify things work:
    • If that sample runs the rest should work too.
    • If you run into errors please see our FAQ or contact our support.

That’s it! You can now play with existing recordings, analyze recordings you’ve made with Ocumen I/O for Unity, or import your pre-existing data for visualization with Ocumen Studio. A simple script to try out could be this:

import ocumen_io as io

# Open a data source and verify it is compatible with this version.
connector = io.WorldConnector.from_file(b"data/sample-recording.ocumen")
connector.check_compatible()

# Read the entire data source (here a file) into memory. We could have connected
# to a live network stream above, in which case `read_incremental` would have
# only read what's available so far.
reader = io.WorldReader.from_connector(connector)
reader.read_incremental()

# Obtain recording meta data
info = reader.recording_information()

# Print the duration of this recording
print(info.duration)

Next Steps

The example above is merely an example how scripting with Ocumen I/O for Python looks like. The Ocumen bundle contains more examples and tutorials, for example:

  • hello_world.py - Connect to the library and make sure it works.
  • error_handling.py - Basic error handling techniques and how to get stack traces.
  • call_safety.py - How to prevent undefined behavior and bad data.
  • opening_recordings.py - Opening existing recordings.
  • obtaining_data.py - Reading data from recordings.
  • scene_objects.py - Obtaining scene objects.
  • which_object_was_gazed_at.py - How to determine which object was looked at.
  • export_data.py - Exporting data to CSVs.
  • import_data.py - Import existing data for visualization with Ocumen Studio.

General Tips

Some tips that are good to know when working with Ocumen I/O for Python:

  • Ocumen I/O is a low-level high-performance library written in Rust, with bindings for various languages such as C# or Python (a bit similar to how NumPy or TensorFlow work). The same code is shared between Ocumen Studio, Ocumen I/O for Unity and Python, improving performance, learnability and your time to market.
  • On Python bindings are handled via ctypes. We recommend you to read through their documentation at least once.
  • Since we use a native library there are some safety considerations you should follow to prevent undefined behavior:
    • Never hold on to slices (anything starting with Slice) for longer than needed. A slice is basically a pointer to internal cache memory. When a function gives you a slice you may use that slice only until your next API call, never longer (unless the documentation clearly says otherwise). If you need to hold on to data across multiple calls create a copy of that slice via .copied().
    • Never invoke function with None for missing pointer parameters unless the documentation clearly allows it.
    • When you have to pass strings, use Python’s byte string b"my byte string" containing ASCII only values.
  • When using a WorldWriter only write monotonically increasing time stamps per type, otherwise the result of subsequent queries is unspecified.