Send user-defined data
Rerun comes with many pre-built Types that you can use out of the box. As long as your own data can be decomposed into Rerun components or can be serialized with Apache Arrow, you can log it directly without needing to recompile Rerun.
For Python and Rust we have helpers for this, called AnyValues
, allowing you to easily attach custom values to any entity instance.
You find the documentation for these helpers here:
rr.log(
"my_entity",
rr.AnyValues(
# Using arbitrary Arrow data.
homepage="https://www.rerun.io",
repository="https://github.com/rerun-io/rerun",
)
# Using Rerun's builtin components.
.with_field(
rr.ComponentDescriptor("confidence", component_type=rr.components.ScalarBatch._COMPONENT_TYPE), [1.2, 3.4, 5.6]
)
.with_field(
rr.ComponentDescriptor("description", component_type=rr.components.TextBatch._COMPONENT_TYPE), "Bla bla blaβ¦"
),
)
You can achieve the same thing in Rust:
let any_values = rerun::AnyValues::default()
// Using arbitrary Arrow data.
.with_field(
"homepage",
Arc::new(arrow::array::StringArray::from(vec![
"https://www.rerun.io",
])),
)
.with_field(
"repository",
Arc::new(arrow::array::StringArray::from(vec![
"https://github.com/rerun-io/rerun",
])),
)
// Using Rerun's builtin components.
.with_component::("confidence", [1.2, 3.4, 5.6])
.with_component::("description", vec!["Bla bla blaβ¦"]);
rec.log("my_entity", &any_values)?;
You can also create your own component by implementing the AsComponents
Python protocol or Rust trait, which means implementing the function, as_component_batches()
.
Remapping to a Rerun archetype remapping-to-a-rerun-archetype
Let's start with a simple example where you have your own point cloud class that is perfectly representable as a Rerun archetype.
@dataclass
class LabeledPoints:
points: np.ndarray
labels: List[str])
If you implement as_component_batches()
on LabeledPoints
, you can pass it directly to rr.log
. The simplest possible way is to use the matching Rerun archetypeβs as_component_batches
method.
import rerun as rr # pip install rerun-sdk
@dataclass
class LabeledPoints:
points: np.ndarray
labels: List[str]
def as_component_batches(self) -> list[rr.ComponentBatch]:
return rr.Points3D(positions=self.points,
labels=self.labels).as_component_batches()
β¦
# Somewhere deep in your code
classified = my_points_classifier(β¦) # type: LabeledPoints
rr.log("points/classified", classified)
Custom archetypes and components custom-archetypes-and-components
You can also define and log your own custom archetypes and components completely from user code, without rebuilding Rerun.
In this example we extend the Rerun Points3D archetype with a custom confidence component and user-defined archetype.
β οΈ NOTE: Due to the component descriptor changes in v0.24
it is currently not possible for custom data to be picked up by visualizers.
We are currently investigating approaches to bring that functionality back.
However, your custom data will still show up in the dataframe view, as shown below.
"""Shows how to implement custom archetypes and components."""
from __future__ import annotations
import argparse
from typing import Any
import numpy as np
import numpy.typing as npt
import pyarrow as pa
import rerun as rr
class ConfidenceBatch(rr.ComponentBatchMixin):
"""A batch of confidence data."""
def __init__(self: Any, confidence: npt.ArrayLike) -> None:
self.confidence = confidence
def as_arrow_array(self) -> pa.Array:
"""The arrow batch representing the custom component."""
return pa.array(self.confidence, type=pa.float32())
class CustomPoints3D(rr.AsComponents):
"""A custom archetype that extends Rerun's builtin `Points3D` archetype with a custom component."""
def __init__(self: Any, positions: npt.ArrayLike, confidences: npt.ArrayLike) -> None:
self.points3d = rr.Points3D(positions)
self.confidences = ConfidenceBatch(confidences).described(
rr.ComponentDescriptor(
"user.CustomPoints3D:confidences",
archetype="user.CustomPoints3D",
component_type="user.Confidence",
)
)
def as_component_batches(self) -> list[rr.DescribedComponentBatch]:
return (
list(self.points3d.as_component_batches()) # The components from Points3D
+ [self.confidences] # Custom confidence data
)
def log_custom_data() -> None:
lin = np.linspace(-5, 5, 3)
z, y, x = np.meshgrid(lin, lin, lin, indexing="ij")
point_grid = np.vstack([x.flatten(), y.flatten(), z.flatten()]).T
rr.log(
"left/my_confident_point_cloud",
CustomPoints3D(
positions=point_grid,
confidences=[42],
),
)
rr.log(
"right/my_polarized_point_cloud",
CustomPoints3D(positions=point_grid, confidences=np.arange(0, len(point_grid))),
)
def main() -> None:
parser = argparse.ArgumentParser(description="Logs rich data using the Rerun SDK.")
rr.script_add_args(parser)
args = parser.parse_args()
rr.script_setup(args, "rerun_example_custom_data")
log_custom_data()
rr.script_teardown(args)
if __name__ == "__main__":
main()
