# Rerun > Rerun is an easy-to-use, multimodal, and time-aware visualization toolbox, > designed to help you explore and understand your data. - **Rerun is in active development.** We are constantly improving it and adding new features. - **Rerun is open-source.** You can find the project on [GitHub](https://github.com/rerun-io/rerun). - **Rerun is free to use.** It is permissively licensed under MIT, so you can use it for personal and commercial projects. - Rerun is currently split into two parts, the SDK and the Viewer. - Rerun has an SDK for [Python](https://ref.rerun.io/docs/python), [C++](https://ref.rerun.io/docs/cpp), and [Rust](https://docs.rs/rerun/). - The Rerun viewer can either be installed and run natively, or in the browser. - You can [try Rerun in your browser](/viewer). ## Docs # Concepts --- title: Concepts order: 2 --- For a deeper understanding of how your logging data can be organized and visualized, it is useful to learn about the underlying concepts in Rerun. # Developing Rerun --- title: Developing Rerun order: 4 --- If you want to contribute and help develop Rerun, that work happens in the [Rerun repository](https://github.com/rerun-io/rerun). Also, make sure to join the [Rerun Discord](https://discord.gg/PXtCgFBSmH). # Getting Started --- title: Getting Started order: 0 redirect: getting-started/what-is-rerun --- # How-to --- title: How-to order: 1 --- Guides for using Rerun in more advanced ways. # Welcome --- title: Welcome order: 0 redirect: getting-started/what-is-rerun --- # Reference --- title: Reference order: 2 --- The reference docs detail how to use the logging APIs and the viewer. # About --- title: About order: 1100 --- To learn more about Rerun, the company, visit our Website at [https://www.rerun.io/](https://www.rerun.io/). Code & License -------------- The Rerun SDK & Viewer are open source, all code is available on [GitHub](https://github.com/rerun-io/rerun/) and open for contributions. Licensing is permissive, the project is dual licensed under [MIT](https://github.com/rerun-io/rerun/blob/main/LICENSE-MIT) & [Apache 2.0](https://github.com/rerun-io/rerun/blob/main/LICENSE-APACHE). Under the hood -------------- The software is almost entirely written in [Rust](https://www.rust-lang.org/), a modern, fast and safe programming language. If you're curious about why we love Rust, checkout our [blog](https://www.rerun.io/blog/why-rust), where we talk about some of the reasons. We depend on a number of third party libraries, most notably: * [Apache Arrow](https://arrow.apache.org/) for our data store * [wgpu](https://wgpu.rs/) for rendering * [egui](https://github.com/emilk/egui) for UI * [PyO3](https://github.com/PyO3/pyo3) for Python bindings If you want to learn more about the different parts of the SDK & Viewer and how they work, check out [this architecture overview](https://github.com/rerun-io/rerun/blob/latest/ARCHITECTURE.md) for an introduction. # CLI manual --- title: CLI manual order: 0 --- ## rerun The Rerun command-line interface: * Spawn viewers to visualize Rerun recordings and other supported formats. * Start TCP and WebSocket servers to share recordings over the network, on native or web. * Inspect, edit and filter Rerun recordings. **Usage**: ` rerun [OPTIONS] [URL_OR_PATHS]… [COMMAND]` **Commands** * `analytics`: Configure the behavior of our analytics. * `rrd`: Manipulate the contents of .rrd and .rbl files. * `reset`: Reset the memory of the Rerun Viewer. * `man`: Generates the Rerun CLI manual (markdown). **Arguments** * `` > Any combination of: > - A WebSocket url to a Rerun server > - A path to a Rerun .rrd recording > - A path to a Rerun .rbl blueprint > - An HTTP(S) URL to an .rrd or .rbl file to load > - A path to an image or mesh, or any other file that Rerun can load (see https://www.rerun.io/docs/reference/data-loaders/overview) > > If no arguments are given, a server will be hosted which a Rerun SDK can connect to. **Options** * `--bind ` > What bind address IP to use. > > [Default: `0.0.0.0`] * `--drop-at-latency ` > Set a maximum input latency, e.g. "200ms" or "10s". > > If we go over this, we start dropping packets. > > The default is no limit, which means Rerun might eat more and more memory and have longer and longer latency, if you are logging data faster than Rerun can index it. * `--memory-limit ` > An upper limit on how much memory the Rerun Viewer should use. > When this limit is reached, Rerun will drop the oldest data. > Example: `16GB` or `50%` (of system total). > > [Default: `75%`] * `--server-memory-limit ` > An upper limit on how much memory the WebSocket server should use. > The server buffers log messages for the benefit of late-arriving viewers. > When this limit is reached, Rerun will drop the oldest data. > Example: `16GB` or `50%` (of system total). > > [Default: `25%`] * `--persist-state ` > Whether the Rerun Viewer should persist the state of the viewer to disk. > When persisted, the state will be stored at the following locations: > - Linux: `/home/UserName/.local/share/rerun` > - macOS: `/Users/UserName/Library/Application Support/rerun` > - Windows: `C:\Users\UserName\AppData\Roaming\rerun` > > [Default: `true`] * `--port ` > What TCP port do we listen to for SDKs to connect to. > > [Default: `9876`] * `--profile ` > Start with the puffin profiler running. > > [Default: `false`] * `--save ` > Stream incoming log events to an .rrd file at the given path. * `--screenshot-to ` > Take a screenshot of the app and quit. We use this to generate screenshots of our examples. Useful together with `--window-size`. * `--serve ` > Deprecated: use `--serve-web` instead. * `--serve-web ` > Serve the recordings over WebSocket to one or more Rerun Viewers. > > This will also host a web-viewer over HTTP that can connect to the WebSocket address, but you can also connect with the native binary. > > `rerun --serve-web` will act like a proxy, listening for incoming TCP connection from logging SDKs, and forwarding it to Rerun viewers. > > [Default: `false`] * `--expect-data-soon ` > This is a hint that we expect a recording to stream in very soon. > > This is set by the `spawn()` method in our logging SDK. > > The viewer will respond by fading in the welcome screen, instead of showing it directly. This ensures that it won't blink for a few frames before switching to the recording. > > [Default: `false`] * `-j, --threads ` > The number of compute threads to use. > > If zero, the same number of threads as the number of cores will be used. If negative, will use that much fewer threads than cores. > > Rerun will still use some additional threads for I/O. > > [Default: `-2`] * `--version ` > Print version and quit. > > [Default: `false`] * `--web-viewer ` > Start the viewer in the browser (instead of locally). > > Requires Rerun to have been compiled with the `web_viewer` feature. > > This implies `--serve-web`. > > [Default: `false`] * `--web-viewer-port ` > What port do we listen to for hosting the web viewer over HTTP. A port of 0 will pick a random port. > > [Default: `9090`] * `--hide-welcome-screen ` > Hide the normal Rerun welcome screen. > > [Default: `false`] * `--window-size ` > Set the screen resolution (in logical points), e.g. "1920x1080". Useful together with `--screenshot-to`. * `--ws-server-port ` > What port do we listen to for incoming websocket connections from the viewer. A port of 0 will pick a random port. > > [Default: `9877`] * `--renderer ` > Override the default graphics backend and for a specific one instead. > > When using `--web-viewer` this should be one of: `webgpu`, `webgl`. > > When starting a native viewer instead this should be one of: > > * `vulkan` (Linux & Windows only) > > * `gl` (Linux & Windows only) > > * `metal` (macOS only) * `--test-receive ` > Ingest data and then quit once the goodbye message has been received. > > Used for testing together with `RERUN_PANIC_ON_WARN=1`. > > Fails if no messages are received, or if no messages are received within a dozen or so seconds. > > [Default: `false`] ## rerun analytics Configure the behavior of our analytics. **Usage**: `rerun analytics ` **Commands** * `details`: Prints extra information about analytics. * `clear`: Deletes everything related to analytics. * `email`: Associate an email address with the current user. * `enable`: Enable analytics. * `disable`: Disable analytics. * `config`: Prints the current configuration. ## rerun analytics email Associate an email address with the current user. **Usage**: `rerun analytics email ` **Arguments** * `` ## rerun rrd Manipulate the contents of .rrd and .rbl files. **Usage**: `rerun rrd ` **Commands** * `compare`: Compares the data between 2 .rrd files, returning a successful shell exit code if they match. * `print`: Print the contents of one or more .rrd/.rbl files/streams. * `compact`: Compacts the contents of one or more .rrd/.rbl files/streams and writes the result standard output. * `merge`: Merges the contents of multiple .rrd/.rbl files/streams, and writes the result to standard output. * `filter`: Filters out data from .rrd/.rbl files/streams, and writes the result to standard output. ## rerun rrd compare Compares the data between 2 .rrd files, returning a successful shell exit code if they match. This ignores the `log_time` timeline. **Usage**: `rerun rrd compare [OPTIONS] ` **Arguments** * `` * `` **Options** * `--full-dump ` > If specified, dumps both .rrd files as tables. > > [Default: `false`] ## rerun rrd print Print the contents of one or more .rrd/.rbl files/streams. Reads from standard input if no paths are specified. Example: `rerun rrd print /my/recordings/*.rrd` **Usage**: `rerun rrd print [OPTIONS] [PATH_TO_INPUT_RRDS]…` **Arguments** * `` > Paths to read from. Reads from standard input if none are specified. **Options** * `-v, --verbose ` > If set, print out table contents. > > [Default: `false`] * `--continue-on-error ` > If set, will try to proceed even in the face of IO and/or decoding errors in the input data. > > [Default: `true`] ## rerun rrd compact Compacts the contents of one or more .rrd/.rbl files/streams and writes the result standard output. Reads from standard input if no paths are specified. Uses the usual environment variables to control the compaction thresholds: `RERUN_CHUNK_MAX_ROWS`, `RERUN_CHUNK_MAX_ROWS_IF_UNSORTED`, `RERUN_CHUNK_MAX_BYTES`. Unless explicit flags are passed, in which case they will override environment values. Examples: * `RERUN_CHUNK_MAX_ROWS=4096 RERUN_CHUNK_MAX_BYTES=1048576 rerun rrd compact /my/recordings/*.rrd -o output.rrd` * `rerun rrd compact --max-rows 4096 --max-bytes=1048576 /my/recordings/*.rrd > output.rrd` **Usage**: `rerun rrd compact [OPTIONS] [PATH_TO_INPUT_RRDS]…` **Arguments** * `` > Paths to read from. Reads from standard input if none are specified. **Options** * `-o, --output ` > Path to write to. Writes to standard output if unspecified. * `--max-bytes ` > What is the threshold, in bytes, after which a Chunk cannot be compacted any further? > > Overrides `RERUN_CHUNK_MAX_BYTES` if set. * `--max-rows ` > What is the threshold, in rows, after which a Chunk cannot be compacted any further? > > Overrides `RERUN_CHUNK_MAX_ROWS` if set. * `--max-rows-if-unsorted ` > What is the threshold, in rows, after which a Chunk cannot be compacted any further? > > This specifically applies to _non_ time-sorted chunks. > > Overrides `RERUN_CHUNK_MAX_ROWS_IF_UNSORTED` if set. * `--continue-on-error ` > If set, will try to proceed even in the face of IO and/or decoding errors in the input data. > > [Default: `false`] ## rerun rrd merge Merges the contents of multiple .rrd/.rbl files/streams, and writes the result to standard output. Reads from standard input if no paths are specified. This will not affect the chunking of the data in any way. Example: `rerun merge /my/recordings/*.rrd > output.rrd` **Usage**: `rerun rrd merge [OPTIONS] [PATH_TO_INPUT_RRDS]…` **Arguments** * `` > Paths to read from. Reads from standard input if none are specified. **Options** * `-o, --output ` > Path to write to. Writes to standard output if unspecified. * `--continue-on-error ` > If set, will try to proceed even in the face of IO and/or decoding errors in the input data. > > [Default: `false`] ## rerun rrd filter Filters out data from .rrd/.rbl files/streams, and writes the result to standard output. Reads from standard input if no paths are specified. This will not affect the chunking of the data in any way. Example: `rerun filter --drop-timeline log_tick /my/recordings/*.rrd > output.rrd` **Usage**: `rerun rrd filter [OPTIONS] [PATH_TO_INPUT_RRDS]…` **Arguments** * `` > Paths to read from. Reads from standard input if none are specified. **Options** * `-o, --output ` > Path to write to. Writes to standard output if unspecified. * `--drop-timeline ` > Names of the timelines to be filtered out. * `--drop-entity ` > Paths of the entities to be filtered out. * `--continue-on-error ` > If set, will try to proceed even in the face of IO and/or decoding errors in the input data. > > [Default: `false`] # 🌊 C++ APIs --- title: 🌊 C++ APIs order: 2000 redirect: https://ref.rerun.io/docs/cpp --- # Data-loaders --- title: Data-loaders order: 800 redirect: reference/data-loaders/overview --- # Dataframes --- title: Dataframes order: 300 --- Rerun, at its core, is a database. As such, you can always get your data back in the form of tables (also known as dataframes, or records, or batches...). This can be achieved in three different ways, depending on your needs: * using the dataframe API, currently available in [Python](https://ref.rerun.io/docs/python/stable/common/dataframe/) and [Rust](https://docs.rs/rerun/latest/rerun/dataframe/index.html), * using the [blueprint API](../concepts/blueprint.md) to configure a [dataframe view](types/views/dataframe_view.md) from code, * or simply by setting up [dataframe view](types/views/dataframe_view.md) manually in the UI. This page is meant as a reference to get you up and running with these different solutions as quickly as possible. For an in-depth introduction to the dataframe API and the possible workflows it enables, check out [our Getting Started guide](../getting-started/data-out) or one of the accompanying [How-Tos](../howto/dataframe-api.md). > We'll need an RRD file to query. Either use one of yours, or grab some of the example ones, e.g.: > ``` > curl 'https://app.rerun.io/version/latest/examples/dna.rrd' -o - > /tmp/dna.rrd > ``` ### Using the dataframe API The following snippet demonstrates how to query the first 10 rows in a Rerun recording using latest-at (i.e. time-aligned) semantics: ```python """Query and display the first 10 rows of a recording.""" import sys import rerun as rr path_to_rrd = sys.argv[1] recording = rr.dataframe.load_recording(path_to_rrd) view = recording.view(index="log_time", contents="/**") batches = view.select() for _ in range(10): row = batches.read_next_batch() if row is None: break # Each row is a `RecordBatch`, which can be easily passed around across different data ecosystems. print(row) ``` Check out the API reference to learn more about all the ways that data can be searched and filtered: * [🐍 Python API reference](https://ref.rerun.io/docs/python/stable/common/dataframe/) * [Example](https://github.com/rerun-io/rerun/blob/c00a9f649fd4463f91620e8e2eac11355b245ac5/examples/python/dataframe_query/dataframe_query.py) * [🦀 Rust API reference](https://docs.rs/rerun/latest/rerun/dataframe/index.html) * [Example](https://github.com/rerun-io/rerun/blob/c00a9f649fd4463f91620e8e2eac11355b245ac5/examples/rust/dataframe_query/src/main.rs) ### Using the blueprint API to configure a dataframe view The following snippet demonstrates how visualize an entire Rerun recording using latest-at (i.e. time-aligned) semantics by displaying the results in a [dataframe view](types/views/dataframe_view.md): ```python """Query and display the first 10 rows of a recording in a dataframe view.""" import sys import rerun as rr import rerun.blueprint as rrb path_to_rrd = sys.argv[1] rr.init("rerun_example_dataframe_view_query", spawn=True) rr.log_file_from_path(path_to_rrd) blueprint = rrb.Blueprint( rrb.DataframeView( origin="/", query=rrb.archetypes.DataframeQuery( timeline="log_time", apply_latest_at=True, ), ), ) rr.send_blueprint(blueprint) ``` #### Aside: re-using blueprint files from other SDKs While the blueprint APIs are currently only available through Python, blueprints can be saved and re-logged as needed from any language our SDKs support. First, save the blueprint to a file (`.rbl` by convention) using either the viewer (`Menu > Save blueprint`) or the python API: ```python """Craft a blueprint with the python API and save it to a file for future use.""" import sys import rerun.blueprint as rrb path_to_rbl = sys.argv[1] rrb.Blueprint( rrb.DataframeView( origin="/", query=rrb.archetypes.DataframeQuery( timeline="log_time", apply_latest_at=True, ), ), ).save("rerun_example_dataframe_view_query", path_to_rbl) ``` Then log that blueprint file in addition to the data itself: ```python """ Query and display the first 10 rows of a recording in a dataframe view. The blueprint is being loaded from an existing blueprint recording file. """ # python dataframe_view_query_external.py /tmp/dna.rrd /tmp/dna.rbl import sys import rerun as rr path_to_rrd = sys.argv[1] path_to_rbl = sys.argv[2] rr.init("rerun_example_dataframe_view_query_external", spawn=True) rr.log_file_from_path(path_to_rrd) rr.log_file_from_path(path_to_rbl) ``` Check out the blueprint API and `log_file_from_path` references to learn more: * [🐍 Python blueprint API reference](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) * [🐍 Python `log_file_from_path`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log_file_from_path) * [🦀 Rust `log_file_from_path`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path) * [🌊 C++ `log_file_from_path`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a20798d7ea74cce5c8174e5cacd0a2c47) You can learn more in our [dedicated page about blueprint re-use](../howto/visualization/reuse-blueprints.md). ### Setting up dataframe view manually in the UI The same [dataframe view](types/views/dataframe_view.md) shown above can be configured purely from the UI: # Entity Queries --- title: Entity Queries order: 100 --- Many views are made up of visualizations that include more than one entity. Rather that requiring you to specify each entity individually, Rerun supports this through "entity queries" that allow you to use "query expressions" to include or exclude entire subtrees. ## Query expression syntax An entity query is made up of a set of "query expressions." Each query expression is either an "inclusion," which starts with an optional `+` or an "exclusion," which always starts with a `-`. Query expressions are also allowed to end with an optional `/**`. The`/**` suffix matches the whole subtree, i.e. self and any child, recursively. For example, `/world/**`matches both`/world`and`/world/car/driver`. Other uses of `*` are not yet supported. When combining multiple query expressions, the rules are sorted by entity-path, from least to most specific: - If there are multiple matching rules, the most specific rule wins. - If there are multiple rules of the same specificity, the last one wins. - If no rules match, the path is excluded. Consider the following example: ```diff + /world/** - /world - /world/car/** + /world/car/driver ``` - The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. - The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. - The last rule matching `/world` is `- /world`, so it is excluded. - The last rule matching `/world/house` is `+ /world/**`, so it is included. ## In the Viewer In the viewer, an entity query is typically displayed as a multi-line edit box, with each query expression shown on its own line. You can find the query editor in the right-hand selection panel when selecting a view. ## In the SDK In the SDK, query expressions are represented as a list or iterable, with each expression written as a separate string. The query expression from above would be written as: ```python rrb.Spatial3DView( contents=[ "+ helix/**, "- helix/structure/scaffolding", ], ), ``` ## `origin` substitution Query expressions also allow you to use the variable `$origin` to refer to the origin of the view that the query belongs to. For example, the above query could be rewritten as: ```python rrb.Spatial3DView( origin="helix", contents=[ "+ $origin/**, "- $origin/structure/scaffolding", ], ), ``` # 💻 Web Viewer API --- title: 💻 Web Viewer API order: 2400 redirect: https://npmjs.com/package/@rerun-io/web-viewer --- # 🐍 Python APIs --- title: 🐍 Python APIs order: 2100 redirect: https://ref.rerun.io/docs/python --- # 🦀 Rust APIs --- title: 🦀 Rust APIs order: 2200 redirect: https://docs.rs/rerun/ --- # Micro Batching --- title: Micro Batching order: 700 redirect: reference/sdk/micro-batching hidden: true --- # Operating Modes --- title: Operating Modes order: 800 redirect: reference/sdk/operating-modes hidden: true --- # SDK configuration --- title: SDK configuration order: 700 redirect: reference/sdk/logging-controls --- # 📖 Code snippets --- title: 📖 Code snippets order: 2500 redirect: https://github.com/rerun-io/rerun/blob/latest/docs/snippets/INDEX.md --- # Datastore compaction --- title: Datastore compaction order: 900 --- The Rerun datastore continuously compacts data as it comes in, in order find a sweet spot between ingestion speed, query performance and memory overhead. The compaction is triggered by both number of rows and number of bytes thresholds, whichever happens to trigger first. This is very similar to, and has many parallels with, the [micro-batching mechanism running on the SDK side](./sdk/micro-batching.md). You can configure these thresholds using the following environment variables: #### RERUN_CHUNK_MAX_BYTES Sets the threshold, in bytes, after which a `Chunk` cannot be compacted any further. Defaults to `RERUN_CHUNK_MAX_BYTES=4194304` (4MiB). #### RERUN_CHUNK_MAX_ROWS Sets the threshold, in rows, after which a `Chunk` cannot be compacted any further. Defaults to `RERUN_CHUNK_MAX_ROWS=4096`. #### RERUN_CHUNK_MAX_ROWS_IF_UNSORTED Sets the threshold, in rows, after which a `Chunk` cannot be compacted any further. Applies specifically to _non_ time-sorted chunks, which can be slower to query. Defaults to `RERUN_CHUNK_MAX_ROWS=1024`. # Types --- title: Types order: 600 --- Rerun has 3 levels of types that can be used in all SDK languages: * [**Archetypes**](types/archetypes.md) - high level bundles of components. * [**Components**](types/components.md) - the base unit of logging data. * [**Data types**](types/datatypes.md) - that make up the individual components. To get an overview of what the Rerun [Viewer](./viewer.md) can show, start at [**Archetypes**](types/archetypes.md). For more information on the relationship between **archetypes** and **components**, check out the concept page on [Entities and Components](../concepts/entity-component.md). # Video --- title: Video order: 400 --- A stream of images (like those produced by a camera) can be logged to Rerun in several different ways: * Uncompressed, as many [`Image`](../reference/types/archetypes/image.md)s * Compressed as many [`EncodedImage`](../reference/types/archetypes/encoded_image.md)s, using e.g. JPEG. * Compressed as a single [`AssetVideo`](../reference/types/archetypes/asset_video.md), using e.g. MP4. These alternatives range on a scale of "simple, lossless, and big" to "complex, lossy, and small". If you want lossless encoded images (with no compression artifacts), then you should log each video frame as `Image`. This will use up a lot of space and bandwidth. You can also encode them as PNG and log them as `EncodedImage`, though it should be noted that PNG encoding usually does very little for the file size of photographic images. If you want to reduce bandwidth and storage cost, you can encode each frame as a JPEG and log it using `EncodedImage`. This can easily reduce the file sizes by almost two orders of magnitude with minimal perceptual loss. This is also very simple to do, and the Python logging SDK has built-in support for it using [`Image.compress`](https://ref.rerun.io/docs/python/0.18.2/common/archetypes/#rerun.archetypes.Image.compress). Finally, you can encode the images as a video file, and log it using `AssetVideo`. This gives the best compression ratio, reducing file sizes and bandwidth requirements. ```python """Log a video asset using automatically determined frame references.""" import sys import rerun as rr if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} ") sys.exit(1) rr.init("rerun_example_asset_video_auto_frames", spawn=True) # Log video asset which is referred to by frame references. video_asset = rr.AssetVideo(path=sys.argv[1]) rr.log("video", video_asset, static=True) # Send automatically determined video frame timestamps. frame_timestamps_ns = video_asset.read_frame_timestamps_ns() rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) ``` ## Video playback limitations Video support is new in Rerun, and has a few limitations: * [#7354](https://github.com/rerun-io/rerun/issues/7354): Only the MP4 container format is supported * [#7755](https://github.com/rerun-io/rerun/issues/7755): No AV1 support on Linux ARM * [#5181](https://github.com/rerun-io/rerun/issues/5181): There is no audio support * [#7594](https://github.com/rerun-io/rerun/issues/7594): HDR video is not supported * There is no video encoder in the Rerun SDK, so you need to create the video file yourself ## Streaming video Rerun does not yet support streaming video support. For scenarios where you don't need live video, you can work around this limitation by logging many small `AssetVideo`s to the same Entity Path. See [#7484](https://github.com/rerun-io/rerun/issues/7484) for more. ## Codec support ### Overview Codec support varies in the web & native viewer: | | Browser | Native | | ---------- | ------- | ------ | | AV1 | ✅ | ✅ | | H.264/avc | ✅ | ✅ | | H.265/hevc | 🔳 | ❌ | | VP9 | ✅ | ❌ | Details see below. When choosing a codec, we recommend [AV1](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#av1), as it seems to have the best overall playback support while also having very high compression quality. Since AV1 can have very long encoding times, it is often not suitable for streaming. In those cases where encoding time matters, we recommend H.264/avc. ### Native viewer #### AV1 AV1 is supported out of the box using a software decoder paired with gpu based image conversion #### H.264/avc H.264/avc is supported via a separately installed `FFmpeg` binary, requiring a minimum version of `5.1`. The viewer does intentionally not come bundled with `FFmpeg` to avoid licensing issues. By default rerun will look for a system installed `FFmpeg` installation in `PATH`, but you can specify a custom path in the viewer's settings. If you select a video that failed to play due to missing or incompatible `FFmpeg` binaries it will offer a download link to a build of `FFmpeg` for your platform. ### Web viewer Video playback in the Rerun Web Viewer is done using the browser's own video decoder, so the exact supported codecs depend on your browser. Overall, we recommend using Chrome or another Chromium-based browser, as it seems to have the best video support as of writing. For decoding video in the Web Viewer, we use the [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API). This API enables us to take advantage of the browser's hardware accelerated video decoding capabilities. It is implemented by all modern browsers, but with varying levels of support for different codecs, and varying levels of quality. When it comes to codecs, we aim to support any codec which the browser supports, but we currently cannot guarantee that all of them will work. For more information about which codecs are supported by which browser, see [Video codecs on MDN](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#codec_details). We tested the following codecs in more detail: | | Linux Firefox | Linux Chrome[^2] | macOS Firefox | macOS Chrome | macOS Safari | Windows Firefox | Windows Chrome[^3] | | ---------- | ------------- | ---------------- | ------------- | ------------ | ------------ | --------------- | ------------------ | | AV1 | ✅ | ✅ | ✅ | ✅ | 🚧[^4] | ✅ | ✅ | | H.264/avc | ✅[^4] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | H.265/hevc | ❌ | ❌ | ❌ | ✅ | 🚧[^5] | ❌ | 🚧[^6] | [^1]: Firefox on Linux has been observed to [stutter when playing back H.264 video](https://github.com/rerun-io/rerun/issues/7532). [^2]: Any Chromium-based browser should work, but we don't test all of them. [^3]: Chrome on Windows has been observed to stutter on playback. It can be mitigated by [using software decoding](https://rerun.io/docs/getting-started/troubleshooting#video-stuttering), but this may lead to high memory usage. See [#7595](https://github.com/rerun-io/rerun/issues/7595). [^4]: Safari/WebKit does not support AV1 decoding except on [Apple Silicon devices with hardware support](https://webkit.org/blog/14445/webkit-features-in-safari-17-0/). [^5]: Safari/WebKit has been observed suttering when playing `hvc1` but working fine with `hevc1`. Despite support being advertised Safari 16.5 has been observed not support H.265 decoding. [^6]: Only supported if hardware encoding is available. Therefore always affected by Windows stuttering issues, see above. Beyond this, for best compatibility we recommend: * prefer YUV over RGB & monochrome formats * don't use more than 8bit per color channel * keep resolutions at 8k & lower (see also [#3782](https://github.com/rerun-io/rerun/issues/3782)) ## Links * [Web video codec guide, by Mozilla](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs) # Viewer --- title: Viewer order: 500 redirect: reference/viewer/overview --- # Blueprint --- title: Blueprint order: 1 --- The blueprint is how you configure what is displayed in the Rerun viewer. It is saved between sessions and is unique to a given [application id](../../concepts/apps-and-recordings.md). The blueprint includes all view configurations, entity groupings and entity settings, also known as _data blueprints_. This view shows the blueprint for the active recording. Everything visible in the [Viewport](viewport.md) has a representation here, making it an easy way to select a View and the [Entities](../../concepts/entity-component.md) it shows. Controls -------- ### Reset The reset button resets the entire blueprint back to its heuristic-chosen default. This includes all settings for entities, Groups and Views. ### Add view With this control you can add new Views for arbitrary [Spaces](../../concepts/spaces-and-transforms.md). Contents -------- Upon hovering any line in the Blueprint panel, you'll find shorthands for removing and hide/show. ### Data blueprints All entities shown in the blueprint panel refer in fact to their Data Blueprints. I.e. the entity plus the associated blueprint settings. As such, all changes made here are only relevant for the View in which they reside. ### Groups Whenever entities are added to a view (either manually or automatically), groupings are automatically created. Groups, despite being derived from the [Entity Path](../../concepts/entity-path.md) are independent of logged data. They are meant to improve the handling of large views and allow for hierarchical manipulation of blueprints. Adding Entities ----------------------------- To (re-)add an entity to a view, you need first need to select the respective view. You then can open a dedicated menu through a button in the [Selection view](selection.md). This allows you to add any entity with a matching [category](viewport.md#view-classes) and a valid [transform](../../concepts/spaces-and-transforms.md) to your view's path. # Overview --- title: Overview order: 0 --- The following sections give an overview of the basic UI concepts and where to find which functionality. Generally, the Viewer tries to be as self-explaining as possible - most items in the UI show a tooltip upon hovering which should give additional information. If you are missing a piece of information, don't hesitate to [file an issue](https://github.com/rerun-io/rerun/issues/new/choose)! Overview -------------------------- ![screenshot of the Viewer with different parts annotated](https://static.rerun.io/a5e708e4bbd2c0b182f7f9103ab42c85e55f8982_viewer-overview.png) ### [Blueprint](blueprint.md) The Blueprint view is where you see and edit the Blueprint for the whole viewer, i.e. what is shown in the Viewer (and how it is shown). ### [Selection](selection.md) The Selection view let's you see details and edit configurations of the current selection(s). ### [Timeline](timeline.md) The timeline panel gives you controls over what point in time you're looking at on which [timeline](../../concepts/timelines.md) for the rest of the viewer. Additionally, it gives you an overview of all events on a given timeline. ### [Viewport](viewport.md) The viewport is where your visualizations live. It is composed of one or more Views that you can arrange freely. ### Top bar & menu The top bar contains operating system controls and generic information. In the menu you find application wide options and actions. Use the buttons at the top right corner to hide/show parts of the viewer. Command Palette ---------------------------- The command palette is a powerful tool to reach arbitrary actions from anywhere via a simple text search. You reach it with `cmd/ctrl + P` or via the menu. Once it's open just start typing to filter and press `Enter` to execute the selected action or cancel with `Esc`. [TODO(#1132)](https://github.com/rerun-io/rerun/issues/1132): The command palette is too limited right now. Help icons ---------- Most views have an info icon at the top right corner. On hover it displays additional information on how to use a view. # Selection --- title: Selection order: 2 --- Making selections is one of the primary ways of exploring data in Rerun. The current selection can be changed with a mouse click on most elements of the - including the [Blueprint](blueprint.md), [Viewport](viewport.md), [Timeline](timeline.md) and even the Selection view itself. Parts of the Selection view --------------------------- ### Selection history Rerun keeps a log of all your selections, allowing you to undo/redo previous selections with the ←/→ buttons at the top of the view or `ctrl + shift + left/right`. Right clicking on the buttons expands the full history ### What is selected Here you find what is selected and for some objects in which context. This context not only gives you a convenient way to jump to related objects, but is also important for what the following sections are showing. ### Data & blueprint sections The data section always shows static, raw user logged data for the currently selected time. Some objects, e.g. Views, may not have a data section and expose only Blueprint options. In contrast, the Blueprint section is timeline independent and exposes the [Blueprint settings](blueprint.md) of an entity in the context of a given View. To learn more about the various settings check the on-hover tooltips. Click-through selections ------------------------ Making selections can be context sensitive to the current selection. The most common case for this is selecting instances of an entity (see also [Batch Data](../../concepts/batches.md)): E.g. in order to select a point of a point cloud in a View, first select the entire entity (the cloud) by clicking on one of the points. Once the cloud is selected, you can further refine that selection by clicking on an individual point. Multi Selection --------------- By holding `cmd/ctrl` upon click, you can add or remove selections from the set of currently selected objects. The selection view shows all selected objects in the order they were added. # Timeline --- title: Timeline order: 3 --- Timeline controls -------------------------- The timeline controls sit at the top of the timeline panel and allow you to control the playback and what [timeline](../../concepts/timelines.md) is active. It lets you select which timeline is currently active and control the replay of the timeline. These controls let you stop play/pause/step/loop time just like a video player. When looping you can choose to loop through the whole recording, or just a sub-section of timeline that you select. The rate of playback can also be sped up or slowed down by adjusting the rate multiplier. Streams ------- The Streams panel can be hidden with the layout config buttons at the top right corner of the viewer. On the right side you see circles for each logged [event](../../concepts/timelines.md) on the currently selected timeline over time. You can use the mouse to scrub the vertical time selector line to jump to arbitrary moments in time. The stream view allows panning with right click and zooming with `ctrl/cmd + scroll`. The tree on the left shows you all entities that were logged for this timeline. When you expand an entity you will see both the components that are associated with it, as well as any child entities. Selecting entities or events in the streams view shows additional information in the selection panel about them respectively. ### Discontinuity skipping Rerun automatically detects discontinuities in the selected timeline and will skip over them while playing. This is particularly useful whenever you have large gaps in the timestamps of your data recordings. Detected discontinuities are visualized with a zigzag cut in the timeline. [TODO(#1150)](https://github.com/rerun-io/rerun/issues/1150): Allow adjusting or disabling the time-discontinuity collapsing. # Viewport --- title: Viewport order: 4 --- The viewport is a flexible area where you can arrange your views: You can grab the title of any view to dock it to different parts of the viewport or to form tabs. ## View controls Clicking on the title of a view has the same effect as selecting it in the [blueprint panel](blueprint.md) and will show additional information and settings in the [selection panel](selection.md). For more information on how to navigate within a specific view, hover its help icon in the top right corner. The maximize button makes a single view fill the entire viewport. Only one view can be maximized at a time. ## View classes Rerun includes multiple view classes, each dedicated to a specific type of visualization; for example, a 3D scene or a timeseries plot. See the [views reference page](../types/views.md) for a list of available view classes. The view class, which is specified upon creation, determines which entities it can display, how it displays them, and the way they can be interacted with. Views can be created both from viewer and from code (see [Configure the Viewer through code](../../howto/configure-viewer-through-code.md)). To learn more about the _internals_ of how view classes work, check the [guide on implementing custom views](../../howto/extend/extend-ui.md). # Archetypes --- title: "Archetypes" order: 1 --- Archetypes are bundles of components for which the Rerun viewer has first-class built-in support. When logged, each archetype also includes an _indicator component_ which captures the intent of the logging code and triggers the activation of the corresponding visualizers. See [Entities and Components](../../concepts/entity-component.md) and [Visualizers and Overrides](../../concepts/visualizers-and-overrides.md) for more information. This page lists all built-in archetypes. ## Geospatial * [`GeoLineStrings`](archetypes/geo_line_strings.md): Geospatial line strings with positions expressed in [EPSG:4326](https://epsg.io/4326) altitude and longitude (North/East-positive degrees), and optional colors and radii. * [`GeoPoints`](archetypes/geo_points.md): Geospatial points with positions expressed in [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees), and optional colors and radii. ## Graph * [`GraphEdges`](archetypes/graph_edges.md): A list of edges in a graph. * [`GraphNodes`](archetypes/graph_nodes.md): A list of nodes in a graph with optional labels, colors, etc. ## Image & tensor * [`DepthImage`](archetypes/depth_image.md): A depth image, i.e. as captured by a depth camera. * [`EncodedImage`](archetypes/encoded_image.md): An image encoded as e.g. a JPEG or PNG. * [`Image`](archetypes/image.md): A monochrome or color image. * [`SegmentationImage`](archetypes/segmentation_image.md): An image made up of integer [`components.ClassId`](https://rerun.io/docs/reference/types/components/class_id)s. * [`Tensor`](archetypes/tensor.md): An N-dimensional array of numbers. ## Plotting * [`BarChart`](archetypes/bar_chart.md): A bar chart. * [`Scalar`](archetypes/scalar.md): A double-precision scalar, e.g. for use for time-series plots. * [`SeriesLine`](archetypes/series_line.md): Define the style properties for a line series in a chart. * [`SeriesPoint`](archetypes/series_point.md): Define the style properties for a point series in a chart. ## Spatial 2D * [`Arrows2D`](archetypes/arrows2d.md): 2D arrows with optional colors, radii, labels, etc. * [`Boxes2D`](archetypes/boxes2d.md): 2D boxes with half-extents and optional center, colors etc. * [`LineStrips2D`](archetypes/line_strips2d.md): 2D line strips with positions and optional colors, radii, labels, etc. * [`Points2D`](archetypes/points2d.md): A 2D point cloud with positions and optional colors, radii, labels, etc. ## Spatial 3D * [`Arrows3D`](archetypes/arrows3d.md): 3D arrows with optional colors, radii, labels, etc. * [`Asset3D`](archetypes/asset3d.md): A prepacked 3D asset (`.gltf`, `.glb`, `.obj`, `.stl`, etc.). * [`Boxes3D`](archetypes/boxes3d.md): 3D boxes with half-extents and optional center, rotations, colors etc. * [`Capsules3D`](archetypes/capsules3d.md): 3D capsules; cylinders with hemispherical caps. * [`Ellipsoids3D`](archetypes/ellipsoids3d.md): 3D ellipsoids or spheres. * [`InstancePoses3D`](archetypes/instance_poses3d.md): One or more transforms between the current entity and its parent. Unlike [`archetypes.Transform3D`](https://rerun.io/docs/reference/types/archetypes/transform3d), it is *not* propagated in the transform hierarchy. * [`LineStrips3D`](archetypes/line_strips3d.md): 3D line strips with positions and optional colors, radii, labels, etc. * [`Mesh3D`](archetypes/mesh3d.md): A 3D triangle mesh as specified by its per-mesh and per-vertex properties. * [`Pinhole`](archetypes/pinhole.md): Camera perspective projection (a.k.a. intrinsics). * [`Points3D`](archetypes/points3d.md): A 3D point cloud with positions and optional colors, radii, labels, etc. * [`Transform3D`](archetypes/transform3d.md): A transform between two 3D spaces, i.e. a pose. * [`ViewCoordinates`](archetypes/view_coordinates.md): How we interpret the coordinate system of an entity/space. ## Text * [`TextDocument`](archetypes/text_document.md): A text element intended to be displayed in its own text box. * [`TextLog`](archetypes/text_log.md): A log entry in a text log, comprised of a text body and its log level. ## Video * [`AssetVideo`](archetypes/asset_video.md): A video binary. * [`VideoFrameReference`](archetypes/video_frame_reference.md): References a single video frame. ## Other * [`AnnotationContext`](archetypes/annotation_context.md): The annotation context provides additional information on how to display entities. * [`Clear`](archetypes/clear.md): Empties all the components of an entity. # Components --- title: "Components" order: 2 --- Components are the fundamental unit of logging in Rerun. This page lists all built-in components. An entity can only ever contain a single array of any given component type. If you log the same component several times on an entity, the last value (or array of values) will overwrite the previous. For more information on the relationship between **archetypes** and **components**, check out the concept page on [Entities and Components](../../concepts/entity-component.md). * [`AggregationPolicy`](components/aggregation_policy.md): Policy for aggregation of multiple scalar plot values. * [`AlbedoFactor`](components/albedo_factor.md): A color multiplier, usually applied to a whole entity, e.g. a mesh. * [`AnnotationContext`](components/annotation_context.md): The annotation context provides additional information on how to display entities. * [`AxisLength`](components/axis_length.md): The length of an axis in local units of the space. * [`Blob`](components/blob.md): A binary blob of data. * [`ClassId`](components/class_id.md): A 16-bit ID representing a type of semantic class. * [`ClearIsRecursive`](components/clear_is_recursive.md): Configures how a clear operation should behave - recursive or not. * [`Color`](components/color.md): An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. * [`Colormap`](components/colormap.md): Colormap for mapping scalar values within a given range to a color. * [`DepthMeter`](components/depth_meter.md): The world->depth map scaling factor. * [`DrawOrder`](components/draw_order.md): Draw order of 2D elements. Higher values are drawn on top of lower values. * [`EntityPath`](components/entity_path.md): A path to an entity, usually to reference some data that is part of the target entity. * [`FillMode`](components/fill_mode.md): How a geometric shape is drawn and colored. * [`FillRatio`](components/fill_ratio.md): How much a primitive fills out the available space. * [`GammaCorrection`](components/gamma_correction.md): A gamma correction value to be used with a scalar value or color. * [`GeoLineString`](components/geo_line_string.md): A geospatial line string expressed in [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees). * [`GraphEdge`](components/graph_edge.md): An edge in a graph connecting two nodes. * [`GraphNode`](components/graph_node.md): A string-based ID representing a node in a graph. * [`GraphType`](components/graph_type.md): Specifies if a graph has directed or undirected edges. * [`HalfSize2D`](components/half_size2d.md): Half-size (radius) of a 2D box. * [`HalfSize3D`](components/half_size3d.md): Half-size (radius) of a 3D box. * [`ImageBuffer`](components/image_buffer.md): A buffer that is known to store image data. * [`ImageFormat`](components/image_format.md): The metadata describing the contents of a [`components.ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer). * [`ImagePlaneDistance`](components/image_plane_distance.md): The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. * [`KeypointId`](components/keypoint_id.md): A 16-bit ID representing a type of semantic keypoint within a class. * [`LatLon`](components/lat_lon.md): A geospatial position expressed in [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees). * [`Length`](components/length.md): Length, or one-dimensional size. * [`LineStrip2D`](components/line_strip2d.md): A line strip in 2D space. * [`LineStrip3D`](components/line_strip3d.md): A line strip in 3D space. * [`MagnificationFilter`](components/magnification_filter.md): Filter used when magnifying an image/texture such that a single pixel/texel is displayed as multiple pixels on screen. * [`MarkerShape`](components/marker_shape.md): The visual appearance of a point in e.g. a 2D plot. * [`MarkerSize`](components/marker_size.md): Radius of a marker of a point in e.g. a 2D plot, measured in UI points. * [`MediaType`](components/media_type.md): A standardized media type (RFC2046, formerly known as MIME types), encoded as a string. * [`Name`](components/name.md): A display name, typically for an entity or a item like a plot series. * [`Opacity`](components/opacity.md): Degree of transparency ranging from 0.0 (fully transparent) to 1.0 (fully opaque). * [`PinholeProjection`](components/pinhole_projection.md): Camera projection, from image coordinates to view coordinates. * [`Plane3D`](components/plane3d.md): An infinite 3D plane represented by a unit normal vector and a distance. * [`PoseRotationAxisAngle`](components/pose_rotation_axis_angle.md): 3D rotation represented by a rotation around a given axis that doesn't propagate in the transform hierarchy. * [`PoseRotationQuat`](components/pose_rotation_quat.md): A 3D rotation expressed as a quaternion that doesn't propagate in the transform hierarchy. * [`PoseScale3D`](components/pose_scale3d.md): A 3D scale factor that doesn't propagate in the transform hierarchy. * [`PoseTransformMat3x3`](components/pose_transform_mat3x3.md): A 3x3 transformation matrix Matrix that doesn't propagate in the transform hierarchy. * [`PoseTranslation3D`](components/pose_translation3d.md): A translation vector in 3D space that doesn't propagate in the transform hierarchy. * [`Position2D`](components/position2d.md): A position in 2D space. * [`Position3D`](components/position3d.md): A position in 3D space. * [`Radius`](components/radius.md): The radius of something, e.g. a point. * [`Range1D`](components/range1d.md): A 1D range, specifying a lower and upper bound. * [`RecordingUri`](components/recording_uri.md): A recording URI (Uniform Resource Identifier). * [`Resolution`](components/resolution.md): Pixel resolution width & height, e.g. of a camera sensor. * [`RotationAxisAngle`](components/rotation_axis_angle.md): 3D rotation represented by a rotation around a given axis. * [`RotationQuat`](components/rotation_quat.md): A 3D rotation expressed as a quaternion. * [`Scalar`](components/scalar.md): A scalar value, encoded as a 64-bit floating point. * [`Scale3D`](components/scale3d.md): A 3D scale factor. * [`ShowLabels`](components/show_labels.md): Whether the entity's [`components.Text`](https://rerun.io/docs/reference/types/components/text) label is shown. * [`StrokeWidth`](components/stroke_width.md): The width of a stroke specified in UI points. * [`TensorData`](components/tensor_data.md): An N-dimensional array of numbers. * [`TensorDimensionIndexSelection`](components/tensor_dimension_index_selection.md): Specifies a concrete index on a tensor dimension. * [`TensorHeightDimension`](components/tensor_height_dimension.md): Specifies which dimension to use for height. * [`TensorWidthDimension`](components/tensor_width_dimension.md): Specifies which dimension to use for width. * [`Texcoord2D`](components/texcoord2d.md): A 2D texture UV coordinate. * [`Text`](components/text.md): A string of text, e.g. for labels and text documents. * [`TextLogLevel`](components/text_log_level.md): The severity level of a text log message. * [`TransformMat3x3`](components/transform_mat3x3.md): A 3x3 transformation matrix Matrix. * [`TransformRelation`](components/transform_relation.md): Specifies relation a spatial transform describes. * [`Translation3D`](components/translation3d.md): A translation vector in 3D space. * [`TriangleIndices`](components/triangle_indices.md): The three indices of a triangle in a triangle mesh. * [`ValueRange`](components/value_range.md): Range of expected or valid values, specifying a lower and upper bound. * [`Vector2D`](components/vector2d.md): A vector in 2D space. * [`Vector3D`](components/vector3d.md): A vector in 3D space. * [`VideoTimestamp`](components/video_timestamp.md): Timestamp inside a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video). * [`ViewCoordinates`](components/view_coordinates.md): How we interpret the coordinate system of an entity/space. # Datatypes --- title: "Datatypes" order: 3 --- Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components. * [`Angle`](datatypes/angle.md): Angle in radians. * [`AnnotationInfo`](datatypes/annotation_info.md): Annotation info annotating a class id or key-point id. * [`Blob`](datatypes/blob.md): A binary blob of data. * [`Bool`](datatypes/bool.md): A single boolean. * [`ChannelDatatype`](datatypes/channel_datatype.md): The innermost datatype of an image. * [`ClassDescription`](datatypes/class_description.md): The description of a semantic Class. * [`ClassDescriptionMapElem`](datatypes/class_description_map_elem.md): A helper type for mapping [`datatypes.ClassId`](https://rerun.io/docs/reference/types/datatypes/class_id)s to class descriptions. * [`ClassId`](datatypes/class_id.md): A 16-bit ID representing a type of semantic class. * [`ColorModel`](datatypes/color_model.md): Specified what color components are present in an [`archetypes.Image`](https://rerun.io/docs/reference/types/archetypes/image). * [`DVec2D`](datatypes/dvec2d.md): A double-precision vector in 2D space. * [`EntityPath`](datatypes/entity_path.md): A path to an entity in the `ChunkStore`. * [`Float32`](datatypes/float32.md): A single-precision 32-bit IEEE 754 floating point number. * [`Float64`](datatypes/float64.md): A double-precision 64-bit IEEE 754 floating point number. * [`ImageFormat`](datatypes/image_format.md): The metadata describing the contents of a [`components.ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer). * [`KeypointId`](datatypes/keypoint_id.md): A 16-bit ID representing a type of semantic keypoint within a class. * [`KeypointPair`](datatypes/keypoint_pair.md): A connection between two [`datatypes.KeypointId`](https://rerun.io/docs/reference/types/datatypes/keypoint_id)s. * [`Mat3x3`](datatypes/mat3x3.md): A 3x3 Matrix. * [`Mat4x4`](datatypes/mat4x4.md): A 4x4 Matrix. * [`PixelFormat`](datatypes/pixel_format.md): Specifieds a particular format of an [`archetypes.Image`](https://rerun.io/docs/reference/types/archetypes/image). * [`Plane3D`](datatypes/plane3d.md): An infinite 3D plane represented by a unit normal vector and a distance. * [`Quaternion`](datatypes/quaternion.md): A Quaternion represented by 4 real numbers. * [`Range1D`](datatypes/range1d.md): A 1D range, specifying a lower and upper bound. * [`Range2D`](datatypes/range2d.md): An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. * [`Rgba32`](datatypes/rgba32.md): An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. * [`RotationAxisAngle`](datatypes/rotation_axis_angle.md): 3D rotation represented by a rotation around a given axis. * [`TensorBuffer`](datatypes/tensor_buffer.md): The underlying storage for [`archetypes.Tensor`](https://rerun.io/docs/reference/types/archetypes/tensor). * [`TensorData`](datatypes/tensor_data.md): An N-dimensional array of numbers. * [`TensorDimensionIndexSelection`](datatypes/tensor_dimension_index_selection.md): Indexing a specific tensor dimension. * [`TensorDimensionSelection`](datatypes/tensor_dimension_selection.md): Selection of a single tensor dimension. * [`TimeInt`](datatypes/time_int.md): A 64-bit number describing either nanoseconds OR sequence numbers. * [`TimeRange`](datatypes/time_range.md): Visible time range bounds for a specific timeline. * [`TimeRangeBoundary`](datatypes/time_range_boundary.md): Left or right boundary of a time range. * [`UInt16`](datatypes/uint16.md): A 16bit unsigned integer. * [`UInt32`](datatypes/uint32.md): A 32bit unsigned integer. * [`UInt64`](datatypes/uint64.md): A 64bit unsigned integer. * [`UVec2D`](datatypes/uvec2d.md): A uint32 vector in 2D space. * [`UVec3D`](datatypes/uvec3d.md): A uint32 vector in 3D space. * [`UVec4D`](datatypes/uvec4d.md): A uint vector in 4D space. * [`Utf8`](datatypes/utf8.md): A string of text, encoded as UTF-8. * [`Utf8Pair`](datatypes/utf8pair.md): Stores a tuple of UTF-8 strings. * [`Uuid`](datatypes/uuid.md): A 16-byte UUID. * [`Vec2D`](datatypes/vec2d.md): A vector in 2D space. * [`Vec3D`](datatypes/vec3d.md): A vector in 3D space. * [`Vec4D`](datatypes/vec4d.md): A vector in 4D space. * [`VideoTimestamp`](datatypes/video_timestamp.md): Presentation timestamp within a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video). * [`ViewCoordinates`](datatypes/view_coordinates.md): How we interpret the coordinate system of an entity/space. * [`VisibleTimeRange`](datatypes/visible_time_range.md): Visible time range bounds for a specific timeline. # Views --- title: "Views" order: 4 --- Views are the panels shown in the viewer's viewport and the primary means of inspecting & visualizing previously logged data. This page lists all built-in views. * [`BarChartView`](views/bar_chart_view.md): A bar chart view. * [`DataframeView`](views/dataframe_view.md): A view to display any data in a tabular form. * [`GraphView`](views/graph_view.md): A graph view to display time-variying, directed or undirected graph visualization. * [`MapView`](views/map_view.md): A 2D map view to display geospatial primitives. * [`Spatial2DView`](views/spatial2d_view.md): For viewing spatial 2D data. * [`Spatial3DView`](views/spatial3d_view.md): For viewing spatial 3D data. * [`TensorView`](views/tensor_view.md): A view on a tensor of any dimensionality. * [`TextDocumentView`](views/text_document_view.md): A view of a single text document, for use with [`archetypes.TextDocument`](https://rerun.io/docs/reference/types/archetypes/text_document). * [`TextLogView`](views/text_log_view.md): A view of a text log, for use with [`archetypes.TextLog`](https://rerun.io/docs/reference/types/archetypes/text_log). * [`TimeSeriesView`](views/time_series_view.md): A time series view for scalars over time, for use with [`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). # BarChartView --- title: "BarChartView" --- A bar chart view. ## Properties ### `plot_legend` Configures the legend of the plot. * `corner`: To what corner the legend is aligned. * `visible`: Whether the legend is shown at all. ## API reference links * 🐍 [Python API docs for `BarChartView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.BarChartView) ## Example ### Use a blueprint to create a BarChartView. ```python """Use a blueprint to show a bar chart.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_bar_chart", spawn=True) # It's recommended to log bar charts with the `rr.BarChart` archetype, # but single dimensional tensors can also be used if a `BarChartView` is created explicitly. rr.log("tensor", rr.Tensor([8, 4, 0, 9, 1, 4, 1, 6, 9, 0])) # Create a bar chart view to display the chart. blueprint = rrb.Blueprint(rrb.BarChartView(origin="tensor", name="Bar Chart"), collapse_panels=True) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`BarChart`](../archetypes/bar_chart.md) * [`Tensor`](../archetypes/tensor.md) (for 1D tensors) # DataframeView --- title: "DataframeView" --- A view to display any data in a tabular form. Any data from the store can be shown, using a flexibly, user-configurable query. ## Properties ### `query` Query of the dataframe. * `timeline`: The timeline for this query. * `filter_by_range`: If provided, only rows whose timestamp is within this range will be shown. * `filter_is_not_null`: If provided, only show rows which contains a logged event for the specified component. * `apply_latest_at`: Should empty cells be filled with latest-at queries? * `select`: Selected columns. If unset, all columns are selected. ## API reference links * 🐍 [Python API docs for `DataframeView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.DataframeView) ## Example ### Use a blueprint to customize a DataframeView. ```python """Use a blueprint to customize a DataframeView.""" import math import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_dataframe", spawn=True) # Log some data. for t in range(0, int(math.pi * 4 * 100.0)): rr.set_time_seconds("t", t) rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0))) rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0))) # some sparse data if t % 5 == 0: rr.log("trig/tan_sparse", rr.Scalar(math.tan(float(t) / 100.0))) # Create a Dataframe View blueprint = rrb.Blueprint( rrb.DataframeView( origin="/trig", query=rrb.archetypes.DataframeQuery( timeline="t", filter_by_range=(rr.TimeInt(seconds=0), rr.TimeInt(seconds=20)), filter_is_not_null="/trig/tan_sparse:Scalar", select=["t", "log_tick", "/trig/sin:Scalar", "/trig/cos:Scalar", "/trig/tan_sparse:Scalar"], ), ), ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes Any data can be displayed by the Dataframe view. # GraphView --- title: "GraphView" --- A graph view to display time-variying, directed or undirected graph visualization. ## Properties ### `visual_bounds` Everything within these bounds is guaranteed to be visible. Somethings outside of these bounds may also be visible due to letterboxing. ### `force_link` Allows to control the interaction between two nodes connected by an edge. * `enabled`: Whether the link force is enabled. * `distance`: The target distance between two nodes. * `iterations`: Specifies how often this force should be applied per iteration. ### `force_many_body` A force between each pair of nodes that ressembles an electrical charge. * `enabled`: Whether the many body force is enabled. * `strength`: The strength of the force. ### `force_position` Similar to gravity, this force pulls nodes towards a specific position. * `enabled`: Whether the position force is enabled. * `strength`: The strength of the force. * `position`: The position where the nodes should be pulled towards. ### `force_collision_radius` Resolves collisions between the bounding spheres, according to the radius of the nodes. * `enabled`: Whether the collision force is enabled. * `strength`: The strength of the force. * `iterations`: Specifies how often this force should be applied per iteration. ### `force_center` Tries to move the center of mass of the graph to the origin. * `enabled`: Whether the center force is enabled. * `strength`: The strength of the force. ## API reference links * 🐍 [Python API docs for `GraphView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.GraphView) ## Example ### Use a blueprint to create a graph view. ```python """Use a blueprint to customize a graph view.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_graph_view", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"] ), ) # Create a Spatial2D view to display the points. blueprint = rrb.Blueprint( rrb.GraphView( origin="/", name="Graph", # Note that this translates the viewbox. visual_bounds=rrb.VisualBounds2D(x_range=[-150, 150], y_range=[-50, 150]), ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`GraphEdges`](../archetypes/graph_edges.md) * [`GraphNodes`](../archetypes/graph_nodes.md) # MapView --- title: "MapView" --- A 2D map view to display geospatial primitives. ## Properties ### `zoom` Configures the zoom level of the map view. ### `background` Configuration for the background map of the map view. ## API reference links * 🐍 [Python API docs for `MapView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.MapView) ## Example ### Use a blueprint to create a map view. ```python """Use a blueprint to customize a map view.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_map_view", spawn=True) rr.log("points", rr.GeoPoints(lat_lon=[[47.6344, 19.1397], [47.6334, 19.1399]], radii=rr.Radius.ui_points(20.0))) # Create a map view to display the chart. blueprint = rrb.Blueprint( rrb.MapView( origin="points", name="MapView", zoom=16.0, background=rrb.MapProvider.OpenStreetMap, ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`GeoLineStrings`](../archetypes/geo_line_strings.md) * [`GeoPoints`](../archetypes/geo_points.md) # Spatial2DView --- title: "Spatial2DView" --- For viewing spatial 2D data. ## Properties ### `background` Configuration for the background of the view. * `kind`: The type of the background. * `color`: Color used for the solid background type. ### `visual_bounds` The visible parts of the scene, in the coordinate space of the scene. Everything within these bounds are guaranteed to be visible. Somethings outside of these bounds may also be visible due to letterboxing. ### `time_ranges` Configures which range on each timeline is shown by this view (unless specified differently per entity). If not specified, the default is to show the latest state of each component. If a timeline is specified more than once, the first entry will be used. ## API reference links * 🐍 [Python API docs for `Spatial2DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial2DView) ## Example ### Use a blueprint to customize a Spatial2DView. ```python """Use a blueprint to customize a Spatial2DView.""" import numpy as np import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_spatial_2d", spawn=True) # Create a spiral of points: n = 150 angle = np.linspace(0, 10 * np.pi, n) spiral_radius = np.linspace(0.0, 3.0, n) ** 2 positions = np.column_stack((np.cos(angle) * spiral_radius, np.sin(angle) * spiral_radius)) colors = np.dstack((np.linspace(255, 255, n), np.linspace(255, 0, n), np.linspace(0, 255, n)))[0].astype(int) radii = np.linspace(0.01, 0.7, n) rr.log("points", rr.Points2D(positions, colors=colors, radii=radii)) # Create a Spatial2D view to display the points. blueprint = rrb.Blueprint( rrb.Spatial2DView( origin="/", name="2D Scene", # Set the background color background=[105, 20, 105], # Note that this range is smaller than the range of the points, # so some points will not be visible. visual_bounds=rrb.VisualBounds2D(x_range=[-5, 5], y_range=[-5, 5]), ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`AnnotationContext`](../archetypes/annotation_context.md) * [`Arrows2D`](../archetypes/arrows2d.md) * [`AssetVideo`](../archetypes/asset_video.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`Clear`](../archetypes/clear.md) * [`DepthImage`](../archetypes/depth_image.md) * [`EncodedImage`](../archetypes/encoded_image.md) * [`Image`](../archetypes/image.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`Pinhole`](../archetypes/pinhole.md) * [`Pinhole`](../archetypes/pinhole.md) * [`Points2D`](../archetypes/points2d.md) * [`SegmentationImage`](../archetypes/segmentation_image.md) * [`VideoFrameReference`](../archetypes/video_frame_reference.md) * [`Arrows3D`](../archetypes/arrows3d.md) (if logged above active projection) * [`Asset3D`](../archetypes/asset3d.md) (if logged above active projection) * [`Boxes3D`](../archetypes/boxes3d.md) (if logged above active projection) * [`Capsules3D`](../archetypes/capsules3d.md) (if logged above active projection) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) (if logged above active projection) * [`InstancePoses3D`](../archetypes/instance_poses3d.md) (if logged above active projection) * [`LineStrips3D`](../archetypes/line_strips3d.md) (if logged above active projection) * [`Mesh3D`](../archetypes/mesh3d.md) (if logged above active projection) * [`Points3D`](../archetypes/points3d.md) (if logged above active projection) * [`Transform3D`](../archetypes/transform3d.md) (if logged above active projection) # Spatial3DView --- title: "Spatial3DView" --- For viewing spatial 3D data. ## Properties ### `background` Configuration for the background of the view. * `kind`: The type of the background. * `color`: Color used for the solid background type. ### `line_grid` Configuration for the 3D line grid. * `visible`: Whether the grid is visible. * `spacing`: Space between grid lines spacing of one line to the next in scene units. * `plane`: In what plane the grid is drawn. * `stroke_width`: How thick the lines should be in ui units. * `color`: Color used for the grid. ### `time_ranges` Configures which range on each timeline is shown by this view (unless specified differently per entity). If not specified, the default is to show the latest state of each component. If a timeline is specified more than once, the first entry will be used. ## API reference links * 🐍 [Python API docs for `Spatial3DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial3DView) ## Example ### Use a blueprint to customize a Spatial3DView. ```python """Use a blueprint to customize a Spatial3DView.""" import rerun as rr import rerun.blueprint as rrb from numpy.random import default_rng rr.init("rerun_example_spatial_3d", spawn=True) # Create some random points. rng = default_rng(12345) positions = rng.uniform(-5, 5, size=[50, 3]) colors = rng.uniform(0, 255, size=[50, 3]) radii = rng.uniform(0.1, 0.5, size=[50]) rr.log("points", rr.Points3D(positions, colors=colors, radii=radii)) rr.log("box", rr.Boxes3D(half_sizes=[5, 5, 5], colors=0)) # Create a Spatial3D view to display the points. blueprint = rrb.Blueprint( rrb.Spatial3DView( origin="/", name="3D Scene", # Set the background color to light blue. background=[100, 149, 237], # Configure the line grid. line_grid=rrb.archetypes.LineGrid3D( visible=True, # The grid is enabled by default, but you can hide it with this property. spacing=0.1, # Makes the grid more fine-grained. # By default, the plane is inferred from view coordinates setup, but you can set arbitrary planes. plane=rr.components.Plane3D.XY.with_distance(-5.0), stroke_width=2.0, # Makes the grid lines twice as thick as usual. color=[255, 255, 255, 128], # Colors the grid a half-transparent white. ), ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`AnnotationContext`](../archetypes/annotation_context.md) * [`Arrows3D`](../archetypes/arrows3d.md) * [`Asset3D`](../archetypes/asset3d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Clear`](../archetypes/clear.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`InstancePoses3D`](../archetypes/instance_poses3d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) * [`Points3D`](../archetypes/points3d.md) * [`Transform3D`](../archetypes/transform3d.md) * [`ViewCoordinates`](../archetypes/view_coordinates.md) * [`Arrows2D`](../archetypes/arrows2d.md) (if logged under a projection) * [`AssetVideo`](../archetypes/asset_video.md) (if logged under a projection) * [`Boxes2D`](../archetypes/boxes2d.md) (if logged under a projection) * [`DepthImage`](../archetypes/depth_image.md) (if logged under a projection) * [`EncodedImage`](../archetypes/encoded_image.md) (if logged under a projection) * [`Image`](../archetypes/image.md) (if logged under a projection) * [`LineStrips2D`](../archetypes/line_strips2d.md) (if logged under a projection) * [`Points2D`](../archetypes/points2d.md) (if logged under a projection) * [`SegmentationImage`](../archetypes/segmentation_image.md) (if logged under a projection) * [`VideoFrameReference`](../archetypes/video_frame_reference.md) (if logged under a projection) # TensorView --- title: "TensorView" --- A view on a tensor of any dimensionality. ## Properties ### `slice_selection` How to select the slice of the tensor to show. * `width`: Which dimension to map to width. * `height`: Which dimension to map to height. * `indices`: Selected indices for all other dimensions. * `slider`: Any dimension listed here will have a slider for the index. ### `scalar_mapping` Configures how scalars are mapped to color. * `mag_filter`: Filter used when zooming in on the tensor. * `colormap`: How scalar values map to colors. * `gamma`: Gamma exponent applied to normalized values before mapping to color. ### `view_fit` Configures how the selected slice should fit into the view. ## API reference links * 🐍 [Python API docs for `TensorView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TensorView) ## Example ### Use a blueprint to create a TensorView. ```python """Use a blueprint to show a tensor view.""" import numpy as np import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_tensor", spawn=True) tensor = np.random.randint(0, 256, (32, 240, 320, 3), dtype=np.uint8) rr.log("tensor", rr.Tensor(tensor, dim_names=("batch", "x", "y", "channel"))) blueprint = rrb.Blueprint( rrb.TensorView( origin="tensor", name="Tensor", # Explicitly pick which dimensions to show. slice_selection=rrb.TensorSliceSelection( # Use the first dimension as width. width=1, # Use the second dimension as height and invert it. height=rr.TensorDimensionSelection(dimension=2, invert=True), # Set which indices to show for the other dimensions. indices=[ rr.TensorDimensionIndexSelection(dimension=2, index=4), rr.TensorDimensionIndexSelection(dimension=3, index=5), ], # Show a slider for dimension 2 only. If not specified, all dimensions in `indices` will have sliders. slider=[2], ), # Set a scalar mapping with a custom colormap, gamma and magnification filter. scalar_mapping=rrb.TensorScalarMapping(colormap="turbo", gamma=1.5, mag_filter="linear"), # Fill the view, ignoring aspect ratio. view_fit="fill", ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`Tensor`](../archetypes/tensor.md) # TextDocumentView --- title: "TextDocumentView" --- A view of a single text document, for use with [`archetypes.TextDocument`](https://rerun.io/docs/reference/types/archetypes/text_document). ## API reference links * 🐍 [Python API docs for `TextDocumentView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TextDocumentView) ## Example ### Use a blueprint to show a text document. ```python """Use a blueprint to show a text document.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_text_document", spawn=True) rr.log( "markdown", rr.TextDocument( ''' # Hello Markdown! [Click here to see the raw text](recording://markdown:Text). Basic formatting: | **Feature** | **Alternative** | | ----------------- | --------------- | | Plain | | | *italics* | _italics_ | | **bold** | __bold__ | | ~~strikethrough~~ | | | `inline code` | | ---------------------------------- ## Support - [x] [Commonmark](https://commonmark.org/help/) support - [x] GitHub-style strikethrough, tables, and checkboxes - Basic syntax highlighting for: - [x] C and C++ - [x] Python - [x] Rust - [ ] Other languages ## Links You can link to [an entity](recording://markdown), a [specific instance of an entity](recording://markdown[#0]), or a [specific component](recording://markdown:Text). Of course you can also have [normal https links](https://github.com/rerun-io/rerun), e.g. . ## Image ![A random image](https://picsum.photos/640/480) '''.strip(), media_type=rr.MediaType.MARKDOWN, ), ) # Create a text view that displays the markdown. blueprint = rrb.Blueprint(rrb.TextDocumentView(origin="markdown", name="Markdown example"), collapse_panels=True) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`TextDocument`](../archetypes/text_document.md) # TextLogView --- title: "TextLogView" --- A view of a text log, for use with [`archetypes.TextLog`](https://rerun.io/docs/reference/types/archetypes/text_log). ## API reference links * 🐍 [Python API docs for `TextLogView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TextLogView) ## Example ### Use a blueprint to show a TextLogView. ```python """Use a blueprint to show a text log.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_text_log", spawn=True) rr.set_time_sequence("time", 0) rr.log("log/status", rr.TextLog("Application started.", level=rr.TextLogLevel.INFO)) rr.set_time_sequence("time", 5) rr.log("log/other", rr.TextLog("A warning.", level=rr.TextLogLevel.WARN)) for i in range(10): rr.set_time_sequence("time", i) rr.log("log/status", rr.TextLog(f"Processing item {i}.", level=rr.TextLogLevel.INFO)) # Create a text view that displays all logs. blueprint = rrb.Blueprint(rrb.TextLogView(origin="/log", name="Text Logs"), collapse_panels=True) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`TextLog`](../archetypes/text_log.md) # TimeSeriesView --- title: "TimeSeriesView" --- A time series view for scalars over time, for use with [`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). ## Properties ### `axis_y` Configures the vertical axis of the plot. * `range`: The range of the axis. * `zoom_lock`: If enabled, the Y axis range will remain locked to the specified range when zooming. ### `plot_legend` Configures the legend of the plot. * `corner`: To what corner the legend is aligned. * `visible`: Whether the legend is shown at all. ### `time_ranges` Configures which range on each timeline is shown by this view (unless specified differently per entity). If not specified, the default is to show the entire timeline. If a timeline is specified more than once, the first entry will be used. ## API reference links * 🐍 [Python API docs for `TimeSeriesView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TimeSeriesView) ## Example ### Use a blueprint to customize a TimeSeriesView. ```python """Use a blueprint to customize a TimeSeriesView.""" import math import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_timeseries", spawn=True) # Log some trigonometric functions rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) rr.log("trig/cos", rr.SeriesLine(color=[0, 0, 255], name="cos(0.01t) scaled"), static=True) for t in range(0, int(math.pi * 4 * 100.0)): rr.set_time_sequence("timeline0", t) rr.set_time_seconds("timeline1", t) rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0))) rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0))) rr.log("trig/cos_scaled", rr.Scalar(math.cos(float(t) / 100.0) * 2.0)) # Create a TimeSeries View blueprint = rrb.Blueprint( rrb.TimeSeriesView( origin="/trig", # Set a custom Y axis. axis_y=rrb.ScalarAxis(range=(-1.0, 1.0), zoom_lock=True), # Configure the legend. plot_legend=rrb.PlotLegend(visible=False), # Set time different time ranges for different timelines. time_ranges=[ # Sliding window depending on the time cursor for the first timeline. rrb.VisibleTimeRange( "timeline0", start=rrb.TimeRangeBoundary.cursor_relative(seq=-100), end=rrb.TimeRangeBoundary.cursor_relative(), ), # Time range from some point to the end of the timeline for the second timeline. rrb.VisibleTimeRange( "timeline1", start=rrb.TimeRangeBoundary.absolute(seconds=300.0), end=rrb.TimeRangeBoundary.infinite(), ), ], ), collapse_panels=True, ) rr.send_blueprint(blueprint) ``` ## Visualized archetypes * [`Clear`](../archetypes/clear.md) * [`Scalar`](../archetypes/scalar.md) * [`SeriesLine`](../archetypes/series_line.md) * [`SeriesPoint`](../archetypes/series_point.md) # Angle --- title: "Angle" --- Angle in radians. ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `Angle`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Angle.html) * 🐍 [Python API docs for `Angle`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Angle) * 🦀 [Rust API docs for `Angle`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Angle.html) ## Used by * [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) # AnnotationInfo --- title: "AnnotationInfo" --- Annotation info annotating a class id or key-point id. Color and label will be used to annotate entities/keypoints which reference the id. The id refers either to a class or key-point id ## Fields #### `id` Type: `uint16` [`datatypes.ClassId`](https://rerun.io/docs/reference/types/datatypes/class_id) or [`datatypes.KeypointId`](https://rerun.io/docs/reference/types/datatypes/keypoint_id) to which this annotation info belongs. #### `label` Type: nullable [`Utf8`](../datatypes/utf8.md) The label that will be shown in the UI. #### `color` Type: nullable [`Rgba32`](../datatypes/rgba32.md) The color that will be applied to the annotated entity. ## Arrow datatype ``` Struct { id: uint16 label: nullable utf8 color: nullable uint32 } ``` ## API reference links * 🌊 [C++ API docs for `AnnotationInfo`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1AnnotationInfo.html) * 🐍 [Python API docs for `AnnotationInfo`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.AnnotationInfo) * 🦀 [Rust API docs for `AnnotationInfo`](https://docs.rs/rerun/latest/rerun/datatypes/struct.AnnotationInfo.html) ## Used by * [`ClassDescription`](../datatypes/class_description.md) # Blob --- title: "Blob" --- A binary blob of data. ## Arrow datatype ``` List ``` ## API reference links * 🌊 [C++ API docs for `Blob`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Blob.html) * 🐍 [Python API docs for `Blob`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Blob) * 🦀 [Rust API docs for `Blob`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Blob.html) ## Used by * [`Blob`](../components/blob.md) * [`ImageBuffer`](../components/image_buffer.md) # Bool --- title: "Bool" --- A single boolean. ## Arrow datatype ``` boolean ``` ## API reference links * 🌊 [C++ API docs for `Bool`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Bool.html) * 🐍 [Python API docs for `Bool`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Bool) * 🦀 [Rust API docs for `Bool`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Bool.html) ## Used by * [`ClearIsRecursive`](../components/clear_is_recursive.md) * [`ShowLabels`](../components/show_labels.md) # ChannelDatatype --- title: "ChannelDatatype" --- The innermost datatype of an image. How individual color channel components are encoded. ## Variants #### `U8` = 6 8-bit unsigned integer. #### `I8` = 7 8-bit signed integer. #### `U16` = 8 16-bit unsigned integer. #### `I16` = 9 16-bit signed integer. #### `U32` = 10 32-bit unsigned integer. #### `I32` = 11 32-bit signed integer. #### `U64` = 12 64-bit unsigned integer. #### `I64` = 13 64-bit signed integer. #### `F16` = 33 16-bit IEEE-754 floating point, also known as `half`. #### `F32` = 34 32-bit IEEE-754 floating point, also known as `float` or `single`. #### `F64` = 35 64-bit IEEE-754 floating point, also known as `double`. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `ChannelDatatype`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1datatypes.html) * 🐍 [Python API docs for `ChannelDatatype`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ChannelDatatype) * 🦀 [Rust API docs for `ChannelDatatype`](https://docs.rs/rerun/latest/rerun/datatypes/enum.ChannelDatatype.html) ## Used by * [`ImageFormat`](../datatypes/image_format.md) # ClassDescription --- title: "ClassDescription" --- The description of a semantic Class. If an entity is annotated with a corresponding [`components.ClassId`](https://rerun.io/docs/reference/types/components/class_id), Rerun will use the attached [`datatypes.AnnotationInfo`](https://rerun.io/docs/reference/types/datatypes/annotation_info) to derive labels and colors. Keypoints within an annotation class can similarly be annotated with a [`components.KeypointId`](https://rerun.io/docs/reference/types/components/keypoint_id) in which case we should defer to the label and color for the [`datatypes.AnnotationInfo`](https://rerun.io/docs/reference/types/datatypes/annotation_info) specifically associated with the Keypoint. Keypoints within the class can also be decorated with skeletal edges. Keypoint-connections are pairs of [`components.KeypointId`](https://rerun.io/docs/reference/types/components/keypoint_id)s. If an edge is defined, and both keypoints exist within the instance of the class, then the keypoints should be connected with an edge. The edge should be labeled and colored as described by the class's [`datatypes.AnnotationInfo`](https://rerun.io/docs/reference/types/datatypes/annotation_info). ## Fields #### `info` Type: [`AnnotationInfo`](../datatypes/annotation_info.md) The [`datatypes.AnnotationInfo`](https://rerun.io/docs/reference/types/datatypes/annotation_info) for the class. #### `keypoint_annotations` Type: List of [`AnnotationInfo`](../datatypes/annotation_info.md) The [`datatypes.AnnotationInfo`](https://rerun.io/docs/reference/types/datatypes/annotation_info) for all of the keypoints. #### `keypoint_connections` Type: List of [`KeypointPair`](../datatypes/keypoint_pair.md) The connections between keypoints. ## Arrow datatype ``` Struct { info: Struct { id: uint16 label: nullable utf8 color: nullable uint32 } keypoint_annotations: List keypoint_connections: List } ``` ## API reference links * 🌊 [C++ API docs for `ClassDescription`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1ClassDescription.html) * 🐍 [Python API docs for `ClassDescription`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ClassDescription) * 🦀 [Rust API docs for `ClassDescription`](https://docs.rs/rerun/latest/rerun/datatypes/struct.ClassDescription.html) ## Used by * [`ClassDescriptionMapElem`](../datatypes/class_description_map_elem.md) # ClassDescriptionMapElem --- title: "ClassDescriptionMapElem" --- A helper type for mapping [`datatypes.ClassId`](https://rerun.io/docs/reference/types/datatypes/class_id)s to class descriptions. This is internal to [`components.AnnotationContext`](https://rerun.io/docs/reference/types/components/annotation_context). ## Fields #### `class_id` Type: [`ClassId`](../datatypes/class_id.md) The key: the [`components.ClassId`](https://rerun.io/docs/reference/types/components/class_id). #### `class_description` Type: [`ClassDescription`](../datatypes/class_description.md) The value: class name, color, etc. ## Arrow datatype ``` Struct { class_id: uint16 class_description: Struct { info: Struct { id: uint16 label: nullable utf8 color: nullable uint32 } keypoint_annotations: List keypoint_connections: List } } ``` ## API reference links * 🌊 [C++ API docs for `ClassDescriptionMapElem`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1ClassDescriptionMapElem.html) * 🐍 [Python API docs for `ClassDescriptionMapElem`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ClassDescriptionMapElem) * 🦀 [Rust API docs for `ClassDescriptionMapElem`](https://docs.rs/rerun/latest/rerun/datatypes/struct.ClassDescriptionMapElem.html) ## Used by * [`AnnotationContext`](../components/annotation_context.md) # ClassId --- title: "ClassId" --- A 16-bit ID representing a type of semantic class. ## Arrow datatype ``` uint16 ``` ## API reference links * 🌊 [C++ API docs for `ClassId`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1ClassId.html) * 🐍 [Python API docs for `ClassId`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ClassId) * 🦀 [Rust API docs for `ClassId`](https://docs.rs/rerun/latest/rerun/datatypes/struct.ClassId.html) ## Used by * [`ClassDescriptionMapElem`](../datatypes/class_description_map_elem.md) * [`ClassId`](../components/class_id.md) # ColorModel --- title: "ColorModel" --- Specified what color components are present in an [`archetypes.Image`](https://rerun.io/docs/reference/types/archetypes/image). This combined with [`datatypes.ChannelDatatype`](https://rerun.io/docs/reference/types/datatypes/channel_datatype) determines the pixel format of an image. ## Variants #### `L` = 1 Grayscale luminance intencity/brightness/value, sometimes called `Y` #### `RGB` = 2 Red, Green, Blue #### `RGBA` = 3 Red, Green, Blue, Alpha #### `BGR` = 4 Blue, Green, Red #### `BGRA` = 5 Blue, Green, Red, Alpha ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `ColorModel`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1datatypes.html) * 🐍 [Python API docs for `ColorModel`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ColorModel) * 🦀 [Rust API docs for `ColorModel`](https://docs.rs/rerun/latest/rerun/datatypes/enum.ColorModel.html) ## Used by * [`ImageFormat`](../datatypes/image_format.md) # DVec2D --- title: "DVec2D" --- A double-precision vector in 2D space. ## Arrow datatype ``` FixedSizeList<2, float64> ``` ## API reference links * 🌊 [C++ API docs for `DVec2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1DVec2D.html) * 🐍 [Python API docs for `DVec2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.DVec2D) * 🦀 [Rust API docs for `DVec2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.DVec2D.html) ## Used by * [`GeoLineString`](../components/geo_line_string.md) * [`LatLon`](../components/lat_lon.md) # EntityPath --- title: "EntityPath" --- A path to an entity in the `ChunkStore`. ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `EntityPath`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1EntityPath.html) * 🐍 [Python API docs for `EntityPath`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.EntityPath) * 🦀 [Rust API docs for `EntityPath`](https://docs.rs/rerun/latest/rerun/datatypes/struct.EntityPath.html) ## Used by * [`EntityPath`](../components/entity_path.md) # Float32 --- title: "Float32" --- A single-precision 32-bit IEEE 754 floating point number. ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `Float32`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Float32.html) * 🐍 [Python API docs for `Float32`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Float32) * 🦀 [Rust API docs for `Float32`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Float32.html) ## Used by * [`AxisLength`](../components/axis_length.md) * [`DepthMeter`](../components/depth_meter.md) * [`DrawOrder`](../components/draw_order.md) * [`FillRatio`](../components/fill_ratio.md) * [`GammaCorrection`](../components/gamma_correction.md) * [`ImagePlaneDistance`](../components/image_plane_distance.md) * [`Length`](../components/length.md) * [`MarkerSize`](../components/marker_size.md) * [`Opacity`](../components/opacity.md) * [`Radius`](../components/radius.md) * [`StrokeWidth`](../components/stroke_width.md) # Float64 --- title: "Float64" --- A double-precision 64-bit IEEE 754 floating point number. ## Arrow datatype ``` float64 ``` ## API reference links * 🌊 [C++ API docs for `Float64`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Float64.html) * 🐍 [Python API docs for `Float64`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Float64) * 🦀 [Rust API docs for `Float64`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Float64.html) ## Used by * [`Scalar`](../components/scalar.md) # ImageFormat --- title: "ImageFormat" --- The metadata describing the contents of a [`components.ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer). ## Fields #### `width` Type: `uint32` The width of the image in pixels. #### `height` Type: `uint32` The height of the image in pixels. #### `pixel_format` Type: nullable [`PixelFormat`](../datatypes/pixel_format.md) Used mainly for chroma downsampled formats and differing number of bits per channel. If specified, this takes precedence over both [`datatypes.ColorModel`](https://rerun.io/docs/reference/types/datatypes/color_model) and [`datatypes.ChannelDatatype`](https://rerun.io/docs/reference/types/datatypes/channel_datatype) (which are ignored). #### `color_model` Type: nullable [`ColorModel`](../datatypes/color_model.md) L, RGB, RGBA, … Also requires a [`datatypes.ChannelDatatype`](https://rerun.io/docs/reference/types/datatypes/channel_datatype) to fully specify the pixel format. #### `channel_datatype` Type: nullable [`ChannelDatatype`](../datatypes/channel_datatype.md) The data type of each channel (e.g. the red channel) of the image data (U8, F16, …). Also requires a [`datatypes.ColorModel`](https://rerun.io/docs/reference/types/datatypes/color_model) to fully specify the pixel format. ## Arrow datatype ``` Struct { width: uint32 height: uint32 pixel_format: nullable uint8 color_model: nullable uint8 channel_datatype: nullable uint8 } ``` ## API reference links * 🌊 [C++ API docs for `ImageFormat`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1ImageFormat.html) * 🐍 [Python API docs for `ImageFormat`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ImageFormat) * 🦀 [Rust API docs for `ImageFormat`](https://docs.rs/rerun/latest/rerun/datatypes/struct.ImageFormat.html) ## Used by * [`ImageFormat`](../components/image_format.md) # KeypointId --- title: "KeypointId" --- A 16-bit ID representing a type of semantic keypoint within a class. ## Arrow datatype ``` uint16 ``` ## API reference links * 🌊 [C++ API docs for `KeypointId`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1KeypointId.html) * 🐍 [Python API docs for `KeypointId`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.KeypointId) * 🦀 [Rust API docs for `KeypointId`](https://docs.rs/rerun/latest/rerun/datatypes/struct.KeypointId.html) ## Used by * [`KeypointId`](../components/keypoint_id.md) * [`KeypointPair`](../datatypes/keypoint_pair.md) # KeypointPair --- title: "KeypointPair" --- A connection between two [`datatypes.KeypointId`](https://rerun.io/docs/reference/types/datatypes/keypoint_id)s. ## Fields #### `keypoint0` Type: [`KeypointId`](../datatypes/keypoint_id.md) The first point of the pair. #### `keypoint1` Type: [`KeypointId`](../datatypes/keypoint_id.md) The second point of the pair. ## Arrow datatype ``` Struct { keypoint0: uint16 keypoint1: uint16 } ``` ## API reference links * 🌊 [C++ API docs for `KeypointPair`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1KeypointPair.html) * 🐍 [Python API docs for `KeypointPair`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.KeypointPair) * 🦀 [Rust API docs for `KeypointPair`](https://docs.rs/rerun/latest/rerun/datatypes/struct.KeypointPair.html) ## Used by * [`ClassDescription`](../datatypes/class_description.md) # Mat3x3 --- title: "Mat3x3" --- A 3x3 Matrix. Matrices in Rerun are stored as flat list of coefficients in column-major order: ```text column 0 column 1 column 2 ------------------------------------------------- row 0 | flat_columns[0] flat_columns[3] flat_columns[6] row 1 | flat_columns[1] flat_columns[4] flat_columns[7] row 2 | flat_columns[2] flat_columns[5] flat_columns[8] ``` ## Arrow datatype ``` FixedSizeList<9, float32> ``` ## API reference links * 🌊 [C++ API docs for `Mat3x3`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Mat3x3.html) * 🐍 [Python API docs for `Mat3x3`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Mat3x3) * 🦀 [Rust API docs for `Mat3x3`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Mat3x3.html) ## Used by * [`PinholeProjection`](../components/pinhole_projection.md) * [`PoseTransformMat3x3`](../components/pose_transform_mat3x3.md) * [`TransformMat3x3`](../components/transform_mat3x3.md) # Mat4x4 --- title: "Mat4x4" --- A 4x4 Matrix. Matrices in Rerun are stored as flat list of coefficients in column-major order: ```text column 0 column 1 column 2 column 3 -------------------------------------------------------------------- row 0 | flat_columns[0] flat_columns[4] flat_columns[8] flat_columns[12] row 1 | flat_columns[1] flat_columns[5] flat_columns[9] flat_columns[13] row 2 | flat_columns[2] flat_columns[6] flat_columns[10] flat_columns[14] row 3 | flat_columns[3] flat_columns[7] flat_columns[11] flat_columns[15] ``` ## Arrow datatype ``` FixedSizeList<16, float32> ``` ## API reference links * 🌊 [C++ API docs for `Mat4x4`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Mat4x4.html) * 🐍 [Python API docs for `Mat4x4`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Mat4x4) * 🦀 [Rust API docs for `Mat4x4`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Mat4x4.html) # PixelFormat --- title: "PixelFormat" --- Specifieds a particular format of an [`archetypes.Image`](https://rerun.io/docs/reference/types/archetypes/image). Most images can be described by a [`datatypes.ColorModel`](https://rerun.io/docs/reference/types/datatypes/color_model) and a [`datatypes.ChannelDatatype`](https://rerun.io/docs/reference/types/datatypes/channel_datatype), e.g. `RGB` and `U8` respectively. However, some image formats has chroma downsampling and/or use differing number of bits per channel, and that is what this [`datatypes.PixelFormat`](https://rerun.io/docs/reference/types/datatypes/pixel_format) is for. All these formats support random access. For more compressed image formats, see [`archetypes.EncodedImage`](https://rerun.io/docs/reference/types/archetypes/encoded_image). ## Variants #### `Y_U_V12_LimitedRange` = 20 `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. First comes entire image in Y in one plane, followed by the U and V planes, which each only have half the resolution of the Y plane. #### `NV12` = 26 `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled form at with 12 bits per pixel and 8 bits per channel. This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. First comes entire image in Y in one plane, followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. #### `YUY2` = 27 `YUY2` (aka 'YUYV', 'YUYV16' or 'NV21'), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. The order of the channels is Y0, U0, Y1, V0, all in the same plane. #### `Y8_FullRange` = 30 Monochrome Y plane only, essentially a YUV 4:0:0 planar format. Also known as just "gray". This is virtually identical to a 8bit luminance/grayscale (see [`datatypes.ColorModel`](https://rerun.io/docs/reference/types/datatypes/color_model)). This uses entire range YUV, i.e. Y is expected to be within [0, 255]. (as opposed to "limited range" YUV as used e.g. in NV12). #### `Y_U_V24_LimitedRange` = 39 `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. First comes entire image in Y in one plane, followed by the U and V planes. #### `Y_U_V24_FullRange` = 40 `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. This uses full range YUV with all components ranging from 0 to 255 (as opposed to "limited range" YUV as used e.g. in NV12). First comes entire image in Y in one plane, followed by the U and V planes. #### `Y8_LimitedRange` = 41 Monochrome Y plane only, essentially a YUV 4:0:0 planar format. Also known as just "gray". This uses limited range YUV, i.e. Y is expected to be within [16, 235]. If not for this range limitation/remapping, this is almost identical to 8bit luminace/grayscale (see [`datatypes.ColorModel`](https://rerun.io/docs/reference/types/datatypes/color_model)). #### `Y_U_V12_FullRange` = 44 `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. This uses full range YUV with all components ranging from 0 to 255 (as opposed to "limited range" YUV as used e.g. in NV12). First comes entire image in Y in one plane, followed by the U and V planes, which each only have half the resolution of the Y plane. #### `Y_U_V16_LimitedRange` = 49 `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. First comes entire image in Y in one plane, followed by the U and V planes, which each only have half the horizontal resolution of the Y plane. #### `Y_U_V16_FullRange` = 50 `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. This uses full range YUV with all components ranging from 0 to 255 (as opposed to "limited range" YUV as used e.g. in NV12). First comes entire image in Y in one plane, followed by the U and V planes, which each only have half the horizontal resolution of the Y plane. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `PixelFormat`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1datatypes.html) * 🐍 [Python API docs for `PixelFormat`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.PixelFormat) * 🦀 [Rust API docs for `PixelFormat`](https://docs.rs/rerun/latest/rerun/datatypes/enum.PixelFormat.html) ## Used by * [`ImageFormat`](../datatypes/image_format.md) # Plane3D --- title: "Plane3D" --- An infinite 3D plane represented by a unit normal vector and a distance. Any point P on the plane fulfills the equation `dot(xyz, P) - d = 0`, where `xyz` is the plane's normal and `d` the distance of the plane from the origin. This representation is also known as the Hesse normal form. Note: although the normal will be passed through to the datastore as provided, when used in the Viewer, planes will always be normalized. I.e. the plane with xyz = (2, 0, 0), d = 1 is equivalent to xyz = (1, 0, 0), d = 0.5 ## Arrow datatype ``` FixedSizeList<4, float32> ``` ## API reference links * 🌊 [C++ API docs for `Plane3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Plane3D.html) * 🐍 [Python API docs for `Plane3D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Plane3D) * 🦀 [Rust API docs for `Plane3D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Plane3D.html) ## Used by * [`Plane3D`](../components/plane3d.md) # Quaternion --- title: "Quaternion" --- A Quaternion represented by 4 real numbers. Note: although the x,y,z,w components of the quaternion will be passed through to the datastore as provided, when used in the Viewer Quaternions will always be normalized. ## Arrow datatype ``` FixedSizeList<4, float32> ``` ## API reference links * 🌊 [C++ API docs for `Quaternion`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Quaternion.html) * 🐍 [Python API docs for `Quaternion`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Quaternion) * 🦀 [Rust API docs for `Quaternion`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Quaternion.html) ## Used by * [`PoseRotationQuat`](../components/pose_rotation_quat.md) * [`RotationQuat`](../components/rotation_quat.md) # Range1D --- title: "Range1D" --- A 1D range, specifying a lower and upper bound. ## Arrow datatype ``` FixedSizeList<2, float64> ``` ## API reference links * 🌊 [C++ API docs for `Range1D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Range1D.html) * 🐍 [Python API docs for `Range1D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Range1D) * 🦀 [Rust API docs for `Range1D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Range1D.html) ## Used by * [`Range1D`](../components/range1d.md) * [`Range2D`](../datatypes/range2d.md) * [`ValueRange`](../components/value_range.md) # Range2D --- title: "Range2D" --- An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. ## Fields #### `x_range` Type: [`Range1D`](../datatypes/range1d.md) The range of the X-axis (usually left and right bounds). #### `y_range` Type: [`Range1D`](../datatypes/range1d.md) The range of the Y-axis (usually top and bottom bounds). ## Arrow datatype ``` Struct { x_range: FixedSizeList<2, float64> y_range: FixedSizeList<2, float64> } ``` ## API reference links * 🌊 [C++ API docs for `Range2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Range2D.html) * 🐍 [Python API docs for `Range2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Range2D) * 🦀 [Rust API docs for `Range2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Range2D.html) # Rgba32 --- title: "Rgba32" --- An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. The color is stored as a 32-bit integer, where the most significant byte is `R` and the least significant byte is `A`. ## Arrow datatype ``` uint32 ``` ## API reference links * 🌊 [C++ API docs for `Rgba32`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Rgba32.html) * 🐍 [Python API docs for `Rgba32`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Rgba32) * 🦀 [Rust API docs for `Rgba32`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Rgba32.html) ## Used by * [`AlbedoFactor`](../components/albedo_factor.md) * [`AnnotationInfo`](../datatypes/annotation_info.md) * [`Color`](../components/color.md) # RotationAxisAngle --- title: "RotationAxisAngle" --- 3D rotation represented by a rotation around a given axis. ## Fields #### `axis` Type: [`Vec3D`](../datatypes/vec3d.md) Axis to rotate around. This is not required to be normalized. However, if normalization of the rotation axis fails (typically due to a zero vector) the rotation is treated as an invalid transform, unless the angle is zero in which case it is treated as an identity. #### `angle` Type: [`Angle`](../datatypes/angle.md) How much to rotate around the axis. ## Arrow datatype ``` Struct { axis: FixedSizeList<3, float32> angle: float32 } ``` ## API reference links * 🌊 [C++ API docs for `RotationAxisAngle`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1RotationAxisAngle.html) * 🐍 [Python API docs for `RotationAxisAngle`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.RotationAxisAngle) * 🦀 [Rust API docs for `RotationAxisAngle`](https://docs.rs/rerun/latest/rerun/datatypes/struct.RotationAxisAngle.html) ## Used by * [`PoseRotationAxisAngle`](../components/pose_rotation_axis_angle.md) * [`RotationAxisAngle`](../components/rotation_axis_angle.md) # TensorBuffer --- title: "TensorBuffer" --- The underlying storage for [`archetypes.Tensor`](https://rerun.io/docs/reference/types/archetypes/tensor). Tensor elements are stored in a contiguous buffer of a single type. ## Variants #### `U8` = 1 Type: List of `uint8` 8bit unsigned integer. #### `U16` = 2 Type: List of `uint16` 16bit unsigned integer. #### `U32` = 3 Type: List of `uint32` 32bit unsigned integer. #### `U64` = 4 Type: List of `uint64` 64bit unsigned integer. #### `I8` = 5 Type: List of `int8` 8bit signed integer. #### `I16` = 6 Type: List of `int16` 16bit signed integer. #### `I32` = 7 Type: List of `int32` 32bit signed integer. #### `I64` = 8 Type: List of `int64` 64bit signed integer. #### `F16` = 9 Type: List of `float16` 16bit IEEE-754 floating point, also known as `half`. #### `F32` = 10 Type: List of `float32` 32bit IEEE-754 floating point, also known as `float` or `single`. #### `F64` = 11 Type: List of `float64` 64bit IEEE-754 floating point, also known as `double`. ## Arrow datatype ``` DenseUnion { 0 = "_null_markers": nullable null 1 = "U8": List 2 = "U16": List 3 = "U32": List 4 = "U64": List 5 = "I8": List 6 = "I16": List 7 = "I32": List 8 = "I64": List 9 = "F16": List 10 = "F32": List 11 = "F64": List } ``` ## API reference links * 🌊 [C++ API docs for `TensorBuffer`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TensorBuffer.html) * 🐍 [Python API docs for `TensorBuffer`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TensorBuffer) * 🦀 [Rust API docs for `TensorBuffer`](https://docs.rs/rerun/latest/rerun/datatypes/enum.TensorBuffer.html) ## Used by * [`TensorData`](../datatypes/tensor_data.md) # TensorData --- title: "TensorData" --- An N-dimensional array of numbers. The number of dimensions and their respective lengths is specified by the `shape` field. The dimensions are ordered from outermost to innermost. For example, in the common case of a 2D RGB Image, the shape would be `[height, width, channel]`. These dimensions are combined with an index to look up values from the `buffer` field, which stores a contiguous array of typed values. ## Fields #### `shape` Type: List of `uint64` The shape of the tensor, i.e. the length of each dimension. #### `names` Type: nullable List of `utf8` The names of the dimensions of the tensor (optional). If set, should be the same length as [`datatypes.TensorData#shape`](https://rerun.io/docs/reference/types/datatypes/tensor_data). If it has a different length your names may show up improperly, and some constructors may produce a warning or even an error. Example: `["height", "width", "channel", "batch"]`. #### `buffer` Type: [`TensorBuffer`](../datatypes/tensor_buffer.md) The content/data. ## Arrow datatype ``` Struct { shape: List names: nullable List buffer: DenseUnion { 0 = "_null_markers": nullable null 1 = "U8": List 2 = "U16": List 3 = "U32": List 4 = "U64": List 5 = "I8": List 6 = "I16": List 7 = "I32": List 8 = "I64": List 9 = "F16": List 10 = "F32": List 11 = "F64": List } } ``` ## API reference links * 🌊 [C++ API docs for `TensorData`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TensorData.html) * 🐍 [Python API docs for `TensorData`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TensorData) * 🦀 [Rust API docs for `TensorData`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TensorData.html) ## Used by * [`TensorData`](../components/tensor_data.md) # TensorDimensionIndexSelection --- title: "TensorDimensionIndexSelection" --- Indexing a specific tensor dimension. Selecting `dimension=2` and `index=42` is similar to doing `tensor[:, :, 42, :, :, …]` in numpy. ## Fields #### `dimension` Type: `uint32` The dimension number to select. #### `index` Type: `uint64` The index along the dimension to use. ## Arrow datatype ``` Struct { dimension: uint32 index: uint64 } ``` ## API reference links * 🌊 [C++ API docs for `TensorDimensionIndexSelection`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TensorDimensionIndexSelection.html) * 🐍 [Python API docs for `TensorDimensionIndexSelection`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TensorDimensionIndexSelection) * 🦀 [Rust API docs for `TensorDimensionIndexSelection`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TensorDimensionIndexSelection.html) ## Used by * [`TensorDimensionIndexSelection`](../components/tensor_dimension_index_selection.md) # TensorDimensionSelection --- title: "TensorDimensionSelection" --- Selection of a single tensor dimension. ## Fields #### `dimension` Type: `uint32` The dimension number to select. #### `invert` Type: `boolean` Invert the direction of the dimension. ## Arrow datatype ``` Struct { dimension: uint32 invert: boolean } ``` ## API reference links * 🌊 [C++ API docs for `TensorDimensionSelection`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TensorDimensionSelection.html) * 🐍 [Python API docs for `TensorDimensionSelection`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TensorDimensionSelection) * 🦀 [Rust API docs for `TensorDimensionSelection`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TensorDimensionSelection.html) ## Used by * [`TensorHeightDimension`](../components/tensor_height_dimension.md) * [`TensorWidthDimension`](../components/tensor_width_dimension.md) # TimeInt --- title: "TimeInt" --- A 64-bit number describing either nanoseconds OR sequence numbers. ## Arrow datatype ``` int64 ``` ## API reference links * 🌊 [C++ API docs for `TimeInt`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeInt.html) * 🐍 [Python API docs for `TimeInt`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TimeInt) * 🦀 [Rust API docs for `TimeInt`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeInt.html) ## Used by * [`TimeRangeBoundary`](../datatypes/time_range_boundary.md) # TimeRange --- title: "TimeRange" --- Visible time range bounds for a specific timeline. ## Fields #### `start` Type: [`TimeRangeBoundary`](../datatypes/time_range_boundary.md) Low time boundary for sequence timeline. #### `end` Type: [`TimeRangeBoundary`](../datatypes/time_range_boundary.md) High time boundary for sequence timeline. ## Arrow datatype ``` Struct { start: DenseUnion { 0 = "_null_markers": nullable null 1 = "CursorRelative": int64 2 = "Absolute": int64 3 = "Infinite": nullable null } end: DenseUnion { 0 = "_null_markers": nullable null 1 = "CursorRelative": int64 2 = "Absolute": int64 3 = "Infinite": nullable null } } ``` ## API reference links * 🌊 [C++ API docs for `TimeRange`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeRange.html) * 🐍 [Python API docs for `TimeRange`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TimeRange) * 🦀 [Rust API docs for `TimeRange`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeRange.html) ## Used by * [`VisibleTimeRange`](../datatypes/visible_time_range.md) # TimeRangeBoundary --- title: "TimeRangeBoundary" --- Left or right boundary of a time range. ## Variants #### `CursorRelative` = 1 Type: [`TimeInt`](../datatypes/time_int.md) Boundary is a value relative to the time cursor. #### `Absolute` = 2 Type: [`TimeInt`](../datatypes/time_int.md) Boundary is an absolute value. #### `Infinite` = 3 Type: `null` The boundary extends to infinity. ## Arrow datatype ``` DenseUnion { 0 = "_null_markers": nullable null 1 = "CursorRelative": int64 2 = "Absolute": int64 3 = "Infinite": nullable null } ``` ## API reference links * 🌊 [C++ API docs for `TimeRangeBoundary`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeRangeBoundary.html) * 🐍 [Python API docs for `TimeRangeBoundary`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TimeRangeBoundary) * 🦀 [Rust API docs for `TimeRangeBoundary`](https://docs.rs/rerun/latest/rerun/datatypes/enum.TimeRangeBoundary.html) ## Used by * [`TimeRange`](../datatypes/time_range.md) # UInt16 --- title: "UInt16" --- A 16bit unsigned integer. ## Arrow datatype ``` uint16 ``` ## API reference links * 🌊 [C++ API docs for `UInt16`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UInt16.html) * 🐍 [Python API docs for `UInt16`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UInt16) * 🦀 [Rust API docs for `UInt16`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UInt16.html) # UInt32 --- title: "UInt32" --- A 32bit unsigned integer. ## Arrow datatype ``` uint32 ``` ## API reference links * 🌊 [C++ API docs for `UInt32`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UInt32.html) * 🐍 [Python API docs for `UInt32`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UInt32) * 🦀 [Rust API docs for `UInt32`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UInt32.html) # UInt64 --- title: "UInt64" --- A 64bit unsigned integer. ## Arrow datatype ``` uint64 ``` ## API reference links * 🌊 [C++ API docs for `UInt64`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UInt64.html) * 🐍 [Python API docs for `UInt64`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UInt64) * 🦀 [Rust API docs for `UInt64`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UInt64.html) # Utf8 --- title: "Utf8" --- A string of text, encoded as UTF-8. ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `Utf8`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Utf8.html) * 🐍 [Python API docs for `Utf8`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Utf8) * 🦀 [Rust API docs for `Utf8`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Utf8.html) ## Used by * [`AnnotationInfo`](../datatypes/annotation_info.md) * [`GraphNode`](../components/graph_node.md) * [`MediaType`](../components/media_type.md) * [`Name`](../components/name.md) * [`RecordingUri`](../components/recording_uri.md) * [`TextLogLevel`](../components/text_log_level.md) * [`Text`](../components/text.md) * [`Utf8Pair`](../datatypes/utf8pair.md) * [`VisibleTimeRange`](../datatypes/visible_time_range.md) # Utf8Pair --- title: "Utf8Pair" --- Stores a tuple of UTF-8 strings. ## Fields #### `first` Type: [`Utf8`](../datatypes/utf8.md) The first string. #### `second` Type: [`Utf8`](../datatypes/utf8.md) The second string. ## Arrow datatype ``` Struct { first: utf8 second: utf8 } ``` ## API reference links * 🌊 [C++ API docs for `Utf8Pair`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Utf8Pair.html) * 🐍 [Python API docs for `Utf8Pair`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Utf8Pair) * 🦀 [Rust API docs for `Utf8Pair`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Utf8Pair.html) ## Used by * [`GraphEdge`](../components/graph_edge.md) # Uuid --- title: "Uuid" --- A 16-byte UUID. ## Arrow datatype ``` FixedSizeList<16, uint8> ``` ## API reference links * 🌊 [C++ API docs for `Uuid`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Uuid.html) * 🐍 [Python API docs for `Uuid`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Uuid) * 🦀 [Rust API docs for `Uuid`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Uuid.html) # UVec2D --- title: "UVec2D" --- A uint32 vector in 2D space. ## Arrow datatype ``` FixedSizeList<2, uint32> ``` ## API reference links * 🌊 [C++ API docs for `UVec2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UVec2D.html) * 🐍 [Python API docs for `UVec2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UVec2D) * 🦀 [Rust API docs for `UVec2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UVec2D.html) # UVec3D --- title: "UVec3D" --- A uint32 vector in 3D space. ## Arrow datatype ``` FixedSizeList<3, uint32> ``` ## API reference links * 🌊 [C++ API docs for `UVec3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UVec3D.html) * 🐍 [Python API docs for `UVec3D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UVec3D) * 🦀 [Rust API docs for `UVec3D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UVec3D.html) ## Used by * [`TriangleIndices`](../components/triangle_indices.md) # UVec4D --- title: "UVec4D" --- A uint vector in 4D space. ## Arrow datatype ``` FixedSizeList<4, uint32> ``` ## API reference links * 🌊 [C++ API docs for `UVec4D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UVec4D.html) * 🐍 [Python API docs for `UVec4D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UVec4D) * 🦀 [Rust API docs for `UVec4D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UVec4D.html) # Vec2D --- title: "Vec2D" --- A vector in 2D space. ## Arrow datatype ``` FixedSizeList<2, float32> ``` ## API reference links * 🌊 [C++ API docs for `Vec2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Vec2D.html) * 🐍 [Python API docs for `Vec2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Vec2D) * 🦀 [Rust API docs for `Vec2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Vec2D.html) ## Used by * [`HalfSize2D`](../components/half_size2d.md) * [`LineStrip2D`](../components/line_strip2d.md) * [`Position2D`](../components/position2d.md) * [`Resolution`](../components/resolution.md) * [`Texcoord2D`](../components/texcoord2d.md) * [`Vector2D`](../components/vector2d.md) # Vec3D --- title: "Vec3D" --- A vector in 3D space. ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `Vec3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Vec3D.html) * 🐍 [Python API docs for `Vec3D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Vec3D) * 🦀 [Rust API docs for `Vec3D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Vec3D.html) ## Used by * [`HalfSize3D`](../components/half_size3d.md) * [`LineStrip3D`](../components/line_strip3d.md) * [`PoseScale3D`](../components/pose_scale3d.md) * [`PoseTranslation3D`](../components/pose_translation3d.md) * [`Position3D`](../components/position3d.md) * [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) * [`Scale3D`](../components/scale3d.md) * [`Translation3D`](../components/translation3d.md) * [`Vector3D`](../components/vector3d.md) # Vec4D --- title: "Vec4D" --- A vector in 4D space. ## Arrow datatype ``` FixedSizeList<4, float32> ``` ## API reference links * 🌊 [C++ API docs for `Vec4D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Vec4D.html) * 🐍 [Python API docs for `Vec4D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Vec4D) * 🦀 [Rust API docs for `Vec4D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Vec4D.html) # VideoTimestamp --- title: "VideoTimestamp" --- Presentation timestamp within a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video). Specified in nanoseconds. Presentation timestamps are typically measured as time since video start. ## Arrow datatype ``` int64 ``` ## API reference links * 🌊 [C++ API docs for `VideoTimestamp`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1VideoTimestamp.html) * 🐍 [Python API docs for `VideoTimestamp`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.VideoTimestamp) * 🦀 [Rust API docs for `VideoTimestamp`](https://docs.rs/rerun/latest/rerun/datatypes/struct.VideoTimestamp.html) ## Used by * [`VideoTimestamp`](../components/video_timestamp.md) # ViewCoordinates --- title: "ViewCoordinates" --- How we interpret the coordinate system of an entity/space. For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). The following constants are used to represent the different directions: * Up = 1 * Down = 2 * Right = 3 * Left = 4 * Forward = 5 * Back = 6 ## Arrow datatype ``` FixedSizeList<3, uint8> ``` ## API reference links * 🌊 [C++ API docs for `ViewCoordinates`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1ViewCoordinates.html) * 🐍 [Python API docs for `ViewCoordinates`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.ViewCoordinates) * 🦀 [Rust API docs for `ViewCoordinates`](https://docs.rs/rerun/latest/rerun/datatypes/struct.ViewCoordinates.html) ## Used by * [`ViewCoordinates`](../components/view_coordinates.md) # VisibleTimeRange --- title: "VisibleTimeRange" --- Visible time range bounds for a specific timeline. ## Fields #### `timeline` Type: [`Utf8`](../datatypes/utf8.md) Name of the timeline this applies to. #### `range` Type: [`TimeRange`](../datatypes/time_range.md) Time range to use for this timeline. ## Arrow datatype ``` Struct { timeline: utf8 range: Struct { start: DenseUnion { 0 = "_null_markers": nullable null 1 = "CursorRelative": int64 2 = "Absolute": int64 3 = "Infinite": nullable null } end: DenseUnion { 0 = "_null_markers": nullable null 1 = "CursorRelative": int64 2 = "Absolute": int64 3 = "Infinite": nullable null } } } ``` ## API reference links * 🌊 [C++ API docs for `VisibleTimeRange`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1VisibleTimeRange.html) * 🐍 [Python API docs for `VisibleTimeRange`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.VisibleTimeRange) * 🦀 [Rust API docs for `VisibleTimeRange`](https://docs.rs/rerun/latest/rerun/datatypes/struct.VisibleTimeRange.html) # AggregationPolicy --- title: "AggregationPolicy" --- Policy for aggregation of multiple scalar plot values. This is used for lines in plots when the X axis distance of individual points goes below a single pixel, i.e. a single pixel covers more than one tick worth of data. It can greatly improve performance (and readability) in such situations as it prevents overdraw. ## Variants #### `Off` = 1 No aggregation. #### `Average` = 2 Average all points in the range together. #### `Max` = 3 Keep only the maximum values in the range. #### `Min` = 4 Keep only the minimum values in the range. #### `MinMax` = 5 Keep both the minimum and maximum values in the range. This will yield two aggregated points instead of one, effectively creating a vertical line. #### `MinMaxAverage` = 6 Find both the minimum and maximum values in the range, then use the average of those. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `AggregationPolicy`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `AggregationPolicy`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AggregationPolicy) * 🦀 [Rust API docs for `AggregationPolicy`](https://docs.rs/rerun/latest/rerun/components/enum.AggregationPolicy.html) ## Used by * [`SeriesLine`](../archetypes/series_line.md) # AlbedoFactor --- title: "AlbedoFactor" --- A color multiplier, usually applied to a whole entity, e.g. a mesh. ## Rerun datatype [`Rgba32`](../datatypes/rgba32.md) ## Arrow datatype ``` uint32 ``` ## API reference links * 🌊 [C++ API docs for `AlbedoFactor`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AlbedoFactor.html) * 🐍 [Python API docs for `AlbedoFactor`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AlbedoFactor) * 🦀 [Rust API docs for `AlbedoFactor`](https://docs.rs/rerun/latest/rerun/components/struct.AlbedoFactor.html) ## Used by * [`Asset3D`](../archetypes/asset3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) # AnnotationContext --- title: "AnnotationContext" --- The annotation context provides additional information on how to display entities. Entities can use [`datatypes.ClassId`](https://rerun.io/docs/reference/types/datatypes/class_id)s and [`datatypes.KeypointId`](https://rerun.io/docs/reference/types/datatypes/keypoint_id)s to provide annotations, and the labels and colors will be looked up in the appropriate annotation context. We use the *first* annotation context we find in the path-hierarchy when searching up through the ancestors of a given entity path. ## Arrow datatype ``` List keypoint_connections: List } }> ``` ## API reference links * 🌊 [C++ API docs for `AnnotationContext`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AnnotationContext.html) * 🐍 [Python API docs for `AnnotationContext`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AnnotationContext) * 🦀 [Rust API docs for `AnnotationContext`](https://docs.rs/rerun/latest/rerun/components/struct.AnnotationContext.html) ## Used by * [`AnnotationContext`](../archetypes/annotation_context.md) # AxisLength --- title: "AxisLength" --- The length of an axis in local units of the space. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `AxisLength`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AxisLength.html) * 🐍 [Python API docs for `AxisLength`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AxisLength) * 🦀 [Rust API docs for `AxisLength`](https://docs.rs/rerun/latest/rerun/components/struct.AxisLength.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # Blob --- title: "Blob" --- A binary blob of data. ## Rerun datatype [`Blob`](../datatypes/blob.md) ## Arrow datatype ``` List ``` ## API reference links * 🌊 [C++ API docs for `Blob`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Blob.html) * 🐍 [Python API docs for `Blob`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Blob) * 🦀 [Rust API docs for `Blob`](https://docs.rs/rerun/latest/rerun/components/struct.Blob.html) ## Used by * [`Asset3D`](../archetypes/asset3d.md) * [`AssetVideo`](../archetypes/asset_video.md) * [`EncodedImage`](../archetypes/encoded_image.md) # ClassId --- title: "ClassId" --- A 16-bit ID representing a type of semantic class. ## Rerun datatype [`ClassId`](../datatypes/class_id.md) ## Arrow datatype ``` uint16 ``` ## API reference links * 🌊 [C++ API docs for `ClassId`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ClassId.html) * 🐍 [Python API docs for `ClassId`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ClassId) * 🦀 [Rust API docs for `ClassId`](https://docs.rs/rerun/latest/rerun/components/struct.ClassId.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Arrows3D`](../archetypes/arrows3d.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GeoPoints`](../archetypes/geo_points.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) # ClearIsRecursive --- title: "ClearIsRecursive" --- Configures how a clear operation should behave - recursive or not. ## Rerun datatype [`Bool`](../datatypes/bool.md) ## Arrow datatype ``` boolean ``` ## API reference links * 🌊 [C++ API docs for `ClearIsRecursive`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ClearIsRecursive.html) * 🐍 [Python API docs for `ClearIsRecursive`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ClearIsRecursive) * 🦀 [Rust API docs for `ClearIsRecursive`](https://docs.rs/rerun/latest/rerun/components/struct.ClearIsRecursive.html) ## Used by * [`Clear`](../archetypes/clear.md) # Color --- title: "Color" --- An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. The color is stored as a 32-bit integer, where the most significant byte is `R` and the least significant byte is `A`. ## Rerun datatype [`Rgba32`](../datatypes/rgba32.md) ## Arrow datatype ``` uint32 ``` ## API reference links * 🌊 [C++ API docs for `Color`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Color.html) * 🐍 [Python API docs for `Color`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Color) * 🦀 [Rust API docs for `Color`](https://docs.rs/rerun/latest/rerun/components/struct.Color.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Arrows3D`](../archetypes/arrows3d.md) * [`BarChart`](../archetypes/bar_chart.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GeoLineStrings`](../archetypes/geo_line_strings.md) * [`GeoPoints`](../archetypes/geo_points.md) * [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) * [`SeriesLine`](../archetypes/series_line.md) * [`SeriesPoint`](../archetypes/series_point.md) * [`TextLog`](../archetypes/text_log.md) # Colormap --- title: "Colormap" --- Colormap for mapping scalar values within a given range to a color. This provides a number of popular pre-defined colormaps. In the future, the Rerun Viewer will allow users to define their own colormaps, but currently the Viewer is limited to the types defined here. ## Variants #### `Grayscale` = 1 A simple black to white gradient. This is a sRGB gray gradient which is perceptually uniform. #### `Inferno` = 2 The Inferno colormap from Matplotlib. This is a perceptually uniform colormap. It interpolates from black to red to bright yellow. #### `Magma` = 3 The Magma colormap from Matplotlib. This is a perceptually uniform colormap. It interpolates from black to purple to white. #### `Plasma` = 4 The Plasma colormap from Matplotlib. This is a perceptually uniform colormap. It interpolates from dark blue to purple to yellow. #### `Turbo` = 5 Google's Turbo colormap map. This is a perceptually non-uniform rainbow colormap addressing many issues of more traditional rainbow colormaps like Jet. It is more perceptually uniform without sharp transitions and is more colorblind-friendly. Details: #### `Viridis` = 6 The Viridis colormap from Matplotlib This is a perceptually uniform colormap which is robust to color blindness. It interpolates from dark purple to green to yellow. #### `CyanToYellow` = 7 Rasmusgo's Cyan to Yellow colormap This is a perceptually uniform colormap which is robust to color blindness. It is especially suited for visualizing signed values. It interpolates from cyan to blue to dark gray to brass to yellow. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `Colormap`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `Colormap`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Colormap) * 🦀 [Rust API docs for `Colormap`](https://docs.rs/rerun/latest/rerun/components/enum.Colormap.html) ## Used by * [`DepthImage`](../archetypes/depth_image.md) # DepthMeter --- title: "DepthMeter" --- The world->depth map scaling factor. This measures how many depth map units are in a world unit. For instance, if a depth map uses millimeters and the world uses meters, this value would be `1000`. Note that the only effect on 2D views is the physical depth values shown when hovering the image. In 3D views on the other hand, this affects where the points of the point cloud are placed. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `DepthMeter`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1DepthMeter.html) * 🐍 [Python API docs for `DepthMeter`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.DepthMeter) * 🦀 [Rust API docs for `DepthMeter`](https://docs.rs/rerun/latest/rerun/components/struct.DepthMeter.html) ## Used by * [`DepthImage`](../archetypes/depth_image.md) # DrawOrder --- title: "DrawOrder" --- Draw order of 2D elements. Higher values are drawn on top of lower values. An entity can have only a single draw order component. Within an entity draw order is governed by the order of the components. Draw order for entities with the same draw order is generally undefined. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `DrawOrder`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1DrawOrder.html) * 🐍 [Python API docs for `DrawOrder`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.DrawOrder) * 🦀 [Rust API docs for `DrawOrder`](https://docs.rs/rerun/latest/rerun/components/struct.DrawOrder.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`DepthImage`](../archetypes/depth_image.md) * [`EncodedImage`](../archetypes/encoded_image.md) * [`Image`](../archetypes/image.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`Points2D`](../archetypes/points2d.md) * [`SegmentationImage`](../archetypes/segmentation_image.md) # EntityPath --- title: "EntityPath" --- A path to an entity, usually to reference some data that is part of the target entity. ## Rerun datatype [`EntityPath`](../datatypes/entity_path.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `EntityPath`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1EntityPath.html) * 🐍 [Python API docs for `EntityPath`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.EntityPath) * 🦀 [Rust API docs for `EntityPath`](https://docs.rs/rerun/latest/rerun/components/struct.EntityPath.html) ## Used by * [`VideoFrameReference`](../archetypes/video_frame_reference.md) # FillMode --- title: "FillMode" --- How a geometric shape is drawn and colored. ## Variants #### `MajorWireframe` = 1 Lines are drawn around the parts of the shape which directly correspond to the logged data. Examples of what this means: * An [`archetypes.Ellipsoids3D`](https://rerun.io/docs/reference/types/archetypes/ellipsoids3d) will draw three axis-aligned ellipses that are cross-sections of each ellipsoid, each of which displays two out of three of the sizes of the ellipsoid. * For [`archetypes.Boxes3D`](https://rerun.io/docs/reference/types/archetypes/boxes3d), it is the edges of the box, identical to [`components.FillMode#DenseWireframe`](https://rerun.io/docs/reference/types/components/fill_mode). #### `DenseWireframe` = 2 Many lines are drawn to represent the surface of the shape in a see-through fashion. Examples of what this means: * An [`archetypes.Ellipsoids3D`](https://rerun.io/docs/reference/types/archetypes/ellipsoids3d) will draw a wireframe triangle mesh that approximates each ellipsoid. * For [`archetypes.Boxes3D`](https://rerun.io/docs/reference/types/archetypes/boxes3d), it is the edges of the box, identical to [`components.FillMode#MajorWireframe`](https://rerun.io/docs/reference/types/components/fill_mode). #### `Solid` = 3 The surface of the shape is filled in with a solid color. No lines are drawn. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `FillMode`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `FillMode`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.FillMode) * 🦀 [Rust API docs for `FillMode`](https://docs.rs/rerun/latest/rerun/components/enum.FillMode.html) ## Used by * [`Boxes3D`](../archetypes/boxes3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) # FillRatio --- title: "FillRatio" --- How much a primitive fills out the available space. Used for instance to scale the points of the point cloud created from [`archetypes.DepthImage`](https://rerun.io/docs/reference/types/archetypes/depth_image) projection in 3D views. Valid range is from 0 to max float although typically values above 1.0 are not useful. Defaults to 1.0. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `FillRatio`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1FillRatio.html) * 🐍 [Python API docs for `FillRatio`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.FillRatio) * 🦀 [Rust API docs for `FillRatio`](https://docs.rs/rerun/latest/rerun/components/struct.FillRatio.html) ## Used by * [`DepthImage`](../archetypes/depth_image.md) # GammaCorrection --- title: "GammaCorrection" --- A gamma correction value to be used with a scalar value or color. Used to adjust the gamma of a color or scalar value between 0 and 1 before rendering. `new_value = old_value ^ gamma` Valid range is from 0 (excluding) to max float. Defaults to 1.0 unless otherwise specified. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `GammaCorrection`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1GammaCorrection.html) * 🐍 [Python API docs for `GammaCorrection`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.GammaCorrection) * 🦀 [Rust API docs for `GammaCorrection`](https://docs.rs/rerun/latest/rerun/components/struct.GammaCorrection.html) # GeoLineString --- title: "GeoLineString" --- A geospatial line string expressed in [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees). ## Arrow datatype ``` List> ``` ## API reference links * 🌊 [C++ API docs for `GeoLineString`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1GeoLineString.html) * 🐍 [Python API docs for `GeoLineString`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.GeoLineString) * 🦀 [Rust API docs for `GeoLineString`](https://docs.rs/rerun/latest/rerun/components/struct.GeoLineString.html) ## Used by * [`GeoLineStrings`](../archetypes/geo_line_strings.md) # GraphEdge --- title: "GraphEdge" --- An edge in a graph connecting two nodes. ## Rerun datatype [`Utf8Pair`](../datatypes/utf8pair.md) ## Arrow datatype ``` Struct { first: utf8 second: utf8 } ``` ## API reference links * 🌊 [C++ API docs for `GraphEdge`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1GraphEdge.html) * 🐍 [Python API docs for `GraphEdge`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.GraphEdge) * 🦀 [Rust API docs for `GraphEdge`](https://docs.rs/rerun/latest/rerun/components/struct.GraphEdge.html) ## Used by * [`GraphEdges`](../archetypes/graph_edges.md) # GraphNode --- title: "GraphNode" --- A string-based ID representing a node in a graph. ## Rerun datatype [`Utf8`](../datatypes/utf8.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `GraphNode`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1GraphNode.html) * 🐍 [Python API docs for `GraphNode`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.GraphNode) * 🦀 [Rust API docs for `GraphNode`](https://docs.rs/rerun/latest/rerun/components/struct.GraphNode.html) ## Used by * [`GraphNodes`](../archetypes/graph_nodes.md) # GraphType --- title: "GraphType" --- Specifies if a graph has directed or undirected edges. ## Variants #### `Undirected` = 1 The graph has undirected edges. #### `Directed` = 2 The graph has directed edges. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `GraphType`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `GraphType`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.GraphType) * 🦀 [Rust API docs for `GraphType`](https://docs.rs/rerun/latest/rerun/components/enum.GraphType.html) ## Used by * [`GraphEdges`](../archetypes/graph_edges.md) # HalfSize2D --- title: "HalfSize2D" --- Half-size (radius) of a 2D box. Measured in its local coordinate system. The box extends both in negative and positive direction along each axis. Negative sizes indicate that the box is flipped along the respective axis, but this has no effect on how it is displayed. ## Rerun datatype [`Vec2D`](../datatypes/vec2d.md) ## Arrow datatype ``` FixedSizeList<2, float32> ``` ## API reference links * 🌊 [C++ API docs for `HalfSize2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1HalfSize2D.html) * 🐍 [Python API docs for `HalfSize2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.HalfSize2D) * 🦀 [Rust API docs for `HalfSize2D`](https://docs.rs/rerun/latest/rerun/components/struct.HalfSize2D.html) ## Used by * [`Boxes2D`](../archetypes/boxes2d.md) # HalfSize3D --- title: "HalfSize3D" --- Half-size (radius) of a 3D box. Measured in its local coordinate system. The box extends both in negative and positive direction along each axis. Negative sizes indicate that the box is flipped along the respective axis, but this has no effect on how it is displayed. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `HalfSize3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1HalfSize3D.html) * 🐍 [Python API docs for `HalfSize3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.HalfSize3D) * 🦀 [Rust API docs for `HalfSize3D`](https://docs.rs/rerun/latest/rerun/components/struct.HalfSize3D.html) ## Used by * [`Boxes3D`](../archetypes/boxes3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) # ImageBuffer --- title: "ImageBuffer" --- A buffer that is known to store image data. To interpret the contents of this buffer, see, [`components.ImageFormat`](https://rerun.io/docs/reference/types/components/image_format). ## Rerun datatype [`Blob`](../datatypes/blob.md) ## Arrow datatype ``` List ``` ## API reference links * 🌊 [C++ API docs for `ImageBuffer`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ImageBuffer.html) * 🐍 [Python API docs for `ImageBuffer`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ImageBuffer) * 🦀 [Rust API docs for `ImageBuffer`](https://docs.rs/rerun/latest/rerun/components/struct.ImageBuffer.html) ## Used by * [`DepthImage`](../archetypes/depth_image.md) * [`Image`](../archetypes/image.md) * [`Mesh3D`](../archetypes/mesh3d.md) * [`SegmentationImage`](../archetypes/segmentation_image.md) # ImageFormat --- title: "ImageFormat" --- The metadata describing the contents of a [`components.ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer). ## Rerun datatype [`ImageFormat`](../datatypes/image_format.md) ## Arrow datatype ``` Struct { width: uint32 height: uint32 pixel_format: nullable uint8 color_model: nullable uint8 channel_datatype: nullable uint8 } ``` ## API reference links * 🌊 [C++ API docs for `ImageFormat`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ImageFormat.html) * 🐍 [Python API docs for `ImageFormat`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ImageFormat) * 🦀 [Rust API docs for `ImageFormat`](https://docs.rs/rerun/latest/rerun/components/struct.ImageFormat.html) ## Used by * [`DepthImage`](../archetypes/depth_image.md) * [`Image`](../archetypes/image.md) * [`Mesh3D`](../archetypes/mesh3d.md) * [`SegmentationImage`](../archetypes/segmentation_image.md) # ImagePlaneDistance --- title: "ImagePlaneDistance" --- The distance from the camera origin to the image plane when the projection is shown in a 3D viewer. This is only used for visualization purposes, and does not affect the projection itself. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `ImagePlaneDistance`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ImagePlaneDistance.html) * 🐍 [Python API docs for `ImagePlaneDistance`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ImagePlaneDistance) * 🦀 [Rust API docs for `ImagePlaneDistance`](https://docs.rs/rerun/latest/rerun/components/struct.ImagePlaneDistance.html) ## Used by * [`Pinhole`](../archetypes/pinhole.md) # KeypointId --- title: "KeypointId" --- A 16-bit ID representing a type of semantic keypoint within a class. ## Rerun datatype [`KeypointId`](../datatypes/keypoint_id.md) ## Arrow datatype ``` uint16 ``` ## API reference links * 🌊 [C++ API docs for `KeypointId`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1KeypointId.html) * 🐍 [Python API docs for `KeypointId`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.KeypointId) * 🦀 [Rust API docs for `KeypointId`](https://docs.rs/rerun/latest/rerun/components/struct.KeypointId.html) ## Used by * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) # LatLon --- title: "LatLon" --- A geospatial position expressed in [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees). ## Rerun datatype [`DVec2D`](../datatypes/dvec2d.md) ## Arrow datatype ``` FixedSizeList<2, float64> ``` ## API reference links * 🌊 [C++ API docs for `LatLon`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1LatLon.html) * 🐍 [Python API docs for `LatLon`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.LatLon) * 🦀 [Rust API docs for `LatLon`](https://docs.rs/rerun/latest/rerun/components/struct.LatLon.html) ## Used by * [`GeoPoints`](../archetypes/geo_points.md) # Length --- title: "Length" --- Length, or one-dimensional size. Measured in its local coordinate system; consult the archetype in use to determine which axis or part of the entity this is the length of. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `Length`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Length.html) * 🐍 [Python API docs for `Length`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Length) * 🦀 [Rust API docs for `Length`](https://docs.rs/rerun/latest/rerun/components/struct.Length.html) ## Used by * [`Capsules3D`](../archetypes/capsules3d.md) # LineStrip2D --- title: "LineStrip2D" --- A line strip in 2D space. A line strip is a list of points connected by line segments. It can be used to draw approximations of smooth curves. The points will be connected in order, like so: ```text 2------3 5 / \ / 0----1 \ / 4 ``` ## Arrow datatype ``` List> ``` ## API reference links * 🌊 [C++ API docs for `LineStrip2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1LineStrip2D.html) * 🐍 [Python API docs for `LineStrip2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.LineStrip2D) * 🦀 [Rust API docs for `LineStrip2D`](https://docs.rs/rerun/latest/rerun/components/struct.LineStrip2D.html) ## Used by * [`LineStrips2D`](../archetypes/line_strips2d.md) # LineStrip3D --- title: "LineStrip3D" --- A line strip in 3D space. A line strip is a list of points connected by line segments. It can be used to draw approximations of smooth curves. The points will be connected in order, like so: ```text 2------3 5 / \ / 0----1 \ / 4 ``` ## Arrow datatype ``` List> ``` ## API reference links * 🌊 [C++ API docs for `LineStrip3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1LineStrip3D.html) * 🐍 [Python API docs for `LineStrip3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.LineStrip3D) * 🦀 [Rust API docs for `LineStrip3D`](https://docs.rs/rerun/latest/rerun/components/struct.LineStrip3D.html) ## Used by * [`LineStrips3D`](../archetypes/line_strips3d.md) # MagnificationFilter --- title: "MagnificationFilter" --- Filter used when magnifying an image/texture such that a single pixel/texel is displayed as multiple pixels on screen. ## Variants #### `Nearest` = 1 Show the nearest pixel value. This will give a blocky appearance when zooming in. Used as default when rendering 2D images. #### `Linear` = 2 Linearly interpolate the nearest neighbors, creating a smoother look when zooming in. Used as default for mesh rendering. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `MagnificationFilter`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `MagnificationFilter`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.MagnificationFilter) * 🦀 [Rust API docs for `MagnificationFilter`](https://docs.rs/rerun/latest/rerun/components/enum.MagnificationFilter.html) # MarkerShape --- title: "MarkerShape" --- The visual appearance of a point in e.g. a 2D plot. ## Variants #### `Circle` = 1 `⏺` #### `Diamond` = 2 `◆` #### `Square` = 3 `◼️` #### `Cross` = 4 `x` #### `Plus` = 5 `+` #### `Up` = 6 `▲` #### `Down` = 7 `▼` #### `Left` = 8 `◀` #### `Right` = 9 `▶` #### `Asterisk` = 10 `*` ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `MarkerShape`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `MarkerShape`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.MarkerShape) * 🦀 [Rust API docs for `MarkerShape`](https://docs.rs/rerun/latest/rerun/components/enum.MarkerShape.html) ## Used by * [`SeriesPoint`](../archetypes/series_point.md) # MarkerSize --- title: "MarkerSize" --- Radius of a marker of a point in e.g. a 2D plot, measured in UI points. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `MarkerSize`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1MarkerSize.html) * 🐍 [Python API docs for `MarkerSize`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.MarkerSize) * 🦀 [Rust API docs for `MarkerSize`](https://docs.rs/rerun/latest/rerun/components/struct.MarkerSize.html) ## Used by * [`SeriesPoint`](../archetypes/series_point.md) # MediaType --- title: "MediaType" --- A standardized media type (RFC2046, formerly known as MIME types), encoded as a string. The complete reference of officially registered media types is maintained by the IANA and can be consulted at . ## Rerun datatype [`Utf8`](../datatypes/utf8.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `MediaType`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1MediaType.html) * 🐍 [Python API docs for `MediaType`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.MediaType) * 🦀 [Rust API docs for `MediaType`](https://docs.rs/rerun/latest/rerun/components/struct.MediaType.html) ## Used by * [`Asset3D`](../archetypes/asset3d.md) * [`AssetVideo`](../archetypes/asset_video.md) * [`EncodedImage`](../archetypes/encoded_image.md) * [`TextDocument`](../archetypes/text_document.md) # Name --- title: "Name" --- A display name, typically for an entity or a item like a plot series. ## Rerun datatype [`Utf8`](../datatypes/utf8.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `Name`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Name.html) * 🐍 [Python API docs for `Name`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Name) * 🦀 [Rust API docs for `Name`](https://docs.rs/rerun/latest/rerun/components/struct.Name.html) ## Used by * [`SeriesLine`](../archetypes/series_line.md) * [`SeriesPoint`](../archetypes/series_point.md) # Opacity --- title: "Opacity" --- Degree of transparency ranging from 0.0 (fully transparent) to 1.0 (fully opaque). The final opacity value may be a result of multiplication with alpha values as specified by other color sources. Unless otherwise specified, the default value is 1. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `Opacity`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Opacity.html) * 🐍 [Python API docs for `Opacity`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Opacity) * 🦀 [Rust API docs for `Opacity`](https://docs.rs/rerun/latest/rerun/components/struct.Opacity.html) ## Used by * [`EncodedImage`](../archetypes/encoded_image.md) * [`Image`](../archetypes/image.md) * [`SegmentationImage`](../archetypes/segmentation_image.md) # PinholeProjection --- title: "PinholeProjection" --- Camera projection, from image coordinates to view coordinates. Child from parent. Image coordinates from camera view coordinates. Example: ```text 1496.1 0.0 980.5 0.0 1496.1 744.5 0.0 0.0 1.0 ``` ## Rerun datatype [`Mat3x3`](../datatypes/mat3x3.md) ## Arrow datatype ``` FixedSizeList<9, float32> ``` ## API reference links * 🌊 [C++ API docs for `PinholeProjection`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1PinholeProjection.html) * 🐍 [Python API docs for `PinholeProjection`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.PinholeProjection) * 🦀 [Rust API docs for `PinholeProjection`](https://docs.rs/rerun/latest/rerun/components/struct.PinholeProjection.html) ## Used by * [`Pinhole`](../archetypes/pinhole.md) # Plane3D --- title: "Plane3D" --- An infinite 3D plane represented by a unit normal vector and a distance. Any point P on the plane fulfills the equation `dot(xyz, P) - d = 0`, where `xyz` is the plane's normal and `d` the distance of the plane from the origin. This representation is also known as the Hesse normal form. Note: although the normal will be passed through to the datastore as provided, when used in the Viewer, planes will always be normalized. I.e. the plane with xyz = (2, 0, 0), d = 1 is equivalent to xyz = (1, 0, 0), d = 0.5 ## Rerun datatype [`Plane3D`](../datatypes/plane3d.md) ## Arrow datatype ``` FixedSizeList<4, float32> ``` ## API reference links * 🌊 [C++ API docs for `Plane3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Plane3D.html) * 🐍 [Python API docs for `Plane3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Plane3D) * 🦀 [Rust API docs for `Plane3D`](https://docs.rs/rerun/latest/rerun/components/struct.Plane3D.html) # PoseRotationAxisAngle --- title: "PoseRotationAxisAngle" --- 3D rotation represented by a rotation around a given axis that doesn't propagate in the transform hierarchy. If normalization of the rotation axis fails the rotation is treated as an invalid transform, unless the angle is zero in which case it is treated as an identity. ## Rerun datatype [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) ## Arrow datatype ``` Struct { axis: FixedSizeList<3, float32> angle: float32 } ``` ## API reference links * 🌊 [C++ API docs for `PoseRotationAxisAngle`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1PoseRotationAxisAngle.html) * 🐍 [Python API docs for `PoseRotationAxisAngle`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.PoseRotationAxisAngle) * 🦀 [Rust API docs for `PoseRotationAxisAngle`](https://docs.rs/rerun/latest/rerun/components/struct.PoseRotationAxisAngle.html) ## Used by * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`InstancePoses3D`](../archetypes/instance_poses3d.md) # PoseRotationQuat --- title: "PoseRotationQuat" --- A 3D rotation expressed as a quaternion that doesn't propagate in the transform hierarchy. Note: although the x,y,z,w components of the quaternion will be passed through to the datastore as provided, when used in the Viewer, quaternions will always be normalized. If normalization fails the rotation is treated as an invalid transform. ## Rerun datatype [`Quaternion`](../datatypes/quaternion.md) ## Arrow datatype ``` FixedSizeList<4, float32> ``` ## API reference links * 🌊 [C++ API docs for `PoseRotationQuat`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1PoseRotationQuat.html) * 🐍 [Python API docs for `PoseRotationQuat`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.PoseRotationQuat) * 🦀 [Rust API docs for `PoseRotationQuat`](https://docs.rs/rerun/latest/rerun/components/struct.PoseRotationQuat.html) ## Used by * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`InstancePoses3D`](../archetypes/instance_poses3d.md) # PoseScale3D --- title: "PoseScale3D" --- A 3D scale factor that doesn't propagate in the transform hierarchy. A scale of 1.0 means no scaling. A scale of 2.0 means doubling the size. Each component scales along the corresponding axis. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `PoseScale3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1PoseScale3D.html) * 🐍 [Python API docs for `PoseScale3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.PoseScale3D) * 🦀 [Rust API docs for `PoseScale3D`](https://docs.rs/rerun/latest/rerun/components/struct.PoseScale3D.html) ## Used by * [`InstancePoses3D`](../archetypes/instance_poses3d.md) # PoseTransformMat3x3 --- title: "PoseTransformMat3x3" --- A 3x3 transformation matrix Matrix that doesn't propagate in the transform hierarchy. 3x3 matrixes are able to represent any affine transformation in 3D space, i.e. rotation, scaling, shearing, reflection etc. Matrices in Rerun are stored as flat list of coefficients in column-major order: ```text column 0 column 1 column 2 ------------------------------------------------- row 0 | flat_columns[0] flat_columns[3] flat_columns[6] row 1 | flat_columns[1] flat_columns[4] flat_columns[7] row 2 | flat_columns[2] flat_columns[5] flat_columns[8] ``` ## Rerun datatype [`Mat3x3`](../datatypes/mat3x3.md) ## Arrow datatype ``` FixedSizeList<9, float32> ``` ## API reference links * 🌊 [C++ API docs for `PoseTransformMat3x3`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1PoseTransformMat3x3.html) * 🐍 [Python API docs for `PoseTransformMat3x3`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.PoseTransformMat3x3) * 🦀 [Rust API docs for `PoseTransformMat3x3`](https://docs.rs/rerun/latest/rerun/components/struct.PoseTransformMat3x3.html) ## Used by * [`InstancePoses3D`](../archetypes/instance_poses3d.md) # PoseTranslation3D --- title: "PoseTranslation3D" --- A translation vector in 3D space that doesn't propagate in the transform hierarchy. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `PoseTranslation3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1PoseTranslation3D.html) * 🐍 [Python API docs for `PoseTranslation3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.PoseTranslation3D) * 🦀 [Rust API docs for `PoseTranslation3D`](https://docs.rs/rerun/latest/rerun/components/struct.PoseTranslation3D.html) ## Used by * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`InstancePoses3D`](../archetypes/instance_poses3d.md) # Position2D --- title: "Position2D" --- A position in 2D space. ## Rerun datatype [`Vec2D`](../datatypes/vec2d.md) ## Arrow datatype ``` FixedSizeList<2, float32> ``` ## API reference links * 🌊 [C++ API docs for `Position2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Position2D.html) * 🐍 [Python API docs for `Position2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Position2D) * 🦀 [Rust API docs for `Position2D`](https://docs.rs/rerun/latest/rerun/components/struct.Position2D.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`GraphNodes`](../archetypes/graph_nodes.md) * [`Points2D`](../archetypes/points2d.md) # Position3D --- title: "Position3D" --- A position in 3D space. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `Position3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Position3D.html) * 🐍 [Python API docs for `Position3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Position3D) * 🦀 [Rust API docs for `Position3D`](https://docs.rs/rerun/latest/rerun/components/struct.Position3D.html) ## Used by * [`Arrows3D`](../archetypes/arrows3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) * [`Points3D`](../archetypes/points3d.md) # Radius --- title: "Radius" --- The radius of something, e.g. a point. Internally, positive values indicate scene units, whereas negative values are interpreted as UI points. UI points are independent of zooming in Views, but are sensitive to the application UI scaling. at 100% UI scaling, UI points are equal to pixels The Viewer's UI scaling defaults to the OS scaling which typically is 100% for full HD screens and 200% for 4k screens. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `Radius`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Radius.html) * 🐍 [Python API docs for `Radius`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Radius) * 🦀 [Rust API docs for `Radius`](https://docs.rs/rerun/latest/rerun/components/struct.Radius.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Arrows3D`](../archetypes/arrows3d.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GeoLineStrings`](../archetypes/geo_line_strings.md) * [`GeoPoints`](../archetypes/geo_points.md) * [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) # Range1D --- title: "Range1D" --- A 1D range, specifying a lower and upper bound. ## Rerun datatype [`Range1D`](../datatypes/range1d.md) ## Arrow datatype ``` FixedSizeList<2, float64> ``` ## API reference links * 🌊 [C++ API docs for `Range1D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Range1D.html) * 🐍 [Python API docs for `Range1D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Range1D) * 🦀 [Rust API docs for `Range1D`](https://docs.rs/rerun/latest/rerun/components/struct.Range1D.html) # RecordingUri --- title: "RecordingUri" --- A recording URI (Uniform Resource Identifier). ## Rerun datatype [`Utf8`](../datatypes/utf8.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `RecordingUri`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1RecordingUri.html) * 🐍 [Python API docs for `RecordingUri`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.RecordingUri) * 🦀 [Rust API docs for `RecordingUri`](https://docs.rs/rerun/latest/rerun/components/struct.RecordingUri.html) # Resolution --- title: "Resolution" --- Pixel resolution width & height, e.g. of a camera sensor. Typically in integer units, but for some use cases floating point may be used. ## Rerun datatype [`Vec2D`](../datatypes/vec2d.md) ## Arrow datatype ``` FixedSizeList<2, float32> ``` ## API reference links * 🌊 [C++ API docs for `Resolution`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Resolution.html) * 🐍 [Python API docs for `Resolution`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Resolution) * 🦀 [Rust API docs for `Resolution`](https://docs.rs/rerun/latest/rerun/components/struct.Resolution.html) ## Used by * [`Pinhole`](../archetypes/pinhole.md) # RotationAxisAngle --- title: "RotationAxisAngle" --- 3D rotation represented by a rotation around a given axis. If normalization of the rotation axis fails the rotation is treated as an invalid transform, unless the angle is zero in which case it is treated as an identity. ## Rerun datatype [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) ## Arrow datatype ``` Struct { axis: FixedSizeList<3, float32> angle: float32 } ``` ## API reference links * 🌊 [C++ API docs for `RotationAxisAngle`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1RotationAxisAngle.html) * 🐍 [Python API docs for `RotationAxisAngle`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.RotationAxisAngle) * 🦀 [Rust API docs for `RotationAxisAngle`](https://docs.rs/rerun/latest/rerun/components/struct.RotationAxisAngle.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # RotationQuat --- title: "RotationQuat" --- A 3D rotation expressed as a quaternion. Note: although the x,y,z,w components of the quaternion will be passed through to the datastore as provided, when used in the Viewer, quaternions will always be normalized. If normalization fails the rotation is treated as an invalid transform. ## Rerun datatype [`Quaternion`](../datatypes/quaternion.md) ## Arrow datatype ``` FixedSizeList<4, float32> ``` ## API reference links * 🌊 [C++ API docs for `RotationQuat`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1RotationQuat.html) * 🐍 [Python API docs for `RotationQuat`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.RotationQuat) * 🦀 [Rust API docs for `RotationQuat`](https://docs.rs/rerun/latest/rerun/components/struct.RotationQuat.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # Scalar --- title: "Scalar" --- A scalar value, encoded as a 64-bit floating point. Used for time series plots. ## Rerun datatype [`Float64`](../datatypes/float64.md) ## Arrow datatype ``` float64 ``` ## API reference links * 🌊 [C++ API docs for `Scalar`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Scalar.html) * 🐍 [Python API docs for `Scalar`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Scalar) * 🦀 [Rust API docs for `Scalar`](https://docs.rs/rerun/latest/rerun/components/struct.Scalar.html) ## Used by * [`Scalar`](../archetypes/scalar.md) # Scale3D --- title: "Scale3D" --- A 3D scale factor. A scale of 1.0 means no scaling. A scale of 2.0 means doubling the size. Each component scales along the corresponding axis. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `Scale3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Scale3D.html) * 🐍 [Python API docs for `Scale3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Scale3D) * 🦀 [Rust API docs for `Scale3D`](https://docs.rs/rerun/latest/rerun/components/struct.Scale3D.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # ShowLabels --- title: "ShowLabels" --- Whether the entity's [`components.Text`](https://rerun.io/docs/reference/types/components/text) label is shown. The main purpose of this component existing separately from the labels themselves is to be overridden when desired, to allow hiding and showing from the viewer and blueprints. ## Rerun datatype [`Bool`](../datatypes/bool.md) ## Arrow datatype ``` boolean ``` ## API reference links * 🌊 [C++ API docs for `ShowLabels`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ShowLabels.html) * 🐍 [Python API docs for `ShowLabels`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ShowLabels) * 🦀 [Rust API docs for `ShowLabels`](https://docs.rs/rerun/latest/rerun/components/struct.ShowLabels.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Arrows3D`](../archetypes/arrows3d.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) # StrokeWidth --- title: "StrokeWidth" --- The width of a stroke specified in UI points. ## Rerun datatype [`Float32`](../datatypes/float32.md) ## Arrow datatype ``` float32 ``` ## API reference links * 🌊 [C++ API docs for `StrokeWidth`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1StrokeWidth.html) * 🐍 [Python API docs for `StrokeWidth`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.StrokeWidth) * 🦀 [Rust API docs for `StrokeWidth`](https://docs.rs/rerun/latest/rerun/components/struct.StrokeWidth.html) ## Used by * [`SeriesLine`](../archetypes/series_line.md) # TensorData --- title: "TensorData" --- An N-dimensional array of numbers. The number of dimensions and their respective lengths is specified by the `shape` field. The dimensions are ordered from outermost to innermost. For example, in the common case of a 2D RGB Image, the shape would be `[height, width, channel]`. These dimensions are combined with an index to look up values from the `buffer` field, which stores a contiguous array of typed values. ## Rerun datatype [`TensorData`](../datatypes/tensor_data.md) ## Arrow datatype ``` Struct { shape: List names: nullable List buffer: DenseUnion { 0 = "_null_markers": nullable null 1 = "U8": List 2 = "U16": List 3 = "U32": List 4 = "U64": List 5 = "I8": List 6 = "I16": List 7 = "I32": List 8 = "I64": List 9 = "F16": List 10 = "F32": List 11 = "F64": List } } ``` ## API reference links * 🌊 [C++ API docs for `TensorData`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TensorData.html) * 🐍 [Python API docs for `TensorData`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TensorData) * 🦀 [Rust API docs for `TensorData`](https://docs.rs/rerun/latest/rerun/components/struct.TensorData.html) ## Used by * [`BarChart`](../archetypes/bar_chart.md) * [`Tensor`](../archetypes/tensor.md) # TensorDimensionIndexSelection --- title: "TensorDimensionIndexSelection" --- Specifies a concrete index on a tensor dimension. ## Rerun datatype [`TensorDimensionIndexSelection`](../datatypes/tensor_dimension_index_selection.md) ## Arrow datatype ``` Struct { dimension: uint32 index: uint64 } ``` ## API reference links * 🌊 [C++ API docs for `TensorDimensionIndexSelection`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TensorDimensionIndexSelection.html) * 🐍 [Python API docs for `TensorDimensionIndexSelection`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TensorDimensionIndexSelection) * 🦀 [Rust API docs for `TensorDimensionIndexSelection`](https://docs.rs/rerun/latest/rerun/components/struct.TensorDimensionIndexSelection.html) # TensorHeightDimension --- title: "TensorHeightDimension" --- Specifies which dimension to use for height. ## Rerun datatype [`TensorDimensionSelection`](../datatypes/tensor_dimension_selection.md) ## Arrow datatype ``` Struct { dimension: uint32 invert: boolean } ``` ## API reference links * 🌊 [C++ API docs for `TensorHeightDimension`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TensorHeightDimension.html) * 🐍 [Python API docs for `TensorHeightDimension`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TensorHeightDimension) * 🦀 [Rust API docs for `TensorHeightDimension`](https://docs.rs/rerun/latest/rerun/components/struct.TensorHeightDimension.html) # TensorWidthDimension --- title: "TensorWidthDimension" --- Specifies which dimension to use for width. ## Rerun datatype [`TensorDimensionSelection`](../datatypes/tensor_dimension_selection.md) ## Arrow datatype ``` Struct { dimension: uint32 invert: boolean } ``` ## API reference links * 🌊 [C++ API docs for `TensorWidthDimension`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TensorWidthDimension.html) * 🐍 [Python API docs for `TensorWidthDimension`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TensorWidthDimension) * 🦀 [Rust API docs for `TensorWidthDimension`](https://docs.rs/rerun/latest/rerun/components/struct.TensorWidthDimension.html) # Texcoord2D --- title: "Texcoord2D" --- A 2D texture UV coordinate. Texture coordinates specify a position on a 2D texture. A range from 0-1 covers the entire texture in the respective dimension. Unless configured otherwise, the texture repeats outside of this range. Rerun uses top-left as the origin for UV coordinates. 0 U 1 0 + --------- → | . V | . | . 1 ↓ . . . . . . This is the same convention as in Vulkan/Metal/DX12/WebGPU, but (!) unlike OpenGL, which places the origin at the bottom-left. ## Rerun datatype [`Vec2D`](../datatypes/vec2d.md) ## Arrow datatype ``` FixedSizeList<2, float32> ``` ## API reference links * 🌊 [C++ API docs for `Texcoord2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Texcoord2D.html) * 🐍 [Python API docs for `Texcoord2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Texcoord2D) * 🦀 [Rust API docs for `Texcoord2D`](https://docs.rs/rerun/latest/rerun/components/struct.Texcoord2D.html) ## Used by * [`Mesh3D`](../archetypes/mesh3d.md) # Text --- title: "Text" --- A string of text, e.g. for labels and text documents. ## Rerun datatype [`Utf8`](../datatypes/utf8.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `Text`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Text.html) * 🐍 [Python API docs for `Text`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Text) * 🦀 [Rust API docs for `Text`](https://docs.rs/rerun/latest/rerun/components/struct.Text.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) * [`Arrows3D`](../archetypes/arrows3d.md) * [`Boxes2D`](../archetypes/boxes2d.md) * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) * [`TextDocument`](../archetypes/text_document.md) * [`TextLog`](../archetypes/text_log.md) # TextLogLevel --- title: "TextLogLevel" --- The severity level of a text log message. Recommended to be one of: * `"CRITICAL"` * `"ERROR"` * `"WARN"` * `"INFO"` * `"DEBUG"` * `"TRACE"` ## Rerun datatype [`Utf8`](../datatypes/utf8.md) ## Arrow datatype ``` utf8 ``` ## API reference links * 🌊 [C++ API docs for `TextLogLevel`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TextLogLevel.html) * 🐍 [Python API docs for `TextLogLevel`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TextLogLevel) * 🦀 [Rust API docs for `TextLogLevel`](https://docs.rs/rerun/latest/rerun/components/struct.TextLogLevel.html) ## Used by * [`TextLog`](../archetypes/text_log.md) # TransformMat3x3 --- title: "TransformMat3x3" --- A 3x3 transformation matrix Matrix. 3x3 matrixes are able to represent any affine transformation in 3D space, i.e. rotation, scaling, shearing, reflection etc. Matrices in Rerun are stored as flat list of coefficients in column-major order: ```text column 0 column 1 column 2 ------------------------------------------------- row 0 | flat_columns[0] flat_columns[3] flat_columns[6] row 1 | flat_columns[1] flat_columns[4] flat_columns[7] row 2 | flat_columns[2] flat_columns[5] flat_columns[8] ``` ## Rerun datatype [`Mat3x3`](../datatypes/mat3x3.md) ## Arrow datatype ``` FixedSizeList<9, float32> ``` ## API reference links * 🌊 [C++ API docs for `TransformMat3x3`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TransformMat3x3.html) * 🐍 [Python API docs for `TransformMat3x3`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TransformMat3x3) * 🦀 [Rust API docs for `TransformMat3x3`](https://docs.rs/rerun/latest/rerun/components/struct.TransformMat3x3.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # TransformRelation --- title: "TransformRelation" --- Specifies relation a spatial transform describes. ## Variants #### `ParentFromChild` = 1 The transform describes how to transform into the parent entity's space. E.g. a translation of (0, 1, 0) with this [`components.TransformRelation`](https://rerun.io/docs/reference/types/components/transform_relation) logged at `parent/child` means that from the point of view of `parent`, `parent/child` is translated 1 unit along `parent`'s Y axis. From perspective of `parent/child`, the `parent` entity is translated -1 unit along `parent/child`'s Y axis. #### `ChildFromParent` = 2 The transform describes how to transform into the child entity's space. E.g. a translation of (0, 1, 0) with this [`components.TransformRelation`](https://rerun.io/docs/reference/types/components/transform_relation) logged at `parent/child` means that from the point of view of `parent`, `parent/child` is translated -1 unit along `parent`'s Y axis. From perspective of `parent/child`, the `parent` entity is translated 1 unit along `parent/child`'s Y axis. ## Arrow datatype ``` uint8 ``` ## API reference links * 🌊 [C++ API docs for `TransformRelation`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) * 🐍 [Python API docs for `TransformRelation`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TransformRelation) * 🦀 [Rust API docs for `TransformRelation`](https://docs.rs/rerun/latest/rerun/components/enum.TransformRelation.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # Translation3D --- title: "Translation3D" --- A translation vector in 3D space. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `Translation3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Translation3D.html) * 🐍 [Python API docs for `Translation3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Translation3D) * 🦀 [Rust API docs for `Translation3D`](https://docs.rs/rerun/latest/rerun/components/struct.Translation3D.html) ## Used by * [`Transform3D`](../archetypes/transform3d.md) # TriangleIndices --- title: "TriangleIndices" --- The three indices of a triangle in a triangle mesh. ## Rerun datatype [`UVec3D`](../datatypes/uvec3d.md) ## Arrow datatype ``` FixedSizeList<3, uint32> ``` ## API reference links * 🌊 [C++ API docs for `TriangleIndices`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1TriangleIndices.html) * 🐍 [Python API docs for `TriangleIndices`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.TriangleIndices) * 🦀 [Rust API docs for `TriangleIndices`](https://docs.rs/rerun/latest/rerun/components/struct.TriangleIndices.html) ## Used by * [`Mesh3D`](../archetypes/mesh3d.md) # ValueRange --- title: "ValueRange" --- Range of expected or valid values, specifying a lower and upper bound. ## Rerun datatype [`Range1D`](../datatypes/range1d.md) ## Arrow datatype ``` FixedSizeList<2, float64> ``` ## API reference links * 🌊 [C++ API docs for `ValueRange`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ValueRange.html) * 🐍 [Python API docs for `ValueRange`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ValueRange) * 🦀 [Rust API docs for `ValueRange`](https://docs.rs/rerun/latest/rerun/components/struct.ValueRange.html) ## Used by * [`DepthImage`](../archetypes/depth_image.md) * [`Tensor`](../archetypes/tensor.md) # Vector2D --- title: "Vector2D" --- A vector in 2D space. ## Rerun datatype [`Vec2D`](../datatypes/vec2d.md) ## Arrow datatype ``` FixedSizeList<2, float32> ``` ## API reference links * 🌊 [C++ API docs for `Vector2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Vector2D.html) * 🐍 [Python API docs for `Vector2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Vector2D) * 🦀 [Rust API docs for `Vector2D`](https://docs.rs/rerun/latest/rerun/components/struct.Vector2D.html) ## Used by * [`Arrows2D`](../archetypes/arrows2d.md) # Vector3D --- title: "Vector3D" --- A vector in 3D space. ## Rerun datatype [`Vec3D`](../datatypes/vec3d.md) ## Arrow datatype ``` FixedSizeList<3, float32> ``` ## API reference links * 🌊 [C++ API docs for `Vector3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Vector3D.html) * 🐍 [Python API docs for `Vector3D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Vector3D) * 🦀 [Rust API docs for `Vector3D`](https://docs.rs/rerun/latest/rerun/components/struct.Vector3D.html) ## Used by * [`Arrows3D`](../archetypes/arrows3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) # VideoTimestamp --- title: "VideoTimestamp" --- Timestamp inside a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video). ## Rerun datatype [`VideoTimestamp`](../datatypes/video_timestamp.md) ## Arrow datatype ``` int64 ``` ## API reference links * 🌊 [C++ API docs for `VideoTimestamp`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1VideoTimestamp.html) * 🐍 [Python API docs for `VideoTimestamp`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.VideoTimestamp) * 🦀 [Rust API docs for `VideoTimestamp`](https://docs.rs/rerun/latest/rerun/components/struct.VideoTimestamp.html) ## Used by * [`VideoFrameReference`](../archetypes/video_frame_reference.md) # ViewCoordinates --- title: "ViewCoordinates" --- How we interpret the coordinate system of an entity/space. For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). The following constants are used to represent the different directions: * Up = 1 * Down = 2 * Right = 3 * Left = 4 * Forward = 5 * Back = 6 ## Rerun datatype [`ViewCoordinates`](../datatypes/view_coordinates.md) ## Arrow datatype ``` FixedSizeList<3, uint8> ``` ## API reference links * 🌊 [C++ API docs for `ViewCoordinates`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1ViewCoordinates.html) * 🐍 [Python API docs for `ViewCoordinates`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.ViewCoordinates) * 🦀 [Rust API docs for `ViewCoordinates`](https://docs.rs/rerun/latest/rerun/components/struct.ViewCoordinates.html) ## Used by * [`Pinhole`](../archetypes/pinhole.md) * [`ViewCoordinates`](../archetypes/view_coordinates.md) # AnnotationContext --- title: "AnnotationContext" --- The annotation context provides additional information on how to display entities. Entities can use [`components.ClassId`](https://rerun.io/docs/reference/types/components/class_id)s and [`components.KeypointId`](https://rerun.io/docs/reference/types/components/keypoint_id)s to provide annotations, and the labels and colors will be looked up in the appropriate annotation context. We use the *first* annotation context we find in the path-hierarchy when searching up through the ancestors of a given entity path. See also [`datatypes.ClassDescription`](https://rerun.io/docs/reference/types/datatypes/class_description). ## Components **Required**: [`AnnotationContext`](../components/annotation_context.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `AnnotationContext`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1AnnotationContext.html) * 🐍 [Python API docs for `AnnotationContext`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.AnnotationContext) * 🦀 [Rust API docs for `AnnotationContext`](https://docs.rs/rerun/latest/rerun/archetypes/struct.AnnotationContext.html) ## Examples ### Rectangles ```python import rerun as rr rr.init("rerun_example_annotation_context_rects", spawn=True) # Log an annotation context to assign a label and color to each class rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) ``` ### Segmentation ```python """Log a segmentation image with annotations.""" import numpy as np import rerun as rr rr.init("rerun_example_annotation_context_segmentation", spawn=True) # Create a simple segmentation image image = np.zeros((200, 300), dtype=np.uint8) image[50:100, 50:120] = 1 image[100:180, 130:280] = 2 # Log an annotation context to assign a label and color to each class rr.log("segmentation", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) rr.log("segmentation/image", rr.SegmentationImage(image)) ``` ### Connections ```python """Log annotation context with connections between keypoints.""" import rerun as rr from rerun.datatypes import ClassDescription rr.init("rerun_example_annotation_context_connections", spawn=True) rr.log( "/", rr.AnnotationContext([ ClassDescription( info=0, keypoint_annotations=[ (0, "zero", (255, 0, 0)), (1, "one", (0, 255, 0)), (2, "two", (0, 0, 255)), (3, "three", (255, 255, 0)), ], keypoint_connections=[(0, 2), (1, 2), (2, 3)], ) ]), static=True, ) rr.log( "points", rr.Points3D( [ (0, 0, 0), (50, 0, 20), (100, 100, 30), (0, 50, 40), ], class_ids=[0], keypoint_ids=[0, 1, 2, 3], ), ) ``` # Arrows2D --- title: "Arrows2D" --- 2D arrows with optional colors, radii, labels, etc. ## Components **Required**: [`Vector2D`](../components/vector2d.md) **Recommended**: [`Position2D`](../components/position2d.md) **Optional**: [`Radius`](../components/radius.md), [`Color`](../components/color.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`DrawOrder`](../components/draw_order.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Arrows2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Arrows2D.html) * 🐍 [Python API docs for `Arrows2D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Arrows2D) * 🦀 [Rust API docs for `Arrows2D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Arrows2D.html) ## Example ### Simple batch of 2D arrows ```python """Log a batch of 2D arrows.""" import rerun as rr rr.init("rerun_example_arrow2d", spawn=True) rr.log( "arrows", rr.Arrows2D( origins=[[0.25, 0.0], [0.25, 0.0], [-0.1, -0.1]], vectors=[[1.0, 0.0], [0.0, -1.0], [-0.7, 0.7]], colors=[[255, 0, 0], [0, 255, 0], [127, 0, 255]], labels=["right", "up", "left-down"], radii=0.025, ), ) ``` # Arrows3D --- title: "Arrows3D" --- 3D arrows with optional colors, radii, labels, etc. ## Components **Required**: [`Vector3D`](../components/vector3d.md) **Recommended**: [`Position3D`](../components/position3d.md) **Optional**: [`Radius`](../components/radius.md), [`Color`](../components/color.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Arrows3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Arrows3D.html) * 🐍 [Python API docs for `Arrows3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Arrows3D) * 🦀 [Rust API docs for `Arrows3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Arrows3D.html) ## Example ### Simple batch of 3D arrows ```python """Log a batch of 3D arrows.""" from math import tau import numpy as np import rerun as rr rr.init("rerun_example_arrow3d", spawn=True) lengths = np.log2(np.arange(0, 100) + 1) angles = np.arange(start=0, stop=tau, step=tau * 0.01) origins = np.zeros((100, 3)) vectors = np.column_stack([np.sin(angles) * lengths, np.zeros(100), np.cos(angles) * lengths]) colors = [[1.0 - c, c, 0.5, 0.5] for c in angles / tau] rr.log("arrows", rr.Arrows3D(origins=origins, vectors=vectors, colors=colors)) ``` # Asset3D --- title: "Asset3D" --- A prepacked 3D asset (`.gltf`, `.glb`, `.obj`, `.stl`, etc.). See also [`archetypes.Mesh3D`](https://rerun.io/docs/reference/types/archetypes/mesh3d). If there are multiple [`archetypes.InstancePoses3D`](https://rerun.io/docs/reference/types/archetypes/instance_poses3d) instances logged to the same entity as a mesh, an instance of the mesh will be drawn for each transform. ## Components **Required**: [`Blob`](../components/blob.md) **Recommended**: [`MediaType`](../components/media_type.md) **Optional**: [`AlbedoFactor`](../components/albedo_factor.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Asset3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Asset3D.html) * 🐍 [Python API docs for `Asset3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Asset3D) * 🦀 [Rust API docs for `Asset3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Asset3D.html) ## Example ### Simple 3D asset ```python """Log a simple 3D asset.""" import sys import rerun as rr if len(sys.argv) < 2: print(f"Usage: {sys.argv[0]} ") sys.exit(1) rr.init("rerun_example_asset3d", spawn=True) rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.log("world/asset", rr.Asset3D(path=sys.argv[1])) ``` # AssetVideo --- title: "AssetVideo" --- A video binary. Only MP4 containers with AV1 are generally supported, though the web viewer supports more video codecs, depending on browser. See for details of what is and isn't supported. In order to display a video, you also need to log a [`archetypes.VideoFrameReference`](https://rerun.io/docs/reference/types/archetypes/video_frame_reference) for each frame. ## Components **Required**: [`Blob`](../components/blob.md) **Recommended**: [`MediaType`](../components/media_type.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `AssetVideo`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1AssetVideo.html) * 🐍 [Python API docs for `AssetVideo`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.AssetVideo) * 🦀 [Rust API docs for `AssetVideo`](https://docs.rs/rerun/latest/rerun/archetypes/struct.AssetVideo.html) ## Examples ### Video with automatically determined frames ```python """Log a video asset using automatically determined frame references.""" import sys import rerun as rr if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} ") sys.exit(1) rr.init("rerun_example_asset_video_auto_frames", spawn=True) # Log video asset which is referred to by frame references. video_asset = rr.AssetVideo(path=sys.argv[1]) rr.log("video", video_asset, static=True) # Send automatically determined video frame timestamps. frame_timestamps_ns = video_asset.read_frame_timestamps_ns() rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) ``` ### Demonstrates manual use of video frame references ```python """Manual use of individual video frame references.""" # TODO(#7298): ⚠️ Video is currently only supported in the Rerun web viewer. import sys import rerun as rr import rerun.blueprint as rrb if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} ") sys.exit(1) rr.init("rerun_example_asset_video_manual_frames", spawn=True) # Log video asset which is referred to by frame references. rr.log("video_asset", rr.AssetVideo(path=sys.argv[1]), static=True) # Create two entities, showing the same video frozen at different times. rr.log( "frame_1s", rr.VideoFrameReference(seconds=1.0, video_reference="video_asset"), ) rr.log( "frame_2s", rr.VideoFrameReference(seconds=2.0, video_reference="video_asset"), ) # Send blueprint that shows two 2D views next to each other. rr.send_blueprint(rrb.Horizontal(rrb.Spatial2DView(origin="frame_1s"), rrb.Spatial2DView(origin="frame_2s"))) ``` # BarChart --- title: "BarChart" --- A bar chart. The x values will be the indices of the array, and the bar heights will be the provided values. ## Components **Required**: [`TensorData`](../components/tensor_data.md) **Optional**: [`Color`](../components/color.md) ## Shown in * [BarChartView](../views/bar_chart_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `BarChart`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1BarChart.html) * 🐍 [Python API docs for `BarChart`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.BarChart) * 🦀 [Rust API docs for `BarChart`](https://docs.rs/rerun/latest/rerun/archetypes/struct.BarChart.html) ## Example ### Simple bar chart ```python """Create and log a bar chart.""" import rerun as rr rr.init("rerun_example_bar_chart", spawn=True) rr.log("bar_chart", rr.BarChart([8, 4, 0, 9, 1, 4, 1, 6, 9, 0])) ``` # Boxes2D --- title: "Boxes2D" --- 2D boxes with half-extents and optional center, colors etc. ## Components **Required**: [`HalfSize2D`](../components/half_size2d.md) **Recommended**: [`Position2D`](../components/position2d.md), [`Color`](../components/color.md) **Optional**: [`Radius`](../components/radius.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`DrawOrder`](../components/draw_order.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Boxes2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Boxes2D.html) * 🐍 [Python API docs for `Boxes2D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Boxes2D) * 🦀 [Rust API docs for `Boxes2D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Boxes2D.html) ## Example ### Simple 2D boxes ```python """Log a simple 2D Box.""" import rerun as rr rr.init("rerun_example_box2d", spawn=True) rr.log("simple", rr.Boxes2D(mins=[-1, -1], sizes=[2, 2])) ``` # Boxes3D --- title: "Boxes3D" --- 3D boxes with half-extents and optional center, rotations, colors etc. Note that orienting and placing the box is handled via `[archetypes.InstancePoses3D]`. Some of its component are repeated here for convenience. If there's more instance poses than half sizes, the last half size will be repeated for the remaining poses. ## Components **Required**: [`HalfSize3D`](../components/half_size3d.md) **Recommended**: [`PoseTranslation3D`](../components/pose_translation3d.md), [`Color`](../components/color.md) **Optional**: [`PoseRotationAxisAngle`](../components/pose_rotation_axis_angle.md), [`PoseRotationQuat`](../components/pose_rotation_quat.md), [`Radius`](../components/radius.md), [`FillMode`](../components/fill_mode.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Boxes3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Boxes3D.html) * 🐍 [Python API docs for `Boxes3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Boxes3D) * 🦀 [Rust API docs for `Boxes3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Boxes3D.html) ## Examples ### Simple 3D boxes ```python """Log a single 3D Box.""" import rerun as rr rr.init("rerun_example_box3d", spawn=True) rr.log("simple", rr.Boxes3D(half_sizes=[2.0, 2.0, 1.0])) ``` ### Batch of 3D boxes ```python """Log a batch of oriented bounding boxes.""" import rerun as rr rr.init("rerun_example_box3d_batch", spawn=True) rr.log( "batch", rr.Boxes3D( centers=[[2, 0, 0], [-2, 0, 0], [0, 0, 2]], half_sizes=[[2.0, 2.0, 1.0], [1.0, 1.0, 0.5], [2.0, 0.5, 1.0]], quaternions=[ rr.Quaternion.identity(), rr.Quaternion(xyzw=[0.0, 0.0, 0.382683, 0.923880]), # 45 degrees around Z ], radii=0.025, colors=[(255, 0, 0), (0, 255, 0), (0, 0, 255)], fill_mode="solid", labels=["red", "green", "blue"], ), ) ``` # Capsules3D --- title: "Capsules3D" --- 3D capsules; cylinders with hemispherical caps. Capsules are defined by two endpoints (the centers of their end cap spheres), which are located at (0, 0, 0) and (0, 0, length), that is, extending along the positive direction of the Z axis. Capsules in other orientations may be produced by applying a rotation to the entity or instances. ## Components **Required**: [`Length`](../components/length.md), [`Radius`](../components/radius.md) **Recommended**: [`PoseTranslation3D`](../components/pose_translation3d.md), [`Color`](../components/color.md) **Optional**: [`PoseRotationAxisAngle`](../components/pose_rotation_axis_angle.md), [`PoseRotationQuat`](../components/pose_rotation_quat.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Capsules3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Capsules3D.html) * 🐍 [Python API docs for `Capsules3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Capsules3D) * 🦀 [Rust API docs for `Capsules3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Capsules3D.html) ## Example ### Batch of capsules ```python """Log a batch of capsules.""" import rerun as rr rr.init("rerun_example_capsule3d_batch", spawn=True) rr.log( "capsules", rr.Capsules3D( lengths=[0.0, 2.0, 4.0, 6.0, 8.0], radii=[1.0, 0.5, 0.5, 0.5, 1.0], colors=[ (255, 0, 0), (188, 188, 0), (0, 255, 0), (0, 188, 188), (0, 0, 255), ], translations=[ (0.0, 0.0, 0.0), (2.0, 0.0, 0.0), (4.0, 0.0, 0.0), (6.0, 0.0, 0.0), (8.0, 0.0, 0.0), ], rotation_axis_angles=[ rr.RotationAxisAngle( [1.0, 0.0, 0.0], rr.Angle(deg=float(i) * -22.5), ) for i in range(0, 5) ], ), ) ``` # Clear --- title: "Clear" --- Empties all the components of an entity. The presence of a clear means that a latest-at query of components at a given path(s) will not return any components that were logged at those paths before the clear. Any logged components after the clear are unaffected by the clear. This implies that a range query that includes time points that are before the clear, still returns all components at the given path(s). Meaning that in practice clears are ineffective when making use of visible time ranges. Scalar plots are an exception: they track clears and use them to represent holes in the data (i.e. discontinuous lines). ## Components **Required**: [`ClearIsRecursive`](../components/clear_is_recursive.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) * [TimeSeriesView](../views/time_series_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Clear`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Clear.html) * 🐍 [Python API docs for `Clear`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Clear) * 🦀 [Rust API docs for `Clear`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Clear.html) ## Examples ### Flat ```python """Log and then clear data.""" import rerun as rr rr.init("rerun_example_clear", spawn=True) vectors = [(1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (-1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] origins = [(-0.5, 0.5, 0.0), (0.5, 0.5, 0.0), (0.5, -0.5, 0.0), (-0.5, -0.5, 0.0)] colors = [(200, 0, 0), (0, 200, 0), (0, 0, 200), (200, 0, 200)] # Log a handful of arrows. for i, (vector, origin, color) in enumerate(zip(vectors, origins, colors)): rr.log(f"arrows/{i}", rr.Arrows3D(vectors=vector, origins=origin, colors=color)) # Now clear them, one by one on each tick. for i in range(len(vectors)): rr.log(f"arrows/{i}", rr.Clear(recursive=False)) # or `rr.Clear.flat()` ``` ### Recursive ```python """Log and then clear data recursively.""" import rerun as rr rr.init("rerun_example_clear_recursive", spawn=True) vectors = [(1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (-1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] origins = [(-0.5, 0.5, 0.0), (0.5, 0.5, 0.0), (0.5, -0.5, 0.0), (-0.5, -0.5, 0.0)] colors = [(200, 0, 0), (0, 200, 0), (0, 0, 200), (200, 0, 200)] # Log a handful of arrows. for i, (vector, origin, color) in enumerate(zip(vectors, origins, colors)): rr.log(f"arrows/{i}", rr.Arrows3D(vectors=vector, origins=origin, colors=color)) # Now clear all of them at once. rr.log("arrows", rr.Clear(recursive=True)) # or `rr.Clear.recursive()` ``` # DepthImage --- title: "DepthImage" --- A depth image, i.e. as captured by a depth camera. Each pixel corresponds to a depth value in units specified by [`components.DepthMeter`](https://rerun.io/docs/reference/types/components/depth_meter). ## Components **Required**: [`ImageBuffer`](../components/image_buffer.md), [`ImageFormat`](../components/image_format.md) **Optional**: [`DepthMeter`](../components/depth_meter.md), [`Colormap`](../components/colormap.md), [`ValueRange`](../components/value_range.md), [`FillRatio`](../components/fill_ratio.md), [`DrawOrder`](../components/draw_order.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `DepthImage`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1DepthImage.html) * 🐍 [Python API docs for `DepthImage`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.DepthImage) * 🦀 [Rust API docs for `DepthImage`](https://docs.rs/rerun/latest/rerun/archetypes/struct.DepthImage.html) ## Examples ### Simple example ```python """Create and log a depth image.""" import numpy as np import rerun as rr depth_image = 65535 * np.ones((200, 300), dtype=np.uint16) depth_image[50:150, 50:150] = 20000 depth_image[130:180, 100:280] = 45000 rr.init("rerun_example_depth_image_simple", spawn=True) # Log the tensor, assigning names to each dimension rr.log("depth", rr.DepthImage(depth_image, meter=10_000.0)) ``` ### Depth to 3D example ```python """Create and log a depth image and pinhole camera.""" import numpy as np import rerun as rr depth_image = 65535 * np.ones((200, 300), dtype=np.uint16) depth_image[50:150, 50:150] = 20000 depth_image[130:180, 100:280] = 45000 rr.init("rerun_example_depth_image_3d", spawn=True) # If we log a pinhole camera model, the depth gets automatically back-projected to 3D rr.log( "world/camera", rr.Pinhole( width=depth_image.shape[1], height=depth_image.shape[0], focal_length=200, ), ) # Log the tensor. rr.log("world/camera/depth", rr.DepthImage(depth_image, meter=10_000.0, colormap="viridis")) ``` # Ellipsoids3D --- title: "Ellipsoids3D" --- 3D ellipsoids or spheres. This archetype is for ellipsoids or spheres whose size is a key part of the data (e.g. a bounding sphere). For points whose radii are for the sake of visualization, use [`archetypes.Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d) instead. Note that orienting and placing the ellipsoids/spheres is handled via `[archetypes.InstancePoses3D]`. Some of its component are repeated here for convenience. If there's more instance poses than half sizes, the last half size will be repeated for the remaining poses. ## Components **Required**: [`HalfSize3D`](../components/half_size3d.md) **Recommended**: [`PoseTranslation3D`](../components/pose_translation3d.md), [`Color`](../components/color.md) **Optional**: [`PoseRotationAxisAngle`](../components/pose_rotation_axis_angle.md), [`PoseRotationQuat`](../components/pose_rotation_quat.md), [`Radius`](../components/radius.md), [`FillMode`](../components/fill_mode.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Ellipsoids3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Ellipsoids3D.html) * 🐍 [Python API docs for `Ellipsoids3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Ellipsoids3D) * 🦀 [Rust API docs for `Ellipsoids3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Ellipsoids3D.html) ## Example ### Covariance ellipsoid ```python """Log random points and the corresponding covariance ellipsoid.""" import numpy as np import rerun as rr rr.init("rerun_example_ellipsoid_simple", spawn=True) center = np.array([0, 0, 0]) sigmas = np.array([5, 3, 1]) points = np.random.randn(50_000, 3) * sigmas.reshape(1, -1) rr.log("points", rr.Points3D(points, radii=0.02, colors=[188, 77, 185])) rr.log( "ellipsoid", rr.Ellipsoids3D( centers=[center, center], half_sizes=[sigmas, 3 * sigmas], colors=[[255, 255, 0], [64, 64, 0]], ), ) ``` # EncodedImage --- title: "EncodedImage" --- An image encoded as e.g. a JPEG or PNG. Rerun also supports uncompressed images with the [`archetypes.Image`](https://rerun.io/docs/reference/types/archetypes/image). For images that refer to video frames see [`archetypes.VideoFrameReference`](https://rerun.io/docs/reference/types/archetypes/video_frame_reference). ## Components **Required**: [`Blob`](../components/blob.md) **Recommended**: [`MediaType`](../components/media_type.md) **Optional**: [`Opacity`](../components/opacity.md), [`DrawOrder`](../components/draw_order.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `EncodedImage`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1EncodedImage.html) * 🐍 [Python API docs for `EncodedImage`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.EncodedImage) * 🦀 [Rust API docs for `EncodedImage`](https://docs.rs/rerun/latest/rerun/archetypes/struct.EncodedImage.html) ## Example ### encoded_image ```python """Create and log an image.""" from pathlib import Path import rerun as rr image_file_path = Path(__file__).parent / "ferris.png" rr.init("rerun_example_encoded_image", spawn=True) rr.log("image", rr.EncodedImage(path=image_file_path)) ``` # GeoLineStrings --- title: "GeoLineStrings" --- Geospatial line strings with positions expressed in [EPSG:4326](https://epsg.io/4326) altitude and longitude (North/East-positive degrees), and optional colors and radii. Also known as "line strips" or "polylines". ## Components **Required**: [`GeoLineString`](../components/geo_line_string.md) **Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) ## Shown in * [MapView](../views/map_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `GeoLineStrings`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1GeoLineStrings.html) * 🐍 [Python API docs for `GeoLineStrings`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.GeoLineStrings) * 🦀 [Rust API docs for `GeoLineStrings`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GeoLineStrings.html) ## Example ### Log a geospatial line string ```python """Log a simple geospatial line string.""" import rerun as rr rr.init("rerun_example_geo_line_strings", spawn=True) rr.log( "colorado", rr.GeoLineStrings( lat_lon=[ [41.0000, -109.0452], [41.0000, -102.0415], [36.9931, -102.0415], [36.9931, -109.0452], [41.0000, -109.0452], ], radii=rr.Radius.ui_points(2.0), colors=[0, 0, 255], ), ) ``` # GeoPoints --- title: "GeoPoints" --- Geospatial points with positions expressed in [EPSG:4326](https://epsg.io/4326) latitude and longitude (North/East-positive degrees), and optional colors and radii. ## Components **Required**: [`LatLon`](../components/lat_lon.md) **Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) **Optional**: [`ClassId`](../components/class_id.md) ## Shown in * [MapView](../views/map_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `GeoPoints`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1GeoPoints.html) * 🐍 [Python API docs for `GeoPoints`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.GeoPoints) * 🦀 [Rust API docs for `GeoPoints`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GeoPoints.html) ## Example ### Log a geospatial point ```python """Log some very simple geospatial point.""" import rerun as rr rr.init("rerun_example_geo_points", spawn=True) rr.log( "rerun_hq", rr.GeoPoints( lat_lon=[59.319221, 18.075631], radii=rr.Radius.ui_points(10.0), colors=[255, 0, 0], ), ) ``` # GraphEdges --- title: "GraphEdges" --- A list of edges in a graph. By default, edges are undirected. ## Components **Required**: [`GraphEdge`](../components/graph_edge.md) **Recommended**: [`GraphType`](../components/graph_type.md) ## Shown in * [GraphView](../views/graph_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `GraphEdges`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1GraphEdges.html) * 🐍 [Python API docs for `GraphEdges`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.GraphEdges) * 🦀 [Rust API docs for `GraphEdges`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GraphEdges.html) ## Examples ### Simple undirected graph ```python """Log a simple undirected graph.""" import rerun as rr rr.init("rerun_example_graph_undirected", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"] ), rr.GraphEdges( edges=[("a", "b"), ("b", "c"), ("c", "a")], # Optional: graphs are undirected by default. graph_type="undirected", ), ) ``` ### Simple directed graph ```python """Log a simple directed graph.""" import rerun as rr rr.init("rerun_example_graph_directed", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"] ), rr.GraphEdges(edges=[("a", "b"), ("b", "c"), ("c", "a")], graph_type="directed"), ) ``` # GraphNodes --- title: "GraphNodes" --- A list of nodes in a graph with optional labels, colors, etc. ## Components **Required**: [`GraphNode`](../components/graph_node.md) **Optional**: [`Position2D`](../components/position2d.md), [`Color`](../components/color.md), [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`Radius`](../components/radius.md) ## Shown in * [GraphView](../views/graph_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `GraphNodes`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1GraphNodes.html) * 🐍 [Python API docs for `GraphNodes`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.GraphNodes) * 🦀 [Rust API docs for `GraphNodes`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GraphNodes.html) ## Examples ### Simple undirected graph ```python """Log a simple undirected graph.""" import rerun as rr rr.init("rerun_example_graph_undirected", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"] ), rr.GraphEdges( edges=[("a", "b"), ("b", "c"), ("c", "a")], # Optional: graphs are undirected by default. graph_type="undirected", ), ) ``` ### Simple directed graph ```python """Log a simple directed graph.""" import rerun as rr rr.init("rerun_example_graph_directed", spawn=True) rr.log( "simple", rr.GraphNodes( node_ids=["a", "b", "c"], positions=[(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)], labels=["A", "B", "C"] ), rr.GraphEdges(edges=[("a", "b"), ("b", "c"), ("c", "a")], graph_type="directed"), ) ``` # Image --- title: "Image" --- A monochrome or color image. See also [`archetypes.DepthImage`](https://rerun.io/docs/reference/types/archetypes/depth_image) and [`archetypes.SegmentationImage`](https://rerun.io/docs/reference/types/archetypes/segmentation_image). Rerun also supports compressed images (JPEG, PNG, …), using [`archetypes.EncodedImage`](https://rerun.io/docs/reference/types/archetypes/encoded_image). For images that refer to video frames see [`archetypes.VideoFrameReference`](https://rerun.io/docs/reference/types/archetypes/video_frame_reference). Compressing images or using video data instead can save a lot of bandwidth and memory. The raw image data is stored as a single buffer of bytes in a [`components.Blob`](https://rerun.io/docs/reference/types/components/blob). The meaning of these bytes is determined by the [`components.ImageFormat`](https://rerun.io/docs/reference/types/components/image_format) which specifies the resolution and the pixel format (e.g. RGB, RGBA, …). The order of dimensions in the underlying [`components.Blob`](https://rerun.io/docs/reference/types/components/blob) follows the typical row-major, interleaved-pixel image format. ## Components **Required**: [`ImageBuffer`](../components/image_buffer.md), [`ImageFormat`](../components/image_format.md) **Optional**: [`Opacity`](../components/opacity.md), [`DrawOrder`](../components/draw_order.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Image`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Image.html) * 🐍 [Python API docs for `Image`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Image) * 🦀 [Rust API docs for `Image`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Image.html) ## Examples ### image_simple ```python """Create and log an image.""" import numpy as np import rerun as rr # Create an image with numpy image = np.zeros((200, 300, 3), dtype=np.uint8) image[:, :, 0] = 255 image[50:150, 50:150] = (0, 255, 0) rr.init("rerun_example_image", spawn=True) rr.log("image", rr.Image(image)) ``` ### Logging images with various formats ```python """Create and log an image with various formats.""" import numpy as np import rerun as rr rr.init("rerun_example_image_formats", spawn=True) # Simple gradient image, logged in different formats. image = np.array([[[x, min(255, x + y), y] for x in range(0, 256)] for y in range(0, 256)], dtype=np.uint8) rr.log("image_rgb", rr.Image(image)) rr.log("image_green_only", rr.Image(image[:, :, 1], color_model="l")) # Luminance only rr.log("image_bgr", rr.Image(image[:, :, ::-1], color_model="bgr")) # BGR # New image with Separate Y/U/V planes with 4:2:2 chroma downsampling y = bytes([128 for y in range(0, 256) for x in range(0, 256)]) u = bytes([x * 2 for y in range(0, 256) for x in range(0, 128)]) # Half horizontal resolution for chroma. v = bytes([y for y in range(0, 256) for x in range(0, 128)]) rr.log("image_yuv422", rr.Image(bytes=y + u + v, width=256, height=256, pixel_format=rr.PixelFormat.Y_U_V16_FullRange)) ``` ### Image from file, PIL & OpenCV ```python """Log an image.""" import tempfile import cv2 import numpy as np import rerun as rr from PIL import Image as PILImage, ImageDraw # Save a transparent PNG to a temporary file. _, file_path = tempfile.mkstemp(suffix=".png") image = PILImage.new("RGBA", (300, 200), color=(0, 0, 0, 0)) draw = ImageDraw.Draw(image) draw.rectangle((0, 0, 300, 200), outline=(255, 0, 0), width=6) draw.rounded_rectangle((50, 50, 150, 150), fill=(0, 255, 0), radius=20) image.save(file_path) rr.init("rerun_example_image_advanced", spawn=True) # Log the image from the file. rr.log("from_file", rr.EncodedImage(path=file_path)) # Read with Pillow and NumPy, and log the image. image = np.array(PILImage.open(file_path)) rr.log("from_pillow_rgba", rr.Image(image)) # Drop the alpha channel from the image. image_rgb = image[..., :3] rr.log("from_pillow_rgb", rr.Image(image_rgb)) # Read with OpenCV. image = cv2.imread(file_path) # OpenCV uses BGR ordering, we need to make this known to Rerun. rr.log("from_opencv", rr.Image(image, color_model="BGR")) ``` ### Update an image over time ```python """ Update an image over time. See also the `image_column_updates` example, which achieves the same thing in a single operation. """ import numpy as np import rerun as rr rr.init("rerun_example_image_row_updates", spawn=True) for t in range(20): rr.set_time_sequence("time", t) image = np.zeros((200, 300, 3), dtype=np.uint8) image[:, :, 2] = 255 image[50:150, (t * 10) : (t * 10 + 100)] = (0, 255, 255) rr.log("image", rr.Image(image)) ``` ### Update an image over time, in a single operation ```python """ Update an image over time, in a single operation. This is semantically equivalent to the `image_row_updates` example, albeit much faster. """ import numpy as np import rerun as rr rr.init("rerun_example_image_column_updates", 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 = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8") rr.log("images", rr.Image.from_fields(format=format), static=True) # Send all images at once. rr.send_columns( "images", indexes=[rr.TimeSequenceColumn("step", times)], # Reshape the images so `Image` can tell that this is several blobs. # # Note that the `Image` consumes arrays of bytes, so we should ensure that we take a # uint8 view of it. This way, this also works when working with datatypes other than `U8`. columns=rr.Image.columns(buffer=images.view(np.uint8).reshape(len(times), -1)), ) ``` # InstancePoses3D --- title: "InstancePoses3D" --- One or more transforms between the current entity and its parent. Unlike [`archetypes.Transform3D`](https://rerun.io/docs/reference/types/archetypes/transform3d), it is *not* propagated in the transform hierarchy. If both [`archetypes.InstancePoses3D`](https://rerun.io/docs/reference/types/archetypes/instance_poses3d) and [`archetypes.Transform3D`](https://rerun.io/docs/reference/types/archetypes/transform3d) are present, first the tree propagating [`archetypes.Transform3D`](https://rerun.io/docs/reference/types/archetypes/transform3d) is applied, then [`archetypes.InstancePoses3D`](https://rerun.io/docs/reference/types/archetypes/instance_poses3d). From the point of view of the entity's coordinate system, all components are applied in the inverse order they are listed here. E.g. if both a translation and a max3x3 transform are present, the 3x3 matrix is applied first, followed by the translation. Currently, many visualizers support only a single instance transform per entity. Check archetype documentations for details - if not otherwise specified, only the first instance transform is applied. Some visualizers like the mesh visualizer used for [`archetypes.Mesh3D`](https://rerun.io/docs/reference/types/archetypes/mesh3d), will draw an object for every pose, a behavior also known as "instancing". ## Components **Optional**: [`PoseTranslation3D`](../components/pose_translation3d.md), [`PoseRotationAxisAngle`](../components/pose_rotation_axis_angle.md), [`PoseRotationQuat`](../components/pose_rotation_quat.md), [`PoseScale3D`](../components/pose_scale3d.md), [`PoseTransformMat3x3`](../components/pose_transform_mat3x3.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `InstancePoses3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1InstancePoses3D.html) * 🐍 [Python API docs for `InstancePoses3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.InstancePoses3D) * 🦀 [Rust API docs for `InstancePoses3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.InstancePoses3D.html) ## Examples ### Regular & instance transforms in tandem ```python """Log a simple 3D box with a regular & instance pose transform.""" import numpy as np import rerun as rr rr.init("rerun_example_instance_pose3d_combined", spawn=True) rr.set_time_sequence("frame", 0) # Log a box and points further down in the hierarchy. rr.log("world/box", rr.Boxes3D(half_sizes=[[1.0, 1.0, 1.0]])) rr.log("world/box/points", rr.Points3D(np.vstack([xyz.ravel() for xyz in np.mgrid[3 * [slice(-10, 10, 10j)]]]).T)) for i in range(0, 180): rr.set_time_sequence("frame", i) # Log a regular transform which affects both the box and the points. rr.log("world/box", rr.Transform3D(rotation_axis_angle=rr.RotationAxisAngle([0, 0, 1], angle=rr.Angle(deg=i * 2)))) # Log an instance pose which affects only the box. rr.log("world/box", rr.InstancePoses3D(translations=[0, 0, abs(i * 0.1 - 5.0) - 5.0])) ``` ### 3D mesh with instancing ```python """Log a simple 3D mesh with several instance pose transforms which instantiate the mesh several times and will not affect its children (known as mesh instancing).""" import rerun as rr rr.init("rerun_example_mesh3d_instancing", spawn=True) rr.set_time_sequence("frame", 0) rr.log( "shape", rr.Mesh3D( vertex_positions=[[1, 1, 1], [-1, -1, 1], [-1, 1, -1], [1, -1, -1]], triangle_indices=[[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]], vertex_colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0]], ), ) # This box will not be affected by its parent's instance poses! rr.log( "shape/box", rr.Boxes3D(half_sizes=[[5.0, 5.0, 5.0]]), ) for i in range(0, 100): rr.set_time_sequence("frame", i) rr.log( "shape", rr.InstancePoses3D( translations=[[2, 0, 0], [0, 2, 0], [0, -2, 0], [-2, 0, 0]], rotation_axis_angles=rr.RotationAxisAngle([0, 0, 1], rr.Angle(deg=i * 2)), ), ) ``` # LineStrips2D --- title: "LineStrips2D" --- 2D line strips with positions and optional colors, radii, labels, etc. ## Components **Required**: [`LineStrip2D`](../components/line_strip2d.md) **Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) **Optional**: [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`DrawOrder`](../components/draw_order.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `LineStrips2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1LineStrips2D.html) * 🐍 [Python API docs for `LineStrips2D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.LineStrips2D) * 🦀 [Rust API docs for `LineStrips2D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.LineStrips2D.html) ## Examples ### line_strips2d_simple ```python """Log a simple line strip.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d", spawn=True) rr.log( "strip", rr.LineStrips2D([[[0, 0], [2, 1], [4, -1], [6, 0]]]), ) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 7], y_range=[-3, 3]))) ``` ### line_strips2d_segments_simple ```python """Log a couple 2D line segments using 2D line strips.""" import numpy as np import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_line_segments2d", spawn=True) rr.log( "segments", rr.LineStrips2D(np.array([[[0, 0], [2, 1]], [[4, -1], [6, 0]]])), ) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 7], y_range=[-3, 3]))) ``` ### line_strips2d_batch ```python """Log a batch of 2D line strips.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d_batch", spawn=True) rr.log( "strips", rr.LineStrips2D( [ [[0, 0], [2, 1], [4, -1], [6, 0]], [[0, 3], [1, 4], [2, 2], [3, 4], [4, 2], [5, 4], [6, 3]], ], colors=[[255, 0, 0], [0, 255, 0]], radii=[0.025, 0.005], labels=["one strip here", "and one strip there"], ), ) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 7], y_range=[-3, 6]))) ``` ### Lines with scene & UI radius each ```python """Log lines with ui points & scene unit radii.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d_ui_radius", spawn=True) # A blue line with a scene unit radii of 0.01. points = [[0, 0], [0, 1], [1, 0], [1, 1]] rr.log( "scene_unit_line", rr.LineStrips2D( [points], # By default, radii are interpreted as world-space units. radii=0.01, colors=[0, 0, 255], ), ) # A red line with a ui point radii of 5. # UI points are independent of zooming in Views, but are sensitive to the application UI scaling. # For 100% ui scaling, UI points are equal to pixels. points = [[3, 0], [3, 1], [4, 0], [4, 1]] rr.log( "ui_points_line", rr.LineStrips2D( [points], # rr.Radius.ui_points produces radii that the viewer interprets as given in ui points. radii=rr.Radius.ui_points(5.0), colors=[255, 0, 0], ), ) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 5], y_range=[-1, 2]))) ``` # LineStrips3D --- title: "LineStrips3D" --- 3D line strips with positions and optional colors, radii, labels, etc. ## Components **Required**: [`LineStrip3D`](../components/line_strip3d.md) **Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) **Optional**: [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `LineStrips3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1LineStrips3D.html) * 🐍 [Python API docs for `LineStrips3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.LineStrips3D) * 🦀 [Rust API docs for `LineStrips3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.LineStrips3D.html) ## Examples ### Simple example ```python """Log a simple line strip.""" import rerun as rr rr.init("rerun_example_line_strip3d", spawn=True) points = [ [0, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1], [0, 1, 0], [0, 1, 1], ] rr.log("strip", rr.LineStrips3D([points])) ``` ### Many individual segments ```python #!/usr/bin/env python3 """Log a simple set of line segments.""" import numpy as np import rerun as rr rr.init("rerun_example_line_segments3d", spawn=True) rr.log( "segments", rr.LineStrips3D( np.array( [ [[0, 0, 0], [0, 0, 1]], [[1, 0, 0], [1, 0, 1]], [[1, 1, 0], [1, 1, 1]], [[0, 1, 0], [0, 1, 1]], ], ) ), ) ``` ### Many strips ```python """Log a batch of 3D line strips.""" import rerun as rr rr.init("rerun_example_line_strip3d_batch", spawn=True) rr.log( "strips", rr.LineStrips3D( [ [ [0, 0, 2], [1, 0, 2], [1, 1, 2], [0, 1, 2], ], [ [0, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1], [0, 1, 0], [0, 1, 1], ], ], colors=[[255, 0, 0], [0, 255, 0]], radii=[0.025, 0.005], labels=["one strip here", "and one strip there"], ), ) ``` ### Lines with scene & UI radius each ```python """Log lines with ui points & scene unit radii.""" import rerun as rr rr.init("rerun_example_line_strip3d_ui_radius", spawn=True) # A blue line with a scene unit radii of 0.01. points = [[0, 0, 0], [0, 0, 1], [1, 0, 0], [1, 0, 1]] rr.log( "scene_unit_line", rr.LineStrips3D( [points], # By default, radii are interpreted as world-space units. radii=0.01, colors=[0, 0, 255], ), ) # A red line with a ui point radii of 5. # UI points are independent of zooming in Views, but are sensitive to the application UI scaling. # For 100% ui scaling, UI points are equal to pixels. points = [[3, 0, 0], [3, 0, 1], [4, 0, 0], [4, 0, 1]] rr.log( "ui_points_line", rr.LineStrips3D( [points], # rr.Radius.ui_points produces radii that the viewer interprets as given in ui points. radii=rr.Radius.ui_points(5.0), colors=[255, 0, 0], ), ) ``` # Mesh3D --- title: "Mesh3D" --- A 3D triangle mesh as specified by its per-mesh and per-vertex properties. See also [`archetypes.Asset3D`](https://rerun.io/docs/reference/types/archetypes/asset3d). If there are multiple [`archetypes.InstancePoses3D`](https://rerun.io/docs/reference/types/archetypes/instance_poses3d) instances logged to the same entity as a mesh, an instance of the mesh will be drawn for each transform. ## Components **Required**: [`Position3D`](../components/position3d.md) **Recommended**: [`TriangleIndices`](../components/triangle_indices.md), [`Vector3D`](../components/vector3d.md) **Optional**: [`Color`](../components/color.md), [`Texcoord2D`](../components/texcoord2d.md), [`AlbedoFactor`](../components/albedo_factor.md), [`ImageBuffer`](../components/image_buffer.md), [`ImageFormat`](../components/image_format.md), [`ClassId`](../components/class_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Mesh3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Mesh3D.html) * 🐍 [Python API docs for `Mesh3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Mesh3D) * 🦀 [Rust API docs for `Mesh3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Mesh3D.html) ## Examples ### Simple indexed 3D mesh ```python """Log a simple colored triangle.""" import rerun as rr rr.init("rerun_example_mesh3d_indexed", spawn=True) rr.log( "triangle", rr.Mesh3D( vertex_positions=[[0.0, 1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 0.0]], vertex_normals=[0.0, 0.0, 1.0], vertex_colors=[[0, 0, 255], [0, 255, 0], [255, 0, 0]], triangle_indices=[2, 1, 0], ), ) ``` ### 3D mesh with instancing ```python """Log a simple 3D mesh with several instance pose transforms which instantiate the mesh several times and will not affect its children (known as mesh instancing).""" import rerun as rr rr.init("rerun_example_mesh3d_instancing", spawn=True) rr.set_time_sequence("frame", 0) rr.log( "shape", rr.Mesh3D( vertex_positions=[[1, 1, 1], [-1, -1, 1], [-1, 1, -1], [1, -1, -1]], triangle_indices=[[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]], vertex_colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0]], ), ) # This box will not be affected by its parent's instance poses! rr.log( "shape/box", rr.Boxes3D(half_sizes=[[5.0, 5.0, 5.0]]), ) for i in range(0, 100): rr.set_time_sequence("frame", i) rr.log( "shape", rr.InstancePoses3D( translations=[[2, 0, 0], [0, 2, 0], [0, -2, 0], [-2, 0, 0]], rotation_axis_angles=rr.RotationAxisAngle([0, 0, 1], rr.Angle(deg=i * 2)), ), ) ``` ### Update specific parts of a 3D mesh over time ```python """Log a simple colored triangle, then update its vertices' positions each frame.""" import numpy as np import rerun as rr rr.init("rerun_example_mesh3d_partial_updates", spawn=True) vertex_positions = np.array([[-1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], dtype=np.float32) # Log the initial state of our triangle rr.set_time_sequence("frame", 0) rr.log( "triangle", rr.Mesh3D( vertex_positions=vertex_positions, vertex_normals=[0.0, 0.0, 1.0], vertex_colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]], ), ) # Only update its vertices' positions each frame factors = np.abs(np.sin(np.arange(1, 300, dtype=np.float32) * 0.04)) for i, factor in enumerate(factors): rr.set_time_sequence("frame", i) rr.log("triangle", rr.Mesh3D.from_fields(vertex_positions=vertex_positions * factor)) ``` # Pinhole --- title: "Pinhole" --- Camera perspective projection (a.k.a. intrinsics). ## Components **Required**: [`PinholeProjection`](../components/pinhole_projection.md) **Recommended**: [`Resolution`](../components/resolution.md) **Optional**: [`ViewCoordinates`](../components/view_coordinates.md), [`ImagePlaneDistance`](../components/image_plane_distance.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial2DView](../views/spatial2d_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Pinhole`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Pinhole.html) * 🐍 [Python API docs for `Pinhole`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Pinhole) * 🦀 [Rust API docs for `Pinhole`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Pinhole.html) ## Examples ### Simple pinhole camera ```python """Log a pinhole and a random image.""" import numpy as np import rerun as rr rr.init("rerun_example_pinhole", spawn=True) rng = np.random.default_rng(12345) image = rng.uniform(0, 255, size=[3, 3, 3]) rr.log("world/image", rr.Pinhole(focal_length=3, width=3, height=3)) rr.log("world/image", rr.Image(image)) ``` ### Perspective pinhole camera ```python """Logs a point cloud and a perspective camera looking at it.""" import rerun as rr rr.init("rerun_example_pinhole_perspective", spawn=True) rr.log( "world/cam", rr.Pinhole(fov_y=0.7853982, aspect_ratio=1.7777778, camera_xyz=rr.ViewCoordinates.RUB, image_plane_distance=0.1), ) rr.log("world/points", rr.Points3D([(0.0, 0.0, -0.5), (0.1, 0.1, -0.5), (-0.1, -0.1, -0.5)], radii=0.025)) ``` # Points2D --- title: "Points2D" --- A 2D point cloud with positions and optional colors, radii, labels, etc. ## Components **Required**: [`Position2D`](../components/position2d.md) **Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) **Optional**: [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`DrawOrder`](../components/draw_order.md), [`ClassId`](../components/class_id.md), [`KeypointId`](../components/keypoint_id.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Points2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Points2D.html) * 🐍 [Python API docs for `Points2D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Points2D) * 🦀 [Rust API docs for `Points2D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Points2D.html) ## Examples ### Simple 2D points ```python """Log some very simple points.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_points2d", spawn=True) rr.log("points", rr.Points2D([[0, 0], [1, 1]])) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 2], y_range=[-1, 2]))) ``` ### Randomly distributed 2D points with varying color and radius ```python """Log some random points with color and radii.""" import rerun as rr import rerun.blueprint as rrb from numpy.random import default_rng rr.init("rerun_example_points2d_random", spawn=True) rng = default_rng(12345) positions = rng.uniform(-3, 3, size=[10, 2]) colors = rng.uniform(0, 255, size=[10, 4]) radii = rng.uniform(0, 1, size=[10]) rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-4, 4], y_range=[-4, 4]))) ``` ### Log points with radii given in UI points ```python """Log some points with ui points & scene unit radii.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_points2d_ui_radius", spawn=True) # Two blue points with scene unit radii of 0.1 and 0.3. rr.log( "scene_units", rr.Points2D( [[0, 0], [0, 1]], # By default, radii are interpreted as world-space units. radii=[0.1, 0.3], colors=[0, 0, 255], ), ) # Two red points with ui point radii of 40 and 60. # UI points are independent of zooming in Views, but are sensitive to the application UI scaling. # For 100% ui scaling, UI points are equal to pixels. rr.log( "ui_points", rr.Points2D( [[1, 0], [1, 1]], # rr.Radius.ui_points produces radii that the viewer interprets as given in ui points. radii=rr.Radius.ui_points([40.0, 60.0]), colors=[255, 0, 0], ), ) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 2], y_range=[-1, 2]))) ``` # Points3D --- title: "Points3D" --- A 3D point cloud with positions and optional colors, radii, labels, etc. ## Components **Required**: [`Position3D`](../components/position3d.md) **Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) **Optional**: [`Text`](../components/text.md), [`ShowLabels`](../components/show_labels.md), [`ClassId`](../components/class_id.md), [`KeypointId`](../components/keypoint_id.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Points3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Points3D.html) * 🐍 [Python API docs for `Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Points3D) * 🦀 [Rust API docs for `Points3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Points3D.html) ## Examples ### Simple 3D points ```python """Log some very simple points.""" import rerun as rr rr.init("rerun_example_points3d", spawn=True) rr.log("points", rr.Points3D([[0, 0, 0], [1, 1, 1]])) ``` ### Randomly distributed 3D points with varying color and radius ```python """Log some random points with color and radii.""" import rerun as rr from numpy.random import default_rng rr.init("rerun_example_points3d_random", spawn=True) rng = default_rng(12345) positions = rng.uniform(-5, 5, size=[10, 3]) colors = rng.uniform(0, 255, size=[10, 3]) radii = rng.uniform(0, 1, size=[10]) rr.log("random", rr.Points3D(positions, colors=colors, radii=radii)) ``` ### Log points with radii given in UI points ```python """Log some points with ui points & scene unit radii.""" import rerun as rr rr.init("rerun_example_points3d_ui_radius", spawn=True) # Two blue points with scene unit radii of 0.1 and 0.3. rr.log( "scene_units", rr.Points3D( [[0, 1, 0], [1, 1, 1]], # By default, radii are interpreted as world-space units. radii=[0.1, 0.3], colors=[0, 0, 255], ), ) # Two red points with ui point radii of 40 and 60. # UI points are independent of zooming in Views, but are sensitive to the application UI scaling. # For 100% ui scaling, UI points are equal to pixels. rr.log( "ui_points", rr.Points3D( [[0, 0, 0], [1, 0, 1]], # rr.Radius.ui_points produces radii that the viewer interprets as given in ui points. radii=rr.Radius.ui_points([40.0, 60.0]), colors=[255, 0, 0], ), ) ``` ### Update a point cloud over time ```python """ Update a point cloud over time. See also the `points3d_column_updates` example, which achieves the same thing in a single operation. """ import numpy as np import rerun as rr rr.init("rerun_example_points3d_row_updates", spawn=True) # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off 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]], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] for i in range(5): rr.set_time_seconds("time", 10 + i) rr.log("points", rr.Points3D(positions[i], colors=colors[i], radii=radii[i])) ``` ### Update a point cloud over time, in a single operation ```python """ Update a point cloud over time, in a single operation. This is semantically equivalent to the `points3d_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_points3d_column_updates", spawn=True) # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off 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], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] rr.send_columns( "points", indexes=[rr.TimeSecondsColumn("time", times)], columns=[ *rr.Points3D.columns(positions=positions).partition(lengths=[2, 4, 4, 3, 4]), *rr.Points3D.columns(colors=colors, radii=radii), ], ) ``` ### Update specific properties of a point cloud over time ```python """Update specific properties of a point cloud over time.""" import rerun as rr rr.init("rerun_example_points3d_partial_updates", spawn=True) positions = [[i, 0, 0] for i in range(0, 10)] rr.set_time_sequence("frame", 0) rr.log("points", rr.Points3D(positions)) for i in range(0, 10): colors = [[20, 200, 20] if n < i else [200, 20, 20] for n in range(0, 10)] radii = [0.6 if n < i else 0.2 for n in range(0, 10)] # Update only the colors and radii, leaving everything else as-is. rr.set_time_sequence("frame", i) rr.log("points", rr.Points3D.from_fields(radii=radii, colors=colors)) # Update the positions and radii, and clear everything else in the process. rr.set_time_sequence("frame", 20) rr.log("points", rr.Points3D.from_fields(clear_unset=True, positions=positions, radii=0.3)) ``` # Scalar --- title: "Scalar" --- A double-precision scalar, e.g. for use for time-series plots. The current timeline value will be used for the time/X-axis, hence scalars cannot be static. When used to produce a plot, this archetype is used to provide the data that is referenced by [`archetypes.SeriesLine`](https://rerun.io/docs/reference/types/archetypes/series_line) or [`archetypes.SeriesPoint`](https://rerun.io/docs/reference/types/archetypes/series_point). You can do this by logging both archetypes to the same path, or alternatively configuring the plot-specific archetypes through the blueprint. ## Components **Required**: [`Scalar`](../components/scalar.md) ## Shown in * [TimeSeriesView](../views/time_series_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Scalar`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Scalar.html) * 🐍 [Python API docs for `Scalar`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Scalar) * 🦀 [Rust API docs for `Scalar`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Scalar.html) ## Examples ### Simple line plot ```python """Log a scalar over time.""" import math import rerun as rr rr.init("rerun_example_scalar", spawn=True) # Log the data on a timeline called "step". for step in range(0, 64): rr.set_time_sequence("step", step) rr.log("scalar", rr.Scalar(math.sin(step / 10.0))) ``` ### Multiple time series plots ```python """Log a scalar over time.""" from math import cos, sin, tau import numpy as np import rerun as rr rr.init("rerun_example_scalar_multiple_plots", spawn=True) lcg_state = np.int64(0) # Set up plot styling: # They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) # Log scattered points under a different root so that they show in a different plot by default. rr.log("scatter/lcg", rr.SeriesPoint(), static=True) # Log the data on a timeline called "step". for t in range(0, int(tau * 2 * 100.0)): rr.set_time_sequence("step", t) rr.log("trig/sin", rr.Scalar(sin(float(t) / 100.0))) rr.log("trig/cos", rr.Scalar(cos(float(t) / 100.0))) lcg_state = (1140671485 * lcg_state + 128201163) % 16777216 # simple linear congruency generator rr.log("scatter/lcg", rr.Scalar(lcg_state)) ``` ### Update a scalar over time ```python """ Update a scalar over time. See also the `scalar_column_updates` example, which achieves the same thing in a single operation. """ from __future__ import annotations import math import rerun as rr rr.init("rerun_example_scalar_row_updates", spawn=True) for step in range(64): rr.set_time_sequence("step", step) rr.log("scalars", rr.Scalar(math.sin(step / 10.0))) ``` ### Update a scalar over time, in a single operation ```python """ Update a scalar over time, in a single operation. This is semantically equivalent to the `scalar_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_scalar_column_updates", spawn=True) times = np.arange(0, 64) scalars = np.sin(times / 10.0) rr.send_columns( "scalars", indexes=[rr.TimeSequenceColumn("step", times)], columns=rr.Scalar.columns(scalar=scalars), ) ``` # SegmentationImage --- title: "SegmentationImage" --- An image made up of integer [`components.ClassId`](https://rerun.io/docs/reference/types/components/class_id)s. Each pixel corresponds to a [`components.ClassId`](https://rerun.io/docs/reference/types/components/class_id) that will be mapped to a color based on annotation context. In the case of floating point images, the label will be looked up based on rounding to the nearest integer value. See also [`archetypes.AnnotationContext`](https://rerun.io/docs/reference/types/archetypes/annotation_context) to associate each class with a color and a label. ## Components **Required**: [`ImageBuffer`](../components/image_buffer.md), [`ImageFormat`](../components/image_format.md) **Optional**: [`Opacity`](../components/opacity.md), [`DrawOrder`](../components/draw_order.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `SegmentationImage`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1SegmentationImage.html) * 🐍 [Python API docs for `SegmentationImage`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.SegmentationImage) * 🦀 [Rust API docs for `SegmentationImage`](https://docs.rs/rerun/latest/rerun/archetypes/struct.SegmentationImage.html) ## Example ### Simple segmentation image ```python """Create and log a segmentation image.""" import numpy as np import rerun as rr # Create a segmentation image image = np.zeros((8, 12), dtype=np.uint8) image[0:4, 0:6] = 1 image[4:8, 6:12] = 2 rr.init("rerun_example_segmentation_image", spawn=True) # Assign a label and color to each class rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) rr.log("image", rr.SegmentationImage(image)) ``` # SeriesLine --- title: "SeriesLine" --- Define the style properties for a line series in a chart. This archetype only provides styling information and should be logged as static when possible. The underlying data needs to be logged to the same entity-path using [`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). ## Components **Optional**: [`Color`](../components/color.md), [`StrokeWidth`](../components/stroke_width.md), [`Name`](../components/name.md), [`AggregationPolicy`](../components/aggregation_policy.md) ## Shown in * [TimeSeriesView](../views/time_series_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `SeriesLine`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1SeriesLine.html) * 🐍 [Python API docs for `SeriesLine`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.SeriesLine) * 🦀 [Rust API docs for `SeriesLine`](https://docs.rs/rerun/latest/rerun/archetypes/struct.SeriesLine.html) ## Example ### Line series ```python """Log a scalar over time.""" from math import cos, sin, tau import rerun as rr rr.init("rerun_example_series_line_style", spawn=True) # Set up plot styling: # They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), static=True) rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), static=True) # Log the data on a timeline called "step". for t in range(0, int(tau * 2 * 100.0)): rr.set_time_sequence("step", t) rr.log("trig/sin", rr.Scalar(sin(float(t) / 100.0))) rr.log("trig/cos", rr.Scalar(cos(float(t) / 100.0))) ``` # SeriesPoint --- title: "SeriesPoint" --- Define the style properties for a point series in a chart. This archetype only provides styling information and should be logged as static when possible. The underlying data needs to be logged to the same entity-path using [`archetypes.Scalar`](https://rerun.io/docs/reference/types/archetypes/scalar). ## Components **Optional**: [`Color`](../components/color.md), [`MarkerShape`](../components/marker_shape.md), [`Name`](../components/name.md), [`MarkerSize`](../components/marker_size.md) ## Shown in * [TimeSeriesView](../views/time_series_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `SeriesPoint`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1SeriesPoint.html) * 🐍 [Python API docs for `SeriesPoint`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.SeriesPoint) * 🦀 [Rust API docs for `SeriesPoint`](https://docs.rs/rerun/latest/rerun/archetypes/struct.SeriesPoint.html) ## Example ### Point series ```python """Log a scalar over time.""" from math import cos, sin, tau import rerun as rr rr.init("rerun_example_series_point_style", spawn=True) # Set up plot styling: # They are logged as static as they don't change over time and apply to all timelines. # Log two point series under a shared root so that they show in the same plot by default. rr.log( "trig/sin", rr.SeriesPoint( color=[255, 0, 0], name="sin(0.01t)", marker="circle", marker_size=4, ), static=True, ) rr.log( "trig/cos", rr.SeriesPoint( color=[0, 255, 0], name="cos(0.01t)", marker="cross", marker_size=2, ), static=True, ) # Log the data on a timeline called "step". for t in range(0, int(tau * 2 * 10.0)): rr.set_time_sequence("step", t) rr.log("trig/sin", rr.Scalar(sin(float(t) / 10.0))) rr.log("trig/cos", rr.Scalar(cos(float(t) / 10.0))) ``` # Tensor --- title: "Tensor" --- An N-dimensional array of numbers. ## Components **Required**: [`TensorData`](../components/tensor_data.md) **Optional**: [`ValueRange`](../components/value_range.md) ## Shown in * [TensorView](../views/tensor_view.md) * [BarChartView](../views/bar_chart_view.md) (for 1D tensors) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Tensor`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Tensor.html) * 🐍 [Python API docs for `Tensor`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Tensor) * 🦀 [Rust API docs for `Tensor`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Tensor.html) ## Example ### Simple tensor ```python """Create and log a tensor.""" import numpy as np import rerun as rr tensor = np.random.randint(0, 256, (8, 6, 3, 5), dtype=np.uint8) # 4-dimensional tensor rr.init("rerun_example_tensor", spawn=True) # Log the tensor, assigning names to each dimension rr.log("tensor", rr.Tensor(tensor, dim_names=("width", "height", "channel", "batch"))) ``` # TextDocument --- title: "TextDocument" --- A text element intended to be displayed in its own text box. Supports raw text and markdown. ## Components **Required**: [`Text`](../components/text.md) **Optional**: [`MediaType`](../components/media_type.md) ## Shown in * [TextDocumentView](../views/text_document_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `TextDocument`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1TextDocument.html) * 🐍 [Python API docs for `TextDocument`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.TextDocument) * 🦀 [Rust API docs for `TextDocument`](https://docs.rs/rerun/latest/rerun/archetypes/struct.TextDocument.html) ## Example ### Markdown text document ```python """Log a `TextDocument`.""" import rerun as rr rr.init("rerun_example_text_document", spawn=True) rr.log("text_document", rr.TextDocument("Hello, TextDocument!")) rr.log( "markdown", rr.TextDocument( ''' # Hello Markdown! [Click here to see the raw text](recording://markdown:Text). Basic formatting: | **Feature** | **Alternative** | | ----------------- | --------------- | | Plain | | | *italics* | _italics_ | | **bold** | __bold__ | | ~~strikethrough~~ | | | `inline code` | | ---------------------------------- ## Support - [x] [Commonmark](https://commonmark.org/help/) support - [x] GitHub-style strikethrough, tables, and checkboxes - Basic syntax highlighting for: - [x] C and C++ - [x] Python - [x] Rust - [ ] Other languages ## Links You can link to [an entity](recording://markdown), a [specific instance of an entity](recording://markdown[#0]), or a [specific component](recording://markdown:Text). Of course you can also have [normal https links](https://github.com/rerun-io/rerun), e.g. . ## Image ![A random image](https://picsum.photos/640/480) '''.strip(), media_type=rr.MediaType.MARKDOWN, ), ) ``` # TextLog --- title: "TextLog" --- A log entry in a text log, comprised of a text body and its log level. ## Components **Required**: [`Text`](../components/text.md) **Recommended**: [`TextLogLevel`](../components/text_log_level.md) **Optional**: [`Color`](../components/color.md) ## Shown in * [TextLogView](../views/text_log_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `TextLog`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1TextLog.html) * 🐍 [Python API docs for `TextLog`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.TextLog) * 🦀 [Rust API docs for `TextLog`](https://docs.rs/rerun/latest/rerun/archetypes/struct.TextLog.html) ## Example ### text_log_integration ```python """Shows integration of Rerun's `TextLog` with the native logging interface.""" import logging import rerun as rr rr.init("rerun_example_text_log_integration", spawn=True) # Log a text entry directly rr.log("logs", rr.TextLog("this entry has loglevel TRACE", level=rr.TextLogLevel.TRACE)) # Or log via a logging handler logging.getLogger().addHandler(rr.LoggingHandler("logs/handler")) logging.getLogger().setLevel(-1) logging.info("This INFO log got added through the standard logging interface") ``` # Transform3D --- title: "Transform3D" --- A transform between two 3D spaces, i.e. a pose. From the point of view of the entity's coordinate system, all components are applied in the inverse order they are listed here. E.g. if both a translation and a max3x3 transform are present, the 3x3 matrix is applied first, followed by the translation. Whenever you log this archetype, it will write all components, even if you do not explicitly set them. This means that if you first log a transform with only a translation, and then log one with only a rotation, it will be resolved to a transform with only a rotation. For transforms that affect only a single entity and do not propagate along the entity tree refer to [`archetypes.InstancePoses3D`](https://rerun.io/docs/reference/types/archetypes/instance_poses3d). ## Components **Optional**: [`Translation3D`](../components/translation3d.md), [`RotationAxisAngle`](../components/rotation_axis_angle.md), [`RotationQuat`](../components/rotation_quat.md), [`Scale3D`](../components/scale3d.md), [`TransformMat3x3`](../components/transform_mat3x3.md), [`TransformRelation`](../components/transform_relation.md), [`AxisLength`](../components/axis_length.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [Spatial2DView](../views/spatial2d_view.md) (if logged above active projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `Transform3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1Transform3D.html) * 🐍 [Python API docs for `Transform3D`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.Transform3D) * 🦀 [Rust API docs for `Transform3D`](https://docs.rs/rerun/latest/rerun/archetypes/struct.Transform3D.html) ## Examples ### Variety of 3D transforms ```python """Log different transforms between three arrows.""" from math import pi import rerun as rr from rerun.datatypes import Angle, RotationAxisAngle rr.init("rerun_example_transform3d", spawn=True) arrow = rr.Arrows3D(origins=[0, 0, 0], vectors=[0, 1, 0]) rr.log("base", arrow) rr.log("base/translated", rr.Transform3D(translation=[1, 0, 0])) rr.log("base/translated", arrow) rr.log( "base/rotated_scaled", rr.Transform3D( rotation=RotationAxisAngle(axis=[0, 0, 1], angle=Angle(rad=pi / 4)), scale=2, ), ) rr.log("base/rotated_scaled", arrow) ``` ### Transform hierarchy ```python """Logs a transforms transform hierarchy.""" import numpy as np import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_transform3d_hierarchy", spawn=True) # One space with the sun in the center, and another one with the planet. rr.send_blueprint( rrb.Horizontal(rrb.Spatial3DView(origin="sun"), rrb.Spatial3DView(origin="sun/planet", contents="sun/**")) ) rr.set_time_seconds("sim_time", 0) # Planetary motion is typically in the XY plane. rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Setup points, all are in the center of their own space: # TODO(#1361): Should use spheres instead of points. rr.log("sun", rr.Points3D([0.0, 0.0, 0.0], radii=1.0, colors=[255, 200, 10])) rr.log("sun/planet", rr.Points3D([0.0, 0.0, 0.0], radii=0.4, colors=[40, 80, 200])) rr.log("sun/planet/moon", rr.Points3D([0.0, 0.0, 0.0], radii=0.15, colors=[180, 180, 180])) # Draw fixed paths where the planet & moon move. d_planet = 6.0 d_moon = 3.0 angles = np.arange(0.0, 1.01, 0.01) * np.pi * 2 circle = np.array([np.sin(angles), np.cos(angles), angles * 0.0]).transpose() rr.log("sun/planet_path", rr.LineStrips3D(circle * d_planet)) rr.log("sun/planet/moon_path", rr.LineStrips3D(circle * d_moon)) # Movement via transforms. for i in range(0, 6 * 120): time = i / 120.0 rr.set_time_seconds("sim_time", time) r_moon = time * 5.0 r_planet = time * 2.0 rr.log( "sun/planet", rr.Transform3D( translation=[np.sin(r_planet) * d_planet, np.cos(r_planet) * d_planet, 0.0], rotation=rr.RotationAxisAngle(axis=(1, 0, 0), degrees=20), ), ) rr.log( "sun/planet/moon", rr.Transform3D( translation=[np.cos(r_moon) * d_moon, np.sin(r_moon) * d_moon, 0.0], from_parent=True, ), ) ``` ### Update a transform over time ```python """ Update a transform over time. See also the `transform3d_column_updates` example, which achieves the same thing in a single operation. """ import math import rerun as rr def truncated_radians(deg: float) -> float: return float(int(math.radians(deg) * 1000.0)) / 1000.0 rr.init("rerun_example_transform3d_row_updates", spawn=True) rr.set_time_sequence("tick", 0) rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), rr.Transform3D(clear=False, axis_length=10), ) for t in range(100): rr.set_time_sequence("tick", t + 1) rr.log( "box", rr.Transform3D( clear=False, translation=[0, 0, t / 10.0], rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=truncated_radians(t * 4)), ), ) ``` ### Update a transform over time, in a single operation ```python """ Update a transform over time, in a single operation. This is semantically equivalent to the `transform3d_row_updates` example, albeit much faster. """ import math import rerun as rr def truncated_radians(deg: float) -> float: return float(int(math.radians(deg) * 1000.0)) / 1000.0 rr.init("rerun_example_transform3d_column_updates", spawn=True) rr.set_time_sequence("tick", 0) rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), rr.Transform3D(clear=False, axis_length=10), ) rr.send_columns( "box", indexes=[rr.TimeSequenceColumn("tick", range(1, 101))], columns=rr.Transform3D.columns( translation=[[0, 0, t / 10.0] for t in range(100)], rotation_axis_angle=[ rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=truncated_radians(t * 4)) for t in range(100) ], ), ) ``` ### Update specific properties of a transform over time ```python """Update specific properties of a transform over time.""" import math import rerun as rr def truncated_radians(deg: float) -> float: return float(int(math.radians(deg) * 1000.0)) / 1000.0 rr.init("rerun_example_transform3d_partial_updates", spawn=True) # Set up a 3D box. rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), rr.Transform3D(clear=False, axis_length=10), ) # Update only the rotation of the box. for deg in range(46): rad = truncated_radians(deg * 4) rr.log( "box", rr.Transform3D.from_fields( rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), ) # Update only the position of the box. for t in range(51): rr.log( "box", rr.Transform3D.from_fields(translation=[0, 0, t / 10.0]), ) # Update only the rotation of the box. for deg in range(46): rad = truncated_radians((deg + 45) * 4) rr.log( "box", rr.Transform3D.from_fields( rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), ) # Clear all of the box's attributes, and reset its axis length. rr.log( "box", rr.Transform3D.from_fields(clear_unset=True, axis_length=15), ) ``` # VideoFrameReference --- title: "VideoFrameReference" --- References a single video frame. Used to display individual video frames from a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video). To show an entire video, a video frame reference for each frame of the video should be logged. See for details of what is and isn't supported. ## Components **Required**: [`VideoTimestamp`](../components/video_timestamp.md) **Optional**: [`EntityPath`](../components/entity_path.md) ## Shown in * [Spatial2DView](../views/spatial2d_view.md) * [Spatial3DView](../views/spatial3d_view.md) (if logged under a projection) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `VideoFrameReference`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1VideoFrameReference.html) * 🐍 [Python API docs for `VideoFrameReference`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.VideoFrameReference) * 🦀 [Rust API docs for `VideoFrameReference`](https://docs.rs/rerun/latest/rerun/archetypes/struct.VideoFrameReference.html) ## Examples ### Video with automatically determined frames ```python """Log a video asset using automatically determined frame references.""" import sys import rerun as rr if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} ") sys.exit(1) rr.init("rerun_example_asset_video_auto_frames", spawn=True) # Log video asset which is referred to by frame references. video_asset = rr.AssetVideo(path=sys.argv[1]) rr.log("video", video_asset, static=True) # Send automatically determined video frame timestamps. frame_timestamps_ns = video_asset.read_frame_timestamps_ns() rr.send_columns( "video", # Note timeline values don't have to be the same as the video timestamps. indexes=[rr.TimeNanosColumn("video_time", frame_timestamps_ns)], columns=rr.VideoFrameReference.columns_nanoseconds(frame_timestamps_ns), ) ``` ### Demonstrates manual use of video frame references ```python """Manual use of individual video frame references.""" # TODO(#7298): ⚠️ Video is currently only supported in the Rerun web viewer. import sys import rerun as rr import rerun.blueprint as rrb if len(sys.argv) < 2: # TODO(#7354): Only mp4 is supported for now. print(f"Usage: {sys.argv[0]} ") sys.exit(1) rr.init("rerun_example_asset_video_manual_frames", spawn=True) # Log video asset which is referred to by frame references. rr.log("video_asset", rr.AssetVideo(path=sys.argv[1]), static=True) # Create two entities, showing the same video frozen at different times. rr.log( "frame_1s", rr.VideoFrameReference(seconds=1.0, video_reference="video_asset"), ) rr.log( "frame_2s", rr.VideoFrameReference(seconds=2.0, video_reference="video_asset"), ) # Send blueprint that shows two 2D views next to each other. rr.send_blueprint(rrb.Horizontal(rrb.Spatial2DView(origin="frame_1s"), rrb.Spatial2DView(origin="frame_2s"))) ``` # ViewCoordinates --- title: "ViewCoordinates" --- How we interpret the coordinate system of an entity/space. For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. Make sure that this archetype is logged at or above the origin entity path of your 3D views. ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). ## Components **Required**: [`ViewCoordinates`](../components/view_coordinates.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) * [DataframeView](../views/dataframe_view.md) ## API reference links * 🌊 [C++ API docs for `ViewCoordinates`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1ViewCoordinates.html) * 🐍 [Python API docs for `ViewCoordinates`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.ViewCoordinates) * 🦀 [Rust API docs for `ViewCoordinates`](https://docs.rs/rerun/latest/rerun/archetypes/struct.ViewCoordinates.html) ## Example ### View coordinates for adjusting the eye camera ```python """Change the view coordinates for the scene.""" import rerun as rr rr.init("rerun_example_view_coordinates", spawn=True) rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.log( "world/xyz", rr.Arrows3D( vectors=[[1, 0, 0], [0, 1, 0], [0, 0, 1]], colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]], ), ) ``` # Logging Controls --- title: Logging Controls order: 600 --- ## Controlling logging globally Rerun logging is enabled by default. The logging behavior can be overridden at runtime using the `RERUN` environment variable: ```sh export RERUN=off python my_rerun_enabled_script.py # or cargo run my_rerun_package # No log messages will be transmitted. ``` The `RERUN` environment variable is read once during SDK initialization. The accepted values for `RERUN` are `1/on/true`, and `0/off/false`. ℹ️ Note: When Rerun is disabled, logging statements are bypassed and essentially become no-ops. ## Creating a default-off setup in code The "default-on" behavior can also be changed to a "default-off" behavior: ```python import rerun as rr rr.init("rerun_example_app", default_enabled=False) ``` ## Dynamically turn logging on/off In order to dynamically turn off logging at runtime, you can swap out the active recording with a disabled recording. When you want to turn logging back on, you simply continue to use the previous recording again. ### Rust In Rust you always pass the recording explicitly, making this fully transparent. In order to create a no-op recording call `RecordingStream::disabled()`. ```rust let noop_rec = RecordingStream::disabled(); ``` ### Python The Python API uses the global recording stream by default. To swap it out with a no-op recording call `set_global_data_recording` with `None`. ```python # Disabling logging prev_rec = rr.set_global_data_recording(None) # … # Re-enabling logging rr.set_global_data_recording(prev_rec) ``` # Micro Batching --- title: Micro Batching order: 700 --- The Rerun SDK automatically handles micro-batching in a background thread in order to find a sweet spot between latency and throughput, reducing metadata overhead and thus improving both bandwidth and CPU usage. The flushing is triggered by both time and space thresholds, whichever happens to trigger first. This is very similar to, and has many parallels with, the [compaction mechanism running on the datastore side](../store-compaction.md). You can configure these thresholds using the following environment variables: #### RERUN_FLUSH_TICK_SECS Sets the duration of the periodic tick that triggers the time threshold, in seconds. Defaults to `RERUN_FLUSH_TICK_SECS=0.008` (8ms). #### RERUN_FLUSH_NUM_BYTES Sets the size limit that triggers the space threshold, in bytes. Defaults to `RERUN_FLUSH_NUM_BYTES=1048576` (1MiB). #### RERUN_FLUSH_NUM_ROWS Sets the number of rows that drives the space threshold. Defaults to `RERUN_FLUSH_NUM_BYTES=18446744073709551615` (`u64::MAX`). # Operating Modes --- title: Operating Modes order: 800 --- There are many different ways of sending data to the Rerun Viewer depending on what you're trying to achieve and whether the Viewer is running in the same process as your code, in another process, or even as a separate web application. In the [official examples](/examples), these different modes of operation are exposed via a standardized set of flags that we'll cover below. We will also demonstrate how you can achieve the same behavior in your own code. Before reading this document, you might want to familiarize yourself with the [Rerun application model](../../concepts/app-model.md). ## Operating modes The Rerun SDK provides 4 modes of operation: `spawn`, `connect`, `serve` & `save`. All four of them are optional: when none of these modes are active, the client will simply buffer the logged data in memory, waiting for one of these modes to be enabled so that it can flush it. ### Spawn This is the default behavior you get when running all of our C++/Python/Rust examples, and is generally the most convenient when you're experimenting. #### C++ `RecordingStream::spawn` spawns a new Rerun Viewer process using an executable available in your PATH, then streams all the data to it via TCP. If an external Viewer was already running, `spawn` will connect to that one instead of spawning a new one. #### Python Call [`rr.spawn`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.spawn) once at the start of your program to start a Rerun Viewer in an external process and stream all the data to it via TCP. If an external Viewer was already running, `spawn` will connect to that one instead of spawning a new one. #### Rust [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) spawns a new Rerun Viewer process using an executable available in your PATH, then streams all the data to it via TCP. If an external Viewer was already running, `spawn` will connect to that one instead of spawning a new one. ### Connect Connects to a remote Rerun Viewer and streams all the data via TCP. You will need to start a stand-alone Viewer first by typing `rerun` in your terminal. #### C++ `RecordingStream::connect` #### Python [`rr.connect`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.connect) #### Rust [`RecordingStream::connect`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.connect) ### Serve This starts the web version of the Rerun Viewer in your browser, and streams data to it in real-time using WebSockets. #### C++ Not available yet. #### Python Use [`rr.serve`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.serve). #### Rust [`RecordingStream::serve`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.serve) ### Save Streams all logging data into an `.rrd` file on disk, which can then be loaded into a stand-alone viewer. To view the saved file, use `rerun path/to/file.rrd`. ⚠️ [RRD files are not yet stable across different versions!](https://github.com/rerun-io/rerun/issues/6410) ⚠️ #### C++ Use `RecordingStream::save`. #### Python Use [`rr.save`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.save). #### Rust Use [`RecordingStream::save`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.save). ### Standard Input/Output Streams all logging data to standard output, which can then be loaded by the Rerun Viewer by streaming it from standard input. #### C++ Use [`RecordingStream::stdout`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html). Check out our [dedicated example](https://github.com/rerun-io/rerun/tree/latest/examples/cpp/stdio/main.cpp). #### Python Use [`rr.stdout`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.stdout). Check out our [dedicated example](https://github.com/rerun-io/rerun/tree/latest/examples/python/stdio/stdio.py). #### Rust Use [`RecordingStream::stdout`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.stdout). Check out our [dedicated example](https://github.com/rerun-io/rerun/tree/latest/examples/rust/stdio/src/main.rs). ## Adding the standard flags to your programs We provide helpers for both Python & Rust to effortlessly add and properly handle all of these flags in your programs. - For Python, checkout the [`script_helpers`](https://ref.rerun.io/docs/python/stable/common/script_helpers/) module. - For Rust, checkout our [`clap`]() [integration](https://docs.rs/rerun/latest/rerun/clap/index.html). Have a look at the [official examples](/examples) to see these helpers in action. # 🌊 C++ example --- title: 🌊 C++ example order: 100 redirect: https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader --- # Overview --- title: Overview order: 50 --- Internally, the [`DataLoader`](https://docs.rs/re_data_loader/latest/re_data_loader/trait.DataLoader.html) trait takes care of loading files into the Viewer and/or SDK. There are 3 broad kinds of `DataLoader`s: _builtin_, _external_ and _custom_. _External_ and _custom_ are the two ways of extending the file loading system that we'll describe below. When a user attempts to open a file in the Viewer/SDK, **all** known `DataLoader`s are notified of the path to be opened, unconditionally. This gives `DataLoader`s maximum flexibility to decide what files they are interested in, as opposed to e.g. only being able to look at a file's extension. Once notified, a `DataLoader` can return a [`DataLoaderError::Incompatible`](https://docs.rs/re_data_loader/latest/re_data_loader/enum.DataLoaderError.html#variant.Incompatible) error to indicate that it doesn't support a given file type. If, and only if, all loaders known to the Viewer/SDK return an `Incompatible` error code, then an error message is shown to the user indicating that this file type is not (_yet_) supported. In these instances of unsupported files, we expose two ways of implementing and registering your `DataLoader`s, explained below. ### External data-loaders The easiest way to create your own `DataLoader` is by implementing what we call an "external loader": a stand alone executable written in any language that the Rerun SDK ships for. Any executable on your `$PATH` with a name that starts with `rerun-loader-` will be treated as a `DataLoader`. This executable takes a file path as a command line argument and outputs Rerun logs on `stdout`. It will be called by the Rerun Viewer/SDK when the user opens a file, and be passed the path to that file. From there, it can log data as usual, using the [`stdout` logging sink](../../reference/sdk/operating-modes.md#standard-inputoutput). The Rerun Viewer/SDK will then automatically load the data streamed to the external loader's standard output. Like any other `DataLoader`, an external loader will be notified of all file openings, unconditionally. To indicate that it does not support a given file, the loader has to exit with a [dedicated status code](https://docs.rs/rerun/latest/rerun/constant.EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE.html). When the Viewer and/or SDK executes an external loader, it will pass to it a set of recommended settings in the form of CLI parameters (in addition to the file path to be loaded, which is passed as the one and only positional argument): * `--application-id ` The recommended `ApplicationId` to log the data to. * `--opened-application-id ` (optional) The `ApplicationId` that is currently opened in the viewer, if any. * `--recording-id ` The recommended `RecordingId` to log the data to. Log data to this recording if you want it to appear in a new recording shared by all data-loaders for the current loading session. * `--opened-recording-id ` (optional) The `RecordingId` that is currently opened in the viewer, if any. * `--entity-path-prefix ` (optional) Recommended prefix to prepend to all entity paths. * `--static` (optional) The data is expected to be logged as static. * `--time = = …` (optional) The data is expected to be logged at these specific temporal timestamps. The timestamps are expected to be in nanoseconds: use `rr.set_time_nanos` (Python) / `RecordingStream::set_time_nanos` (C++, Rust) appropriately. * `--sequence = = …` (optional) The data is expected to be logged at these specific sequence timestamps. Check out our examples for [C++](https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader), [Python](https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader) and [Rust](https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader) that cover every steps in details. ### Custom Rust data-loaders Another Rust-specific approach is to implement the `DataLoader` trait yourself and register it in the Rerun Viewer/SDK. To do so, you'll need to import `rerun` as a library, register your `DataLoader` and then start the Viewer/SDK from code. Check out our [example](https://github.com/rerun-io/rerun/tree/main/examples/rust/custom_data_loader) that cover all these steps in details. # 🐍 Python example --- title: 🐍 Python example order: 100 redirect: https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader --- # 🦀 Rust example --- title: 🦀 Rust example order: 120 redirect: https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader --- # Configure the Viewer through code --- title: Configure the Viewer through code hidden: true redirect: howto/visualization/configure-viewer-through-code --- # Get data out of Rerun with code --- title: Get data out of Rerun with code hidden: true redirect: howto/get-data-out --- # Embed a Rerun Viewer --- title: Embed a Rerun Viewer hidden: true redirect: howto/integrations/embed-web --- # Extend Rerun --- title: Extend Rerun hidden: true --- There are currently two major ways of extending Rerun. You can use Rerun with [your own custom data](logging/custom-data.md), or [extend the Rerun Viewer](visualization/extend-ui.md) (currently Rust only). The goal is for Rerun to become easy to extend at every level. For example, with plugins for - data sources - data stores - data transforms - custom rendering - custom UI interactions If you're in need of a particular kind of extension mechanism that we don't yet support. Head over to [GitHub](https://github.com/rerun-io/rerun/issues) and either upvote an existing issue or open a new one. # Create a fixed-window plot --- title: Create a fixed-window plot hidden: true redirect: howto/visualization/fixed-window-plot --- # Query data out of Rerun --- title: Query data out of Rerun order: 100 --- Rerun comes with a Dataframe API, which enables getting data out of Rerun from code. This page provides an overview of the API, as well as recipes to load the data in popular packages such as [Pandas](https://pandas.pydata.org), [Polars](https://pola.rs), and [DuckDB](https://duckdb.org). ## The dataframe API ### Loading a recording A recording can be loaded from a RRD using the `load_recording()` function: ```python import rerun as rr recording = rr.dataframe.load_recording("/path/to/file.rrd") ``` Although RRD files generally contain a single recording, they may occasionally contain 2 or more. This can happen, for example, if the RRD includes a blueprint, which is stored as a recording that is separate from the data. For such RRD, the `load_archive()` function can be used: ```python import rerun as rr archive = rr.dataframe.load_archive("/pat/to/file.rrd") print(f"The archive contains {archive.num_recordings()} recordings.") for recording in archive.all_recordings(): ... ``` The overall content of the recording can be inspected using the `schema()` method: ```python schema = recording.schema() schema.index_columns() # list of all index columns (timelines) schema.component_columns() # list of all component columns ``` ### Creating a view The first step for getting data out of a recording is to create a view, which requires specifying an index column and what content to include. As of Rerun 0.19, views must have exactly one index column, which can be any of the recording timelines. Each row of the view will correspond to a unique value of the index column. If a row has a `null` in the returned index (time) column, it means that data was static. In the future, it will be possible to have other kinds of column as index, and more than a single index column. The `contents` define which columns are included in the view and can be flexibly specified as entity expression, optionally providing a corresponding list of components. These are all valid ways to specify view content: ```python # everything in the recording view = recording.view(index="frame_nr", contents="/**") # everything in the recording, except the /world/robot subtree view = recording.view(index="frame_nr", contents="/**\n- /world/robot/**") # all `Scalar` components in the recording view = recording.view(index="frame_nr", contents={"/**": ["Scalar"]}) # some components in an entity subtree and a specific component # of a specific entity view = recording.view(index="frame_nr", contents={ "/world/robot/**": ["Position3D", "Color"], "/world/scene": ["Text"], }) ``` ### Filtering rows in a view A view has several APIs to further filter the rows it will return. #### Filtering by time range Rows may be filtered to keep only a given range of values from its index column: ```python # only keep rows for frames 0 to 10 view = view.filter_range_sequence(0, 10) ``` This API exists for both temporal and sequence timeline, and for various units: - `view.filter_range_sequence(start_frame, end_frame)` (takes `int` arguments) - `view.filter_range_seconds(stat_second, end_second)` (takes `float` arguments) - `view.filter_range_nanos(start_nano, end_nano)` (takes `int` arguments) (all ranges are including both start and end values) #### Filtering by index value Rows may be filtered to keep only those whose index corresponds to a specific set of value: ```python view = view.filter_index_values([0, 5, 10]) ``` Note that a precise match is required. Since Rerun internally stores times as `int64`, this method is only available for integer arguments (nanos or sequence number). Floating point seconds would risk false mismatch due to numerical conversion. ##### Filtering by column not null Rows where a specific column has null values may be filtered out using the `filter_is_not_null()` method. When using this method, only rows for which a logging event exist for the provided column are returned. ```python # only keep rows where a position is available for the robot view = view.filter_is_not_null("/world/robot:Position3D") ``` ### Specifying rows Instead of filtering rows based on the existing data, it is possible to specify exactly which rows must be returned by the view using the `using_index_values()` method: ```python # resample the first second of data at every millisecond view = view.using_index_values(range(0, 1_000_000, 1_000_0000_000)) ``` In this case, the view will return rows in multiples of 1e6 nanoseconds (i.e. for each millisecond) over a period of one second. A precise match on the index value is required for data to be produced on the row. For this reason, a floating point version of this method is not provided for this feature. Note that this feature is typically used in conjunction with `fill_latest_at()` (see next paragraph) to enable arbitrary resampling of the original data. ### Filling empty values with latest-at data By default, the rows returned by the view may be sparse and contain values only for the columns where a logging event actually occurred at the corresponding index value. The view can optionally replace these empty cells using a latest-at query. This means that, for each such empty cell, the view traces back to find the last logged value and uses it instead. This is enabled by calling the `fill_latest_at()` method: ```python view = view.fill_latest_at() ``` ### Reading the data Once the view is fully set up (possibly using the filtering features previously described), its content can be read using the `select()` method. This method optionally allows specifying which subset of columns should be produced: ```python # select all columns record_batches = view.select() # select only the specified columns record_batches = view.select( [ "frame_nr", "/world/robot:Position3D", ], ) ``` The `select()` method returns a [`pyarrow.RecordBatchReader`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatchReader.html), which is essentially an iterator over a stream of [`pyarrow.RecordBatch`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatch.html#pyarrow-recordbatch)es containing the actual data. See the [PyArrow documentation](https://arrow.apache.org/docs/python/index.html) for more information. For the rest of this page, we explore how these `RecordBatch`es can be ingested in some of the popular data science packages. ## Load data to a PyArrow `Table` The `RecordBatchReader` provides a [`read_all()`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatchReader.html#pyarrow.RecordBatchReader.read_all) method which directly produces a [`pyarrow.Table`](https://arrow.apache.org/docs/python/generated/pyarrow.Table.html#pyarrow.Table): ```python import rerun as rr recording = rr.dataframe.load_recording("/path/to/file.rrd") view = recording.view(index="frame_nr", contents="/**") table = view.select().read_all() ``` ## Load data to a Pandas dataframe The `RecordBatchReader` provides a [`read_pandas()`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatchReader.html#pyarrow.RecordBatchReader.read_pandas) method which returns a [Pandas dataframe](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html): ```python import rerun as rr recording = rr.dataframe.load_recording("/path/to/file.rrd") view = recording.view(index="frame_nr", contents="/**") df = view.select().read_pandas() ``` ## Load data to a Polars dataframe A [Polars dataframe](https://docs.pola.rs/api/python/stable/reference/dataframe/index.html) can be created from a PyArrow table: ```python import rerun as rr import polars as pl recording = rr.dataframe.load_recording("/path/to/file.rrd") view = recording.view(index="frame_nr", contents="/**") df = pl.from_arrow(view.select().read_all()) ``` ## Load data to a DuckDB relation A [DuckDB](https://duckdb.org) relation can be created directly using the `pyarrow.RecordBatchReader` returned by `select()`: ```python import rerun as rr import duckdb recording = rr.dataframe.load_recording("/path/to/file.rrd") view = recording.view(index="frame_nr", contents="/**") rel = duckdb.arrow(view.select()) ``` # Integrations --- title: Integrations order: 900 redirect: howto/integrations/embed-notebooks --- # Limit memory usage --- title: Limit memory usage hidden: true redirect: howto/visualization/limit-ram --- # Send data to Rerun --- title: Send data to Rerun order: 0 redirect: howto/logging/send-columns --- # Embed Rerun in notebooks --- title: Embed Rerun in notebooks hidden: true redirect: howto/integrations/embed-notebooks --- # Use Rerun with ROS 2 --- title: Use Rerun with ROS 2 hidden: true redirect: howto/integrations/ros2-nav-turtlebot --- # Efficiently log time series data using `send_columns` --- title: Efficiently log time series data using `send_columns` hidden: true redirect: howto/logging/send-columns --- # Share recordings across multiple processes --- title: Share recordings across multiple processes hidden: true redirect: howto/logging/shared-recordings --- # Clear out already logged data --- title: Clear out already logged data hidden: true redirect: howto/logging/clears --- # Integrate Rerun with native loggers --- title: Integrate Rerun with native loggers hidden: true redirect: howto/integrations/integrate-host-loggers --- # Visualization --- title: Visualization order: 200 redirect: howto/visualization/limit-ram --- # Configure the Viewer through code (Blueprints) --- title: Configure the Viewer through code (Blueprints) order: 100 --- As of Rerun 0.15, the state of the [blueprint](../../reference/viewer/blueprint.md) can be directly manipulated using the Rerun SDK. In the initial 0.15 release, the APIs are still somewhat limited and only available in the Python SDK. Future releases will add support for the full scope of blueprint. See issues: [#5519](https://github.com/rerun-io/rerun/issues/5519), [#5520](https://github.com/rerun-io/rerun/issues/5520), [#5521](https://github.com/rerun-io/rerun/issues/5521). ## Blueprint API overview All blueprint APIs are in the [`rerun.blueprint`](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) namespace. In our Python examples, we typically import this using the `rrb` alias: ```python import rerun.blueprint as rrb ``` The Python blueprint API is declarative and object-centric. There are 3 main types of blueprint objects you will encounter: - `Blueprint`: The root object that represents the entire Viewer layout. - `Container`: A layout object that contains other containers or views. - `View`: A view object that represents a single view of the data. Both containers and views should be used via typed subclasses instead.: - `Container` has subclasses: `Horizontal`, `Vertical`, `Grid`, and `Tabs`. - `View` has subclasses: `BarChartView`, `Spatial2DView`, `Spatial3DView`, `TensorView`, `TextDocumentView`, `TextLogView`, and `TimeSeriesView`. These paths can be combined hierarchically to create a complex Viewer layout. For example: ```python my_blueprint = rrb.Blueprint( rrb.Horizontal( rrb.BarChartView(), rrb.Vertical( rrb.Spatial2DView(), rrb.Spatial3DView(), ), ), ) ``` ## Sending the blueprint to the Viewer To provide a blueprint, simply pass it to either `init` or `connect` using the `default_blueprint` parameter. Using `init` with `spawn=True`: ```python my_blueprint = rrb.Blueprint(...) rr.init("rerun_example_my_blueprint", spawn=True, default_blueprint=my_blueprint) ``` Or if you use `connect` separate from `init`: ```python my_blueprint = rrb.Blueprint(...) rr.init("rerun_example_my_blueprint") ... rr.connect(default_blueprint=my_blueprint) ``` ## Activating the default blueprint Just like the Viewer can store many different recordings internally, it can also store many different blueprints. For each `application_id` in the viewer, are two particularly important blueprints: the "default blueprint" and the "active blueprint". When a recording is selected, the active blueprint for the corresponding `application_id` will completely determine what is displayed by the viewer. When you send a blueprint to the viewer, it will not necessarily be activated immediately. The standard behavior is to only update the "default blueprint" in the viewer. This minimizes the chance that you accidentally overwrite blueprint edits you may have made locally. If you want to start using the new blueprint, after sending it, you will need to current default. ## Always activating the blueprint If you want to always activate the blueprint as soon as it is received, you can instead use the `send_blueprint` API. This API has two flags `make_active` and `make_default`, both of which default to `True`. If `make_active` is set, the blueprint will be activated immediately. Exercise care in using this API, as it can be surprising for users to have their blueprint changed without warning. ```python my_blueprint = rrb.Blueprint(...) rr.init("rerun_example_my_blueprint", spawn=True) rr.send_blueprint(my_blueprint, make_active=True) ``` ## Customizing views Any of the views (`BarChartView`, `Spatial2DView`, `Spatial3DView`, `TensorView`, `TextDocumentView`, `TextLogView`, or `TimeSeriesView`) can be instantiated with no arguments. By default these views try to include all compatible entities. For example, the following blueprint creates a single 3D view that includes all the 3D content you have logged to the entity tree: ```python rrb.Blueprint( rrb.Spatial3DView() ) ``` Beyond instantiating the views, there are 3 parameters you may want to specify: `name`, `origin`, and `contents`. `name` is simply the name of the view used as a label in the viewer. However, both `origin` and `contents` play an important role in determining what data is included in the view. ### `origin` The `origin` of a view is a generalized "frame of reference" for the view. We think of showing all data in the view as relative to the `origin`. By default, only data that is under the `origin` will be included in the view. As such this is one of the most convenient ways of restricting a view to a particular subtree. Because the data in the view is relative to the `origin`, the `origin` will be the first entity displayed in the blueprint tree, with all entities under the origin shown using relative paths. For Spatial views such as `Spatial2DView` and `Spatial3DView`, the `origin` plays an additional role with respect to data transforms. All data in the view will be transformed to the `origin` space before being displayed. See [Spaces and Transforms](../../concepts/spaces-and-transforms.md) for more information. For example: ```python rrb.Blueprint( rrb.Horizontal( rrb.Spatial3DView(origin="/world"), rrb.Spatial2DView(origin="/world/robot/camera"), ) ) ``` ### `contents` If you need to further modify the contents of a view, you can use the `contents` parameter. This parameter is a list of [entity query expressions](../../reference/) that are either included or excluded from the view. Each entity expressions starts with "+" for inclusion or "-" for an exclusion. The expressions can either be specific entity paths, or may end in a wildcard `/**` to include all entities under a specific subtree. When combining multiple expressions, the "most specific" rule wins. Additionally, these expressions can reference `$origin` to refer to the origin of the view. For example: ```python rrb.Blueprint( rrb.Horizontal( rrb.Spatial3DView( origin="/world", contents=[ "+ $origin/robot/**", ], ), rrb.Spatial2DView( origin="/world/robot/camera", contents=[ "+ $origin/**", "+ /world/robot/actuator/**", ], ), ) ) ``` ## Implicit conversion For convenience all of the blueprint APIs take a `BlueprintLike` rather than requiring a `Blueprint` object. Both `View`s and `Containers` are considered `BlueprintLike`. Similarly, the `Blueprint` object can take a `View` or `Container` as an argument. All of the following are equivalent: ```python rr.send_blueprint(rrb.Spatial3DView()) ``` ```python rr.send_blueprint( rrb.Grid( Spatial3DView(), ) ) ``` ```python rr.send_blueprint( rrb.Blueprint( Spatial3DView(), ), ) ``` ```python rr.send_blueprint( rrb.Blueprint( rrb.Grid( Spatial3DView(), ) ), ) ``` ## Customizing the top-level blueprint The top-level `Blueprint` object can also be customized. ### Controlling the panel state The `Blueprint` controls the default panel-state of the 3 panels: the `BlueprintPanel`, the `SelectionPanel`, and the `TimePanel`. These can be controlled by passing them as additional arguments to the `Blueprint` constructor. ```python rrb.Blueprint( rrb.TimePanel(state="collapsed") ) ``` As an convenience, you can also use the blueprint argument: `collapse_panels=True` as a short-hand for: ```python rrb.Blueprint( rrb.TimePanel(state="collapsed"), rrb.SelectionPanel(state="collapsed"), rrb.BlueprintPanel(state="collapsed"), ) ``` ### Controlling the auto behaviors The blueprint has two additional parameters that influence the behavior of the viewer: - `auto_views` controls whether the Viewer will automatically create views for entities that are not explicitly included in the blueprint. - `auto_layout` controls whether the Viewer should automatically layout the containers when introducing new views. If you pass in your own `View` or `Container` objects, these will both default to `False` so that the Blueprint you get is exactly what you specify. Otherwise they will default to `True` so that you will still get content (this matches the default behavior of the Viewer if no blueprint is provided). This means that: ```python rrb.Blueprint() ``` and ```python rrb.Blueprint( auto_views=True, auto_layout=True ) ``` are both equivalent to the viewer's default behavior. If you truly want to create an empty blueprint, you must set both values to `False`: ```python rrb.Blueprint( auto_views=False, auto_layout=False ), ``` # Implement custom visualizations (Rust only) --- title: Implement custom visualizations (Rust only) order: 200 description: How to extend the Rerun Viewer UI using Rust and egui --- ## Embedding custom UI in the Viewer ![The Rerun Viewer, extended with a custom panel to the right](https://github.com/rerun-io/rerun/assets/1148717/cbbad63e-9b18-4e54-bafe-b6ffd723f63e) In the above screenshot you see the example [`extend_viewer_ui`](https://github.com/rerun-io/rerun/tree/main/examples/rust/extend_viewer_ui), which contains the Rerun Viewer to the left and a custom panel to the right. In this example the panel contains a hierarchial text view of the loaded data. ### How to build it The Rerun Viewer is defined by the crate [`re_viewer`](https://github.com/rerun-io/rerun/tree/main/crates/viewer/re_viewer). It uses the popular Rust GUI library [`egui`](https://github.com/emilk/egui) (written by our CTO) and its framework [`eframe`](https://github.com/emilk/egui/tree/master/crates/eframe). To extend the UI you need to create your own `eframe` application and embed `re_viewer` inside of it. You can then use `egui` to add custom panels and windows. The best way to get started is by reading [the source code of the `extend_viewer_ui` example](https://github.com/rerun-io/rerun/tree/main/examples/rust/extend_viewer_ui). ## Custom views classes Above screenshot shows the [`custom_view`](https://github.com/rerun-io/rerun/tree/main/examples/rust/custom_view) example. This example demonstrates how to add a fully custom View class to Rerun on startup. Views that are added this way have access to the exact same interfaces as all other Views, meaning that any of the built-in Views serves can serve as an additional example on how to implement Views. **⚠️ Note that the interface for adding Views are very far from stable.** Expect code implementing custom Views to break with every release of Rerun. # Future work We plan to also support embedding your own GUI widgets inside existing views. # Visualize fixed-window plots --- title: Visualize fixed-window plots order: 200 --- As of Rerun 0.16, the [TimeSeriesView](../../reference/types/views/time_series_view.md) now supports direct manipulation of the visible time range. This allows you to create a plot that only shows a fixed window of data. ## VisibleTimeRange To specify the visible time range, you must pass one or more `VisibleTimeRange` objects to the `time_ranges` parameter of the `TimeSeriesView` blueprint type. If your app only uses a single timeline, you can directly pass a single `VisibleTimeRange` object instead of wrapping it in a list. The `VisibleTimeRange` object takes three parameters: - `timeline`: The timeline that the range will apply to. This must match the timeline used to log your data, or if you are only using the rerun-provided timestamps, you can use the strings `"log_time"`, or `"log_tick"`. - `start`: The start of the visible time range. - `end`: The end of the visible time range. The `start` and `end` parameters are set using a `TimeRangeBoundary`: - To specify an absolute time, you can use the `TimeRangeBoundary.absolute()` method. - To specify a cursor-relative time, you can use the `TimeRangeBoundary.cursor_relative()` method. - You can also specify `TimeRangeBoundary.infinite()` to indicate that the start or end of the time range should be unbounded. In order to account for the different types of timeline (temporal or sequence-based), both the `TimeRangeBoundary.absolute()` and `TimeRangeBoundary.cursor_relative()` methods can be specified using one of the keyword args: - `seconds`: Use this if you called `rr.set_time_seconds()` to update the timeline. - `nanos`: Use this if you called `rr.set_time_nanos()` to update the timeline. - `seq`: Use this if you called `rr.set_time_seq()` to update the timeline. ## Example syntax To create a trailing 5 second window plot, you can specify your `TimeSeriesView` like this: ```python rrb.TimeSeriesView( origin="plot_path", time_ranges=rrb.VisibleTimeRange( timeline="time", start=rrb.TimeRangeBoundary.cursor_relative(seconds=-5.0), end=rrb.TimeRangeBoundary.cursor_relative(), ) ) ``` ## Full example For a complete working example, you can run the following code: ```python #!/usr/bin/env python3 """A live plot of a random walk using a scrolling fixed window size.""" from __future__ import annotations import time import numpy as np import rerun as rr # pip install rerun-sdk import rerun.blueprint as rrb rr.init("rerun_example_fixed_window_plot", spawn=True) rr.send_blueprint( rrb.TimeSeriesView( origin="random_walk", time_ranges=rrb.VisibleTimeRange( "time", start=rrb.TimeRangeBoundary.cursor_relative(seconds=-5.0), end=rrb.TimeRangeBoundary.cursor_relative(), ), ) ) cur_time = time.time() value = 0.0 while True: cur_time += 0.01 sleep_for = cur_time - time.time() if sleep_for > 0: time.sleep(sleep_for) value += np.random.normal() rr.set_time_seconds("time", cur_time) rr.log("random_walk", rr.Scalar(value)) ``` This should create a plot that only shows the last 5 seconds of data. If you select the view, you should see that the time range is configured as expected. Alternatively, you can check out a more full-featured example with multiple plot windows [here](https://github.com/rerun-io/rerun/tree/latest/examples/python/live_scrolling_plot). ## Additional notes - Any time you log data, it has two timepoints associated with it: "log_time", and "log_tick". # Visualize geospatial data --- title: Visualize geospatial data order: 300 --- Rerun 0.20 introduced a new [map view](../../reference/types/views/map_view.md). This guide provides a short overview on how to use it to visualise geospatial data. ## Coordinate system The map view uses the [ESPG:3857](https://epsg.io/3857) [spherical mercator projection](https://en.wikipedia.org/wiki/Web_Mercator_projection) commonly used by web services such as [OpenStreetMap](https://www.openstreetmap.org/). This enables the use of commonly available web tiles for the background map. To be compatible with this view, geospatial data must be expressed using [ESPG:4326](https://epsg.io/4326) (aka WGS84) latitudes and longitudes. This corresponds to what is commonly referred to as "GPS coordinates." Rerun provides a set of archetypes prefixed with `Geo` designed to encapsulate such data. For example, [`GeoPoints`](../../reference/types/archetypes/geo_points.md) represent a single geospatial location (or a batch thereof). The location of the Eiffel Tower can be logged as follows: ```python rr.log("eiffel_tower", rr.GeoPoints(lat_lon=[48.858222, 2.2945])) ``` Both the latitude and longitude must be provided in degrees, with positive values corresponding to the North, resp. East directions. Note that Rerun always expects latitudes first and longitudes second. As there is [no accepted ordering standard](https://stackoverflow.com/questions/7309121/preferred-order-of-writing-latitude-longitude-tuples-in-gis-services), our APIs strive to make this ordering choice as explicit as possible. In this case, the `lat_lon` argument is keyword-only and must thus be explicitly named as a reminder of this order. ## Types of geometries Rerun currently supports two types of geometries: - [`GeoPoints`](../../reference/types/archetypes/geo_points.md): batch of individual points, with optional [radius](../../reference/types/components/radius.md) and [color](../../reference/types/components/color.md) - [`GeoLineStrings`](../../reference/types/archetypes/geo_line_strings.md): batch of line strings, with optional [radius](../../reference/types/components/radius.md) and [color](../../reference/types/components/color.md) *Note*: polygons are planned but are not supported yet (see [this issue](https://github.com/rerun-io/rerun/issues/8066)). As in other views, radii may be expressed either as UI points (negative values) or scene units (positive values). For the latter case, the map view uses meters are scene units. Apart from the use of latitude and longitude, `GeoPoints` and `GeoLineStrings` are otherwise similar to the [`Points2D`](../../reference/types/archetypes/points2d.md) and [`LineStrip2D`](../../reference/types/archetypes/line_strips2d.md) archetypes used in the [2D view](../../reference/types/views/spatial2d_view.md). The map view supports several types of background maps, including a few from [Mapbox](https://www.mapbox.com). A Mapbox access token is required to use them. It must be provided either using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable or configured in the settings screen ("Settings…" item in the Rerun menu). An access token may be freely obtained by creating a Mapbox account. ## Creating a map view from code Like other views, the map view can be configured using the [blueprint API](https://rerun.io/docs/howto/configure-viewer-through-code): ```python import rerun.blueprint as rrb blueprint = rrb.Blueprint( rrb.MapView( origin="/robot/position", name="map view", zoom=16.0, background=rrb.MapProvider.OpenStreetMap, ), ) ``` Check the [map view](../../reference/types/views/map_view.md) reference for details. # Limit the viewer's memory usage --- title: Limit the viewer's memory usage order: 0 description: How to limit the memory used by the Rerun Viewer so that it doesn't run out of RAM. --- ### --memory-limit The Rerun Viewer can not yet view more data than fits in RAM. The more data you log, the more RAM the Rerun Viewer will use. When it reaches a certain limit, the oldest data will be dropped. The default limit it to use up to 75% of the total system RAM. You can set the limit by with the `--memory-limit` command-lint argument, or the `memory_limit` argument of [`rr.spawn`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.spawn). ### --drop-at-latency If you have multiple processes generating log data to Rerun it could happen that the Viewer builds up a backlog of unprocessed log messages. This can induce latency and also use up memory, which `--memory-limit` cannot fix. To handle this case, you can use `rerun --drop-at-latency 500ms` to start ignoring _new_ data if the input buffer exceeds 500ms of data. This is a rarely used feature, and is mostly documented here for completeness. # Re-use blueprints across sessions and SDKs --- title: Re-use blueprints across sessions and SDKs order: 150 --- While the [blueprint APIs](configure-viewer-through-code.md) are currently only available through [🐍 Python](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/), blueprints can be saved to file and then re-logged as needed from any language our SDKs support. This enables you to re-use your saved blueprints both from any language we support as well as across different recordings that share a similar-enough structure, and makes it possible to share those blueprints with other users. For this you'll need to create a blueprint file and _import_ that file when needed. ## Creating a blueprint file Blueprint files (`.rbl`, by convention) can currently be created in two ways. One is to use the Rerun viewer to interactively build the blueprint you want (e.g. by moving panels around, changing view settings, etc), and then using `Menu > Save blueprint` (or the equivalent palette command) to save the blueprint as a file. The other is to use the [🐍 Python blueprint API](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) to programmatically build the blueprint, and then use the [`Blueprint.save`](https://ref.rerun.io/docs/python/0.19.0/common/blueprint_apis/#rerun.blueprint.Blueprint.save) method to save it as a file: ```python """Craft an example blueprint with the python API and save it to a file for future use.""" import sys import rerun.blueprint as rrb path_to_rbl = sys.argv[1] rrb.Blueprint( rrb.Horizontal( rrb.Grid( rrb.BarChartView(name="Bar Chart", origin="/bar_chart"), rrb.TimeSeriesView( name="Curves", origin="/curves", ), ), rrb.TextDocumentView(name="Description", origin="/description"), column_shares=[3, 1], ), rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ).save("your_blueprint_name", path_to_rbl) ``` ## (Re)Using a blueprint file There are two ways to re-use a blueprint file. The interactive way is to import the blueprint file directly into the Rerun viewer, using either `Menu > Import…` (or the equivalent palette command) or simply by drag-and-dropping the blueprint file into your recording. The programmatic way works by calling `log_file_from_path`: * [🐍 Python `log_file_from_path`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log_file_from_path) * [🦀 Rust `log_file_from_path`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path) * [🌊 C++ `log_file_from_path`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a20798d7ea74cce5c8174e5cacd0a2c47) This method allows you to log any file that contains data that Rerun understands (in this case, blueprint data) as part of your current recording: ```python """Demonstrates how to programmatically re-use a blueprint stored in a file.""" import sys import rerun as rr path_to_rbl = sys.argv[1] rr.init("rerun_example_reuse_blueprint_file", spawn=True) rr.log_file_from_path(path_to_rbl) # … log some data as usual … ``` ## Limitation: dynamic blueprints Sometimes, you might need your blueprint to dynamically react to the data you receive at runtime (e.g. you want to create one view per anomaly detected, and there is no way of knowing how many anomalies you're going to detect until the program actually runs). The only way to deal with these situations today is to use the [🐍 Python](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) API. # Clear out data using tombstones --- title: Clear out data using tombstones order: 300 description: How to log data that isn't valid for the whole recording --- In order to create coherent views of streaming data, the Rerun Viewer shows the latest values for each visible entity at the current timepoint. But some data may not be valid for the entire recording even if there are no updated values. How do you tell Rerun that something you've logged should no longer be shown? ## Log entities as cleared The most straight forward option is to explicitly log that an entity has been cleared. Rerun allows you to do this by logging a special `Clear` to any path. The timepoint at which the `Clear` is logged is the time point after which that entity will no longer be visible in your views. For example, if you have an object tracking application, your code might look something like this: ```python … for frame in sensors.read(): # Associate the following logs with `frame == frame.id` rr.set_time_sequence("frame", frame.id) # Do the actual tracking update tracker.update(frame) if tracker.is_lost: # Clear everything on or below `tracked/{tracker.id}` # and that happened on or before `frame == frame.id` rr.log(f"tracked/{tracker.id}", rr.Clear(recursive=True)) else: # Log data to the main entity and a child entity rr.log(f"tracked/{tracker.id}", rr.Rect2D(tracker.bounds)) rr.log(f"tracked/{tracker.id}/cm", rr.Point2D(tracker.cm)) ``` ## Clarify data meaning In some cases, the best approach may be to rethink how you log data to better express what is actually happening. Take the following example where update frequencies don't match: ```python … for frame in sensors.read(): # Associate the following logs with `frame = frame.id` rr.set_time_sequence("frame", frame.id) # Log every image that comes in rr.log("input/image", rr.Image(frame.image)) if frame.id % 10 == 0: # Run detection every 10 frames detection = detector.detect(frame) # Woops! These detections will not update at the # same frequency as the input data and thus look strange rr.log("input/detections", rr.Rect2D(detection.bounds)) ``` You could fix this example by logging `rr.Clear`, but in this case it makes more sense to change what you log to better express what is happening. Re-logging the image to another namespace on only the frames where the detection runs makes it explicit which frame was used as the input to the detector. This will create a second view in the Viewer that always allows you to see the frame that was used for the current detection input. Here is an example fix: ```python class Detector: … def detect(self, frame): downscaled = self.downscale(frame.image) # Log the downscaled image rr.log("detections/source", rr.Image(downscaled)) result = self.model(downscaled) detection = self.post_process(result) # Log the detections together with the downscaled image # Image and detections will update at the same frequency rr.log("downscaled/detections", rr.Rect2D(detection.bounds)) return detection … for frame in sensors.read(): # Associate the following logs with `frame = frame.id` rr.set_time_sequence("frame", frame.id) # Log every image that comes in rr.log("input/image", rr.Image(frame.image)) if frame.id % 10 == 0: # Run detection every 10 frames # Logging of detections now happens inside the detector detected = detector.detect(frame) ``` ## Log data with spans instead of timepoints In some cases you already know how long a piece of data will be valid at the time of logging. Rerun does **not yet support** associating logged data with spans like `(from_timepoint, to_timepoint)` or `(timepoint, time-to-live)`. Follow the issue [here](https://github.com/rerun-io/rerun/issues/3008). ### Workaround by manually clearing entities For now the best workaround is to manually clear data when it is no longer valid. ```python # Associate the following data with `start_time` on the `time` timeline rr.set_time_seconds("time", start_time) # Log the data as usual rr.log("short_lived", rr.Tensor(one_second_tensor)) # Associate the following clear with `start_time + 1.0` on the `time` timeline rr.set_time_seconds("time", start_time + 1.0) rr.log("short_lived", rr.Clear(recursive=False)) # or `rr.Clear.flat()` # Set the time back so other data isn't accidentally logged in the future. rr.set_time_seconds("time", start_time) ``` # Send user-defined data --- title: Send user-defined data order: 200 description: How to use Rerun with custom data --- Rerun comes with many pre-built [Types](../../reference/types.md) that you can use out of the box. As long as your own data can be decomposed into Rerun [components](../../reference/types/components.md) or can be serialized with [Apache Arrow](https://arrow.apache.org/), you can log it directly without needing to recompile Rerun. For Python we have a helper for this, called [`AnyValues`](https://ref.rerun.io/docs/python/main/common/custom_data/), allowing you to easily attach custom values to any entity instance: ```python rr.log( "my_entity", rr.AnyValues( confidence=[1.2, 3.4, 5.6], description="Bla bla bla…", # URIs will become clickable links homepage="https://www.rerun.io", repository="https://github.com/rerun-io/rerun", ), ) ``` You can also create your own component by implementing the `AsComponents` [Python protocol](https://ref.rerun.io/docs/python/0.9.0/common/interfaces/#rerun.AsComponents) or [Rust trait](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html), which means implementing the function, `as_component_batches()`. ## 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. ```python @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. ```python 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 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 custom confidence and indicator components. ```python """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 component_descriptor(self) -> rr.ComponentDescriptor: """The descriptor of the custom component.""" return rr.ComponentDescriptor("user.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).or_with_descriptor_overrides( archetype_name="user.CustomPoints3D", archetype_field_name="confidences" ) 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() ``` # Send entire columns at once --- title: Send entire columns at once order: 0 description: How to use the Rerun SDK to log big chunks of data in one call --- The [`log` API](../../getting-started/data-in/python.md#logging-our-first-points) is designed to extract data from your running code as it's being generated. It is, by nature, *row-oriented*. If you already have data stored in something more *column-oriented*, it can be both a lot easier and more efficient to send it to Rerun in that form directly. This is what the `send_columns` API is for: it lets you efficiently update the state of an entity over time, sending data for multiple index and component columns in a single operation. > ⚠️ `send_columns` API bypasses the time context and [micro-batcher](../../reference/sdk/micro-batching.md) ⚠️ > > In contrast to the `log` API, `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](../../concepts/timelines.md). Only the timelines explicitly included in the call to `send_columns` will be included. To learn more about the concepts behind the columnar APIs, and the Rerun data model in general, [refer to this page](../../concepts/chunks.md). ## Reference * [🌊 C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#ad17571d51185ce2fc2fc2f5c3070ad65) * [🐍 Python](https://ref.rerun.io/docs/python/stable/common/columnar_api/#rerun.send_columns) * [🦀 Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.send_columns) ## Examples ### Updating a scalar over time, in a single operation Consider this snippet, using the row-oriented `log` API: ```python """ Update a scalar over time. See also the `scalar_column_updates` example, which achieves the same thing in a single operation. """ from __future__ import annotations import math import rerun as rr rr.init("rerun_example_scalar_row_updates", spawn=True) for step in range(64): rr.set_time_sequence("step", step) rr.log("scalars", rr.Scalar(math.sin(step / 10.0))) ``` which can be translated to the column-oriented `send_columns` API as such: ```python """ Update a scalar over time, in a single operation. This is semantically equivalent to the `scalar_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_scalar_column_updates", spawn=True) times = np.arange(0, 64) scalars = np.sin(times / 10.0) rr.send_columns( "scalars", indexes=[rr.TimeSequenceColumn("step", times)], columns=rr.Scalar.columns(scalar=scalars), ) ``` ### Updating a point cloud over time, in a single operation Consider this snippet, using the row-oriented `log` API: ```python """ Update a point cloud over time. See also the `points3d_column_updates` example, which achieves the same thing in a single operation. """ import numpy as np import rerun as rr rr.init("rerun_example_points3d_row_updates", spawn=True) # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off 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]], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] for i in range(5): rr.set_time_seconds("time", 10 + i) rr.log("points", rr.Points3D(positions[i], colors=colors[i], radii=radii[i])) ``` which can be translated to the column-oriented `send_columns` API as such: ```python """ Update a point cloud over time, in a single operation. This is semantically equivalent to the `points3d_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_points3d_column_updates", spawn=True) # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off 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], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] rr.send_columns( "points", indexes=[rr.TimeSecondsColumn("time", times)], columns=[ *rr.Points3D.columns(positions=positions).partition(lengths=[2, 4, 4, 3, 4]), *rr.Points3D.columns(colors=colors, radii=radii), ], ) ``` Each row 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. ### Updating a point cloud over time, in a single operation Consider this snippet, using the row-oriented `log` API: ```python """ Update a point cloud over time. See also the `points3d_column_updates` example, which achieves the same thing in a single operation. """ import numpy as np import rerun as rr rr.init("rerun_example_points3d_row_updates", spawn=True) # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off 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]], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] for i in range(5): rr.set_time_seconds("time", 10 + i) rr.log("points", rr.Points3D(positions[i], colors=colors[i], radii=radii[i])) ``` which can be translated to the column-oriented `send_columns` API as such: ```python """ Update a point cloud over time, in a single operation. This is semantically equivalent to the `points3d_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_points3d_column_updates", spawn=True) # Prepare a point cloud that evolves over 5 timesteps, changing the number of points in the process. times = np.arange(10, 15, 1.0) # fmt: off 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], ] # fmt: on # At each timestep, all points in the cloud share the same but changing color and radius. colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] radii = [0.05, 0.01, 0.2, 0.1, 0.3] rr.send_columns( "points", indexes=[rr.TimeSecondsColumn("time", times)], columns=[ *rr.Points3D.columns(positions=positions).partition(lengths=[2, 4, 4, 3, 4]), *rr.Points3D.columns(colors=colors, radii=radii), ], ) ``` Each row 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. ### Updating a transform over time, in a single operation Consider this snippet, using the row-oriented `log` API: ```python """ Update a transform over time. See also the `transform3d_column_updates` example, which achieves the same thing in a single operation. """ import math import rerun as rr def truncated_radians(deg: float) -> float: return float(int(math.radians(deg) * 1000.0)) / 1000.0 rr.init("rerun_example_transform3d_row_updates", spawn=True) rr.set_time_sequence("tick", 0) rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), rr.Transform3D(clear=False, axis_length=10), ) for t in range(100): rr.set_time_sequence("tick", t + 1) rr.log( "box", rr.Transform3D( clear=False, translation=[0, 0, t / 10.0], rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=truncated_radians(t * 4)), ), ) ``` which can be translated to the column-oriented `send_columns` API as such: ```python """ Update a transform over time, in a single operation. This is semantically equivalent to the `transform3d_row_updates` example, albeit much faster. """ import math import rerun as rr def truncated_radians(deg: float) -> float: return float(int(math.radians(deg) * 1000.0)) / 1000.0 rr.init("rerun_example_transform3d_column_updates", spawn=True) rr.set_time_sequence("tick", 0) rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), rr.Transform3D(clear=False, axis_length=10), ) rr.send_columns( "box", indexes=[rr.TimeSequenceColumn("tick", range(1, 101))], columns=rr.Transform3D.columns( translation=[[0, 0, t / 10.0] for t in range(100)], rotation_axis_angle=[ rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=truncated_radians(t * 4)) for t in range(100) ], ), ) ``` ### Updating an image over time, in a single operation Consider this snippet, using the row-oriented `log` API: ```python """ Update an image over time. See also the `image_column_updates` example, which achieves the same thing in a single operation. """ import numpy as np import rerun as rr rr.init("rerun_example_image_row_updates", spawn=True) for t in range(20): rr.set_time_sequence("time", t) image = np.zeros((200, 300, 3), dtype=np.uint8) image[:, :, 2] = 255 image[50:150, (t * 10) : (t * 10 + 100)] = (0, 255, 255) rr.log("image", rr.Image(image)) ``` which can be translated to the column-oriented `send_columns` API as such: ```python """ Update an image over time, in a single operation. This is semantically equivalent to the `image_row_updates` example, albeit much faster. """ import numpy as np import rerun as rr rr.init("rerun_example_image_column_updates", 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 = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8") rr.log("images", rr.Image.from_fields(format=format), static=True) # Send all images at once. rr.send_columns( "images", indexes=[rr.TimeSequenceColumn("step", times)], # Reshape the images so `Image` can tell that this is several blobs. # # Note that the `Image` consumes arrays of bytes, so we should ensure that we take a # uint8 view of it. This way, this also works when working with datatypes other than `U8`. columns=rr.Image.columns(buffer=images.view(np.uint8).reshape(len(times), -1)), ) ``` ### Updating custom user-defined values over time, in a single operation [User-defined data](./custom-data.md) can also benefit from the column-oriented APIs. Consider this snippet, using the row-oriented `log` API: ```python """ Update custom user-defined values over time. See also the `any_values_column_updates` example, which achieves the same thing in a single operation. """ from __future__ import annotations import math import rerun as rr rr.init("rerun_example_any_values_row_updates", spawn=True) for step in range(64): rr.set_time_sequence("step", step) rr.log("/", rr.AnyValues(sin=math.sin(step / 10.0), cos=math.cos(step / 10.0))) ``` which can be translated to the column-oriented `send_columns` API as such: ```python """ Update custom user-defined values over time, in a single operation. This is semantically equivalent to the `any_values_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_any_values_column_updates", spawn=True) timestamps = np.arange(0, 64) rr.send_columns( "/", indexes=[rr.TimeSequenceColumn("step", timestamps)], columns=rr.AnyValues.columns(sin=np.sin(timestamps / 10.0), cos=np.cos(timestamps / 10.0)), ) ``` # Send partial updates over time --- title: Send partial updates over time order: 10 description: How to use the Rerun SDK to send partial data updates over time --- Rerun allows you to log only the data that has changed in-between frames (or whatever atomic unit [your timeline](../../concepts/timelines.md) is using), i.e. you can think of this as a sort of diffs or delta encodings. This is a natural consequence of how Rerun [ingests, stores](../../concepts/chunks.md) and finally [queries](../../reference/entity-queries.md) data: Rerun *always* operates that way, whether you're aware of it or not. Consider this simple snippet: ```python """Log some very simple points.""" import rerun as rr rr.init("rerun_example_points3d", spawn=True) rr.log("points", rr.Points3D([[0, 0, 0], [1, 1, 1]])) ``` Here, only the positions of the points have been specified but, looking at the [complete definition for Points3D](../../reference/types/archetypes/points3d.md), we can see that it has quite a few more [components](../../concepts/entity-component.md#data-model) available: > **Required**: [`Position3D`](../../reference/types/components/position3d.md) > > **Recommended** & **Optional**: [`Radius`](../../reference/types/components/radius.md), [`Color`](../../reference/types/components/color.md), [`Text`](../../reference/types/components/text.md), [`ShowLabels`](../../reference/types/components/show_labels.md), [`ClassId`](../../reference/types/components/class_id.md), [`KeypointId`](../../reference/types/components/keypoint_id.md) All three languages for which we provide logging SDKs (Python, Rust, C++) expose APIs that allow fine-grained control over which components of an archetypes, when, and how. The best way to learn about these APIs is to see them in action: check out the examples below. ## Examples ### Update specific properties of a point cloud over time ```python """Update specific properties of a point cloud over time.""" import rerun as rr rr.init("rerun_example_points3d_partial_updates", spawn=True) positions = [[i, 0, 0] for i in range(0, 10)] rr.set_time_sequence("frame", 0) rr.log("points", rr.Points3D(positions)) for i in range(0, 10): colors = [[20, 200, 20] if n < i else [200, 20, 20] for n in range(0, 10)] radii = [0.6 if n < i else 0.2 for n in range(0, 10)] # Update only the colors and radii, leaving everything else as-is. rr.set_time_sequence("frame", i) rr.log("points", rr.Points3D.from_fields(radii=radii, colors=colors)) # Update the positions and radii, and clear everything else in the process. rr.set_time_sequence("frame", 20) rr.log("points", rr.Points3D.from_fields(clear_unset=True, positions=positions, radii=0.3)) ``` ### Update specific properties of a transform over time ```python """Update specific properties of a transform over time.""" import math import rerun as rr def truncated_radians(deg: float) -> float: return float(int(math.radians(deg) * 1000.0)) / 1000.0 rr.init("rerun_example_transform3d_partial_updates", spawn=True) # Set up a 3D box. rr.log( "box", rr.Boxes3D(half_sizes=[4.0, 2.0, 1.0], fill_mode=rr.components.FillMode.Solid), rr.Transform3D(clear=False, axis_length=10), ) # Update only the rotation of the box. for deg in range(46): rad = truncated_radians(deg * 4) rr.log( "box", rr.Transform3D.from_fields( rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), ) # Update only the position of the box. for t in range(51): rr.log( "box", rr.Transform3D.from_fields(translation=[0, 0, t / 10.0]), ) # Update only the rotation of the box. for deg in range(46): rad = truncated_radians((deg + 45) * 4) rr.log( "box", rr.Transform3D.from_fields( rotation_axis_angle=rr.RotationAxisAngle(axis=[0.0, 1.0, 0.0], radians=rad), ), ) # Clear all of the box's attributes, and reset its axis length. rr.log( "box", rr.Transform3D.from_fields(clear_unset=True, axis_length=15), ) ``` ### Update specific parts of a 3D mesh over time ```python """Log a simple colored triangle, then update its vertices' positions each frame.""" import numpy as np import rerun as rr rr.init("rerun_example_mesh3d_partial_updates", spawn=True) vertex_positions = np.array([[-1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], dtype=np.float32) # Log the initial state of our triangle rr.set_time_sequence("frame", 0) rr.log( "triangle", rr.Mesh3D( vertex_positions=vertex_positions, vertex_normals=[0.0, 0.0, 1.0], vertex_colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]], ), ) # Only update its vertices' positions each frame factors = np.abs(np.sin(np.arange(1, 300, dtype=np.float32) * 0.04)) for i, factor in enumerate(factors): rr.set_time_sequence("frame", i) rr.log("triangle", rr.Mesh3D.from_fields(vertex_positions=vertex_positions * factor)) ``` # Share recordings across multiple processes --- title: Share recordings across multiple processes order: 100 --- A common need is to log data from multiple processes and then visualize all of that data as part of a single shared recording. Rerun has the notion of a [Recording ID](../../concepts/apps-and-recordings.md) for that: any recorded datasets that share the same Recording ID will be visualized as one shared dataset. The data can be logged from any number of processes, whether they run on the same machine or not, or implemented in different programming languages. All that matter is that they share the same Recording ID. By default, Rerun generates a random Recording ID everytime you start a new logging session, but you can override that behavior, e.g.: ```python rr.init("rerun_example_shared_recording", recording_id="my_shared_recording") ``` It's up to you to decide where each recording ends up: - all processes could stream their share of the data in real-time to a Rerun Viewer, - or maybe they all write to their own file on disk that are later loaded in a viewer, - or some other combination of the above. Here's a simple example of such a workflow: ```python # Process 1 logs some spheres to a recording file. ./app1.py # rr.init(recording_id='my_shared_recording', rr.save('/tmp/recording1.rrd') # Process 2 logs some cubes to another recording file. ./app2.py # rr.init(recording_id='my_shared_recording', rr.save('/tmp/recording2.rrd') # Visualize a 3D scene with both spheres and cubes. rerun /tmp/recording*.rrd # they share the same Recording ID! ``` For more information, check out our dedicated examples: * [🐍 Python](https://github.com/rerun-io/rerun/blob/latest/examples/python/shared_recording/shared_recording.py) * [🦀 Rust](https://github.com/rerun-io/rerun/blob/latest/examples/rust/shared_recording/src/main.rs) * [🌊 C++](https://github.com/rerun-io/rerun/blob/latest/examples/cpp/shared_recording/main.cpp) ### Merging recordings with the Rerun CLI It is possible to merge multiple recording files into a single one using the [Rerun CLI](../../reference/cli.md#rerun-rrd-merge), e.g. `rerun rrd merge -o merged_recordings.rrd my_first_recording.rrd my_second_recording.rrd`. The Rerun CLI offers several options to manipulate recordings in different ways, check out [the CLI reference](../../reference/cli.md) for more information. # Embed Rerun in notebooks --- title: Embed Rerun in notebooks order: 0 description: How to embed Rerun in notebooks like Jupyter or Colab --- Starting with version 0.15.1, Rerun has improved support for embedding the Rerun Viewer directly within IPython-style notebooks. This makes it easy to iterate on API calls as well as to share data with others. Rerun has been tested with: - [Jupyter Notebook Classic](https://jupyter.org/) - [Jupyter Lab](https://jupyter.org/) - [VSCode](https://code.visualstudio.com/blogs/2021/08/05/notebooks) - [Google Colab](https://colab.research.google.com/) To begin, install the `rerun-sdk` package with the `notebook` extra: ```sh pip install rerun-sdk[notebook] ``` This installs both [rerun-sdk](https://pypi.org/project/rerun-sdk/) and [rerun-notebook](https://pypi.org/project/rerun-notebook/). ## The APIs When using the Rerun logging APIs, by default, the logged messages are buffered in-memory until you send them to a sink such as via `rr.connect()` or `rr.save()`. When using Rerun in a notebook, rather than using the other sinks, you have the option to use [`rr.notebook_show()`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.notebook_show). This method embeds the [web viewer](./embed-web.md) using the IPython `display` mechanism in the cell output, and sends the current recording data to it. Once the viewer is open, any subsequent `rr.log()` calls will send their data directly to the viewer, without any intermediate buffering. For example: ```python import rerun as rr from numpy.random import default_rng rr.init("rerun_example_notebook") rng = default_rng(12345) positions = rng.uniform(-5, 5, size=[10, 3]) colors = rng.uniform(0, 255, size=[10, 3]) radii = rng.uniform(0, 1, size=[10]) rr.log("random", rr.Points3D(positions, colors=colors, radii=radii)) rr.notebook_show() ``` This is similar to calling `rr.connect()` or `rr.serve()` in that it configures the Rerun SDK to send data to a viewer instance. Note that the call to `rr.notebook_show()` drains the recording of its data. This means that any subsequent calls to `rr.notebook_show()` will not result in the same data being displayed, because it has already been removed from the recording. Support for this is tracked in [#6612](https://github.com/rerun-io/rerun/issues/6612). If you wish to start a new recording, you can call `rr.init()` again. The `notebook_show()` method also takes optional arguments for specifying the width and height of the viewer. For example: ```python rr.notebook_show(width=400, height=400) ``` ## Working with blueprints [Blueprints](../visualization/configure-viewer-through-code.md) can also be used with `notebook_show()` by providing a `blueprint` parameter. For example ```python blueprint = rrb.Blueprint( rrb.Horizontal( rrb.Spatial3DView(origin="/world"), rrb.Spatial2DView(origin="/world/camera"), column_shares=[2,1]), ) rr.notebook_show(blueprint=blueprint) ``` Because blueprint types implement `_ipython_display_`, you can also just end any cell with a blueprint object, and it will call `notebook_show()` behind the scenes. ```python import numpy as np import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_image") rng = np.random.default_rng(12345) image1 = rng.uniform(0, 255, size=[24, 64, 3]) image2 = rng.uniform(0, 255, size=[24, 64, 1]) rr.log("image1", rr.Image(image1)) rr.log("image2", rr.Image(image2)) rrb.Vertical( rrb.Spatial2DView(origin='/image1'), rrb.Spatial2DView(origin='/image2') ) ``` ## Streaming data The notebook integration supports streaming data to the viewer during cell execution. You can call `rr.notebook_show()` at any point after calling `rr.init()`, and any `rr.log()` calls will be sent to the viewer in real-time. ```python import math from time import sleep import numpy as np import rerun as rr from rerun.utilities import build_color_grid rr.init("rerun_example_notebook") rr.notebook_show() STEPS = 100 twists = math.pi * np.sin(np.linspace(0, math.tau, STEPS)) / 4 for t in range(STEPS): sleep(0.05) # delay to simulate a long-running computation rr.set_time_sequence("step", t) cube = build_color_grid(10, 10, 10, twist=twists[t]) rr.log("cube", rr.Points3D(cube.positions, colors=cube.colors, radii=0.5)) ``` ## Some working examples To experiment with notebooks yourself, there are a few options. ### Running locally The GitHub repo includes a [notebook example](https://github.com/rerun-io/rerun/blob/main/examples/python/notebook/cube.ipynb). If you have a local checkout of Rerun, you can: ```bash $ cd examples/python/notebook $ pip install -r requirements.txt $ jupyter notebook cube.ipynb ``` This will open a browser window showing the notebook where you can follow along. ### Running in Google Colab We also host a copy of the notebook in [Google Colab](https://colab.research.google.com/drive/1R9I7s4o6wydQC_zkybqaSRFTtlEaked_) Note that if you copy and run the notebook yourself, the first Cell installs Rerun into the Colab environment. After running this cell you will need to restart the Runtime for the Rerun package to show up successfully. ## Limitations Browsers have limitations in the amount of memory usable by a single tab. If you are working with large datasets, you may run into browser tab crashes due to out-of-memory errors. If you encounter the issue, you can try to use the `save()` API to save the data to a file and share it as a standalone asset. ## Future work We are actively working on improving the notebook experience and welcome any feedback or suggestions. The ongoing roadmap is being tracked in [GitHub issue #1815](https://github.com/rerun-io/rerun/issues/1815). # Embed Rerun in Web pages --- title: Embed Rerun in Web pages order: 100 --- Integrating the Rerun Viewer into your web application can be accomplished either by [utilizing an iframe](#embedding-apprerunio-using-an-iframe) or by using our [JavaScript package](#using-the-javascript-package). ## Embedding `app.rerun.io` using an ` ``` To implement this, fill in the placeholders: - `RRD_URL` - The URL of the recording to display in the viewer. - `RERUN_VERSION` - The version of the Rerun SDK used to generate the recording. The `RRD_URL` can be a file served over `http` (e.g. `https://app.rerun.io/version/0.20.3/examples/arkit_scenes.rrd`), or a connection to an SDK using our [serve](https://www.rerun.io/docs/reference/sdk/operating-modes#serve) API (e.g. `ws://localhost:4321`). For instance: ```html ``` ## Using the JavaScript package We offer JavaScript bindings to the Rerun Viewer via NPM. This method provides control over the Viewer but requires a JavaScript web application setup with a bundler. Various packages are available: - [@rerun-io/web-viewer](https://www.npmjs.com/package/@rerun-io/web-viewer): Suitable for JS apps without a framework or frameworks without dedicated packages. - [@rerun-io/web-viewer-react](https://www.npmjs.com/package/@rerun-io/web-viewer-react): Designed specifically for React apps. > ℹ️ Note: The stability of the `rrd` format is still evolving, so the package version corresponds to the supported Rerun SDK version. Therefore, `@rerun-io/web-viewer@0.10.0` can only connect to a data source (`.rrd` file, WebSocket connection, etc.) originating from a Rerun SDK with version `0.10.0`! ### Basic example To begin, install the package ([@rerun-io/web-viewer](https://www.npmjs.com/package/@rerun-io/web-viewer)) from NPM: ``` npm i @rerun-io/web-viewer ``` > ℹ Note: This package is compatible only with recent browser versions. If your target browser lacks support for Wasm imports or top-level await, additional plugins may be required for your bundler setup. For instance, if you're using [Vite](https://vitejs.dev/), you'll need to install [vite-plugin-wasm](https://www.npmjs.com/package/vite-plugin-wasm) and [vite-plugin-top-level-await](https://www.npmjs.com/package/vite-plugin-top-level-await) and integrate them into your `vite.config.js`. Once installed and configured, import and use it within your application: ```js import { WebViewer } from "@rerun-io/web-viewer"; const rrdUrl = null; const parentElement = document.body; const viewer = new WebViewer(); await viewer.start(rrdUrl, parentElement); ``` The Viewer creates a `` on the provided `parentElement` and executes within it. The first argument for `start` determines the recordings to open in the viewer. It can be: - `null` for an initially empty viewer - a URL string to open a single recording - an array of strings to open multiple recordings Each URL can be either a file served over `http` or a connection to an SDK using our [serve](https://www.rerun.io/docs/reference/sdk/operating-modes#serve) API. See [web-viewer-serve-example](https://github.com/rerun-io/web-viewer-serve-example) for a full example of how to log data from our Python SDK to an embedded Rerun Viewer. ### Controlling the canvas By default, the web viewer attempts to expand the canvas to occupy all available space. You can customize its dimensions by placing it within a container: ```html,id=embed-web-viewer-canvas-control-html
``` ```css,id=embed-web-viewer-canvas-control-css #viewer-container { position: relative; height: 640px; width: 100%; } ``` ```js,id=embed-web-viewer-canvas-control-js const parentElement = document.getElementById("viewer-container"); const viewer = new WebViewer(); await viewer.start(null, parentElement); ``` ### Viewer API The Viewer API supports adding and removing recordings: ```js,id=embed-web-viewer-api-js-open-close const rrdUrl = "https://app.rerun.io/version/0.20.3/examples/arkit_scenes.rrd"; // Open a recording: viewer.open(rrdUrl); // Later on… viewer.close(rrdUrl); ``` Once finished with the Viewer, you can stop it and release all associated resources: ```js,id=embed-web-viewer-api-js-stop viewer.stop(); ``` This action also removes the canvas from the page. You can `start` and `stop` the same `WebViewer` instance multiple times. # Integrate Rerun with native loggers --- title: Integrate Rerun with native loggers order: 400 description: How to use the Rerun SDK as a native logger for the host language --- The Rerun SDK implements the native logging interfaces of its supported host languages, allowing you to transparently stream text logs logged with the native APIs into the Rerun Viewer. The details of how to achieve that vary language by language, see the snippets below. ```python """Shows integration of Rerun's `TextLog` with the native logging interface.""" import logging import rerun as rr rr.init("rerun_example_text_log_integration", spawn=True) # Log a text entry directly rr.log("logs", rr.TextLog("this entry has loglevel TRACE", level=rr.TextLogLevel.TRACE)) # Or log via a logging handler logging.getLogger().addHandler(rr.LoggingHandler("logs/handler")) logging.getLogger().setLevel(-1) logging.info("This INFO log got added through the standard logging interface") ``` # Use Rerun with ROS 2 --- title: Use Rerun with ROS 2 order: 300 ogImageUrl: /docs-media/og-howto-ros.jpg description: Rerun does not yet have native ROS support, but many of the concepts in ROS and Rerun line up fairly well. In this guide, you will learn how to write a simple ROS 2 Python node that subscribes to some common ROS topics and logs them to Rerun. --- Rerun does not yet have native ROS support, but many of the concepts in ROS and Rerun line up fairly well. In this guide, you will learn how to write a simple ROS 2 Python node that subscribes to some common ROS topics and logs them to Rerun. For information on future plans to enable more native ROS support see [#1537](https://github.com/rerun-io/rerun/issues/1537) The following is primarily intended for existing ROS 2 users. It will not spend much time covering how to use ROS 2 itself. If you are a Rerun user that is curious about ROS, please consult the [ROS 2 Documentation](https://docs.ros.org/en/humble/index.html) instead. All of the code for this guide can be found on GitHub in [rerun/examples/python/ros_node](https://github.com/rerun-io/rerun/blob/main/examples/python/ros_node/). ## Prerequisites Other relevant tutorials: - [Python SDK Tutorial](../../getting-started/data-in/python.md) - [Viewer Walkthrough](../../getting-started/navigating-the-viewer.md) ### ROS 2 & navigation You will need to have installed [ROS 2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) and the [turtlebot3 navigation getting-started example](https://docs.nav2.org/getting_started/index.html). Installing ROS is outside the scope of this guide, but you will need the equivalent of the following packages: ```bash $ sudo apt install ros-humble-desktop gazebo ros-humble-navigation2 ros-humble-turtlebot3 ros-humble-turtlebot3-gazebo ``` If you don't already have ROS installed, we recommend trying [RoboStack](https://robostack.github.io/) for setting up your installation. Before proceeding, you should follow the [navigation example](https://docs.nav2.org/getting_started/index.html) and confirm that you can successfully run: ```bash $ export TURTLEBOT3_MODEL=waffle $ export GAZEBO_MODEL_PATH=/opt/ros/humble/share/turtlebot3_gazebo/models $ ros2 launch nav2_bringup tb3_simulation_launch.py headless:=False ``` Make sure that you can set the 2D Pose Estimate and send a Navigation Goal via rviz. You can now leave this running in the background for the remainder of the guide. ### Additional dependencies The code for this guide is in the `rerun` repository. If you do not already have Rerun cloned, you should do so now: ```bash git clone git@github.com:rerun-io/rerun.git cd rerun ``` The example code can be found in the folder: `examples/python/ros_node`. In addition to the ROS dependencies, the Rerun node makes use of some dependencies specified in [`requirements.txt`](https://github.com/rerun-io/rerun/blob/main/examples/python/ros_node/requirements.txt). Rerun recommends using `venv` (or the equivalent) to create an environment for installing these dependencies. Note that _after_ setting up your virtualenv you will need to activate your ROS2 environment. ```bash $ python3 -m venv venv $ source venv/bin/active (venv) $ pip install -r examples/python/ros_node/requirements.txt (venv) $ source /opt/ros/humble/setup.bash ``` ## Running the example With the previous dependencies installed, and gazebo running, you should now be able to launch the Rerun ROS example: ```bash (venv) $ python3 examples/python/ros_node/main.py ``` You should see a window similar to: Use rviz to send a new navigation goal and confirm that Rerun updates with new data as turtlebot drives around the environment. ### Overview If you are familiar with the turtlebot nav example and rviz, this view will likely be familiar: - `map/box` is a placeholder for the map. (This will eventually be a map: [#1531](https://github.com/rerun-io/rerun/issues/1531).) - `map/robot` is a transform representing the robot pose logged as a rigid [transform3d](../../reference/types/archetypes/transform3d.md). - `map/robot/urdf` contains the `URDF` logged as a [mesh](../../reference/types/archetypes/mesh3d.md). - `map/robot/scan` contains a `LaserScan` msg logged as a [linestrip3d](../../reference/types/archetypes/line_strips3d.md). (This will eventually be a native type: [#1534](https://github.com/rerun-io/rerun/issues/1534).) - `map/robot/camera` contains a `CameraInfo` msg logged as a [pinhole](../../reference/types/archetypes/pinhole.md) transform. - `map/robot/camera/img` contains an `Image` msg logged as an [image](../../reference/types/archetypes/image.md). - `map/robot/camera/points` contains a `PointCloud2` msg logged as a [point3d](../../reference/types/archetypes/points3d.md). - `map/points` contains a second copy of `PointCloud2` with a different transform. (This is a workaround until Rerun has support for ROS-style fixed frames [#1522](https://github.com/rerun-io/rerun/issues/1522).) - `odometry/vel` is a plot of the linear velocity of the robot logged as a [scalar](../../reference/types/archetypes/scalar.md). - `odometry/ang_vel` is a plot of the angular velocity of the robot logged as a [scalar](../../reference/types/archetypes/scalar.md). ## Code explanation It may be helpful to open [rerun/examples/python/ros_node/main.py](https://github.com/rerun-io/rerun/blob/latest/examples/python/ros_node/main.py) to follow along. Outside of TF, the node is mostly stateless. At a very high level, for each ROS message we are interested in, we create a subscriber with a callback that does some form of data transformation and then logs the data to Rerun. For simplicity, this example uses the rosclpy `MultiThreadedExecutor` and `ReentrantCallbackGroup` for each topic. This allows each callback thread to do TF lookups without blocking the other incoming messages. More advanced ROS execution models and using asynchronous TF lookups are outside the scope of this guide. ### Updating time First of all, we want our messages to show up on the timeline based on their _stamped_ time rather than the time that they were received by the listener, or relayed to Rerun. To do this, we will use a Rerun timeline called `ros_time`. Each callback follows a common pattern of updating `ros_time` based on the stamped time of the message that was received. ```python def some_msg_callback(self, msg: Msg): time = Time.from_msg(msg.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) ``` This timestamp will apply to all subsequent log calls on in this callback (on this thread) until the time is updated again. ### TF to rr.Transform3D Next, we need to map the [ROS TF2](https://docs.ros.org/en/humble/Concepts/About-Tf2.html) transforms to the corresponding [Rerun Transforms](../../concepts/spaces-and-transforms.md#space-transformations). In Rerun, each path represents a coordinate frame, so we need to decide which TF frame each path will correspond to. In general, this is the frame_id of the sensor data that will be logged to that path. For consistency, we define this once in `__init__()`. ```python # Define a mapping for transforms self.path_to_frame = { "map": "map", "map/points": "camera_depth_frame", "map/robot": "base_footprint", "map/robot/scan": "base_scan", "map/robot/camera": "camera_rgb_optical_frame", "map/robot/camera/points": "camera_depth_frame", } ``` Because we have chosen a Rerun path hierarchy that does not exactly match the TF graph topology the values for the transforms at these paths need to be derived using TF on the client logging side at log-time. In the future, Rerun will support deriving these values in the viewer (see: [#1533](https://github.com/rerun-io/rerun/issues/1533) for more details), allowing all of this code to go away. For now, on each incoming log message, we want to use the mapping to update the transform at the timestamp in question: ```python def log_tf_as_transform3d(self, path: str, time: Time) -> None: """Helper to look up a transform with tf and log using `log_transform3d`.""" # Get the parent path parent_path = path.rsplit("/", 1)[0] # Find the corresponding frames from the mapping child_frame = self.path_to_frame[path] parent_frame = self.path_to_frame[parent_path] # Do the TF lookup to get transform from child (source) -> parent (target) try: tf = self.tf_buffer.lookup_transform(parent_frame, child_frame, time, timeout=Duration(seconds=0.1)) t = tf.transform.translation q = tf.transform.rotation rr.log(path, rr.Transform3D(translation=[t.x, t.y, t.z], rotation=rr.Quaternion(xyzw=[q.x, q.y, q.z, q.w]))) except TransformException as ex: print(f"Failed to get transform: {ex}") ``` As an example of logging points in the map frame, we simply call: ```python rr.log("map/points", rr.Points3D(positions=pts, colors=colors)) self.log_tf_as_transform3d("map/points", time) ``` Note that because we previously called `set_time_nanos` in this callback, this transform will be logged to the same point on the timeline as the data, using a timestamp looked up from TF at the matching timepoint. ### Odometry to rr.Scalar and rr.Transform3D When receiving odometry messages, we log the linear and angular velocities using `rr.Scalar`. Additionally, since we know that odometry will also update the `map/robot` transform, we use this as a cue to look up the corresponding transform and log it. ```python def odom_callback(self, odom: Odometry) -> None: """Update transforms when odom is updated.""" time = Time.from_msg(odom.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) # Capture time-series data for the linear and angular velocities rr.log("odometry/vel", rr.Scalar(odom.twist.twist.linear.x)) rr.log("odometry/ang_vel", rr.Scalar(odom.twist.twist.angular.z)) # Update the robot pose itself via TF self.log_tf_as_transform3d("map/robot", time) ``` ### CameraInfo to rr.Pinhole Not all Transforms are rigid as defined in TF. The other transform we want to log is the pinhole projection that is stored in the `CameraInfo` msg. Fortunately, the `image_geometry` package has a `PinholeCameraModel` that exposes the intrinsic matrix in the same structure used by Rerun `rr.Pinhole`: ```python def __init__(self) -> None: # … self.model = PinholeCameraModel() def cam_info_callback(self, info: CameraInfo) -> None: """Log a `CameraInfo` with `log_pinhole`.""" time = Time.from_msg(info.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) self.model.fromCameraInfo(info) rr.log( "map/robot/camera/img", rr.Pinhole( resolution=[self.model.width, self.model.height], image_from_camera=self.model.intrinsicMatrix(), ), ) ``` ### Image to rr.Image ROS Images can also be mapped to Rerun very easily, using the `cv_bridge` package. The output of `cv_bridge.imgmsg_to_cv2` can be fed directly into `rr.Image`: ```python def __init__(self) -> None: # … self.cv_bridge = cv_bridge.CvBridge() def image_callback(self, img: Image) -> None: """Log an `Image` with `log_image` using `cv_bridge`.""" time = Time.from_msg(img.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) rr.log("map/robot/camera/img", rr.Image(self.cv_bridge.imgmsg_to_cv2(img))) self.log_tf_as_transform3d("map/robot/camera", time) ``` ### PointCloud2 to rr.Points3D The ROS [PointCloud2](https://github.com/ros2/common_interfaces/blob/humble/sensor_msgs/msg/PointCloud2.msg) message is stored as a binary blob that needs to be reinterpreted using the details about its fields. Each field is a named collection of offsets into the data buffer, and datatypes. The `sensor_msgs_py` package includes a `point_cloud2` reader, which can be used to convert to a Rerun-compatible Numpy array. These fields are initially returned as Numpy structured arrays, whereas Rerun currently expects an unstructured array of Nx3 floats. Color is extracted in a similar way, although the realsense gazebo driver does not provide the correct offsets for the r,g,b channels, requiring us to patch the field values. After extracting the positions and colors as Numpy arrays, the entire cloud can be logged as a batch with `rr.Points3D` ```python def points_callback(self, points: PointCloud2) -> None: """Log a `PointCloud2` with `log_points`.""" time = Time.from_msg(points.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) pts = point_cloud2.read_points(points, field_names=["x", "y", "z"], skip_nans=True) # The realsense driver exposes a float field called 'rgb', but the data is # actually stored as bytes within the payload (not a float at all). Patch # points.field to use the correct r,g,b, offsets so we can extract them with # read_points. points.fields = [ PointField(name="r", offset=16, datatype=PointField.UINT8, count=1), PointField(name="g", offset=17, datatype=PointField.UINT8, count=1), PointField(name="b", offset=18, datatype=PointField.UINT8, count=1), ] colors = point_cloud2.read_points(points, field_names=["r", "g", "b"], skip_nans=True) pts = structured_to_unstructured(pts) colors = colors = structured_to_unstructured(colors) # Log points once rigidly under robot/camera/points. This is a robot-centric # view of the world. rr.log("map/robot/camera/points", rr.Points3D(pts, colors=colors)) self.log_tf_as_transform3d("map/robot/camera/points", time) ``` ### LaserScan to rr.LineStrips3D Rerun does not yet have native support for a `LaserScan` style primitive so we need to do a bit of additional transformation logic (see: [#1534](https://github.com/rerun-io/rerun/issues/1534).) First, we convert the scan into a point-cloud using the `laser_geometry` package. After converting to a point-cloud, we extract the pts just as above with `PointCloud2`. We could have logged the Points directly using `rr.Points3D`, but for the sake of this demo, we wanted to instead log a laser scan as a bunch of lines in a similar fashion to how it is depicted in gazebo. We generate a second matching set of points for each ray projected out 0.3m from the origin and then interlace the two sets of points using Numpy hstack and reshape. This results in a set of alternating points defining rays from the origin to each laser scan result, which is the format expected by `rr.LineStrips3D`: ```python def __init__(self) -> None: # … self.laser_proj = laser_geometry.laser_geometry.LaserProjection() def scan_callback(self, scan: LaserScan) -> None: """Log a LaserScan after transforming it to line-segments.""" time = Time.from_msg(scan.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) # Project the laser scan to a collection of points points = self.laser_proj.projectLaser(scan) pts = point_cloud2.read_points(points, field_names=["x", "y", "z"], skip_nans=True) pts = structured_to_unstructured(pts) # Turn every pt into a line-segment from the origin to the point. origin = (pts / np.linalg.norm(pts, axis=1).reshape(-1, 1)) * 0.3 segs = np.hstack([origin, pts]).reshape(pts.shape[0] * 2, 3) rr.log("map/robot/scan", rr.LineStrips3D(segs, radii=0.0025)) self.log_tf_as_transform3d("map/robot/scan", time) ``` ### URDF to rr.Mesh3D The URDF conversion is actually the most complex operation in this example. As such the functionality is split out into a separate [rerun/examples/python/ros_node/rerun_urdf.py](https://github.com/rerun-io/rerun/blob/main/examples/python/ros_node/rerun_urdf.py) helper. Loading the URDF from the `/robot_description` topic is relatively straightforward since we use [yourdfpy](https://github.com/clemense/yourdfpy) library to do the heavy lifting. The main complication is that the actual mesh resources in that URDF need to be located via `ament`. Fortunately, `yourdfpy` accepts a filename handler, which we shim together with ament `get_package_share_directory`. ```python def ament_locate_package(fname: str) -> str: """Helper to locate urdf resources via ament.""" if not fname.startswith("package://"): return fname parsed = urlparse(fname) return os.path.join(get_package_share_directory(parsed.netloc), parsed.path[1:]) def load_urdf_from_msg(msg: String) -> URDF: """Load a URDF file using `yourdfpy` and find resources via ament.""" f = io.StringIO(msg.data) return URDF.load(f, filename_handler=ament_locate_package) ``` We then use `rerun_urdf.load_urdf_from_msg` from the URDF subscription callback. Note that when developing this guide, we noticed that the camera mesh URDF was not having its scale applied to it. This seems like a bug in either `yourdfpy` or `pycollada` not respecting the scale hint. To accommodate this, we manually re-scale the camera link. Once we have correctly re-scaled the camera component, we can send the whole scene to Rerun with `rerun_urdf.log_scene`. ```python def urdf_callback(self, urdf_msg: String) -> None: """Log a URDF using `log_scene` from `rerun_urdf`.""" urdf = load_urdf_from_msg(urdf_msg) # The turtlebot URDF appears to have scale set incorrectly for the # camera_link. Although rviz loads it properly `yourdfpy` does not. orig, _ = urdf.scene.graph.get("camera_link") scale = trimesh.transformations.scale_matrix(0.00254) urdf.scene.graph.update(frame_to="camera_link", matrix=orig.dot(scale)) scaled = urdf.scene.scaled(1.0) rerun_urdf.log_scene(scene=scaled, node=urdf.base_link, path="map/robot/urdf", static=True) ``` Back in `rerun_urdf.log_scene` all the code is doing is recursively walking through the trimesh scene graph. For each node, it extracts the transform to the parent, which it logs via `rr.Transform3D` before then using `rr.Mesh3D` to send the vertices, indices, and normals from the trimesh geometry. This code is almost entirely URDF-independent and is a good candidate for a future Python API ([#1536](https://github.com/rerun-io/rerun/issues/1536).) ```python node_data = scene.graph.get(frame_to=node, frame_from=parent) if node_data: # Log the transform between this node and its direct parent (if it has one!). if parent: world_from_mesh = node_data[0] rr.log( path, rr.Transform3D( translation=world_from_mesh[3, 0:3], mat3x3=world_from_mesh[0:3, 0:3], ), static=static, ) # Log this node's mesh, if it has one. mesh = cast(trimesh.Trimesh, scene.geometry.get(node_data[1])) if mesh: # … extract some color information rr.log( path, rr.Mesh3D( vertex_positions=mesh.vertices, triangle_indices=mesh.faces, vertex_normals=mesh.vertex_normals, albedo_factor=albedo_factor, ), static=static, ) ``` Color data is also extracted from the trimesh, but omitted here for brevity. ## In summary Although there is a non-trivial amount of code, none of it is overly complicated. Each message callback operates independently of the others, processing an incoming message, adapting it to Rerun and then logging it again. There are several places where Rerun is currently missing support for primitives that will further simplify this implementation. We will continue to update this guide as new functionality becomes available. While this guide has only covered a small fraction of the possible ROS messages that could be sent to Rerun, hopefully, it has given you some tools to apply to your project. If you find that specific functionality is lacking for your use case, please provide more context in the existing issues or [open an new one](https://github.com/rerun-io/rerun/issues/new/choose) on GitHub. # By logging custom data --- title: By logging custom data hidden: true redirect: howto/logging/custom-data --- # By implementing custom visualizations (Rust only) --- title: By implementing custom visualizations (Rust only) hidden: true redirect: howto/visualization/extend-ui --- # Configure the viewer --- title: Configure the viewer order: 600 --- By default, the Rerun Viewer uses heuristics to automatically determine an appropriate layout given the data that you provide. However, there will always be situations where the heuristic results don't match the needs of a particular use-case. Fortunately, almost all aspects of the Viewer can be configured via the [Blueprint](../reference/viewer/blueprint.md). The Viewer Blueprint completely determines: - What contents are included in each view - The type of view used to visualize the data - The organizational layout and names of the different view panels and containers - Configuration and styling properties of the individual data visualizers There are a few different ways to work with Blueprints: - [Blueprints can be modified interactively](./configure-the-viewer/interactively.md) - [Blueprint files (.rbl) can be saved and loaded from disk](./configure-the-viewer/save-and-load.md) - [Blueprints can be controlled directly from code](./configure-the-viewer/through-code-tutorial.md) # Send data to Rerun --- title: Send data to Rerun order: 400 --- This section shows you how to send data to Rerun from either your running applications or existing files. - Sending data from your code - [C++](./data-in/cpp.md) - [Python](./data-in/python.md) - [Rust](./data-in/rust.md) - [Opening files](./data-in/open-any-file.md) # Query data out of Rerun --- title: Query data out of Rerun order: 450 --- At its core, Rerun is a database. The viewer includes the [dataframe view](../reference/types/views/dataframe_view.md) to explore data in tabular form, and the SDK includes an API to export the data as dataframes from the recording. These features can be used, for example, to perform analysis on the data and send back the results to the original recording. In this three-part guide, we explore such a workflow by implementing an "open jaw detector" on top of our [face tracking example](https://rerun.io/examples/video-image/face_tracking). This process is split into three steps: 1. [Explore a recording with the dataframe view](data-out/explore-as-dataframe.md) 2. [Export the dataframe](data-out/export-dataframe.md) 3. [Analyze the data and send back the results](data-out/analyze-and-send.md) Note: this guide uses the popular [Pandas](https://pandas.pydata.org) dataframe package. The same concept however applies in the same way for alternative dataframe packages such as [Polars](https://pola.rs). If you just want to see the final result, jump to the [complete script](data-out/analyze-and-send.md#complete-script) at the end of the third section. # Installing Rerun --- title: Installing Rerun order: 300 --- ## Installing the SDK ### C++ If you're using CMake you can add the SDK to your project using `FetchContent`: ```cmake include(FetchContent) FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip) FetchContent_MakeAvailable(rerun_sdk) ``` For more details see [Build & Distribution](https://ref.rerun.io/docs/cpp/stable/index.html#autotoc_md8) in the C++ reference documentation. You'll additionally need to install the Viewer, see [below](#installing-the-viewer) ### Python - `pip install rerun-sdk` via pip - `conda install -c conda-forge rerun-sdk` via Conda Either way this includes both the SDK & the Viewer and you're ready to go! ### Rust Add the [Rerun crate](https://crates.io/crates/rerun) using `cargo add rerun`. You'll additionally need to install the Viewer, see [below](#installing-the-viewer). ## Installing the Viewer The [Viewer](../reference/viewer/overview.md) can be installed independent of the library language you're using. Make sure that your library version matches the version of the Viewer you're using, because [our data format is not yet stable across different versions](https://github.com/rerun-io/rerun/issues/6410). There are many ways to install the viewer. Please pick whatever works best for your setup: - Download `rerun-cli` for your platform from the [GitHub Release artifacts](https://github.com/rerun-io/rerun/releases/latest/). - Via Cargo - `cargo binstall rerun-cli` - download binaries via [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) - `cargo install rerun-cli --locked` - build it from source (this requires Rust 1.81+) - Together with the Rerun [Python SDK](./quick-start/python.md): - `pip3 install rerun-sdk` - download it via pip - `conda install -c conda-forge rerun-sdk` - download via Conda - `pixi global install rerun-sdk` - download it via [Pixi](https://pixi.sh/latest/) In any case you should be able to run `rerun` afterwards to start the Viewer. You'll be welcomed by an overview page that allows you to jump into some examples. If you're facing any difficulties, don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose) or [join the Discord server](https://discord.gg/PXtCgFBSmH). The Rerun Viewer has built-in support for opening many kinds of files, and can be [extended to open any other file type](./data-in/open-any-file.md) without needing to modify the Rerun codebase itself. ## Next steps To start getting your own data streamed to the viewer, check one of the respective getting started guides: - [C++](./quick-start/cpp.md) - [Python](./quick-start/python.md) - [Rust](./quick-start/rust.md) # Navigating the viewer --- title: Navigating the viewer order: 500 --- This guide will familiarize you with the basics of using the Rerun Viewer with an example dataset. By the end you should be comfortable with the following topics: - [Launching the demo](#launching-an-example) - [The Viewer panels](#the-viewer-panels) - [Exploring data](#exploring-data) - [Navigating the timeline](#navigating-the-timeline) Here is a preview of the dataset that we will be working with: The demo uses the output of the [COLMAP](https://colmap.github.io/) structure-from-motion pipeline on a small dataset. Familiarity with structure-from-motion algorithms is not a prerequisite for following the guide. All you need to know is that at a very high level, COLMAP processes a series of images, and by tracking identifiable "keypoints" from frame to frame, it is able to reconstruct both a sparse representation of the scene as well as the positions of the camera used to take the images. ## Prerequisites Although the Rerun SDK is available in both Python and Rust, this walkthrough makes use the Python installation. Even if you plan to use Rerun with Rust, we still recommend having a Rerun Python environment available for quick experimentation and working with examples. You can either follow the [Python Quickstart](./quick-start/python.md) or simply run: ```bash pip install rerun-sdk ``` You can also find `rerun-sdk` on [`conda`](https://github.com/conda-forge/rerun-sdk-feedstock). ## Launching an example If you have already followed the Python Quickstart you may have already check the "Helix" integrated example. This time, we will use the "Structure from Motion" example. Start by running the viewer: ```bash $ rerun ``` _Note: If this is your first time launching Rerun you will see a notification about the Rerun anonymous data usage policy. Rerun collects anonymous usage data to help improve the SDK, though you may choose to opt out if you would like._ This will bring you the Rerun viewer's Welcome screen: From there you can chose the "Structure from Motion" example. A window that looks like this will appear: Depending on your display size, the panels may have a different arrangements. Further in this guide you will learn how you can change that. ## The Viewer panels This window has five main sections: - [Viewport](../reference/viewer/viewport.md) (center): Displays the rendered views for your session. - [Recordings panel](../concepts/apps-and-recordings.md) (top left): Lists loaded recordings and their applications, and allows navigation back to the welcome screen. - [Blueprint panel](../reference/viewer/blueprint.md) (below Recordings): Controls the different views. - [Selection panel](../reference/viewer/selection.md) (right): Shows detailed information and configuration for selected items. - [Timeline panel](../reference/viewer/timeline.md) (bottom): Controls the current point in time being viewed. Each of the three sides has a button in the upper-right corner. Click these to show or hide the corresponding panels. There are several ways to rearrange the viewer layout to your liking: through the Viewer [user interface](configure-the-viewer/interactively.md), via the [Blueprint API](configure-the-viewer/through-code-tutorial.md), or by [loading an .rbl file](configure-the-viewer/save-and-load.md). ## Exploring data In Rerun, data is modeled using [entities](../concepts/entity-component.md) (essentially objects) that contain batches of [components](../reference/types/components.md) that change over time. Each entity is identified by an entity path, which uses a hierarchical syntax to represent relationships between entities. Let's explore an example of this hierarchy in our scene: - `/camera/image/keypoints` is an entity stream that contains 3 component streams (`Points2DIndicator`, `Color`, `Position2D`). `Points2DIndicator` component indicates that together, they form a [Points2D archetype](../reference/types/archetypes/points2d.md), representing point clouds that were detected and tracked in images. - The images themselves are represented by the parent entity `/camera/image`. This entity consist of 6 components: 4 form an [Image archetype](../reference/types/archetypes/image.md), while the remaining 2 correspond to a [pinhole projection](../reference/types/archetypes/pinhole.md). The images are captures by the camera, and a pinhole projection defines the relationship between 2D and 3D space. - Both the images and pinhole projection are hierarchically dependent on the camera's position, which is described by the `/camera` entity. This entity includes a series of transforms that together form a [Transform3D archetype](../reference/types/archetypes/transform3d.md). The hierarchy of logged entity streams and their component streams is found under `Streams` in the Timeline panel. A similar list appears in the `Blueprint` panel, but the key difference is that the Blueprint panel focuses on how data is arranged and visualized in the Viewport, while the Streams panel shows when and what events were logged. In other words, an entity may be logged once but displayed in multiple views. Visualizations can also be customized per each view using [Overrides](../concepts/visualizers-and-overrides.md) in the Selection panel. In the screenshot below, the same entity `keypoints` is displayed in different colors: yellow and magenta. This is reflected in Selection > Visualizers > Points2D > Color, where yellow is an overridden value, even though the logged color value was different. ### Hover and selection You can easily identify which entity mentions and visual representations refer to the same entities across different panels by seeing them simultaneously highlighted in the UI. Hovering over an entity will display a popup with additional information about its content. Clicking on it will reveal more details in the [Selection panel](../reference/viewer/selection.md). Try each of the following: - Hover over the image to see a zoomed-in preview - Click on the point cloud to select the whole cloud - With the point cloud selected, hover and click individual points ### Rotate, zoom, and pan Clicking and dragging the contents of any view will move it. You can rotate 3D views, or pan 2D views and plots. You can also zoom using ctrl+scrollwheel or pinch gestures on a trackpad. Most views can be restored to their default state by double-clicking somewhere in the view. Every view has a "?" icon in the upper right hand corner. You can always mouse over this icon to find out more information about the specific view. Try each of the following: - Drag the camera image and zoom in on one of the stickers - Rotate the 3D point cloud - Right-click and drag a rectangle to see a zoomed-in region of the plot - Double-click in each of the views to return them to default ## Navigating the timeline If you look at the Timeline panel at the bottom of the window, you will see a series of white dots. Each of those dots represents a piece of data that was logged at a different point in time. In fact, if you hover over the dot, the context popup will give you more information about the specific thing that was logged. There are several ways to navigate through the timeline: - Move the time indicator by dragging it to a different point on the timeline. You can also click on the frame number and manually type the desired frame. - Adjust the playback speed, and for index-based timelines, you can also modify the number of frames per second to specify how indices relate to time. - Use the play, pause, step, and loop controls to playback Rerun data, similar to how you would with a video file. Try out the following: - Use the arrow buttons (or Arrow keys on your keyboard) to step forward and backwards by a single frame - Click play to watch the data update on its own - Hit space bar to stop and start the playback - Hold shift and drag in the timeline to select a region - Toggle the loop button to playback on a loop of either the whole recording or just the selection ### Selecting different timelines The current view of timeline is showing the data organized by the _frame number_ at which it was logged. Using frame numbers can be a helpful way to synchronize things that may not have been logged at precisely the same time. However, it's possible to also view the data in the specific order that it was logged. Click on the drop-down that says "frame" and switch it to "log_time." If you zoom in on the timeline (using ctrl+scrollwheel), you can see that these events were all logged at slightly different times. Feel free to spend a bit of time looking at the data across the different timelines. When you are done, switch back to the "frame" timeline and double-click the timeline panel to reset it to the default range. One thing to notice is there is a gap in the timeline in the "frame" view. This dataset is actually missing a few frames, and the timeline view of frames makes this easy to spot. This highlights the importance of applying meaningful timestamps to your data as you log it. You also aren't limited to frame and log_time. Rerun lets you define your own timelines however you would like. You can read more about timelines [here](../concepts/timelines.md). ## Conclusion That brings us to the end of this walkthrough. To recap, you have learned how to: - Install the `rerun-sdk` pypi package. - Run the Rerun Viewer using the `rerun` command. - Open the examples integrated in the viewer. - Work with the [Blueprint](../reference/viewer/blueprint.md), [Selection](../reference/viewer/selection.md) and [Timeline](../reference/viewer/timeline.md) panels. - Rearrange view layouts. - Explore data through hover and selection. - Change the time selection. - Switch between different timelines. Again, if you ran into any issues following this guide, please don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). ### Up next - [Get started](./quick-start) by writing a program to log data with the Rerun SDK. - Learn how to further [configure the viewer](./configure-the-viewer) to suit your data. - Explore other [examples of using Rerun](/examples). - Consult the [concept overview](../concepts.md) for more context on the ideas covered here. # Quick start --- title: Quick start order: 200 --- Rerun is an SDK and engine for storing, querying, and visualizing and handling multimodal data streams. The primary way to get data into Rerun is to write code in one of the supported languages. To learn more about installing Rerun and the basics of getting started, choose your language: * [C++](./quick-start/cpp.md) * [Python](./quick-start/python.md) * [Rust](./quick-start/rust.md) # Troubleshooting --- title: Troubleshooting order: 800 --- You can set `RUST_LOG=debug` before running to get some verbose logging output. If you run into any issues don't hesitate to [open a ticket](https://github.com/rerun-io/rerun/issues/new/choose) or [join our Discord](https://discord.gg/Gcm8BbTaAj). ## Running on Linux Rerun should work out-of-the-box on Mac and Windows, but on Linux you need to first run: ```sh sudo apt-get -y install \ libclang-dev \ libatk-bridge2.0 \ libfontconfig1-dev \ libfreetype6-dev \ libglib2.0-dev \ libgtk-3-dev \ libssl-dev \ libxcb-render0-dev \ libxcb-shape0-dev \ libxcb-xfixes0-dev \ libxkbcommon-dev \ patchelf ``` On Fedora Rawhide you need to run: ```sh sudo dnf install \ clang \ clang-devel \ clang-tools-extra \ libxcb-devel \ libxkbcommon-devel \ openssl-devel \ pkg-config ``` [TODO(#1250)](https://github.com/rerun-io/rerun/issues/1250): Running with the wayland window manager sometimes causes Rerun to crash. Try unsetting the wayland display (`unset WAYLAND_DISPLAY` or `WAYLAND_DISPLAY= `) as a workaround. ## Running on WSL2 (Ubuntu) WSL's graphics drivers won't work out of the box and you'll have to update to a more recent version. To install the latest stable version of the mesa Vulkan drivers run: ```sh sudo add-apt-repository ppa:kisak/kisak-mesa sudo apt-get update sudo apt-get install -y mesa-vulkan-drivers ``` Since the Mesa driver on WSL dispatches to the Windows host graphics driver, it is important to keep the Windows drivers up-to-date as well. For example, [line rendering issues](https://github.com/rerun-io/rerun/issues/6749) have been observed when running from WSL with an outdated AMD driver on the Windows host. On Ubuntu 24 [issues with Wayland](https://github.com/rerun-io/rerun/issues/6748) have been observed. To mitigate this install `libxkbcommon-x11` ``` sudo apt install libxkbcommon-x11-0 ``` And unset the wayland display either by `unset WAYLAND_DISPLAY` or `WAYLAND_DISPLAY= `. ## `pip install` issues If you see the following when running `pip install rerun-sdk` or `pip install rerun-notebook` on a supported platform: ```sh ERROR: Could not find a version that satisfies the requirement rerun-sdk (from versions: none) ERROR: No matching distribution found for rerun-sdk ``` Then this is likely because you're running a version of pip that is too old. You can check the version of pip with `pip --version`. If you're running a version of pip 20 or older, you should upgrade it with `pip install --upgrade pip`. ⚠️ depending on your system configuration this may upgrade the pip installation aliased by `pip3` instead of `pip`. ## Startup issues If Rerun is having trouble starting, you can try resetting its memory with: ``` rerun reset ``` ## Graphics issues Make sure to keep your graphics drivers updated. [Wgpu](https://github.com/gfx-rs/wgpu) (the graphics API we use) maintains a list of [known driver issues](https://github.com/gfx-rs/wgpu/wiki/Known-Driver-Issues) and workarounds for them. The configuration we use for wgpu can be influenced in the following ways: - pass `--renderer=` on startup: `` must be one of `vulkan`, `metal` or `gl` for native and either `webgl` or `webgpu` for the web viewer (see also `--web-viewer` argument). Naturally, support depends on your OS. The default backend is `vulkan` everywhere except on Mac where we use `metal`. On the web we prefer WebGPU and fall back automatically to WebGL if no support for WebGPU was detected. - For instance, you can try `rerun --renderer=gl` or for the web viewer respectively `rerun --web-viewer --renderer=webgl`. - Alternatively, for the native viewer you can also use the `WGPU_BACKEND` environment variable with the above values. - The web viewer is configured by the `renderer=` url argument, e.g. [https://rerun.io/viewer?renderer=webgl] - `WGPU_POWER_PREF`: Overwrites the power setting used for choosing a graphics adapter, must be `high` or `low`. (Default is `high`) We recommend setting these only if you're asked to try them or know what you're doing, since we don't support all of these settings equally well. ### Multiple GPUs When using Wgpu's Vulkan backend (the default on Windows & Linux) on a computer that has both integrated and dedicated GPUs, a lot of issues can arise from Vulkan either picking the "wrong" GPU at runtime, or even simply from the fact that this choice conflicts with other driver picking technologies (e.g. NVIDIA Optimus). In both cases, forcing Vulkan to pick either the integrated or discrete GPU (try both!) using the [`VK_ICD_FILENAMES`](https://vulkan.lunarg.com/doc/view/latest/mac/LoaderDriverInterface.html#user-content-driver-discovery) environment variable might help with crashes, artifacts and bad performance. E.g.: - Force the Intel integrated GPU: - Linux: `export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/intel.json`. - Force the discrete Nvidia GPU: - Linux: `export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia.json`. - Windows: `set VK_ICD_FILENAMES=\windows\system32\nv-vk64.json`. ## Video stuttering On some browsers the default video decoder may cause stuttering. This has been for instance observed with Chrome 129 on Windows. To mitigate these issues, you can try to specify software decoding. This can be configured from the viewer's option menu. Alternatively, you can also override this setting on startup: * for the web viewer pass `&video_decoder=prefer_software` as a url parameter * for the native viewer & for starting the web viewer via command line (`--web-viewer` argument), pass `--video-decoder=prefer_software` TODO(#7532): Some stuttering that can't be mitigated this way has been observed with H.264 video on Linux Firefox v130.0. For more information about video decoding, see also the reference page on [video](../reference/video.md). # What is Rerun for? --- title: What is Rerun for? order: 100 --- Rerun is built to help you understand and improve complex processes that include rich multimodal data, like 2D, 3D, text, time series, tensors, etc. It is used in many industries, including robotics, simulation, computer vision, or anything that involves a lot of sensors or other signals that evolve over time. ### Example use case Say you're building a vacuum cleaning robot and it keeps running into walls. Why is it doing that? You need some tool to debug it, but a normal debugger isn't gonna be helpful. Similarly, just logging text won't be very helpful either. The robot may log "Going through doorway" but that won't explain why it thinks the wall is a door. What you need is a visual and temporal debugger, that can log all the different representations of the world the robots holds in its little head, such as: * RGB camera feed * depth images * lidar scan * segmentation image (how the robot interprets what it sees) * its 3D map of the apartment * all the objects the robot has detected (or thinks it has detected), as 3D shapes in the 3D map * its confidence in its prediction * etc You also want to see how all these streams of data evolve over time so you can go back and pinpoint exactly what went wrong, when and why. Maybe it turns out that a glare from the sun hit one of the sensors in the wrong way, confusing the segmentation network leading to bad object detection. Or maybe it was a bug in the lidar scanning code. Or maybe the robot thought it was somewhere else in the apartment, because its odometry was broken. Or it could be one of a thousand other things. Rerun will help you find out! But seeing the world from the point of the view of the robot is not just for debugging - it will also give you ideas on how to improve the algorithms, new test cases to set up, or datasets to collect. It will also let you explain the brains of the robot to your colleagues, boss, and customers. And so on. Seeing is believing, and an image is worth a thousand words, and multimodal temporal logging is worth a thousand images :) While seeing and understanding your data is core to making progress in robotics, there is one more thing: You can also use the data you collected for visualization to create new datasets for training and evaluating the models and algorithms that run on your robot. Rerun provides query APIs to make it easy to extract clean datasets from your recording for exactly that purpose. Of course, Rerun is useful for much more than just robots. Any time you have any form of sensors, or 2D or 3D state evolving over time, Rerun is a great tool. # What is Rerun? --- title: What is Rerun? order: 0 --- Rerun is building the multimodal data stack to model, ingest, store, query and view robotics-style data. It's used in areas like robotics, spatial and embodied AI, generative media, industrial processing, simulation, security, and health. ## Open source: visualization and log handling The open source project combines simple and flexible log handling with a fast, embeddable visualizer. It’s easy to get started and can be used as a stand alone library. The data model is a time aware Entity Component System (ECS), designed for domains like robotics and XR. The project includes a custom database query engine and rendering engine, both built around this model. ## Commercial: multimodal data handling at scale The commercial offering is managed infrastructure to ingest, store, analyze, and stream large amounts of robotics-style data. It's built around Rerun's open source data model to make data pipelines simple to build, and easy to operate with built-in visual debugging. It gives you a single database interface to operate on data from multiple sources, including MCAP, proprietary log-formats, LeRobot Datasets, and multimodal table formats like Lance. It's under development with select partners. [Get in touch](https://5li7zhj98k8.typeform.com/to/a5XDpBkZ) if you'd like to be one of them. ## How do you use it? 1. Use the Rerun SDK to log multimodal data from your code or load it from storage 2. View live or recorded data in the standalone viewer or embedded in your app 3. Build layouts and customize visualizations interactively in the UI or through the SDK 4. Query recordings to get clean dataframes into tools like Pandas, Polars, or DuckDB 5. Extend Rerun when you need to ## How does it work? That's a big question for a welcome page. The short answer is that Rerun goes to extreme lengths to make handling and visualizing multimodal data streams easy and performant. ## Can't find what you're looking for? - Join us in the [Rerun Community Discord](https://discord.gg/xwcxHUjD35) - Or [submit an issue](https://github.com/rerun-io/rerun/issues) in the Rerun GitHub project # C++ --- title: C++ order: 1 --- ## Setup Before adding Rerun to your application, start by [installing the viewer](../installing-viewer.md#installing-the-viewer). ## Learning by example If you prefer to learn by example, check out our example repository which uses the Rerun C++ SDK to log some data from Eigen and OpenCV: . ## Using Rerun with CMake Assuming you are starting with a bare-bones `CMakeLists.txt` such as: ```cmake cmake_minimum_required(VERSION 3.16...3.27) project(example_minimal LANGUAGES CXX) add_executable(example_minimal main.cpp) ``` You can add Rerun to your project using `FetchContent` ```cmake include(FetchContent) FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip) FetchContent_MakeAvailable(rerun_sdk) ``` This will download a bundle with pre-built Rerun C static libraries for most desktop platforms, all Rerun C++ sources and headers, as well as CMake build instructions for them. By default this will in turn download & build [Apache Arrow](https://arrow.apache.org/)'s C++ library which is required to build the Rerun C++. See [Install arrow-cpp](https://ref.rerun.io/docs/cpp/stable/md__2home_2runner_2work_2rerun_2rerun_2rerun__cpp_2arrow__cpp__install.html) to learn more about this step and how to use an existing install. Finally, make sure you link with `rerun_sdk`: ```cmake target_link_libraries(example_minimal PRIVATE rerun_sdk) ``` Combining the above, a minimal self-contained `CMakeLists.txt` looks like: ```cmake cmake_minimum_required(VERSION 3.16...3.27) project(example_minimal LANGUAGES CXX) add_executable(example_minimal main.cpp) # Download the rerun_sdk include(FetchContent) FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip) FetchContent_MakeAvailable(rerun_sdk) # Link against rerun_sdk. target_link_libraries(example_minimal PRIVATE rerun_sdk) ``` Note that Rerun requires at least C++17. Depending on the sdk will automatically ensure that C++17 or newer is enabled. ## Logging some data Add the following code to your `main.cpp` (this example also lives in the `rerun` source tree [example](https://github.com/rerun-io/rerun/blob/latest/examples/cpp/minimal/main.cpp)): ```cpp #include #include using namespace rerun::demo; int main() { // Create a new `RecordingStream` which sends data over TCP to the viewer process. const auto rec = rerun::RecordingStream("rerun_example_cpp"); // Try to spawn a new viewer instance. rec.spawn().exit_on_failure(); // Create some data using the `grid` utility function. std::vector points = grid3d(-10.f, 10.f, 10); std::vector colors = grid3d(0, 255, 10); // Log the "my_points" entity with our data, using the `Points3D` archetype. rec.log("my_points", rerun::Points3D(points).with_colors(colors).with_radii({0.5f})); } ``` ## Building and running You can configure cmake, build, and run your application like so: ```bash cmake -B build cmake --build build -j ./build/example_minimal ``` Once everything finishes compiling, the application will spawn the Rerun Viewer and send the data to it: ## Using the Viewer Try out the following to interact with the viewer: - Click and drag in the main view to rotate the cube. - Zoom in and out with the scroll wheel. - Mouse over the "?" icons to find out about more controls. - Click on the cube to select all of the points. - Hover and select individual points to see more information. If you're facing any difficulties, don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose) or [join the Discord server](https://discord.gg/PXtCgFBSmH). ## What's next If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../navigating-the-viewer.md) or our more advanced guide for [Logging Data in C++](../data-in/cpp.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. There's also a stand-alone example that shows [interop with Eigen and OpenCV](https://github.com/rerun-io/cpp-example-opencv-eigen). To learn more about how to work with your own types, check the [Custom Collection Adapter](https://github.com/rerun-io/rerun/tree/latest/examples/cpp/custom_collection_adapter) example on how to zero-copy adapt to Rerun types and the [Use custom data](../../howto/extend/custom-data.md) page for completely custom types. To learn more about how to configure the C++ SDK's CMake file, check [CMake Setup in Detail](https://ref.rerun.io/docs/cpp/stable/md__2home_2runner_2work_2rerun_2rerun_2rerun__cpp_2cmake__setup__in__detail.html). # Python --- title: Python order: 2 --- ## Installing Rerun The Rerun SDK for Python requires a working installation of [Python-3.8+](https://www.python.org/). You can install the Rerun SDK using the [rerun-sdk](https://pypi.org/project/rerun-sdk/) pypi package via pip: ```bash $ pip3 install rerun-sdk ``` You are now ready to start logging and visualizing data. ## Trying out the Viewer Rerun comes packaged with integrated examples to make it easy to explore the viewer. Launch it with: ```bash $ rerun ``` This command is automatically installed by the `rerun-sdk` Python package. When running it, you should end up with a window like below: Click on the "View Examples" button, and then on the "Helix" example. This should bring you to this screen: Try looping the recording to see the fun animation. _Note: If this is your first time launching Rerun you will see a notification in the terminal about the Rerun anonymous data usage policy. Rerun collects anonymous usage data to help improve the project, though you may choose to opt out if you would like._ ### If you're having problems - Checkout out our [troubleshooting guide](../troubleshooting.md). - [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). - Or [join the Discord server](https://discord.gg/PXtCgFBSmH). ## Using the Viewer Try out the following to interact with the viewer: - Click and drag in the main view to rotate the cube. - Zoom in and out with the scroll wheel. - Mouse over the "?" icons to find out about more controls. - Grab the time-slider and move it to see the cube at different time-points. - Click the "play" button to animate the cube. - Click on the cube to select all the points. - Hover and select individual points to see more information. This is just a taste of some of what you can do with the viewer. We will cover other functionality in much more detail later in the [Viewer Walkthrough](../navigating-the-viewer.md) ## Logging your own data After exploring a built-in example, let's create some data ourselves. We will start with an extremely simplified version of this dataset that just logs 1 dimension of points instead of 3. Create a new Python script with the following code: ```python import rerun as rr # NOTE: `rerun`, not `rerun-sdk`! import numpy as np rr.init("rerun_example_my_data", spawn=True) positions = np.zeros((10, 3)) positions[:,0] = np.linspace(-10,10,10) colors = np.zeros((10,3), dtype=np.uint8) colors[:,0] = np.linspace(0,255,10) rr.log( "my_points", rr.Points3D(positions, colors=colors, radii=0.5) ) ``` When you run this script you will again be greeted with the Rerun Viewer, this time only showing a simple line of red points. The [`rr.log`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) is the primary way to log data. It's a flexible call that can accept a variety of correctly-formatted data—including your own. The easiest way to use it is to use an instance of one of the built-in _archetype_ class, such as [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D). Archetypes take care of gathering the various components representing, in this case, a batch of 3D points such that it is recognized and correctly displayed by the Rerun viewer. The `rr.Points3D` archetype accepts any collection of positions that can be converted to a Nx3 Numpy array, along with other components such as colors, radii, etc. Feel free to modify the code to log a different set of points. For example, this code generates a more elaborate 3D colored cube: ```python import rerun as rr import numpy as np rr.init("rerun_example_my_data", spawn=True) SIZE = 10 pos_grid = np.meshgrid(*[np.linspace(-10, 10, SIZE)]*3) positions = np.vstack([d.reshape(-1) for d in pos_grid]).T col_grid = np.meshgrid(*[np.linspace(0, 255, SIZE)]*3) colors = np.vstack([c.reshape(-1) for c in col_grid]).astype(np.uint8).T rr.log( "my_points", rr.Points3D(positions, colors=colors, radii=0.5) ) ``` ## What's next If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../navigating-the-viewer.md) or our more advanced guide for [Logging Data in Python](../data-in/python.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. # Rust --- title: Rust order: 3 --- ## Setup The Rerun SDK for Rust requires a working installation of Rust 1.81+. After you have [installed the viewer](../installing-viewer.md#installing-the-viewer) you can simply add [the Rerun crate](https://crates.io/crates/rerun) to your project with `cargo add rerun`. Let's try it out in a brand new Rust project: ```bash $ cargo init cube && cd cube && cargo add rerun ``` ## Logging some data Add the following code to your `main.rs` (This example also lives in the `rerun` source tree [example](https://github.com/rerun-io/rerun/tree/latest/examples/rust/minimal/src/main.rs)) ```rust use rerun::{demo_util::grid, external::glam}; fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_minimal").spawn()?; let points = grid(glam::Vec3::splat(-10.0), glam::Vec3::splat(10.0), 10); let colors = grid(glam::Vec3::ZERO, glam::Vec3::splat(255.0), 10) .map(|v| rerun::Color::from_rgb(v.x as u8, v.y as u8, v.z as u8)); rec.log( "my_points", &rerun::Points3D::new(points) .with_colors(colors) .with_radii([0.5]), )?; Ok(()) } ``` Now run your application: ``` cargo run ``` Once everything finishes compiling, you will see the points in the Rerun Viewer: ## Using the Viewer Try out the following to interact with the viewer: - Click and drag in the main view to rotate the cube. - Zoom in and out with the scroll wheel. - Mouse over the "?" icons to find out about more controls. - Click on the cube to select all of the points. - Hover and select individual points to see more information. If you're facing any difficulties, don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose) or [join the Discord server](https://discord.gg/PXtCgFBSmH). ## What's next If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../navigating-the-viewer.md) or our more advanced guide for [Logging Data in Rust](../data-in/rust.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. # Analyze the data and send back the results --- title: Analyze the data and send back the results order: 3 redirect: getting-started/data-out/analyze-and-send hidden: true --- # Analyze the data and send back the results --- title: Analyze the data and send back the results order: 3 --- In the previous sections, we explored our data and exported it to a Pandas dataframe. In this section, we will analyze the data to extract a "jaw open state" signal and send it back to the viewer. ## Analyze the data We already identified that thresholding the `jawOpen` signal at 0.15 is all we need to produce a binary "jaw open state" signal. In the [previous section](export-dataframe.md#inspect-the-dataframe), we prepared a flat, floating point column with the signal of interest called `"jawOpen"`. Let's add a boolean column to our Pandas dataframe to hold our jaw open state: ```python df["jawOpenState"] = df["jawOpen"] > 0.15 ``` ## Send the result back to the viewer The first step is to initialize the logging SDK targeting the same recording we just analyzed. This requires matching both the application ID and recording ID precisely. By using the same identifiers, we're appending new data to an existing recording. If the recording is currently open in the viewer (and it's listening for new connections), this approach enables us to seamlessly add the new data to the ongoing session. ```python rr.init( recording.application_id(), recording_id=recording.recording_id(), ) rr.connect() ``` _Note_: When automating data analysis, it is typically preferable to log the results to an distinct RRD file next to the source RRD (using `rr.save()`). In such a situation, it is also valid to use the same app ID and recording ID. This allows opening both the source and result RRDs in the viewer, which will display data from both files under the same recording. We will send our jaw open state data in two forms: 1. As a standalone `Scalar` component, to hold the raw data. 2. As a `Text` component on the existing bounding box entity, such that we obtain a textual representation of the state in the visualization. Here is how to send the data as a scalar: ```python rr.send_columns( "/jaw_open_state", indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], columns=rr.Scalar.columns(scalar=df["jawOpenState"]), ) ``` We use the [`rr.send_column()`](../../howto/send_columns.md) API to efficiently send the entire column of data in a single batch. Next, let's send the same data as `Text` component: ```python target_entity = "/video/detector/faces/0/bbox" rr.log(target_entity, rr.Boxes2D.update_fields(show_labels=True), static=True) rr.send_columns( target_entity, indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], columns=rr.Boxes2D.columns(labels=np.where(df["jawOpenState"], "OPEN", "CLOSE")), ) ``` Here we first log the [`ShowLabel`](../../reference/types/components/show_labels.md) component as static to enable the display of the label. Then, we use `rr.send_column()` again to send an entire batch of text labels. We use [`np.where()`](https://numpy.org/doc/stable/reference/generated/numpy.where.html) to produce a label matching the state for each timestamp. ### Final result With some adjustments to the viewer blueprint, we obtain the following result: The OPEN/CLOSE label is displayed along the bounding box on the 2D view, and the `/jaw_open_state` signal is visible in both the timeseries and dataframe views. ### Complete script Here is the complete script used by this guide to load data, analyze it, and send the result back: ```python from __future__ import annotations import numpy as np import rerun as rr # ---------------------------------------------------------------------------------------------- # Load and prepare the data # load the recording recording = rr.dataframe.load_recording("face_tracking.rrd") # query the recording into a pandas dataframe record_batches = recording.view(index="frame_nr", contents="/blendshapes/0/jawOpen").select() df = record_batches.read_pandas() # convert the "jawOpen" column to a flat list of floats df["jawOpen"] = df["/blendshapes/0/jawOpen:Scalar"].explode().astype(float) # ---------------------------------------------------------------------------------------------- # Analyze the data # compute the mouth state df["jawOpenState"] = df["jawOpen"] > 0.15 # ---------------------------------------------------------------------------------------------- # Log the data back to the viewer # Connect to the viewer rr.init(recording.application_id(), recording_id=recording.recording_id()) rr.connect_tcp() # log the jaw open state signal as a scalar rr.send_columns( "/jaw_open_state", indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], columns=rr.Scalar.columns(scalar=df["jawOpenState"]), ) # log a `Label` component to the face bounding box entity target_entity = "/video/detector/faces/0/bbox" rr.log(target_entity, rr.Boxes2D.from_fields(show_labels=True), static=True) rr.send_columns( target_entity, indexes=[rr.TimeSequenceColumn("frame_nr", df["frame_nr"])], columns=rr.Boxes2D.columns(labels=np.where(df["jawOpenState"], "OPEN", "CLOSE")), ) ``` # Explore a recording with the dataframe view --- title: Explore a recording with the dataframe view order: 1 --- In this first part of the guide, we run the [face tracking example](https://rerun.io/examples/video-image/face_tracking) and explore the data in the viewer. ## Create a recording The first step is to create a recording in the viewer using the face tracking example. Check the [face tracking installation instruction](https://rerun.io/examples/video-image/face_tracking#run-the-code) for more information on how to run this example. Here is such a recording: A person's face is visible and being tracked. Their jaws occasionally open and close. In the middle of the recording, the face is also temporarily hidden and no longer tracked. ## Explore the data Amongst other things, the [MediaPipe Face Landmark](https://ai.google.dev/edge/mediapipe/solutions/vision/face_landmarker) package used by the face tracking example outputs so-called blendshapes signals, which provide information on various aspects of the face expression. These signals are logged under the `/blendshapes` root entity by the face tracking example. One signal, `jawOpen` (logged under the `/blendshapes/0/jawOpen` entity as a [`Scalar`](../../reference/types/components/scalar.md) component), is of particular interest for our purpose. Let's inspect it further using a timeseries view: This signal indeed seems to jump from approximately 0.0 to 0.5 whenever the jaws are open. We also notice a discontinuity in the middle of the recording. This is due to the blendshapes being [`Clear`](../../reference/types/archetypes/clear.md)ed when no face is detected. Let's create a dataframe view to further inspect the data: Here is how this view is configured: - Its content is set to `/blendshapes/0/jawOpen`. As a result, the table only contains columns pertaining to that entity (along with any timeline(s)). For this entity, a single column exists in the table, corresponding to entity's single component (a `Scalar`). - The `frame_nr` timeline is used as index for the table. This means that the table will contain one row for each distinct value of `frame_nr` for which data is available. - The rows can further be filtered by time range. In this case, we keep the default "infinite" boundaries, so no filtering is applied. - The dataframe view has other advanced features which we are not using here, including filtering rows based on the existence of data for a given column, or filling empty cells with latest-at data. Now, let's look at the actual data as represented in the above screenshot. At around frame #140, the jaws are open, and, accordingly, the `jawOpen` signal has values around 0.55. Shortly after, they close again and the signal decreases to below 0.1. Then, the signal becomes empty. This happens in rows corresponding to the period of time when the face cannot be tracked and all the signals are cleared. ## Next steps Our exploration of the data in the viewer so far provided us with two important pieces of information useful to implement the jaw open detector. First, we identified that the `Scalar` value contained in `/blendshapes/0/jawOpen` contains relevant data. In particular, thresholding this signal with a value of 0.15 should provide us with a closed/opened jaw state binary indicator. Then, we explored the numerical data in a dataframe view. Importantly, the way we configured this view for our needs informs us on how to query the recording from code such as to obtain the correct output. From there, our next step is to query the recording and extract the data as a Pandas dataframe in Python. This is covered in the [next section](export-dataframe.md) of this guide. # Export the dataframe --- title: Export the dataframe order: 2 --- In the [previous section](explore-as-dataframe.md), we explored some face tracking data using the dataframe view. In this section, we will see how we can use the dataframe API of the Rerun SDK to export the same data into a [Pandas](https://pandas.pydata.org) dataframe to further inspect and process it. ## Load the recording The dataframe SDK loads data from an .RRD file. The first step is thus to save the recording as RRD, which can be done from the Rerun menu: We can then load the recording in a Python script as follows: ```python import rerun as rr import numpy as np # We'll need this later. # load the recording recording = rr.dataframe.load_recording("face_tracking.rrd") ``` ## Query the data Once we loaded a recording, we can query it to extract some data. Here is how it is done: ```python # query the recording into a pandas dataframe view = recording.view( index="frame_nr", contents="/blendshapes/0/jawOpen" ) table = view.select().read_all() ``` A lot is happening here, let's go step by step: 1. We first create a _view_ into the recording. The view specifies which index column we want to use (in this case the `"frame_nr"` timeline), and which other content we want to consider (here, only the `/blendshapes/0/jawOpen` entity). The view defines a subset of all the data contained in the recording where each row has a unique value for the index, and columns are filtered based on the value(s) provided as `contents` argument. 2. A view can then be queried. Here we use the simplest possible form of querying by calling `select()`. No filtering is applied, and all view columns are selected. The result thus corresponds to the entire view. 3. The object returned by `select()` is a [`pyarrow.RecordBatchReader`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatchReader.html). This is essentially an iterator that returns the stream of [`pyarrow.RecordBatch`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatch.html#pyarrow-recordbatch)es containing the query data. 4. Finally, we use the [`pyarrow.RecordBatchReader.read_all()`](https://arrow.apache.org/docs/python/generated/pyarrow.RecordBatchReader.html#pyarrow.RecordBatchReader.read_all) function to read all record batches as a [`pyarrow.Table`](https://arrow.apache.org/docs/python/generated/pyarrow.Table.html#pyarrow.Table). **Note**: queries can be further narrowed by filtering rows and/or selecting a subset of the view columns. See the reference documentation for more information. Let's have a look at the resulting table: ```python print(table) ``` Here is the result: ``` pyarrow.Table frame_nr: int64 frame_time: timestamp[ns] log_tick: int64 log_time: timestamp[ns] /blendshapes/0/jawOpen:Scalar: list child 0, item: double ---- frame_nr: [[0],[1],...,[412],[413]] frame_time: [[1970-01-01 00:00:00.000000000],[1970-01-01 00:00:00.040000000],...,[1970-01-01 00:00:16.480000000],[1970-01-01 00:00:16.520000000]] log_tick: [[34],[92],...,[22077],[22135]] log_time: [[2024-10-13 08:26:46.819571000],[2024-10-13 08:26:46.866358000],...,[2024-10-13 08:27:01.722971000],[2024-10-13 08:27:01.757358000]] /blendshapes/0/jawOpen:Scalar: [[[0.03306490555405617]],[[0.03812221810221672]],...,[[0.06996039301156998]],[[0.07366073131561279]]] ``` Again, this is a [PyArrow](https://arrow.apache.org/docs/python/index.html) table which contains the result of our query. Further exploring Arrow structures is beyond the scope of this guide. Yet, it is a reminder that Rerun natively stores—and returns—data in arrow format. As such, it efficiently interoperates with other Arrow-native and/or compatible tools such as [Polars](https://pola.rs) or [DuckDB](https://duckdb.org). ## Create a Pandas dataframe Before exploring the data further, let's convert the table to a Pandas dataframe: ```python df = table.to_pandas() ``` Alternatively, the dataframe can be created directly, without using the intermediate PyArrow table: ```python df = view.select().read_pandas() ``` ## Inspect the dataframe Let's have a first look at this dataframe: ```python print(df) ``` Here is the result: ``` frame_nr frame_time log_tick log_time /blendshapes/0/jawOpen:Scalar 0 0 1970-01-01 00:00:00.000 34 2024-10-13 08:26:46.819571 [0.03306490555405617] 1 1 1970-01-01 00:00:00.040 92 2024-10-13 08:26:46.866358 [0.03812221810221672] 2 2 1970-01-01 00:00:00.080 150 2024-10-13 08:26:46.899699 [0.027743922546505928] 3 3 1970-01-01 00:00:00.120 208 2024-10-13 08:26:46.934704 [0.024137917906045914] 4 4 1970-01-01 00:00:00.160 266 2024-10-13 08:26:46.967762 [0.022867577150464058] .. ... ... ... ... ... 409 409 1970-01-01 00:00:16.360 21903 2024-10-13 08:27:01.619732 [0.07283800840377808] 410 410 1970-01-01 00:00:16.400 21961 2024-10-13 08:27:01.656455 [0.07037288695573807] 411 411 1970-01-01 00:00:16.440 22019 2024-10-13 08:27:01.689784 [0.07556036114692688] 412 412 1970-01-01 00:00:16.480 22077 2024-10-13 08:27:01.722971 [0.06996039301156998] 413 413 1970-01-01 00:00:16.520 22135 2024-10-13 08:27:01.757358 [0.07366073131561279] [414 rows x 5 columns] ``` We can make several observations from this output. - The first four columns are timeline columns. These are the various timelines the data is logged to in this recording. - The last columns is named `/blendshapes/0/jawOpen:Scalar`. This is what we call a _component column_, and it corresponds to the [Scalar](../../reference/types/components/scalar.md) component logged to the `/blendshapes/0/jawOpen` entity. - Each row in the `/blendshapes/0/jawOpen:Scalar` column consists of a _list_ of (typically one) scalar. This last point may come as a surprise but is a consequence of Rerun's data model where components are always stored as arrays. This enables, for example, to log an entire point cloud using the [`Points3D`](../../reference/types/archetypes/points3d.md) archetype under a single entity and at a single timestamp. Let's explore this further, recalling that, in our recording, no face was detected at around frame #170: ```python print(df["/blendshapes/0/jawOpen:Scalar"][160:180]) ``` Here is the result: ``` 160 [0.0397215373814106] 161 [0.037685077637434006] 162 [0.0402931347489357] 163 [0.04329492896795273] 164 [0.0394592322409153] 165 [0.020853394642472267] 166 [] 167 [] 168 [] 169 [] 170 [] 171 [] 172 [] 173 [] 174 [] 175 [] 176 [] 177 [] 178 [] 179 [] Name: /blendshapes/0/jawOpen:Scalar, dtype: object ``` We note that the data contains empty lists when no face is detected. When the blendshapes entities are [`Clear`](../../reference/types/archetypes/clear.md)ed, this happens for the corresponding timestamps and all further timestamps until a new value is logged. While this data representation is in general useful, a flat floating point representation with NaN for missing values is typically more convenient for scalar data. This is achieved using the [`explode()`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.explode.html) method: ```python df["jawOpen"] = df["/blendshapes/0/jawOpen:Scalar"].explode().astype(float) print(df["jawOpen"][160:180]) ``` Here is the result: ``` 160 0.039722 161 0.037685 162 0.040293 163 0.043295 164 0.039459 165 0.020853 166 NaN 167 NaN 168 NaN 169 NaN 170 NaN 171 NaN 172 NaN 173 NaN 174 NaN 175 NaN 176 NaN 177 NaN 178 NaN 179 NaN Name: jawOpen, dtype: float64 ``` This confirms that the newly created `"jawOpen"` column now contains regular, 64-bit float numbers, and missing values are represented by NaNs. _Note_: should you want to filter out the NaNs, you may use the [`dropna()`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html) method. ## Next steps With this, we are ready to analyze the data and log back the result to the Rerun viewer, which is covered in the [next section](analyze-and-log.md) of this guide. # Send from C++ --- title: Send from C++ order: 1 --- In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. There are links to other doc pages where you can learn more about specific topics. At any time, you can checkout the complete code listing for this tutorial [here](https://github.com/rerun-io/rerun/tree/latest/examples/cpp/dna/main.cpp) to better keep track of the overall picture. To build the example from the repository, run: ```bash cd examples/cpp/dna cmake -B build cmake --build build -j ``` And then to run it on Linux/Mac: ``` ./build/example_dna ``` and Windows respectively: ``` build\Debug\example_dna.exe ``` ## Prerequisites You should have already [installed the viewer](../installing-viewer.md). We assume you have a working C++ toolchain and are using `CMake` to build your project. For this example we will let Rerun download build [Apache Arrow](https://arrow.apache.org/)'s C++ library itself. To learn more about how Rerun's CMake script can be configured, see [CMake Setup in Detail](https://ref.rerun.io/docs/cpp/stable/md__2home_2runner_2work_2rerun_2rerun_2rerun__cpp_2cmake__setup__in__detail.html) in the C++ reference documentation. ## Setting up your CMakeLists.txt A minimal CMakeLists.txt for this example looks like this: ```cmake cmake_minimum_required(VERSION 3.16...3.27) project(example_dna LANGUAGES CXX) add_executable(example_dna main.cpp) # Download the rerun_sdk include(FetchContent) FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip) FetchContent_MakeAvailable(rerun_sdk) # Link against rerun_sdk. target_link_libraries(example_dna PRIVATE rerun_sdk) ``` Note that Rerun requires at least C++17. Depending on the sdk will automatically ensure that C++17 or newer is enabled. ## Includes To use Rerun all you need to include is `rerun.hpp`, however for this example we will pull in a few extra headers. Starting our `main.cpp`: ```cpp #include #include #include // std::generate #include #include using namespace rerun::demo; using namespace std::chrono_literals; static constexpr size_t NUM_POINTS = 100; ``` ## Initializing the SDK To get going we want to create a [`RecordingStream`](https://github.com/rerun-io/rerun/blob/latest/rerun_cpp/src/rerun/recording_stream.hpp), which is the main interface for sending data to Rerun. When creating the `RecordingStream` we also need to specify the name of the application we're working on by setting it's `ApplicationId`. We then use the stream to spawn a new Rerun Viewer via [`spawn`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L151). Add our initial `main` to `main.cpp`: ```cpp int main() { auto rec = rerun::RecordingStream("rerun_example_dna_abacus"); rec.spawn().exit_on_failure(); } ``` Among other things, a stable `ApplicationId` will make it so the [Rerun Viewer](../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). ## Testing our app Even though we haven't logged any data yet this is a good time to verify everything is working. ```bash cmake -B build cmake --build build -j ./build/example_dna ``` When everything finishes compiling, an empty Rerun Viewer should be spawned: ## Logging our first points Now let's add some data to the viewer. The core structure of our DNA looking shape can easily be described using two point clouds shaped like spirals. Add the following to your `main` function: ```cpp std::vector points1, points2; std::vector colors1, colors2; color_spiral(NUM_POINTS, 2.0f, 0.02f, 0.0f, 0.1f, points1, colors1); color_spiral(NUM_POINTS, 2.0f, 0.02f, TAU * 0.5f, 0.1f, points2, colors2); rec.log( "dna/structure/left", rerun::Points3D(points1).with_colors(colors1).with_radii({0.08f}) ); rec.log( "dna/structure/right", rerun::Points3D(points2).with_colors(colors2).with_radii({0.08f}) ); ``` Re-compile and run your program again: ```bash cmake --build build -j ./build/example_dna ``` and now you should now see this scene in the viewer: _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ _Checkout the [Viewer Walkthrough](../navigating-the-viewer.md) and [viewer reference](../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood This tiny snippet of code actually holds much more than meets the eye… ### Archetypes The easiest way to log geometric primitives is the use the [`RecordingStream::log`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a7badac918d44d66e04e948f38818ff11) method with one of the built-in archetype class, such as [`Points3D`](https://github.com/rerun-io/rerun/blob/latest/rerun_cpp/src/rerun/archetypes/points3d.hpp). Archetypes take care of building batches of components that are recognized and correctly displayed by the Rerun viewer. ### Components Under the hood, the Rerun C++ SDK logs individual _components_ like positions, colors, and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. For more information on how the Rerun data model works, refer to our section on [Entities and Components](../../concepts/entity-component.md). Notably, the [`RecordingStream::log`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a7badac918d44d66e04e948f38818ff11) method will handle any data type that implements the [`AsComponents`](https://github.com/rerun-io/rerun/blob/latest/rerun_cpp/src/rerun/as_components.hpp) trait, making it easy to add your own data. For more information on how to supply your own components see [Use custom data](../../howto/extend/custom-data.md). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` and `"dna/structure/right"`. These are [_entity paths_](../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. [Entity paths typically form a hierarchy](../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Component batches One final observation: notice how we're logging a whole batch of points and colors all at once here. [Component batches](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _clamping_. --- A _lot_ is happening in these two simple function calls. Good news is: once you've digested all of the above, logging any other entity will simply be more of the same. In fact, let's go ahead and log everything else in the scene now. ## Adding the missing pieces We can represent the scaffolding using a batch of 3D line segments: ```cpp std::vector lines; for (size_t i = 0; i < points1.size(); ++i) { lines.emplace_back(rerun::LineStrip3D({points1[i].xyz, points2[i].xyz})); } rec.log( "dna/structure/scaffolding", rerun::LineStrips3D(lines).with_colors(rerun::Color(128, 128, 128)) ); ``` Which only leaves the beads: ```cpp std::default_random_engine gen; std::uniform_real_distribution dist(0.0f, 1.0f); std::vector offsets(NUM_POINTS); std::generate(offsets.begin(), offsets.end(), [&] { return dist(gen); }); std::vector beads_positions(lines.size()); std::vector beads_colors(lines.size()); for (size_t i = 0; i < lines.size(); ++i) { float offset = offsets[i]; auto c = static_cast(bounce_lerp(80.0f, 230.0f, offset * 2.0f)); beads_positions[i] = rerun::Position3D( bounce_lerp(lines[i].points[0].x(), lines[i].points[1].x(), offset), bounce_lerp(lines[i].points[0].y(), lines[i].points[1].y(), offset), bounce_lerp(lines[i].points[0].z(), lines[i].points[1].z(), offset) ); beads_colors[i] = rerun::Color(c, c, c); } rec.log( "dna/structure/scaffolding/beads", rerun::Points3D(beads_positions).with_colors(beads_colors).with_radii({0.06f}) ); ``` Once again, although we are getting fancier and fancier with our iterator mappings, there is nothing new here: it's all about populating archetypes and feeding them to the Rerun API. ## Animating the beads ### Introducing time Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). Even so, if you look at your [Timeline View](../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. Unfortunately, the logging time isn't particularly helpful to us in this case: we can't have our beads animate depending on the logging time, else they would move at different speeds depending on the performance of the logging process! For that, we need to introduce our own custom timeline that uses a deterministic clock which we control. Rerun has rich support for time: whether you want concurrent or disjoint timelines, out-of-order insertions or even data that lives _outside_ the timeline(s). You will find a lot of flexibility in there. Let's add our custom timeline. Replace the section that logs the beads with a loop that logs the beads at different timestamps: ```cpp for (int t = 0; t < 400; t++) { auto time = std::chrono::duration(t) * 0.01f; rec.set_time("stable_time"); for (size_t i = 0; i < lines.size(); ++i) { float time_offset = time.count() + offsets[i]; auto c = static_cast(bounce_lerp(80.0f, 230.0f, time_offset * 2.0f)); beads_positions[i] = rerun::Position3D( bounce_lerp(lines[i].points[0].x(), lines[i].points[1].x(), time_offset), bounce_lerp(lines[i].points[0].y(), lines[i].points[1].y(), time_offset), bounce_lerp(lines[i].points[0].z(), lines[i].points[1].z(), time_offset) ); beads_colors[i] = rerun::Color(c, c, c); } rec.log( "dna/structure/scaffolding/beads", rerun::Points3D(beads_positions).with_colors(beads_colors).with_radii({0.06f}) ); } ``` First we use [`RecordingStream::set_time_seconds`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#ad735156502aea8eecd0a5eb2f6678d55) to declare our own custom `Timeline` and set the current timestamp. You can add as many timelines and timestamps as you want when logging data. ⚠️ If you run this code as is, the result will be.. surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ ![logging data - wat](https://static.rerun.io/a396c8aae1cbd717a3f35472594f789e4829b1ae_logging_data7_wat.png) Enter… ### Latest-at semantics That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, go back to the top of your main and initialize your timeline before logging the initial structure: ```cpp rec.set_time_seconds("stable_time", 0.0f); rec.log( "dna/structure/left", rerun::Points3D(points1).with_colors(colors1).with_radii({0.08f}) ); rec.log( "dna/structure/right", rerun::Points3D(points2).with_colors(colors2).with_radii({0.08f}) ); ``` This fix actually introduces yet another very important concept in Rerun: "latest-at" semantics. Notice how entities `"dna/structure/left"` & `"dna/structure/right"` have only ever been logged at time zero, and yet they are still visible when querying times far beyond that point. _Rerun always reasons in terms of "latest" data: for a given entity, it retrieves all of its most recent components at a given time._ ## Transforming space There's only one thing left: our original scene had the abacus rotate along its principal axis. As was the case with time, (hierarchical) space transformations are first class-citizens in Rerun. Now it's just a matter of combining the two: we need to log the transform of the scaffolding at each timestamp. Either expand the previous loop to include logging transforms or simply add a second loop like this: ```cpp for (int t = 0; t < 400; t++) { float time = static_cast(t) * 0.01f; rec.log( "dna/structure", rerun::archetypes::Transform3D(rerun::RotationAxisAngle( {0.0f, 0.0f, 1.0f}, rerun::Angle::radians(time.count() / 4.0f * TAU) )) ); } ``` Voila! ## Other ways of logging & visualizing data ### Saving & loading to/from RRD files Sometimes, sending the data over the network is not an option. Maybe you'd like to share the data, attach it to a bug report, etc. Rerun has you covered: - Use [`RecordingStream::save`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a555a7940a076c93d951de5b139d14918) to stream all logging data to disk. - Visualize it via `rerun path/to/recording.rrd` You can also save a recording (or a portion of it) as you're visualizing it, directly from the viewer. ⚠️ [RRD files are not yet stable across different versions!](https://github.com/rerun-io/rerun/issues/6410) ⚠️ ### Closing This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main data types. # Opening files --- title: Opening files order: 4 --- The Rerun Viewer and SDK have built-in support for opening many kinds of files, and can be extended to support any other file type without needing to modify the Rerun codebase itself. The Viewer can load files in 3 different ways: - via CLI arguments (e.g. `rerun myfile.jpeg`), - using drag-and-drop, - using the open dialog in the Rerun Viewer. All these file loading methods support loading a single file, many files at once (e.g. `rerun myfiles/*`), or even folders. ⚠ Drag-and-drop of folders does [not yet work](https://github.com/rerun-io/rerun/issues/4528) on the web version of the Rerun Viewer ⚠ The following file types have built-in support in the Rerun Viewer and SDK: - Native Rerun files: `rrd` - 3D models: `gltf`, `glb`, `obj`, `stl` - Images: `avif`, `bmp`, `dds`, `exr`, `farbfeld`, `ff`, `gif`, `hdr`, `ico`, `jpeg`, `jpg`, `pam`, `pbm`, `pgm`, `png`, `ppm`, `tga`, `tif`, `tiff`, `webp`. - Point clouds: `ply`. - Text files: `md`, `txt`. With the exception of `rrd` files that can be streamed from an HTTP URL (e.g. `rerun https://demo.rerun.io/version/latest/examples/dna/data.rrd`), we only support loading files from the local filesystem for now, with [plans to make this generic over any URI and protocol in the future](https://github.com/rerun-io/rerun/issues/4525). ## Logging file contents from the SDK To log the contents of a file from the SDK you can use the `log_file_from_path` and `log_file_from_contents` methods ([C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a8f253422a7adc2a19b89d1538c05bcac), [Python](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.log_file_from_path), [Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path)) and the associated examples ([C++](https://github.com/rerun-io/rerun/blob/main/examples/cpp/log_file/main.cpp), [Python](https://github.com/rerun-io/rerun/blob/main/examples/python/log_file/log_file.py), [Rust](https://github.com/rerun-io/rerun/blob/main/examples/rust/log_file/src/main.rs)). Note: when calling these APIs from the SDK, the data will be loaded by the process running the SDK, not the Viewer! ```python import sys import rerun as rr rr.init("rerun_example_log_file", spawn=True) rr.log_file_from_path(sys.argv[1]) ``` # Send from Python --- title: Send from Python order: 2 --- In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. There are links to other doc pages where you can learn more about specific topics. At any time, you can checkout the complete code listing for this tutorial [here](https://github.com/rerun-io/rerun/tree/latest/examples/python/dna/dna.py) to better keep track of the overall picture. ## Prerequisites We assume you have working Python and `rerun-sdk` installations. If not, check out the [setup page](../quick-start/python.md). ## Initializing the SDK Start by opening your editor of choice and creating a new file called `dna_example.py`. The first thing we need to do is to import `rerun` and initialize the SDK by calling [`rr.init`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init). This init call is required prior to using any of the global logging calls, and allows us to name our recording using an `ApplicationId`. We also import some other utilities we will use later in the example. ```python import rerun as rr from math import tau import numpy as np from rerun.utilities import build_color_spiral from rerun.utilities import bounce_lerp rr.init("rerun_example_dna_abacus") ``` Among other things, a stable [`ApplicationId`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) will make it so the [Rerun Viewer](../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). ## Starting the Viewer Next up, we want to spawn the [Rerun Viewer](../../reference/viewer/overview.md) itself. To do this, you can add the line: ```python rr.spawn() ``` Now you can run your application just as you would any other Python script: ``` (venv) $ python dna_example.py ``` And with that, we're ready to start sending out data: By default, the SDK will start a Viewer in another process and automatically pipe the data through. There are other means of sending data to a Viewer as we'll see at the end of this section, but for now this default will work great as we experiment. ## Logging our first points The core structure of our DNA looking shape can easily be described using two point clouds shaped like spirals. Add the following to your file: ```python NUM_POINTS = 100 # Points and colors are both np.array((NUM_POINTS, 3)) points1, colors1 = build_color_spiral(NUM_POINTS) points2, colors2 = build_color_spiral(NUM_POINTS, angular_offset=tau*0.5) rr.log("dna/structure/left", rr.Points3D(points1, colors=colors1, radii=0.08)) rr.log("dna/structure/right", rr.Points3D(points2, colors=colors2, radii=0.08)) ``` Run your script once again and you should now see this scene in the viewer. Note that if the Viewer was still running, Rerun will simply connect to this existing session and replace the data with this new [_recording_](../../concepts/apps-and-recordings.md). _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ _Checkout the [Viewer Walkthrough](../navigating-the-viewer.md) and [viewer reference](../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood This tiny snippet of code actually holds much more than meets the eye… ### Archetypes The easiest way to log geometric primitives is the use the [`rr.log`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) function with one of the built-in archetype class, such as [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D). Archetypes take care of building batches of components that are recognized and correctly displayed by the Rerun viewer. ### Components Under the hood, the Rerun [Python SDK](https://ref.rerun.io/docs/python) logs individual _components_ like positions, colors, and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. For more information on how the Rerun data model works, refer to our section on [Entities and Components](../../concepts/entity-component.md). Our [Python SDK](https://ref.rerun.io/docs/python) integrates with the rest of the Python ecosystem: the points and colors returned by [`build_color_spiral`](https://ref.rerun.io/docs/python/stable/common/demo_utilities/#rerun.utilities.data.build_color_spiral) in this example are vanilla `numpy` arrays. Rerun takes care of mapping those arrays to actual Rerun components depending on the context (e.g. we're calling [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D) in this case). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` & `"dna/structure/right"`. These are [_entity paths_](../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. [Entity paths typically form a hierarchy](../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Component batches One final observation: notice how we're logging a whole batch of points and colors all at once here. [Component batches](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _clamping_. --- A _lot_ is happening in these two simple function calls. Good news is: once you've digested all of the above, logging any other entity will simply be more of the same. In fact, let's go ahead and log everything else in the scene now. ## Adding the missing pieces We can represent the scaffolding using a batch of 3D line strips: ```python rr.log( "dna/structure/scaffolding", rr.LineStrips3D(np.stack((points1, points2), axis=1), colors=[128, 128, 128]) ) ``` Which only leaves the beads: ```python offsets = np.random.rand(NUM_POINTS) beads = [bounce_lerp(points1[n], points2[n], offsets[n]) for n in range(NUM_POINTS)] colors = [[int(bounce_lerp(80, 230, offsets[n] * 2))] for n in range(NUM_POINTS)] rr.log( "dna/structure/scaffolding/beads", rr.Points3D(beads, radii=0.06, colors=np.repeat(colors, 3, axis=-1)), ) ``` Once again, although we are getting fancier and fancier with our [`numpy` incantations](https://ref.rerun.io/docs/python/stable/common/demo_utilities/#rerun.utilities.util.bounce_lerp), there is nothing new here: it's all about building out `numpy` arrays and feeding them to the Rerun API. ## Animating the beads ### Introducing time Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). Even so, if you look at your [Timeline View](../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. Unfortunately, the logging time isn't particularly helpful to us in this case: we can't have our beads animate depending on the logging time, else they would move at different speeds depending on the performance of the logging process! For that, we need to introduce our own custom timeline that uses a deterministic clock which we control. Rerun has rich support for time: whether you want concurrent or disjoint timelines, out-of-order insertions or even data that lives _outside_ the timeline(s). You will find a lot of flexibility in there. Let's add our custom timeline: ```python time_offsets = np.random.rand(NUM_POINTS) for i in range(400): time = i * 0.01 rr.set_time_seconds("stable_time", time) times = np.repeat(time, NUM_POINTS) + time_offsets beads = [bounce_lerp(points1[n], points2[n], times[n]) for n in range(NUM_POINTS)] colors = [[int(bounce_lerp(80, 230, times[n] * 2))] for n in range(NUM_POINTS)] rr.log( "dna/structure/scaffolding/beads", rr.Points3D(beads, radii=0.06, colors=np.repeat(colors, 3, axis=-1)), ) ``` A call to [`set_time_seconds`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_seconds) will create our new `Timeline` and make sure that any logging calls that follow gets assigned that time. ⚠️ If you run this code as is, the result will be… surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ Enter… ### Latest-at semantics That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, go back to the top of the file and add: ```python rr.spawn() rr.set_time_seconds("stable_time", 0) ``` This fix actually introduces yet another very important concept in Rerun: "latest-at" semantics. Notice how entities `"dna/structure/left"` & `"dna/structure/right"` have only ever been logged at time zero, and yet they are still visible when querying times far beyond that point. _Rerun always reasons in terms of "latest" data: for a given entity, it retrieves all of its most recent components at a given time._ ## Transforming space There's only one thing left: our original scene had the abacus rotate along its principal axis. As was the case with time, (hierarchical) space transformations are first class-citizens in Rerun. Now it's just a matter of combining the two: we need to log the transform of the scaffolding at each timestamp. Either expand the previous loop to include logging transforms or simply add a second loop like this: ```python for i in range(400): time = i * 0.01 rr.set_time_seconds("stable_time", time) rr.log( "dna/structure", rr.Transform3D(rotation=rr.RotationAxisAngle(axis=[0, 0, 1], radians=time / 4.0 * tau)), ) ``` Voila! ## Other ways of logging & visualizing data [`rr.spawn`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.spawn) is great when you're experimenting on a single machine like we did in this tutorial, but what if the logging happens on, for example, a headless computer? Rerun offers several solutions for such use cases. ### Logging data over the network At any time, you can start a Rerun Viewer by running `rerun`. This Viewer is in fact a server that's ready to accept data over TCP (it's listening on `0.0.0.0:9876` by default). On the logger side, simply use [`rr.connect`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.connect) instead of [`rr.spawn`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.spawn) to start sending the data over to any TCP address. Checkout `rerun --help` for more options. ### Saving & loading to/from RRD files Sometimes, sending the data over the network is not an option. Maybe you'd like to share the data, attach it to a bug report, etc. Rerun has you covered: - Use [`rr.save`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.save) to stream all logged data to disk. - View it with `rerun path/to/recording.rrd` You can also save a recording (or a portion of it) as you're visualizing it, directly from the viewer. ⚠️ [RRD files are not yet stable across different versions!](https://github.com/rerun-io/rerun/issues/6410) ⚠️ ## Closing This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. # Send from Rust --- title: Send from Rust order: 3 --- In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. There are links to other doc pages where you can learn more about specific topics. At any time, you can checkout the complete code listing for this tutorial [here](https://github.com/rerun-io/rerun/tree/latest/examples/rust/dna/src/main.rs) to better keep track of the overall picture. To run the example from the repository, run `cargo run -p dna`. ## Prerequisites We assume you have a working Rust environment and have started a new project with the `rerun` dependency. If not, check out the [setup page](rust.md). For this example in particular, we're going to need all of these: ```toml [dependencies] rerun = "0.9" itertools = "0.11" rand = "0.8" ``` While we're at it, let's get imports out of the way: ```rust use std::f32::consts::TAU; use itertools::Itertools as _; use rerun::{ demo_util::{bounce_lerp, color_spiral}, external::glam, }; ``` ## Starting the Viewer Just run `rerun` to start the [Rerun Viewer](../../reference/viewer/overview.md). It will wait for your application to log some data to it. This Viewer is in fact a server that's ready to accept data over TCP (it's listening on `0.0.0.0:9876` by default). Checkout `rerun --help` for more options. ## Initializing the SDK To get going we want to create a [`RecordingStream`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html): We can do all of this with the [`rerun::RecordingStreamBuilder::new`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.new) function which allows us to name the dataset we're working on by setting its [`ApplicationId`](https://docs.rs/rerun/latest/rerun/struct.ApplicationId.html). We then connect it to the already running Viewer via [`connect_tcp`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.connect_tcp), returning the `RecordingStream` upon success. ```rust fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_dna_abacus") .connect_tcp()?; Ok(()) } ``` Among other things, a stable [`ApplicationId`](https://docs.rs/rerun/latest/rerun/struct.ApplicationId.html) will make it so the [Rerun Viewer](../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). ## Logging our first points The core structure of our DNA looking shape can easily be described using two point clouds shaped like spirals. Add the following to your `main` function: ```rust const NUM_POINTS: usize = 100; let (points1, colors1) = color_spiral(NUM_POINTS, 2.0, 0.02, 0.0, 0.1); let (points2, colors2) = color_spiral(NUM_POINTS, 2.0, 0.02, TAU * 0.5, 0.1); rec.log( "dna/structure/left", &rerun::Points3D::new(points1.iter().copied()) .with_colors(colors1) .with_radii([0.08]), )?; rec.log( "dna/structure/right", &rerun::Points3D::new(points2.iter().copied()) .with_colors(colors2) .with_radii([0.08]), )?; ``` Run your program with `cargo run` and you should now see this scene in the viewer: _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ _Checkout the [Viewer Walkthrough](../navigating-the-viewer.md) and [viewer reference](../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood This tiny snippet of code actually holds much more than meets the eye… ### Archetypes The easiest way to log geometric primitives is the use the [`RecordingStream::log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log) method with one of the built-in archetype class, such as [`Points3D`](https://docs.rs/rerun/latest/0.9.0-alpha.10/struct.Points3D.html). Archetypes take care of building batches of components that are recognized and correctly displayed by the Rerun viewer. ### Components Under the hood, the Rerun [Rust SDK](https://ref.rerun.io/docs/rust) logs individual _components_ like positions, colors, and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. For more information on how the Rerun data model works, refer to our section on [Entities and Components](../../concepts/entity-component.md). Notably, the [`RecordingStream::log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log) method will handle any data type that implements the [`AsComponents`](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html) trait, making it easy to add your own data. For more information on how to supply your own components see [Use custom data](../../howto/extend/custom-data.md). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` and `"dna/structure/right"`. These are [_entity paths_](../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. [Entity paths typically form a hierarchy](../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Component batches One final observation: notice how we're logging a whole batch of points and colors all at once here. [Component batches](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _clamping_. --- A _lot_ is happening in these two simple function calls. Good news is: once you've digested all of the above, logging any other entity will simply be more of the same. In fact, let's go ahead and log everything else in the scene now. ## Adding the missing pieces We can represent the scaffolding using a batch of 3D line segments: ```rust let points_interleaved: Vec<[glam::Vec3; 2]> = points1 .into_iter() .interleave(points2) .chunks(2) .into_iter() .map(|chunk| chunk.into_iter().collect_vec().try_into().unwrap()) .collect_vec(); rec.log( "dna/structure/scaffolding", &rerun::LineStrips3D::new(points_interleaved.iter().cloned()) .with_colors([rerun::Color::from([128, 128, 128, 255])]), )?; ``` Which only leaves the beads: ```rust use rand::Rng as _; let mut rng = rand::thread_rng(); let offsets = (0..NUM_POINTS).map(|_| rng.gen::()).collect_vec(); let (beads, colors): (Vec<_>, Vec<_>) = points_interleaved .iter() .enumerate() .map(|(n, &[p1, p2])| { let c = bounce_lerp(80.0, 230.0, times[n] * 2.0) as u8; ( rerun::Position3D::from(bounce_lerp(p1, p2, times[n])), rerun::Color::from_rgb(c, c, c), ) }) .unzip(); rec.log( "dna/structure/scaffolding/beads", &rerun::Points3D::new(beads) .with_colors(colors) .with_radii([0.06]), )?; ``` Once again, although we are getting fancier and fancier with our iterator mappings, there is nothing new here: it's all about populating archetypes and feeding them to the Rerun API. ## Animating the beads ### Introducing time Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). Even so, if you look at your [Timeline View](../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. Unfortunately, the logging time isn't particularly helpful to us in this case: we can't have our beads animate depending on the logging time, else they would move at different speeds depending on the performance of the logging process! For that, we need to introduce our own custom timeline that uses a deterministic clock which we control. Rerun has rich support for time: whether you want concurrent or disjoint timelines, out-of-order insertions or even data that lives _outside_ the timeline(s). You will find a lot of flexibility in there. Let's add our custom timeline: ```rust for i in 0..400 { let time = i as f32 * 0.01; rec.set_time_seconds("stable_time", time as f64); let times = offsets.iter().map(|offset| time + offset).collect_vec(); let (beads, colors): (Vec<_>, Vec<_>) = points_interleaved .iter() .enumerate() .map(|(n, &[p1, p2])| { let c = bounce_lerp(80.0, 230.0, times[n] * 2.0) as u8; ( rerun::Position3D::from(bounce_lerp(p1, p2, times[n])), rerun::Color::from_rgb(c, c, c), ) }) .unzip(); rec.log( "dna/structure/scaffolding/beads", &rerun::Points3D::new(beads) .with_colors(colors) .with_radii([0.06]), )?; } ``` First we use [`RecordingStream::set_time_seconds`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.set_time_seconds) to declare our own custom `Timeline` and set the current timestamp. You can add as many timelines and timestamps as you want when logging data. ⚠️ If you run this code as is, the result will be.. surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ ![logging data - wat](https://static.rerun.io/a396c8aae1cbd717a3f35472594f789e4829b1ae_logging_data7_wat.png) Enter… ### Latest-at semantics That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, add this at the beginning of the main function: ```rust rec.set_time_seconds("stable_time", 0f64); ``` This fix actually introduces yet another very important concept in Rerun: "latest-at" semantics. Notice how entities `"dna/structure/left"` & `"dna/structure/right"` have only ever been logged at time zero, and yet they are still visible when querying times far beyond that point. _Rerun always reasons in terms of "latest" data: for a given entity, it retrieves all of its most recent components at a given time._ ## Transforming space There's only one thing left: our original scene had the abacus rotate along its principal axis. As was the case with time, (hierarchical) space transformations are first class-citizens in Rerun. Now it's just a matter of combining the two: we need to log the transform of the scaffolding at each timestamp. Either expand the previous loop to include logging transforms or simply add a second loop like this: ```rust for i in 0..400 { // …everything else… rec.log( "dna/structure", &rerun::archetypes::Transform3D::from_rotation(rerun::RotationAxisAngle::new( glam::Vec3::Z, rerun::Angle::Radians(time / 4.0 * TAU), )), )?; } ``` Voila! ## Other ways of logging & visualizing data ### Saving & loading to/from RRD files Sometimes, sending the data over the network is not an option. Maybe you'd like to share the data, attach it to a bug report, etc. Rerun has you covered: - Use [`RecordingStream::save`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.save) to stream all logging data to disk. - Visualize it via `rerun path/to/recording.rrd` You can also save a recording (or a portion of it) as you're visualizing it, directly from the viewer. ⚠️ [RRD files are not yet stable across different versions!](https://github.com/rerun-io/rerun/issues/6410) ⚠️ ### Spawning the Viewer from your process If the Rerun Viewer is [installed](../installing-viewer.md) and available in your `PATH`, you can use [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) to automatically start a Viewer in a new process and connect to it over TCP. If an external Viewer was already running, `spawn` will connect to that one instead of spawning a new one. ```rust fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_dna_abacus") .spawn()?; // … log data to `rec` … Ok(()) } ``` Alternatively, you can use [`rerun::native_viewer::show`](https://docs.rs/rerun/latest/rerun/native_viewer/fn.show.html) to start a Viewer on the main thread (for platform-compatibility reasons) and feed it data from memory. This requires the `native_viewer` feature to be enabled in `Cargo.toml`: ```toml rerun = { version = "0.9", features = ["native_viewer"] } ``` Doing so means you're building the Rerun Viewer itself as part of your project, meaning compilation will take a bit longer the first time. Unlike `spawn` however, this expects a complete recording instead of being fed in real-time: ```rust let (rec, storage) = rerun::RecordingStreamBuilder::new("rerun_example_dna_abacus").memory()?; // … log data to `rec` … rerun::native_viewer::show(storage.take())?; ``` The Viewer will block the main thread until it is closed. ### Closing This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main data types. # Configure the Viewer interactively --- title: Configure the Viewer interactively order: 1 --- The Rerun Viewer is configurable directly through the UI itself. ## Viewer overview The central part is known as the viewport and contains the various views displaying the data. The left panel of the Viewer is the "Blueprint Panel". It shows a visual tree view representing the contents of the current blueprint. The right panel of the Viewer is the "Selection Panel" this panel allows you to configure specific blueprint properties of the currently selected element. The blueprint defines the structure, the type of views, and their content in the viewport. Changing the content of the viewport is done by editing the blueprint. After editing the Viewer you may want to [save or share the blueprint](./save-and-load.md). ## Configuring the view hierarchy The viewport is made of various views, laid out hierarchically with nested containers of various kinds: vertical, horizontal, grid, and tabs. This hierarchy is represented in the blueprint panel, with the top container corresponding to the viewport. In this section, we cover the various ways this view hierarchy can be interactively created and modified. ### Show or hide parts of the blueprint Any container or view can be hidden or shown by clicking the "eye" icon. ### Add new containers or views Adding a container or a view to the view port can be done by clicking the "+" at the top of the blueprint panel. If a container (or the viewport) is already selected, a "+" button will also be available in the selection panel. ### Remove a view or container Removing a view or a container can be done by clicking the "-" button next to it: ### Re-arrange existing containers or views The viewport hierarchy can be reorganized by drag-and-dropping containers or views in the blueprint panel. It ssi also possible to drag views directly in the viewport by using their title tab: ### Rename a view or container Both views and containers may be assigned a custom name. This can be done by selecting the view or container, and editing the name at the top of the selection panel. ### Change a container kind Containers come in four different kinds: vertical, horizontal, grid, and tabs. To change an existing container's kind, select it and change the value from the dropdown menu in the selection panel: ### Using context menus The context menu is accessed by right-clicking on a container or view in the blueprint panel. Many of the previous operations are also available there: One key advantage of using the context menu is that it enable operations on multiple items at once. For example, you may select several views (ctrl-click, or cmd-click on Mac), and remove them all in a single operation using the context menu. ## Configuring the content of a view The content of a view is determined by its entity query, which can be manually edited in the selection panel when the view is selected (see [Entity Queries](../../reference/entity-queries.md) for more information). This section covers the interactive means of manipulating the view content (which typically operate by actually modifying the query). ### Show or hide view content Like containers and views, any entity in a view may be shown and hidden with the "eye" icon or the context menu. ### Remove data from a view Likewise, entities may be removed from a view by clicking the "-" next to it: ### Using the query editor A visual query editor is available from the selection panel when a view is selected. Click the "Edit" button next to the entity query: The query editor allows visually adding and removing entities and entity trees from the query. ### Adding entities to a new view with context menu Like with viewport hierarchy, most operations on view data are available from the context menu. In particular, a new view can be created with custom content by selecting one or more entities (either in existing views in the blueprint panel, or in the time panel's streams), and clicking "Add to new view" in the context menu: When using one of the recommended views with this method, the view's origin will automatically be set to a sensible default based on the actual data. ### Overriding visualizers and component values By selecting an entity from a view, it is possible to specify which visualizer(s) should be enabled, and to override values of specific components: When selecting a view, it is also possible to specify default values for components of a given type, which is used when no value has been logged: See [Visualizers and Overrides](../../concepts/visualizers-and-overrides.md) for detailed information and more examples. # Save and load Viewer configuration files --- title: Save and load Viewer configuration files order: 2 --- If you have made changes to the Viewer and you would like to save or share them, you can do so by saving your blueprint to an `.rbl` file. ## Saving a blueprint To save the currently active blueprint, go to the file-menu and choose "Save blueprint…" ## Loading a blueprint Once you have saved a blueprint, you can later load it in the viewer. The "Open…" menu item is used to load either recordings (`.rrd`) or blueprints (`.rbl`). Alternatively, you can drag an `.rbl` file directly into the viewer. Note that the application ID of the blueprint must match the application ID of the recording you wish to use it with. It is not currently possible to change the application ID of a blueprint to use it with a different type of recording. # Configure the Viewer through code --- title: Configure the Viewer through code order: 3 --- This tutorial will walk you through using the [Blueprint APIs](../../howto/configure-viewer-through-code.md) to better control the layout and appearance of your data in the Rerun Viewer in Python. This walkthrough is based on the [stock charts](https://github.com/rerun-io/rerun/tree/main/examples/python/blueprint_stocks) example. The main differences between this tutorial and the linked example are related to additional processing of command-line flags, which are omitted here for simplicity. All of the examples in this tutorial use the exact same data. However, by changing the blueprint using small statements such as: ```python rrb.Blueprint( rrb.Vertical( rrb.TextDocumentView(name="Info", origin="/stocks/AAPL/info"), rrb.TimeSeriesView(name="Chart", origin="/stocks/AAPL"), row_shares=[1, 4], ) ) ``` we will completely change the way the data is presented. ## Create an environment for the example We start by creating a new virtual environment and installing the Rerun SDK along with the dependencies we will use in this example. On Linux or Mac: ```bash mkdir stocks_example cd stocks_example python -m venv venv source venv/bin/activate pip install rerun-sdk humanize yfinance ``` On windows: ```bash mkdir stocks_example cd stocks_example python -m venv venv .\venv\Scripts\activate pip install rerun-sdk humanize yfinance ``` ## Create your script In your project folder, add a new file, `stocks.py`. First, we import the necessary libraries: ```python #!/usr/bin/env python3 import datetime as dt import humanize import pytz import yfinance as yf from typing import Any import rerun as rr import rerun.blueprint as rrb ``` Next, we create some helper functions for style data and a template for an info card: ```python brand_colors = { "AAPL": 0xA2AAADFF, "AMZN": 0xFF9900FF, "GOOGL": 0x34A853FF, "META": 0x0081FBFF, "MSFT": 0xF14F21FF, } def style_plot(symbol: str) -> rr.SeriesLine: return rr.SeriesLine( color=brand_colors[symbol], name=symbol, ) def style_peak(symbol: str) -> rr.SeriesPoint: return rr.SeriesPoint( color=0xFF0000FF, name=f"{symbol} (peak)", marker="Up", ) def info_card( shortName: str, industry: str, marketCap: int, totalRevenue: int, **args: dict[str, Any], ) -> rr.TextDocument: markdown = f""" - **Name**: {shortName} - **Industry**: {industry} - **Market cap**: ${humanize.intword(marketCap)} - **Total Revenue**: ${humanize.intword(totalRevenue)} """ return rr.TextDocument(markdown, media_type=rr.MediaType.MARKDOWN) ``` And finally, we create our main function that queries and logs the data: ```python def main() -> None: symbols = ["AAPL", "AMZN", "GOOGL", "META", "MSFT"] # Use eastern time for market hours et_timezone = pytz.timezone("America/New_York") start_date = dt.date(2024, 3, 18) dates = [start_date + dt.timedelta(days=i) for i in range(5)] # Initialize Rerun and spawn a new viewer rr.init("rerun_example_blueprint_stocks", spawn=True) # This is where we will edit the blueprint blueprint = None #rr.send_blueprint(blueprint) # Log the stock data for each symbol and date for symbol in symbols: stock = yf.Ticker(symbol) # Log the stock info document as static rr.log(f"stocks/{symbol}/info", info_card(**stock.info), static=True) for day in dates: # Log the styling data as static rr.log(f"stocks/{symbol}/{day}", style_plot(symbol), static=True) rr.log(f"stocks/{symbol}/peaks/{day}", style_peak(symbol), static=True) # Query the stock data during market hours open_time = dt.datetime.combine(day, dt.time(9, 30), et_timezone) close_time = dt.datetime.combine(day, dt.time(16, 00), et_timezone) hist = stock.history(start=open_time, end=close_time, interval="5m") # Offset the index to be in seconds since the market open hist.index = hist.index - open_time peak = hist.High.idxmax() # Log the stock state over the course of the day for row in hist.itertuples(): rr.set_time_seconds("time", row.Index.total_seconds()) rr.log(f"stocks/{symbol}/{day}", rr.Scalar(row.High)) if row.Index == peak: rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalar(row.High)) if __name__ == "__main__": main() ``` ## Run your script You can now run the script and view the results in the Rerun Viewer: ```bash python stocks.py ``` You should see the application launch and display the stock data, but you will also notice the layout is far from ideal: ## Create a blueprint To improve the layout, we will now use the blueprint APIs to create some custom layouts. All we need to do is modify the section of the code that currently reads: ```python # This is where we will edit the blueprint blueprint = None #rr.send_blueprint(blueprint) ``` ### Create a view for an origin Replace these lines with the following: ```python # Create a single chart for all the AAPL data: blueprint = rrb.Blueprint( rrb.TimeSeriesView(name="AAPL", origin="/stocks/AAPL"), ) rr.send_blueprint(blueprint) ``` This blueprint uses the `origin` parameter to scope the view to just a portion of the entity tree. If you run the script again, you should see a single chart for the AAPL data: ### Control the default panel state In addition to controlling the data, you can also control the default state of the blueprint, selection, and time panels. Let's modify the code again to include additional blueprint specifications for these: ```python # Create a single chart for all the AAPL data, and collapse the selection and time panels: blueprint = rrb.Blueprint( rrb.TimeSeriesView(name="AAPL", origin="/stocks/AAPL"), rrb.BlueprintPanel(state="expanded"), rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ) rr.send_blueprint(blueprint) ``` This time when you run the script, you will now see the panels start off collapsed, giving you a more focused view of your data: ### Combining multiple views When using blueprints, you don't have to limit yourself to a single view. You can create multiple views and use containers to combine them. Let's modify the code to include the info card as well. We will use the `Vertical` container and the `row_shares` parameter to control the relative size of the views: ```python # Create a vertical layout of an info document and a time series chart blueprint = rrb.Blueprint( rrb.Vertical( rrb.TextDocumentView(name="Info", origin="/stocks/AAPL/info"), rrb.TimeSeriesView(name="Chart", origin="/stocks/AAPL"), row_shares=[1, 4], ), rrb.BlueprintPanel(state="expanded"), rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ) rr.send_blueprint(blueprint) ``` Running the script now produces two views stacked vertically: ### Including specific contents Specifying the `origin` of a view is convenient, but sometimes you need more control. In this case, you can specify the `contents` of a view by providing multiple content expressions. For example, we can create a stock that includes data from both META and MSFT for a single day on the same chart. Using `origin` alone there is no way we could have expressed this: ```python # Create a view with two stock time series blueprint = rrb.Blueprint( rrb.TimeSeriesView( name="META vs MSFT", contents=[ "+ /stocks/META/2024-03-19", "+ /stocks/MSFT/2024-03-19", ], ), rrb.BlueprintPanel(state="expanded"), rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ) rr.send_blueprint(blueprint) ``` Running the script now produces a chart that combines data from multiple sources: ### More complex filtering Just specifying single path inclusions can also be challenging when dealing datasets that include large subtrees. Filter expressions can be used to include or exclude data based on a path pattern. This pattern can optionally start with `$origin` to refer to the origin of the given space, and can end with the wildcard `/**` to include or exclude an entire subtree, Going back to our single stock example, we can filter out the peaks data by excluding the `peaks` subtree: ```python # Create a single chart for all the AAPL data and filter out the peaks: blueprint = rrb.Blueprint( rrb.TimeSeriesView( name="AAPL", origin="/stocks/AAPL", contents=[ "+ $origin/**", "- $origin/peaks/**", ], ), rrb.BlueprintPanel(state="expanded"), rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ) rr.send_blueprint(blueprint) ``` When you run the script you will see that the data from the peaks subtree is no longer part of the view: ### Programmatic layouts Since these layouts are created by executing Python code, they can also be generated programmatically. For example, we can create a create a separate view for every piece of data we were interested in. Setting this up by hand would be extremely tedious. ```python # Iterate over all the symbols and days to log the stock data in a grid blueprint = rrb.Blueprint( rrb.Vertical( contents=[ rrb.Horizontal( contents=[ rrb.TextDocumentView( name=f"{symbol}", origin=f"/stocks/{symbol}/info", ), ] + [ rrb.TimeSeriesView( name=f"{day}", origin=f"/stocks/{symbol}/{day}", ) for day in dates ], name=symbol, ) for symbol in symbols ] ), rrb.BlueprintPanel(state="expanded"), rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ) rr.send_blueprint(blueprint) ``` Running the script again this final chart is a significant improvement over the original heuristic-based layout: ### Visualizers and overrides Since release 0.17, even deeper configurations from code are possible. This includes overriding component values for a given view entity, specifying default values for components for a given view, and controlling which visualizer(s) are used per view entity. See [Visualizers and Overrides](../../concepts/visualizers-and-overrides.md) for more information and code examples. # Architecture --- title: Architecture order: 50 redirect: https://github.com/rerun-io/rerun/blob/main/ARCHITECTURE.md --- # Code of Conduct --- title: Code of Conduct order: 100 redirect: https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md --- # Contributing --- title: Contributing order: 200 redirect: https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md --- # Roadmap --- title: Roadmap order: 0 --- Rerun is building a data management and visualization engine for multimodal data that changes over time. We aim to make it fast, and easy to use, and easy to adapt and integrate into your existing workflows. Open an issue or pull request on [GitHub](https://github.com/rerun-io/rerun) or join us on [Discord](https://discord.gg/PXtCgFBSmH) to let the community know what you'd like to see. This page is meant to give an high level overview of ongoing and planned work. ## We continually work on - Performance improvements - UX & DX improvements - Supporting more data types ## Roadmap of major feature areas ### Near term: Q4 2024 - Video streaming: sending individual video encoded frames at a time - Improved support for working directly with Arrow data and the Rerun extension types ### Medium term (Q1 2025) - Official ROS2 bridge - Callbacks and the ability to build interactive applications with Rerun - For example: UI for tweaking configs, custom data annotation tools, etc - Rerun data platform alpha (commercial) - Get in touch on hi@rerun.io if you're interested in becoming a design partner ### Longer term - Extensibility of all parts of the stack - Data format stability # Annotation Context --- title: Annotation Context order: 800 --- ## Overview Any visualization that assigns an identifier ("Class ID") to an instance or entity can benefit from using Annotations. By using an Annotation Context, you can associate labels and colors with a given class and then re-use that class across entities. This is particularly useful for visualizing the output of classifications algorithms (as demonstrated by the [Detect and Track Objects](https://github.com/rerun-io/rerun/tree/main/examples/python/detect_and_track_objects) example), but can be used more generally for any kind of reoccurring categorization within a Rerun recording. ### Keypoints & keypoint connections Rerun allows you to define keypoints *within* a class. Each keypoint can define its own properties (colors, labels, etc.) that overwrite its parent class. A typical example usage of keypoints is annotating the joints of a skeleton within a pose detection. In that case, the entire detected pose/skeleton is assigned a Class ID and each joint within gets a Keypoint ID. To help you more with this (and similar) use-case(s), you can also define connections between keypoints as part of your annotation class description. The Viewer will draw the connecting lines for all connected keypoints whenever that class is used. Just as with labels and colors this allows you to use the same connection information on any instance that class in your scene. Keypoints are currently only applicable to 2D and 3D points. ### Logging an annotation context Annotation Context is typically logged as [static](timelines.md#static-data) data, but can change over time if needed. The Annotation Context is defined as a list of Class Descriptions that define how classes are styled (as well as optional keypoint style and connection). Annotation contexts are logged with: * Python: 🐍[`rr.AnnotationContext`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.AnnotationContext) * Rust: 🦀[`rerun::AnnotationContext`](https://docs.rs/rerun/latest/rerun/archetypes/struct.AnnotationContext.html#) ```python import rerun as rr rr.init("rerun_example_annotation_context_connections") # Annotation context with two classes, using two labeled classes, of which ones defines a color. rr.log( "masks", # Applies to all entities below "masks". rr.AnnotationContext( [ rr.AnnotationInfo(id=0, label="Background"), rr.AnnotationInfo(id=1, label="Person", color=(255, 0, 0)), ], ), static=True, ) # Annotation context with simple keypoints & keypoint connections. rr.log( "detections", # Applies to all entities below "detections". rr.ClassDescription( info=rr.AnnotationInfo(0, label="Snake"), keypoint_annotations=[rr.AnnotationInfo(id=i, color=(0, 28 * i, 0)) for i in range(10)], keypoint_connections=[(i, i + 1) for i in range(9)], ), static=True, ) ``` ## Affected entities Each entity that uses a Class ID component (and optionally Keypoint ID components) will look for the nearest ancestor that in the [entity path hierarchy](entity-path.md#path-hierarchy-functions) that has an Annotation Context defined. ## Segmentation images Segmentation images are single channel integer images/tensors where each pixel represents a class id. By default, Rerun will automatically assign colors to each class id, but by defining an Annotation Context, you can explicitly determine the color of each class. * Python: [`rr.SegmentationImage`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.SegmentationImage) * Rust: Log a [`rerun::SegmentationImage`](https://docs.rs/rerun/latest/rerun/archetypes/struct.SegmentationImage.html) # Application model --- title: Application model order: 0 --- The Rerun distribution comes with numerous moving pieces: * The **SDKs** (Python, Rust & C++), for logging data and querying it back. These are libraries running directly in the end user's process. * The **Native Viewer**: the Rerun GUI application for native platforms (Linux, macOS, Windows). * The **TCP server**, which receives data from the **SDKs** and forwards it to the **Native Viewer** and/or **WebSocket Server**. The communication is unidirectional: clients push data into the TCP connection, never the other way around. * The **Web Viewer**, which packs the **Native Viewer** into a WASM application that can run on the Web and its derivatives (notebooks, etc). * The **Web/HTTP Server**, for serving the web page that hosts the **Web Viewer**. * The **WebSocket server**, for serving data to the **Web Viewer**. The communication is unidirectional: the server pushes data to the **Web Viewer**, never the other way around. * The **CLI**, which allows you to control all the pieces above as well as manipulate RRD files. The **Native Viewer** always includes: * A **Chunk Store**: an in-memory database that stores the logged data. * A **Renderer**: a 3D engine that renders the contents of the **Chunk Store**. ## What runs where? This is a lot to take in at first, but as we'll see these different pieces are generally deployed in just a few unique configurations for most common cases. The first thing to understand is what process do each of these things run in. The **CLI**, **Native Viewer**, **TCP server**, **Web/HTTP Server** and **WebSocket Server** are all part of the same binary: `rerun`. Some of them can be enabled or disabled on demand using the appropriate flags but, no matter what, all these pieces are part of the same binary and execute in the same process. Keep in mind that even the **Native Viewer** can be disabled (headless mode). The **SDKs** are vanilla software libraries and therefore always executes in the same context as the end-user's code. Finally, the **Web Viewer** is a WASM application and therefore has its own dedicated `.wasm` artifact, and always runs in isolation in the end-user's web browser. The best way to make sense of it all it to look at some of the most common scenarios when: * Logging and visualizing data on native. * Logging data on native and visualizing it on the web. ## Logging and visualizing data on native There are two common sub-scenarios when working natively: * Data is being logged and visualized at the same time (synchronous workflow). * Data is being logged first to some persistent storage, and visualized at a later time (asynchronous workflow). ### Synchronous workflow This is the most common kind of Rerun deployment, and also the simplest: one or more **SDKs**, embedded into the user's process, are logging data directly to a **TCP Server**, which in turns feeds the **Native Viewer**. Both the **Native Viewer** and the **TCP Server** are running in the same `rerun` process. Logging script: ```python #!/usr/bin/env python3 import rerun as rr rr.init("rerun_example_native_sync") # Connect to the Rerun TCP server using the default address and # port: localhost:9876 rr.connect_tcp() # Log data as usual, thereby pushing it into the TCP socket. while True: rr.log("/", rr.TextLog("Logging things...")) ``` Deployment: ```sh # Start the Rerun Native Viewer in the background. # # This will also start the TCP server on its default port (9876, use `--port` # to pick another one). # # We could also have just used `spawn()` instead of `connect()` in the logging # script above, and # we wouldn't have had to start the Native Viewer manually. # `spawn()` does exactly this: it fork-execs a Native Viewer in the background # using the first `rerun` # binary available # on your $PATH. $ rerun & # Start logging data. It will be pushed to the Native Viewer through the TCP link. $ ./logging_script ``` Dataflow: Reference: * [SDK operating modes: `connect`](../reference/sdk/operating-modes.md#connect) * [🐍 Python `connect`](https://ref.rerun.io/docs/python/0.19.0/common/initialization_functions/#rerun.connect) * [🦀 Rust `connect`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.connect) * [🌊 C++ `connect`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#aef3377ffaa2441b906d2bac94dd8fc64) ### Asynchronous workflow The asynchronous native workflow is similarly simple: one or more **SDKs**, embedded into the user's process, are logging data directly to one or more files. The user will then manually start the **Native Viewer** at some later point, in order to visualize these files. Note: the `rerun` process still embeds both a **Native Viewer** and a **TCP Server**. For each **Native Viewer**, there is **always** an accompanying **TCP Server**, no exception. Logging script: ```python #!/usr/bin/env python3 import rerun as rr rr.init("rerun_example_native_sync") # Open a local file handle to stream the data into. rr.save("/tmp/my_recording.rrd") # Log data as usual, thereby writing it into the file. while True: rr.log("/", rr.TextLog("Logging things...")) ``` Deployment: ```sh # Log the data into one or more files. $ ./logging_script # Start the Rerun Native Viewer and feed it the RRD file directly. # # This will also start the TCP server on its default port (9876, use `--port` # to pick another one). Although it is not used yet, some client might want # to connect in the future. $ rerun /tmp/my_recording.rrd ``` Dataflow: Reference: * [SDK operating modes: `save`](../reference/sdk/operating-modes.md#save) * [🐍 Python `save`](https://ref.rerun.io/docs/python/0.19.0/common/initialization_functions/#rerun.save) * [🦀 Rust `save`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.save) * [🌊 C++ `save`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a555a7940a076c93d951de5b139d14918) ## FAQ ### How can I use multiple **Native Viewers** at the same (i.e. multiple windows)? Every **Native Viewer** comes with a corresponding **TCP Server** -- always. You cannot start a **Native Viewer** without starting a **TCP server**. The only way to have more than one Rerun window is to have more than one **TCP server**, by means of the `--port` flag. E.g.: ```sh # starts a new viewer, listening for TCP connections on :9876 rerun & # does nothing, there's already a viewer session running at that address rerun & # does nothing, there's already a viewer session running at that address rerun --port 9876 & # logs the image file to the existing viewer running on :9876 rerun image.jpg # logs the image file to the existing viewer running on :9876 rerun --port 9876 image.jpg # starts a new viewer, listening for TCP connections on :6789, and logs the image data to it rerun --port 6789 image.jpg # does nothing, there's already a viewer session running at that address rerun --port 6789 & # logs the image file to the existing viewer running on :6789 rerun --port 6789 image.jpg & ``` # Recordings --- title: Recordings order: 0 --- Recordings are the core abstraction for organizing data in Rerun. A Recording is a semantic collection of data with an associated _Recording ID_ (which is just another name for a UID). That's it. Recordings are a _logical abstraction_, not a physical one: a recording is not confined to a specific file, or folder, or database, or whichever physical storage you might think of. Similarly, there is no such thing as "closing" a recording: as long as there exists or will exist a system somewhere that is capable of producing _chunks_ of data, and tagging these chunks with the appropriate _Recording ID_, then that recording is effectively still growing. Whether that happens today, tomorrow, or in some distant future. This design naturally allows for both the production and the storage of recordings to be horizontally distributed: * Production can be handled by multiple producers that all log data to the same _Recording ID_, independently. * Storage can be sharded over multiple independent files (or any other storage medium). You can learn more about sharding in the [dedicated documentation page](../howto/logging/shared-recordings.md). In practice, most Rerun recordings are encoded in binary files with the `.rrd` extension by default. This is our basic storage solution for recordings, which is specifically designed for streaming use cases (i.e. `.rrd` files do not offer random-access to the data within). Note that [blueprints](../howto/configure-viewer-through-code.md) are recordings too, and by convention are stored in binary `.rbl` files. ## Application IDs Rerun recordings have an extra piece of metadata associated with them in addition to their _Recording ID_: an _Application ID_. _Application IDs_ are arbitrary user-defined strings. When you initialize the Rerun logging SDK, you need to set an _Application ID_. ```python rr.init("my_custom_application_id") ``` The Rerun viewer will store your blueprint based on this _Application ID_. This means that you can run your app and set up the viewer to your liking, and then when you run the app again the Rerun viewer will remember how you set up your Views etc. Different recordings (i.e. different _Recording IDs_) will share the same blueprint as long as they share the same _Application ID_. Check out the API to learn more about SDK initialization: * [🐍 Python](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) * [🦀 Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html#method.new) * [🌊 C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#abda6202900fa439fe5c27f7aa0d1105a) ## Recording IDs in practice Each time you start logging using Rerun, a random _Recording ID_ is generated. For instance, each `.rrd` file will have a unique _Recording ID_. This means you can have multiple recordings with different Recording IDs sharing the same application ID. If you want to log from multiple processes and want all the log data to show up together in the viewer, you need to make sure all processes use the same Recording ID. # Component Batches --- title: Component Batches order: 700 --- Rerun has built-in support for batch data. Whenever you have a collection of things that all have the same type, rather than logging each element individually, you can log the entire collection together as a single "Batch". This provides significant benefits in terms of storage and compute. Some examples of batched data include points in a point cloud, bounding boxes for detected objects, tracked keypoints in a skeleton, or a collection of line strips. In the logging APIs, the majority of archetypes are named with the plural form, for example [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D). They accept both single elements (internally treated as an N=1 batch) or arrays corresponding to the batches. ## Terminology - An *entity* is a collection of *components* (see [Entities and Components](entity-component.md)). - When an entity is batched, its components' individual elements are called *instances*. - When every instance within an entity shares the same value for a component, we say that this component is clamped. This is a common pattern and has dedicated support for it (see the [Component Clamping](#component-clamping) section below). For instance, you can set all the colors of a point cloud to the same color by passing a single color value to the `color` parameter. - During queries, a batch always has a *primary* component. The primary component is what determines how many instances exist in the batch. ## Restrictions When using batched entities there are a few restrictions: - Because there is a one-to-one mapping between batches and entities: - If data needs to span multiple entity paths, it needs to be split up into separate batches. - If data needs to be split into multiple batches, each must be logged to a different path. - Whenever you log a batched entity, for any component that is updated, you must provide values for every instance. - It is not possible to only update a subset of the instances in the batch. ## Batch join rules Rerun lets you choose which components in an entity you want to log at any point in time. If you don't log to a component, then in general it is not updated. For example, if you log a point cloud with positions and colors and then later log just new positions, when the Viewer displays that point cloud it will still look up the *last* colors that were logged (we refer to this as the *latest-at* semantics). This can be quite convenient since updating different components at different times puts far fewer restrictions on the organization of your code. It even means if a component on an entity is static, you only need to log it once. However, if both a batch of colors and a batch of positions have been logged at two different points in time, we need a way to know which point receives which color. For that, Rerun uses the index of the instance. When querying a batched component, the component-values are joined together based on this index. Logically, this happens as a *left-join* using the primary component for the entity. For example, if you log 3 points and then later log 5 colors, you will still only see 3 points in the viewer. What should happen if you have 5 points and 3 colors then? This is where clamping semantics come into play. ## Component clamping As mentioned, Rerun has special semantics when joining batches of different sizes, for example this is what happens when you mix arrays and single values in an API call. If the component on the left-side of the join (the so-called primary component) has more instances than the other, then these tail values will simply be ignored. On the other hand, if the component on the left-side of the join (the so-called primary component) has less instances than the other, then the last instance will be repeated across every instance left in the batch. We call this clamping, in reference to texture sampling (think `CLAMP_TO_EDGE`!). ## See also [`send_columns`](../howto/send_columns.md) lets you efficiently send many batches of data in one log call. # Blueprints --- title: Blueprints order: 600 --- ## Blueprints and recordings When you are working with the Rerun viewer, there are two separate pieces that combine to produce what you see: the "recording" and the "blueprint." - The recording provides the actual data you are visualizing. - The blueprint is the configuration that determines how the data from the recording is displayed. Both of these pieces are crucial—without the recording there is nothing to show, and without the blueprint there is no way to show it. Even if you have used Rerun before without explicitly loading a blueprint, the Viewer was actually creating one for you. Without a blueprint, there is literally nothing for the Viewer to display. ## Loose coupling The blueprint and the recording are only loosely coupled. Rerun uses the [application ID](apps-and-recordings.md) to determine whether a blueprint and a recording should be used together, but they are not directly linked beyond that. This means that either can be changed independently of the other. Keeping the blueprint constant while changing the recording will allow you to compare different datasets using a consistent set of views. On the other hand, changing the blueprint while keeping a recording constant will allow you to view the same data in different ways. ## What the blueprint controls Every aspect of what the Viewer displays is controlled by the blueprint. This includes the type and content of the different views, the organization and layout of the different containers, and the configuration and styling properties of the individual data visualizers (see [Visualizers and Overrides](visualizers-and-overrides.md) for more details). In general, if you can modify an aspect of how something looks through the viewer, you are actually modifying the blueprint. (Note that while there may be some exceptions to this rule at the moment, the intent is to eventually migrate all state to the blueprint.) ## Current, default, and heuristics blueprints Blueprints may originate from multiple sources. - The "current blueprint" for a given application ID is the one that is used by the Viewer to display data at any given time. It is updated for each change made to the visualization within the viewer, and may be saved to a blueprint file at any time. - The "default blueprint" is a snapshot that is set or updated when a blueprint is received from code or loaded from a file. The current blueprint may be reset to default blueprint at any time by using the "reset" button in the blueprint panel's header. - The "heuristic blueprint" is an automatically-produced blueprint based on the recording data. When no default blueprint is available, the heuristic blueprint is used when resetting the current blueprint. It is also possible to reset to the heuristic blueprint in the selection panel after selecting an application. ## What is a blueprint Under the hood, the blueprint is just data. It is represented by a [time-series ECS](./entity-component.md), just like a recording. The only difference is that it uses a specific set of blueprint archetypes and a special blueprint timeline. Note that even though the blueprint may be sent over the same connection, blueprint data is kept in an isolated store and is not mixed with your recording data. Although the Rerun APIs for working with blueprint may look different from the regular logging APIs, they are really just syntactic sugar for logging a collection of blueprint-specific archetypes to a separate blueprint stream. Furthermore, when you make any change to the Viewer in the UI, what is actually happening is the Viewer is creating a new blueprint event and adding it to the end of the blueprint timeline in the blueprint store. ## Viewer operation Outside of caching that exists primarily for performance reasons, the viewer persists very little state frame-to-frame. The goal is for the output of the Viewer to be a deterministic function of the blueprint and the recording. Every frame, the Viewer starts with a minimal context of an "active" blueprint, and an "active" recording. The Viewer then uses the current revision on the blueprint timeline to query the container and view archetypes from the blueprint store. The view archetypes, in turn, specify the paths types that need to be queried from the recording store in order to render the views. Any user interactions that modify the blueprint are queued and written back to the blueprint using the next revision on the blueprint timeline. ## Blueprint architecture motivation Although this architecture adds some complexity and indirection, the fact that the Viewer stores all of its meaningful frame-to-frame state in a structured blueprint data-store has several advantages: - Anything you modify in the Viewer can be saved and shared as a blueprint. - A blueprint can be produced programmatically using just the Rerun SDK without a dependency on the Viewer libraries. - The blueprint is capable of representing any data that a recording can represent. This means that blueprint-sourced data [overrides](visualizers-and-overrides.md#Per-entity-component-override) are just as expressive as any logged data. - The blueprint is actually stored as a full time-series, simplifying future implementations of things like snapshots and undo/redo mechanisms. - Debugging tools for inspecting generic Rerun data can be used to inspect internal blueprint state. # Chunks --- title: Chunks order: 475 --- A *Chunk* is the core datastructure at the heart of Rerun: it dictates how data gets logged, injected, stored, and queried. A basic understanding of chunks is important in order to understand why and how Rerun and its APIs work the way they work. ## How Rerun stores data All the data you send into Rerun is stored in chunks, always. A chunk is an [Arrow](https://arrow.apache.org/)-encoded, column-oriented table of binary data: A *Component Column* contains one or more [*Component Batches*](./batches.md), which in turn contain one or more instances (that is, a component is *always* an array). Each component batch corresponds to a single *Row ID* and one [time point per timeline](./timelines.md). This design allows for keeping chunks within a target size range, even for recordings that combine low frequency but large data like point clouds or tensors (wide columns), with high frequency but small signals (tall columns). Here's an excerpt from a real-world chunk (taken from the [Helix example](https://app.rerun.io/?url=https%3A%2F%2Fapp.rerun.io%2Fversion%2Flatest%2Fexamples%2Fdna.rrd)) (you might want to open [this image](https://static.rerun.io/a_real_chunk/ef010ee1ca03516c3f9cce320dc18f814e7e546c/full.png) in a new tab): You can see that this matches very closely the diagram above: * A single *control* column, that contains the globally unique row IDs. * Multiple *time*/*index* columns (`log_time`, `log_tick`, `stable_time`). * Multiple component columns (`Color`, `Position3D`, `Radius`). Within each row of each component column, the individual cells are [*Component Batches*](./batches.md). Component batches are the atomic unit of data in Rerun. The data in this specific chunk was logged with the following code: ```python rr.set_time_seconds("stable_time", time) beads = [bounce_lerp(points1[n], points2[n], times[n]) for n in range(NUM_POINTS)] colors = [[int(bounce_lerp(80, 230, times[n] * 2))] for n in range(NUM_POINTS)] rr.log( "helix/structure/scaffolding/beads", rr.Points3D(beads, radii=0.06, colors=np.repeat(colors, 3, axis=-1)) ) ``` You can learn more about chunks and how they came to be in [this blog post](http://rerun.io/blog/column-chunks#storage-is-based-around-chunks-of-component-columns). ## Getting chunks into Rerun If you've used the Rerun SDK before, you know it doesn't actually force to manually craft these chunks byte by byte - that would be rather cumbersome! How does one creates and stores chunks in Rerun, then? ### The row-oriented way: `log` The `log` API is generally [what we show in the getting-started guides](https://rerun.io/docs/getting-started/quick-start/python#logging-your-own-data) since it's the easiest to use: ```python """ Update a scalar over time. See also the `scalar_column_updates` example, which achieves the same thing in a single operation. """ from __future__ import annotations import math import rerun as rr rr.init("rerun_example_scalar_row_updates", spawn=True) for step in range(64): rr.set_time_sequence("step", step) rr.log("scalars", rr.Scalar(math.sin(step / 10.0))) ``` The `log` API makes it possible to send data into Rerun on a row-by-row basis, without requiring any extra effort. This row-oriented interface makes it very easy to integrate into existing codebase and just start logging data as it comes (hence the name). Reference: * [🐍 Python `log`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) * [🦀 Rust `log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log) * [🌊 C++ `log`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a7badac918d44d66e04e948f38818ff11) But if you're handing a bunch of rows of data over to Rerun, how does it end up neatly packaged in columnar chunks? #### How are these rows turned into columns? Before logging data, you can use the `rr.set_time_` APIs to update the SDK's time context with timestamps for custom timelines. For example, `rr.set_time_sequence("frame", 42)` will set the "frame" timeline's current value to 42 in the time context. When you later call `rr.log`, the SDK will generate a row id and values for the built-in timelines `log_time` and `log_tick`. It will also grab the current values for any custom timelines from the time context. Any data passed to `rr.log` or `rr.log_components` becomes component batches. The row id, timestamps, and logged component batches are then encoded as Apache Arrow arrays and together make up a row. That row is then passed to a batcher, which appends the values from the row to the current chunk for the entity path. The current chunk is then sent to its destination, either periodically or as soon as it crosses a size threshold. Building up small column chunks before sending from the SDK trades off a small amount of latency and memory use in favor of more efficient transfer and ingestion. You can read about how to configure the batcher [here](../reference/sdk/micro-batching.md). ### The column-oriented way: `send_columns` The `log` API showcased above is designed to extract data from your running code as it's being generated. It is, by nature, *row-oriented*. If you already have data stored in something more *column-oriented*, it can be both a lot easier and more efficient to send it to Rerun in that form directly. This is what the `send_columns` API is for: it lets you efficiently update the state of an entity over time, sending data for multiple index and component columns in a single operation. > ⚠️ `send_columns` API bypasses the time context and [micro-batcher](../reference/sdk/micro-batching.md) ⚠️ > > In contrast to the `log` API, `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](../concepts/timelines.md). Only the timelines explicitly included in the call to `send_columns` will be included. ```python """ Update a scalar over time, in a single operation. This is semantically equivalent to the `scalar_row_updates` example, albeit much faster. """ from __future__ import annotations import numpy as np import rerun as rr rr.init("rerun_example_scalar_column_updates", spawn=True) times = np.arange(0, 64) scalars = np.sin(times / 10.0) rr.send_columns( "scalars", indexes=[rr.TimeSequenceColumn("step", times)], columns=rr.Scalar.columns(scalar=scalars), ) ``` See also the reference: * [🐍 Python `send_columns`](https://ref.rerun.io/docs/python/0.21.0/common/columnar_api/#rerun.send_columns) * [🦀 Rust `send_columns`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.send_columns) * [🌊 C++ `send_columns`](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a7e326526d1473c02fcb2ed94afe6da69) # Entities and Components --- title: Entities and Components order: 100 --- ## Data model The core of Rerun's data model is inspired by the ideas of the [Entity Component System (ECS)](https://en.wikipedia.org/wiki/Entity_component_system) architecture pattern. In short, an ECS is a composition-oriented framework in which *entities* represent generic objects while *components* describe data associated with those entities. * *Entities* are the "things" that you log with the [`rr.log()`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log)function. They are represented by the [*entity path*](entity-path.md) string which is passed as first argument. * *Components*, however, are what contains the data that is associated with those "things". For example, position, color, pixel data, etc. Entities are like folders, and components are like files. Additionally, the Rerun SDKs expose two additional concepts: * *Archetypes* are coherent set of components corresponding to primitive such as 2D points or 3D boxes. In the Rerun SDKs, archetypes take the form of builder objects that assist with the creation of such component sets. They are meant as high-level, convenience helpers that can be bypassed entirely if/when required by advanced use-cases. * *Datatypes* are regular data structures that components occasionally rely on when fundamental data types (`float`, `uint32`, etc.) are not sufficient. ### Logging and viewing data All the data that you log within Rerun is mapped to the concepts of entities and components. For example, consider the case of logging a point: ```python rr.log("my_point", rr.Points2D([32.7, 45.9], color=[255, 0, 0])) ``` This statement uses the [`rr.Points2D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points2D) archetype. Internally, this archetype builds a set of, in this case, two components: [`Position2D`](../reference/types/components/position2d.md) and [`Color`](../reference/types/components/color.md). Then, the `rr.log()` function records these two components and associate them with the `"my_point"` entity. Later, the View for spatial types queries the data store for all the entities that have a `Position2D` component. In this case it would find the "my_point" entity. This query additionally returns the `Color` component because that component is associated with the same entity. These two components are recognized as corresponding to the `Points2D` archetype, which informs the Viewer on how to display the corresponding entity. See the [Types](../reference/types.md) reference for a list of [archetypes](../reference/types/archetypes.md), [components](../reference/types/components.md), and [datatypes](../reference/types/datatypes.md). ### Adding custom data Although both the SDKs' archetype objects and the view are based on the same archetype definition (and are actually implemented using code that is automatically generated based on that definition), they both operate on arbitrary collection of components. Neither the SDKs nor the Viewer enforce or require that an entity should contain a *specific* set of component. The Rerun Viewer will display any data in a generic form, but its views will only work on sets of components it can make sense of. Your entity could have any number of additional components as well. This isn't a problem. Any components that aren't relevant to the scene that the view is drawing are safely ignored. Also, Rerun even allows you to log your own set of components, bypassing archetypes altogether. In Python, the [rr.AnyValues](https://ref.rerun.io/docs/python/stable/common/custom_data/#rerun.AnyValues) helper object can be used to add custom component(s) to an archetype: ```python """Log extra values with a `Points2D`.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_extra_values", spawn=True) rr.log( "extra_values", rr.Points2D([[-1, -1], [-1, 1], [1, -1], [1, 1]]), rr.AnyValues( confidence=[0.3, 0.4, 0.5, 0.6], ), ) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1.5, 1.5], y_range=[-1.5, 1.5]))) ``` It can also be used log an entirely custom set of components: ```python """Log arbitrary data.""" import rerun as rr rr.init("rerun_example_any_values", spawn=True) rr.log( "any_values", rr.AnyValues( confidence=[1.2, 3.4, 5.6], description="Bla bla bla…", # URIs will become clickable links homepage="https://www.rerun.io", repository="https://github.com/rerun-io/rerun", ), ) ``` For more complex use-cases, custom objects implementing the `rr.AsComponents` protocol can be used. For Rust, the `rerun::AsComponents` trait must be implemented: ```python """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 component_descriptor(self) -> rr.ComponentDescriptor: """The descriptor of the custom component.""" return rr.ComponentDescriptor("user.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).or_with_descriptor_overrides( archetype_name="user.CustomPoints3D", archetype_field_name="confidences" ) 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() ``` ### Empty entities An entity without components is nothing more than an identity (represented by its entity path). It contains no data, and has no type. When you log a piece of data, all that you are doing is setting the values of one or more components associated with that entity. ## ECS systems There is a third concept we haven't touched on: *systems* are processes which operate on the entities based on the components they possess. Rerun is still settling on the exact form of formalized systems and outside of Rust Viewer code it is not yet possible to write your own systems. However, views work under the hood using a variety of systems. For more information see the [Extend the Viewer in Rust](../howto/extend/extend-ui.md) section. # The Entity Path Hierarchy --- title: The Entity Path Hierarchy order: 200 --- ## Entity paths As mentioned in the [Entity Component](entity-component.md) overview, all entities within Rerun have a unique _entity path_. The first argument to the `log()` function is this path. Each time you log to a specific entity path you will update the entity, i.e. log a new instance of it along the timeline. It is possible to log multiple types of archetypes on the same entity path, but you should generally avoid mixing different kinds of geometric primitive. For example, logging a [`Points3D`](../reference/types/archetypes/points3d.md) point cloud on an entity path where a [`Mesh3D`](../reference/types/archetypes/mesh3d.md) was previously logged would overwrite the mesh's [`Position3D`](../reference/types/components/position3d.md) component with the point cloud's, but would leave the `triangle_indices` component untouched. The Rerun Viewer would likely be unable to display the result. See the [Entity Component](entity-component.md) section for more information. There _are_ valid reasons to logs different kinds of archetypes to the same entity path, though. For example, it's common to log a [`Transform3D`](../reference/types/archetypes/transform3d.md) along with some geometry it relates to (see the [Spaces and Transforms](spaces-and-transforms.md) for more info). Rerun treats entity paths as being arranged in a hierarchy with the `/` character acting as a separator between path elements. The conventional path semantics including concepts of *root* and *parent*/*child* generally apply. When writing paths in logging APIs the leading `/` is usually omitted. In the file path analogy, each entity is a folder, and a component is a file. This implies that any entity in a hierarchy can contain components. For example (this uses the Python SDK but the same applies for all supported languages): ```python rr.log("image", rr.Image(img)) rr.log("image/points", rr.Points2D(points)) ``` It is also acceptable to leave implicitly "empty" entities in your paths as well. ```python rr.log("camera/image", rr.Image(img)) rr.log("camera/image/detections/points", rr.Points2D(points)) ``` Nothing needs to be explicitly logged to `"camera"` or `"camera/image/detection"` to make the above valid. In other words, the `log` call is akin to creating a folder with `mkdir -p` and then writing files (components) to it. Existing components of the same name will be overwritten. ### Path parts Each "part" of a path must be a non-empty string. Any character is allowed, but special characters need to be escaped using `\`. Characters that need NOT be escaped are letters, numbers, and underscore, dash, and dot (`_`, `-`, `.`). Any other character should be escaped, including symbols (`\:`, `\$`, …) and whitespace (`\ `, `\n`, `\t`, …). You can an arbitrary unicode code point into an entity path using `\u{262E}`. So for instance, `world/3D/My\ Image.jpg/detection` is a valid path (note the escaped space!). ⚠️ NOTE: even though entity paths are somewhat analogous to file paths, they are NOT the same. `..` does not mean "parent folder", and you are NOT intended to pass a file path as an entity path (especially not on Windows, which use `\` as a path separator). ### Path hierarchy functions Path hierarchy plays an important role in a number of different functions within Rerun: * With the [Transform System](spaces-and-transforms.md) the `transform` component logged to any entity always describes the relationship between that entity and its direct parent. * When resolving the meaning of [`ClassId`](../reference/types/components/class_id.md) and [`KeypointId`](../reference/types/components/keypoint_id.md) components, Rerun uses the [Annotation Context](annotation-context.md) from the nearest ancestor in the hierarchy. * When adding data to [Blueprints](../reference/viewer/blueprint.md), it is common to add a path and all of its descendants. * When using `rr.log("entity/path", rr.Clear(recursive=True))`, it marks an entity *and all of its descendants* as being cleared. * In the future, it will also be possible to use path-hierarchy to set default-values for descendants ([#1158](https://github.com/rerun-io/rerun/issues/1158)). ### Reserved paths The path prefix `rerun/` is considered reserved for use by the Rerun SDK itself and should not be used for logging user data. This is where Rerun will log additional information such as warnings. # Query semantics & partial updates --- title: Query semantics & partial updates order: 480 --- ## The Rerun data model is based around streams of entities with components In Rerun, you model your data using entities (roughly objects) with [batches of components](./batches.md) that change over time. An entity is identified by an entity path, e.g. `/car/lidar/points`, where the path syntax can be used to model hierarchies of entities. A point cloud could be made up of positions and colors, but you can add whatever components you like to the entity. Point positions are e.g. represented as a batch of `Position3D` component instances. Components can have different values for different times, and do not have to be updated all at once. Rerun supports multiple timelines (sequences of times), so that you can explore your data organized according to e.g. the camera's frame index or the time it was logged. ## Core queries All data that gets sent to the Rerun viewer is stored in an in-memory database, and there are two core types of queries against the database that visualizers in the viewer run. **Latest-at queries** collect the latest version of each of an entity's components at a particular time. This allows the visualizer to draw the current state of an object that was updated incrementally. For example, you might want to update the vertex positions of a mesh while keeping textures and triangle indices constant. **Range queries** instead collect all components associated with times on a time range. These queries drive any visualization where data from more than one time is shown at the same time. The obvious example is time series plots, but it can also be used to e.g. show lidar point clouds from the last 10 frames together. The queried range is typically configurable, see for instance [this how-to guide on fixed windows plots](../howto/visualization/fixed-window-plot.md) for more information. ## Partial updates As mentioned above, the query semantics that power the Rerun Viewer, coupled with our [chunk-based storage](./chunks.md), make it possible to log only the components that have changed in-between frames (or whatever atomic unit [your timeline](./timelines.md) is using). Here's an example of updating only some specific properties of a point cloud, over time: ```python """Update specific properties of a point cloud over time.""" import rerun as rr rr.init("rerun_example_points3d_partial_updates", spawn=True) positions = [[i, 0, 0] for i in range(0, 10)] rr.set_time_sequence("frame", 0) rr.log("points", rr.Points3D(positions)) for i in range(0, 10): colors = [[20, 200, 20] if n < i else [200, 20, 20] for n in range(0, 10)] radii = [0.6 if n < i else 0.2 for n in range(0, 10)] # Update only the colors and radii, leaving everything else as-is. rr.set_time_sequence("frame", i) rr.log("points", rr.Points3D.from_fields(radii=radii, colors=colors)) # Update the positions and radii, and clear everything else in the process. rr.set_time_sequence("frame", 20) rr.log("points", rr.Points3D.from_fields(clear_unset=True, positions=positions, radii=0.3)) ``` To learn more about how to use our partial updates APIs, refer to [this page](../howto/logging/send-partial-updates.md). # Spaces and Transforms --- title: Spaces and Transforms order: 300 --- ## The definition of a space Every entity in Rerun exists in some _space_. This is at the core of how Rerun organizes the visualizations of the data that you have logged. In the [Rerun Viewer](../reference/viewer.md) you view data by configuring a _view_, which is a view of a set of entities _as seen from a particular origin._ The origin of a space is, very loosely, a generalization of the idea of a "coordinate system" (sometimes known as a "coordinate frame") to arbitrary data. If a collection of entities are part of the same space, it means they can be rendered together. For example: - For 2D and 3D geometric primitives this means they share the same coordinate system. - For scalar plots it means they share the same plot axes. - For text logs, it means they share the same conceptual stream. As explained below, a view _may_ display data belonging to multiple spaces, but there must be a well-defined means of transforming the data from one space to another. Which entities belong to which spaces is a function of the transform system, which uses the following rules to define the space connectivity: 1. Every unique entity path defines a potentially unique space. 1. Unless otherwise specified, every path is trivially connected to its parent by the identity transform. 1. Logging a transform to a path defines the relationship between that path and its parent (replacing the identity connection). 1. Only paths which are connected by the identity transform are effectively considered to be part of the same space. All others are considered to be disjoint. Note that in the absence of transforms, all entity paths are fully connected by the identity transform, and therefore share the same space. However, as soon as you begin to log transforms, you can end up with additional spaces. Consider the following scenario: ```python rr.log("world/mapped_keypoints", rr.Points3D(…)) rr.log("world/robot/observed_features",rr.Points3D(…)) rr.log("world/robot", rr.Transforms3D(…)) ``` There are 4 parent/child entity relationships represented in this hierarchy. - `(root)` -> `world` - `world` -> `world/mapped_keypoints` - `world` -> `world/robot` - `world/robot` -> `world/robot/observed_features` The call: `rr.log("world/robot", rr.Transforms3D(…))` only applies to the relationship: `world` -> `world/robot` because the logged transform (`world/robot`) describes the relationship between the entity and its _parent_ (`world`). All other relationships are considered to be an identity transform. This leaves us with two spaces. In one space, we have the entities `world`, and `world/mapped_keypoints`. In the other space we have the entities `world/robot` and `world/robot/observed_features`. Practically speaking, this means that the position values of the points from `world/mapped_keypoints` and the points from `world/robot/observed_features` are not directly comparable. If you were to directly draw these points in a single coordinate system the results would be meaningless. As noted above, Rerun can still display these entities in the same view because it is able to automatically transform data between different spaces. ## Space transformations In order to correctly display data from different spaces in the same view, Rerun uses the information from logged transforms. Since most transforms are invertible, Rerun can usually transform data from a parent space to a child space or vice versa. As long as there is a continuous chain of well-defined transforms, Rerun will apply the correct series of transformations to the component data when building the scene. Rerun transforms are currently limited to connections between _spatial_ views of 2D or 3D data. There are 3 types of transforms that can be logged: - Affine 3D transforms, which can define any combination of translation, rotation, and scale relationship between two paths (see [`rr.Transform3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Transform3D)). - Pinhole transforms define a 3D -> 2D camera projection (see [`rr.Pinhole`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Pinhole)). In the future, Rerun will be adding support for additional types of transforms. - [#349: Log 2D -> 2D transformations in the transform hierarchy](https://github.com/rerun-io/rerun/issues/349) ## Examples Say you have a 3D world with two cameras with known extrinsics (pose) and intrinsics (pinhole model and resolution). You want to log some things in the shared 3D space, and also log each camera image and some detection in these images. ```py # Log some data to the 3D world: rr.log("world/points", rr.Points3D(…)) # Log first camera: rr.log("world/camera/0", rr.Transform3D(translation=cam0_pose.pos, mat3x3=cam0_pose.rot)) rr.log("world/camera/0/image", rr.Pinhole(…)) # Log second camera: rr.log("world/camera/1", rr.Transform3D(translation=cam1_pose.pos, mat3x3=cam1_pose.rot)) rr.log("world/camera/1/image", rr.Pinhole(…)) # Log some data to the image spaces of the first camera: rr.log("world/camera/0/image", rr.Image(…)) rr.log("world/camera/0/image/detection", rr.Boxes2D(…)) ``` Rerun will from this understand how the `world` space and the two image spaces (`world/camera/0/image` and `world/camera/1/image`) relate to each other, which allows you to explore their relationship in the Rerun Viewer. In the 3D view you will see the two cameras show up with their respective camera frustums (based on the intrinsics). If you hover your mouse in one of the image spaces, a corresponding ray will be shot through the 3D space. Note that none of the names in the paths are special. ## View coordinates You can use [`rr.ViewCoordinates`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.ViewCoordinates) to set your preferred view coordinate systems, giving semantic meaning to the XYZ axes of the space. For 3D spaces it can be used to log what the up-axis is in your coordinate system. This will help Rerun set a good default view of your 3D scene, as well as make the virtual eye interactions more natural. This can be done with `rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True)`. Note that in this example the archetype is logged at the root path, this will make it apply to all 3D views. Generally, a 3D view picks up view coordinates at or above its origin entity path. You can also use this `log_view_coordinates` for pinhole entities, but it is encouraged that you instead use [`rr.log(…, rr.Pinhole(camera_xyz=…))`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Pinhole) for this. The default coordinate system for pinhole entities is `RDF` (X=Right, Y=Down, Z=Forward). WARNING: unlike in 3D views where `rr.ViewCoordinates` only impacts how the rendered scene is oriented, applying `rr.ViewCoordinates` to a pinhole-camera will actually influence the projection transform chain. Under the hood this value inserts a hidden transform that re-orients the axis of projection. Different world-content will be projected into your camera with different orientations depending on how you choose this value. See for instance the `open_photogrammetry_format` example. For 2D spaces and other entities the view coordinates currently do nothing ([#1387](https://github.com/rerun-io/rerun/issues/1387)). # Static data --- title: Static data order: 450 --- The Rerun SDK allows you to store data as _static_. Static data belongs to all timelines (existing ones, and ones not yet created) and shadows any temporal data of the same type on the same entity. That is, any time you log static data to an entity path, all past, present and future temporal data on that same entity path and component is _semantically_ discarded in favor of the static one (which doesn't necessarily mean that it is _physically_ discarded, more on that below). ## How to store static data? Internally, all data in Rerun is stored as chunks of columns. Specifically, each chunk holds zero or more time columns (the indices), and zero or more component columns (the data). Static data is data that lives in a chunk whose set of time columns is the empty set. The easiest way to create such chunks is by using the `log` family of methods, which exposes a `static` flag where appropriate: ```python rr.log("skybox", static=True, generate_skybox_mesh()) ``` The same can be achieved using the `send_columns` API by simply leaving the time column set empty: ```python rr.send_columns("skybox", indexes=[], columns=generate_skybox_mesh()) ``` (Using `send_columns` that way is rarely useful in practice, but is just a logical continuation of the data model.) ## When should I use static data? There are two broad categories of situations where you'd want to use static data: scene setting and memory savings. ### Scene setting Often, you'll want to store data that isn't part of normal data capture, but sets the scene for how it should be shown. For instance, if you are logging cars on a street, perhaps you want to always show a street mesh as part of the scenery, and for that it makes sense for that data to be static. ```python rr.log("skybox", static=True, generate_skybox_mesh()) ``` The alternative would be to log that data at the beginning of every relevant timeline, which can be very problematic as the set of timelines might not even be known before runtime. Similarly, [coordinate systems](spaces-and-transforms.md) or [annotation context](annotation-context.md) are typically stored as static. ### Memory savings When you store _temporal_ data in Rerun, it is always appended to the existing dataset: there is no such thing as overwriting temporal data. The dataset only grows, it never shrinks. To compensate for that, the Rerun viewer has a [garbage collection mechanism](../howto/visualization/limit-ram.md) that will drop the oldest data from the store when memory becomes scarce. For example, the following snippet stores 10 images at index `4` on the `frame` [timeline](timelines.md): ```python rr.set_time_sequence("frame", 4) for _ in range(10): rr.log("camera/image", camera.save_current_frame()) ``` All these images are actually stored, and all of them can be visualized in the viewer independently, even though they share the same index. Contrary to temporal data, static data is **never** garbage collected… but it can actually be overwritten! _Semantically_, only a single piece of static data can exist at a given time for a specific component on a specific entity. In the following snippet, only the data from latest log call (in execution order) will be inspectable in the viewer: ```python for _ in range(10): rr.log("camera/image", static=True, camera.save_current_frame()) ``` In practice, the Rerun datastore will rely on these semantics to physically drop the superfluous static data where possible, therefore drastically reducing memory costs. See ["Understanding storage costs"](#understanding-storage-costs) for more information. ## Understanding storage costs In ["Memory savings"](#memory-savings), we mentioned that the following snippet _semantically_ stores a single image: ```python for _ in range(10): rr.log("camera/image", static=True, camera.save_current_frame()) ``` How these semantics actually translate to physical storage depends on the context. ### In recordings Rerun recordings (`.rrd` files) are just streams of binary messages: they have no semantics whatsoever, therefore they don't know what static means and can't do anything about it. If you were to log the snippet above to a file (using e.g. `rr.save()`), you'd find that the recording does in fact contains your 10 images. If you wanted the recording file itself to only contain a single static value, you would need to either: * Stream the data to the viewer, and then save the recording directly out of the viewer using `Menu > Save recording` (or the equivalent palette command). * Manually recompact your recording using the [Rerun CLI](../reference/cli.md#rerun-rrd-compact) so that the data overwrite semantics can get appropriately applied, e.g.: `rerun rrd compact -o compacted.rrd myrecording.rrd`. ### In the viewer The data store that backs the Rerun viewer natively understands these temporal/garbage-collected vs. static/overwritten semantics. If you were to log the snippet above directly to the Rerun viewer (using e.g. `rr.connect()`), you'd notice that the viewer's memory usage stays constant: the data is automatically being overwritten as new updates come in. For data where you don't need to keep track of historical values, this effectively to logs its new values indefinitely. In the following example, you can see our [face tracking example]() indefinitely tracking my face while maintaining constant memory usage by logging all data as static: # Events and Timelines --- title: Events and Timelines order: 400 --- ## Timelines Each piece of logged data is associated with one or more timelines. The logging SDK always creates two timelines for you: * `log_tick` - a sequence timeline with the sequence number of the log call * `log_time` - a temporal timeline with the time of the log call You can use the _set time_ functions (Python reference: [set_time_sequence](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_sequence), [set_time_seconds](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_seconds), [set_time_nanos](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_nanos)) to associate logs with other timestamps on other timelines. For example: ```python for frame in read_sensor_frames(): rr.set_time_sequence("frame_idx", frame.idx) rr.set_time_seconds("sensor_time", frame.timestamp) rr.log("sensor/points", rr.Points3D(frame.points)) ``` This will add the logged points to the timelines `log_time`, `frame_idx`, and `sensor_time`. You can then choose which timeline you want to organize your data along in the expanded timeline view in the bottom of the Rerun Viewer. ### Reset active timeline & differing data per timeline You can clear the active timeline(s) at any point using `reset_time`. This can be particularly useful when you want to log different data for individual timelines as illustrated here: ```python """Log different data on different timelines.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_different_data_per_timeline", spawn=True) rr.set_time_sequence("blue timeline", 0) rr.set_time_seconds("red timeline", 0.0) rr.log("points", rr.Points2D([[0, 0], [1, 1]], radii=rr.Radius.ui_points(10.0))) # Log a red color on one timeline. rr.reset_time() # Clears all set timeline info. rr.set_time_seconds("red timeline", 1.0) rr.log("points", [rr.components.Color(0xFF0000FF)]) # And a blue color on the other. rr.reset_time() # Clears all set timeline info. rr.set_time_sequence("blue timeline", 1) rr.log("points", [rr.components.Color(0x0000FFFF)]) # Set view bounds: rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds2D(x_range=[-1, 2], y_range=[-1, 2]))) ``` On one timeline the points will appear blue, on the other they appear red. ### Sending many time points at once To get full control over the logged timelines you can use [`send_columns`](../howto/send_columns.md). This is often a lot more efficient when you already have a chunk of temporal data, e.g. some sensor value over time. ## Events An _event_ refer to an instance of logging one or more component batches to one or more timelines. In the viewer, the Time panel provide a graphical representation of these events across time and entities. ## Static data The [`rr.log()`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) function has a `static=False` default argument. If `static=True` is used instead, the data logged becomes *static*. Static data belongs to all timelines (existing ones, and ones not yet created) and shadows any temporal data of the same type on the same entity. This is useful for data that isn't part of normal data capture, but sets the scene for how it should be shown. For instance, if you are logging cars on a street, perhaps you want to always show a street mesh as part of the scenery, and for that it makes sense for that data to be static. Similarly, [coordinate systems](spaces-and-transforms.md) or [annotation context](annotation-context.md) are typically static. You can read more about static data in the [dedicated section](static.md). # Visualizers and Overrides --- title: Visualizers and Overrides order: 650 --- This section explains the process by which logged data is used to produce a visualization and how it can be customized via the user interface or code. *Note*: this area is under heavy development and subject to changes in future releases. ## How are visualizations produced? In the Rerun viewer, visualizations happen within _views_, which are defined by their [_blueprint_](blueprint.md). The first step for a view to display its content is to determine which entities are involved. This is determined by the [entity query](../reference/entity-queries.md), which is part of the view blueprint. The query is run against the data store to generate the list of view entities. Views rely on visualizers to display each of their entities. For example, [3D views](../reference/types/views/spatial3d_view.md) use the `Points3D` visualizer to display 3D point clouds, and [time series views](../reference/types/views/time_series_view.md) use the `SeriesLine` visualizer to display time series line plots. Which visualizers are available is highly dependent on the specific kind of view. For example, the `SeriesLine` visualizer only exist for time series views—not, e.g., for 3D views. For a given view, each entity's components determine which visualizers are available. By default, visualizers are selected for entities logged with a corresponding [archetype](../reference/types/archetypes.md). For example, in a 3D view, an entity logged with the [`Points3D`](../reference/types/archetypes/points3d.md) archetype results in the `Points3D` visualizer being selected by default. This happens because [archetypes](../reference/types/archetypes.md) include an _indicator component_ to capture the intent of the logging code. This indicator component in turn triggers the default activation of the associated visualizer. (We will see that this process can be influenced by both the user interface and the blueprints.) Then, each selected visualizer determines the values for the components it supports. For example, the `Points3D` visualizer handles, among others, the [`Position3D`](../reference/types/components/position3d.md), [`Radius`](../reference/types/components/radius.md), and [`Color`](../reference/types/components/color.md) components. For each of these (and the others it also supports), the visualizer must determine a value. By default, it will use the value that was logged to the data store, if any. Otherwise, it will use some fallback value that depends on the actual type of visualizer and view. For an illustration, let's consider a simple example with just two [`Boxes2D`](../reference/types/archetypes/boxes2d.md): ```python """Base example.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_component_override", spawn=True) # Data logged to the data store. rr.log("boxes/1", rr.Boxes2D(centers=[0, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.log("boxes/2", rr.Boxes2D(centers=[2, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.send_blueprint(rrb.Spatial2DView()) ``` Here is how the user interface represents the `Boxes2D` visualizers in the selection panel, when the corresponding entity is selected: All components used by the visualizer are represented, along with their corresponding values as determined by the visualizer. For the [`Color`](../reference/types/components/color.md) component, we can see both the store and fallback values, the former taking precedence over the latter. ## Per-entity component override To customize a visualization, the blueprint may override any component value for any view entity. This can be achieved either from the user interface or the logging SDK. When such an override is defined, it takes precedence over any value that might have been logged to the data store. This is how it is achieved with the blueprint API: ```python """Override a component.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_component_override", spawn=True) # Data logged to the data store. rr.log("boxes/1", rr.Boxes2D(centers=[0, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.log("boxes/2", rr.Boxes2D(centers=[2, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.send_blueprint( rrb.Spatial2DView( # Override the values from the data store for the first box. overrides={ "boxes/1": [ rr.components.Color([0, 255, 0]), ] }, ), ) ``` The color of `/boxes/1` is overridden to green. Here is how the user interface represents the corresponding visualizer: The override is listed above the store and fallback value since it has precedence. It can also be edited or removed from the user interface. ## Per-view component default The blueprint may also specify a default value for all components of a given type, should their value not be logged to the store or overridden for a given view entity. This makes it easy to configure visual properties for a potentially large number of entities. This is how it is achieved with the blueprint API: ```python """Add a component default.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_component_override", spawn=True) # Data logged to the data store. rr.log("boxes/1", rr.Boxes2D(centers=[0, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.log("boxes/2", rr.Boxes2D(centers=[2, 0], sizes=[1, 1])) rr.send_blueprint( rrb.Spatial2DView( overrides={ "boxes/1": [ rr.components.Color([0, 255, 0]), ] }, # Add a default value for all Color components in this view defaults=[rr.components.Color([0, 0, 255])], ), ) ``` Here, the `/boxes/2` entity is no longer logged with a color value, but a default color is added to the blueprint. Here is how the user interface represents its visualizer: The default color value is displayed above the fallback since it takes precedence. It can also be edited or removed from the user interface. All component default values are displayed in the selection panel when selecting the corresponding view: Again, it is possible to manually add, edit, and remove component defaults from the user interface. ## Component value resolution order The previous sections showed that visualizers use a variety of sources to determine the values of the components they are interested in. Here is a summary of the priority order: 1. **Override**: the per-entity override (the highest priority) 2. **Store**: the value that was logged to the data store (e.g., with the `rr.log()` API) 3. **Default**: the default value for this component type 4. **Fallback**: a context-specific fallback value which may depend on the specific visualizer and view type (the lowest priority) As an illustration, all four values are available for the `/boxes/1` entity of the previous example. Here is how its visualizer is represented in the user interface: ## Visualizer override So far, we discussed how visualizers determine values for the components they are interested in and how this can be customized. This section instead discusses the process of how visualizers themselves are determined and how to override this process. ⚠️NOTE: the feature covered by this section, including its API, is very likely to change in future releases (relevant [issue](https://github.com/rerun-io/rerun/issues/6626)). In the previous examples, because [`Boxes2D`](../reference/types/archetypes/boxes2d.md) archetypes were used for logging then entities, `Boxes2D` visualizers were automatically selected. A key factor driving this behavior is the `Boxes2DIndicator` component, which is a data-less marker automatically inserted by the corresponding `Boxes2D` archetype. This is, however, not the only visualizer capable of displaying these entities. The `Point2D` visualizer can also be used, since it only requires [`Position2D`](../reference/types/components/position2d.md) components. Here is how to force a `Points2D` visualizer for `/boxes/1`, instead of the default `Boxes2D` visualizer: ```python """Override a visualizer.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_component_override", spawn=True) # Data logged to the data store. rr.log("boxes/1", rr.Boxes2D(centers=[0, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.log("boxes/2", rr.Boxes2D(centers=[2, 0], sizes=[1, 1])) rr.send_blueprint( rrb.Spatial2DView( overrides={ "boxes/1": [ # Specify which visualizer to use. rrb.VisualizerOverrides(rrb.visualizers.Points2D), rr.components.Color([0, 255, 0]), ] }, defaults=[rr.components.Color([0, 0, 255])], ), ) ``` The view now displays a point instead of the box. Here is how the visualizer is displayed in the user interface (note the visualizer of type `Points2D`): It is also possible to have _multiple_ visualizers for the same view entity by using an array: ```python """Override a visualizer.""" import rerun as rr import rerun.blueprint as rrb rr.init("rerun_example_component_override", spawn=True) # Data logged to the data store. rr.log("boxes/1", rr.Boxes2D(centers=[0, 0], sizes=[1, 1], colors=[255, 0, 0])) rr.log("boxes/2", rr.Boxes2D(centers=[2, 0], sizes=[1, 1])) rr.send_blueprint( rrb.Spatial2DView( overrides={ "boxes/1": [ # Specify multiple visualizers rrb.VisualizerOverrides([ rrb.visualizers.Boxes2D, rrb.visualizers.Points2D, ]), rr.components.Color([0, 255, 0]), ] }, defaults=[rr.components.Color([0, 0, 255])], ), ) ``` In this case, both a box and a point will be displayed. Adding and removing visualizers is also possible from the user interface.