diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index aa6e28f7f917..651a0af550b2 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -62,7 +62,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.80.0 + toolchain: 1.81.0 - run: cargo build -p rerun diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d046c9cfedc2..f11e5db8cde3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -189,7 +189,7 @@ jobs: - [ ] cargo install of cli tool: does it install and run? - [ ] C++ SDK zip: does it contain rerun_c for all platforms? - [ ] Populate the release with the changelog and a nice header video/picture, check `Set as latest release`, then click `Publish release`. - - [ ] Update the [google colab notebooks](https://drive.google.com/drive/folders/0AC0q24MFKh3fUk9PVA) to install this version and re-execute the notebook. + - [ ] Update the [google colab notebooks](https://colab.research.google.com/drive/1R9I7s4o6wydQC_zkybqaSRFTtlEaked_) to install this version and re-execute the notebook. - [ ] Update landing's version of the web viewer (@jprochazk) A few hours after the GitHub release is created, `regro-cf-autotick-bot` will create a @@ -321,7 +321,7 @@ jobs: github-release: name: "GitHub Release" - if: inputs.release-type == 'final' + if: inputs.release-type == 'rc' || inputs.release-type == 'final' needs: [ version, @@ -347,9 +347,16 @@ jobs: run: | version="${{ needs.version.outputs.final }}" commit="${{ needs.version.outputs.release-commit }}" + + if [ ${{ inputs.release-type }} = "final" ]; then + pre_arg="" + else + pre_arg="--prerelease" + fi + git tag $version $commit git push origin $version - gh release create $version --verify-tag --draft --title $version + gh release create $version --verify-tag --draft --title $version $pre_arg - name: Create comment env: diff --git a/.gitignore b/.gitignore index 43b4208ba656..06d4384f6e35 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ __MACOSX *.bin *.o /arrow/ -/build/ +./build/ **/build-msvc/ **/CMakeFiles/ **/CMakeCache.txt diff --git a/BUILD.md b/BUILD.md index 24aa759a8fe3..161679017155 100644 --- a/BUILD.md +++ b/BUILD.md @@ -23,12 +23,12 @@ cd rerun Now install the `pixi` package manager: -Make sure `cargo --version` prints `1.80.0` once you are done. +Make sure `cargo --version` prints `1.81.0` once you are done. If you are using an Apple-silicon Mac (M1, M2), make sure `rustc -vV` outputs `host: aarch64-apple-darwin`. If not, this should fix it: ```sh -rustup set default-host aarch64-apple-darwin && rustup install 1.80.0 +rustup set default-host aarch64-apple-darwin && rustup install 1.81.0 ``` ## Git-lfs diff --git a/CHANGELOG.md b/CHANGELOG.md index a94fc73a0c0d..6f40cd8ec176 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,182 @@ ## [Unreleased](https://github.com/rerun-io/rerun/compare/latest...HEAD) +## [0.21.0](https://github.com/rerun-io/rerun/compare/0.20.3...0.21.0) - Graph view, 3D Grid & UI/UX improvements + +📖 Release blogpost: https://rerun.io/blog/graphs + +🧳 Migration guide: https://rerun.io/docs/reference/migration/migration-0-21 + +### ✨ Overview & highlights + +#### Graph view + +We've added two new logging primitives: [`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes) and [`GraphEdges`](https://rerun.io/docs/reference/types/archetypes/graph_edges) that can be used to visualize node-link diagrams. For this, we have implemented a new Graph View that uses force-based layouts to draw graphs. + +This video demonstrates the main features of the new graph view: + +https://github.com/user-attachments/assets/77db75c9-a8d8-401d-b90d-3daf08baf0ba + +You can also have a look at https://github.com/rerun-io/rerun/pull/7500 if you want to learn to more. + +#### UX improvements + +This video demonstrates the main UX improvements that went into this release: + +https://github.com/user-attachments/assets/bef071b5-0681-41b2-9ef0-1c6a557ff138 + +#### 3D grid + +The 3D view now offers an infinite 3D grid, enabled by default. Further controls and settings are available as usual through the blueprint API and/or the selection panel. + +

+ + + +

+ +All the nitty gritty details in https://github.com/rerun-io/rerun/pull/8230 and https://github.com/rerun-io/rerun/pull/8234. + +#### Undo/Redo support & many more UI/UX improvements + +You can now undo/redo blueprint changes in the viewer! +Watch [@emilk](https://github.com/emilk/) putting it to action and explains how it works: + +https://github.com/user-attachments/assets/a29c099d-35a3-4d32-8946-932b5a184943 + + +#### Other UX improvements + +But that's not the only thing that improved in the viewer: +* Breadcrumbs show up in the selection menu now + + ![image](https://github.com/user-attachments/assets/c1d20eb1-f259-4b43-89d4-b9fdc75dc88c) + +* Take screenshots of views from context menus + + ![image](https://github.com/user-attachments/assets/6c50e6f0-330f-43f7-a393-65dd47aa171b) + +* Entities can now be dragged from Blueprint & Streams panel into views + + ![image](https://github.com/user-attachments/assets/493d9711-c4d1-407e-ab41-eef2e4e51ba8) + +#### Index of code snippets + +We now have a new [index for all our code snippets](./docs/snippets/INDEX.md). + +You can use it to quickly find copy-pastable snippets of code for any Rerun feature you're interested in (API, Archetypes, Components, etc). +No special tools required -- all you need is a keyword of interest, and plain old text search. + +It's still the early days so it is far from perfect, but we think it can already be quite helpful; feedback welcome. +Most of it is auto-generated, so it will never get out of sync! + +### ⚠️ Breaking changes + +* Near clip plane for `Spatial2D` views now defaults to `0.1` in 3D scene units. +* Blueprint: types and fields got renamed from `.*space_view.*`/`.*SpaceView.*` to `.*view.*`/`.*View.*`. +* 3D transform arrow visualization show up less often by default. +* `DisconnectedSpace` archetype/component is deprecated in favor of implicit invalid transforms (like zero scale or zero rotation matrix). +* `RotationAxisAngle` with zero rotation axis is no longer treated as identity. + +Read our 🧳 migration guide for more detailed information: https://rerun.io/docs/reference/migration/migration-0-21. + +### 🔎 Details + +#### 🪵 Log API +- End-to-end tagging: Rust [#8304](https://github.com/rerun-io/rerun/pull/8304) +- Encode `LogMsg` using protobuf [#8347](https://github.com/rerun-io/rerun/pull/8347) + +#### 🌊 C++ API +- End-to-end tagging: C++ [#8316](https://github.com/rerun-io/rerun/pull/8316) + +#### 🐍 Python API +- Never direct users towards using `rr.log_components` [#8151](https://github.com/rerun-io/rerun/pull/8151) +- Make it possible to log custom components using `rr.send_columns` [#8163](https://github.com/rerun-io/rerun/pull/8163) +- Lint and fix python SDK `(Py)RecordingStream` upcasting issues [#8184](https://github.com/rerun-io/rerun/pull/8184) +- End-to-end tagging: Python [#8298](https://github.com/rerun-io/rerun/pull/8298) +- Rename space view to view everywhere [#8396](https://github.com/rerun-io/rerun/pull/8396) +- Fix broken notebook loading on firefox by compressing the encoded wasm payload [#8426](https://github.com/rerun-io/rerun/pull/8426) +- Add utility to `rr.components.Color` to generate colors from any string (and use it in the air traffic data example) [#8458](https://github.com/rerun-io/rerun/pull/8458) +- Introduce new API to send a dataframe to Rerun [#8461](https://github.com/rerun-io/rerun/pull/8461) + +#### 🦀 Rust API +- Update MSRV to 1.80 [#8178](https://github.com/rerun-io/rerun/pull/8178) +- Remove `Loggable::NAME` -- Loggables do not have any semantics [#8082](https://github.com/rerun-io/rerun/pull/8082) +- Never direct users towards using `RecordingStream::log_component_batches` [#8149](https://github.com/rerun-io/rerun/pull/8149) +- Rust API: be explicit about when we're using the arrow2 crate [#8194](https://github.com/rerun-io/rerun/pull/8194) +- Add `from_gray16` for `DepthImage` [#8213](https://github.com/rerun-io/rerun/pull/8213) (thanks [@fawdlstty](https://github.com/fawdlstty)!) +- Rust: more `impl` helpers [#8401](https://github.com/rerun-io/rerun/pull/8401) + +#### 🪳 Bug fixes +- Fix outlines for lines having more perceived aliasing since 0.20 [#8317](https://github.com/rerun-io/rerun/pull/8317) +- Fix handling unnormalized axis for (Pose)RotationAxisAngle [#8341](https://github.com/rerun-io/rerun/pull/8341) +- Fix 2D/3D view artifacts on view's border when using fractional zoom [#8369](https://github.com/rerun-io/rerun/pull/8369) + +#### 🌁 Viewer improvements +- World grid part 1/2: add world grid renderer to `re_renderer` [#8230](https://github.com/rerun-io/rerun/pull/8230) +- World grid part 2/2: Integrate into Viewer [#8234](https://github.com/rerun-io/rerun/pull/8234) +- Add Undo/Redo support in the viewer [#7546](https://github.com/rerun-io/rerun/pull/7546) +- Space view screenshotting in native viewer [#8258](https://github.com/rerun-io/rerun/pull/8258) +- Remove selection history [#8296](https://github.com/rerun-io/rerun/pull/8296) +- Make the near clipping plane editable in 2D views [#8348](https://github.com/rerun-io/rerun/pull/8348) +- Don't show transform arrows on all entities without any other visualizer [#8387](https://github.com/rerun-io/rerun/pull/8387) +- Do query for default components only once per view [#8424](https://github.com/rerun-io/rerun/pull/8424) +- Improve hovered order in 2D views [#8405](https://github.com/rerun-io/rerun/pull/8405) +- Remove wait-time when opening settings panel [#8464](https://github.com/rerun-io/rerun/pull/8464) +- Deprecate `DisconnectedSpace` archetype/component in favor of implicit invalid transforms [#8459](https://github.com/rerun-io/rerun/pull/8459) +- Improve graphics device capability detection, warn on old devices, early error on unsupported render targets [#8476](https://github.com/rerun-io/rerun/pull/8476) + +#### 🧑‍🏫 Examples +- Add a new "Air Traffic Data" example [#5449](https://github.com/rerun-io/rerun/pull/5449) +- Use video logging api in `detect_and_track` example [#8261](https://github.com/rerun-io/rerun/pull/8261) (thanks [@oxkitsune](https://github.com/oxkitsune)!) +- Add hloc_glomap example and update manifest [#8352](https://github.com/rerun-io/rerun/pull/8352) (thanks [@pablovela5620](https://github.com/pablovela5620)!) +- Introduce the Snippet Index [#8383](https://github.com/rerun-io/rerun/pull/8383) +- Implement complete Graph View example [#8421](https://github.com/rerun-io/rerun/pull/8421) + +#### 📚 Docs +- Update wheel build instruction [#8235](https://github.com/rerun-io/rerun/pull/8235) +- Fix various doc links in SDKs [#8331](https://github.com/rerun-io/rerun/pull/8331) + +#### 🖼 UI improvements +- Implement graph components and archetypes [#7500](https://github.com/rerun-io/rerun/pull/7500) +- Add support for Bezier-curve multi (self-)edges [#8256](https://github.com/rerun-io/rerun/pull/8256) +- Implement incremental graph layouts [#8308](https://github.com/rerun-io/rerun/pull/8308) +- Revert label background color to that in 0.19 [#8337](https://github.com/rerun-io/rerun/pull/8337) +- Add selection hierarchy breadcrumbs [#8319](https://github.com/rerun-io/rerun/pull/8319) +- More compact selection panel when multiple items selected [#8351](https://github.com/rerun-io/rerun/pull/8351) +- Make Position2D components editable in selection panel [#8357](https://github.com/rerun-io/rerun/pull/8357) +- Dynamic configuration of graph layout forces through blueprints [#8299](https://github.com/rerun-io/rerun/pull/8299) +- Document legend interaction in the timeseries view help text [#8406](https://github.com/rerun-io/rerun/pull/8406) +- Allow drag-and-dropping multiple containers and views in the blueprint tree [#8334](https://github.com/rerun-io/rerun/pull/8334) +- Improve picking in 2D views [#8404](https://github.com/rerun-io/rerun/pull/8404) +- Make our collapsing triangle thinner for more consistency with our icons [#8408](https://github.com/rerun-io/rerun/pull/8408) +- Entities can be dragged from the blueprint tree and streams tree to an existing view in the viewport [#8431](https://github.com/rerun-io/rerun/pull/8431) + +#### 🎨 Renderer improvements +- Update egui to latest, update wgpu to 23.0.0 [#8183](https://github.com/rerun-io/rerun/pull/8183) + +#### ✨ Other enhancement +- Improve `rrd print`'s verbosity modes [#8392](https://github.com/rerun-io/rerun/pull/8392) +- Miscellaneous improvements to archetype reflection [#8432](https://github.com/rerun-io/rerun/pull/8432) +- Migration kernel for the blueprint space-view-related breaking changes [#8439](https://github.com/rerun-io/rerun/pull/8439) + +#### 🗣 Refactors +- Add arrow(1)-interface on top of `Loggable` and `ArrowBuffer` [#8197](https://github.com/rerun-io/rerun/pull/8197) +- `re_types_blueprint` -> `re_types::blueprint` [#8419](https://github.com/rerun-io/rerun/pull/8419) +- `re_viewer::reflection` -> `re_types::reflection` [#8420](https://github.com/rerun-io/rerun/pull/8420) + +#### 📦 Dependencies +- Numpy 2.0 allowed in pyproject.toml [#8306](https://github.com/rerun-io/rerun/pull/8306) (thanks [@Ipuch](https://github.com/Ipuch)!) +- Upgrade to egui 0.30 (+ ecosystem) [#8516](https://github.com/rerun-io/rerun/pull/8516) + +#### 🧑‍💻 Dev-experience +- Add `MainThreadToken` to ensure file-dialogs only run on the main thread [#8467](https://github.com/rerun-io/rerun/pull/8467) + +#### 🤷‍ Other +- Deprecate `--serve`, add `--serve-web` [#8144](https://github.com/rerun-io/rerun/pull/8144) +- Clean up pass over all superfluous hashing happening on the query path [#8207](https://github.com/rerun-io/rerun/pull/8207) +- Improve performance of time panel [#8224](https://github.com/rerun-io/rerun/pull/8224) + ## [0.20.3](https://github.com/rerun-io/rerun/compare/0.20.2...0.20.3) - Web viewer fix ### 🔎 Details diff --git a/Cargo.lock b/Cargo.lock index 935feec6db76..b413b7d3b722 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,7 +38,7 @@ dependencies = [ "accesskit_consumer 0.26.0", "atspi-common", "serde", - "thiserror", + "thiserror 1.0.65", "zvariant", ] @@ -187,7 +187,7 @@ dependencies = [ "ndk-context", "ndk-sys 0.6.0+11769913", "num_enum", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -318,7 +318,7 @@ dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -691,7 +691,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -731,7 +731,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -748,7 +748,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -854,7 +854,7 @@ dependencies = [ "num-derive", "num-rational", "num-traits", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -1066,7 +1066,7 @@ checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1108,7 +1108,7 @@ dependencies = [ "sha2", "ssri", "tempfile", - "thiserror", + "thiserror 1.0.65", "tokio", "tokio-stream", "walkdir", @@ -1125,7 +1125,7 @@ dependencies = [ "polling", "rustix", "slab", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -1156,7 +1156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03fa8484a7f2eef80e6dd2e2be90b322b9c29aeb1bbc206013d6eb2104db7241" dependencies = [ "serde", - "thiserror", + "thiserror 1.0.65", "toml", ] @@ -1205,7 +1205,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -1321,7 +1321,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "696283b40e1a39d208ee614b92e5f6521d16962edeb47c48372585ec92419943" dependencies = [ - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -1355,7 +1355,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1381,7 +1381,7 @@ dependencies = [ [[package]] name = "clock" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -1724,7 +1724,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "custom_data_loader" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "re_build_tools", "rerun", @@ -1732,7 +1732,7 @@ dependencies = [ [[package]] name = "custom_store_subscriber" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "re_build_tools", "rerun", @@ -1740,7 +1740,7 @@ dependencies = [ [[package]] name = "custom_view" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "mimalloc", "re_crash_handler", @@ -1768,7 +1768,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1779,7 +1779,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1796,7 +1796,7 @@ checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" [[package]] name = "dataframe_query" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "itertools 0.13.0", "rerun", @@ -1877,7 +1877,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -1891,7 +1891,7 @@ dependencies = [ [[package]] name = "dna" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "itertools 0.13.0", "rand", @@ -1933,8 +1933,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ecolor" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d72e9c39f6e11a2e922d04a34ec5e7ef522ea3f5a1acfca7a19d16ad5fe50f5" dependencies = [ "bytemuck", "color-hex", @@ -1950,8 +1951,9 @@ checksum = "18aade80d5e09429040243ce1143ddc08a92d7a22820ac512610410a4dd5214f" [[package]] name = "eframe" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2f2d9e7ea2d11ec9e98a8683b6eb99f9d7d0448394ef6e0d6d91bd4eb817220" dependencies = [ "ahash", "bytemuck", @@ -1989,8 +1991,9 @@ dependencies = [ [[package]] name = "egui" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252d52224d35be1535d7fd1d6139ce071fb42c9097773e79f7665604f5596b5e" dependencies = [ "accesskit", "ahash", @@ -2006,8 +2009,9 @@ dependencies = [ [[package]] name = "egui-wgpu" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c1e821d2d8921ef6ce98b258c7e24d9d6aab2ca1f9cdf374eca997e7f67f59" dependencies = [ "ahash", "bytemuck", @@ -2016,7 +2020,7 @@ dependencies = [ "epaint", "log", "profiling", - "thiserror", + "thiserror 1.0.65", "type-map", "web-time", "wgpu", @@ -2025,8 +2029,9 @@ dependencies = [ [[package]] name = "egui-winit" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e84c2919cd9f3a38a91e8f84ac6a245c19251fd95226ed9fae61d5ea564fce3" dependencies = [ "accesskit_winit", "ahash", @@ -2044,9 +2049,9 @@ dependencies = [ [[package]] name = "egui_commonmark" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f169228b94d1c8eb9330b7ea1b5f65b1193b6bea95159c87f574ed4aff8c172" +checksum = "43d76bd08ab5264071aab3bd0ad0f5bdc34cf36cbb4be4c17c853a935c84d5fe" dependencies = [ "egui", "egui_commonmark_backend", @@ -2056,9 +2061,9 @@ dependencies = [ [[package]] name = "egui_commonmark_backend" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcd08f95abeb137e59c9bfdd0880d362bff74a83afe13805fde7a2d014ef773d" +checksum = "47acd9dde83a575127a498e4ef77b00377f85c258ae259214bb125c79efefd00" dependencies = [ "egui", "egui_extras", @@ -2067,8 +2072,9 @@ dependencies = [ [[package]] name = "egui_extras" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7a8198c088b1007108cb2d403bc99a5e370999b200db4f14559610d7330126" dependencies = [ "ahash", "egui", @@ -2084,8 +2090,9 @@ dependencies = [ [[package]] name = "egui_glow" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf6264cc7608e3e69a7d57a6175f438275f1b3889c1a551b418277721c95e6" dependencies = [ "ahash", "bytemuck", @@ -2101,8 +2108,9 @@ dependencies = [ [[package]] name = "egui_kittest" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27fe1ba792adf7a7bd8c51852d2dfa2a1711aea05bc532f9aa5f54a15533d33e" dependencies = [ "dify", "egui", @@ -2114,9 +2122,9 @@ dependencies = [ [[package]] name = "egui_plot" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8dca4871c15d51aadb79534dcf51a8189e5de3426ee7b465eb7db9a0a81ea67" +checksum = "c226cae80a6ee10c4d3aaf9e33bd9e9b2f1c0116b6036bdc2a1cfc9d2d0dcc10" dependencies = [ "ahash", "egui", @@ -2125,9 +2133,9 @@ dependencies = [ [[package]] name = "egui_table" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef148ce13d97a23376b92d3c5d0dddedd98c28b17053ceb326b31b92ea45d07" +checksum = "dc957dce337da3794d73f0c20a998e205850ed8a0fa1410432bddf31133667f8" dependencies = [ "egui", "serde", @@ -2136,8 +2144,9 @@ dependencies = [ [[package]] name = "egui_tiles" -version = "0.10.1" -source = "git+https://github.com/rerun-io/egui_tiles?rev=48e0ef566479000a23d8dabf84badced98f1b9a6#48e0ef566479000a23d8dabf84badced98f1b9a6" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588dcf9028464fb4d23baf1f7805c13927fb540f2f9096f7d177b814848645a3" dependencies = [ "ahash", "egui", @@ -2170,8 +2179,9 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "emath" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4fe73c1207b864ee40aa0b0c038d6092af1030744678c60188a05c28553515d" dependencies = [ "bytemuck", "serde", @@ -2216,7 +2226,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2237,7 +2247,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2248,7 +2258,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2269,7 +2279,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2286,8 +2296,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5666f8d25236293c966fbb3635eac18b04ad1914e3bab55bc7d44b9980cafcac" dependencies = [ "ab_glyph", "ahash", @@ -2305,8 +2316,9 @@ dependencies = [ [[package]] name = "epaint_default_fonts" -version = "0.29.1" -source = "git+https://github.com/emilk/egui.git?rev=0823a36952a6791a0e28e6e8eac4f35639ab3091#0823a36952a6791a0e28e6e8eac4f35639ab3091" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66f6ddac3e6ac6fd4c3d48bb8b1943472f8da0f43a4303bcd8a18aa594401c80" [[package]] name = "equivalent" @@ -2383,7 +2395,7 @@ dependencies = [ [[package]] name = "extend_viewer_ui" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "mimalloc", "re_crash_handler", @@ -2514,7 +2526,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2616,7 +2628,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2794,7 +2806,7 @@ dependencies = [ "inflections", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -2916,7 +2928,7 @@ dependencies = [ [[package]] name = "graph_lattice" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -3440,7 +3452,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -3508,7 +3520,7 @@ dependencies = [ [[package]] name = "incremental_logging" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -3676,7 +3688,7 @@ dependencies = [ "combine", "jni-sys", "log", - "thiserror", + "thiserror 1.0.65", "walkdir", "windows-sys 0.45.0", ] @@ -3731,7 +3743,8 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" [[package]] name = "kittest" version = "0.1.0" -source = "git+https://github.com/rerun-io/kittest?branch=main#06e01f17fed36a997e1541f37b2d47e3771d7533" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f659954571a3c132356bd15c25f0dcf14d270a28ec5c58797adc2f432831bed5" dependencies = [ "accesskit", "accesskit_consumer 0.25.0", @@ -3938,7 +3951,7 @@ dependencies = [ [[package]] name = "log_benchmark" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -3949,7 +3962,7 @@ dependencies = [ [[package]] name = "log_file" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -4075,7 +4088,7 @@ checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" dependencies = [ "miette-derive", "once_cell", - "thiserror", + "thiserror 1.0.65", "unicode-width", ] @@ -4087,7 +4100,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4127,14 +4140,14 @@ dependencies = [ [[package]] name = "minimal" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "rerun", ] [[package]] name = "minimal_options" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -4144,7 +4157,7 @@ dependencies = [ [[package]] name = "minimal_serve" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "rerun", ] @@ -4212,7 +4225,7 @@ dependencies = [ "rustc-hash 1.1.0", "spirv", "termcolor", - "thiserror", + "thiserror 1.0.65", "unicode-xid", ] @@ -4269,7 +4282,7 @@ dependencies = [ "ndk-sys 0.6.0+11769913", "num_enum", "raw-window-handle", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -4396,7 +4409,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4459,7 +4472,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4745,7 +4758,7 @@ dependencies = [ [[package]] name = "objectron" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -4928,7 +4941,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -4971,7 +4984,7 @@ dependencies = [ [[package]] name = "plot_dashboard_stress" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -5110,7 +5123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5148,7 +5161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5178,7 +5191,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.85", + "syn 2.0.87", "tempfile", ] @@ -5192,7 +5205,7 @@ dependencies = [ "itertools 0.13.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5313,7 +5326,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5326,7 +5339,7 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -5362,7 +5375,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls 0.23.18", "socket2", - "thiserror", + "thiserror 1.0.65", "tokio", "tracing", ] @@ -5379,7 +5392,7 @@ dependencies = [ "rustc-hash 2.0.0", "rustls 0.23.18", "slab", - "thiserror", + "thiserror 1.0.65", "tinyvec", "tracing", ] @@ -5464,7 +5477,7 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "raw_mesh" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "bytes", @@ -5507,7 +5520,7 @@ checksum = "3b42e27ef78c35d3998403c1d26f3efd9e135d3e5121b0a4845cc5cc27547f4f" [[package]] name = "re_analytics" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "crossbeam", "directories", @@ -5518,7 +5531,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "thiserror", + "thiserror 1.0.65", "time", "url", "uuid", @@ -5555,7 +5568,7 @@ dependencies = [ [[package]] name = "re_blueprint_tree" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "itertools 0.13.0", @@ -5574,14 +5587,14 @@ dependencies = [ [[package]] name = "re_build_info" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "serde", ] [[package]] name = "re_build_tools" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -5594,7 +5607,7 @@ dependencies = [ [[package]] name = "re_capabilities" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "document-features", "egui", @@ -5603,14 +5616,14 @@ dependencies = [ [[package]] name = "re_case" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "convert_case", ] [[package]] name = "re_chunk" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -5634,12 +5647,12 @@ dependencies = [ "re_types_core", "serde", "similar-asserts", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "re_chunk_store" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -5664,14 +5677,14 @@ dependencies = [ "re_types", "re_types_core", "similar-asserts", - "thiserror", + "thiserror 1.0.65", "tinyvec", "web-time", ] [[package]] name = "re_chunk_store_ui" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_extras", @@ -5686,7 +5699,7 @@ dependencies = [ [[package]] name = "re_component_ui" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_extras", @@ -5705,7 +5718,7 @@ dependencies = [ [[package]] name = "re_context_menu" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_tiles", @@ -5726,7 +5739,7 @@ dependencies = [ [[package]] name = "re_crash_handler" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "backtrace", "econtext", @@ -5739,7 +5752,7 @@ dependencies = [ [[package]] name = "re_data_loader" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -5761,14 +5774,14 @@ dependencies = [ "re_tracing", "re_types", "tempfile", - "thiserror", + "thiserror 1.0.65", "uuid", "walkdir", ] [[package]] name = "re_data_source" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "itertools 0.13.0", @@ -5786,7 +5799,7 @@ dependencies = [ [[package]] name = "re_data_ui" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -5816,7 +5829,7 @@ dependencies = [ [[package]] name = "re_dataframe" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "itertools 0.13.0", @@ -5840,7 +5853,7 @@ dependencies = [ [[package]] name = "re_dev_tools" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "argh", @@ -5867,7 +5880,7 @@ dependencies = [ [[package]] name = "re_entity_db" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -5894,27 +5907,27 @@ dependencies = [ "re_types_core", "serde", "similar-asserts", - "thiserror", + "thiserror 1.0.65", "web-time", ] [[package]] name = "re_error" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", ] [[package]] name = "re_format" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "num-traits", ] [[package]] name = "re_format_arrow" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "comfy-table", "re_arrow2", @@ -5924,7 +5937,7 @@ dependencies = [ [[package]] name = "re_grpc_client" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "re_chunk", "re_error", @@ -5934,7 +5947,7 @@ dependencies = [ "re_protos", "re_smart_channel", "re_types", - "thiserror", + "thiserror 1.0.65", "tokio", "tokio-stream", "tonic", @@ -5945,7 +5958,7 @@ dependencies = [ [[package]] name = "re_int_histogram" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "criterion", "insta", @@ -5956,7 +5969,7 @@ dependencies = [ [[package]] name = "re_log" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "env_logger", "js-sys", @@ -5969,7 +5982,7 @@ dependencies = [ [[package]] name = "re_log_encoding" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "criterion", "ehttp", @@ -5988,7 +6001,7 @@ dependencies = [ "re_types", "rmp-serde", "serde_test", - "thiserror", + "thiserror 1.0.65", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -5997,7 +6010,7 @@ dependencies = [ [[package]] name = "re_log_types" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6027,7 +6040,7 @@ dependencies = [ "serde_bytes", "similar-asserts", "static_assertions", - "thiserror", + "thiserror 1.0.65", "time", "typenum", "uuid", @@ -6046,7 +6059,7 @@ dependencies = [ [[package]] name = "re_memory" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "backtrace", @@ -6076,22 +6089,22 @@ dependencies = [ "num-rational", "serde", "serde_json", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "re_protos" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "prost", - "thiserror", + "thiserror 1.0.65", "tonic", "tonic-web-wasm-client", ] [[package]] name = "re_protos_builder" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "camino", "prost-build", @@ -6101,7 +6114,7 @@ dependencies = [ [[package]] name = "re_query" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6127,7 +6140,7 @@ dependencies = [ "re_types_core", "seq-macro", "similar-asserts", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -6155,7 +6168,7 @@ dependencies = [ [[package]] name = "re_renderer" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6191,7 +6204,7 @@ dependencies = [ "slotmap", "smallvec", "static_assertions", - "thiserror", + "thiserror 1.0.65", "tinystl", "tobj", "type-map", @@ -6207,7 +6220,7 @@ dependencies = [ [[package]] name = "re_renderer_examples" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6231,7 +6244,7 @@ dependencies = [ [[package]] name = "re_sdk" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "crossbeam", @@ -6260,13 +6273,13 @@ dependencies = [ "re_web_viewer_server", "re_ws_comms", "similar-asserts", - "thiserror", + "thiserror 1.0.65", "webbrowser", ] [[package]] name = "re_sdk_comms" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "crossbeam", @@ -6277,12 +6290,12 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_smart_channel", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "re_selection_panel" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_tiles", @@ -6309,7 +6322,7 @@ dependencies = [ [[package]] name = "re_smart_channel" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "crossbeam", "parking_lot", @@ -6320,7 +6333,7 @@ dependencies = [ [[package]] name = "re_string_interner" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "nohash-hasher", @@ -6332,7 +6345,7 @@ dependencies = [ [[package]] name = "re_time_panel" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "criterion", @@ -6361,7 +6374,7 @@ dependencies = [ [[package]] name = "re_tracing" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "puffin", "puffin_http", @@ -6372,7 +6385,7 @@ dependencies = [ [[package]] name = "re_tuid" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "criterion", "document-features", @@ -6385,7 +6398,7 @@ dependencies = [ [[package]] name = "re_types" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "array-init", @@ -6421,13 +6434,13 @@ dependencies = [ "serde", "similar-asserts", "smallvec", - "thiserror", + "thiserror 1.0.65", "uuid", ] [[package]] name = "re_types_builder" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "arrow", @@ -6449,7 +6462,7 @@ dependencies = [ "re_tracing", "rust-format", "serde", - "syn 2.0.85", + "syn 2.0.87", "tempfile", "toml", "unindent", @@ -6458,7 +6471,7 @@ dependencies = [ [[package]] name = "re_types_core" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "arrow", @@ -6478,12 +6491,12 @@ dependencies = [ "re_tuid", "serde", "smallvec", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "re_ui" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "eframe", "egui", @@ -6510,7 +6523,7 @@ dependencies = [ [[package]] name = "re_video" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "bit-vec", "cfg_aliases 0.2.1", @@ -6531,14 +6544,14 @@ dependencies = [ "re_rav1d", "re_tracing", "serde", - "thiserror", + "thiserror 1.0.65", "wasm-bindgen", "web-sys", ] [[package]] name = "re_view" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "arrow", @@ -6563,7 +6576,7 @@ dependencies = [ [[package]] name = "re_view_bar_chart" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_plot", @@ -6581,7 +6594,7 @@ dependencies = [ [[package]] name = "re_view_dataframe" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "egui", @@ -6599,12 +6612,12 @@ dependencies = [ "re_ui", "re_viewer_context", "re_viewport_blueprint", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "re_view_graph" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "egui", @@ -6628,7 +6641,7 @@ dependencies = [ [[package]] name = "re_view_map" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "bytemuck", "egui", @@ -6652,7 +6665,7 @@ dependencies = [ [[package]] name = "re_view_spatial" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6689,14 +6702,14 @@ dependencies = [ "re_viewport_blueprint", "serde", "smallvec", - "thiserror", + "thiserror 1.0.65", "vec1", "web-time", ] [[package]] name = "re_view_tensor" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "bytemuck", @@ -6714,13 +6727,13 @@ dependencies = [ "re_view", "re_viewer_context", "re_viewport_blueprint", - "thiserror", + "thiserror 1.0.65", "wgpu", ] [[package]] name = "re_view_text_document" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_commonmark", @@ -6735,7 +6748,7 @@ dependencies = [ [[package]] name = "re_view_text_log" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_extras", @@ -6755,7 +6768,7 @@ dependencies = [ [[package]] name = "re_view_time_series" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "egui", "egui_plot", @@ -6777,7 +6790,7 @@ dependencies = [ [[package]] name = "re_viewer" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6844,7 +6857,7 @@ dependencies = [ "serde_json", "strum", "strum_macros", - "thiserror", + "thiserror 1.0.65", "uuid", "wasm-bindgen", "wasm-bindgen-futures", @@ -6855,7 +6868,7 @@ dependencies = [ [[package]] name = "re_viewer_context" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "anyhow", @@ -6872,6 +6885,7 @@ dependencies = [ "emath", "glam", "half", + "home", "image", "indexmap 2.6.0", "itertools 0.13.0", @@ -6903,7 +6917,7 @@ dependencies = [ "slotmap", "smallvec", "strum_macros", - "thiserror", + "thiserror 1.0.65", "uuid", "wasm-bindgen-futures", "wgpu", @@ -6911,7 +6925,7 @@ dependencies = [ [[package]] name = "re_viewport" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "egui", @@ -6934,7 +6948,7 @@ dependencies = [ [[package]] name = "re_viewport_blueprint" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "egui", @@ -6955,23 +6969,23 @@ dependencies = [ "re_viewer_context", "slotmap", "smallvec", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "re_web_viewer_server" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "document-features", "re_analytics", "re_log", - "thiserror", + "thiserror 1.0.65", "tiny_http", ] [[package]] name = "re_ws_comms" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "bincode", @@ -6985,7 +6999,7 @@ dependencies = [ "re_memory", "re_smart_channel", "re_tracing", - "thiserror", + "thiserror 1.0.65", "tungstenite", ] @@ -7015,7 +7029,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.65", ] [[package]] @@ -7163,12 +7177,12 @@ dependencies = [ "reqwest 0.11.27", "serde", "task-local-extensions", - "thiserror", + "thiserror 1.0.65", ] [[package]] name = "rerun" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7209,7 +7223,7 @@ dependencies = [ [[package]] name = "rerun-cli" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "document-features", "mimalloc", @@ -7224,7 +7238,7 @@ dependencies = [ [[package]] name = "rerun-loader-rust-file" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "argh", @@ -7233,7 +7247,7 @@ dependencies = [ [[package]] name = "rerun_c" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "ahash", "infer", @@ -7247,7 +7261,7 @@ dependencies = [ [[package]] name = "rerun_py" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "arrow", "crossbeam", @@ -7380,7 +7394,7 @@ dependencies = [ [[package]] name = "roundtrip_annotation_context" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7390,7 +7404,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows2d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7400,7 +7414,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows3d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7410,7 +7424,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes2d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7420,7 +7434,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes3d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7430,7 +7444,7 @@ dependencies = [ [[package]] name = "roundtrip_depth_image" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7441,7 +7455,7 @@ dependencies = [ [[package]] name = "roundtrip_disconnected_space" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7451,7 +7465,7 @@ dependencies = [ [[package]] name = "roundtrip_image" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7464,7 +7478,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips2d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7474,7 +7488,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips3d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7484,7 +7498,7 @@ dependencies = [ [[package]] name = "roundtrip_pinhole" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7494,7 +7508,7 @@ dependencies = [ [[package]] name = "roundtrip_points2d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7504,7 +7518,7 @@ dependencies = [ [[package]] name = "roundtrip_points3d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7514,7 +7528,7 @@ dependencies = [ [[package]] name = "roundtrip_segmentation_image" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7525,7 +7539,7 @@ dependencies = [ [[package]] name = "roundtrip_tensor" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7536,7 +7550,7 @@ dependencies = [ [[package]] name = "roundtrip_text_document" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7546,7 +7560,7 @@ dependencies = [ [[package]] name = "roundtrip_text_log" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7556,7 +7570,7 @@ dependencies = [ [[package]] name = "roundtrip_transform3d" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7566,7 +7580,7 @@ dependencies = [ [[package]] name = "roundtrip_view_coordinates" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7576,7 +7590,7 @@ dependencies = [ [[package]] name = "roundtrip_visible_time_ranges" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -7592,7 +7606,7 @@ checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" [[package]] name = "run_wasm" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "cargo-run-wasm", "pico-args", @@ -7641,7 +7655,7 @@ dependencies = [ "cargo-manifest", "cargo_metadata 0.18.1", "serde", - "thiserror", + "thiserror 1.0.65", "toml", "tracing", ] @@ -7880,7 +7894,7 @@ checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -7903,7 +7917,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -7984,7 +7998,7 @@ dependencies = [ [[package]] name = "shared_recording" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "rerun", ] @@ -8108,7 +8122,7 @@ dependencies = [ "log", "memmap2 0.9.5", "rustix", - "thiserror", + "thiserror 1.0.65", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -8163,7 +8177,7 @@ dependencies = [ [[package]] name = "snippets" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "itertools 0.13.0", "ndarray", @@ -8187,7 +8201,7 @@ dependencies = [ [[package]] name = "spawn_viewer" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "rerun", ] @@ -8220,7 +8234,7 @@ dependencies = [ "serde", "sha-1", "sha2", - "thiserror", + "thiserror 1.0.65", "xxhash-rust", ] @@ -8238,7 +8252,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdio" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "rerun", ] @@ -8277,7 +8291,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -8315,9 +8329,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.85" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -8347,7 +8361,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -8415,7 +8429,7 @@ dependencies = [ [[package]] name = "template" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "rerun", ] @@ -8431,7 +8445,7 @@ dependencies = [ [[package]] name = "test_api" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -8446,7 +8460,7 @@ dependencies = [ [[package]] name = "test_data_density_graph" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "rand", @@ -8456,7 +8470,7 @@ dependencies = [ [[package]] name = "test_image_memory" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "mimalloc", "re_format", @@ -8465,7 +8479,7 @@ dependencies = [ [[package]] name = "test_pinhole_projection" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -8476,7 +8490,7 @@ dependencies = [ [[package]] name = "test_send_columns" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "re_chunk", "rerun", @@ -8484,7 +8498,7 @@ dependencies = [ [[package]] name = "test_ui_wakeup" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = [ "anyhow", "clap", @@ -8498,7 +8512,16 @@ version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.65", +] + +[[package]] +name = "thiserror" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +dependencies = [ + "thiserror-impl 2.0.7", ] [[package]] @@ -8509,7 +8532,18 @@ checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] @@ -8698,7 +8732,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -8822,7 +8856,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -8841,7 +8875,7 @@ dependencies = [ "httparse", "js-sys", "pin-project", - "thiserror", + "thiserror 1.0.65", "tonic", "tower-service", "wasm-bindgen", @@ -8916,7 +8950,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -8956,7 +8990,7 @@ dependencies = [ "rustls 0.23.18", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.65", "utf-8", "webpki-roots 0.26.6", ] @@ -9187,9 +9221,9 @@ dependencies = [ [[package]] name = "walkers" -version = "0.29.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0688ad9bfb3bd49d997a6fb831e9ef21e251f4698c07e2f9902dcdb72d254bd" +checksum = "70ca9bf7f5ff8a6d57de654d06fb25e5c6d60e0acc7e938d6fc15324b8e22a2f" dependencies = [ "egui", "egui_extras", @@ -9201,7 +9235,7 @@ dependencies = [ "lru", "reqwest 0.11.27", "reqwest-middleware", - "thiserror", + "thiserror 2.0.7", "tokio", "wasm-bindgen-futures", ] @@ -9231,7 +9265,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -9271,7 +9305,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-shared", ] @@ -9339,7 +9373,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9646,7 +9680,7 @@ dependencies = [ "raw-window-handle", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.65", "wgpu-hal", "wgpu-types", ] @@ -9685,7 +9719,7 @@ dependencies = [ "renderdoc-sys", "rustc-hash 1.1.0", "smallvec", - "thiserror", + "thiserror 1.0.65", "wasm-bindgen", "web-sys", "wgpu-types", @@ -9784,7 +9818,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -9795,7 +9829,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -10244,7 +10278,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "synstructure", ] @@ -10304,7 +10338,7 @@ checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "zbus-lockstep", "zbus_xml", "zvariant", @@ -10319,7 +10353,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "zvariant_utils", ] @@ -10365,7 +10399,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -10385,7 +10419,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "synstructure", ] @@ -10414,7 +10448,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] [[package]] @@ -10467,7 +10501,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", "zvariant_utils", ] @@ -10479,5 +10513,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.85", + "syn 2.0.87", ] diff --git a/Cargo.toml b/Cargo.toml index d30bcb6219b2..7a43f9933c01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,8 +30,8 @@ include = [ ] license = "MIT OR Apache-2.0" repository = "https://github.com/rerun-io/rerun" -rust-version = "1.80" -version = "0.21.0-alpha.1+dev" +rust-version = "1.81" +version = "0.22.0-alpha.1+dev" [workspace.dependencies] # When using alpha-release, always use exact version, e.g. `version = "=0.x.y-alpha.z" @@ -40,78 +40,78 @@ version = "0.21.0-alpha.1+dev" # re_log_types 0.3.0-alpha.0, NOT 0.3.0-alpha.4 even though it is newer and semver-compatible. # crates/build: -re_build_info = { path = "crates/build/re_build_info", version = "=0.21.0-alpha.1", default-features = false } -re_build_tools = { path = "crates/build/re_build_tools", version = "=0.21.0-alpha.1", default-features = false } -re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.21.0-alpha.1", default-features = false } -re_protos_builder = { path = "crates/build/re_protos_builder", version = "=0.21.0-alpha.1", default-features = false } -re_types_builder = { path = "crates/build/re_types_builder", version = "=0.21.0-alpha.1", default-features = false } +re_build_info = { path = "crates/build/re_build_info", version = "=0.22.0-alpha.1", default-features = false } +re_build_tools = { path = "crates/build/re_build_tools", version = "=0.22.0-alpha.1", default-features = false } +re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.22.0-alpha.1", default-features = false } +re_protos_builder = { path = "crates/build/re_protos_builder", version = "=0.22.0-alpha.1", default-features = false } +re_types_builder = { path = "crates/build/re_types_builder", version = "=0.22.0-alpha.1", default-features = false } # crates/store: -re_chunk = { path = "crates/store/re_chunk", version = "=0.21.0-alpha.1", default-features = false } -re_chunk_store = { path = "crates/store/re_chunk_store", version = "=0.21.0-alpha.1", default-features = false } -re_data_loader = { path = "crates/store/re_data_loader", version = "=0.21.0-alpha.1", default-features = false } -re_data_source = { path = "crates/store/re_data_source", version = "=0.21.0-alpha.1", default-features = false } -re_dataframe = { path = "crates/store/re_dataframe", version = "=0.21.0-alpha.1", default-features = false } -re_entity_db = { path = "crates/store/re_entity_db", version = "=0.21.0-alpha.1", default-features = false } -re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.21.0-alpha.1", default-features = false } -re_grpc_client = { path = "crates/store/re_grpc_client", version = "=0.21.0-alpha.1", default-features = false } -re_protos = { path = "crates/store/re_protos", version = "=0.21.0-alpha.1", default-features = false } -re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.21.0-alpha.1", default-features = false } -re_log_types = { path = "crates/store/re_log_types", version = "=0.21.0-alpha.1", default-features = false } -re_query = { path = "crates/store/re_query", version = "=0.21.0-alpha.1", default-features = false } -re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.21.0-alpha.1", default-features = false } -re_types = { path = "crates/store/re_types", version = "=0.21.0-alpha.1", default-features = false } -re_types_core = { path = "crates/store/re_types_core", version = "=0.21.0-alpha.1", default-features = false } -re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.21.0-alpha.1", default-features = false } +re_chunk = { path = "crates/store/re_chunk", version = "=0.22.0-alpha.1", default-features = false } +re_chunk_store = { path = "crates/store/re_chunk_store", version = "=0.22.0-alpha.1", default-features = false } +re_data_loader = { path = "crates/store/re_data_loader", version = "=0.22.0-alpha.1", default-features = false } +re_data_source = { path = "crates/store/re_data_source", version = "=0.22.0-alpha.1", default-features = false } +re_dataframe = { path = "crates/store/re_dataframe", version = "=0.22.0-alpha.1", default-features = false } +re_entity_db = { path = "crates/store/re_entity_db", version = "=0.22.0-alpha.1", default-features = false } +re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.22.0-alpha.1", default-features = false } +re_grpc_client = { path = "crates/store/re_grpc_client", version = "=0.22.0-alpha.1", default-features = false } +re_protos = { path = "crates/store/re_protos", version = "=0.22.0-alpha.1", default-features = false } +re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.22.0-alpha.1", default-features = false } +re_log_types = { path = "crates/store/re_log_types", version = "=0.22.0-alpha.1", default-features = false } +re_query = { path = "crates/store/re_query", version = "=0.22.0-alpha.1", default-features = false } +re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.22.0-alpha.1", default-features = false } +re_types = { path = "crates/store/re_types", version = "=0.22.0-alpha.1", default-features = false } +re_types_core = { path = "crates/store/re_types_core", version = "=0.22.0-alpha.1", default-features = false } +re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.22.0-alpha.1", default-features = false } # crates/top: -re_sdk = { path = "crates/top/re_sdk", version = "=0.21.0-alpha.1", default-features = false } -rerun = { path = "crates/top/rerun", version = "=0.21.0-alpha.1", default-features = false } -rerun_c = { path = "crates/top/rerun_c", version = "=0.21.0-alpha.1", default-features = false } -rerun-cli = { path = "crates/top/rerun-cli", version = "=0.21.0-alpha.1", default-features = false } +re_sdk = { path = "crates/top/re_sdk", version = "=0.22.0-alpha.1", default-features = false } +rerun = { path = "crates/top/rerun", version = "=0.22.0-alpha.1", default-features = false } +rerun_c = { path = "crates/top/rerun_c", version = "=0.22.0-alpha.1", default-features = false } +rerun-cli = { path = "crates/top/rerun-cli", version = "=0.22.0-alpha.1", default-features = false } # crates/utils: -re_analytics = { path = "crates/utils/re_analytics", version = "=0.21.0-alpha.1", default-features = false } -re_capabilities = { path = "crates/utils/re_capabilities", version = "=0.21.0-alpha.1", default-features = false } -re_case = { path = "crates/utils/re_case", version = "=0.21.0-alpha.1", default-features = false } -re_crash_handler = { path = "crates/utils/re_crash_handler", version = "=0.21.0-alpha.1", default-features = false } -re_error = { path = "crates/utils/re_error", version = "=0.21.0-alpha.1", default-features = false } -re_format = { path = "crates/utils/re_format", version = "=0.21.0-alpha.1", default-features = false } -re_int_histogram = { path = "crates/utils/re_int_histogram", version = "=0.21.0-alpha.1", default-features = false } -re_log = { path = "crates/utils/re_log", version = "=0.21.0-alpha.1", default-features = false } -re_memory = { path = "crates/utils/re_memory", version = "=0.21.0-alpha.1", default-features = false } -re_smart_channel = { path = "crates/utils/re_smart_channel", version = "=0.21.0-alpha.1", default-features = false } -re_string_interner = { path = "crates/utils/re_string_interner", version = "=0.21.0-alpha.1", default-features = false } -re_tracing = { path = "crates/utils/re_tracing", version = "=0.21.0-alpha.1", default-features = false } -re_tuid = { path = "crates/utils/re_tuid", version = "=0.21.0-alpha.1", default-features = false } -re_video = { path = "crates/utils/re_video", version = "=0.21.0-alpha.1", default-features = false } +re_analytics = { path = "crates/utils/re_analytics", version = "=0.22.0-alpha.1", default-features = false } +re_capabilities = { path = "crates/utils/re_capabilities", version = "=0.22.0-alpha.1", default-features = false } +re_case = { path = "crates/utils/re_case", version = "=0.22.0-alpha.1", default-features = false } +re_crash_handler = { path = "crates/utils/re_crash_handler", version = "=0.22.0-alpha.1", default-features = false } +re_error = { path = "crates/utils/re_error", version = "=0.22.0-alpha.1", default-features = false } +re_format = { path = "crates/utils/re_format", version = "=0.22.0-alpha.1", default-features = false } +re_int_histogram = { path = "crates/utils/re_int_histogram", version = "=0.22.0-alpha.1", default-features = false } +re_log = { path = "crates/utils/re_log", version = "=0.22.0-alpha.1", default-features = false } +re_memory = { path = "crates/utils/re_memory", version = "=0.22.0-alpha.1", default-features = false } +re_smart_channel = { path = "crates/utils/re_smart_channel", version = "=0.22.0-alpha.1", default-features = false } +re_string_interner = { path = "crates/utils/re_string_interner", version = "=0.22.0-alpha.1", default-features = false } +re_tracing = { path = "crates/utils/re_tracing", version = "=0.22.0-alpha.1", default-features = false } +re_tuid = { path = "crates/utils/re_tuid", version = "=0.22.0-alpha.1", default-features = false } +re_video = { path = "crates/utils/re_video", version = "=0.22.0-alpha.1", default-features = false } # crates/viewer: -re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.21.0-alpha.1", default-features = false } -re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.21.0-alpha.1", default-features = false } -re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.21.0-alpha.1", default-features = false } -re_data_ui = { path = "crates/viewer/re_data_ui", version = "=0.21.0-alpha.1", default-features = false } -re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.21.0-alpha.1", default-features = false } -re_renderer = { path = "crates/viewer/re_renderer", version = "=0.21.0-alpha.1", default-features = false } -re_renderer_examples = { path = "crates/viewer/re_renderer_examples", version = "=0.21.0-alpha.1", default-features = false } -re_selection_panel = { path = "crates/viewer/re_selection_panel", version = "=0.21.0-alpha.1", default-features = false } -re_view = { path = "crates/viewer/re_view", version = "=0.21.0-alpha.1", default-features = false } -re_view_bar_chart = { path = "crates/viewer/re_view_bar_chart", version = "=0.21.0-alpha.1", default-features = false } -re_view_spatial = { path = "crates/viewer/re_view_spatial", version = "=0.21.0-alpha.1", default-features = false } -re_view_dataframe = { path = "crates/viewer/re_view_dataframe", version = "=0.21.0-alpha.1", default-features = false } -re_view_graph = { path = "crates/viewer/re_view_graph", version = "=0.21.0-alpha.1", default-features = false } -re_view_map = { path = "crates/viewer/re_view_map", version = "=0.21.0-alpha.1", default-features = false } -re_view_tensor = { path = "crates/viewer/re_view_tensor", version = "=0.21.0-alpha.1", default-features = false } -re_view_text_document = { path = "crates/viewer/re_view_text_document", version = "=0.21.0-alpha.1", default-features = false } -re_view_text_log = { path = "crates/viewer/re_view_text_log", version = "=0.21.0-alpha.1", default-features = false } -re_view_time_series = { path = "crates/viewer/re_view_time_series", version = "=0.21.0-alpha.1", default-features = false } -re_time_panel = { path = "crates/viewer/re_time_panel", version = "=0.21.0-alpha.1", default-features = false } -re_ui = { path = "crates/viewer/re_ui", version = "=0.21.0-alpha.1", default-features = false } -re_viewer = { path = "crates/viewer/re_viewer", version = "=0.21.0-alpha.1", default-features = false } -re_viewer_context = { path = "crates/viewer/re_viewer_context", version = "=0.21.0-alpha.1", default-features = false } -re_viewport = { path = "crates/viewer/re_viewport", version = "=0.21.0-alpha.1", default-features = false } -re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version = "=0.21.0-alpha.1", default-features = false } -re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.21.0-alpha.1", default-features = false } +re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.22.0-alpha.1", default-features = false } +re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.22.0-alpha.1", default-features = false } +re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.22.0-alpha.1", default-features = false } +re_data_ui = { path = "crates/viewer/re_data_ui", version = "=0.22.0-alpha.1", default-features = false } +re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.22.0-alpha.1", default-features = false } +re_renderer = { path = "crates/viewer/re_renderer", version = "=0.22.0-alpha.1", default-features = false } +re_renderer_examples = { path = "crates/viewer/re_renderer_examples", version = "=0.22.0-alpha.1", default-features = false } +re_selection_panel = { path = "crates/viewer/re_selection_panel", version = "=0.22.0-alpha.1", default-features = false } +re_view = { path = "crates/viewer/re_view", version = "=0.22.0-alpha.1", default-features = false } +re_view_bar_chart = { path = "crates/viewer/re_view_bar_chart", version = "=0.22.0-alpha.1", default-features = false } +re_view_spatial = { path = "crates/viewer/re_view_spatial", version = "=0.22.0-alpha.1", default-features = false } +re_view_dataframe = { path = "crates/viewer/re_view_dataframe", version = "=0.22.0-alpha.1", default-features = false } +re_view_graph = { path = "crates/viewer/re_view_graph", version = "=0.22.0-alpha.1", default-features = false } +re_view_map = { path = "crates/viewer/re_view_map", version = "=0.22.0-alpha.1", default-features = false } +re_view_tensor = { path = "crates/viewer/re_view_tensor", version = "=0.22.0-alpha.1", default-features = false } +re_view_text_document = { path = "crates/viewer/re_view_text_document", version = "=0.22.0-alpha.1", default-features = false } +re_view_text_log = { path = "crates/viewer/re_view_text_log", version = "=0.22.0-alpha.1", default-features = false } +re_view_time_series = { path = "crates/viewer/re_view_time_series", version = "=0.22.0-alpha.1", default-features = false } +re_time_panel = { path = "crates/viewer/re_time_panel", version = "=0.22.0-alpha.1", default-features = false } +re_ui = { path = "crates/viewer/re_ui", version = "=0.22.0-alpha.1", default-features = false } +re_viewer = { path = "crates/viewer/re_viewer", version = "=0.22.0-alpha.1", default-features = false } +re_viewer_context = { path = "crates/viewer/re_viewer_context", version = "=0.22.0-alpha.1", default-features = false } +re_viewport = { path = "crates/viewer/re_viewport", version = "=0.22.0-alpha.1", default-features = false } +re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version = "=0.22.0-alpha.1", default-features = false } +re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.22.0-alpha.1", default-features = false } # Rerun crates in other repos: ewebsock = "0.8.0" @@ -124,27 +124,27 @@ dav1d = { package = "re_rav1d", version = "0.1.3", default-features = false } # dav1d = { version = "0.10.3" } # Requires separate install of `dav1d` library. Fast in debug builds. Useful for development. # egui-crates: -ecolor = "0.29.1" -eframe = { version = "0.29.1", default-features = false, features = [ +ecolor = "0.30.0" +eframe = { version = "0.30.0", default-features = false, features = [ "accesskit", "default_fonts", "wayland", "x11", ] } -egui = { version = "0.29.1", features = [ +egui = { version = "0.30.0", features = [ "callstack", "color-hex", "log", "rayon", ] } -egui_commonmark = { version = "0.18", default-features = false } -egui_extras = { version = "0.29.1", features = ["http", "image", "serde"] } -egui_kittest = { version = "0.29.1", features = ["wgpu", "snapshot"] } -egui_plot = "0.29.0" # https://github.com/emilk/egui_plot -egui_table = "0.1.0" # https://github.com/rerun-io/egui_table -egui_tiles = "0.10.1" # https://github.com/rerun-io/egui_tiles -egui-wgpu = "0.29.1" -emath = "0.29.1" +egui_commonmark = { version = "0.19", default-features = false } +egui_extras = { version = "0.30.0", features = ["http", "image", "serde"] } +egui_kittest = { version = "0.30.0", features = ["wgpu", "snapshot"] } +egui_plot = "0.30.0" # https://github.com/emilk/egui_plot +egui_table = "0.2.0" # https://github.com/rerun-io/egui_table +egui_tiles = "0.11.0" # https://github.com/rerun-io/egui_tiles +egui-wgpu = "0.30.0" +emath = "0.30.0" # All of our direct external dependencies should be found here: ahash = "0.8" @@ -193,6 +193,7 @@ glob = "0.3" gltf = "1.1" half = "2.3.1" hexasphere = "14.1.0" +home = "=0.5.9" image = { version = "0.25", default-features = false } indent = "0.1" indexmap = "2.1" # Version chosen to align with other dependencies @@ -294,7 +295,7 @@ url = "2.3" uuid = "1.1" vec1 = "1.8" walkdir = "2.0" -walkers = "0.29" +walkers = "0.32" # NOTE: `rerun_js/web-viewer/build-wasm.mjs` is HIGHLY sensitive to changes in `wasm-bindgen`. # Whenever updating `wasm-bindgen`, update this and the narrower dependency specifications in # `crates/viewer/re_viewer/Cargo.toml`, and make sure that the build script still works. @@ -383,6 +384,7 @@ rust_2021_prelude_collisions = "warn" semicolon_in_expressions_from_macros = "warn" trivial_numeric_casts = "warn" unsafe_op_in_unsafe_fn = "warn" # `unsafe_op_in_unsafe_fn` may become the default in future Rust versions: https://github.com/rust-lang/rust/issues/71668 +unexpected_cfgs = "deny" unused_extern_crates = "warn" unused_import_braces = "warn" unused_lifetimes = "warn" @@ -467,7 +469,6 @@ match_same_arms = "warn" match_wild_err_arm = "warn" match_wildcard_for_single_variants = "warn" mem_forget = "warn" -mismatched_target_os = "warn" mismatching_type_param_order = "warn" missing_enforced_import_renames = "warn" missing_safety_doc = "warn" @@ -496,6 +497,7 @@ ref_option_ref = "warn" rest_pat_in_fully_bound_structs = "warn" same_functions_in_if_condition = "warn" semicolon_if_nothing_returned = "warn" +set_contains_or_insert = "warn" should_panic_without_expect = "warn" single_char_pattern = "warn" single_match_else = "warn" @@ -555,13 +557,13 @@ significant_drop_tightening = "allow" # An update of parking_lot made this trigg # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 -eframe = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 -egui = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 -egui_kittest = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 -emath = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28e6e8eac4f35639ab3091" } # egui master 2024-12-16 15:08 +# ecolor = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release +# eframe = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release +# egui = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release +# egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release +# egui_kittest = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release +# egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release +# emath = { git = "https://github.com/emilk/egui.git", rev = "0fb340fe89e9476b2fec15c2eff1405e51e5c04e" } # egui master 2024-12-16 just pre 0.30.0 release # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } @@ -575,7 +577,7 @@ emath = { git = "https://github.com/emilk/egui.git", rev = "0823a36952a6791a0e28 # egui_plot = { git = "https://github.com/emilk/egui_plot.git", rev = "1f6ae49a5f6bf43a869c215dea0d3028be8d742a" } # egui_plot = { path = "../../egui_plot/egui_plot" } -egui_tiles = { git = "https://github.com/rerun-io/egui_tiles", rev = "48e0ef566479000a23d8dabf84badced98f1b9a6" } # https://github.com/rerun-io/egui_tiles/pull/89 2024-11-19 +# egui_tiles = { git = "https://github.com/rerun-io/egui_tiles", rev = "48e0ef566479000a23d8dabf84badced98f1b9a6" } # https://github.com/rerun-io/egui_tiles/pull/89 2024-11-19 #egui_tiles = { path = "../egui_tiles" } # egui_commonmark = { git = "https://github.com/rerun-io/egui_commonmark", rev = "7a9dc755bfa351a3796274cb8ca87129b051c084" } # https://github.com/lampsitter/egui_commonmark/pull/65 diff --git a/clippy.toml b/clippy.toml index b9f05c287f9e..ec39e9871d72 100644 --- a/clippy.toml +++ b/clippy.toml @@ -3,7 +3,7 @@ # ----------------------------------------------------------------------------- # Section identical to the main scripts/clippy_wasm/clippy.toml: -msrv = "1.80" +msrv = "1.81" allow-unwrap-in-tests = true diff --git a/crates/build/re_dev_tools/src/build_web_viewer/lib.rs b/crates/build/re_dev_tools/src/build_web_viewer/lib.rs index 3a0973bc56bc..8fa7c622d433 100644 --- a/crates/build/re_dev_tools/src/build_web_viewer/lib.rs +++ b/crates/build/re_dev_tools/src/build_web_viewer/lib.rs @@ -124,7 +124,7 @@ pub fn build( cmd.arg("--no-default-features"); } if !features.is_empty() { - cmd.arg(&format!("--features={features}")); + cmd.arg(format!("--features={features}")); } if profile == Profile::Release { cmd.arg("--release"); diff --git a/crates/build/re_protos_builder/src/lib.rs b/crates/build/re_protos_builder/src/lib.rs index 6f382e89fb48..ddbbce158a99 100644 --- a/crates/build/re_protos_builder/src/lib.rs +++ b/crates/build/re_protos_builder/src/lib.rs @@ -32,7 +32,7 @@ pub fn generate_rust_code( std::process::exit(1); } _ => { - panic!("{err:?}"); + panic!("{err}"); } } } diff --git a/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs b/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs index 47fe4e3cfeac..322785041e9c 100644 --- a/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs +++ b/crates/build/re_types_builder/src/codegen/docs/snippets_ref.rs @@ -631,9 +631,8 @@ fn is_speculative(any_name: &str) -> anyhow::Result { let minor: u32 = env!("CARGO_PKG_VERSION_MINOR") .parse() .context("couldn't parse minor crate version")?; - let pre = env!("CARGO_PKG_VERSION_PRE"); - minor < 21 || !pre.is_empty() + minor < 21 }; const RELEASED_IN_0_21: &[&str] = &[ diff --git a/crates/build/re_types_builder/src/codegen/rust/arrow.rs b/crates/build/re_types_builder/src/codegen/rust/arrow.rs index 890f9d95004b..303dbf684637 100644 --- a/crates/build/re_types_builder/src/codegen/rust/arrow.rs +++ b/crates/build/re_types_builder/src/codegen/rust/arrow.rs @@ -7,7 +7,7 @@ use quote::quote; /// `(Datatype, is_recursive)` /// /// If `is_recursive` is set to `true`, -/// then the generate code will often be shorter, as it it will +/// then the generated code will often be shorter, as it will /// defer to calling `arrow_datatype()` on the inner type. pub struct ArrowDataTypeTokenizer<'a>(pub &'a ::arrow2::datatypes::DataType, pub bool); diff --git a/crates/build/re_types_builder/src/codegen/rust/serializer.rs b/crates/build/re_types_builder/src/codegen/rust/serializer.rs index 8f8063923dc4..6156c4895bc4 100644 --- a/crates/build/re_types_builder/src/codegen/rust/serializer.rs +++ b/crates/build/re_types_builder/src/codegen/rust/serializer.rs @@ -843,7 +843,7 @@ fn quote_arrow_field_serializer( // if we make the C++ and Python codegen match the rust behavior or // make our comparison tests more lenient. // - // This workaround does not apply if we don't have any validity validity on the outer type. + // This workaround does not apply if we don't have any validity on the outer type. // (as it is always the case with unions where the nullability is encoded as a separate variant) let quoted_inner_validity = if let (true, DataType::FixedSizeList(_, count)) = (elements_are_nullable, datatype.to_logical_type()) diff --git a/crates/store/re_chunk/src/iter.rs b/crates/store/re_chunk/src/iter.rs index 571c5995c48b..1534d9ac0a28 100644 --- a/crates/store/re_chunk/src/iter.rs +++ b/crates/store/re_chunk/src/iter.rs @@ -710,7 +710,7 @@ impl Chunk { Err(err) => { if cfg!(debug_assertions) { panic!( - "deserialization failed for {}, data discarded: {}", + "[DEBUG-ONLY] deserialization failed for {}, data discarded: {}", C::name(), re_error::format_ref(&err), ); diff --git a/crates/store/re_chunk_store/src/stats.rs b/crates/store/re_chunk_store/src/stats.rs index 1f281b8179be..213d946b9b23 100644 --- a/crates/store/re_chunk_store/src/stats.rs +++ b/crates/store/re_chunk_store/src/stats.rs @@ -320,4 +320,24 @@ impl ChunkStore { .sum() }) } + + /// Returns the number of temporal events logged for an entity for a specific component on all timelines. + /// + /// This ignores static events. + pub fn num_temporal_events_for_component_on_all_timelines( + &self, + entity_path: &EntityPath, + component_name: ComponentName, + ) -> u64 { + self.all_timelines() + .iter() + .map(|timeline| { + self.num_temporal_events_for_component_on_timeline( + timeline, + entity_path, + component_name, + ) + }) + .sum() + } } diff --git a/crates/store/re_grpc_client/src/lib.rs b/crates/store/re_grpc_client/src/lib.rs index 5b6f553ee428..f324862dc3a8 100644 --- a/crates/store/re_grpc_client/src/lib.rs +++ b/crates/store/re_grpc_client/src/lib.rs @@ -5,6 +5,7 @@ mod address; pub use address::{InvalidRedapAddress, RedapAddress}; use re_chunk::external::arrow2; use re_log_types::external::re_types_core::ComponentDescriptor; +use re_protos::remote_store::v0::CatalogFilter; use re_types::blueprint::archetypes::{ContainerBlueprint, ViewportBlueprint}; use re_types::blueprint::archetypes::{ViewBlueprint, ViewContents}; use re_types::blueprint::components::{ContainerKind, RootContainer}; @@ -16,6 +17,7 @@ use url::Url; // ---------------------------------------------------------------------------- use std::error::Error; +use std::sync::Arc; use arrow2::array::Utf8Array as Arrow2Utf8Array; use arrow2::datatypes::Field as Arrow2Field; @@ -175,6 +177,43 @@ async fn stream_recording_async( StorageNodeClient::new(tonic_client).max_decoding_message_size(usize::MAX) }; + re_log::debug!("Fetching catalog data for {recording_id}…"); + + let resp = client + .query_catalog(QueryCatalogRequest { + column_projection: None, // fetch all columns + filter: Some(CatalogFilter { + recording_ids: vec![RecordingId { + id: recording_id.clone(), + }], + }), + }) + .await + .map_err(TonicStatusError)? + .into_inner() + .filter_map(|resp| { + resp.and_then(|r| { + decode(r.encoder_version(), &r.payload) + .map_err(|err| tonic::Status::internal(err.to_string())) + }) + .transpose() + }) + .collect::, tonic::Status>>() + .await + .map_err(TonicStatusError)?; + + if resp.len() != 1 || resp[0].num_rows() != 1 { + return Err(StreamError::ChunkError(re_chunk::ChunkError::Malformed { + reason: format!( + "expected exactly one recording with id {recording_id}, got {}", + resp.len() + ), + })); + } + + let store_info = store_info_from_catalog_chunk(&resp[0], &recording_id)?; + let store_id = store_info.store_id.clone(); + re_log::debug!("Fetching {recording_id}…"); let mut resp = client @@ -196,19 +235,6 @@ async fn stream_recording_async( drop(client); - // TODO(zehiko) - we need a separate gRPC endpoint for fetching Store info REDAP #85 - let store_id = StoreId::from_string(StoreKind::Recording, recording_id.clone()); - - let store_info = StoreInfo { - application_id: ApplicationId::from("redap_recording"), - store_id: store_id.clone(), - cloned_from: None, - is_official_example: false, - started: Time::now(), - store_source: StoreSource::Unknown, - store_version: None, - }; - // We need a whole StoreInfo here. if tx .send(LogMsg::SetStoreInfo(SetStoreInfo { @@ -242,6 +268,51 @@ async fn stream_recording_async( Ok(()) } +fn store_info_from_catalog_chunk( + tc: &TransportChunk, + recording_id: &str, +) -> Result { + let store_id = StoreId::from_string(StoreKind::Recording, recording_id.to_owned()); + + let (_field, data) = tc + .components() + .find(|(f, _)| f.name == "application_id") + .ok_or(StreamError::ChunkError(re_chunk::ChunkError::Malformed { + reason: "no application_id field found".to_owned(), + }))?; + let app_id = data + .as_any() + .downcast_ref::>() + .ok_or(StreamError::ChunkError(re_chunk::ChunkError::Malformed { + reason: format!("application_id must be a utf8 array: {:?}", tc.schema), + }))? + .value(0); + + let (_field, data) = tc + .components() + .find(|(f, _)| f.name == "start_time") + .ok_or(StreamError::ChunkError(re_chunk::ChunkError::Malformed { + reason: "no start_time field found".to_owned(), + }))?; + let start_time = data + .as_any() + .downcast_ref::() + .ok_or(StreamError::ChunkError(re_chunk::ChunkError::Malformed { + reason: format!("start_time must be an int64 array: {:?}", tc.schema), + }))? + .value(0); + + Ok(StoreInfo { + application_id: ApplicationId::from(app_id), + store_id: store_id.clone(), + cloned_from: None, + is_official_example: false, + started: Time::from_ns_since_epoch(start_time), + store_source: StoreSource::Unknown, + store_version: None, + }) +} + async fn stream_catalog_async( tx: re_smart_channel::Sender, redap_endpoint: Url, @@ -318,16 +389,88 @@ async fn stream_catalog_async( re_log::info!("Starting to read..."); while let Some(result) = resp.next().await { - let mut tc = result.map_err(TonicStatusError)?; - // received TransportChunk doesn't have ChunkId, hence we need to add it before converting - // to Chunk + let input = result.map_err(TonicStatusError)?; + + // Catalog received from the ReDap server isn't suitable for direct conversion to a Rerun Chunk: + // - conversion expects "data" columns to be ListArrays, hence we need to convert any individual row column data to ListArray + // - conversion expects the input TransportChunk to have a ChunkId so we need to add that piece of metadata + + let mut fields = Vec::new(); + let mut arrays = Vec::new(); + // add the (row id) control field + let (row_id_field, row_id_data) = input.controls().next().ok_or( + StreamError::ChunkError(re_chunk::ChunkError::Malformed { + reason: "no control field found".to_owned(), + }), + )?; + + fields.push( + Arrow2Field::new( + RowId::name().to_string(), // need to rename to Rerun Chunk expected control field + row_id_field.data_type().clone(), + false, /* not nullable */ + ) + .with_metadata(TransportChunk::field_metadata_control_column()), + ); + arrays.push(row_id_data.clone()); + + // next add any timeline field + for (field, data) in input.timelines() { + fields.push(field.clone()); + arrays.push(data.clone()); + } + + // now add all the 'data' fields - we slice each column array into individual arrays and then convert the whole lot into a ListArray + for (field, data) in input.components() { + let data_field_inner = + Arrow2Field::new("item", field.data_type().clone(), true /* nullable */); + + let data_field = Arrow2Field::new( + field.name.clone(), + arrow2::datatypes::DataType::List(Arc::new(data_field_inner.clone())), + false, /* not nullable */ + ) + .with_metadata(TransportChunk::field_metadata_data_column()); + + let mut sliced: Vec> = Vec::new(); + for idx in 0..data.len() { + let mut array = data.clone(); + array.slice(idx, 1); + sliced.push(array); + } + + let data_arrays = sliced.iter().map(|e| Some(e.as_ref())).collect::>(); + #[allow(clippy::unwrap_used)] // we know we've given the right field type + let data_field_array: arrow2::array::ListArray = + re_chunk::util::arrays_to_list_array( + data_field_inner.data_type().clone(), + &data_arrays, + ) + .unwrap(); + + fields.push(data_field); + arrays.push(Box::new(data_field_array)); + } + + let mut schema = arrow2::datatypes::Schema::from(fields); + schema.metadata.insert( + TransportChunk::CHUNK_METADATA_KEY_ENTITY_PATH.to_owned(), + "catalog".to_owned(), + ); + + // modified and enriched TransportChunk + let mut tc = TransportChunk { + schema, + data: arrow2::chunk::Chunk::new(arrays), + }; + tc.schema.metadata.insert( TransportChunk::CHUNK_METADATA_KEY_ID.to_owned(), ChunkId::new().to_string(), ); let mut chunk = Chunk::from_transport(&tc)?; - // enrich catalog data with RecordingUri that's based on the ReDap endpoint (that we know) + // finally, enrich catalog data with RecordingUri that's based on the ReDap endpoint (that we know) // and the recording id (that we have in the catalog data) let host = redap_endpoint .host() diff --git a/crates/store/re_log_types/src/path/entity_path_filter.rs b/crates/store/re_log_types/src/path/entity_path_filter.rs index a59629c1e089..9f94525e9bcc 100644 --- a/crates/store/re_log_types/src/path/entity_path_filter.rs +++ b/crates/store/re_log_types/src/path/entity_path_filter.rs @@ -16,8 +16,11 @@ pub enum EntityPathFilterParseError { } /// A set of substitutions for entity paths. +/// +/// Important: the same substitutions must be used in every place we parse entity path filters. +// TODO(ab): the above requirement is a foot-gun we already fell in and should be addressed. #[derive(Default)] -pub struct EntityPathSubs(pub HashMap); +pub struct EntityPathSubs(HashMap); impl EntityPathSubs { /// Create a new set of substitutions from a single origin. diff --git a/crates/store/re_protos/proto/rerun/v0/remote_store.proto b/crates/store/re_protos/proto/rerun/v0/remote_store.proto index 2955f45b8b3c..5d2f68ca3794 100644 --- a/crates/store/re_protos/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_protos/proto/rerun/v0/remote_store.proto @@ -44,7 +44,6 @@ message RegisterRecordingRequest { // ---------------- UpdateCatalog ----------------- message UpdateCatalogRequest { - rerun.common.v0.RecordingId recording_id = 1; DataframePart metadata = 2; } diff --git a/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs b/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs index 1429146e776d..a755b57daac4 100644 --- a/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_protos/src/v0/rerun.remote_store.v0.rs @@ -47,8 +47,6 @@ impl ::prost::Name for RegisterRecordingRequest { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpdateCatalogRequest { - #[prost(message, optional, tag = "1")] - pub recording_id: ::core::option::Option, #[prost(message, optional, tag = "2")] pub metadata: ::core::option::Option, } diff --git a/crates/store/re_types/definitions/rerun/archetypes/ellipsoids3d.fbs b/crates/store/re_types/definitions/rerun/archetypes/ellipsoids3d.fbs index 0fb824dc7017..469ff7009186 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/ellipsoids3d.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/ellipsoids3d.fbs @@ -12,7 +12,7 @@ namespace rerun.archetypes; /// 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. /// -/// \example archetypes/ellipsoids3d_simple !api title="Covariance ellipsoid" image="https://static.rerun.io/elliopsoid3d_simple/bd5d46e61b80ae44792b52ee07d750a7137002ea/1200w.png" +/// \example archetypes/ellipsoids3d_simple title="Covariance ellipsoid" image="https://static.rerun.io/elliopsoid3d_simple/bd5d46e61b80ae44792b52ee07d750a7137002ea/1200w.png" table Ellipsoids3D ( "attr.rust.derive": "PartialEq", "attr.rust.new_pub_crate", diff --git a/crates/store/re_types/definitions/rerun/archetypes/graph_edges.fbs b/crates/store/re_types/definitions/rerun/archetypes/graph_edges.fbs index a20ea2d39fa1..c85a4e58e4bb 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/graph_edges.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/graph_edges.fbs @@ -7,13 +7,11 @@ namespace rerun.archetypes; /// By default, edges are undirected. /// /// \example archetypes/graph_undirected !api title="Simple undirected graph" image="https://static.rerun.io/graph_undirected/15f46bec77452a8c6220558e4403b99cac188e2e/1200w.png" -/// \example archetypes/graph_directed !api title="Simple directed graph" image="https://static.rerun.io/graph_directed/ca29a37b65e1e0b6482251dce401982a0bc568fa/1200w.png" +/// \example archetypes/graph_directed title="Simple directed graph" image="https://static.rerun.io/graph_directed/ca29a37b65e1e0b6482251dce401982a0bc568fa/1200w.png" table GraphEdges ( "attr.docs.category": "Graph", - "attr.docs.unreleased", "attr.docs.view_types": "GraphView", - "attr.rust.derive": "PartialEq, Eq", - "attr.rerun.experimental" + "attr.rust.derive": "PartialEq, Eq" ) { // --- Required --- diff --git a/crates/store/re_types/definitions/rerun/archetypes/graph_nodes.fbs b/crates/store/re_types/definitions/rerun/archetypes/graph_nodes.fbs index 7e7ddb535164..d169b97bd25b 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/graph_nodes.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/graph_nodes.fbs @@ -5,13 +5,11 @@ namespace rerun.archetypes; /// A list of nodes in a graph with optional labels, colors, etc. /// /// \example archetypes/graph_undirected !api title="Simple undirected graph" image="https://static.rerun.io/graph_undirected/15f46bec77452a8c6220558e4403b99cac188e2e/1200w.png" -/// \example archetypes/graph_directed !api title="Simple directed graph" image="https://static.rerun.io/graph_directed/ca29a37b65e1e0b6482251dce401982a0bc568fa/1200w.png" +/// \example archetypes/graph_directed title="Simple directed graph" image="https://static.rerun.io/graph_directed/ca29a37b65e1e0b6482251dce401982a0bc568fa/1200w.png" table GraphNodes ( "attr.docs.category": "Graph", - "attr.docs.unreleased", "attr.docs.view_types": "GraphView", - "attr.rust.derive": "PartialEq", - "attr.rerun.experimental" + "attr.rust.derive": "PartialEq" ) { // --- Required --- diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs index c3b477bf49d0..a574b9c696c0 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_center.fbs @@ -4,7 +4,9 @@ namespace rerun.blueprint.archetypes; struct ForceCenter ( "attr.rerun.scope": "blueprint" ) { - /// Whether the force is enabled. + /// Whether the center force is enabled. + /// + /// The center force tries to move the center of mass of the graph towards the origin. enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); /// The strength of the force. diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs index 9ffcf43376ff..f4a4e760b59a 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_collision_radius.fbs @@ -1,10 +1,12 @@ namespace rerun.blueprint.archetypes; -/// Resolves collisions between the bounding spheres, according to the radius of the nodes. +/// Resolves collisions between the bounding circles, according to the radius of the nodes. struct ForceCollisionRadius ( "attr.rerun.scope": "blueprint" ) { - /// Whether the force is enabled. + /// Whether the collision force is enabled. + /// + /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); /// The strength of the force. diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs index fc963b757cf3..2d34b1c936ae 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_link.fbs @@ -4,7 +4,9 @@ namespace rerun.blueprint.archetypes; struct ForceLink ( "attr.rerun.scope": "blueprint" ) { - /// Whether the force is enabled. + /// Whether the link force is enabled. + /// + /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); /// The target distance between two nodes. diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs index edafce01c777..abc576912fca 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_many_body.fbs @@ -6,7 +6,10 @@ namespace rerun.blueprint.archetypes; struct ForceManyBody ( "attr.rerun.scope": "blueprint" ) { - /// Whether the force is enabled. + /// Whether the many body force is enabled. + /// + /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); /// The strength of the force. diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs index 7ff9fd24d340..6689b95b48d7 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/force_position.fbs @@ -4,7 +4,9 @@ namespace rerun.blueprint.archetypes; struct ForcePosition ( "attr.rerun.scope": "blueprint" ) { - /// Whether the force is enabled. + /// Whether the position force is enabled. + /// + /// The position force pulls nodes towards a specific position, similar to gravity. enabled: rerun.blueprint.components.Enabled ("attr.rerun.component_optional", nullable, order: 100); /// The strength of the force. diff --git a/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs b/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs index a157d67a2982..9875dfde1004 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/archetypes/near_clip_plane.fbs @@ -2,7 +2,6 @@ namespace rerun.blueprint.archetypes; /// Controls the distance to the near clip plane in 3D scene units. table NearClipPlane ( - "attr.docs.unreleased", "attr.rerun.scope": "blueprint", "attr.rust.derive": "Copy" ) { diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/near_clip_plane.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/near_clip_plane.fbs index 200fc64ef33b..aa7aa3582d1f 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/components/near_clip_plane.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/components/near_clip_plane.fbs @@ -6,8 +6,7 @@ namespace rerun.blueprint.components; struct NearClipPlane ( "attr.rerun.scope": "blueprint", "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", - "attr.rust.repr": "transparent", - "attr.docs.unreleased" + "attr.rust.repr": "transparent" ) { /// Distance to the near clip plane in 3D scene units. near_clip_plane: rerun.datatypes.Float32 (order: 100); diff --git a/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs b/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs index 848ad4f3255a..7710b0856c02 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/views/graph.fbs @@ -4,8 +4,7 @@ namespace rerun.blueprint.views; /// /// \example views/graph title="Use a blueprint to create a graph view." image="https://static.rerun.io/graph_lattice/f9169da9c3f35b7260c9d74cd5be5fe710aec6a8/1200w.png" table GraphView ( - "attr.rerun.view_identifier": "Graph", - "attr.docs.unreleased" + "attr.rerun.view_identifier": "Graph" ) { /// Everything within these bounds is guaranteed to be visible. /// diff --git a/crates/store/re_types/definitions/rerun/components/graph_edge.fbs b/crates/store/re_types/definitions/rerun/components/graph_edge.fbs index 1f97a2e6c506..435dee9efa5a 100644 --- a/crates/store/re_types/definitions/rerun/components/graph_edge.fbs +++ b/crates/store/re_types/definitions/rerun/components/graph_edge.fbs @@ -4,7 +4,6 @@ namespace rerun.components; /// An edge in a graph connecting two nodes. table GraphEdge ( - "attr.docs.unreleased", "attr.rust.derive": "Default, PartialEq, Eq, PartialOrd, Ord", "attr.rust.repr": "transparent" ) { diff --git a/crates/store/re_types/definitions/rerun/components/graph_node.fbs b/crates/store/re_types/definitions/rerun/components/graph_node.fbs index 7867665a380a..3af3d6f2f185 100644 --- a/crates/store/re_types/definitions/rerun/components/graph_node.fbs +++ b/crates/store/re_types/definitions/rerun/components/graph_node.fbs @@ -4,7 +4,6 @@ namespace rerun.components; /// A string-based ID representing a node in a graph. table GraphNode ( - "attr.docs.unreleased", "attr.python.aliases": "str", "attr.python.array_aliases": "str, Sequence[str]", "attr.rust.derive": "Default, PartialEq, Eq, PartialOrd, Ord, Hash", diff --git a/crates/store/re_types/definitions/rerun/components/graph_type.fbs b/crates/store/re_types/definitions/rerun/components/graph_type.fbs index 283e3a2b93b4..1348c6b20479 100644 --- a/crates/store/re_types/definitions/rerun/components/graph_type.fbs +++ b/crates/store/re_types/definitions/rerun/components/graph_type.fbs @@ -4,7 +4,6 @@ namespace rerun.components; /// Specifies if a graph has directed or undirected edges. enum GraphType: ubyte ( - "attr.docs.unreleased", "attr.rust.derive": "Default, PartialEq, Eq" ) { /// Invalid value. Won't show up in generated types. diff --git a/crates/store/re_types/definitions/rerun/components/plane3d.fbs b/crates/store/re_types/definitions/rerun/components/plane3d.fbs index e60aa4efdf58..21c8b139d1c4 100644 --- a/crates/store/re_types/definitions/rerun/components/plane3d.fbs +++ b/crates/store/re_types/definitions/rerun/components/plane3d.fbs @@ -10,7 +10,6 @@ namespace rerun.components; /// 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 struct Plane3D ( - "attr.docs.unreleased", "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", "attr.rust.repr": "transparent" ) { diff --git a/crates/store/re_types/definitions/rerun/components/recording_uri.fbs b/crates/store/re_types/definitions/rerun/components/recording_uri.fbs index e27204f5251d..22966e126eb4 100644 --- a/crates/store/re_types/definitions/rerun/components/recording_uri.fbs +++ b/crates/store/re_types/definitions/rerun/components/recording_uri.fbs @@ -4,8 +4,7 @@ namespace rerun.components; /// A recording URI (Uniform Resource Identifier). table RecordingUri ( - "attr.rust.derive": "PartialEq, Eq, PartialOrd, Ord, Hash", - "attr.docs.unreleased" + "attr.rust.derive": "PartialEq, Eq, PartialOrd, Ord, Hash" ) { recording_uri: rerun.datatypes.Utf8 (order: 100); } diff --git a/crates/store/re_types/definitions/rerun/datatypes.fbs b/crates/store/re_types/definitions/rerun/datatypes.fbs index 5772f4c3b8d5..fa325413e155 100644 --- a/crates/store/re_types/definitions/rerun/datatypes.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes.fbs @@ -27,7 +27,6 @@ include "./datatypes/rgba32.fbs"; include "./datatypes/rotation_axis_angle.fbs"; include "./datatypes/tensor_buffer.fbs"; include "./datatypes/tensor_data.fbs"; -include "./datatypes/tensor_dimension.fbs"; include "./datatypes/tensor_dimension_selection.fbs"; include "./datatypes/time_int.fbs"; include "./datatypes/uint16.fbs"; diff --git a/crates/store/re_types/definitions/rerun/datatypes/plane3d.fbs b/crates/store/re_types/definitions/rerun/datatypes/plane3d.fbs index a490f8450481..acfeb4741ce8 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/plane3d.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/plane3d.fbs @@ -10,7 +10,6 @@ namespace rerun.datatypes; /// 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 struct Plane3D ( - "attr.docs.unreleased", "attr.arrow.transparent", "attr.python.array_aliases": "npt.NDArray[Any], npt.ArrayLike, Sequence[Sequence[float]]", "attr.rust.derive": "Copy, PartialEq, PartialOrd, bytemuck::Pod, bytemuck::Zeroable", diff --git a/crates/store/re_types/definitions/rerun/datatypes/tensor_data.fbs b/crates/store/re_types/definitions/rerun/datatypes/tensor_data.fbs index 1624be6e00f3..6301c33c7abb 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/tensor_data.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/tensor_data.fbs @@ -19,8 +19,17 @@ table TensorData ( "attr.python.array_aliases": "npt.ArrayLike", "attr.rust.derive": "PartialEq," ) { - /// The shape of the tensor, including optional names for each dimension. - shape: [rerun.datatypes.TensorDimension] (order: 200); + /// The shape of the tensor, i.e. the length of each dimension. + shape: [uint64] (order: 200); + + /// The names of the dimensions of the tensor (optional). + /// + /// If set, should be the same length as [datatypes.TensorData.shape]. + /// 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"]`. + names: [string] (order: 250, nullable); /// The content/data. buffer: rerun.datatypes.TensorBuffer (order: 300); diff --git a/crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs b/crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs deleted file mode 100644 index 7d755a8b81e5..000000000000 --- a/crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs +++ /dev/null @@ -1,15 +0,0 @@ -namespace rerun.datatypes; - -// --- - -/// A single dimension within a multi-dimensional tensor. -// TODO(jleibs): Support for stride. -table TensorDimension ( - "attr.rust.derive_only": "Clone, Default, Eq, PartialEq" -) { - /// The length of this dimension. - size: ulong (order: 100); - - /// The name of this dimension, e.g. "width", "height", "channel", "batch', …. - name: string (order: 200, nullable); -} diff --git a/crates/store/re_types/definitions/rerun/datatypes/utf8_pair.fbs b/crates/store/re_types/definitions/rerun/datatypes/utf8_pair.fbs index 9acbb85a5052..051722a1e200 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/utf8_pair.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/utf8_pair.fbs @@ -2,7 +2,6 @@ namespace rerun.datatypes; /// Stores a tuple of UTF-8 strings. table Utf8Pair ( - "attr.docs.unreleased", "attr.python.aliases": "Tuple[datatypes.Utf8Like, datatypes.Utf8Like]", "attr.python.array_aliases": "npt.NDArray[np.str_]", "attr.rust.derive": "Default, PartialEq, Eq, PartialOrd, Ord" diff --git a/crates/store/re_types/src/archetypes/depth_image_ext.rs b/crates/store/re_types/src/archetypes/depth_image_ext.rs index b1c7044c0914..af72285a3edd 100644 --- a/crates/store/re_types/src/archetypes/depth_image_ext.rs +++ b/crates/store/re_types/src/archetypes/depth_image_ext.rs @@ -20,7 +20,7 @@ impl DepthImage { let tensor_data: TensorData = data .try_into() .map_err(ImageConstructionError::TensorDataConversion)?; - let shape = tensor_data.shape; + let TensorData { shape, buffer, .. } = tensor_data; let non_empty_dim_inds = find_non_empty_dim_indices(&shape); @@ -28,13 +28,11 @@ impl DepthImage { return Err(ImageConstructionError::BadImageShape(shape)); } - let (blob, datatype) = blob_and_datatype_from_tensor(tensor_data.buffer); + let (blob, datatype) = blob_and_datatype_from_tensor(buffer); - let (height, width) = (&shape[non_empty_dim_inds[0]], &shape[non_empty_dim_inds[1]]); - let height = height.size as u32; - let width = width.size as u32; + let (height, width) = (shape[non_empty_dim_inds[0]], shape[non_empty_dim_inds[1]]); - let image_format = ImageFormat::depth([width, height], datatype); + let image_format = ImageFormat::depth([width as u32, height as u32], datatype); Ok(Self { buffer: blob.into(), diff --git a/crates/store/re_types/src/archetypes/ellipsoids3d.rs b/crates/store/re_types/src/archetypes/ellipsoids3d.rs index bc6ee14a53f6..034fbb9f6047 100644 --- a/crates/store/re_types/src/archetypes/ellipsoids3d.rs +++ b/crates/store/re_types/src/archetypes/ellipsoids3d.rs @@ -27,6 +27,58 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// 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. +/// +/// ## Example +/// +/// ### Covariance ellipsoid +/// ```ignore +/// use rand::distributions::Distribution; +/// +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_ellipsoid_simple").spawn()?; +/// +/// let sigmas: [f32; 3] = [5., 3., 1.]; +/// +/// let mut rng = rand::thread_rng(); +/// let normal = rand_distr::Normal::new(0.0, 1.0)?; +/// +/// rec.log( +/// "points", +/// &rerun::Points3D::new((0..50_000).map(|_| { +/// ( +/// sigmas[0] * normal.sample(&mut rng), +/// sigmas[1] * normal.sample(&mut rng), +/// sigmas[2] * normal.sample(&mut rng), +/// ) +/// })) +/// .with_radii([0.02]) +/// .with_colors([rerun::Color::from_rgb(188, 77, 185)]), +/// )?; +/// +/// rec.log( +/// "ellipsoid", +/// &rerun::Ellipsoids3D::from_centers_and_half_sizes( +/// [(0.0, 0.0, 0.0), (0.0, 0.0, 0.0)], +/// [sigmas, [sigmas[0] * 3., sigmas[1] * 3., sigmas[2] * 3.]], +/// ) +/// .with_colors([ +/// rerun::Color::from_rgb(255, 255, 0), +/// rerun::Color::from_rgb(64, 64, 0), +/// ]), +/// )?; +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
#[derive(Clone, Debug, PartialEq)] pub struct Ellipsoids3D { /// For each ellipsoid, half of its size on its three axes. diff --git a/crates/store/re_types/src/archetypes/graph_edges.rs b/crates/store/re_types/src/archetypes/graph_edges.rs index a4aee2905982..19fa08c8c526 100644 --- a/crates/store/re_types/src/archetypes/graph_edges.rs +++ b/crates/store/re_types/src/archetypes/graph_edges.rs @@ -22,7 +22,35 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// By default, edges are undirected. /// -/// ⚠️ **This type is experimental and may be removed in future versions** +/// ## Example +/// +/// ### Simple directed graph +/// ```ignore +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_graph_directed").spawn()?; +/// +/// rec.log( +/// "simple", +/// &[ +/// &rerun::GraphNodes::new(["a", "b", "c"]) +/// .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) +/// .with_labels(["A", "B", "C"]) as &dyn rerun::AsComponents, +/// &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]).with_directed_edges(), +/// ], +/// )?; +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
#[derive(Clone, Debug, PartialEq, Eq)] pub struct GraphEdges { /// A list of node tuples. diff --git a/crates/store/re_types/src/archetypes/graph_nodes.rs b/crates/store/re_types/src/archetypes/graph_nodes.rs index 7a2c73d84601..5931330051f3 100644 --- a/crates/store/re_types/src/archetypes/graph_nodes.rs +++ b/crates/store/re_types/src/archetypes/graph_nodes.rs @@ -20,7 +20,35 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: A list of nodes in a graph with optional labels, colors, etc. /// -/// ⚠️ **This type is experimental and may be removed in future versions** +/// ## Example +/// +/// ### Simple directed graph +/// ```ignore +/// fn main() -> Result<(), Box> { +/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_graph_directed").spawn()?; +/// +/// rec.log( +/// "simple", +/// &[ +/// &rerun::GraphNodes::new(["a", "b", "c"]) +/// .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) +/// .with_labels(["A", "B", "C"]) as &dyn rerun::AsComponents, +/// &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]).with_directed_edges(), +/// ], +/// )?; +/// +/// Ok(()) +/// } +/// ``` +///
+/// +/// +/// +/// +/// +/// +/// +///
#[derive(Clone, Debug, PartialEq)] pub struct GraphNodes { /// A list of node IDs. diff --git a/crates/store/re_types/src/archetypes/image_ext.rs b/crates/store/re_types/src/archetypes/image_ext.rs index 1beff5061887..0304cecb27fe 100644 --- a/crates/store/re_types/src/archetypes/image_ext.rs +++ b/crates/store/re_types/src/archetypes/image_ext.rs @@ -33,17 +33,17 @@ impl Image { let tensor_data: TensorData = data .try_into() .map_err(ImageConstructionError::TensorDataConversion)?; - let shape = tensor_data.shape; + let TensorData { shape, buffer, .. } = tensor_data; let non_empty_dim_inds = find_non_empty_dim_indices(&shape); let is_shape_correct = match color_model { ColorModel::L => non_empty_dim_inds.len() == 2, ColorModel::RGB | ColorModel::BGR => { - non_empty_dim_inds.len() == 3 && shape[non_empty_dim_inds[2]].size == 3 + non_empty_dim_inds.len() == 3 && shape[non_empty_dim_inds[2]] == 3 } ColorModel::RGBA | ColorModel::BGRA => { - non_empty_dim_inds.len() == 3 && shape[non_empty_dim_inds[2]].size == 4 + non_empty_dim_inds.len() == 3 && shape[non_empty_dim_inds[2]] == 4 } }; @@ -51,15 +51,13 @@ impl Image { return Err(ImageConstructionError::BadImageShape(shape)); } - let (blob, datatype) = blob_and_datatype_from_tensor(tensor_data.buffer); + let (blob, datatype) = blob_and_datatype_from_tensor(buffer); - let (height, width) = (&shape[non_empty_dim_inds[0]], &shape[non_empty_dim_inds[1]]); - let height = height.size as u32; - let width = width.size as u32; + let (height, width) = (shape[non_empty_dim_inds[0]], shape[non_empty_dim_inds[1]]); let image_format = ImageFormat { - width, - height, + width: width as _, + height: height as _, pixel_format: None, channel_datatype: Some(datatype), color_model: Some(color_model), diff --git a/crates/store/re_types/src/archetypes/segmentation_image_ext.rs b/crates/store/re_types/src/archetypes/segmentation_image_ext.rs index 4c2f71375b39..a90856eb24d3 100644 --- a/crates/store/re_types/src/archetypes/segmentation_image_ext.rs +++ b/crates/store/re_types/src/archetypes/segmentation_image_ext.rs @@ -19,7 +19,7 @@ impl SegmentationImage { let tensor_data: TensorData = data .try_into() .map_err(ImageConstructionError::TensorDataConversion)?; - let shape = tensor_data.shape; + let TensorData { shape, buffer, .. } = tensor_data; let non_empty_dim_inds = find_non_empty_dim_indices(&shape); @@ -27,13 +27,11 @@ impl SegmentationImage { return Err(ImageConstructionError::BadImageShape(shape)); } - let (blob, datatype) = blob_and_datatype_from_tensor(tensor_data.buffer); + let (blob, datatype) = blob_and_datatype_from_tensor(buffer); - let (height, width) = (&shape[non_empty_dim_inds[0]], &shape[non_empty_dim_inds[1]]); - let height = height.size as u32; - let width = width.size as u32; + let (height, width) = (shape[non_empty_dim_inds[0]], shape[non_empty_dim_inds[1]]); - let image_format = ImageFormat::segmentation([width, height], datatype); + let image_format = ImageFormat::segmentation([width as _, height as _], datatype); Ok(Self { buffer: blob.into(), diff --git a/crates/store/re_types/src/archetypes/tensor_ext.rs b/crates/store/re_types/src/archetypes/tensor_ext.rs index c7063b0b6264..2bfa7c1f08ef 100644 --- a/crates/store/re_types/src/archetypes/tensor_ext.rs +++ b/crates/store/re_types/src/archetypes/tensor_ext.rs @@ -1,4 +1,4 @@ -use crate::datatypes::{TensorData, TensorDimension}; +use crate::datatypes::TensorData; use re_types_core::ArrowString; @@ -24,37 +24,16 @@ impl Tensor { /// Update the `names` of the contained [`TensorData`] dimensions. /// - /// Any existing Dimension names will be overwritten. + /// Any existing names will be overwritten. /// - /// If too many, or too few names are provided, this function will warn and only - /// update the subset of names that it can. - pub fn with_dim_names(self, names: impl IntoIterator>) -> Self { - let names: Vec<_> = names.into_iter().map(|x| Some(x.into())).collect(); - if names.len() != self.data.0.shape.len() { - re_log::warn_once!( - "Wrong number of names provided for tensor dimension. {} provided but {} expected.", - names.len(), - self.data.0.shape.len(), - ); - } - Self { - data: TensorData { - shape: self - .data - .0 - .shape - .into_iter() - .zip(names.into_iter().chain(std::iter::repeat(None))) - .map(|(dim, name)| TensorDimension { - size: dim.size, - name: name.or(dim.name), - }) - .collect(), - buffer: self.data.0.buffer, - } - .into(), - value_range: None, - } + /// If the wrong number of names are given, a warning will be logged, + /// and the names might not show up correctly. + pub fn with_dim_names( + mut self, + names: impl IntoIterator>, + ) -> Self { + self.data.0 = self.data.0.with_dim_names(names); + self } } diff --git a/crates/store/re_types/src/blueprint/archetypes/force_center.rs b/crates/store/re_types/src/blueprint/archetypes/force_center.rs index 9cb1870a5af5..5f12962b42dc 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_center.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_center.rs @@ -21,7 +21,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: Tries to move the center of mass of the graph to the origin. #[derive(Clone, Debug)] pub struct ForceCenter { - /// Whether the force is enabled. + /// Whether the center force is enabled. + /// + /// The center force tries to move the center of mass of the graph towards the origin. pub enabled: Option, /// The strength of the force. @@ -207,7 +209,9 @@ impl ForceCenter { } } - /// Whether the force is enabled. + /// Whether the center force is enabled. + /// + /// The center force tries to move the center of mass of the graph towards the origin. #[inline] pub fn with_enabled( mut self, diff --git a/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs b/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs index 71055ab49f0f..9f4536a2b750 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_collision_radius.rs @@ -18,10 +18,12 @@ use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; use ::re_types_core::{ComponentDescriptor, ComponentName}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Archetype**: Resolves collisions between the bounding spheres, according to the radius of the nodes. +/// **Archetype**: Resolves collisions between the bounding circles, according to the radius of the nodes. #[derive(Clone, Debug)] pub struct ForceCollisionRadius { - /// Whether the force is enabled. + /// Whether the collision force is enabled. + /// + /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. pub enabled: Option, /// The strength of the force. @@ -250,7 +252,9 @@ impl ForceCollisionRadius { } } - /// Whether the force is enabled. + /// Whether the collision force is enabled. + /// + /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. #[inline] pub fn with_enabled( mut self, diff --git a/crates/store/re_types/src/blueprint/archetypes/force_link.rs b/crates/store/re_types/src/blueprint/archetypes/force_link.rs index 9c6fe8aa11d2..f294b0eb9818 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_link.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_link.rs @@ -21,7 +21,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: Aims to achieve a target distance between two nodes that are connected by an edge. #[derive(Clone, Debug)] pub struct ForceLink { - /// Whether the force is enabled. + /// Whether the link force is enabled. + /// + /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. pub enabled: Option, /// The target distance between two nodes. @@ -249,7 +251,9 @@ impl ForceLink { } } - /// Whether the force is enabled. + /// Whether the link force is enabled. + /// + /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. #[inline] pub fn with_enabled( mut self, diff --git a/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs b/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs index 9720ff5a4f17..026e249436d4 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_many_body.rs @@ -23,7 +23,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. #[derive(Clone, Debug)] pub struct ForceManyBody { - /// Whether the force is enabled. + /// Whether the many body force is enabled. + /// + /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. pub enabled: Option, /// The strength of the force. @@ -211,7 +214,10 @@ impl ForceManyBody { } } - /// Whether the force is enabled. + /// Whether the many body force is enabled. + /// + /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. #[inline] pub fn with_enabled( mut self, diff --git a/crates/store/re_types/src/blueprint/archetypes/force_position.rs b/crates/store/re_types/src/blueprint/archetypes/force_position.rs index e106a452c2a2..cc74aa2aabf4 100644 --- a/crates/store/re_types/src/blueprint/archetypes/force_position.rs +++ b/crates/store/re_types/src/blueprint/archetypes/force_position.rs @@ -21,7 +21,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: Similar to gravity, this force pulls nodes towards a specific position. #[derive(Clone, Debug)] pub struct ForcePosition { - /// Whether the force is enabled. + /// Whether the position force is enabled. + /// + /// The position force pulls nodes towards a specific position, similar to gravity. pub enabled: Option, /// The strength of the force. @@ -246,7 +248,9 @@ impl ForcePosition { } } - /// Whether the force is enabled. + /// Whether the position force is enabled. + /// + /// The position force pulls nodes towards a specific position, similar to gravity. #[inline] pub fn with_enabled( mut self, diff --git a/crates/store/re_types/src/datatypes/.gitattributes b/crates/store/re_types/src/datatypes/.gitattributes index 289cbd45793c..5995b6d6c716 100644 --- a/crates/store/re_types/src/datatypes/.gitattributes +++ b/crates/store/re_types/src/datatypes/.gitattributes @@ -25,7 +25,6 @@ rgba32.rs linguist-generated=true rotation_axis_angle.rs linguist-generated=true tensor_buffer.rs linguist-generated=true tensor_data.rs linguist-generated=true -tensor_dimension.rs linguist-generated=true tensor_dimension_index_selection.rs linguist-generated=true tensor_dimension_selection.rs linguist-generated=true utf8pair.rs linguist-generated=true diff --git a/crates/store/re_types/src/datatypes/mod.rs b/crates/store/re_types/src/datatypes/mod.rs index d1edf377eb08..f18d728fd794 100644 --- a/crates/store/re_types/src/datatypes/mod.rs +++ b/crates/store/re_types/src/datatypes/mod.rs @@ -46,8 +46,6 @@ mod tensor_buffer; mod tensor_buffer_ext; mod tensor_data; mod tensor_data_ext; -mod tensor_dimension; -mod tensor_dimension_ext; mod tensor_dimension_index_selection; mod tensor_dimension_selection; mod tensor_dimension_selection_ext; @@ -95,7 +93,6 @@ pub use self::rgba32::Rgba32; pub use self::rotation_axis_angle::RotationAxisAngle; pub use self::tensor_buffer::TensorBuffer; pub use self::tensor_data::TensorData; -pub use self::tensor_dimension::TensorDimension; pub use self::tensor_dimension_index_selection::TensorDimensionIndexSelection; pub use self::tensor_dimension_selection::TensorDimensionSelection; pub use self::utf8pair::Utf8Pair; diff --git a/crates/store/re_types/src/datatypes/tensor_data.rs b/crates/store/re_types/src/datatypes/tensor_data.rs index 0d19cb6190a6..4d75cc0c12e3 100644 --- a/crates/store/re_types/src/datatypes/tensor_data.rs +++ b/crates/store/re_types/src/datatypes/tensor_data.rs @@ -28,8 +28,17 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// which stores a contiguous array of typed values. #[derive(Clone, Debug, PartialEq)] pub struct TensorData { - /// The shape of the tensor, including optional names for each dimension. - pub shape: Vec, + /// The shape of the tensor, i.e. the length of each dimension. + pub shape: ::re_types_core::ArrowBuffer, + + /// The names of the dimensions of the tensor (optional). + /// + /// If set, should be the same length as [`datatypes::TensorData::shape`][crate::datatypes::TensorData::shape]. + /// 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"]`. + pub names: Option>, /// The content/data. pub buffer: crate::datatypes::TensorBuffer, @@ -47,11 +56,20 @@ impl ::re_types_core::Loggable for TensorData { "shape", DataType::List(std::sync::Arc::new(Field::new( "item", - ::arrow_datatype(), + DataType::UInt64, false, ))), false, ), + Field::new( + "names", + DataType::List(std::sync::Arc::new(Field::new( + "item", + DataType::Utf8, + false, + ))), + true, + ), Field::new( "buffer", ::arrow_datatype(), @@ -76,11 +94,20 @@ impl ::re_types_core::Loggable for TensorData { "shape", DataType::List(std::sync::Arc::new(Field::new( "item", - ::arrow_datatype(), + DataType::UInt64, false, ))), false, ), + Field::new( + "names", + DataType::List(std::sync::Arc::new(Field::new( + "item", + DataType::Utf8, + false, + ))), + true, + ), Field::new( "buffer", ::arrow_datatype(), @@ -113,29 +140,73 @@ impl ::re_types_core::Loggable for TensorData { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; + { + let offsets = + arrow::buffer::OffsetBuffer::::from_lengths(shape.iter().map( + |opt| opt.as_ref().map_or(0, |datum| datum.num_instances()), + )); + let shape_inner_data: ScalarBuffer<_> = shape + .iter() + .flatten() + .map(|b| b.as_slice()) + .collect::>() + .concat() + .into(); + let shape_inner_validity: Option = None; + as_array_ref(ListArray::try_new( + std::sync::Arc::new(Field::new("item", DataType::UInt64, false)), + offsets, + as_array_ref(PrimitiveArray::::new( + shape_inner_data, + shape_inner_validity, + )), + shape_validity, + )?) + } + }, + { + let (somes, names): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = + datum.as_ref().map(|datum| datum.names.clone()).flatten(); + (datum.is_some(), datum) + }) + .unzip(); + let names_validity: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; { let offsets = arrow::buffer::OffsetBuffer::::from_lengths( - shape + names .iter() .map(|opt| opt.as_ref().map_or(0, |datum| datum.len())), ); - let shape_inner_data: Vec<_> = - shape.into_iter().flatten().flatten().collect(); - let shape_inner_validity: Option = None; + let names_inner_data: Vec<_> = + names.into_iter().flatten().flatten().collect(); + let names_inner_validity: Option = None; as_array_ref(ListArray::try_new( - std::sync::Arc::new(Field::new( - "item", - ::arrow_datatype(), - false, - )), + std::sync::Arc::new(Field::new("item", DataType::Utf8, false)), offsets, { - _ = shape_inner_validity; - crate::datatypes::TensorDimension::to_arrow_opt( - shape_inner_data.into_iter().map(Some), - )? + let offsets = arrow::buffer::OffsetBuffer::::from_lengths( + names_inner_data.iter().map(|datum| datum.len()), + ); + let inner_data: arrow::buffer::Buffer = names_inner_data + .into_iter() + .flat_map(|s| s.into_arrow2_buffer()) + .collect(); + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + as_array_ref(unsafe { + StringArray::new_unchecked( + offsets, + inner_data, + names_inner_validity, + ) + }) }, - shape_validity, + names_validity, )?) } }, @@ -208,7 +279,7 @@ impl ::re_types_core::Loggable for TensorData { .ok_or_else(|| { let expected = DataType::List(std::sync::Arc::new(Field::new( "item", - ::arrow_datatype(), + DataType::UInt64, false, ))); let actual = arrow_data.data_type().clone(); @@ -220,10 +291,133 @@ impl ::re_types_core::Loggable for TensorData { } else { let arrow_data_inner = { let arrow_data_inner = &**arrow_data.values(); - crate::datatypes::TensorDimension::from_arrow2_opt(arrow_data_inner) + arrow_data_inner + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::UInt64; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) .with_context("rerun.datatypes.TensorData#shape")? + .values() + }; + let offsets = arrow_data.offsets(); + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets.windows(2), + arrow_data.validity(), + ) + .map(|elem| { + elem.map(|window| { + let start = window[0] as usize; + let end = window[1] as usize; + if arrow_data_inner.len() < end { + return Err(DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner.len(), + )); + } + + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let data = unsafe { + arrow_data_inner + .clone() + .sliced_unchecked(start, end - start) + }; + let data = ::re_types_core::ArrowBuffer::from(data); + Ok(data) + }) + .transpose() + }) + .collect::>>>()? + } + .into_iter() + } + }; + let names = { + if !arrays_by_name.contains_key("names") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "names", + )) + .with_context("rerun.datatypes.TensorData"); + } + let arrow_data = &**arrays_by_name["names"]; + { + let arrow_data = arrow_data + .as_any() + .downcast_ref::>() + .ok_or_else(|| { + let expected = DataType::List(std::sync::Arc::new(Field::new( + "item", + DataType::Utf8, + false, + ))); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.TensorData#names")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let arrow_data_inner = { + let arrow_data_inner = &**arrow_data.values(); + { + let arrow_data_inner = arrow_data_inner + .as_any() + .downcast_ref::>() + .ok_or_else(|| { + let expected = DataType::Utf8; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch( + expected, actual, + ) + }) + .with_context("rerun.datatypes.TensorData#names")?; + let arrow_data_inner_buf = arrow_data_inner.values(); + let offsets = arrow_data_inner.offsets(); + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets.windows(2), + arrow_data_inner.validity(), + ) + .map(|elem| { + elem.map(|window| { + let start = window[0] as usize; + let end = window[1] as usize; + let len = end - start; + if arrow_data_inner_buf.len() < end { + return Err( + DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner_buf.len(), + ), + ); + } + + #[allow( + unsafe_code, + clippy::undocumented_unsafe_blocks + )] + let data = unsafe { + arrow_data_inner_buf + .clone() + .sliced_unchecked(start, len) + }; + Ok(data) + }) + .transpose() + }) + .map(|res_or_opt| { + res_or_opt.map(|res_or_opt| { + res_or_opt + .map(|v| ::re_types_core::ArrowString::from(v)) + }) + }) + .collect::>>>() + .with_context("rerun.datatypes.TensorData#names")? .into_iter() - .collect::>() + } + .collect::>() }; let offsets = arrow_data.offsets(); arrow2::bitmap::utils::ZipValidity::new_with_validity( @@ -272,15 +466,16 @@ impl ::re_types_core::Loggable for TensorData { .into_iter() }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(shape, buffer), + ::itertools::izip!(shape, names, buffer), arrow_data.validity(), ) .map(|opt| { - opt.map(|(shape, buffer)| { + opt.map(|(shape, names, buffer)| { Ok(Self { shape: shape .ok_or_else(DeserializationError::missing_data) .with_context("rerun.datatypes.TensorData#shape")?, + names, buffer: buffer .ok_or_else(DeserializationError::missing_data) .with_context("rerun.datatypes.TensorData#buffer")?, @@ -298,12 +493,13 @@ impl ::re_types_core::Loggable for TensorData { impl ::re_types_core::SizeBytes for TensorData { #[inline] fn heap_size_bytes(&self) -> u64 { - self.shape.heap_size_bytes() + self.buffer.heap_size_bytes() + self.shape.heap_size_bytes() + self.names.heap_size_bytes() + self.buffer.heap_size_bytes() } #[inline] fn is_pod() -> bool { - >::is_pod() + <::re_types_core::ArrowBuffer>::is_pod() + && >>::is_pod() && ::is_pod() } } diff --git a/crates/store/re_types/src/datatypes/tensor_data_ext.rs b/crates/store/re_types/src/datatypes/tensor_data_ext.rs index bca0ddde0c2d..537368d08ace 100644 --- a/crates/store/re_types/src/datatypes/tensor_data_ext.rs +++ b/crates/store/re_types/src/datatypes/tensor_data_ext.rs @@ -1,3 +1,5 @@ +use re_types_core::{ArrowBuffer, ArrowString}; + use crate::tensor_data::{TensorCastError, TensorDataType, TensorElement}; #[cfg(feature = "image")] @@ -6,33 +8,69 @@ use crate::tensor_data::TensorImageLoadError; #[allow(unused_imports)] // Used for docstring links use crate::archetypes::EncodedImage; -use super::{TensorBuffer, TensorData, TensorDimension}; +use super::{TensorBuffer, TensorData}; // ---------------------------------------------------------------------------- impl TensorData { /// Create a new tensor. #[inline] - pub fn new(shape: Vec, buffer: TensorBuffer) -> Self { - Self { shape, buffer } + pub fn new(shape: impl Into>, buffer: TensorBuffer) -> Self { + Self { + shape: shape.into(), + names: None, + buffer, + } } - /// The shape of the tensor, including optional dimension names. + /// Set the names of the dimensions to the provided names. + /// + /// Any existing names will be overwritten. + /// + /// If the wrong number of names are given, a warning will be logged, + /// and the names might not show up correctly. + pub fn with_dim_names( + mut self, + names: impl IntoIterator>, + ) -> Self { + let names: Vec = names.into_iter().map(|x| x.into()).collect(); + + if names.len() != self.shape.len() { + re_log::warn_once!( + "Wrong number of names provided for tensor dimension. {} provided but {} expected. The names will be ignored.", + names.len(), + self.shape.len(), + ); + } + + self.names = Some(names); + + self + } + + /// The shape of the tensor. #[inline] - pub fn shape(&self) -> &[TensorDimension] { + pub fn shape(&self) -> &[u64] { self.shape.as_slice() } + /// Get the name of a specific dimension. + /// + /// Returns `None` if the dimension does not have a name. + pub fn dim_name(&self, dim: usize) -> Option<&ArrowString> { + self.names.as_ref().and_then(|names| names.get(dim)) + } + /// Returns the shape of the tensor with all leading & trailing dimensions of size 1 ignored. /// /// If all dimension sizes are one, this returns only the first dimension. #[inline] - pub fn shape_short(&self) -> &[TensorDimension] { + pub fn shape_short(&self) -> &[u64] { if self.shape.is_empty() { &self.shape } else { - let first_not_one = self.shape.iter().position(|dim| dim.size != 1); - let last_not_one = self.shape.iter().rev().position(|dim| dim.size != 1); + let first_not_one = self.shape.iter().position(|&dim| dim != 1); + let last_not_one = self.shape.iter().rev().position(|&dim| dim != 1); &self.shape[first_not_one.unwrap_or(0)..self.shape.len() - last_not_one.unwrap_or(0)] } } @@ -53,7 +91,7 @@ impl TensorData { if self.shape.is_empty() { false } else { - self.shape.iter().filter(|dim| dim.size > 1).count() <= 1 + self.shape.iter().filter(|&&dim| dim > 1).count() <= 1 } } @@ -63,12 +101,12 @@ impl TensorData { pub fn get(&self, index: &[u64]) -> Option { let mut stride: usize = 1; let mut offset: usize = 0; - for (TensorDimension { size, .. }, index) in self.shape.iter().zip(index).rev() { + for (&size, &index) in self.shape.iter().zip(index).rev() { if size <= index { return None; } - offset += *index as usize * stride; - stride *= *size as usize; + offset += index as usize * stride; + stride *= size as usize; } match &self.buffer { @@ -103,7 +141,8 @@ impl Default for TensorData { #[inline] fn default() -> Self { Self { - shape: Vec::new(), + shape: Default::default(), + names: None, buffer: TensorBuffer::U8(Vec::new().into()), } } @@ -117,7 +156,7 @@ macro_rules! ndarray_from_tensor { type Error = TensorCastError; fn try_from(value: &'a TensorData) -> Result { - let shape: Vec<_> = value.shape.iter().map(|d| d.size as usize).collect(); + let shape: Vec = value.shape.iter().map(|&d| d as usize).collect(); if let TensorBuffer::$variant(data) = &value.buffer { ndarray::ArrayViewD::from_shape(shape, data.as_slice()) @@ -138,26 +177,17 @@ macro_rules! tensor_from_ndarray { type Error = TensorCastError; fn try_from(view: ::ndarray::ArrayView<'a, $type, D>) -> Result { - let shape = view - .shape() - .iter() - .map(|dim| TensorDimension { - size: *dim as u64, - name: None, - }) - .collect(); + let shape = ArrowBuffer::from_iter(view.shape().iter().map(|&dim| dim as u64)); match view.to_slice() { - Some(slice) => Ok(TensorData { + Some(slice) => Ok(TensorData::new( shape, - buffer: TensorBuffer::$variant(Vec::from(slice).into()), - }), - None => Ok(TensorData { + TensorBuffer::$variant(Vec::from(slice).into()), + )), + None => Ok(TensorData::new( shape, - buffer: TensorBuffer::$variant( - view.iter().cloned().collect::>().into(), - ), - }), + TensorBuffer::$variant(view.iter().cloned().collect::>().into()), + )), } } } @@ -166,14 +196,7 @@ macro_rules! tensor_from_ndarray { type Error = TensorCastError; fn try_from(value: ndarray::Array<$type, D>) -> Result { - let shape = value - .shape() - .iter() - .map(|dim| TensorDimension { - size: *dim as u64, - name: None, - }) - .collect(); + let shape = ArrowBuffer::from_iter(value.shape().iter().map(|&dim| dim as u64)); let vec = if value.is_standard_layout() { let (mut vec, offset) = value.into_raw_vec_and_offset(); @@ -190,28 +213,22 @@ macro_rules! tensor_from_ndarray { value.into_iter().collect::>() }; - Ok(Self { - shape, - buffer: TensorBuffer::$variant(vec.into()), - }) + Ok(Self::new(shape, TensorBuffer::$variant(vec.into()))) } } impl From> for TensorData { fn from(vec: Vec<$type>) -> Self { - TensorData { - shape: vec![TensorDimension::unnamed(vec.len() as u64)], - buffer: TensorBuffer::$variant(vec.into()), - } + Self::new(vec![vec.len() as u64], TensorBuffer::$variant(vec.into())) } } impl From<&[$type]> for TensorData { fn from(slice: &[$type]) -> Self { - TensorData { - shape: vec![TensorDimension::unnamed(slice.len() as u64)], - buffer: TensorBuffer::$variant(slice.into()), - } + Self::new( + vec![slice.len() as u64], + TensorBuffer::$variant(slice.into()), + ) } } }; @@ -247,7 +264,7 @@ impl<'a> TryFrom<&'a TensorData> for ::ndarray::ArrayViewD<'a, u8> { fn try_from(value: &'a TensorData) -> Result { match &value.buffer { TensorBuffer::U8(data) => { - let shape: Vec<_> = value.shape.iter().map(|d| d.size as usize).collect(); + let shape: Vec = value.shape.iter().map(|&d| d as usize).collect(); ndarray::ArrayViewD::from_shape(shape, bytemuck::cast_slice(data.as_slice())) .map_err(|err| TensorCastError::BadTensorShape { source: err }) } @@ -363,19 +380,15 @@ impl TensorData { )); } }; - let shape = if depth == 1 { - vec![ - TensorDimension::height(h as _), - TensorDimension::width(w as _), - ] + let (shape, names) = if depth == 1 { + (vec![h as _, w as _], vec!["height", "width"]) } else { - vec![ - TensorDimension::height(h as _), - TensorDimension::width(w as _), - TensorDimension::depth(depth), - ] + ( + vec![h as _, w as _, depth], + vec!["height", "width", "depth"], + ) }; - Ok(Self { shape, buffer }) + Ok(Self::new(shape, buffer).with_dim_names(names)) } } diff --git a/crates/store/re_types/src/datatypes/tensor_dimension.rs b/crates/store/re_types/src/datatypes/tensor_dimension.rs deleted file mode 100644 index 619c954eea2f..000000000000 --- a/crates/store/re_types/src/datatypes/tensor_dimension.rs +++ /dev/null @@ -1,266 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs". - -#![allow(unused_imports)] -#![allow(unused_parens)] -#![allow(clippy::clone_on_copy)] -#![allow(clippy::cloned_instead_of_copied)] -#![allow(clippy::map_flatten)] -#![allow(clippy::needless_question_mark)] -#![allow(clippy::new_without_default)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::too_many_lines)] - -use ::re_types_core::external::arrow2; -use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, ComponentBatchCowWithDescriptor}; -use ::re_types_core::{ComponentDescriptor, ComponentName}; -use ::re_types_core::{DeserializationError, DeserializationResult}; - -/// **Datatype**: A single dimension within a multi-dimensional tensor. -#[derive(Clone, Default, Eq, PartialEq)] -pub struct TensorDimension { - /// The length of this dimension. - pub size: u64, - - /// The name of this dimension, e.g. "width", "height", "channel", "batch', …. - pub name: Option<::re_types_core::ArrowString>, -} - -::re_types_core::macros::impl_into_cow!(TensorDimension); - -impl ::re_types_core::Loggable for TensorDimension { - #[inline] - fn arrow_datatype() -> arrow::datatypes::DataType { - #![allow(clippy::wildcard_imports)] - use arrow::datatypes::*; - DataType::Struct(Fields::from(vec![ - Field::new("size", DataType::UInt64, false), - Field::new("name", DataType::Utf8, true), - ])) - } - - fn to_arrow_opt<'a>( - data: impl IntoIterator>>>, - ) -> SerializationResult - where - Self: Clone + 'a, - { - #![allow(clippy::wildcard_imports)] - #![allow(clippy::manual_is_variant_and)] - use ::re_types_core::{arrow_helpers::as_array_ref, Loggable as _, ResultExt as _}; - use arrow::{array::*, buffer::*, datatypes::*}; - Ok({ - let fields = Fields::from(vec![ - Field::new("size", DataType::UInt64, false), - Field::new("name", DataType::Utf8, true), - ]); - let (somes, data): (Vec<_>, Vec<_>) = data - .into_iter() - .map(|datum| { - let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); - (datum.is_some(), datum) - }) - .unzip(); - let validity: Option = { - let any_nones = somes.iter().any(|some| !*some); - any_nones.then(|| somes.into()) - }; - as_array_ref(StructArray::new( - fields, - vec![ - { - let (somes, size): (Vec<_>, Vec<_>) = data - .iter() - .map(|datum| { - let datum = datum.as_ref().map(|datum| datum.size.clone()); - (datum.is_some(), datum) - }) - .unzip(); - let size_validity: Option = { - let any_nones = somes.iter().any(|some| !*some); - any_nones.then(|| somes.into()) - }; - as_array_ref(PrimitiveArray::::new( - ScalarBuffer::from( - size.into_iter() - .map(|v| v.unwrap_or_default()) - .collect::>(), - ), - size_validity, - )) - }, - { - let (somes, name): (Vec<_>, Vec<_>) = data - .iter() - .map(|datum| { - let datum = - datum.as_ref().map(|datum| datum.name.clone()).flatten(); - (datum.is_some(), datum) - }) - .unzip(); - let name_validity: Option = { - let any_nones = somes.iter().any(|some| !*some); - any_nones.then(|| somes.into()) - }; - { - let offsets = - arrow::buffer::OffsetBuffer::::from_lengths(name.iter().map( - |opt| opt.as_ref().map(|datum| datum.len()).unwrap_or_default(), - )); - let inner_data: arrow::buffer::Buffer = name - .into_iter() - .flatten() - .flat_map(|s| s.into_arrow2_buffer()) - .collect(); - #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] - as_array_ref(unsafe { - StringArray::new_unchecked(offsets, inner_data, name_validity) - }) - } - }, - ], - validity, - )) - }) - } - - fn from_arrow2_opt( - arrow_data: &dyn arrow2::array::Array, - ) -> DeserializationResult>> - where - Self: Sized, - { - #![allow(clippy::wildcard_imports)] - use ::re_types_core::{Loggable as _, ResultExt as _}; - use arrow::datatypes::*; - use arrow2::{array::*, buffer::*}; - Ok({ - let arrow_data = arrow_data - .as_any() - .downcast_ref::() - .ok_or_else(|| { - let expected = Self::arrow_datatype(); - let actual = arrow_data.data_type().clone(); - DeserializationError::datatype_mismatch(expected, actual) - }) - .with_context("rerun.datatypes.TensorDimension")?; - if arrow_data.is_empty() { - Vec::new() - } else { - let (arrow_data_fields, arrow_data_arrays) = - (arrow_data.fields(), arrow_data.values()); - let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data_fields - .iter() - .map(|field| field.name.as_str()) - .zip(arrow_data_arrays) - .collect(); - let size = { - if !arrays_by_name.contains_key("size") { - return Err(DeserializationError::missing_struct_field( - Self::arrow_datatype(), - "size", - )) - .with_context("rerun.datatypes.TensorDimension"); - } - let arrow_data = &**arrays_by_name["size"]; - arrow_data - .as_any() - .downcast_ref::() - .ok_or_else(|| { - let expected = DataType::UInt64; - let actual = arrow_data.data_type().clone(); - DeserializationError::datatype_mismatch(expected, actual) - }) - .with_context("rerun.datatypes.TensorDimension#size")? - .into_iter() - .map(|opt| opt.copied()) - }; - let name = { - if !arrays_by_name.contains_key("name") { - return Err(DeserializationError::missing_struct_field( - Self::arrow_datatype(), - "name", - )) - .with_context("rerun.datatypes.TensorDimension"); - } - let arrow_data = &**arrays_by_name["name"]; - { - let arrow_data = arrow_data - .as_any() - .downcast_ref::>() - .ok_or_else(|| { - let expected = DataType::Utf8; - let actual = arrow_data.data_type().clone(); - DeserializationError::datatype_mismatch(expected, actual) - }) - .with_context("rerun.datatypes.TensorDimension#name")?; - let arrow_data_buf = arrow_data.values(); - let offsets = arrow_data.offsets(); - arrow2::bitmap::utils::ZipValidity::new_with_validity( - offsets.windows(2), - arrow_data.validity(), - ) - .map(|elem| { - elem.map(|window| { - let start = window[0] as usize; - let end = window[1] as usize; - let len = end - start; - if arrow_data_buf.len() < end { - return Err(DeserializationError::offset_slice_oob( - (start, end), - arrow_data_buf.len(), - )); - } - - #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] - let data = - unsafe { arrow_data_buf.clone().sliced_unchecked(start, len) }; - Ok(data) - }) - .transpose() - }) - .map(|res_or_opt| { - res_or_opt.map(|res_or_opt| { - res_or_opt.map(|v| ::re_types_core::ArrowString::from(v)) - }) - }) - .collect::>>>() - .with_context("rerun.datatypes.TensorDimension#name")? - .into_iter() - } - }; - arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(size, name), - arrow_data.validity(), - ) - .map(|opt| { - opt.map(|(size, name)| { - Ok(Self { - size: size - .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.datatypes.TensorDimension#size")?, - name, - }) - }) - .transpose() - }) - .collect::>>() - .with_context("rerun.datatypes.TensorDimension")? - } - }) - } -} - -impl ::re_types_core::SizeBytes for TensorDimension { - #[inline] - fn heap_size_bytes(&self) -> u64 { - self.size.heap_size_bytes() + self.name.heap_size_bytes() - } - - #[inline] - fn is_pod() -> bool { - ::is_pod() && >::is_pod() - } -} diff --git a/crates/store/re_types/src/datatypes/tensor_dimension_ext.rs b/crates/store/re_types/src/datatypes/tensor_dimension_ext.rs deleted file mode 100644 index 8f50ab11ecd9..000000000000 --- a/crates/store/re_types/src/datatypes/tensor_dimension_ext.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::TensorDimension; - -impl TensorDimension { - const DEFAULT_NAME_WIDTH: &'static str = "width"; - const DEFAULT_NAME_HEIGHT: &'static str = "height"; - const DEFAULT_NAME_DEPTH: &'static str = "depth"; - - /// Create a new dimension with a given size, and the name "height". - #[inline] - pub fn height(size: u64) -> Self { - Self::named(size, String::from(Self::DEFAULT_NAME_HEIGHT)) - } - - /// Create a new dimension with a given size, and the name "width". - #[inline] - pub fn width(size: u64) -> Self { - Self::named(size, String::from(Self::DEFAULT_NAME_WIDTH)) - } - - /// Create a new dimension with a given size, and the name "depth". - #[inline] - pub fn depth(size: u64) -> Self { - Self::named(size, String::from(Self::DEFAULT_NAME_DEPTH)) - } - - /// Create a named dimension. - #[inline] - pub fn named(size: u64, name: impl Into) -> Self { - Self { - size, - name: Some(name.into()), - } - } - - /// Create an unnamed dimension. - #[inline] - pub fn unnamed(size: u64) -> Self { - Self { size, name: None } - } -} - -impl std::fmt::Debug for TensorDimension { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(name) = &self.name { - write!(f, "{}={}", name, self.size) - } else { - self.size.fmt(f) - } - } -} - -impl std::fmt::Display for TensorDimension { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(name) = &self.name { - write!(f, "{}={}", name, self.size) - } else { - self.size.fmt(f) - } - } -} diff --git a/crates/store/re_types/src/image.rs b/crates/store/re_types/src/image.rs index 75e13f6f1e16..1041f07ff38b 100644 --- a/crates/store/re_types/src/image.rs +++ b/crates/store/re_types/src/image.rs @@ -1,10 +1,11 @@ //! Image-related utilities. +use re_types_core::ArrowBuffer; use smallvec::{smallvec, SmallVec}; use crate::{ datatypes::ChannelDatatype, - datatypes::{Blob, TensorBuffer, TensorData, TensorDimension}, + datatypes::{Blob, TensorBuffer, TensorData}, }; // ---------------------------------------------------------------------------- @@ -95,7 +96,7 @@ where /// The tensor did not have the right shape for an image (e.g. had too many dimensions). #[error("Could not create Image from TensorData with shape {0:?}")] - BadImageShape(Vec), + BadImageShape(ArrowBuffer), /// Happens if you try to cast `NV12` or `YUY2` to a depth image or segmentation image. #[error("Chroma downsampling is not supported for this image type (e.g. DepthImage or SegmentationImage)")] @@ -181,7 +182,7 @@ impl ImageChannelType for f64 { /// /// For instance: `[1, 480, 640, 3, 1]` would return `[1, 2, 3]`, /// the indices of the `[480, 640, 3]` dimensions. -pub fn find_non_empty_dim_indices(shape: &[TensorDimension]) -> SmallVec<[usize; 4]> { +pub fn find_non_empty_dim_indices(shape: &[u64]) -> SmallVec<[usize; 4]> { match shape.len() { 0 => return smallvec![], 1 => return smallvec![0], @@ -197,7 +198,7 @@ pub fn find_non_empty_dim_indices(shape: &[TensorDimension]) -> SmallVec<[usize; shape .iter() .enumerate() - .filter_map(|(ind, dim)| if dim.size != 1 { Some(ind) } else { None }); + .filter_map(|(ind, &dim)| if dim != 1 { Some(ind) } else { None }); // 0 is always a valid index. let mut min = non_unit_indices.next().unwrap_or(0); @@ -216,7 +217,7 @@ pub fn find_non_empty_dim_indices(shape: &[TensorDimension]) -> SmallVec<[usize; // Grow up to 3 if the inner dimension is already 3 or 4 (Color Images) // Otherwise, only grow up to 2. // (1x1x3) -> 1x1x3 rgb rather than 1x3 mono - let target_len = match shape[max].size { + let target_len = match shape[max] { 3 | 4 => 3, _ => 2, }; @@ -231,14 +232,7 @@ pub fn find_non_empty_dim_indices(shape: &[TensorDimension]) -> SmallVec<[usize; #[test] fn test_find_non_empty_dim_indices() { fn expect(shape: &[u64], expected: &[usize]) { - let dim: Vec<_> = shape - .iter() - .map(|s| TensorDimension { - size: *s, - name: None, - }) - .collect(); - let got = find_non_empty_dim_indices(&dim); + let got = find_non_empty_dim_indices(shape); assert!( got.as_slice() == expected, "Input: {shape:?}, got {got:?}, expected {expected:?}" diff --git a/crates/store/re_types/src/reflection/mod.rs b/crates/store/re_types/src/reflection/mod.rs index 2deab0ebfb3c..cd1537ad937b 100644 --- a/crates/store/re_types/src/reflection/mod.rs +++ b/crates/store/re_types/src/reflection/mod.rs @@ -1413,11 +1413,11 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "edges", display_name : "Edges", component_name : "rerun.components.GraphEdge".into(), docstring_md : - "A list of node tuples.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", - is_required : true, }, ArchetypeFieldReflection { name : - "graph_type", display_name : "Graph type", component_name : - "rerun.components.GraphType".into(), docstring_md : - "Specifies if the graph is directed or undirected.\n\nIf no [`components.GraphType`](https://rerun.io/docs/reference/types/components/graph_type?speculative-link) is provided, the graph is assumed to be undirected.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + "A list of node tuples.", is_required : true, }, + ArchetypeFieldReflection { name : "graph_type", display_name : + "Graph type", component_name : "rerun.components.GraphType".into(), + docstring_md : + "Specifies if the graph is directed or undirected.\n\nIf no [`components.GraphType`](https://rerun.io/docs/reference/types/components/graph_type) is provided, the graph is assumed to be undirected.", is_required : false, }, ], }, @@ -1431,29 +1431,24 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "node_ids", display_name : "Node ids", component_name : "rerun.components.GraphNode".into(), - docstring_md : - "A list of node IDs.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", - is_required : true, }, ArchetypeFieldReflection { name : "positions", - display_name : "Positions", component_name : - "rerun.components.Position2D".into(), docstring_md : - "Optional center positions of the nodes.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", - is_required : false, }, ArchetypeFieldReflection { name : "colors", - display_name : "Colors", component_name : "rerun.components.Color" - .into(), docstring_md : - "Optional colors for the boxes.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", - is_required : false, }, ArchetypeFieldReflection { name : "labels", - display_name : "Labels", component_name : "rerun.components.Text" - .into(), docstring_md : - "Optional text labels for the node.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", - is_required : false, }, ArchetypeFieldReflection { name : - "show_labels", display_name : "Show labels", component_name : + docstring_md : "A list of node IDs.", is_required : true, }, + ArchetypeFieldReflection { name : "positions", display_name : + "Positions", component_name : "rerun.components.Position2D".into(), + docstring_md : "Optional center positions of the nodes.", is_required + : false, }, ArchetypeFieldReflection { name : "colors", display_name + : "Colors", component_name : "rerun.components.Color".into(), + docstring_md : "Optional colors for the boxes.", is_required : false, + }, ArchetypeFieldReflection { name : "labels", display_name : + "Labels", component_name : "rerun.components.Text".into(), + docstring_md : "Optional text labels for the node.", is_required : + false, }, ArchetypeFieldReflection { name : "show_labels", + display_name : "Show labels", component_name : "rerun.components.ShowLabels".into(), docstring_md : - "Optional choice of whether the text labels should be shown by default.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + "Optional choice of whether the text labels should be shown by default.", is_required : false, }, ArchetypeFieldReflection { name : "radii", display_name : "Radii", component_name : "rerun.components.Radius" - .into(), docstring_md : - "Optional radii for nodes.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", - is_required : false, }, + .into(), docstring_md : "Optional radii for nodes.", is_required : + false, }, ], }, ), @@ -2040,8 +2035,9 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "enabled", display_name : "Enabled", component_name : "rerun.blueprint.components.Enabled" - .into(), docstring_md : "Whether the force is enabled.", is_required - : false, }, ArchetypeFieldReflection { name : "strength", + .into(), docstring_md : + "Whether the center force is enabled.\n\nThe center force tries to move the center of mass of the graph towards the origin.", + is_required : false, }, ArchetypeFieldReflection { name : "strength", display_name : "Strength", component_name : "rerun.blueprint.components.ForceStrength".into(), docstring_md : "The strength of the force.", is_required : false, }, @@ -2057,8 +2053,9 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "enabled", display_name : "Enabled", component_name : "rerun.blueprint.components.Enabled" - .into(), docstring_md : "Whether the force is enabled.", is_required - : false, }, ArchetypeFieldReflection { name : "strength", + .into(), docstring_md : + "Whether the collision force is enabled.\n\nThe collision force resolves collisions between nodes based on the bounding circle defined by their radius.", + is_required : false, }, ArchetypeFieldReflection { name : "strength", display_name : "Strength", component_name : "rerun.blueprint.components.ForceStrength".into(), docstring_md : "The strength of the force.", is_required : false, }, @@ -2079,8 +2076,9 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "enabled", display_name : "Enabled", component_name : "rerun.blueprint.components.Enabled" - .into(), docstring_md : "Whether the force is enabled.", is_required - : false, }, ArchetypeFieldReflection { name : "distance", + .into(), docstring_md : + "Whether the link force is enabled.\n\nThe link force aims to achieve a target distance between two nodes that are connected by one ore more edges.", + is_required : false, }, ArchetypeFieldReflection { name : "distance", display_name : "Distance", component_name : "rerun.blueprint.components.ForceDistance".into(), docstring_md : "The target distance between two nodes.", is_required : false, }, @@ -2101,8 +2099,9 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "enabled", display_name : "Enabled", component_name : "rerun.blueprint.components.Enabled" - .into(), docstring_md : "Whether the force is enabled.", is_required - : false, }, ArchetypeFieldReflection { name : "strength", + .into(), docstring_md : + "Whether the many body force is enabled.\n\nThe many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the\nstrength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together.", + is_required : false, }, ArchetypeFieldReflection { name : "strength", display_name : "Strength", component_name : "rerun.blueprint.components.ForceStrength".into(), docstring_md : "The strength of the force.\n\nIf `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together.", @@ -2119,8 +2118,9 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { fields: vec![ ArchetypeFieldReflection { name : "enabled", display_name : "Enabled", component_name : "rerun.blueprint.components.Enabled" - .into(), docstring_md : "Whether the force is enabled.", is_required - : false, }, ArchetypeFieldReflection { name : "strength", + .into(), docstring_md : + "Whether the position force is enabled.\n\nThe position force pulls nodes towards a specific position, similar to gravity.", + is_required : false, }, ArchetypeFieldReflection { name : "strength", display_name : "Strength", component_name : "rerun.blueprint.components.ForceStrength".into(), docstring_md : "The strength of the force.", is_required : false, }, diff --git a/crates/store/re_types/tests/types/tensor.rs b/crates/store/re_types/tests/types/tensor.rs index 3474ae7b1d35..2fb8a132217a 100644 --- a/crates/store/re_types/tests/types/tensor.rs +++ b/crates/store/re_types/tests/types/tensor.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use re_types::{ archetypes::Tensor, - datatypes::{TensorBuffer, TensorData, TensorDimension}, + datatypes::{TensorBuffer, TensorData}, tensor_data::TensorCastError, Archetype as _, AsComponents as _, }; @@ -12,20 +12,7 @@ use crate::util; #[test] fn tensor_roundtrip() { let all_expected = [Tensor { - data: TensorData { - shape: vec![ - TensorDimension { - size: 2, - name: None, - }, - TensorDimension { - size: 3, - name: None, - }, - ], - buffer: TensorBuffer::U8(vec![1, 2, 3, 4, 5, 6].into()), - } - .into(), + data: TensorData::new(vec![2, 3], TensorBuffer::U8(vec![1, 2, 3, 4, 5, 6].into())).into(), value_range: None, }]; @@ -60,14 +47,7 @@ fn tensor_roundtrip() { #[test] fn convert_tensor_to_ndarray_u8() { - let t = TensorData::new( - vec![ - TensorDimension::unnamed(3), - TensorDimension::unnamed(4), - TensorDimension::unnamed(5), - ], - TensorBuffer::U8(vec![0; 60].into()), - ); + let t = TensorData::new(vec![3, 4, 5], TensorBuffer::U8(vec![0; 60].into())); let n = ndarray::ArrayViewD::::try_from(&t).unwrap(); @@ -76,14 +56,7 @@ fn convert_tensor_to_ndarray_u8() { #[test] fn convert_tensor_to_ndarray_u16() { - let t = TensorData::new( - vec![ - TensorDimension::unnamed(3), - TensorDimension::unnamed(4), - TensorDimension::unnamed(5), - ], - TensorBuffer::U16(vec![0_u16; 60].into()), - ); + let t = TensorData::new(vec![3, 4, 5], TensorBuffer::U16(vec![0_u16; 60].into())); let n = ndarray::ArrayViewD::::try_from(&t).unwrap(); @@ -92,14 +65,7 @@ fn convert_tensor_to_ndarray_u16() { #[test] fn convert_tensor_to_ndarray_f32() { - let t = TensorData::new( - vec![ - TensorDimension::unnamed(3), - TensorDimension::unnamed(4), - TensorDimension::unnamed(5), - ], - TensorBuffer::F32(vec![0_f32; 60].into()), - ); + let t = TensorData::new(vec![3, 4, 5], TensorBuffer::F32(vec![0_f32; 60].into())); let n = ndarray::ArrayViewD::::try_from(&t).unwrap(); @@ -111,10 +77,7 @@ fn convert_ndarray_f64_to_tensor() { let n = ndarray::array![[1., 2., 3.], [4., 5., 6.]]; let t = TensorData::try_from(n).unwrap(); - assert_eq!( - t.shape(), - &[TensorDimension::unnamed(2), TensorDimension::unnamed(3)] - ); + assert_eq!(t.shape(), &[2, 3]); } #[test] @@ -123,7 +86,7 @@ fn convert_ndarray_slice_to_tensor() { let n = &n.slice(ndarray::s![.., 1]); let t = TensorData::try_from(*n).unwrap(); - assert_eq!(t.shape(), &[TensorDimension::unnamed(2)]); + assert_eq!(t.shape(), &[2]); } #[test] @@ -220,11 +183,7 @@ fn convert_ndarray_to_tensor_both_layouts_nonzero_offset() { #[test] fn check_slices() { let t = TensorData::new( - vec![ - TensorDimension::unnamed(3), - TensorDimension::unnamed(4), - TensorDimension::unnamed(5), - ], + vec![3, 4, 5], TensorBuffer::U16((0_u16..60).collect::>().into()), ); @@ -258,14 +217,7 @@ fn check_slices() { #[test] fn check_tensor_shape_error() { - let t = TensorData::new( - vec![ - TensorDimension::unnamed(3), - TensorDimension::unnamed(4), - TensorDimension::unnamed(5), - ], - TensorBuffer::U8(vec![0; 59].into()), - ); + let t = TensorData::new(vec![3, 4, 5], TensorBuffer::U8(vec![0; 59].into())); let n = ndarray::ArrayViewD::::try_from(&t); @@ -279,14 +231,7 @@ fn check_tensor_shape_error() { #[test] fn check_tensor_type_error() { - let t = TensorData::new( - vec![ - TensorDimension::unnamed(3), - TensorDimension::unnamed(4), - TensorDimension::unnamed(5), - ], - TensorBuffer::U16(vec![0; 60].into()), - ); + let t = TensorData::new(vec![3, 4, 5], TensorBuffer::U16(vec![0; 60].into())); let n = ndarray::ArrayViewD::::try_from(&t); diff --git a/crates/store/re_types_core/src/arrow_buffer.rs b/crates/store/re_types_core/src/arrow_buffer.rs index a8ed54e38d8d..a07e47ca2e88 100644 --- a/crates/store/re_types_core/src/arrow_buffer.rs +++ b/crates/store/re_types_core/src/arrow_buffer.rs @@ -133,6 +133,16 @@ impl FromIterator for ArrowBuffer { } } +impl<'a, T: ArrowNativeType> IntoIterator for &'a ArrowBuffer { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.as_slice().iter() + } +} + impl std::ops::Deref for ArrowBuffer { type Target = [T]; diff --git a/crates/top/re_sdk/src/lib.rs b/crates/top/re_sdk/src/lib.rs index ebb46e4ef346..2ef51e0e1dd7 100644 --- a/crates/top/re_sdk/src/lib.rs +++ b/crates/top/re_sdk/src/lib.rs @@ -91,7 +91,7 @@ pub mod time { pub use time::{Time, TimePoint, Timeline}; pub use re_types_core::{ - Archetype, ArchetypeName, AsComponents, Component, ComponentBatch, + Archetype, ArchetypeName, AsComponents, Component, ComponentBatch, ComponentBatchCow, ComponentBatchCowWithDescriptor, ComponentDescriptor, ComponentName, DatatypeName, DeserializationError, DeserializationResult, GenericIndicatorComponent, Loggable, LoggableBatch, NamedIndicatorComponent, SerializationError, SerializationResult, SizeBytes, diff --git a/crates/top/rerun/src/commands/entrypoint.rs b/crates/top/rerun/src/commands/entrypoint.rs index 5ef16f301e40..6ea1089cb469 100644 --- a/crates/top/rerun/src/commands/entrypoint.rs +++ b/crates/top/rerun/src/commands/entrypoint.rs @@ -621,7 +621,7 @@ where } fn run_impl( - main_thread_token: crate::MainThreadToken, + _main_thread_token: crate::MainThreadToken, _build_info: re_build_info::BuildInfo, call_source: CallSource, args: Args, @@ -838,10 +838,10 @@ fn run_impl( } else { #[cfg(feature = "native_viewer")] return re_viewer::run_native_app( - main_thread_token, + _main_thread_token, Box::new(move |cc| { let mut app = re_viewer::App::new( - main_thread_token, + _main_thread_token, _build_info, &call_source.app_env(), startup_options, diff --git a/crates/top/rerun/src/commands/rrd/compare.rs b/crates/top/rerun/src/commands/rrd/compare.rs index 3472eacd8f90..c9c7c4778e4d 100644 --- a/crates/top/rerun/src/commands/rrd/compare.rs +++ b/crates/top/rerun/src/commands/rrd/compare.rs @@ -30,6 +30,8 @@ impl CompareCommand { full_dump, } = self; + re_log::debug!("Comparing {path_to_rrd1:?} to {path_to_rrd2:?}…"); + let path_to_rrd1 = PathBuf::from(path_to_rrd1); let path_to_rrd2 = PathBuf::from(path_to_rrd2); @@ -75,6 +77,8 @@ impl CompareCommand { ); } + re_log::debug!("{path_to_rrd1:?} and {path_to_rrd2:?} are similar enough."); + Ok(()) } } diff --git a/crates/top/rerun/src/lib.rs b/crates/top/rerun/src/lib.rs index 486e96a4ae7a..3386ccc73ddc 100644 --- a/crates/top/rerun/src/lib.rs +++ b/crates/top/rerun/src/lib.rs @@ -81,12 +81,13 @@ //! You can buffer the log messages in memory and then show them in an embedded viewer: //! //! ```no_run +//! # let main_thread_token = re_capabilities::MainThreadToken::i_promise_i_am_on_the_main_thread(); //! # fn log_to(rec: &rerun::RecordingStream) {} //! let (rec, storage) = rerun::RecordingStreamBuilder::new("rerun_example_app").memory()?; //! log_to(&rec); //! //! // Will block program execution! -//! rerun::native_viewer::show(storage.take()); +//! rerun::native_viewer::show(main_thread_token, storage.take()); //! //! # Ok::<(), Box>(()) //! ``` @@ -168,10 +169,10 @@ pub const EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE: i32 = 66; pub mod external { pub use anyhow; - pub use re_build_info; - pub use re_entity_db; - pub use re_entity_db::external::*; - pub use re_format; + pub use ::re_build_info; + pub use ::re_entity_db; + pub use ::re_entity_db::external::*; + pub use ::re_format; #[cfg(feature = "run")] pub use re_data_source; diff --git a/crates/top/rerun/src/sdk.rs b/crates/top/rerun/src/sdk.rs index 4d8c70a28931..3eab417ce267 100644 --- a/crates/top/rerun/src/sdk.rs +++ b/crates/top/rerun/src/sdk.rs @@ -31,7 +31,7 @@ mod prelude { pub use re_types::datatypes::{ Angle, AnnotationInfo, ChannelDatatype, ClassDescription, ColorModel, Float32, KeypointPair, Mat3x3, PixelFormat, Quaternion, Rgba32, RotationAxisAngle, TensorBuffer, - TensorData, TensorDimension, Vec2D, Vec3D, Vec4D, + TensorData, Vec2D, Vec3D, Vec4D, }; } pub use prelude::*; diff --git a/crates/utils/re_analytics/src/lib.rs b/crates/utils/re_analytics/src/lib.rs index a0a10c8e7b0d..709f08f27345 100644 --- a/crates/utils/re_analytics/src/lib.rs +++ b/crates/utils/re_analytics/src/lib.rs @@ -217,12 +217,13 @@ pub struct Analytics { fn load_config() -> Result { let config = match Config::load() { Ok(config) => config, - #[allow(unused_variables)] + Err(err) => { // NOTE: This will cause the first run disclaimer to show up again on native, // and analytics will be disabled for the rest of the session. - #[cfg(not(target_arch = "wasm32"))] - re_log::warn!("failed to load analytics config file: {err}"); + if !cfg!(target_arch = "wasm32") { + re_log::warn!("failed to load analytics config file: {err}"); + } None } }; diff --git a/crates/utils/re_capabilities/Cargo.toml b/crates/utils/re_capabilities/Cargo.toml index d4c36f8b600e..7b9a410df627 100644 --- a/crates/utils/re_capabilities/Cargo.toml +++ b/crates/utils/re_capabilities/Cargo.toml @@ -31,5 +31,5 @@ egui = ["dep:egui"] # External dependencies: document-features.workspace = true -egui = { workspace = true, default-features = false, optional = true } +egui = { workspace = true, optional = true } static_assertions.workspace = true diff --git a/crates/utils/re_capabilities/README.md b/crates/utils/re_capabilities/README.md index c61326593afe..0388f986f3b5 100644 --- a/crates/utils/re_capabilities/README.md +++ b/crates/utils/re_capabilities/README.md @@ -3,7 +3,7 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. [![Latest version](https://img.shields.io/crates/v/re_capabilities.svg)](https://crates.io/crates/re_capabilitiescrates/utils/) -[![Documentation](https://docs.rs/re_capabilities/badge.svg?speculative-link)](https://docs.rs/re_capabilities?speculative-link) +[![Documentation](https://docs.rs/re_capabilities/badge.svg)](https://docs.rs/re_capabilities) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/utils/re_crash_handler/src/lib.rs b/crates/utils/re_crash_handler/src/lib.rs index 9efe2c28aa69..781954fb971b 100644 --- a/crates/utils/re_crash_handler/src/lib.rs +++ b/crates/utils/re_crash_handler/src/lib.rs @@ -28,69 +28,72 @@ pub fn install_crash_handlers(build_info: BuildInfo) { fn install_panic_hook(_build_info: BuildInfo) { let previous_panic_hook = std::panic::take_hook(); - std::panic::set_hook(Box::new(move |panic_info: &std::panic::PanicInfo<'_>| { - let callstack = callstack_from(&["panicking::panic_fmt\n"]); - - let file_line = panic_info.location().map(|location| { - let file = anonymize_source_file_path(&std::path::PathBuf::from(location.file())); - format!("{file}:{}", location.line()) - }); - - let msg = panic_info_message(panic_info); - - if let Some(msg) = &msg { - // Print our own panic message. - // Our formatting is nicer than `std` since we shorten the file paths (for privacy reasons). - // This also makes it easier for users to copy-paste the callstack into an issue - // without having any sensitive data in it. - - let thread = std::thread::current(); - let thread_name = thread - .name() - .map_or_else(|| format!("{:?}", thread.id()), |name| name.to_owned()); - - eprintln!("\nthread '{thread_name}' panicked at '{msg}'"); - if let Some(file_line) = &file_line { - eprintln!("{file_line}"); + std::panic::set_hook(Box::new( + move |panic_info: &std::panic::PanicHookInfo<'_>| { + let callstack = callstack_from(&["panicking::panic_fmt\n"]); + + let file_line = panic_info.location().map(|location| { + let file = anonymize_source_file_path(&std::path::PathBuf::from(location.file())); + format!("{file}:{}", location.line()) + }); + + let msg = panic_info_message(panic_info); + + if let Some(msg) = &msg { + // Print our own panic message. + // Our formatting is nicer than `std` since we shorten the file paths (for privacy reasons). + // This also makes it easier for users to copy-paste the callstack into an issue + // without having any sensitive data in it. + + let thread = std::thread::current(); + let thread_name = thread + .name() + .map_or_else(|| format!("{:?}", thread.id()), |name| name.to_owned()); + + eprintln!("\nthread '{thread_name}' panicked at '{msg}'"); + if let Some(file_line) = &file_line { + eprintln!("{file_line}"); + } + eprintln!("stack backtrace:\n{callstack}"); + } else { + // This prints the panic message and callstack: + (*previous_panic_hook)(panic_info); } - eprintln!("stack backtrace:\n{callstack}"); - } else { - // This prints the panic message and callstack: - (*previous_panic_hook)(panic_info); - } - econtext::print_econtext(); // Print additional error context, if any + econtext::print_econtext(); // Print additional error context, if any - eprintln!( - "\n\ + eprintln!( + "\n\ Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting \n\ Report bugs: https://github.com/rerun-io/rerun/issues" - ); + ); - #[cfg(feature = "analytics")] - { - if let Ok(analytics) = re_analytics::Analytics::new(std::time::Duration::from_millis(1)) + #[cfg(feature = "analytics")] { - analytics.record(re_analytics::event::CrashPanic { - build_info: _build_info, - callstack, - // Don't include panic message, because it can contain sensitive information, - // e.g. `panic!("Couldn't read {sensitive_file_path}")`. - message: None, - file_line, - }); - - std::thread::sleep(std::time::Duration::from_secs(1)); // Give analytics time to send the event + if let Ok(analytics) = + re_analytics::Analytics::new(std::time::Duration::from_millis(1)) + { + analytics.record(re_analytics::event::CrashPanic { + build_info: _build_info, + callstack, + // Don't include panic message, because it can contain sensitive information, + // e.g. `panic!("Couldn't read {sensitive_file_path}")`. + message: None, + file_line, + }); + + std::thread::sleep(std::time::Duration::from_secs(1)); // Give analytics time to send the event + } } - } - // We compile with `panic = "abort"`, but we don't want to report the same problem twice, so just exit: - #[allow(clippy::exit)] - std::process::exit(102); - })); + // We compile with `panic = "abort"`, but we don't want to report the same problem twice, so just exit: + #[allow(clippy::exit)] + std::process::exit(102); + }, + )); } -fn panic_info_message(panic_info: &std::panic::PanicInfo<'_>) -> Option { +fn panic_info_message(panic_info: &std::panic::PanicHookInfo<'_>) -> Option { // `panic_info.message` is unstable, so this is the recommended way of getting // the panic message out. We need both the `&str` and `String` variants. diff --git a/crates/viewer/re_component_ui/src/marker_shape.rs b/crates/viewer/re_component_ui/src/marker_shape.rs index 5c08682ee1f4..92ceaa4245e4 100644 --- a/crates/viewer/re_component_ui/src/marker_shape.rs +++ b/crates/viewer/re_component_ui/src/marker_shape.rs @@ -81,7 +81,7 @@ pub(crate) fn paint_marker( .filled(true); let bounds = egui_plot::PlotBounds::new_symmetrical(0.5); - let transform = egui_plot::PlotTransform::new(rect, bounds, true, true); + let transform = egui_plot::PlotTransform::new(rect, bounds, [true, true].into()); let mut shapes = vec![]; points.shapes(ui, &transform, &mut shapes); diff --git a/crates/viewer/re_component_ui/src/plane3d.rs b/crates/viewer/re_component_ui/src/plane3d.rs index 2b3484f60e19..d0432dd7a4a2 100644 --- a/crates/viewer/re_component_ui/src/plane3d.rs +++ b/crates/viewer/re_component_ui/src/plane3d.rs @@ -83,37 +83,41 @@ pub fn edit_or_view_plane3d( let distance = value.distance(); ui.label("n"); - // Show simplified combobox if this is axis aligned. - let mut axis_dir = AxisDirection::from(glam::Vec3::from(value.normal())); - let normal_response = response_with_changes_of_inner( - egui::ComboBox::from_id_salt("plane_normal") - .selected_text(format!("{axis_dir}")) - .height(250.0) - .show_ui(ui, |ui| { - let mut variants = AxisDirection::VARIANTS.iter(); - #[allow(clippy::unwrap_used)] // We know there's more than zero variants. - let variant = variants.next().unwrap(); - - let mut response = - ui.selectable_value(&mut axis_dir, *variant, variant.to_string()); - for variant in variants { - response |= ui.selectable_value(&mut axis_dir, *variant, variant.to_string()); - } - - if let MaybeMutRef::MutRef(value) = value { + + let normal_response = if let Some(value_mut) = value.as_mut() { + // Show simplified combobox if this is axis aligned. + let mut axis_dir = AxisDirection::from(glam::Vec3::from(value_mut.normal())); + response_with_changes_of_inner( + egui::ComboBox::from_id_salt("plane_normal") + .selected_text(format!("{axis_dir}")) + .height(250.0) + .show_ui(ui, |ui| { + let mut variants = AxisDirection::VARIANTS.iter(); + #[allow(clippy::unwrap_used)] // We know there's more than zero variants. + let variant = variants.next().unwrap(); + + let mut response = + ui.selectable_value(&mut axis_dir, *variant, variant.to_string()); + for variant in variants { + response |= + ui.selectable_value(&mut axis_dir, *variant, variant.to_string()); + } if let Ok(new_dir) = glam::Vec3::try_from(axis_dir) { - **value = components::Plane3D::new(new_dir, distance); + *value_mut = components::Plane3D::new(new_dir, distance); } - } - response - }), - ) - .on_hover_text(format!( - "{} {} {}", - re_format::format_f32(value.normal().x()), - re_format::format_f32(value.normal().y()), - re_format::format_f32(value.normal().z()), - )); + response + }), + ) + .on_hover_text(format!( + "{} {} {}", + re_format::format_f32(value.normal().x()), + re_format::format_f32(value.normal().y()), + re_format::format_f32(value.normal().z()), + )) + } else { + let normal = value.normal(); + edit_or_view_vec3d_raw(ui, &mut MaybeMutRef::Ref(&normal)) + }; ui.label("d"); let mut maybe_mut_distance = match value { diff --git a/crates/viewer/re_data_ui/src/component.rs b/crates/viewer/re_data_ui/src/component.rs index eeab5dabdbf0..663923ddb5cd 100644 --- a/crates/viewer/re_data_ui/src/component.rs +++ b/crates/viewer/re_data_ui/src/component.rs @@ -75,8 +75,7 @@ impl DataUi for ComponentPathLatestAtResults<'_> { let temporal_message_count = engine .store() - .num_temporal_events_for_component_on_timeline( - &query.timeline(), + .num_temporal_events_for_component_on_all_timelines( entity_path, *component_name, ); diff --git a/crates/viewer/re_data_ui/src/instance_path.rs b/crates/viewer/re_data_ui/src/instance_path.rs index c2bdecf82db7..7030face69d7 100644 --- a/crates/viewer/re_data_ui/src/instance_path.rs +++ b/crates/viewer/re_data_ui/src/instance_path.rs @@ -67,7 +67,7 @@ impl DataUi for InstancePath { .filter(|c| c.is_indicator_component()) .count(); - let components = latest_at(db, query, entity_path, &components); + let mut components = latest_at(db, query, entity_path, &components); if components.is_empty() { ui_layout.label( @@ -96,6 +96,20 @@ impl DataUi for InstancePath { ), ); } else { + // TODO(#7026): Instances today are too poorly defined: + // For many archetypes it makes sense to slice through all their component arrays with the same index. + // However, there are cases when there are multiple dimensions of slicing that make sense. + // This is most obvious for meshes & graph nodes where there are different dimensions for vertices/edges/etc. + // + // For graph nodes this is particularly glaring since our indicices imply nodes today and + // unlike with meshes it's very easy to hover & select individual nodes. + // In order to work around the GraphEdges showing up associated with random nodes, we just hide them here. + // (this is obviously a hack and these relationships should be formalized such that they are accessible to the UI, see ticket link above) + if !self.is_all() { + components + .retain(|(component, _chunk)| component != &components::GraphEdge::name()); + } + component_list_ui( ctx, ui, diff --git a/crates/viewer/re_data_ui/src/tensor.rs b/crates/viewer/re_data_ui/src/tensor.rs index afe680f47228..8d21b1c1d45c 100644 --- a/crates/viewer/re_data_ui/src/tensor.rs +++ b/crates/viewer/re_data_ui/src/tensor.rs @@ -2,41 +2,34 @@ use itertools::Itertools as _; use re_chunk_store::RowId; use re_log_types::EntityPath; -use re_types::datatypes::{TensorData, TensorDimension}; +use re_types::datatypes::TensorData; use re_ui::UiExt as _; use re_viewer_context::{TensorStats, TensorStatsCache, UiLayout, ViewerContext}; use super::EntityDataUi; -pub fn format_tensor_shape_single_line(shape: &[TensorDimension]) -> String { - const MAX_SHOWN: usize = 4; // should be enough for width/height/depth and then some! - let iter = shape.iter().take(MAX_SHOWN); - let labelled = iter.clone().any(|dim| dim.name.is_some()); - let shapes = iter - .map(|dim| { +fn format_tensor_shape_single_line(tensor: &TensorData) -> String { + let has_names = tensor + .shape + .iter() + .enumerate() + .any(|(dim_idx, _)| tensor.dim_name(dim_idx).is_some()); + tensor + .shape + .iter() + .enumerate() + .map(|(dim_idx, dim_len)| { format!( "{}{}", - dim.size, - if let Some(name) = &dim.name { + dim_len, + if let Some(name) = tensor.dim_name(dim_idx) { format!(" ({name})") } else { String::new() } ) }) - .join(if labelled { " × " } else { "×" }); - format!( - "{shapes}{}", - if shape.len() > MAX_SHOWN { - if labelled { - " × …" - } else { - "×…" - } - } else { - "" - } - ) + .join(if has_names { " × " } else { "×" }) } impl EntityDataUi for re_types::components::TensorData { @@ -75,7 +68,7 @@ pub fn tensor_ui( let text = format!( "{}, {}", tensor.dtype(), - format_tensor_shape_single_line(&tensor.shape) + format_tensor_shape_single_line(tensor) ); ui_layout.label(ui, text).on_hover_ui(|ui| { tensor_summary_ui(ui, tensor, &tensor_stats); @@ -94,7 +87,7 @@ pub fn tensor_summary_ui_grid_contents( tensor: &TensorData, tensor_stats: &TensorStats, ) { - let TensorData { shape, buffer: _ } = tensor; + let TensorData { shape, names, .. } = tensor; ui.grid_left_hand_label("Data type") .on_hover_text("Data type used for all individual elements within the tensor"); @@ -107,12 +100,12 @@ pub fn tensor_summary_ui_grid_contents( // For unnamed tensor dimension more than a single line usually doesn't make sense! // But what if some are named and some are not? // -> If more than 1 is named, make it a column! - if shape.iter().filter(|d| d.name.is_some()).count() > 1 { - for dim in shape { - ui.label(dim.to_string()); + if let Some(names) = names { + for (name, size) in itertools::izip!(names, shape) { + ui.label(format!("{name}={size}")); } } else { - ui.label(format_tensor_shape_single_line(shape)); + ui.label(format_tensor_shape_single_line(tensor)); } }); ui.end_row(); diff --git a/crates/viewer/re_selection_panel/src/selection_panel.rs b/crates/viewer/re_selection_panel/src/selection_panel.rs index 9d2cf9e3209c..4bec1216ff8d 100644 --- a/crates/viewer/re_selection_panel/src/selection_panel.rs +++ b/crates/viewer/re_selection_panel/src/selection_panel.rs @@ -7,7 +7,7 @@ use re_data_ui::{ DataUi, }; use re_entity_db::{EntityPath, InstancePath}; -use re_log_types::{ComponentPath, EntityPathFilter}; +use re_log_types::{ComponentPath, EntityPathFilter, EntityPathSubs}; use re_types::blueprint::components::Interactive; use re_ui::{ icons, @@ -559,7 +559,12 @@ fn entity_path_filter_ui( } // Apply the edit. - let new_filter = EntityPathFilter::parse_forgiving(&filter_string, &Default::default()); + // + // NOTE: The comparison of `EntityPathFilter` is done on the _expanded_ data (i.e. with variables substituted), + // so we must make sure to expand the new filter too before we compare it to the existing one. + // See + let new_filter = + EntityPathFilter::parse_forgiving(&filter_string, &EntityPathSubs::new_with_origin(origin)); if &new_filter == filter { None // no change } else { diff --git a/crates/viewer/re_selection_panel/src/view_entity_picker.rs b/crates/viewer/re_selection_panel/src/view_entity_picker.rs index 513111b3bb9c..d1a6b7ecb4fc 100644 --- a/crates/viewer/re_selection_panel/src/view_entity_picker.rs +++ b/crates/viewer/re_selection_panel/src/view_entity_picker.rs @@ -1,4 +1,3 @@ -use egui::NumExt as _; use itertools::Itertools; use nohash_hasher::IntMap; @@ -39,6 +38,7 @@ impl ViewEntityPicker { re_ui::modal::ModalWrapper::new("Add/remove Entities") .default_height(640.0) .full_span_content(true) + .scrollable([false, true]) }, |ui, open| { let Some(view_id) = &self.view_id else { @@ -51,21 +51,7 @@ impl ViewEntityPicker { return; }; - // Make the modal size less jumpy and work around https://github.com/emilk/egui/issues/5138 - // TODO(ab): move that boilerplate to `ModalWrapper` by adding a `scrollable` flag. - let max_height = 0.85 * ui.ctx().screen_rect().height(); - let min_height = 0.3 * ui.ctx().screen_rect().height().at_most(max_height); - - egui::ScrollArea::vertical() - .min_scrolled_height(max_height) - .max_height(max_height) - .show(ui, |ui| { - add_entities_ui(ctx, ui, view); - - if ui.min_rect().height() < min_height { - ui.add_space(min_height - ui.min_rect().height()); - } - }); + add_entities_ui(ctx, ui, view); }, ); } diff --git a/crates/viewer/re_ui/src/design_tokens.rs b/crates/viewer/re_ui/src/design_tokens.rs index b36456220429..32cda5097531 100644 --- a/crates/viewer/re_ui/src/design_tokens.rs +++ b/crates/viewer/re_ui/src/design_tokens.rs @@ -15,7 +15,7 @@ pub struct DesignTokens { /// Color table for all colors used in the UI. /// /// Loaded at startup from `design_tokens.json`. - color_table: ColorTable, + pub color_table: ColorTable, // TODO(ab): get rid of these, they should be function calls like the rest. pub top_bar_color: egui::Color32, diff --git a/crates/viewer/re_ui/src/lib.rs b/crates/viewer/re_ui/src/lib.rs index f35e5575523b..bae5f64d2117 100644 --- a/crates/viewer/re_ui/src/lib.rs +++ b/crates/viewer/re_ui/src/lib.rs @@ -20,7 +20,7 @@ use egui::Color32; use egui::NumExt as _; pub use self::{ - color_table::{ColorToken, Hue, Scale}, + color_table::{ColorTable, ColorToken, Hue, Scale}, command::{UICommand, UICommandSender}, command_palette::CommandPalette, context_ext::ContextExt, diff --git a/crates/viewer/re_ui/src/modal.rs b/crates/viewer/re_ui/src/modal.rs index e6f7b9113c18..1f5963ee7d65 100644 --- a/crates/viewer/re_ui/src/modal.rs +++ b/crates/viewer/re_ui/src/modal.rs @@ -1,3 +1,5 @@ +use eframe::emath::NumExt; + use crate::{DesignTokens, UiExt as _}; /// Helper object to handle a [`ModalWrapper`] window. @@ -83,6 +85,7 @@ pub struct ModalWrapper { min_height: Option, default_height: Option, full_span_content: bool, + scrollable: egui::Vec2b, } impl ModalWrapper { @@ -94,6 +97,7 @@ impl ModalWrapper { min_height: None, default_height: None, full_span_content: false, + scrollable: false.into(), } } @@ -131,6 +135,13 @@ impl ModalWrapper { self } + /// Enclose the contents in a scroll area. + #[inline] + pub fn scrollable(mut self, scrollable: impl Into) -> Self { + self.scrollable = scrollable.into(); + self + } + /// Show the modal window. /// /// Typically called by [`ModalHandler::ui`]. @@ -148,7 +159,7 @@ impl ModalWrapper { area = area.default_height(default_height); } - let modal_response = egui::Modal::new("add_view_or_container_modal".into()) + let modal_response = egui::Modal::new(id.with("modal")) .frame(egui::Frame { fill: ctx.style().visuals.panel_fill, ..Default::default() @@ -168,38 +179,82 @@ impl ModalWrapper { ui.set_min_height(min_height); } - egui::Frame { - inner_margin: egui::Margin::symmetric(DesignTokens::view_padding(), 0.0), - ..Default::default() - } + // + // Title bar + // + + view_padding_frame(&ViewPaddingFrameParams { + left_and_right: true, + top: true, + bottom: false, + }) .show(ui, |ui| { - ui.add_space(DesignTokens::view_padding()); Self::title_bar(ui, &self.title, &mut open); ui.add_space(DesignTokens::view_padding()); ui.full_span_separator(); + }); - if self.full_span_content { - // no further spacing for the content UI - content_ui(ui, &mut open) - } else { - // we must restore vertical spacing and add view padding at the bottom - ui.add_space(item_spacing_y); - - egui::Frame { - inner_margin: egui::Margin { - bottom: DesignTokens::view_padding(), - ..Default::default() - }, - ..Default::default() + // + // Inner content + // + + let wrapped_content_ui = |ui: &mut egui::Ui, open: &mut bool| -> R { + // We always have side margin, but these must happen _inside_ the scroll area + // (if any). Otherwise, the scroll bar is not snug with the right border and + // may interfere with the action buttons of `ListItem`s. + view_padding_frame(&ViewPaddingFrameParams { + left_and_right: true, + top: false, + bottom: false, + }) + .show(ui, |ui| { + if self.full_span_content { + // no further spacing for the content UI + content_ui(ui, open) + } else { + // we must restore vertical spacing and add view padding at the bottom + ui.add_space(item_spacing_y); + + view_padding_frame(&ViewPaddingFrameParams { + left_and_right: false, + top: false, + bottom: true, + }) + .show(ui, |ui| { + ui.spacing_mut().item_spacing.y = item_spacing_y; + content_ui(ui, open) + }) + .inner } + }) + .inner + }; + + // + // Optional scroll area + // + + if self.scrollable.any() { + // Make the modal size less jumpy and work around https://github.com/emilk/egui/issues/5138 + let max_height = 0.85 * ui.ctx().screen_rect().height(); + let min_height = 0.3 * ui.ctx().screen_rect().height().at_most(max_height); + + egui::ScrollArea::new(self.scrollable) + .min_scrolled_height(max_height) + .max_height(max_height) .show(ui, |ui| { - ui.spacing_mut().item_spacing.y = item_spacing_y; - content_ui(ui, &mut open) + let res = wrapped_content_ui(ui, &mut open); + + if ui.min_rect().height() < min_height { + ui.add_space(min_height - ui.min_rect().height()); + } + + res }) .inner - } - }) - .inner + } else { + wrapped_content_ui(ui, &mut open) + } }); if modal_response.should_close() { @@ -230,3 +285,44 @@ impl ModalWrapper { }); } } + +struct ViewPaddingFrameParams { + left_and_right: bool, + top: bool, + bottom: bool, +} + +/// Utility to produce a [`egui::Frame`] with padding on some sides. +#[inline] +fn view_padding_frame(params: &ViewPaddingFrameParams) -> egui::Frame { + let ViewPaddingFrameParams { + left_and_right, + top, + bottom, + } = *params; + egui::Frame { + inner_margin: egui::Margin { + left: if left_and_right { + DesignTokens::view_padding() + } else { + 0.0 + }, + right: if left_and_right { + DesignTokens::view_padding() + } else { + 0.0 + }, + top: if top { + DesignTokens::view_padding() + } else { + 0.0 + }, + bottom: if bottom { + DesignTokens::view_padding() + } else { + 0.0 + }, + }, + ..Default::default() + } +} diff --git a/crates/viewer/re_view/README.md b/crates/viewer/re_view/README.md index 54410b016536..4c7f372db337 100644 --- a/crates/viewer/re_view/README.md +++ b/crates/viewer/re_view/README.md @@ -3,7 +3,7 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. [![Latest version](https://img.shields.io/crates/v/re_view.svg)](https://crates.io/crates/re_view) -[![Documentation](https://docs.rs/re_view/badge.svg?speculative-link)](https://docs.rs/re_view?speculative-link) +[![Documentation](https://docs.rs/re_view/badge.svg)](https://docs.rs/re_view) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_bar_chart/README.md b/crates/viewer/re_view_bar_chart/README.md index 524f0772e339..b3fc22dc9785 100644 --- a/crates/viewer/re_view_bar_chart/README.md +++ b/crates/viewer/re_view_bar_chart/README.md @@ -3,7 +3,7 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. [![Latest version](https://img.shields.io/crates/v/re_view_bar_chart.svg)](https://crates.io/crates/re_view_bar_chart) -[![Documentation](https://docs.rs/re_view_bar_chart/badge.svg??speculative-link)](https://docs.rs/re_view_bar_chart?speculative-link) +[![Documentation](https://docs.rs/re_view_bar_chart/badge.svg?)](https://docs.rs/re_view_bar_chart) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_dataframe/README.md b/crates/viewer/re_view_dataframe/README.md index 23fc1c7eee2f..f08ed1966a56 100644 --- a/crates/viewer/re_view_dataframe/README.md +++ b/crates/viewer/re_view_dataframe/README.md @@ -3,7 +3,7 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. [![Latest version](https://img.shields.io/crates/v/re_view_dataframe.svg)](https://crates.io/crates/re_view_dataframe) -[![Documentation](https://docs.rs/re_view_dataframe/badge.svg?speculative-link)](https://docs.rs/re_view_dataframe?speculative-link) +[![Documentation](https://docs.rs/re_view_dataframe/badge.svg)](https://docs.rs/re_view_dataframe) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_graph/README.md b/crates/viewer/re_view_graph/README.md index 3a106e7ad8c3..b64b99770608 100644 --- a/crates/viewer/re_view_graph/README.md +++ b/crates/viewer/re_view_graph/README.md @@ -1,9 +1,9 @@ # re_view_graph -Part of the [`rerun`](https://github.com/rerun-io/rerun?speculative-link) family of crates. +Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_graph.svg)](https://crates.io/crates/re_view_graph?speculative-link) -[![Documentation](https://docs.rs/re_view_graph/badge.svg)](https://docs.rs/re_view_graph?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_graph.svg)](https://crates.io/crates/re_view_graph) +[![Documentation](https://docs.rs/re_view_graph/badge.svg)](https://docs.rs/re_view_graph) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_graph/src/graph/mod.rs b/crates/viewer/re_view_graph/src/graph/mod.rs index 4ddb4c969087..35f5c5f43750 100644 --- a/crates/viewer/re_view_graph/src/graph/mod.rs +++ b/crates/viewer/re_view_graph/src/graph/mod.rs @@ -48,14 +48,6 @@ impl Node { } } - /// The original [`components::GraphNode`] id that was logged by the user. - pub fn graph_node(&self) -> &components::GraphNode { - match self { - Self::Explicit { instance, .. } => &instance.graph_node, - Self::Implicit { graph_node, .. } => graph_node, - } - } - pub fn label(&self) -> &DrawableLabel { match self { Self::Explicit { label, .. } | Self::Implicit { label, .. } => label, @@ -81,6 +73,7 @@ pub struct Graph { entity: EntityPath, nodes: Vec, edges: Vec, + #[expect(unused)] kind: GraphType, } @@ -110,21 +103,19 @@ impl Graph { let (edges, kind) = if let Some(data) = edge_data { for edge in &data.edges { - if !seen.contains(&edge.source_index) { + if seen.insert(edge.source_index) { nodes.push(Node::Implicit { id: edge.source_index, graph_node: edge.source.clone(), label: DrawableLabel::implicit_circle(ui), }); - seen.insert(edge.source_index); } - if !seen.contains(&edge.target_index) { + if seen.insert(edge.target_index) { nodes.push(Node::Implicit { id: edge.target_index, graph_node: edge.target.clone(), label: DrawableLabel::implicit_circle(ui), }); - seen.insert(edge.target_index); } } @@ -155,10 +146,6 @@ impl Graph { &self.edges } - pub fn kind(&self) -> GraphType { - self.kind - } - pub fn entity(&self) -> &EntityPath { &self.entity } diff --git a/crates/viewer/re_view_graph/src/layout/geometry.rs b/crates/viewer/re_view_graph/src/layout/geometry.rs index 52498c900049..0a8e2d306d19 100644 --- a/crates/viewer/re_view_graph/src/layout/geometry.rs +++ b/crates/viewer/re_view_graph/src/layout/geometry.rs @@ -39,6 +39,7 @@ impl EdgeGeometry { } /// The starting position of an edge. + #[expect(unused)] pub fn source_pos(&self) -> Pos2 { match self.path { PathGeometry::Line { source, .. } | PathGeometry::CubicBezier { source, .. } => source, @@ -53,6 +54,7 @@ impl EdgeGeometry { } /// The direction of the edge at the source node (normalized). + #[expect(unused)] pub fn source_arrow_direction(&self) -> Vec2 { use PathGeometry::{CubicBezier, Line}; match self.path { diff --git a/crates/viewer/re_view_graph/src/layout/provider.rs b/crates/viewer/re_view_graph/src/layout/provider.rs index b49f3f6669a0..d9c718d29146 100644 --- a/crates/viewer/re_view_graph/src/layout/provider.rs +++ b/crates/viewer/re_view_graph/src/layout/provider.rs @@ -139,13 +139,17 @@ impl ForceLayoutProvider { layout: &Layout, params: &ForceLayoutParams, ) -> Self { - let nodes = request.all_nodes().map(|(id, v)| { - if let Some(rect) = layout.get_node(&id) { - let pos = rect.center(); - fj::Node::from(v).position(pos.x as f64, pos.y as f64) - } else { - fj::Node::from(v) + let nodes = request.all_nodes().map(|(id, template)| { + let node = fj::Node::from(template); + + if template.fixed_position.is_none() { + if let Some(rect) = layout.get_node(&id) { + let pos = rect.center(); + return node.position(pos.x as f64, pos.y as f64); + } } + + node }); let radii = request .all_nodes() @@ -207,13 +211,17 @@ impl ForceLayoutProvider { target: edge.target, }) .or_default(); - geometries.push(EdgeGeometry { - target_arrow, - path: line_segment( - layout.nodes[&edge.source], - layout.nodes[&edge.target], - ), - }); + + let source = layout.nodes[&edge.source]; + let target = layout.nodes[&edge.target]; + + // We only draw edges if they can be displayed meaningfully. + if source.center() != target.center() && !source.intersects(target) { + geometries.push(EdgeGeometry { + target_arrow, + path: line_segment(source, target), + }); + } } else { // Multiple edges occupy the same space, so we fan them out. let num_edges = edges.len(); @@ -222,6 +230,14 @@ impl ForceLayoutProvider { let source_rect = layout.nodes[slot_source]; let target_rect = layout.nodes[slot_target]; + if source_rect.center() == target_rect.center() + || source_rect.intersects(target_rect) + { + // There is no meaningful geometry to draw here. + // Keep in mind that self-edges are handled separately above. + continue; + } + let d = (target_rect.center() - source_rect.center()).normalized(); let source_pos = source_rect.intersects_ray_from_center(d); diff --git a/crates/viewer/re_view_graph/src/layout/result.rs b/crates/viewer/re_view_graph/src/layout/result.rs index 85c03a5d33fb..7ed15553187b 100644 --- a/crates/viewer/re_view_graph/src/layout/result.rs +++ b/crates/viewer/re_view_graph/src/layout/result.rs @@ -41,6 +41,7 @@ impl Layout { } /// Gets the shape of an edge in the final layout. + #[expect(unused)] pub fn get_edge(&self, edge: &EdgeId) -> Option<&[EdgeGeometry]> { self.edges.get(edge).map(|es| es.as_slice()) } diff --git a/crates/viewer/re_view_graph/src/ui/draw.rs b/crates/viewer/re_view_graph/src/ui/draw.rs index 4122377be478..ad58886a3761 100644 --- a/crates/viewer/re_view_graph/src/ui/draw.rs +++ b/crates/viewer/re_view_graph/src/ui/draw.rs @@ -130,6 +130,13 @@ fn draw_circle_label( Color32::TRANSPARENT, Stroke::new(2.0, visuals.selection.stroke.color), ); + } else if highlight.hover == HoverHighlight::Hovered { + painter.circle( + resp.rect.center(), + radius - 2.0, + Color32::TRANSPARENT, + Stroke::new(2.0, visuals.widgets.hovered.bg_fill), + ); } resp @@ -323,6 +330,7 @@ pub fn draw_graph( layout: &Layout, query: &ViewQuery<'_>, lod: LevelOfDetail, + hover_click_item: &mut Option<(Item, Response)>, ) -> Rect { let entity_path = graph.entity(); let entity_highlights = query.highlights.entity_highlight(entity_path.hash()); @@ -356,19 +364,18 @@ pub fn draw_graph( }); }); - ctx.handle_select_hover_drag_interactions( - &response, - Item::DataResult(query.view_id, instance_path.clone()), - false, - ); - - // double click selects the entire entity + // Warning! The order is very important here. if response.double_clicked() { // Select the entire entity ctx.selection_state().set_selection(Item::DataResult( query.view_id, instance_path.entity_path.clone().into(), )); + } else if response.hovered() || response.clicked() { + *hover_click_item = Some(( + Item::DataResult(query.view_id, instance_path.clone()), + response.clone(), + )); } response diff --git a/crates/viewer/re_view_graph/src/ui/state.rs b/crates/viewer/re_view_graph/src/ui/state.rs index e15ec96afb3c..79c0221174e0 100644 --- a/crates/viewer/re_view_graph/src/ui/state.rs +++ b/crates/viewer/re_view_graph/src/ui/state.rs @@ -82,10 +82,6 @@ impl LayoutState { *self = Self::None; } - pub fn is_none(&self) -> bool { - matches!(self, Self::None) - } - pub fn is_in_progress(&self) -> bool { matches!(self, Self::InProgress { .. }) } diff --git a/crates/viewer/re_view_graph/src/view.rs b/crates/viewer/re_view_graph/src/view.rs index 3bef101d01c3..b7ecf8b0d91e 100644 --- a/crates/viewer/re_view_graph/src/view.rs +++ b/crates/viewer/re_view_graph/src/view.rs @@ -1,3 +1,4 @@ +use egui::Response; use re_log_types::EntityPath; use re_types::{ blueprint::{ @@ -191,16 +192,28 @@ Display a graph of nodes and edges. let level_of_detail = LevelOfDetail::from_scaling(ui_from_world.scaling); + let mut hover_click_item: Option<(Item, Response)> = None; + let resp = zoom_pan_area(ui, &mut ui_from_world, |ui| { let mut world_bounding_rect = egui::Rect::NOTHING; for graph in &graphs { - let graph_rect = draw_graph(ui, ctx, graph, layout, query, level_of_detail); + let graph_rect = draw_graph( + ui, + ctx, + graph, + layout, + query, + level_of_detail, + &mut hover_click_item, + ); world_bounding_rect = world_bounding_rect.union(graph_rect); } }); - if resp.hovered() { + if let Some((item, response)) = hover_click_item { + ctx.handle_select_hover_drag_interactions(&response, item, false); + } else if resp.hovered() { ctx.selection_state().set_hovered(Item::View(query.view_id)); } diff --git a/crates/viewer/re_view_graph/src/visualizers/nodes.rs b/crates/viewer/re_view_graph/src/visualizers/nodes.rs index 2d7c1f0176da..d65e45f15c6f 100644 --- a/crates/viewer/re_view_graph/src/visualizers/nodes.rs +++ b/crates/viewer/re_view_graph/src/visualizers/nodes.rs @@ -3,7 +3,6 @@ use re_chunk::LatestAtQuery; use re_log_types::{EntityPath, Instance}; use re_query::{clamped_zip_2x4, range_zip_1x4}; use re_types::components::{Color, Radius, ShowLabels}; -use re_types::datatypes::Float32; use re_types::{ self, archetypes, components::{self}, @@ -23,6 +22,8 @@ pub struct NodeVisualizer { pub data: ahash::HashMap, } +pub const FALLBACK_RADIUS: f32 = 4.0; + /// The label information of a [`re_types::archetypes::GraphNodes`]. #[derive(Clone)] pub enum Label { @@ -40,7 +41,6 @@ pub enum Label { /// A [`NodeInstance`] is the output of the [`NodeVisualizer`] and represents a single node in the graph. #[derive(Clone)] pub struct NodeInstance { - pub graph_node: components::GraphNode, pub instance_index: Instance, pub id: NodeId, pub position: Option, @@ -120,13 +120,13 @@ impl VisualizerSystem for NodeVisualizer { color, }, _ => Label::Circle { - radius: radius.unwrap_or(4.0), + // Radius is negative for UI radii, but we don't handle this here. + radius: radius.unwrap_or(FALLBACK_RADIUS).abs(), color, }, }; NodeInstance { - graph_node: node.clone(), instance_index: instance, id: NodeId::from_entity_node(&data_result.entity_path, node), position: position.map(|[x, y]| egui::Pos2::new(x, y)), @@ -160,7 +160,7 @@ impl TypedComponentFallbackProvider for NodeVisualizer { impl TypedComponentFallbackProvider for NodeVisualizer { fn fallback_for(&self, _ctx: &QueryContext<'_>) -> Radius { - Radius(Float32(4.0f32)) + FALLBACK_RADIUS.into() } } diff --git a/crates/viewer/re_view_map/README.md b/crates/viewer/re_view_map/README.md index 5555ab0cf427..e4f2338ed605 100644 --- a/crates/viewer/re_view_map/README.md +++ b/crates/viewer/re_view_map/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_map.svg)](https://crates.io/crates/re_view_spatial?speculative-link) -[![Documentation](https://docs.rs/re_view_map/badge.svg)](https://docs.rs/re_view_spatial?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_map.svg)](https://crates.io/crates/re_view_spatial) +[![Documentation](https://docs.rs/re_view_map/badge.svg)](https://docs.rs/re_view_spatial) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_spatial/README.md b/crates/viewer/re_view_spatial/README.md index 950c5eb13548..3a23de917b1e 100644 --- a/crates/viewer/re_view_spatial/README.md +++ b/crates/viewer/re_view_spatial/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_spatial.svg)](https://crates.io/crates/re_view_spatial?speculative-link) -[![Documentation](https://docs.rs/re_view_spatial/badge.svg)](https://docs.rs/re_view_spatial?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_spatial.svg)](https://crates.io/crates/re_view_spatial) +[![Documentation](https://docs.rs/re_view_spatial/badge.svg)](https://docs.rs/re_view_spatial) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_tensor/README.md b/crates/viewer/re_view_tensor/README.md index bd8bab191ee3..c0a325259122 100644 --- a/crates/viewer/re_view_tensor/README.md +++ b/crates/viewer/re_view_tensor/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_tensor.svg)](https://crates.io/crates/re_view_tensor?speculative-link) -[![Documentation](https://docs.rs/re_view_tensor/badge.svg)](https://docs.rs/re_view_tensor?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_tensor.svg)](https://crates.io/crates/re_view_tensor) +[![Documentation](https://docs.rs/re_view_tensor/badge.svg)](https://docs.rs/re_view_tensor) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_tensor/src/dimension_mapping.rs b/crates/viewer/re_view_tensor/src/dimension_mapping.rs index f3804733b1d8..43ccab9a812b 100644 --- a/crates/viewer/re_view_tensor/src/dimension_mapping.rs +++ b/crates/viewer/re_view_tensor/src/dimension_mapping.rs @@ -1,11 +1,14 @@ use egui::NumExt as _; + use re_types::{ blueprint::{archetypes::TensorSliceSelection, components::TensorDimensionIndexSlider}, components::{TensorDimensionIndexSelection, TensorHeightDimension, TensorWidthDimension}, - datatypes::{TensorDimension, TensorDimensionSelection}, + datatypes::TensorDimensionSelection, }; use re_viewport_blueprint::ViewProperty; +use crate::TensorDimension; + /// Loads slice selection from blueprint and makes modifications (without writing back) such that it is valid /// for the given tensor shape. /// @@ -250,7 +253,7 @@ fn longest_and_second_longest_dim_indices(shape: &[TensorDimension]) -> (usize, #[cfg(test)] mod tests { - use re_types::datatypes::TensorDimension; + use crate::TensorDimension; use re_types::{ blueprint::components::TensorDimensionIndexSlider, components::TensorDimensionIndexSelection, diff --git a/crates/viewer/re_view_tensor/src/lib.rs b/crates/viewer/re_view_tensor/src/lib.rs index 2dda9636b659..f6e913430dd0 100644 --- a/crates/viewer/re_view_tensor/src/lib.rs +++ b/crates/viewer/re_view_tensor/src/lib.rs @@ -1,6 +1,6 @@ -//! Rerun tensor View. +//! Rerun tensor view. //! -//! A View dedicated to visualizing tensors with arbitrary dimensionality. +//! A view dedicated to visualizing tensors with arbitrary dimensionality. // TODO(#6330): remove unwrap() #![allow(clippy::unwrap_used)] @@ -12,3 +12,36 @@ mod view_class; mod visualizer_system; pub use view_class::TensorView; + +/// Information about a dimension of a tensor. +struct TensorDimension { + pub size: u64, + pub name: Option, +} + +impl TensorDimension { + pub fn from_tensor_data(tensor_data: &re_types::datatypes::TensorData) -> Vec { + tensor_data + .shape + .iter() + .enumerate() + .map(|(dim_idx, dim_len)| Self { + size: *dim_len, + name: tensor_data.dim_name(dim_idx).cloned(), + }) + .collect() + } + + #[allow(dead_code)] // Used for tests + pub fn unnamed(size: u64) -> Self { + Self { size, name: None } + } + + #[allow(dead_code)] // Used for tests + pub fn named(size: u64, name: impl Into) -> Self { + Self { + size, + name: Some(name.into()), + } + } +} diff --git a/crates/viewer/re_view_tensor/src/tensor_dimension_mapper.rs b/crates/viewer/re_view_tensor/src/tensor_dimension_mapper.rs index ac224320bc12..07e6bed75cb1 100644 --- a/crates/viewer/re_view_tensor/src/tensor_dimension_mapper.rs +++ b/crates/viewer/re_view_tensor/src/tensor_dimension_mapper.rs @@ -1,11 +1,12 @@ use re_types::{ - blueprint::archetypes::TensorSliceSelection, - datatypes::{TensorDimension, TensorDimensionIndexSelection}, + blueprint::archetypes::TensorSliceSelection, datatypes::TensorDimensionIndexSelection, }; use re_ui::UiExt as _; use re_viewer_context::ViewerContext; use re_viewport_blueprint::ViewProperty; +use crate::TensorDimension; + #[derive(Clone, Copy, PartialEq, Eq)] enum DragDropAddress { None, diff --git a/crates/viewer/re_view_tensor/src/tensor_tests.rs b/crates/viewer/re_view_tensor/src/tensor_tests.rs index e8e46712330e..0da7b00c5394 100644 --- a/crates/viewer/re_view_tensor/src/tensor_tests.rs +++ b/crates/viewer/re_view_tensor/src/tensor_tests.rs @@ -1,6 +1,6 @@ #![allow(clippy::unwrap_used)] -use re_types::datatypes::{TensorBuffer, TensorData, TensorDimension}; +use re_types::datatypes::{TensorBuffer, TensorData}; use re_types::tensor_data::TensorCastError; #[test] diff --git a/crates/viewer/re_view_tensor/src/view_class.rs b/crates/viewer/re_view_tensor/src/view_class.rs index 191c327de4fe..0e8165f0101a 100644 --- a/crates/viewer/re_view_tensor/src/view_class.rs +++ b/crates/viewer/re_view_tensor/src/view_class.rs @@ -1,6 +1,5 @@ use egui::{epaint::TextShape, Align2, NumExt as _, Vec2}; use ndarray::Axis; -use re_view::{suggest_view_for_each_entity, view_property_ui}; use re_data_ui::tensor_summary_ui_grid_contents; use re_log_types::EntityPath; @@ -10,10 +9,11 @@ use re_types::{ components::ViewFit, }, components::{Colormap, GammaCorrection, MagnificationFilter, TensorDimensionIndexSelection}, - datatypes::{TensorData, TensorDimension}, + datatypes::TensorData, View, ViewClassIdentifier, }; use re_ui::{list_item, UiExt as _}; +use re_view::{suggest_view_for_each_entity, view_property_ui}; use re_viewer_context::{ gpu_bridge, ApplicableEntities, ColormapWithRange, IdentifiedViewSystem as _, IndicatedEntities, PerVisualizer, TensorStatsCache, TypedComponentFallbackProvider, ViewClass, @@ -26,6 +26,7 @@ use crate::{ dimension_mapping::load_tensor_slice_selection_and_make_valid, tensor_dimension_mapper::dimension_mapping_ui, visualizer_system::{TensorSystem, TensorVisualization}, + TensorDimension, }; #[derive(Default)] @@ -151,12 +152,20 @@ Note: select the view to configure which dimensions are shown." ctx.blueprint_query, view_id, ); - let slice_selection = - load_tensor_slice_selection_and_make_valid(&slice_property, tensor.shape())?; + let slice_selection = load_tensor_slice_selection_and_make_valid( + &slice_property, + &TensorDimension::from_tensor_data(tensor), + )?; ui.separator(); ui.strong("Dimension Mapping"); - dimension_mapping_ui(ctx, ui, tensor.shape(), &slice_selection, &slice_property); + dimension_mapping_ui( + ctx, + ui, + &TensorDimension::from_tensor_data(tensor), + &slice_selection, + &slice_property, + ); // TODO(andreas): this is a bit too inconsistent with the other UIs - we don't offer the same reset/option buttons here if ui @@ -242,8 +251,10 @@ impl TensorView { ctx.blueprint_query, view_id, ); - let slice_selection = - load_tensor_slice_selection_and_make_valid(&slice_property, tensor.shape())?; + let slice_selection = load_tensor_slice_selection_and_make_valid( + &slice_property, + &TensorDimension::from_tensor_data(tensor), + )?; let default_item_spacing = ui.spacing_mut().item_spacing; ui.spacing_mut().item_spacing.y = 0.0; // No extra spacing between sliders and tensor @@ -259,17 +270,26 @@ impl TensorView { } .show(ui, |ui| { ui.spacing_mut().item_spacing = default_item_spacing; // keep the default spacing between sliders - selectors_ui(ctx, ui, tensor.shape(), &slice_selection, &slice_property); + selectors_ui( + ctx, + ui, + &TensorDimension::from_tensor_data(tensor), + &slice_selection, + &slice_property, + ); }); } let dimension_labels = [ - slice_selection - .width - .map(|width| (dimension_name(&tensor.shape, width.dimension), width.invert)), + slice_selection.width.map(|width| { + ( + dimension_name(&TensorDimension::from_tensor_data(tensor), width.dimension), + width.invert, + ) + }), slice_selection.height.map(|height| { ( - dimension_name(&tensor.shape, height.dimension), + dimension_name(&TensorDimension::from_tensor_data(tensor), height.dimension), height.invert, ) }), diff --git a/crates/viewer/re_view_text_document/README.md b/crates/viewer/re_view_text_document/README.md index 28580760e6cd..bc8b92289567 100644 --- a/crates/viewer/re_view_text_document/README.md +++ b/crates/viewer/re_view_text_document/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_text_document.svg)](https://crates.io/crates/re_view_text_document?speculative-link) -[![Documentation](https://docs.rs/re_view_text_document/badge.svg)](https://docs.rs/re_view_text_document?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_text_document.svg)](https://crates.io/crates/re_view_text_document) +[![Documentation](https://docs.rs/re_view_text_document/badge.svg)](https://docs.rs/re_view_text_document) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_text_log/README.md b/crates/viewer/re_view_text_log/README.md index 8ae9b824d012..1d0ff0848bf9 100644 --- a/crates/viewer/re_view_text_log/README.md +++ b/crates/viewer/re_view_text_log/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_text_log.svg)](https://crates.io/crates/re_view_text_log?speculative-link) -[![Documentation](https://docs.rs/re_view_text_log/badge.svg)](https://docs.rs/re_view_text_log?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_text_log.svg)](https://crates.io/crates/re_view_text_log) +[![Documentation](https://docs.rs/re_view_text_log/badge.svg)](https://docs.rs/re_view_text_log) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_view_time_series/README.md b/crates/viewer/re_view_time_series/README.md index 2c6c7fb5ab32..fc2556bd111d 100644 --- a/crates/viewer/re_view_time_series/README.md +++ b/crates/viewer/re_view_time_series/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_view_bar_chart.svg)](https://crates.io/crates/re_view_bar_chart?speculative-link) -[![Documentation](https://docs.rs/re_view_bar_chart/badge.svg)](https://docs.rs/re_view_bar_chart?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_view_bar_chart.svg)](https://crates.io/crates/re_view_bar_chart) +[![Documentation](https://docs.rs/re_view_bar_chart/badge.svg)](https://docs.rs/re_view_bar_chart) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_viewer/README.md b/crates/viewer/re_viewer/README.md index adf3ef575924..10c648321f03 100644 --- a/crates/viewer/re_viewer/README.md +++ b/crates/viewer/re_viewer/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_viewer.svg)](https://crates.io/crates/viewer/re_viewer?speculative-link) -[![Documentation](https://docs.rs/re_viewer/badge.svg)](https://docs.rs/re_viewer?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_viewer.svg)](https://crates.io/crates/viewer/re_viewer) +[![Documentation](https://docs.rs/re_viewer/badge.svg)](https://docs.rs/re_viewer) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_viewer/data/quick_start_guides/rust_connect.md b/crates/viewer/re_viewer/data/quick_start_guides/rust_connect.md index c5b748b7772f..e3facf5f3f64 100644 --- a/crates/viewer/re_viewer/data/quick_start_guides/rust_connect.md +++ b/crates/viewer/re_viewer/data/quick_start_guides/rust_connect.md @@ -10,7 +10,7 @@ Let's try it out in a brand-new Rust project: cargo init cube && cd cube && cargo add rerun --features native_viewer ``` -Note that the Rerun SDK requires a working installation of Rust 1.80+. +Note that the Rerun SDK requires a working installation of Rust 1.81+. ## Logging your own data diff --git a/crates/viewer/re_viewer/data/quick_start_guides/rust_spawn.md b/crates/viewer/re_viewer/data/quick_start_guides/rust_spawn.md index cde772f1aad2..ae2c4aa1cddd 100644 --- a/crates/viewer/re_viewer/data/quick_start_guides/rust_spawn.md +++ b/crates/viewer/re_viewer/data/quick_start_guides/rust_spawn.md @@ -10,7 +10,7 @@ Let's try it out in a brand-new Rust project: cargo init cube && cd cube && cargo add rerun ``` -Note that the Rerun SDK requires a working installation of Rust 1.80+. +Note that the Rerun SDK requires a working installation of Rust 1.81+. ## Logging your own data diff --git a/crates/viewer/re_viewer_context/Cargo.toml b/crates/viewer/re_viewer_context/Cargo.toml index a0768622da06..e8cf0eef90d3 100644 --- a/crates/viewer/re_viewer_context/Cargo.toml +++ b/crates/viewer/re_viewer_context/Cargo.toml @@ -74,6 +74,7 @@ wgpu.workspace = true arboard = { workspace = true, default-features = false, features = [ "image-data", ] } +home.workspace = true # Web dependencies: [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/crates/viewer/re_viewer_context/README.md b/crates/viewer/re_viewer_context/README.md index fa3ef603ddc5..7edbbaaf7fde 100644 --- a/crates/viewer/re_viewer_context/README.md +++ b/crates/viewer/re_viewer_context/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_viewer_context.svg)](https://crates.io/crates/viewer/re_viewer_context?speculative-link) -[![Documentation](https://docs.rs/re_viewer_context/badge.svg)](https://docs.rs/re_viewer_context?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_viewer_context.svg)](https://crates.io/crates/viewer/re_viewer_context) +[![Documentation](https://docs.rs/re_viewer_context/badge.svg)](https://docs.rs/re_viewer_context) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_viewport/README.md b/crates/viewer/re_viewport/README.md index b6bf90cd4967..8bd5548bbb5e 100644 --- a/crates/viewer/re_viewport/README.md +++ b/crates/viewer/re_viewport/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_viewport.svg)](https://crates.io/crates/re_viewport?speculative-link) -[![Documentation](https://docs.rs/re_viewport/badge.svg)](https://docs.rs/re_viewport?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_viewport.svg)](https://crates.io/crates/re_viewport) +[![Documentation](https://docs.rs/re_viewport/badge.svg)](https://docs.rs/re_viewport) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_viewport/src/viewport_ui.rs b/crates/viewer/re_viewport/src/viewport_ui.rs index ad4d3a005480..ceba4abe229e 100644 --- a/crates/viewer/re_viewport/src/viewport_ui.rs +++ b/crates/viewer/re_viewport/src/viewport_ui.rs @@ -6,7 +6,7 @@ use ahash::HashMap; use egui_tiles::{Behavior as _, EditAction}; use re_context_menu::{context_menu_ui_for_item, SelectionUpdateBehavior}; -use re_log_types::{EntityPath, EntityPathRule}; +use re_log_types::{EntityPath, EntityPathRule, RuleEffect}; use re_ui::{design_tokens, ContextExt as _, DesignTokens, Icon, UiExt as _}; use re_viewer_context::{ blueprint_id_to_tile_id, icon_for_container_kind, Contents, DragAndDropFeedback, @@ -165,6 +165,13 @@ impl ViewportUi { continue; }; + if matches!(contents, Contents::View(_)) + && !should_display_drop_destination_frame + { + // We already light up the view tab title; that is enough + continue; + } + // We want the rectangle to be on top of everything in the viewport, // including stuff in "zoom-pan areas", like we use in the graph view. let top_layer_id = @@ -270,14 +277,18 @@ impl ViewportUi { if ctx.egui_ctx.input(|i| i.pointer.any_released()) { egui::DragAndDrop::clear_payload(ctx.egui_ctx); - for entity in entities { - if can_entity_be_added(entity) { - view_blueprint.contents.raw_add_entity_inclusion( - ctx, - EntityPathRule::including_subtree(entity.clone()), - ); - } - } + view_blueprint + .contents + .mutate_entity_path_filter(ctx, |filter| { + for entity in entities { + if can_entity_be_added(entity) { + filter.add_rule( + RuleEffect::Include, + EntityPathRule::including_subtree(entity.clone()), + ); + } + } + }); ctx.selection_state() .set_selection(Item::View(view_blueprint.id)); diff --git a/crates/viewer/re_viewport_blueprint/README.md b/crates/viewer/re_viewport_blueprint/README.md index ee8c229a13c8..8280a9e5d34b 100644 --- a/crates/viewer/re_viewport_blueprint/README.md +++ b/crates/viewer/re_viewport_blueprint/README.md @@ -2,8 +2,8 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. -[![Latest version](https://img.shields.io/crates/v/re_viewport_blueprint.svg)](https://crates.io/crates/re_viewport_blueprint?speculative-link) -[![Documentation](https://docs.rs/re_viewport_blueprint/badge.svg)](https://docs.rs/re_viewport_blueprint?speculative-link) +[![Latest version](https://img.shields.io/crates/v/re_viewport_blueprint.svg)](https://crates.io/crates/re_viewport_blueprint) +[![Documentation](https://docs.rs/re_viewport_blueprint/badge.svg)](https://docs.rs/re_viewport_blueprint) ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) diff --git a/crates/viewer/re_viewport_blueprint/src/ui/add_view_or_container_modal.rs b/crates/viewer/re_viewport_blueprint/src/ui/add_view_or_container_modal.rs index 4a38ee15a48f..63f2fc83e02f 100644 --- a/crates/viewer/re_viewport_blueprint/src/ui/add_view_or_container_modal.rs +++ b/crates/viewer/re_viewport_blueprint/src/ui/add_view_or_container_modal.rs @@ -1,11 +1,12 @@ //! Modal for adding a new view of container to an existing target container. -use crate::{ViewBlueprint, ViewportBlueprint}; use re_ui::UiExt as _; use re_viewer_context::{ blueprint_id_to_tile_id, icon_for_container_kind, ContainerId, RecommendedView, ViewerContext, }; +use crate::{ViewBlueprint, ViewportBlueprint}; + #[derive(Default)] pub struct AddViewOrContainerModal { target_container: Option, @@ -30,6 +31,7 @@ impl AddViewOrContainerModal { re_ui::modal::ModalWrapper::new("Add view or container") .min_width(500.0) .full_span_content(true) + .scrollable([false, true]) }, |ui, keep_open| modal_ui(ui, ctx, viewport, self.target_container, keep_open), ); diff --git a/crates/viewer/re_viewport_blueprint/src/view_contents.rs b/crates/viewer/re_viewport_blueprint/src/view_contents.rs index ef4079f1f515..7988a7c9d65a 100644 --- a/crates/viewer/re_viewport_blueprint/src/view_contents.rs +++ b/crates/viewer/re_viewport_blueprint/src/view_contents.rs @@ -142,6 +142,9 @@ impl ViewContents { ); } + /// Set the entity path filter. WARNING: a single mutation is allowed per frame, or data will be + /// lost. + //TODO(#8518): address this massive foot-gun. pub fn set_entity_path_filter( &self, ctx: &ViewerContext<'_>, @@ -184,40 +187,65 @@ impl ViewContents { } } - /// Remove a subtree and any existing rules that it would match. + /// Perform arbitrary mutation on the entity path filter. WARNING: a single mutation is allowed + /// per frame, or data will be lost. + /// + /// This method exists because of the single mutation per frame limitation. It currently is the + /// only way to perform multiple mutations on the entity path filter in a single frame. + //TODO(#8518): address this massive foot-gun. + pub fn mutate_entity_path_filter( + &self, + ctx: &ViewerContext<'_>, + f: impl FnOnce(&mut EntityPathFilter), + ) { + let mut new_entity_path_filter = self.entity_path_filter.clone(); + f(&mut new_entity_path_filter); + self.set_entity_path_filter(ctx, &new_entity_path_filter); + } + + /// Remove a subtree and any existing rules that it would match. WARNING: a single mutation is + /// allowed per frame, or data will be lost. /// /// Because most-specific matches win, if we only add a subtree exclusion /// it can still be overridden by existing inclusions. This method ensures /// that not only do we add a subtree exclusion, but clear out any existing /// inclusions or (now redundant) exclusions that would match the subtree. + //TODO(#8518): address this massive foot-gun. pub fn remove_subtree_and_matching_rules(&self, ctx: &ViewerContext<'_>, path: EntityPath) { let mut new_entity_path_filter = self.entity_path_filter.clone(); new_entity_path_filter.remove_subtree_and_matching_rules(path); self.set_entity_path_filter(ctx, &new_entity_path_filter); } - /// Directly add an exclusion rule to the [`EntityPathFilter`]. + /// Directly add an exclusion rule to the [`EntityPathFilter`]. WARNING: a single mutation is + /// allowed per frame, or data will be lost. /// /// This is a direct modification of the filter and will not do any simplification /// related to overlapping or conflicting rules. /// /// If you are trying to remove an entire subtree, prefer using [`Self::remove_subtree_and_matching_rules`]. + //TODO(#8518): address this massive foot-gun. pub fn raw_add_entity_exclusion(&self, ctx: &ViewerContext<'_>, rule: EntityPathRule) { let mut new_entity_path_filter = self.entity_path_filter.clone(); new_entity_path_filter.add_rule(RuleEffect::Exclude, rule); self.set_entity_path_filter(ctx, &new_entity_path_filter); } - /// Directly add an inclusion rule to the [`EntityPathFilter`]. + /// Directly add an inclusion rule to the [`EntityPathFilter`]. WARNING: a single mutation is + /// allowed per frame, or data will be lost. /// /// This is a direct modification of the filter and will not do any simplification /// related to overlapping or conflicting rules. + //TODO(#8518): address this massive foot-gun. pub fn raw_add_entity_inclusion(&self, ctx: &ViewerContext<'_>, rule: EntityPathRule) { let mut new_entity_path_filter = self.entity_path_filter.clone(); new_entity_path_filter.add_rule(RuleEffect::Include, rule); self.set_entity_path_filter(ctx, &new_entity_path_filter); } + /// Remove rules for a given entity. WARNING: a single mutation is allowed per frame, or data + /// will be lost. + //TODO(#8518): address this massive foot-gun. pub fn remove_filter_rule_for(&self, ctx: &ViewerContext<'_>, ent_path: &EntityPath) { let mut new_entity_path_filter = self.entity_path_filter.clone(); new_entity_path_filter.remove_rule_for(ent_path); diff --git a/docs/content/getting-started/installing-viewer.md b/docs/content/getting-started/installing-viewer.md index 55ebc55e8ab8..89aac23fed2b 100644 --- a/docs/content/getting-started/installing-viewer.md +++ b/docs/content/getting-started/installing-viewer.md @@ -40,7 +40,7 @@ There are many ways to install the viewer. Please pick whatever works best for y - 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.80+) + - `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 diff --git a/docs/content/getting-started/quick-start/rust.md b/docs/content/getting-started/quick-start/rust.md index c79bc34db7c2..69f92ff3c9ce 100644 --- a/docs/content/getting-started/quick-start/rust.md +++ b/docs/content/getting-started/quick-start/rust.md @@ -5,7 +5,7 @@ order: 3 ## Setup -The Rerun SDK for Rust requires a working installation of Rust 1.80+. +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`. diff --git a/docs/content/howto/logging/send-columns.md b/docs/content/howto/logging/send-columns.md index 07c6051e8c08..a1b28109f65f 100644 --- a/docs/content/howto/logging/send-columns.md +++ b/docs/content/howto/logging/send-columns.md @@ -33,7 +33,7 @@ snippet: archetypes/points3d_send_columns.py ### Using `send_columns` for logging custom components -An entire batch of a custom component can be logged at once using [`rr.AnyBatchValue`](https://ref.rerun.io/docs/python/0.20.0/common/custom_data/#rerun.AnyBatchValue?speculative-link) along with `send_column`: +An entire batch of a custom component can be logged at once using [`rr.AnyBatchValue`](https://ref.rerun.io/docs/python/0.20.0/common/custom_data/#rerun.AnyBatchValue) along with `send_column`: snippet: howto/any_batch_value_send_columns diff --git a/docs/content/reference/migration/migration-0-21.md b/docs/content/reference/migration/migration-0-21.md index 15c149d369f1..481c17a509bb 100644 --- a/docs/content/reference/migration/migration-0-21.md +++ b/docs/content/reference/migration/migration-0-21.md @@ -3,6 +3,9 @@ title: Migrating from 0.20 to 0.21 order: 989 --- +### File compatibility +We've changed how tensors are encoded in .rrd files, so tensors will no longer load from older .rrd files ([#8376](https://github.com/rerun-io/rerun/pull/8376)). + ### Near clip plane for `Spatial2D` views now defaults to `0.1` in 3D scene units. Previously, the clip plane was set an arbitrary value that worked reasonably for @@ -26,14 +29,15 @@ rr.send_blueprint( ``` -### Types and fields got renamed from `.*space_view.*`/`.*SpaceView.*` to `.*view.*`/`.*View.*` +### Blueprint types and fields got renamed from `.*space_view.*`/`.*SpaceView.*` to `.*view.*`/`.*View.*` Various types and fields got changed to refer to "views" rather than "space views". -This exclusively affects the Python blueprint sdk: +This exclusively affects the Python blueprint sdk. + +#### Field/argument changes -#### Field/argument changes: -* `ViewportBlueprint(...auto_views=...)` -> `ViewportBlueprint(...auto_views=...)` -* `Blueprint(...auto_views=...)` -> `Blueprint(...auto_views=...)` +* `ViewportBlueprint(...auto_space_views=...)` -> `ViewportBlueprint(...auto_views=...)` +* `Blueprint(...auto_space_views=...)` -> `Blueprint(...auto_views=...)` #### Type changes diff --git a/docs/content/reference/types/archetypes/graph_edges.md b/docs/content/reference/types/archetypes/graph_edges.md index 47dc62ca7791..de405287b53b 100644 --- a/docs/content/reference/types/archetypes/graph_edges.md +++ b/docs/content/reference/types/archetypes/graph_edges.md @@ -3,9 +3,6 @@ title: "GraphEdges" --- - -⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - A list of edges in a graph. By default, edges are undirected. @@ -21,9 +18,9 @@ By default, edges are undirected. * [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?speculative-link) - * 🐍 [Python API docs for `GraphEdges`](https://ref.rerun.io/docs/python/stable/common/archetypes?speculative-link#rerun.archetypes.GraphEdges) - * 🦀 [Rust API docs for `GraphEdges`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GraphEdges.html?speculative-link) + * 🌊 [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 diff --git a/docs/content/reference/types/archetypes/graph_nodes.md b/docs/content/reference/types/archetypes/graph_nodes.md index c5b6d38ebab0..69fc86ddb4da 100644 --- a/docs/content/reference/types/archetypes/graph_nodes.md +++ b/docs/content/reference/types/archetypes/graph_nodes.md @@ -3,9 +3,6 @@ title: "GraphNodes" --- - -⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - A list of nodes in a graph with optional labels, colors, etc. ## Components @@ -19,9 +16,9 @@ A list of nodes in a graph with optional labels, colors, etc. * [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?speculative-link) - * 🐍 [Python API docs for `GraphNodes`](https://ref.rerun.io/docs/python/stable/common/archetypes?speculative-link#rerun.archetypes.GraphNodes) - * 🦀 [Rust API docs for `GraphNodes`](https://docs.rs/rerun/latest/rerun/archetypes/struct.GraphNodes.html?speculative-link) + * 🌊 [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 diff --git a/docs/content/reference/types/components/color.md b/docs/content/reference/types/components/color.md index 7e28f1ebae84..835488c2c0cf 100644 --- a/docs/content/reference/types/components/color.md +++ b/docs/content/reference/types/components/color.md @@ -34,7 +34,7 @@ uint32 * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GeoLineStrings`](../archetypes/geo_line_strings.md) * [`GeoPoints`](../archetypes/geo_points.md) -* [`GraphNodes`](../archetypes/graph_nodes.md?speculative-link) +* [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Mesh3D`](../archetypes/mesh3d.md) diff --git a/docs/content/reference/types/components/graph_edge.md b/docs/content/reference/types/components/graph_edge.md index 7e3d6a7a8300..002d4ef6010f 100644 --- a/docs/content/reference/types/components/graph_edge.md +++ b/docs/content/reference/types/components/graph_edge.md @@ -18,11 +18,11 @@ Struct { ``` ## API reference links - * 🌊 [C++ API docs for `GraphEdge`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1GraphEdge.html?speculative-link) - * 🐍 [Python API docs for `GraphEdge`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.GraphEdge) - * 🦀 [Rust API docs for `GraphEdge`](https://docs.rs/rerun/latest/rerun/components/struct.GraphEdge.html?speculative-link) + * 🌊 [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?speculative-link) +* [`GraphEdges`](../archetypes/graph_edges.md) diff --git a/docs/content/reference/types/components/graph_node.md b/docs/content/reference/types/components/graph_node.md index 23e0732351b0..638c20cf3217 100644 --- a/docs/content/reference/types/components/graph_node.md +++ b/docs/content/reference/types/components/graph_node.md @@ -15,11 +15,11 @@ utf8 ``` ## API reference links - * 🌊 [C++ API docs for `GraphNode`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1GraphNode.html?speculative-link) - * 🐍 [Python API docs for `GraphNode`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.GraphNode) - * 🦀 [Rust API docs for `GraphNode`](https://docs.rs/rerun/latest/rerun/components/struct.GraphNode.html?speculative-link) + * 🌊 [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?speculative-link) +* [`GraphNodes`](../archetypes/graph_nodes.md) diff --git a/docs/content/reference/types/components/graph_type.md b/docs/content/reference/types/components/graph_type.md index 5bb3a94c79ec..24aa3323c707 100644 --- a/docs/content/reference/types/components/graph_type.md +++ b/docs/content/reference/types/components/graph_type.md @@ -19,11 +19,11 @@ uint8 ``` ## API reference links - * 🌊 [C++ API docs for `GraphType`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html?speculative-link) - * 🐍 [Python API docs for `GraphType`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.GraphType) - * 🦀 [Rust API docs for `GraphType`](https://docs.rs/rerun/latest/rerun/components/enum.GraphType.html?speculative-link) + * 🌊 [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?speculative-link) +* [`GraphEdges`](../archetypes/graph_edges.md) diff --git a/docs/content/reference/types/components/plane3d.md b/docs/content/reference/types/components/plane3d.md index 58d7e4e31c40..4dc7f25f7c0c 100644 --- a/docs/content/reference/types/components/plane3d.md +++ b/docs/content/reference/types/components/plane3d.md @@ -23,8 +23,8 @@ FixedSizeList<4, float32> ``` ## API reference links - * 🌊 [C++ API docs for `Plane3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Plane3D.html?speculative-link) - * 🐍 [Python API docs for `Plane3D`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.Plane3D) - * 🦀 [Rust API docs for `Plane3D`](https://docs.rs/rerun/latest/rerun/components/struct.Plane3D.html?speculative-link) + * 🌊 [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) diff --git a/docs/content/reference/types/components/position2d.md b/docs/content/reference/types/components/position2d.md index faa24a3318ab..78f839ff55db 100644 --- a/docs/content/reference/types/components/position2d.md +++ b/docs/content/reference/types/components/position2d.md @@ -24,5 +24,5 @@ FixedSizeList<2, float32> * [`Arrows2D`](../archetypes/arrows2d.md) * [`Boxes2D`](../archetypes/boxes2d.md) -* [`GraphNodes`](../archetypes/graph_nodes.md?speculative-link) +* [`GraphNodes`](../archetypes/graph_nodes.md) * [`Points2D`](../archetypes/points2d.md) diff --git a/docs/content/reference/types/components/radius.md b/docs/content/reference/types/components/radius.md index 3d976dd859d9..e0ded53ec2f4 100644 --- a/docs/content/reference/types/components/radius.md +++ b/docs/content/reference/types/components/radius.md @@ -37,7 +37,7 @@ float32 * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) * [`GeoLineStrings`](../archetypes/geo_line_strings.md) * [`GeoPoints`](../archetypes/geo_points.md) -* [`GraphNodes`](../archetypes/graph_nodes.md?speculative-link) +* [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) diff --git a/docs/content/reference/types/components/recording_uri.md b/docs/content/reference/types/components/recording_uri.md index 99133fc12b35..0e002267a23d 100644 --- a/docs/content/reference/types/components/recording_uri.md +++ b/docs/content/reference/types/components/recording_uri.md @@ -15,8 +15,8 @@ utf8 ``` ## API reference links - * 🌊 [C++ API docs for `RecordingUri`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1RecordingUri.html?speculative-link) - * 🐍 [Python API docs for `RecordingUri`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.RecordingUri) - * 🦀 [Rust API docs for `RecordingUri`](https://docs.rs/rerun/latest/rerun/components/struct.RecordingUri.html?speculative-link) + * 🌊 [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) diff --git a/docs/content/reference/types/components/show_labels.md b/docs/content/reference/types/components/show_labels.md index 1f81d6c88e8f..81c2df55751c 100644 --- a/docs/content/reference/types/components/show_labels.md +++ b/docs/content/reference/types/components/show_labels.md @@ -32,7 +32,7 @@ boolean * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) -* [`GraphNodes`](../archetypes/graph_nodes.md?speculative-link) +* [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) diff --git a/docs/content/reference/types/components/tensor_data.md b/docs/content/reference/types/components/tensor_data.md index 212c6f45a755..3de2724c3242 100644 --- a/docs/content/reference/types/components/tensor_data.md +++ b/docs/content/reference/types/components/tensor_data.md @@ -19,10 +19,8 @@ which stores a contiguous array of typed values. ## Arrow datatype ``` Struct { - shape: List + shape: List + names: nullable List buffer: DenseUnion { 0 = "_null_markers": nullable null 1 = "U8": List diff --git a/docs/content/reference/types/components/text.md b/docs/content/reference/types/components/text.md index 456c2fc088df..c4dfafa3c62d 100644 --- a/docs/content/reference/types/components/text.md +++ b/docs/content/reference/types/components/text.md @@ -28,7 +28,7 @@ utf8 * [`Boxes3D`](../archetypes/boxes3d.md) * [`Capsules3D`](../archetypes/capsules3d.md) * [`Ellipsoids3D`](../archetypes/ellipsoids3d.md) -* [`GraphNodes`](../archetypes/graph_nodes.md?speculative-link) +* [`GraphNodes`](../archetypes/graph_nodes.md) * [`LineStrips2D`](../archetypes/line_strips2d.md) * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 6902ee39e313..b12bd42d39db 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -34,7 +34,6 @@ Data types are the lowest layer of the data model hierarchy. They are re-usable * [`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. -* [`TensorDimension`](datatypes/tensor_dimension.md): A single dimension within a multi-dimensional tensor. * [`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. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index 3454eebe12d8..771fe1303bcf 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -28,7 +28,6 @@ rgba32.md linguist-generated=true rotation_axis_angle.md linguist-generated=true tensor_buffer.md linguist-generated=true tensor_data.md linguist-generated=true -tensor_dimension.md linguist-generated=true tensor_dimension_index_selection.md linguist-generated=true tensor_dimension_selection.md linguist-generated=true time_int.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/plane3d.md b/docs/content/reference/types/datatypes/plane3d.md index 3f0973d64b6d..94cb6e572b38 100644 --- a/docs/content/reference/types/datatypes/plane3d.md +++ b/docs/content/reference/types/datatypes/plane3d.md @@ -20,11 +20,11 @@ FixedSizeList<4, float32> ``` ## API reference links - * 🌊 [C++ API docs for `Plane3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Plane3D.html?speculative-link) - * 🐍 [Python API docs for `Plane3D`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.Plane3D) - * 🦀 [Rust API docs for `Plane3D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Plane3D.html?speculative-link) + * 🌊 [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?speculative-link) +* [`Plane3D`](../components/plane3d.md) diff --git a/docs/content/reference/types/datatypes/tensor_data.md b/docs/content/reference/types/datatypes/tensor_data.md index d8af8ecbb674..abc09ba17823 100644 --- a/docs/content/reference/types/datatypes/tensor_data.md +++ b/docs/content/reference/types/datatypes/tensor_data.md @@ -14,9 +14,20 @@ which stores a contiguous array of typed values. ## Fields #### `shape` -Type: List of [`TensorDimension`](../datatypes/tensor_dimension.md) +Type: List of `uint64` -The shape of the tensor, including optional names for each dimension. +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) @@ -27,10 +38,8 @@ The content/data. ## Arrow datatype ``` Struct { - shape: List + shape: List + names: nullable List buffer: DenseUnion { 0 = "_null_markers": nullable null 1 = "U8": List diff --git a/docs/content/reference/types/datatypes/tensor_dimension.md b/docs/content/reference/types/datatypes/tensor_dimension.md deleted file mode 100644 index 71d1446ed11e..000000000000 --- a/docs/content/reference/types/datatypes/tensor_dimension.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "TensorDimension" ---- - - -A single dimension within a multi-dimensional tensor. - -## Fields -#### `size` -Type: `uint64` - -The length of this dimension. - -#### `name` -Type: nullable `utf8` - -The name of this dimension, e.g. "width", "height", "channel", "batch', …. - - -## Arrow datatype -``` -Struct { - size: uint64 - name: nullable utf8 -} -``` - -## API reference links - * 🌊 [C++ API docs for `TensorDimension`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TensorDimension.html) - * 🐍 [Python API docs for `TensorDimension`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TensorDimension) - * 🦀 [Rust API docs for `TensorDimension`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TensorDimension.html) - - -## Used by - -* [`TensorData`](../datatypes/tensor_data.md) diff --git a/docs/content/reference/types/datatypes/utf8.md b/docs/content/reference/types/datatypes/utf8.md index b4180a94ad44..092555b91625 100644 --- a/docs/content/reference/types/datatypes/utf8.md +++ b/docs/content/reference/types/datatypes/utf8.md @@ -20,11 +20,11 @@ utf8 ## Used by * [`AnnotationInfo`](../datatypes/annotation_info.md) -* [`GraphNode`](../components/graph_node.md?speculative-link) +* [`GraphNode`](../components/graph_node.md) * [`MediaType`](../components/media_type.md) * [`Name`](../components/name.md) -* [`RecordingUri`](../components/recording_uri.md?speculative-link) +* [`RecordingUri`](../components/recording_uri.md) * [`TextLogLevel`](../components/text_log_level.md) * [`Text`](../components/text.md) -* [`Utf8Pair`](../datatypes/utf8pair.md?speculative-link) +* [`Utf8Pair`](../datatypes/utf8pair.md) * [`VisibleTimeRange`](../datatypes/visible_time_range.md) diff --git a/docs/content/reference/types/datatypes/utf8pair.md b/docs/content/reference/types/datatypes/utf8pair.md index 1815cd16438e..15cb7fb87d49 100644 --- a/docs/content/reference/types/datatypes/utf8pair.md +++ b/docs/content/reference/types/datatypes/utf8pair.md @@ -26,11 +26,11 @@ Struct { ``` ## API reference links - * 🌊 [C++ API docs for `Utf8Pair`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Utf8Pair.html?speculative-link) - * 🐍 [Python API docs for `Utf8Pair`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.Utf8Pair) - * 🦀 [Rust API docs for `Utf8Pair`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Utf8Pair.html?speculative-link) + * 🌊 [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?speculative-link) +* [`GraphEdge`](../components/graph_edge.md) diff --git a/docs/content/reference/types/views/graph_view.md b/docs/content/reference/types/views/graph_view.md index 7e39cfc769e4..e76a96c14613 100644 --- a/docs/content/reference/types/views/graph_view.md +++ b/docs/content/reference/types/views/graph_view.md @@ -14,34 +14,34 @@ 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 force is enabled. +* `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 force is enabled. +* `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 force is enabled. +* `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 force is enabled. +* `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 force is enabled. +* `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?speculative-link#rerun.blueprint.views.GraphView) + * 🐍 [Python API docs for `GraphView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.GraphView) ## Example diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index d64fed561048..16ee05d96c03 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -25,7 +25,7 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' | **Dataframes** | `dataframe_query` | Query and display the first 10 rows of a recording | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/reference/dataframe_query.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/reference/dataframe_query.rs) | | | **Dataframes** | `dataframe_view_query` | Query and display the first 10 rows of a recording in a dataframe view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/reference/dataframe_view_query.py) | | | | **`AnyValue`** | `any_values` | Log arbitrary data | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/any_values.py) | | | -| **`AnyValue`** | `any_values_send_columns` | Use `AnyValues` and `send_column` to send entire columns of custom data to Rerun | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/howto/any_values_send_columns.py?speculative-link) | | | +| **`AnyValue`** | `any_values_send_columns` | Use `AnyValues` and `send_column` to send entire columns of custom data to Rerun | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/howto/any_values_send_columns.py) | | | | **`AnyValue`** | `extra_values` | Log extra values with a Points2D | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.py) | | | @@ -82,11 +82,11 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`GeoLineStrings`](https://rerun.io/docs/reference/types/archetypes/geo_line_strings)** | `archetypes/geo_line_strings_simple` | Log a simple geospatial line string | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.cpp) | | **[`GeoPoints`](https://rerun.io/docs/reference/types/archetypes/geo_points)** | `archetypes/geo_points_simple` | Log some very simple geospatial point | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_points_simple.cpp) | | **[`GeoPoints`](https://rerun.io/docs/reference/types/archetypes/geo_points)** | `views/map` | Use a blueprint to customize a map view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/map.py) | | | -| **[`GraphEdges`](https://rerun.io/docs/reference/types/archetypes/graph_edges?speculative-link)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp?speculative-link) | -| **[`GraphEdges`](https://rerun.io/docs/reference/types/archetypes/graph_edges?speculative-link)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp?speculative-link) | -| **[`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes?speculative-link)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp?speculative-link) | -| **[`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes?speculative-link)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp?speculative-link) | -| **[`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes?speculative-link)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py?speculative-link?speculative-link) | | | +| **[`GraphEdges`](https://rerun.io/docs/reference/types/archetypes/graph_edges)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp) | +| **[`GraphEdges`](https://rerun.io/docs/reference/types/archetypes/graph_edges)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp) | +| **[`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp) | +| **[`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp) | +| **[`GraphNodes`](https://rerun.io/docs/reference/types/archetypes/graph_nodes)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **[`Image`](https://rerun.io/docs/reference/types/archetypes/image)** | `archetypes/segmentation_image_simple` | Create and log a segmentation image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.cpp) | | **[`Image`](https://rerun.io/docs/reference/types/archetypes/image)** | `archetypes/image_simple` | Create and log an image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_simple.cpp) | | **[`Image`](https://rerun.io/docs/reference/types/archetypes/image)** | `archetypes/image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | @@ -135,9 +135,9 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes/instance_poses3d_combined` | Log a simple 3D box with a regular & instance pose transform | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/instance_poses3d_combined.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes/pinhole_perspective` | Logs a point cloud and a perspective camera looking at it | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/pinhole_perspective.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/pinhole_perspective.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/pinhole_perspective.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `archetypes/transform3d_hierarchy` | Logs a transforms transform hierarchy | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_hierarchy.cpp) | -| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `concepts/explicit_recording` | Just makes sure that explicit recordings actually work | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/explicit_recording.py?speculative-link) | | | -| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `descriptors/descr_builtin_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_archetype.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_archetype.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_archetype.cpp?speculative-link) | -| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `descriptors/descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp?speculative-link) | +| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `concepts/explicit_recording` | Just makes sure that explicit recordings actually work | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/explicit_recording.py) | | | +| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `descriptors/descr_builtin_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_archetype.cpp) | +| **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `descriptors/descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `migration/log_line` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/migration/log_line.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/migration/log_line.rs) | | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `quick_start/quick_start_connect` | Connect to the viewer and log some data | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_connect.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_connect.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_connect.cpp) | | **[`Points3D`](https://rerun.io/docs/reference/types/archetypes/points3d)** | `quick_start/quick_start_spawn` | Spawn a viewer and log some data | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_spawn.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_spawn.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/quick_start/quick_start_spawn.cpp) | @@ -204,25 +204,25 @@ _All snippets, organized by the [`Component`](https://rerun.io/docs/reference/ty | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts/viscomp-component-override` | Override a component | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-component-override.py) | | | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts/viscomp-visualizer-override` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override.py) | | | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `concepts/viscomp-visualizer-override-multiple` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override-multiple.py) | | | -| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `descriptors/descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp?speculative-link) | +| **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `descriptors/descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp) | | **[`Color`](https://rerun.io/docs/reference/types/components/color)** | `views/spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | | **[`DisconnectedSpace`](https://rerun.io/docs/reference/types/components/disconnected_space)** | `archetypes/disconnected_space` | Disconnect two spaces | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/disconnected_space.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/disconnected_space.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/disconnected_space.cpp) | | **[`GeoLineString`](https://rerun.io/docs/reference/types/components/geo_line_string)** | `archetypes/geo_line_strings_simple` | Log a simple geospatial line string | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/geo_line_strings_simple.cpp) | -| **[`GraphEdge`](https://rerun.io/docs/reference/types/components/graph_edge?speculative-link)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp?speculative-link) | -| **[`GraphEdge`](https://rerun.io/docs/reference/types/components/graph_edge?speculative-link)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp?speculative-link) | -| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node?speculative-link)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp?speculative-link) | -| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node?speculative-link)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp?speculative-link) | -| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node?speculative-link)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py?speculative-link?speculative-link) | | | +| **[`GraphEdge`](https://rerun.io/docs/reference/types/components/graph_edge)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp) | +| **[`GraphEdge`](https://rerun.io/docs/reference/types/components/graph_edge)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp) | +| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `archetypes/graph_directed` | Log a simple directed graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_directed.cpp) | +| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `archetypes/graph_undirected` | Log a simple undirected graph | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/graph_undirected.cpp) | +| **[`GraphNode`](https://rerun.io/docs/reference/types/components/graph_node)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **[`ImageBuffer`](https://rerun.io/docs/reference/types/components/image_buffer)** | `archetypes/image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | | **[`ImageFormat`](https://rerun.io/docs/reference/types/components/image_format)** | `archetypes/image_send_columns` | Send multiple images at once using `send_columns` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/image_send_columns.cpp) | | **[`MediaType`](https://rerun.io/docs/reference/types/components/media_type)** | `archetypes/text_document` | Log a `TextDocument` | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/text_document.cpp) | | **[`MediaType`](https://rerun.io/docs/reference/types/components/media_type)** | `views/text_document` | Use a blueprint to show a text document | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/text_document.py) | | | -| **[`Plane3D`](https://rerun.io/docs/reference/types/components/plane3d?speculative-link)** | `views/spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py?speculative-link) | | | +| **[`Plane3D`](https://rerun.io/docs/reference/types/components/plane3d)** | `views/spatial3d` | Use a blueprint to customize a Spatial3DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial3d.py) | | | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes/mesh3d_partial_updates` | Log a simple colored triangle, then update its vertices' positions each frame | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/mesh3d_partial_updates.cpp) | | **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `archetypes/points3d_send_columns` | Use the `send_columns` API to send several point clouds over time in a single call | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.py) | | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_send_columns.cpp) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_builtin_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.cpp?speculative-link) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp?speculative-link) | -| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_custom_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.py?speculative-link) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.rs?speculative-link) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.cpp?speculative-link) | +| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_builtin_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_builtin_component.cpp) | +| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_custom_archetype` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_archetype.cpp) | +| **[`Position3D`](https://rerun.io/docs/reference/types/components/position3d)** | `descriptors/descr_custom_component` | | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/descriptors/descr_custom_component.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/points3d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_ui_radius.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/points2d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.cpp) | | **[`Radius`](https://rerun.io/docs/reference/types/components/radius)** | `archetypes/line_strips3d_ui_radius` | Log lines with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips3d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips3d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips3d_ui_radius.cpp) | @@ -280,7 +280,7 @@ _All snippets, organized by the [`View`](https://rerun.io/docs/reference/types/v | **[`DataframeView`](https://rerun.io/docs/reference/types/views/dataframe_view)** | `reference/dataframe_view_query` | Query and display the first 10 rows of a recording in a dataframe view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/reference/dataframe_view_query.py) | | | | **[`DataframeView`](https://rerun.io/docs/reference/types/views/dataframe_view)** | `reference/dataframe_save_blueprint` | Craft a blueprint with the python API and save it to a file for future use | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/reference/dataframe_save_blueprint.py) | | | | **[`DataframeView`](https://rerun.io/docs/reference/types/views/dataframe_view)** | `views/dataframe` | Use a blueprint to customize a DataframeView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/dataframe.py) | | | -| **[`GraphView`](https://rerun.io/docs/reference/types/views/graph_view?speculative-link)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py?speculative-link?speculative-link) | | | +| **[`GraphView`](https://rerun.io/docs/reference/types/views/graph_view)** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **[`MapView`](https://rerun.io/docs/reference/types/views/map_view)** | `views/map` | Use a blueprint to customize a map view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/map.py) | | | | **[`Spatial2DView`](https://rerun.io/docs/reference/types/views/spatial2d_view)** | `archetypes/line_strips2d_batch` | Log a batch of 2D line strips | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_batch.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_batch.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_batch.cpp) | | **[`Spatial2DView`](https://rerun.io/docs/reference/types/views/spatial2d_view)** | `archetypes/line_strips2d_segments_simple` | Log a couple 2D line segments using 2D line strips | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_segments_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_segments_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/line_strips2d_segments_simple.cpp) | @@ -333,7 +333,7 @@ _All snippets, organized by the blueprint-related [`Archetype`](https://rerun.io | **`VisualBounds2D`** | `archetypes/points2d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.cpp) | | **`VisualBounds2D`** | `concepts/different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | | **`VisualBounds2D`** | `tutorials/extra_values` | Log extra values with a Points2D | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.py) | | | -| **`VisualBounds2D`** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py?speculative-link) | | | +| **`VisualBounds2D`** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **`VisualBounds2D`** | `views/spatial2d` | Use a blueprint to customize a Spatial2DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial2d.py) | | | @@ -357,7 +357,7 @@ _All snippets, organized by the blueprint-related [`Component`](https://rerun.io | **`VisualBounds2D`** | `archetypes/points2d_ui_radius` | Log some points with ui points & scene unit radii | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points2d_ui_radius.cpp) | | **`VisualBounds2D`** | `concepts/different_data_per_timeline` | Log different data on different timelines | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/different_data_per_timeline.cpp) | | **`VisualBounds2D`** | `tutorials/extra_values` | Log extra values with a Points2D | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.py) | | | -| **`VisualBounds2D`** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py?speculative-link) | | | +| **`VisualBounds2D`** | `views/graph` | Use a blueprint to customize a graph view | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/graph.py) | | | | **`VisualBounds2D`** | `views/spatial2d` | Use a blueprint to customize a Spatial2DView | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/views/spatial2d.py) | | | | **`VisualizerOverrides`** | `concepts/viscomp-visualizer-override` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override.py) | | | | **`VisualizerOverrides`** | `concepts/viscomp-visualizer-override-multiple` | Override a visualizer | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/concepts/viscomp-visualizer-override-multiple.py) | | | diff --git a/docs/snippets/README.md b/docs/snippets/README.md index a221615ae85a..21d51dcb2c10 100644 --- a/docs/snippets/README.md +++ b/docs/snippets/README.md @@ -11,7 +11,7 @@ You can run each example individually using the following: - **C++**: - `pixi run -e cpp cpp-build-snippets` to compile all examples - `./build/debug/docs/snippets/all/` to run, e.g. `./build/debug/docs/snippets/all/point3d_random` -- **Python**: `pixi run -e py python .py`, e.g. `pixi run -e py python point3d_random.py`. +- **Python**: `pixi run py-build && pixi run -e py python .py`, e.g. `pixi run -e py python point3d_random.py`. - **Rust**: `cargo run -p snippets -- [args]`, e.g. `cargo run -p snippets -- point3d_random`. ## Comparison test @@ -23,8 +23,8 @@ These tests check that A) all of our SDKs yield the exact same data when used th ### Usage -To run the comparison tests, check out `./docs/snippets/compare_snippet_output.py --help`. -`./docs/snippets/compare_snippet_output.py` is a valid invocation that will build all 3 SDKs and run all tests for all of them. +To run the comparison tests, check out `pixi run -e py docs/snippets/compare_snippet_output.py --help`. +`pixi run -e py docs/snippets/compare_snippet_output.py` is a valid invocation that will build all 3 SDKs and run all tests for all of them. ### Implementing new tests diff --git a/docs/snippets/all/archetypes/graph_directed.cpp b/docs/snippets/all/archetypes/graph_directed.cpp index 3f09463b0eac..97b902d7bb4d 100644 --- a/docs/snippets/all/archetypes/graph_directed.cpp +++ b/docs/snippets/all/archetypes/graph_directed.cpp @@ -10,12 +10,7 @@ int main() { "simple", rerun::GraphNodes({"a", "b", "c"}) .with_positions({{0.0, 100.0}, {-100.0, 0.0}, {100.0, 0.0}}) - .with_labels({"A", "B", "C"}) - ); - - // Note: We log to the same entity here. - rec.log( - "simple", + .with_labels({"A", "B", "C"}), rerun::GraphEdges({{"a", "b"}, {"b", "c"}, {"c", "a"}}) // Graphs are undirected by default. .with_graph_type(rerun::components::GraphType::Directed) diff --git a/docs/snippets/all/archetypes/graph_directed.py b/docs/snippets/all/archetypes/graph_directed.py index 63a803138a3b..d4471994c178 100644 --- a/docs/snippets/all/archetypes/graph_directed.py +++ b/docs/snippets/all/archetypes/graph_directed.py @@ -9,8 +9,5 @@ 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.log( - "simple", rr.GraphEdges(edges=[("a", "b"), ("b", "c"), ("c", "a")], graph_type="directed"), ) diff --git a/docs/snippets/all/archetypes/graph_directed.rs b/docs/snippets/all/archetypes/graph_directed.rs index be05ad8bd407..8a411238fb45 100644 --- a/docs/snippets/all/archetypes/graph_directed.rs +++ b/docs/snippets/all/archetypes/graph_directed.rs @@ -5,14 +5,12 @@ fn main() -> Result<(), Box> { rec.log( "simple", - &rerun::GraphNodes::new(["a", "b", "c"]) - .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) - .with_labels(["A", "B", "C"]), - )?; - // Note: We log to the same entity here. - rec.log( - "simple", - &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]).with_directed_edges(), + &[ + &rerun::GraphNodes::new(["a", "b", "c"]) + .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) + .with_labels(["A", "B", "C"]) as &dyn rerun::AsComponents, + &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]).with_directed_edges(), + ], )?; Ok(()) diff --git a/docs/snippets/all/archetypes/graph_undirected.cpp b/docs/snippets/all/archetypes/graph_undirected.cpp index 2d7e82ddba24..e81fecf36655 100644 --- a/docs/snippets/all/archetypes/graph_undirected.cpp +++ b/docs/snippets/all/archetypes/graph_undirected.cpp @@ -10,12 +10,7 @@ int main() { "simple", rerun::GraphNodes({"a", "b", "c"}) .with_positions({{0.0, 100.0}, {-100.0, 0.0}, {100.0, 0.0}}) - .with_labels({"A", "B", "C"}) - ); - - // Note: We log to the same entity here. - rec.log( - "simple", + .with_labels({"A", "B", "C"}), rerun::GraphEdges({{"a", "b"}, {"b", "c"}, {"c", "a"}}) // Optional: graphs are undirected by default. .with_graph_type(rerun::components::GraphType::Undirected) diff --git a/docs/snippets/all/archetypes/graph_undirected.py b/docs/snippets/all/archetypes/graph_undirected.py index 2397bfc31c5b..556a3782cfc0 100644 --- a/docs/snippets/all/archetypes/graph_undirected.py +++ b/docs/snippets/all/archetypes/graph_undirected.py @@ -9,8 +9,9 @@ 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.log( - "simple", - rr.GraphEdges(edges=[("a", "b"), ("b", "c"), ("c", "a")], graph_type="undirected"), + rr.GraphEdges( + edges=[("a", "b"), ("b", "c"), ("c", "a")], + # Optional: graphs are undirected by default. + graph_type="undirected", + ), ) diff --git a/docs/snippets/all/archetypes/graph_undirected.rs b/docs/snippets/all/archetypes/graph_undirected.rs index affd0ec3d0ee..c87219a931f2 100644 --- a/docs/snippets/all/archetypes/graph_undirected.rs +++ b/docs/snippets/all/archetypes/graph_undirected.rs @@ -5,14 +5,14 @@ fn main() -> Result<(), Box> { rec.log( "simple", - &rerun::GraphNodes::new(["a", "b", "c"]) - .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) - .with_labels(["A", "B", "C"]), - )?; - // Note: We log to the same entity here. - rec.log( - "simple", - &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]).with_undirected_edges(), // Optional: graphs are undirected by default. + &[ + &rerun::GraphNodes::new(["a", "b", "c"]) + .with_positions([(0.0, 100.0), (-100.0, 0.0), (100.0, 0.0)]) + .with_labels(["A", "B", "C"]) as &dyn rerun::AsComponents, + &rerun::GraphEdges::new([("a", "b"), ("b", "c"), ("c", "a")]) + // Optional: graphs are undirected by default. + .with_undirected_edges(), + ], )?; Ok(()) diff --git a/examples/python/graph_lattice/README.md b/examples/python/graph_lattice/README.md index a44ec2eeab8d..f6d55edcd3c9 100644 --- a/examples/python/graph_lattice/README.md +++ b/examples/python/graph_lattice/README.md @@ -17,8 +17,8 @@ Since no explicit positions are passed for the nodes, Rerun will layout the grap ## Used Rerun types -[`GraphNodes`](https://www.rerun.io/docs/reference/types/archetypes/graph_nodes?speculative-link), -[`GraphEdges`](https://www.rerun.io/docs/reference/types/archetypes/graph_edges?speculative-link) +[`GraphNodes`](https://www.rerun.io/docs/reference/types/archetypes/graph_nodes), +[`GraphEdges`](https://www.rerun.io/docs/reference/types/archetypes/graph_edges) ## Run the code diff --git a/examples/python/graph_lattice/graph_lattice.py b/examples/python/graph_lattice/graph_lattice.py index 21eb327df1ca..0df3efa1f7d3 100644 --- a/examples/python/graph_lattice/graph_lattice.py +++ b/examples/python/graph_lattice/graph_lattice.py @@ -17,7 +17,7 @@ In this example, the node positions—and therefore the graph layout—are computed by Rerun internally. The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/graph_lattice?speculative-link). +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/graph_lattice). """.strip() diff --git a/examples/python/graphs/README.md b/examples/python/graphs/README.md index b06d813bd166..2d855c9cb919 100644 --- a/examples/python/graphs/README.md +++ b/examples/python/graphs/README.md @@ -25,8 +25,8 @@ This example shows different types of layouts: ## Used Rerun types -[`GraphNodes`](https://www.rerun.io/docs/reference/types/archetypes/graph_nodes?speculative-link), -[`GraphEdges`](https://www.rerun.io/docs/reference/types/archetypes/graph_edges?speculative-link) +[`GraphNodes`](https://www.rerun.io/docs/reference/types/archetypes/graph_nodes), +[`GraphEdges`](https://www.rerun.io/docs/reference/types/archetypes/graph_edges) ## Force-based layouts diff --git a/examples/python/graphs/graphs.py b/examples/python/graphs/graphs.py index 3bf490c625d9..9b1abf9c6acc 100644 --- a/examples/python/graphs/graphs.py +++ b/examples/python/graphs/graphs.py @@ -37,7 +37,7 @@ You can modify how these graphs look by changing the parameters of the force-based layout algorithm in the selection panel. The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/graphs?speculative-link). +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/graphs). """.strip() diff --git a/examples/python/remote/metadata.py b/examples/python/remote/metadata.py index e199499d8f2a..31371bfac2d3 100644 --- a/examples/python/remote/metadata.py +++ b/examples/python/remote/metadata.py @@ -14,23 +14,31 @@ subparsers = parser.add_subparsers(dest="subcommand") print_cmd = subparsers.add_parser("print", help="Print everything") + register_cmd = subparsers.add_parser("register", help="Register a new recording") update_cmd = subparsers.add_parser("update", help="Update metadata for a recording") update_cmd.add_argument("id", help="ID of the recording to update") update_cmd.add_argument("key", help="Key of the metadata to update") update_cmd.add_argument("value", help="Value of the metadata to update") + register_cmd.add_argument("storage_url", help="Storage URL to register") + args = parser.parse_args() # Register the new rrd conn = rr.remote.connect("http://0.0.0.0:51234") - catalog = pl.from_arrow(conn.query_catalog()) + catalog = pl.from_arrow(conn.query_catalog().read_all()) if args.subcommand == "print": print(catalog) - if args.subcommand == "update": + elif args.subcommand == "register": + extra_metadata = pa.Table.from_pydict({"extra": [42]}) + id = conn.register(args.storage_url, extra_metadata) + print(f"Registered new recording with ID: {id}") + + elif args.subcommand == "update": id = catalog.filter(catalog["id"].str.starts_with(args.id)).select(pl.first("id")).item() if id is None: @@ -38,4 +46,7 @@ exit(1) print(f"Updating metadata for {id}") - conn.update_catalog(id, {args.key: pa.array([args.value])}) + new_metadata = pa.Table.from_pydict({"id": [id], args.key: [args.value]}) + print(new_metadata) + + conn.update_catalog(new_metadata) diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index 8e7862da7ed7..1d27cfce16ef 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "clock" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index a7c4699037ac..cbdf1c81a6b0 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "custom_data_loader" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index 654d3353575c..a1b110bc6c8f 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "custom_store_subscriber" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/custom_view/Cargo.toml b/examples/rust/custom_view/Cargo.toml index 31818d428102..cc38521c6e30 100644 --- a/examples/rust/custom_view/Cargo.toml +++ b/examples/rust/custom_view/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "custom_view" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/dataframe_query/Cargo.toml b/examples/rust/dataframe_query/Cargo.toml index 538b9047d8aa..004e0a4804a6 100644 --- a/examples/rust/dataframe_query/Cargo.toml +++ b/examples/rust/dataframe_query/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "dataframe_query" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index 21dec7a03ced..8b023677ef44 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "dna" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index 6e4a385aa850..633cdb891f63 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "extend_viewer_ui" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index 956a9c949d0c..5eab8acb917c 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "rerun-loader-rust-file" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/graph_lattice/Cargo.toml b/examples/rust/graph_lattice/Cargo.toml index b0c602c619e7..ca476d428b9e 100644 --- a/examples/rust/graph_lattice/Cargo.toml +++ b/examples/rust/graph_lattice/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "graph_lattice" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/graph_lattice/README.md b/examples/rust/graph_lattice/README.md index 0f3e4ea460f9..eaddac3f256d 100644 --- a/examples/rust/graph_lattice/README.md +++ b/examples/rust/graph_lattice/README.md @@ -17,8 +17,8 @@ Since no explicit positions are passed for the nodes, Rerun will layout the grap ## Used Rerun types -[`GraphNodes`](https://www.rerun.io/docs/reference/types/archetypes/graph_nodes?speculative-link), -[`GraphEdges`](https://www.rerun.io/docs/reference/types/archetypes/graph_edges?speculative-link) +[`GraphNodes`](https://www.rerun.io/docs/reference/types/archetypes/graph_nodes), +[`GraphEdges`](https://www.rerun.io/docs/reference/types/archetypes/graph_edges) ## Run the code diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index 16d0e2c8dcfd..f23f29eb4d35 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "incremental_logging" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index 61efa8c61bdb..517929141648 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "log_file" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index fa1574b3c4cb..2f42d214ca71 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "minimal" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index 12aeb3549093..263afae8696b 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "minimal_options" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index cc9b36b7eaab..323edd8656c3 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "minimal_serve" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index 201a3218a7e8..fb1af36d4c16 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "objectron" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index 051b612e2275..2e4aa045e57c 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "raw_mesh" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index ba713863611f..d892dade3bb2 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "shared_recording" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index 050cc9655af5..2b16517bf9b0 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "spawn_viewer" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index 285564d8bc2f..8966b236b5a3 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "stdio" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index 2876785083e5..38c375a8ecf4 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "template" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" edition = "2021" -rust-version = "1.80" +rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/pixi.lock b/pixi.lock index 704ab17f98a4..ad8fed5b1757 100644 --- a/pixi.lock +++ b/pixi.lock @@ -30286,8 +30286,8 @@ packages: - watchfiles ; extra == 'dev' - pypi: rerun_notebook name: rerun-notebook - version: 0.21.0a1+dev - sha256: 047bf251505a9b46f02e7f700fe4073247fa2c95f8dd36f6f2f628e0ade8c055 + version: 0.22.0a1+dev + sha256: 7e12a38063373d2b82c7eb731a3985d7646c0ecd59b5c6230a8a48955094b723 requires_dist: - anywidget - jupyter-ui-poll @@ -30362,8 +30362,8 @@ packages: requires_python: '>=3.8,<3.13' - pypi: rerun_py name: rerun-sdk - version: 0.21.0a1+dev - sha256: a2a848bd650eb5075582955b9dfcb9e4e43a5d1209ca7f053ceeed16ded0118a + version: 0.22.0a1+dev + sha256: 4a0b3da14f4aef104a2c3c4c8db24f35528b5b96590c282a5e52d53a96aea177 requires_dist: - attrs>=23.1.0 - numpy>=1.23 @@ -30371,7 +30371,7 @@ packages: - pyarrow>=14.0.2 - typing-extensions>=4.5 - pytest==7.1.2 ; extra == 'tests' - - rerun-notebook==0.21.0a1+dev ; extra == 'notebook' + - rerun-notebook==0.22.0a1+dev ; extra == 'notebook' requires_python: '>=3.8' editable: true - pypi: https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl diff --git a/rerun_cpp/src/rerun.hpp b/rerun_cpp/src/rerun.hpp index 8f4546fc4c01..4b2d4933db05 100644 --- a/rerun_cpp/src/rerun.hpp +++ b/rerun_cpp/src/rerun.hpp @@ -66,7 +66,6 @@ namespace rerun { using datatypes::RotationAxisAngle; using datatypes::TensorBuffer; using datatypes::TensorData; - using datatypes::TensorDimension; using datatypes::Vec2D; using datatypes::Vec3D; using datatypes::Vec4D; diff --git a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp index b65fbb6419ee..b84f7c317287 100644 --- a/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/ellipsoids3d.hpp @@ -34,6 +34,61 @@ namespace rerun::archetypes { /// 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. + /// + /// ## Example + /// + /// ### Covariance ellipsoid + /// ![image](https://static.rerun.io/elliopsoid3d_simple/bd5d46e61b80ae44792b52ee07d750a7137002ea/full.png) + /// + /// ```cpp + /// #include + /// + /// #include + /// #include + /// #include + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_ellipsoid_simple"); + /// rec.spawn().exit_on_failure(); + /// + /// const float sigmas[3] = {5.0f, 3.0f, 1.0f}; + /// + /// std::default_random_engine gen; + /// std::normal_distribution dist(0.0, 1.0f); + /// + /// std::vector points3d(50000); + /// std::generate(points3d.begin(), points3d.end(), [&] { + /// return rerun::Position3D( + /// sigmas[0] * dist(gen), + /// sigmas[1] * dist(gen), + /// sigmas[2] * dist(gen) + /// ); + /// }); + /// + /// rec.log( + /// "points", + /// rerun::Points3D(points3d).with_radii(0.02f).with_colors(rerun::Rgba32(188, 77, 185)) + /// ); + /// + /// rec.log( + /// "ellipsoid", + /// rerun::Ellipsoids3D::from_centers_and_half_sizes( + /// { + /// {0.0f, 0.0f, 0.0f}, + /// {0.0f, 0.0f, 0.0f}, + /// }, + /// { + /// {sigmas[0], sigmas[1], sigmas[2]}, + /// {3.0f * sigmas[0], 3.0f * sigmas[1], 3.0f * sigmas[2]}, + /// } + /// ) + /// .with_colors({ + /// rerun::Rgba32(255, 255, 0), + /// rerun::Rgba32(64, 64, 0), + /// }) + /// ); + /// } + /// ``` struct Ellipsoids3D { /// For each ellipsoid, half of its size on its three axes. /// diff --git a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp index 4e60d8e23d82..7ae79b0a58b6 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_edges.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_edges.hpp @@ -21,7 +21,29 @@ namespace rerun::archetypes { /// /// By default, edges are undirected. /// - /// ⚠ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** + /// ## Example + /// + /// ### Simple directed graph + /// ![image](https://static.rerun.io/graph_directed/ca29a37b65e1e0b6482251dce401982a0bc568fa/full.png) + /// + /// ```cpp + /// #include + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_graph_directed"); + /// rec.spawn().exit_on_failure(); + /// + /// rec.log( + /// "simple", + /// rerun::GraphNodes({"a", "b", "c"}) + /// .with_positions({{0.0, 100.0}, {-100.0, 0.0}, {100.0, 0.0}}) + /// .with_labels({"A", "B", "C"}), + /// rerun::GraphEdges({{"a", "b"}, {"b", "c"}, {"c", "a"}}) + /// // Graphs are undirected by default. + /// .with_graph_type(rerun::components::GraphType::Directed) + /// ); + /// } + /// ``` struct GraphEdges { /// A list of node tuples. Collection edges; diff --git a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp index 1323569a7137..6017a265a565 100644 --- a/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp +++ b/rerun_cpp/src/rerun/archetypes/graph_nodes.hpp @@ -23,7 +23,29 @@ namespace rerun::archetypes { /// **Archetype**: A list of nodes in a graph with optional labels, colors, etc. /// - /// ⚠ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** + /// ## Example + /// + /// ### Simple directed graph + /// ![image](https://static.rerun.io/graph_directed/ca29a37b65e1e0b6482251dce401982a0bc568fa/full.png) + /// + /// ```cpp + /// #include + /// + /// int main() { + /// const auto rec = rerun::RecordingStream("rerun_example_graph_directed"); + /// rec.spawn().exit_on_failure(); + /// + /// rec.log( + /// "simple", + /// rerun::GraphNodes({"a", "b", "c"}) + /// .with_positions({{0.0, 100.0}, {-100.0, 0.0}, {100.0, 0.0}}) + /// .with_labels({"A", "B", "C"}), + /// rerun::GraphEdges({{"a", "b"}, {"b", "c"}, {"c", "a"}}) + /// // Graphs are undirected by default. + /// .with_graph_type(rerun::components::GraphType::Directed) + /// ); + /// } + /// ``` struct GraphNodes { /// A list of node IDs. Collection node_ids; diff --git a/rerun_cpp/src/rerun/archetypes/tensor.hpp b/rerun_cpp/src/rerun/archetypes/tensor.hpp index 881c6f34bb60..8f2b553ab2c9 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.hpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.hpp @@ -77,7 +77,7 @@ namespace rerun::archetypes { public: // START of extensions from tensor_ext.cpp: /// New Tensor from dimensions and tensor buffer. - Tensor(Collection shape, datatypes::TensorBuffer buffer) + Tensor(Collection shape, datatypes::TensorBuffer buffer) : Tensor(datatypes::TensorData(std::move(shape), std::move(buffer))) {} /// New tensor from dimensions and pointer to tensor data. @@ -88,7 +88,7 @@ namespace rerun::archetypes { /// \param data_ /// Target of the pointer must outlive the archetype. template - explicit Tensor(Collection shape, const TElement* data_) + explicit Tensor(Collection shape, const TElement* data_) : Tensor(datatypes::TensorData(std::move(shape), data_)) {} /// Update the `names` of the contained `TensorData` dimensions. diff --git a/rerun_cpp/src/rerun/archetypes/tensor_ext.cpp b/rerun_cpp/src/rerun/archetypes/tensor_ext.cpp index 850416c0bed9..d684252c1822 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/tensor_ext.cpp @@ -13,7 +13,7 @@ namespace rerun::archetypes { // /// New Tensor from dimensions and tensor buffer. - Tensor(Collection shape, datatypes::TensorBuffer buffer) + Tensor(Collection shape, datatypes::TensorBuffer buffer) : Tensor(datatypes::TensorData(std::move(shape), std::move(buffer))) {} /// New tensor from dimensions and pointer to tensor data. @@ -24,7 +24,7 @@ namespace rerun::archetypes { /// \param data_ /// Target of the pointer must outlive the archetype. template - explicit Tensor(Collection shape, const TElement* data_) + explicit Tensor(Collection shape, const TElement* data_) : Tensor(datatypes::TensorData(std::move(shape), data_)) {} /// Update the `names` of the contained `TensorData` dimensions. @@ -51,11 +51,7 @@ namespace rerun::archetypes { .handle(); } - auto new_shape = shape.to_vector(); - for (size_t i = 0; i < std::min(shape.size(), names.size()); ++i) { - new_shape[i].name = std::move(names[i]); - } - shape = std::move(new_shape); + this->data.data.names = std::move(names); return std::move(*this); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp index 8c3854765b91..4a76fb9c2ff7 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_center.hpp @@ -19,7 +19,9 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Tries to move the center of mass of the graph to the origin. struct ForceCenter { - /// Whether the force is enabled. + /// Whether the center force is enabled. + /// + /// The center force tries to move the center of mass of the graph towards the origin. std::optional enabled; /// The strength of the force. @@ -36,7 +38,9 @@ namespace rerun::blueprint::archetypes { ForceCenter() = default; ForceCenter(ForceCenter&& other) = default; - /// Whether the force is enabled. + /// Whether the center force is enabled. + /// + /// The center force tries to move the center of mass of the graph towards the origin. ForceCenter with_enabled(rerun::blueprint::components::Enabled _enabled) && { enabled = std::move(_enabled); // See: https://github.com/rerun-io/rerun/issues/4027 diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp index 5b8ff3d1d511..f51201ee8bd0 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_collision_radius.hpp @@ -18,9 +18,11 @@ #include namespace rerun::blueprint::archetypes { - /// **Archetype**: Resolves collisions between the bounding spheres, according to the radius of the nodes. + /// **Archetype**: Resolves collisions between the bounding circles, according to the radius of the nodes. struct ForceCollisionRadius { - /// Whether the force is enabled. + /// Whether the collision force is enabled. + /// + /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. std::optional enabled; /// The strength of the force. @@ -42,7 +44,9 @@ namespace rerun::blueprint::archetypes { ForceCollisionRadius() = default; ForceCollisionRadius(ForceCollisionRadius&& other) = default; - /// Whether the force is enabled. + /// Whether the collision force is enabled. + /// + /// The collision force resolves collisions between nodes based on the bounding circle defined by their radius. ForceCollisionRadius with_enabled(rerun::blueprint::components::Enabled _enabled) && { enabled = std::move(_enabled); // See: https://github.com/rerun-io/rerun/issues/4027 diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp index 0d88538bc59b..b543152710b4 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_link.hpp @@ -20,7 +20,9 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Aims to achieve a target distance between two nodes that are connected by an edge. struct ForceLink { - /// Whether the force is enabled. + /// Whether the link force is enabled. + /// + /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. std::optional enabled; /// The target distance between two nodes. @@ -42,7 +44,9 @@ namespace rerun::blueprint::archetypes { ForceLink() = default; ForceLink(ForceLink&& other) = default; - /// Whether the force is enabled. + /// Whether the link force is enabled. + /// + /// The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. ForceLink with_enabled(rerun::blueprint::components::Enabled _enabled) && { enabled = std::move(_enabled); // See: https://github.com/rerun-io/rerun/issues/4027 diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp index c5267b3cf692..9b0e2686745d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_many_body.hpp @@ -21,7 +21,10 @@ namespace rerun::blueprint::archetypes { /// /// If `strength` is smaller than 0, it pushes nodes apart, if it is larger than 0 it pulls them together. struct ForceManyBody { - /// Whether the force is enabled. + /// Whether the many body force is enabled. + /// + /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. std::optional enabled; /// The strength of the force. @@ -40,7 +43,10 @@ namespace rerun::blueprint::archetypes { ForceManyBody() = default; ForceManyBody(ForceManyBody&& other) = default; - /// Whether the force is enabled. + /// Whether the many body force is enabled. + /// + /// The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + /// strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. ForceManyBody with_enabled(rerun::blueprint::components::Enabled _enabled) && { enabled = std::move(_enabled); // See: https://github.com/rerun-io/rerun/issues/4027 diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp index 36d740ce7393..3c6fbf9d266b 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/force_position.hpp @@ -20,7 +20,9 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Similar to gravity, this force pulls nodes towards a specific position. struct ForcePosition { - /// Whether the force is enabled. + /// Whether the position force is enabled. + /// + /// The position force pulls nodes towards a specific position, similar to gravity. std::optional enabled; /// The strength of the force. @@ -40,7 +42,9 @@ namespace rerun::blueprint::archetypes { ForcePosition() = default; ForcePosition(ForcePosition&& other) = default; - /// Whether the force is enabled. + /// Whether the position force is enabled. + /// + /// The position force pulls nodes towards a specific position, similar to gravity. ForcePosition with_enabled(rerun::blueprint::components::Enabled _enabled) && { enabled = std::move(_enabled); // See: https://github.com/rerun-io/rerun/issues/4027 diff --git a/rerun_cpp/src/rerun/c/sdk_info.h b/rerun_cpp/src/rerun/c/sdk_info.h index d1e864f0498e..eb36492072a9 100644 --- a/rerun_cpp/src/rerun/c/sdk_info.h +++ b/rerun_cpp/src/rerun/c/sdk_info.h @@ -2,13 +2,13 @@ /// /// This should match the string returned by `rr_version_string` (C) or `rerun::version_string` (C++). /// If not, the SDK's binary and the C header are out of sync. -#define RERUN_SDK_HEADER_VERSION "0.21.0-alpha.1+dev" +#define RERUN_SDK_HEADER_VERSION "0.22.0-alpha.1+dev" /// Major version of the Rerun C SDK. #define RERUN_SDK_HEADER_VERSION_MAJOR 0 /// Minor version of the Rerun C SDK. -#define RERUN_SDK_HEADER_VERSION_MINOR 21 +#define RERUN_SDK_HEADER_VERSION_MINOR 22 /// Patch version of the Rerun C SDK. #define RERUN_SDK_HEADER_VERSION_PATCH 0 diff --git a/rerun_cpp/src/rerun/components/tensor_data.hpp b/rerun_cpp/src/rerun/components/tensor_data.hpp index d85bb7960091..a7ececf996fd 100644 --- a/rerun_cpp/src/rerun/components/tensor_data.hpp +++ b/rerun_cpp/src/rerun/components/tensor_data.hpp @@ -28,10 +28,7 @@ namespace rerun::components { /// /// \param shape Shape of the tensor. /// \param buffer The tensor buffer containing the tensor's data. - TensorData( - rerun::Collection shape, - rerun::datatypes::TensorBuffer buffer - ) + TensorData(rerun::Collection shape, rerun::datatypes::TensorBuffer buffer) : data(rerun::datatypes::TensorData(std::move(shape), std::move(buffer))) {} /// New tensor data from dimensions and pointer to tensor data. @@ -40,7 +37,7 @@ namespace rerun::components { /// \param shape Shape of the tensor. Determines the number of elements expected to be in `data_`. /// \param data_ Target of the pointer must outlive the archetype. template - explicit TensorData(Collection shape, const TElement* data_) + explicit TensorData(Collection shape, const TElement* data_) : data(rerun::datatypes::TensorData(std::move(shape), data_)) {} // END of extensions from tensor_data_ext.cpp, start of generated code: diff --git a/rerun_cpp/src/rerun/components/tensor_data_ext.cpp b/rerun_cpp/src/rerun/components/tensor_data_ext.cpp index 3da2dde1f4cf..3d797a51f227 100644 --- a/rerun_cpp/src/rerun/components/tensor_data_ext.cpp +++ b/rerun_cpp/src/rerun/components/tensor_data_ext.cpp @@ -11,7 +11,7 @@ namespace rerun::components { /// \param shape Shape of the tensor. /// \param buffer The tensor buffer containing the tensor's data. TensorData( - rerun::Collection shape, + rerun::Collection shape, rerun::datatypes::TensorBuffer buffer ) : data(rerun::datatypes::TensorData(std::move(shape), std::move(buffer))) {} @@ -22,7 +22,7 @@ namespace rerun::components { /// \param shape Shape of the tensor. Determines the number of elements expected to be in `data_`. /// \param data_ Target of the pointer must outlive the archetype. template - explicit TensorData(Collection shape, const TElement* data_) + explicit TensorData(Collection shape, const TElement* data_) : data(rerun::datatypes::TensorData(std::move(shape), data_)) {} // diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 0d41f3d62a23..30807019b8a6 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -29,7 +29,6 @@ #include "datatypes/rotation_axis_angle.hpp" #include "datatypes/tensor_buffer.hpp" #include "datatypes/tensor_data.hpp" -#include "datatypes/tensor_dimension.hpp" #include "datatypes/tensor_dimension_index_selection.hpp" #include "datatypes/tensor_dimension_selection.hpp" #include "datatypes/time_int.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 46c43435cc8b..a571592c1e65 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -55,8 +55,6 @@ tensor_buffer.cpp linguist-generated=true tensor_buffer.hpp linguist-generated=true tensor_data.cpp linguist-generated=true tensor_data.hpp linguist-generated=true -tensor_dimension.cpp linguist-generated=true -tensor_dimension.hpp linguist-generated=true tensor_dimension_index_selection.cpp linguist-generated=true tensor_dimension_index_selection.hpp linguist-generated=true tensor_dimension_selection.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/tensor_data.cpp b/rerun_cpp/src/rerun/datatypes/tensor_data.cpp index dfaa17f489c0..0a53b1bec03d 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_data.cpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_data.cpp @@ -4,7 +4,6 @@ #include "tensor_data.hpp" #include "tensor_buffer.hpp" -#include "tensor_dimension.hpp" #include #include @@ -14,15 +13,8 @@ namespace rerun::datatypes {} namespace rerun { const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::struct_({ - arrow::field( - "shape", - arrow::list(arrow::field( - "item", - Loggable::arrow_datatype(), - false - )), - false - ), + arrow::field("shape", arrow::list(arrow::field("item", arrow::uint64(), false)), false), + arrow::field("names", arrow::list(arrow::field("item", arrow::utf8(), false)), true), arrow::field( "buffer", Loggable::arrow_datatype(), @@ -67,26 +59,41 @@ namespace rerun { { auto field_builder = static_cast(builder->field_builder(0)); - auto value_builder = static_cast(field_builder->value_builder()); + auto value_builder = static_cast(field_builder->value_builder()); ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); ARROW_RETURN_NOT_OK(value_builder->Reserve(static_cast(num_elements * 2))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { const auto& element = elements[elem_idx]; ARROW_RETURN_NOT_OK(field_builder->Append()); - if (element.shape.data()) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - value_builder, - element.shape.data(), - element.shape.size() - ) - ); + ARROW_RETURN_NOT_OK(value_builder->AppendValues( + element.shape.data(), + static_cast(element.shape.size()), + nullptr + )); + } + } + { + auto field_builder = static_cast(builder->field_builder(1)); + auto value_builder = static_cast(field_builder->value_builder()); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + ARROW_RETURN_NOT_OK(value_builder->Reserve(static_cast(num_elements * 1))); + + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + const auto& element = elements[elem_idx]; + if (element.names.has_value()) { + ARROW_RETURN_NOT_OK(field_builder->Append()); + for (size_t item_idx = 0; item_idx < element.names.value().size(); + item_idx += 1) { + ARROW_RETURN_NOT_OK(value_builder->Append(element.names.value()[item_idx])); + } + } else { + ARROW_RETURN_NOT_OK(field_builder->AppendNull()); } } } { - auto field_builder = static_cast(builder->field_builder(1)); + auto field_builder = static_cast(builder->field_builder(2)); ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( diff --git a/rerun_cpp/src/rerun/datatypes/tensor_data.hpp b/rerun_cpp/src/rerun/datatypes/tensor_data.hpp index b09aae93f06b..5822b81be239 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_data.hpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_data.hpp @@ -7,10 +7,11 @@ #include "../component_descriptor.hpp" #include "../result.hpp" #include "tensor_buffer.hpp" -#include "tensor_dimension.hpp" #include #include +#include +#include namespace arrow { class Array; @@ -28,8 +29,17 @@ namespace rerun::datatypes { /// These dimensions are combined with an index to look up values from the `buffer` field, /// which stores a contiguous array of typed values. struct TensorData { - /// The shape of the tensor, including optional names for each dimension. - rerun::Collection shape; + /// The shape of the tensor, i.e. the length of each dimension. + rerun::Collection shape; + + /// The names of the dimensions of the tensor (optional). + /// + /// If set, should be the same length as `datatypes::TensorData::shape`. + /// 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"]`. + std::optional> names; /// The content/data. rerun::datatypes::TensorBuffer buffer; @@ -39,9 +49,7 @@ namespace rerun::datatypes { /// /// \param shape_ Shape of the tensor. /// \param buffer_ The tensor buffer containing the tensor's data. - TensorData( - Collection shape_, datatypes::TensorBuffer buffer_ - ) + TensorData(Collection shape_, datatypes::TensorBuffer buffer_) : shape(std::move(shape_)), buffer(std::move(buffer_)) {} /// New tensor data from dimensions and pointer to tensor data. @@ -50,11 +58,11 @@ namespace rerun::datatypes { /// \param shape_ Shape of the tensor. Determines the number of elements expected to be in `data`. /// \param data Target of the pointer must outlive the archetype. template - explicit TensorData(Collection shape_, const TElement* data) + explicit TensorData(Collection shape_, const TElement* data) : shape(std::move(shape_)) { size_t num_elements = shape.empty() ? 0 : 1; for (const auto& dim : shape) { - num_elements *= dim.size; + num_elements *= dim; } buffer = rerun::Collection::borrow(data, num_elements); } diff --git a/rerun_cpp/src/rerun/datatypes/tensor_data_ext.cpp b/rerun_cpp/src/rerun/datatypes/tensor_data_ext.cpp index 2c0aa306117b..a7a6c0fda766 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_data_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_data_ext.cpp @@ -10,7 +10,7 @@ namespace rerun::datatypes { /// \param shape_ Shape of the tensor. /// \param buffer_ The tensor buffer containing the tensor's data. TensorData( - Collection shape_, datatypes::TensorBuffer buffer_ + Collection shape_, datatypes::TensorBuffer buffer_ ) : shape(std::move(shape_)), buffer(std::move(buffer_)) {} @@ -20,10 +20,10 @@ namespace rerun::datatypes { /// \param shape_ Shape of the tensor. Determines the number of elements expected to be in `data`. /// \param data Target of the pointer must outlive the archetype. template - explicit TensorData(Collection shape_, const TElement* data) : shape(std::move(shape_)) { + explicit TensorData(Collection shape_, const TElement* data) : shape(std::move(shape_)) { size_t num_elements = shape.empty() ? 0 : 1; for (const auto& dim : shape) { - num_elements *= dim.size; + num_elements *= dim; } buffer = rerun::Collection::borrow(data, num_elements); } diff --git a/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp b/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp deleted file mode 100644 index c58c45b1264a..000000000000 --- a/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs". - -#include "tensor_dimension.hpp" - -#include -#include - -namespace rerun::datatypes {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = arrow::struct_({ - arrow::field("size", arrow::uint64(), false), - arrow::field("name", arrow::utf8(), true), - }); - return datatype; - } - - Result> Loggable::to_arrow( - const datatypes::TensorDimension* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const datatypes::TensorDimension* elements, - size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - { - auto field_builder = static_cast(builder->field_builder(0)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - ARROW_RETURN_NOT_OK(field_builder->Append(elements[elem_idx].size)); - } - } - { - auto field_builder = static_cast(builder->field_builder(1)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - const auto& element = elements[elem_idx]; - if (element.name.has_value()) { - ARROW_RETURN_NOT_OK(field_builder->Append(element.name.value())); - } else { - ARROW_RETURN_NOT_OK(field_builder->AppendNull()); - } - } - } - ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); - - return Error::ok(); - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp b/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp deleted file mode 100644 index 052ff23efffd..000000000000 --- a/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs". - -#pragma once - -#include "../component_descriptor.hpp" -#include "../result.hpp" - -#include -#include -#include -#include - -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - -namespace rerun::datatypes { - /// **Datatype**: A single dimension within a multi-dimensional tensor. - struct TensorDimension { - /// The length of this dimension. - uint64_t size; - - /// The name of this dimension, e.g. "width", "height", "channel", "batch', …. - std::optional name; - - public: // START of extensions from tensor_dimension_ext.cpp: - /// Nameless dimension. - TensorDimension(size_t size_) : size(size_) {} - - /// Dimension with name. - TensorDimension(size_t size_, std::string name_) : size(size_), name(std::move(name_)) {} - - // END of extensions from tensor_dimension_ext.cpp, start of generated code: - - public: - TensorDimension() = default; - }; -} // namespace rerun::datatypes - -namespace rerun { - template - struct Loggable; - - /// \private - template <> - struct Loggable { - static constexpr ComponentDescriptor Descriptor = "rerun.datatypes.TensorDimension"; - - /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Serializes an array of `rerun::datatypes::TensorDimension` into an arrow array. - static Result> to_arrow( - const datatypes::TensorDimension* instances, size_t num_instances - ); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const datatypes::TensorDimension* elements, - size_t num_elements - ); - }; -} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_dimension_ext.cpp b/rerun_cpp/src/rerun/datatypes/tensor_dimension_ext.cpp deleted file mode 100644 index 6699700c5ae9..000000000000 --- a/rerun_cpp/src/rerun/datatypes/tensor_dimension_ext.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include "tensor_dimension.hpp" - -// #define EDIT_EXTENSION - -namespace rerun { - namespace datatypes { - -#ifdef EDIT_EXTENSION - // - - /// Nameless dimension. - TensorDimension(size_t size_) : size(size_) {} - - /// Dimension with name. - TensorDimension(size_t size_, std::string name_) : size(size_), name(std::move(name_)) {} - - // -#endif - } // namespace datatypes -} // namespace rerun diff --git a/rerun_js/web-viewer-react/README.md b/rerun_js/web-viewer-react/README.md index 361b1d63f155..3b569a57ea11 100644 --- a/rerun_js/web-viewer-react/README.md +++ b/rerun_js/web-viewer-react/README.md @@ -35,7 +35,7 @@ export default function App() { ``` The `rrd` in the snippet above should be a URL pointing to either: -- A hosted `.rrd` file, such as +- A hosted `.rrd` file, such as - A WebSocket connection to the SDK opened via the [`serve`](https://www.rerun.io/docs/reference/sdk/operating-modes#serve) API If `rrd` is not set, the Viewer will display the same welcome screen as . diff --git a/rerun_js/web-viewer-react/package.json b/rerun_js/web-viewer-react/package.json index a3f9eb5734a1..2b296ea8b714 100644 --- a/rerun_js/web-viewer-react/package.json +++ b/rerun_js/web-viewer-react/package.json @@ -1,6 +1,6 @@ { "name": "@rerun-io/web-viewer-react", - "version": "0.21.0-alpha.1+dev", + "version": "0.22.0-alpha.1+dev", "description": "Embed the Rerun web viewer in your React app", "licenses": [ { @@ -39,7 +39,7 @@ "tsconfig.json" ], "dependencies": { - "@rerun-io/web-viewer": "0.21.0-alpha.1", + "@rerun-io/web-viewer": "0.22.0-alpha.1", "@types/react": "^18.2.33", "react": "^18.2.0" }, diff --git a/rerun_js/web-viewer/README.md b/rerun_js/web-viewer/README.md index 7b714f3915a6..a9f0609f49e5 100644 --- a/rerun_js/web-viewer/README.md +++ b/rerun_js/web-viewer/README.md @@ -41,7 +41,7 @@ viewer.stop(); ``` The `rrd` in the snippet above should be a URL pointing to either: -- A hosted `.rrd` file, such as +- A hosted `.rrd` file, such as - A WebSocket connection to the SDK opened via the [`serve`](https://www.rerun.io/docs/reference/sdk/operating-modes#serve) API If `rrd` is not set, the Viewer will display the same welcome screen as . diff --git a/rerun_js/web-viewer/package.json b/rerun_js/web-viewer/package.json index 4da306e5c0a6..2ee11bf4a1dd 100644 --- a/rerun_js/web-viewer/package.json +++ b/rerun_js/web-viewer/package.json @@ -1,6 +1,6 @@ { "name": "@rerun-io/web-viewer", - "version": "0.21.0-alpha.1+dev", + "version": "0.22.0-alpha.1+dev", "description": "Embed the Rerun web viewer in your app", "licenses": [ { diff --git a/rerun_notebook/pyproject.toml b/rerun_notebook/pyproject.toml index 52105c2c8d55..23ae9bdd7ae0 100644 --- a/rerun_notebook/pyproject.toml +++ b/rerun_notebook/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "rerun-notebook" description = "Implementation helper for running rerun-sdk in notebooks" -version = "0.21.0-alpha.1+dev" +version = "0.22.0-alpha.1+dev" dependencies = ["anywidget", "jupyter-ui-poll"] readme = "README.md" keywords = ["rerun", "notebook"] diff --git a/rerun_py/README.md b/rerun_py/README.md index 92678ac6b1dc..d86ad3f7c513 100644 --- a/rerun_py/README.md +++ b/rerun_py/README.md @@ -89,3 +89,8 @@ While we try to keep the main branch usable at all times, it may be unstable occ ```sh pixi run -e py py-build && pixi run -e py py-test ``` + +# Running specific Python unit tests +```sh +pixi run -e py py-build && pixi run -e py pytest rerun_py/tests/unit/test_tensor.py +``` diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index fb430c0a825f..7c67fc68b6b0 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -33,7 +33,7 @@ text = "MIT OR Apache-2.0" [project.optional-dependencies] tests = ["pytest==7.1.2"] -notebook = ["rerun-notebook==0.21.0-alpha.1+dev"] +notebook = ["rerun-notebook==0.22.0-alpha.1+dev"] [project.urls] documentation = "https://www.rerun.io/docs" diff --git a/rerun_py/rerun_bindings/rerun_bindings.pyi b/rerun_py/rerun_bindings/rerun_bindings.pyi index 53fd6781b43f..bd046bf15069 100644 --- a/rerun_py/rerun_bindings/rerun_bindings.pyi +++ b/rerun_py/rerun_bindings/rerun_bindings.pyi @@ -3,7 +3,7 @@ from typing import Iterator, Optional, Sequence, Union import pyarrow as pa -from .types import AnyColumn, AnyComponentColumn, ComponentLike, IndexValuesLike, MetadataLike, ViewContentsLike +from .types import AnyColumn, AnyComponentColumn, ComponentLike, IndexValuesLike, TableLike, ViewContentsLike class IndexColumnDescriptor: """ @@ -581,7 +581,7 @@ class StorageNodeClient: """Get the metadata for all recordings in the storage node.""" ... - def register(self, storage_url: str, metadata: Optional[dict[str, MetadataLike]] = None) -> str: + def register(self, storage_url: str, metadata: Optional[TableLike] = None) -> str: """ Register a recording along with some metadata. @@ -589,22 +589,24 @@ class StorageNodeClient: ---------- storage_url : str The URL to the storage location. - metadata : dict[str, MetadataLike] - A dictionary where the keys are the metadata columns and the values are pyarrow arrays. + metadata : Optional[Table | RecordBatch] + A pyarrow Table or RecordBatch containing the metadata to update. + This Table must contain only a single row. """ ... - def update_catalog(self, id: str, metadata: dict[str, MetadataLike]) -> None: + def update_catalog(self, metadata: TableLike) -> None: """ - Update the metadata for the recording with the given id. + Update the catalog metadata for one or more recordings. + + The updates are provided as a pyarrow Table or RecordBatch containing the metadata to update. + The Table must contain an 'id' column, which is used to specify the recording to update for each row. Parameters ---------- - id : str - The id of the recording to update. - metadata : dict[str, MetadataLike] - A dictionary where the keys are the metadata columns and the values are pyarrow arrays. + metadata : Table | RecordBatch + A pyarrow Table or RecordBatch containing the metadata to update. """ ... diff --git a/rerun_py/rerun_bindings/types.py b/rerun_py/rerun_bindings/types.py index c5ddf94e7477..a38e70036d34 100644 --- a/rerun_py/rerun_bindings/types.py +++ b/rerun_py/rerun_bindings/types.py @@ -68,4 +68,7 @@ This can be any numpy-compatible array of integers, or a [`pa.Int64Array`][] """ -MetadataLike: TypeAlias = pa.Array +TableLike: TypeAlias = Union[pa.Table, pa.RecordBatch, pa.RecordBatchReader] +""" +A type alias for TableLike pyarrow objects. +""" diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index ffa7ac282107..f396868fbd8e 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -9,8 +9,8 @@ import numpy as np -__version__ = "0.21.0-alpha.1+dev" -__version_info__ = (0, 21, 0, "alpha.1") +__version__ = "0.22.0-alpha.1+dev" +__version_info__ = (0, 22, 0, "alpha.1") if sys.version_info < (3, 9): warnings.warn( diff --git a/rerun_py/rerun_sdk/rerun/_validators.py b/rerun_py/rerun_sdk/rerun/_validators.py index 324a0799e440..1ea9535dc2cd 100644 --- a/rerun_py/rerun_sdk/rerun/_validators.py +++ b/rerun_py/rerun_sdk/rerun/_validators.py @@ -5,7 +5,7 @@ import numpy as np import numpy.typing as npt -from ._converters import to_np_float32, to_np_float64, to_np_uint32 +from ._converters import to_np_float32, to_np_float64, to_np_uint32, to_np_uint64 # This code is a straight port from Rust. @@ -67,6 +67,13 @@ def flat_np_uint32_array_from_array_like(data: Any, dimension: int) -> npt.NDArr return flat_np_array_from_array_like(array, dimension) +def flat_np_uint64_array_from_array_like(data: Any, dimension: int) -> npt.NDArray[np.uint64]: + """Converts to a flat uint numpy array from an arbitrary vector, validating for an expected dimensionality.""" + + array = to_np_uint64(data) + return flat_np_array_from_array_like(array, dimension) + + def flat_np_array_from_array_like(array: npt.NDArray[Any], dimension: int) -> npt.NDArray[Any]: """Converts to a flat numpy array from an arbitrary vector, validating for an expected dimensionality.""" diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py index 20d1198e8b98..f066f3098749 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py @@ -21,7 +21,7 @@ def values__field_converter_override(data: TensorDataArrayLike) -> TensorDataBat # TODO(jleibs): Doing this on raw arrow data is not great. Clean this up # once we coerce to a canonical non-arrow type. - shape_dims = tensor_data.as_arrow_array()[0][0].values.field(0).to_numpy() + shape_dims = tensor_data.as_arrow_array()[0][0].values.to_numpy() if len([d for d in shape_dims if d != 1]) != 1: _send_warning_or_raise( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py index 0b8b6b679faa..d96015a93802 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py @@ -28,6 +28,40 @@ class Ellipsoids3D(Ellipsoids3DExt, Archetype): 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. + + Example + ------- + ### Covariance ellipsoid: + ```python + 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]], + ), + ) + ``` +
+ + + + + + + +
+ """ # __init__ can be found in ellipsoids3d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py index 4fa4c6017d9b..9cc648521d64 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py @@ -25,7 +25,32 @@ class GraphEdges(Archetype): By default, edges are undirected. - ⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** + Example + ------- + ### Simple directed graph: + ```python + 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"), + ) + ``` +
+ + + + + + + +
+ """ def __init__(self: Any, edges: datatypes.Utf8PairArrayLike, *, graph_type: components.GraphTypeLike | None = None): diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py index bed4372bbaad..ad23e270e2dc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py @@ -23,7 +23,32 @@ class GraphNodes(Archetype): """ **Archetype**: A list of nodes in a graph with optional labels, colors, etc. - ⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** + Example + ------- + ### Simple directed graph: + ```python + 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"), + ) + ``` +
+ + + + + + + +
+ """ def __init__( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor_ext.py index 0ee17ce0edab..14531279ff6c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor_ext.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor_ext.py @@ -18,7 +18,7 @@ def __init__( self: Any, data: TensorDataLike | TensorLike | None = None, *, - dim_names: Sequence[str | None] | None = None, + dim_names: Sequence[str] | None = None, value_range: Range1DLike | None = None, ): """ @@ -36,11 +36,11 @@ def __init__( ---------- self: The TensorData object to construct. - data: TensorDataLike | None + data: A TensorData object, or type that can be converted to a numpy array. - dim_names: Sequence[str] | None + dim_names: The names of the tensor dimensions when generating the shape from an array. - value_range: Sequence[float] | None + value_range: The range of values to use for colormapping. If not specified, the range will be estimated from the data. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py index 7d026c887d70..5804b3c0db7f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_center.py @@ -32,7 +32,9 @@ def __init__( Parameters ---------- enabled: - Whether the force is enabled. + Whether the center force is enabled. + + The center force tries to move the center of mass of the graph towards the origin. strength: The strength of the force. @@ -63,7 +65,9 @@ def _clear(cls) -> ForceCenter: default=None, converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] ) - # Whether the force is enabled. + # Whether the center force is enabled. + # + # The center force tries to move the center of mass of the graph towards the origin. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py index 80464759b93f..169c8f5e7ba0 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_collision_radius.py @@ -21,7 +21,7 @@ @define(str=False, repr=False, init=False) class ForceCollisionRadius(Archetype): - """**Archetype**: Resolves collisions between the bounding spheres, according to the radius of the nodes.""" + """**Archetype**: Resolves collisions between the bounding circles, according to the radius of the nodes.""" def __init__( self: Any, @@ -36,7 +36,9 @@ def __init__( Parameters ---------- enabled: - Whether the force is enabled. + Whether the collision force is enabled. + + The collision force resolves collisions between nodes based on the bounding circle defined by their radius. strength: The strength of the force. iterations: @@ -72,7 +74,9 @@ def _clear(cls) -> ForceCollisionRadius: default=None, converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] ) - # Whether the force is enabled. + # Whether the collision force is enabled. + # + # The collision force resolves collisions between nodes based on the bounding circle defined by their radius. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py index bf24c7265d63..f3c179715a0a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_link.py @@ -36,7 +36,9 @@ def __init__( Parameters ---------- enabled: - Whether the force is enabled. + Whether the link force is enabled. + + The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. distance: The target distance between two nodes. iterations: @@ -72,7 +74,9 @@ def _clear(cls) -> ForceLink: default=None, converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] ) - # Whether the force is enabled. + # Whether the link force is enabled. + # + # The link force aims to achieve a target distance between two nodes that are connected by one ore more edges. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py index 4750ac834505..1881af385409 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_many_body.py @@ -36,7 +36,10 @@ def __init__( Parameters ---------- enabled: - Whether the force is enabled. + Whether the many body force is enabled. + + The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. strength: The strength of the force. @@ -69,7 +72,10 @@ def _clear(cls) -> ForceManyBody: default=None, converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] ) - # Whether the force is enabled. + # Whether the many body force is enabled. + # + # The many body force is applied on each pair of nodes in a way that ressembles an electrical charge. If the + # strength is smaller than 0, it pushes nodes apart; if it is larger than 0, it pulls them together. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py index 61e63623c9c2..aa83eb92516d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/force_position.py @@ -36,7 +36,9 @@ def __init__( Parameters ---------- enabled: - Whether the force is enabled. + Whether the position force is enabled. + + The position force pulls nodes towards a specific position, similar to gravity. strength: The strength of the force. position: @@ -70,7 +72,9 @@ def _clear(cls) -> ForcePosition: default=None, converter=blueprint_components.EnabledBatch._optional, # type: ignore[misc] ) - # Whether the force is enabled. + # Whether the position force is enabled. + # + # The position force pulls nodes towards a specific position, similar to gravity. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/dataframe.py b/rerun_py/rerun_sdk/rerun/dataframe.py index b525bf1e9e81..777a962b6b72 100644 --- a/rerun_py/rerun_sdk/rerun/dataframe.py +++ b/rerun_py/rerun_sdk/rerun/dataframe.py @@ -77,7 +77,13 @@ def as_arrow_array(self) -> pa.Array: def send_record_batch(batch: pa.RecordBatch, rec: Optional[RecordingStream] = None) -> None: - """Coerce a single pyarrow `RecordBatch` to Rerun structure.""" + """ + Coerce a single pyarrow `RecordBatch` to Rerun structure. + + If this `RecordBatch` came from a call to [`RecordingView.view`][rerun.dataframe.RecordingView.view], you + will want to make sure the `view` call includes `include_indicator_columns = True` or else the + viewer will not know about the archetypes in the data. + """ indexes = [] data: defaultdict[str, list[Any]] = defaultdict(list) @@ -112,7 +118,14 @@ def send_record_batch(batch: pa.RecordBatch, rec: Optional[RecordingStream] = No def send_dataframe(df: pa.RecordBatchReader | pa.Table, rec: Optional[RecordingStream] = None) -> None: - """Coerce a pyarrow `RecordBatchReader` or `Table` to Rerun structure.""" + """ + Coerce a pyarrow `RecordBatchReader` or `Table` to Rerun structure. + + If this `Table` came from a call to [`RecordingView.view`][rerun.dataframe.RecordingView.view], you + will want to make sure the `view` call includes `include_indicator_columns = True` or else the + viewer will not know about the archetypes in the data. + + """ if isinstance(df, pa.Table): df = df.to_reader() diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index dcfe4dfeec99..c3a9b1f6cc22 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -29,7 +29,6 @@ rgba32.py linguist-generated=true rotation_axis_angle.py linguist-generated=true tensor_buffer.py linguist-generated=true tensor_data.py linguist-generated=true -tensor_dimension.py linguist-generated=true tensor_dimension_index_selection.py linguist-generated=true tensor_dimension_selection.py linguist-generated=true time_int.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 1cf1156f07c8..49397b6713b3 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -39,7 +39,6 @@ ) from .tensor_buffer import TensorBuffer, TensorBufferArrayLike, TensorBufferBatch, TensorBufferLike from .tensor_data import TensorData, TensorDataArrayLike, TensorDataBatch, TensorDataLike -from .tensor_dimension import TensorDimension, TensorDimensionArrayLike, TensorDimensionBatch, TensorDimensionLike from .tensor_dimension_index_selection import ( TensorDimensionIndexSelection, TensorDimensionIndexSelectionArrayLike, @@ -185,14 +184,10 @@ "TensorDataArrayLike", "TensorDataBatch", "TensorDataLike", - "TensorDimension", - "TensorDimensionArrayLike", - "TensorDimensionBatch", "TensorDimensionIndexSelection", "TensorDimensionIndexSelectionArrayLike", "TensorDimensionIndexSelectionBatch", "TensorDimensionIndexSelectionLike", - "TensorDimensionLike", "TensorDimensionSelection", "TensorDimensionSelectionArrayLike", "TensorDimensionSelectionBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py index fa8e1e8364a5..28e3f52c428f 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Sequence, Union +import numpy as np import numpy.typing as npt import pyarrow as pa from attrs import define, field @@ -15,6 +16,9 @@ from .._baseclasses import ( BaseBatch, ) +from .._converters import ( + to_np_uint64, +) from .tensor_data_ext import TensorDataExt __all__ = ["TensorData", "TensorDataArrayLike", "TensorDataBatch", "TensorDataLike"] @@ -46,8 +50,8 @@ class TensorData(TensorDataExt): # __init__ can be found in tensor_data_ext.py - shape: list[datatypes.TensorDimension] = field() - # The shape of the tensor, including optional names for each dimension. + shape: npt.NDArray[np.uint64] = field(converter=to_np_uint64) + # The shape of the tensor, i.e. the length of each dimension. # # (Docstring intentionally commented out to hide this field from the docs) @@ -56,6 +60,17 @@ class TensorData(TensorDataExt): # # (Docstring intentionally commented out to hide this field from the docs) + names: list[str] | None = field(default=None) + # The names of the dimensions of the tensor (optional). + # + # If set, should be the same length as [`datatypes.TensorData.shape`][rerun.datatypes.TensorData.shape]. + # 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"]`. + # + # (Docstring intentionally commented out to hide this field from the docs) + if TYPE_CHECKING: TensorDataLike = Union[TensorData, npt.ArrayLike] @@ -68,20 +83,10 @@ class TensorData(TensorDataExt): class TensorDataBatch(BaseBatch[TensorDataArrayLike]): _ARROW_DATATYPE = pa.struct([ pa.field( - "shape", - pa.list_( - pa.field( - "item", - pa.struct([ - pa.field("size", pa.uint64(), nullable=False, metadata={}), - pa.field("name", pa.utf8(), nullable=True, metadata={}), - ]), - nullable=False, - metadata={}, - ) - ), - nullable=False, - metadata={}, + "shape", pa.list_(pa.field("item", pa.uint64(), nullable=False, metadata={})), nullable=False, metadata={} + ), + pa.field( + "names", pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})), nullable=True, metadata={} ), pa.field( "buffer", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py index 5d89c7f050fe..64dd756cf60e 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py @@ -8,6 +8,7 @@ import numpy.typing as npt import pyarrow as pa +from rerun._validators import flat_np_uint64_array_from_array_like from rerun.error_utils import _send_warning_or_raise from .._unions import build_dense_union @@ -20,7 +21,7 @@ def numpy(self, force: bool) -> npt.NDArray[Any]: ... if TYPE_CHECKING: - from . import TensorBufferLike, TensorDataArrayLike, TensorDataLike, TensorDimension, TensorDimensionLike + from . import TensorBufferLike, TensorDataArrayLike, TensorDataLike TensorLike = Union[TensorDataLike, TorchTensorLike] """Type helper for a tensor-like object that can be logged to Rerun.""" @@ -48,10 +49,10 @@ class TensorDataExt: def __init__( self: Any, *, - shape: Sequence[TensorDimensionLike] | None = None, + shape: Sequence[int] | None = None, buffer: TensorBufferLike | None = None, array: TensorLike | None = None, - dim_names: Sequence[str | None] | None = None, + dim_names: Sequence[str] | None = None, ) -> None: """ Construct a `TensorData` object. @@ -64,18 +65,18 @@ def __init__( Parameters ---------- - self: TensorData + self: The TensorData object to construct. - shape: Sequence[TensorDimensionLike] | None + shape: The shape of the tensor. If None, and an array is provided, the shape will be inferred from the shape of the array. - buffer: TensorBufferLike | None + buffer: The buffer of the tensor. If None, and an array is provided, the buffer will be generated from the array. - array: Tensor | None + array: A numpy array (or The array of the tensor. If None, the array will be inferred from the buffer. - dim_names: Sequence[str] | None - The names of the tensor dimensions when generating the shape from an array. + dim_names: + The names of the tensor dimensions. """ if array is None and buffer is None: @@ -84,10 +85,8 @@ def __init__( raise ValueError("Can only provide one of 'array' or 'buffer'") if buffer is not None and shape is None: raise ValueError("If 'buffer' is provided, 'shape' is also required") - if shape is not None and dim_names is not None: - raise ValueError("Can only provide one of 'shape' or 'names'") - from . import TensorBuffer, TensorDimension + from . import TensorBuffer from .tensor_data import _tensor_data__buffer__special_field_converter_override if shape is not None: @@ -101,7 +100,7 @@ def __init__( # If a shape we provided, it must match the array if resolved_shape: - shape_tuple = tuple(d.size for d in resolved_shape) + shape_tuple = tuple(d for d in resolved_shape) if shape_tuple != array.shape: _send_warning_or_raise( ( @@ -113,21 +112,10 @@ def __init__( resolved_shape = None if resolved_shape is None: - if dim_names: - if len(array.shape) != len(dim_names): - _send_warning_or_raise( - ( - f"len(array.shape) = {len(array.shape)} != " - + f"len(dim_names) = {len(dim_names)}. Dropping tensor dimension names." - ), - 2, - ) - resolved_shape = [TensorDimension(size, name) for size, name in zip(array.shape, dim_names)] # type: ignore[arg-type] - else: - resolved_shape = [TensorDimension(size) for size in array.shape] + resolved_shape = [size for size in array.shape] if resolved_shape is not None: - self.shape = resolved_shape + self.shape: npt.NDArray[np.uint64] = resolved_shape else: # This shouldn't be possible but typing can't figure it out raise ValueError("No shape provided.") @@ -137,7 +125,20 @@ def __init__( elif array is not None: self.buffer = TensorBuffer(array.flatten()) - expected_buffer_size = prod(d.size for d in self.shape) + self.names: list[str] | None = None + if dim_names: + if len(self.shape) == len(dim_names): + self.names = dim_names + else: + _send_warning_or_raise( + ( + f"len(shape) = {len(self.shape)} != " + + f"len(dim_names) = {len(dim_names)}. Ignoring tensor dimension names." + ), + 2, + ) + + expected_buffer_size = prod(d for d in self.shape) if len(self.buffer.inner) != expected_buffer_size: raise ValueError( f"Shape and buffer size do not match. {len(self.buffer.inner)} {self.shape}->{expected_buffer_size}" @@ -166,20 +167,26 @@ def native_to_pa_array_override(data: TensorDataArrayLike, data_type: pa.DataTyp data = TensorData(array=array) # Now build the actual arrow fields - shape = _build_shape_array(data.shape).cast(data_type.field("shape").type) + shape = pa.array([flat_np_uint64_array_from_array_like(data.shape, 1)], type=data_type.field("shape").type) buffer = _build_buffer_array(data.buffer) + if data.names is None: + names = pa.array([None], type=data_type.field("names").type) + else: + names = pa.array([data.names], type=data_type.field("names").type) + return pa.StructArray.from_arrays( [ shape, + names, buffer, ], - fields=[data_type.field("shape"), data_type.field("buffer")], + fields=data_type.fields, ).cast(data_type) def numpy(self: Any, force: bool) -> npt.NDArray[Any]: """Convert the TensorData back to a numpy array.""" - dims = [d.size for d in self.shape] + dims = [d for d in self.shape] return self.buffer.inner.reshape(dims) # type: ignore[no-any-return] @@ -188,26 +195,6 @@ def numpy(self: Any, force: bool) -> npt.NDArray[Any]: ################################################################################ -def _build_shape_array(dims: list[TensorDimension]) -> pa.Array: - from . import TensorDimensionBatch - - data_type = TensorDimensionBatch._ARROW_DATATYPE - - array = np.asarray([d.size for d in dims], dtype=np.uint64).flatten() - names = pa.array([d.name for d in dims], mask=[d is None for d in dims], type=data_type.field("name").type) - - return pa.ListArray.from_arrays( - offsets=[0, len(array)], - values=pa.StructArray.from_arrays( - [ - array, - names, - ], - fields=[data_type.field("size"), data_type.field("name")], - ), - ) - - DTYPE_MAP: Final[dict[npt.DTypeLike, str]] = { np.uint8: "U8", np.uint16: "U16", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py deleted file mode 100644 index 99b1b0977ec3..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py +++ /dev/null @@ -1,71 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/store/re_types/definitions/rerun/datatypes/tensor_dimension.fbs". - -# You can extend this class by creating a "TensorDimensionExt" class in "tensor_dimension_ext.py". - -from __future__ import annotations - -from typing import Any, Sequence, Union - -import pyarrow as pa -from attrs import define, field - -from .._baseclasses import ( - BaseBatch, -) -from .._converters import ( - str_or_none, -) - -__all__ = ["TensorDimension", "TensorDimensionArrayLike", "TensorDimensionBatch", "TensorDimensionLike"] - - -@define(init=False) -class TensorDimension: - """**Datatype**: A single dimension within a multi-dimensional tensor.""" - - def __init__(self: Any, size: int, name: str | None = None): - """ - Create a new instance of the TensorDimension datatype. - - Parameters - ---------- - size: - The length of this dimension. - name: - The name of this dimension, e.g. "width", "height", "channel", "batch', …. - - """ - - # You can define your own __init__ function as a member of TensorDimensionExt in tensor_dimension_ext.py - self.__attrs_init__(size=size, name=name) - - size: int = field(converter=int) - # The length of this dimension. - # - # (Docstring intentionally commented out to hide this field from the docs) - - name: str | None = field(default=None, converter=str_or_none) - # The name of this dimension, e.g. "width", "height", "channel", "batch', …. - # - # (Docstring intentionally commented out to hide this field from the docs) - - -TensorDimensionLike = TensorDimension -TensorDimensionArrayLike = Union[ - TensorDimension, - Sequence[TensorDimensionLike], -] - - -class TensorDimensionBatch(BaseBatch[TensorDimensionArrayLike]): - _ARROW_DATATYPE = pa.struct([ - pa.field("size", pa.uint64(), nullable=False, metadata={}), - pa.field("name", pa.utf8(), nullable=True, metadata={}), - ]) - - @staticmethod - def _native_to_pa_array(data: TensorDimensionArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of TensorDimension not implemented: We lack codegen for arrow-serialization of general structs" - ) # You need to implement native_to_pa_array_override in tensor_dimension_ext.py diff --git a/rerun_py/src/remote.rs b/rerun_py/src/remote.rs index a74f3a1a0666..2619d3990088 100644 --- a/rerun_py/src/remote.rs +++ b/rerun_py/src/remote.rs @@ -1,11 +1,12 @@ #![allow(unsafe_op_in_unsafe_fn)] use arrow::{ - array::{ArrayData, RecordBatch, RecordBatchIterator, RecordBatchReader}, + array::{RecordBatch, RecordBatchIterator, RecordBatchReader}, datatypes::Schema, + ffi_stream::ArrowArrayStreamReader, pyarrow::PyArrowType, }; // False positive due to #[pyfunction] macro -use pyo3::{exceptions::PyRuntimeError, prelude::*, types::PyDict, Bound, PyResult}; +use pyo3::{exceptions::PyRuntimeError, prelude::*, Bound, PyResult}; use re_chunk::{Chunk, TransportChunk}; use re_chunk_store::ChunkStore; use re_dataframe::ChunkStoreHandle; @@ -134,17 +135,14 @@ impl PyStorageNodeClient { /// ---------- /// storage_url : str /// The URL to the storage location. - /// metadata : dict[str, MetadataLike] - /// A dictionary where the keys are the metadata columns and the values are pyarrow arrays. + /// metadata : Optional[Table | RecordBatch] + /// A pyarrow Table or RecordBatch containing the metadata to update. + /// This Table must contain only a single row. #[pyo3(signature = ( storage_url, metadata = None ))] - fn register( - &mut self, - storage_url: &str, - metadata: Option<&Bound<'_, PyDict>>, - ) -> PyResult { + fn register(&mut self, storage_url: &str, metadata: Option) -> PyResult { self.runtime.block_on(async { let storage_url = url::Url::parse(storage_url) .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; @@ -152,51 +150,32 @@ impl PyStorageNodeClient { let _obj = object_store::ObjectStoreScheme::parse(&storage_url) .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; - let payload = metadata + let metadata = metadata .map(|metadata| { - let (schema, data): ( - Vec, - Vec>, - ) = metadata - .iter() - .map(|(key, value)| { - let key = key.to_string(); - let value = value.extract::()?; - let value_array = value.to_arrow2()?; - let field = arrow2::datatypes::Field::new( - key, - value_array.data_type().clone(), - true, - ); - Ok((field, value_array)) - }) - .collect::>>()? - .into_iter() - .unzip(); - - let schema = arrow2::datatypes::Schema::from(schema); - let data = arrow2::chunk::Chunk::new(data); - - let metadata_tc = TransportChunk { - schema: schema.clone(), - data, - }; + let metadata = metadata.into_record_batch()?; + + if metadata.num_rows() != 1 { + return Err(PyRuntimeError::new_err( + "Metadata must contain exactly one row", + )); + } + + let metadata_tc = TransportChunk::from_arrow_record_batch(&metadata); encode(EncoderVersion::V0, metadata_tc) .map_err(|err| PyRuntimeError::new_err(err.to_string())) }) .transpose()? - // TODO(zehiko) this is going away soon - .ok_or(PyRuntimeError::new_err("No metadata"))?; + .map(|payload| DataframePart { + encoder_version: EncoderVersion::V0 as i32, + payload, + }); let request = RegisterRecordingRequest { // TODO(jleibs): Description should really just be in the metadata description: Default::default(), storage_url: storage_url.to_string(), - metadata: Some(DataframePart { - encoder_version: EncoderVersion::V0 as i32, - payload, - }), + metadata, typ: RecordingType::Rrd.into(), }; @@ -226,48 +205,33 @@ impl PyStorageNodeClient { }) } - /// Update the metadata for the recording with the given id. + /// Update the catalog metadata for one or more recordings. + /// + /// The updates are provided as a pyarrow Table or RecordBatch containing the metadata to update. + /// The Table must contain an 'id' column, which is used to specify the recording to update for each row. /// /// Parameters /// ---------- - /// id : str - /// The id of the recording to update. - /// metadata : dict[str, MetadataLike] - /// A dictionary where the keys are the metadata columns and the values are pyarrow arrays. + /// metadata : Table | RecordBatch + /// A pyarrow Table or RecordBatch containing the metadata to update. #[pyo3(signature = ( - id, metadata ))] - fn update_catalog(&mut self, id: &str, metadata: &Bound<'_, PyDict>) -> PyResult<()> { + #[allow(clippy::needless_pass_by_value)] + fn update_catalog(&mut self, metadata: MetadataLike) -> PyResult<()> { self.runtime.block_on(async { - let (schema, data): ( - Vec, - Vec>, - ) = metadata - .iter() - .map(|(key, value)| { - let key = key.to_string(); - let value = value.extract::()?; - let value_array = value.to_arrow2()?; - let field = - arrow2::datatypes::Field::new(key, value_array.data_type().clone(), true); - Ok((field, value_array)) - }) - .collect::>>()? - .into_iter() - .unzip(); + let metadata = metadata.into_record_batch()?; - let schema = arrow2::datatypes::Schema::from(schema); - - let data = arrow2::chunk::Chunk::new(data); + // TODO(jleibs): This id name should probably come from `re_protos` + if metadata.schema().column_with_name("id").is_none() { + return Err(PyRuntimeError::new_err( + "Metadata must contain an 'id' column", + )); + } - let metadata_tc = TransportChunk { - schema: schema.clone(), - data, - }; + let metadata_tc = TransportChunk::from_arrow_record_batch(&metadata); let request = UpdateCatalogRequest { - recording_id: Some(RecordingId { id: id.to_owned() }), metadata: Some(DataframePart { encoder_version: EncoderVersion::V0 as i32, payload: encode(EncoderVersion::V0, metadata_tc) @@ -363,39 +327,23 @@ impl PyStorageNodeClient { /// A type alias for metadata. #[derive(FromPyObject)] enum MetadataLike { - PyArrow(PyArrowType), - // TODO(jleibs): Support converting other primitives + RecordBatch(PyArrowType), + Reader(PyArrowType), } impl MetadataLike { - fn to_arrow2(&self) -> PyResult> { - match self { - Self::PyArrow(array) => { - let array = arrow2::array::from_data(&array.0); - if array.len() == 1 { - Ok(array) - } else { - Err(PyRuntimeError::new_err( - "Metadata must be a single array, not a list", - )) - } - } - } - } - - #[allow(dead_code)] - fn to_arrow(&self) -> PyResult> { - match self { - Self::PyArrow(array) => { - let array = arrow::array::make_array(array.0.clone()); - if array.len() == 1 { - Ok(array) - } else { - Err(PyRuntimeError::new_err( - "Metadata must be a single array, not a list", - )) - } - } - } + fn into_record_batch(self) -> PyResult { + let (schema, batches) = match self { + Self::RecordBatch(record_batch) => (record_batch.0.schema(), vec![record_batch.0]), + Self::Reader(reader) => ( + reader.0.schema(), + reader.0.collect::, _>>().map_err(|err| { + PyRuntimeError::new_err(format!("Failed to read RecordBatches: {err}")) + })?, + ), + }; + + arrow::compute::concat_batches(&schema, &batches) + .map_err(|err| PyRuntimeError::new_err(err.to_string())) } } diff --git a/rerun_py/tests/unit/test_tensor.py b/rerun_py/tests/unit/test_tensor.py index 34dbf4ab6923..b55f1d0ec3b2 100644 --- a/rerun_py/tests/unit/test_tensor.py +++ b/rerun_py/tests/unit/test_tensor.py @@ -6,7 +6,7 @@ import pytest import rerun as rr from rerun.components import TensorData, TensorDataBatch -from rerun.datatypes import TensorBuffer, TensorDataLike, TensorDimension +from rerun.datatypes import TensorBuffer, TensorDataLike rng = np.random.default_rng(12345) RANDOM_TENSOR_SOURCE = rng.uniform(0.0, 1.0, (8, 6, 3, 5)) @@ -15,12 +15,8 @@ TENSOR_DATA_INPUTS: list[TensorDataLike] = [ # Full explicit construction TensorData( - shape=[ - TensorDimension(8, name="a"), - TensorDimension(6, name="b"), - TensorDimension(3, name="c"), - TensorDimension(5, name="d"), - ], + shape=[8, 6, 3, 5], + dim_names=["a", "b", "c", "d"], buffer=TensorBuffer(RANDOM_TENSOR_SOURCE), ), # Implicit construction from ndarray @@ -33,14 +29,15 @@ TensorData(array=RANDOM_TENSOR_SOURCE, dim_names=["a", "b", "c", "d"]), ] -# 0 = shape -# 1 = buffer +SHAPE = 0 # Based on datatypes/tensor_data.fbs +NAMES = 1 # Based on datatypes/tensor_data.fbs +BUFFER = 2 # Based on datatypes/tensor_data.fbs CHECK_FIELDS: list[list[int]] = [ - [0, 1], - [1], - [1], - [0, 1], - [0, 1], + [SHAPE, NAMES, BUFFER], + [BUFFER], + [BUFFER], + [SHAPE, NAMES, BUFFER], + [SHAPE, NAMES, BUFFER], ] @@ -87,12 +84,8 @@ def test_bad_tensors() -> None: # Wrong size buffer for dimensions with pytest.raises(ValueError): TensorData( - shape=[ - TensorDimension(8, name="a"), - TensorDimension(6, name="b"), - TensorDimension(3, name="c"), - TensorDimension(4, name="d"), - ], + shape=[1, 2, 3], + dim_names=["a", "b", "c", "d"], buffer=RANDOM_TENSOR_SOURCE, ) @@ -108,11 +101,7 @@ def test_bad_tensors() -> None: # Shape disagrees with array with pytest.raises(ValueError): TensorData( - shape=[ - TensorDimension(8, name="a"), - TensorDimension(6, name="b"), - TensorDimension(5, name="c"), - TensorDimension(3, name="d"), - ], + shape=[1, 2, 3], + dim_names=["a", "b", "c", "d"], array=RANDOM_TENSOR_SOURCE, ) diff --git a/rust-toolchain b/rust-toolchain index 38e5e90f3acf..0eefd31bc5a3 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -5,6 +5,6 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "1.80.0" +channel = "1.81.0" components = ["rustfmt", "clippy"] targets = ["wasm32-unknown-unknown"] diff --git a/scripts/check_env.py b/scripts/check_env.py index 66c6cdd9854d..c93375c3fc3b 100644 --- a/scripts/check_env.py +++ b/scripts/check_env.py @@ -7,8 +7,8 @@ import subprocess PIXI_VERSION = "0.39.0" -CARGO_VERSION = "1.80.0" -RUST_VERSION = "1.80.0" +CARGO_VERSION = "1.81.0" +RUST_VERSION = "1.81.0" def check_version(cmd: str, expected: str, update: str, install: str) -> bool: diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py index 89079fe39e3d..e4e818286d0a 100755 --- a/scripts/ci/crates.py +++ b/scripts/ci/crates.py @@ -434,7 +434,7 @@ def publish_crate(crate: Crate, token: str, version: str, env: dict[str, Any]) - while True: try: cargo( - f"publish --quiet --token {token}", + f"publish --quiet --locked --token {token}", cwd=crate.path, env=env, dry_run=False, diff --git a/scripts/clippy_wasm/clippy.toml b/scripts/clippy_wasm/clippy.toml index 1db82f4f0cec..34291cb025f6 100644 --- a/scripts/clippy_wasm/clippy.toml +++ b/scripts/clippy_wasm/clippy.toml @@ -6,7 +6,7 @@ # ----------------------------------------------------------------------------- # Section identical to the main clippy.toml: -msrv = "1.80" +msrv = "1.81" allow-unwrap-in-tests = true diff --git a/scripts/generate_changelog.py b/scripts/generate_changelog.py index 40556952af3d..61c58a418e0d 100755 --- a/scripts/generate_changelog.py +++ b/scripts/generate_changelog.py @@ -29,6 +29,7 @@ "abey79", "emilk", "gavrelina", + "grtlr", "jleibs", "jprochazk", "nikolausWest", diff --git a/scripts/lint.py b/scripts/lint.py index f99428e69a89..f9ba2ed823ea 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -619,7 +619,7 @@ def test_lint_workspace_deps() -> None: name = "clock" version = "0.6.0-alpha.0" edition = "2021" - rust-version = "1.80" + rust-version = "1.81" license = "MIT OR Apache-2.0" publish = false diff --git a/tests/cpp/roundtrips/tensor/main.cpp b/tests/cpp/roundtrips/tensor/main.cpp index c1a218349a5f..98d367454b74 100644 --- a/tests/cpp/roundtrips/tensor/main.cpp +++ b/tests/cpp/roundtrips/tensor/main.cpp @@ -8,10 +8,10 @@ int main(int, char** argv) { const auto rec = rerun::RecordingStream("rerun_example_roundtrip_tensor"); rec.save(argv[1]).exit_on_failure(); - std::vector dimensions{{3, 4, 5, 6}}; + std::vector shape{{3, 4, 5, 6}}; std::vector data(360); std::generate(data.begin(), data.end(), [n = 0]() mutable { return n++; }); - rec.log("tensor", rerun::archetypes::Tensor(rerun::datatypes::TensorData{dimensions, data})); + rec.log("tensor", rerun::archetypes::Tensor(rerun::datatypes::TensorData{shape, data})); } diff --git a/tests/python/release_checklist/README.md b/tests/python/release_checklist/README.md index ec710d70a2cf..d41559405ab9 100644 --- a/tests/python/release_checklist/README.md +++ b/tests/python/release_checklist/README.md @@ -3,12 +3,6 @@ # Interactive release checklist Welcome to the release checklist. -_**⚠ Make sure to clean your blueprints if you want to start from a clean slate ⚠**_ - -``` -pixi run rerun reset -``` - Run the testlist with: ``` pixi run -e examples python tests/python/release_checklist/main.py diff --git a/tests/python/release_checklist/check_1d_tensor_data.py b/tests/python/release_checklist/check_1d_tensor_data.py index ae418182e979..2e7aa43ad5cc 100644 --- a/tests/python/release_checklist/check_1d_tensor_data.py +++ b/tests/python/release_checklist/check_1d_tensor_data.py @@ -50,6 +50,8 @@ def run(args: Namespace) -> None: log_readme() log_1d_data() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_all_components_ui.py b/tests/python/release_checklist/check_all_components_ui.py index 0849f5983c8b..2819ee163442 100644 --- a/tests/python/release_checklist/check_all_components_ui.py +++ b/tests/python/release_checklist/check_all_components_ui.py @@ -218,7 +218,7 @@ def alternatives(self) -> list[Any] | None: rr.datatypes.TensorData(array=np.random.randint(0, 255, (5, 3, 6, 4), dtype=np.uint8)), rr.datatypes.TensorData( array=np.random.randint(0, 255, (5, 3, 6, 4), dtype=np.uint8), - dim_names=[None, "hello", None, "world"], + dim_names=["hello", "brave", "new", "world"], ), rr.datatypes.TensorData(array=np.random.randint(0, 255, (5, 3, 6, 4, 3), dtype=np.uint8)), ] @@ -299,6 +299,8 @@ def run(args: Namespace) -> None: log_readme() log_some_views() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_annotations.py b/tests/python/release_checklist/check_annotations.py index 3e8ff3f8012b..a63db849ce91 100644 --- a/tests/python/release_checklist/check_annotations.py +++ b/tests/python/release_checklist/check_annotations.py @@ -55,6 +55,8 @@ def run(args: Namespace) -> None: log_readme() log_annotations() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_bgr.py b/tests/python/release_checklist/check_bgr.py index f1316e5c0504..8011e6692ff9 100644 --- a/tests/python/release_checklist/check_bgr.py +++ b/tests/python/release_checklist/check_bgr.py @@ -75,7 +75,8 @@ def download_example_image_as_rgb() -> np.ndarray: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) sample_image_rgb_u8 = download_example_image_as_rgb() log_readme() diff --git a/tests/python/release_checklist/check_blueprint_bw_compat.py b/tests/python/release_checklist/check_blueprint_bw_compat.py index dabc4fff1e5d..ee67012b93f5 100644 --- a/tests/python/release_checklist/check_blueprint_bw_compat.py +++ b/tests/python/release_checklist/check_blueprint_bw_compat.py @@ -54,12 +54,9 @@ def log_readme() -> None: def run(args: Namespace) -> None: - rr.script_setup( - args, - f"{os.path.basename(__file__)}", - recording_id=uuid4(), - default_blueprint=rrb.Grid(rrb.TextDocumentView(origin="readme")), - ) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + rr.send_blueprint(rrb.Grid(rrb.TextDocumentView(origin="readme")), make_active=True, make_default=True) log_readme() diff --git a/tests/python/release_checklist/check_blueprint_overrides.py b/tests/python/release_checklist/check_blueprint_overrides.py index 8fe9f5a91f6e..d09472cf39f6 100644 --- a/tests/python/release_checklist/check_blueprint_overrides.py +++ b/tests/python/release_checklist/check_blueprint_overrides.py @@ -34,26 +34,6 @@ def log_plots() -> None: cos_of_t = cos(float(t) / 10.0) rr.log("plots/cos", rr.Scalar(cos_of_t)) - rr.send_blueprint( - rrb.Blueprint( - rrb.Grid( - rrb.TextDocumentView(origin="readme", name="Instructions"), - rrb.TimeSeriesView( - name="Plots", - defaults=[rr.components.Color([0, 0, 255])], - overrides={ - "plots/cos": [ - rrb.VisualizerOverrides("SeriesPoint"), - rr.components.Color([0, 255, 0]), - # TODDO(#6670): This should just be `rr.components.MarkerShape.Cross` - rr.components.MarkerShapeBatch("cross"), - ], - }, - ), - ) - ) - ) - def run(args: Namespace) -> None: rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) @@ -61,6 +41,25 @@ def run(args: Namespace) -> None: log_readme() log_plots() + blueprint = rrb.Blueprint( + rrb.Grid( + rrb.TextDocumentView(origin="readme", name="Instructions"), + rrb.TimeSeriesView( + name="Plots", + defaults=[rr.components.Color([0, 0, 255])], + overrides={ + "plots/cos": [ + rrb.VisualizerOverrides("SeriesPoint"), + rr.components.Color([0, 255, 0]), + # TODDO(#6670): This should just be `rr.components.MarkerShape.Cross` + rr.components.MarkerShapeBatch("cross"), + ], + }, + ), + ) + ) + rr.send_blueprint(blueprint, make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_chroma_subsampling.py b/tests/python/release_checklist/check_chroma_subsampling.py index c072c57a995e..cb321b1e1807 100644 --- a/tests/python/release_checklist/check_chroma_subsampling.py +++ b/tests/python/release_checklist/check_chroma_subsampling.py @@ -220,7 +220,8 @@ def log_data() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_data() diff --git a/tests/python/release_checklist/check_colormap_edit_ui.py b/tests/python/release_checklist/check_colormap_edit_ui.py index 7d7279469cd7..f022c49cdafb 100644 --- a/tests/python/release_checklist/check_colormap_edit_ui.py +++ b/tests/python/release_checklist/check_colormap_edit_ui.py @@ -35,7 +35,8 @@ def blueprint() -> rrb.BlueprintLike: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_depth_image() diff --git a/tests/python/release_checklist/check_component_and_transform_clamping.py b/tests/python/release_checklist/check_component_and_transform_clamping.py index cfabe06a2fb2..66f6c832d99b 100644 --- a/tests/python/release_checklist/check_component_and_transform_clamping.py +++ b/tests/python/release_checklist/check_component_and_transform_clamping.py @@ -73,7 +73,8 @@ def log_data() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_data() diff --git a/tests/python/release_checklist/check_container_hierarchy.py b/tests/python/release_checklist/check_container_hierarchy.py index 90150e3c6514..b602b0a2c422 100644 --- a/tests/python/release_checklist/check_container_hierarchy.py +++ b/tests/python/release_checklist/check_container_hierarchy.py @@ -91,6 +91,8 @@ def run(args: Namespace) -> None: log_readme() log_some_views() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index 2bd104a8927a..ee01607dcac6 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -58,7 +58,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py index ee1d9d74ffa8..05d378b7e522 100644 --- a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py +++ b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py @@ -51,7 +51,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py index 9a32db71f704..670f3118b68f 100644 --- a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -46,7 +46,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index 8864588a4fd4..7c42f59bbc8e 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -83,7 +83,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index 14f7d5180281..5b9a3a9aca54 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -109,7 +109,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index 4b5ab7a340f1..bcf310ca2fda 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -85,7 +85,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index 02c120940bdb..a0b4933f8def 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -76,7 +76,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_deselect_on_escape.py b/tests/python/release_checklist/check_deselect_on_escape.py index e74698bc9656..dd86cfeb7fa8 100644 --- a/tests/python/release_checklist/check_deselect_on_escape.py +++ b/tests/python/release_checklist/check_deselect_on_escape.py @@ -38,6 +38,8 @@ def run(args: Namespace) -> None: log_readme() log_some_data() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_drag_and_drop_selection.py b/tests/python/release_checklist/check_drag_and_drop_selection.py index 2ca4d7ee9b82..1c1f90ce5fcc 100644 --- a/tests/python/release_checklist/check_drag_and_drop_selection.py +++ b/tests/python/release_checklist/check_drag_and_drop_selection.py @@ -63,7 +63,8 @@ def log_some_scalar_entities() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_scalar_entities() diff --git a/tests/python/release_checklist/check_draw_order.py b/tests/python/release_checklist/check_draw_order.py index df6ed675cbd0..87e397d6bf48 100644 --- a/tests/python/release_checklist/check_draw_order.py +++ b/tests/python/release_checklist/check_draw_order.py @@ -71,11 +71,11 @@ def run_2d_layering() -> None: def run(args: Namespace) -> None: - rr.script_setup( - args, - f"{os.path.basename(__file__)}", - recording_id=uuid4(), - default_blueprint=rrb.Grid(rrb.Spatial2DView(origin="/"), rrb.TextDocumentView(origin="readme")), + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint( + rrb.Blueprint(rrb.Grid(rrb.Spatial2DView(origin="/"), rrb.TextDocumentView(origin="readme"))), + make_active=True, + make_default=True, ) log_readme() diff --git a/tests/python/release_checklist/check_entity_drag_and_drop.py b/tests/python/release_checklist/check_entity_drag_and_drop.py index 0e9d718064dd..85439d8cf03b 100644 --- a/tests/python/release_checklist/check_entity_drag_and_drop.py +++ b/tests/python/release_checklist/check_entity_drag_and_drop.py @@ -79,7 +79,8 @@ def log_some_scalar_entities() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_scalar_entities() diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index 91c25335f0e7..2bdbe82ce447 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -42,7 +42,8 @@ def log_some_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_some_views() diff --git a/tests/python/release_checklist/check_graph_view.py b/tests/python/release_checklist/check_graph_view.py index 97e9964394bd..4998792806e9 100644 --- a/tests/python/release_checklist/check_graph_view.py +++ b/tests/python/release_checklist/check_graph_view.py @@ -15,6 +15,7 @@ * `graph` has directed edges, while `graph2` has undirected edges. * `graph` and `graph2` are shown in two different viewers. * There is a third viewer, `Both`, that shows both `graph` and `graph2` in the same viewer. +* The `coincident` viewer shows two nodes, `A` and `B`, at the same position """ @@ -22,6 +23,10 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) +def log_coincident_nodes() -> None: + rr.log("coincident", rr.GraphNodes(["A", "B"], labels=["A", "B"], positions=[[-150, 0], [150, 0]])) + + def log_graphs() -> None: DATA = [ ("A", None), @@ -51,16 +56,22 @@ def run(args: Namespace) -> None: log_readme() log_graphs() + log_coincident_nodes() rr.send_blueprint( - rrb.Blueprint( - rrb.Grid( - rrb.GraphView(origin="graph", name="Graph 1"), - rrb.GraphView(origin="graph2", name="Graph 2"), - rrb.GraphView(name="Both", contents=["/graph", "/graph2"]), - rrb.TextDocumentView(origin="readme", name="Instructions"), - ) - ) + rrb.Grid( + rrb.GraphView(origin="graph", name="Graph 1"), + rrb.GraphView(origin="graph2", name="Graph 2"), + rrb.GraphView(name="Both", contents=["/graph", "/graph2"]), + rrb.GraphView( + origin="coincident", + name="Coincident nodes", + overrides={"coincident": [rr.components.Position2D([0, 0])]}, + ), + rrb.TextDocumentView(origin="readme", name="Instructions"), + ), + make_default=True, + make_active=True, ) diff --git a/tests/python/release_checklist/check_graph_view_multi_self_edges.py b/tests/python/release_checklist/check_graph_view_multi_self_edges.py index 8b43cac93fc0..bef301ff7c23 100644 --- a/tests/python/release_checklist/check_graph_view_multi_self_edges.py +++ b/tests/python/release_checklist/check_graph_view_multi_self_edges.py @@ -55,17 +55,17 @@ def run(args: Namespace) -> None: log_readme() rr.send_blueprint( - rrb.Blueprint( - rrb.Grid( - rrb.GraphView(origin="graph", name="Multiple edges and self-edges"), - rrb.GraphView( - origin="graph", - name="Multiple edges and self-edges (without labels)", - defaults=[rr.components.ShowLabels(False)], - ), - rrb.TextDocumentView(origin="readme", name="Instructions"), - ) - ) + rrb.Grid( + rrb.GraphView(origin="graph", name="Multiple edges and self-edges"), + rrb.GraphView( + origin="graph", + name="Multiple edges and self-edges (without labels)", + defaults=[rr.components.ShowLabels(False)], + ), + rrb.TextDocumentView(origin="readme", name="Instructions"), + ), + make_active=True, + make_default=True, ) diff --git a/tests/python/release_checklist/check_heuristics_2d.py b/tests/python/release_checklist/check_heuristics_2d.py index a951d05bec2f..96549cbf06ea 100644 --- a/tests/python/release_checklist/check_heuristics_2d.py +++ b/tests/python/release_checklist/check_heuristics_2d.py @@ -70,6 +70,8 @@ def run(args: Namespace) -> None: log_readme() log_images() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py b/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py index ba151b266d41..18ee34985583 100644 --- a/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py +++ b/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py @@ -56,6 +56,8 @@ def run(args: Namespace) -> None: log_images() log_3d_scene() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_heuristics_mixed_all_root.py b/tests/python/release_checklist/check_heuristics_mixed_all_root.py index 5b90b33e876a..38c2e1cbf12b 100644 --- a/tests/python/release_checklist/check_heuristics_mixed_all_root.py +++ b/tests/python/release_checklist/check_heuristics_mixed_all_root.py @@ -29,6 +29,8 @@ def run(args: Namespace) -> None: rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"])) rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_hover_select_reset.py b/tests/python/release_checklist/check_hover_select_reset.py index a83560ba7150..abcc498bac10 100644 --- a/tests/python/release_checklist/check_hover_select_reset.py +++ b/tests/python/release_checklist/check_hover_select_reset.py @@ -11,9 +11,6 @@ This checks whether different UIs behave correctly with hover and selection. -Known bugs: -* TODO(#5138): Hovering over text document views does not highlight the corresponding entity in the blueprint tree. - ### Hover For each of the views: * Hover the view and verify it shows up as highlighted in the blueprint tree. @@ -108,6 +105,8 @@ def run(args: Namespace) -> None: log_graph() log_map() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_latest_at_partial_updates.py b/tests/python/release_checklist/check_latest_at_partial_updates.py index 18d25bdbb82c..13bf39d61437 100644 --- a/tests/python/release_checklist/check_latest_at_partial_updates.py +++ b/tests/python/release_checklist/check_latest_at_partial_updates.py @@ -65,10 +65,6 @@ def blueprint() -> rrb.BlueprintLike: ), ] ), - # NOTE: It looks nice but it's very annoying when going through several checklists. - # rrb.BlueprintPanel(state="collapsed"), - # rrb.TimePanel(state="collapsed"), - # rrb.SelectionPanel(state="collapsed"), ) @@ -119,7 +115,7 @@ def log_points() -> None: def run(args: Namespace) -> None: rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) - rr.send_blueprint(blueprint()) + rr.send_blueprint(blueprint(), make_default=True, make_active=True) log_readme() log_points() diff --git a/tests/python/release_checklist/check_modal_scrolling.py b/tests/python/release_checklist/check_modal_scrolling.py new file mode 100644 index 000000000000..bfb7e61df626 --- /dev/null +++ b/tests/python/release_checklist/check_modal_scrolling.py @@ -0,0 +1,50 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr +import rerun.blueprint as rrb + +README = """\ +# Modal scrolling + +* Select the 2D view +* Open the Entity Path Filter modal +* Make sure it behaves properly, including scrolling +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_many_entities() -> None: + for i in range(0, 1000): + rr.log(f"points/{i}", rr.Points2D([(i, i)])) + + +def run(args: Namespace) -> None: + rr.script_setup( + args, + f"{os.path.basename(__file__)}", + recording_id=uuid4(), + ) + rr.send_blueprint( + rrb.Grid(rrb.Spatial2DView(origin="/"), rrb.TextDocumentView(origin="readme")), + make_active=True, + make_default=True, + ) + + log_readme() + log_many_entities() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_mono_entity_views.py b/tests/python/release_checklist/check_mono_entity_views.py index 90a45b40b821..b5c242635ee1 100644 --- a/tests/python/release_checklist/check_mono_entity_views.py +++ b/tests/python/release_checklist/check_mono_entity_views.py @@ -44,7 +44,8 @@ def blueprint() -> rrb.BlueprintLike: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_data() diff --git a/tests/python/release_checklist/check_multi_entity_drag_and_drop.py b/tests/python/release_checklist/check_multi_entity_drag_and_drop.py new file mode 100644 index 000000000000..e541458b3881 --- /dev/null +++ b/tests/python/release_checklist/check_multi_entity_drag_and_drop.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import numpy as np +import rerun as rr +import rerun.blueprint as rrb + +README = """\ +# Multi-entity drag-and-drop + +This test checks that dragging multiple entities to a view correctly adds all entities. + +1. Multi-select `cos_curve` and `line_curve` entities in the streams tree. +2. Drag them to the PLOT view. +3. _Expect_: both entities are visible in the plot view and each are listed in the view's entity path filter. +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) + + +def blueprint() -> rrb.BlueprintLike: + return rrb.Vertical( + rrb.TextDocumentView(origin="readme"), + rrb.TimeSeriesView(origin="/", contents=[], name="PLOT"), + ) + + +def log_some_scalar_entities() -> None: + times = np.arange(100) + curves = [ + ("cos_curve", np.cos(times / 100 * 2 * np.pi)), + ("line_curve", times / 100 + 0.2), + ] + + time_column = rr.TimeSequenceColumn("frame", times) + + for path, curve in curves: + rr.send_columns(path, times=[time_column], components=[rr.components.ScalarBatch(curve)]) + + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_default=True, make_active=True) + + log_readme() + log_some_scalar_entities() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_notebook.py b/tests/python/release_checklist/check_notebook.py index 978acd0c2932..42612295067d 100644 --- a/tests/python/release_checklist/check_notebook.py +++ b/tests/python/release_checklist/check_notebook.py @@ -23,8 +23,8 @@ def run(args: Namespace) -> None: args, f"{os.path.basename(__file__)}", recording_id=uuid4(), - default_blueprint=rrb.Grid(rrb.TextDocumentView(origin="readme")), ) + rr.send_blueprint(rrb.Grid(rrb.TextDocumentView(origin="readme")), make_active=True, make_default=True) log_readme() diff --git a/tests/python/release_checklist/check_out_of_tree_data_results.py b/tests/python/release_checklist/check_out_of_tree_data_results.py index 99f1edf440c7..e1d71272f26c 100644 --- a/tests/python/release_checklist/check_out_of_tree_data_results.py +++ b/tests/python/release_checklist/check_out_of_tree_data_results.py @@ -38,7 +38,8 @@ def log_data() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_data() diff --git a/tests/python/release_checklist/check_overrides_2d.py b/tests/python/release_checklist/check_overrides_2d.py index d8dc0c24de94..64ef757769e4 100644 --- a/tests/python/release_checklist/check_overrides_2d.py +++ b/tests/python/release_checklist/check_overrides_2d.py @@ -67,6 +67,13 @@ def log_boxes() -> None: rr.Arrows2D(origins=[[-2.0, 0.0], [0.0, 0.0], [2.0, 0.0]], vectors=[[-2.0, 1.0], [0.0, 2.0], [2.0, 1.0]]), ) + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_boxes() + visual_bounds = rrb.VisualBounds2D(x_range=[-5.5, 5.5], y_range=[-3.0, 3.0]) overrides = { "arrows": [ @@ -87,68 +94,58 @@ def log_boxes() -> None: rr.components.TextBatch(["TeenyYellow", "AverageCyan", "GigaPurple"]), ] - rr.send_blueprint( - rrb.Blueprint( - rrb.Grid( - rrb.TextDocumentView(origin="readme", name="Instructions"), - rrb.Vertical( - rrb.Spatial2DView( - name="1) Overrides, logged values & defaults", - visual_bounds=visual_bounds, - overrides=overrides, - defaults=defaults, - ), - rrb.Spatial2DView( - name="2) Logged values & defaults", - visual_bounds=visual_bounds, - defaults=defaults, - ), - rrb.Spatial2DView( - name="3) Logged values only", - visual_bounds=visual_bounds, - ), + blueprint = rrb.Blueprint( + rrb.Grid( + rrb.TextDocumentView(origin="readme", name="Instructions"), + rrb.Vertical( + rrb.Spatial2DView( + name="1) Overrides, logged values & defaults", + visual_bounds=visual_bounds, + overrides=overrides, + defaults=defaults, + ), + rrb.Spatial2DView( + name="2) Logged values & defaults", + visual_bounds=visual_bounds, + defaults=defaults, ), - rrb.Vertical( - rrb.Spatial2DView( - name="What you should get after removing overrides from 1)", - visual_bounds=visual_bounds, - defaults=defaults, - ), - rrb.Spatial2DView( - name="What you should get after removing defaults from 2)", - visual_bounds=visual_bounds, - ), - rrb.Spatial2DView( - name="What you should get after adding overrides & defaults to 3)", - visual_bounds=visual_bounds, - overrides={ - "arrows": [ - rrb.VisualizerOverrides([ - rrb.visualizers.Arrows2D, - rrb.visualizers.Points2D, - ]), - rr.components.Color([255, 255, 255]), - rr.components.Radius(0.1), - rr.components.Text("Cerberus"), - rr.components.Position2D([0.0, 0.0]), - ] - }, - ), + rrb.Spatial2DView( + name="3) Logged values only", + visual_bounds=visual_bounds, ), - grid_columns=3, - column_shares=[1, 1, 1], ), - rrb.BlueprintPanel(state="collapsed"), - rrb.TimePanel(state="collapsed"), - ) + rrb.Vertical( + rrb.Spatial2DView( + name="What you should get after removing overrides from 1)", + visual_bounds=visual_bounds, + defaults=defaults, + ), + rrb.Spatial2DView( + name="What you should get after removing defaults from 2)", + visual_bounds=visual_bounds, + ), + rrb.Spatial2DView( + name="What you should get after adding overrides & defaults to 3)", + visual_bounds=visual_bounds, + overrides={ + "arrows": [ + rrb.VisualizerOverrides([ + rrb.visualizers.Arrows2D, + rrb.visualizers.Points2D, + ]), + rr.components.Color([255, 255, 255]), + rr.components.Radius(0.1), + rr.components.Text("Cerberus"), + rr.components.Position2D([0.0, 0.0]), + ] + }, + ), + ), + grid_columns=3, + column_shares=[1, 1, 1], + ), ) - - -def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) - - log_readme() - log_boxes() + rr.send_blueprint(blueprint, make_active=True, make_default=True) if __name__ == "__main__": diff --git a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py index 304d66c1644d..842a1dd2e6da 100644 --- a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py +++ b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py @@ -177,7 +177,8 @@ def log_spatial() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_text_logs() diff --git a/tests/python/release_checklist/check_plot_overrides.py b/tests/python/release_checklist/check_plot_overrides.py index cc3a482bb3ce..c46d88669f4f 100644 --- a/tests/python/release_checklist/check_plot_overrides.py +++ b/tests/python/release_checklist/check_plot_overrides.py @@ -62,6 +62,8 @@ def run(args: Namespace) -> None: log_readme() log_plots() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_range_partial_updates.py b/tests/python/release_checklist/check_range_partial_updates.py index 39220eaf58d7..caeb50c805fc 100644 --- a/tests/python/release_checklist/check_range_partial_updates.py +++ b/tests/python/release_checklist/check_range_partial_updates.py @@ -98,10 +98,6 @@ def blueprint() -> rrb.BlueprintLike: ], grid_columns=3, ), - # NOTE: It looks nice but it's very annoying when going through several checklists. - # rrb.BlueprintPanel(state="collapsed"), - # rrb.TimePanel(state="collapsed"), - # rrb.SelectionPanel(state="collapsed"), ) @@ -134,7 +130,7 @@ def log_points() -> None: def run(args: Namespace) -> None: rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) - rr.send_blueprint(blueprint()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) log_readme() log_points() diff --git a/tests/python/release_checklist/check_rbl_import.py b/tests/python/release_checklist/check_rbl_import.py index 942fb8d3e33d..c74e93305f5d 100644 --- a/tests/python/release_checklist/check_rbl_import.py +++ b/tests/python/release_checklist/check_rbl_import.py @@ -37,9 +37,6 @@ def log_external_blueprint() -> None: rrb.TextDocumentView(origin="readme"), column_shares=[3, 2], ), - rrb.BlueprintPanel(state="collapsed"), - rrb.SelectionPanel(state="collapsed"), - rrb.TimePanel(state="collapsed"), ).save("some_unrelated_blueprint_app_id", tmp.name) rr.log_file_from_path(tmp.name) @@ -76,7 +73,9 @@ def run(args: Namespace) -> None: args, f"{os.path.basename(__file__)}", recording_id=uuid4(), - default_blueprint=rrb.Blueprint( + ) + rr.send_blueprint( + rrb.Blueprint( rrb.Horizontal( rrb.TimeSeriesView(origin="/"), rrb.TextDocumentView(origin="readme"), @@ -86,6 +85,8 @@ def run(args: Namespace) -> None: rrb.SelectionPanel(state="collapsed"), rrb.TimePanel(state="collapsed"), ), + make_active=True, + make_default=True, ) log_readme() diff --git a/tests/python/release_checklist/check_scalar_clears.py b/tests/python/release_checklist/check_scalar_clears.py index 81e922bf93c1..c3f025ccbaca 100644 --- a/tests/python/release_checklist/check_scalar_clears.py +++ b/tests/python/release_checklist/check_scalar_clears.py @@ -46,6 +46,8 @@ def run(args: Namespace) -> None: log_readme() log_plots() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_static_components_ui.py b/tests/python/release_checklist/check_static_components_ui.py index 61bb20845ee1..6c53e9d66ca3 100644 --- a/tests/python/release_checklist/check_static_components_ui.py +++ b/tests/python/release_checklist/check_static_components_ui.py @@ -62,6 +62,8 @@ def run(args: Namespace) -> None: log_readme() log_some_views() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_static_override.py b/tests/python/release_checklist/check_static_override.py index ddf28ccb33f3..7c2748c9733a 100644 --- a/tests/python/release_checklist/check_static_override.py +++ b/tests/python/release_checklist/check_static_override.py @@ -29,6 +29,8 @@ def run(args: Namespace) -> None: # Log it again, to ensure that the newest one is visible rr.log("points", rr.Points3D([[0, 0, 0], [1, 1, 1], [2, 2, 2]]), static=True) + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_transform3d_hierarchy.py b/tests/python/release_checklist/check_transform3d_hierarchy.py index 5e0d0f81bf8d..ea54715593ee 100644 --- a/tests/python/release_checklist/check_transform3d_hierarchy.py +++ b/tests/python/release_checklist/check_transform3d_hierarchy.py @@ -72,9 +72,9 @@ def log_data() -> None: rr.set_time_sequence("steps", 4) path += "scale_back_mat3x3/" # fmt: off - rr.log(path, rr.Transform3D(mat3x3=[1.0, 0.0, 0.0, - 0.0, 5.0, 0.0, - 0.0, 0.0, 1.0])) + rr.log(path, rr.Transform3D(mat3x3=[1.0, 0.0, 0.0, + 0.0, 5.0, 0.0, + 0.0, 0.0, 1.0])) # fmt: on rr.set_time_sequence("steps", 5) @@ -112,7 +112,8 @@ def log_data() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.send_blueprint(blueprint(), make_active=True, make_default=True) # Extract the rerun_obj.zip file with zipfile.ZipFile(f"{rerun_obj_path}.zip", "r") as zip_ref: diff --git a/tests/python/release_checklist/check_version.py b/tests/python/release_checklist/check_version.py index 78d34a59a5d2..35ede9dc7f44 100644 --- a/tests/python/release_checklist/check_version.py +++ b/tests/python/release_checklist/check_version.py @@ -38,6 +38,8 @@ def run(args: Namespace) -> None: log_readme() log_the_versions() + rr.send_blueprint(rr.blueprint.Blueprint(auto_layout=True, auto_views=True), make_active=True, make_default=True) + if __name__ == "__main__": import argparse diff --git a/tests/python/release_checklist/check_video.py b/tests/python/release_checklist/check_video.py index 5dd2f4aec54d..14720f3cc626 100644 --- a/tests/python/release_checklist/check_video.py +++ b/tests/python/release_checklist/check_video.py @@ -66,20 +66,19 @@ def run(args: Namespace) -> None: static=True, # Static, so it shows up in the "video_time" timeline! ) - rr.send_blueprint( - rrb.Blueprint( - rrb.Grid( - rrb.TextDocumentView(origin="readme", name="Instructions"), - rrb.Spatial3DView(origin="/", name="AV1 frustum", contents="av1"), - rrb.Spatial2DView(origin="av1", name="AV1"), - rrb.Spatial2DView(origin="h264", name="H.264"), - rrb.Spatial2DView(origin="h265", name="H.265"), - rrb.Spatial2DView(origin="vp9", name="VP9"), - ), - rrb.TimePanel(state="collapsed"), - ) + blueprint = rrb.Blueprint( + rrb.Grid( + rrb.TextDocumentView(origin="readme", name="Instructions"), + rrb.Spatial3DView(origin="/", name="AV1 frustum", contents="av1"), + rrb.Spatial2DView(origin="av1", name="AV1"), + rrb.Spatial2DView(origin="h264", name="H.264"), + rrb.Spatial2DView(origin="h265", name="H.265"), + rrb.Spatial2DView(origin="vp9", name="VP9"), + ), ) + rr.send_blueprint(blueprint, make_active=True, make_default=True) + if __name__ == "__main__": import argparse