Efficiently log time series data using `send_columns`

Sometimes you want to send big chunks of data to Rerun efficiently. To do so, you can use send_columns.

send_columns lets you efficiently log the state of an entity over time, logging multiple time and component columns in one call.

In contrast to the log function, send_columns does NOT add any other timelines to the data. Neither the built-in timelines log_time and log_tick, nor any user timelines. Only the timelines explicitly included in the call to send_columns will be included.

API docs of send_columns:

Using send_columns for logging scalars using-sendcolumns-for-logging-scalars

#!/usr/bin/env python3
"""Use the `send_columns` API to send scalars over time in a single call."""

from __future__ import annotations

import numpy as np
import rerun as rr

rr.init("rerun_example_send_columns", spawn=True)

times = np.arange(0, 64)
scalars = np.sin(times / 10.0)

rr.send_columns(
    "scalars",
    times=[rr.TimeSequenceColumn("step", times)],
    components=[rr.components.ScalarBatch(scalars)],
)

Using send_columns for logging images using-sendcolumns-for-logging-images

"""Send multiple images at once using `send_columns`."""

import numpy as np
import rerun as rr

rr.init("rerun_example_image_send_columns", spawn=True)

# Timeline on which the images are distributed.
times = np.arange(0, 20)

# Create a batch of images with a moving rectangle.
width, height = 300, 200
images = np.zeros((len(times), height, width, 3), dtype=np.uint8)
images[:, :, :, 2] = 255
for t in times:
    images[t, 50:150, (t * 10) : (t * 10 + 100), 1] = 255

# Log the ImageFormat and indicator once, as static.
format_static = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8")
rr.log("images", [format_static, rr.Image.indicator()], static=True)

# Send all images at once.
rr.send_columns(
    "images",
    times=[rr.TimeSequenceColumn("step", times)],
    # Reshape the images so `ImageBufferBatch` can tell that this is several blobs.
    #
    # Note that the `ImageBufferBatch` consumes arrays of bytes,
    # so if you have a different channel datatype than `U8`, you need to make sure
    # that the data is converted to arrays of bytes before passing it to `ImageBufferBatch`.
    components=[rr.components.ImageBufferBatch(images.reshape(len(times), -1))],
)

Using send_columns for logging points using-sendcolumns-for-logging-points

Each row the in the component column can be a batch of data, e.g. a batch of positions. This lets you log the evolution of a point cloud over time efficiently.

"""Use the `send_columns` API to send several point clouds over time in a single call."""

from __future__ import annotations

import numpy as np
import rerun as rr

rr.init("rerun_example_send_columns_arrays", spawn=True)

# Prepare a point cloud that evolves over time 5 timesteps, changing the number of points in the process.
times = np.arange(10, 15, 1.0)
positions = [
    [[1.0, 0.0, 1.0], [0.5, 0.5, 2.0]],
    [[1.5, -0.5, 1.5], [1.0, 1.0, 2.5], [-0.5, 1.5, 1.0], [-1.5, 0.0, 2.0]],
    [[2.0, 0.0, 2.0], [1.5, -1.5, 3.0], [0.0, -2.0, 2.5], [1.0, -1.0, 3.5]],
    [[-2.0, 0.0, 2.0], [-1.5, 1.5, 3.0], [-1.0, 1.0, 3.5]],
    [[1.0, -1.0, 1.0], [2.0, -2.0, 2.0], [3.0, -1.0, 3.0], [2.0, 0.0, 4.0]],
]
positions_arr = np.concatenate(positions)

# At each time stamp, all points in the cloud share the same but changing color.
colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF]

rr.send_columns(
    "points",
    times=[rr.TimeSecondsColumn("time", times)],
    components=[
        rr.Points3D.indicator(),
        rr.components.Position3DBatch(positions_arr).partition([len(row) for row in positions]),
        rr.components.ColorBatch(colors),
    ],
)