Files
2026-07-13 13:05:14 +08:00

204 lines
6.7 KiB
Python

"""
A collection of delightfully unique chunk specimens, for science.
IMPORTANT: the viewer should be set with `RERUN_CHUNK_MAX_BYTES=0` to disable the compactor.
To add new specimens to the zoo, add a function whose name starts with "specimen_".
"""
from __future__ import annotations
import argparse
from typing import TYPE_CHECKING
import numpy as np
import rerun as rr
if TYPE_CHECKING:
from collections.abc import Sequence
def frame_times(t: int | Sequence[int], *args: int) -> list[rr.TimeColumn]:
if isinstance(t, int):
t = [t]
else:
t = list(t)
if args:
t.extend(args)
return [rr.TimeColumn("frame", sequence=t)]
def set_frame_time(t: int) -> None:
rr.set_time("frame", sequence=t)
def specimen_two_rows_span_two_chunks() -> None:
"""Two rows spanning two chunks."""
rr.send_columns("/rows_span_two_chunks", frame_times(0, 2), rr.Points2D.columns(positions=[(0, 1), (2, 3)]))
rr.send_columns("/rows_span_two_chunks", frame_times(0, 2), rr.Points2D.columns(radii=[10, 11]))
def specimen_two_rows_span_two_chunks_sparse() -> None:
"""Two rows spanning two chunks with partially matching timestamps (so sparse results)."""
rr.send_columns(
"/rows_span_two_chunks_sparse",
frame_times(0, 2, 3),
rr.Points2D.columns(positions=[(0, 1), (2, 3), (4, 5)]),
)
rr.send_columns("/rows_span_two_chunks_sparse", frame_times(0, 2, 4), rr.Points2D.columns(radii=[10, 11, 12]))
def specimen_archetype_with_clamp_join_semantics() -> None:
"""Single row of an archetype with clamp join semantics (Points2D)."""
rr.send_columns(
"/archetype_with_clamp_join_semantics",
frame_times(0),
[
*rr.Points2D.columns(
positions=[(i, i) for i in range(10)],
).partition([10]),
*rr.Points2D.columns(radii=2),
],
)
def specimen_archetype_with_latest_at_semantics() -> None:
"""Archetype spread over a multi-row chunk and a single row chunk, with latest-at semantics."""
rr.send_columns(
"/archetype_chunk_with_latest_at_semantics",
frame_times(range(10)),
rr.Points2D.columns(positions=[(i, i) for i in range(10)], class_ids=range(10)),
)
set_frame_time(5)
rr.log("/archetype_chunk_with_latest_at_semantics", rr.Points2D.from_fields(radii=2))
def specimen_archetype_with_clamp_join_semantics_two_chunks() -> None:
"""Single row of an archetype with clamp join semantics (Points2D), across two chunks."""
rr.send_columns(
"/archetype_with_clamp_join_semantics_two_batches",
frame_times(0),
rr.Points2D.columns(positions=[(i, i) for i in range(10)]).partition([10]),
)
rr.send_columns(
"/archetype_with_clamp_join_semantics_two_batches",
frame_times(0),
rr.Points2D.columns(radii=2),
)
def specimen_archetype_without_clamp_join_semantics() -> None:
"""Single row of an archetype without clamp join semantics (Mesh3D)."""
rr.send_columns(
"/archetype_without_clamp_join_semantics",
frame_times(0),
[
*rr.Mesh3D.columns(
vertex_positions=[(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)],
vertex_colors=[(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0)],
).partition([4]),
*rr.Mesh3D.columns(triangle_indices=[(0, 1, 2), (0, 2, 3)]).partition([2]),
],
)
def specimen_many_rows_with_mismatched_instance_count() -> None:
"""Points2D across many timestamps with varying and mismatch instance counts."""
# Useful for dataframe view row expansion testing.
np.random.seed(0)
positions_partitions = np.random.randint(
3,
15,
size=100,
)
batch_size = int(np.sum(positions_partitions))
# Shuffle the color partitions to induce the mismatch
colors_partitions = positions_partitions.copy()
np.random.shuffle(colors_partitions)
positions = np.random.rand(batch_size, 2)
colors = np.random.randint(0, 255, size=(batch_size, 4))
rr.send_columns(
"/many_rows_with_mismatched_instance_count",
frame_times(range(len(positions_partitions))),
[
*rr.Points2D.columns(positions=positions).partition(positions_partitions),
*rr.Points2D.columns(colors=colors).partition(colors_partitions),
],
)
# TODO(ab): add variants (unordered, overlapping timestamps, etc.)
def specimen_scalars_interlaced_in_two_chunks() -> None:
"""Scalar column stored in two chunks, with interlaced timestamps."""
rr.send_columns(
"/scalars_interlaced_in_two_chunks",
frame_times(0, 2, 5, 6, 8),
rr.Scalars.columns(scalars=[0, 2, 5, 6, 8]),
)
rr.send_columns(
"/scalars_interlaced_in_two_chunks",
frame_times(1, 3, 7),
rr.Scalars.columns(scalars=[1, 3, 7]),
)
def specimen_archetype_chunk_with_clear() -> None:
"""Archetype spread on multi-row and single-row chunks, with a `Clear` in the middle."""
rr.send_columns(
"/archetype_chunk_with_clear",
frame_times(range(10)),
rr.Points2D.columns(positions=[(i, i) for i in range(10)], class_ids=range(10)),
)
set_frame_time(0)
rr.log("/archetype_chunk_with_clear", rr.Points2D.from_fields(radii=2))
set_frame_time(5)
rr.log("/archetype_chunk_with_clear", rr.Clear(recursive=False))
def main() -> None:
parser = argparse.ArgumentParser(
description="Logs a bunch of chunks of various typologies. Use `RERUN_CHUNK_MAX_BYTES=0`!",
)
parser.add_argument("--filter", type=str, help="Only run specimens whose name contains this substring")
rr.script_add_args(parser)
args = parser.parse_args()
rr.script_setup(args, "rerun_example_chunk_zoo", default_blueprint=rr.blueprint.TextDocumentView(origin="/info"))
# Round up the specimens
specimens = [
globals()[name]
for name in globals()
if name.startswith("specimen_") and callable(globals()[name]) and (not args.filter or args.filter in name)
]
specimen_list = "\n".join([f"| {s.__name__.removeprefix('specimen_')} | {s.__doc__} |" for s in specimens])
markdown = (
"# Chunk Zoo\n\n"
"This recording contains a variety of chunks of various typologies, for testing purposes.\n\n"
"**IMPORTANT**: The viewer should be set with `RERUN_CHUNK_MAX_BYTES=0` to disable the compactor.\n\n"
"### Specimens\n\n"
f"| **Item** | **Description** |\n| --- | --- |\n{specimen_list}"
)
rr.log("info", rr.TextDocument(text=markdown, media_type="text/markdown"), static=True)
# Set the specimens loose
for specimen in specimens:
specimen()
if __name__ == "__main__":
main()